示例#1
0
// write the rboot config
// preserves the contents of the rest of the sector,
// so the rest of the sector can be used to store user data
// updates checksum automatically (if enabled)
bool ICACHE_FLASH_ATTR rboot_set_config(rboot_config *conf) {
	uint8 *buffer;
	buffer = (uint8*)os_malloc(SECTOR_SIZE);
	if (!buffer) {
		//os_printf("No ram!\r\n");
		return false;
	}
	
#ifdef BOOT_CONFIG_CHKSUM
	conf->chksum = calc_chksum((uint8*)conf, (uint8*)&conf->chksum);
#endif
	
	spi_flash_read(BOOT_CONFIG_SECTOR * SECTOR_SIZE, (uint32*)((void*)buffer), SECTOR_SIZE);
	memcpy(buffer, conf, sizeof(rboot_config));
	vPortEnterCritical();
	spi_flash_erase_sector(BOOT_CONFIG_SECTOR);
	vPortExitCritical();
	taskYIELD();
	vPortEnterCritical();
	//spi_flash_write(BOOT_CONFIG_SECTOR * SECTOR_SIZE, (uint32*)((void*)buffer), SECTOR_SIZE);
	spi_flash_write(BOOT_CONFIG_SECTOR * SECTOR_SIZE, (uint32*)((void*)buffer), SECTOR_SIZE);
	vPortExitCritical();	
	os_free(buffer);
	return true;
}
示例#2
0
err_t
sio_close( serdev_t * dev )
{
    int             i;
    err_t           error = ERR_VAL;

    for( i = 0; i < UART_DEVICES_MAX; i++ )
    {
        if( &devices[i] == dev )
        {
            break;
        }
    }
    if( i < UART_DEVICES_MAX )
    {
        vPortEnterCritical(  );
        error = sio_close_low_level( i, dev );
        vPortExitCritical(  );

        if( dev->tx_sem != ( xSemaphoreHandle ) 0 )
        {
            vQueueDelete( dev->tx_sem );
        }
        if( dev->rx_sem != ( xSemaphoreHandle ) 0 )
        {
            vQueueDelete( dev->tx_sem );
        }
        SIO_RESET_STATE( dev );
    }

    return error;
}
示例#3
0
void PendSV( char req )
{
char tmp=0;
if(ClosedLv1Isr == 0)
{
	vPortEnterCritical();
	tmp = 1;
}
	if(req ==1)
	{
		SWReq = 1;
	}
	else
		HdlMacSig= 1;
#if 0
	GPIO_REG_WRITE(GPIO_STATUS_W1TS_ADDRESS, 0x40);	
#else
	if(PendSvIsPosted == 0)
	{
		PendSvIsPosted = 1;
		xthal_set_intset(1<<ETS_SOFT_INUM);
	}
#endif
	if(tmp == 1)
		vPortExitCritical();
}
示例#4
0
文件: rtc.c 项目: pl4nkton/drquad32
uint32_t rtc_get_jiffies(void)
{
    vPortEnterCritical();

    static unsigned last, count;

    unsigned  divh, divl;
    do {
        divh = RTC->DIVH & 0x0F;
        divl = RTC->DIVL;
    } while (divh != (RTC->DIVH & 0x0F));

    unsigned ticks = RTC_PRESCALER - (divh << 16) - divl;

    count += ticks - last;

    if (ticks < last)
        count += RTC_PRESCALER;

    last = ticks;

    vPortExitCritical();

    return count;
}
示例#5
0
文件: rtc.c 项目: pl4nkton/drquad32
int _gettimeofday(struct timeval *tp, void *tzvp)
{
    if (tp) {
        unsigned divh, divl, cnth, cntl;

        vPortEnterCritical();
        do {
            divh = RTC->DIVH & 0x0F;
            divl = RTC->DIVL;
            cnth = RTC->CNTH;
            cntl = RTC->CNTL;
        } while (divh != (RTC->DIVH & 0x0F));
        vPortExitCritical();

        tp->tv_sec  = (cnth << 16) + cntl;
        tp->tv_usec = RTC_JIFFIES_TO_US( RTC_PRESCALER - (divh << 16) - divl );
    }

    struct timezone *tzp = tzvp;
    if (tzp)  {
        tzp->tz_minuteswest = 0;
        tzp->tz_dsttime = 0;
    }

    return 0;
}
示例#6
0
u32_t
sio_write( sio_fd_t fd, u8_t * buf, u32_t size )
{
    u32_t           ch_left;

    volatile serdev_t *dev = fd;

    if( dev->ready )
    {
        ch_left = size;
        while( ch_left > 0 )
        {
            vPortEnterCritical(  );
            while( ( dev->tx_buf_cnt < DEFAULT_TX_BUFSIZE ) && ( ch_left > 0 ) )
            {
                dev->tx_buf[dev->tx_buf_wrpos] = *buf++;
                dev->tx_buf_wrpos = ( dev->tx_buf_wrpos + 1 ) % DEFAULT_TX_BUFSIZE;
                dev->tx_buf_cnt++;
                ch_left--;
            }
            /* Enable transmit FIFO empty interrupts and block. */
            UART_ItConfig( dev->UARTx, UART_TxHalfEmpty, ENABLE );
            vPortExitCritical(  );

            /* Not all characters sent within one write. Block on a semaphore
             * which is triggered when the buffer is empty again.
             */
            if( ch_left != 0 )
            {
                while( xSemaphoreTake( dev->tx_sem, portMAX_DELAY ) != pdTRUE );
            }
        }
    }
    return size;
}
示例#7
0
文件: sw_spi.c 项目: saiyn/web
 unsigned char SWReadSPI(void)
 {
     unsigned char i;
     unsigned char ReceivedByte;
 
     vPortEnterCritical();
 
     SmartDelay_spi(5);
     ReceivedByte = 0;
     for (i = 0; i < 8; i++) 
     {       
         SPICLK2(0);
         //SmartDelay_spi(5);         
         ReceivedByte <<= 1;
         if (SPIDI2())
             ReceivedByte |= 0x01;
         SmartDelay_spi(2);
         SPICLK2(1);
         SmartDelay_spi(5);   
     }
     //SPICLK(0);
 
     vPortExitCritical();
 
     return (ReceivedByte);
 }
