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();
}