type
status
password
date
slug
summary
category
URL
tags
icon
1. 邮箱的原理与创建
1.1 问题概述
1.1.1 问题引入
引入邮箱机制的目的是为了实现多个任务之间的消息通信
1.1.2实现形式
邮箱机制需要满足如下需求,
- 任务A产生消息放入邮箱,由邮箱负责在任务间分发消息
- 如果邮箱中没有消息,等待消息的任务可以在邮箱上实现等待
- 如果没有任务在邮箱上等待消息,邮箱可以先缓存接收到的消息
1.2 设计原理
设计要点如下:
- 邮箱无消息,任务在事件控制块上等待
- 邮箱没有任务等待消息,消息在ring buffer中缓存
- 考虑到效率问题,ring buffer中只保存消息的地址,而非消息本身
说明:适用场景
此处设计的邮箱适用于2个任务之间实现消息通信,且一个固定为消息发送者,一个固定为消息接收者
1.3 设计实现
1.3.1 定义邮箱类型
说明:关于消息缓冲区
在邮箱类型中,消息缓冲区被定义为void **类型,即对应void *类型数组,由于目前没有涉及内存管理相关内容,在实现中会定义全局的void *类型数组作为邮箱的消息缓冲区
1.3.2 添加tMboxInit函数
说明:tEventTypeMbox为新增的与邮箱对应的事件控制块类型
2. 邮箱的获取与释放
2.1 设计原理
2.1.1 获取消息时缓冲区有消息
处理步骤:1、任务根据读索引获取消息;2、修改读索引,维护消息计数
2.1.2 获取消息时缓冲区无消息
处理步骤:将任务加入等待消息的任务列表
2.1.3 释放消息时等待队列有任务
处理步骤:唤醒等待队列中的队首任务,并将消息传递给该任务
2.1.4 释放消息时等待队列无任务
处理步骤:1、根据写索引将消息加入缓冲区;2、修改写索引,维护消息计数
2.1.5 使用数组实现ring buffer
注意:需要处理下标绕回
2.1.6 实现按优先级写入消息
当写入高优先级消息时,通过反向移动读索引,并在读索引处写入实现
2.2 设计实现
2.2.1 添加tMboxWait函数
说明1:任务再次被调度运行。可能是1、消息就位,被消息唤醒;2、等待超时,被强制唤醒
此时需要tMboxWait函数的调用者根据返回值进行判断
说明2:如果任务是被消息唤醒,那么消息会被记录到task->eventMsg字段,该操作由tEventWakeUp函数实现,详见tMboxNotify函数
2.2.2 添加tMboxNoWaitGet函数
2.2.3 添加tMboxNotify函数
2.2.4 应用
3. 邮箱的清空与删除
3.1 设计原理
3.1.1 邮箱的清空
说明:清空邮箱就是重置消息缓冲区,读索引、写索引归位。无需操作等待队列
3.1.2 邮箱的删除
说明:由于目前没有涉及内存的分配与释放,因此删除邮箱时只需要将等待队列清空,消息缓冲区可不做处理
3.2 设计实现
3.2.1 添加tMboxFlush函数(邮箱清空)
3.2.2 添加tMboxDestroy函数(邮箱删除)
说明1:注意销毁邮箱时传递的等待结果为tErrorDel,可以据此判断tMboxWait函数的返回值,以确定任务被唤醒的原因(e.g. 资源就绪 / 延时超时 / 邮箱被删除),而不是任务被唤醒后立即进行相关资源的操作
说明2:任务调用tTaskSched的时机
① 当前任务需要进入睡眠状态时(e.g. 延时或等待资源),释放CPU
② 当前任务知道可能有优先级更高的任务可以运行时
其中第②点就体现了RTOS的实时特性