示例#8
0
uint8_t EEPROM_Write(uint16_t AddressToWrite, void* DataArray, uint16_t BytesToWrite)
{
	IAP_Result[0] = 0;

	//TODO: check to make sure the address is valid

#ifdef USE_EEPROM_LIB
	IAP_Command[0] = EELIB_IAP_COMMAND_EEPROM_WRITE;	//EEPROM library write command
#else
	IAP_Command[0] = IAP_EEPROM_WRITE;					//IAP EEPROM write command
#endif
	IAP_Command[1] = (uint32_t)AddressToWrite;			//EEPROM address to write to
	IAP_Command[2] = (uint32_t)DataArray;				//RAM address of the data to write
	IAP_Command[3] = (uint32_t)BytesToWrite;			//Number of bytes to write
	IAP_Command[4] = SystemCoreClock/1000;				//System clock frequency in kHz

#ifdef USE_EEPROM_LIB
	EELIB_entry(IAP_Command, IAP_Result);
#else
	vPortEnterCritical();
	iap_entry(IAP_Command, IAP_Result);
	vPortExitCritical();
#endif

	return (uint8_t)IAP_Result[0];
}
示例#9
0
void PendSV( char req )
{
	char tmp=0;
//ETS_INTR_LOCK();

	if( NMIIrqIsOn == 0 )
	{
		vPortEnterCritical();
		//PortDisableInt_NoNest();
		tmp = 1;
	}

	if(req ==1)
	{
		SWReq = 1;
	}
	else if(req ==2)
		HdlMacSig= 1;
#if 0
	GPIO_REG_WRITE(GPIO_STATUS_W1TS_ADDRESS, 0x40);	
#else
	if(PendSvIsPosted == 0)
	{
		PendSvIsPosted = 1;
		xthal_set_intset(1<<ETS_SOFT_INUM);
	}
#endif
	if(tmp == 1)
		vPortExitCritical();
}
void WriteScriptPage(Serial *serial, unsigned int argc, char **argv){
	if (argc < 2){
		put_commandError(serial, ERROR_CODE_INVALID_PARAM);
		return;
	}

	unsigned int page = modp_atoi(argv[1]);
	char *scriptPage = "";
	if (argc >= 3) scriptPage = argv[2];

	if (page >=0 && page < SCRIPT_PAGES){
		if (argc >= 2) unescape(scriptPage);
		lockLua();
		vPortEnterCritical();
		pr_info_int(strlen(scriptPage));
		pr_info("=");
		pr_info(scriptPage);
		pr_info("\r\n");
		int result = flashScriptPage(page, scriptPage);
		vPortExitCritical();
		unlockLua();
		if (result == 0){
			put_commandOK(serial);
		}
		else{
			put_commandError(serial, result);
		}
	}
	else{
		put_commandError(serial, ERROR_CODE_INVALID_PARAM);
	}
}
示例#11
0
/*
  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 id of the new thread is returned. Both the id and
  the priority are system dependent.
*/
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 )
   {
	   vPortEnterCritical();
       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;
       vPortExitCritical();
	   
	   if(result == pdPASS)
	   {
		   return CreatedTask;
	   }
	   else
	   {
		   return NULL;
	   }
   }
   else
   {
      return NULL;
   }
}
示例#12
0
文件: sw_spi.c 项目: saiyn/web
unsigned char SWWriteSPI(unsigned char cData)
{
    unsigned char i;
    unsigned char send;

    vPortEnterCritical();
    
    SmartDelay_spi(5);
    send = cData&0xff;
    for (i = 0; i < 8; i++) 
    {
        SPICLK2(0);
        if (send & 0x80)	SPIDO2(1);
        else				SPIDO2(0);
        send <<= 1;		 
        SmartDelay_spi(2);
        SPICLK2(1);		 
        SmartDelay_spi(5);
    }
    //SPICLK(0);
    //SPIDO(0);

    vPortExitCritical();

    return 0;
}
/*
 * 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;
}
示例#14
0
void
vPortFree(void *p)
{
	vPortEnterCritical();
	msheap_free(p);
	vPortExitCritical();
}
示例#15
0
文件: rs485.c 项目: FlameN/STM32RUNO
bool SendReseive()
    {
    //  vTaskDelay(50);
	GPIO_SetBits(GPIOB, GPIO_Pin_14);
   // AT91F_PIO_SetOutput(AT91C_BASE_PIOA, LED_485);
    vTaskDelay(5);

    processBuffer8to7(rs485buf,rs485size);
    uart3Write ((uint8*) rs485buf, rs485size);
    vTaskDelay(20);
    //AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, LED_485);

    GPIO_ResetBits(GPIOB, GPIO_Pin_14);
    vPortEnterCritical();
    vTaskDelay(1500);

    rs485size = uart3Read((uint8*) rs485buf, 256/*, 3000*/);
    vPortExitCritical();
    if (rs485size == 0)
	return false;
    processBuffer7to8(rs485buf,rs485size);
    vTaskDelay(50);
  //  AT91F_PIO_SetOutput(AT91C_BASE_PIOA, LED_485);
    vTaskDelay(100);
    return true;
    }
