CoOS Demonstrator adapted to mbed Hardware.

Dependencies:   mbed

Committer:
ericebert
Date:
Fri Dec 03 19:45:30 2010 +0000
Revision:
0:57690853989a
Some basic LED-Flashing works in the CoOS-RTOS using Tasks

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ericebert 0:57690853989a 1 /**
ericebert 0:57690853989a 2 *******************************************************************************
ericebert 0:57690853989a 3 * @file mutex.c
ericebert 0:57690853989a 4 * @version V1.1.3
ericebert 0:57690853989a 5 * @date 2010.04.26
ericebert 0:57690853989a 6 * @brief Mutex management implementation code of CooCox CoOS kernel.
ericebert 0:57690853989a 7 *******************************************************************************
ericebert 0:57690853989a 8 * @copy
ericebert 0:57690853989a 9 *
ericebert 0:57690853989a 10 * INTERNAL FILE,DON'T PUBLIC.
ericebert 0:57690853989a 11 *
ericebert 0:57690853989a 12 * <h2><center>&copy; COPYRIGHT 2009 CooCox </center></h2>
ericebert 0:57690853989a 13 *******************************************************************************
ericebert 0:57690853989a 14 */
ericebert 0:57690853989a 15
ericebert 0:57690853989a 16
ericebert 0:57690853989a 17
ericebert 0:57690853989a 18 /*---------------------------- Include ---------------------------------------*/
ericebert 0:57690853989a 19 #include <coocox.h>
ericebert 0:57690853989a 20
ericebert 0:57690853989a 21
ericebert 0:57690853989a 22 /*---------------------------- Variable Define -------------------------------*/
ericebert 0:57690853989a 23 #if CFG_MUTEX_EN > 0
ericebert 0:57690853989a 24
ericebert 0:57690853989a 25 OS_MutexID MutexFreeID = 0; /*!< Point to next vliad mutex ID. */
ericebert 0:57690853989a 26 MUTEX MutexTbl[CFG_MAX_MUTEX] = {{0}}; /*!< Mutex struct array */
ericebert 0:57690853989a 27
ericebert 0:57690853989a 28
ericebert 0:57690853989a 29
ericebert 0:57690853989a 30 /**
ericebert 0:57690853989a 31 *******************************************************************************
ericebert 0:57690853989a 32 * @brief Create a mutex
ericebert 0:57690853989a 33 * @param[in] None
ericebert 0:57690853989a 34 * @param[out] None
ericebert 0:57690853989a 35 * @retval E_CREATE_FAIL Create mutex fail.
ericebert 0:57690853989a 36 * @retval others Create mutex successful.
ericebert 0:57690853989a 37 *
ericebert 0:57690853989a 38 * @par Description
ericebert 0:57690853989a 39 * @details This function is called to create a mutex.
ericebert 0:57690853989a 40 * @note
ericebert 0:57690853989a 41 *******************************************************************************
ericebert 0:57690853989a 42 */
ericebert 0:57690853989a 43 OS_MutexID CoCreateMutex(void)
ericebert 0:57690853989a 44 {
ericebert 0:57690853989a 45 OS_MutexID id;
ericebert 0:57690853989a 46 P_MUTEX pMutex;
ericebert 0:57690853989a 47 OsSchedLock();
ericebert 0:57690853989a 48
ericebert 0:57690853989a 49 /* Assign a free mutex control block */
ericebert 0:57690853989a 50 if(MutexFreeID < CFG_MAX_MUTEX )
ericebert 0:57690853989a 51 {
ericebert 0:57690853989a 52 id = MutexFreeID++;
ericebert 0:57690853989a 53 OsSchedUnlock();
ericebert 0:57690853989a 54 pMutex = &MutexTbl[id];
ericebert 0:57690853989a 55 pMutex->hipriTaskID = INVALID_ID;
ericebert 0:57690853989a 56 pMutex->originalPrio = 0xff;
ericebert 0:57690853989a 57 pMutex->mutexFlag = MUTEX_FREE; /* Mutex is free,not was occupied */
ericebert 0:57690853989a 58 pMutex->taskID = INVALID_ID;
ericebert 0:57690853989a 59 pMutex->waittingList = 0;
ericebert 0:57690853989a 60 return id; /* Return mutex ID */
ericebert 0:57690853989a 61 }
ericebert 0:57690853989a 62
ericebert 0:57690853989a 63 OsSchedUnlock();
ericebert 0:57690853989a 64 return E_CREATE_FAIL; /* No free mutex control block */
ericebert 0:57690853989a 65 }
ericebert 0:57690853989a 66
ericebert 0:57690853989a 67
ericebert 0:57690853989a 68
ericebert 0:57690853989a 69 /**
ericebert 0:57690853989a 70 *******************************************************************************
ericebert 0:57690853989a 71 * @brief Enter a critical area
ericebert 0:57690853989a 72 * @param[in] mutexID Specify mutex.
ericebert 0:57690853989a 73 * @param[out] None
ericebert 0:57690853989a 74 * @retval E_INVALID_ID Invalid mutex id.
ericebert 0:57690853989a 75 * @retval E_CALL Error call in ISR.
ericebert 0:57690853989a 76 * @retval E_OK Enter critical area successful.
ericebert 0:57690853989a 77 *
ericebert 0:57690853989a 78 * @par Description
ericebert 0:57690853989a 79 * @details This function is called when entering a critical area.
ericebert 0:57690853989a 80 * @note
ericebert 0:57690853989a 81 *******************************************************************************
ericebert 0:57690853989a 82 */
ericebert 0:57690853989a 83 StatusType CoEnterMutexSection(OS_MutexID mutexID)
ericebert 0:57690853989a 84 {
ericebert 0:57690853989a 85 P_OSTCB ptcb,pCurTcb;
ericebert 0:57690853989a 86 P_MUTEX pMutex;
ericebert 0:57690853989a 87
ericebert 0:57690853989a 88 #if CFG_EVENT_EN >0
ericebert 0:57690853989a 89 P_ECB pecb;
ericebert 0:57690853989a 90 #endif
ericebert 0:57690853989a 91
ericebert 0:57690853989a 92 if(OSIntNesting > 0) /* If the caller is ISR */
ericebert 0:57690853989a 93 {
ericebert 0:57690853989a 94 return E_CALL;
ericebert 0:57690853989a 95 }
ericebert 0:57690853989a 96 if(OSSchedLock != 0) /* Is OS lock? */
ericebert 0:57690853989a 97 {
ericebert 0:57690853989a 98 return E_OS_IN_LOCK; /* Yes,error return */
ericebert 0:57690853989a 99 }
ericebert 0:57690853989a 100
ericebert 0:57690853989a 101 #if CFG_PAR_CHECKOUT_EN >0
ericebert 0:57690853989a 102 if(mutexID >= MutexFreeID) /* Invalid 'mutexID' */
ericebert 0:57690853989a 103 {
ericebert 0:57690853989a 104 return E_INVALID_ID;
ericebert 0:57690853989a 105 }
ericebert 0:57690853989a 106 #endif
ericebert 0:57690853989a 107
ericebert 0:57690853989a 108 OsSchedLock();
ericebert 0:57690853989a 109 pCurTcb = TCBRunning;
ericebert 0:57690853989a 110 pMutex = &MutexTbl[mutexID];
ericebert 0:57690853989a 111
ericebert 0:57690853989a 112 pCurTcb->mutexID = mutexID;
ericebert 0:57690853989a 113 if(pMutex->mutexFlag == MUTEX_FREE) /* If mutex is available */
ericebert 0:57690853989a 114 {
ericebert 0:57690853989a 115 pMutex->originalPrio = pCurTcb->prio; /* Save priority of owning task */
ericebert 0:57690853989a 116 pMutex->taskID = pCurTcb->taskID; /* Acquire the resource */
ericebert 0:57690853989a 117 pMutex->hipriTaskID = pCurTcb->taskID;
ericebert 0:57690853989a 118 pMutex->mutexFlag = MUTEX_OCCUPY; /* Occupy the mutex resource*/
ericebert 0:57690853989a 119 }
ericebert 0:57690853989a 120 /* If the mutex resource had been occupied */
ericebert 0:57690853989a 121 else if(pMutex->mutexFlag == MUTEX_OCCUPY)
ericebert 0:57690853989a 122 {
ericebert 0:57690853989a 123 ptcb = &TCBTbl[pMutex->taskID];
ericebert 0:57690853989a 124 if(ptcb->prio > pCurTcb->prio) /* Need to promote priority of owner? */
ericebert 0:57690853989a 125 {
ericebert 0:57690853989a 126 #if CFG_ORDER_LIST_SCHEDULE_EN ==0
ericebert 0:57690853989a 127 DeleteTaskPri(ptcb->prio);
ericebert 0:57690853989a 128 ActiveTaskPri(pCurTcb->prio);
ericebert 0:57690853989a 129 #endif
ericebert 0:57690853989a 130 ptcb->prio = pCurTcb->prio; /* Promote prio of owner */
ericebert 0:57690853989a 131
ericebert 0:57690853989a 132 /* Upgarde the highest priority about the mutex */
ericebert 0:57690853989a 133 pMutex->hipriTaskID = pCurTcb->taskID;
ericebert 0:57690853989a 134 if(ptcb->state == TASK_READY) /* If the task is ready to run */
ericebert 0:57690853989a 135 {
ericebert 0:57690853989a 136 RemoveFromTCBRdyList(ptcb); /* Remove the task from READY list*/
ericebert 0:57690853989a 137 InsertToTCBRdyList(ptcb); /* Insert the task into READY list*/
ericebert 0:57690853989a 138 }
ericebert 0:57690853989a 139 #if CFG_EVENT_EN >0
ericebert 0:57690853989a 140 /* If the task is waiting on a event */
ericebert 0:57690853989a 141 else if(ptcb->eventID != INVALID_ID)
ericebert 0:57690853989a 142 {
ericebert 0:57690853989a 143 pecb = &EventTbl[ptcb->eventID];
ericebert 0:57690853989a 144
ericebert 0:57690853989a 145 /* If the event waiting type is preemptive Priority */
ericebert 0:57690853989a 146 if(pecb->eventSortType == EVENT_SORT_TYPE_PRIO)
ericebert 0:57690853989a 147 {
ericebert 0:57690853989a 148 /* Remove the task from event waiting list */
ericebert 0:57690853989a 149 RemoveEventWaittingList(ptcb);
ericebert 0:57690853989a 150
ericebert 0:57690853989a 151 /* Insert the task into event waiting list */
ericebert 0:57690853989a 152 EventTaskToWait(pecb,ptcb);
ericebert 0:57690853989a 153 }
ericebert 0:57690853989a 154 }
ericebert 0:57690853989a 155 #endif
ericebert 0:57690853989a 156 }
ericebert 0:57690853989a 157
ericebert 0:57690853989a 158 pCurTcb->state = TASK_WAITING; /* Block current task */
ericebert 0:57690853989a 159 TaskSchedReq = TRUE;
ericebert 0:57690853989a 160 pCurTcb->TCBnext = 0;
ericebert 0:57690853989a 161 pCurTcb->TCBprev = 0;
ericebert 0:57690853989a 162
ericebert 0:57690853989a 163 ptcb = pMutex->waittingList;
ericebert 0:57690853989a 164 if(ptcb == 0) /* If the event waiting list is empty */
ericebert 0:57690853989a 165 {
ericebert 0:57690853989a 166 pMutex->waittingList = pCurTcb; /* Insert the task to head */
ericebert 0:57690853989a 167 }
ericebert 0:57690853989a 168 else /* If the event waiting list is not empty */
ericebert 0:57690853989a 169 {
ericebert 0:57690853989a 170 while(ptcb->TCBnext != 0) /* Insert the task to tail */
ericebert 0:57690853989a 171 {
ericebert 0:57690853989a 172 ptcb = ptcb->TCBnext;
ericebert 0:57690853989a 173 }
ericebert 0:57690853989a 174 ptcb->TCBnext = pCurTcb;
ericebert 0:57690853989a 175 pCurTcb->TCBprev = ptcb;
ericebert 0:57690853989a 176 pCurTcb->TCBnext = 0;
ericebert 0:57690853989a 177 }
ericebert 0:57690853989a 178 }
ericebert 0:57690853989a 179 OsSchedUnlock();
ericebert 0:57690853989a 180 return E_OK;
ericebert 0:57690853989a 181 }
ericebert 0:57690853989a 182
ericebert 0:57690853989a 183
ericebert 0:57690853989a 184 /**
ericebert 0:57690853989a 185 *******************************************************************************
ericebert 0:57690853989a 186 * @brief Leave from a critical area
ericebert 0:57690853989a 187 * @param[in] mutexID Specify mutex id.
ericebert 0:57690853989a 188 * @param[out] None
ericebert 0:57690853989a 189 * @retval E_INVALID_ID Invalid mutex id.
ericebert 0:57690853989a 190 * @retval E_CALL Error call in ISR.
ericebert 0:57690853989a 191 * @retval E_OK Exit a critical area successful.
ericebert 0:57690853989a 192 *
ericebert 0:57690853989a 193 * @par Description
ericebert 0:57690853989a 194 * @details This function must be called when exiting from a critical area.
ericebert 0:57690853989a 195 * @note
ericebert 0:57690853989a 196 *******************************************************************************
ericebert 0:57690853989a 197 */
ericebert 0:57690853989a 198 StatusType CoLeaveMutexSection(OS_MutexID mutexID)
ericebert 0:57690853989a 199 {
ericebert 0:57690853989a 200 P_OSTCB ptcb;
ericebert 0:57690853989a 201 P_MUTEX pMutex;
ericebert 0:57690853989a 202 U8 prio;
ericebert 0:57690853989a 203 U8 taskID;
ericebert 0:57690853989a 204
ericebert 0:57690853989a 205 if(OSIntNesting > 0) /* If the caller is ISR */
ericebert 0:57690853989a 206 {
ericebert 0:57690853989a 207 return E_CALL;
ericebert 0:57690853989a 208 }
ericebert 0:57690853989a 209
ericebert 0:57690853989a 210 #if CFG_PAR_CHECKOUT_EN >0
ericebert 0:57690853989a 211 if(mutexID >= MutexFreeID)
ericebert 0:57690853989a 212 {
ericebert 0:57690853989a 213 return E_INVALID_ID; /* Invalid mutex id, return error */
ericebert 0:57690853989a 214 }
ericebert 0:57690853989a 215 #endif
ericebert 0:57690853989a 216 OsSchedLock();
ericebert 0:57690853989a 217 pMutex = &MutexTbl[mutexID]; /* Obtain point of mutex control block*/
ericebert 0:57690853989a 218 ptcb = &TCBTbl[pMutex->taskID];
ericebert 0:57690853989a 219 ptcb->mutexID = INVALID_ID;
ericebert 0:57690853989a 220 if(pMutex->waittingList == 0) /* If the mutex waiting list is empty */
ericebert 0:57690853989a 221 {
ericebert 0:57690853989a 222 pMutex->mutexFlag = MUTEX_FREE; /* The mutex resource is available */
ericebert 0:57690853989a 223 pMutex->taskID = INVALID_ID;
ericebert 0:57690853989a 224 OsSchedUnlock();
ericebert 0:57690853989a 225 }
ericebert 0:57690853989a 226 else /* If there is at least one task waitting for the mutex */
ericebert 0:57690853989a 227 {
ericebert 0:57690853989a 228 taskID = pMutex->taskID; /* Get task ID of mutex owner */
ericebert 0:57690853989a 229
ericebert 0:57690853989a 230 /* we havn't promoted current task's priority */
ericebert 0:57690853989a 231 if(pMutex->hipriTaskID == taskID)
ericebert 0:57690853989a 232 {
ericebert 0:57690853989a 233 ptcb = pMutex->waittingList;/* Point to mutex first waiting task */
ericebert 0:57690853989a 234 prio = ptcb->prio;
ericebert 0:57690853989a 235 while(ptcb != 0) /* Find the highest priority task */
ericebert 0:57690853989a 236 {
ericebert 0:57690853989a 237 if(ptcb->prio < prio)
ericebert 0:57690853989a 238 {
ericebert 0:57690853989a 239 prio = ptcb->prio;
ericebert 0:57690853989a 240 pMutex->hipriTaskID = ptcb->taskID;
ericebert 0:57690853989a 241 }
ericebert 0:57690853989a 242 ptcb = ptcb->TCBnext;
ericebert 0:57690853989a 243 }
ericebert 0:57690853989a 244 }
ericebert 0:57690853989a 245 else /* we have promoted current task's priority */
ericebert 0:57690853989a 246 {
ericebert 0:57690853989a 247 prio = TCBTbl[taskID].prio;
ericebert 0:57690853989a 248 }
ericebert 0:57690853989a 249
ericebert 0:57690853989a 250 /* Reset the task priority */
ericebert 0:57690853989a 251 pMutex->taskID = INVALID_ID;
ericebert 0:57690853989a 252 CoSetPriority(taskID,pMutex->originalPrio);
ericebert 0:57690853989a 253
ericebert 0:57690853989a 254 /* Find first task in waiting list ready to run */
ericebert 0:57690853989a 255 ptcb = pMutex->waittingList;
ericebert 0:57690853989a 256 pMutex->waittingList = ptcb->TCBnext;
ericebert 0:57690853989a 257 pMutex->originalPrio = ptcb->prio;
ericebert 0:57690853989a 258 pMutex->taskID = ptcb->taskID;
ericebert 0:57690853989a 259
ericebert 0:57690853989a 260 #if CFG_ORDER_LIST_SCHEDULE_EN ==0
ericebert 0:57690853989a 261 if(prio != ptcb->prio)
ericebert 0:57690853989a 262 {
ericebert 0:57690853989a 263 DeleteTaskPri(ptcb->prio);
ericebert 0:57690853989a 264 ActiveTaskPri(prio);
ericebert 0:57690853989a 265 }
ericebert 0:57690853989a 266 #endif
ericebert 0:57690853989a 267
ericebert 0:57690853989a 268 ptcb->prio = prio; /* Raise the task's priority */
ericebert 0:57690853989a 269
ericebert 0:57690853989a 270 /* Insert the task which acquire the mutex into ready list. */
ericebert 0:57690853989a 271 ptcb->TCBnext = 0;
ericebert 0:57690853989a 272 ptcb->TCBprev = 0;
ericebert 0:57690853989a 273
ericebert 0:57690853989a 274 InsertToTCBRdyList(ptcb); /* Insert the task into the READY list */
ericebert 0:57690853989a 275 OsSchedUnlock();
ericebert 0:57690853989a 276 }
ericebert 0:57690853989a 277 return E_OK;
ericebert 0:57690853989a 278 }
ericebert 0:57690853989a 279
ericebert 0:57690853989a 280 /**
ericebert 0:57690853989a 281 *******************************************************************************
ericebert 0:57690853989a 282 * @brief Remove a task from mutex waiting list
ericebert 0:57690853989a 283 * @param[in] ptcb TCB which will remove out.
ericebert 0:57690853989a 284 * @param[out] None
ericebert 0:57690853989a 285 * @retval None
ericebert 0:57690853989a 286 *
ericebert 0:57690853989a 287 * @par Description
ericebert 0:57690853989a 288 * @details This function be called when delete a task.
ericebert 0:57690853989a 289 * @note
ericebert 0:57690853989a 290 *******************************************************************************
ericebert 0:57690853989a 291 */
ericebert 0:57690853989a 292 void RemoveMutexList(P_OSTCB ptcb)
ericebert 0:57690853989a 293 {
ericebert 0:57690853989a 294 U8 prio;
ericebert 0:57690853989a 295 OS_TID taskID;
ericebert 0:57690853989a 296 P_MUTEX pMutex;
ericebert 0:57690853989a 297 pMutex = &MutexTbl[ptcb->mutexID];
ericebert 0:57690853989a 298
ericebert 0:57690853989a 299 /* If only one task waiting on mutex */
ericebert 0:57690853989a 300 if((ptcb->TCBnext ==0) && (ptcb->TCBprev == 0))
ericebert 0:57690853989a 301 {
ericebert 0:57690853989a 302 pMutex->waittingList = 0; /* Waiting list is empty */
ericebert 0:57690853989a 303 }
ericebert 0:57690853989a 304 else if(ptcb->TCBnext == 0) /* If the task is the last of waiting list*/
ericebert 0:57690853989a 305 {
ericebert 0:57690853989a 306 /* Remove task from mutex waiting list */
ericebert 0:57690853989a 307 ptcb->TCBprev->TCBnext = 0;
ericebert 0:57690853989a 308 ptcb->TCBprev = 0;
ericebert 0:57690853989a 309 }
ericebert 0:57690853989a 310 else if(ptcb->TCBprev == 0)/* If the task is the first of waiting list*/
ericebert 0:57690853989a 311 {
ericebert 0:57690853989a 312 /* Remove task from waiting list */
ericebert 0:57690853989a 313 ptcb->TCBnext->TCBprev = 0;
ericebert 0:57690853989a 314 ptcb->TCBnext = 0;
ericebert 0:57690853989a 315 }
ericebert 0:57690853989a 316 else /* If the task is in the middle of waiting list */
ericebert 0:57690853989a 317 {
ericebert 0:57690853989a 318 /* Remove task from wait list */
ericebert 0:57690853989a 319 ptcb->TCBnext->TCBprev = ptcb->TCBprev;
ericebert 0:57690853989a 320 ptcb->TCBprev->TCBnext = ptcb->TCBnext;
ericebert 0:57690853989a 321 ptcb->TCBprev = 0;
ericebert 0:57690853989a 322 ptcb->TCBnext = 0;
ericebert 0:57690853989a 323 }
ericebert 0:57690853989a 324
ericebert 0:57690853989a 325 ptcb->mutexID = INVALID_ID;
ericebert 0:57690853989a 326
ericebert 0:57690853989a 327 /* If the task have highest priority in mutex waiting list */
ericebert 0:57690853989a 328 if(pMutex->hipriTaskID == ptcb->taskID)
ericebert 0:57690853989a 329 {
ericebert 0:57690853989a 330 ptcb = pMutex->waittingList;
ericebert 0:57690853989a 331 prio = pMutex->originalPrio;
ericebert 0:57690853989a 332 pMutex->hipriTaskID = pMutex->taskID;
ericebert 0:57690853989a 333 while(ptcb != 0) /* Find task ID of highest priority task*/
ericebert 0:57690853989a 334 {
ericebert 0:57690853989a 335 if(ptcb->prio < prio)
ericebert 0:57690853989a 336 {
ericebert 0:57690853989a 337 prio = ptcb->prio;
ericebert 0:57690853989a 338 pMutex->hipriTaskID = ptcb->taskID;
ericebert 0:57690853989a 339 }
ericebert 0:57690853989a 340 ptcb = ptcb->TCBnext;
ericebert 0:57690853989a 341 }
ericebert 0:57690853989a 342 taskID = pMutex->taskID;
ericebert 0:57690853989a 343 pMutex->taskID = INVALID_ID;
ericebert 0:57690853989a 344 CoSetPriority(taskID,prio); /* Reset the mutex ower priority */
ericebert 0:57690853989a 345 pMutex->taskID = taskID;
ericebert 0:57690853989a 346 }
ericebert 0:57690853989a 347 }
ericebert 0:57690853989a 348
ericebert 0:57690853989a 349 #endif