Prusa MINI Firmware overview
tcpip.c File Reference
#include "lwip/opt.h"
#include "lwip/priv/tcpip_priv.h"
#include "lwip/sys.h"
#include "lwip/memp.h"
#include "lwip/mem.h"
#include "lwip/init.h"
#include "lwip/ip.h"
#include "lwip/pbuf.h"
#include "lwip/etharp.h"
#include "netif/ethernet.h"

Macros

#define TCPIP_MSG_VAR_REF(name)   API_VAR_REF(name)
 
#define TCPIP_MSG_VAR_DECLARE(name)   API_VAR_DECLARE(struct tcpip_msg, name)
 
#define TCPIP_MSG_VAR_ALLOC(name)   API_VAR_ALLOC(struct tcpip_msg, MEMP_TCPIP_MSG_API, name, ERR_MEM)
 
#define TCPIP_MSG_VAR_FREE(name)   API_VAR_FREE(MEMP_TCPIP_MSG_API, name)
 
#define TCPIP_MBOX_FETCH(mbox, msg)   sys_mbox_fetch(mbox, msg)
 

Functions

static void tcpip_thread (void *arg)
 
err_t tcpip_inpkt (struct pbuf *p, struct netif *inp, netif_input_fn input_fn)
 
err_t tcpip_input (struct pbuf *p, struct netif *inp)
 
err_t tcpip_callback_with_block (tcpip_callback_fn function, void *ctx, u8_t block)
 
err_t tcpip_send_msg_wait_sem (tcpip_callback_fn fn, void *apimsg, sys_sem_t *sem)
 
err_t tcpip_api_call (tcpip_api_call_fn fn, struct tcpip_api_call_data *call)
 
struct tcpip_callback_msg * tcpip_callbackmsg_new (tcpip_callback_fn function, void *ctx)
 
void tcpip_callbackmsg_delete (struct tcpip_callback_msg *msg)
 
err_t tcpip_trycallback (struct tcpip_callback_msg *msg)
 
void tcpip_init (tcpip_init_done_fn initfunc, void *arg)
 
static void pbuf_free_int (void *p)
 
err_t pbuf_free_callback (struct pbuf *p)
 
err_t mem_free_callback (void *m)
 

Variables

static tcpip_init_done_fn tcpip_init_done
 
static voidtcpip_init_done_arg
 
static sys_mbox_t mbox
 

Detailed Description

Sequential API Main thread module

Macro Definition Documentation

◆ TCPIP_MSG_VAR_REF

#define TCPIP_MSG_VAR_REF (   name)    API_VAR_REF(name)

◆ TCPIP_MSG_VAR_DECLARE

#define TCPIP_MSG_VAR_DECLARE (   name)    API_VAR_DECLARE(struct tcpip_msg, name)

◆ TCPIP_MSG_VAR_ALLOC

#define TCPIP_MSG_VAR_ALLOC (   name)    API_VAR_ALLOC(struct tcpip_msg, MEMP_TCPIP_MSG_API, name, ERR_MEM)

◆ TCPIP_MSG_VAR_FREE

#define TCPIP_MSG_VAR_FREE (   name)    API_VAR_FREE(MEMP_TCPIP_MSG_API, name)

◆ TCPIP_MBOX_FETCH

#define TCPIP_MBOX_FETCH (   mbox,
  msg 
)    sys_mbox_fetch(mbox, msg)

Function Documentation

◆ tcpip_thread()

static void tcpip_thread ( void arg)
static

The main lwIP thread. This thread has exclusive access to lwIP core functions (unless access to them is not locked). Other threads communicate with this thread using message boxes.

It also starts all the timers to make sure they are running in the right thread context.

Parameters
argunused argument
88 {
89  struct tcpip_msg *msg;
91 
92  if (tcpip_init_done != NULL) {
94  }
95 
97  while (1) { /* MAIN Loop */
100  /* wait for a message, timeouts are processed while waiting */
101  TCPIP_MBOX_FETCH(&mbox, (void **)&msg);
102  LOCK_TCPIP_CORE();
103  if (msg == NULL) {
104  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n"));
105  LWIP_ASSERT("tcpip_thread: invalid message", 0);
106  continue;
107  }
108  switch (msg->type) {
109 #if !LWIP_TCPIP_CORE_LOCKING
110  case TCPIP_MSG_API:
111  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg));
112  msg->msg.api_msg.function(msg->msg.api_msg.msg);
113  break;
114  case TCPIP_MSG_API_CALL:
115  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API CALL message %p\n", (void *)msg));
116  msg->msg.api_call.arg->err = msg->msg.api_call.function(msg->msg.api_call.arg);
117  sys_sem_signal(msg->msg.api_call.sem);
118  break;
119 #endif /* !LWIP_TCPIP_CORE_LOCKING */
120 
121 #if !LWIP_TCPIP_CORE_LOCKING_INPUT
122  case TCPIP_MSG_INPKT:
123  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg));
124  msg->msg.inp.input_fn(msg->msg.inp.p, msg->msg.inp.netif);
125  memp_free(MEMP_TCPIP_MSG_INPKT, msg);
126  break;
127 #endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */
128 
129 #if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS
130  case TCPIP_MSG_TIMEOUT:
131  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg));
132  sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg);
133  memp_free(MEMP_TCPIP_MSG_API, msg);
134  break;
135  case TCPIP_MSG_UNTIMEOUT:
136  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg));
137  sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg);
138  memp_free(MEMP_TCPIP_MSG_API, msg);
139  break;
140 #endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */
141 
142  case TCPIP_MSG_CALLBACK:
143  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
144  msg->msg.cb.function(msg->msg.cb.ctx);
145  memp_free(MEMP_TCPIP_MSG_API, msg);
146  break;
147 
149  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK_STATIC %p\n", (void *)msg));
150  msg->msg.cb.function(msg->msg.cb.ctx);
151  break;
152 
153  default:
154  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type));
155  LWIP_ASSERT("tcpip_thread: invalid message", 0);
156  break;
157  }
158  }
159 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tcpip_inpkt()

err_t tcpip_inpkt ( struct pbuf p,
struct netif inp,
netif_input_fn  input_fn 
)

Pass a received packet to tcpip_thread for input processing

Parameters
pthe received packet
inpthe network interface on which the packet was received
input_fninput function to call
170 {
171 #if LWIP_TCPIP_CORE_LOCKING_INPUT
172  err_t ret;
173  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_inpkt: PACKET %p/%p\n", (void *)p, (void *)inp));
174  LOCK_TCPIP_CORE();
175  ret = input_fn(p, inp);
177  return ret;
178 #else /* LWIP_TCPIP_CORE_LOCKING_INPUT */
179  struct tcpip_msg *msg;
180 
181  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
182 
183  msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT);
184  if (msg == NULL) {
185  return ERR_MEM;
186  }
187 
188  msg->type = TCPIP_MSG_INPKT;
189  msg->msg.inp.p = p;
190  msg->msg.inp.netif = inp;
191  msg->msg.inp.input_fn = input_fn;
192  if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
193  memp_free(MEMP_TCPIP_MSG_INPKT, msg);
194  return ERR_MEM;
195  }
196  return ERR_OK;
197 #endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */
198 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tcpip_input()

err_t tcpip_input ( struct pbuf p,
struct netif inp 
)

Pass a received packet to tcpip_thread for input processing with ethernet_input or ip_input. Don't call directly, pass to netif_add() and call netif->input().

Parameters
pthe received packet, p->payload pointing to the Ethernet header or to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or NETIF_FLAG_ETHERNET flags)
inpthe network interface on which the packet was received
213 {
214 #if LWIP_ETHERNET
215  if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) {
216  return tcpip_inpkt(p, inp, ethernet_input);
217  } else
218 #endif /* LWIP_ETHERNET */
219  return tcpip_inpkt(p, inp, ip_input);
220 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tcpip_callback_with_block()

err_t tcpip_callback_with_block ( tcpip_callback_fn  function,
void ctx,
u8_t  block 
)

Call a specific function in the thread context of tcpip_thread for easy access synchronization. A function called in that way may access lwIP core code without fearing concurrent access.

Parameters
functionthe function to call
ctxparameter passed to f
block1 to block until the request is posted, 0 to non-blocking mode
Returns
ERR_OK if the function was called, another err_t if not
235 {
236  struct tcpip_msg *msg;
237 
238  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
239 
240  msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
241  if (msg == NULL) {
242  return ERR_MEM;
243  }
244 
245  msg->type = TCPIP_MSG_CALLBACK;
246  msg->msg.cb.function = function;
247  msg->msg.cb.ctx = ctx;
248  if (block) {
250  } else {
251  if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
252  memp_free(MEMP_TCPIP_MSG_API, msg);
253  return ERR_MEM;
254  }
255  }
256  return ERR_OK;
257 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tcpip_send_msg_wait_sem()