/* 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;
}
示例#17
0
bool  scheduler_task::addSharedObject(const char *name, void *obj_ptr)
{
    bool duplicate = false;

    vPortEnterCritical();
    do {
        if (!mpNamePtrPair) {
            mpNamePtrPair = new VECTOR<PtrNamePairType>;
        }

        /* Disallow adding duplicate items by name */
        for(unsigned int i=0; i < mpNamePtrPair->size(); i++) {
            if (0 == strcmp(mpNamePtrPair->at(i).name, name)) {
                duplicate = true;
                break;
            }
        }

        /* Push back to vector */
        PtrNamePairType item;
        item.ptr  = obj_ptr;
        item.name = name;
        mpNamePtrPair->push_back(item);
    } while(0);
    vPortExitCritical();

    return !duplicate;
}
示例#18
0
文件: backup.c 项目: pandc/unitek
void BKP_storeWord(uint16_t bkpidx,uint16_t value)
{
	if (bkpidx >= BKP_DR_NUMBER)
		return;
	vPortEnterCritical();
	BKP_WriteBackupRegister(BKPDataReg[bkpidx],value);
	vPortExitCritical();
}
示例#19
0
static void add_thread_signal_map (osThreadId thread_id, EventGroupHandle_t signals)
{
    int dummy;
//    uint32_t i;
    ThreadSignalRec *prec_entity;

    if (inHandlerMode()) {
        dummy = portSET_INTERRUPT_MASK_FROM_ISR();
    }
    else {
        vPortEnterCritical();
    }

    prec_entity = (ThreadSignalRec*) malloc(sizeof(ThreadSignalRec));

    if (prec_entity != NULL) {
        prec_entity->thread_id = thread_id;
        prec_entity->signals = signals;
        prec_entity->pnext = NULL;
        if (pThreadSignalMapHead == NULL) {
            pThreadSignalMapHead = prec_entity;
            pThreadSignalMapTail = prec_entity;
        }
        else {
            pThreadSignalMapTail->pnext = prec_entity;
            pThreadSignalMapTail = prec_entity;
        }
    }
    else {
        CMSIS_OS_ERR("No Free Thread-Signal entity\n");
    }

#if 0    
    for (i=0;i<THREAD_SIGNAL_MAP_SIZE;i++)
    {
        if (!ThreadSignalMapTable[i].is_in_use) {
            ThreadSignalMapTable[i].is_in_use = 1;
            ThreadSignalMapTable[i].thread_id = thread_id;
            ThreadSignalMapTable[i].signals = signals;
            break;
        }
    }

    if (i >= THREAD_SIGNAL_MAP_SIZE) {
        // No free Thread-Signals map entity
        CMSIS_OS_ERR("No Free Thread-Signal entity\n");
    }

#endif

    if (inHandlerMode()) {
        portCLEAR_INTERRUPT_MASK_FROM_ISR(dummy);
    }
    else {
        vPortExitCritical();
    }

}
示例#20
0
bool CAN_tx (can_t can, can_msg_t *pCanMsg, uint32_t timeout_ms)
{
    volatile LPC_CAN_TypeDef *CANx = CAN_ENUM_TO_REGS(can);
    const uint8_t cidx = CAN_INDEX(can);
    bool ok = false;

    if (!CANx || !pCanMsg) {
        return false;
    }

    /* Try transmitting to one of the available buffers */
    vPortEnterCritical();
    {
        ok = CAN_tx_now(CANx, pCanMsg);
    }
    vPortExitCritical();

    /* If all three buffers are busy, just queue the message */
    if (!ok) {
        if (taskSCHEDULER_RUNNING == xTaskGetSchedulerState()) {
            ok = xQueueSend(g_can_tx_qs[cidx], pCanMsg, OS_MS(timeout_ms));
        }
        else {
            ok = xQueueSendFromISR(g_can_tx_qs[cidx], pCanMsg, NULL);
        }

        /* There is possibility that before we queued the message, we got interrupted
         * and all hw buffers were emptied meanwhile, and our queued message will now
         * sit in the queue forever until another Tx interrupt takes place.
         * So we dequeue it here if all are empty and send it over.
         */
        vPortEnterCritical();
        {
            can_msg_t msg;
            if (tx_all_avail == (CANx->SR & tx_all_avail) &&
                xQueueReceiveFromISR(g_can_tx_qs[cidx], &msg, NULL)
            ) {
                ok = CAN_tx_now(CANx, &msg);
            }
        }
        vPortExitCritical();
    }

    return ok;
}
示例#21
0
文件: backup.c 项目: pandc/unitek
void BKP_storeDWord(uint16_t bkpidx,uint32_t value)
{
	if (bkpidx >= (BKP_DR_NUMBER-1))
		return;
	vPortEnterCritical();
	BKP_WriteBackupRegister(BKPDataReg[bkpidx],(uint16_t)(value >> 16));
	BKP_WriteBackupRegister(BKPDataReg[bkpidx+1],(uint16_t)value);
	vPortExitCritical();
}
/**
 * Leaves a critical section.
 *
 * @param the preivous protection level
 */
