[導(dǎo)讀] 大家好,我是逸珺。
之前挖了圖解freeRTOS的坑,挖了坑就得填。今天就從使用開始,先把freeRTOS用起來(lái)。先聊一聊在STM32F407上的如何電燈,如果只用freeRTOS點(diǎn)燈,無(wú)疑有點(diǎn)殺雞用牛刀的感覺(jué)。但是想用freeRTOS做產(chǎn)品,先照類似步驟則可以驗(yàn)證最小系統(tǒng),驗(yàn)證freeRTOS是否能正確跑起來(lái),再在此基礎(chǔ)上開始做應(yīng)用開發(fā),就把任務(wù)分解了。本文主要梳理一下如何利用官方移植例子,創(chuàng)建一個(gè)自己demo工程,對(duì)于沒(méi)用過(guò)的有點(diǎn)參考價(jià)值。
注:本文基于IAR for ARM 8.22.1(個(gè)人喜歡IAR),硬件采用正點(diǎn)原子的STM32F407探索者開發(fā)板,STLink V2。
準(zhǔn)備工作
去官網(wǎng)https://www.freertos.org/a00104.html下載:

按圖中所示下載,目前最新為202104.00,這個(gè)帶多種移植好的例子。解壓出來(lái),是這樣的:

- tools為AWS iot配置工具,quick start例子以及cmake
- FreeRTOS-Plus包含了MQTT,TCP,F(xiàn)AT等很多例子,先不去管
- FreeRTOS為真正的操作系統(tǒng)源碼以及多平臺(tái)移植例子,如下:

- Demo:大部分硬件平臺(tái)的官方移植例子
- Source:內(nèi)核代碼,包含硬件獨(dú)立文件與可移植文件
- Test:內(nèi)核測(cè)試代碼
- license:MIT開源協(xié)議,可以直接商業(yè)應(yīng)用。
建立工程
1.打開IAR,創(chuàng)建Workspace

2.創(chuàng)建工程

選擇空工程(Empty project),命名為demo保存。

-
設(shè)置工程
右鍵選擇Options,進(jìn)入設(shè)置界面

-
設(shè)置單片機(jī)為STM32F407VG

-
Library Configuration使能CMSIS

-
添加源文件
4.1 新建freeRTOS文件夾

-
4.2 添加內(nèi)核文件,在工程文件夾下新建freeRTOS文件夾,將下列文件拷貝過(guò)來(lái)

4.3 添加進(jìn)IAR工程

4.4 將freeRTOS下的include文件夾以及portable文件夾拷貝到當(dāng)前工程下

4.5 portable文件夾下保留下面這幾個(gè)文件夾

4.6 IAR文件夾下保留下面這兩個(gè)文件夾

注:全保留也可以,就是其他的用不到,會(huì)使工程文件夾變的很大,如果用版本控制軟件管理,會(huì)增加倉(cāng)庫(kù)的大小。ARM_CM4F_MPU文件夾暫時(shí)沒(méi)用,這個(gè)留做備用。
4.7 在IAR工程中新建portable文件夾,并加入相應(yīng)的文件

4.8 將下面幾個(gè)文件從官方例子中拷貝過(guò)來(lái),并加入工程

FreeRTOSConfig.h是內(nèi)核配置文件,本文配置如下:
-
#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禁止了,先不去關(guān)注這兩個(gè)功能。
-
將STM32相關(guān)文件搬過(guò)來(lái),如下加入到工程

-
建立main.c
正點(diǎn)原子的板子,有兩個(gè)LED,我們就建立兩個(gè)任務(wù)來(lái)閃燈吧,相當(dāng)于hello world,容易理解。

-
/*操作系統(tǒng)頭文件.*/ #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時(shí)能時(shí)鐘*/ 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時(shí)能時(shí)鐘*/ 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) { /*配置時(shí)鐘,PLL,FLASH*/ SystemInit(); /*配置NVIC優(yōu)先級(jí).*/ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); /*LEDGPIO配置*/ prvLedInitialise(); } //500msLED1燈狀態(tài)翻轉(zhuǎn)一次 staticvoidled1Task(void*pvParameters) { while(1) { LED1_GPIO_PORT->ODR^=LED1_PIN; vTaskDelay(500); } } //1000msLED2燈狀態(tài)翻轉(zhuǎn)一次 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); /*啟動(dòng)任務(wù)調(diào)度器.*/ vTaskStartScheduler(); }
5.設(shè)置包含路徑
5.1 右鍵打開options,設(shè)置C/C++編譯器包含路徑

5.2 設(shè)置包含路徑為:
$PROJECT_DIR$是一個(gè)變量,表示當(dāng)前路徑,不要設(shè)成絕對(duì)路徑,否則拷貝到不同路徑就無(wú)法編譯了。
-
$PROJ_DIR$ $PROJ_DIR$halCMSISDeviceSTSTM32F4xxInclude $PROJ_DIR$halSTM32F4xx_StdPeriph_Driverinc $PROJ_DIR$freeRTOSinclude $PROJ_DIR$freeRTOSportableIARARM_CM4F $PROJ_DIR$Commoninclude示當(dāng)前工程目錄,利用這個(gè)變量就可以設(shè)置和工程相關(guān)的路徑了,不要設(shè)置為絕對(duì)路徑,否則如果工程拷貝到其他路徑,就無(wú)法正確編譯了。并設(shè)置兩個(gè)宏:
USE_STDPERIPH_DRIVER STM32F4XX
5.3 設(shè)置匯編器包含路徑

6. 設(shè)置鏈接配置文件

注:如果遇到下面的錯(cuò)誤,應(yīng)該是你使用了老版本的startup_stm32f4xx.s
Warning[25]:Label'CAN2_SCE_IRQHandler'isdefinedpubweakinasectionimplicitlydeclaredroot
官方例子中下面路徑的startup_stm32f4xx.s為老版本
CMSISDeviceSTSTM32F4xxSourceTemplatesiar
該警告詳細(xì)信息可參考:
https://www.iar.com/knowledge/support/technical-notes/assembler/warning25-label-xxxxx-is-defined-pubweak-in-a-section-implicitly-declared-root/
編譯運(yùn)行


下載運(yùn)行


閃燈效果
總結(jié)一下
官方的例子,要直接拿來(lái)開發(fā)產(chǎn)品有很多不需要的文件,可以按照本文的步驟做些刪減,先建立這樣一個(gè)基本工程,然后就可以結(jié)合自己的實(shí)際硬件以及需求,開始做應(yīng)用開發(fā)了。
審核編輯 :李倩
-
STM32
+關(guān)注
關(guān)注
2313文章
11195瀏覽量
374723 -
FreeRTOS
+關(guān)注
關(guān)注
14文章
499瀏覽量
67285
原文標(biāo)題:手把手教你在STM32F4上跑freeRTOS
文章出處:【微信號(hào):zhuyandz,微信公眾號(hào):FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
基于極海APM32F4的Azure RTOS ThreadX移植過(guò)程分享
如何利用官方移植例子,創(chuàng)建一個(gè)自己demo工程
評(píng)論