STM32 OSAL操作系統抽象層的移植


 

 

 

什么是 OSAL?

今天同學忽然問我有沒有搞過OSAL,忽然間一頭霧水,於是在搜索引擎上找到了答案,發現這是一個十分實用的東西。
OSAL(operating system abstraction layer),操作系統抽象層,是一種以實現多任務為核心的系統資源管理機制,實現了類似RTOS的某些功能,但並不能稱之為真正意義上的RTOS,因為其本身還不支持任務的掛起,任務的搶占等等功能,但是這種機制,實現的代碼十分精簡,占用資源也非常少,對於資源十分緊張的嵌入式平台,也可以完成比較復雜的邏輯功能。
TI CC2530ZIGBEE協議棧Z-STACK中可以找到OSAL的身影,可以在官網上搜索z-stack下載相關的源碼,其中就包含了OSAL機制實現的源碼;移除掉一些無關功能的代碼之后,剩下OSAL的源碼總共約1100多行代碼,全部由C語言實現,資源占用約為RAM:512Byte,ROM:2KB。理論上可以移植到絕大多數的芯片平台上。

源碼安裝

目前官網上最新的版本,下載安裝到本地;

在這里插入圖片描述

安裝完成之后,可以到安裝目錄下,找到相應的源碼,不過這里基本上是zigbee的協議棧,所以OSAL相關的部分在下圖所示的路徑中;

在這里插入圖片描述
進入到osal路徑下的文件結構如下圖所示;
在這里插入圖片描述
這個OSAL操作系統抽象層用於保護協議棧軟件組件不受程序硬件細節的影響,減少程序的耦合性,提高可移植性和復用性。它可以獨立於程序環境,並且提供了以下功能。

  1. 任務注冊、初始化、啟動;
  2. 任務間的消息交換;
  3. 任務同步;
  4. 中斷處理;
  5. 計時器;
  6. 內存分配;

Linux 上OSAL的移植

可以嘗試把OSAL的框架移植到單片機上,進行測試,這里是GitHubfork的一個倉庫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工程目錄下,然后對工程文件列表進行刷新,可以看到如下圖所示;

在這里插入圖片描述
下面是作者基於tiosal的移植說明:

  1. 完成OSAL\hal\timer.c文件,為系統提供時鍾;
  2. 修改OSAL\include\type.h文件中的全局中斷開關函數(可以為空),添加芯片對應的頭文件,根據需要修改數據類型重定義,根據芯片字長修改halDataAlign_t類型;
  3. 根據需要修改OSAL\osal\osal_memory.h文件中的內存池大小定義,文件中osalMemHdr_t類型需要確保長度為16bit或以上,非8位單片機需要設定內存池的字節對齊;
  4. 添加任務函數中的任務優先級數值大的任務則優先級高;
  5. 根據需要修改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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM