基于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
(注:此架构图来自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和事件集,在此函数中需要剔除掉对应的事件,然后将剔除事件 过后 的事件集 返回,然后将返回值 或上任务的事件集
(注:此架构图来自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越大&#…...
c++ string类 +底层模拟实现
提醒: 本片博客只是小编的听课笔记,介意勿看。 基础 包含在头文件<string>,才能使用string类似函数接口。 string常见构造类 string s1; cin>>s1;//无参构造 string s2(s1);//拷贝构造 string s1("jfksa");//传参构造 三种…...

六十分之三十七——一转眼、时光飞逝
一、目标 明确可落地,对于自身执行完成需要一定的努力才可以完成的 1.第三版分组、激励、立体化权限、智能设备、AIPPT做课 2.8本书 3.得到:头条、吴军来信2、卓克科技参考3 4.总结思考 二、计划 科学规律的,要结合番茄工作法、快速阅读、…...
Shell基础:中括号的使用
在Shell脚本中,中括号([ ... ] 和 [[ ... ]])是一种常见的条件测试结构。它们用于进行文件类型检查、值比较以及逻辑判断。通过了解它们的不同特点和用法,能够帮助你编写更加高效、安全且易读的脚本。本文将详细介绍Shell中单中括…...

《基于Scapy的综合性网络扫描与通信工具集解析》
在网络管理和安全评估中,网络扫描和通信是两个至关重要的环节。Python 的 Scapy 库因其强大的网络数据包处理能力,成为开发和实现这些功能的理想工具。本文将介绍一个基于 Scapy 编写的 Python 脚本,该脚本集成了 ARP 扫描、端口扫描以及 TCP…...
面经--C语言——sizeof和strlen,数组和链表,#include <>和 #include ““ #define 和typedef 内存对齐概述
文章目录 sizeof 和 strlen数组和链表总结 #include <>和 #include ""#define 和typedef内存对齐概述对齐规则示例:结构体的内存对齐分析: 内存对齐的常见规则:填充字节的计算对齐影响的实际例子 sizeof 和 strlen 特性size…...
使用 Kotlin 将 Vertx 和 Springboot 整合
本篇文章目的是将 Springboot 和 Vertx 进行简单整合。整合目的仅仅是为了整活,因为两个不同的东西整合在一起提升的性能并没有只使用 Vertx 性能高,因此追求高性能的话这是在我来说不推荐。而且他们不仅没有提高很多性能甚至增加了学习成本 一、整合流…...

线性回归算法-01
线性回归简介 学习目标 了解线性回归的应用场景知道线性回归的定义 1 线性回归应用场景 房价预测销售额度预测贷款额度预测 2 什么是线性回归 2.1 定义与公式 线性回归(Linear regression)是利用 回归方程(函数)对 一个或多个自变量(特征值)和因变量(目标值)之间关系进行建模…...

洛谷 P1130 红牌 C语言
题目描述 某地临时居民想获得长期居住权就必须申请拿到红牌。获得红牌的过程是相当复杂,一共包括 N 个步骤。每一步骤都由政府的某个工作人员负责检查你所提交的材料是否符合条件。为了加快进程,每一步政府都派了 M 个工作人员来检查材料。不幸的是&…...

虚幻UE5手机安卓Android Studio开发设置2025
一、下载Android Studio历史版本 步骤1:虚幻4.27、5.0、5.1、5.2官方要求Andrd Studio 4.0版本; 5.3、5.4、5.5官方要求的版本为Android Studio Flamingo | 2022.2.1 Patch 2 May 24, 2023 虚幻官网查看对应Andrd Studiob下载版本: https:/…...
线性代数复习笔记
1. 课程学习 1.1 3Blue1Brown 线性代数 2. 基本术语 eigenvector(特征向量):线性变换中方向保持不变的向量 可以视作3D旋转矩阵形成的旋转的轴...
你需要更深层次的解放
先谈一谈理性认知中的属性替换原则。简单来说,属性替换就是用简单的问题取代难题。 当人们需要评估属性A时,却发现评估属性B更容易一些(A与B之间存在一定的关系),于是就改为评估属性B。这叫做属性替换。 作为一种认知…...

机器学习算法在网络安全中的实践
机器学习算法在网络安全中的实践 本文将深入探讨机器学习算法在网络安全领域的应用实践,包括基本概念、常见算法及其应用案例,从而帮助程序员更好地理解和应用这一领域的技术。"> 序言 网络安全一直是信息技术领域的重要议题,随着互联…...

Qt事件处理:理解处理器、过滤器与事件系统
1. 事件 事件 是一个描述应用程序中、发生的某些事情的对象。 在 Qt 中,所有事件都继承自 QEvent ,并且每个事件都有特定的标识符,如:Qt::MouseButtonPress 代表鼠标按下事件。 每个事件对象包含该事件的所有相关信息ÿ…...
DeepSeek相关技术整理
相关介绍 2024年12月26日,DeepSeek V3模型发布(用更低的训练成本,训练出更好的效果)671B参数,激活37B。2025年1月20日,DeepSeek-R1模型发布(仅需少量标注数据(高质量长cotÿ…...

DeepSeek 遭 DDoS 攻击背后:DDoS 攻击的 “千层套路” 与安全防御 “金钟罩”
当算力博弈升级为网络战争:拆解DDoS攻击背后的技术攻防战——从DeepSeek遇袭看全球网络安全新趋势 在数字化浪潮席卷全球的当下,网络已然成为人类社会运转的关键基础设施,深刻融入经济、生活、政务等各个领域。从金融交易的实时清算…...

蓝桥杯之c++入门(二)【输入输出(上)】
目录 前言1.getchar和 putchar1.1 getchar()1.2 putchar() 2.scanf和 printf2.1 printf2.1.1基本用法2.1.2占位符2.1.3格式化输出2.1.3.1 限定宽度2.1.3.2 限定小数位数 2.2 scanf2.2.1基本用法2.2.2 占位符2.2.3 scanf的返回值 2.3练习练习1:…...

消息队列应用示例MessageQueues-STM32CubeMX-FreeRTOS《嵌入式系统设计》P343-P347
消息队列 使用信号量、事件标志组和线标志进行任务同步时,只能提供同步的时刻信息,无法在任务之间进行数据传输。要实现任务间的数据传输,一般使用两种方式: 1. 全局变量 在 RTOS 中使用全局变量时,必须保证每个任务…...

算法题(55):用最少数量的箭引爆气球
审题: 本题需要我们找到最少需要的箭数,并返回 思路: 首先我们需要把本题描述的问题理解准确 (1)arrow从x轴任一点垂直射出 (2)一旦射出,无限前进 也就是说如果气球有公共区域(交集&…...

谭浩强C语言程序设计(4) 8章(下)
1、输入三个字符串按照字母顺序从小到大输出 #include <cstdio> // 包含cstdio头文件,用于输入输出函数 #include <cstring> // 包含cstring头文件,用于字符串处理函数#define N 20 // 定义字符串的最大长度为20// 函数:…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...

Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...

在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...

逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...