ソースの整理中ですが、利用はできます。

Dependencies:   EthernetInterface HttpServer TextLCD mbed-rpc mbed-rtos mbed Socket lwip-eth lwip-sys lwip

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sys_arch.c Source File

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 */