请选择 进入手机版 | 继续访问电脑版
快捷导航
2 160

FreeRTOS移植到STM32F103ZET6

Serial 于 2017-12-12 10:55 发表在 [技术分享] [复制链接]
将FreeRTOS移植到STM32,首先我们需要到FreeRTOS官网下载官方库:FreeRTOS官网,下载后会发现很多文件

我们使用的是FreeRTOS里面的东西,FreeRTOSPlus里面的东西我没有看明白是做什么用的。
在FreeRTOS中存在Dome,Source两个文件夹,Dome中存在一些演示项目,但是STM32F103的项目与我们使用的开发板不同比如APB2的基址以及引脚组数量、地址都是不同的,那么我们便需要自己进行移植。
我们可以新建一个项目,也可以使用以前的项目,如果使用新建的,那么需要搭建STM32F103的项目框架。一切完成之后,我们便可以进入这次的主题,看似FreeRTOS中有很多文件,其实使用到的很少,Source下面显示的是FreeRTOS的库,我们需要根据使用的开发板进行选择部分文件,通过查找网上的博客,我才知道需要使用哪些,一下文件全部在FreeRTOS下的Source文件夹下:
include文件夹,Source下的.c文件,portable下的RVDS、MemMang文件夹;

include文件夹下存在FreeRTOS内核代码头文件、
Source下的.c文件为FreeRTOS内核代码文件,同时包含了timers.c、event_groups.c、croutine.c三个文件,分别实现软件定时、事件组和协程功能、
RVDS文件下存在各个对应不同类型开发板的文件,我们使用的STM32,那么选择ARM_CM3、
MemMang文件夹下存在五个文件,对应五种不同的内存管理方式。


将以上讲述的文件添加到之前的STM32项目框架中便可,不要忘记包含所头文件:方式为选择Target Options-->选择C/C++-->在Include Paths中添加


点击编译则会显示无法查找到freertosconfig.h文件,我们可以直接从Dome文件中的STM32F103的演示项目中复制一个freertosconfig.h文件过来便可。
之后我们要对应使用的FreeRTOS来修改启动文件startup_stm32f10x_hd.s
1、

添加这三句,有点像宏定义的声明一样
2、

将对应部分代码进行修改,不能修改顺序
为了检测我们的移植是否成功,我们可以写一段代码进行实验,万事从点灯开始,这次也不例外。
首先对LED1、LED2进行引脚初始化,这些之前都做过很多次了,这里我们直接从freertos开始,创建两个任务函数为之后做准备
  1. //LED1任务函数
  2. void led1_task(void *pvParameters)
  3. {
  4.     while(1)
  5.     {
  6.                                 LED1_ON;
  7.                                 vTaskDelay(500);
  8.                                 LED1_OFF;
  9.                                 vTaskDelay(500);
  10.     }
  11. }   

  12. //LED2任务函数
  13. void led2_task(void *pvParameters)
  14. {
  15.     while(1)
  16.     {
  17.         LED2_ON;
  18.         vTaskDelay(200);
  19.         LED2_OFF;
  20.         vTaskDelay(800);
  21.     }
  22. }
复制代码
并需要创建一个开始任务函数,用于管理任务,之前的led1_task、led2_task都只是一个函数,现在我们要将其作为一个任务
  1. //开始任务任务函数
  2. void start_task(void *pvParameters)
  3. {
  4.     taskENTER_CRITICAL();           //进入临界区
  5.     //创建LED0任务
  6.     xTaskCreate((TaskFunction_t )led1_task,
  7.                 (const char*    )"led1_task",
  8.                 (uint16_t       )LED0_STK_SIZE,
  9.                 (void*          )NULL,
  10.                 (UBaseType_t    )LED0_TASK_PRIO,
  11.                 (TaskHandle_t*  )&LED0Task_Handler);
  12.     //创建LED1任务
  13.     xTaskCreate((TaskFunction_t )led2_task,
  14.                 (const char*    )"led2_task",
  15.                 (uint16_t       )LED1_STK_SIZE,
  16.                 (void*          )NULL,
  17.                 (UBaseType_t    )LED1_TASK_PRIO,
  18.                 (TaskHandle_t*  )&LED1Task_Handler);
  19.    
复制代码
xTaskCreate函数便是用来创建任务的,现在这种情况可以理解为在一个start_task函数中存在两个任务,依照之前的思路,接下来我们便是要将start_task函数创建为任务,这我们便可以直接在main函数中进行创建:
  1. int main(void)
  2. {
  3.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
  4.         //delay_init();                                            //延时函数初始化          
  5.         //uart_init(115200);                                        //初始化串口
  6.         LED_Init();                                                          //初始化LED
  7.        
  8.         //创建开始任务
  9.        
  10.     xTaskCreate((TaskFunction_t )start_task,            //任务函数
  11.                 (const char*    )"start_task",          //任务名称
  12.                 (uint16_t       )START_STK_SIZE,        //任务堆栈大小
  13.                 (void*          )NULL,                  //传递给任务函数的参数
  14.                 (UBaseType_t    )START_TASK_PRIO,       //任务优先级
  15.                 (TaskHandle_t*  )&StartTask_Handler);   //任务句柄
  16.     vTaskStartScheduler();          //开启任务调度
  17. }
复制代码
这里也给出了xTaskCreate函数中各参数的意义。

到这里我们应该能想到,这些都是任务,那么任务会存在优先级吧,不然该怎么执行呢?而且在创建任务的时候也存在任务堆栈大小、任务优先级、任务句柄,这些东西又是哪来的呢??
其实这些都是我们自己定义的宏定义,用来任务的具体执行。
  1. //任务优先级
  2. #define START_TASK_PRIO                1
  3. //任务堆栈大小       
  4. #define START_STK_SIZE                 128  
  5. //任务句柄
  6. TaskHandle_t StartTask_Handler;
  7. //任务函数
  8. void start_task(void *pvParameters);

  9. //任务优先级
  10. #define LED0_TASK_PRIO                2
  11. //任务堆栈大小       
  12. #define LED0_STK_SIZE                 50  
  13. //任务句柄
  14. TaskHandle_t LED0Task_Handler;
  15. //任务函数
  16. void led1_task(void *pvParameters);

  17. //任务优先级
  18. #define LED1_TASK_PRIO                3
  19. //任务堆栈大小       
  20. #define LED1_STK_SIZE                 50  
  21. //任务句柄
  22. TaskHandle_t LED1Task_Handler;
  23. //任务函数
  24. void led2_task(void *pvParameters);
复制代码
到这里,我们便将FreeRTOS移植到STM32F103中了,将程序下载到开发板中便可以知道我们是否成功移植。
如果是按照之前的测试实验来写,那么便会看到LED1闪烁,且闪烁频率相同;LED2闪烁,亮的时间比灭的时间短。
至此,移植便成功,我们便可以学习FreeRTOS的东西了。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
Connecting & Messaging from Any.

共 2 个关于本帖的回复 最后回复于 2017-12-13 09:18

a1783463455 注册会员 发表于 2017-12-13 08:29:16 | 显示全部楼层
66666666666666666666666666666666
Connecting & Messaging from Any.
举报 使用道具
小七仔 注册会员 发表于 2017-12-13 09:18:47 | 显示全部楼层
66666666666
Connecting & Messaging from Any.
举报 使用道具
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

推荐板块

精彩推荐

热门排行

明星用户

手机版|小黑屋|AnyMSG ( ©AnyMSG 2009 - 2017 · ICP备16009991号 )

GMT+8, 2019-4-25 23:00