⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sys_arch.c

📁 FreeRTOS is a portable, open source, mini Real Time Kernel - a free to download and royalty free RTO
💻 C
📖 第 1 页 / 共 2 页
字号:
 * of an error the functions returns NULL.
 */
sys_thread_t
sys_arch_thread_current( void )
{
    sys_tcb_t      *p = tasks;
    xTaskHandle     pid = xTaskGetCurrentTaskHandle(  );

    vPortEnterCritical(  );
    while( ( p != NULL ) && ( p->pid != pid ) )
    {
        p = p->next;
    }
    vPortExitCritical(  );
    return p;
}

/*
 * Returns a pointer to the per-thread sys_timeouts structure. In lwIP,
 * each thread has a list of timeouts which is represented as a linked
 * list of sys_timeout structures. The sys_timeouts structure holds a
 * pointer to a linked list of timeouts. This function is called by
 * the lwIP timeout scheduler and must not return a NULL value.
 *
 * In a single threaded sys_arch implementation, this function will
 * simply return a pointer to a global sys_timeouts variable stored in
 * the sys_arch module.
 */
struct sys_timeouts *
sys_arch_timeouts( void )
{
    sys_tcb_t      *ptask;

    ptask = sys_arch_thread_current(  );
    LWIP_ASSERT( "sys_arch_timeouts: ptask != NULL", ptask != NULL );
    return ptask != NULL ? &( ptask->timeouts ) : NULL;
}

/* ------------------------ Start implementation ( Semaphores ) ----------- */

/* Creates and returns a new semaphore. The "count" argument specifies
 * the initial state of the semaphore.
 */
sys_sem_t
sys_sem_new( u8_t count )
{
    xSemaphoreHandle xSemaphore;

    vSemaphoreCreateBinary( xSemaphore );
    if( xSemaphore != SYS_SEM_NULL )
    {
        if( count == 0 )
        {
            xSemaphoreTake( xSemaphore, 1 );
        }
#ifdef SYS_STATS
        vPortEnterCritical(  );
        lwip_stats.sys.sem.used++;
        if( lwip_stats.sys.sem.used > lwip_stats.sys.sem.max )
        {
            lwip_stats.sys.sem.max = lwip_stats.sys.sem.used;
        }
        vPortExitCritical(  );
#endif
    }
    else
    {
        LWIP_ASSERT( "sys_sem_new: xSemaphore == SYS_SEM_NULL", xSemaphore != SYS_SEM_NULL );
    }

    return xSemaphore;
}

/* Deallocates a semaphore */
void
sys_sem_free( sys_sem_t sem )
{
    LWIP_ASSERT( "sys_sem_free: sem != SYS_SEM_NULL", sem != SYS_SEM_NULL );
    if( sem != SYS_SEM_NULL )
    {
#ifdef SYS_STATS
        vPortEnterCritical(  );
        lwip_stats.sys.sem.used--;
        vPortExitCritical(  );
#endif
        vQueueDelete( sem );
    }
}

/* Signals a semaphore */
void
sys_sem_signal( sys_sem_t sem )
{
    LWIP_ASSERT( "sys_sem_signal: sem != SYS_SEM_NULL", sem != SYS_SEM_NULL );
    xSemaphoreGive( sem );
}

/*
 * 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 )
{
    portBASE_TYPE   xStatus;
    portTickType    xTicksStart, xTicksEnd, xTicksElapsed;
    u32_t           timespent;

    LWIP_ASSERT( "sys_arch_sem_wait: sem != SYS_SEM_NULL", sem != SYS_SEM_NULL );
    xTicksStart = xTaskGetTickCount(  );
    if( timeout == 0 )
    {
        do
        {
            xStatus = xSemaphoreTake( sem, MS_TO_TICKS( 100 ) );
        }
        while( xStatus != pdTRUE );
    }
    else
    {
        xStatus = xSemaphoreTake( sem, MS_TO_TICKS( timeout ) );
    }

    /* Semaphore was signaled. */
    if( xStatus == pdTRUE )
    {
        xTicksEnd = xTaskGetTickCount(  );
        xTicksElapsed = xTicksEnd - xTicksStart;
        timespent = TICKS_TO_MS( xTicksElapsed );
    }
    else
    {
        timespent = SYS_ARCH_TIMEOUT;
    }
    return timespent;
}


