首页 > 其他分享 >zynq Lwip学习笔记-low_level_init函数

zynq Lwip学习笔记-low_level_init函数

时间:2024-04-06 09:02:38浏览次数:21  
标签:Lwip netif level 网络接口 mac init xemac xemacpsif

这里写目录标题

前言

最近在学习zynq中的lwip协议族,找不到很好的记笔记的地方,所以就用csdn记录一下自己的学习过程。现在对lwip不熟悉,只是把官方的lwip echo server例程跑了一下,能跑通就一点点的照着学了,笔记都是根据自己的理解写的,而且部分内容可能也只针对lwip echo server例程有效,笔记可以供有缘人参考,但不敢保证全对,有不对的地方也期待有高人指点一二。
————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/weixin_40356705/article/details/136824649

一、概述

  • 原型
static err_t low_level_init(struct netif *netif)
  • 参数
    struct netif *netif :结构体的指针,该结构体包含了网络接口的各种信息,如名称、输出函数、链路层输出函数等。
  • 作用
  • 网络接口初始化函数

二、函数体

static err_t low_level_init(struct netif *netif)  
{  
	/* 将网络接口的状态(MAC地址)转换为无符号整数指针 */  
	UINTPTR mac_address = (UINTPTR)(netif->state);  
	  
	/* 定义指向xemac结构体和xemacpsif结构体的指针 */  
	struct xemac_s *xemac;  
	xemacpsif_s *xemacpsif;  
	  
	/* 定义DMA控制寄存器变量 */  
	u32 dmacrreg;  
	  
	/* 定义状态变量,用于记录函数执行状态 */  
	s32_t status = XST_SUCCESS;  
	  
	/* 将全局变量NetIf指向当前网络接口 */  
	NetIf = netif;  
	  
	/* 为xemacpsif结构体分配内存 */  
	xemacpsif = mem_malloc(sizeof *xemacpsif);  
	if (xemacpsif == NULL) {  
		/* 如果内存分配失败,则打印调试信息并返回内存错误 */  
		LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_init: out of memory\r\n"));  
		return ERR_MEM;  
	}  
	  
	/* 为xemac结构体分配内存 */  
	xemac = mem_malloc(sizeof *xemac);  
	if (xemac == NULL) {  
		/* 如果内存分配失败,则释放之前为xemacpsif分配的内存,并返回内存错误 */  
		mem_free(xemacpsif);  
		LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_init: out of memory\r\n"));  
		return ERR_MEM;  
	}  
	  
	/* 设置xemac结构体的状态字段为xemacpsif结构体的地址 */  
	xemac->state = (void *)xemacpsif;  
	  
	/* 根据MAC地址查找拓扑索引 */  
	xemac->topology_index = xtopology_find_index(mac_address);  
	  
	/* 设置xemac结构体的类型为xemacps */  
	xemac->type = xemac_type_emacps;  
	  
	/* 初始化xemacpsif结构体的发送队列为空 */  
	xemacpsif->send_q = NULL;  
	  
	/* 创建接收队列 */  
	xemacpsif->recv_q = pq_create_queue();  
	if (!xemacpsif->recv_q) {  
		/* 如果队列创建失败,则释放之前分配的内存,并返回内存错误 */  
		mem_free(xemac);  
		mem_free(xemacpsif);  
		return ERR_MEM;  
	}  
	  
	/* 设置网络接口的最大传输单元(MTU) */  
#ifdef ZYNQMP_USE_JUMBO  
	/* 如果定义了ZYNQMP_USE_JUMBO,则使用更大的MTU */  
	netif->mtu = XEMACPS_MTU_JUMBO - XEMACPS_HDR_SIZE;  
#else  
	/* 否则使用默认的MTU */  
	netif->mtu = XEMACPS_MTU - XEMACPS_HDR_SIZE;  
#endif  
	  
	/* 设置网络接口支持的IGMP和MLD过滤函数 */  
#if LWIP_IGMP  
	netif->igmp_mac_filter = xemacpsif_mac_filter_update;  
#endif  
	  
#if LWIP_IPV6 && LWIP_IPV6_MLD  
	netif->mld_mac_filter = xemacpsif_mld6_mac_filter_update;  
#endif  
	  
	/* 设置网络接口的标志位 */  
	netif->flags = NETIF
	NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP |  
											NETIF_FLAG_LINK_UP;  
  
	/* 如果支持IPv6和MLD,则设置相应的标志位 */  
#if LWIP_IPV6 && LWIP_IPV6_MLD  
	netif->flags |= NETIF_FLAG_MLD6;  
#endif  
  
	/* 如果支持IGMP,则设置相应的标志位 */  
#if LWIP_IGMP  
	netif->flags |= NETIF_FLAG_IGMP;  
#endif  
  
	/* 在没有操作系统的环境下,创建用于接收数据可用的信号量 */  
#if !NO_SYS  
	sys_sem_new(&xemac->sem_rx_data_available, 0);  
#endif  
  
	/* 获取该EMAC的配置信息 */  
	mac_config = (XEmacPs_Config *)xemacps_lookup_config((unsigned)(UINTPTR)netif->state);  
  
	/* 在EL1非安全模式下,请求设备以指示此库正在使用它 */  
#if EL1_NONSECURE  
	if (mac_config->BaseAddress == VERSAL_EMACPS_0_BASEADDR) {  
		Xil_Smc(PM_REQUEST_DEVICE_SMC_FID, DEV_GEM_0, 1, 0, 100, 1, 0, 0);  
	}  
	if (mac_config->BaseAddress == VERSAL_EMACPS_1_BASEADDR) {  
		Xil_Smc(PM_REQUEST_DEVICE_SMC_FID, DEV_GEM_1, 1, 0, 100, 1, 0, 0);  
	}  
#endif 
// 初始化EMACPS硬件  
status = XEmacPs_CfgInitialize(&xemacpsif->emacps, mac_config, mac_config->BaseAddress);  
// 检查初始化是否成功  
if (status != XST_SUCCESS) {  
    // 如果初始化失败,则打印错误信息  
    xil_printf("In %s:EmacPs Configuration Failed....\r\n", __func__);  
}  
  
// 调用函数来进一步初始化EMACPS  
init_emacps(xemacpsif, netif);  
  
// 读取EMACPS的DMA控制寄存器的内容  
dmacrreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_DMACR_OFFSET);  
// 修改DMA控制寄存器的值,这里通过或运算设置特定的位  
dmacrreg = dmacrreg | (0x00000010);  
// 将修改后的值写回DMA控制寄存器  
XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_DMACR_OFFSET, dmacrreg);  
  
