/* 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. */
+#if !LWIP_COMPAT_MUTEX
/* Create a new mutex */
err_t sys_mutex_new(sys_mutex_t *mutex)
{
*mutex = xSemaphoreCreateMutex();
- if(mutex != NULL)return ERR_OK;
+ if(*mutex != NULL)return ERR_OK;
return ERR_MEM;
}
/* locks a mutex */
-void inline sys_mutex_lock(sys_mutex_t *mutex)
+void sys_mutex_lock(sys_mutex_t *mutex)
{
- xSemaphoreTake(*mutex,0);
+ xSemaphoreTake(*mutex,portMAX_DELAY); /* block time changed from 0 to portMAX_DELAY -- it might break timers! - just testing stability */
}
/* unlocks a mutex */
-void inline sys_mutex_unlock(sys_mutex_t *mutex)
+void 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)
+void sys_mutex_free(sys_mutex_t *mutex)
{
vSemaphoreDelete(*mutex);
}
+#endif
/* 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;
+ if(*sem != NULL)return ERR_OK;
return ERR_MEM;
}
/* signals a semaphore */
-void inline sys_sem_signal(sys_sem_t *sem)
+void sys_sem_signal(sys_sem_t *sem)
{
xSemaphoreGive(*sem);
}
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;
+ if(timeout == 0)
+ {
+ xSemaphoreTake( *sem, portMAX_DELAY );
+ }
+ else
+ {
+ 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)
+void sys_sem_free(sys_sem_t *sem)
{
vSemaphoreDelete(*sem);
}
err_t sys_mbox_new(sys_mbox_t *mbox, int size)
{
*mbox = xQueueCreate( size, sizeof( MBOX_PTR_TYPE ) );
- if(mbox == 0)return ERR_MEM;
+ if(*mbox == NULL)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)
+void sys_mbox_post(sys_mbox_t *mbox, void *msg)
{
- while(xQueueSendToBack(*mbox, msg, portMAX_DELAY) == errQUEUE_FULL);
+ 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)
+ if(xQueueSendToBackFromISR( *mbox, &msg, pxHigherPriorityTaskWoken ) == errQUEUE_FULL)
#else
- if(xQueueSendToBack(*mbox, msg, 0) == errQUEUE_FULL)
+ if(xQueueSendToBack(*mbox, &msg, 0) == errQUEUE_FULL)
#endif
return ERR_MEM;
return ERR_OK;
}
-/* TODO: message which arrives may be NULL */
+/* 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)
{
}
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 */
+/* if message is not present immediately returns SYS_MBOX_EMPTY, on success returns 0 ms */
u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
{
#if TRYFETCH_ISR_SAFE
return 0; /* we waited 0ms */
}
/* deletes a mbox */
-void inline sys_mbox_free(sys_mbox_t *mbox)
+void sys_mbox_free(sys_mbox_t *mbox)
{
vQueueDelete(*mbox);
}
#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
+#if SYS_ARCH_SEMPHR_PROTECT
+sys_mutex_t sys_arch_prot_semphr;
+xTaskHandle protectedTask = NULL;
+#endif /* SYS_ARCH_SEMPHR_PROTECT */
+
+/* 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 */
{
+#if SYS_ARCH_SEMPHR_PROTECT
+ sys_mutex_new(&sys_arch_prot_semphr);
+#endif /* SYS_ARCH_SEMPHR_PROTECT */
}
u32_t sys_jiffies(void)
}
*/
- /* for configTICK_RATE_Hz = 1000; when GetTickCount() fce returns 64-bit unsigned type it holds
+ /* for configTICK_RATE_Hz = 1000; when GetTickCount() fnc 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
+#if !SYS_ARCH_SEMPHR_PROTECT
unsigned int IntMasterStatusGet (void)
{
- return 0;//(unsigned int)(0xC0 & _get_CPSR());
+ return (unsigned int)(0xC0 & _get_CPSR());
}
+#endif /* !SYS_ARCH_SEMPHR_PROTECT */
+
/**
* This function is used to lock access to critical sections when lwipopt.h
* defines SYS_LIGHTWEIGHT_PROT. It disables interrupts and returns a value
*/
sys_prot_t sys_arch_protect(void)
{
+#if !SYS_ARCH_SEMPHR_PROTECT
sys_prot_t status;
status = (IntMasterStatusGet() & 0xFF);
_disable_IRQ();
+ /* while interrupts ethernet related or interrupt for context switch don't use FIQ, we dont need to disable it */
+/* _disable_FIQ(); */
return status;
+#else /* !SYS_ARCH_SEMPHR_PROTECT */
+ taskENTER_CRITICAL();
+ if(protectedTask == xTaskGetCurrentTaskHandle()){ /* if protected task calls nested sys_arch_protect we let it know that it was protected already */
+ taskEXIT_CRITICAL();
+ return TRUE;
+ } else {
+ while(1)
+ {
+ sys_mutex_lock(&sys_arch_prot_semphr);
+ if(protectedTask == NULL)
+ {
+ protectedTask = xTaskGetCurrentTaskHandle();
+ break;
+ }
+ else
+ {
+ sys_mutex_unlock(&sys_arch_prot_semphr); /* we shouldn't get here ever */
+ }
+ }
+ }
+ taskEXIT_CRITICAL();
+ return FALSE;
+#endif /* !SYS_ARCH_SEMPHR_PROTECT */
}
/**
*/
void sys_arch_unprotect(sys_prot_t lev)
{
+#if !SYS_ARCH_SEMPHR_PROTECT
/* 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();
}
+ /* while interrupts ethernet related or interrupt for context switch don't use FIQ, we dont need to protect against it */
+/* if((lev & 0x40) == 0) {
+ _enable_FIQ();
+ }*/
+#else /* !SYS_ARCH_SEMPHR_PROTECT */
+ taskENTER_CRITICAL();
+ if(!lev) /* if task wasn't already protected when sys_arch_protect() was called, unprotect it now */
+ {
+ protectedTask = NULL;
+ sys_mutex_unlock(&sys_arch_prot_semphr);
+ }
+ taskEXIT_CRITICAL();
+#endif /* !SYS_ARCH_SEMPHR_PROTECT */
}
#endif /* SYS_LIGHTWEIGHT_PROT */