ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

QNX开发之ECAT专用网卡驱动ecpkt · 03-完成自协商

QNX开发之ECAT专用网卡驱动ecpkt · 03-完成自协商 QNX开发之ECAT专用网卡驱动ecpkt · 03-完成自协商在上一篇中我们准备好了Resource Manager框架得到了一个可以编译运行、但还没有任何功能的工程。这一篇的目标是完成硬件配置从硬件层面得到一条完整可用的链路为下一步的收发报文做准备。GEM支持千兆速率的自协商完成自协商可以作为硬件链路可用的标志我们就把它作为这一步的目标——具体来说把电路板上的网卡接到PC的网卡上在PC上看到网口状态变为“已连接”并协商出一个可用的速率就代表自协商成功。1. 从原生iopkt框架中剥离出目标网卡在原生iopkt框架中系统里所有的网卡都交给iopkt控制。ecpkt的第一步就是把目标网卡从iopkt中剥离出来由ecpkt取得完全的控制权——否则iopkt会和ecpkt同时操作这块网卡通信无法正常进行。原生devnp驱动会自动挂载系统中所有注册过的网卡devices_attached 0; for (idx 0; idx XZYNQ_MAX_INSTANCES; idx) { /* Use deviceindex values if specified. Otherwise, try every interface listed in hwinfo. */ if (num_dev_idx_opts 0) { if (dev_idx_opts[idx] ! ~0U) { attach_args.device_index dev_idx_opts[idx]; } else { /* Reached the end of the deviceindex values. */ break; } } else { /* Look up this device index in hwinfo. */ hwi_off hwi_find_device(XZYNQ_HWI_ENET, idx); if (hwi_off HWI_NULL_OFF) { /* Reached the end of the hwinfo list. */ break; } attach_args.device_index idx; } err dev_attach(eth, options, xzynq_ca, attach_args, single, dev[devices_attached], NULL);可以看到devnp根据启动参数deviceindex决定调用dev_attach挂载哪些网卡。所以我们只要在iopkt的启动参数里指定deviceindex就能限定iopkt只挂载指定的网卡从而把ecpkt的目标网卡从iopkt框架里剥离出来io-pkt-v6-hc -dxzynq-ultrascaledeviceindex0p0_mac000A350023C8这里我把网卡0交给iopkt去做Ethernet通信网卡1预留给ecpkt去做EtherCAT通信所以指定deviceindex为0。补充一下我最初尝试剥离网卡时没有注意到deviceindex这个参数陷入了另一个误区。我的系统没有用到设备树系统硬件都是在QNX的startup模块里注册的/* Add GEM0 */ hwidev_add_emac(emac_interface_idx, MPSOC_EMAC0_BASE, MPSOC_IRQ_GEM0, 0); /* Add GEM3 */ hwidev_add_emac(emac_interface_idx, MPSOC_EMAC3_BASE, MPSOC_IRQ_GEM3, 0);最初我认为直接在startup里去掉GEM3对应网卡1是最干净的事实上iopkt也确实不再也不能挂载GEM3了这种做法确实能保证GEM3完全由ecpkt控制。但代价是GEM3对QNX也不可见了会不会产生别的影响不好说所以并不推荐这样做。另一个顾虑在于startup的职责Zynq的startup似乎只是把硬件设备注册到系统设备列表但按我的理解startup模块还可以根据注册的硬件来使能对应模块的power和clock以此降低系统功耗——Zynq的BSP里没有这样做其他BSP里却可能会有所以还是尽量不要通过改动startup来分离硬件。从分层的角度来讲Startup → 注册硬件 → 使能硬件iopkt/ecpkt → 驱动硬件startup只负责硬件这一层的管理至于硬件由哪个软件来驱动——比如网卡由iopkt还是ecpkt来驱动——则由驱动层负责。2. 开始自协商网卡硬件分离完成后就可以开始尝试自协商了。上一篇里我们已经完成了软件逻辑部分包括GEM和PHY的基本配置并把devnp中的MDI控制移植到了ecpkt里理论上自协商可以直接进行了。为了监控自协商的过程我们在PHY的控制函数寄存器读写里加上了打印用来观察PHY芯片在自协商过程中的行为和最终结果uint16_t xzynq_mdi_read(void *hdl, uint8_t phyid, uint8_t reg) { … printf(%s:%d:%x:%x\r\n, __func__, __LINE__, reg, data); … } void xzynq_mdi_write(void *hdl, uint8_t phyid, uint8_t reg, uint16_t data) { … printf(%s:%d:%x:%x\r\n, __func__, __LINE__, reg, data); … }现在插上网线运行程序自协商会自动开始我们得到了下面的日志xzynq_mdi_read:67:1:7949← BMSR自协商重启中AN 未完成、link downxzynq_mdi_read:67:1:7949xzynq_mdi_read:67:1:7969← ★ bit5(0x0020) 置位自协商完成xzynq_mdi_read:67:1:796d← ★ bit2(0x0004) 置位链路建立这就表示自协商完成、链路成功建立此时在PC上可以看到对应的网口状态变成可以看到网卡工作在1.0Gbps 的全双工链路与协商结果一致至此初始化阶段全部完成驱动第一次真正“拥有”了这块网卡PHY自协商成功、link状态正常。接下来就可以开发最关键的报文收发功能了。
返回列表