Introduction to FreeRTOS
FreeRTOS is an open-source real-time operating system (RTOS) designed for embedded systems. It provides the following core features:
-
Task Management: Supports concurrent execution of multiple tasks, with the ability to set task priorities.
-
Memory Management: Provides dynamic memory allocation mechanisms (such as heap_1, heap_2, heap_4, etc.).
-
Inter-task Communication: Supports mechanisms such as queues, semaphores, and mutexes.
-
Timers: Provides software timer functionality.
-
Interrupt Management: Supports communication between interrupt service routines (ISRs) and tasks.
-
Portability: The code of FreeRTOS is highly modular, making it easy to port to different hardware platforms.
FreeRTOS is widely used in resource-constrained embedded devices, such as sensor nodes, industrial controllers, consumer electronics, and automotive electronics.
Detailed Steps to Port FreeRTOS in STM32 Using Standard Libraries
1. Preparation
-
Hardware: STM32F103C8.
-
Software:
-
Keil MDK.
-
STM32 Standard Peripheral Library (StdPeriph Library).
-
FreeRTOS Source Code: Download the latest version from the FreeRTOS official website.
2. Porting Steps
2.1 Create Project
-
Create a new STM32 project in Keil using the standard peripheral library template.
2.2 Add FreeRTOS Source Code
-
Copy the FreeRTOS source code into the project directory, typically including the following files:
-
<span>FreeRTOS/Source/*</span>: FreeRTOS core source code. -
<span>FreeRTOS/Source/portable/[compiler]/[architecture]</span>: Port layer files (e.g.,<span>RVDS/ARM_CM3</span>for Cortex-M3). -
<span>FreeRTOS/Source/include/*</span>: FreeRTOS header files.
Add the following files to the project:
-
<span>tasks.c</span>,<span>queue.c</span>,<span>list.c</span>,<span>timers.c</span>: FreeRTOS core files. -
<span>port.c</span>: Port layer file. -
<span>heap_4.c</span>: Memory management implementation (recommended to use heap_4).
2.3 Configure FreeRTOS
-
Modify the
<span>FreeRTOSConfig.h</span>file to configure FreeRTOS parameters:
#define configUSE_PREEMPTION 1
#define configUSE_TIME_SLICING 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#define configUSE_TICKLESS_IDLE 0
#define configCPU_CLOCK_HZ (SystemCoreClock)
#define configTICK_RATE_HZ ((TickType_t)1000)
#define configMAX_PRIORITIES (32)
#define configMINIMAL_STACK_SIZE ((unsigned short)128)
#define configMAX_TASK_NAME_LEN (16)
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_QUEUE_SETS 0
#define configUSE_TASK_NOTIFICATIONS 1
#define configUSE_MUTEXES 0
#define configUSE_RECURSIVE_MUTEXES 0
#define configUSE_COUNTING_SEMAPHORES 0
#define configQUEUE_REGISTRY_SIZE 10
#define configUSE_APPLICATION_TASK_TAG 0
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configSUPPORT_STATIC_ALLOCATION 0
#define configTOTAL_HEAP_SIZE ((size_t)(10*1024))
Implement the SysTick interrupt in <span>stm32f10x_it.c</span>:
void SysTick_Handler(void)
{
if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)
{
xPortSysTickHandler();
}
}
2.4 Write Task Code
Create tasks in <span>main.c</span>:
int main()
{
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
GPIO_LCD_Init();
GPIO_FillScreen(BLUE);
// Create start task
xTaskCreate((TaskFunction_t)start_task,
(const char*)