20181025 vivado2016.4 sdk
花了两天时间看的,总算是看懂了一点,不过主要看的是以太网怎样接收数据和发送数据的,其他的还不是很懂,将看懂的记录下,给需要的人一点参考。
这个官方例子应该是通过以太网中断接收数据,并且回传接收的数据。这里timer中断的作用还没看明白。
不用看懂所有代码,只需要看有注释的地方。没几句,看着很简单,但是自己去看程序的时候就没那么顺利。拿来主义是最简单的,自己看这些,太花时间。以前拿来的太多,还是多还点吧。
main函数之前都是库的调用和通用配置就不讲了
int main() { struct ip_addr ipaddr, netmask, gw; /* the mac address of the board. this should be unique per board */ unsigned char mac_ethernet_address[] = { 0x00, 0x0a, 0x35, 0x00, 0x01, 0x02 }; echo_netif = &server_netif; #if defined (__arm__) && !defined (ARMR5) #if XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1 || XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1 ProgramSi5324(); ProgramSfpPhy(); #endif #endif /* Define this board specific macro in order perform PHY reset on ZCU102 */ #ifdef XPS_BOARD_ZCU102 IicPhyReset(); #endif init_platform();//timer中断初始化init_platform()函数原型 在platform_zynq.c中
main函数 #if LWIP_DHCP==1 ipaddr.addr = 0; gw.addr = 0; netmask.addr = 0; #else /* initliaze IP addresses to be used */ IP4_ADDR(&ipaddr, 192, 168, 1, 10); IP4_ADDR(&netmask, 255, 255, 255, 0); IP4_ADDR(&gw, 192, 168, 1, 1); #endif print_app_header(); lwip_init(); /* Add network interface to the netif_list, and set it as default */ //最重要,以太网中断函数在这里指定 if (!xemac_add(echo_netif, &ipaddr, &netmask,//引用xemacpsif_init()函数,引用以太网的中断函数 &gw, mac_ethernet_address, PLATFORM_EMAC_BASEADDR)) { xil_printf("Error adding N/W interface\n\r"); return -1; }选中xemac_add函数鼠标右击选择Open Declaration,可以查看xemac_add
/* * xemac_add: this is a wrapper around lwIP's netif_add function. * The objective is to provide portability between the different Xilinx MAC's * This function can be used to add both xps_ethernetlite and xps_ll_temac * based interfaces xemacpsif_init */ struct netif * xemac_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask, struct ip_addr *gw, unsigned char *mac_ethernet_address, unsigned mac_baseaddr) { int i; /* set mac address */ netif->hwaddr_len = 6; for (i = 0; i < 6; i++) netif->hwaddr[i] = mac_ethernet_address[i]; /* initialize based on MAC type */ switch (find_mac_type(mac_baseaddr)) { case xemac_type_xps_emaclite: #ifdef XLWIP_CONFIG_INCLUDE_EMACLITE return netif_add(netif, ipaddr, netmask, gw, (void*)mac_baseaddr, xemacliteif_init, #if NO_SYS ethernet_input #else tcpip_input #endif ); #else return NULL; #endif case xemac_type_axi_ethernet: #ifdef XLWIP_CONFIG_INCLUDE_AXI_ETHERNET return netif_add(netif, ipaddr, netmask, gw, (void*)mac_baseaddr, xaxiemacif_init, #if NO_SYS ethernet_input #else tcpip_input #endif ); #else return NULL; #endif #if defined (__arm__) || defined (__aarch64__) case xemac_type_emacps://执行的是这个case xil_printf("xemacpsif_init11\n\r"); #ifdef XLWIP_CONFIG_INCLUDE_GEM xil_printf("xemacpsif_init22\n\r"); return netif_add(netif, ipaddr, netmask, gw, (void*)(UINTPTR)mac_baseaddr, xemacpsif_init,//以太网中断初始化在这个函数里 #if NO_SYS ethernet_input #else tcpip_input #endif ); #endif #endif default: xil_printf("unable to determine type of EMAC with baseaddress 0x%08x\r\n", mac_baseaddr); return NULL; } }选中xemacpsif_init函数鼠标右击选择Open Declaration,可以查看xemacpsif_init
/* * xemacpsif_init(): * * Should be called at the beginning of the program to set up the * network interface. It calls the function low_level_init() to do the * actual setup of the hardware. *应该在程序开始时调用来设置网络接口。 它调用函数low_level_init()来进行硬件的实际设置。 */ err_t xemacpsif_init(struct netif *netif) { #if LWIP_SNMP //LWIP_SNMP=0 /* ifType ethernetCsmacd(6) @see RFC1213 */ netif->link_type = 6; /* your link speed here */ netif->link_speed = ; netif->ts = 0; netif->ifinoctets = 0; netif->ifinucastpkts = 0; netif->ifinnucastpkts = 0; netif->ifindiscards = 0; netif->ifoutoctets = 0; netif->ifoutucastpkts = 0; netif->ifoutnucastpkts = 0; netif->ifoutdiscards = 0; #endif netif->name[0] = IFNAME0; netif->name[1] = IFNAME1; netif->output = xemacpsif_output; netif->linkoutput = low_level_output; low_level_init(netif);//主要是这个函数,以太网中断函数 return ERR_OK; }选中low_level_init函数鼠标右击选择Open Declaration,可以查看low_level_init
static err_t low_level_init(struct netif *netif) { UINTPTR mac_address = (UINTPTR)(netif->state); struct xemac_s *xemac; xemacpsif_s *xemacpsif; u32 dmacrreg; s32_t status = XST_SUCCESS; NetIf = netif; xemacpsif = mem_malloc(sizeof *xemacpsif); if (xemacpsif == NULL) { LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_init: out of memory\r\n")); return ERR_MEM; } xemac = mem_malloc(sizeof *xemac); if (xemac == NULL) { LWIP_DEBUGF(NETIF_DEBUG, ("xemacpsif_init: out of memory\r\n")); return ERR_MEM; } xemac->state = (void *)xemacpsif; xemac->topology_index = xtopology_find_index(mac_address); xemac->type = xemac_type_emacps; xemacpsif->send_q = NULL; xemacpsif->recv_q = pq_create_queue(); if (!xemacpsif->recv_q) return ERR_MEM; /* maximum transfer unit */ netif->mtu = XEMACPS_MTU - XEMACPS_HDR_SIZE; #if LWIP_IGMP netif->igmp_mac_filter = xemacpsif_mac_filter_update; #endif netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; #if LWIP_IGMP netif->flags |= NETIF_FLAG_IGMP; #endif #if !NO_SYS sys_sem_new(&xemac->sem_rx_data_available, 0); #endif /* obtain config of this emac */ mac_config = (XEmacPs_Config *)xemacps_lookup_config((unsigned)(UINTPTR)netif->state); status = XEmacPs_CfgInitialize(&xemacpsif->emacps, mac_config, mac_config->BaseAddress); if (status != XST_SUCCESS) { xil_printf("In %s:EmacPs Configuration Failed....\r\n", __func__); } /* initialize the mac */ init_emacps(xemacpsif, netif); dmacrreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_DMACR_OFFSET); dmacrreg = dmacrreg | (0x00000010); XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_DMACR_OFFSET, dmacrreg); setup_isr(xemac);//这个就是最终的函数 init_dma(xemac); start_emacps(xemacpsif); /* replace the state in netif (currently the emac baseaddress) * with the mac instance pointer. */ netif->state = (void *)xemac; return ERR_OK; }选中setup_isr函数鼠标右击选择Open Declaration,可以查看setup_isr
void setup_isr (struct xemac_s *xemac) { xemacpsif_s *xemacpsif; xemacpsif = (xemacpsif_s *)(xemac->state); /* * Setup callbacks */ XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMASEND, (void *) emacps_send_handler,//以太网发送中断连接这个函数句柄,当产生以太网发送中断时调用emacps_send_handler函数 (void *) xemac); XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMARECV, (void *) emacps_recv_handler,//以太网接收中断连接这个函数句柄,当产生以太网接收中断时调用emacps_recv_handler函数 (void *) xemac); XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_ERROR, (void *) emacps_error_handler,//错误中断 (void *) xemac); }选中emacps_send_handler函数鼠标右击选择Open Declaration,可以查看emacps_send_handler
void emacps_send_handler(void *arg) { struct xemac_s *xemac; xil_printf("发送1111wzq\n\r"); xemacpsif_s *xemacpsif; XEmacPs_BdRing *txringptr; u32_t regval; #ifdef OS_IS_FREERTOS xInsideISR++; #endif xemac = (struct xemac_s *)(arg); xemacpsif = (xemacpsif_s *)(xemac->state); txringptr = &(XEmacPs_GetTxRing(&xemacpsif->emacps)); regval = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_TXSR_OFFSET); XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,XEMACPS_TXSR_OFFSET, regval); /* If Transmit done interrupt is asserted, process completed BD's */ process_sent_bds(xemacpsif, txringptr); #ifdef OS_IS_FREERTOS xInsideISR--; #endif } void emacps_recv_handler(void *arg) { struct pbuf *p; XEmacPs_Bd *rxbdset, *curbdptr; struct xemac_s *xemac; xemacpsif_s *xemacpsif; XEmacPs_BdRing *rxring; volatile s32_t bd_processed; s32_t rx_bytes, k; u32_t bdindex; u32_t regval; u32_t index; u32_t gigeversion; xil_printf("接收1111wzq\n\r"); xemac = (struct xemac_s *)(arg); xemacpsif = (xemacpsif_s *)(xemac->state); rxring = &XEmacPs_GetRxRing(&xemacpsif->emacps); #ifdef OS_IS_FREERTOS xInsideISR++; #endif gigeversion = ((Xil_In32(xemacpsif->emacps.Config.BaseAddress + 0xFC)) >> 16) & 0xFFF; index = get_base_index_rxpbufsstorage (xemacpsif); /* * If Reception done interrupt is asserted, call RX call back function * to handle the processed BDs and then raise the according flag. */ regval = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXSR_OFFSET); XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEMACPS_RXSR_OFFSET, regval); if (gigeversion <= 2) { resetrx_on_no_rxdata(xemacpsif); } while(1) { bd_processed = XEmacPs_BdRingFromHwRx(rxring, XLWIP_CONFIG_N_RX_DESC, &rxbdset); if (bd_processed <= 0) { break; } for (k = 0, curbdptr=rxbdset; k < bd_processed; k++) { bdindex = XEMACPS_BD_TO_INDEX(rxring, curbdptr); p = (struct pbuf *)rx_pbufs_storage[index + bdindex]; /* * Adjust the buffer size to the actual number of bytes received. */ rx_bytes = XEmacPs_BdGetLength(curbdptr); pbuf_realloc(p, rx_bytes); /* store it in the receive queue, * where it'll be processed by a different handler */ if (pq_enqueue(xemacpsif->recv_q, (void*)p) < 0) { #if LINK_STATS lwip_stats.link.memerr++; lwip_stats.link.drop++; #endif pbuf_free(p); } curbdptr = XEmacPs_BdRingNext( rxring, curbdptr); } /* free up the BD's */ XEmacPs_BdRingFree(rxring, bd_processed, rxbdset); setup_rx_bds(xemacpsif, rxring); #if !NO_SYS sys_sem_signal(&xemac->sem_rx_data_available); #endif } #ifdef OS_IS_FREERTOS xInsideISR--; #endif return; } main函数 /* receive and process packets recv_handler*/ while (1) { if (TcpFastTmrFlag) { //xil_printf("11\r\n"); tcp_fasttmr();//不是很懂什么意思,250ms执行一次 TcpFastTmrFlag = 0; } if (TcpSlowTmrFlag) { //xil_printf("22\r\n"); tcp_slowtmr();//不是很懂什么意思,500ms执行一次 TcpSlowTmrFlag = 0; } //xil_printf("33\r\n"); xemacif_input(echo_netif);//将MAC 队列里的packets 传输到你的LwIP/IP stack 里 transfer_data(); }
