]> git.donarmstrong.com Git - qmk_firmware.git/blob - tool/mbed/mbed-sdk/libraries/net/lwip/lwip-sys/arch/sys_arch.c
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
[qmk_firmware.git] / tool / mbed / mbed-sdk / libraries / net / lwip / lwip-sys / arch / sys_arch.c
1 /* Copyright (C) 2012 mbed.org, MIT License
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
4  * and associated documentation files (the "Software"), to deal in the Software without restriction,
5  * including without limitation the rights to use, copy, modify, merge, publish, distribute,
6  * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
7  * furnished to do so, subject to the following conditions:
8  *
9  * The above copyright notice and this permission notice shall be included in all copies or
10  * substantial portions of the Software.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
13  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
14  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
15  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17  */
18 #include <string.h>
19
20 /* mbed includes */
21 #include "mbed_error.h"
22 #include "mbed_interface.h"
23 #include "us_ticker_api.h"
24
25 /* lwIP includes. */
26 #include "lwip/opt.h"
27 #include "lwip/debug.h"
28 #include "lwip/def.h"
29 #include "lwip/sys.h"
30 #include "lwip/mem.h"
31
32  #if NO_SYS==1
33 #include "cmsis.h"
34
35 /* Saved total time in ms since timer was enabled */
36 static volatile u32_t systick_timems;
37
38 /* Enable systick rate and interrupt */
39 void SysTick_Init(void) {
40     if (SysTick_Config(SystemCoreClock / 1000)) {
41         while (1);     /* Capture error */
42     }
43 }
44
45 /** \brief  SysTick IRQ handler and timebase management
46  *
47  *  This function keeps a timebase for the sysTick that can be
48  * used for other functions. It also calls an external function
49  * (SysTick_User) that must be defined outside this handler.
50  */
51 void SysTick_Handler(void) {
52     systick_timems++;
53 }
54
55 /* Delay for the specified number of milliSeconds */
56 void osDelay(uint32_t ms) {
57     uint32_t to = ms + systick_timems;
58     while (to > systick_timems);
59 }
60
61 /* Returns the current time in mS. This is needed for the LWIP timers */
62 u32_t sys_now(void) {
63   return (u32_t) systick_timems;
64 }
65
66 #else
67 /* CMSIS-RTOS implementation of the lwip operating system abstraction */
68 #include "arch/sys_arch.h"
69
70 /*---------------------------------------------------------------------------*
71  * Routine:  sys_mbox_new
72  *---------------------------------------------------------------------------*
73  * Description:
74  *      Creates a new mailbox
75  * Inputs:
76  *      sys_mbox_t mbox         -- Handle of mailbox
77  *      int queue_sz            -- Size of elements in the mailbox
78  * Outputs:
79  *      err_t                   -- ERR_OK if message posted, else ERR_MEM
80  *---------------------------------------------------------------------------*/
81 err_t sys_mbox_new(sys_mbox_t *mbox, int queue_sz) {
82     if (queue_sz > MB_SIZE)
83         error("sys_mbox_new size error\n");
84     
85 #ifdef CMSIS_OS_RTX
86     memset(mbox->queue, 0, sizeof(mbox->queue));
87     mbox->def.pool = mbox->queue;
88     mbox->def.queue_sz = queue_sz;
89 #endif
90     mbox->id = osMessageCreate(&mbox->def, NULL);
91     return (mbox->id == NULL) ? (ERR_MEM) : (ERR_OK);
92 }
93
94 /*---------------------------------------------------------------------------*
95  * Routine:  sys_mbox_free
96  *---------------------------------------------------------------------------*
97  * Description:
98  *      Deallocates a mailbox. If there are messages still present in the
99  *      mailbox when the mailbox is deallocated, it is an indication of a
100  *      programming error in lwIP and the developer should be notified.
101  * Inputs:
102  *      sys_mbox_t *mbox         -- Handle of mailbox
103  *---------------------------------------------------------------------------*/
104 void sys_mbox_free(sys_mbox_t *mbox) {
105     osEvent event = osMessageGet(mbox->id, 0);
106     if (event.status == osEventMessage)
107         error("sys_mbox_free error\n");
108 }
109
110 /*---------------------------------------------------------------------------*
111  * Routine:  sys_mbox_post
112  *---------------------------------------------------------------------------*
113  * Description:
114  *      Post the "msg" to the mailbox.
115  * Inputs:
116  *      sys_mbox_t mbox        -- Handle of mailbox
117  *      void *msg              -- Pointer to data to post
118  *---------------------------------------------------------------------------*/
119 void sys_mbox_post(sys_mbox_t *mbox, void *msg) {
120     if (osMessagePut(mbox->id, (uint32_t)msg, osWaitForever) != osOK)
121         error("sys_mbox_post error\n");
122 }
123
124 /*---------------------------------------------------------------------------*
125  * Routine:  sys_mbox_trypost
126  *---------------------------------------------------------------------------*
127  * Description:
128  *      Try to post the "msg" to the mailbox.  Returns immediately with
129  *      error if cannot.
130  * Inputs:
131  *      sys_mbox_t mbox         -- Handle of mailbox
132  *      void *msg               -- Pointer to data to post
133  * Outputs:
134  *      err_t                   -- ERR_OK if message posted, else ERR_MEM
135  *                                  if not.
136  *---------------------------------------------------------------------------*/
137 err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) {
138     osStatus status = osMessagePut(mbox->id, (uint32_t)msg, 0);
139     return (status == osOK) ? (ERR_OK) : (ERR_MEM);
140 }
141
142 /*---------------------------------------------------------------------------*
143  * Routine:  sys_arch_mbox_fetch
144  *---------------------------------------------------------------------------*
145  * Description:
146  *      Blocks the thread until a message arrives in the mailbox, but does
147  *      not block the thread longer than "timeout" milliseconds (similar to
148  *      the sys_arch_sem_wait() function). The "msg" argument is a result
149  *      parameter that is set by the function (i.e., by doing "*msg =
150  *      ptr"). The "msg" parameter maybe NULL to indicate that the message
151  *      should be dropped.
152  *
153  *      The return values are the same as for the sys_arch_sem_wait() function:
154  *      Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
155  *      timeout.
156  *
157  *      Note that a function with a similar name, sys_mbox_fetch(), is
158  *      implemented by lwIP.
159  * Inputs:
160  *      sys_mbox_t mbox         -- Handle of mailbox
161  *      void **msg              -- Pointer to pointer to msg received
162  *      u32_t timeout           -- Number of milliseconds until timeout
163  * Outputs:
164  *      u32_t                   -- SYS_ARCH_TIMEOUT if timeout, else number
165  *                                  of milliseconds until received.
166  *---------------------------------------------------------------------------*/
167 u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) {
168     u32_t start = us_ticker_read();
169     
170     osEvent event = osMessageGet(mbox->id, (timeout != 0)?(timeout):(osWaitForever));
171     if (event.status != osEventMessage)
172         return SYS_ARCH_TIMEOUT;
173     
174     *msg = (void *)event.value.v;
175     
176     return (us_ticker_read() - start) / 1000;
177 }
178
179 /*---------------------------------------------------------------------------*
180  * Routine:  sys_arch_mbox_tryfetch
181  *---------------------------------------------------------------------------*
182  * Description:
183  *      Similar to sys_arch_mbox_fetch, but if message is not ready
184  *      immediately, we'll return with SYS_MBOX_EMPTY.  On success, 0 is
185  *      returned.
186  * Inputs:
187  *      sys_mbox_t mbox         -- Handle of mailbox
188  *      void **msg              -- Pointer to pointer to msg received
189  * Outputs:
190  *      u32_t                   -- SYS_MBOX_EMPTY if no messages.  Otherwise,
191  *                                  return ERR_OK.
192  *---------------------------------------------------------------------------*/
193 u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) {
194     osEvent event = osMessageGet(mbox->id, 0);
195     if (event.status != osEventMessage)
196         return SYS_MBOX_EMPTY;
197     
198     *msg = (void *)event.value.v;
199     
200     return ERR_OK;
201 }
202
203 /*---------------------------------------------------------------------------*
204  * Routine:  sys_sem_new
205  *---------------------------------------------------------------------------*
206  * Description:
207  *      Creates and returns a new semaphore. The "ucCount" argument specifies
208  *      the initial state of the semaphore.
209  *      NOTE: Currently this routine only creates counts of 1 or 0
210  * Inputs:
211  *      sys_sem_t sem         -- Handle of semaphore
212  *      u8_t count            -- Initial count of semaphore
213  * Outputs:
214  *      err_t                 -- ERR_OK if semaphore created
215  *---------------------------------------------------------------------------*/
216 err_t sys_sem_new(sys_sem_t *sem, u8_t count) {
217 #ifdef CMSIS_OS_RTX
218     memset(sem->data, 0, sizeof(uint32_t)*2);
219     sem->def.semaphore = sem->data;
220 #endif
221     sem->id = osSemaphoreCreate(&sem->def, count);
222     if (sem->id == NULL)
223         error("sys_sem_new create error\n");
224     
225     return ERR_OK;
226 }
227
228 /*---------------------------------------------------------------------------*
229  * Routine:  sys_arch_sem_wait
230  *---------------------------------------------------------------------------*
231  * Description:
232  *      Blocks the thread while waiting for the semaphore to be
233  *      signaled. If the "timeout" argument is non-zero, the thread should
234  *      only be blocked for the specified time (measured in
235  *      milliseconds).
236  *
237  *      If the timeout argument is non-zero, the return value is the number of
238  *      milliseconds spent waiting for the semaphore to be signaled. If the
239  *      semaphore wasn't signaled within the specified time, the return value is
240  *      SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore
241  *      (i.e., it was already signaled), the function may return zero.
242  *
243  *      Notice that lwIP implements a function with a similar name,
244  *      sys_sem_wait(), that uses the sys_arch_sem_wait() function.
245  * Inputs:
246  *      sys_sem_t sem           -- Semaphore to wait on
247  *      u32_t timeout           -- Number of milliseconds until timeout
248  * Outputs:
249  *      u32_t                   -- Time elapsed or SYS_ARCH_TIMEOUT.
250  *---------------------------------------------------------------------------*/
251 u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) {
252     u32_t start = us_ticker_read();
253     
254     if (osSemaphoreWait(sem->id, (timeout != 0)?(timeout):(osWaitForever)) < 1)
255         return SYS_ARCH_TIMEOUT;
256     
257     return (us_ticker_read() - start) / 1000;
258 }
259
260 /*---------------------------------------------------------------------------*
261  * Routine:  sys_sem_signal
262  *---------------------------------------------------------------------------*
263  * Description:
264  *      Signals (releases) a semaphore
265  * Inputs:
266  *      sys_sem_t sem           -- Semaphore to signal
267  *---------------------------------------------------------------------------*/
268 void sys_sem_signal(sys_sem_t *data) {
269     if (osSemaphoreRelease(data->id) != osOK)
270         mbed_die(); /* Can be called by ISR do not use printf */
271 }
272
273 /*---------------------------------------------------------------------------*
274  * Routine:  sys_sem_free
275  *---------------------------------------------------------------------------*
276  * Description:
277  *      Deallocates a semaphore
278  * Inputs:
279  *      sys_sem_t sem           -- Semaphore to free
280  *---------------------------------------------------------------------------*/
281 void sys_sem_free(sys_sem_t *sem) {}
282
283 /** Create a new mutex
284  * @param mutex pointer to the mutex to create
285  * @return a new mutex */
286 err_t sys_mutex_new(sys_mutex_t *mutex) {
287 #ifdef CMSIS_OS_RTX
288     memset(mutex->data, 0, sizeof(int32_t)*3);
289     mutex->def.mutex = mutex->data;
290 #endif
291     mutex->id = osMutexCreate(&mutex->def);
292     if (mutex->id == NULL)
293         return ERR_MEM;
294     
295     return ERR_OK;
296 }
297
298 /** Lock a mutex
299  * @param mutex the mutex to lock */
300 void sys_mutex_lock(sys_mutex_t *mutex) {
301     if (osMutexWait(mutex->id, osWaitForever) != osOK)
302         error("sys_mutex_lock error\n");
303 }
304
305 /** Unlock a mutex
306  * @param mutex the mutex to unlock */
307 void sys_mutex_unlock(sys_mutex_t *mutex) {
308     if (osMutexRelease(mutex->id) != osOK)
309         error("sys_mutex_unlock error\n");
310 }
311
312 /** Delete a mutex
313  * @param mutex the mutex to delete */
314 void sys_mutex_free(sys_mutex_t *mutex) {}
315
316 /*---------------------------------------------------------------------------*
317  * Routine:  sys_init
318  *---------------------------------------------------------------------------*
319  * Description:
320  *      Initialize sys arch
321  *---------------------------------------------------------------------------*/
322 osMutexId lwip_sys_mutex;
323 osMutexDef(lwip_sys_mutex);
324
325 void sys_init(void) {
326     us_ticker_read(); // Init sys tick
327     lwip_sys_mutex = osMutexCreate(osMutex(lwip_sys_mutex));
328     if (lwip_sys_mutex == NULL)
329         error("sys_init error\n");
330 }
331
332 /*---------------------------------------------------------------------------*
333  * Routine:  sys_jiffies
334  *---------------------------------------------------------------------------*
335  * Description:
336  *      Used by PPP as a timestamp-ish value
337  *---------------------------------------------------------------------------*/
338 u32_t sys_jiffies(void) {
339     static u32_t jiffies = 0;
340     jiffies += 1 + (us_ticker_read()/10000);
341     return jiffies;
342 }
343
344 /*---------------------------------------------------------------------------*
345  * Routine:  sys_arch_protect
346  *---------------------------------------------------------------------------*
347  * Description:
348  *      This optional function does a "fast" critical region protection and
349  *      returns the previous protection level. This function is only called
350  *      during very short critical regions. An embedded system which supports
351  *      ISR-based drivers might want to implement this function by disabling
352  *      interrupts. Task-based systems might want to implement this by using
353  *      a mutex or disabling tasking. This function should support recursive
354  *      calls from the same task or interrupt. In other words,
355  *      sys_arch_protect() could be called while already protected. In
356  *      that case the return value indicates that it is already protected.
357  *
358  *      sys_arch_protect() is only required if your port is supporting an
359  *      operating system.
360  * Outputs:
361  *      sys_prot_t              -- Previous protection level (not used here)
362  *---------------------------------------------------------------------------*/
363 sys_prot_t sys_arch_protect(void) {
364     if (osMutexWait(lwip_sys_mutex, osWaitForever) != osOK)
365         error("sys_arch_protect error\n");
366     return (sys_prot_t) 1;
367 }
368
369 /*---------------------------------------------------------------------------*
370  * Routine:  sys_arch_unprotect
371  *---------------------------------------------------------------------------*
372  * Description:
373  *      This optional function does a "fast" set of critical region
374  *      protection to the value specified by pval. See the documentation for
375  *      sys_arch_protect() for more information. This function is only
376  *      required if your port is supporting an operating system.
377  * Inputs:
378  *      sys_prot_t              -- Previous protection level (not used here)
379  *---------------------------------------------------------------------------*/
380 void sys_arch_unprotect(sys_prot_t p) {
381     if (osMutexRelease(lwip_sys_mutex) != osOK)
382         error("sys_arch_unprotect error\n");
383 }
384
385 u32_t sys_now(void) {
386     return us_ticker_read() / 1000;
387 }
388
389 void sys_msleep(u32_t ms) {
390     osDelay(ms);
391 }
392
393 // Keep a pool of thread structures
394 static int thread_pool_index = 0;
395 static sys_thread_data_t thread_pool[SYS_THREAD_POOL_N];
396
397 /*---------------------------------------------------------------------------*
398  * Routine:  sys_thread_new
399  *---------------------------------------------------------------------------*
400  * Description:
401  *      Starts a new thread with priority "prio" that will begin its
402  *      execution in the function "thread()". The "arg" argument will be
403  *      passed as an argument to the thread() function. The id of the new
404  *      thread is returned. Both the id and the priority are system
405  *      dependent.
406  * Inputs:
407  *      char *name                -- Name of thread
408  *      void (*thread)(void *arg) -- Pointer to function to run.
409  *      void *arg                 -- Argument passed into function
410  *      int stacksize             -- Required stack amount in bytes
411  *      int priority              -- Thread priority
412  * Outputs:
413  *      sys_thread_t              -- Pointer to thread handle.
414  *---------------------------------------------------------------------------*/
415 sys_thread_t sys_thread_new(const char *pcName,
416                             void (*thread)(void *arg),
417                             void *arg, int stacksize, int priority) {
418     LWIP_DEBUGF(SYS_DEBUG, ("New Thread: %s\n", pcName));
419     
420     if (thread_pool_index >= SYS_THREAD_POOL_N)
421         error("sys_thread_new number error\n");
422     sys_thread_t t = (sys_thread_t)&thread_pool[thread_pool_index];
423     thread_pool_index++;
424     
425 #ifdef CMSIS_OS_RTX
426     t->def.pthread = (os_pthread)thread;
427     t->def.tpriority = (osPriority)priority;
428     t->def.stacksize = stacksize;
429 #ifndef __MBED_CMSIS_RTOS_CA9
430     t->def.stack_pointer = (uint32_t*)malloc(stacksize);
431     if (t->def.stack_pointer == NULL) {
432       error("Error allocating the stack memory");
433     }
434 #endif
435 #endif
436     t->id = osThreadCreate(&t->def, arg);
437     if (t->id == NULL)
438         error("sys_thread_new create error\n");
439     
440     return t;
441 }
442
443 #endif
444
445 #ifdef LWIP_DEBUG
446
447 /** \brief  Displays an error message on assertion
448
449     This function will display an error message on an assertion
450     to the debug output.
451
452     \param[in]    msg   Error message to display
453     \param[in]    line  Line number in file with error
454     \param[in]    file  Filename with error
455  */
456 void assert_printf(char *msg, int line, char *file) {
457     if (msg)
458         error("%s:%d in file %s\n", msg, line, file);
459     else
460         error("LWIP ASSERT\n");
461 }
462
463 #endif /* LWIP_DEBUG */