現(xiàn)成輪子OSAL操作系統(tǒng)抽象層的移植
簡(jiǎn)單介紹一下Z-STACK中的OSAL,值得一看的現(xiàn)成輪子;
什么是 OSAL?
今天同學(xué)忽然問我有沒有搞過OSAL
,忽然間一頭霧水,于是在搜索引擎上找到了答案,發(fā)現(xiàn)這是一個(gè)十分實(shí)用的東西。
OSAL(operating system abstraction layer
),操作系統(tǒng)抽象層,是一種以實(shí)現(xiàn)多任務(wù)為核心的系統(tǒng)資源管理機(jī)制,實(shí)現(xiàn)了類似RTOS
的某些功能,但并不能稱之為真正意義上的RTOS
,因?yàn)槠浔旧磉€不支持任務(wù)的掛起,任務(wù)的搶占等等功能。
但是這種機(jī)制,實(shí)現(xiàn)的代碼十分精簡(jiǎn),占用資源也非常少,對(duì)于資源十分緊張的嵌入式平臺(tái),也可以完成比較復(fù)雜的邏輯功能。
在TI CC2530
的ZIGBEE
協(xié)議棧Z-STACK
中可以找到OSAL的身影,可以在官網(wǎng)上搜索z-stack
下載相關(guān)的源碼,其中就包含了OSAL
實(shí)現(xiàn)的源碼;
移除掉一些無關(guān)功能的代碼之后,剩下OSAL的源碼總共約1100多行代碼,全部由C語言實(shí)現(xiàn),資源占用約為
-
RAM:512Byte -
ROM:2KB
理論上可以移植到絕大多數(shù)的芯片平臺(tái)上。
源碼安裝
目前官網(wǎng)上最新的版本,下載安裝到本地;
安裝完成之后,可以到安裝目錄下,找到相應(yīng)的源碼,不過這里基本上是zigbee
的協(xié)議棧,所以OSAL
相關(guān)的部分在下圖所示的路徑中;
進(jìn)入到osal
路徑下的文件結(jié)構(gòu)如下圖所示;
這個(gè)OSAL
操作系統(tǒng)抽象層用于保護(hù)協(xié)議棧軟件組件不受程序硬件細(xì)節(jié)的影響,減少程序的耦合性,提高可移植性和復(fù)用性。它可以獨(dú)立于程序環(huán)境,并且提供了以下功能。
-
任務(wù)注冊(cè)、初始化、啟動(dòng); -
任務(wù)間的消息交換; -
任務(wù)同步; -
中斷處理; -
計(jì)時(shí)器; -
內(nèi)存分配;
Linux 上OSAL的移植
可以嘗試把OSAL
的框架移植到單片機(jī)上,進(jìn)行測(cè)試,這里是GitHub
上fork
的一個(gè)倉庫OSAL ,已經(jīng)具體的移植方法,可以在Linux
平臺(tái)上進(jìn)行測(cè)試,
void osal_main(void)
{
//系統(tǒng)硬件、外設(shè)等初始化
//禁止中斷
HAL_DISABLE_INTERRUPTS();
//osal操作系統(tǒng)初始化
osal_init_system();
//添加任務(wù)
osal_add_Task(print_task_init, print_task_event_process, 1);
osal_add_Task(statistics_task_init, statistics_task_event_process, 2);
//添加的任務(wù)統(tǒng)一進(jìn)行初始化
osal_Task_init();
osal_mem_kick();
//允許中斷
HAL_ENABLE_INTERRUPTS();
//設(shè)置初始任務(wù)事件,上電就需要自動(dòng)輪詢的任務(wù)事件可在此添加
//啟動(dòng)osal系統(tǒng),不會(huì)再返回
osal_start_system();
}
STM32上OSAL的移植
如果直接使用ti
官方的代碼改動(dòng)會(huì)相對(duì)比較大,這里直接在github
上找到一份移植到stm32
的工程,直接fork了一份改成HAL
庫,可以參考一下stm32-osal, 克隆代碼之后,直接復(fù)制osal
文件夾到CubeIDE
工程目錄下,然后對(duì)工程文件列表進(jìn)行刷新,可以看到如下圖所示;
下面是作者基于ti
的osal
的移植說明:
-
完成 OSAL\hal\timer.c
文件,為系統(tǒng)提供時(shí)鐘; -
修改 OSAL\include\type.h
文件中的全局中斷開關(guān)函數(shù)(可以為空),添加芯片對(duì)應(yīng)的頭文件,根據(jù)需要修改數(shù)據(jù)類型重定義,根據(jù)芯片字長(zhǎng)修改halDataAlign_t類型; -
根據(jù)需要修改 OSAL\osal\osal_memory.h
文件中的內(nèi)存池大小定義,文件中osalMemHdr_t類型需要確保長(zhǎng)度為16bit或以上,非8位單片機(jī)需要設(shè)定內(nèi)存池的字節(jié)對(duì)齊; -
添加任務(wù)函數(shù)中的任務(wù)優(yōu)先級(jí)數(shù)值大的任務(wù)則優(yōu)先級(jí)高; -
根據(jù)需要修改 OSAL\include\osal_memory.h
文件中的OSALMEM_METRICS定義,有效則開啟內(nèi)存統(tǒng)計(jì)功能;
關(guān)鍵點(diǎn)
總體來說,因?yàn)檎驹诰奕说募绨蛏?,整體的代碼需要修改的部分已經(jīng)很少了。首先這個(gè)機(jī)制是根據(jù)時(shí)間片輪詢調(diào)度的,所以會(huì)對(duì)每個(gè)任務(wù)分配一個(gè)ID以及一個(gè)任務(wù)專屬的定時(shí)器,同時(shí),使用一個(gè)鏈表管理每個(gè)任務(wù)的定時(shí)器,同樣的,每個(gè)定時(shí)器會(huì)更加任務(wù)ID來進(jìn)行匹配,所以,需要在hal增加對(duì)定時(shí)器更新的函數(shù);如下所示;
因?yàn)槭褂肅ubeMX修改配置,重新生成代碼后會(huì)覆蓋原文件stm32f1xx_it.c
,所以,重新生成的時(shí)候,注意添加osal_update_timers()
,如果對(duì)其他內(nèi)容感興趣的話,可以參考一下源碼;
測(cè)試代碼
使用串口3進(jìn)行任務(wù)測(cè)試,定義了兩個(gè)任務(wù),先貼出其中的一部分,詳細(xì)的可以全部的工程代碼;
int osal_main(void)
{
HAL_DISABLE_INTERRUPTS();
osal_init_system();
osal_add_Task(Serial_Task_Init,Serial_Task_EventProcess, 1);
osal_add_Task(Serial_Task_02_Init,Serial_Task_02_EventProcess, 2);
osal_Task_init();
osal_mem_kick();
HAL_ENABLE_INTERRUPTS();
//"hello task 01\r\n";
osal_start_reload_timer( Serial_TaskID, PRINTF_STR, 100);
//"hello task 02\r\n";
osal_start_reload_timer( Serial_Task_02_ID, PRINTF_STR_TASK_02, 500);
osal_start_system();
}
下面是運(yùn)行結(jié)果:
結(jié)語
如果不使用RTOS
,那么OSAL
也是不錯(cuò)的選擇,不過還需要對(duì)其源碼需要進(jìn)一步的理解,這樣在出現(xiàn)問題的時(shí)候,才可以對(duì)癥下藥。
附件
該工程基于CubeIDE 1.3
:
百度網(wǎng)盤:https://pan.baidu.com/s/1zXkEp7jNoO-ODqMtU5YxBA)
提取碼:ncry
Github:https://github.com/hotsauce1861/osal.git
長(zhǎng)按下圖二維碼關(guān)注,獨(dú)自前進(jìn),走得快;結(jié)伴而行,走得遠(yuǎn);在這里除了肝出來的文章,還有一步一個(gè)腳印學(xué)習(xí)的點(diǎn)點(diǎn)滴滴;
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問題,請(qǐng)聯(lián)系我們,謝謝!