FreeRTOS學習(1)——FreeRTOS移植

爲什麼要讓你的單片機裸奔?

什麼是FreeRTOS?

首先看到兩個概念:

  1. RTOS:實時操作系統,目前主流的嵌入式操作系統有:UCOS、FreeRTOS、LWIP、EMWIN、RT-Thread 等
  2. FreeRTOS:FreeRTOS是一個迷你的實時操作系統內核。作爲一個輕量級的操作系統,功能包括:任務管理、時間管理、信號量、消息隊列、內存管理、記錄功能、軟件定時器、協程等,可基本滿足較小系統的需要

也許在百度百科截取的這段解釋不夠接地氣,通俗的解釋就是更加有序的管理單片機的各個任務功能執行。

爲什麼要學習FreeRTOS?

採用嵌入式實時操作系統(RTOS)可以更合理、更有效地利用CPU的資源,簡化應用軟件的設計,縮短系統開發時間,更好地保證系統的實時性和可靠性

通常我們在寫單片機程序的時候,都是將許多功能寫成一個一個的函數,然後寫在main函數中的while(1)裏,與中斷進行配合實現系統功能。這種情況就叫做前後臺系統,通常也稱之爲——裸奔。但是加上了RTOS之後就是穿上了實時操作系統的衣服,更加合理,更加高級。

這裏有一個關於竹林七賢之一——劉伶的故事:
有人去拜訪劉伶,適逢他喝醉了酒,一絲不掛地在屋裏亂晃,不禁譏諷道:“你也是禮教之人,如此行徑成何體統?”劉伶一聽,頗不以爲然地反脣相譏:“我以天地爲房屋,以房屋爲衣裳,你怎麼跑到我褲子裏來權了?”客人聽了瞠目結舌,無言以對。
從上可以看出,穿衣與否並不是評判是否成體統的標誌,影射到單片機上也是一樣,不是加了操作系統就一定優於裸機開發,還要視具體情況而定。

在stm32上的移植

首先是到FreeRTOS官網下載移植文件:官網地址外國網站可能有點慢
下載好之後是一個exe文件:

在這裏插入圖片描述點擊就會生成一個文件夾:在這裏插入圖片描述
進到FreeRTOS->Source,裏面放的就是移植需要的文件
在這裏插入圖片描述
然後打開一個stm32工程
在stm32工程中添加一個FreeRTOS文件夾
將Source裏面的文件都複製過去,也就是上圖文件
把portable文件夾裏除了keil、MemMang 和 RVDS三個文件全部刪除,因爲用不到
向工程中添加分組FreeRTOS_CORE、FreeRTOS_PORTABLE,添加文件,添加路徑
在這裏插入圖片描述
編譯一次會發現少了FreeRTOSCongif.h這個文件,我們可以從官方下載的例程中去添加這個文件到FreeRTOS的include目錄下

具體過程

修改SYSTEM文件夾

修改sys.h文件

#define SYSTEM_SUPPORT_OS		0	
****************************************************************
//修改爲:
#define SYSTEM_SUPPORT_OS		1		//支持操作系統	

修改usart.c文件
第一處:

#if SYSTEM_SUPPORT_OS
#include "includes.h"				 
#endif
****************************************************************
//修改爲:
#if SYSTEM_SUPPORT_OS
#include "FreeRTOS.h" 		//os 使用 
#endif

第二處:將OSIntEnter()和 OSIntExit()刪除掉

void USART1_IRQHandler(void)                	
	{
	u8 Res;
#if SYSTEM_SUPPORT_OS 		
	OSIntEnter();    
#endif
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  
		{
		Res =USART_ReceiveData(USART1);	
		
		if((USART_RX_STA&0x8000)==0)
			{
			if(USART_RX_STA&0x4000)
				{
				if(Res!=0x0a)USART_RX_STA=0;
				else USART_RX_STA|=0x8000;	
				}
			else 
				{	
				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;  
					}		 
				}
			}   		 
     } 
#if SYSTEM_SUPPORT_OS 
	OSIntExit();  											 
#endif
} 
****************************************************************
//修改爲:
void USART1_IRQHandler(void)                	
{
	u8 Res;

	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) 
		{
		Res =USART_ReceiveData(USART1);	
		
		if((USART_RX_STA&0x8000)==0)
			{
			if(USART_RX_STA&0x4000)
				{
				if(Res!=0x0a)USART_RX_STA=0;
				else USART_RX_STA|=0x8000;	
				}
			else 
				{	
				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;
					}		 
				}
			}   		 
     } 
} 

修改delay.c文件,這裏有點多直接替換成下面的代碼即可

#include "delay.h"
#include "sys.h"

#if SYSTEM_SUPPORT_OS
#include "FreeRTOS.h"						  
#include "task.h" 
#endif

static u8  fac_us=0;								   
static u16 fac_ms=0;						
 
extern void xPortSysTickHandler(void);

void SysTick_Handler(void)
{	
    if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)
        xPortSysTickHandler();	
    }
}
			   
void delay_init()
{
	u32 reload;
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
	fac_us=SystemCoreClock/1000000;				
	reload=SystemCoreClock/1000000;				
	reload*=1000000/configTICK_RATE_HZ;			
												
	fac_ms=1000/configTICK_RATE_HZ;			

	SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;   	
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;   	   
}								    

								   
void delay_us(u32 nus)
{		
	u32 ticks;
	u32 told,tnow,tcnt=0;
	u32 reload=SysTick->LOAD;				  	 
	ticks=nus*fac_us; 						 
	told=SysTick->VAL;        			
	while(1)
	{
		tnow=SysTick->VAL;	
		if(tnow!=told)
		{	    
			if(tnow<told)tcnt+=told-tnow;	
			else tcnt+=reload-tnow+told;	    
			told=tnow;
			if(tcnt>=ticks)break;			
		}  
	};										    
}  

void delay_ms(u32 nms)
{	
	if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)
	{		
		if(nms>=fac_ms)						
		{ 
   			vTaskDelay(nms/fac_ms);	 		
		}
		nms%=fac_ms;						
	}
	delay_us((u32)(nms*1000));				
}

void delay_xms(u32 nms)
{
	u32 i;
	for(i=0;i<nms;i++) delay_us(1000);
}

最後就是將stm32f10x_it.c裏面的這三個中斷服務函數屏蔽
在這裏插入圖片描述
這樣就完成了FreeRTOS的移植,當然在這裏還是要感謝正點原子出的教程,我是站在巨人的肩膀上,才能看得更遠。

在實際的工程中,我們直接使用原子的模板就好了,每次都自己移植有點費時間,只需要瞭解這麼一個過程就好。

最後還是感謝嵌入式教育巨頭——原子哥。
你看的到嗎,原子哥?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章