err_t tcpip_send_msg_wait_sem ( tcpip_callback_fn  fn,
void apimsg,
sys_sem_t sem 
)

Sends a message to TCPIP thread to call a function. Caller thread blocks on on a provided semaphore, which ist NOT automatically signalled by TCPIP thread, this has to be done by the user. It is recommended to use LWIP_TCPIP_CORE_LOCKING since this is the way with least runtime overhead.

Parameters
fnfunction to be called from TCPIP thread
apimsgargument to API function
semsemaphore to wait on
Returns
ERR_OK if the function was called, another err_t if not
330 {
331 #if LWIP_TCPIP_CORE_LOCKING
333  LOCK_TCPIP_CORE();
334  fn(apimsg);
336  return ERR_OK;
337 #else /* LWIP_TCPIP_CORE_LOCKING */
339 
340  LWIP_ASSERT("semaphore not initialized", sys_sem_valid(sem));
341  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
342 
345  TCPIP_MSG_VAR_REF(msg).msg.api_msg.function = fn;
346  TCPIP_MSG_VAR_REF(msg).msg.api_msg.msg = apimsg;
350  return ERR_OK;
351 #endif /* LWIP_TCPIP_CORE_LOCKING */
352 }
Here is the call graph for this function:

◆ tcpip_api_call()

err_t tcpip_api_call ( tcpip_api_call_fn  fn,
struct tcpip_api_call_data call 
)

Synchronously calls function in TCPIP thread and waits for its completion. It is recommended to use LWIP_TCPIP_CORE_LOCKING (preferred) or LWIP_NETCONN_SEM_PER_THREAD. If not, a semaphore is created and destroyed on every call which is usually an expensive/slow operation.

Parameters
fnFunction to call
callCall parameters
Returns
Return value from tcpip_api_call_fn
366 {
367 #if LWIP_TCPIP_CORE_LOCKING
368  err_t err;
369  LOCK_TCPIP_CORE();
370  err = fn(call);
372  return err;
373 #else /* LWIP_TCPIP_CORE_LOCKING */
375 
376 #if !LWIP_NETCONN_SEM_PER_THREAD
377  err_t err = sys_sem_new(&call->sem, 0);
378  if (err != ERR_OK) {
379  return err;
380  }
381 #endif /* LWIP_NETCONN_SEM_PER_THREAD */
382 
383  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
384 
387  TCPIP_MSG_VAR_REF(msg).msg.api_call.arg = call;
388  TCPIP_MSG_VAR_REF(msg).msg.api_call.function = fn;
389 #if LWIP_NETCONN_SEM_PER_THREAD
390  TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = LWIP_NETCONN_THREAD_SEM_GET();
391 #else /* LWIP_NETCONN_SEM_PER_THREAD */
392  TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = &call->sem;
393 #endif /* LWIP_NETCONN_SEM_PER_THREAD */
395  sys_arch_sem_wait(TCPIP_MSG_VAR_REF(msg).msg.api_call.sem, 0);
397 
398 #if !LWIP_NETCONN_SEM_PER_THREAD
399  sys_sem_free(&call->sem);
400 #endif /* LWIP_NETCONN_SEM_PER_THREAD */
401 
402  return call->err;
403 #endif /* LWIP_TCPIP_CORE_LOCKING */
404 }
Here is the call graph for this function:

◆ tcpip_callbackmsg_new()

struct tcpip_callback_msg* tcpip_callbackmsg_new ( tcpip_callback_fn  function,
void ctx 
)

Allocate a structure for a static callback message and initialize it. This is intended to be used to send "static" messages from interrupt context.

Parameters
functionthe function to call
ctxparameter passed to function
Returns
a struct pointer to pass to tcpip_trycallback().
416 {
417  struct tcpip_msg *msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
418  if (msg == NULL) {
419  return NULL;
420  }
422  msg->msg.cb.function = function;
423  msg->msg.cb.ctx = ctx;
424  return (struct tcpip_callback_msg*)msg;
425 }
Here is the call graph for this function:

