在STM32F4上跑freeRTOS

原文链接:手把手教你在STM32F4上跑freeRTOS

之前挖了图解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保存。

在这里插入图片描述
3.设置工程

右键选择Options,进入设置界面
在这里插入图片描述
设置单片机为STM32F407VG
在这里插入图片描述
Library Configuration使能CMSIS
在这里插入图片描述
4.添加源文件
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 设置包含路径为:

P R O J E C T D I R PROJECT_DIR PROJECTDIR是一个变量,表示当前路径,不要设成绝对路径,否则拷贝到不同路径就无法编译了。


$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 设置汇编器包含路径
在这里插入图片描述

  1. 设置链接配置文件
    在这里插入图片描述

注:如果遇到下面的错误,应该是你使用了老版本的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
在这里插入图片描述
下载运行
在这里插入图片描述
在这里插入图片描述

总结一下

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

版权归原作者所有,如有侵权,请联系删除。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值