博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
手把手教你在STM32F4上跑freeRTOS!
阅读量:2125 次
发布时间:2019-04-30

本文共 5511 字,大约阅读时间需要 18 分钟。

[导读] 大家好,我是逸珺。

之前挖了图解freeRTOS的坑,挖了坑就得填。今天就从使用开始,先把freeRTOS用起来。先聊一聊在STM32F407上的如何电灯,如果只用freeRTOS点灯,无疑有点杀鸡用牛刀的感觉。但是想用freeRTOS做产品,先照类似步骤则可以验证最小系统,验证freeRTOS是否能正确跑起来,再在此基础上开始做应用开发,就把任务分解了。本文主要梳理一下如何利用官方移植例子,创建一个自己demo工程,对于没用过的有点参考价值。

注:本文基于IAR for ARM 8.22.1(个人喜欢IAR),硬件采用正点原子的STM32F407探索者开发板,STLink V2。

准备工作

去官网https://www.freertos.org/a00104.html下载:

按图中所示下载,目前最新为202104.00,这个带多种移植好的例子。解压出来,是这样的:

  • tools为AWS iot配置工具,quick start例子以及cmake

  • FreeRTOS-Plus包含了MQTT,TCP,FAT等很多例子,先不去管

  • FreeRTOS为真正的操作系统源码以及多平台移植例子,如下:

使用开源软件,记得看看README,一般会有些介绍信息。分别介绍一下该文件夹下的大体内容:
  1. Demo:大部分硬件平台的官方移植例子

  2. Source:内核代码,包含硬件独立文件与可移植文件

  3. Test:内核测试代码

  4. license:MIT开源协议,可以直接商业应用。

建立工程

1.打开IAR,创建Workspace

2.创建工程

选择空工程(Empty project),命名为demo保存。

  1. 设置工程

    右键选择Options,进入设置界面设置单片机为STM32F407VGLibrary Configuration使能CMSIS

  2. 添加源文件

    4.1 新建freeRTOS文件夹4.2 添加内核文件,在工程文件夹下新建freeRTOS文件夹,将下列文件拷贝过来

4.3 添加进IAR工程

4.4 将freeRTOS下的include文件夹以及portable文件夹拷贝到当前工程下

4.5 portable文件夹下保留下面这几个文件夹

4.6 IAR文件夹下保留下面这两个文件夹

注:全保留也可以,就是其他的用不到,会使工程文件夹变的很大,如果用版本控制软件管理,会增加仓库的大小。ARM_CM4F_MPU文件夹暂时没用,这个留做备用。

4.7 在IAR工程中新建portable文件夹,并加入相应的文件

4.8 将下面几个文件从官方例子中拷贝过来,并加入工程

FreeRTOSConfig.h是内核配置文件,本文配置如下:

  • #define configUSE_PREEMPTION   1#define configUSE_IDLE_HOOK    0#define configUSE_TICK_HOOK    0#define configCPU_CLOCK_HZ    ( SystemCoreClock )#define configTICK_RATE_HZ    ( ( TickType_t ) 1000 )#define configMAX_PRIORITIES   ( 5 )#define configMINIMAL_STACK_SIZE  ( ( unsigned short ) 130 )#define configTOTAL_HEAP_SIZE   ( ( size_t ) ( 75 * 1024 ) )#define configMAX_TASK_NAME_LEN   ( 10 )#define configUSE_TRACE_FACILITY  1#define configUSE_16_BIT_TICKS   0#define configIDLE_SHOULD_YIELD   1#define configUSE_MUTEXES    1#define configQUEUE_REGISTRY_SIZE  8#define configCHECK_FOR_STACK_OVERFLOW 0#define configUSE_RECURSIVE_MUTEXES  1#define configUSE_MALLOC_FAILED_HOOK 0#define configUSE_APPLICATION_TASK_TAG 0#define configUSE_COUNTING_SEMAPHORES 1#define configGENERATE_RUN_TIME_STATS 0/* Co-routine definitions. */#define configUSE_CO_ROUTINES   0#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )/* Software timer definitions. */#define configUSE_TIMERS    1#define configTIMER_TASK_PRIORITY  ( 2 )#define configTIMER_QUEUE_LENGTH  10#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 )/* Set the following definitions to 1 to include the API function, or zeroto exclude the API function. */#define INCLUDE_vTaskPrioritySet  1#define INCLUDE_uxTaskPriorityGet  1#define INCLUDE_vTaskDelete    1#define INCLUDE_vTaskCleanUpResources 1#define INCLUDE_vTaskSuspend   1#define INCLUDE_vTaskDelayUntil   1#define INCLUDE_vTaskDelay    1

    将IDLE_HOOK/TICK_HOOK禁止了,先不去关注这两个功能。

  • 将STM32相关文件搬过来,如下加入到工程

  • 建立main.c

    正点原子的板子,有两个LED,我们就建立两个任务来闪灯吧,相当于hello world,容易理解。

    /* 操作系统头文件. */#include "FreeRTOS.h"#include "task.h"#include "timers.h"#include "semphr.h"#include "stm32f4xx.h"//LED管脚#define LED1_PIN        GPIO_Pin_9#define LED1_GPIO_PORT    GPIOF#define LED1_GPIO_CLK     RCC_AHB1Periph_GPIOF    #define LED2_PIN       GPIO_Pin_10#define LED2_GPIO_PORT    GPIOF#define LED2_GPIO_CLK    RCC_AHB1Periph_GPIOF  static void prvLedInitialise(){  GPIO_InitTypeDef  GPIO_InitStructure;    /* LED1时能时钟 */  RCC_AHB1PeriphClockCmd(LED1_GPIO_CLK, ENABLE);  /* LED1 GPIO 配置为输出 */  GPIO_InitStructure.GPIO_Pin = LED1_PIN;  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStructure);      /* LED2时能时钟 */  RCC_AHB1PeriphClockCmd(LED2_GPIO_CLK, ENABLE);  /* LED2 GPIO配置为输出 */  GPIO_InitStructure.GPIO_Pin = LED2_PIN;  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  GPIO_Init(LED2_GPIO_PORT, &GPIO_InitStructure);    }static void prvSetupHardware( void ){  /* 配置时钟,PLL,FLASH */  SystemInit();  /* 配置NVIC优先级. */  NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );      /*LED GPIO配置*/  prvLedInitialise();}//500ms LED1灯状态翻转一次static void led1Task( void * pvParameters ){  while(1)  {     LED1_GPIO_PORT->ODR ^= LED1_PIN;     vTaskDelay(500);  }}//1000ms LED2灯状态翻转一次static void led2Task( void * pvParameters ){  while(1)  {    LED2_GPIO_PORT->ODR ^= LED2_PIN;    vTaskDelay(1000);  }}int main(void){  prvSetupHardware();      xTaskCreate(led1Task,"LED1",256,NULL,100,(TaskHandle_t *)NULL);  xTaskCreate(led2Task,"LED2",256,NULL,101,(TaskHandle_t *)NULL);      /* 启动任务调度器. */  vTaskStartScheduler();    }

