Published 03 Dec 2010, by
Eric Ebert
CoOS,
rtos
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <coocox.h>
00020
00021 #if CFG_FLAG_EN > 0
00022
00023 #define FLAG_MAX_NUM 32
00024 FCB FlagCrl = {0};
00025
00026
00027
00028 static void FlagBlock(P_FLAG_NODE pnode,U32 flags,U8 waitType);
00029 static P_FLAG_NODE RemoveFromLink(P_FLAG_NODE pnode);
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 OS_FlagID CoCreateFlag(BOOL bAutoReset,BOOL bInitialState)
00046 {
00047 U8 i;
00048 OsSchedLock ();
00049
00050 for(i=0;i<FLAG_MAX_NUM;i++)
00051 {
00052
00053 if((FlagCrl.flagActive &(1<<i)) == 0 )
00054 {
00055 FlagCrl.flagActive |= (1<<i);
00056 FlagCrl.flagRdy |= (bInitialState<<i);
00057 FlagCrl.resetOpt |= (bAutoReset<<i);
00058 OsSchedUnlock();
00059 return i ;
00060 }
00061 }
00062 OsSchedUnlock();
00063
00064 return E_CREATE_FAIL;
00065 }
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 StatusType CoDelFlag(OS_FlagID id,U8 opt)
00085 {
00086 P_FLAG_NODE pnode;
00087 P_FCB pfcb;
00088 pfcb = &FlagCrl;
00089 if(OSIntNesting > 0)
00090 {
00091 return E_CALL;
00092 }
00093 #if CFG_PAR_CHECKOUT_EN >0
00094 if((pfcb->flagActive &(1<<id)) == 0)
00095 {
00096 return E_INVALID_ID;
00097 }
00098 #endif
00099 OsSchedLock ();
00100 pnode = pfcb->headNode ;
00101
00102 while(pnode != 0)
00103 {
00104 if((pnode->waitFlags &(1<<id)) != 0)
00105 {
00106 if(opt == OPT_DEL_NO_PEND )
00107 {
00108 OsSchedUnlock();
00109 return E_TASK_WAITING;
00110 }
00111 else if (opt == OPT_DEL_ANYWAY )
00112 {
00113 if(pnode->waitType == OPT_WAIT_ALL )
00114 {
00115
00116 if( pnode->waitFlags == (1<<id) )
00117 {
00118
00119 pnode = RemoveFromLink(pnode);
00120 continue;
00121 }
00122 else
00123 {
00124 pnode->waitFlags &= ~(1<<id);
00125 }
00126 }
00127 else
00128 {
00129 pnode = RemoveFromLink(pnode);
00130 continue;
00131 }
00132 }
00133 }
00134 pnode = pnode->nextNode ;
00135 }
00136
00137
00138 pfcb->flagActive &= ~(1<<id);
00139 pfcb->flagRdy &= ~(1<<id);
00140 pfcb->resetOpt &= ~(1<<id);
00141 OsSchedUnlock();
00142 return E_OK;
00143 }
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 StatusType CoAcceptSingleFlag(OS_FlagID id)
00161 {
00162 P_FCB pfcb;
00163 pfcb = &FlagCrl;
00164 #if CFG_PAR_CHECKOUT_EN >0
00165 if(id >= FLAG_MAX_NUM)
00166 {
00167 return E_INVALID_ID;
00168 }
00169 if((pfcb->flagActive &(1<<id)) == 0)
00170 {
00171 return E_INVALID_ID;
00172 }
00173 #endif
00174 if((pfcb->flagRdy &(1<<id)) != 0)
00175 {
00176 OsSchedLock ()
00177 pfcb->flagRdy &= ~((FlagCrl.resetOpt)&(1<<id));
00178 OsSchedUnlock();
00179 return E_OK;
00180 }
00181 else
00182 {
00183 return E_FLAG_NOT_READY;
00184 }
00185 }
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202 U32 CoAcceptMultipleFlags(U32 flags,U8 waitType,StatusType *perr)
00203 {
00204 U32 springFlag;
00205 P_FCB pfcb;
00206 pfcb = &FlagCrl;
00207
00208 #if CFG_PAR_CHECKOUT_EN >0
00209 if((flags&pfcb->flagActive ) != flags )
00210 {
00211 *perr = E_INVALID_PARAMETER;
00212 return 0;
00213 }
00214 #endif
00215
00216 springFlag = flags & pfcb->flagRdy ;
00217
00218 OsSchedLock ();
00219
00220 if( (springFlag != 0) && (waitType == OPT_WAIT_ANY ) )
00221 {
00222
00223 pfcb->flagRdy &= ~(springFlag & pfcb->resetOpt );
00224 OsSchedUnlock();
00225 *perr = E_OK;
00226 return springFlag;
00227 }
00228
00229
00230 if((springFlag == flags) && (waitType == OPT_WAIT_ALL ))
00231 {
00232 pfcb->flagRdy &= ~(springFlag&pfcb->resetOpt );
00233 OsSchedUnlock();
00234 *perr = E_OK;
00235 return springFlag;
00236 }
00237 OsSchedUnlock();
00238 *perr = E_FLAG_NOT_READY;
00239 return 0;
00240 }
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266 StatusType CoWaitForSingleFlag(OS_FlagID id,U32 timeout)
00267 {
00268 FLAG_NODE flagNode;
00269 P_FCB pfcb;
00270 P_OSTCB curTCB;
00271
00272 if(OSIntNesting > 0)
00273 {
00274 return E_CALL;
00275 }
00276 if(OSSchedLock != 0)
00277 {
00278 return E_OS_IN_LOCK;
00279 }
00280
00281 #if CFG_PAR_CHECKOUT_EN >0
00282 if(id >= FLAG_MAX_NUM)
00283 {
00284 return E_INVALID_ID;
00285 }
00286 if((FlagCrl.flagActive &(1<<id)) == 0 )
00287 {
00288 return E_INVALID_ID;
00289 }
00290 #endif
00291
00292 OsSchedLock ();
00293 pfcb = &FlagCrl;
00294
00295 if((pfcb->flagRdy &(1<<id)) != 0)
00296 {
00297 pfcb->flagRdy &= ~((pfcb->resetOpt &(1<<id)));
00298 OsSchedUnlock();
00299 }
00300 else
00301 {
00302 curTCB = TCBRunning ;
00303 if(timeout == 0)
00304 {
00305
00306 FlagBlock (&flagNode,(1<<id),OPT_WAIT_ONE );
00307 curTCB->state = TASK_WAITING ;
00308 TaskSchedReq = TRUE;
00309 OsSchedUnlock();
00310
00311
00312 curTCB->pnode = 0;
00313 OsSchedLock ();
00314
00315
00316 pfcb->flagRdy &= ~((1<<id)&(pfcb->resetOpt ));
00317 OsSchedUnlock();
00318 }
00319 else
00320 {
00321
00322 FlagBlock(&flagNode,(1<<id),OPT_WAIT_ONE );
00323 InsertDelayList(curTCB,timeout);
00324
00325 OsSchedUnlock();
00326 if(curTCB->pnode == 0)
00327 {
00328 return E_TIMEOUT;
00329 }
00330 else
00331 {
00332 curTCB->pnode = 0;
00333 OsSchedLock ();
00334
00335
00336 pfcb->flagRdy &= ~((1<<id)&(pfcb->resetOpt ));
00337 OsSchedUnlock();
00338 }
00339 }
00340 }
00341 return E_OK;
00342 }
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 U32 CoWaitForMultipleFlags(U32 flags,U8 waitType,U32 timeout,StatusType *perr)
00361 {
00362 U32 springFlag;
00363 P_FCB pfcb;
00364 FLAG_NODE flagNode;
00365 P_OSTCB curTCB;
00366
00367
00368 if(OSIntNesting > 0)
00369 {
00370 *perr = E_CALL;
00371 return 0;
00372 }
00373 if(OSSchedLock != 0)
00374 {
00375 *perr = E_OS_IN_LOCK;
00376 return 0;
00377 }
00378 #if CFG_PAR_CHECKOUT_EN >0
00379 if( (flags&FlagCrl.flagActive ) != flags )
00380 {
00381 *perr = E_INVALID_PARAMETER;
00382 return 0;
00383 }
00384 #endif
00385 OsSchedLock ();
00386 pfcb = &FlagCrl;
00387 springFlag = flags & pfcb->flagRdy ;
00388
00389
00390 if((springFlag != 0) && (waitType == OPT_WAIT_ANY ))
00391 {
00392 pfcb->flagRdy &= ~(springFlag & pfcb->resetOpt );
00393 OsSchedUnlock();
00394 *perr = E_OK;
00395 return springFlag;
00396 }
00397
00398
00399 if( (springFlag == flags) && (waitType == OPT_WAIT_ALL ) )
00400 {
00401 pfcb->flagRdy &= ~(springFlag & pfcb->resetOpt );
00402 OsSchedUnlock();
00403 *perr = E_OK;
00404 return springFlag;
00405 }
00406
00407 curTCB = TCBRunning ;
00408 if(timeout == 0)
00409 {
00410
00411 FlagBlock(&flagNode,flags,waitType);
00412 curTCB->state = TASK_WAITING ;
00413 TaskSchedReq = TRUE;
00414 OsSchedUnlock();
00415
00416 curTCB->pnode = 0;
00417 OsSchedLock ();
00418 springFlag = flags & pfcb->flagRdy ;
00419 pfcb->flagRdy &= ~(springFlag & pfcb->resetOpt );
00420 OsSchedUnlock();
00421 *perr = E_OK;
00422 return springFlag;
00423 }
00424 else
00425 {
00426
00427 FlagBlock(&flagNode,flags,waitType);
00428 InsertDelayList(curTCB,timeout);
00429
00430 OsSchedUnlock();
00431 if(curTCB->pnode == 0)
00432 {
00433 *perr = E_TIMEOUT;
00434 return 0;
00435 }
00436 else
00437 {
00438 curTCB->pnode = 0;
00439 OsSchedLock ();
00440 springFlag = flags & FlagCrl.flagRdy ;
00441
00442
00443 pfcb->flagRdy &= ~(springFlag & pfcb->resetOpt );
00444 OsSchedUnlock();
00445 *perr = E_OK;
00446 return springFlag;
00447 }
00448 }
00449 }
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 StatusType CoClearFlag(OS_FlagID id)
00467 {
00468 P_FCB pfcb;
00469 pfcb = &FlagCrl;
00470 #if CFG_PAR_CHECKOUT_EN >0
00471 if(id >= FLAG_MAX_NUM)
00472 {
00473 return E_INVALID_ID;
00474 }
00475 if((pfcb->flagActive &(1<<id)) == 0)
00476 {
00477 return E_INVALID_ID;
00478 }
00479 #endif
00480
00481 pfcb->flagRdy &= ~(1<<id);
00482 return E_OK;
00483 }
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499 StatusType CoSetFlag(OS_FlagID id)
00500 {
00501 P_FLAG_NODE pnode;
00502 P_FCB pfcb;
00503 pfcb = &FlagCrl;
00504
00505 #if CFG_PAR_CHECKOUT_EN >0
00506 if(id >= FLAG_MAX_NUM)
00507 {
00508 return E_INVALID_ID;
00509 }
00510 if((pfcb->flagActive &(1<<id)) == 0)
00511 {
00512 return E_INVALID_ID;
00513 }
00514 #endif
00515
00516 if((pfcb->flagRdy &(1<<id)) != 0)
00517 {
00518 return E_OK;
00519 }
00520
00521 pfcb->flagRdy |= (1<<id);
00522
00523 OsSchedLock ();
00524 pnode = pfcb->headNode ;
00525 while(pnode != 0)
00526 {
00527 if(pnode->waitType == OPT_WAIT_ALL )
00528 {
00529 if((pnode->waitFlags &pfcb->flagRdy ) == pnode->waitFlags )
00530 {
00531
00532 pnode = RemoveFromLink(pnode);
00533 if((pfcb->resetOpt &(1<<id)) != 0)
00534 {
00535 break;
00536 }
00537 continue;
00538 }
00539 }
00540 else
00541 {
00542 if( (pnode->waitFlags & pfcb->flagRdy ) != 0)
00543 {
00544
00545 pnode = RemoveFromLink(pnode);
00546 if((pfcb->resetOpt &(1<<id)) != 0)
00547 {
00548 break;
00549 }
00550 continue;
00551 }
00552 }
00553 pnode = pnode->nextNode ;
00554 }
00555 OsSchedUnlock();
00556 return E_OK;
00557 }
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574 #if CFG_MAX_SERVICE_REQUEST > 0
00575 StatusType isr_SetFlag(OS_FlagID id)
00576 {
00577 if(OSSchedLock > 0)
00578 {
00579
00580 if(InsertInSRQ(FLAG_REQ,id,0) == FALSE)
00581 {
00582 return E_SEV_REQ_FULL;
00583 }
00584 else
00585 {
00586 return E_OK;
00587 }
00588 }
00589 else
00590 {
00591 return(CoSetFlag(id));
00592 }
00593 }
00594 #endif
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610 static void FlagBlock(P_FLAG_NODE pnode,U32 flags,U8 waitType)
00611 {
00612 P_FCB pfcb;
00613 pfcb = &FlagCrl;
00614
00615 TCBRunning ->pnode = pnode;
00616 pnode->waitTask = TCBRunning ;
00617 pnode->waitFlags = flags;
00618 pnode->waitType = waitType;
00619
00620 if(pfcb->tailNode == 0)
00621 {
00622 pnode->nextNode = 0;
00623 pnode->prevNode = 0;
00624 pfcb->headNode = pnode;
00625 }
00626 else
00627 {
00628 pfcb->tailNode ->nextNode = pnode;
00629 pnode->prevNode = pfcb->tailNode ;
00630 pnode->nextNode = 0;
00631 }
00632 pfcb->tailNode = pnode;
00633 }
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648 static P_FLAG_NODE RemoveFromLink(P_FLAG_NODE pnode)
00649 {
00650 P_OSTCB ptcb;
00651
00652 RemoveLinkNode(pnode);
00653 ptcb = pnode->waitTask ;
00654
00655
00656 if(ptcb->delayTick != INVALID_VALUE)
00657 {
00658 RemoveDelayList(ptcb);
00659 }
00660
00661 ptcb->pnode = (void*)0xffffffff;
00662
00663 if(ptcb == TCBRunning )
00664 {
00665 ptcb->state = TASK_RUNNING ;
00666 }
00667 else
00668 {
00669 InsertToTCBRdyList(ptcb);
00670 }
00671 return (pnode->nextNode );
00672 }
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686 void RemoveLinkNode(P_FLAG_NODE pnode)
00687 {
00688
00689 if((pnode->nextNode == 0) && (pnode->prevNode == 0))
00690 {
00691 FlagCrl.headNode = 0;
00692 FlagCrl.tailNode = 0;
00693 }
00694 else if(pnode->nextNode == 0)
00695 {
00696 FlagCrl.tailNode = pnode->prevNode ;
00697 pnode->prevNode ->nextNode = 0;
00698 }
00699 else if(pnode->prevNode == 0)
00700 {
00701 FlagCrl.headNode = pnode->nextNode ;
00702 pnode->nextNode ->prevNode = 0;
00703 }
00704 else
00705 {
00706 pnode->nextNode ->prevNode = pnode->prevNode ;
00707 pnode->prevNode ->nextNode = pnode->nextNode ;
00708 }
00709 pnode->waitTask ->pnode = 0;
00710 }
00711
00712 #endif