/* * QueueDeleteLoop() * * Internal function, used to assert all tasks waiting for any event related * to queue when a kernel object is about to be destroyed * */ inline static void QueueDeleteLoop(OsHandler_t h) { QueuePtr_t q = (QueuePtr_t)h; uint32_t i = 0, j = 0; //remove out all tasks of all wait lists: while((q->queueSlotWait.prioGrp != 0)&&(q->queueInsertWait.prioGrp != 0)) { //Remove for priority order: i = uLipeKernelFindHighPrio(&q->queueSlotWait); j = uLipeKernelFindHighPrio(&q->queueInsertWait); uLipePrioClr(i, &q->queueSlotWait); uLipePrioClr(j, &q->queueInsertWait); //Set these tasks as ready: //make this task ready: tcbPtrTbl[i]->taskStatus &= ~(1 << kTaskPendQueue); if(tcbPtrTbl[i]->taskStatus == 0) { uLipePrioSet(i, &taskPrioList); } //make this task ready: tcbPtrTbl[j]->taskStatus &= ~(1 << kTaskPendQueue); if(tcbPtrTbl[j]->taskStatus == 0) { uLipePrioSet(j, &taskPrioList); } } }
/* * QueueDeleteLoop() * * Internal function, used to assert all tasks waiting for any event related * to queue when a kernel object is about to be destroyed * */ inline static void QueueDeleteLoop(OsHandler_t h) { QueuePtr_t q = (QueuePtr_t)h; uint32_t i = 0, j = 0; #if OS_USE_DEPRECATED == 1 for(i = 0; i < OS_NUMBER_OF_TASKS; i++) { //check for tasks waiting for slot free: if(q->tasksPending[i] != OS_Q_PEND_NOT) { //make this task ready: tcbPtrTbl[i]->taskStatus = (1 << kTaskReady); uLipePrioSet(i, &taskPrioList); } //remove this task from wait list: q->tasksPending[i] = OS_Q_PEND_NOT; } #else //remove out all tasks of all wait lists: while((q->queueSlotWait.prioGrp != 0)&&(q->queueInsertWait.prioGrp != 0)) { //Remove for priority order: i = uLipeFindHighPrio(&q->queueSlotWait); j = uLipeFindHighPrio(&q->queueInsertWait); uLipePrioClr(i, &q->queueSlotWait); uLipePrioClr(j, &q->queueInsertWait); //Set these tasks as ready: tcbPtrTbl[i]->taskStatus = (1 << kTaskReady); uLipePrioSet(i, &taskPrioList); tcbPtrTbl[j]->taskStatus = (1 << kTaskReady); uLipePrioSet(j, &taskPrioList); } #endif }
/* * QueueRemoveLoop() * * Internal function, used to process all tasks that waiting to at least * one slot became free, when a slot had its data removed * */ inline static void QueueRemoveLoop(OsHandler_t h) { QueuePtr_t q = (QueuePtr_t)h; uint32_t i = 0; #if OS_USE_DEPRECATED == 1 for(i = 0; i < OS_NUMBER_OF_TASKS; i++) { //check for tasks waiting for slot free: if(q->tasksPending[i] == OS_Q_PEND_FULL) { //make this task ready: tcbPtrTbl[i]->taskStatus = (1 << kTaskReady); uLipePrioSet(i, &taskPrioList); //remove this task from wait list: q->tasksPending[i] = OS_Q_PEND_NOT; } } #else //extract the highest priority task which waits for a slot: i = (uint16_t)uLipeFindHighPrio(&q->queueSlotWait); //valid prio? if(i != 0) { //Remove task from wait list: uLipePrioClr(i, &q->queueSlotWait); //make this task ready: tcbPtrTbl[i]->taskStatus = (1 << kTaskReady); uLipePrioSet(i, &taskPrioList); } #endif }
inline static void FlagsDeleteLoop(OsHandler_t h) { FlagsGrpPtr_t f = (FlagsGrpPtr_t)h; uint16_t i = 0; i = uLipeKernelFindHighPrio(&f->waitTasks[f->activeList]); while( i != 0) { //make this task ready: tcbPtrTbl[i]->taskStatus &= ~((1 << kTaskPendFlagAll) | (1 << kTaskPendFlagAny) | (1 << kTaskPenFlagConsume)); if(tcbPtrTbl[i]->taskStatus == 0) uLipePrioSet(i, &taskPrioList); i = uLipeKernelFindHighPrio(&f->waitTasks[f->activeList]); uLipePrioClr(i, &f->waitTasks[f->activeList]); } }
/* * QueueInsertLoop() * * Internal function, used to proccess all tasks that waiting to at least * one slot became filled, when a slot had is space filled of data */ inline static void QueueInsertLoop(OsHandler_t h) { QueuePtr_t q = (QueuePtr_t)h; uint32_t i = 0; //extract the highest priority task which waits for a slot: i = (uint16_t)uLipeKernelFindHighPrio(&q->queueInsertWait); //valid prio? if(i != 0) { //Remove task from wait list: uLipePrioClr(i, &q->queueInsertWait); //make this task ready: tcbPtrTbl[i]->taskStatus &= ~((1 << kTaskPendQueue)|(1 << kTaskPendDelay)); if(tcbPtrTbl[i]->taskStatus == 0) { uLipePrioSet(i, &taskPrioList); } } }
/* * uLipeQueueRemove() */ void *uLipeQueueRemove(OsHandler_t h, uint8_t opt, uint16_t timeout, OsStatus_t *err) { QueuePtr_t q = (QueuePtr_t)h; uint32_t sReg = 0; void *ptr = NULL; //check arguments: if(q == 0) { if(err != NULL )*err = kInvalidParam ; return(NULL); } //Arguments valid, then proceed: OS_CRITICAL_IN(); //Check queue status first: if(q->usedSlots == 0) { OS_CRITICAL_OUT(); //Queue full, check options: switch(opt) { case OS_Q_BLOCK_EMPTY: { //task will block so: OS_CRITICAL_IN(); uLipePrioClr(currentTask->taskPrio, &taskPrioList); //prepare task to wait currentTask->taskStatus |= (1 << kTaskPendQueue); if(timeout != 0) { currentTask->taskStatus |= (1 << kTaskPendDelay); currentTask->delayTime = timeout; uLipePrioSet(currentTask->taskPrio, &timerPendingList.list[timerPendingList.activeList]); } //Adds task to wait list: currentTask->queueBmp = &q->queueInsertWait; uLipePrioSet(currentTask->taskPrio, &q->queueInsertWait); OS_CRITICAL_OUT(); //So check for a context switch: uLipeKernelTaskYield(); if(err != NULL )*err = kQueueEmpty; return(ptr); } break; case OS_Q_NON_BLOCK: { if(q->usedSlots != 0) break; else { OS_CRITICAL_OUT(); if(err != NULL )*err = kQueueEmpty; return(ptr); } } break; default: { //All other cases, only return: if(err != NULL )*err = kQueueEmpty; return(ptr); } break; } } //queue holds data, so remove it: ptr = (void *) q->queueBase[q->queueBack]; q->queueBack++; //queue bevahes as circular FIFO fashion if(q->queueBack > (q->numSlots - 1)) { q->queueBack = 0; } //Update the number of used slots: q->usedSlots--; //Update tasks wich pend this queue: QueueRemoveLoop(h); OS_CRITICAL_OUT(); //Check for context switching: uLipeKernelTaskYield(); if(err != NULL )*err = kStatusOk; //All gone well: return(ptr); }
/* * uLipeQueueInsert() */ OsStatus_t uLipeQueueInsert(OsHandler_t h, void *data, uint8_t opt, uint16_t timeout) { QueuePtr_t q = (QueuePtr_t)h; uint32_t sReg = 0; //check arguments: if(data == NULL) { return(kInvalidParam); } if(q == 0) { return(kInvalidParam); } //Arguments valid, proceed then: OS_CRITICAL_IN(); //Before insert, check queue status: if(q->usedSlots >= q->numSlots) { OS_CRITICAL_OUT(); //Queue full, check options: switch(opt) { case OS_Q_BLOCK_FULL: { //suspend current task: uLipePrioClr(currentTask->taskPrio, &taskPrioList); currentTask->taskStatus |= (1 << kTaskPendQueue); if(timeout != 0) { currentTask->taskStatus |= (1 << kTaskPendDelay); currentTask->delayTime = timeout; uLipePrioSet(currentTask->taskPrio, &timerPendingList.list[timerPendingList.activeList]); } currentTask->queueBmp = &q->queueSlotWait; //Adds task to wait list: uLipePrioSet(currentTask->taskPrio, &q->queueSlotWait); OS_CRITICAL_OUT(); //So check for a context switch: uLipeKernelTaskYield(); return(kQueueFull); } break; case OS_Q_NON_BLOCK: { if(q->usedSlots < q->numSlots) break; else { OS_CRITICAL_OUT(); return(kQueueFull); } } break; default: { OS_CRITICAL_OUT(); return(kQueueFull); } break; } } //freespace, Insert the data pointer on queue: q->queueBase[q->queueFront] = (void *)data; q->queueFront++; //queue behaves as a circular FIFO fashion: if(q->queueFront > (q->numSlots - 1)) { q->queueFront = 0; } //update number of used slots q->usedSlots++; //Run insertion update loop: QueueInsertLoop(h); OS_CRITICAL_OUT(); //check for a context switch: uLipeKernelTaskYield(); //All gone ok: return(kStatusOk); }
/* * uLipeQueueRemove() */ void *uLipeQueueRemove(OsHandler_t h, uint8_t opt, uint16_t timeout, OsStatus_t *err) { uint32_t sReg = 0; QueuePtr_t q = (QueuePtr_t)h; void *ptr = NULL; //check arguments: if(h == NULL) { return(kInvalidParam); } //Arguments valid, then proceed: OS_CRITICAL_IN(); //Check queue status first: if(q->usedSlots == 0) { OS_CRITICAL_OUT(); //Queue full, check options: switch(opt) { case OS_Q_BLOCK_EMPTY: { //task will block so: OS_CRITICAL_IN(); //suspend current task: uLipePrioClr(currentTask->taskPrio, &taskPrioList); currentTask->taskStatus = (1 << kTaskPendQueue) | (1 << kTaskPendDelay); currentTask->delayTime = timeout; #if OS_USE_DEPRECATED == 1 //Assert this task on queue wait list: q->tasksPending[currentTask->taskPrio] = OS_Q_PEND_EMPTY; #else //Adds task to wait list: uLipePrioSet(currentTask->taskPrio, &q->queueInsertWait); #endif OS_CRITICAL_OUT(); //So check for a context switch: uLipeKernelTaskYield(); *err = kQueueEmpty; return(ptr); } break; default: { //All other cases, only return: *err = kQueueEmpty; return(ptr); } break; } } //queue holds data, so remove it: ptr = (void *) q->queueBase[q->queueBack]; q->queueBack++; //queue bevahes as circular FIFO fashion if(q->queueBack > (q->numSlots - 1)) { q->queueBack = 0; } //Update the number of used slots: q->usedSlots--; //Update tasks wich pend this queue: QueueRemoveLoop(h); OS_CRITICAL_OUT(); //Check for context switching: uLipeKernelTaskYield(); *err = kStatusOk; //All gone well: return(ptr); }
/* * FlagsPostLoop() * Internal, used to process when all tasks when a flag is asserted */ inline static void FlagsPostLoop(OsHandler_t h) { FlagsGrpPtr_t f = (FlagsGrpPtr_t)h; uint16_t i = 0; uint16_t match = FALSE; uint32_t mask = 0; uint16_t tmp = 0; //Search for a match flags: i = uLipeKernelFindHighPrio(&f->waitTasks[f->activeList]); while(i != 0) { //check for pend type of this task: switch(tcbPtrTbl[i]->taskStatus & ((1 << kTaskPendFlagAll) | (1 << kTaskPendFlagAny))) { case (1 << kTaskPendFlagAll): { //Only match if all specific flags are set mask = f->flagRegister & tcbPtrTbl[i]->flagsPending; if(mask == tcbPtrTbl[i]->flagsPending) { match = TRUE; tcbPtrTbl[i]->taskStatus &= ~((1 << kTaskPendFlagAll | (1 << kTaskPendDelay)) ); } } break; case (1 << kTaskPendFlagAny): { //Match if any of flags are set mask = f->flagRegister; if(mask != 0) { match = TRUE; tcbPtrTbl[i]->taskStatus &= ~((1 << kTaskPendFlagAny | (1 << kTaskPendDelay)) ); } } break; default: match = FALSE; //task waiting nothing break; } //match ocurred? if(match != FALSE) { //Assert a false for next loop match = FALSE; //Check if this assert will consume flags: if(tcbPtrTbl[i]->taskStatus & (1 << kTaskPenFlagConsume)) { //clear these flags tmp |= mask; tcbPtrTbl[i]->taskStatus &= ~(1 << kTaskPenFlagConsume) ; //If we had a consume event, so clear these flags; f->flagRegister &= ~(tmp); } //Make this task as ready: if(tcbPtrTbl[i]->taskStatus == 0) { uLipePrioSet(i, &taskPrioList); } } else { /* ensure this flag is waiting for flags */ if(tcbPtrTbl[i]->taskStatus & ((1 << kTaskPendFlagAll) | (1 << kTaskPendFlagAny))) { uLipePrioSet(i, &f->waitTasks[f->activeList ^ 0x01]); } } i = uLipeKernelFindHighPrio(&f->waitTasks[f->activeList]); uLipePrioClr(i, &f->waitTasks[f->activeList]); } /* swap to new active list */ f->activeList ^= 0x01; }
/* * uLipeFlagsPend() */ OsStatus_t uLipeFlagsPend(OsHandler_t h, uint32_t flags, uint8_t opt, uint16_t timeout) { uint32_t sReg = 0; uint32_t mask = 0; uint16_t match = FALSE; FlagsGrpPtr_t f = (FlagsGrpPtr_t)h; //Check for valid handler if(h == 0) { return(kInvalidParam); } OS_CRITICAL_IN(); //Check if this task already asserted: mask = f->flagRegister & currentTask->flagsPending; //check the pend type: switch(opt & ~(OS_FLAGS_CONSUME)) { case OS_FLAGS_PEND_ALL: { if(mask != flags) { currentTask->taskStatus |= (1 << kTaskPendFlagAll); //check if wants to consume: if(opt & OS_FLAGS_CONSUME) { currentTask->taskStatus |= (1 << kTaskPenFlagConsume); } } else { if(opt & OS_FLAGS_CONSUME) { f->flagRegister &= ~currentTask->flagsPending; } //The flags of this task is already asserted match = TRUE; } } break; case OS_FLAGS_PEND_ANY: { if(f->flagRegister == 0x0000000) { currentTask->taskStatus |= (1 << kTaskPendFlagAny); //check if wants to consume: if(opt & OS_FLAGS_CONSUME) { currentTask->taskStatus |= (1 << kTaskPenFlagConsume); } } else { if(opt & OS_FLAGS_CONSUME) { f->flagRegister = 0; } //Any flags of this task was already assert match = TRUE; } } break; default: { //Invalid option, return with error: OS_CRITICAL_OUT(); return(kInvalidParam); } } //check for match: if(match != FALSE) { //Only return, without suspend task: OS_CRITICAL_OUT(); return(kStatusOk); } //Set the flags: currentTask->flagsPending |= flags; //if not, then suspend task: uLipePrioClr(currentTask->taskPrio, &taskPrioList); uLipePrioSet(currentTask->taskPrio, &f->waitTasks[f->activeList]); currentTask->flagsBmp = &f->waitTasks[0]; //adds the timeout if(timeout != 0) { currentTask->delayTime = timeout; currentTask->taskStatus |= (1 << kTaskPendDelay); uLipePrioSet(currentTask->taskPrio, &timerPendingList.list[timerPendingList.activeList]); } OS_CRITICAL_OUT(); //Check for a context switch: uLipeKernelTaskYield(); //all gone well: return(kStatusOk); }