FreeRTOS在STM32F429上移植

準備工作

  1. FreeRTOS系統源碼
  2. 基礎工程,這里我們用跑馬燈實驗

1.在工程里面添加FreeRTOS源碼

在工程里面新建一個名為FreeROTS的文件夾
在這里插入圖片描述
將FreeRTOS源碼添加到這個文件夾里面
在這里插入圖片描述
protable里面只需留下Keil、MemMang、RVDS文件夾
在這里插入圖片描述

2、向工程分組中添加文件

在這里插入圖片描述
FreeRTOS_CORE的文件在FreeRTOS源碼的首目錄下,FreeRTOS_PORTABLE的port.c在RVDS文件夾下的ARM_CM4F中,heap_4.c在MenMang中,是內存管理方法

3、添加相應的頭文件路徑

在這里插入圖片描述

4、添加FreeRTOSConfig.h文件

放在include文件夾下,這個文件官方的例程有,是FreeRTOS的配置文件
在這里插入圖片描述
打開FreeRTOSConfig.h文件,修改下圖代碼為
在這里插入圖片描述

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

在這里插入圖片描述

4、屏蔽port.c和stmf32f4xx_it.c重復定義的函數

void PendSV_Handler(void)void SysTick_Handler(void)void PPP_IRQHandler(void)

5、修改system文件

5.1 sys.h

SYSTEM_SUPPORT_OS修改成1

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

修改成以下內容

#include "usart.h"
#include "delay.h"
// 	 
//如果使用os,則包括下面的頭文件即可.
#if SYSTEM_SUPPORT_OS
#include "FreeRTOS.h"      //os 使用	  
#endif//加入以下代碼,支持printf函數,而不需要選擇use MicroLIB	  
//#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)	
#if 1
#pragma import(__use_no_semihosting)             
//標準庫需要的支持函數                 
struct __FILE 
{ int handle; 
}; FILE __stdout;       
//定義_sys_exit()以避免使用半主機模式    
void _sys_exit(int x) 
{ x = x; 
} 
//重定義fputc函數 
int fputc(int ch, FILE *f)
{ 	while((USART1->SR&0X40)==0);//循環發送,直到發送完畢   USART1->DR = (u8) ch;      return ch;
}
#endif #if EN_USART1_RX   //如果使能了接收
//串口1中斷服務程序
//注意,讀取USARTx->SR能避免莫名其妙的錯誤   	
u8 USART_RX_BUF[USART_REC_LEN];     //接收緩沖,最大USART_REC_LEN個字節.
//接收狀態
//bit15,	接收完成標志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字節數目
u16 USART_RX_STA=0;       //接收狀態標記	u8 aRxBuffer[RXBUFFERSIZE];//HAL庫使用的串口接收緩沖
UART_HandleTypeDef UART1_Handler; //UART句柄//初始化IO 串口1 
//bound:波特率
void uart_init(u32 bound)
{	//UART 初始化設置UART1_Handler.Instance=USART1;					    //USART1UART1_Handler.Init.BaudRate=bound;				    //波特率UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B;   //字長為8位數據格式UART1_Handler.Init.StopBits=UART_STOPBITS_1;	    //一個停止位UART1_Handler.Init.Parity=UART_PARITY_NONE;		    //無奇偶校驗位UART1_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //無硬件流控UART1_Handler.Init.Mode=UART_MODE_TX_RX;		    //收發模式HAL_UART_Init(&UART1_Handler);					    //HAL_UART_Init()會使能UART1HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE);//該函數會開啟接收中斷:標志位UART_IT_RXNE,并且設置接收緩沖以及接收緩沖接收最大數據量}//UART底層初始化,時鐘使能,引腳配置,中斷配置
//此函數會被HAL_UART_Init()調用
//huart:串口句柄void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{//GPIO端口設置GPIO_InitTypeDef GPIO_Initure;if(huart->Instance==USART1)//如果是串口1,進行串口1 MSP初始化{__HAL_RCC_GPIOA_CLK_ENABLE();			//使能GPIOA時鐘__HAL_RCC_USART1_CLK_ENABLE();			//使能USART1時鐘GPIO_Initure.Pin=GPIO_PIN_9;			//PA9GPIO_Initure.Mode=GPIO_MODE_AF_PP;		//復用推挽輸出GPIO_Initure.Pull=GPIO_PULLUP;			//上拉GPIO_Initure.Speed=GPIO_SPEED_FAST;		//高速GPIO_Initure.Alternate=GPIO_AF7_USART1;	//復用為USART1HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA9GPIO_Initure.Pin=GPIO_PIN_10;			//PA10HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA10#if EN_USART1_RXHAL_NVIC_EnableIRQ(USART1_IRQn);				//使能USART1中斷通道HAL_NVIC_SetPriority(USART1_IRQn,3,3);			//搶占優先級3,子優先級3
#endif	}}void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if(huart->Instance==USART1)//如果是串口1{if((USART_RX_STA&0x8000)==0)//接收未完成{if(USART_RX_STA&0x4000)//接收到了0x0d{if(aRxBuffer[0]!=0x0a)USART_RX_STA=0;//接收錯誤,重新開始else USART_RX_STA|=0x8000;	//接收完成了 }else //還沒收到0X0D{	if(aRxBuffer[0]==0x0d)USART_RX_STA|=0x4000;else{USART_RX_BUF[USART_RX_STA&0X3FFF]=aRxBuffer[0] ;USART_RX_STA++;if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收數據錯誤,重新開始接收	  }		 }}}
}//串口1中斷服務程序
void USART1_IRQHandler(void)                	
{ u32 timeout=0;u32 maxDelay=0x1FFFF;HAL_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;	}
} 
#endif	/*下面代碼我們直接把中斷控制邏輯寫在中斷服務函數內部。*/
/*//串口1中斷服務程序
void USART1_IRQHandler(void)                	
{ u8 Res;if((__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_RXNE)!=RESET))  //接收中斷(接收到的數據必須是0x0d 0x0a結尾){HAL_UART_Receive(&UART1_Handler,&Res,1,1000); if((USART_RX_STA&0x8000)==0)//接收未完成{if(USART_RX_STA&0x4000)//接收到了0x0d{if(Res!=0x0a)USART_RX_STA=0;//接收錯誤,重新開始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;//接收數據錯誤,重新開始接收	  }		 }}   		 }HAL_UART_IRQHandler(&UART1_Handler);	
} 
#endif	
*/
5.3 delay.c

