基于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.rhkb.cn/news/7924.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【测试】UI自动化测试

长期更新&#xff0c;建议关注收藏点赞&#xff01; 目录 概论WEB环境搭建Selenium元素定位 APPAppium 概论 user interface UI 使用工具和代码执行用例。 什么样的项目需要自动化&#xff1f; 需要回归测试、自动化的功能模块需求变更不频繁、项目周期长&#xff08;功能测试…

【随手笔记】FFT资料整理

&#xff08;一&#xff09;结果验证 函数波形示例1 #define Fs 44800 #define NPT 256 void InitBufInArray() {int i 0;float fx 0;for(i0; i<NPT; i){// fx 1500 * sin(2*PI * i * 350.0 / Fs) // 2700 * sin(2*PI * i * 8400.0 / Fs) // 4000 * sin(2*P…

Airflow:Airflow子流程应用实践

Apache Airflow是一个强大的开源平台&#xff0c;用于以编程方式编写、调度和监控工作流。它的一个强大功能是使用子DAG&#xff08;子有向无环图&#xff09;创建复杂工作流的能力&#xff0c;子DAG本质上是在父DAG中更小的嵌套DAG。在这篇博文中&#xff0c;我们将深入探讨su…

狗狗能吃萝卜吗?

各位铲屎官们&#xff0c;今天咱们来聊聊一个超实用的话题&#xff1a;狗狗能吃萝卜吗&#xff1f;很多新手铲屎官可能会觉得萝卜营养丰富&#xff0c;想给狗狗也尝尝鲜&#xff0c;但其实这里面大有讲究&#xff01; 狗狗可以吃萝卜&#xff0c;但要注意方法 首先&#xff0c…

Excel制作合同到期自动提醒!

大家好&#xff0c;我是小鱼。 今天分享一下如何利用Excel制作合同到期提醒表&#xff0c;实现Excel表格自动计算合同到期日和天数&#xff0c;根据合同状态和到期天数自动填充颜色提醒&#xff0c;超实用。先看一下效果&#xff0c;已经到期的合同会自动被填充为红色&#xf…

Python Flask教程

一、前言 Flask是一个用Python编写的轻量级的Web应用框架。 Flask基于WSGI&#xff08;Web Server Gateway Interface&#xff09;和 Jinja2 模板引擎&#xff0c;旨在帮助开发者快速、简便地创建 Web 应用。 Flask 被称为"微框架"&#xff0c;因为它使用简单的核…

【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】1.10 文本数据炼金术:从CSV到结构化数组

1.10 《文本数据炼金术&#xff1a;从CSV到结构化数组》 目录 #mermaid-svg-TNkACjzvaSXnULaB {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-TNkACjzvaSXnULaB .error-icon{fill:#552222;}#mermaid-svg-TNkACjzva…

Linux进程概念:【环境变量】【程序地址空间】

目录 一.环境变量 1.1基本概念 1.2命令行参数 1.3一个例子&#xff0c;一个环境变量 1.4环境变量的组织方式 1.5查看环境变量的方法 ​编辑 1.6从存储的角度理解环境变量 1.7环境变量最开始是从系统的配置文件里来的 1.8认识更多的环境变量 HOME HISTSIZE HOSTNANE…

医疗集群系统中基于超融合数据库架构的应用与前景探析

一、引言 1.1 研究背景与意义 随着医疗信息化的飞速发展,医疗数据呈爆炸式增长。从日常诊疗记录、患者病历,到各类医疗影像、检查检验数据等,海量信息不断涌现。据统计,医疗数据的年增长率高达 30% 以上 ,2025 年,全球医疗数据量将达到 2314 艾字节(EB)。如此庞大的数…

【leetcode100】从前序与中序遍历序列构造二叉树

1、题目描述 给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵树的中序遍历&#xff0c;请构造二叉树并返回其根节点。 示例 1: 输入: preorder [3,9,20,15,7], inorder [9,3,15,20,7] 输出: [3,9,20,nul…

【CSS入门学习】Flex布局设置div水平、垂直分布与居中

水平平均分布 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><style>…

【ARM】解决MDK在打开工程的时候提示CMSIS的版本不对问题

1、 文档目标 解决MDK在打开使用Compiler 6的工程的时候&#xff0c;提示CMSIS 的API版本过低的报错。 2、 问题场景 客户在Pack包中打开一个示例工程&#xff0c;打算熟悉一下对应芯片的功能和软件的功能&#xff0c;但是&#xff0c;打开软件后&#xff0c;在构建信息输出框…

PyCharm接入DeepSeek实现AI编程

目录 效果演示 创建API key 在PyCharm中下载CodeGPT插件 配置Continue DeepSeek 是一家专注于人工智能技术研发的公司&#xff0c;致力于开发高性能、低成本的 AI 模型。DeepSeek-V3 是 DeepSeek 公司推出的最新一代 AI 模型。其前身是 DeepSeek-V2.5&#xff0c;经过持续的…

【PyTorch][chapter 29][李宏毅深度学习]Fine-tuning LLM

参考&#xff1a; https://www.youtube.com/watch?veC6Hd1hFvos 目录&#xff1a; 什么是 Fine-tune 为什么需要Fine-tuning 如何进行Fine-tune Fine-tuning- Supervised Fine-tuning 流程 Fine-tuning参数训练的常用方案 LORA 简介 示例代码 一 什么是 Fine-tune …

动手学图神经网络(3):利用图神经网络进行节点分类 从理论到实践

利用图神经网络进行节点分类&#xff1a;从理论到实践 前言 在之前的学习中&#xff0c;大家对图神经网络有了初步的了解。本次教程将深入探讨如何运用图神经网络&#xff08;GNNs&#xff09;来解决节点分类问题。在节点分类任务里&#xff0c;大家往往仅掌握少量节点的真实…

云原生:构建现代化应用的基石

一、什么是云原生&#xff1f; 云原生是一种构建和运行应用程序的方法&#xff0c;旨在充分利用云计算的分布式系统优势&#xff0c;例如弹性伸缩、微服务架构、容器化技术等。云原生应用程序从设计之初就考虑到了云环境的特点&#xff0c;能够更好地适应云平台的动态变化&…

springboot3 集成 knife4j(接口文档)

提示&#xff1a;文章是集成 knife4j&#xff0c;而非 swagger2 或者 swagger3&#xff0c;效果如图 文章目录 前言一、添加依赖二、如何集成1.配置文件2.注解部分1.Tag2.Operation3.Parameter4.Schema 3.使用 总结 前言 提示&#xff1a;&#xff1a;大家在开发阶段&#xff…

基于单片机的智能小区门禁系统设计(论文+源码)

1总体架构 智能小区门禁系统以STM32单片机和WiFi技术为核心&#xff0c;STM32单片机作为主控单元&#xff0c;通过WiFi模块实现与手机APP的连接&#xff0c;构建整个门禁系统。系统硬件包括RFID模块、指纹识别模块、显示屏、按键以及继电器。通过RFID绑定IC卡、APP面部识别、指…

后盾人JS--闭包明明白白

延伸函数环境生命周期 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> <…

The just sharing principle: advice for advice givers

原文 A while ago I wrote about how Only you know what’s best for your application. That’s because only you fully understand the context within which you are making technical decisions. Any advice need to filtered through that context in order to determi…