[uTenux] the mailbox

Recommended for you: Get network issues from WhatsUp Gold. Not end users.

   The mailbox is a through in system (shared) object memory space to deliver the message to realize the synchronization and communication. UTenux of each email contains a to send a message in the message queue and a queue of tasks waiting for message receipt, the use function of mail message content is placed in the sender and recipient share memory in , therefore, the actual sending and receiving only in this shared space news the starting address. the contents of the message itself is not copied.

   Mailbox API including create delete sending and receiving delete function.

   1,Create a message using tk_cre_mbx. Property is very simple.

   2,Send messages to the mailbox

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

Only a message needs to be thrown to a mailbox, send messages task does not enter the wait state.

3,The receiving of messages in the mailbox

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

The starting address is mailbox information. If the mailbox is empty, the task in wait.

Here a few places used null pointer void*, about the empty type pointer usage here, appendix reference behind.

A detailed description of the void* pointer, reference here:

We must make clear the place: message passing, passing only.


[Experimental description]

The sample code. First create two tasks TaskA and TaskB priority is respectively 24 and 25, two e-mail: Mbx_S and Mbx_R. After starting the TaskA. Start the TaskB in TaskA. And then to the Mbx_S send a message, and then wait for the start of the message in Mbx_R. Because there is no message in Mbx_R, TaskA dormancy.

At this time TaskB start, TaskB to take the message from the Mbx_S, and then the output message. Finally, sending a message to Mbx_R. Mbx_R in the news release, TaskA waiting to enter the Ready ready state. TaskA priority is higher than TaskB, occupy the TaskB started, continue to complete the subsequent message handling code

[The code and the output]

#include "MailboxSample.h" 

typedef struct u_msg {
    VP  msgque[1];  /* Area for message queue,as same as T_MSG */
    UB  *usrmsg;    /* Area for message pointer */
} 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;
  
  //Create two tasks
  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);
  
  //Create two MBX
  cmbx.mbxatr = TA_TFIFO | TA_MFIFO;
  cmbx.exinf = NULL;
  MbxID_S = tk_cre_mbx(&cmbx);
  MbxID_R = tk_cre_mbx(&cmbx);
  
  //Start the task 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*)"TaskB is ready to send a message to \n");
    tk_rcv_mbx(MbxID_S,(T_MSG**)&pk_rcvmsg,-1);
    tm_putstring((UB*)"This is the TaskB receives the message \n");
    tm_putstring((UB*)pk_rcvmsg->usrmsg);
    
    sndmsg.usrmsg = "TaskB send a message";
    tm_putstring((UB*)"This is a message sent by the TaskB \n");
    tm_putstring((UB*)sndmsg.usrmsg);
    tm_putstring((UB*)"\n");
    tk_snd_mbx(MbxID_R,(T_MSG*)&sndmsg);    
  }
}

void MbxSampleTaskA(W stacd,VP exinf)
{
  U_MSG *pk_rcvmsg;
  U_MSG sndmsg;
  sndmsg.usrmsg = "TaskA Send a Message\n";
  tk_sta_tsk(TaskID_B,0);
  while(1)
  {
    tm_putstring((UB*)"This is a message sent by the TaskA \n");
    tm_putstring((UB*)sndmsg.usrmsg);
    tm_putstring((UB*)"\n");
    tk_snd_mbx(MbxID_S,(T_MSG*)&sndmsg);
    
    tk_rcv_mbx(MbxID_R,(T_MSG**)&pk_rcvmsg,-1);
    tm_putstring((UB*)"This is the TaskA receives the message \n");
    tm_putstring((UB*)pk_rcvmsg->usrmsg);
    tm_putstring((UB*)"\n");
  }  
}

[Serial output]

----------------------------------------------------

micro Tenux Version 1.6.00(build 0180)

Supported MCU is ST STM32F407VG

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

----------------------------------------------------

This is a message sent by the TaskA

TaskA Send a Message

TaskB is ready to send a message

This is receiving the message of TaskB

