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