// 条件编译,只有当定义了FreeRTOS操作系统,并且是ARM架构且不是ARMR5时,以下代码才会被编译  
#if defined(OS_IS_FREERTOS) && defined(__arm__) && !defined(ARMR5)  
    // 创建一个FreeRTOS定时器,周期为10ms,回调函数为vTimerCallback  
    xemac->xTimer = xTimerCreate("Timer", 10, pdTRUE, ( void * ) 1, vTimerCallback);  
    // 检查定时器是否创建成功  
    if (xemac->xTimer == NULL) {  
        // 如果定时器创建失败,则打印错误信息  
        xil_printf("In %s:Timer creation failed....\r\n", __func__);  
    } else {  
        // 启动定时器  
        if(xTimerStart(xemac->xTimer, 0) != pdPASS) {  
            // 如果定时器启动失败,则打印错误信息  
            xil_printf("In %s:Timer start failed....\r\n", __func__);  
        }  
    }  
#endif  
  
// 设置EMACPS的中断服务例程  
setup_isr(xemac);  
  
// 初始化EMACPS的DMA功能  
init_dma(xemac);  
  
// 启动EMACPS硬件  
start_emacps(xemacpsif);  
  
// 将网络接口的状态更新为EMAC实例的指针  
// 这样其他与网络接口相关的函数可以通过netif->state来访问EMAC实例  
netif->state = (void *)xemac;  
  
// 返回成功状态  
return ERR_OK;
}

三、调用关系

被xemacpsif_init调用,重点调用了setup_isr,init_dma,start_emacps函数。其中setup_isr为关键调用。其主要作用是注册以太网数据接受与发送的中断函数。

标签:Lwip,netif,level,网络接口,mac,init,xemac,xemacpsif
From: https://blog.csdn.net/weixin_40356705/article/details/137412632

