如何利用官方移植例子,创建一个自己demo工程

2024-02-23  

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


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


准备工作

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

3f84380c-d57a-11ec-bce3-dac502259ad0.png

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

3fc0ecc0-d57a-11ec-bce3-dac502259ad0.png

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

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

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

3fdfc8ca-d57a-11ec-bce3-dac502259ad0.png

使用开源软件,记得看看README,一般会有些介绍信息。分别介绍一下该文件夹下的大体内容:

  1. Demo:大部分硬件平台的官方移植例子

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

  3. Test:内核测试代码

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

建立工程

1.打开IAR,创建Workspace

4004a492-d57a-11ec-bce3-dac502259ad0.png

2.创建工程

4026655a-d57a-11ec-bce3-dac502259ad0.png

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

403f24d2-d57a-11ec-bce3-dac502259ad0.png

  1. 设置工程

    右键选择Options,进入设置界面

40971fe8-d57a-11ec-bce3-dac502259ad0.png

  1. 设置单片机为STM32F407VG

40b95f0e-d57a-11ec-bce3-dac502259ad0.png

  1. Library Configuration使能CMSIS

411f1344-d57a-11ec-bce3-dac502259ad0.png


  1. 添加源文件

    4.1 新建freeRTOS文件夹

413479e6-d57a-11ec-bce3-dac502259ad0.png

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

4150a13e-d57a-11ec-bce3-dac502259ad0.png

4.3 添加进IAR工程

417146f0-d57a-11ec-bce3-dac502259ad0.png

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

418f0550-d57a-11ec-bce3-dac502259ad0.png

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

41a7a448-d57a-11ec-bce3-dac502259ad0.png

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

41bc3ff2-d57a-11ec-bce3-dac502259ad0.png

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

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

41eb619c-d57a-11ec-bce3-dac502259ad0.png

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

4221da06-d57a-11ec-bce3-dac502259ad0.png

#defineconfigUSE_PREEMPTION1

#defineconfigUSE_IDLE_HOOK0

#defineconfigUSE_TICK_HOOK0

#defineconfigCPU_CLOCK_HZ(SystemCoreClock)

#defineconfigTICK_RATE_HZ((TickType_t)1000)

#defineconfigMAX_PRIORITIES(5)

#defineconfigMINIMAL_STACK_SIZE((unsignedshort)130)

#defineconfigTOTAL_HEAP_SIZE((size_t)(75*1024))

#defineconfigMAX_TASK_NAME_LEN(10)

#defineconfigUSE_TRACE_FACILITY1

#defineconfigUSE_16_BIT_TICKS0

#defineconfigIDLE_SHOULD_YIELD1

#defineconfigUSE_MUTEXES1

#defineconfigQUEUE_REGISTRY_SIZE8

#defineconfigCHECK_FOR_STACK_OVERFLOW0

#defineconfigUSE_RECURSIVE_MUTEXES1

#defineconfigUSE_MALLOC_FAILED_HOOK0

#defineconfigUSE_APPLICATION_TASK_TAG0

#defineconfigUSE_COUNTING_SEMAPHORES1

#defineconfigGENERATE_RUN_TIME_STATS0


/*Co-routinedefinitions.*/

#defineconfigUSE_CO_ROUTINES0

#defineconfigMAX_CO_ROUTINE_PRIORITIES(2)


/*Softwaretimerdefinitions.*/

#defineconfigUSE_TIMERS1

#defineconfigTIMER_TASK_PRIORITY(2)

#defineconfigTIMER_QUEUE_LENGTH10

#defineconfigTIMER_TASK_STACK_DEPTH(configMINIMAL_STACK_SIZE*2)


/*Setthefollowingdefinitionsto1toincludetheAPIfunction,orzero

toexcludetheAPIfunction.*/

#defineINCLUDE_vTaskPrioritySet1

#defineINCLUDE_uxTaskPriorityGet1

#defineINCLUDE_vTaskDelete1

#defineINCLUDE_vTaskCleanUpResources1

#defineINCLUDE_vTaskSuspend1

#defineINCLUDE_vTaskDelayUntil1

#defineINCLUDE_vTaskDelay1

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


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

423ff356-d57a-11ec-bce3-dac502259ad0.png

  • 建立main.c

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

4258cf98-d57a-11ec-bce3-dac502259ad0.png

/*操作系统头文件.*/

#include"FreeRTOS.h"

#include"task.h"

#include"timers.h"

#include"semphr.h"


#include"stm32f4xx.h"

//LED管脚

#defineLED1_PIN GPIO_Pin_9

#defineLED1_GPIO_PORTGPIOF

#defineLED1_GPIO_CLKRCC_AHB1Periph_GPIOF


#defineLED2_PINGPIO_Pin_10

#defineLED2_GPIO_PORTGPIOF

#defineLED2_GPIO_CLKRCC_AHB1Periph_GPIOF


staticvoidprvLedInitialise()

{

GPIO_InitTypeDefGPIO_InitStructure;


/*LED1时能时钟*/

RCC_AHB1PeriphClockCmd(LED1_GPIO_CLK,ENABLE);

/*LED1GPIO配置为输出*/

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);

/*LED2GPIO配置为输出*/

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);

}


staticvoidprvSetupHardware(void)

{

/*配置时钟,PLL,FLASH*/

SystemInit();


/*配置NVIC优先级.*/

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);


/*LEDGPIO配置*/

prvLedInitialise();

}


//500msLED1灯状态翻转一次

staticvoidled1Task(void*pvParameters)

{

while(1)

{

LED1_GPIO_PORT->ODR^=LED1_PIN;

vTaskDelay(500);

}

}

//1000msLED2灯状态翻转一次

staticvoidled2Task(void*pvParameters)

{

while(1)

{

LED2_GPIO_PORT->ODR^=LED2_PIN;

vTaskDelay(1000);

}

}


intmain(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++编译器包含路径

42beec60-d57a-11ec-bce3-dac502259ad0.png

5.2 设置包含路径为:


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


$PROJ_DIR$

$PROJ_DIR$halCMSISDeviceSTSTM32F4xxInclude

$PROJ_DIR$halSTM32F4xx_StdPeriph_Driverinc

$PROJ_DIR$freeRTOSinclude

$PROJ_DIR$freeRTOSportableIARARM_CM4F

$PROJ_DIR$Commoninclude示当前工程目录,利用这个变量就可以设置和工程相关的路径了,不要设置为绝对路径,否则如果工程拷贝到其他路径,就无法正确编译了。

并设置两个宏:


USE_STDPERIPH_DRIVER

STM32F4XX


5.3 设置汇编器包含路径

42f4ff62-d57a-11ec-bce3-dac502259ad0.png

6. 设置链接配置文件

43207d7c-d57a-11ec-bce3-dac502259ad0.png

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

Warning[25]:Label'CAN2_SCE_IRQHandler'isdefinedpubweakinasectionimplicitlydeclaredroot


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

CMSISDeviceSTSTM32F4xxSourceTemplatesiar

该警告详细信息可参考:

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

编译运行

43389c04-d57a-11ec-bce3-dac502259ad0.png

设置ST-Link

43833a84-d57a-11ec-bce3-dac502259ad0.png

下载运行

43c49592-d57a-11ec-bce3-dac502259ad0.png

43e2e470-d57a-11ec-bce3-dac502259ad0.gif

闪灯效果

总结一下

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


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。