Improve documentation: Some words about multiple execution contexts in lwIP

This commit is contained in:
Dirk Ziegelmeier 2016-09-29 12:51:45 +02:00
parent 65796cd827
commit 682b82aad8
6 changed files with 66 additions and 6 deletions

View File

@ -2071,6 +2071,7 @@ INCLUDE_FILE_PATTERNS = *.h
PREDEFINED = __DOXYGEN__=1 \
NO_SYS=0 \
SYS_LIGHTWEIGHT_PROT=1 \
LWIP_TCPIP_CORE_LOCKING=1 \
LWIP_IPV4=1 \
LWIP_IPV6=1 \
LWIP_ICMP=1 \

View File

@ -1,4 +1,4 @@
/**
/**
* @defgroup lwip lwIP
*
* @defgroup infrastructure Infrastructure
@ -7,7 +7,7 @@
* Non thread-safe APIs, callback style for maximum performance and minimum
* memory footprint.
*
* @defgroup threadsafe_api Thread-safe APIs
* @defgroup sequential_api Sequential-style APIs
* Thread-safe APIs, blocking functions. More overhead, but can be called
* from any thread except TCPIP thread.
*
@ -31,6 +31,63 @@
* @verbinclude "contrib.txt"
*/
/**
* @page pitfalls Common pitfalls
*
* Multiple Execution Contexts in lwIP code
* ========================================
*
* The most common source of lwIP problems is to have multiple execution contexts
* inside the lwIP code.
*
* lwIP can be used in two basic modes: @ref lwip_nosys (no OS/RTOS
* running on target system) or @ref lwip_os (there is an OS running
* on the target system).
*
* Mainloop Mode
* -------------
* In mainloop mode, only @ref callbackstyle_api can be used.
* The user has two possibilities to ensure there is only one
* exection context at a time in lwIP:
*
* 1) Deliver RX ethernet packets directly in interrupt context to lwIP
* by calling netif->input directly in interrupt. This implies all lwIP
* callback functions are called in IRQ context, which may cause further
* problems in application code: IRQ is blocked for a long time, multiple
* execution contexts in application code etc. When the application wants
* to call lwIP, it only needs to disable interrupts during the call.
* If timers are involved, even more locking code is needed to lock out
* timer IRQ and ethernet IRQ from each other, assuming these may be nested.
*
* 2) Run lwIP in a mainloop. There is example code here: @ref lwip_nosys.
* lwIP is _ONLY_ called from mainloop callstacks here. The ethernet IRQ
* has to put received telegrams into a queue which is polled in the
* mainloop. Ensure lwIP is _NEVER_ called from an interrupt, e.g.
* some SPI IRQ wants to forward data to udp_send() or tcp_write()!
*
* OS Mode
* -------
* In OS mode, @ref callbackstyle_api AND @ref sequential_api can be used.
* @ref sequential_api are designed to be called from threads other than
* the TCPIP thread, so there is nothing to consider here.
* But @ref callbackstyle_api functions must _ONLY_ be called from
* TCPIP thread. It is a common error to call these from other threads
* or from IRQ contexts. Ethernet RX needs to deliver incoming packets
* in the correct way by sending a message to TCPIP thread, this is
* implemented in tcpip_input().
* Again, ensure lwIP is _NEVER_ called from an interrupt, e.g.
* some SPI IRQ wants to forward data to udp_send() or tcp_write()!
*
* 1) tcpip_callback() can be used get called back from TCPIP thread,
* it is safe to call any @ref callbackstyle_api from there.
*
* 2) Use @ref LWIP_TCPIP_CORE_LOCKING. All @ref callbackstyle_api
* functions can be called when lwIP core lock is aquired, see
* @ref LOCK_TCPIP_CORE() and @ref UNLOCK_TCPIP_CORE().
* These macros cannot be used in an interrupt context!
* Note the OS must correctly handle priority inversion for this.
*/
/**
* @page bugs Reporting bugs
* Please report bugs in the lwIP bug tracker at savannah.\n
@ -60,7 +117,7 @@
* to use @ref LWIP_TCPIP_CORE_LOCKING.\n
* Porting: implement all functions in @ref sys_layer.\n
* You can use @ref callbackstyle_api together with @ref tcpip_callback,
* and all @ref threadsafe_api.
* and all @ref sequential_api.
*/
/**

View File

@ -3,7 +3,7 @@
* Sequential API External module
*
* @defgroup netconn Netconn API
* @ingroup threadsafe_api
* @ingroup sequential_api
* Thread-safe, to be called from non-TCPIP threads only.
* TX/RX handling based on @ref netbuf (containing @ref pbuf)
* to avoid copying data around.

View File

@ -3,7 +3,7 @@
* Network Interface Sequential API module
*
* @defgroup netifapi NETIF API
* @ingroup threadsafe_api
* @ingroup sequential_api
* Thread-safe functions to be called from non-TCPIP threads
*
* @defgroup netifapi_netif NETIF related

View File

@ -3,7 +3,7 @@
* Sockets BSD-Like API module
*
* @defgroup socket Socket API
* @ingroup threadsafe_api
* @ingroup sequential_api
* BSD-style socket API.\n
* Thread-safe, to be called from non-TCPIP threads only.\n
* Can be activated by defining @ref LWIP_SOCKET to 1.\n

View File

@ -52,7 +52,9 @@ extern "C" {
#if LWIP_TCPIP_CORE_LOCKING
/** The global semaphore to lock the stack. */
extern sys_mutex_t lock_tcpip_core;
/** Lock lwIP core mutex (needs @ref LWIP_TCPIP_CORE_LOCKING 1) */
#define LOCK_TCPIP_CORE() sys_mutex_lock(&lock_tcpip_core)
/** Unlock lwIP core mutex (needs @ref LWIP_TCPIP_CORE_LOCKING 1) */
#define UNLOCK_TCPIP_CORE() sys_mutex_unlock(&lock_tcpip_core)
#else /* LWIP_TCPIP_CORE_LOCKING */
#define LOCK_TCPIP_CORE()