]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lwip.git/blob - src/arch/sys_arch.c
2a1fcac5370c9246d9457b871b7b2cb24b2a5eb0
[pes-rpp/rpp-lwip.git] / src / arch / sys_arch.c
1 /**
2  * @file - sys_arch.c
3  * System Architecture support routines for HDK devices.
4  *
5  */
6
7 /*
8  * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
9  * All rights reserved. 
10  * 
11  * Redistribution and use in source and binary forms, with or without modification, 
12  * are permitted provided that the following conditions are met:
13  *
14  * 1. Redistributions of source code must retain the above copyright notice,
15  *    this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright notice,
17  *    this list of conditions and the following disclaimer in the documentation
18  *    and/or other materials provided with the distribution.
19  * 3. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission. 
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
23  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
24  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
25  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
27  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
30  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
31  * OF SUCH DAMAGE.
32  *
33  * This file is part of the lwIP TCP/IP stack.
34  * 
35  * Author: Adam Dunkels <adam@sics.se>
36  *
37  */
38
39 /* Copyright (c) 2010 Texas Instruments Incorporated */
40
41 /* lwIP includes. */
42 #include "arch/sys_arch.h"
43 #include "lwip/opt.h"
44 #include "lwip/sys.h"
45
46 #if !NO_SYS
47 /* DETAILS: ./lwip/doc/sys_arch.txt
48  *          ./lwip/src/include/lwip/sys.h */
49
50 /* For mutexes you can just set option in opt.h/lwipopts.h LWIP_COMPAT_MUTEX,
51  * which is using defined semaphores. This is basicaly doing the same thing. */
52 #if !LWIP_COMPAT_MUTEX
53 /* Create a new mutex */
54 err_t sys_mutex_new(sys_mutex_t *mutex)
55 {
56         *mutex = xSemaphoreCreateMutex();
57         if(*mutex != NULL)return ERR_OK;
58     return ERR_MEM;
59 }
60 /* locks a mutex */
61 void inline sys_mutex_lock(sys_mutex_t *mutex)
62 {
63         xSemaphoreTake(*mutex,portMAX_DELAY); /* block time changed from 0 to portMAX_DELAY -- it might break timers! - just testing stability */
64 }
65 /* unlocks a mutex */
66 void inline sys_mutex_unlock(sys_mutex_t *mutex)
67 {
68         xSemaphoreGive(*mutex);
69 }
70 /* frees memory space formerly taken by mutex */
71 void inline sys_mutex_free(sys_mutex_t *mutex)
72 {
73         vSemaphoreDelete(*mutex);
74 }
75 #endif
76
77 /* creates a new semaphore */
78 err_t sys_sem_new(sys_sem_t *sem, u8_t count)
79 {
80     *sem = xSemaphoreCreateCounting( SEMPHR_MAX_CNT, count); /* it's supposedly possible to use vSemaphoreCreateBinary */
81     if(*sem != NULL)return ERR_OK;
82     return ERR_MEM;
83 }
84 /* signals a semaphore */
85 void inline sys_sem_signal(sys_sem_t *sem)
86 {
87         xSemaphoreGive(*sem);
88 }
89 /* blocks thread while waiting for the semaphore */
90 u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
91 {
92         portTickType ticksBeforeSemphr = xTaskGetTickCount();
93         if(timeout == 0)
94         {
95                 xSemaphoreTake( *sem, portMAX_DELAY );
96         }
97         else
98         {
99                 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 */
100                         return SYS_ARCH_TIMEOUT;
101         }
102     return ( (xTaskGetTickCount() - ticksBeforeSemphr) / portTICK_RATE_MS ); /* return time spent waiting for the semaphore - u can use xTaskGetTickCount() */
103 }
104 /* deletes a semaphore */
105 void inline sys_sem_free(sys_sem_t *sem)
106 {
107         vSemaphoreDelete(*sem);
108 }
109
110 /* creates an empty mailbox for maximum "size" elements */
111 err_t sys_mbox_new(sys_mbox_t *mbox, int size)
112 {
113         *mbox = xQueueCreate( size, sizeof( MBOX_PTR_TYPE ) );
114         if(*mbox == NULL)return ERR_MEM;
115         return ERR_OK;
116 }
117 /* posts the "msg" to the mailbox, blocks if mbox full */
118 void inline sys_mbox_post(sys_mbox_t *mbox, void *msg)
119 {
120         while(xQueueSendToBack(*mbox, &msg, portMAX_DELAY) == errQUEUE_FULL);
121 }
122 /* returns ERR_MEM if mailbox is full, ERR_OK if "msg" is posted */
123 err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
124 {
125 #if TRYPOST_ISR_SAFE
126         signed portBASE_TYPE *pxHigherPriorityTaskWoken;
127         if(xQueueSendToBackFromISR( *mbox, &msg, pxHigherPriorityTaskWoken ) == errQUEUE_FULL)
128 #else
129     if(xQueueSendToBack(*mbox, &msg, 0) == errQUEUE_FULL)
130 #endif
131                 return ERR_MEM;
132         return ERR_OK;
133 }
134 /* message which arrives may be NULL */
135 /* blocks the thread until a message arrives in the mailbox or timeout expires */
136 u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
137 {
138         portTickType ticksBeforeFetch = xTaskGetTickCount();
139         if(timeout == 0)
140         {
141                 while(xQueueReceive( *mbox, msg, portMAX_DELAY ) == pdFALSE);
142         }
143         else
144         {
145                 if(xQueueReceive( *mbox, msg, timeout / portTICK_RATE_MS ) == pdFALSE)
146                         return SYS_ARCH_TIMEOUT;
147         }
148         return ( (xTaskGetTickCount() - ticksBeforeFetch) / portTICK_RATE_MS ); /* return time spent waiting for the space in the mailbox */
149 }
150 /* if message is not present immediately returns SYS_MBOX_EMPTY, on success returns 0 ms */
151 u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
152 {
153 #if TRYFETCH_ISR_SAFE
154         signed portBASE_TYPE *pxTaskWoken;
155         if(xQueueReceiveFromISR( *mbox, msg, pxTaskWoken ) == pdFALSE)
156 #else
157     if(xQueueReceive(*mbox, msg, 0) == pdFALSE)
158 #endif
159         return SYS_MBOX_EMPTY;
160         return 0; /* we waited 0ms */
161 }
162 /* deletes a mbox */
163 void inline sys_mbox_free(sys_mbox_t *mbox)
164 {
165         vQueueDelete(*mbox);
166 }
167
168 sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio)
169 {
170         xTaskHandle *pvCreatedTask = NULL;
171         if(xTaskCreate(thread, (const signed char *) name, (unsigned short)stacksize, arg, prio, pvCreatedTask) != pdPASS)
172                 return NULL; /* lwIP doesn't specify, how should be informed that thread creation failed */
173         return pvCreatedTask;
174 }
175
176 #endif /* NO_SYS */
177
178 #if SYS_ARCH_SEMPHR_PROTECT
179 sys_mutex_t sys_arch_prot_semphr;
180 #endif /* SYS_ARCH_SEMPHR_PROTECT */
181
182 /* void sys_init(void). lwIP system initialization. This function is called before the any other
183  * sys_arch-function is called and is meant to be used to initialize anything that has to be up and
184  * running for the rest of the functions to work. for example to set up a pool of semaphores.
185  * This function is called from lwip_init() */
186 void sys_init(void) /* initialize sys_arch layer */
187 {
188 #if SYS_ARCH_SEMPHR_PROTECT
189         sys_mutex_new(&sys_arch_prot_semphr);
190 #endif /* SYS_ARCH_SEMPHR_PROTECT */
191 }
192
193 u32_t sys_jiffies(void)
194 {
195     return (u32_t) xTaskGetTickCount();
196 }
197
198 /* TODO: consider overflowing */
199 u32_t sys_now(void)
200 {
201         return (u32_t) xTaskGetTickCount(); /* this works on condition that portTICK_RATE_MS is 1 */
202         /*
203         portTickType currentTicks = xTaskGetTickCount();
204         static portTickType previousTickCount;
205         if(previousTickCount>currentTicks){
206
207         }
208         */
209         /* for configTICK_RATE_Hz = 1000; when GetTickCount() fnc returns 64-bit unsigned type it holds
210        about half billion years, for unsigned 32-bit type just about an hour ; ((((2³²)÷1000)÷configTICK_RATE_HZ)÷3600)÷24 */
211         /*return (xTaskGetTickCount()*1000 / configTICK_RATE_HZ) ;*/
212
213 }
214
215
216 #if SYS_LIGHTWEIGHT_PROT
217
218 #if !SYS_ARCH_SEMPHR_PROTECT
219 unsigned int IntMasterStatusGet (void)
220 {
221     return (unsigned int)(0xC0 & _get_CPSR());
222 }
223 #endif /* !SYS_ARCH_SEMPHR_PROTECT */
224
225 /**
226  * This function is used to lock access to critical sections when lwipopt.h
227  * defines SYS_LIGHTWEIGHT_PROT. It disables interrupts and returns a value
228  * indicating the interrupt enable state when the function entered. This
229  * value must be passed back on the matching call to sys_arch_unprotect().
230  *
231  * @return the interrupt level when the function was entered.
232  */
233 sys_prot_t sys_arch_protect(void)
234 {
235 #if !SYS_ARCH_SEMPHR_PROTECT
236     sys_prot_t status;
237     status = (IntMasterStatusGet() & 0xFF);
238
239     _disable_IRQ();
240     _disable_FIQ();
241     return status;
242 #else /* !SYS_ARCH_SEMPHR_PROTECT */
243     if(xSemaphoreTake(sys_arch_prot_semphr,0) == pdFALSE) /* if semphr was already taken */
244     {
245         return TRUE;
246     }
247     else
248     {
249         return FALSE;
250     }
251 #endif /* !SYS_ARCH_SEMPHR_PROTECT */
252 }
253
254 /**
255  * This function is used to unlock access to critical sections when lwipopt.h
256  * defines SYS_LIGHTWEIGHT_PROT. It enables interrupts if the value of the lev
257  * parameter indicates that they were enabled when the matching call to
258  * sys_arch_protect() was made.
259  *
260  * @param lev is the interrupt level when the matching protect function was
261  * called
262  */
263 void sys_arch_unprotect(sys_prot_t lev)
264 {
265 #if !SYS_ARCH_SEMPHR_PROTECT
266     /* Only turn interrupts back on if they were originally on when the matching
267        sys_arch_protect() call was made. */
268     if((lev & 0x80) == 0) {
269         _enable_IRQ();
270     }
271     if((lev & 0x40) == 0) {
272         _enable_FIQ();
273     }
274 #else /* !SYS_ARCH_SEMPHR_PROTECT */
275     if(!lev) /* if semaphore was unlocked */
276     {
277         sys_mutex_unlock(&sys_arch_prot_semphr);
278     }
279 #endif /* !SYS_ARCH_SEMPHR_PROTECT */
280 }
281
282 #endif /* SYS_LIGHTWEIGHT_PROT */
283
284