修改成以下內容

#include "delay.h"
#include "sys.h"
// 	 
//如果使用OS,則包括下面的頭文件即可.
#if SYSTEM_SUPPORT_OS
#include "FreeRTOS.h"					//FreeRTOS使用	 
#include "task.h"
#endifstatic u32 fac_us=0;							//us延時倍乘數#if SYSTEM_SUPPORT_OS		static u16 fac_ms=0;				        //ms延時倍乘數,在os下,代表每個節拍的ms數
#endifextern void xPortSysTickHandler(void);
//systick中斷服務函數,使用OS時用到
void SysTick_Handler(void)
{  if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系統已經運行{xPortSysTickHandler();	}HAL_IncTick();
}//初始化延遲函數
//當使用ucos的時候,此函數會初始化ucos的時鐘節拍
//SYSTICK的時鐘固定為AHB時鐘
//SYSCLK:系統時鐘頻率
void delay_init(u8 SYSCLK)
{u32 reload;HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);//SysTick頻率為HCLKfac_us=SYSCLK;						    //不論是否使用OS,fac_us都需要使用reload=SYSCLK;					        //每秒鐘的計數次數 單位為K	   reload*=1000000/configTICK_RATE_HZ;		//根據configTICK_RATE_HZ設定溢出時間//reload為24位寄存器,最大值:16777216,在180M下,約合0.745s左右	fac_ms=1000/configTICK_RATE_HZ;			//代表OS可以延時的最少單位		SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;//開啟SYSTICK中斷SysTick->LOAD=reload; 					//每1/configTICK_RATE_HZ斷一次	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //開啟SYSTICK
}								    //延時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);
}

編譯一下,如果沒有錯誤就可以了
在這里插入圖片描述

測試

