[导读] 大家好,我是逸珺。
之前挖了图解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,这个带多种移植好的例子。解压出来,是这样的:
- Demo:大部分硬件平台的官方移植例子
- Source:内核代码,包含硬件独立文件与可移植文件
- Test:内核测试代码
- license:MIT开源协议,可以直接商业应用。
建立工程
1.打开IAR,创建Workspace
2.创建工程
选择空工程(Empty project),命名为demo保存。
-
设置工程
右键选择Options,进入设置界面
-
设置单片机为STM32F407VG
-
Library Configuration使能CMSIS
-
添加源文件
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是内核配置文件,本文配置如下:
-
#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相关文件搬过来,如下加入到工程
-
建立main.c
正点原子的板子,有两个LED,我们就建立两个任务来闪灯吧,相当于hello world,容易理解。
-
/*操作系统头文件.*/ #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++编译器包含路径
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 设置汇编器包含路径
6. 设置链接配置文件
注:如果遇到下面的错误,应该是你使用了老版本的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/
编译运行
下载运行
闪灯效果
总结一下
官方的例子,要直接拿来开发产品有很多不需要的文件,可以按照本文的步骤做些删减,先建立这样一个基本工程,然后就可以结合自己的实际硬件以及需求,开始做应用开发了。
审核编辑 :李倩
-
STM32
+关注
关注
2239文章
10671浏览量
348720 -
FreeRTOS
+关注
关注
12文章
473浏览量
61346
原文标题:手把手教你在STM32F4上跑freeRTOS
文章出处:【微信号:zhuyandz,微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论