/* Blocks the thread until a message arrives in the mailbox, but does not block the thread longer than "timeout" milliseconds (similar to the sys_arch_sem_wait() function). The "msg" argument is a result parameter that is set by the function (i.e., by doing "*msg = ptr"). The "msg" parameter maybe NULL to indicate that the message should be dropped. The return values are the same as for the sys_arch_sem_wait() function: Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a timeout. Note that a function with a similar name, sys_mbox_fetch(), is implemented by lwIP. */ u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout) { void *dummyptr; INT16U StartTime, EndTime, Elapsed; StartTime = OSGetTickCount(); if( msg == NULL ) { msg = &dummyptr; } if( timeout != 0 ) { if(!OSDQueuePend (mbox, &(*msg), timeout)) { EndTime = OSGetTickCount(); if (EndTime > StartTime) { Elapsed = EndTime - StartTime; }else { Elapsed = (TICK_COUNT_OVERFLOW - StartTime) + EndTime; } if( Elapsed == 0 ) { Elapsed = 1; } return ( Elapsed ); } else // timed out blocking for message { *msg = NULL; return SYS_ARCH_TIMEOUT; } } else // block forever for a message. { while( OSDQueuePend (mbox, &(*msg), 10000)) // time is arbitrary { ; } EndTime = OSGetTickCount(); if (EndTime > StartTime) { Elapsed = EndTime - StartTime; }else { Elapsed = (TICK_COUNT_OVERFLOW - StartTime) + EndTime; } if( Elapsed == 0 ) { Elapsed = 1; } return ( Elapsed ); // return time blocked TBD test } }
/* Blocks the thread while waiting for the semaphore to be signaled. If the "timeout" argument is non-zero, the thread should only be blocked for the specified time (measured in milliseconds). If the timeout argument is non-zero, the return value is the number of milliseconds spent waiting for the semaphore to be signaled. If the semaphore wasn't signaled within the specified time, the return value is SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore (i.e., it was already signaled), the function may return zero. Notice that lwIP implements a function with a similar name, sys_sem_wait(), that uses the sys_arch_sem_wait() function. */ u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout) { INT16U StartTime, EndTime, Elapsed; StartTime = OSGetTickCount(); if( timeout != 0) { if(!OSSemPend(sem, timeout)) { EndTime = OSGetTickCount(); if (EndTime > StartTime) { Elapsed = EndTime - StartTime; }else { Elapsed = (TICK_COUNT_OVERFLOW - StartTime) + EndTime; } if( Elapsed == 0 ) { Elapsed = 1; } return (Elapsed); // return time blocked TBD test } else { return SYS_ARCH_TIMEOUT; } } else // must block without a timeout { while( OSSemPend(sem, 10000) ) { ; } EndTime = OSGetTickCount(); if (EndTime > StartTime) { Elapsed = EndTime - StartTime; }else { Elapsed = (TICK_COUNT_OVERFLOW - StartTime) + EndTime; } if( Elapsed == 0 ) { Elapsed = 1; } return ( Elapsed ); // return time blocked } }
/* Timer Task */ void BRTOS_TimerTask(void) { OS_SR_SAVE_VAR BRTOS_TIMER p; TIMER_CNT tickcount; TIMER_CNT repeat; INT32U timeout; TIMER_CNT next_time_to_wake; /* tick count of next timer */ BRTOS_TMR_T *list, *list_tmp; BRTOS_TIMER_VECTOR.handling_task = currentTask; list = BRTOS_TIMER_VECTOR.current; p=list->timers[1]; if(p!= NULL) { next_time_to_wake = p->timeout; } else { next_time_to_wake = TIMER_MAX_COUNTER; } for(;;) { BRTOS_TimerTaskSleep(next_time_to_wake); tickcount = OSGetTickCount(); timer_loop: list = BRTOS_TIMER_VECTOR.current; p=list->timers[1]; while(p!= NULL && p->timeout <= tickcount) { // some timer has expired if((p)->func_cb != NULL) { repeat = (TIMER_CNT)((p)->func_cb()); /* callback */ OSEnterCritical(); if (repeat > 0) { /* needs to repeat after "repeat" time ? */ timeout = (INT32U)((INT32U)tickcount + (INT32U)repeat); if (timeout >= TICK_COUNT_OVERFLOW) { p->timeout = (TIMER_CNT)(timeout - TICK_COUNT_OVERFLOW); list_tmp = BRTOS_TIMER_VECTOR.future; // add into future list list_tmp->timers[++list_tmp->count] = p; // insert in the end Subir(list_tmp->timers,list_tmp->count); list->timers[1]=list->timers[list->count]; // remove from current list list->timers[list->count] = NULL; list->count--; } else { p->timeout = (TIMER_CNT)timeout; } } else { p->timeout = 0; p->state = TIMER_NOT_ALLOCATED; p->func_cb = NULL; 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 p=list->timers[1]; OSExitCritical(); } if(tickcount == TIMER_MAX_COUNTER) { if(p==NULL) { /* time to switch lists */ void* tmp = BRTOS_TIMER_VECTOR.current; BRTOS_TIMER_VECTOR.current = BRTOS_TIMER_VECTOR.future; BRTOS_TIMER_VECTOR.future = tmp; list = BRTOS_TIMER_VECTOR.current; p=list->timers[1]; } else { /* there is a delayed timer */ tickcount++; goto timer_loop; } } /* if any timer waiting, set task to wake */ if(p!= NULL) { next_time_to_wake = p->timeout; } else { next_time_to_wake = TIMER_MAX_COUNTER; } } }