基于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.mzph.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助…