日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

STM32F103--移植FreeRTOS完整教程

發(fā)布時(shí)間:2023/12/14 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 STM32F103--移植FreeRTOS完整教程 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

最近按照正點(diǎn)原子教程開始學(xué)習(xí)FreeRTOS,發(fā)現(xiàn)其手冊(cè)的移植教程中有些地方可能不是那么詳細(xì),在此基于正點(diǎn)原子做一期最完整的FreeRTOS移植教程給大家。


小b將本次教程整理的資料放在網(wǎng)盤,以下鏈接供各位小伙伴下載和學(xué)習(xí):
鏈接:https://pan.baidu.com/s/1z74dzFtQ198XLJwYhOVWlw
提取碼:rson


  • 打開FreeRTOS.exe文件,等待些許時(shí)間獲取FreeRTOS源碼

  • 拷貝庫函數(shù)一個(gè)最簡(jiǎn)單的跑馬燈實(shí)驗(yàn)工程作為待移植工程文件,并在基礎(chǔ)工程中新建一個(gè)名為 FreeRTOS 的文件夾

  • 創(chuàng)建FreeRTOS文件夾之后將步驟1獲取到的FreeRTOS文件下的FreeRTOSv9.0.0->FreeRTOS->Source中的全部文件全部拷貝到創(chuàng)建文件夾下

  • 其中為了工程輕簡(jiǎn),protable文件夾下只留下以下三個(gè)文件夾:

  • 用keil打開工程文件,點(diǎn)擊所示圖標(biāo)新建兩個(gè)分組FreeRTOS_CORE 和 FreeRTOS_PORTABLE

  • 創(chuàng)建成功后左邊工程欄出現(xiàn)對(duì)應(yīng)兩個(gè)分組,雙擊添加對(duì)應(yīng)的文件如下圖所示,其中FreeRTOS_CORE中的文件為源碼直接打開可看到的.c文件,FreeRTOS_PORTABLE中的文件為port.c 是 RVDS 文件 夾下的 ARM_CM3 中的文件,因?yàn)?STM32F103 是 Cortex-M3 內(nèi)核的,因此要選擇 ARM_CM3 中的 port.c 文件,heap_4.c 是 MemMang 文件夾中的,因?yàn)閔eap_4 提供了一個(gè)最優(yōu)的匹配算法,選擇heap_4相關(guān)API進(jìn)行內(nèi)存管理。

  • 添加完FreeRTOS源碼中的.c文件,接下來添加相應(yīng)頭文件的路徑。點(diǎn)擊如下圖標(biāo)進(jìn)行設(shè)置:

  • 編譯,發(fā)現(xiàn)缺少FreeRTOSConfig.h,他是FreeRTOS 的配置文件,一般的操作系統(tǒng)都有裁剪、配置功能,而這些裁剪及配置都是通過一個(gè)文件來完成的,基本都是通過宏定 義來完成對(duì)系統(tǒng)的配置和裁剪的。可以到FreeRTOS的demo里面相關(guān)的,但是不同硬件和環(huán)境配置不同,本操作采用正點(diǎn)原子的板子,直接拷貝一份正點(diǎn)原子STM32的FreeRTOSConfig.h到FreeRTOS的include目錄下,再次進(jìn)行編譯

  • 編譯結(jié)果有錯(cuò)誤,打開USER的system_stm32f0x_it.c,將以下報(bào)錯(cuò)兩個(gè)函數(shù)屏蔽掉,編譯成功

  • 修改sys.h文件
    在 sys.h 文件里面用宏 SYSTEM_SUPPORT_OS 來定義是否使用 OS, 我們使用了 FreeRTOS,所以應(yīng)該將宏 SYSTEM_SUPPORT_OS 改為 1。

  • 更改delay.c
    delay.c需要修改比較多地方
    函數(shù) SysTick_Handler():

  • extern void xPortSysTickHandler(void);//systick中斷服務(wù)函數(shù),使用ucos時(shí)用到 void SysTick_Handler(void) { if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系統(tǒng)已經(jīng)運(yùn)行{xPortSysTickHandler(); } }

    delay_init()函數(shù):

    //初始化延遲函數(shù) //SYSTICK的時(shí)鐘固定為AHB時(shí)鐘,基礎(chǔ)例程里面SYSTICK時(shí)鐘頻率為AHB/8 //這里為了兼容FreeRTOS,所以將SYSTICK的時(shí)鐘頻率改為AHB的頻率! //SYSCLK:系統(tǒng)時(shí)鐘頻率 void delay_init() {u32 reload;SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);//選擇外部時(shí)鐘 HCLKfac_us=SystemCoreClock/1000000; //不論是否使用OS,fac_us都需要使用reload=SystemCoreClock/1000000; //每秒鐘的計(jì)數(shù)次數(shù) 單位為M reload*=1000000/configTICK_RATE_HZ; //根據(jù)configTICK_RATE_HZ設(shè)定溢出時(shí)間//reload為24位寄存器,最大值:16777216,在72M下,約合0.233s左右 fac_ms=1000/configTICK_RATE_HZ; //代表OS可以延時(shí)的最少單位 SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; //開啟SYSTICK中斷SysTick->LOAD=reload; //每1/configTICK_RATE_HZ秒中斷一次 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //開啟SYSTICK }

    剩下三個(gè)函數(shù)都是延時(shí)函數(shù):

    //延時(shí)nus //nus:要延時(shí)的us數(shù). //nus:0~204522252(最大值即2^32/fac_us@fac_us=168) void delay_us(u32 nus) { u32 ticks;u32 told,tnow,tcnt=0;u32 reload=SysTick->LOAD; //LOAD的值 ticks=nus*fac_us; //需要的節(jié)拍數(shù) told=SysTick->VAL; //剛進(jìn)入時(shí)的計(jì)數(shù)器值while(1){tnow=SysTick->VAL; if(tnow!=told){ if(tnow<told)tcnt+=told-tnow; //這里注意一下SYSTICK是一個(gè)遞減的計(jì)數(shù)器就可以了.else tcnt+=reload-tnow+told; told=tnow;if(tcnt>=ticks)break; //時(shí)間超過/等于要延遲的時(shí)間,則退出.} }; } //延時(shí)nms //nms:要延時(shí)的ms數(shù) //nms:0~65535 void delay_ms(u32 nms) { if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系統(tǒng)已經(jīng)運(yùn)行{ if(nms>=fac_ms) //延時(shí)的時(shí)間大于OS的最少時(shí)間周期 { vTaskDelay(nms/fac_ms); //FreeRTOS延時(shí)}nms%=fac_ms; //OS已經(jīng)無法提供這么小的延時(shí)了,采用普通方式延時(shí) }delay_us((u32)(nms*1000)); //普通方式延時(shí) }//延時(shí)nms,不會(huì)引起任務(wù)調(diào)度 //nms:要延時(shí)的ms數(shù) void delay_xms(u32 nms) {u32 i;for(i=0;i<nms;i++) delay_us(1000); }

    注意:delay_ms函數(shù)改完之后和頭文件聲明的不對(duì)應(yīng),需要到頭文件delay.h更改下u16改成u32

    最后,不要忘記將”includes.h”換成頭文件”FreeRTOS.h”,并添加其他頭文件如下圖所示

    其他無關(guān)的程序如:

    #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS定義了,說明要支持OS了(不限于UCOS). #ifdef OS_CRITICAL_METHOD //OS_CRITICAL_METHOD定義了,說明要支持UCOSII ... ...OSTimeDly(ticks); //UCOSII延時(shí) #endif }

    都可以刪掉了。

  • 更改usart.c
    usart.c 文件有兩部分要修改,一個(gè)是添加 FreeRTOS.h 頭文件, 默認(rèn)是添加的 UCOS 中的 includes.h 頭文件,修改以后如下:

    另外一個(gè)就是 USART1 的中斷服務(wù)函數(shù),在使用 UCOS 的時(shí)候進(jìn)出中斷的時(shí)候需要添加 OSIntEnter()和 OSIntExit(),使用 FreeRTOS 的話就不需要了,所以將這兩行代碼刪除掉,修改 以后如下:
  • void USART1_IRQHandler(void) //串口1中斷服務(wù)程序 {u8 Res;if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中斷(接收到的數(shù)據(jù)必須是0x0d 0x0a結(jié)尾){Res =USART_ReceiveData(USART1); //讀取接收到的數(shù)據(jù)if((USART_RX_STA&0x8000)==0)//接收未完成{if(USART_RX_STA&0x4000)//接收到了0x0d{if(Res!=0x0a)USART_RX_STA=0;//接收錯(cuò)誤,重新開始else USART_RX_STA|=0x8000; //接收完成了 }else //還沒收到0X0D{ if(Res==0x0d)USART_RX_STA|=0x4000;else{USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;USART_RX_STA++;if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收數(shù)據(jù)錯(cuò)誤,重新開始接收 } }} } }
  • 直接將以下代碼替換到main.c中的全部程序,編譯燒錄到板子中,有跑馬燈現(xiàn)象證明成功。(本次實(shí)驗(yàn)使用的是戰(zhàn)艦版,如果使用其他板可能需要稍作調(diào)整)
  • #include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "FreeRTOS.h" #include "task.h" /************************************************ALIENTEK 戰(zhàn)艦STM32F103開發(fā)板 FreeRTOS實(shí)驗(yàn)2-1FreeRTOS移植實(shí)驗(yàn)-庫函數(shù)版本技術(shù)支持:www.openedv.com淘寶店鋪:http://eboard.taobao.com 關(guān)注微信公眾平臺(tái)微信號(hào):"正點(diǎn)原子",免費(fèi)獲取STM32資料。廣州市星翼電子科技有限公司 作者:正點(diǎn)原子 @ALIENTEK ************************************************///任務(wù)優(yōu)先級(jí) #define START_TASK_PRIO 1 //任務(wù)堆棧大小 #define START_STK_SIZE 128 //任務(wù)句柄 TaskHandle_t StartTask_Handler; //任務(wù)函數(shù) void start_task(void *pvParameters);//任務(wù)優(yōu)先級(jí) #define LED0_TASK_PRIO 2 //任務(wù)堆棧大小 #define LED0_STK_SIZE 50 //任務(wù)句柄 TaskHandle_t LED0Task_Handler; //任務(wù)函數(shù) void led0_task(void *pvParameters);//任務(wù)優(yōu)先級(jí) #define LED1_TASK_PRIO 3 //任務(wù)堆棧大小 #define LED1_STK_SIZE 50 //任務(wù)句柄 TaskHandle_t LED1Task_Handler; //任務(wù)函數(shù) void led1_task(void *pvParameters);int main(void) {NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//設(shè)置系統(tǒng)中斷優(yōu)先級(jí)分組4 delay_init(); //延時(shí)函數(shù)初始化 uart_init(115200); //初始化串口LED_Init(); //初始化LED//創(chuàng)建開始任務(wù)xTaskCreate((TaskFunction_t )start_task, //任務(wù)函數(shù)(const char* )"start_task", //任務(wù)名稱(uint16_t )START_STK_SIZE, //任務(wù)堆棧大小(void* )NULL, //傳遞給任務(wù)函數(shù)的參數(shù)(UBaseType_t )START_TASK_PRIO, //任務(wù)優(yōu)先級(jí)(TaskHandle_t* )&StartTask_Handler); //任務(wù)句柄 vTaskStartScheduler(); //開啟任務(wù)調(diào)度 }//開始任務(wù)任務(wù)函數(shù) void start_task(void *pvParameters) {taskENTER_CRITICAL(); //進(jìn)入臨界區(qū)//創(chuàng)建LED0任務(wù)xTaskCreate((TaskFunction_t )led0_task, (const char* )"led0_task", (uint16_t )LED0_STK_SIZE, (void* )NULL, (UBaseType_t )LED0_TASK_PRIO, (TaskHandle_t* )&LED0Task_Handler); //創(chuàng)建LED1任務(wù)xTaskCreate((TaskFunction_t )led1_task, (const char* )"led1_task", (uint16_t )LED1_STK_SIZE, (void* )NULL,(UBaseType_t )LED1_TASK_PRIO,(TaskHandle_t* )&LED1Task_Handler); vTaskDelete(StartTask_Handler); //刪除開始任務(wù)taskEXIT_CRITICAL(); //退出臨界區(qū) }//LED0任務(wù)函數(shù) void led0_task(void *pvParameters) {while(1){LED0=~LED0;vTaskDelay(500);} } //LED1任務(wù)函數(shù) void led1_task(void *pvParameters) {while(1){LED1=0;vTaskDelay(200);LED1=1;vTaskDelay(800);} }

    學(xué)完有收獲的小伙伴不妨點(diǎn)個(gè)贊支持一下小b呀~

    總結(jié)

    以上是生活随笔為你收集整理的STM32F103--移植FreeRTOS完整教程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。