blob: 7cbc93a51f9ef0c5b7dbd23737c6c47a20ca4407 [file] [log] [blame]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>lwIP: Common pitfalls</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
$(document).ready(initResizable);
</script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">lwIP
&#160;<span id="projectnumber">2.1.2</span>
</div>
<div id="projectbrief">Lightweight IP stack</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search",false,'Search');
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
$(function() {
initMenu('',true,false,'search.php','Search');
$(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
<div id="nav-tree">
<div id="nav-tree-contents">
<div id="nav-sync" class="sync"></div>
</div>
</div>
<div id="splitbar" style="-moz-user-select:none;"
class="ui-resizable-handle">
</div>
</div>
<script type="text/javascript">
$(document).ready(function(){initNavTree('pitfalls.html','');});
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0"
name="MSearchResults" id="MSearchResults">
</iframe>
</div>
<div class="header">
<div class="headertitle">
<div class="title">Common pitfalls </div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><h1>Multiple Execution Contexts in lwIP code </h1>
<p>The most common source of lwIP problems is to have multiple execution contexts inside the lwIP code.</p>
<p>lwIP can be used in two basic modes: <a class="el" href="group__lwip__nosys.html">Mainloop mode ("NO_SYS")</a> (no OS/RTOS running on target system) or <a class="el" href="group__lwip__os.html">OS mode (TCPIP thread)</a> (there is an OS running on the target system).</p>
<p>See also: <a class="el" href="multithreading.html">Multithreading</a> (especially the part about <a class="el" href="group__lwip__opts__lock.html#ga6a30040db307b3459fc11906bd433f75">LWIP_ASSERT_CORE_LOCKED()</a>!)</p>
<h2>Mainloop Mode </h2>
<p>In mainloop mode, only <a class="el" href="group__callbackstyle__api.html">"raw" APIs</a> can be used. The user has two possibilities to ensure there is only one exection context at a time in lwIP:</p>
<p>1) Deliver RX ethernet packets directly in interrupt context to lwIP by calling netif-&gt;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.</p>
<p>2) Run lwIP in a mainloop. There is example code here: <a class="el" href="group__lwip__nosys.html">Mainloop mode ("NO_SYS")</a>. lwIP is <em>ONLY</em> 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 <em>NEVER</em> called from an interrupt, e.g. some SPI IRQ wants to forward data to <a class="el" href="group__udp__raw.html#gaa4546c43981f043c0ae4514d625cc3fc">udp_send()</a> or <a class="el" href="group__tcp__raw.html#ga6b2aa0efbf10e254930332b7c89cd8c5">tcp_write()</a>!</p>
<h2>OS Mode </h2>
<p>In OS mode, <a class="el" href="group__callbackstyle__api.html">"raw" APIs</a> AND <a class="el" href="group__sequential__api.html">Sequential-style APIs</a> can be used. <a class="el" href="group__sequential__api.html">Sequential-style APIs</a> are designed to be called from threads other than the TCPIP thread, so there is nothing to consider here. But <a class="el" href="group__callbackstyle__api.html">"raw" APIs</a> functions must <em>ONLY</em> 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 <a class="el" href="group__lwip__os.html#gae510f195171bed8499ae94e264a92717">tcpip_input()</a>.​​ Again, ensure lwIP is <em>NEVER</em> called from an interrupt, e.g. some SPI IRQ wants to forward data to <a class="el" href="group__udp__raw.html#gaa4546c43981f043c0ae4514d625cc3fc">udp_send()</a> or <a class="el" href="group__tcp__raw.html#ga6b2aa0efbf10e254930332b7c89cd8c5">tcp_write()</a>!</p>
<p>1) <a class="el" href="group__lwip__os.html#gaab838fe3417ab3a1f61f0728009a0c2a">tcpip_callback()</a> can be used get called back from TCPIP thread, it is safe to call any <a class="el" href="group__callbackstyle__api.html">"raw" APIs</a> from there.</p>
<p>2) Use <a class="el" href="group__lwip__opts__lock.html#ga8e46232794349c209e8ed4e9e7e4f011">LWIP_TCPIP_CORE_LOCKING</a>. All <a class="el" href="group__callbackstyle__api.html">"raw" APIs</a> functions can be called when lwIP core lock is aquired, see <a class="el" href="tcpip_8h.html#a4700525e737fc025fea4887b172e0c95">LOCK_TCPIP_CORE()</a> and <a class="el" href="tcpip_8h.html#a915effea029b9c4891e1ec635eb1826d">UNLOCK_TCPIP_CORE()</a>. These macros cannot be used in an interrupt context! Note the OS must correctly handle priority inversion for this.</p>
<h1>Cache / DMA issues </h1>
<h2>DMA-capable ethernet hardware and zero-copy RX </h2>
<p>lwIP changes the content of RECEIVED pbufs in the TCP code path. This implies one or more cacheline(s) of the RX pbuf become dirty and need to be flushed before the memory is handed over to the DMA ethernet hardware for the next telegram to be received. See <a href="http://lists.nongnu.org/archive/html/lwip-devel/2017-12/msg00070.html">http://lists.nongnu.org/archive/html/lwip-devel/2017-12/msg00070.html</a> for a more detailed explanation. Also keep in mind the user application may also write into pbufs, so it is generally a bug not to flush the data cache before handing a buffer to DMA hardware.</p>
<h2>DMA-capable ethernet hardware and cacheline alignment </h2>
<p>Nice description about DMA capable hardware and buffer handling: <a href="http://www.pebblebay.com/a-guide-to-using-direct-memory-access-in-embedded-systems-part-two/">http://www.pebblebay.com/a-guide-to-using-direct-memory-access-in-embedded-systems-part-two/</a> Read especially sections "Cache coherency" and "Buffer alignment". </p>
</div></div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
<li class="footer">Generated by
<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.8.13 </li>
</ul>
</div>
</body>
</html>