Ucos ii Task 4: Email

Source: Internet
Author: User

 

Ucos ii Task 4: Email

After learning semaphores, I can look at the mailbox and find that they are very similar. Sometimes the mailbox can be used as a semaphores. Compared with semaphores, the mailbox only transmits a pointer variable.

Similar to semaphores, ucos ii provides five functions for mailbox operations. They are:

1. Create a mailbox, osmboxcreate ()

2. Wait for a message in an email, osmboxpend ()

3. Send a message to the mailbox, osmboxpost ()

4. Get a message from the mailbox without waiting, osmboxaccept ()

5. query the status of a mailbox, osmboxquery ()

You must create a mailbox before using it. This operation can be completed by calling the osmboxcreate () function and specifying the initial value of the pointer. Generally, this initial value is null, but a mailbox can also be initialized to contain a message at the very beginning. If the mailbox is used to notify the task that an event has occurred (send a message), it is necessary to initialize the mailbox to null. If you use a mailbox to share some resources, initialize the mailbox as a non-null pointer. In this case, the mailbox is used as a binary semaphore.

Let's take a look at the implementation code for creating a mailbox function:

OS _event * osmboxcreate (void * MSG)

{

OS _event * pevent;

 

 

OS _enter_critical ();

Pevent = oseventfreelist;

If (oseventfreelist! = (OS _event *) 0 ){

Oseventfreelist = (OS _event *) oseventfreelist-> oseventptr;

}

OS _exit_critical ();

If (pevent! = (OS _event *) 0 ){

Pevent-> oseventtype = OS _event_type_mbox; (1)

Pevent-> oseventptr = MSG; (2)

Oseventwaitlistinit (pevent );

}

Return (pevent); (3)

}

Take a closer look. In fact, the process of creating a semaphore is almost the same. First, apply for an empty event control block and then initialize the event control block. Finally, a pointer pointing to the Event Control Block is returned. The difference is that the type of the Event Control Block is set to OS _event_type_mbox [(1)], and the. oseventptr domain is used to hold the message pointer.

Next let's take a look at the code for the mailbox function implementation:

Void * osmboxpend (OS _event * pevent, int16u timeout, int8u * ERR)

{

Void * MSG;

 

OS _enter_critical ();

If (pevent-> oseventtype! = OS _event_type_mbox) {(1)

OS _exit_critical ();

* Err = OS _err_event_type;

Return (void *) 0 );

}

MSG = pevent-> oseventptr;

If (MSG! = (Void *) 0) {(2)

Pevent-> oseventptr = (void *) 0; (3)

OS _exit_critical ();

* Err = OS _no_err;

} Else if (osintnesting> 0) {(4)

OS _exit_critical ();

* Err = OS _err_pend_isr;

} Else {

Ostcbcur-> ostcbstat | = OS _stat_mbox; (5)

Ostcbcur-> ostcbdly = timeout;

Oseventtaskwait (pevent );

OS _exit_critical ();

Ossched ();

OS _enter_critical ();

If (MSG = ostcbcur-> ostcbmsg )! = (Void *) 0) {(6)

Ostcbcur-> ostcbmsg = (void *) 0;

Ostcbcur-> ostcbstat = OS _stat_rdy;

Ostcbcur-> ostcbeventptr = (OS _event *) 0;

OS _exit_critical ();

* Err = OS _no_err;

} Else if (ostcbcur-> ostcbstat & OS _stat_mbox) {(7)

Oseventto (pevent); (8)

OS _exit_critical ();

MSG = (void *) 0; (9)

* Err = OS _timeout;

} Else {

MSG = pevent-> oseventptr; (10)

Pevent-> oseventptr = (void *) 0; (11)

Ostcbcur-> ostcbeventptr = (OS _event *) 0; (12)

OS _exit_critical ();

* Err = OS _no_err;

}

}

Return (MSG );

}

Similarly, it is similar to ossempend (). To put it bluntly, you can check whether there are any useful messages. If not, you can hook up the task.

Osmboxpend () first checks that the event control block is created by the osmboxcreate () function [(1)]. When the. oseventptr domain is a non-null pointer, there is a message available in the mailbox [(2)]. In this case, the osmboxpend () function copies the value of this field to the local variable MSG, and then sets. oseventptr to null [(3)]. This is exactly what we expected. It is also the fastest path to execute the osmboxpend () function.

If no message is available in the mailbox at this time (the oseventptr domain is a null pointer), The osmboxpend () function checks whether its caller is an interrupt service subroutine [(4)]. Like the ossempend () function, you cannot call osmboxpend () in the interrupt service subprogram because the interrupt service subprogram cannot wait. The code here is also used in case of exceptions. However, if a message is available in the mailbox, it is successful even if the osmboxpend () function is called from the interrupt service subroutine.

If no message is available in the mailbox, the call task of osmboxpend () is suspended until a message exists in the mailbox or waits for timeout [(5)]. When another task sends a message to the mailbox (or the wait time times out), the task becomes the highest priority task again, And ossched () returns. In this case, the osmboxpend () function checks whether messages are put in the task control block of the task [(6)]. If yes, the function call is successful and the corresponding message is returned to the called function.

The code for sending a message to osmboxpost () in the mailbox is as follows:

Int8u osmboxpost (OS _event * pevent, void * MSG)

{

OS _enter_critical ();

If (pevent-> oseventtype! = OS _event_type_mbox) {(1)

OS _exit_critical ();

Return (OS _err_event_type );

}

If (pevent-> oseventgrp) {(2)

Oseventtaskrdy (pevent, MSG, OS _stat_mbox); (3)

OS _exit_critical ();

Ossched (); (4)

Return (OS _no_err );

} Else {

If (pevent-> oseventptr! = (Void *) 0) {(5)

OS _exit_critical ();

Return (OS _mbox_full );

} Else {

Pevent-> oseventptr = MSG; (6)

OS _exit_critical ();

Return (OS _no_err );

}

}

}

Sending a message to the mailbox is similar to sending a semaphore, that is, checking whether a task is waiting for the message. If yes, pull the task from the sleep state back to the ready state.

The code is described as follows:

After checking whether the event control block is a mailbox [(1)], the osmboxpost () function also checks whether a task is waiting for messages in the mailbox [(2)]. If the oseventgrp field in the event control block contains a non-zero value, it implies that a task is waiting for the message. At this time, call oseventtaskrdy () to delete the highest priority task from the waiting list [(3)], add it to the ready task list of the system, and prepare to run the task. Then, call the ossched () function [(4)] to check whether the task is a ready task with the highest priority in the system. If yes, the task is executed [only when the osmboxpost () function is called by the task. If the task is not the highest priority, ossched () returns, and the call function of osmboxpost () continues to be executed. If no task is waiting for the message, the pointer to the message is saved to the mailbox [
(6)] (assuming that the pointer in the mailbox is not null [(5)]). In this way, the next task that calls the osmboxpend () function can immediately obtain the message.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.