手把手教你在STM32F4上跑freeRTOS

原创 嵌入式客栈 2021-07-02 07:30
关注、星标嵌入式客栈,精彩及时送达

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

之前挖了图解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 zero
    to 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_DRIVER
    STM32F4XX

5.3 设置汇编器包含路径

6. 设置链接配置文件

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

Warning[25]: Label 'CAN2_SCE_IRQHandler' is defined pubweak in a section 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-section-implicitly-declared-root/

编译运行

设置ST-Link

下载运行

闪灯效果

总结一下

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

如对本文例子工程有兴趣,可以后台回复“demo”,自行领取。

END
往期精彩推荐,点击即可阅读




深度解析U-Boot网络实现 
图解FreeRTOS原理系列之任务管理器基本框架
万变不离其宗之SPI总线要点总结
▲程序猿都应学习的语言:看25张图学UML
 ▲RS-485总线,这篇很详细
 ▲图文详解Modbus-RTU

嵌入式客栈 欢迎关注嵌入式客栈,主要分享嵌入式Linux系统构建、嵌入式linux驱动开发、单片机技术、FPGA开发、信号处理、工业通讯等技术主题。欢迎关注,一起交流,一起进步!
评论
  • 根据环洋市场咨询(Global Info Research)项目团队最新调研,预计2030年全球中空长航时无人机产值达到9009百万美元,2024-2030年期间年复合增长率CAGR为8.0%。 环洋市场咨询机构出版了的【全球中空长航时无人机行业总体规模、主要厂商及IPO上市调研报告,2025-2031】研究全球中空长航时无人机总体规模,包括产量、产值、消费量、主要生产地区、主要生产商及市场份额,同时分析中空长航时无人机市场主要驱动因素、阻碍因素、市场机遇、挑战、新产品发布等。报告从中空长航时
    GIRtina 2025-01-09 10:35 56浏览
  • 1月7日-10日,2025年国际消费电子产品展览会(CES 2025)盛大举行,广和通发布Fibocom AI Stack,赋智千行百业端侧应用。Fibocom AI Stack提供集高性能模组、AI工具链、高性能推理引擎、海量模型、支持与服务一体化的端侧AI解决方案,帮助智能设备快速实现AI能力商用。为适应不同端侧场景的应用,AI Stack具备海量端侧AI模型及行业端侧模型,基于不同等级算力的芯片平台或模组,Fibocom AI Stack可将TensorFlow、PyTorch、ONNX、
    物吾悟小通 2025-01-08 18:17 52浏览
  • 在过去十年中,自动驾驶和高级驾驶辅助系统(AD/ADAS)软件与硬件的快速发展对多传感器数据采集的设计需求提出了更高的要求。然而,目前仍缺乏能够高质量集成多传感器数据采集的解决方案。康谋ADTF正是应运而生,它提供了一个广受认可和广泛引用的软件框架,包含模块化的标准化应用程序和工具,旨在为ADAS功能的开发提供一站式体验。一、ADTF的关键之处!无论是奥迪、大众、宝马还是梅赛德斯-奔驰:他们都依赖我们不断发展的ADTF来开发智能驾驶辅助解决方案,直至实现自动驾驶的目标。从新功能的最初构思到批量生
    康谋 2025-01-09 10:04 55浏览
  • HDMI 2.2 规格将至,开启视听新境界2025年1月6日,HDMI Forum, Inc. 宣布即将发布HDMI规范2.2版本。新HDMI规范为规模庞大的 HDMI 生态系统带来更多选择,为创建、分发和体验理想的终端用户效果提供更先进的解决方案。新技术为电视、电影和游戏工作室等内容制作商在当前和未来提供更高质量的选择,同时实现多种分发平台。96Gbps的更高带宽和新一代 HDMI 固定比率速率传输(Fixed Rate Link)技术为各种设备应用提供更优质的音频和视频。终端用户显示器能以最
    百佳泰测试实验室 2025-01-09 17:33 55浏览
  • 故障现象一辆2017款东风风神AX7车,搭载DFMA14T发动机,累计行驶里程约为13.7万km。该车冷起动后怠速运转正常,热机后怠速运转不稳,组合仪表上的发动机转速表指针上下轻微抖动。 故障诊断 用故障检测仪检测,发动机控制单元中无故障代码存储;读取发动机数据流,发现进气歧管绝对压力波动明显,有时能达到69 kPa,明显偏高,推断可能的原因有:进气系统漏气;进气歧管绝对压力传感器信号失真;发动机机械故障。首先从节气门处打烟雾,没有发现进气管周围有漏气的地方;接着拔下进气管上的两个真空
    虹科Pico汽车示波器 2025-01-08 16:51 107浏览
  • 光伏逆变器是一种高效的能量转换设备,它能够将光伏太阳能板(PV)产生的不稳定的直流电压转换成与市电频率同步的交流电。这种转换后的电能不仅可以回馈至商用输电网络,还能供独立电网系统使用。光伏逆变器在商业光伏储能电站和家庭独立储能系统等应用领域中得到了广泛的应用。光耦合器,以其高速信号传输、出色的共模抑制比以及单向信号传输和光电隔离的特性,在光伏逆变器中扮演着至关重要的角色。它确保了系统的安全隔离、干扰的有效隔离以及通信信号的精准传输。光耦合器的使用不仅提高了系统的稳定性和安全性,而且由于其低功耗的
    晶台光耦 2025-01-09 09:58 43浏览
  • 在当前人工智能(AI)与物联网(IoT)的快速发展趋势下,各行各业的数字转型与自动化进程正以惊人的速度持续进行。如今企业在设计与营运技术系统时所面临的挑战不仅是技术本身,更包含硬件设施、第三方软件及配件等复杂的外部因素。然而这些系统往往讲究更精密的设计与高稳定性,哪怕是任何一个小小的问题,都可能对整体业务运作造成严重影响。 POS应用环境与客户需求以本次分享的客户个案为例,该客户是一家全球领先的信息技术服务与数字解决方案提供商,遭遇到一个由他们所开发的POS机(Point of Sal
    百佳泰测试实验室 2025-01-09 17:35 52浏览
  • 一个真正的质量工程师(QE)必须将一件产品设计的“意图”与系统的可制造性、可服务性以及资源在现实中实现设计和产品的能力结合起来。所以,可以说,这确实是一种工程学科。我们常开玩笑说,质量工程师是工程领域里的「侦探」、「警察」或「律师」,守护神是"墨菲”,信奉的哲学就是「墨菲定律」。(注:墨菲定律是一种启发性原则,常被表述为:任何可能出错的事情最终都会出错。)做质量工程师的,有时会不受欢迎,也会被忽视,甚至可能遭遇主动或被动的阻碍,而一旦出了问题,责任往往就落在质量工程师的头上。虽然质量工程师并不负
    优思学院 2025-01-09 11:48 79浏览
  • 职场是人生的重要战场,既是谋生之地,也是实现个人价值的平台。然而,有些思维方式却会悄无声息地拖住你的后腿,让你原地踏步甚至退步。今天,我们就来聊聊职场中最忌讳的五种思维方式,看看自己有没有中招。1. 固步自封的思维在职场中,最可怕的事情莫过于自满于现状,拒绝学习和改变。世界在不断变化,行业的趋势、技术的革新都在要求我们与时俱进。如果你总觉得自己的方法最优,或者害怕尝试新事物,那就很容易被淘汰。与其等待机会找上门,不如主动出击,保持学习和探索的心态。加入优思学院,可以帮助你快速提升自己,与行业前沿
    优思学院 2025-01-09 15:48 46浏览
  • 在智能网联汽车中,各种通信技术如2G/3G/4G/5G、GNSS(全球导航卫星系统)、V2X(车联网通信)等在行业内被广泛使用。这些技术让汽车能够实现紧急呼叫、在线娱乐、导航等多种功能。EMC测试就是为了确保在复杂电磁环境下,汽车的通信系统仍然可以正常工作,保护驾乘者的安全。参考《QCT-基于LTE-V2X直连通信的车载信息交互系统技术要求及试验方法-1》标准10.5电磁兼容试验方法,下面将会从整车功能层面为大家解读V2X整车电磁兼容试验的过程。测试过程揭秘1. 设备准备为了进行电磁兼容试验,技
    北汇信息 2025-01-09 11:24 65浏览
我要评论
4
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