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.
Dependents: mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510
lwip_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 "mbed_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 /* Define the heap ourselves to give us section placement control */ 00033 #ifndef ETHMEM_SECTION 00034 #if defined(TARGET_LPC4088) || defined(TARGET_LPC4088_DM) 00035 # if defined (__ICCARM__) 00036 # define ETHMEM_SECTION 00037 # elif defined(TOOLCHAIN_GCC_CR) 00038 # define ETHMEM_SECTION __attribute__((section(".data.$RamPeriph32"))) 00039 # else 00040 # define ETHMEM_SECTION __attribute__((section("AHBSRAM1"),aligned)) 00041 # endif 00042 #elif defined(TARGET_LPC1768) 00043 # if defined (__ICCARM__) 00044 # define ETHMEM_SECTION 00045 # elif defined(TOOLCHAIN_GCC_CR) 00046 # define ETHMEM_SECTION __attribute__((section(".data.$RamPeriph32"))) 00047 # else 00048 # define ETHMEM_SECTION __attribute__((section("AHBSRAM0"),aligned)) 00049 # endif 00050 #else 00051 #define ETHMEM_SECTION 00052 #endif 00053 #endif 00054 00055 /* LWIP's mem.c doesn't give visibility of its overhead; memory area has to be big 00056 * enough to hold "MEM_SIZE" (which we specify) plus mem.c's overhead. Have to work 00057 * it all out here, copying code from mem.c */ 00058 struct mem { 00059 /** index (-> ram[next]) of the next struct */ 00060 mem_size_t next; 00061 /** index (-> ram[prev]) of the previous struct */ 00062 mem_size_t prev; 00063 /** 1: this area is used; 0: this area is unused */ 00064 u8_t used; 00065 }; 00066 00067 #define SIZEOF_STRUCT_MEM LWIP_MEM_ALIGN_SIZE(sizeof(struct mem)) 00068 #define MEM_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEM_SIZE) 00069 00070 #if defined (__ICCARM__) 00071 #pragma location = ".ethusbram" 00072 #endif 00073 LWIP_DECLARE_MEMORY_ALIGNED(lwip_ram_heap, MEM_SIZE_ALIGNED + (2U*SIZEOF_STRUCT_MEM)) ETHMEM_SECTION; 00074 00075 #if NO_SYS==1 00076 #include "cmsis.h" 00077 00078 /* Saved total time in ms since timer was enabled */ 00079 static volatile u32_t systick_timems; 00080 00081 /* Enable systick rate and interrupt */ 00082 void SysTick_Init(void) { 00083 if (SysTick_Config(SystemCoreClock / 1000)) { 00084 while (1); /* Capture error */ 00085 } 00086 } 00087 00088 /** \brief SysTick IRQ handler and timebase management 00089 * 00090 * This function keeps a timebase for the sysTick that can be 00091 * used for other functions. It also calls an external function 00092 * (SysTick_User) that must be defined outside this handler. 00093 */ 00094 void SysTick_Handler(void) { 00095 systick_timems++; 00096 } 00097 00098 /* Delay for the specified number of milliSeconds */ 00099 void osDelay(uint32_t ms) { 00100 uint32_t to = ms + systick_timems; 00101 while (to > systick_timems); 00102 } 00103 00104 /* Returns the current time in mS. This is needed for the LWIP timers */ 00105 u32_t sys_now(void) { 00106 return (u32_t) systick_timems; 00107 } 00108 00109 #else 00110 /* CMSIS-RTOS implementation of the lwip operating system abstraction */ 00111 #include "arch/sys_arch.h" 00112 00113 /*---------------------------------------------------------------------------* 00114 * Routine: sys_mbox_new 00115 *---------------------------------------------------------------------------* 00116 * Description: 00117 * Creates a new mailbox 00118 * Inputs: 00119 * sys_mbox_t mbox -- Handle of mailbox 00120 * int queue_sz -- Size of elements in the mailbox 00121 * Outputs: 00122 * err_t -- ERR_OK if message posted, else ERR_MEM 00123 *---------------------------------------------------------------------------*/ 00124 err_t sys_mbox_new(sys_mbox_t *mbox, int queue_sz) { 00125 if (queue_sz > MB_SIZE) 00126 error("sys_mbox_new size error\n"); 00127 00128 #ifdef CMSIS_OS_RTX 00129 memset(mbox->queue, 0, sizeof(mbox->queue)); 00130 mbox->def.pool = mbox->queue; 00131 mbox->def.queue_sz = queue_sz; 00132 #endif 00133 mbox->id = osMessageCreate(&mbox->def, NULL); 00134 return (mbox->id == NULL) ? (ERR_MEM) : (ERR_OK); 00135 } 00136 00137 /*---------------------------------------------------------------------------* 00138 * Routine: sys_mbox_free 00139 *---------------------------------------------------------------------------* 00140 * Description: 00141 * Deallocates a mailbox. If there are messages still present in the 00142 * mailbox when the mailbox is deallocated, it is an indication of a 00143 * programming error in lwIP and the developer should be notified. 00144 * Inputs: 00145 * sys_mbox_t *mbox -- Handle of mailbox 00146 *---------------------------------------------------------------------------*/ 00147 void sys_mbox_free(sys_mbox_t *mbox) { 00148 osEvent event = osMessageGet(mbox->id, 0); 00149 if (event.status == osEventMessage) 00150 error("sys_mbox_free error\n"); 00151 } 00152 00153 /*---------------------------------------------------------------------------* 00154 * Routine: sys_mbox_post 00155 *---------------------------------------------------------------------------* 00156 * Description: 00157 * Post the "msg" to the mailbox. 00158 * Inputs: 00159 * sys_mbox_t mbox -- Handle of mailbox 00160 * void *msg -- Pointer to data to post 00161 *---------------------------------------------------------------------------*/ 00162 void sys_mbox_post(sys_mbox_t *mbox, void *msg) { 00163 if (osMessagePut(mbox->id, (uint32_t)msg, osWaitForever) != osOK) 00164 error("sys_mbox_post error\n"); 00165 } 00166 00167 /*---------------------------------------------------------------------------* 00168 * Routine: sys_mbox_trypost 00169 *---------------------------------------------------------------------------* 00170 * Description: 00171 * Try to post the "msg" to the mailbox. Returns immediately with 00172 * error if cannot. 00173 * Inputs: 00174 * sys_mbox_t mbox -- Handle of mailbox 00175 * void *msg -- Pointer to data to post 00176 * Outputs: 00177 * err_t -- ERR_OK if message posted, else ERR_MEM 00178 * if not. 00179 *---------------------------------------------------------------------------*/ 00180 err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) { 00181 osStatus status = osMessagePut(mbox->id, (uint32_t)msg, 0); 00182 return (status == osOK) ? (ERR_OK) : (ERR_MEM); 00183 } 00184 00185 /*---------------------------------------------------------------------------* 00186 * Routine: sys_arch_mbox_fetch 00187 *---------------------------------------------------------------------------* 00188 * Description: 00189 * Blocks the thread until a message arrives in the mailbox, but does 00190 * not block the thread longer than "timeout" milliseconds (similar to 00191 * the sys_arch_sem_wait() function). The "msg" argument is a result 00192 * parameter that is set by the function (i.e., by doing "*msg = 00193 * ptr"). The "msg" parameter maybe NULL to indicate that the message 00194 * should be dropped. 00195 * 00196 * The return values are the same as for the sys_arch_sem_wait() function: 00197 * Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a 00198 * timeout. 00199 * 00200 * Note that a function with a similar name, sys_mbox_fetch(), is 00201 * implemented by lwIP. 00202 * Inputs: 00203 * sys_mbox_t mbox -- Handle of mailbox 00204 * void **msg -- Pointer to pointer to msg received 00205 * u32_t timeout -- Number of milliseconds until timeout 00206 * Outputs: 00207 * u32_t -- SYS_ARCH_TIMEOUT if timeout, else number 00208 * of milliseconds until received. 00209 *---------------------------------------------------------------------------*/ 00210 u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) { 00211 u32_t start = us_ticker_read(); 00212 00213 osEvent event = osMessageGet(mbox->id, (timeout != 0)?(timeout):(osWaitForever)); 00214 if (event.status != osEventMessage) 00215 return SYS_ARCH_TIMEOUT; 00216 00217 *msg = (void *)event.value.v; 00218 00219 return (us_ticker_read() - start) / 1000; 00220 } 00221 00222 /*---------------------------------------------------------------------------* 00223 * Routine: sys_arch_mbox_tryfetch 00224 *---------------------------------------------------------------------------* 00225 * Description: 00226 * Similar to sys_arch_mbox_fetch, but if message is not ready 00227 * immediately, we'll return with SYS_MBOX_EMPTY. On success, 0 is 00228 * returned. 00229 * Inputs: 00230 * sys_mbox_t mbox -- Handle of mailbox 00231 * void **msg -- Pointer to pointer to msg received 00232 * Outputs: 00233 * u32_t -- SYS_MBOX_EMPTY if no messages. Otherwise, 00234 * return ERR_OK. 00235 *---------------------------------------------------------------------------*/ 00236 u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) { 00237 osEvent event = osMessageGet(mbox->id, 0); 00238 if (event.status != osEventMessage) 00239 return SYS_MBOX_EMPTY; 00240 00241 *msg = (void *)event.value.v; 00242 00243 return ERR_OK; 00244 } 00245 00246 /*---------------------------------------------------------------------------* 00247 * Routine: sys_sem_new 00248 *---------------------------------------------------------------------------* 00249 * Description: 00250 * Creates and returns a new semaphore. The "ucCount" argument specifies 00251 * the initial state of the semaphore. 00252 * NOTE: Currently this routine only creates counts of 1 or 0 00253 * Inputs: 00254 * sys_sem_t sem -- Handle of semaphore 00255 * u8_t count -- Initial count of semaphore 00256 * Outputs: 00257 * err_t -- ERR_OK if semaphore created 00258 *---------------------------------------------------------------------------*/ 00259 err_t sys_sem_new(sys_sem_t *sem, u8_t count) { 00260 #ifdef CMSIS_OS_RTX 00261 memset(sem->data, 0, sizeof(uint32_t)*2); 00262 sem->def.semaphore = sem->data; 00263 #endif 00264 sem->id = osSemaphoreCreate(&sem->def, count); 00265 if (sem->id == NULL) 00266 error("sys_sem_new create error\n"); 00267 00268 return ERR_OK; 00269 } 00270 00271 /*---------------------------------------------------------------------------* 00272 * Routine: sys_arch_sem_wait 00273 *---------------------------------------------------------------------------* 00274 * Description: 00275 * Blocks the thread while waiting for the semaphore to be 00276 * signaled. If the "timeout" argument is non-zero, the thread should 00277 * only be blocked for the specified time (measured in 00278 * milliseconds). 00279 * 00280 * If the timeout argument is non-zero, the return value is the number of 00281 * milliseconds spent waiting for the semaphore to be signaled. If the 00282 * semaphore wasn't signaled within the specified time, the return value is 00283 * SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore 00284 * (i.e., it was already signaled), the function may return zero. 00285 * 00286 * Notice that lwIP implements a function with a similar name, 00287 * sys_sem_wait(), that uses the sys_arch_sem_wait() function. 00288 * Inputs: 00289 * sys_sem_t sem -- Semaphore to wait on 00290 * u32_t timeout -- Number of milliseconds until timeout 00291 * Outputs: 00292 * u32_t -- Time elapsed or SYS_ARCH_TIMEOUT. 00293 *---------------------------------------------------------------------------*/ 00294 u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) { 00295 u32_t start = us_ticker_read(); 00296 00297 if (osSemaphoreWait(sem->id, (timeout != 0)?(timeout):(osWaitForever)) < 1) 00298 return SYS_ARCH_TIMEOUT; 00299 00300 return (us_ticker_read() - start) / 1000; 00301 } 00302 00303 /*---------------------------------------------------------------------------* 00304 * Routine: sys_sem_signal 00305 *---------------------------------------------------------------------------* 00306 * Description: 00307 * Signals (releases) a semaphore 00308 * Inputs: 00309 * sys_sem_t sem -- Semaphore to signal 00310 *---------------------------------------------------------------------------*/ 00311 void sys_sem_signal(sys_sem_t *data) { 00312 if (osSemaphoreRelease(data->id) != osOK) 00313 mbed_die(); /* Can be called by ISR do not use printf */ 00314 } 00315 00316 /*---------------------------------------------------------------------------* 00317 * Routine: sys_sem_free 00318 *---------------------------------------------------------------------------* 00319 * Description: 00320 * Deallocates a semaphore 00321 * Inputs: 00322 * sys_sem_t sem -- Semaphore to free 00323 *---------------------------------------------------------------------------*/ 00324 void sys_sem_free(sys_sem_t *sem) {} 00325 00326 /** Create a new mutex 00327 * @param mutex pointer to the mutex to create 00328 * @return a new mutex */ 00329 err_t sys_mutex_new(sys_mutex_t *mutex) { 00330 #ifdef CMSIS_OS_RTX 00331 #if defined(__MBED_CMSIS_RTOS_CA9) || defined(__MBED_CMSIS_RTOS_CM) 00332 memset(mutex->data, 0, sizeof(int32_t)*4); 00333 #else 00334 memset(mutex->data, 0, sizeof(int32_t)*3); 00335 #endif 00336 mutex->def.mutex = mutex->data; 00337 #endif 00338 mutex->id = osMutexCreate(&mutex->def); 00339 if (mutex->id == NULL) 00340 return ERR_MEM; 00341 00342 return ERR_OK; 00343 } 00344 00345 /** Lock a mutex 00346 * @param mutex the mutex to lock */ 00347 void sys_mutex_lock(sys_mutex_t *mutex) { 00348 if (osMutexWait(mutex->id, osWaitForever) != osOK) 00349 error("sys_mutex_lock error\n"); 00350 } 00351 00352 /** Unlock a mutex 00353 * @param mutex the mutex to unlock */ 00354 void sys_mutex_unlock(sys_mutex_t *mutex) { 00355 if (osMutexRelease(mutex->id) != osOK) 00356 error("sys_mutex_unlock error\n"); 00357 } 00358 00359 /** Delete a mutex 00360 * @param mutex the mutex to delete */ 00361 void sys_mutex_free(sys_mutex_t *mutex) {} 00362 00363 /*---------------------------------------------------------------------------* 00364 * Routine: sys_init 00365 *---------------------------------------------------------------------------* 00366 * Description: 00367 * Initialize sys arch 00368 *---------------------------------------------------------------------------*/ 00369 osMutexId lwip_sys_mutex; 00370 osMutexDef(lwip_sys_mutex); 00371 00372 void sys_init(void) { 00373 us_ticker_read(); // Init sys tick 00374 lwip_sys_mutex = osMutexCreate(osMutex(lwip_sys_mutex)); 00375 if (lwip_sys_mutex == NULL) 00376 error("sys_init error\n"); 00377 } 00378 00379 /*---------------------------------------------------------------------------* 00380 * Routine: sys_jiffies 00381 *---------------------------------------------------------------------------* 00382 * Description: 00383 * Used by PPP as a timestamp-ish value 00384 *---------------------------------------------------------------------------*/ 00385 u32_t sys_jiffies(void) { 00386 static u32_t jiffies = 0; 00387 jiffies += 1 + (us_ticker_read()/10000); 00388 return jiffies; 00389 } 00390 00391 /*---------------------------------------------------------------------------* 00392 * Routine: sys_arch_protect 00393 *---------------------------------------------------------------------------* 00394 * Description: 00395 * This optional function does a "fast" critical region protection and 00396 * returns the previous protection level. This function is only called 00397 * during very short critical regions. An embedded system which supports 00398 * ISR-based drivers might want to implement this function by disabling 00399 * interrupts. Task-based systems might want to implement this by using 00400 * a mutex or disabling tasking. This function should support recursive 00401 * calls from the same task or interrupt. In other words, 00402 * sys_arch_protect() could be called while already protected. In 00403 * that case the return value indicates that it is already protected. 00404 * 00405 * sys_arch_protect() is only required if your port is supporting an 00406 * operating system. 00407 * Outputs: 00408 * sys_prot_t -- Previous protection level (not used here) 00409 *---------------------------------------------------------------------------*/ 00410 sys_prot_t sys_arch_protect(void) { 00411 if (osMutexWait(lwip_sys_mutex, osWaitForever) != osOK) 00412 error("sys_arch_protect error\n"); 00413 return (sys_prot_t) 1; 00414 } 00415 00416 /*---------------------------------------------------------------------------* 00417 * Routine: sys_arch_unprotect 00418 *---------------------------------------------------------------------------* 00419 * Description: 00420 * This optional function does a "fast" set of critical region 00421 * protection to the value specified by pval. See the documentation for 00422 * sys_arch_protect() for more information. This function is only 00423 * required if your port is supporting an operating system. 00424 * Inputs: 00425 * sys_prot_t -- Previous protection level (not used here) 00426 *---------------------------------------------------------------------------*/ 00427 void sys_arch_unprotect(sys_prot_t p) { 00428 if (osMutexRelease(lwip_sys_mutex) != osOK) 00429 error("sys_arch_unprotect error\n"); 00430 } 00431 00432 u32_t sys_now(void) { 00433 return us_ticker_read() / 1000; 00434 } 00435 00436 void sys_msleep(u32_t ms) { 00437 osDelay(ms); 00438 } 00439 00440 // Keep a pool of thread structures 00441 static int thread_pool_index = 0; 00442 static sys_thread_data_t thread_pool[SYS_THREAD_POOL_N]; 00443 00444 /*---------------------------------------------------------------------------* 00445 * Routine: sys_thread_new 00446 *---------------------------------------------------------------------------* 00447 * Description: 00448 * Starts a new thread with priority "prio" that will begin its 00449 * execution in the function "thread()". The "arg" argument will be 00450 * passed as an argument to the thread() function. The id of the new 00451 * thread is returned. Both the id and the priority are system 00452 * dependent. 00453 * Inputs: 00454 * char *name -- Name of thread 00455 * void (*thread)(void *arg) -- Pointer to function to run. 00456 * void *arg -- Argument passed into function 00457 * int stacksize -- Required stack amount in bytes 00458 * int priority -- Thread priority 00459 * Outputs: 00460 * sys_thread_t -- Pointer to thread handle. 00461 *---------------------------------------------------------------------------*/ 00462 sys_thread_t sys_thread_new(const char *pcName, 00463 void (*thread)(void *arg), 00464 void *arg, int stacksize, int priority) { 00465 LWIP_DEBUGF(SYS_DEBUG, ("New Thread: %s\n", pcName)); 00466 00467 if (thread_pool_index >= SYS_THREAD_POOL_N) 00468 error("sys_thread_new number error\n"); 00469 sys_thread_t t = (sys_thread_t)&thread_pool[thread_pool_index]; 00470 thread_pool_index++; 00471 00472 #ifdef CMSIS_OS_RTX 00473 t->def.pthread = (os_pthread)thread; 00474 t->def.tpriority = (osPriority)priority; 00475 t->def.stacksize = stacksize; 00476 t->def.stack_pointer = (uint32_t*)malloc(stacksize); 00477 if (t->def.stack_pointer == NULL) { 00478 error("Error allocating the stack memory"); 00479 } 00480 #endif 00481 t->id = osThreadCreate(&t->def, arg); 00482 if (t->id == NULL) 00483 error("sys_thread_new create error\n"); 00484 00485 return t; 00486 } 00487 00488 #endif 00489 00490 #ifdef LWIP_DEBUG 00491 00492 /** \brief Displays an error message on assertion 00493 00494 This function will display an error message on an assertion 00495 to the debug output. 00496 00497 \param[in] msg Error message to display 00498 \param[in] line Line number in file with error 00499 \param[in] file Filename with error 00500 */ 00501 void assert_printf(char *msg, int line, char *file) { 00502 if (msg) 00503 error("%s:%d in file %s\n", msg, line, file); 00504 else 00505 error("LWIP ASSERT\n"); 00506 } 00507 00508 #endif /* LWIP_DEBUG */
Generated on Tue Jul 12 2022 11:02:42 by
