/** \fn TIMER_CNT BRTOS_TimerGet (BRTOS_TIMER p) \brief public function to get remaining time of a soft timer \param p soft timer \return timeout value or "0" as error code */ TIMER_CNT OSTimerGet (BRTOS_TIMER p) { OS_SR_SAVE_VAR TIMER_CNT timeout; TIMER_CNT tickcount; if((p!= NULL) && (p->state == TIMER_RUNNING)) { if (currentTask) OSEnterCritical(); tickcount = OSGetCount(); if(p->timeout >= tickcount) { timeout = (TIMER_CNT)(p->timeout - tickcount); } else { timeout = (TIMER_CNT)(TIMER_MAX_COUNTER - tickcount + p->timeout + 1); } if (currentTask) OSExitCritical(); return timeout; } return 0; /* "0" null event pointer or timer not running */ }
INT8U OSTimerStop (BRTOS_TIMER p, INT8U del){ OS_SR_SAVE_VAR BRTOS_TMR_T* list; INT8U pos_timer = 0; if(p != NULL) { if (currentTask) OSEnterCritical(); if(p->timeout >= OSGetCount()) { list = BRTOS_TIMER_VECTOR.current; // remove from current list } else { list = BRTOS_TIMER_VECTOR.future; // remove from future list } /* search timer index */ p->state = TIMER_SEARCH; for(pos_timer = 1; pos_timer <= list->count; pos_timer++) { if(list->timers[pos_timer]->state == TIMER_SEARCH) { break; } } p->timeout = 0; Subir (list->timers, pos_timer); // order it list->timers[1]=list->timers[list->count]; // remove from current list list->timers[list->count] = NULL; list->count--; Descer (list->timers, 1, list->count); // order it if(del > 0) { p->state = TIMER_NOT_ALLOCATED; p->func_cb = NULL; } else { p->state = TIMER_STOPPED; } if (currentTask) OSExitCritical(); return OK; } return NULL_EVENT_POINTER; }
/** \fn INT8U BRTOS_TimerStart (BRTOS_TIMER p, TIMER_CNT time_wait) \brief public function to start or restart a soft timer \param p soft timer \param time_wait soft timer expiration time \return OK success \return NULL_EVENT_POINTER error code */ INT8U OSTimerStart (BRTOS_TIMER p, TIMER_CNT time_wait){ OS_SR_SAVE_VAR INT32U timeout; BRTOS_TMR_T* list; if(p!= NULL && time_wait != 0) { if(time_wait> TIMER_MAX_COUNTER) time_wait = TIMER_MAX_COUNTER; if (currentTask) OSEnterCritical(); if(time_wait > 0) { timeout = (INT32U)((INT32U)OSGetCount() + (INT32U)time_wait); if (timeout >= TICK_COUNT_OVERFLOW) { p->timeout = (TIMER_CNT)(timeout - TICK_COUNT_OVERFLOW); list = BRTOS_TIMER_VECTOR.future; // add into future list list->timers[++list->count] = p; // insert in the end Subir (list->timers, list->count); // order it } else { p->timeout = (TIMER_CNT)timeout; list = BRTOS_TIMER_VECTOR.current; // add into current list list->timers[++list->count] = p; // insert in the end Subir (list->timers, list->count); // order it // may need to change wake time of timer task if(currentTask) { if(p->timeout == (list->timers[1])->timeout) { ContextTask[BRTOS_TIMER_VECTOR.handling_task].TimeToWait = p->timeout; } } } p->state = TIMER_RUNNING; } if (currentTask) OSExitCritical(); return OK; } return NULL_EVENT_POINTER; /* any error number */ }
INT8U OSSemPend (BRTOS_Sem *pont_event, INT16U time_wait) { OS_SR_SAVE_VAR INT8U iPriority = 0; INT32U timeout; ContextType *Task; #if (ERROR_CHECK == 1) // Can not use semaphore pend function from interrupt handling code if(iNesting > 0) { return(IRQ_PEND_ERR); } // Verifies if the pointer is NULL if(pont_event == NULL) { return(NULL_EVENT_POINTER); } #endif // Enter Critical Section OSEnterCritical(); #if (ERROR_CHECK == 1) // Verifies if the event is allocated if(pont_event->OSEventAllocated != TRUE) { // Exit Critical Section OSExitCritical(); return(ERR_EVENT_NO_CREATED); } #endif // BRTOS TRACE SUPPORT #if (OSTRACE == 1) #if(OS_TRACE_BY_TASK == 1) Update_OSTrace(currentTask, SEMPEND); #else Update_OSTrace(ContextTask[currentTask].Priority, SEMPEND); #endif #endif // Verify if there was a post if (pont_event->OSEventCount > 0) { // Decreases semaphore count pont_event->OSEventCount--; // Exit Critical Section OSExitCritical(); return OK; } Task = (ContextType*)&ContextTask[currentTask]; // Copy task priority to local scope iPriority = Task->Priority; // Increases the semaphore wait list counter pont_event->OSEventWait++; // Allocates the current task on the semaphore wait list pont_event->OSEventWaitList = pont_event->OSEventWaitList | (PriorityMask[iPriority]); // Task entered suspended state, waiting for semaphore post #if (VERBOSE == 1) Task->State = SUSPENDED; Task->SuspendedType = SEMAPHORE; #endif // Remove current task from the Ready List OSReadyList = OSReadyList & ~(PriorityMask[iPriority]); // Set timeout overflow if (time_wait) { timeout = (INT32U)((INT32U)OSGetCount() + (INT32U)time_wait); if (timeout >= TICK_COUNT_OVERFLOW) { Task->TimeToWait = (INT16U)(timeout - TICK_COUNT_OVERFLOW); } else { Task->TimeToWait = (INT16U)timeout; } // Put task into delay list IncludeTaskIntoDelayList(); } else { Task->TimeToWait = NO_TIMEOUT; } // Change Context - Returns on time overflow or semaphore post ChangeContext(); if (time_wait) { /* Edited by Carlos H. Barriquello */ /* Moved critical region to inside test region */ // Exit Critical Section OSExitCritical(); // Enter Critical Section OSEnterCritical(); /* End of edition */ // Verify if the reason of task wake up was queue timeout if(Task->TimeToWait == EXIT_BY_TIMEOUT) { // Test if both timeout and post have occured before arrive here if ((pont_event->OSEventWaitList & PriorityMask[iPriority])) { // Remove the task from the queue wait list pont_event->OSEventWaitList = pont_event->OSEventWaitList & ~(PriorityMask[iPriority]); // Decreases the queue wait list counter pont_event->OSEventWait--; // Exit Critical Section OSExitCritical(); // Indicates queue timeout return TIMEOUT; } } else { // Remove the time to wait condition Task->TimeToWait = NO_TIMEOUT; // Remove from delay list RemoveFromDelayList(); } } // Exit Critical Section OSExitCritical(); return OK; }
INT8U OSMboxPend (BRTOS_Mbox *pont_event, void **Mail, INT16U time_wait) { OS_SR_SAVE_VAR INT8U iPriority = 0; INT32U timeout; ContextType *Task; #if (ERROR_CHECK == 1) /// Can not use mailbox pend function from interrupt handling code if(iNesting > 0) { // Return NULL message *Mail = (void *)NULL; return(IRQ_PEND_ERR); } // Verifies if the pointer is NULL if(pont_event == NULL) { return(NULL_EVENT_POINTER); } #endif // Enter Critical Section OSEnterCritical(); #if (ERROR_CHECK == 1) // Verifies if the event is allocated if(pont_event->OSEventAllocated != TRUE) { // Exit Critical Section OSExitCritical(); return(ERR_EVENT_NO_CREATED); } #endif // Verify if there was a message post if (pont_event->OSEventState == AVAILABLE_MESSAGE) { // Copy message pointer *Mail = pont_event->OSEventPointer; // Free message slot pont_event->OSEventState = NO_MESSAGE; // Exit Critical Section OSExitCritical(); return OK; } else { Task = (ContextType*)&ContextTask[currentTask]; // Copy task priority to local scope iPriority = Task->Priority; // Increases the semaphore wait list counter pont_event->OSEventWait++; // Allocates the current task on the mailbox wait list pont_event->OSEventWaitList = pont_event->OSEventWaitList | (PriorityMask[iPriority]); // Task entered suspended state, waiting for mailbox post #if (VERBOSE == 1) Task->State = SUSPENDED; Task->SuspendedType = MAILBOX; #endif // Remove current task from the Ready List OSReadyList = OSReadyList & ~(PriorityMask[iPriority]); // Set timeout overflow if (time_wait) { timeout = (INT32U)((INT32U)OSGetCount() + (INT32U)time_wait); if (timeout >= TICK_COUNT_OVERFLOW) { Task->TimeToWait = (INT16U)(timeout - TICK_COUNT_OVERFLOW); } else { Task->TimeToWait = (INT16U)timeout; } // Put task into delay list IncludeTaskIntoDelayList(); } else { Task->TimeToWait = NO_TIMEOUT; } // Change Context - Returns on time overflow or mailbox post ChangeContext(); // Exit Critical Section OSExitCritical(); // Enter Critical Section OSEnterCritical(); if (time_wait) { // Verify if the reason of task wake up was queue timeout if(Task->TimeToWait == EXIT_BY_TIMEOUT) { // Test if both timeout and post have occured before arrive here if ((pont_event->OSEventWaitList & PriorityMask[iPriority])) { // Remove the task from the queue wait list pont_event->OSEventWaitList = pont_event->OSEventWaitList & ~(PriorityMask[iPriority]); // Decreases the queue wait list counter pont_event->OSEventWait--; // Return NULL message *Mail = (void *)NULL; // Exit Critical Section OSExitCritical(); // Indicates queue timeout return TIMEOUT; } } else { // Remove the time to wait condition Task->TimeToWait = NO_TIMEOUT; // Remove from delay list RemoveFromDelayList(); } } // Copy message pointer *Mail = pont_event->OSEventPointer; // Free message slot pont_event->OSEventState = NO_MESSAGE; // Exit Critical Section OSExitCritical(); return OK; } }
INT8U OSMutexAcquire(BRTOS_Mutex *pont_event, INT16U time_wait) { OS_SR_SAVE_VAR INT8U iPriority = 0; INT32U timeout; ContextType *Task; #if (ERROR_CHECK == 1) /// Can not use mutex acquire function from interrupt handling code if(iNesting > 0) { return(IRQ_PEND_ERR); } // Verifies if the pointer is NULL if(pont_event == NULL) { return(NULL_EVENT_POINTER); } #endif // Enter Critical Section OSEnterCritical(); #if (ERROR_CHECK == 1) // Verifies if the event is allocated if(pont_event->OSEventAllocated != TRUE) { // Exit Critical Section OSExitCritical(); return(ERR_EVENT_NO_CREATED); } #endif // BRTOS TRACE SUPPORT #if (OSTRACE == 1) #if(OS_TRACE_BY_TASK == 1) Update_OSTrace(currentTask, MUTEXPEND); #else Update_OSTrace(ContextTask[currentTask].Priority, MUTEXPEND); #endif #endif // Verifies if the task is trying to acquire the mutex again if (currentTask == pont_event->OSEventOwner) { // It is already the mutex owner OSExitCritical(); return OK; } Task = (ContextType*)&ContextTask[currentTask]; // Verify if the shared resource is available if (pont_event->OSEventState == AVAILABLE_RESOURCE) { // Set shared resource busy pont_event->OSEventState = BUSY_RESOURCE; // Current task becomes the temporary owner of the mutex pont_event->OSEventOwner = currentTask; /////////////////////////////////////////////////////////////////////////////// // Performs the temporary exchange of mutex owner priority, if needed // /////////////////////////////////////////////////////////////////////////////// // Backup the original task priority pont_event->OSOriginalPriority = ContextTask[currentTask].Priority; if (pont_event->OSMaxPriority > ContextTask[currentTask].Priority) { // Receives the priority ceiling temporarily Task->Priority = pont_event->OSMaxPriority; // Priority vector change PriorityVector[pont_event->OSMaxPriority] = currentTask; // Remove "original priority current task" from the Ready List OSReadyList = OSReadyList & ~(PriorityMask[pont_event->OSOriginalPriority]); // Put the "max priority current task" into Ready List OSReadyList = OSReadyList | (PriorityMask[pont_event->OSMaxPriority]); } OSExitCritical(); return OK; } else { // If no timeout is used and the mutex is not available, exit the mutex with an error if (time_wait == NO_TIMEOUT) { // Exit Critical Section OSExitCritical(); return EXIT_BY_NO_RESOURCE_AVAILABLE; } // Copy task priority to local scope iPriority = Task->Priority; // Increases the mutex wait list counter pont_event->OSEventWait++; // Allocates the current task on the mutex wait list pont_event->OSEventWaitList = pont_event->OSEventWaitList | (PriorityMask[iPriority]); // Task entered suspended state, waiting for mutex release #if (VERBOSE == 1) ContextTask[currentTask].State = SUSPENDED; ContextTask[currentTask].SuspendedType = MUTEX; #endif // Remove current task from the Ready List OSReadyList = OSReadyList & ~(PriorityMask[iPriority]); // Set timeout overflow if (time_wait) { timeout = (INT32U)((INT32U)OSGetCount() + (INT32U)time_wait); if (timeout >= TICK_COUNT_OVERFLOW) { Task->TimeToWait = (INT16U)(timeout - TICK_COUNT_OVERFLOW); } else { Task->TimeToWait = (INT16U)timeout; } // Put task into delay list IncludeTaskIntoDelayList(); } else { Task->TimeToWait = NO_TIMEOUT; } // Change Context - Returns on mutex release ChangeContext(); // Exit Critical Section OSExitCritical(); // Enter Critical Section OSEnterCritical(); if (time_wait) { // Verify if the reason of task wake up was queue timeout if(Task->TimeToWait == EXIT_BY_TIMEOUT) { // Test if both timeout and post have occured before arrive here if ((pont_event->OSEventWaitList & PriorityMask[iPriority])) { // Remove the task from the queue wait list pont_event->OSEventWaitList = pont_event->OSEventWaitList & ~(PriorityMask[iPriority]); // Decreases the queue wait list counter pont_event->OSEventWait--; // Exit Critical Section OSExitCritical(); // Indicates resource not available return EXIT_BY_NO_RESOURCE_AVAILABLE; } } else { // Remove the time to wait condition Task->TimeToWait = NO_TIMEOUT; // Remove from delay list RemoveFromDelayList(); } } // Backup the original task priority pont_event->OSOriginalPriority = iPriority; if (pont_event->OSMaxPriority > iPriority) { // Receives the priority ceiling temporarily Task->Priority = pont_event->OSMaxPriority; // Priority vector change PriorityVector[pont_event->OSMaxPriority] = currentTask; // Remove "original priority current task" from the Ready List OSReadyList = OSReadyList & ~(PriorityMask[iPriority]); // Put the "max priority current task" into Ready List OSReadyList = OSReadyList | (PriorityMask[pont_event->OSMaxPriority]); } OSExitCritical(); return OK; } }
INT8U OSTimerSet (BRTOS_TIMER *cbp, FCN_CALLBACK cb, TIMER_CNT time_wait) { OS_SR_SAVE_VAR INT8U i; BRTOS_TIMER p; INT32U timeout; BRTOS_TMR_T* list; if((cb == NULL) || (cbp == NULL)) return NULL_EVENT_POINTER; /* return error code */ if (currentTask) OSEnterCritical(); // Search available timer control block for(i=0;i<=BRTOS_MAX_TIMER;i++) { if(i >= BRTOS_MAX_TIMER) { // Exit critical Section if (currentTask) OSExitCritical(); // Return error code return(NO_AVAILABLE_EVENT); } if(BRTOS_TIMER_VECTOR.mem[i].state == TIMER_NOT_ALLOCATED){ // Exit critical Section if (currentTask) OSExitCritical(); // Return error code return(ERR_EVENT_NO_CREATED); } if(BRTOS_TIMER_VECTOR.mem[i].state == TIMER_NOT_USED) { p = &BRTOS_TIMER_VECTOR.mem[i]; break; } } p->state = TIMER_STOPPED; p->func_cb = cb; // store callback function if(time_wait > 0) { timeout = (INT32U)((INT32U)OSGetCount() + (INT32U)time_wait); if (timeout >= TICK_COUNT_OVERFLOW) { p->timeout = (INT16U)(timeout - TICK_COUNT_OVERFLOW); list = BRTOS_TIMER_VECTOR.future; // add into future list list->timers[++list->count] = p; // insert in the end Subir (list->timers, list->count); // order it } else { p->timeout = (INT16U)timeout; list = BRTOS_TIMER_VECTOR.current; // add into current list list->timers[++list->count] = p; // insert in the end Subir (list->timers, list->count); // order it // may need to change wake time of timer task if(currentTask) { if(p->timeout == (list->timers[1])->timeout) { ContextTask[BRTOS_TIMER_VECTOR.handling_task].TimeToWait = p->timeout; } } } p->state = TIMER_RUNNING; } *cbp = p; if (currentTask) OSExitCritical(); return OK; }