/* ************************************************************************************************************************ * uC/OS-III * The Real-Time Kernel * * (c) Copyright 2009-2011; Micrium, Inc.; Weston, FL * All rights reserved. Protected by international copyright laws. * * MESSAGE HANDLING SERVICES * * File : OS_MSG.C * By : JJL * Version : V3.02.00 * * LICENSING TERMS: * --------------- * uC/OS-III is provided in source form for FREE short-term evaluation, for educational use or * for peaceful research. If you plan or intend to use uC/OS-III in a commercial application/ * product then, you need to contact Micrium to properly license uC/OS-III for its use in your * application/product. We provide ALL the source code for your convenience and to help you * experience uC/OS-III. The fact that the source is provided does NOT mean that you can use * it commercially without paying a licensing fee. * * Knowledge of the source code may NOT be used to develop a similar product. * * Please help us continue to provide the embedded community with the finest software available. * Your honesty is greatly appreciated. * * You can contact us at www.micrium.com, or by phone at +1 (954) 217-2036. ************************************************************************************************************************ */ #include #ifdef VSC_INCLUDE_SOURCE_FILE_NAMES const CPU_CHAR *os_msg__c = "$Id: $"; #endif #if OS_MSG_EN > 0u /* ************************************************************************************************************************ * EXTEND THE POOL OF 'OS_MSG' * * Description: This function is called by your application to add OS_MSGs to the free list of OS_MSGs * * Arguments : p_msg is a pointer to the base address of an array of OS_MSG and should be declared as follows: * * OS_MSG MyNewMsgTbl[size]; * * size is the size of the above array * * p_err is a pointer to a variable that will contain an error code returned by this function. * * OS_ERR_MSG_POOL_NULL_PTR * OS_ERR_MSG_POOL_EMPTY * OS_ERR_NONE * * Returns : none ************************************************************************************************************************ */ void OSMsgPoolExtend (OS_MSG *p_msg, OS_MSG_QTY size, OS_ERR *p_err) { #ifdef OS_SAFETY_CRITICAL if (p_err == (OS_ERR *)0) { OS_SAFETY_CRITICAL_EXCEPTION(); return; } #endif #if OS_CFG_ARG_CHK_EN > 0u if (p_msg == (OS_MSG *)0) { *p_err = OS_ERR_MSG_POOL_NULL_PTR; return; } if (size == (OS_MSG_QTY)0) { *p_err = OS_ERR_MSG_POOL_EMPTY; return; } #endif OS_MsgPoolCreate(p_msg, /* Create the singly linked list */ size); p_msg[size - 1u].NextPtr = OSMsgPool.NextPtr; /* Link last OS_MSG of new list to current pool */ OSMsgPool.NextPtr = p_msg; OSMsgPool.NbrFree += size; /* All new OS_MSGs are now available */ *p_err = OS_ERR_NONE; } /*$PAGE*/ /* ************************************************************************************************************************ * CREATE A LINKED LIST OF 'OS_MSG' * * Description: This function is called to create a singly linked list of OS_MSGs which is used as a pool of available * OS_MSGs to be used for sending messages. * * Arguments : p_msg is a pointer to the base address of an array of OS_MSG and should be declared as follows: * ----- * OS_MSG MyMsgTbl[size]; * * size is the size of the above array * * Returns : none * * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it. ************************************************************************************************************************ */ void OS_MsgPoolCreate (OS_MSG *p_msg, OS_MSG_QTY size) { OS_MSG *p_msg1; OS_MSG *p_msg2; OS_MSG_QTY i; OS_MSG_QTY loops; p_msg1 = p_msg; p_msg2 = p_msg; p_msg2++; loops = size - 1u; for (i = 0u; i < loops; i++) { /* Init. list of free OS_MSGs */ p_msg1->NextPtr = p_msg2; p_msg1->MsgPtr = (void *)0; p_msg1->MsgSize = (OS_MSG_SIZE)0u; p_msg1->MsgTS = (CPU_TS )0u; p_msg1++; p_msg2++; } p_msg1->NextPtr = (OS_MSG *)0; /* Last OS_MSG */ p_msg1->MsgPtr = (void *)0; p_msg1->MsgSize = (OS_MSG_SIZE)0u; p_msg1->MsgTS = (CPU_TS )0u; } /*$PAGE*/ /* ************************************************************************************************************************ * INITIALIZE THE POOL OF 'OS_MSG' * * Description: This function is called by OSInit() to initialize the free list of OS_MSGs. * * Argument(s): p_err is a pointer to a variable that will contain an error code returned by this function. * * OS_ERR_MSG_POOL_NULL_PTR * OS_ERR_MSG_POOL_EMPTY * OS_ERR_NONE * * Returns : none * * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it. ************************************************************************************************************************ */ void OS_MsgPoolInit (OS_ERR *p_err) { #ifdef OS_SAFETY_CRITICAL if (p_err == (OS_ERR *)0) { OS_SAFETY_CRITICAL_EXCEPTION(); return; } #endif #if OS_CFG_ARG_CHK_EN > 0u if (OSCfg_MsgPoolBasePtr == (OS_MSG *)0) { *p_err = OS_ERR_MSG_POOL_NULL_PTR; return; } if (OSCfg_MsgPoolSize == (OS_MSG_QTY)0) { *p_err = OS_ERR_MSG_POOL_EMPTY; return; } #endif OS_MsgPoolCreate(OSCfg_MsgPoolBasePtr, OSCfg_MsgPoolSize); OSMsgPool.NextPtr = OSCfg_MsgPoolBasePtr; OSMsgPool.NbrFree = OSCfg_MsgPoolSize; OSMsgPool.NbrUsed = (OS_MSG_QTY)0; *p_err = OS_ERR_NONE; } /*$PAGE*/ /* ************************************************************************************************************************ * RESET MESSAGE QUEUE ENTRIES PEAK TRACKING * * Description: This function clear the peak detection mechanism of the message queue * * Arguments : p_msg_q is a pointer to the OS_MSG_Q structure * ------- * * Returns : none * * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it. ************************************************************************************************************************ */ void OS_MsgQEntriesPeakReset (OS_MSG_Q *p_msg_q) { CPU_SR_ALLOC(); CPU_CRITICAL_ENTER(); p_msg_q->NbrEntriesMax = (OS_MSG_QTY)0; CPU_CRITICAL_EXIT(); } /*$PAGE*/ /* ************************************************************************************************************************ * RELEASE ALL MESSAGE IN MESSAGE QUEUE * * Description: This function returns all the messages in a message queue to the free list. * * Arguments : p_msg_q is a pointer to the OS_MSG_Q structure containing messages to free. * ------- * * Returns : the number of OS_MSGs returned to the free list * * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it. ************************************************************************************************************************ */ OS_MSG_QTY OS_MsgQFreeAll (OS_MSG_Q *p_msg_q) { OS_MSG *p_msg; OS_MSG_QTY qty; qty = p_msg_q->NbrEntries; /* Get the number of OS_MSGs being freed */ if (p_msg_q->NbrEntries > (OS_MSG_QTY)0) { p_msg = p_msg_q->InPtr; /* Point to end of message chain */ p_msg->NextPtr = OSMsgPool.NextPtr; OSMsgPool.NextPtr = p_msg_q->OutPtr; /* Point to beginning of message chain */ OSMsgPool.NbrUsed -= p_msg_q->NbrEntries; /* Update statistics for free list of messages */ OSMsgPool.NbrFree += p_msg_q->NbrEntries; p_msg_q->NbrEntries = (OS_MSG_QTY)0; /* Flush the message queue */ p_msg_q->NbrEntriesMax = (OS_MSG_QTY)0; p_msg_q->InPtr = (OS_MSG *)0; p_msg_q->OutPtr = (OS_MSG *)0; } return (qty); } /*$PAGE*/ /* ************************************************************************************************************************ * INITIALIZE A MESSAGE QUEUE * * Description: This function is called to initialize a message queue * * Arguments : p_msg_q is a pointer to the message queue to initialize * ------- * * max is the maximum number of entries that a message queue can have. * * Returns : none * * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it. ************************************************************************************************************************ */ void OS_MsgQInit (OS_MSG_Q *p_msg_q, OS_MSG_QTY size) { p_msg_q->NbrEntriesSize = (OS_MSG_QTY)size; p_msg_q->NbrEntries = (OS_MSG_QTY)0; p_msg_q->NbrEntriesMax = (OS_MSG_QTY)0; p_msg_q->InPtr = (OS_MSG *)0; p_msg_q->OutPtr = (OS_MSG *)0; } /*$PAGE*/ /* ************************************************************************************************************************ * RETRIEVE MESSAGE FROM MESSAGE QUEUE * * Description: This function retrieves a message from a message queue * * Arguments : p_msg_q is a pointer to the message queue where we want to extract the message from * ------- * * p_msg_size is a pointer to where the size (in bytes) of the message will be placed * * p_ts is a pointer to where the time stamp will be placed * * p_err is a pointer to an error code that will be returned from this call. * * OS_ERR_Q_EMPTY * OS_ERR_NONE * * Returns : The message (a pointer) * * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it. ************************************************************************************************************************ */ void *OS_MsgQGet (OS_MSG_Q *p_msg_q, OS_MSG_SIZE *p_msg_size, CPU_TS *p_ts, OS_ERR *p_err) { OS_MSG *p_msg; void *p_void; #ifdef OS_SAFETY_CRITICAL if (p_err == (OS_ERR *)0) { OS_SAFETY_CRITICAL_EXCEPTION(); return ((void *)0); } #endif if (p_msg_q->NbrEntries == (OS_MSG_QTY)0) { *p_msg_size = (OS_MSG_SIZE)0; if (p_ts != (CPU_TS *)0) { *p_ts = (CPU_TS )0; } *p_err = OS_ERR_Q_EMPTY; return ((void *)0); } p_msg = p_msg_q->OutPtr; p_void = p_msg->MsgPtr; *p_msg_size = p_msg->MsgSize; if (p_ts != (CPU_TS *)0) { *p_ts = p_msg->MsgTS; } p_msg_q->OutPtr = p_msg->NextPtr; if (p_msg_q->OutPtr == (OS_MSG *)0) { p_msg_q->InPtr = (OS_MSG *)0; p_msg_q->NbrEntries = (OS_MSG_QTY)0; } else { p_msg_q->NbrEntries--; } p_msg->NextPtr = OSMsgPool.NextPtr; /* Return message control block to free list */ OSMsgPool.NextPtr = p_msg; OSMsgPool.NbrFree++; OSMsgPool.NbrUsed--; *p_err = OS_ERR_NONE; return (p_void); } /* ************************************************************************************************************************ * DEPOSIT MESSAGE IN MESSAGE QUEUE * * Description: This function places a message in a message queue * * Arguments : p_msg_q is a pointer to the OS_TCB of the task to post the message to * ------- * * p_void is a pointer to the message to send. * * msg_size is the size of the message (in bytes) * * opt specifies whether the message will be posted in FIFO or LIFO order * * OS_OPT_POST_FIFO * OS_OPT_POST_LIFO * * ts is a timestamp as to when the message was posted * * p_err is a pointer to a variable that will contain an error code returned by this function. * * OS_ERR_Q_MAX if the queue is full * OS_ERR_MSG_POOL_EMPTY if we no longer have any OS_MSG to use * OS_ERR_NONE the message was deposited in the queue * * Returns : none * * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it. ************************************************************************************************************************ */ void OS_MsgQPut (OS_MSG_Q *p_msg_q, void *p_void, OS_MSG_SIZE msg_size, OS_OPT opt, CPU_TS ts, OS_ERR *p_err) { OS_MSG *p_msg; OS_MSG *p_msg_in; #ifdef OS_SAFETY_CRITICAL if (p_err == (OS_ERR *)0) { OS_SAFETY_CRITICAL_EXCEPTION(); return; } #endif if (p_msg_q->NbrEntries >= p_msg_q->NbrEntriesSize) { *p_err = OS_ERR_Q_MAX; /* Message queue cannot accept any more messages */ return; } if (OSMsgPool.NbrFree == (OS_MSG_QTY)0) { *p_err = OS_ERR_MSG_POOL_EMPTY; /* No more OS_MSG to use */ return; } p_msg = OSMsgPool.NextPtr; /* Remove message control block from free list */ OSMsgPool.NextPtr = p_msg->NextPtr; OSMsgPool.NbrFree--; OSMsgPool.NbrUsed++; if (p_msg_q->NbrEntries == (OS_MSG_QTY)0) { /* Is this first message placed in the queue? */ p_msg_q->InPtr = p_msg; /* Yes */ p_msg_q->OutPtr = p_msg; p_msg_q->NbrEntries = (OS_MSG_QTY)1; } else { if ((opt & OS_OPT_POST_LIFO) == OS_OPT_POST_FIFO) { /* Assume FIFO if not LIFO */ p_msg_in = p_msg_q->InPtr; /* FIFO */ p_msg_in->NextPtr = p_msg; p_msg->NextPtr = (OS_MSG *)0; p_msg_q->InPtr = p_msg; } else { p_msg->NextPtr = p_msg_q->OutPtr; /* LIFO */ p_msg_q->OutPtr = p_msg; } p_msg_q->NbrEntries++; } if (p_msg_q->NbrEntries > p_msg_q->NbrEntriesMax) { p_msg_q->NbrEntriesMax = p_msg_q->NbrEntries; } p_msg->MsgPtr = p_void; /* Deposit message in the message queue entry */ p_msg->MsgSize = msg_size; p_msg->MsgTS = ts; *p_err = OS_ERR_NONE; } #endif