相关文章

  • zynq Lwip学习笔记-setup_isr 函数
    这里写目录标题前言一、概述二、函数体三、调用关系前言最近在学习zynq中的lwip协议族,找不到很好的记笔记的地方,所以就用csdn记录一下自己的学习过程。现在对lwip不熟悉,只是把官方的lwipechoserver例程跑了一下,能跑通就一点点的照着学了,笔记都是根据自己的理解写的......
  • 【WCH以太网接口系列芯片】STM32+CH390+Lwip协议栈简单应用测试
    本篇文章基于STM32F103和CH390H芯片进行例程移植及相关注意事项,简单验证TCP\UDP\Ping基础功能。硬件:STM32F103开发板+沁恒CH390H的评估版图一示,SPI使用接口为:INT->PA0,RST->PA1,CS->PA2,SCK->PA5,MISO->PA6,MOSI->PA7,WOL->PA8。 图一 软件移植:采用的沁恒官方提供的CH......
  • 构造函数init到底是什么作用 是下面的方法都可以从init里面获取参数吗?(AI+Python)
    大家好,我是Python进阶者。一、前言前几天在Python白银交流群【无敌劈叉小狗】问了一个Python基础的问题,问题如下:问一下构造函数init到底是什么作用是下面的方法都可以从init里面获取参数吗?二、实现过程这里【黄志诚】分享了自己的一个经验:全局呀,相当于初始化一个参数,全局都......
  • 初始化kubeadm init失败,再次初始化时显示6443、10259、10257、10250、2379、2380被占
    第一次使用kubeadminit初始化时,因kubelet.service和和kubelet未启动等部分原因导致初始化失败,当再次初始化时显示6443、10259、10257、10250、2379、2380这几个端口被占用,一个个使用sudolsof-i:port查看太麻烦,直接使用kubeadmreset将当前节点恢复为未安装Kubernetes的状......
  • gem5 CPU ISA level is lower than required
    错误提示:/lib/x86_64-linux-gnu/libc.so.6:CPUISAlevelislowerthanrequired错误截图:在互联网上搜索该错误,在gem5的邮件列表发现:Jason说在某次commit解决了这个问题,然后去这两个链接里面看一下:大概的意思是说GLIBC更新了,对硬件检查更严格了。当尝试加载动态......
  • 洛谷P3543 [POI2012] WYR-Leveling Ground
    题目描述给定\(n\)个数和\(a,b\)每次可以选择一段区间\(+a,-a,+b,或-b\),问最少操作几次能把它们都变成\(0\)。如果无解请输出\(-1\)。样例输入5231211-15分析对于区间修改是很麻烦的,为了简化复杂度,这里可以将数组转化为差分数组以降低难度,对于每一个数,我......
  • KingbaseES V8R6集群运维案例之---数据库实例initdb后配置
    案例说明:KingbaseESV8R6集群在数据库实例启动时需加载repmgr插件,并且具有集群管理的用户esrep和存储元数据的数据库esrep库;但在手工initdb新的实例后,默认的实例将不包含repmgrextension及esrep库和esrep用户,需要手工配置,完善集群管理应用。适用版本:KingbaseESV8R6一、默认......
  • 安洵杯2023 side_channel , initiate!:侧信道爆破flag
    当程序有办法读取到flag但无法将flag输出出来时,可以采用侧信道爆破flag确定其内容。例题:安洵杯2023side_channel,initiate!题目本身很简单,允许在bss上写一大段,然后一个栈溢出。但沙箱是这个画风:函数里还有一个单纯的movrax0fh,允许了rt_stgreturn和mprotect的权限,很明显的提......
  • Error in callback for immediate watcher “chartsData“: “Error: Initialize fail
     在使用echarts提示dom未找到,原因就是当我们封装了echarts组件初始化传值时通常会造成过早调用,也就是在数据还未处理完就已经调用init函数进行初始化,此时dom还未挂载成功,就会报这个错,这里解决可以使用nextTick()函数在初始化时延时调用;this.$nextTick(()=>{this.draw......
  • C语言实现半定规划(Semidefinite Programming, SDP)算法
    目录前言A.建议B.简介一代码实现A.半定规划的基本概念B.使用C语言进行半定规划建模二时空复杂度A.时间复杂度B.空间复杂度C.实际考虑三优缺点A.优点B.缺点C.总结四现实中的应用前言A.建议1.学习算法最重要的是理解算法的每一步,而不是记住算法。2.......