main.c文件內容如下

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "FreeRTOS.h"
#include "task.h"//任務優先級
#define START_TASK_PRIO		1
//任務堆棧大小	
#define START_STK_SIZE 		128  
//任務句柄
TaskHandle_t StartTask_Handler;
//任務函數
void start_task(void *pvParameters);//任務優先級
#define LED0_TASK_PRIO		2
//任務堆棧大小	
#define LED0_STK_SIZE 		50  
//任務句柄
TaskHandle_t LED0Task_Handler;
//任務函數
void led0_task(void *pvParameters);//任務優先級
#define LED1_TASK_PRIO		3
//任務堆棧大小	
#define LED1_STK_SIZE 		50  
//任務句柄
TaskHandle_t LED1Task_Handler;
//任務函數
void led1_task(void *pvParameters);//任務優先級
#define FLOAT_TASK_PRIO		4
//任務堆棧大小	
#define FLOAT_STK_SIZE 		128
//任務句柄
TaskHandle_t FLOATTask_Handler;
//任務函數
void float_task(void *pvParameters);int main(void)
{HAL_Init();                     //初始化HAL庫   Stm32_Clock_Init(360,25,2,8);   //設置時鐘,180Mhzdelay_init(180);                //初始化延時函數LED_Init();                     //初始化LED uart_init(115200);              //初始化串口//創建開始任務xTaskCreate((TaskFunction_t )start_task,            //任務函數(const char*    )"start_task",          //任務名稱(uint16_t       )START_STK_SIZE,        //任務堆棧大小(void*          )NULL,                  //傳遞給任務函數的參數(UBaseType_t    )START_TASK_PRIO,       //任務優先級(TaskHandle_t*  )&StartTask_Handler);   //任務句柄              vTaskStartScheduler();          //開啟任務調度
}//開始任務任務函數
void start_task(void *pvParameters)
{taskENTER_CRITICAL();           //進入臨界區//創建LED0任務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);   //創建LED1任務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);        //浮點測試任務xTaskCreate((TaskFunction_t )float_task,     (const char*    )"float_task",   (uint16_t       )FLOAT_STK_SIZE, (void*          )NULL, (UBaseType_t    )FLOAT_TASK_PRIO,(TaskHandle_t*  )&FLOATTask_Handler);  vTaskDelete(StartTask_Handler); //刪除開始任務taskEXIT_CRITICAL();            //退出臨界區
}//LED0任務函數 
void led0_task(void *pvParameters)
{while(1){LED0=~LED0;vTaskDelay(500);}
}   //LED1任務函數
void led1_task(void *pvParameters)
{while(1){LED1=0;vTaskDelay(200);LED1=1;vTaskDelay(800);}
}//浮點測試任務
void float_task(void *pvParameters)
{static float float_num=0.00;while(1){	float_num+=0.01f;printf("float_num的值為: %.4f\r\n",float_num);vTaskDelay(1000);}
}

編譯,將程序燒錄到開發板中,可以發現LED0、LED1閃爍,移植成功

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/379775.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/379775.shtml
英文地址,請注明出處:http://en.pswp.cn/news/379775.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++中的指針與引用(轉)

原文地址&#xff1a;http://www.cnblogs.com/skynet/archive/2010/09/22/1832911.html寫在前面 指針和引用形式上很好區別&#xff0c;但是他們似乎有相同的功能,都能夠直接引用對象&#xff0c;對其進行直接的操作。但是什么時候使用指針&#xff1f;什么時候使用引用呢&…

實訓09.11:數據庫一些簡單操作

new Database 新建數據庫 new Table 新建表 utf-8 編碼格式 primary key 主鍵&#xff1a;特點&#xff1a;在表中是唯一的不可重復的&#xff0c;一般都是學號&#xff0c;編號 auto increment 自增&#xff0c;一般都把主鍵設置為自增 allow nul…

c語言中將整數轉換成字符串_在C語言中將ASCII字符串(char [])轉換為八進制字符串(char [])...

c語言中將整數轉換成字符串Given an ASCII string (char[]) and we have to convert it into octal string (char[]) in C. 給定一個ASCII字符串(char [])&#xff0c;我們必須在C中將其轉換為八進制字符串(char [])。 Logic: 邏輯&#xff1a; To convert an ASCII string t…

Javascript的IE和Firefox兼容性匯編收藏.txt

document.form.item 問題 現有問題&#xff1a;現有代碼中存在許多 document.formName.item("itemName") 這樣的語句&#xff0c;不能在 MF 下運行 解決方法&#xff1a;改用 document.formName.elements["elementName"] 集合類對象問題 現有問題&#xff…

FreeRTOS系統配置文件FreeRTOSConfig.h

實際使用FreeRTOS的時候&#xff0c;我們時常需要根據自己需求來配置FreeRTOS&#xff0c;而且不同架構的MCU在使用的時候配置也不同&#xff0c;FreeRTOS的系統配置文件FreeRTOSConfig.h可以完成FreeRTOS的裁剪和配置。FreeRTOSConfig.h分成兩個部分&#xff0c;一個是INCLUDE…

SQL更新多條數據

問題&#xff1a;有兩個不同的表&#xff0c;其中都有一個編號的字段&#xff0c;而且存儲的內容是相同的&#xff0c;需要將一張表中的另外一些字段依據編號去與另一個表中編號對應來更新到另一個表中。 方法&#xff1a;由于在sql中是不支持同時更新多條包含編號的數據的&…

簡單的登錄系統(java+JFrame+Mysql)

