One, the mailbox control block: in Include/rtdef.h
#ifdef Rt_using_mailbox/** * Mailbox Structure*/structrt_mailbox{structRt_ipc_object parent;/**< inherit from Ipc_object*/ //inherit from IPC objectrt_uint32_t*msg_pool;/**< start address of message buffer*/ //Message Buffer Addressrt_uint16_t size; /**< size of message pool*/ //maximum number of messages that can be storedrt_uint16_t entry; /**< Index of messages in Msg_pool*/ //number of message bars stored in the current mailboxrt_uint16_t In_offset;/**< input offset of the message buffer*/ //offset location of message depositrt_uint16_t Out_offset;/**< output offset of the message buffer*/ //offset position when the message is taken outrt_list_t Suspend_sender_thread; /**< Sender thread suspended on this mailbox*///Mailboxthe Send thread suspends the list (the sending thread is suspended when no fetch is taken)};typedefstructRt_mailbox *rt_mailbox_t;#endif
Second, the mailbox-related interface: in the SRC/IPC.C
Create mailbox: rt_mailbox_t rt_mb_create (constChar *name, rt_size_t size, rt_uint8_t flag); When you create a mailbox object, you create a Mailbox object control block, and then assign a memory space to the mailbox to hold the message, which is the same size as the message size (4 bytes) and the mailbox capacity , and then initialize the offset of the incoming message and the sending message in the mailbox. Delete mailbox: rt_err_t rt_mb_delete (rt_mailbox_t MB); When you delete a mailbox, if the thread is suspended on that mailbox object, the kernel wakes up all the threads that are suspended on that mailbox (threads get a return value of -rt_error). Then release the memory used by the mailbox, and finally delete the mailbox object.
Initialize mailbox: rt_err_t rt_mb_init (rt_mailbox_t MB,//handle to the mailbox object Const Char*name,//Mailbox Name void*msgpool,//buffer Pointerrt_size_t size,//Mailbox Capacityrt_uint8_t flag);//Mailbox Flag (Fifo/prio)Unlike creating a mailbox, the memory space used by the static mailbox object here is a buffer space specified by the user thread , and the user passes a pointer to the buffer to the mailbox object control block, and the rest of the initialization works the same as when the mailbox was created. Note: The size parameter here specifies the capacity of the mailbox, that is, if the number of bytes in Msgpool is N, the mailbox capacity should be n /4out-of-box: rt_err_t Rt_mb_detach (rt_mailbox_t MB); When the function interface is used, the kernel wakes all threads that are hung on the mailbox (the thread gets the return value is-rt_error), and then remove the mailbox object from the Kernel object manager.
wait mode send message: rt_err_t rt_mb_send_wait (rt_mailbox_t MB, rt_uint32_t value, rt_int32_t timeout); the difference between rt_mb_send_wait and rt_mb_send is that if the mailbox is full, the sending thread waits for the message to be empty in the mailbox according to the set timeout parameter. If the timeout time is set to arrive still there is no space available, this is the send thread that will be woken back to the error code . Send message: rt_err_t rt_mb_send (rt_mailbox_t MB, rt_uint32_t value); This function is associated with rt_mb_send_wait (MB, value,0EquivalentThe sent message can be 32-bit data in any format, an integer value, or a pointer to a buffer.
When the message in the mailbox is full, the thread or interrupt program that sent the message receives- The return value of the Rt_efull . The send function suspends the sending thread that is currently in place when the mailbox is full . Incoming mail: rt_err_t rt_mb_recv (rt_mailbox_t MB, rt_uint32_t*value, rt_int32_t timeout); The recipient can immediately fetch the message and return the return value of Rt_eok only if the recipient receives the message in the mailbox, or the receiving thread is set on the time-out, or hangs on the queue of the waiting thread for the mailbox, or returns directly. when a message is received, the recipient specifies the mailbox handle to receive the message and specifies the location of the message to be received and the maximum time-out to wait. If a timeout is set at the time of receipt, the message will be returned when it is not received within the specified-rt_etimeout. The entire process of the function is:
(1) The receiving mail function will determine whether the current mailbox is empty and the time parameter is 0, if it is directly returned, and then a while loop, in this while loop in the judgment condition is the mailbox is empty, why do you want to do so? So the program will wait for the message to arrive in this while loop, and only the message arrives before it jumps out of the loop (the direct function returns if the wait time-out).
(2) After entering the while loop, the program again determines whether the current wait time parameter is 0, and if so, returns directly. Then suspend the current thread, again determine whether the time parameter is greater than 0, here is mainly to sweep the situation of Timeout=rt_waiting_forever, because Rt_waiting_ The Forever macro is defined as-1. Record the current point in time within the IF statement, then set a timer and turn it on, then reschedule.after rescheduling, the system may switch to another thread, assuming that the system switches back for a period of time for several reasons,1: The mailbox is detached, the current thread thread->error=-rt_error;2 timer time arrives, but the message has not arrived, at this time thread->error=-rt_etimeout;3: The message arrives, this thread is awakened in the Send mail function (note: The sending message function only wakes up the first thread waiting for the message), at this time, Thread->error still keep the original value Rt_eok; 4: Other reasons assume that after a while the thread switches back, At this point, the value of error remains the same rt_eok. Therefore, after the thread is re-dispatched, there is an if statement that determines whether the current thread is awakened by the Send mail function by judging whether the value of Thread->error is Rt_eok. If not, the error is returned directly.
(3) Next, according to principle, the current thread must be sent by the mail function to wake up, so there must be a message received at the moment, but the next few lines of code is again to determine the time parameter is greater than 0 cases, the calculation also remaining more time, and then return to the while loop and then loop. The reason for this is that the only criterion for determining whether a message is actually present in a mailbox is a while loop, where the number of received letters in a mailbox cannot be empty or empty, then the loop is judged, or not empty, and it is naturally not going into the while loop. However, if the original mailbox is found to be empty, then when the front-line should continue to wait, it should be calculated the next cycle to wait for the remaining time, so that the next cycle of accurate waiting time.
(4) Next is to take out the received mail, and update the mailbox import and export offset location and the number of messages in the mailbox minus 1, so that after the operation, do not forget that the mailbox may still remain in the mail because of the previous mailbox space suspended from the sending thread, this time due to read mail operations, then must be at least an empty location, Then it is time to wake up a possible pending send thread (if one exists). Finally, reschedule.
void *arg); only support Rt_ipc_cmd_reset this command, which means resetting the mailbox (re-initializing the mailbox).
Third, summary
Email related source code is mainly in the sending and receiving. When sending, because the current mailbox may be full, not enough to send the message, at this point, you have to suspend the current send thread (if there is a time parameter), as long as the receiving function read out a message will not wake it. Similarly, if the current mailbox is empty, the receive function suspends the current receive thread until a new message arrives (wakes the receive thread in the Send function) or waits for a timeout.
It is also important to note that thert-thread operating system supports multiple send threads and multiple receive threads, and multiple send threads are fine, but many receive threads are not very well controlled, and generally this is not the case , if this is really the case, Then more than one receive thread has to take control, because it is not good to say which receiving thread is receiving the message.
Rt-thread the kernel mailbox