1*10465441SEvalZerosys_arch interface for lwIP 0.6++ 2*10465441SEvalZero 3*10465441SEvalZeroAuthor: Adam Dunkels 4*10465441SEvalZero 5*10465441SEvalZeroThe operating system emulation layer provides a common interface 6*10465441SEvalZerobetween the lwIP code and the underlying operating system kernel. The 7*10465441SEvalZerogeneral idea is that porting lwIP to new architectures requires only 8*10465441SEvalZerosmall changes to a few header files and a new sys_arch 9*10465441SEvalZeroimplementation. It is also possible to do a sys_arch implementation 10*10465441SEvalZerothat does not rely on any underlying operating system. 11*10465441SEvalZero 12*10465441SEvalZeroThe sys_arch provides semaphores and mailboxes to lwIP. For the full 13*10465441SEvalZerolwIP functionality, multiple threads support can be implemented in the 14*10465441SEvalZerosys_arch, but this is not required for the basic lwIP 15*10465441SEvalZerofunctionality. Previous versions of lwIP required the sys_arch to 16*10465441SEvalZeroimplement timer scheduling as well but as of lwIP 0.5 this is 17*10465441SEvalZeroimplemented in a higher layer. 18*10465441SEvalZero 19*10465441SEvalZeroIn addition to the source file providing the functionality of sys_arch, 20*10465441SEvalZerothe OS emulation layer must provide several header files defining 21*10465441SEvalZeromacros used throughout lwip. The files required and the macros they 22*10465441SEvalZeromust define are listed below the sys_arch description. 23*10465441SEvalZero 24*10465441SEvalZeroSemaphores can be either counting or binary - lwIP works with both 25*10465441SEvalZerokinds. Mailboxes are used for message passing and can be implemented 26*10465441SEvalZeroeither as a queue which allows multiple messages to be posted to a 27*10465441SEvalZeromailbox, or as a rendez-vous point where only one message can be 28*10465441SEvalZeroposted at a time. lwIP works with both kinds, but the former type will 29*10465441SEvalZerobe more efficient. A message in a mailbox is just a pointer, nothing 30*10465441SEvalZeromore. 31*10465441SEvalZero 32*10465441SEvalZeroSemaphores are represented by the type "sys_sem_t" which is typedef'd 33*10465441SEvalZeroin the sys_arch.h file. Mailboxes are equivalently represented by the 34*10465441SEvalZerotype "sys_mbox_t". lwIP does not place any restrictions on how 35*10465441SEvalZerosys_sem_t or sys_mbox_t are represented internally. 36*10465441SEvalZero 37*10465441SEvalZeroSince lwIP 1.4.0, semaphore and mailbox functions are prototyped in a way that 38*10465441SEvalZeroallows both using pointers or actual OS structures to be used. This way, memory 39*10465441SEvalZerorequired for such types can be either allocated in place (globally or on the 40*10465441SEvalZerostack) or on the heap (allocated internally in the "*_new()" functions). 41*10465441SEvalZero 42*10465441SEvalZeroThe following functions must be implemented by the sys_arch: 43*10465441SEvalZero 44*10465441SEvalZero- void sys_init(void) 45*10465441SEvalZero 46*10465441SEvalZero Is called to initialize the sys_arch layer. 47*10465441SEvalZero 48*10465441SEvalZero- err_t sys_sem_new(sys_sem_t *sem, u8_t count) 49*10465441SEvalZero 50*10465441SEvalZero Creates a new semaphore. The semaphore is allocated to the memory that 'sem' 51*10465441SEvalZero points to (which can be both a pointer or the actual OS structure). 52*10465441SEvalZero The "count" argument specifies the initial state of the semaphore (which is 53*10465441SEvalZero either 0 or 1). 54*10465441SEvalZero If the semaphore has been created, ERR_OK should be returned. Returning any 55*10465441SEvalZero other error will provide a hint what went wrong, but except for assertions, 56*10465441SEvalZero no real error handling is implemented. 57*10465441SEvalZero 58*10465441SEvalZero- void sys_sem_free(sys_sem_t *sem) 59*10465441SEvalZero 60*10465441SEvalZero Deallocates a semaphore. 61*10465441SEvalZero 62*10465441SEvalZero- void sys_sem_signal(sys_sem_t *sem) 63*10465441SEvalZero 64*10465441SEvalZero Signals a semaphore. 65*10465441SEvalZero 66*10465441SEvalZero- u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) 67*10465441SEvalZero 68*10465441SEvalZero Blocks the thread while waiting for the semaphore to be 69*10465441SEvalZero signaled. If the "timeout" argument is non-zero, the thread should 70*10465441SEvalZero only be blocked for the specified time (measured in 71*10465441SEvalZero milliseconds). If the "timeout" argument is zero, the thread should be 72*10465441SEvalZero blocked until the semaphore is signalled. 73*10465441SEvalZero 74*10465441SEvalZero If the timeout argument is non-zero, the return value is the number of 75*10465441SEvalZero milliseconds spent waiting for the semaphore to be signaled. If the 76*10465441SEvalZero semaphore wasn't signaled within the specified time, the return value is 77*10465441SEvalZero SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore 78*10465441SEvalZero (i.e., it was already signaled), the function may return zero. 79*10465441SEvalZero 80*10465441SEvalZero Notice that lwIP implements a function with a similar name, 81*10465441SEvalZero sys_sem_wait(), that uses the sys_arch_sem_wait() function. 82*10465441SEvalZero 83*10465441SEvalZero- int sys_sem_valid(sys_sem_t *sem) 84*10465441SEvalZero 85*10465441SEvalZero Returns 1 if the semaphore is valid, 0 if it is not valid. 86*10465441SEvalZero When using pointers, a simple way is to check the pointer for != NULL. 87*10465441SEvalZero When directly using OS structures, implementing this may be more complex. 88*10465441SEvalZero This may also be a define, in which case the function is not prototyped. 89*10465441SEvalZero 90*10465441SEvalZero- void sys_sem_set_invalid(sys_sem_t *sem) 91*10465441SEvalZero 92*10465441SEvalZero Invalidate a semaphore so that sys_sem_valid() returns 0. 93*10465441SEvalZero ATTENTION: This does NOT mean that the semaphore shall be deallocated: 94*10465441SEvalZero sys_sem_free() is always called before calling this function! 95*10465441SEvalZero This may also be a define, in which case the function is not prototyped. 96*10465441SEvalZero 97*10465441SEvalZero- err_t sys_mbox_new(sys_mbox_t *mbox, int size) 98*10465441SEvalZero 99*10465441SEvalZero Creates an empty mailbox for maximum "size" elements. Elements stored 100*10465441SEvalZero in mailboxes are pointers. You have to define macros "_MBOX_SIZE" 101*10465441SEvalZero in your lwipopts.h, or ignore this parameter in your implementation 102*10465441SEvalZero and use a default size. 103*10465441SEvalZero If the mailbox has been created, ERR_OK should be returned. Returning any 104*10465441SEvalZero other error will provide a hint what went wrong, but except for assertions, 105*10465441SEvalZero no real error handling is implemented. 106*10465441SEvalZero 107*10465441SEvalZero- void sys_mbox_free(sys_mbox_t *mbox) 108*10465441SEvalZero 109*10465441SEvalZero Deallocates a mailbox. If there are messages still present in the 110*10465441SEvalZero mailbox when the mailbox is deallocated, it is an indication of a 111*10465441SEvalZero programming error in lwIP and the developer should be notified. 112*10465441SEvalZero 113*10465441SEvalZero- void sys_mbox_post(sys_mbox_t *mbox, void *msg) 114*10465441SEvalZero 115*10465441SEvalZero Posts the "msg" to the mailbox. This function have to block until 116*10465441SEvalZero the "msg" is really posted. 117*10465441SEvalZero 118*10465441SEvalZero- err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) 119*10465441SEvalZero 120*10465441SEvalZero Try to post the "msg" to the mailbox. Returns ERR_MEM if this one 121*10465441SEvalZero is full, else, ERR_OK if the "msg" is posted. 122*10465441SEvalZero 123*10465441SEvalZero- u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) 124*10465441SEvalZero 125*10465441SEvalZero Blocks the thread until a message arrives in the mailbox, but does 126*10465441SEvalZero not block the thread longer than "timeout" milliseconds (similar to 127*10465441SEvalZero the sys_arch_sem_wait() function). If "timeout" is 0, the thread should 128*10465441SEvalZero be blocked until a message arrives. The "msg" argument is a result 129*10465441SEvalZero parameter that is set by the function (i.e., by doing "*msg = 130*10465441SEvalZero ptr"). The "msg" parameter maybe NULL to indicate that the message 131*10465441SEvalZero should be dropped. 132*10465441SEvalZero 133*10465441SEvalZero The return values are the same as for the sys_arch_sem_wait() function: 134*10465441SEvalZero Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a 135*10465441SEvalZero timeout. 136*10465441SEvalZero 137*10465441SEvalZero Note that a function with a similar name, sys_mbox_fetch(), is 138*10465441SEvalZero implemented by lwIP. 139*10465441SEvalZero 140*10465441SEvalZero- u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) 141*10465441SEvalZero 142*10465441SEvalZero This is similar to sys_arch_mbox_fetch, however if a message is not 143*10465441SEvalZero present in the mailbox, it immediately returns with the code 144*10465441SEvalZero SYS_MBOX_EMPTY. On success 0 is returned. 145*10465441SEvalZero 146*10465441SEvalZero To allow for efficient implementations, this can be defined as a 147*10465441SEvalZero function-like macro in sys_arch.h instead of a normal function. For 148*10465441SEvalZero example, a naive implementation could be: 149*10465441SEvalZero #define sys_arch_mbox_tryfetch(mbox,msg) \ 150*10465441SEvalZero sys_arch_mbox_fetch(mbox,msg,1) 151*10465441SEvalZero although this would introduce unnecessary delays. 152*10465441SEvalZero 153*10465441SEvalZero- int sys_mbox_valid(sys_mbox_t *mbox) 154*10465441SEvalZero 155*10465441SEvalZero Returns 1 if the mailbox is valid, 0 if it is not valid. 156*10465441SEvalZero When using pointers, a simple way is to check the pointer for != NULL. 157*10465441SEvalZero When directly using OS structures, implementing this may be more complex. 158*10465441SEvalZero This may also be a define, in which case the function is not prototyped. 159*10465441SEvalZero 160*10465441SEvalZero- void sys_mbox_set_invalid(sys_mbox_t *mbox) 161*10465441SEvalZero 162*10465441SEvalZero Invalidate a mailbox so that sys_mbox_valid() returns 0. 163*10465441SEvalZero ATTENTION: This does NOT mean that the mailbox shall be deallocated: 164*10465441SEvalZero sys_mbox_free() is always called before calling this function! 165*10465441SEvalZero This may also be a define, in which case the function is not prototyped. 166*10465441SEvalZero 167*10465441SEvalZeroIf threads are supported by the underlying operating system and if 168*10465441SEvalZerosuch functionality is needed in lwIP, the following function will have 169*10465441SEvalZeroto be implemented as well: 170*10465441SEvalZero 171*10465441SEvalZero- sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio) 172*10465441SEvalZero 173*10465441SEvalZero Starts a new thread named "name" with priority "prio" that will begin its 174*10465441SEvalZero execution in the function "thread()". The "arg" argument will be passed as an 175*10465441SEvalZero argument to the thread() function. The stack size to used for this thread is 176*10465441SEvalZero the "stacksize" parameter. The id of the new thread is returned. Both the id 177*10465441SEvalZero and the priority are system dependent. 178*10465441SEvalZero 179*10465441SEvalZero- sys_prot_t sys_arch_protect(void) 180*10465441SEvalZero 181*10465441SEvalZero This optional function does a "fast" critical region protection and returns 182*10465441SEvalZero the previous protection level. This function is only called during very short 183*10465441SEvalZero critical regions. An embedded system which supports ISR-based drivers might 184*10465441SEvalZero want to implement this function by disabling interrupts. Task-based systems 185*10465441SEvalZero might want to implement this by using a mutex or disabling tasking. This 186*10465441SEvalZero function should support recursive calls from the same task or interrupt. In 187*10465441SEvalZero other words, sys_arch_protect() could be called while already protected. In 188*10465441SEvalZero that case the return value indicates that it is already protected. 189*10465441SEvalZero 190*10465441SEvalZero sys_arch_protect() is only required if your port is supporting an operating 191*10465441SEvalZero system. 192*10465441SEvalZero 193*10465441SEvalZero- void sys_arch_unprotect(sys_prot_t pval) 194*10465441SEvalZero 195*10465441SEvalZero This optional function does a "fast" set of critical region protection to the 196*10465441SEvalZero value specified by pval. See the documentation for sys_arch_protect() for 197*10465441SEvalZero more information. This function is only required if your port is supporting 198*10465441SEvalZero an operating system. 199*10465441SEvalZero 200*10465441SEvalZeroFor some configurations, you also need: 201*10465441SEvalZero 202*10465441SEvalZero- u32_t sys_now(void) 203*10465441SEvalZero 204*10465441SEvalZero This optional function returns the current time in milliseconds (don't care 205*10465441SEvalZero for wraparound, this is only used for time diffs). 206*10465441SEvalZero Not implementing this function means you cannot use some modules (e.g. TCP 207*10465441SEvalZero timestamps, internal timeouts for NO_SYS==1). 208*10465441SEvalZero 209*10465441SEvalZero 210*10465441SEvalZeroNote: 211*10465441SEvalZero 212*10465441SEvalZeroBe carefull with using mem_malloc() in sys_arch. When malloc() refers to 213*10465441SEvalZeromem_malloc() you can run into a circular function call problem. In mem.c 214*10465441SEvalZeromem_init() tries to allcate a semaphore using mem_malloc, which of course 215*10465441SEvalZerocan't be performed when sys_arch uses mem_malloc. 216*10465441SEvalZero 217*10465441SEvalZero------------------------------------------------------------------------------- 218*10465441SEvalZeroAdditional files required for the "OS support" emulation layer: 219*10465441SEvalZero------------------------------------------------------------------------------- 220*10465441SEvalZero 221*10465441SEvalZerocc.h - Architecture environment, some compiler specific, some 222*10465441SEvalZero environment specific (probably should move env stuff 223*10465441SEvalZero to sys_arch.h.) 224*10465441SEvalZero 225*10465441SEvalZero Typedefs for the types used by lwip - 226*10465441SEvalZero u8_t, s8_t, u16_t, s16_t, u32_t, s32_t, mem_ptr_t 227*10465441SEvalZero 228*10465441SEvalZero Compiler hints for packing lwip's structures - 229*10465441SEvalZero PACK_STRUCT_FIELD(x) 230*10465441SEvalZero PACK_STRUCT_STRUCT 231*10465441SEvalZero PACK_STRUCT_BEGIN 232*10465441SEvalZero PACK_STRUCT_END 233*10465441SEvalZero 234*10465441SEvalZero Platform specific diagnostic output - 235*10465441SEvalZero LWIP_PLATFORM_DIAG(x) - non-fatal, print a message. 236*10465441SEvalZero LWIP_PLATFORM_ASSERT(x) - fatal, print message and abandon execution. 237*10465441SEvalZero Portability defines for printf formatters: 238*10465441SEvalZero U16_F, S16_F, X16_F, U32_F, S32_F, X32_F, SZT_F 239*10465441SEvalZero 240*10465441SEvalZero "lightweight" synchronization mechanisms - 241*10465441SEvalZero SYS_ARCH_DECL_PROTECT(x) - declare a protection state variable. 242*10465441SEvalZero SYS_ARCH_PROTECT(x) - enter protection mode. 243*10465441SEvalZero SYS_ARCH_UNPROTECT(x) - leave protection mode. 244*10465441SEvalZero 245*10465441SEvalZero If the compiler does not provide memset() this file must include a 246*10465441SEvalZero definition of it, or include a file which defines it. 247*10465441SEvalZero 248*10465441SEvalZero This file must either include a system-local <errno.h> which defines 249*10465441SEvalZero the standard *nix error codes, or it should #define LWIP_PROVIDE_ERRNO 250*10465441SEvalZero to make lwip/arch.h define the codes which are used throughout. 251*10465441SEvalZero 252*10465441SEvalZero 253*10465441SEvalZeroperf.h - Architecture specific performance measurement. 254*10465441SEvalZero Measurement calls made throughout lwip, these can be defined to nothing. 255*10465441SEvalZero PERF_START - start measuring something. 256*10465441SEvalZero PERF_STOP(x) - stop measuring something, and record the result. 257*10465441SEvalZero 258*10465441SEvalZerosys_arch.h - Tied to sys_arch.c 259*10465441SEvalZero 260*10465441SEvalZero Arch dependent types for the following objects: 261*10465441SEvalZero sys_sem_t, sys_mbox_t, sys_thread_t, 262*10465441SEvalZero And, optionally: 263*10465441SEvalZero sys_prot_t 264*10465441SEvalZero 265*10465441SEvalZero Defines to set vars of sys_mbox_t and sys_sem_t to NULL. 266*10465441SEvalZero SYS_MBOX_NULL NULL 267*10465441SEvalZero SYS_SEM_NULL NULL 268