欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

FreeRTOS+STM32F103系列--1.移植

程序员文章站 2024-02-22 18:36:17
...

—-Done is better than perfect

1.前言

   用了一年多FreeRTOS,感觉还是不能很好的掌握这个系统,可能是自己从来没有认真去研究过它吧!为了不这样含含糊糊的用着,我决定开始深入研究下FreeRTOS,探索它背后的原理,掌握其编程方法,避免其缺陷和陷阱,并将它安全的用在将来的项目中。
先移植个闪灯程序把系统先跑起来,go…

开发板: ALIENTEK战舰STM32开发板
CPU: STM32F103ZET6
FreeRTOS版本: FreeRTOSv9.0.0
编译软件: keil5

2.如何创建一个新的FreeRTOS工程

  参考FreeRTOS官网创建一个新工程http://www.freertos.org/Creating-a-new-FreeRTOS-project.html例子。

  • 源文件 .c
    FreeRTOS+STM32F103系列--1.移植

  最小FreeRTOS只需要包含五个文件,分别是tasks.c、queue.c、list.c、port.c、heap_x.c(x是1,2,3,4,5任意选一个)

  • 头文件 .h
    FreeRTOS+STM32F103系列--1.移植
    需要的头文件路径
    FreeRTOS/Source/include
    FreeRTOS/Source/portable/[compiler]/[architecture].

  • 配置文件 FreeRTOSConfig.h
    FreeRTOS+STM32F103系列--1.移植
    FreeRTOS官网提供了很多平台演示例程,STM32F103的演示例程也提供了,可以根据下面路径,拷贝一份出来:
    FreeRTOSv9.0.0\FreeRTOS\Demo\CORTEX_STM32F103_Keil\FreeRTOSConfig.h

  • 安装中断向量
    FreeRTOS+STM32F103系列--1.移植
    每个RTOS端口都使用一个定时器生成周期性的滴答中断。许多端口使用额外的中断来管理上下文切换。RTOS端口需要的中断请求由RTOS端口源文件提供。

这个部分很重要,我刚开始移植一直失败,最后找到原因就是这部分没有配置好造成的。
看一下FAQ文档
[Cortex-M users: Information on installing interrupt handers is provided in the “The application I created compiles, but does not run” FAQ]
FreeRTOS+STM32F103系列--1.移植
ARMCortex-M用户需要特别注意:ARM Cortex-M3,ARM Cortex-M4,ARM Cortex-M4F ports需要在SysTick,PenSV和SVCCall中断向量上安装FreeRTOS handlers。向量表可以直接使用FreeRTOS定义的xPortSysTickHandler()、xPortPendSVHandler()和vPortSVCHandler()函数来填充,或者,如果中断向量表是符合CMSIS要求,那么可以将下面的三行添加到FreeRTOSConfig.h将FreeRTOS的函数名映射到它们的CMSIS当量:

#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler

稍后将在启动文件startup_stm32f10x_hd.s做修改

3.STM32需要哪些文件

STM32需要的文件和原来裸机上需要的文件相同。如果做过STM32裸机项目的可以基本照搬过来。

  • 库文件: STM32F10x_FWLib
  • 启动文件: startup_stm32f10x_hd.s
  • CMSIS核心文件: core_cm3.c、core_cm3.h
  • system文件: system_stm32f10x.c、system_stm32f10x.h、stm32f10x.h
  • 中断相关: stm32f10x_it.c、stm32f10x_it.h

4.Keil工程Blinky

  • 项目结构
    ├─CORE (CM3核心文件)
    ├─FreeRTOS (FreeRTOSv9.0.0\FreeRTOS\Source下所有文件拷贝过来就行了)
    │ ├─include
    │ └─portable (保留Keil、MemMang、RVDS,其他文件夹删除)
    │ ├─Keil
    │ ├─MemMang
    │ └─RVDS
    │ ├─ARM7_LPC21xx
    │ ├─ARM_CA9
    │ ├─ARM_CM0
    │ ├─ARM_CM3
    │ ├─ARM_CM4F
    │ ├─ARM_CM4_MPU
    │ └─ARM_CM7
    │ └─r0p1
    ├─OBJ (目标生成目录)
    ├─PRO (工程目录)
    ├─STM32F10x_FWLib (STM32库函数)
    │ ├─inc
    │ └─src
    └─USER (用户目录)

    • Keil工程结构
      FreeRTOS+STM32F103系列--1.移植
      STM32库函数文件只用到了gpio、rcc只包含这两个就好了,加快编译
    • Keil包含头文件路径
      FreeRTOS+STM32F103系列--1.移植

    • 添加编译宏
      STM32F10X_HD,USE_STDPERIPH_DRIVER
      记得添加宏不然一堆错误。

