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 mbed-os by
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 13:15:54 by
