基于OSAL的嵌入式裸機事件驅動框架——整體架構調度機制


參考B站up主【架構分析】嵌入式祼機事件驅動框架
感謝大佬分享


  1. 任務ID : TASK_XXX
    TASK_XXX 在系統中每個任務的ID是唯一的,范圍是 0 to 0xFFFE,0xFFFF保留為SYS_TSK_INIT。
    同時任務ID的大小也充當任務調度的優先級,ID越大,優先級越高,越排在任務鏈表的最前面

  2. 事件ID :EVE_XXX
    EVE_XXX和任務綁定,對于一個任務來說,一個任務的事件集有16位,最高位1<<15 保留為系統消息事件SYS_EVE_MSG,剩下的1<<0 到 1<<14由用戶定義
    對于不同的任務,EVE_XXX可以相同,但是對于某一個任務,EVE_XXX應是唯一的

  3. 消息事件ID : EVE_MSG_XXX
    EVE_MSG_XXX被消息的bdy所攜帶,當將消息發送給任務時,會觸發任務的系統消息事件SYS_EVE_MSG,然后在任務的事件處理函數handler中,取出消息事件EVE_MSG_XXX和數據data,根據EVE_MSG_XXX做不同的處理。
    EVE_MSG_XXX與EVE_XXX是不同的,EVE_MSG_XXX是消息事件中的消息所攜帶的事件,EVE_XXX是某個任務事件集中的某個事件。
    EVE_MSG_XXX的范圍是 0 到 0xFFFF,盡可能使用不同的EVE_MSG_XXX

![[Pasted image 20250123183033.png]]
(注:此架構圖來自B站up主的視頻【架構分析】嵌入式祼機事件驅動框架)

創建任務,初始化(包括硬件方面,軟件邏輯方面等)
也可以在初始化中創建軟件定時器,軟件定時器超時后會把對應任務的事件置位,即觸發事件。

系統調度后在osal_system_start中會循環檢查有沒有觸發事件的任務,有則通過task_handler處理

消息通過osal_send_msg發送消息到消息隊列,因為消息其實是和任務task_id綁定起來的,消息發送到消息隊列后會把對應的任務中的 SYS_MSG_EVE置位,即觸發消息事件。然后在task_handler中通過osal_recv_msg讀取 消息,把消息提取出來,然后釋放消息內存

也可以直接通過調用osal_task_seteve觸發指定任務的事件

核心就是任務task,應用層中 通過 task_id和event_id實現事件驅動的調度

中斷中如何往OSAL中去集成

  1. 通過直接觸發相應的事件osal_task_seteve
  2. 通過消息隊列
    如果數據比較少,可以直接通過消息隊列發送。
    或者使用數據緩沖層,在任務處理task_handler中取數據

在app.h中聲明所有的任務id,事件id,以及處理接口ops

調度函數

osal_system_start
在主程序中調用osal_system_start

  1. 尋找觸發事件的任務
  2. 執行任務事件處理函數
  3. 將執行完的事件在事件集中剔除掉

通過osal_task_active獲取有效任務,即有事件觸發的任務,將其事件集提取出來賦值給events變量。
將task_active->events給清理掉,最開始是一個多線程的考慮,在邏輯輪詢中
調用任務的事件處理函數task_active->ops->handler,這個函數由用戶提供,參數是任務id和事件集,在此函數中需要剔除掉對應的事件,然后將剔除事件 過后 的事件集 返回,然后將返回值 或上任務的事件集
![[Pasted image 20250125200955.png]]
(注:此架構圖來自B站up主的視頻【架構分析】嵌入式祼機事件驅動框架)

/*********************************************************************  * @fn      osal_system_start * * @brief * *   This function is the main loop function of the task system.  It *   will look through all task events and call the task_event_processor() *   function for the task with the event.  If there are no events (for *   all tasks), this function puts the processor into Sleep. *   This Function doesn't return. * * @param   void * * @return  none *//*可以考慮不加臨界區,直接用原子操作,減少開銷*/  
void osal_system_start(void)  
{  event_asb_t events,ret_events;  osal_task_t *task_active;  while(1)  {  task_active = osal_task_active();  if ( task_active != NULL )  {  OSAL_ENTER_CRITICAL();  events = task_active->events;  task_active->events = SYS_EVE_NONE;  OSAL_EXIT_CRITICAL();  if(events != SYS_EVE_NONE)  {  if(task_active->ops->handler != NULL)  {  ret_events = task_active->ops->handler(task_active->task_id,events);  OSAL_ENTER_CRITICAL();  task_active->events |= ret_events;  OSAL_EXIT_CRITICAL();  }  }  }  }  
}

