LWIP一句話記住就行:
一項工程,兩份配置,三種內存分配,四套操作API,五步初始化,六個"數據流",七個數據結構
-------------------------------------------
前面在第一節乃至後面每一篇我都在強調五步初始化,第三節也實操了一下.
今天呢就詳細的再來講一下這五步初始化的具體操作.
1.xxx_init(網絡驅動,一般由具體廠商弄,比如BCM,RTL,AW...)
2.tcpip_init(lwip的初始化流程了)
3.lwip_init(就是一些通用協議,內存,網卡的初始化調用)
4.netif_init(網卡的初始化,同上步還有很多同級的初始化操作)
5.ethernetif_init(底層硬件初始化,上面的netif可以理解爲抽象的網卡)
1.xxx_init()
這裏我們還是借鑑博通的ap6203來看:
static int bcm_cmd_wifi_init(rt_uint32_t argc, char** argv)
{
rt_kprintf("argc=%d\n", argc);
if (argc > 1)
{
++argv;
--argc;
}
tcpip_init(NULL, NULL);
#ifdef USE_POLLING_MODE
mhd_config_polling(1);
mhd_config_polling_interval(50);
#endif
bcm_wifi_start();
return 0;
}
MSH_CMD_EXPORT_ALIAS(bcm_cmd_wifi_init, bcm_init, Broadcom WiFi Init commands);
這裏我們可以主要分兩個部分:
1.tcpip_inti()進行協議棧的初始化,也就是後面會提到的lwip_init().
2.mhd_xxx()以及bcm_xxx()這些都是博通網卡的初始化,你可以理解爲硬件操作,當然啦這都是不開源的,所以我也沒辦法幫大家分析了.
但你們知道的我總會給大家帶來點特別的東西.於是翻山越嶺,終於在<嵌入式網絡那些事LWIP協議>一書中找到了一個RTL8019的網卡初始化:
/************************************
**函數名:board_init
**輸入參數:無
**輸出參數:無
**功能描述:網卡復位與初始化函數
**************************************/
void board_int(void)
{
NE_RESET = 0x11;
Delay(500);
NE_CR = ENCR_PAGE0 + ENCR_NODMA;
NE_DCR = NEDCRVAL;
NE_TPSR = TX_START_PG;
NE_PSTART = RX_START_PG;
NE_STOP = RX_STOP_PG;
NE_BNRY = RX_START_PG;
...
本來想着把代碼全部粘貼上來,仔細一看就不要佔用我的版面了.因爲看不懂,所以我就簡單的告訴大家,這就是廠商自己整出來操作一下寄存器.如果你恰好在博通,聯發科,正基...這些公司,那就更不需要我說了,但是如果不是,哈哈就直接忽略吧.記住有這麼一個過程就好.
值得一提的是:
MSH_CMD_EXPORT_ALIAS(bcm_cmd_wifi_init, bcm_init, Broadcom WiFi Init commands);
可以看到集成了一條命令,bcm_init.那麼我們可以猜想一下,肯定還有聯網,斷開,掃描...命令,類似wifimanager.
2.tcpip_init()
好了我們接着來看重點:lwip/src/api/tcpip.c
/**
* @ingroup lwip_os
* Initialize this module:
* - initialize all sub modules
* - start the tcpip_thread
*
* @param initfunc a function to call when tcpip_thread is running and finished initializing
* @param arg argument to pass to initfunc
*/
void
tcpip_init(tcpip_init_done_fn initfunc, void *arg)
{
lwip_init();
tcpip_init_done = initfunc;
tcpip_init_done_arg = arg;
if (sys_mbox_new(&tcpip_mbox, TCPIP_MBOX_SIZE) != ERR_OK) {
LWIP_ASSERT("failed to create tcpip_thread mbox", 0);
}
#if LWIP_TCPIP_CORE_LOCKING
if (sys_mutex_new(&lock_tcpip_core) != ERR_OK) {
LWIP_ASSERT("failed to create lock_tcpip_core", 0);
}
#endif /* LWIP_TCPIP_CORE_LOCKING */
sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, RT_THREAD_PRIORITY_MAX-1);
}
1.調用lwip_init()初始化sub modules.
2.利用sys_mbox_new()創建一個郵箱.
3.利用sys_mutex_new()創建一個鎖.
4.利用sys_thread_new()創建一個tcpip_thread線程.
/**
* 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.
*
* @param arg unused argument
*/
static void
tcpip_thread(void *arg)
{
struct tcpip_msg *msg;
LWIP_UNUSED_ARG(arg);
LWIP_MARK_TCPIP_THREAD();
LOCK_TCPIP_CORE();
if (tcpip_init_done != NULL) {
tcpip_init_done(tcpip_init_done_arg);
}
while (1) { /* MAIN Loop */
LWIP_TCPIP_THREAD_ALIVE();
/* wait for a message, timeouts are processed while waiting */
TCPIP_MBOX_FETCH(&tcpip_mbox, (void **)&msg);
if (msg == NULL) {
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n"));
LWIP_ASSERT("tcpip_thread: invalid message", 0);
continue;
}
tcpip_thread_handle_msg(msg);
}
}
這裏我也只把代碼先貼出來,後面也會單獨來分析.總之tcpip_init()大家先記住上面這四步就行了,重要的兩步後面會詳細分析.
3.lwip_init()
一些子系統的初始化操作,包括sys,mem,memp,pbuf,tcp,udp,arp…
如果詳細的展開講,那麼篇幅就很長很長了,不過呢我之前在百度腦圖整了個流程分析.
這裏貼上連接,方便大家去跟一下.
https://naotu.baidu.com/file/9a8cb83b68a7ac578aa833079e2f3b83
這裏需要重點提出來的就是netif_init(),緊接着下一節我就會單獨來分析.
4.netif_init()
其實這也只是lwip_init()中調用的而已,只是個人覺得很重要就拿出來了.等下一節具體分析吧.
5.ethernetif_init()
其實這篇博文呢也只是給初始化開個頭,因爲接下來都會一直停留在初始化階段,會結合代碼詳細的分析.大家拭目以待吧.
-------------------------------------------
這期就到這裏了,LWIP想怎麼玩就怎麼玩,我們下期再見.