Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of lwip-sys by
sys_arch.c
00001 /* Copyright (C) 2012 mbed.org, MIT License 00002 * 00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00004 * and associated documentation files (the "Software"), to deal in the Software without restriction, 00005 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 00006 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 00007 * furnished to do so, subject to the following conditions: 00008 * 00009 * The above copyright notice and this permission notice shall be included in all copies or 00010 * substantial portions of the Software. 00011 * 00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00017 */ 00018 #include <string.h> 00019 00020 /* mbed includes */ 00021 //#include "error.h" 00022 #include "mbed_interface.h" 00023 #include "us_ticker_api.h" 00024 00025 /* lwIP includes. */ 00026 #include "lwip/opt.h" 00027 #include "lwip/debug.h" 00028 #include "lwip/def.h" 00029 #include "lwip/sys.h" 00030 #include "lwip/mem.h" 00031 00032 #if NO_SYS==1 00033 #include "cmsis.h" 00034 00035 /* Saved total time in ms since timer was enabled */ 00036 static volatile u32_t systick_timems; 00037 00038 /* Enable systick rate and interrupt */ 00039 void SysTick_Init(void) { 00040 if (SysTick_Config(SystemCoreClock / 1000)) { 00041 while (1); /* Capture error */ 00042 } 00043 } 00044 00045 /** \brief SysTick IRQ handler and timebase management 00046 * 00047 * This function keeps a timebase for the sysTick that can be 00048 * used for other functions. It also calls an external function 00049 * (SysTick_User) that must be defined outside this handler. 00050 */ 00051 void SysTick_Handler(void) { 00052 systick_timems++; 00053 } 00054 00055 /* Delay for the specified number of milliSeconds */ 00056 void osDelay(uint32_t ms) { 00057 uint32_t to = ms + systick_timems; 00058 while (to > systick_timems); 00059 } 00060 00061 /* Returns the current time in mS. This is needed for the LWIP timers */ 00062 u32_t sys_now(void) { 00063 return (u32_t) systick_timems; 00064 } 00065 00066 #else 00067 /* CMSIS-RTOS implementation of the lwip operating system abstraction */ 00068 #include "arch/sys_arch.h" 00069 00070 /*---------------------------------------------------------------------------* 00071 * Routine: sys_mbox_new 00072 *---------------------------------------------------------------------------* 00073 * Description: 00074 * Creates a new mailbox 00075 * Inputs: 00076 * sys_mbox_t mbox -- Handle of mailbox 00077 * int queue_sz -- Size of elements in the mailbox 00078 * Outputs: 00079 * err_t -- ERR_OK if message posted, else ERR_MEM 00080 *---------------------------------------------------------------------------*/ 00081 err_t sys_mbox_new(sys_mbox_t *mbox, int queue_sz) { 00082 if (queue_sz > MB_SIZE) 00083 error("sys_mbox_new size error\n"); 00084 00085 #ifdef CMSIS_OS_RTX 00086 memset(mbox->queue, 0, sizeof(mbox->queue)); 00087 mbox->def.pool = mbox->queue; 00088 mbox->def.queue_sz = queue_sz; 00089 #endif 00090 mbox->id = osMessageCreate(&mbox->def, NULL); 00091 return (mbox->id == NULL) ? (ERR_MEM) : (ERR_OK); 00092 } 00093 00094 /*---------------------------------------------------------------------------* 00095 * Routine: sys_mbox_free 00096 *---------------------------------------------------------------------------* 00097 * Description: 00098 * Deallocates a mailbox. If there are messages still present in the 00099 * mailbox when the mailbox is deallocated, it is an indication of a 00100 * programming error in lwIP and the developer should be notified. 00101 * Inputs: 00102 * sys_mbox_t *mbox -- Handle of mailbox 00103 *---------------------------------------------------------------------------*/ 00104 void sys_mbox_free(sys_mbox_t *mbox) { 00105 osEvent event = osMessageGet(mbox->id, 0); 00106 if (event.status == osEventMessage) 00107 error("sys_mbox_free error\n"); 00108 } 00109 00110 /*---------------------------------------------------------------------------* 00111 * Routine: sys_mbox_post 00112 *---------------------------------------------------------------------------* 00113 * Description: 00114 * Post the "msg" to the mailbox. 00115 * Inputs: 00116 * sys_mbox_t mbox -- Handle of mailbox 00117 * void *msg -- Pointer to data to post 00118 *---------------------------------------------------------------------------*/ 00119 void sys_mbox_post(sys_mbox_t *mbox, void *msg) { 00120 if (osMessagePut(mbox->id, (uint32_t)msg, osWaitForever) != osOK) 00121 error("sys_mbox_post error\n"); 00122 } 00123 00124 /*---------------------------------------------------------------------------* 00125 * Routine: sys_mbox_trypost 00126 *---------------------------------------------------------------------------* 00127 * Description: 00128 * Try to post the "msg" to the mailbox. Returns immediately with 00129 * error if cannot. 00130 * Inputs: 00131 * sys_mbox_t mbox -- Handle of mailbox 00132 * void *msg -- Pointer to data to post 00133 * Outputs: 00134 * err_t -- ERR_OK if message posted, else ERR_MEM 00135 * if not. 00136 *---------------------------------------------------------------------------*/ 00137 err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) { 00138 osStatus status = osMessagePut(mbox->id, (uint32_t)msg, 0); 00139 return (status == osOK) ? (ERR_OK) : (ERR_MEM); 00140 } 00141 00142 /*---------------------------------------------------------------------------* 00143 * Routine: sys_arch_mbox_fetch 00144 *---------------------------------------------------------------------------* 00145 * Description: 00146 * Blocks the thread until a message arrives in the mailbox, but does 00147 * not block the thread longer than "timeout" milliseconds (similar to 00148 * the sys_arch_sem_wait() function). The "msg" argument is a result 00149 * parameter that is set by the function (i.e., by doing "*msg = 00150 * ptr"). The "msg" parameter maybe NULL to indicate that the message 00151 * should be dropped. 00152 * 00153 * The return values are the same as for the sys_arch_sem_wait() function: 00154 * Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a 00155 * timeout. 00156 * 00157 * Note that a function with a similar name, sys_mbox_fetch(), is 00158 * implemented by lwIP. 00159 * Inputs: 00160 * sys_mbox_t mbox -- Handle of mailbox 00161 * void **msg -- Pointer to pointer to msg received 00162 * u32_t timeout -- Number of milliseconds until timeout 00163 * Outputs: 00164 * u32_t -- SYS_ARCH_TIMEOUT if timeout, else number 00165 * of milliseconds until received. 00166 *---------------------------------------------------------------------------*/ 00167 u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) { 00168 u32_t start = us_ticker_read(); 00169 00170 osEvent event = osMessageGet(mbox->id, (timeout != 0)?(timeout):(osWaitForever)); 00171 if (event.status != osEventMessage) 00172 return SYS_ARCH_TIMEOUT; 00173 00174 *msg = (void *)event.value.v; 00175 00176 return (us_ticker_read() - start) / 1000; 00177 } 00178 00179 /*---------------------------------------------------------------------------* 00180 * Routine: sys_arch_mbox_tryfetch 00181 *---------------------------------------------------------------------------* 00182 * Description: 00183 * Similar to sys_arch_mbox_fetch, but if message is not ready 00184 * immediately, we'll return with SYS_MBOX_EMPTY. On success, 0 is 00185 * returned. 00186 * Inputs: 00187 * sys_mbox_t mbox -- Handle of mailbox 00188 * void **msg -- Pointer to pointer to msg received 00189 * Outputs: 00190 * u32_t -- SYS_MBOX_EMPTY if no messages. Otherwise, 00191 * return ERR_OK. 00192 *---------------------------------------------------------------------------*/ 00193 u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) { 00194 osEvent event = osMessageGet(mbox->id, 0); 00195 if (event.status != osEventMessage) 00196 return SYS_MBOX_EMPTY; 00197 00198 *msg = (void *)event.value.v; 00199 00200 return ERR_OK; 00201 } 00202 00203 /*---------------------------------------------------------------------------* 00204 * Routine: sys_sem_new 00205 *---------------------------------------------------------------------------* 00206 * Description: 00207 * Creates and returns a new semaphore. The "ucCount" argument specifies 00208 * the initial state of the semaphore. 00209 * NOTE: Currently this routine only creates counts of 1 or 0 00210 * Inputs: 00211 * sys_sem_t sem -- Handle of semaphore 00212 * u8_t count -- Initial count of semaphore 00213 * Outputs: 00214 * err_t -- ERR_OK if semaphore created 00215 *---------------------------------------------------------------------------*/ 00216 err_t sys_sem_new(sys_sem_t *sem, u8_t count) { 00217 #ifdef CMSIS_OS_RTX 00218 memset(sem->data, 0, sizeof(uint32_t)*2); 00219 sem->def.semaphore = sem->data; 00220 #endif 00221 sem->id = osSemaphoreCreate(&sem->def, count); 00222 if (sem->id == NULL) 00223 error("sys_sem_new create error\n"); 00224 00225 return ERR_OK; 00226 } 00227 00228 /*---------------------------------------------------------------------------* 00229 * Routine: sys_arch_sem_wait 00230 *---------------------------------------------------------------------------* 00231 * Description: 00232 * Blocks the thread while waiting for the semaphore to be 00233 * signaled. If the "timeout" argument is non-zero, the thread should 00234 * only be blocked for the specified time (measured in 00235 * milliseconds). 00236 * 00237 * If the timeout argument is non-zero, the return value is the number of 00238 * milliseconds spent waiting for the semaphore to be signaled. If the 00239 * semaphore wasn't signaled within the specified time, the return value is 00240 * SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore 00241 * (i.e., it was already signaled), the function may return zero. 00242 * 00243 * Notice that lwIP implements a function with a similar name, 00244 * sys_sem_wait(), that uses the sys_arch_sem_wait() function. 00245 * Inputs: 00246 * sys_sem_t sem -- Semaphore to wait on 00247 * u32_t timeout -- Number of milliseconds until timeout 00248 * Outputs: 00249 * u32_t -- Time elapsed or SYS_ARCH_TIMEOUT. 00250 *---------------------------------------------------------------------------*/ 00251 u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) { 00252 u32_t start = us_ticker_read(); 00253 00254 if (osSemaphoreWait(sem->id, (timeout != 0)?(timeout):(osWaitForever)) < 1) 00255 return SYS_ARCH_TIMEOUT; 00256 00257 return (us_ticker_read() - start) / 1000; 00258 } 00259 00260 /*---------------------------------------------------------------------------* 00261 * Routine: sys_sem_signal 00262 *---------------------------------------------------------------------------* 00263 * Description: 00264 * Signals (releases) a semaphore 00265 * Inputs: 00266 * sys_sem_t sem -- Semaphore to signal 00267 *---------------------------------------------------------------------------*/ 00268 void sys_sem_signal(sys_sem_t *data) { 00269 if (osSemaphoreRelease(data->id) != osOK) 00270 mbed_die(); /* Can be called by ISR do not use printf */ 00271 } 00272 00273 /*---------------------------------------------------------------------------* 00274 * Routine: sys_sem_free 00275 *---------------------------------------------------------------------------* 00276 * Description: 00277 * Deallocates a semaphore 00278 * Inputs: 00279 * sys_sem_t sem -- Semaphore to free 00280 *---------------------------------------------------------------------------*/ 00281 void sys_sem_free(sys_sem_t *sem) {} 00282 00283 /** Create a new mutex 00284 * @param mutex pointer to the mutex to create 00285 * @return a new mutex */ 00286 err_t sys_mutex_new(sys_mutex_t *mutex) { 00287 #ifdef CMSIS_OS_RTX 00288 memset(mutex->data, 0, sizeof(int32_t)*3); 00289 mutex->def.mutex = mutex->data; 00290 #endif 00291 mutex->id = osMutexCreate(&mutex->def); 00292 if (mutex->id == NULL) 00293 return ERR_MEM; 00294 00295 return ERR_OK; 00296 } 00297 00298 /** Lock a mutex 00299 * @param mutex the mutex to lock */ 00300 void sys_mutex_lock(sys_mutex_t *mutex) { 00301 if (osMutexWait(mutex->id, osWaitForever) != osOK) 00302 error("sys_mutex_lock error\n"); 00303 } 00304 00305 /** Unlock a mutex 00306 * @param mutex the mutex to unlock */ 00307 void sys_mutex_unlock(sys_mutex_t *mutex) { 00308 if (osMutexRelease(mutex->id) != osOK) 00309 error("sys_mutex_unlock error\n"); 00310 } 00311 00312 /** Delete a mutex 00313 * @param mutex the mutex to delete */ 00314 void sys_mutex_free(sys_mutex_t *mutex) {} 00315 00316 /*---------------------------------------------------------------------------* 00317 * Routine: sys_init 00318 *---------------------------------------------------------------------------* 00319 * Description: 00320 * Initialize sys arch 00321 *---------------------------------------------------------------------------*/ 00322 osMutexId lwip_sys_mutex; 00323 osMutexDef(lwip_sys_mutex); 00324 00325 void sys_init(void) { 00326 us_ticker_read(); // Init sys tick 00327 lwip_sys_mutex = osMutexCreate(osMutex(lwip_sys_mutex)); 00328 if (lwip_sys_mutex == NULL) 00329 error("sys_init error\n"); 00330 } 00331 00332 /*---------------------------------------------------------------------------* 00333 * Routine: sys_jiffies 00334 *---------------------------------------------------------------------------* 00335 * Description: 00336 * Used by PPP as a timestamp-ish value 00337 *---------------------------------------------------------------------------*/ 00338 u32_t sys_jiffies(void) { 00339 static u32_t jiffies = 0; 00340 jiffies += 1 + (us_ticker_read()/10000); 00341 return jiffies; 00342 } 00343 00344 /*---------------------------------------------------------------------------* 00345 * Routine: sys_arch_protect 00346 *---------------------------------------------------------------------------* 00347 * Description: 00348 * This optional function does a "fast" critical region protection and 00349 * returns the previous protection level. This function is only called 00350 * during very short critical regions. An embedded system which supports 00351 * ISR-based drivers might want to implement this function by disabling 00352 * interrupts. Task-based systems might want to implement this by using 00353 * a mutex or disabling tasking. This function should support recursive 00354 * calls from the same task or interrupt. In other words, 00355 * sys_arch_protect() could be called while already protected. In 00356 * that case the return value indicates that it is already protected. 00357 * 00358 * sys_arch_protect() is only required if your port is supporting an 00359 * operating system. 00360 * Outputs: 00361 * sys_prot_t -- Previous protection level (not used here) 00362 *---------------------------------------------------------------------------*/ 00363 sys_prot_t sys_arch_protect(void) { 00364 if (osMutexWait(lwip_sys_mutex, osWaitForever) != osOK) 00365 error("sys_arch_protect error\n"); 00366 return (sys_prot_t) 1; 00367 } 00368 00369 /*---------------------------------------------------------------------------* 00370 * Routine: sys_arch_unprotect 00371 *---------------------------------------------------------------------------* 00372 * Description: 00373 * This optional function does a "fast" set of critical region 00374 * protection to the value specified by pval. See the documentation for 00375 * sys_arch_protect() for more information. This function is only 00376 * required if your port is supporting an operating system. 00377 * Inputs: 00378 * sys_prot_t -- Previous protection level (not used here) 00379 *---------------------------------------------------------------------------*/ 00380 void sys_arch_unprotect(sys_prot_t p) { 00381 if (osMutexRelease(lwip_sys_mutex) != osOK) 00382 error("sys_arch_unprotect error\n"); 00383 } 00384 00385 u32_t sys_now(void) { 00386 return us_ticker_read() / 1000; 00387 } 00388 00389 void sys_msleep(u32_t ms) { 00390 osDelay(ms); 00391 } 00392 00393 // Keep a pool of thread structures 00394 static int thread_pool_index = 0; 00395 static sys_thread_data_t thread_pool[SYS_THREAD_POOL_N]; 00396 00397 /*---------------------------------------------------------------------------* 00398 * Routine: sys_thread_new 00399 *---------------------------------------------------------------------------* 00400 * Description: 00401 * Starts a new thread with priority "prio" that will begin its 00402 * execution in the function "thread()". The "arg" argument will be 00403 * passed as an argument to the thread() function. The id of the new 00404 * thread is returned. Both the id and the priority are system 00405 * dependent. 00406 * Inputs: 00407 * char *name -- Name of thread 00408 * void (*thread)(void *arg) -- Pointer to function to run. 00409 * void *arg -- Argument passed into function 00410 * int stacksize -- Required stack amount in bytes 00411 * int priority -- Thread priority 00412 * Outputs: 00413 * sys_thread_t -- Pointer to thread handle. 00414 *---------------------------------------------------------------------------*/ 00415 sys_thread_t sys_thread_new(const char *pcName, 00416 void (*thread)(void *arg), 00417 void *arg, int stacksize, int priority) { 00418 LWIP_DEBUGF(SYS_DEBUG, ("New Thread: %s\n", pcName)); 00419 00420 if (thread_pool_index >= SYS_THREAD_POOL_N) 00421 error("sys_thread_new number error\n"); 00422 sys_thread_t t = (sys_thread_t)&thread_pool[thread_pool_index]; 00423 thread_pool_index++; 00424 00425 #ifdef CMSIS_OS_RTX 00426 t->def.pthread = (os_pthread)thread; 00427 t->def.tpriority = (osPriority)priority; 00428 t->def.stacksize = stacksize; 00429 t->def.stack_pointer = (unsigned char*)malloc(stacksize); 00430 if (t->def.stack_pointer == NULL) { 00431 error("Error allocating the stack memory"); 00432 } 00433 #endif 00434 t->id = osThreadCreate(&t->def, arg); 00435 if (t->id == NULL) 00436 error("sys_thread_new create error\n"); 00437 00438 return t; 00439 } 00440 00441 #endif 00442 00443 #ifdef LWIP_DEBUG 00444 00445 /** \brief Displays an error message on assertion 00446 00447 This function will display an error message on an assertion 00448 to the debug output. 00449 00450 \param[in] msg Error message to display 00451 \param[in] line Line number in file with error 00452 \param[in] file Filename with error 00453 */ 00454 void assert_printf(char *msg, int line, char *file) { 00455 if (msg) 00456 error("%s:%d in file %s\n", msg, line, file); 00457 else 00458 error("LWIP ASSERT\n"); 00459 } 00460 00461 #endif /* LWIP_DEBUG */
Generated on Sat Jul 30 2022 07:35:49 by
1.7.2