◆ tcpip_callbackmsg_delete()

void tcpip_callbackmsg_delete ( struct tcpip_callback_msg *  msg)

Free a callback message allocated by tcpip_callbackmsg_new().

Parameters
msgthe message to free
434 {
435  memp_free(MEMP_TCPIP_MSG_API, msg);
436 }
Here is the call graph for this function:

◆ tcpip_trycallback()

err_t tcpip_trycallback ( struct tcpip_callback_msg *  msg)

Try to post a callback-message to the tcpip_thread mbox This is intended to be used to send "static" messages from interrupt context.

Parameters
msgpointer to the message to post
Returns
sys_mbox_trypost() return code
447 {
448  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
449  return sys_mbox_trypost(&mbox, msg);
450 }
Here is the call graph for this function:

◆ tcpip_init()

void tcpip_init ( tcpip_init_done_fn  initfunc,
void arg 
)

Initialize this module:

  • initialize all sub modules
  • start the tcpip_thread
Parameters
initfunca function to call when tcpip_thread is running and finished initializing
argargument to pass to initfunc
463 {
464  lwip_init();
465 
466  tcpip_init_done = initfunc;
469  LWIP_ASSERT("failed to create tcpip_thread mbox", 0);
470  }
471 #if LWIP_TCPIP_CORE_LOCKING
472  if (sys_mutex_new(&lock_tcpip_core) != ERR_OK) {
473  LWIP_ASSERT("failed to create lock_tcpip_core", 0);
474  }
475 #endif /* LWIP_TCPIP_CORE_LOCKING */
476 
478 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pbuf_free_int()

static void pbuf_free_int ( void p)
static

Simple callback function used with tcpip_callback to free a pbuf (pbuf_free has a wrong signature for tcpip_callback)

Parameters
pThe pbuf (chain) to be dereferenced.
488 {
489  struct pbuf *q = (struct pbuf *)p;
490  pbuf_free(q);
491 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pbuf_free_callback()

err_t pbuf_free_callback ( struct pbuf p)

A simple wrapper function that allows you to free a pbuf from interrupt context.

Parameters
pThe pbuf (chain) to be dereferenced.
Returns
ERR_OK if callback could be enqueued, an err_t if not
501 {
503 }
Here is the call graph for this function:

◆ mem_free_callback()

err_t mem_free_callback ( void m)

A simple wrapper function that allows you to free heap memory from interrupt context.

Parameters
mthe heap memory to free
Returns
ERR_OK if callback could be enqueued, an err_t if not
514 {
515  return tcpip_callback_with_block(mem_free, m, 0);
516 }
Here is the call graph for this function:

Variable Documentation

◆ tcpip_init_done

tcpip_init_done_fn tcpip_init_done
static

◆ tcpip_init_done_arg

void* tcpip_init_done_arg
static

◆ mbox

sys_mbox_t mbox
static
sys_mbox_valid_val
#define sys_mbox_valid_val(mbox)
Definition: sys.h:311
tcpip_callback_with_block
err_t tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block)
Definition: tcpip.c:234
TCPIP_MSG_VAR_DECLARE
#define TCPIP_MSG_VAR_DECLARE(name)
Definition: tcpip.c:54
tcpip_msg::sem
sys_sem_t * sem
Definition: tcpip_priv.h:133
memp_malloc
void * memp_malloc(memp_t type)
Definition: memp.c:385
lwip_init
void lwip_init(void)
Definition: init.c:337
LWIP_TCPIP_THREAD_ALIVE
#define LWIP_TCPIP_THREAD_ALIVE()
Definition: opt.h:1574
TCPIP_DEBUG
#define TCPIP_DEBUG
Definition: opt.h:2814
LWIP_ASSERT
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:116
memp_free
void memp_free(memp_t type, void *mem)
Definition: memp.c:469
TCPIP_MSG_INPKT
Definition: tcpip_priv.h:114
sys_mbox_new
err_t sys_mbox_new(sys_mbox_t *mbox, int size)
Definition: sys_arch.c:50
mbox
static sys_mbox_t mbox
Definition: tcpip.c:61
tcpip_api_call_data::err
err_t err
Definition: tcpip_priv.h:100
tcpip_init_done_arg
static void * tcpip_init_done_arg
Definition: tcpip.c:60
NETIF_FLAG_ETHARP
#define NETIF_FLAG_ETHARP
Definition: netif.h:91
UNLOCK_TCPIP_CORE
#define UNLOCK_TCPIP_CORE()
Definition: tcpip.h:61
sys_arch_sem_wait
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
Definition: sys_arch.c:251
pbuf_free
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:715
sys_thread_new
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio)
Definition: sys_arch.c:376
NULL
#define NULL
Definition: usbd_def.h:53
sys_mbox_post
void sys_mbox_post(sys_mbox_t *mbox, void *msg)
Definition: sys_arch.c:96
tcpip_msg::msg
void * msg
Definition: tcpip_priv.h:128
tcpip_api_call_data::sem
sys_sem_t sem
Definition: tcpip_priv.h:102
ERR_MEM
Definition: err.h:65
TCPIP_MSG_VAR_REF
#define TCPIP_MSG_VAR_REF(name)
Definition: tcpip.c:53
TCPIP_MBOX_FETCH
#define TCPIP_MBOX_FETCH(mbox, msg)
Definition: tcpip.c:73
TCPIP_MSG_VAR_ALLOC
#define TCPIP_MSG_VAR_ALLOC(name)
Definition: tcpip.c:55
tcpip_thread
static void tcpip_thread(void *arg)
Definition: tcpip.c:87
TCPIP_MBOX_SIZE
#define TCPIP_MBOX_SIZE
Definition: opt.h:1566
tcpip_msg::input_fn
netif_input_fn input_fn
Definition: tcpip_priv.h:138
LWIP_UNUSED_ARG
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:308
tcpip_inpkt
err_t tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn)
Definition: tcpip.c:169
sys_sem_signal
void sys_sem_signal(sys_sem_t *sem)
Definition: sys_arch.c:275
tcpip_msg::inp
struct tcpip_msg::@61::@64 inp
sys_mutex_new
err_t sys_mutex_new(sys_mutex_t *mutex)
Definition: sys_arch.c:319
TCPIP_MSG_CALLBACK_STATIC
Definition: tcpip_priv.h:120
tcpip_msg
Definition: tcpip_priv.h:123
sys_sem_new
err_t sys_sem_new(sys_sem_t *sem, u8_t count)
Definition: sys_arch.c:206
ERR_OK
Definition: err.h:63
err_t
s8_t err_t
Definition: err.h:57
NETIF_FLAG_ETHERNET
#define NETIF_FLAG_ETHERNET
Definition: netif.h:95
TCPIP_THREAD_PRIO
#define TCPIP_THREAD_PRIO
Definition: opt.h:1557
TCPIP_MSG_API
Definition: tcpip_priv.h:112
TCPIP_MSG_API_CALL
Definition: tcpip_priv.h:113
tcpip_msg::ctx
void * ctx
Definition: tcpip_priv.h:142
pbuf_free_int
static void pbuf_free_int(void *p)
Definition: tcpip.c:487
TCPIP_THREAD_NAME
#define TCPIP_THREAD_NAME
Definition: opt.h:1539
sys_mbox_trypost
err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
Definition: sys_arch.c:104
TCPIP_MSG_VAR_FREE
#define TCPIP_MSG_VAR_FREE(name)
Definition: tcpip.c:56
TCPIP_THREAD_STACKSIZE
#define TCPIP_THREAD_STACKSIZE
Definition: opt.h:1548
tcpip_msg::p
struct pbuf * p
Definition: tcpip_priv.h:136
mem_free
void mem_free(void *rmem)
Definition: mem.c:419
sys_sem_valid
int sys_sem_valid(sys_sem_t *sem)
Definition: sys_arch.c:291
pbuf
Definition: pbuf.h:142
LWIP_DEBUGF
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:164
tcpip_init_done
static tcpip_init_done_fn tcpip_init_done
Definition: tcpip.c:59
LOCK_TCPIP_CORE
#define LOCK_TCPIP_CORE()
Definition: tcpip.h:60
TCPIP_MSG_CALLBACK
Definition: tcpip_priv.h:119
tcpip_msg::arg
struct tcpip_api_call_data * arg
Definition: tcpip_priv.h:132
sys_sem_free
void sys_sem_free(sys_sem_t *sem)
Definition: sys_arch.c:282