🌁RTOS原理与实现07:邮箱实现
2023-6-4
| 2023-6-29
0  |  阅读时长 0 分钟
type
status
password
date
slug
summary
category
URL
tags
icon
notion image
notion image

1. 邮箱的原理与创建

1.1 问题概述

1.1.1 问题引入

引入邮箱机制的目的是为了实现多个任务之间的消息通信
notion image

1.1.2实现形式

notion image
邮箱机制需要满足如下需求,
  1. 任务A产生消息放入邮箱,由邮箱负责在任务间分发消息
  1. 如果邮箱中没有消息,等待消息的任务可以在邮箱上实现等待
  1. 如果没有任务在邮箱上等待消息,邮箱可以先缓存接收到的消息

1.2 设计原理

notion image
设计要点如下:
  1. 邮箱无消息,任务在事件控制块上等待
  1. 邮箱没有任务等待消息,消息在ring buffer中缓存
  1. 考虑到效率问题,ring buffer中只保存消息的地址,而非消息本身
💡
说明:适用场景
此处设计的邮箱适用于2个任务之间实现消息通信,且一个固定为消息发送者,一个固定为消息接收者

1.3 设计实现

1.3.1 定义邮箱类型

💡
说明:关于消息缓冲区
在邮箱类型中,消息缓冲区被定义为void **类型,即对应void *类型数组,由于目前没有涉及内存管理相关内容,在实现中会定义全局的void *类型数组作为邮箱的消息缓冲区

1.3.2 添加tMboxInit函数

💡
说明:tEventTypeMbox为新增的与邮箱对应的事件控制块类型

2. 邮箱的获取与释放

2.1 设计原理

2.1.1 获取消息时缓冲区有消息

notion image
处理步骤:1、任务根据读索引获取消息;2、修改读索引,维护消息计数

2.1.2 获取消息时缓冲区无消息

notion image
处理步骤:将任务加入等待消息的任务列表

2.1.3 释放消息时等待队列有任务

notion image
处理步骤:唤醒等待队列中的队首任务,并将消息传递给该任务

2.1.4 释放消息时等待队列无任务

notion image
处理步骤:1、根据写索引将消息加入缓冲区;2、修改写索引,维护消息计数

2.1.5 使用数组实现ring buffer

notion image
💡
注意:需要处理下标绕回

2.1.6 实现按优先级写入消息

notion image
当写入高优先级消息时,通过反向移动读索引,并在读索引处写入实现

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 邮箱的清空

notion image
💡
说明:清空邮箱就是重置消息缓冲区,读索引、写索引归位。无需操作等待队列

3.1.2 邮箱的删除

notion image
说明:由于目前没有涉及内存的分配与释放,因此删除邮箱时只需要将等待队列清空,消息缓冲区可不做处理

3.2 设计实现

3.2.1 添加tMboxFlush函数(邮箱清空)

3.2.2 添加tMboxDestroy函数(邮箱删除)

说明1:注意销毁邮箱时传递的等待结果为tErrorDel,可以据此判断tMboxWait函数的返回值,以确定任务被唤醒的原因(e.g. 资源就绪 / 延时超时 / 邮箱被删除),而不是任务被唤醒后立即进行相关资源的操作
说明2:任务调用tTaskSched的时机
① 当前任务需要进入睡眠状态时(e.g. 延时或等待资源),释放CPU
② 当前任务知道可能有优先级更高的任务可以运行时
其中第②点就体现了RTOS的实时特性

4. 邮箱的状态查询

4.1 设计实现

4.1.1 添加邮箱状态类型

4.1.2 添加tMboxGetInfo函数

 
  • RTOS
  • RTOS原理与实现06:计数信号量实现RTOS原理与实现08:存储块实现
    Loading...
    目录