?? sys_arch.c
字號:
/*
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
* Modifications Copyright (c) 2006 Christian Walter <wolti@sil.at>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
* Modifcations: Christian Walter <wolti@sil.at>
*
* $Id: sys_arch.c,v 1.6 2006/09/24 22:04:53 wolti Exp $
*/
/* ------------------------ System includes ------------------------------- */
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
/* ------------------------ FreeRTOS includes ----------------------------- */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/* ------------------------ lwIP includes --------------------------------- */
#include "lwip/debug.h"
#include "lwip/def.h"
#include "lwip/sys.h"
#include "lwip/mem.h"
#include "lwip/sio.h"
#include "lwip/stats.h"
/* ------------------------ Project includes ------------------------------ */
/* ------------------------ Defines --------------------------------------- */
/* This is the number of threads that can be started with sys_thead_new() */
#define SYS_MBOX_SIZE ( 16 )
#define MS_TO_TICKS( ms ) \
( portTickType )( ( portTickType ) ( ms ) / portTICK_RATE_MS )
#define TICKS_TO_MS( ticks ) \
( unsigned portLONG )( ( portTickType ) ( ticks ) * portTICK_RATE_MS )
#define THREAD_STACK_SIZE ( 1024 )
#define THREAD_NAME "lwIP"
#define THREAD_INIT( tcb ) \
do { \
tcb->next = NULL; \
tcb->pid = ( xTaskHandle )0; \
tcb->timeouts.next = NULL; \
} while( 0 )
/* ------------------------ Type definitions ------------------------------ */
typedef struct sys_tcb
{
struct sys_tcb *next;
struct sys_timeouts timeouts;
xTaskHandle pid;
} sys_tcb_t;
/* ------------------------ Prototypes ------------------------------------ */
/* ------------------------ Static functions ------------------------------ */
sys_tcb_t *sys_thread_current( void );
/* ------------------------ Static variables ------------------------------ */
static sys_tcb_t *tasks = NULL;
/* ------------------------ Start implementation -------------------------- */
void
sys_init( void )
{
LWIP_ASSERT( "sys_init: not called first", tasks == NULL );
tasks = NULL;
}
/*
* This optional function does a "fast" critical region protection and returns
* the previous protection level. This function is only called during very short
* critical regions. An embedded system which supports ISR-based drivers might
* want to implement this function by disabling interrupts. Task-based systems
* might want to implement this by using a mutex or disabling tasking. This
* function should support recursive calls from the same task or interrupt. In
* other words, sys_arch_protect() could be called while already protected. In
* that case the return value indicates that it is already protected.
*
* sys_arch_protect() is only required if your port is supporting an operating
* system.
*/
sys_prot_t
sys_arch_protect( void )
{
vPortEnterCritical( );
return 1;
}
/*
* This optional function does a "fast" set of critical region protection to the
* value specified by pval. See the documentation for sys_arch_protect() for
* more information. This function is only required if your port is supporting
* an operating system.
*/
void
sys_arch_unprotect( sys_prot_t pval )
{
( void )pval;
vPortExitCritical( );
}
/*
* Prints an assertion messages and aborts execution.
*/
void
sys_assert( const char *msg )
{
fputs( msg, stderr );
fputs( "\n\r", stderr );
vPortEnterCritical( );
for( ;; );
}
void
sys_debug( const char *const fmt, ... )
{
va_list ap;
va_start( ap, fmt );
( void )vprintf( fmt, ap );
( void )putchar( '\r' );
va_end( ap );
}
/* ------------------------ Start implementation ( Threads ) -------------- */
sys_thread_t
sys_thread_new( void ( *thread ) ( void *arg ), void *arg, int prio )
{
return sys_arch_thread_new( thread, arg, prio, THREAD_STACK_SIZE );
}
/*
* Starts a new thread with priority "prio" that will begin its execution in the
* function "thread()". The "arg" argument will be passed as an argument to the
* thread() function. The argument "ssize" is the requested stack size for the
* new thread. The id of the new thread is returned. Both the id and the
* priority are system dependent.
*/
sys_thread_t
sys_arch_thread_new( void ( *thread ) ( void *arg ), void *arg, int prio, size_t ssize )
{
sys_thread_t thread_hdl = SYS_THREAD_NULL;
int i;
sys_tcb_t *p;
char thread_name[ configMAX_TASK_NAME_LEN ];
/* We disable the FreeRTOS scheduler because it might be the case that the new
* tasks gets scheduled inside the xTaskCreate function. To prevent this we
* disable the scheduling. Note that this can happen although we have interrupts
* disabled because xTaskCreate contains a call to taskYIELD( ).
*/
vPortEnterCritical( );
p = tasks;
i = 0;
/* We are called the first time. Initialize it. */
if( p == NULL )
{
p = pvPortMalloc( sizeof( sys_tcb_t ) );
if( p != NULL )
{
tasks = p;
}
}
else
{
/* First task already counter. */
i++;
/* Cycle to the end of the list. */
while( p->next != NULL )
{
i++;
p = p->next;
}
p->next = pvPortMalloc( sizeof( sys_tcb_t ) );
p = p->next;
}
if( p != NULL )
{
/* Memory allocated. Initialize the data structure. */
THREAD_INIT( p );
( void )snprintf( thread_name, configMAX_TASK_NAME_LEN, "lwIP%d", i );
/* Now q points to a free element in the list. */
if( xTaskCreate( thread, thread_name, ssize, arg, prio, &p->pid ) == pdPASS )
{
thread_hdl = p;
}
else
{
vPortFree( p );
}
}
vPortExitCritical( );
return thread_hdl;
}
void
sys_arch_thread_remove( sys_thread_t hdl )
{
sys_tcb_t *current = tasks, *prev;
sys_tcb_t *toremove = hdl;
xTaskHandle pid = ( xTaskHandle ) 0;
LWIP_ASSERT( "sys_arch_thread_remove: assertion hdl != NULL failed!", hdl != NULL );
/* If we have to remove the first task we must update the global "tasks"
* variable. */
vPortEnterCritical( );
if( hdl != NULL )
{
prev = NULL;
while( ( current != NULL ) && ( current != toremove ) )
{
prev = current;
current = current->next;
}
/* Found it. */
if( current == toremove )
{
/* Not the first entry in the list. */
if( prev != NULL )
{
prev->next = toremove->next;
}
else
{
tasks = toremove->next;
}
LWIP_ASSERT( "sys_arch_thread_remove: can't remove thread with timeouts!",
toremove->timeouts.next == NULL );
pid = toremove->pid;
THREAD_INIT( toremove );
vPortFree( toremove );
}
}
/* We are done with accessing the shared datastructure. Release the
* resources.
*/
vPortExitCritical( );
if( pid != ( xTaskHandle ) 0 )
{
vTaskDelete( pid );
/* not reached. */
}
}
/*
* Returns the thread control block for the currently active task. In case
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -