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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

STM32F411移植FreeRtos教程

發布時間:2023/12/14 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 STM32F411移植FreeRtos教程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

1.第一步準備好基礎工程

?2.軟件仿真相關設置

3.軟件仿真環境,printf重定向

4.移植FreeRtos源碼

4.1 拷貝文件

5.增加freertos源碼到keil工程中

5.1增加.c文件到工程:

5.2增加頭文件到工程:

6.修改編譯問題

7.修改SYSTEM文件和systick中斷處理函數

7.1 修改sys.h文件

7.2?修改usart.c文件

7.3?修改delay.c文件

7.3?修改SysTick_Handler中斷處理函數

7.修改main文件,創建freertos任務


1.第一步準備好基礎工程

準備好基礎工程,并且編譯通過,這里使用正點原子STM32F411提供的“F411_標準例程-寄存器版本“中的”實驗4 串口通信實驗“為基礎。

?2.軟件仿真相關設置

?通過菜單project->Options for target,打開工程設置

?修改外部時鐘頻率為8M:

設置軟件仿真,初始化文件,以及STM32F411RC對應的調試DLL

?說明:

1.選擇Use Simulator可以直接使用軟件仿真,不需要硬件單板。

2.設置Initialization File是為.\DebugConfig\debug.ini,是為了避免出現

*** error 65: access violation at 0x40023800 : no 'read' permission錯誤。

對應文件內容為:

map 0x40000000, 0x40007FFF read write // APB1
map 0x40010000, 0x400157FF read write // APB2
map 0x40020000, 0x4007FFFF read write // AHB1
map 0x50000000, 0x50060BFF read write // AHB2
map 0x60000000, 0x60000FFF read write // AHB3
map 0xE0000000, 0xE00FFFFF read write // CORTEX-M4 internal peripherals

3.設置調試dll和參數,調試dll為DARMSTM.DLL,Parameter根據需要仿真的硬件單板來填。

3.軟件仿真環境,printf重定向

3.1修改部分仿真環境下死循環問題

  • 在仿真環境下,設置時鐘為HSE后,等待HSE READY一直等不到,具體原因不曉得。

修改的辦法就是增加一個宏隔離,在#ifndef SIM情況下,不用死等。

3.2修改printf仿真環境下無法輸出問題

?主要參考教材:(4條消息) MDK下仿真實現printf功能_mytt2013的博客-CSDN博客_mdk中printf

?基于原工程,只需要修改一個函數:

//重定義fputc函數 int fputc(int ch, FILE *f) { #ifdef SIM //仿真環境下printf重定向return ITM_SendChar(ch); #else while((USART1->SR&0X40)==0);//循環發送,直到發送完畢 USART1->DR = (u8) ch; return ch; #endif }

?另外還有一個教程,是使用微庫的版本,也可以參考:printf系列教程01_UART打印輸出配置,基于STM32(Keil、IAR)_strongerHuang的博客-CSDN博客

4.移植FreeRtos源碼

主要過程參考:(4條消息) FreeRTOS在STM32F4上移植_Zach_z的博客-CSDN博客

4.1 拷貝文件

1.在測試工程中建立兩個文件夾,分別為Freertos_core和Freertos_port,

?2.拷貝freertosv9.0.0\FreeRTOS\Source公共源碼到工程目錄Freertos_core下:

?拷貝source目錄下所有文件,除了portable文件到工程目錄的Freertos_core目錄下:

3.拷貝FreeRtos架構相關源碼到工程目錄Freertos_port下:

拷貝:FreeRTOS\Source\portable\MemMang\heap_4.c

拷貝:\freertosv9.0.0\FreeRTOS\Source\portable\RVDS\ARM_CM4F 下所有文件

另外,還需要一個FreeRTOSConfig.h,由于我們單板是STM32F411,所以選擇FreeRTOS\Demo\CORTEX_M4F_STM32F407ZG-SK工程下的文件,將該文件拷貝到freertos_stm32f411\Freertos_port\include目錄,拷貝后的文件結構:

5.增加freertos源碼到keil工程中

5.1增加.c文件到工程:

打開keil工程,點擊Manager Project item,增加

?增加Group,并增加文件到Group后的狀態:

?點擊OK后,可以看到工程中,已經增加了FreeRtos相關源碼:

5.2增加頭文件到工程:

點擊Project->Options for "Target 1"

?在C/C++選項卡中,增加相關頭文件:

?增加Freertos頭文件后如圖:

6.修改編譯問題

1.修改SystemCoreClock條件編譯,

? Freertos_port\include\FreeRTOSConfig.h中

#ifdef __ICCARM__#include <stdint.h>extern uint32_t SystemCoreClock; #endif

修改為

#if defined(__ICCARM__) || defined(__CC_ARM) ||defined(__GUNC__)#include <stdint.h>extern uint32_t SystemCoreClock; #endif

2.重定義函數處理

PendSV_Handler,SVC_Handler ,SysTick_Handler三個函數有重復定義:

注釋掉SYSTEM\delay\delay.c中的PendSV_Handler和SVC_Handler定義,

注釋掉include\FreeRTOSConfig.h中的#define xPortSysTickHandler SysTick_Handler