5.设置包含路径

5.1 右键打开options,设置C/C++编译器包含路径

5.2 设置包含路径为:

$PROJECT_DIR$是一个变量,表示当前路径,不要设成绝对路径,否则拷贝到不同路径就无法编译了。

  • $PROJ_DIR$\$PROJ_DIR$\hal\CMSIS\Device\ST\STM32F4xx\Include$PROJ_DIR$\hal\STM32F4xx_StdPeriph_Driver\inc$PROJ_DIR$\freeRTOS\include$PROJ_DIR$\freeRTOS\portable\IAR\ARM_CM4F$PROJ_DIR$\Common\include示当前工程目录,利用这个变量就可以设置和工程相关的路径了,不要设置为绝对路径,否则如果工程拷贝到其他路径,就无法正确编译了。

    并设置两个宏:

    USE_STDPERIPH_DRIVERSTM32F4XX

5.3 设置汇编器包含路径

6. 设置链接配置文件

注:如果遇到下面的错误,应该是你使用了老版本的startup_stm32f4xx.s

Warning[25]: Label 'CAN2_SCE_IRQHandler' is defined pubweak in a p implicitly declared root 

官方例子中下面路径的startup_stm32f4xx.s为老版本

CMSIS\Device\ST\STM32F4xx\Source\Templates\iar

该警告详细信息可参考:

https://www.iar.com/knowledge/support/technical-notes/assembler/warning25-label-xxxxx-is-defined-pubweak-in-a-p-implicitly-declared-root/

编译运行

设置ST-Link

下载运行

闪灯效果

总结一下

官方的例子,要直接拿来开发产品有很多不需要的文件,可以按照本文的步骤做些删减,先建立这样一个基本工程,然后就可以结合自己的实际硬件以及需求,开始做应用开发了。

免责声明:本文系网络转载,版权归原作者所有。如涉及作品版权问题,请与我们联系,我们将根据您提供的版权证明材料确认版权并支付稿酬或者删除内容。

你可能感兴趣的文章
C++/C 宏定义(define)中# ## 的含义 宏拼接
查看>>
Git安装配置
查看>>
linux中fork()函数详解
查看>>
C语言字符、字符串操作偏僻函数总结
查看>>
Git的Patch功能
查看>>
分析C语言的声明
查看>>
TCP为什么是三次握手,为什么不是两次或者四次 && TCP四次挥手
查看>>
C结构体、C++结构体、C++类的区别
查看>>
进程和线程的概念、区别和联系
查看>>
CMake 入门实战
查看>>
绑定CPU逻辑核心的利器——taskset
查看>>
Linux下perf性能测试火焰图只显示函数地址不显示函数名的问题
查看>>
c结构体、c++结构体和c++类的区别以及错误纠正
查看>>
Linux下查看根目录各文件内存占用情况
查看>>
A星算法详解(个人认为最详细,最通俗易懂的一个版本)
查看>>
利用栈实现DFS
查看>>
逆序对的数量(递归+归并思想)
查看>>
数的范围(二分查找上下界)
查看>>
算法导论阅读顺序
查看>>
Windows程序设计:直线绘制
查看>>