00001 /** 00002 ******************************************************************************* 00003 * @file mbox.c 00004 * @version V1.1.3 00005 * @date 2010.04.26 00006 * @brief Mailbox management implementation code of CooCox CoOS kernel. 00007 ******************************************************************************* 00008 * @copy 00009 * 00010 * INTERNAL FILE,DON'T PUBLIC. 00011 * 00012 * <h2><center>© COPYRIGHT 2009 CooCox </center></h2> 00013 ******************************************************************************* 00014 */ 00015 00016 /*---------------------------- Include ---------------------------------------*/ 00017 #include <coocox.h> 00018 00019 00020 #if CFG_MAILBOX_EN > 0 00021 00022 00023 /** 00024 ******************************************************************************* 00025 * @brief Create a mailbox 00026 * @param[in] sortType Mail box waiting list sort type. 00027 * @param[out] None 00028 * @retval E_CREATE_FAIL Create mailbox fail. 00029 * @retval others Create mailbox successful. 00030 * 00031 * @par Description 00032 * @details This function is called to create a mailbox. 00033 * @note 00034 ******************************************************************************* 00035 */ 00036 OS_EventID CoCreateMbox(U8 sortType) 00037 { 00038 P_ECB pecb; 00039 00040 /* Create a mailbox type event control block */ 00041 pecb = CreatEvent (EVENT_TYPE_MBOX ,sortType,0); 00042 if(pecb == 0) /* If failed to create event block */ 00043 { 00044 return E_CREATE_FAIL; 00045 } 00046 pecb->eventCounter = 0; 00047 return (pecb->id ); /* Create a mailbox successfully, return event ID */ 00048 } 00049 00050 00051 00052 /** 00053 ******************************************************************************* 00054 * @brief Delete a mailbox 00055 * @param[in] id Event ID. 00056 * @param[in] opt Delete option. 00057 * @param[out] None 00058 * @retval E_INVALID_ID Invalid event ID. 00059 * @retval E_INVALID_PARAMETER Invalid parameter. 00060 * @retval E_TASK_WAITTING Tasks waitting for the event,delete fail. 00061 * @retval E_OK Event deleted successful. 00062 * 00063 * @par Description 00064 * @details This function is called to delete a mailbox. 00065 * @note 00066 ******************************************************************************* 00067 */ 00068 StatusType CoDelMbox(OS_EventID id,U8 opt) 00069 { 00070 P_ECB pecb; 00071 00072 #if CFG_PAR_CHECKOUT_EN >0 00073 if(id >= CFG_MAX_EVENT ) /* Judge id is valid or not? */ 00074 { 00075 return E_INVALID_ID; /* Id is invalid ,return error */ 00076 } 00077 #endif 00078 pecb = &EventTbl [id]; 00079 #if CFG_PAR_CHECKOUT_EN >0 00080 if(pecb->eventType != EVENT_TYPE_MBOX )/* Validate event control block type*/ 00081 { 00082 return E_INVALID_ID; /* The event is not mailbox */ 00083 } 00084 #endif 00085 return (DeleteEvent (pecb,opt)); /* Delete the mailbox event control block */ 00086 } 00087 00088 00089 00090 /** 00091 ******************************************************************************* 00092 * @brief Accept a mailbox 00093 * @param[in] id Event ID. 00094 * @param[out] perr A pointer to error code. 00095 * @retval 0 00096 * @retval A pointer to mailbox accepted. 00097 * 00098 * @par Description 00099 * @details This function is called to accept a mailbox. 00100 * @note 00101 ******************************************************************************* 00102 */ 00103 void* CoAcceptMail(OS_EventID id,StatusType* perr) 00104 { 00105 P_ECB pecb; 00106 void* pmail; 00107 #if CFG_PAR_CHECKOUT_EN >0 00108 if(id >= CFG_MAX_EVENT ) 00109 { 00110 *perr = E_INVALID_ID; /* Invalid 'id' */ 00111 return 0; 00112 } 00113 #endif 00114 pecb = &EventTbl [id]; 00115 00116 #if CFG_PAR_CHECKOUT_EN >0 00117 if(pecb->eventType != EVENT_TYPE_MBOX )/* Invalid event control block type */ 00118 { 00119 *perr = E_INVALID_ID; 00120 return 0; 00121 } 00122 #endif 00123 OsSchedLock (); 00124 if(pecb->eventCounter == 1) /* If there is already a message */ 00125 { 00126 *perr = E_OK; 00127 pmail = pecb->eventPtr ; /* Get the message */ 00128 pecb->eventPtr = 0; /* Clear the mailbox */ 00129 pecb->eventCounter = 0; 00130 OsSchedUnlock(); 00131 return pmail; /* Return the message received */ 00132 } 00133 else /* If the mailbox is empty */ 00134 { 00135 OsSchedUnlock(); 00136 *perr = E_MBOX_EMPTY; /* Mailbox is empty,return 0 */ 00137 return 0; 00138 } 00139 } 00140 00141 00142 00143 /** 00144 ******************************************************************************* 00145 * @brief Wait for a mailbox 00146 * @param[in] id Event ID. 00147 * @param[in] timeout The longest time for writting mail. 00148 * @param[out] perr A pointer to error code. 00149 * @retval 0 00150 * @retval A pointer to mailbox accept. 00151 * 00152 * @par Description 00153 * @details This function is called to wait a mailbox. 00154 * @note 00155 ******************************************************************************* 00156 */ 00157 void* CoPendMail(OS_EventID id,U32 timeout,StatusType* perr) 00158 { 00159 P_ECB pecb; 00160 void* pmail; 00161 P_OSTCB curTCB; 00162 00163 if(OSIntNesting > 0) /* If the caller is ISR */ 00164 { 00165 *perr = E_CALL; 00166 return 0; 00167 } 00168 00169 #if CFG_PAR_CHECKOUT_EN >0 00170 if(id >= CFG_MAX_EVENT ) 00171 { 00172 *perr = E_INVALID_ID; /* Invalid 'id',retrun error */ 00173 return 0; 00174 } 00175 #endif 00176 00177 pecb = &EventTbl [id]; 00178 #if CFG_PAR_CHECKOUT_EN >0 00179 if(pecb->eventType != EVENT_TYPE_MBOX ) 00180 { 00181 *perr = E_INVALID_ID; /* Invalid event type,not EVENT_TYPE_MBOX */ 00182 return 0; 00183 } 00184 #endif 00185 00186 if(OSSchedLock != 0) /* Judge schedule is locked or not? */ 00187 { 00188 *perr = E_OS_IN_LOCK; /* Schedule is locked */ 00189 return 0; /* return 0 */ 00190 } 00191 if( pecb->eventCounter == 1) /* If there is already a message */ 00192 { 00193 *perr = E_OK; 00194 pmail = pecb->eventPtr ; /* Get the message */ 00195 pecb->eventPtr = 0; /* Clear the mailbox */ 00196 pecb->eventCounter = 0; 00197 return pmail; /* Return the message received */ 00198 } 00199 else /* If message is not available, task will pend */ 00200 { 00201 curTCB = TCBRunning ; 00202 if(timeout == 0) /* If time-out is not configured */ 00203 { 00204 EventTaskToWait(pecb,curTCB); /* Block task until event occurs */ 00205 *perr = E_OK; 00206 00207 /* Have recived a message or the mailbox have been deleted */ 00208 pmail = curTCB->pmail; 00209 curTCB->pmail = 0; 00210 return pmail; /* Return received message or 0 */ 00211 } 00212 else /* If time-out is configured */ 00213 { 00214 OsSchedLock (); 00215 00216 /* Block task until event or timeout occurs */ 00217 EventTaskToWait(pecb,curTCB); 00218 InsertDelayList(curTCB,timeout); 00219 OsSchedUnlock(); 00220 if( curTCB->pmail == 0) /* Time-out occurred */ 00221 { 00222 *perr = E_TIMEOUT; 00223 return 0; 00224 } 00225 else /* Have recived a message or the mailbox have been deleted*/ 00226 { 00227 *perr = E_OK; 00228 pmail = curTCB->pmail; 00229 curTCB->pmail = 0; 00230 return pmail; /* Return received message or 0 */ 00231 } 00232 } 00233 } 00234 } 00235 00236 00237 /** 00238 ******************************************************************************* 00239 * @brief Post a mailbox 00240 * @param[in] id Event ID. 00241 * @param[in] pmail Pointer to mail that want to send. 00242 * @param[out] None 00243 * @retval E_INVALID_ID 00244 * @retval E_OK 00245 * 00246 * @par Description 00247 * @details This function is called to post a mail. 00248 * @note 00249 ******************************************************************************* 00250 */ 00251 StatusType CoPostMail(OS_EventID id,void* pmail) 00252 { 00253 P_ECB pecb; 00254 #if CFG_PAR_CHECKOUT_EN >0 00255 if(id >= CFG_MAX_EVENT ) 00256 { 00257 return E_INVALID_ID; /* Invalid id,return error */ 00258 } 00259 #endif 00260 00261 pecb = &EventTbl [id]; 00262 #if CFG_PAR_CHECKOUT_EN >0 00263 if(pecb->eventType != EVENT_TYPE_MBOX )/* Validate event control block type*/ 00264 { 00265 return E_INVALID_ID; /* Event is not mailbox,return error*/ 00266 } 00267 #endif 00268 00269 if(pecb->eventCounter == 0) /* If mailbox doesn't already have a message*/ 00270 { 00271 OsSchedLock (); 00272 pecb->eventPtr = pmail; /* Place message in mailbox */ 00273 pecb->eventCounter = 1; 00274 EventTaskToRdy (pecb); /* Check waiting list */ 00275 OsSchedUnlock(); 00276 return E_OK; 00277 } 00278 else /* If there is already a message in mailbox */ 00279 { 00280 return E_MBOX_FULL; /* Mailbox is full,and return "E_MBOX_FULL" */ 00281 } 00282 } 00283 00284 /** 00285 ******************************************************************************* 00286 * @brief Post a mailbox in ISR 00287 * @param[in] id Event ID. 00288 * @param[in] pmail Pointer to mail that want to send. 00289 * @param[out] None 00290 * @retval E_INVALID_ID 00291 * @retval E_OK 00292 * 00293 * @par Description 00294 * @details This function is called to post a mail in ISR. 00295 * @note 00296 ******************************************************************************* 00297 */ 00298 #if CFG_MAX_SERVICE_REQUEST > 0 00299 StatusType isr_PostMail(OS_EventID id,void* pmail) 00300 { 00301 if(OSSchedLock > 0) /* If scheduler is locked,(the caller is ISR) */ 00302 { 00303 /* Insert the request into service request queue */ 00304 if(InsertInSRQ(MBOX_REQ,id,pmail) == FALSE) 00305 { 00306 return E_SEV_REQ_FULL; /* If service request queue is full */ 00307 } 00308 else /* Operate successfully */ 00309 { 00310 return E_OK; 00311 } 00312 } 00313 else 00314 { 00315 return(CoPostMail(id,pmail)); /* Sends the message to the mailbox */ 00316 } 00317 } 00318 #endif 00319 00320 #endif 00321 00322