連接數據庫 package 注冊信息; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; public class conn_db{ Connection con; String url null; Statement stmt; public void connection() throws ClassNotFoundException{ //…

冬季止咳化痰的飲食偏方集錦

1、蘿卜蔥白風寒咳嗽 蘿卜1個,蔥白6根,生姜15克.用水三碗先將蘿卜煮熟,再放蔥白,姜,煮剩一碗湯.連渣一次服.宣肺解表,化痰止咳.治風寒咳嗽,痰多泡沫,伴畏寒,身倦酸痛等. 2、紅糖姜棗湯治傷風咳嗽 紅糖30克,鮮姜15克,紅棗30克. 以水三碗煎至過半.頓服,服后出微汗即愈. 驅風散寒.…

c語言中數組越界怎么辦_如果我們使用C語言數組中的越界索引怎么辦?

c語言中數組越界怎么辦Let’s understand first, what is index out of bounds? 首先讓我們了解一下 &#xff0c; 什么是索引超出范圍&#xff1f; Let suppose you have an array with 5 elements then the array indexing will be from 0 to 4 i.e. we can access element…

FreeRTOS任務基礎知識

任務特性 在RTOS中&#xff0c;一個實時應用可以作為一個獨立的任務&#xff0c;支持搶占&#xff0c;支持優先級&#xff0c;每個任務都有自己的堆棧&#xff0c;當任務切換時將上下文環境保存在堆棧中&#xff0c;再次調用任務時&#xff0c;取出上下文信息&#xff0c;繼續…

測試Rockey 4 Smart加密鎖的C語言代碼

測試Rockey 4 Smart加密鎖的C語言代碼 // win32Console_dog_test.cpp : Defines the entry point for the console application. /// // //測試Rockey 4 Smart加密鎖的C語言代碼 // /// #include "stdafx.h" #include <conio.h> #include "time.h" #…

C——任意一個偶數分解兩個素數

題目&#xff1a;一個偶數總能表示為兩個素數之和 以上實例運行輸出結果為&#xff1a; 請輸入一個偶數: 4 偶數4可以分解成1和3兩個素數的和 #include <stdio.h> #include <stdlib.h> int Isprimer(int n); int main() {int n,i;do{printf("請輸入一個偶數&…

c#委托調用另一窗口函數_在C#中使用委托調用成員函數

c#委托調用另一窗口函數Prerequisite: Delegates in C# 先決條件&#xff1a; C&#xff03;中的代表 We can also call a member function of a class using delegates. It is similar to static function calls, here we have to pass member function using an object on t…

Java版AVG游戲開發入門[0]——游戲模式轉換中的事件交互

Java版AVG游戲開發入門[0]——游戲模式轉換中的事件交互 示例程序下載地址&#xff1a;http://download.csdn.net/source/999273&#xff08;源碼在jar內&#xff09; AVG&#xff0c;即Adventure Game&#xff0c;可以直譯為[冒險游戲]。但是通常情況下我們說AVG是指[文字冒險…

FreeRTOS任務創建和刪除

任務創建和刪除的API函數 xTaskCreate()&#xff1a;使用動態方法創建一個任務xTaskCreateStatic()&#xff1a;使用靜態方法創建一個任務xTaskCreateRestricated()&#xff1a;創建一個使用MPU進行限制的任務&#xff0c;相關內存使用動態內存分配vTaskDelete()&#xff1a;刪…

Delphi 調試

調試&#xff1a;F9執行F8逐過程單步調試F7逐語句單步調試轉載于:https://www.cnblogs.com/JackShao/archive/2012/04/30/2476931.html

1.創建單項鏈表

# include <stdio.h> # include <malloc.h> # include <stdlib.h>typedef struct Node{int data;//數據域struct Node *pNext;//指針域}NODE, *PNODE; //NODE等價于struct Node //PNOD等價于struct Node * //函數聲明PNODE create_list(void); void traverse…

python 日本就業_日本的繪圖標志 Python中的圖像處理

python 日本就業Read basics of the drawing/image processing in python: Drawing flag of Thailand 閱讀python中繪圖/圖像處理的基礎知識&#xff1a; 泰國的繪圖標志 The national flag of Japan is a rectangular white banner bearing a crimson-red disc at its center…

[windows phone 7 ]查看已安裝程序GUID

首先介紹下wp7RootToolsSDK,這個功能相當強大&#xff0c;適合研究wp7高級功能。 它支持File&#xff0c;Register操作&#xff0c;比之前的COM調用要簡單&#xff0c;方便。 功能:查看已安裝程序的guid 開發心得: 用的是mozart,rom多&#xff0c;刷機吧&#xff0c;最麻煩的是…

FreeRTOS任務掛起和恢復

任務掛起&#xff1a;暫停某個任務的執行 任務恢復&#xff1a;讓暫停的任務繼續執行 通過任務掛起和恢復&#xff0c;可以達到讓任務停止一段時間后重新運行。 相關API函數&#xff1a; vTaskSuspend void vTaskSuspend( TaskHandle_t xTaskToSuspend );xTaskToSuspend &am…