Understanding uCOS task message queue related functions

Task message queue : Like the task semaphore, the task message queue exists in the TCB of each task. The element is defined as OS_MSG_Q MsgQ. There is no need to create it separately, and there is no related creation function. The task message queue is unique to each task. Only the task itself can obtain messages through its own task message queue, and other tasks can only send messages to this message queue. If other tasks cannot be obtained, there is no need to wait. There is no need for a waiting list to store other tasks, so there is no waiting list and the operation of entering and exiting the waiting list is omitted.

Elements in TCB related to task message queue :

{

OS_MSG_Q MsgQ; //Message list

CPU_TS MsgQPendTime; The waiting time for a task to wait for its own task message list.

CPU_TS MsgQPendTimeMax; The longest waiting time for a task to wait multiple times for the task message list.

}

Message structure :

struct  os_msg {                                           

    OS_MSG *NextPtr; //Pointer to the next message                         

    void *MsgPtr; //Pointer to message content           

    OS_MSG_SIZE MsgSize; //A variable indicating the message size           

    CPU_TS MsgTS; //Time stamp of a message sent    

};

It is worth noting that the timestamp of the message sent by the message queue is stored in the message structure, unlike the semaphore, which relies on the element CPU_TS TS in the TCB to save the timestamp when the semaphore is released .

OS_MSG_Q MsgQ : In fact, the OS_MSG_Q structure is a message list structure, not a message queue structure. Because looking back at the kernel message queue structure, except for the message list and wait list elements, the others are debugging-related elements and the name of the message queue. Since the task message queue is unique to each task, there is no need to specify the message queue name. You can find its message queue by directly looking for the corresponding task; there is no need for a waiting list and a debugging list. So the task message queue just adds an element OS_MSG_Q MsgQ to the message list in the TCB .

struct  os_msg_q {                                     

    OS_MSG *InPtr; //Pointer to the next message to be inserted into the queue                    

    OS_MSG *OutPtr; //Pointer to the next message to be fetched from the queue;                

    OS_MSG_QTY NbrEntriesSize; //The maximum number of messages allowed in the queue       

    OS_MSG_QTY NbrEntries; //The current number of messages in the queue        

    OS_MSG_QTY NbrEntriesMax; //The peak number of messages in the queue                  

    CPU_INT32U MsgQID; //The unique ID of third-party debuggers and tracers                   

};

Message queue sending and receiving message mechanism : ① Message queue sends messages by fetching messages from the message pool. If a message is successfully obtained, the number of available messages in the message pool is reduced by 1. ② The messages in the message pool do not specify the message point during initialization. The use of pointers is not only to point to messages of variable length, but also to flexibly point to the messages that the user wants to send during the running process. ③ The message queue sending function only assigns a value to the message structure when sending the message. However, when the task obtains the message, it directly returns the message to the message pool and does not clear the message pointer. Because it is assigned a value every time a message is sent, there is no need to clear it .

OSTaskQPost() : Task message queue sending function

{

5 entry parameters : pointer p_tcb pointing to the target TCB; pointer p_void pointing to the message content; message size msg_size; option opt; returned error type p_err.

Function process : ① First perform security check and parameter option check. Options mainly include OS_OPT_POST_FIFO and OS_OPT_POST_LIFO and their combination with OS_OPT_POST_NO_SCHED. ② Get the timestamp as the time point when sending the message queue. ③ If interrupt delayed publishing is enabled and this function is called in an interrupt, call OS_IntQPost(), send the message to the interrupt message queue first, and return. ④ Otherwise, call OS_TaskQPost() to send the message directly.

--Call OS_TaskQPost() :

6 entry parameters : pointer p_tcb pointing to the target TCB; pointer p_void pointing to the message content; message size variable msg_size; option opt; timestamp ts; returned error type p_err.

Function process : ① uCOS allows you to specify an empty TCB pointer. If the TCB pointer is empty, the message is sent to the task itself, not to other tasks. ②Because there are two situations when sending a message to a task: one is that a task is blocked and waiting for the message, and the other is that there is no task waiting for the message. Because the task message queue is unique to the task and has no waiting list, it is judged based on the status of the target task whether the task is waiting for the message . If the status of the target TCB does not have a waiting state, it means that the task is not waiting for the message queue, then call OS_MsgQPut() to insert the message into the message list. ③ If the target TCB status changes from waiting state, it depends on whether it is waiting for the task message queue: if it is waiting for the message queue, then call OS_Post() to send the message to the target TCB (actually assigning values ​​to the message-related elements in the TCB ) ; Then determine whether it is necessary to call OSSched() for task scheduling. If you are not waiting for the task message queue, the sent message should also be inserted into the message list. Perform step ② and call OS_MsgQPut() to insert the message into the message list.

OS_MsgQPut() operates on the message list. Therefore, the operations of the kernel message queue and the task message queue are the same. But among the parameters, the kernel message queue is to operate the message list in the kernel message queue structure; the task message queue is to operate the message list element in the TCB structure.

}  

OSTaskQPend() : Task message queue acquisition function

{

5 entry parameters : timeout timeout; option opt; pointer to message size p_msg_size; return timestamp p_ts when the message is published; returned error type p_err.

Return : This function is a pointer function, essentially a function, and the return is void * type. The returned pointer is a pointer to the message content.

Function process : ① Check for illegal calls in security, parameters, options, and interrupts. ② The message queue acquisition function first checks whether there are any waiting messages in the task message list. Get the messages in the message list through OS_MsgQGet(). If the error type returned is OS_ERR_NONE, it means there is a message in the message list, and the pointer p_void to the message is obtained; then the difference between the current timestamp and the timestamp when the message was published is obtained to obtain the waiting time for the message; if necessary Update MsgQPendTimeMax; finally return the pointer p_void to the message. ③ OS_MsgQGet() will only return two errors: one is OS_ERR_NONE, indicating that there is a message in the message list; the other is OS_ERR_Q_EMPTY indicating that there is a message at noon in the message list. If there is no message, it is necessary to determine whether the user specifies the task to enter blocking according to opt to wait for the message. If the user chooses not to block, the OS_ERR_PEND_WOULD_BLOCK error type is returned, and a null pointer is returned. ( In fact, you can deliberately choose the non-blocking option here, and then judge whether the task has obtained the message through the error type. Because if the message is obtained, the pointer to the message has been returned, and the step of judging whether to block will not be carried out; otherwise, a null pointer will be returned. and error types that require blocking ). ④ If there is no message available in the message list and the user chooses to block and wait, then the task must be removed from the ready list. At this time, it is necessary to determine whether the scheduler is locked. If it is not locked, call OS_Pend() to block the task, that is, remove the task from the ready list and add it to the time base list (if the timeout is not 0). Finally, call OSSched() for task switching. ⑤ When the program is executed to this point, the task must be added to the ready list, either get the message, be aborted, time out to get the message, etc. Therefore, corresponding processing needs to be carried out according to the task status. If you wait until the message OS_STATUS_PEND_OK, then get the pointer to the message and the size of the message, and return the pointer to the message. In other cases, the pointer to the message content is null and the message size is 0.

}

Guess you like

Origin blog.csdn.net/m0_43443861/article/details/126373515