5.修改启动文件 startup_stm32f10x_hd.s

根据Cortex-M3权威指南(中文).pdf中断和异常介绍
FreeRTOS+STM32F103系列--1.移植

   Cortex-M3提供了16个内部异常中断源,前文讲了“ARMCortex-M用户需要特别注意:ARM Cortex-M3,ARM Cortex-M4,ARM Cortex-M4F ports需要在SysTick,PenSV和SVCCall中断向量上安装FreeRTOS handlers”。将启动文件中SysTick,PenSV和SVCCall对应的三个回调函数替换成FreeRTOS提供回调函数。
替换SVC_HandlervPortSVCHandler
替换PendSV_HandlerxPortPendSVHandler
替换SysTick_HandlerxPortSysTickHandler
这三个中断处理函数包含在port.c里。
FreeRTOS+STM32F103系列--1.移植
因为这三个函数是引用外部函数所以要先包含进去:
FreeRTOS+STM32F103系列--1.移植

6.代码实现

 程序说明:创建一个任务用来闪烁LED灯。

#include "FreeRTOS.h"
#include "task.h"

/* Library includes. */
#include "stm32f10x.h"

void vLED_Init(void)
{

 GPIO_InitTypeDef  GPIO_InitStructure;

 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);  //使能PB,PE端口时钟

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;               //LED0-->PB.5 端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;        //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       //IO口速度为50MHz
 GPIO_Init(GPIOB, &GPIO_InitStructure);                  //根据设定参数初始化GPIOB.5
 GPIO_SetBits(GPIOB,GPIO_Pin_5);                         //PB.5 输出高

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;               //LED1-->PE.5 端口配置, 推挽输出
 GPIO_Init(GPIOE, &GPIO_InitStructure);                  //推挽输出 ,IO口速度为50MHz
 GPIO_SetBits(GPIOE,GPIO_Pin_5);                         //PE.5 输出高 
}

void vLed0_task(void *pvParameters)
{
    while(1) {
        GPIO_SetBits(GPIOB,GPIO_Pin_5);
        vTaskDelay(500 / portTICK_PERIOD_MS);
        GPIO_ResetBits(GPIOB,GPIO_Pin_5);
        vTaskDelay(500 / portTICK_PERIOD_MS);
    }
}

int main(void)
{       
    vLED_Init();

    //创建开始任务
    xTaskCreate(vLed0_task, "led0_task",     configMINIMAL_STACK_SIZE, NULL, 3, NULL);

    vTaskStartScheduler();          //开启任务调度

    return 0;
}

编译、下载即可看到LED灯闪烁,最简单的FreeRTOS就移植成功了。

7.总结

   摸索了几个小时终于在STM32上运行起来FreeRTOS了,开始移植老是失败,对比Demo程序也没有发现错误所在,后来研究了下Cortex-M3权威指南(中文).pdf中断向量表介绍再对比了一下移植程序终于知道问题所在,原来是中断向量表没有配置对,配置过后问题迎刃而解。
   FreeRTOS在STM32移植还是比较容易的,如果做过裸机程序直接把工程照搬过来,把FreeRTOS内核拷贝过来,将FreeRTOS源文件和头文件添加到工程中,修改STM32启动文件,工程就顺利跑起来了。
  移植成功了,接下来可以探索它背后的原理了。特意移植了一个最精简的工程,方便后面分析启动原理和代码分析。

代码链接

8.参考资料

FreeRTOS官网
Cortex-M3权威指南(中文).pdf