X-Git-Url: http://rtime.felk.cvut.cz/gitweb/pes-rpp/rpp-lwip.git/blobdiff_plain/ae300c98a4107458d0aa040c074d89ee9d3ac984..bd4e582d54d4f67c1e047a8624a90b9c4734b99e:/src/arch/sys_arch.c diff --git a/src/arch/sys_arch.c b/src/arch/sys_arch.c new file mode 100644 index 00000000..3724d0b7 --- /dev/null +++ b/src/arch/sys_arch.c @@ -0,0 +1,245 @@ +/** + * @file - sys_arch.c + * System Architecture support routines for HDK devices. + * + */ + +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * 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 + * + */ + +/* Copyright (c) 2010 Texas Instruments Incorporated */ + +/* lwIP includes. */ +#include "arch/sys_arch.h" +#include "lwip/opt.h" +#include "lwip/sys.h" + +#if !NO_SYS +/* DETAILS: ./lwip/doc/sys_arch.txt + * ./lwip/src/include/lwip/sys.h */ + +/* For mutexes you can just set option in opt.h/lwipopts.h LWIP_COMPAT_MUTEX, + * which is using defined semaphores. This is basicaly doing the same thing. */ +/* Create a new mutex */ +err_t sys_mutex_new(sys_mutex_t *mutex) +{ + *mutex = xSemaphoreCreateMutex(); + if(mutex != NULL)return ERR_OK; + return ERR_MEM; +} +/* locks a mutex */ +void inline sys_mutex_lock(sys_mutex_t *mutex) +{ + xSemaphoreTake(*mutex,0); +} +/* unlocks a mutex */ +void inline sys_mutex_unlock(sys_mutex_t *mutex) +{ + xSemaphoreGive(*mutex); +} +/* frees memory space formerly taken by mutex */ +void inline sys_mutex_free(sys_mutex_t *mutex) +{ + vSemaphoreDelete(*mutex); +} + +/* creates a new semaphore */ +err_t sys_sem_new(sys_sem_t *sem, u8_t count) +{ + *sem = xSemaphoreCreateCounting( SEMPHR_MAX_CNT, count); /* it's supposedly possible to use vSemaphoreCreateBinary */ + if(sem != NULL)return ERR_OK; + return ERR_MEM; +} +/* signals a semaphore */ +void inline sys_sem_signal(sys_sem_t *sem) +{ + xSemaphoreGive(*sem); +} +/* blocks thread while waiting for the semaphore */ +u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) +{ + portTickType ticksBeforeSemphr = xTaskGetTickCount(); + if(xSemaphoreTake( *sem, timeout / portTICK_RATE_MS ) == pdFALSE) /* note that it is important for the semaphores to return an accurate count of elapsed milliseconds, since they are used to schedule timers in lwIP */ + return SYS_ARCH_TIMEOUT; + return ( (xTaskGetTickCount() - ticksBeforeSemphr) / portTICK_RATE_MS ); /* return time spent waiting for the semaphore - u can use xTaskGetTickCount() */ +} +/* deletes a semaphore */ +void inline sys_sem_free(sys_sem_t *sem) +{ + vSemaphoreDelete(*sem); +} + +/* creates an empty mailbox for maximum "size" elements */ +err_t sys_mbox_new(sys_mbox_t *mbox, int size) +{ + *mbox = xQueueCreate( size, sizeof( MBOX_PTR_TYPE ) ); + if(mbox == 0)return ERR_MEM; + return ERR_OK; +} +/* posts the "msg" to the mailbox, blocks if mbox full */ +void inline sys_mbox_post(sys_mbox_t *mbox, void *msg) +{ + while(xQueueSendToBack(*mbox, msg, portMAX_DELAY) == errQUEUE_FULL); +} +/* returns ERR_MEM if mailbox is full, ERR_OK if "msg" is posted */ +err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) +{ +#if TRYPOST_ISR_SAFE + signed portBASE_TYPE *pxHigherPriorityTaskWoken; + if(xQueueSendToBackFromISR( *mbox, msg, pxHigherPriorityTaskWoken ) == errQUEUE_FULL) +#else + if(xQueueSendToBack(*mbox, msg, 0) == errQUEUE_FULL) +#endif + return ERR_MEM; + return ERR_OK; +} +/* TODO: message which arrives may be NULL */ +/* blocks the thread until a message arrives in the mailbox or timeout expires */ +u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) +{ + portTickType ticksBeforeFetch = xTaskGetTickCount(); + if(timeout == 0) + { + while(xQueueReceive( *mbox, msg, portMAX_DELAY ) == pdFALSE); + } + else + { + if(xQueueReceive( *mbox, msg, timeout / portTICK_RATE_MS ) == pdFALSE) + return SYS_ARCH_TIMEOUT; + } + return ( (xTaskGetTickCount() - ticksBeforeFetch) / portTICK_RATE_MS ); /* return time spent waiting for the space in the mailbox */ +} +/* if message is not present immediately returns SYS_MBOX_EMPTY, on success returns 0 */ +u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) +{ +#if TRYFETCH_ISR_SAFE + signed portBASE_TYPE *pxTaskWoken; + if(xQueueReceiveFromISR( *mbox, msg, pxTaskWoken ) == pdFALSE) +#else + if(xQueueReceive(*mbox, msg, 0) == pdFALSE) +#endif + return SYS_MBOX_EMPTY; + return 0; /* we waited 0ms */ +} +/* deletes a mbox */ +void inline sys_mbox_free(sys_mbox_t *mbox) +{ + vQueueDelete(*mbox); +} + +sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio) +{ + xTaskHandle *pvCreatedTask = NULL; + if(xTaskCreate(thread, (const signed char *) name, (unsigned short)stacksize, arg, prio, pvCreatedTask) != pdPASS) + return NULL; /* lwIP doesn't specify, how should be informed that thread creation failed */ + return pvCreatedTask; +} + +#endif /* NO_SYS */ + + +/* TODO: research on what put to sys_init() >> + * void sys_init(void). lwIP system initialization. This function is called before the any other + * sys_arch-function is called and is meant to be used to initialize anything that has to be up and + * running for the rest of the functions to work. for example to set up a pool of semaphores. + * This function is called from lwip_init() */ +void sys_init(void) /* initialize sys_arch layer */ +{ +} + +u32_t sys_jiffies(void) +{ + return (u32_t) xTaskGetTickCount(); +} + +/* TODO: consider overflowing */ +u32_t sys_now(void) +{ + return (u32_t) xTaskGetTickCount(); /* this works on condition that portTICK_RATE_MS is 1 */ + /* + portTickType currentTicks = xTaskGetTickCount(); + static portTickType previousTickCount; + if(previousTickCount>currentTicks){ + + } + */ + /* for configTICK_RATE_Hz = 1000; when GetTickCount() fce returns 64-bit unsigned type it holds + about half billion years, for unsigned 32-bit type just about an hour ; ((((2³²)÷1000)÷configTICK_RATE_HZ)÷3600)÷24 */ + /*return (xTaskGetTickCount()*1000 / configTICK_RATE_HZ) ;*/ + +} + + +#if SYS_LIGHTWEIGHT_PROT + +unsigned int IntMasterStatusGet (void) +{ + return 0;//(unsigned int)(0xC0 & _get_CPSR()); +} +/** + * This function is used to lock access to critical sections when lwipopt.h + * defines SYS_LIGHTWEIGHT_PROT. It disables interrupts and returns a value + * indicating the interrupt enable state when the function entered. This + * value must be passed back on the matching call to sys_arch_unprotect(). + * + * @return the interrupt level when the function was entered. + */ +sys_prot_t sys_arch_protect(void) +{ + sys_prot_t status; + status = (IntMasterStatusGet() & 0xFF); + + _disable_IRQ(); + return status; +} + +/** + * This function is used to unlock access to critical sections when lwipopt.h + * defines SYS_LIGHTWEIGHT_PROT. It enables interrupts if the value of the lev + * parameter indicates that they were enabled when the matching call to + * sys_arch_protect() was made. + * + * @param lev is the interrupt level when the matching protect function was + * called + */ +void sys_arch_unprotect(sys_prot_t lev) +{ + /* Only turn interrupts back on if they were originally on when the matching + sys_arch_protect() call was made. */ + if((lev & 0x80) == 0) { + _enable_IRQ(); + } +} + +#endif /* SYS_LIGHTWEIGHT_PROT */ + +