osal.h

#ifndef OSAL_H  
#define OSAL_H  //#include "heap.h"  
#include "stm32h7xx_hal.h"  #define OSAL_ERROR                0  
#define OSAL_SUCCESS              1  
#define INVALID_TASK              2  
#define INVALID_MSG_POINTER       3  
#define INVALID_EVENT_ID          4  
#define INVALID_TIMER             5  //芯片硬件字長  
typedef unsigned int        halDataAlign_t;  // Unsigned numbers  
typedef unsigned char       osal_bool_t;  
typedef unsigned char       osal_byte_t;  
typedef unsigned char       osal_uint8_t;  
typedef unsigned short      osal_uint16_t;  
typedef unsigned int        osal_uint32_t;  // Signed numbers  
typedef signed char         osal_int8_t;  
typedef signed short        osal_int16_t;  
typedef signed int          osal_int32_t;  #define osal_container_of(ptr, type, member) ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))  /**進入臨界區和退出臨界區**/  
//#define CLI()         __set_PRIMASK(1)              // Disable Interrupts  
//#define SEI()         __set_PRIMASK(0)              // Enable Interrupts  
#define CLI()           __disable_irq()               // Disable Interrupts  
#define SEI()           __enable_irq()                // Enable Interrupts  #define OSAL_ENABLE_INTERRUPTS()         SEI()       // Enable Interrupts  
#define OSAL_DISABLE_INTERRUPTS()        CLI()       // Disable Interrupts  
#define OSAL_ENTER_CRITICAL()            CLI()  
#define OSAL_EXIT_CRITICAL()             SEI()  /**內存管理**/  
//#define osal_mem_alloc                  pvHeapMalloc  
//#define osal_mem_free                   vHeapFree  #define osal_delay(ms)                  HAL_Delay(ms)  osal_uint8_t osal_init_system(void);  
void osal_system_start(void);  int osal_strlen( char *pString );  
void *osal_memcpy( void *dst, const void *src, unsigned int len );  
void *osal_revmemcpy( void *dst, const void *src, unsigned int len );  
void *osal_memdup( const void *src, unsigned int len );  
osal_uint8_t osal_memcmp( const void *src1, const void *src2, unsigned int len );  
void *osal_memset( void *dest, osal_uint8_t value, int len );  #endif

osal.c

