最近项目要在STM32L152上移植FreeRTOS轻量级系统,本文将从FreeRTOS的入门知识讲起,记录FreeRTOS的一些基本知识点和学习心得。
硬件平台:STM32L152 ,备注:PA12连接LED1,PA11连接LED2;
软件平台:keil v5和 cubeMx。
FreeRTOS是一种轻量级实时操作系统。RTOS:Real Time OperatingSystem实时操作系统。FreeRTOS可拆分为Free + RTOS,前面Free代表一种操作系统类型的名称,后面RTOS代表实时操作系统。
近几年,FreeRTOS的排名在嵌入式操作系统的排名中还是比较高的,且有不断上升趋势。
首先,打开CUBEMX软件,点击NEW Project,选择芯片STM32L152RC;
2,配置RCC时钟
3,设置PA12和PA11为GPIO_OUTPUT;
4,使能FREERTOS;
5,设置时钟树,本例外部晶振8M,8倍频,2分频,得到32M;
6,配置FREERTOS,创建两个任务;
7,生成基于Keil V5的代码。
8,添加LED点亮和熄灭程序;
编译运行,可以看到LED1和LED2 分别以不同的频率闪烁。
下面重点分析生成的代码:
下面分析MX_FREERTOS_Init()函数;
void MX_FREERTOS_Init(void)
{
osThreadDef(Task_LED1, Func_LED1, osPriorityNormal, 0, 128);//宏定义,定义了一个名为os_thread_def_Task_LED1的osThreadDef_t类型结构体,并赋值给各个成员变量。
Task_LED0Handle = osThreadCreate(osThread(Task_LED1), NULL);//创建了LED1任务
osThreadDef(Task_LED2, Func_LED2, osPriorityNormal, 0, 128);//宏定义,定义了一个名为os_thread_def_Task_LED2的osThreadDef_t类型结构体,并赋值给各个成员变量。
Task_LED1Handle = osThreadCreate(osThread(Task_LED2), NULL);//创建了LED2任务
}
go to definition of osThreadDef,该宏定义如下
#define osThreadDef(name, thread, priority, instances, stacksz) \
const osThreadDef_t os_thread_def_##name = \
{ #name, (thread), (priority), (instances), (stacksz)}
#endif
上诉宏定义中出现了##和# 符号,其中
##是一个连接符号,用于把参数连在一起;
#是“字符串化”的意思。出现在宏定义中的#是把跟在后面的参数转换成一个字符串。
例如:
#define paster( n ) printf( "token" #n" = %d\n ", token##n )
所以paster(9);就是相当于 printf("token 9 = %d\n",token9);
那么osThreadDef(Task_LED1, Func_LED1, osPriorityNormal, 0, 128);等价于下面的定义
#defineosThreadDef(Task_LED1, Func_LED1, osPriorityNormal, 0, 128) \
const osThreadDef_t os_thread_def_Task_LED1 = { Task_LED1,Func_LED1,osPriorityNormal, 0, 128}
#endif
本例中的两个任务函数Func_LED1和Func_LED2,他们实际占用CPU的时间很少,在调用osDelay()函数之后,它们就进入阻塞状态了,它们在等待“定时时间到”事件。在用户任务都进入阻塞状态时,运行的是空闲任务。空闲任务是启动调度器时自动创建的。
在调试过程中,尝试把两个任务函数的osDelay都改成500后,观察现象是LED1和LED2同时同频率的闪烁,但这和FreeRTOS中的某一任意时刻,只会有一个任务在运行,不会有同时两个任务在运行的理论相悖。之后分析发现,在调用osDelay()函数之后,它们就进入阻塞状态了,当500ms到时,LED1先切换至运行态,之后LED2切换至运行态,然后进入组态等待下一个500ms。LED1运行和切换到LED2这个时间非常短,以至于表面上看lED1和LED2同时运行,实际上依然是2个任务在不停的切换。