3.關閉鉤子函數

復制過來的FreeRTOSConfig.h文件中默認開啟了一些鉤子函數,都是以Hook結尾,但并未定義,在FreeRTOSConfig.h中把configUSE_IDLE_HOOK、configUSE_TICK_HOOK、configCHECK_FOR_STACK_OVERFLOW和configUSE_MALLOC_FAILED_HOOK的宏定義改為0

至此,應該能編譯通過了。

7.修改SYSTEM文件和systick中斷處理函數

因為原子的SYSTEM文件夾是針對UCOS編寫的,所以要進行對應的修改

7.1 修改sys.h文件

把宏定義SYSTEM_SUPPORT_OS改為1即可,要支持OS,UCOS也一樣的

//0,不支持os //1,支持os #define SYSTEM_SUPPORT_OS 1 //定義系統文件夾是否支持OS

? ?調試過程中發現直接定義SYSTEM_SUPPORT_OS宏,更好一些,避免有些文件沒有包含sys.h,導致一些異常難以發現。所以這里可以直接把這行去掉,然后在宏里面定義。

7.2?修改usart.c文件

打開SYSTEM文件夾下usart.c文件,添加FreeRTOS.h頭文件

#if SYSTEM_SUPPORT_OS #include "FreeRTOS.h" //FreeRtos #endif

USART1的中斷服務函數在使用UCOS時進出中斷添加OSIntEnter()與OSIntExit(),使用FreeRTOS則不需要,故注釋掉

//串口1中斷服務程序 void USART1_IRQHandler(void) { u32 timeout=0;u32 maxDelay=0x1FFFF; //#if SYSTEM_SUPPORT_OS //使用OS // OSIntEnter(); //#endifHAL_UART_IRQHandler(&UART1_Handler); //調用HAL庫中斷處理公用函數timeout=0;while (HAL_UART_GetState(&UART1_Handler) != HAL_UART_STATE_READY)//等待就緒{timeout++;超時處理if(timeout>maxDelay) break; }timeout=0;while(HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)//一次處理完成之后,重新開啟中斷并設置RxXferCount為1{timeout++; //超時處理if(timeout>maxDelay) break; } //#if SYSTEM_SUPPORT_OS //使用OS // OSIntExit(); //#endif }

7.3?修改delay.c文件

使用以下代碼:

#include "delay.h" #include "sys.h" // //如果需要使用OS,則包括下面的頭文件即可. #if SYSTEM_SUPPORT_OS #include "FreeRTOS.h" //freertos 使用 #include "task.h" #endif// static u32 fac_us=0; //us延時倍乘數#if SYSTEM_SUPPORT_OS static u16 fac_ms=0; //ms延時倍乘數,在os下,代表每個節拍的ms數 #endif//初始化延遲函數 //當使用ucos的時候,此函數會初始化ucos的時鐘節拍 //SYSTICK的時鐘固定為AHB時鐘 //SYSCLK:系統時鐘頻率 void delay_init(u8 SYSCLK) { #if SYSTEM_SUPPORT_OS //如果需要支持OS.u32 reload; #endifHAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);//SysTick頻率為HCLKfac_us=SYSCLK; //不論是否使用OS,fac_us都需要使用 #if SYSTEM_SUPPORT_OS //如果需要支持OS.reload=SYSCLK; //每秒鐘的計數次數 單位為K reload*=1000000/configTICK_RATE_HZ; //根據configTICK_RATE_HZ設定溢出時間//reload為24位寄存器,最大值:16777216,在72M下,約合0.233s左右 fac_ms=1000/configTICK_RATE_HZ; //代表OS可以延時的最少單位 SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;//開啟SYSTICK中斷SysTick->LOAD=reload; //每1/OS_TICKS_PER_SEC秒中斷一次 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //開啟SYSTICK #else #endif } #if SYSTEM_SUPPORT_OS //如果需要支持OS. //延時nus //nus:要延時的us數. //nus:0~190887435(最大值即2^32/fac_us@fac_us=22.5) void delay_us(u32 nus) { u32 ticks;u32 told,tnow,tcnt=0;u32 reload=SysTick->LOAD; //LOAD的值 ticks=nus*fac_us; //需要的節拍數 told=SysTick->VAL; //剛進入時的計數器值while(1){tnow=SysTick->VAL; if(tnow!=told){ if(tnow<told)tcnt+=told-tnow; //這里注意一下SYSTICK是一個遞減的計數器就可以了.else tcnt+=reload-tnow+told; told=tnow;if(tcnt>=ticks)break; //時間超過/等于要延遲的時間,則退出.} }; } //延時nms,會引起任務調度 //nms:要延時的ms數 //nms:0~65535 void delay_ms(u32 nms) { if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系統已經運行{ if(nms>=fac_ms) //延時的時間大于OS的最少時間周期 { vTaskDelay(nms/fac_ms); //FreeRTOS延時}nms%=fac_ms; //OS已經無法提供這么小的延時了,采用普通方式延時 }delay_us((u32)(nms*1000)); //普通方式延時 }//延時nms,不會引起任務調度 //nms:要延時的ms數 void delay_xms(u32 nms) {u32 i;for(i=0;i<nms;i++) delay_us(1000); }#else //不用ucos時//延時nus //nus為要延時的us數. //nus:0~190887435(最大值即2^32/fac_us@fac_us=22.5) void delay_us(u32 nus) { u32 ticks;u32 told,tnow,tcnt=0;u32 reload=SysTick->LOAD; //LOAD的值 ticks=nus*fac_us; //需要的節拍數 told=SysTick->VAL; //剛進入時的計數器值while(1){tnow=SysTick->VAL; if(tnow!=told){ if(tnow<told)tcnt+=told-tnow; //這里注意一下SYSTICK是一個遞減的計數器就可以了.else tcnt+=reload-tnow+told; told=tnow;if(tcnt>=ticks)break; //時間超過/等于要延遲的時間,則退出.} }; }//延時nms //nms:要延時的ms數 void delay_ms(u32 nms) {u32 i;for(i=0;i<nms;i++) delay_us(1000); } #endif

