FreeRTOS simulation on Ubuntu/ Linux

FreeRTOS simulation on Ubuntu/ Linux

In this article, I would like to discuss how you can simulate your project on freeRTOS upon an Linux OS. I have used Ubuntu 20.04 for this project.

I have previously discussed FreeRTOS in many of my articles. If you have not read them or want some basics, I advise reading them first.

If you are searching for a reference to the API - https://www.freertos.org/a00106.html

The first step that you will have to do is clone this example project

git clone https://github.com/JuggernautPanda/freeRTOS_linux        

This has a dependency of the following package on linux. Consider installing it first

sudo apt-get install libc6-dev-i386        

For any FreeRTOS application, the following files are important

raja@raja-Inspiron-N5110:/media/raja/raja/scripts/project_FreeRTOS/Source$ ls -lr
total 404
-rwxrwxrwx 1 raja raja  39795 Mar 15 18:31 timers.c
-rwxrwxrwx 1 raja raja 165734 Mar 15 18:31 tasks.c
-rwxrwxrwx 1 raja raja  43062 Mar 15 18:31 stream_buffer.c
-rwxrwxrwx 1 raja raja    822 Mar 15 18:31 readme.txt
-rwxrwxrwx 1 raja raja  93743 Mar 15 18:31 queue.c
drwxrwxrwx 1 raja raja      0 Mar 15 18:31 portable
-rwxrwxrwx 1 raja raja   8399 Mar 15 18:31 list.c
drwxrwxrwx 1 raja raja   4096 Mar 15 18:31 include
-rwxrwxrwx 1 raja raja  24612 Mar 15 18:31 event_groups.c
-rwxrwxrwx 1 raja raja  13177 Mar 15 18:31 croutine.c

t        

They are timers, tasks, queue, semaphores, etc which should be added to a project. You may find the files as shown above.

#include <stdio.h>
#include <stdlib.h>
#include "FreeRTOS.h"		/* RTOS firmware */
#include "task.h"			/* Task */
#include "timers.h"
#include "queue.h"
#include "semphr.h" // include semaphore!


        

Create a task as follows inside main.c-

xTaskCreate( vFirstTask, "Task 1", 1024, NULL, 1, NULL );
xTaskCreate( vSecondTask,"Task 2", 1024, NULL, 1, NULL);
xTaskCreate( vThirdTask, "Task 3", 1024, NULL, 1, NULL );        

Start the scheduler

	// start the schedule
	vTaskStartScheduler();        

Make the project using the make file that is present.

make        

Once made, you can run it as -

./sim_FreeRTOS        

Now, you can simply call the required API functions for mutex, semaphore, queue etc.

Binary semaphores are used for both mutual exclusion and synchronisation purposes.

Binary semaphores and mutexes are very similar but have some subtle differences: Mutexes include a priority inheritance mechanism, binary semaphores do not. This makes binary semaphores the better choice for implementing synchronisation (between tasks or between tasks and an interrupt), and mutexes the better choice for implementing simple mutual exclusion. The description of how a mutex can be used as a mutual exclusion mechanism holds equally for binary semaphores. This sub section will only describe using binary semaphores for synchronisation.

Semaphore API functions permit a block time to be specified. The block time indicates the maximum number of 'ticks' that a task should enter the Blocked state when attempting to 'take' a semaphore, should the semaphore not be immediately available. If more than one task blocks on the same semaphore then the task with the highest priority will be the task that is unblocked the next time the semaphore becomes available.

Think of a binary semaphore as a queue that can only hold one item. The queue can therefore only be empty or full (hence binary). Tasks and interrupts using the queue don't care what the queue holds - they only want to know if the queue is empty or full. This mechanism can be exploited to synchronise (for example) a task with an interrupt.

Consider the case where a task is used to service a peripheral. Polling the peripheral would be wasteful of CPU resources, and prevent other tasks from executing. It is therefore preferable that the task spends most of its time in the Blocked state (allowing other tasks to execute) and only execute itself when there is actually something for it to do. This is achieved using a binary semaphore by having the task Block while attempting to 'take' the semaphore. An interrupt routine is then written for the peripheral that just 'gives' the semaphore when the peripheral requires servicing. The task always 'takes' the semaphore (reads from the queue to make the queue empty), but never 'gives' it. The interrupt always 'gives' the semaphore (writes to the queue to make it full) but never takes it. The source code provided on the xSemaphoreGiveFromISR() documentation page should make this clearer. Also see RTOS task notifications, which can be used as a faster and lighter weight binary semaphore alternaitve in some situations.

Task prioritisation can be used to ensure peripherals get services in a timely manner - effectively generating a 'deferred interrupt' scheme. (note FreeRTOS also has a built in deferred interrupt mechanism). An alternative approach is to use a queue in place of the semaphore. When this is done the interrupt routine can capture the data associated with the peripheral event and send it on a queue to the task. The task unblocks when data becomes available on the queue, retrieves the data from the queue, then performs any data processing that is required. This second scheme permits interrupts to remain as short as possible, with all post processing instead occurring within a task.

See the Semaphores/Mutexes section of the user documentation for a list of semaphore related API functions. Searching the files in the FreeRTOS/Demo/Common/Minimal directory will reveal multiple examples of their usage. Note that interrupts must NOT use API functions that do not end in "FromISR".

This is how you deal with mutex.

// Global
	static SemaphoreHandle_t mutex;

void vThirdTask(void* parameter
{
	while(1)
	{
		vTaskDelay(pdMS_TO_TICKS(30000)); // The third task should run every 30 seconds
	 printf("Task 3 - locked\n");
		if (xSemaphoreTake(mutex, 0) == pdTRUE) 
	   {
		   //locking is the critical section
	 sab.state = lock;
	 vTaskDelay(pdMS_TO_TICKS(10000)); // Keep it locked for 10 seconds.
     sab.state = unlock; // Now unlock it
	 printf("Task 3 - unlocked\n");
	 // Give mutex after critical section
      xSemaphoreGive(mutex);
    }
	}
}

        

To view or add a comment, sign in

More articles by Gurajapu Raja Sumant

Others also viewed

Explore content categories