0
点赞
收藏
分享

微信扫一扫

【SemiDrive源码分析】【X9芯片启动流程】15 - freertos_safetyos目录 R5 SafetyOS 之 tcpip_init() 代码流程分析



【SemiDrive源码分析】【X9芯片启动流程】15 - freertos_safetyos目录 R5 SafetyOS 之 tcpip_init 代码流程分析

  • ​​1. tcpip_init() 初始化tcpip相关模块,初始化MailBox邮箱,创建tcpip_thread 线程​​
  • ​​1.1 lwip_init() 初始化回环网卡,随机生成Port口,配置超时时间及处理函数​​
  • ​​1.2 tcpip_thread() 线程函数​​


本 SemiDrive源码分析 之 Yocto源码分析 系列文章汇总如下:

  1. 《​​【SemiDrive源码分析】【Yocto源码分析】01 - yocto/base目录源码分析(编译环境初始化流程)​​》
  2. 《​​【SemiDrive源码分析】【Yocto源码分析】02 - yocto/meta-openembedded目录源码分析​​》
  3. 《​​【SemiDrive源码分析】【Yocto源码分析】03 - yocto/meta-semidrive目录及Yocto Kernel编译过程分析(上)​​》
  4. 《​​【SemiDrive源码分析】【Yocto源码分析】04 - yocto/meta-semidrive目录及Yocto Kernel编译过程分析(下)​​》
  5. 《​​【SemiDrive源码分析】【Yocto源码分析】05 - 找一找Yocto Kernel编译过程中所有Task的源码在哪定义的呢?​​》
  6. 《​​【SemiDrive源码分析】【Yocto源码分析】06 - Kernel编译生成的Image.bin、Image_nobt.dtb、modules.tgz 这三个文件分别是如何生成的?​​》
  7. 《​​【SemiDrive源码分析】【Yocto源码分析】07 - core-image-base-x9h_ref_serdes.rootfs.ext4 文件系统是如何生成的​​》
  8. 《​​【SemiDrive源码分析】【X9芯片启动流程】08 - X9平台 lk 目录源码分析 之 目录介绍​​》
  9. 《​​【SemiDrive源码分析】【X9芯片启动流程】09 - X9平台系统启动流程分析​​》
  10. 《​​【SemiDrive源码分析】【X9芯片启动流程】10 - BareMetal_Suite目录R5 DIL.bin 引导程序源代码分析​​》
  11. 《​​【SemiDrive源码分析】【X9芯片启动流程】11 - freertos_safetyos目录Cortex-R5 DIL2.bin 引导程序源代码分析​​》
  12. 《​​【SemiDrive源码分析】【X9芯片启动流程】12 - freertos_safetyos目录Cortex-R5 DIL2.bin 之 sdm_display_init 显示初始化源码分析​​》
  13. 《​​【SemiDrive源码分析】【X9芯片驱动调试】13 - GPIO 配置方法​​》
  14. 《​​【SemiDrive源码分析】【X9芯片启动流程】14 - freertos_safetyos目录Cortex-R5 SafetyOS/RTOS工作流程分析​​》
  15. 《​​【SemiDrive源码分析】【X9芯片启动流程】15 - freertos_safetyos目录 R5 SafetyOS 之 tcpip_init() 代码流程分析​​》
  16. 《【SemiDrive源码分析】【X9芯片启动流程】16 - freertos_safetyos目录 R5 SafetyOS 之 LK_INIT_LEVEL_PLATFORM 阶段代码流程分析》
  17. 《【SemiDrive源码分析】【X9芯片启动流程】17 - freertos_safetyos目录 R5 SafetyOS 之 LK_INIT_LEVEL_TARGET 阶段代码流程分析》
  18. 《【SemiDrive源码分析】【X9芯片启动流程】18 - freertos_safetyos目录 R5 SafetyOS 之 .apps 应用启动代码流程分析》



前文,我们分析​​Cortex-R5​​ ​​SafetyOS​​系统的启动流程,分析到执行​​LK_INIT_LEVEL_THREADING​​ 阶段的任务,

在这个阶段时,主要是执行​​boot_sec()​​、​​lwip_init_hook()​​两个函数,其中:

  1. ​boot_sec()​​​ 主要是​​Safety R5​​​​CPU​​​ 触发​​Secure R5​​​​CPU​​​重启,加载并运行​​Ssytem​​镜像。
  2. ​lwip_init_hook()​​​ 主要是初始化并启动​​lwip​​​ 这个小型开源的​​TCP/IP​​协议栈功能。

​lwip​​是一个小型开源的​​TCP/IP​​协议栈源码,主要目的是在保持​​TCP​​协议主要功能的基础上减少对​​RAM​​ 的占用,

有无操作系统的支持都可以运行,它只需十几​​KB​​的​​RAM​​和​​40K​​左右的​​ROM​​就可以运行。

它由宏控​​SUPPORT_LWIP​​来控制是否编译。

在​​lwip_init_hook() ​​​中主要是对​​tcpip_init() ​​函数的封装,如下:

# rtos\lk_boot\3rd\lwip\contrib\ports\lk\sys_arch.c
/* run lwip init as soon as threads are running */
void lwip_init_hook(uint level){
tcpip_init(NULL, NULL);
}

LK_INIT_HOOK(lwip, &lwip_init_hook, LK_INIT_LEVEL_THREADING);

