LWIP_简记(6.走一遍初始化)

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_简记(6.走一遍初始化)_第1张图片
LWIP_简记(6.走一遍初始化)_第2张图片
其实这篇博文呢也只是给初始化开个头,因为接下来都会一直停留在初始化阶段,会结合代码详细的分析.大家拭目以待吧.

-------------------------------------------
这期就到这里了,LWIP想怎么玩就怎么玩,我们下期再见.

你可能感兴趣的:(#,lwip专栏)