该函数用于从消息队列中取出一条消息。该函数是一个阻塞函数。调用该函数的线程若未取到消息,则在形参timeout所指定的时间内,该线程被阻塞。当超过timeout所指定的时间后,该线程恢复至就绪状态。若timeout为0,则调用该函数的线程一直被阻塞,直到收到消息。
u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) {
void *dummyptr;
portTickType StartTime, EndTime, Elapsed;
StartTime = xTaskGetTickCount();
if ( msg == NULL ) { msg = &dummyptr; }
if ( timeout != 0 ) { if ( pdTRUE == xQueueReceive( *mbox, &(*msg), timeout / portTICK_RATE_MS ) )
{ EndTime = xTaskGetTickCount(); Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; return ( Elapsed ); } else // timed out blocking for message { *msg = NULL; return SYS_ARCH_TIMEOUT; } }
else // block forever for a message. { while( pdTRUE != xQueueReceive( *mbox, &(*msg), portMAX_DELAY ) ){} // time is arbitrary
EndTime = xTaskGetTickCount(); Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; return ( Elapsed ); // return time blocked TODO test } }
6. sys_arch_mbox_tryfetch函数
该函数尝试从消息队列中取出消息。它是一个非阻塞函数。当去带消息时,则返回成功,否则立即退出,返回“队列空”。具体代码如下:
u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) {
void *dummyptr; if ( msg == NULL ) { msg = &dummyptr; }
if ( pdTRUE == xQueueReceive( *mbox, &(*msg), 0 ) ) {
return ERR_OK; } else {
return SYS_MBOX_EMPTY; } }
7. sys_sem_new函数
该函数用于创建一个信号量,其中形参count指明了当前信号量的状态。若count为0,则该信号量在创建时就被“取走”(take)了。代码如下:
err_t sys_sem_new(sys_sem_t *sem, u8_t count) {
vSemaphoreCreateBinary(*sem ); if(*sem == NULL) {
#if SYS_STATS
++lwip_stats.sys.sem.err; #endif /* SYS_STATS */ return ERR_MEM; }
if(count == 0) // Means it can't be taken { xSemaphoreTake(*sem,1); }
#if SYS_STATS
++lwip_stats.sys.sem.used;
if (lwip_stats.sys.sem.max < lwip_stats.sys.sem.used) { lwip_stats.sys.sem.max = lwip_stats.sys.sem.used; }
#endif /* SYS_STATS */
return ERR_OK;
}
8. sys_arch_sem_wait函数
该函数是一个阻塞函数。调用该函数的线程在形参timeout指定的时间内被阻塞。若timeout为0,则调用该函数的线程一直被阻塞,直到等待的信号量被释放。当该函数取到信号量时,它将返回取得该信号量所占用的时间。代码如下:
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) {
portTickType StartTime, EndTime, Elapsed;
StartTime = xTaskGetTickCount();
if( timeout != 0) { if( xSemaphoreTake( *sem, timeout / portTICK_RATE_MS ) == pdTRUE ) { EndTime = xTaskGetTickCount(); Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; return (Elapsed); // return time blocked TODO test } else { return SYS_ARCH_TIMEOUT; } }
else // must block without a timeout { while( xSemaphoreTake(*sem, portMAX_DELAY) != pdTRUE){} EndTime = xTaskGetTickCount(); Elapsed = (EndTime - StartTime) * portTICK_RATE_MS; return ( Elapsed ); // return time blocked } }
9. sys_sem_signal函数
该函数用于释放一个信号量。代码如下: void sys_sem_signal(sys_sem_t *sem) {
xSemaphoreGive(*sem); }
10. sys_sem_free函数
该函数是用于删除一个信号量。代码如下:
void sys_sem_free(sys_sem_t *sem) {
#if SYS_STATS
--lwip_stats.sys.sem.used; #endif /* SYS_STATS */ vQueueDelete(*sem); }
11. sys_thread_new函数
该函数用于创建一个新的线程。其中,形参name指定了该线程的名称,thread是该线程对应的函数,arg是该线程的形参,stacksize指定了该线程对应的堆栈大小,prio则指定该线程的优先级。代码如下:
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread , void *arg, int stacksize, int prio)
{
xTaskHandle CreatedTask; int result;
if ( s_nextthread < SYS_THREAD_MAX ) {
result = xTaskCreate( thread, ( signed portCHAR * ) name, stacksize, arg, prio, &CreatedTask );
// For each task created, store the task handle (pid) in the timers array. // This scheme doesn't allow for threads to be deleted //s_timeoutlist[s_nextthread++].pid = CreatedTask;
if(result == pdPASS) { return CreatedTask; } else { return NULL; } } else {
return NULL; } }
12. sys_init函数
该函数是操作系统模拟层的初始化函数。它主要对定时器管理数组进行了初始化。代码如下:
sys_init(void)
{
int i;
// Initialize the the per-thread sys_timeouts structures // make sure there are no valid pids in the list for(i = 0; i < SYS_THREAD_MAX; i++) {
timeoutlist[i].pid = 0; }
// keep track of how many threads have been created nextthread = 0; }
13. sys_arch_timeouts函数
该函数用于返回当前任务的定时器管理链表首地址。代码如下:
sys_arch_timeouts(void) {
int i;
xTaskHandle pid;
struct timeoutlist *tl;
pid = xTaskGetCurrentTaskHandle( ); for(i = 0; i < nextthread; i++) {
tl = &timeoutlist[i]; if(tl->pid == pid) {
return &(tl->timeouts); } }
// Error return NULL; }
14. sys_arch_protect函数
该函数用于保护临界区资源,代码如下:
sys_prot_t sys_arch_protect(void) {
vPortEnterCritical(); return 1; }
15. sys_arch_unprotect函数
该函数在访问临界区资源时使用,必须与sys_arch_protect函数成对使用。代码如下: void sys_arch_unprotect(sys_prot_t pval) {
( void ) pval;
vPortExitCritical(); }