/* * uLipeQueueDelete() */ OsStatus_t uLipeQueueDelete(OsHandler_t *h) { uint32_t sReg; QueuePtr_t q = (QueuePtr_t)h; //check arguments: if( h == (OsHandler_t *)NULL) { return(kInvalidParam); } //Argument valid, then proceed: OS_CRITICAL_IN(); //Assert all tasks pending the queue will be destroyed: QueueDeleteLoop(*h); uLipeMemFree(q->queueBase); uLipeMemFree(q); //Destroy the reference: h = (OsHandler_t *)NULL; q = NULL; OS_CRITICAL_OUT(); uLipeKernelTaskYield(); //All gone well: return(kStatusOk); }
/* * uLipeFlagsDelete() */ OsStatus_t uLipeFlagsDelete(OsHandler_t *h) { FlagsGrpPtr_t f = (FlagsGrpPtr_t)h; uint32_t sReg = 0; //Check argument: if(h == NULL) { return(kInvalidParam); } //valid argument, then proceed: OS_CRITICAL_IN(); //Assert all flag events before to destroy it: FlagsDeleteLoop(*h); uLipeMemFree(f); OS_CRITICAL_OUT(); //Destroy this handler: *h = 0 ; f = NULL; uLipeKernelTaskYield(); //All gone well: return(kStatusOk); }
/* * uLipeQueueFlush() */ OsStatus_t uLipeQueueFlush(OsHandler_t h) { uint32_t sReg; QueuePtr_t q = (QueuePtr_t)h; //check parameters: if(h == 0) { return(kInvalidParam); } //So flush queue: OS_CRITICAL_IN(); q->queueBack = 0; q->queueFront = 0; q->usedSlots = 0; //Update for all pending tasks: QueueRemoveLoop(h); QueueInsertLoop(h); //Queue flushed: OS_CRITICAL_OUT(); //schedule a new task (if needed): uLipeKernelTaskYield(); return(kStatusOk); }
/* * OsQueueDelete() */ OsStatus_t OsQueueDelete(OsQueuePtr_t queue) { #if OS_QUEUE_COUNT > 0 uint8_t ieReg; //checa argumentos: if (queue == NULL) return (kOsInvalidParam); //Libera qualquer evento associado a esse queue: OS_CRITICAL_IN(); OsQueueDeleteLoop(queue); //Devolve esse bloco: queue->queueTaken = FALSE; queueCount--; queue->queueData = NULL; //Destroi referencia desse queue. queue = NULL; OS_CRITICAL_OUT(); OsTaskYield(); #endif return (kOsStatusOk); }
/* * uLipeFlagsPost() */ OsStatus_t uLipeFlagsPost(OsHandler_t h, uint32_t flags) { FlagsGrpPtr_t f = (FlagsGrpPtr_t)h; uint32_t sReg = 0; //Check argument: if(h == 0) { return(kInvalidParam); } //Valid argument, proceed: OS_CRITICAL_IN(); //Assert the flags in register: f->flagRegister |= flags; //Run the PostLoop to update the tasks pending: FlagsPostLoop(h); OS_CRITICAL_OUT(); //Check for a context switch: uLipeKernelTaskYield(); //All gone well: return(kStatusOk); }
/* * uLipeFlagsCreate() */ OsHandler_t uLipeFlagsCreate(OsStatus_t *err) { uint32_t sReg = 0; FlagsGrpPtr_t f = uLipeMemAlloc(sizeof(FlagsGrp_t)); //Check if we have freeFlags: OS_CRITICAL_IN(); if(f == NULL) { OS_CRITICAL_OUT(); if(err != NULL) *err = kOutOfFlags; //Return a null handler: return((OsHandler_t)f); } f->activeList = 0; f->flagRegister = 0; f->waitTasks[0].prioGrp = 0; f->waitTasks[1].prioGrp = 0; OS_CRITICAL_OUT(); if(err != NULL)*err = kStatusOk; //All gone well. return((OsHandler_t)f); }
/* * uLipeQueueCreate() */ OsHandler_t uLipeQueueCreate(uint32_t slots, OsStatus_t *err) { uint32_t sReg = 0; QueuePtr_t q = uLipeMemAlloc(sizeof(Queue_t)); QueueData_t data_array = uLipeMemAlloc(sizeof(QueueData_t) * slots); //Valid arguments, then proceed: OS_CRITICAL_IN(); //Check for free blocks: if(q == NULL) { OS_CRITICAL_OUT(); if(err != NULL) *err = kOutOfQueue; return((OsHandler_t)NULL); } if(data_array == NULL) { OS_CRITICAL_OUT(); uLipeMemFree(q); if(err != NULL)*err = kInvalidParam; return((OsHandler_t)NULL); } //fill the control block: q->queueBase = data_array; q->numSlots = slots; q->queueBack = 0; q->queueFront = 0; q->usedSlots = 0; OS_CRITICAL_OUT(); if(err != NULL) *err = kStatusOk; //Return in handler form: return((OsHandler_t)q); }
/* * uLipeQueueCreate() */ OsHandler_t uLipeQueueCreate(QueueData_t *data, uint32_t size, OsStatus_t *err) { uint32_t sReg = 0; QueuePtr_t q; //Check arguments: if(data == NULL) { err = kInvalidParam; return((OsHandler_t)NULL); } //Valid arguments, then proceed: OS_CRITICAL_IN(); //Check for free blocks: if(queueFree == NULL) { OS_CRITICAL_OUT(); err = kOutOfQueue; return((OsHandler_t)NULL); } q = queueFree; //updates next queueFree: queueFree = queueFree->nextNode; OS_CRITICAL_OUT(); //fill the control block: q->queueBase = data; q->numSlots = size; q->queueBack = 0; q->queueFront = 0; q->usedSlots = 0; err = kStatusOk; //Return in handler form: return((OsHandler_t)q); }
/* * OsQueueGetStatus() */ OsStatus_t OsQueueGetStatus(OsQueuePtr_t queue, uint8_t *freeEntries) { #if OS_QUEUE_COUNT > 0 uint8_t ieReg; //checa argumentos: if(queue == NULL)return(kOsInvalidParam); //checa se a queue nao esta cheia: OS_CRITICAL_IN(); if(queue->queueCurrentEntries == queue->queueEntries) { OS_CRITICAL_OUT(); *freeEntries = 0; return(kOsQueueFull); } //se esta vazia: if(queue->queueCurrentEntries == 0) { OS_CRITICAL_OUT(); *freeEntries = queue->queueEntries; return(kOsQueueEmpty); } //entao pode esta com n-Entries livres: *freeEntries = (queue->queueEntries - queue->queueCurrentEntries); OS_CRITICAL_OUT(); #endif return(kOsStatusOk); }
/* * 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); }
/* * OsQueuePost() */ OsStatus_t OsQueuePost(OsQueuePtr_t queue, uint8_t *dataPtr, uint8_t sizeInBytes, uint8_t opt) { #if OS_QUEUE_COUNT > 0 uint8_t i; uint8_t ieReg; uint16_t queueBaseIndex; //checa argumentos: if (queue == NULL) return (kOsInvalidParam); if (dataPtr == NULL) return (kOsInvalidParam); if ((opt != OS_Q_POST_BLOCK_FULL) && (opt != OS_Q_NOT_BLOCK)) return (kOsInvalidParam); if (sizeInBytes > queue->queueDataSize) return (kOsTooManyData); OS_CRITICAL_IN(); //checa se ha espaço: if (queue->queueCurrentEntries == queue->queueEntries) { //checa se deve bloquear a task: if (opt != OS_Q_NOT_BLOCK) { //se for bloquear, entao retira a task corrente da lista de prontas: OsPrioClr(currentTask->prioVal, &osTaskList); currentTask->taskState &= ~(1 << kOsTaskRdy); currentTask->taskState |= (1 << kOsQueuePend); queue->tasksPending[currentTask->prioVal] = OS_Q_PENDING_FULL; OS_CRITICAL_OUT(); OsTaskYield(); return (kOsStatusOk); } else { OS_CRITICAL_OUT(); //se nao for bloquear entao notifioca que a queue esta cheia: return (kOsQueueFull); } } //Se temos espaço entao calcula o deslocamento dentro da area de dados: queueBaseIndex = (queue->queueCurrentFree * (queue->queueDataSize + 1)); queue->queueCurrentFree++; if(queue->queueCurrentFree == queue->queueEntries) { //Se houver espaço livre, faz wrap around: if(queue->queueCurrentEntries < queue->queueEntries) { queue->queueCurrentFree = 0; } } queue->queueCurrentEntries++; OS_CRITICAL_OUT(); //Deposita os dados: queue->queueData[queueBaseIndex] = sizeInBytes; queueBaseIndex++; for (i = 0; i < sizeInBytes; i++) { queue->queueData[queueBaseIndex++] = *dataPtr++; } //Depositou, notifica que a queue nao esta mais vaizia (se estiver) OS_CRITICAL_IN(); OsQueueFullLoop(queue); OS_CRITICAL_OUT(); OsTaskYield(); #endif return (kOsStatusOk); }
/* * OsQueuePend() */ OsStatus_t OsQueuePend(OsQueuePtr_t queue, uint8_t *dataPtr, uint8_t *sizeInBytes, uint8_t opt) { #if OS_QUEUE_COUNT > 0 uint8_t i,tmp; uint8_t ieReg; uint16_t queueBaseIndex; //checa argumentos: if (queue == NULL) return (kOsInvalidParam); if (dataPtr == NULL) return (kOsInvalidParam); if ((opt != OS_Q_PEND_BLOCK_EMPTY) && (opt != OS_Q_NOT_BLOCK)) return (kOsInvalidParam); OS_CRITICAL_IN(); //checa se a fifo da queue esta vazia: if (queue->queueCurrentEntries == 0) { //esta vazio, checa se deve bloquear: if (opt != OS_Q_NOT_BLOCK) { //sinaliza qual prio vai aguardar daddos na queue: queue->tasksPending[currentTask->prioVal] = OS_Q_PENDING_EMPTY; //Suspende execucao da task corrente: OsPrioClr(currentTask->prioVal, &osTaskList); currentTask->taskState &= ~(1 << kOsTaskRdy); currentTask->taskState |= (1 << kOsQueuePend); OS_CRITICAL_OUT(); //pede uma troca de contexto: OsTaskYield(); return (kOsStatusOk); } //Senao, apenas notifica que a queue esta vazia: else { OS_CRITICAL_OUT(); return (kOsQueueEmpty); } } //Se tem dado na queue, vamos retirar e copiar //para o endereço apontado por dataPtr: //calcula o deslocamento no vetor de dados: queueBaseIndex = ((queue->queueCurrentFront) * (queue->queueDataSize + 1)); queue->queueCurrentFront++; if(queue->queueCurrentFront > queue->queueEntries) { //A queue se comporta de forma circular desde que tenhamos slots livres queue->queueCurrentFront = 0; } queue->queueCurrentEntries--; OS_CRITICAL_OUT(); //Toma a quantidade de dados: tmp = queue->queueData[queueBaseIndex]; queueBaseIndex++; for (i = 0; i < tmp; i++) { //copia *dataPtr++ = queue->queueData[queueBaseIndex++]; } if(sizeInBytes != NULL) { *sizeInBytes = tmp; } OS_CRITICAL_IN(); OsQueueEmptyLoop(queue); OS_CRITICAL_OUT(); OsTaskYield(); #endif return (kOsStatusOk); }
/* * OsQueueCreate() */ OsQueuePtr_t OsQueueCreate(OsQueueData_t *dataPtr, uint8_t dataSize, uint8_t queueSize, uint8_t *err) { #if OS_QUEUE_COUNT > 0 uint8_t ieReg; uint8_t i; //checa argumentos: if (dataPtr == NULL) { *err = kOsInvalidParam; return (NULL ); } if (dataSize == 0) { *err = kOsInvalidParam; return (NULL ); } if (queueSize == 0) { *err = kOsInvalidParam; return (NULL ); } //checa se temos blocos livres: OS_CRITICAL_IN(); if (queueCount >= OS_QUEUE_COUNT) { OS_CRITICAL_OUT(); *err = kOsOutOfQueue; return (NULL); } //procura pelo primeiro bloco de queue livre: for (i = 0; i < OS_QUEUE_COUNT; i++) { if (queueBlockTbl[i].queueTaken != TRUE) { //achou livre queueBlockTbl[i].queueTaken = TRUE; queueCount++; break; } } OS_CRITICAL_OUT(); //Preenche restante do bloco de controle: queueBlockTbl[i].queueData = dataPtr; queueBlockTbl[i].queueDataSize = dataSize; queueBlockTbl[i].queueEntries = queueSize; //Primeiro bloco livre da queue é sempre o indice 0 queueBlockTbl[i].queueCurrentFree = 0; return ((OsQueuePtr_t) &queueBlockTbl[i]); #endif }
/* * 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); }
/* * 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); }