I messed up the merge, so pushing it over to another repo so I don't lose it. Will tidy up and remove later
Dependencies: BufferedSerial FatFileSystemCpp mbed
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 Thu Dec 15 2022 06:07:05 by 1.7.2