之前freeRTOS用过几次,但是项目赶工的急,一直没有认真的去里面看过,最近正好有空,准备到里面看下源码实现,毕竟核心文件就这么几个,认真看一下流程,对操作系统的雏形也就有一个认识了。而且一些常用的功能,队列,内存管理,信号量之类的,都有,基本上彻底弄懂一个,对以后理解别的也有帮助。
FreeRTOS其实不用再多介绍了,现在太火了,主要是免费,感觉很多厂家的出场demo都会带。
而且FreeRTOS是一个十分小巧的系统,占用资源也不多,甚至可以在stm32f103c8t6(64k flash ,20k ram)上跑起来。具体能裁剪到多小倒是没有看到有介绍,但是基本够用。(这里移到c8t6上也只是为了学习一下流程,如果真的使用可以用个大点的MCU。)
先放上官网,FreeRTOS官网。在这里可以轻松下载到最新的freeRTOS源码、组件、demo、新功能,而且现在的官网比以前好看多了。
现在(2020.4.11)最新的是v10.3.1,下载之后,打开文件夹,文件列表如下:
FreeRTOSv10.3.1
|
| -- FreeRTOS
| -- Demo
| -- License
| -- Source
| -- include
| -- portable
| -- croutine.c
| -- event_groups.c
| -- list.c
| -- queue.c
| -- stream_buffer.c
| -- tasks.c
| -- timers.c
|
| -- FreeRTOS-Plus
| -- Demo
| -- Source
| -- FreeRTOS-Plus-CLI
基本功能:
另外的几个.c,看他们放在这么明显的位置上,就知道是FreeRTOS的关键了。
这里只是为了把系统跑起来,所以只移植了核心组件。
我们需要移植的,最少的文件只需要:
之前main是按这个格式写的:
//全局变量
int main()
{
//局部变量
bsp初始化
while(1)
{
//任务
}
}
需要修改为task的,这边随手写了一个测试的。
#include
#include "hdl_sys.h" //Öжϡ¢GPIO¡¢Êý¾ÝÀàÐÍ
#include "hdl_systickdelay.h" //sysÑÓʱ
#include "hdl_led.h" //Êä³öIO¿Ú
#include "hdl_key.h" //ÊäÈëIO¿Ú
#include "hdl_usart1.h" //´®¿Ú1
#include "hdl_usart2.h" //´®¿Ú2
#include "hdl_usart3.h" //´®¿Ú2
#include "hdl_timer.h" //¶¨Ê±Æ÷
#include "hdl_iwdg.h"
#include "FreeRTOS.h"
#include "task.h"
//°æ±¾ºÅ
static Uint8 Version[4] = {20,4,9,1};
TaskHandle_t StartTask_Handler;
void uart1_task(void *pvParameters)
{
while(1)
{
printf("Uart1 PA9 send PA10 rec @ %lld ms\r\n",GetSysMs());
vTaskDelay(2000);
}
}
void uart2_task(void *pvParameters)
{
while(1)
{
UART2_Put_String("´®¿Ú¶þPA2£¬PA3·¢ËÍÕý³£\r\n");
vTaskDelay(1000);
}
}
void start_task(void *pvParameters)
{
taskENTER_CRITICAL();
xTaskCreate((TaskFunction_t )uart1_task,
(const char* )"uart1_task",
(uint16_t )128,
(void* )NULL,
(UBaseType_t )2,
(TaskHandle_t* )NULL);
xTaskCreate((TaskFunction_t )uart2_task,
(const char* )"uart2_task",
(uint16_t )128,
(void* )NULL,
(UBaseType_t )3,
(TaskHandle_t* )NULL);
vTaskDelete(StartTask_Handler);
taskEXIT_CRITICAL();
}
int main(void)
{
DelayInit(72); //ϵͳʱÖÓÉèÖÃ
NvicConfiguration(); //ÖжÏÔ´·Ö×é
Uart1Init(115200L); //´®¿Ú1³õʼ»¯
Uart2Init(115200L); //´®¿Ú2³õʼ»¯
//Uart3Init(115200L); //´®¿Ú3³õʼ»¯
//Timer2Init(9,7199); //719±íÃ÷72M/(7199+1)=10KhzµÄ¼ÆÊýƵÂÊ£¬¼ÆÊýµ½10£¨9+1£©Îª1ms, ΪϵͳÌṩʱÖÓ
//IWDG_Init(4,625*5); //Óë·ÖƵÊýΪ64,ÖØÔØֵΪ625,Òç³öʱ¼äΪ3s
printf("\r\n\r\n***************************************\r\n");
printf("** STM32 taotao Demo **\r\n");
printf("** Complie Time:%s %s **\r\n", __TIME__,__DATE__);
printf("** Version:%d.%d.%d.%d **\r\n", Version[0],Version[1],Version[2],Version[3]);
printf("***************************************\r\n");
xTaskCreate((TaskFunction_t )start_task,
(const char* )"start_task",
(uint16_t )128,
(void* )NULL,
(UBaseType_t )1,
(TaskHandle_t* )&StartTask_Handler);
vTaskStartScheduler();
while(1)
{
}
}
因为使用的是stm32f103c8t6,ram只有20k,所以选择吧heap设置小一些,毕竟只是个测试程序,能用就行。
这么修改之后,运行依然跑不起来,一旦全速运行就会出现HardFault_Handler。
之前一直不理解,跟着堆栈跑觉得挺正常的,怎么一进中断就HardFault_Handler了,后来搜了一下,发现是因为名字不一样。
修改中断函数名