文章目录[隐藏]
目录
都说,不会写 RTOS 的程序员不是好厨师,那么就写点东西吧;
V1.0 版本大概的组织是这样的:
这个 RTOS 命名为 MxOS;
项目地址为:
0. 配置
MxOS 相关的配置全部都在 os_configs.h 文件中,配置是自注释的,看命名就知道干嘛用的,提供的配置并不算丰富,省去了很多无意义的配置;
1. 体系架构
最先适配了 Cortex-M4 (带 FPU) 的体系架构(后面会适配 Cortex-A 系列和 RISC-V);和体系架构相关的代码放在 arch 目录下,主要是和 CPU(MCU)紧密相关的部分,包含一些中断开关,中断初始化,OS Tick 心跳,CPU(MCU)上下文的定义和上下文切换的汇编等等,这部分独立抽象出来,将接口定义完整,以便进行日后的体系架构的扩展;
针对 Cortex-M4 需要注意一点的是,Specification 里面提到的 FPU Lazy stacking 模式,在使用 OS 的情况下,最好打开它,可以提高上下文切换的效率,至于什么是 Lazy stacking,打开它有什么好处,以及如何打开它,请自行阅读 Cortex-M4 的 Specification;
2. 内存管理
一个简单的内存管理模型,以预定义的内存 heap 为管理内容,所有的内存分配都在这进行;提供内存分配和释放的接口,分配按照 Bestfit 原则进行分配,释放的时候,进行相邻内存合并操作;为了进一步减少内存碎片,一些模块的描述符(IPC部分)都使用了预定义数组的方式,用户根据实际的设计情况,合理的定义描述符的个数(比如你的设计可能用到 3 个 Mutex Lock,那就定义 3 个);
内存分配释放的过程类似如下所示:
这里的蓝色部分是内存初始对齐后砍掉的部分,红色部分是每一块内存的描述符;后续会考虑实现类似 Slab 的东东;
3. 任务/调度器
RTOS 需要及时的调度出当前处于 Ready 并且优先级最高的任务来执行,MxOS 支持最大 32 级任务优先级定义,抢占式调度;
任务优先级的值越高代表优先级越高,同等优先级的任务轮流执行;
默认会启动一个 Idle 任务;
支持任务延时,挂起;
支持主动让出 CPU;
支持一定程度的堆栈溢出检查;
支持动态切换优先级;
支持挂起调度器;
3. IPC
IPC 的描述符资源都是静态定义,根据使用的具体情况,用户来定义,以减小内存碎片;
3.1 信号量
支持计数信号量和二进制信号量用于任务之间,任务与中断之间的同步;
支持 TryWait、和 WaitTimeout 操作;
3.2 互斥锁
支持互斥锁用于临界区的互斥访问,为了更好的 RT 特性,使用优先级继承的方式来减少优先级翻转带来的影响;
支持 TryWait、和 WaitTimeout 操作;
3.3 消息队列
提供一种任务与任务,中断与任务的数据传输的消息队列机制;
4. 临界区保护
提供3中临界区保护方式:
4.1. 全局中断
支持可嵌套的,给予全局中断开关的临界区保护方式;
4.2. 挂起调度器
支持挂起调度器的临界区保护方式;
4.3. 互斥锁
支持基于互斥锁的临界区保护方式;
5. 软件定时器
支持创建软件定时器,软件定时器以一个高优先级任务的方式运行,支持 Auto Reload 和 Oneshot 的定时器模式,超时Handler运行在任务上下文;
6. 支持 Log 日志分级
日志等级分为 4 级输出,输出等级定义越高,低等级的 log 便被阻止输出:
ERROR、WARNING、INFO、DEBUG
7. Trace
支持 Trace OS,根据需要添加 Trace point;
8. Shell
支持外挂 Shell,并注册到内核(当前已经注册了一个开源的 Shell);
适配 Shell 需要板级支持,具体适配方式参考发布链接的 Readme;
现目前 Shell 已经支持了几个命令:
task : 查看当前任务状态
mem : 查看当前内存情况
cls : 清屏
help : 帮助
9. Demo
OS_Uint32_t task1_handle = 0;
OS_Uint32_t task2_handle = 0;
OS_Uint32_t task3_handle = 0;
int main(void)
{
PlatformInit();
OS_API_KernelInit();
OS_Uint32_t TaskInputParam = 1;
TaskInitParameter Param;
OS_Memset(Param.Name, 0x00, CONFIG_TASK_NAME_LEN);
Param.Name[0] ='T';
Param.Name[1] ='1';
Param.Priority = 1;
Param.PrivateData = &TaskInputParam;
Param.StackSize = 1024;
Param.TaskEntry = TASK1_FUNC;
OS_API_TaskCreate(Param, (void *)&task1_handle);
Param.Name[0] ='T';
Param.Name[1] ='2';
Param.Priority = 2;
Param.TaskEntry = TASK2_FUNC;
OS_API_TaskCreate(Param, (void *)&task2_handle);
Param.Name[0] ='T';
Param.Name[1] ='3';
Param.Priority = 3;
Param.TaskEntry = TASK3_FUNC;
OS_API_TaskCreate(Param, (void *)&task3_handle);
OS_API_KernelStart();
while(1);
}
版权声明:本文为CSDN博主「爱洋葱」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zhoutaopower/article/details/122229253
暂无评论