/* ------------------------ Start implementation ( Mailboxes ) ------------ */

/* Creates an empty mailbox. */
sys_mbox_t
sys_mbox_new( void )
{
    xQueueHandle    mbox;

    mbox = xQueueCreate( SYS_MBOX_SIZE, sizeof( void * ) );
    if( mbox != SYS_MBOX_NULL )
    {
#ifdef SYS_STATS
        vPortEnterCritical(  );
        lwip_stats.sys.mbox.used++;
        if( lwip_stats.sys.mbox.used > lwip_stats.sys.mbox.max )
        {
            lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used;
        }
        vPortExitCritical(  );
#endif
    }
    return mbox;
}

/*
  Deallocates a mailbox. If there are messages still present in the
  mailbox when the mailbox is deallocated, it is an indication of a
  programming error in lwIP and the developer should be notified.
*/
void
sys_mbox_free( sys_mbox_t mbox )
{
    void           *msg;

    LWIP_ASSERT( "sys_mbox_free: mbox != SYS_MBOX_NULL", mbox != SYS_MBOX_NULL );
    if( mbox != SYS_MBOX_NULL )
    {
        while( uxQueueMessagesWaiting( mbox ) != 0 )
        {
            if( sys_arch_mbox_fetch( mbox, &msg, 1 ) != SYS_ARCH_TIMEOUT )
            {
                LWIP_ASSERT( "sys_mbox_free: memory leak (msg != NULL)", msg == NULL );
            }
        }
        vQueueDelete( mbox );
#ifdef SYS_STATS
        vPortEnterCritical(  );
        lwip_stats.sys.mbox.used--;
        vPortExitCritical(  );
#endif
    }
}

/*
 * This function sends a message to a mailbox. It is unusual in that no error
 * return is made. This is because the caller is responsible for ensuring that
 * the mailbox queue will not fail. The caller does this by limiting the number
 * of msg structures which exist for a given mailbox.
 */
void
sys_mbox_post( sys_mbox_t mbox, void *data )
{
    portBASE_TYPE   xQueueSent;

    /* Queue must not be full - Otherwise it is an error. */
    xQueueSent = xQueueSend( mbox, &data, 0 );
    LWIP_ASSERT( "sys_mbox_post: xQueueSent == pdPASS", xQueueSent == pdPASS );
}

/*
 * 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.
 *
 * 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           *ret_msg;
    portBASE_TYPE   xStatus;
    portTickType    xTicksStart, xTicksEnd, xTicksElapsed;
    u32_t           timespent;

    LWIP_ASSERT( "sys_arch_mbox_fetch: mbox != SYS_MBOX_NULL", mbox != SYS_MBOX_NULL );
    xTicksStart = xTaskGetTickCount(  );
    if( timeout == 0 )
    {
        do
        {
            xStatus = xQueueReceive( mbox, &ret_msg, MS_TO_TICKS( 100 ) );
        }
        while( xStatus != pdTRUE );
    }
    else
    {
        xStatus = xQueueReceive( mbox, &ret_msg, MS_TO_TICKS( timeout ) );
    }

    if( xStatus == pdTRUE )
    {
        if( msg )
        {
            *msg = ret_msg;
        }
        xTicksEnd = xTaskGetTickCount(  );
        xTicksElapsed = xTicksEnd - xTicksStart;
        timespent = TICKS_TO_MS( xTicksElapsed );
    }
    else
    {
        if( msg )
        {
            *msg = NULL;
        }
        timespent = SYS_ARCH_TIMEOUT;
    }
    return timespent;
}

u32_t
sys_jiffies( void )
{
    portTickType    xTicks = xTaskGetTickCount(  );

    return ( u32_t )TICKS_TO_MS( xTicks );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -