当前位置:   article > 正文

FreeRTOS移植到STM32-任务的创建

freertos移植到stm32

本文的主要内容重在应用,将FreeRTOS移植到STM32F103ZET6(其他类型的型号一样可以参考本文,只用略做一点修改就行,会在下面进行讲解,区别在哪里)上进行相关的小实验。

1.FreeRTOS的源码下载

  源码的官方下载地址为 FreeRTOS官方下载链接,本次移植的版本的是V10.3.0。

下载好后的文件如下:

其中我们只关心FreeRTOS文件夹,里面是内核所在的文件夹,包含源码和示例程序;FreeRTOS-Plus文件包含第3方中间源码及示例程序;FreeRTOS-Labs文件是V9.0及以前版本中所没有的。

1.1 FreeRTOS源码文件夹

其中Demo是FreeRTOS的示例,Source是FreeRTOS内核所在的文件夹。

1.2 Source文件夹

include文件夹存放的是对应.c文件的头文件。portable文件夹是FreeRTOS和具体硬件联系在一起的桥梁,也叫移植层文件夹。

1.3 portable文件夹

 FreeRTOS在不同的编译环境,不同的硬件平台实现,需要portable文件夹对应的文件支持,因此移植层文件是进行移植的关键文件。

对于在MDK-ARM编译环境下,需要Keil,MenMang,RVDS文件。其中重点关注RVDS文件夹,它里面包含了针对不同架构的MCU实现FreeRTOS与硬件相关的操作与宏定义,不同的架构的MCU使用对于其架构相对于的文件夹。列如,STM32F1xx系列的芯片属于ARM Cortex-M3内核,使用ARM_CM3文件夹的文件就行,用STM32F4xx系列的芯片使用ARM_CM4F文件夹的文件就行,这里主要就是不同芯片移植主要的不同点之一。

1.3 ARM_CM3文件夹

到这里基本要移植需要的文件已经列举出来了。

2. FreeRTOS的移植

2.1 移植前基础工程的准备

本文采用的是MDK-ARM为编译环境,以STM32F103ZET6开发板为移植平台。先准备一个LED闪烁的基础工程。本文用的工程是以B站的江科大up主的基础模板,(只要你的工程可以点灯就行)使用的是标准库。当然,用标准库,寄存器或者HAL库都是可以的,移植和用那个库没有必要的联系,移植的过程是一样的。

基础工程的项目分组如下:

2.2 复制FreeRTOS源码

在基础工程的的文件夹下新建立一个FreeRTOS的文件夹。

将FreeRTOS源码文件夹下的Source文件夹下的全部文件复制到基础工程下新建的FreeRTOS文件夹下。

打开portable文件夹,只保留Keil,MenMang,RVDS这3个目录。

2.3 向工程中添加.c文件

点击3个小方块

这就是完整的项目工程,如果不会添加.c文件的请他其他文章。

2.3 配置头文件

点击魔术棒

在include paths配置头文件路径

2.4 配置FreeRTOS

FreeRTOS使用FreeRTOSConfig.h文件进行配置和裁剪。FreeRTOSConfig.h文件可以从下载的FreeRTOS源码G:\FreeRTOSv10.3.0\FreeRTOSv10.3.0\FreeRTOS\Demo\CORTEX_STM32F103_Keil示例程序中复制。

把FreeRTOSConfig复制到自己的FreeRTOS工程下的include目录下(复制到其他目录下也是可以的,但是要注意配置好头文件包含路径)

2.5 修改stm32f1xx_it.c文件

在stm32f1xx_it.c会生成SysTick,PendSV和SVC这3个中断服务函数,这3个中断服务函数已经在FreeRTOS中使用,会造成重复编译,所以我们要屏蔽点这3个中断服务函数。然后编译。

你应该会报一个错误

  1. .\stm32_freertos.axf: Error: L6218E: Undefined symbol xTaskGetCurrentTaskHandle (referred from stream_buffer.o).

解决办法是在FreeRTOS.h文件中的

  1. #ifndef INCLUDE_xTaskGetCurrentTaskHandle
  2. #define INCLUDE_xTaskGetCurrentTaskHandle 1
  3. #endif

把开始的0修改成1 这样就0警告0错误。

3.FreeRTOS移植验证

首先在main函数中包含FreeRTOS.h和task.h

  1. #include "FreeRTOS.h"
  2. #include "task.h"

3.1 编写测试任务函数

  1. static TaskHandle_t LedTaskHandle = NULL;//任务句柄
  2. //函数功能是让LED灯以1秒的间隔闪烁
  3. //形参pvParameters是创建该任务是传递的参数
  4. static void LedTask(void *pvParameters)
  5. {
  6. while(1)
  7. {
  8. LED_ON();
  9. Delay_ms(1000);
  10. LED_off();
  11. Delay_ms(1000);
  12. }
  13. }
  14. //---------------------------LED函数---------------------//
  15. void LED_init(void){
  16. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
  17. GPIO_InitTypeDef GPIO_InitStruvture;
  18. GPIO_InitStruvture.GPIO_Mode=GPIO_Mode_Out_PP;
  19. GPIO_InitStruvture.GPIO_Pin=GPIO_Pin_2;
  20. GPIO_InitStruvture.GPIO_Speed=GPIO_Speed_50MHz;
  21. GPIO_Init(GPIOA,&GPIO_InitStruvture);
  22. GPIO_SetBits(GPIOA,GPIO_Pin_2);
  23. }
  24. void LED_ON(){
  25. GPIO_ResetBits(GPIOA,GPIO_Pin_2);
  26. }
  27. void LED_off(){
  28. GPIO_SetBits(GPIOA,GPIO_Pin_2);
  29. }

3.1 创建一个任务

创建任务函数的原型

BaseType_t xTaskCreate(    TaskFunction_t pvTaskCode,
                            const char * const pcName,
                            configSTACK_DEPTH_TYPE usStackDepth,
                            void *pvParameters,
                            UBaseType_t uxPriority,
                            TaskHandle_t *pxCreatedTask
                          );

xTaskCreate(LedTask,"LedTask",128,NULL,4,&LedTaskHandle);

3.2 开启调度器

用vTaskStartScheduler()函数来开启调度器,正常情况下,函数不会执行到这语句的后面的代码。

  1. int main(void)
  2. {
  3. LED_init();
  4. xTaskCreate(LedTask,"LedTask",128,NULL,4,&LedTaskHandle);
  5. vTaskStartScheduler();
  6. //后面的while函数不会执行
  7. while(1)
  8. {
  9. }
  10. }

3.3 下载测试

第一次下载程序可能LED不会闪烁,如何来排除问题的经验是很重要的,我们在开启任务调度的前面写一个打开灯的代码。

  1. int main(void)
  2. {
  3. LED_init();
  4. xTaskCreate(LedTask,"LedTask",128,NULL,4,&LedTaskHandle);
  5. LED_ON();
  6. vTaskStartScheduler();
  7. //后面的while函数不会执行
  8. while(1)
  9. {
  10. }
  11. }

会发现灯亮了,这就说明是卡死在 vTaskStartScheduler();这句代码。然后我们带着问题去百度。发现是ARM Cortex-M3,ARM Cortex-M4和ARM Cortex-M4F上的移植需要FreeRTOS处理安装的SysTick,PendSV和SVCCall中断向量,中断向量表可以分别直接使用FreeRTOS定义的xPortSysTickHandler(),xPortPendSVHandler()和vPortSVCHandler()三个函数。但是,如果中断向量表是与CMSIS兼容的话,用户需在FreeRTOSConfig.h中添加以下三行代码以使FreeRTOS和CMSIS中中断向量名字做映射。

解决方案是:

将下面的代码放到FreeRTOSConfig.h

  1. #define vPortSVCHandler SVC_Handler
  2. #define xPortPendSVHandler PendSV_Handler
  3. #define xPortSysTickHandler SysTick_Handler

原文链接

下载后程序正是1秒的间隔闪烁,到此,FreeRTOS的移植完毕,后续将会继续编写有关FreeRTOS的小应用。

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号