OpenLab ARM utilizes the LPC1768 Cortex M3 microcontroller which is suited for Embedded real-time application. These kinds of application typically consists of both hard and soft real-time application. FreeRTOS is a real-time kernel or real-time scheduler that can be used to meet the hard real-time requirements. It allows all applications to be organized as a collection of independent threads of execution. As the LPC1768 has only one core, in reality only a single thread can be executing at any one time. The kernel decides which thread should be executed by examining the priority assigned to each thread by the application designer. In the simplest case, the application designer could assign higher priorities to threads that implement hard real-time requirements, and lower priorities to threads that implement soft real-time requirements. This would ensure that hard real-time threads are always executed ahead of soft real-time threads.
The LPC1768 port includes all the standard FreeRTOS features:
FreeRTOS also manages interrupt nesting, and allows interrupts above a user-definable priority level to remain unaffected by the activity of the kernel. Using FreeRTOS will not introduce any additional timing jitter or latency for these interrupts.
After creating a project there are different files that are required to be located and copied to the project folder.
some of the files are given below:
-> FreeRTOSv9.0.0\FreeRTOS\Source\include
-> FreeRTOSv9.0.0\FreeRTOS\Source
After locating the above files copy them to the project folder and add the c files to the project from the Keil Ide.
After all those procedures its time to configure the project, this configuration is done within the startup_lpc17xx.c file and FreeRTOSConfig.h. startup_lpc17xx.c file will be added to the project when we create the project, FreeRTOSConfig.h file is needed to created by our own or edit any existing FreeRTOSConfig.h from different available demo project in FreeRTOS folder (FreeRTOSv9.0.0\FreeRTOS\Demo).
While using FreeRTOS there are some FreeRTOS specific files that are required to be added to the startup_lpc17xx.c to make it work.
Add the above lines to the startup_lpc17xx.c file before Vector Table Mapped to Address 0 at Reset.
After that its is required to change some native key words of startup_lpc17xx.c with that of FreeRTOS specific ones such as SVC_Handler, PendSV_Handler, SysTick_Handler from Vector Table Mapped to Address 0 at Reset.
While creating FreeRTOSConfig.h files there are various conditions that are needed to be considered and those conditions depend on the user-specific application. Regarding this, there are clean guides available from FreeRTOS in a pdf book form that is available from their official website.
Here we will be discussing on how to modify an existing FreeRTOSConfig.h file from a demo project in FreeRTOS (for eg: FreeRTOSv9.0.0\FreeRTOS\Demo\CORTEX_LPC1768_GCC_RedSuite\src). It will be configured for basic applications such as LED blinking. For high-end applications, users can refer the manual form FreeRTOS to configure FreeRTOSConfig.h file.
It depends on the application we develop on how to configure all these functions in the project, a correct configuration only allows a user to run the application successfully, A complete description on this function and its configurations are available in the user manual for FreeRTOS.
The definitions that are used in this program are as follows:
#include <lpc17xx.h> #include "FreeRTOS.h" #include "task.h" #define LED1 16 /* LED for Task-1 */#define LED2 17 /* LED for Task-2 */#define LED3 18 /* LED for Task-2 */#define IDEAL_LED 19 /* LED for Ideal-Task */ #define GPIO_PIN_DIR LPC_GPIO0->FIODIR #define GPIO_PIN_SET LPC_GPIO0->FIOSET #define GPIO_PIN_CLR LPC_GPIO0->FIOSET
/* Local Functions for Task declaration */void vTask1(void *pvParameters); void vTask2(void *pvParameters); void vTask3(void *pvParameters); void vIdealTask(void *pvParameters);
void vTask1(void *pvParameters) { while(1) { GPIO_PIN_SET |= (1<LED1); /* LED for Task-1 with priority 1 */ vTaskDelay(500); GPIO_PIN_CLR |= (1<LED1); vTaskDelay(500); } }
The required task is always an infinite loop to maintain its functionality throughout the execution. Even though the tasks are in the infinite loop it does not affect the task switching, it is taken control by the scheduler.
int main(void) { SystemInit(); /* Setting Port0 Pins 16, 17, 18 & 19 as output for Task-1, Task-2, Task-3 & Ideal-Task. */ GPIO_PIN_DIR |= (1<<LED1)|(1<<LED2)|(1<<LED3)|(1<<IDEAL_LED); /* Creating four tasks with priorities Ideal priority, 1, 2 and 3. */ xTaskCreate( vIdealTask, /* Pointer to the function that implements the task. */ "IdealTask", /* Text name for the task. This is to facilitate debugging only. */ configMINIMAL_STACK_SIZE, /* The size of the stack that should be created for the task. * This is defined in words, not bytes. */ NULL, /* A reference to xParameters is used as the task parameter. * This is cast to a void * to prevent compiler warnings. * This example does not use the task parameter. */ tskIDLE_PRIORITY, /* The priority to assign to the newly created task. * This task has Ideal Priority. */ NULL); /* The handle to the task being created will be placed in xHandle. * This example does not use the task handle. */ xTaskCreate( vTask1, "Task1", configMINIMAL_STACK_SIZE, NULL, 1, NULL ); xTaskCreate( vTask2, "Task2", configMINIMAL_STACK_SIZE, NULL, 2, NULL ); xTaskCreate( vTask3, "Task3", configMINIMAL_STACK_SIZE, NULL, 3, NULL ); /* Start the scheduler so the tasks start executing. */ vTaskStartScheduler(); /* If all is well then main() will never reach here as the scheduler will now be running the tasks. If main() does reach here then it is likely that the idle task could not be created inside vTaskStartScheduler() or there was insufficient heap memory available for the idle task to be created. */ while(1); }
xTaskCreate( TaskFunction_t pvTaskCode, const char * const pcName, unsigned short usStackDepth, void *pvParameters, UBaseType_t uxPriority, TaskHandle_t *pxCreatedTask );
[fusion_table fusion_table_type=”1″ hide_on_mobile=”small-visibility,medium-visibility,large-visibility” class=”” id=”” animation_type=”” animation_direction=”left” animation_speed=”0.3″ animation_offset=””]
Arguments | Description |
---|---|
pvTaskCode | The pvTaskCode parameter is simply a pointer to the function (in effect, just the function name) that implements the task |
pcName | A descriptive name for the task. This is mainly used to facilitate debugging, but can also be used in a call to xTaskGetHandle() to obtain a task handle. |
usStackDepth | Each task has its own unique stack that is allocated by the kernel to the task when the task is created. The usStackDepth value tells the kernel how large to make the stack. |
pvParameters | Task functions accept a parameter of type ‘pointer to void’ ( void* ). The value assigned to pvParameters will be the value passed into the task. |
uxPriority | Defines the priority at which the task will execute. Priorities can be assigned from 0, which is the lowest priority, to (configMAX_PRIORITIES – 1), which is the highest priority. |
pxCreatedTask | pxCreatedTask can be used to pass out a handle to the task being created. This handle can then be used to reference the task in API calls that, for example, change the task priority or delete the task.If your application has no use for the task handle, then pxCreatedTask can be set to NULL. |
[/fusion_table]