什么是 OSAL?
今天同學忽然問我有沒有搞過OSAL,忽然間一頭霧水,於是在搜索引擎上找到了答案,發現這是一個十分實用的東西。
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操作系統抽象層用於保護協議棧軟件組件不受程序硬件細節的影響,減少程序的耦合性,提高可移植性和復用性。它可以獨立於程序環境,並且提供了以下功能。
- 任務注冊、初始化、啟動;
- 任務間的消息交換;
- 任務同步;
- 中斷處理;
- 計時器;
- 內存分配;
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位單片機需要設定內存池的字節對齊; - 添加任務函數中的任務優先級數值大的任務則優先級高;
- 根據需要修改
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吧,支持的功能也比較多,如果不用rtos的話,osal的話感覺也是不錯的選擇,不過還需要對其源碼需要進一步的理解,這樣在出現問題的時候,才可以對症下葯。
附件
該工程基於CubeIDE 1.3:
鏈接
提取碼:ncry
