【uTenux实验】邮箱

邮箱是一个通过在系统(共享)内存空间传递消息来实现同步和通信的对象。uTenux中每个邮箱都包含一个用来发送消息的消息队列和一个用于等待接收消息的任务队列,其使用邮箱功能的消息内容放置在发送方和接收方共享的内存中,因此,实际发送和接收的只有位于这片共享空间的消息起始地址。消息的内容本身并不复制。

消息邮箱的API包括创建删除发送接收删除的功能。

1、使用tk_cre_mbx创建一个消息邮箱。属性设置很简单。

2、向邮箱发送消息

ER ercd= tk_snd_mbx(ID mbxid,T_MSG* pk_msg);

只需要将消息丢给邮箱即可,发送消息的任务不会进入等待状态。

3、接收邮箱中的消息

ERercd= tk_rcv_mbx(IDmbxid,T_MSG**ppk_msg,TMOtmout);

得到消息邮箱提供的消息的起始地址。如果消息邮箱是空的,任务进入等待。

这里一几个地方使用了void*的空类型指针,关于空类型指针在这里的用法,可参考后边的附录。

关于void*指针的详细介绍,可参考这里:

必须要明确的地方:消息传递中,传递的只是地址。

【实验描述】

参考示例代码。首先创建两个任务TaskA和TaskB优先级分别为24和25,两个邮箱Mbx_S和Mbx_R。之后启动TaskA。在TaskA中启动TaskB。然后向Mbx_S发送一个消息,然后开始等待Mbx_R中的消息。由于Mbx_R中没有消息,TaskA进入休眠。

此时TaskB开始执行,TaskB先从Mbx_S中取消息,服务器空间,然后输出消息。最后再向Mbx_R中发送消息。Mbx_R中有了消息,网站空间,TaskA释放等待进入Ready就绪状态。TaskA优先级高于TaskB,美国服务器,抢占TaskB开始执行,继续完成以后的消息处理代码

【代码和输出】

#include typedef struct u_msg {VP msgque[UB *usrmsg; } U_MSG;void MbxSampleTaskA(W stacd,VP exinf);void MbxSampleTaskB(W stacd,VP exinf);static ID TaskID_A;static ID TaskID_B;static ID MbxID_S;static ID MbxID_R;ER MbxSample( void){ T_CTSK ctsk; T_CMBX cmbx; ER ercd;//创建两个任务 ctsk.bufptr = NULL; ctsk.exinf = NULL; ctsk.itskpri = 24; ctsk.stksz = 512; ctsk.task = MbxSampleTaskA; ctsk.tskatr = TA_HLNG | TA_RNG0; TaskID_A = tk_cre_tsk(&ctsk);ctsk.task = MbxSampleTaskB; ctsk.itskpri = 26; TaskID_B = tk_cre_tsk(&ctsk);//创建两个mbx cmbx.mbxatr = TA_TFIFO | TA_MFIFO; cmbx.exinf = NULL; MbxID_S = tk_cre_mbx(&cmbx); MbxID_R = tk_cre_mbx(&cmbx);//启动任务A ercd = tk_sta_tsk(TaskID_A,5);return TRUE;}void MbxSampleTaskB(W stacd,VP exinf){ U_MSG *pk_rcvmsg; U_MSG sndmsg; while(1) {tm_putstring((UB*));tk_rcv_mbx(MbxID_S,(T_MSG**)&pk_rcvmsg,-1);tm_putstring((UB*));tm_putstring((UB*)pk_rcvmsg->usrmsg);sndmsg.usrmsg = ;tm_putstring((UB*));tm_putstring((UB*)sndmsg.usrmsg);tm_putstring((UB*));tk_snd_mbx(MbxID_R,(T_MSG*)&sndmsg);}}void MbxSampleTaskA(W stacd,VP exinf){ U_MSG *pk_rcvmsg; U_MSG sndmsg; sndmsg.usrmsg = ; tk_sta_tsk(TaskID_B,0); while(1) {tm_putstring((UB*));tm_putstring((UB*)sndmsg.usrmsg);tm_putstring((UB*));tk_snd_mbx(MbxID_S,(T_MSG*)&sndmsg);tk_rcv_mbx(MbxID_R,(T_MSG**)&pk_rcvmsg,-1);tm_putstring((UB*));tm_putstring((UB*)pk_rcvmsg->usrmsg);tm_putstring((UB*)); } }

【串口输出】

—————————————————-

micro Tenux Version 1.6.00(build 0180)

Supported MCU is ST STM32F407VG

Copyright(c) 2008-2013 by Dalian uLoong Co.,Ltd.

—————————————————-

这是TaskA发送的消息

TaskA Send a Message

TaskB准备发送消息

这是TaskB接收到的消息

TaskA Send a Message

这是TaskB发送的消息

TaskB send a message

这是TaskA接收到的消息

TaskB send a message

这是TaskA发送的消息

TaskA Send a Message

【PS】

邮箱是一个很好玩的东西。我想写一个用于控制的东西,控制部分的输入数据是不连续的。有控制数据来了,执行部分就要改变一下运行状态。

其中控制部分可以将控制字做成邮箱消息,然后在去等待用户输入。执行部分,每隔一段时间检查一下邮箱,看看有没有控制部分来的更新。如果有,就根据邮箱消息改变下运行状态,没有的话保持运行状态。

比如我的电机控制部分,检测用户输入的任务可以是一个控制源,系统周期性的自检测的任务也可以当做一个控制源。两个任务同时工作,同时向邮箱丢控制信息。

用户输入任务可以发送以下消息:改变电机的转速,让电机停转,让电机刹车等等,自检任务检测到故障之后,发送一下消息:让电机刹车,让电机停转等。

执行部分的任务,只需要根据消息来广州就可以了。不用考虑谁在控制。

【关于void型指针 VP】

创建邮箱时,需要提供一个邮箱消息的指针T_MSG。

这个指针指向存放消息的地址。查看定义可发现,他是这样定义的:

typedef struct t_msg {VP msgque[} T_MSG;

而VP的定义是:

typedef void *VP;

这里就用到了一个void型的指针。在示例程序中,将自己定义的消息类型强制转换成T_MSG型的指针。即void型的指针。

Void类型的指针是无类型的指针,可以指向任何结构。因为它就是一个指针!

在引用这个指针时候,需要预先知道这个指针指向地址的结构。不然编译器无法知道所指数据的类型而报错

这样的消息传递,使得mbx所传递的消息类型不再固定。需要使用者手动定义。 下午某时,天气晴,我在某地,想念你。

【uTenux实验】邮箱

相关文章:

你感兴趣的文章:

标签云: