zynq Lwip学习笔记-low_level_init函数

前言

最近在学习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为关键调用。其主要作用是注册以太网数据接受与发送的中断函数。

  • 12
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值