TaskA Send a Message

This is a message sent by the TaskB

TaskB send a message

This is receiving the message of TaskA

TaskB send a message

This is a message sent by the TaskA

TaskA Send a Message

[PS]

The mailbox is a funny thing. I want to write one for the control of things, the input data of the control part is not continuous. A control data to the executive part, to change the running state.

The control part of the control word e-mail messages can be made, and go to wait for user input. The operative part, every once in a while to check email, have a look have no control part to update. If there is, according to the mailbox message to change running state, if not keep running.

For example, motor control part of me, the task of detecting user input can be a control source, since the detection of periodic task system can also be used as a control source. Two tasks at the same time, lost control information to a mailbox at the same time.

The user input task can send the following message: changing the motor speed, let the motor stopped, let the motor brake and so on, self checking task detection of the failure, sending a message: let the motor brake, let the motor stops.

The execution part, only need according to the message to Guangzhou on it. Regardless of who is in control.


[About void pointer VP]

Create a mailbox, need to provide an email message pointer T_MSG.

This pointer stored messages. View definition can be found, he is such a definition:

typedef struct t_msg { 

      VP msgque[1]; /* Area for message queue */ 

} T_MSG;

While the VP is defined as:

typedef void *VP;

Here we use a pointer to a void type. In the sample program, the pointer will define their own news casts to type T_MSG. Void type pointer.

The pointer of Void type is a pointer type less, can point to any structure. Because it is a pointer´╝ü

In reference to the pointer when, need to know in advance the pointer to the address structure. Otherwise, the compiler cannot know the types of data error

Such a message, the MBX message type is no longer fixed. The need to manually define user.

When sending a message, send task does not enter the wait state. That is: as long as the message sent to the mailbox is still can be, as for the news to where go to, to OS for processing. When the mailbox is empty, the message directly in the mailbox. The mailbox is not empty, the message into the message queue of that mailbox. Send these, the task is not interested in.

When receiving messages, use tm_rcv_mbx to complete. ID provides mailboxes and message data packet starting address, and a waiting timeout. If no message to receiving email, then receiving a task enters wait state.

Problems concerning the use of email, send a message and receiving message function in the empty type pointer void*

The definition of the two functions is this:

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

    ER ercd= tk_rcv_mbx(ID mbxid,T_MSG** ppk_msg,TMO tmout);

The T_MSG is defined as follows:

typedef struct t_msg { 
      VP msgque[1]; /* Area for message queue */ 
    } T_MSG;

Where VP is typedef void *VP; that is to say, the T_MSG structure itself contains a null pointer. This is the message header message structure, OS is responsible for the maintenance, the user need not tube. But without it, otherwise the OS will be in error.

Below is I use the empty type pointer to the understanding.

1,Tk_snd_mbx using T_MSG*

T_MSG* is a pointer to a structure of news, and msgque is the same. This pointer is a pointer to a void* type. Can point to any type of data.

So tk_snd_mbx(IDmbxid,T_MSG*pk_msg);

This usage, is to pass a null pointer to function.

2,The use of tk_rcv_mbx in the.

Here is a pointer to a pointer (T_MSG** ppk_msg). There's a note about ppk_msg kernel specification: ppk_msg is contained in the message packet (including the header, the starting address).

That is to say ppk_msg is an address (address 1). * ppk_msg is the address of the data, the data is also an address (address 2). So T_MSG** ppk_msg is the address of the data stored in the. This data is of type T_MSG.

In the example project, this usage:

tk_rcv_mbx(MbxID_S,(T_MSG**)&pk_rcvmsg,-1);

The definition of pk_rcvmsg is this: U_MSG *pk_rcvmsg is a pointer;.

& pk_rcvmsg, is taking the pointer address. (T_MSG**) & pk_rcvmsg became the data block to the memory address in the pk_rcvmsg address, forced conversion to type T_MSG*.

Just and function definitions are part of the same.

Void* type more details, please visit

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download

Posted by Kenneth at November 19, 2013 - 1:33 AM