7.3?修改SysTick_Handler中斷處理函數

使用以下代碼:

#ifdef SYSTEM_SUPPORT_OS #include "FreeRTOS.h" //freertos 使用 #include "task.h" extern void xPortSysTickHandler(void); //systick中斷服務函數,使用OS時用到 void SysTick_Handler(void) { if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系統已經運行{xPortSysTickHandler(); }HAL_IncTick(); } #else void SysTick_Handler(void) {HAL_IncTick(); } #endif

7.修改main文件,創建freertos任務

#include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "beep.h" #include "key.h"/************************************************ALIENTEK NANO板STM32F4開發板實驗4串口通信實驗-HAL庫版本技術支持:www.openedv.com淘寶店鋪:http://eboard.taobao.com 關注微信公眾平臺微信號:"正點原子",免費獲取STM32資料。廣州市星翼電子科技有限公司 作者:正點原子 @ALIENTEK ************************************************///說明,在工程宏定義中增加SYSTEM_SUPPORT_OS定義,則編譯出來版本就是freertos創建任務的版本。否則就是普通的裸機版本。 #ifdef SYSTEM_SUPPORT_OS #include "FreeRTOS.h" #include "task.h" #include "timers.h" #include "semphr.h"//500ms LED1燈狀態翻轉一次 static void led1Task( void * pvParameters ) {u8 len; while(1){if(USART_RX_STA&0x8000){ len=USART_RX_STA&0x3fff;//得到此次接收到的數據長度printf("\r\n您發送的消息為:\r\n");HAL_UART_Transmit(&UART1_Handler,(uint8_t*)USART_RX_BUF,len,1000); //發送接收到的數據while(__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_TC)!=SET); //等待發送結束printf("\r\n\r\n");//插入換行USART_RX_STA=0;}vTaskDelay(1);} } //1000ms LED2燈狀態翻轉一次 static void led2Task( void * pvParameters ) {u32 times=0; while(1){if(times%5000==0){printf("\r\nALIENTEK NANO STM32開發板 Freertos串口實驗\r\n");printf("正點原子@ALIENTEK\r\n\r\n\r\n");}times++;if(times%200==0)printf("請輸入數據,以回車鍵結束\r\n"); if(times%30==0)LED0=!LED0;//閃爍LED,提示系統正在運行.vTaskDelay(10);} }void startTasks(void) {xTaskCreate(led1Task,"LED1",256,NULL,100,(TaskHandle_t *)NULL);xTaskCreate(led2Task,"LED2",256,NULL,101,(TaskHandle_t *)NULL);/* 啟動任務調度器. */vTaskStartScheduler(); } #else void startTasks(void) {u8 len; u32 times=0; while(1){if(USART_RX_STA&0x8000){ len=USART_RX_STA&0x3fff;//得到此次接收到的數據長度printf("\r\n您發送的消息為:\r\n");HAL_UART_Transmit(&UART1_Handler,(uint8_t*)USART_RX_BUF,len,1000); //發送接收到的數據while(__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_TC)!=SET); //等待發送結束printf("\r\n\r\n");//插入換行USART_RX_STA=0;}else{if(times%5000==0){printf("\r\nALIENTEK NANO STM32開發板 裸機串口實驗\r\n");printf("正點原子@ALIENTEK\r\n\r\n\r\n");}times++;if(times%200==0)printf("請輸入數據,以回車鍵結束\r\n"); if(times%30==0)LED0=!LED0;//閃爍LED,提示系統正在運行.delay_ms(10); } } } #endifint main(void) {HAL_Init(); //初始化HAL庫 Stm32_Clock_Init(96,4,2,4); //設置時鐘,96Mhzdelay_init(96); //初始化延時函數LED_Init(); //初始化LED uart_init(115200); //初始化串口115200startTasks();}

其他參考文章:

2、STM32F407移植FreeRTOS步驟_nandycooh的博客-CSDN博客_stm32f407移植freertos

FreeRTOS的移植與初步使用_不吃魚的貓丿的博客-CSDN博客

總結

以上是生活随笔為你收集整理的STM32F411移植FreeRtos教程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。