OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3787|回复: 3

让我来学RTOS----- 消息邮箱

[复制链接]

22

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
335
金钱
335
注册时间
2014-5-25
在线时间
67 小时
发表于 2016-8-29 19:42:34 | 显示全部楼层 |阅读模式
本帖最后由 lotoohe 于 2016-8-29 20:09 编辑

最新的zrtos以及实现了timer了,软件定时器,并且任务也不需要写在一个for循环中了,后面揭晓
在zrtos中的消息邮箱,是由一个消息控制块来存放信息,函数来处理信息,这就和面向对象编程中的类的操作方式有一点相识,

在zrtos中的消息邮箱是一个先进先出的消息队列,消息队列的长度是由数组来控制的,为什么不用动态内存分配与链表内:

主要有两个原因:1.内存分配就可能出现内存的泄露。2.方便学习,代码简单。

下面来看看我的的消息队列的控制块:

typedef struct _TCB_MSG{
//消息id
uint32 msg_id;
//队首指针
int32 head_index;
//消息,存放的指针,必须将指针强制转换为uint32类型
  uint32 msg[MSG_MAX_LEN];
}TCB_MSG;
当我们每一次进行消息存放或存取成功的时候都会进行队列头指针的更新与消息队列的更新,我们来看看下面的代码:
/**
* 存放消息.
* 存放消息到消息控制块
* @param[in]  mTCB_MSG 要存放的消息的消息控制块
* @param[in]  msg   要发送的消息的地址
* @param[in]  msg_get_delay 存放消息的超时时间,为0xffffffff时一直等待
* @retval    true 成功
* @retval   false 内存申请失败
*/
uint32 msg_put(TCB_MSG* mTCB_MSG,uint32 msg,uint32 msg_get_delay){
if(mTCB_MSG==null){return false;}
//如果等待时间没有限制
if(msg_get_delay==MSG_WAIT_ENDLESS){
  //一直等待直到邮箱有空
  for(;mTCB_MSG->head_index >= MSG_MAX_LEN-1;);
}else{
  //如果邮箱满了
  if(mTCB_MSG->head_index >= MSG_MAX_LEN-1){
   //等待一段时间
   if(msg_get_delay!=0){
   //进行延时等待
    os_task_delay(msg_get_delay);
   }
   //如果还满则退出
   if(mTCB_MSG->head_index >= MSG_MAX_LEN-1){
    return false;
   }
  }
}
enter_int();
mTCB_MSG->head_index++;
//存放消息
(mTCB_MSG->msg)[mTCB_MSG->head_index] = msg;
exit_int();
return true;
}


在存放消息的时候我们会先判断队列是否已经满了,然后在根据队列头指针进行消息的存放,如果我们要取消息怎么操作的内,下面我们来看一下:
/**
* 获取消息.
* 从消息队列中获取消息
* @param[in]  mTCB_MSG 要获取的消息的消息控制块
* @param[in]  msg   要获取的消息存放地址
* @param[in]  msg_get_delay 获取消息的超时时间,为0xffffffff时一直等待
* @retval    true 成功
* @retval   false 内存申请失败
*/
uint32 msg_get(TCB_MSG* mTCB_MSG,void **msg,uint32 msg_get_delay){
int32 i=0;
if(mTCB_MSG==null){return false;}
do{
  //没有消息
  if(mTCB_MSG->head_index<0){
   //如果一直等待
   if(msg_get_delay==MSG_WAIT_ENDLESS){
    continue;
   }
   //等待一段时间
   if(msg_get_delay!=0){
    os_task_delay(msg_get_delay);
   }
   //还没有消息则退出
   if(mTCB_MSG->head_index<0){
    return false;
   }
  }
  //有消息
  enter_int();
  //获取消息
  *msg = (void*)mTCB_MSG->msg[0];
  //消息右移
  for(i=1;i<MSG_MAX_LEN;i++){
   mTCB_MSG->msg[i-1]=mTCB_MSG->msg;
  }
  //队列头减1
  mTCB_MSG->head_index--;
  exit_int();
  return true;
}while(msg_get_delay==MSG_WAIT_ENDLESS);
return false;
}
在取消息中,我们先看消息队列中是否存在有数据,如果有数据,我们则从消息队列中取出最底下的一个数据,然后在将消息队列中的数据向右移动一个。
当然这些都是在临界区完成的。
在使用是,我们需要创建一个消息邮箱 TCB_MSG* msg_create(void);该函数返回一个新的消息控制块,然后我们就可以使用这个消息控制块了。
总的来说zrtos中的消息队列还是非常的简单的。
上次说更新了zrtos的timer,稍后发上来。
zrtos v0.12 源代码:
zrtos操作统.zip (2.58 MB, 下载次数: 47)
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

9

主题

538

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3371
金钱
3371
注册时间
2015-1-7
在线时间
794 小时
发表于 2016-8-29 21:58:49 | 显示全部楼层
回复 支持 反对

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2016-8-30 13:03:15 | 显示全部楼层
good
回复 支持 反对

使用道具 举报

22

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
335
金钱
335
注册时间
2014-5-25
在线时间
67 小时
 楼主| 发表于 2016-9-1 11:11:11 来自手机 | 显示全部楼层
八度空间 发表于 2016-8-30 13:03
good

还没有解决优先级翻转的问题
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-30 02:46

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表