那本文来分析下​​tcpip_init() ​​这个小型​​TCP/IP​​开源协议栈的初始化过程。




1. tcpip_init() 初始化tcpip相关模块,初始化MailBox邮箱,创建tcpip_thread 线程

主要工作如下:

  1. 初始化回环网卡,随机生成​​Port​​口,配置超时时间及处理函数
  2. 初始化​​tcpip mailbox​​ 邮箱
  3. 创建​​tcpip_thread​​ 线程
# rtos\lk_boot\3rd\lwip\src\api\tcpip.c
/* @ingroup lwip_os Initialize this module: initialize all sub modules, start the tcpip_thread */
void tcpip_init(tcpip_init_done_fn initfunc, void *arg)
{
// 1. 初始化回环网卡,随机生成Port口,配置超时时间及处理函数
lwip_init();

tcpip_init_done = initfunc;
tcpip_init_done_arg = arg;

// 2. 初始化 tcpip mailbox 邮箱
if (sys_mbox_new(&tcpip_mbox, TCPIP_MBOX_SIZE) != ERR_OK) { LWIP_ASSERT("failed to create tcpip_thread mbox", 0);}
================>
mbox->sem = CreateSemaphore(0, 0, MAX_QUEUE_ENTRIES, 0);
memset(&mbox->q_mem, 0, sizeof(u32_t)*MAX_QUEUE_ENTRIES);
mbox->head = 0;
mbox->tail = 0;
<================

// 3. 创建 tcpip_thread 线程
sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
}



1.1 lwip_init() 初始化回环网卡,随机生成Port口,配置超时时间及处理函数

主要工作如下:

  1. 初始化并启动​​127.0.0.1​​ 回环网卡
  2. 从​​49152​​​ 到​​65535​​​随机生成一个​​UDP Port口​
  3. 从​​49152​​​ 到​​65535​​​随机生成一个​​TCP Port口​
  4. 配置各场景超时时间及超时函数
# buildsystem\rtos\lk_boot\3rd\lwip\src\core\init.c
/* Initialize all modules, Use this in NO_SYS mode. Use tcpip_init() otherwise*/
void lwip_init(void){

/* Modules initialization */
stats_init(); // 空函数 lwip_stats.mem.name = "MEM";
sys_init(); // 空函数
lwip_mem_init(); // 空函数
memp_init(); // 定义了MEMP_MEM_MALLOC ,不需要提前申请内存池,这个函数不会跑
pbuf_init(); // 空函数
netif_init(); // 初始化并启动 127.0.0.1 回环网卡
===============>
#define LOOPIF_ADDRINIT &loop_ipaddr, &loop_netmask, &loop_gw,
ip4_addr_t loop_ipaddr, loop_netmask, loop_gw;
IP4_ADDR(&loop_gw, 127, 0, 0, 1);
IP4_ADDR(&loop_ipaddr, 127, 0, 0, 1);
IP4_ADDR(&loop_netmask, 255, 0, 0, 0);
netif_add(&loop_netif, LOOPIF_ADDRINIT NULL, netif_loopif_init, tcpip_input);
netif_set_link_up(&loop_netif);
netif_set_up(&loop_netif);
<===============
ip_init(); // 空函数
etharp_init(); // 空函数
raw_init(); // 空函数
udp_init(); // 从49152 through 65535随机生成一个UDP Port口:udp_port = UDP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND());
tcp_init(); // 从49152 through 65535随机生成一个TCP Port口:tcp_port = TCP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND());

#if LWIP_DNS // 0
dns_init();
#endif /* LWIP_DNS */
#if PPP_SUPPORT // 0
ppp_init();
#endif

sys_timeouts_init(); // 配置各场景超时时间及超时函数
==================>
/** Initialize this module */
void sys_timeouts_init(void)
{
size_t i;
/* tcp_tmr() at index 0 is started on demand */
for (i = (LWIP_TCP ? 1 : 0); i < LWIP_ARRAYSIZE(lwip_cyclic_timers); i++) {
sys_timeout(lwip_cyclic_timers[i].interval_ms, lwip_cyclic_timer, LWIP_CONST_CAST(void *, &lwip_cyclic_timers[i]));
}
}
// 超时时间定义于: buildsystem\rtos\lk_boot\3rd\lwip\src\core\timeouts.c
const struct lwip_cyclic_timer lwip_cyclic_timers[] = {
#if LWIP_TCP
{TCP_TMR_INTERVAL, HANDLER(tcp_tmr)}, // 250ms, 如果超时运行 tcp_tmr() 释放
#endif /* LWIP_TCP */
#if LWIP_IPV4
{IP_TMR_INTERVAL, HANDLER(ip_reass_tmr)}, // 1s , 如果超时运行 ip_reass_tmr() 释放
#if LWIP_ARP
{ARP_TMR_INTERVAL, HANDLER(etharp_tmr)}, // 1s , 如果超时运行 ip_reass_tmr() 释放
#endif /* LWIP_ARP */
#endif /* LWIP_IPV4 */
// 后面的宏都没定义,我就不写了
};
<==================
}



1.2 tcpip_thread() 线程函数

主要工作如下:

# buildsystem\rtos\lk_boot\3rd\lwip\src\api\tcpip.c
/**
* 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.
*/
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);
}
}



举报

相关推荐

0 条评论