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 F7_Ethernet 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 "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 #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 #if defined(__MBED_CMSIS_RTOS_CA9) || defined(__MBED_CMSIS_RTOS_CM) 00289 memset(mutex->data, 0, sizeof(int32_t)*4); 00290 #else 00291 memset(mutex->data, 0, sizeof(int32_t)*3); 00292 #endif 00293 mutex->def.mutex = mutex->data; 00294 #endif 00295 mutex->id = osMutexCreate(&mutex->def); 00296 if (mutex->id == NULL) 00297 return ERR_MEM; 00298 00299 return ERR_OK; 00300 } 00301 00302 /** Lock a mutex 00303 * @param mutex the mutex to lock */ 00304 void sys_mutex_lock(sys_mutex_t *mutex) { 00305 if (osMutexWait(mutex->id, osWaitForever) != osOK) 00306 error("sys_mutex_lock error\n"); 00307 } 00308 00309 /** Unlock a mutex 00310 * @param mutex the mutex to unlock */ 00311 void sys_mutex_unlock(sys_mutex_t *mutex) { 00312 if (osMutexRelease(mutex->id) != osOK) 00313 error("sys_mutex_unlock error\n"); 00314 } 00315 00316 /** Delete a mutex 00317 * @param mutex the mutex to delete */ 00318 void sys_mutex_free(sys_mutex_t *mutex) {} 00319 00320 /*---------------------------------------------------------------------------* 00321 * Routine: sys_init 00322 *---------------------------------------------------------------------------* 00323 * Description: 00324 * Initialize sys arch 00325 *---------------------------------------------------------------------------*/ 00326 osMutexId lwip_sys_mutex; 00327 osMutexDef(lwip_sys_mutex); 00328 00329 void sys_init(void) { 00330 us_ticker_read(); // Init sys tick 00331 lwip_sys_mutex = osMutexCreate(osMutex(lwip_sys_mutex)); 00332 if (lwip_sys_mutex == NULL) 00333 error("sys_init error\n"); 00334 } 00335 00336 /*---------------------------------------------------------------------------* 00337 * Routine: sys_jiffies 00338 *---------------------------------------------------------------------------* 00339 * Description: 00340 * Used by PPP as a timestamp-ish value 00341 *---------------------------------------------------------------------------*/ 00342 u32_t sys_jiffies(void) { 00343 static u32_t jiffies = 0; 00344 jiffies += 1 + (us_ticker_read()/10000); 00345 return jiffies; 00346 } 00347 00348 /*---------------------------------------------------------------------------* 00349 * Routine: sys_arch_protect 00350 *---------------------------------------------------------------------------* 00351 * Description: 00352 * This optional function does a "fast" critical region protection and 00353 * returns the previous protection level. This function is only called 00354 * during very short critical regions. An embedded system which supports 00355 * ISR-based drivers might want to implement this function by disabling 00356 * interrupts. Task-based systems might want to implement this by using 00357 * a mutex or disabling tasking. This function should support recursive 00358 * calls from the same task or interrupt. In other words, 00359 * sys_arch_protect() could be called while already protected. In 00360 * that case the return value indicates that it is already protected. 00361 * 00362 * sys_arch_protect() is only required if your port is supporting an 00363 * operating system. 00364 * Outputs: 00365 * sys_prot_t -- Previous protection level (not used here) 00366 *---------------------------------------------------------------------------*/ 00367 sys_prot_t sys_arch_protect(void) { 00368 if (osMutexWait(lwip_sys_mutex, osWaitForever) != osOK) 00369 error("sys_arch_protect error\n"); 00370 return (sys_prot_t) 1; 00371 } 00372 00373 /*---------------------------------------------------------------------------* 00374 * Routine: sys_arch_unprotect 00375 *---------------------------------------------------------------------------* 00376 * Description: 00377 * This optional function does a "fast" set of critical region 00378 * protection to the value specified by pval. See the documentation for 00379 * sys_arch_protect() for more information. This function is only 00380 * required if your port is supporting an operating system. 00381 * Inputs: 00382 * sys_prot_t -- Previous protection level (not used here) 00383 *---------------------------------------------------------------------------*/ 00384 void sys_arch_unprotect(sys_prot_t p) { 00385 if (osMutexRelease(lwip_sys_mutex) != osOK) 00386 error("sys_arch_unprotect error\n"); 00387 } 00388 00389 u32_t sys_now(void) { 00390 return us_ticker_read() / 1000; 00391 } 00392 00393 void sys_msleep(u32_t ms) { 00394 osDelay(ms); 00395 } 00396 00397 // Keep a pool of thread structures 00398 static int thread_pool_index = 0; 00399 static sys_thread_data_t thread_pool[SYS_THREAD_POOL_N]; 00400 00401 /*---------------------------------------------------------------------------* 00402 * Routine: sys_thread_new 00403 *---------------------------------------------------------------------------* 00404 * Description: 00405 * Starts a new thread with priority "prio" that will begin its 00406 * execution in the function "thread()". The "arg" argument will be 00407 * passed as an argument to the thread() function. The id of the new 00408 * thread is returned. Both the id and the priority are system 00409 * dependent. 00410 * Inputs: 00411 * char *name -- Name of thread 00412 * void (*thread)(void *arg) -- Pointer to function to run. 00413 * void *arg -- Argument passed into function 00414 * int stacksize -- Required stack amount in bytes 00415 * int priority -- Thread priority 00416 * Outputs: 00417 * sys_thread_t -- Pointer to thread handle. 00418 *---------------------------------------------------------------------------*/ 00419 sys_thread_t sys_thread_new(const char *pcName, 00420 void (*thread)(void *arg), 00421 void *arg, int stacksize, int priority) { 00422 LWIP_DEBUGF(SYS_DEBUG, ("New Thread: %s\n", pcName)); 00423 00424 if (thread_pool_index >= SYS_THREAD_POOL_N) 00425 error("sys_thread_new number error\n"); 00426 sys_thread_t t = (sys_thread_t)&thread_pool[thread_pool_index]; 00427 thread_pool_index++; 00428 00429 #ifdef CMSIS_OS_RTX 00430 t->def.pthread = (os_pthread)thread; 00431 t->def.tpriority = (osPriority)priority; 00432 t->def.stacksize = stacksize; 00433 t->def.stack_pointer = (uint32_t*)malloc(stacksize); 00434 if (t->def.stack_pointer == NULL) { 00435 error("Error allocating the stack memory"); 00436 } 00437 #endif 00438 t->id = osThreadCreate(&t->def, arg); 00439 if (t->id == NULL) 00440 error("sys_thread_new create error\n"); 00441 00442 return t; 00443 } 00444 00445 #endif 00446 00447 #ifdef LWIP_DEBUG 00448 00449 /** \brief Displays an error message on assertion 00450 00451 This function will display an error message on an assertion 00452 to the debug output. 00453 00454 \param[in] msg Error message to display 00455 \param[in] line Line number in file with error 00456 \param[in] file Filename with error 00457 */ 00458 void assert_printf(char *msg, int line, char *file) { 00459 if (msg) 00460 error("%s:%d in file %s\n", msg, line, file); 00461 else 00462 error("LWIP ASSERT\n"); 00463 } 00464 00465 #endif /* LWIP_DEBUG */
Generated on Tue Jul 12 2022 21:19:02 by
1.7.2