void
sys_arch_unprotect(sys_prot_t val)
{
#if RTOS_SAFERTOS
  vPortExitCritical();
#elif RTOS_FREERTOS
  taskEXIT_CRITICAL();
#endif
}
示例#23
0
//extern unsigned char set__;
void mad_synth_frame(struct mad_synth *synth, struct mad_frame /*const*/ *frame)
{
  unsigned int nch, ns;
  static int samplerate=0;
  void (*synth_frame)(struct mad_synth *, struct mad_frame /*const*/ *,
		      unsigned int, unsigned int);

  nch = MAD_NCHANNELS(&frame->header);
  ns  = MAD_NSBSAMPLES(&frame->header);

  synth->pcm.samplerate = frame->header.samplerate;
  
  //--set_dac_sample_rate(synth->pcm.samplerate);
  //while(g_ulFlags!=7);
  
  //if(set__)
  {
    vPortEnterCritical( );
    SoundSetFormat(frame->header.samplerate,16,1);
    //set__=0;
    vPortExitCritical( );
  }
  
  synth->pcm.channels   = nch;
  synth->pcm.length     = 32 * ns;
  samplerate = synth->pcm.samplerate;

  synth_frame = synth_full;

  if (frame->options & MAD_OPTION_HALFSAMPLERATE) {
    synth->pcm.samplerate /= 2;
    synth->pcm.length     /= 2;
    //--set_dac_sample_rate(synth->pcm.samplerate);
    vPortEnterCritical( );
    SoundSetFormat(frame->header.samplerate,16,1);
    vPortExitCritical( );
    synth_frame = synth_half;
  }

  synth_frame(synth, frame, nch, ns);
  synth->phase = (synth->phase + ns) % 16;
}
/*
 * Returns the thread control block for the currently active task. In case
 * 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;
}
/* 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 );
    }
}
示例#26
0
void *
pvPortMalloc(size_t s)
{
	void *p;

	vPortEnterCritical();
	p = msheap_alloc(s);
	vPortExitCritical();

	if (p == NULL && &vApplicationMallocFailedHook != NULL)
		vApplicationMallocFailedHook();

	return p;
}
示例#27
0
/* PendSV is called in place of vPortYield() to request a supervisor
   call.

   The portYIELD macro calls pendSV if it's a software request.

   The libpp and libudhcp libraries also call this function, assuming
   always with arg==2 (but maybe sometimes with arg==1?)

   In the original esp_iot_rtos_sdk implementation, arg was a char. Using an
   enum is ABI-compatible, though.
*/
void IRAM PendSV(enum SVC_ReqType req)
{
	vPortEnterCritical();

	if(req == SVC_Software)
	{
		pending_soft_sv = 1;
	}
	else if(req == SVC_MACLayer)
		pending_maclayer_sv= 1;

	xthal_set_intset(BIT(INUM_SOFT));
	vPortExitCritical();
}
示例#28
0
void USART1_IRQHandler(void) {
  if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
    vPortEnterCritical();

    USART_ClearFlag(USART1, USART_IT_RXNE);
    short unsigned int c = USART_ReceiveData(USART1);

    consoleAppendChar(c);

    vPortExitCritical();

    //USART_putchar(c);
  }
}
示例#29
0
static EventGroupHandle_t find_signal_by_thread (osThreadId thread_id)
{
    EventGroupHandle_t signals_hdl=NULL;
//    uint32_t i;
    int dummy;
    ThreadSignalRec *prec_entity;
    
    if (inHandlerMode()) {
        dummy = portSET_INTERRUPT_MASK_FROM_ISR();
    }
    else {
        vPortEnterCritical();
    }

    prec_entity = pThreadSignalMapHead;
    while (prec_entity != NULL) {
        if (prec_entity->thread_id == thread_id) {
            signals_hdl = prec_entity->signals;
            break;
        }
        else {
            prec_entity = prec_entity->pnext;
        }
    }

#if 0    
    for (i=0;i<THREAD_SIGNAL_MAP_SIZE;i++)
    {
        if ((ThreadSignalMapTable[i].is_in_use)  && 
            (ThreadSignalMapTable[i].thread_id == thread_id)) {
            signals_hdl = ThreadSignalMapTable[i].signals;
            break;
        }
    }
#endif

    if (inHandlerMode()) {
        portCLEAR_INTERRUPT_MASK_FROM_ISR(dummy);
    }
    else {
        vPortExitCritical();
    }

    if (NULL == signals_hdl) {
        CMSIS_OS_ERR("Cannot find the EventGroup Handle by thread_id\n");
    }

    return signals_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. */
    }
}