基于OSAL的嵌入式裸机事件驱动框架——整体架构调度机制
参考B站up主【架构分析】嵌入式祼机事件驱动框架
感谢大佬分享
-
任务ID : TASK_XXX
TASK_XXX 在系统中每个任务的ID是唯一的,范围是 0 to 0xFFFE,0xFFFF保留为SYS_TSK_INIT。
同时任务ID的大小也充当任务调度的优先级,ID越大,优先级越高,越排在任务链表的最前面 -
事件ID :EVE_XXX
EVE_XXX和任务绑定,对于一个任务来说,一个任务的事件集有16位,最高位1<<15 保留为系统消息事件SYS_EVE_MSG,剩下的1<<0 到 1<<14由用户定义
对于不同的任务,EVE_XXX可以相同,但是对于某一个任务,EVE_XXX应是唯一的 -
消息事件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]]](https://i-blog.csdnimg.cn/direct/276fe6425bd6470ab95444fd07cbb5a6.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中去集成
- 通过直接触发相应的事件osal_task_seteve
- 通过消息队列
如果数据比较少,可以直接通过消息队列发送。
或者使用数据缓冲层,在任务处理task_handler中取数据
在app.h中声明所有的任务id,事件id,以及处理接口ops
调度函数
osal_system_start
在主程序中调用osal_system_start
- 寻找触发事件的任务
- 执行任务事件处理函数
- 将执行完的事件在事件集中剔除掉
通过osal_task_active获取有效任务,即有事件触发的任务,将其事件集提取出来赋值给events变量。
将task_active->events给清理掉,最开始是一个多线程的考虑,在逻辑轮询中
调用任务的事件处理函数task_active->ops->handler,这个函数由用户提供,参数是任务id和事件集,在此函数中需要剔除掉对应的事件,然后将剔除事件 过后 的事件集 返回,然后将返回值 或上任务的事件集
![![[Pasted image 20250125200955.png]]](https://i-blog.csdnimg.cn/direct/7bbc529ea1df45cb94419232d050efe2.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(); } } } }
}
相关文章:
基于OSAL的嵌入式裸机事件驱动框架——整体架构调度机制
参考B站up主【架构分析】嵌入式祼机事件驱动框架 感谢大佬分享 任务ID : TASK_XXX TASK_XXX 在系统中每个任务的ID是唯一的,范围是 0 to 0xFFFE,0xFFFF保留为SYS_TSK_INIT。 同时任务ID的大小也充当任务调度的优先级,ID越大&#…...
Three.js 后期处理(Post-Processing)详解
目录 前言 一、什么是后期处理? 二、Three.js 后期处理的工作流程 2.1 创建 EffectComposer 2.2 添加渲染通道(Render Pass) 2.3 应用最终渲染 三、后期处理实现示例 3.1 基础代码 四、常见的后期处理效果 4.1 辉光效果…...
HTML特殊符号的使用示例
目录 一、基本特殊符号的使用 1、空格符号: 2、小于号 和 大于号: 3、引号: 二、版权、注册商标符号的使用 1、版权符号:© 2、注册商标符号: 三、数学符号的使用 四、箭头符号的使用 五、货币符号的使用…...
JAVA实战开源项目:在线文档管理系统(Vue+SpringBoot) 附源码
本文项目编号 T 038 ,文末自助获取源码 \color{red}{T038,文末自助获取源码} T038,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 查…...
git中有关old mode 100644、new mode 10075的问题解决小结
在 Git 版本控制系统中,文件权限变更是一种常见情况。当你看到类似 old mode 100644 和 new mode 100755 的信息时,这通常表示文件的权限发生了变化。本文将详细解析这种情况,并提供解决方法和注意事项。 问题背景 在 Git 中,文…...
快速分析LabVIEW主要特征进行判断
在LabVIEW中,快速分析程序特征进行判断是提升开发效率和减少调试时间的重要技巧。本文将介绍如何高效地识别和分析程序的关键特征,从而帮助开发者在编写和优化程序时做出及时的判断,避免不必要的错误。 数据流和并行性分析 LabVIEW的图形…...
UE学习日志#15 C++笔记#1 基础复习
1.C20的import 看看梦开始的地方: import <iostream>;int main() {std::cout << "Hello World!\n"; } 经过不仔细观察发现梦开始的好像不太一样,这个import是C20的模块特性 如果是在VS里编写的话,要用这个功能需要新…...
不够专业,想更体系化
在赚钱路上,总觉得学的不够好,还不专业,觉得拿不出手,不敢去教别人或者帮别人解决问题,发言,说自己的想法,或者收钱。 于是继续拼命学习,看书,买课,报班&…...
Deep Seek R1本地化部署
目录 说明 一、下载ollama 二、在ollama官网下载模型 三、使用 后记 说明 操作系统:win10 使用工具:ollama 一、下载ollama 从官网下载ollama: ollama默认安装在C盘,具体位置为C:\Users\用户名\AppData\Local\Programs\O…...
C# Winform制作一个登录系统
using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms;namespace 登录 {p…...
动态规划DP 最长上升子序列模型 总览
最长上升子序列模型 1. 最长上升子序列 1.1 怪盗基德的滑翔伞 1.1.1 登山 1.1.2 合唱队形 1.2 友好城市 1.3 最长上升子序列和 1.4 导弹拦截...
怎样在PPT中启用演讲者视图功能?
怎样在PPT中启用演讲者视图功能? 如果你曾经参加过重要的会议或者演讲,你就会知道,演讲者视图(Presenter View)对PPT展示至关重要。它不仅能帮助演讲者更好地掌控演讲节奏,还能提供额外的提示和支持&#…...
Ubuntu安装VMware17
安装 下载本文的附件,之后执行 sudo chmod x VMware-Workstation-Full-17.5.2-23775571.x86_64.bundle sudo ./VMware-Workstation-Full-17.5.2-23775571.x86_64.bundle安装注意事项: 跳过账户登录的办法:断开网络 可能出现的问题以及解决…...
论文阅读(七):贝叶斯因果表型网络解释遗传变异和生物学知识
1.论文链接:Bayesian Causal Phenotype Network Incorporating Genetic Variation and Biological Knowledge 摘要: 在分离群体中,数量性状基因座(QTL)定位可以确定对表型有因果效应的QTL。这些方法的一个共同特点是Q…...
CAPL与外部接口
CAPL与外部接口 目录 CAPL与外部接口1. 引言2. CAPL与C/C++交互2.1 CAPL与C/C++交互简介2.2 CAPL与C/C++交互实现3. CAPL与Python交互3.1 CAPL与Python交互简介3.2 CAPL与Python交互实现4. CAPL与MATLAB交互4.1 CAPL与MATLAB交互简介4.2 CAPL与MATLAB交互实现5. 案例说明5.1 案…...
1.27补题 回训练营
E 智乃的小球 题目描述 在一条无限长的水平直线上,有 n 个小球,每个小球的质量相同,体积可以忽略不计。这些小球初始时位于直线上的不同位置,并且每个小球有一个初始速度,速度为 -1 m/s 或 1 m/s。速度为 -1 m/s 表示…...
INCOSE需求编写指南-附录 B: 首字母缩略词和缩写
附录 Appendix B: 首字母缩略词和缩写ACRONYMS AND ABBREVIATIONS AD 难易程度的进阶 Advancement Degree of Difficulty AI 人工智能 Artificial Intelligence CM 配置管理 Configuration Management ConOps 运作理念 Concept of Operations COTS 商业现货 Comme…...
B站吴恩达机器学习笔记
机器学习视频地址: 4.5 线性回归中的梯度下降_哔哩哔哩_bilibili 损失函数学习地址: 损失函数选择 选凸函数的话,会收敛到全局最小值。证明凸函数用Hessian矩阵。凸函数定义:两点连线比线上所有点都大。 batch理解࿱…...
Vscode编辑器下 Markdown无法显示图片
1.问题 在vscode 编辑器中无法预览 markdon 文件中的图片 2.解决方案 大部分出现这种情况是因为新版本的vscode会阻拦有风险的资源显示,将安全等级调低即可。 方式一: 1.打开任意 MD 文件,ctrl,调出设置 2. 输入 markdown.ch…...
mysql重学(一)mysql语句执行流程
思考 一条查询语句如何执行?mysql语句中若列不存在,则在哪个阶段报错一条更新语句如何执行?redolog和binlog的区别?为什么要引入WAL什么是Changbuf?如何工作写缓冲一定好吗?什么情况会引发刷脏页删除语句会…...
国产650V碳化硅MOSFET在通信电源应用中全面取代超结MOSFET
在通信电源应用中,国产650V碳化硅(SiC)MOSFET全面取代超结MOSFET(如硅基CoolMOS),是技术迭代、政策推动、市场需求和国产产业链成熟共同作用的结果。倾佳电子杨茜从以下多个维度解析这一趋势: 倾…...
【ComfyUI专栏】通过软件获取PNG图片中的工作流信息
自从AI生成图片技术发展之后,你会发现很有意思的情况就是所有的图片中开始包含利用AI生成的工作流。有的时候你直接将图片拖到ComfyUI来获取图片中的工作流。下面的图片中的信息很意外的没有包含工作流,但那时我们可以看到的Parameters里面包含了设置之外,也有工作流节点内容…...
大一计算机的自学总结:位运算实现加减乘除
前言 位运算当然可以用来实现加减乘除。 一、加法 #include<bits/stdc.h> using namespace std;int add(int a,int b) {int ansa;while(b!0){ansa^b;b(a&b)<<1;aans;}return ans; }int main() {int a,b;cout<<"a,b:"<<endl;cin>&g…...
《LLM大语言模型+RAG实战+Langchain+ChatGLM-4+Transformer》
文章目录 Langchain的定义Langchain的组成三个核心组件实现整个核心组成部分 为什么要使用LangchainLangchain的底层原理Langchain实战操作LangSmithLangChain调用LLM安装openAI库-国内镜像源代码运行结果小结 使用Langchain的提示模板部署Langchain程序安装langserve代码请求格…...
天融信 NGFW2.3 mibs
1. 新节点 库节点名称含义OID数据类型权限私有库tosRouteEntryrouteNetDst路由目地址1.3.6.1.4.1.14331.5.5.1.8.1.3OCTET STRINGread-only私有库tosRouteEntryrouteWeight路由权重1.3.6.1.4.1.14331.5.5.1.8.1.9Integer32read-only私有库tosRouteEntryrouteProbeID路由探测ID…...
进程控制的学习
目录 1.进程创建 1.1 fork函数 1.2 fork函数返回值 1.3 写时拷贝 1.4 fork 常规用法 1.5 fork 调用失败的原因 2. 进程终止 2.1 进程退出场景 2.2 进程常见退出方法 2.2.1 从main 返回 2.2.2 echo $? 查看进程退出码 2.2.2.1 我们如何得到退出码代表的含…...
rsync安装与使用-linux015
使用 rsync 可以非常高效地将文件或目录从一个服务器传输到另一个服务器。 能力: 支持 64 位文件、64 位 inode、64 位时间戳、64 位长整型支持套接字对、符号链接、符号链接时间、硬链接、硬链接特殊文件、硬链接符号链接支持 IPv6、访问时间(atimes&…...
Formality:时序变换(二)(不可读寄存器移除)
相关阅读 Formalityhttps://blog.csdn.net/weixin_45791458/category_12841971.html?spm1001.2014.3001.5482 一、引言 时序变换在Design Compiler的首次综合和增量综合中都可能发生,它们包括:时钟门控(Clock Gating)、寄存器合并(Register Merging)、…...
前端实战:小程序搭建商品购物全流程
目录 项目概述 开发环境搭建 微信开发者工具下载与安装 项目创建流程 项目目录结构及各文件作用 商品展示页面开发 页面布局(WXML 与 WXSS) 数据获取与绑定(JavaScript) 加入购物车功能实现 购物车功能开发 购物车页面布…...
Python中的函数(下)
函数返回值 返回单个值 函数可以通过 return 语句返回一个值。一旦执行到 return 语句,函数就会停止执行,并将指定的值返回给调用者。例如: 返回多个值 实际上,Python函数只能返回一个值,但可以通过返回一个元组来模…...
