A Real-Time Operating System (RTOS) is a type of computer operating system designed to be small and deterministic. RTOSes are commonly used in embedded systems such as medical devices and automotive ECUs that need to react to external events within strict time constraints.
Each executing program is implemented by one or more threads under control of the operating system. If an operating system can execute multiple threads in this manner it is said to be multitasking. Small RTOSes, like FreeRTOS, normally call threads tasks because they don't support virtual memory, so there is no distinction between processes and threads.
Scheduling:
The scheduler is the part of the kernel responsible for deciding which task should be executing at any particular time. The kernel can pause and later resume a task many times during the task's lifetime. If task B replaces task A as the executing task (task A is paused and task B resumed) then task A is said to have been swapped (or switched) out, and task B swapped (or switched) in.
Documents:
We are using Free RTOS in STM32 in Keil IDE.
Build_your_first_project (steps to follow by freertos.org)
Steps to include RTOS in KEIL:
1. Download Free RTOS from https://www.freertos.org/
Also available in GitHub repository
2. Include the required C and header files in your Keil project which are present in below folders
Necessary folders:
-- FreeRTOS -> FreeRTOS-Kernel: contains necessary C files like task.c, timer.c, etc.,.
-- FreeRTOS -> FreeRTOS-Kernel -> include: contains necessary header files
-- FreeRTOS -> FreeRTOS-Kernel -> portable
- MemMang: contains heap files
- Then use the folder based on the board and compiler you are using, in our case GCC -> ARM_CM3 (ARM Cortex M3 and ARM compiler 6, if using compiler 5, then use RVDS instead of GCC)
-- FreeRTOSConfig.h file:
Use the FreeRTOSConfig.h from GitHub, which is suitable for your specific board and copy that file to your local RTOS folder, In our case for STM32F103C8T6 in KEIL compiler
https://github.com/FreeRTOS/FreeRTOS/blob/main/FreeRTOS/Demo/CORTEX_STM32F103_Keil/FreeRTOSConfig.h
Lets copy the file to the new folder, lets say "include" inside path
FreeRTOS -> FreeRTOS-Kernel -> include, which also need to be included in KEIL
Header files:
In KEIL -> Project -> options for target -> C/C++ -> Include Paths
Include the C files in Source group
- Right click on Source Group 1 -> Add existing files to group
Heap management: Include any one of the heap C file from FreeRTOS -> FreeRTOS-Kernel -> portable -> MemMang. Heap 4 implementation is preferred.
OR, instead of manually including FreeRTOS, we can select RTOS when creating KEIL project
3. Include the following header files in your main program:
#include "FreeRTOS.h"
#include "task.h" - If you are going to use task functions
- If you are using queue / semaphore / timer - include related header files
4. RTOS uses one of the STM32 timer as SysTick Timer
- Configure the RCC registers to get desired system clock, for more details see this RCC post
- SysClk / 8 is Cortex system timer, which is the SysTick timer
The SysTick calibration value is set to 9000, which gives a reference time base of 1 ms with
the SysTick clock set to 9 MHz (max HCLK/8)
SysClk = 72 MHz
system Timer = 72 / 8 = 9 MHz
9 MHz / 9000 = 1000 Hz
Tick_HZ = 1000 Hz = 1 ms
If your tasks don't run, check out this page
Program:
/* FreeRTOS in STM32 */
#include "stm32f10x.h"
#include "FreeRTOS.h"
#include "task.h"
void led_on(void *);
void led_off(void *);
void led_on(void *pvParameters)
{
while(1) // Tasks runs forever
{
GPIOC -> BSRR = GPIO_BSRR_BR13; // PC13 LED - ON
vTaskDelay(500 / portTICK_PERIOD_MS); // wait for 500 ticks - 500 / tick_time = 500 / 1 ms = 500 ms
}
}
void led_off(void *pvParameters)
{
while(1) // Tasks runs forever
{
GPIOC -> BSRR = GPIO_BSRR_BS13; // PC13 LED - OFF
vTaskDelay(500 / portTICK_PERIOD_MS); // wait for 500 ticks - 500 / tick_time = 500 / 1 ms = 500 ms
}
}
void RCC_config(void);
void RCC_config() // RCC clock configuration
{
RCC -> CR |= RCC_CR_HSEON; // HSE ON
RCC -> CFGR |= (RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL9);
// Setting PLL - HSE * 9, APB1 / 2
RCC -> CFGR |= RCC_CFGR_SW_1; // SysClk = PLLCLK
RCC -> CR |= RCC_CR_PLLON;
// Turn ON PLL after above PLL configurations, making SysClk = HSE * 9 = 8 * 9 = 72 MHz
RCC -> CFGR |= RCC_CFGR_PPRE1_DIV2;
// APB1 = AHB / 2 = 72 / 2 = 36 MHz (max)
}
int main()
{
RCC_config();
/* PC13 LED configuration */
RCC -> APB2ENR |= RCC_APB2ENR_IOPCEN; // Enable Port-C Clock
GPIOC -> CRH |= GPIO_CRH_MODE13_1 | GPIO_CRH_CNF13_0; // PortC_Pin 13 as output @2MHZ with open-drain
GPIOC -> BSRR = GPIO_BSRR_BS13; // Initialize PC13 LED - OFF
if(xTaskCreate(led_on, // Function / Task name
"ON", // Descriptive name
128, // Minimum Stack length in words
NULL, // Argument to the function
0, // Priority, 0 - Lowest
NULL) // Task handle
!= pdPASS){ // Check if task is created successfully using return value
return 0; } // else return
if(xTaskCreate(led_off, "OFF", 128, NULL, 0, NULL) != pdPASS)
{return 0;}
vTaskStartScheduler(); // Start the scheduler
// Code after this will never gets executed
return 0;
}
Explanation:
1. Initially the main function will run, where we will be configuring the tasks and then start the scheduler. After which RTOS takes over and runs all the created tasks based on priorities.
2. Lets create 2 tasks, one turns ON the LED and other turns OFF the LED
3. Use vTaskDELAY() in RTOS instead of normal delay, as it considers tick time.
Comments
Post a Comment