[導(dǎo)讀] 大家好,我是逸珺。
之前挖了圖解freeRTOS的坑,挖了坑就得填。今天就從使用開始,先把freeRTOS用起來。先聊一聊在STM32F407上的如何電燈,如果只用freeRTOS點燈,無疑有點殺雞用牛刀的感覺。但是想用freeRTOS做產(chǎn)品,先照類似步驟則可以驗證最小系統(tǒng),驗證freeRTOS是否能正確跑起來,再在此基礎(chǔ)上開始做應(yīng)用開發(fā),就把任務(wù)分解了。本文主要梳理一下如何利用官方移植例子,創(chuàng)建一個自己demo工程,對于沒用過的有點參考價值。
注:本文基于IAR for ARM 8.22.1(個人喜歡IAR),硬件采用正點原子的STM32F407探索者開發(fā)板,STLink V2。
準(zhǔn)備工作
去官網(wǎng)https://www.freertos.org/a00104.html下載:
按圖中所示下載,目前最新為202104.00,這個帶多種移植好的例子。解壓出來,是這樣的:
- tools為AWS iot配置工具,quick start例子以及cmake
- FreeRTOS-Plus包含了MQTT,TCP,F(xiàn)AT等很多例子,先不去管
- FreeRTOS為真正的操作系統(tǒng)源碼以及多平臺移植例子,如下:
- Demo:大部分硬件平臺的官方移植例子
- Source:內(nèi)核代碼,包含硬件獨立文件與可移植文件
- Test:內(nèi)核測試代碼
- 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文件夾,將下列文件拷貝過來
4.3 添加進(jìn)IAR工程
4.4 將freeRTOS下的include文件夾以及portable文件夾拷貝到當(dāng)前工程下
4.5 portable文件夾下保留下面這幾個文件夾
4.6 IAR文件夾下保留下面這兩個文件夾
注:全保留也可以,就是其他的用不到,會使工程文件夾變的很大,如果用版本控制軟件管理,會增加倉庫的大小。ARM_CM4F_MPU文件夾暫時沒用,這個留做備用。
4.7 在IAR工程中新建portable文件夾,并加入相應(yīng)的文件
4.8 將下面幾個文件從官方例子中拷貝過來,并加入工程
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)注這兩個功能。
-
將STM32相關(guān)文件搬過來,如下加入到工程
-
建立main.c
正點原子的板子,有兩個LED,我們就建立兩個任務(wù)來閃燈吧,相當(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時能時鐘*/ 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優(yōu)先級.*/ 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); /*啟動任務(wù)調(diào)度器.*/ vTaskStartScheduler(); }
5.設(shè)置包含路徑
5.1 右鍵打開options,設(shè)置C/C++編譯器包含路徑
5.2 設(shè)置包含路徑為:
$PROJECT_DIR$是一個變量,表示當(dāng)前路徑,不要設(shè)成絕對路徑,否則拷貝到不同路徑就無法編譯了。
-
$PROJ_DIR$ $PROJ_DIR$halCMSISDeviceSTSTM32F4xxInclude $PROJ_DIR$halSTM32F4xx_StdPeriph_Driverinc $PROJ_DIR$freeRTOSinclude $PROJ_DIR$freeRTOSportableIARARM_CM4F $PROJ_DIR$Commoninclude示當(dāng)前工程目錄,利用這個變量就可以設(shè)置和工程相關(guān)的路徑了,不要設(shè)置為絕對路徑,否則如果工程拷貝到其他路徑,就無法正確編譯了。
并設(shè)置兩個宏:
USE_STDPERIPH_DRIVER STM32F4XX
5.3 設(shè)置匯編器包含路徑
6. 設(shè)置鏈接配置文件
注:如果遇到下面的錯誤,應(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/
編譯運行
下載運行
閃燈效果
總結(jié)一下
官方的例子,要直接拿來開發(fā)產(chǎn)品有很多不需要的文件,可以按照本文的步驟做些刪減,先建立這樣一個基本工程,然后就可以結(jié)合自己的實際硬件以及需求,開始做應(yīng)用開發(fā)了。
審核編輯 :李倩
-
STM32
+關(guān)注
關(guān)注
2270文章
10915瀏覽量
356751 -
FreeRTOS
+關(guān)注
關(guān)注
12文章
484瀏覽量
62274
原文標(biāo)題:手把手教你在STM32F4上跑freeRTOS
文章出處:【微信號:zhuyandz,微信公眾號:FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論