OS_MBOX.c
上传用户:jinguanrq
上传日期:2022-06-04
资源大小:724k
文件大小:12k
源码类别:

uCOS

开发平台:

C/C++

  1. /*
  2. *********************************************************************************************************
  3. *                                                uC/OS-II
  4. *                                          The Real-Time Kernel
  5. *                                       MESSAGE MAILBOX MANAGEMENT
  6. *
  7. *                        (c) Copyright 1992-1998, Jean J. Labrosse, Plantation, FL
  8. *                                           All Rights Reserved
  9. *
  10. *                                                  V2.00
  11. *
  12. * File : OS_MBOX.C
  13. * By   : Jean J. Labrosse
  14. *********************************************************************************************************
  15. */
  16. #ifndef  OS_MASTER_FILE
  17. #include "includes.h"
  18. #endif
  19. #if OS_MBOX_EN
  20. /*
  21. *********************************************************************************************************
  22. *                                     ACCEPT MESSAGE FROM MAILBOX
  23. *
  24. * Description: This function checks the mailbox to see if a message is available.  Unlike OSMboxPend(),
  25. *              OSMboxAccept() does not suspend the calling task if a message is not available.
  26. *
  27. * Arguments  : pevent        is a pointer to the event control block
  28. *
  29. * Returns    : != (void *)0  is the message in the mailbox if one is available.  The mailbox is cleared
  30. *                            so the next time OSMboxAccept() is called, the mailbox will be empty.
  31. *              == (void *)0  if the mailbox is empty or if you didn't pass the proper event pointer.
  32. *********************************************************************************************************
  33. */
  34. void *OSMboxAccept (OS_EVENT *pevent)
  35. {
  36.     void  *msg;
  37.     OS_ENTER_CRITICAL();
  38.     if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {      /* Validate event block type                 */
  39.         OS_EXIT_CRITICAL();
  40.         return ((void *)0);
  41.     }
  42.     msg = pevent->OSEventPtr; 
  43.     if (msg != (void *)0) {                               /* See if there is already a message         */
  44.         pevent->OSEventPtr = (void *)0;                   /* Clear the mailbox                         */
  45.     }
  46.     OS_EXIT_CRITICAL();
  47.     return (msg);                                         /* Return the message received (or NULL)     */
  48. }
  49. /*$PAGE*/
  50. /*
  51. *********************************************************************************************************
  52. *                                        CREATE A MESSAGE MAILBOX
  53. *
  54. * Description: This function creates a message mailbox if free event control blocks are available.
  55. *
  56. * Arguments  : msg           is a pointer to a message that you wish to deposit in the mailbox.  If
  57. *                            you set this value to the NULL pointer (i.e. (void *)0) then the mailbox
  58. *                            will be considered empty.
  59. *
  60. * Returns    : != (void *)0  is a pointer to the event control clock (OS_EVENT) associated with the
  61. *                            created mailbox
  62. *              == (void *)0  if no event control blocks were available
  63. *********************************************************************************************************
  64. */
  65. OS_EVENT *OSMboxCreate (void *msg)
  66. {
  67.     OS_EVENT *pevent;
  68.     OS_ENTER_CRITICAL();
  69.     pevent = OSEventFreeList;                    /* Get next free event control block                  */
  70.     if (OSEventFreeList != (OS_EVENT *)0) {      /* See if pool of free ECB pool was empty             */
  71.         OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
  72.     }
  73.     OS_EXIT_CRITICAL();
  74.     if (pevent != (OS_EVENT *)0) {
  75.         pevent->OSEventType = OS_EVENT_TYPE_MBOX;
  76.         pevent->OSEventPtr  = msg;               /* Deposit message in event control block             */
  77.         OSEventWaitListInit(pevent);
  78.     }
  79.     return (pevent);                             /* Return pointer to event control block              */
  80. }
  81. /*$PAGE*/
  82. /*
  83. *********************************************************************************************************
  84. *                                      PEND ON MAILBOX FOR A MESSAGE
  85. *
  86. * Description: This function waits for a message to be sent to a mailbox
  87. *
  88. * Arguments  : pevent        is a pointer to the event control block associated with the desired mailbox
  89. *
  90. *              timeout       is an optional timeout period (in clock ticks).  If non-zero, your task will
  91. *                            wait for a message to arrive at the mailbox up to the amount of time 
  92. *                            specified by this argument.  If you specify 0, however, your task will wait 
  93. *                            forever at the specified mailbox or, until a message arrives.
  94. *
  95. *              err           is a pointer to where an error message will be deposited.  Possible error
  96. *                            messages are:
  97. *
  98. *                            OS_NO_ERR         The call was successful and your task received a message.
  99. *                            OS_TIMEOUT        A message was not received within the specified timeout
  100. *                            OS_ERR_EVENT_TYPE Invalid event type
  101. *                            OS_ERR_PEND_ISR   If you called this function from an ISR and the result
  102. *                                              would lead to a suspension.
  103. *
  104. * Returns    : != (void *)0  is a pointer to the message received
  105. *              == (void *)0  if no message was received or you didn't pass the proper pointer to the
  106. *                            event control block.
  107. *********************************************************************************************************
  108. */
  109. void *OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
  110. {
  111.     void  *msg;
  112.     OS_ENTER_CRITICAL();
  113.     if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {  /* Validate event block type                     */
  114.         OS_EXIT_CRITICAL();
  115.         *err = OS_ERR_EVENT_TYPE;
  116.         return ((void *)0);
  117.     }
  118.     msg = pevent->OSEventPtr;
  119.     if (msg != (void *)0) {                           /* See if there is already a message             */
  120.         pevent->OSEventPtr = (void *)0;               /* Clear the mailbox                             */
  121.         OS_EXIT_CRITICAL();
  122.         *err = OS_NO_ERR;
  123.     } else if (OSIntNesting > 0) {                    /* See if called from ISR ...                    */
  124.         OS_EXIT_CRITICAL();                           /* ... can't PEND from an ISR                    */
  125.         *err = OS_ERR_PEND_ISR;
  126.     } else {
  127.         OSTCBCur->OSTCBStat |= OS_STAT_MBOX;          /* Message not available, task will pend         */
  128.         OSTCBCur->OSTCBDly   = timeout;               /* Load timeout in TCB                           */
  129.         OSEventTaskWait(pevent);                      /* Suspend task until event or timeout occurs    */
  130.         OS_EXIT_CRITICAL();
  131.         OSSched();                                    /* Find next highest priority task ready to run  */
  132.         OS_ENTER_CRITICAL();
  133.         if ((msg = OSTCBCur->OSTCBMsg) != (void *)0) {     /* See if we were given the message         */
  134.             OSTCBCur->OSTCBMsg      = (void *)0;           /* Yes, clear message received              */
  135.             OSTCBCur->OSTCBStat     = OS_STAT_RDY;
  136.             OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;       /* No longer waiting for event              */
  137.             OS_EXIT_CRITICAL();
  138.             *err                    = OS_NO_ERR;
  139.         } else if (OSTCBCur->OSTCBStat & OS_STAT_MBOX) {   /* If status is not OS_STAT_RDY, timed out  */
  140.             OSEventTO(pevent);                             /* Make task ready                          */
  141.             OS_EXIT_CRITICAL();
  142.             msg                     = (void *)0;           /* Set message contents to NULL             */
  143.             *err                    = OS_TIMEOUT;          /* Indicate that a timeout occured          */
  144.         } else {
  145.             msg                     = pevent->OSEventPtr;  /* Message received                         */
  146.             pevent->OSEventPtr      = (void *)0;           /* Clear the mailbox                        */
  147.             OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;
  148.             OS_EXIT_CRITICAL();
  149.             *err                    = OS_NO_ERR;
  150.         }
  151.     }
  152.     return (msg);                                          /* Return the message received (or NULL)    */
  153. }
  154. /*$PAGE*/
  155. /*
  156. *********************************************************************************************************
  157. *                                       POST MESSAGE TO A MAILBOX
  158. *
  159. * Description: This function sends a message to a mailbox
  160. *
  161. * Arguments  : pevent        is a pointer to the event control block associated with the desired mailbox
  162. *
  163. *              msg           is a pointer to the message to send.  You MUST NOT send a NULL pointer.  
  164. *
  165. * Returns    : OS_NO_ERR          The call was successful and the message was sent
  166. *              OS_MBOX_FULL       If the mailbox already contains a message.  You can can only send one
  167. *                                 message at a time and thus, the message MUST be consumed before you are
  168. *                                 allowed to send another one.
  169. *              OS_ERR_EVENT_TYPE  If you are attempting to post to a non mailbox.
  170. *********************************************************************************************************
  171. */
  172. INT8U OSMboxPost (OS_EVENT *pevent, void *msg)
  173. {
  174.     OS_ENTER_CRITICAL();
  175.     if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {  /* Validate event block type                     */
  176.         OS_EXIT_CRITICAL();
  177.         return (OS_ERR_EVENT_TYPE);
  178.     }
  179.     if (pevent->OSEventGrp) {                         /* See if any task pending on mailbox            */
  180.         OSEventTaskRdy(pevent, msg, OS_STAT_MBOX);    /* Ready highest priority task waiting on event  */
  181.         OS_EXIT_CRITICAL();
  182.         OSSched();                                    /* Find highest priority task ready to run       */
  183.         return (OS_NO_ERR);
  184.     } else {
  185.         if (pevent->OSEventPtr != (void *)0) {        /* Make sure mailbox doesn't already have a msg  */
  186.             OS_EXIT_CRITICAL();
  187.             return (OS_MBOX_FULL);
  188.         } else {
  189.             pevent->OSEventPtr = msg;                 /* Place message in mailbox                      */
  190.             OS_EXIT_CRITICAL();
  191.             return (OS_NO_ERR);
  192.         }
  193.     }
  194. }
  195. /*$PAGE*/
  196. /*
  197. *********************************************************************************************************
  198. *                                        QUERY A MESSAGE MAILBOX
  199. *
  200. * Description: This function obtains information about a message mailbox.
  201. *
  202. * Arguments  : pevent        is a pointer to the event control block associated with the desired mailbox
  203. *
  204. *              pdata         is a pointer to a structure that will contain information about the message
  205. *                            mailbox.
  206. *
  207. * Returns    : OS_NO_ERR          The call was successful and the message was sent
  208. *              OS_ERR_EVENT_TYPE  If you are attempting to obtain data from a non mailbox.
  209. *********************************************************************************************************
  210. */
  211. INT8U OSMboxQuery (OS_EVENT *pevent, OS_MBOX_DATA *pdata)
  212. {
  213.     INT8U  i;
  214.     INT8U *psrc;
  215.     INT8U *pdest;
  216.     
  217.     
  218.     OS_ENTER_CRITICAL();
  219.     if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {       /* Validate event block type                */
  220.         OS_EXIT_CRITICAL();
  221.         return (OS_ERR_EVENT_TYPE);
  222.     }
  223.     pdata->OSEventGrp = pevent->OSEventGrp;                /* Copy message mailbox wait list           */
  224.     psrc              = &pevent->OSEventTbl[0];
  225.     pdest             = &pdata->OSEventTbl[0];
  226.     for (i = 0; i < OS_EVENT_TBL_SIZE; i++) {
  227.         *pdest++ = *psrc++;   
  228.     }
  229.     pdata->OSMsg = pevent->OSEventPtr;                     /* Get message from mailbox                 */
  230.     OS_EXIT_CRITICAL();
  231.     return (OS_NO_ERR);
  232. }
  233. #endif