/*********************************************************************  * @fn      osal_init_system * * @brief * *   This function initializes the "task" system by creating the *   tasks defined in the task table (OSAL_Tasks.h). * * @param   void * * @return  ZSUCCESS */osal_uint8_t osal_init_system( void )  
{  // Initialize the Memory Allocation System  
#if OSALMEM_METRICS  osal_mem_init();  
#endif  return ( OSAL_SUCCESS );  
}  /*********************************************************************  * @fn      osal_system_start * * @brief * *   This function is the main loop function of the task system.  It *   will look through all task events and call the task_event_processor() *   function for the task with the event.  If there are no events (for *   all tasks), this function puts the processor into Sleep. *   This Function doesn't return. * * @param   void * * @return  none *//*可以考慮不加臨界區,直接用原子操作,減少開銷*/  
void osal_system_start(void)  
{  event_asb_t events,ret_events;  osal_task_t *task_active;  while(1)  {  task_active = osal_task_active();  if ( task_active != NULL )  {  OSAL_ENTER_CRITICAL();  events = task_active->events;  task_active->events = SYS_EVE_NONE;  OSAL_EXIT_CRITICAL();  if(events != SYS_EVE_NONE)  {  if(task_active->ops->handler != NULL)  {  ret_events = task_active->ops->handler(task_active->task_id,events);  OSAL_ENTER_CRITICAL();  task_active->events |= ret_events;  OSAL_EXIT_CRITICAL();  }  }  }  }  
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/67236.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/67236.shtml
英文地址,請注明出處:http://en.pswp.cn/web/67236.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

WGCLOUD運維工具從入門到精通 - 如何設置主題背景

需要升級到WGCLOUD的v3.5.7或者以上版本&#xff0c;才會支持自定義設置主題背景色 WGCLOUD下載&#xff1a;www.wgstart.com 我們登錄后&#xff0c;在右上角點擊如下的小圖標&#xff0c;就可以設置主題背景色了&#xff0c;包括&#xff1a;經典白&#xff08;默認&#x…

LigerUI在MVC模式下的響應原則

LigerUI是基于jQuery的UI框架&#xff0c;故他也是遵守jQuery的開發模式&#xff0c;但是也具有其特色的偵聽函數&#xff0c;那么當LigerUI作為View層的時候&#xff0c;他所發送后端的必然是表單的數據&#xff0c;在此我們以倆個div為例&#xff1a; {Layout "~/View…

基于RIP的MGRE VPN綜合實驗

實驗拓撲 實驗需求 1、R5為ISP&#xff0c;只能進行IP地址配置&#xff0c;其所有地址均配為公有IP地址&#xff1b; 2、R1和R5間使用PPP的PAP認證&#xff0c;R5為主認證方&#xff1b; R2與R5之間使用ppp的CHAP認證&#xff0c;R5為主認證方&#xff1b; R3與R5之間使用HDLC封…

git的理解與使用

本地的git git除了最經典的add commit push用來做版本管理&#xff0c;其實他的分支管理也非常強大 可以說你學好了分支管理&#xff0c;就可以完成團隊的配合協作了 git倉庫 我們可以使用git init來初始化一個git倉庫&#xff0c;只要能看見.git文件夾&#xff0c;就代表這…

Java 編程初體驗

Java學習資料 Java學習資料 Java學習資料 一、引言 在當今數字化的時代&#xff0c;編程已然成為一項極具價值的技能。而 Java 作為一門廣泛應用于企業級開發、移動應用、大數據等眾多領域的編程語言&#xff0c;吸引著無數初學者投身其中。當我們初次踏入 Java 編程的世界&…

STM32 對射式紅外傳感器配置

這次用的是STM32F103的開發板&#xff08;這里面的exti.c文件沒有how to use this driver 配置說明&#xff09; 對射式紅外傳感器 由一個紅外發光二極管和NPN光電三極管組成&#xff0c;M3固定安裝孔&#xff0c;有輸出狀態指示燈&#xff0c;輸出高電平燈滅&#xff0c;輸出…

https數字簽名手動驗簽

以bing.com 為例 1. CA 層級的基本概念 CA 層級是一種樹狀結構&#xff0c;由多個層級的 CA 組成。每個 CA 負責為其下一層級的實體&#xff08;如子 CA 或終端實體&#xff09;頒發證書。層級結構的頂端是 根 CA&#xff08;Root CA&#xff09;&#xff0c;它是整個 PKI 體…

【自然語言處理(NLP)】深度循環神經網絡(Deep Recurrent Neural Network,DRNN)原理和實現

文章目錄 介紹深度循環神經網絡&#xff08;DRNN&#xff09;原理和實現結構特點工作原理符號含義公式含義 應用領域優勢與挑戰DRNN 代碼實現 個人主頁&#xff1a;道友老李 歡迎加入社區&#xff1a;道友老李的學習社區 介紹 **自然語言處理&#xff08;Natural Language Pr…

Niagara學習筆記

橙色 發射器 , 綠色 粒子, 紅色 渲染器 Emitter State 發射器狀態 Life Cycle Mode&#xff08;生命周期模式&#xff09; 選擇Self就是發射器自身管理生命周期 Loop Behavior 決定粒子發射次數 一次&#xff08;Once&#xff09;&#xff1a;發射器只播放一次多次&#…

17 一個高并發的系統架構如何設計

高并發系統的理解 第一:我們設計高并發系統的前提是該系統要高可用&#xff0c;起碼整體上的高可用。 第二:高并發系統需要面對很大的流量沖擊&#xff0c;包括瞬時的流量和黑客攻擊等 第三:高并發系統常見的需要考慮的問題&#xff0c;如內存不足的問題&#xff0c;服務抖動的…

2025數學建模美賽|F題成品論文

國家安全政策與網絡安全 摘要 隨著互聯網技術的迅猛發展&#xff0c;網絡犯罪問題已成為全球網絡安全中的重要研究課題&#xff0c;且網絡犯罪的形式和影響日益復雜和嚴重。本文針對網絡犯罪中的問題&#xff0c;基于多元回歸分析和差異中的差異&#xff08;DiD&#xff09;思…

適配Android16

Android16新特性 Android 16帶來了許多新特性和改進&#xff0c;提升了系統的流暢度、用戶體驗和安全性。對于應用開發者來說&#xff0c;適配Android 16可以確保應用在該版本上的兼容性和性能&#xff0c;同時也可以利用其新特性為用戶提供更好的服務。以下是Android 16的一些…

【C++數論】880. 索引處的解碼字符串|2010

本文涉及知識點 數論&#xff1a;質數、最大公約數、菲蜀定理 LeetCode880. 索引處的解碼字符串 給定一個編碼字符串 s 。請你找出 解碼字符串 并將其寫入磁帶。解碼時&#xff0c;從編碼字符串中 每次讀取一個字符 &#xff0c;并采取以下步驟&#xff1a; 如果所讀的字符是…

【MQ】如何保證消息隊列的高可用?

RocketMQ NameServer集群部署 Broker做了集群部署 主從模式 類型&#xff1a;同步復制、異步復制 主節點返回消息給客戶端的時候是否需要同步從節點 Dledger&#xff1a;要求至少消息復制到半數以上的節點之后&#xff0c;才給客戶端返回寫入成功 slave定時從master同步數據…

ESP32 I2S音頻總線學習筆記(二):I2S讀取INMP441音頻數據

簡介 在這個系列的上一篇文章中&#xff0c;我們介紹了ESP32 I2S音頻總線的相關知識&#xff0c;簡要了解了什么是I2S總線、它的通信格式&#xff0c;以及相關的底層API函數。沒有看過上篇文章的可以點擊文章進行回顧&#xff1a; ESP32 I2S音頻總線學習筆記&#xff08;一&a…

EasyExcel使用詳解

文章目錄 EasyExcel使用詳解一、引言二、環境準備與基礎配置1、添加依賴2、定義實體類 三、Excel 讀取詳解1、基礎讀取2、自定義監聽器3、多 Sheet 處理 四、Excel 寫入詳解1、基礎寫入2、動態列與復雜表頭3、樣式與模板填充 五、總結 EasyExcel使用詳解 一、引言 EasyExcel 是…

objection的簡單使用

objection環境配置 下載以下版本 objection1.11.0 frida-tools9.2.4 python3.8.8 報錯的話看這里: 在這個網站下載frida-tools14.2.18的離線包Links for frida 然后放入C:\Users\Asus\frida-14.2.18-py3.8-win-amd64.egg文件夾下 執行poetry add frida-tools14.2.18 ob…

危機13小時:追蹤一場GitHub投毒事件

事件概要 自北京時間 2024.12.4 晚間6點起&#xff0c; GitHub 上不斷出現“幽靈倉庫”&#xff0c;倉庫中沒有任何代碼&#xff0c;只有誘導性的病毒文件。當天&#xff0c;他們成為了 GitHub 上 star 增速最快的倉庫。超過 180 個虛假僵尸賬戶正在傳播病毒&#xff0c;等待不…

【Redis】緩存+分布式鎖

目錄 緩存 Redis最主要的使用場景就是作為緩存 緩存的更新策略&#xff1a; 1.定期生成 2.實時生成 面試重點&#xff1a; 緩存預熱&#xff08;Cache preheating&#xff09;&#xff1a; 緩存穿透&#xff08;Cache penetration&#xff09; 緩存雪崩 (Cache avalan…

記錄 | MaxKB創建本地AI智能問答系統

目錄 前言一、重建MaxKBStep1 復制路徑Step2 刪除MaxKBStep3 創建數據存儲文件夾Step4 重建 二、創建知識庫Step1 新建知識庫Step2 下載測試所用的txtStep3 上傳本地文檔Step4 選擇模型補充智譜的API Key如何獲取 Step5 查看是否成功 三、創建應用Step1 新建應用Step2 配置AI助…