Zynq-Linux移植学习笔记之十-u-boot网络配置

在zynq开发板zc706上,网络通路由下面三个设备组成:


其中zynq负责对phy进行配置,当zynq上的网络控制器以及phy完成正确配置时,能够看到RJ45上面的黄灯亮,此时表明链路已经通了。如果u-boot中已经设置了IP地址,通过网线就可以ping通电脑,此时会打印host alive这句话。

但是如果板子不是这样做的,比如是下面这种方式:


这里用到了BCM5396网络交换芯片,此时要保证网络链路通就需要对5396和两个PHY进行配置。幸运地是,PHY0由5396进行配置,当我们对5396进行正确配置后,PHY0也就配置完成了,PHY1的配置还是老样子。整个配置可以分为两步走,首先通过SPI总线配置5396,再配置PHY1,完成全部配置后,就能看到RJ45上面的黄灯亮起。

 

u-boot中需要修改的代码主要涉及三个地方

1、  arch/arm/lib/Board.c

其中board_init_r函数中需要在网络驱动配置前加入配置bcm5396的函数调用,这里我放在了串口驱动配置之后运行。

[cpp]  view plain  copy
 print ?
  1. void board_init_r(gd_t *id, ulong dest_addr)  
  2. {  
  3.     ulong malloc_start;  
  4. #if !defined(CONFIG_SYS_NO_FLASH)  
  5.     ulong flash_size;  
  6. #endif  
  7.   
  8.     gd->flags |= GD_FLG_RELOC;   /* tell others: relocation done */  
  9.     bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_R, "board_init_r");  
  10.   
  11.     monitor_flash_len = _end_ofs;  
  12.   
  13.     /* Enable caches */  
  14.     enable_caches();  
  15.   
  16.     debug("monitor flash len: %08lX\n", monitor_flash_len);  
  17.     board_init();   /* Setup chipselects */  
  18.     /* 
  19.      * TODO: printing of the clock inforamtion of the board is now 
  20.      * implemented as part of bdinfo command. Currently only support for 
  21.      * davinci SOC's is added. Remove this check once all the board 
  22.      * implement this. 
  23.      */  
  24. #ifdef CONFIG_CLOCKS  
  25.     set_cpu_clk_info(); /* Setup clock information */  
  26. #endif  
  27.     serial_initialize();  
  28.   
  29.     myspi_init(); /*init bcm5396*/  
  30.   
  31.     printf("Now running in RAM - U-Boot at: %08lx\n", dest_addr);  
  32.   
  33. #ifdef CONFIG_LOGBUFFER  


 

2、  net/Eth.c

在其中加入配置bcm5396的代码

 

[cpp]  view plain  copy
 print ?
  1. void myspi_init()  
  2. {  
  3.     XSpiPs Spi;  
  4.     int i32Option,status;  
  5.     int i;  
  6.     unsigned char workBuf[10];  
  7.   
  8.     workBuf[0]=0xf0;  
  9.     workBuf[1]=0x1;  
  10.   
  11.     g_SpiConfig = &XSpiPs_ConfigTable[0];  
  12.   
  13.     //Initialize the SPI device.  
  14.     Spi.IsBusy = 0;  
  15.   
  16.     Spi.Config.BaseAddress = g_SpiConfig->BaseAddress;  
  17.     //Spi.StatusHandler = StubStatusHandler;  
  18.   
  19.     Spi.SendBufferPtr = NULL;  
  20.     Spi.RecvBufferPtr = NULL;  
  21.     Spi.RequestedBytes = 0;  
  22.     Spi.RemainingBytes = 0;  
  23.     Spi.IsReady = 0x11111111;  
  24.   
  25.     XSpiPs_WriteReg(Spi.Config.BaseAddress,0,0x00020000);  
  26.     //Initialize the SPI device. end  
  27.       
  28.     i32Option = 0x1 | 0x2 | 0x4 | 0x10;  
  29.     Spi_SetOptions(&Spi, i32Option);  
  30.   
  31.     XSpiPs_SetSlaveSelect(&Spi,1 );  
  32.   
  33.     XSpiPs_SetClkPrescaler(&Spi, 6 );  
  34.   
  35.     workBuf[0]=0xf0;  
  36.     workBuf[1]=0x1;  
  37.     workBuf[2]=0;  
  38.     for(i=0x10;i<=0x1f;i++)  
  39.     {  
  40.         status = writeBCM5396(&Spi, i, 0x20, workBuf );  
  41.     }  
  42.   
  43.     printf("*****************Read SPI Reg of 5396******************\r\n");  
  44.     printf("---BMC Status Registers(PAGE 0x10-0x1F)---\n");  
  45.     for(i=0x10;i<=0x1f;i++)  
  46.     {  
  47.           status = readBCM5396(&Spi, i, 0x28, workBuf );  
  48.           printf("port=%d,offset=0x28,data=0x%x\n",(i-0x10),workBuf[2]);  
  49.           printf("port=%d,offset=0x29,data=0x%x\n",(i-0x10),workBuf[3]);  
  50.         }  
  51.   
  52.     printf("---BMC Status Registers(PAGE 0x10-0x1F)---\n\r");  
  53.     for(i=0x10;i<=0x1f;i++)  
  54.     {  
  55.           status = readBCM5396(&Spi, i, 0x20, workBuf );  
  56.           printf("port=%d,offset=0x20,data=0x%x\n\r",(i-0x10),workBuf[2]);  
  57.       
  58.           printf("port=%d,offset=0x21,data=0x%x\n\r",(i-0x10),workBuf[3]);  
  59.         }  
  60.   
  61. }  

 

3、  drivers/net/Zynq_gem.c

这里的修改是可选项,主要是配置phy,我这里使用的是marvell的88E1111,u-boot中提供的配置方法不起效,于是进行了手动配置。加了phy_detect和negotiat函数

[cpp]  view plain  copy
 print ?
  1. static void phy_negotiat(struct eth_device *dev)  
  2. {  
  3.     struct zynq_gem_priv *priv = dev->priv;  
  4.     u16 control;  
  5.     u16 status;  
  6.     u16 temp;  
  7.     u16 timeout_counter=0;  
  8.       
  9.     printf("Start PHY autonegotiation.\n");  
  10.   
  11.     phywrite(dev,priv->phyaddr, 22, 2);  
  12.     phyread(dev, priv->phyaddr, 21, &control);  
  13.     control |= 0x0030;  
  14.     phywrite(dev, priv->phyaddr, 21, control);  
  15.   
  16.     phywrite(dev, priv->phyaddr, 22, 0);  
  17.   
  18.     phyread(dev, priv->phyaddr, 4, &control);  
  19.     control |= 0x0800;  
  20.     control |= 0x0400;  
  21.     control |= (0x0100 | 0x0080);  
  22.     control |= (0x0040 | 0x0020);  
  23.     phywrite(dev, priv->phyaddr, 4, control);  
  24.   
  25.     phyread(dev, priv->phyaddr, 9,&control);  
  26.     control |= 0x0300;  
  27.     phywrite(dev, priv->phyaddr, 9,control);  
  28.   
  29.     phywrite(dev, priv->phyaddr, 22, 0);  
  30.     phyread(dev, priv->phyaddr, 16,&control);  
  31.     control |= (7 << 12); /* max number of gigabit attempts */  
  32.     control |= (1 << 11); /* enable downshift */  
  33.     phywrite(dev, priv->phyaddr, 16,control);  
  34.     phyread(dev, priv->phyaddr, 0, &control);  
  35.     control |= 0x1000;  
  36.     control |= 0x0200;  
  37.     phywrite(dev, priv->phyaddr, 0, control);  
  38.   
  39.     phyread(dev, priv->phyaddr, 0, &control);  
  40.     control |= 0x8000;  
  41.     phywrite(dev, priv->phyaddr, 0, control);  
  42.   
  43.     while (1)   
  44.     {  
  45.         phyread(dev, priv->phyaddr, 0, &control);  
  46.         if (control & 0x8000)  
  47.         {  
  48.                 continue;  
  49.         }  
  50.         else  
  51.         {  
  52.                 break;  
  53.         }  
  54.     }  
  55.     phyread(dev, priv->phyaddr, 1, &status);  
  56.       
  57.     printf("Waiting for PHY to complete autonegotiation.\n");  
  58.   
  59.     while ( !(status & 0x0020) )   
  60.     {  
  61.         phyread(dev, priv->phyaddr,19,  &temp);  
  62. //      timeout_counter++;  
  63.   
  64. //      if (timeout_counter == 30)   
  65. //      {  
  66. //          printf("Auto negotiation error\n");  
  67. //          return;  
  68. //      }  
  69.         phyread(dev, priv->phyaddr, 1, &status);  
  70.     }  
  71.     printf("autonegotiation complete.\n");  
  72. }  
  73.   
  74. static void phy_detection(struct eth_device *dev)  
  75. {  
  76.     int i;  
  77.     u16 phyreg;  
  78.     struct zynq_gem_priv *priv = dev->priv;  
  79.   
  80.          
  81.     if (priv->phyaddr != -1) {  
  82.         phyread(dev, priv->phyaddr, PHY_DETECT_REG, &phyreg);  
  83.         printf("phy reg is %d\n",phyreg);  
  84.         if ((phyreg != 0xFFFF) &&  
  85.             ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {  
  86.             /* Found a valid PHY address */  
  87.             printf("Default phy address %d is valid\n",  
  88.                   priv->phyaddr);  
  89.             return;  
  90.         } else {  
  91.             printf("PHY address is not setup correctly %d\n",  
  92.                   priv->phyaddr);  
  93.             priv->phyaddr = -1;  
  94.         }  
  95.     }  
  96.     printf("detecting phy address\n");  
  97.     if (priv->phyaddr == -1) {  
  98.         /* detect the PHY address */  
  99.         for (i = 31; i >= 0; i--) {  
  100.             phyread(dev, i, PHY_DETECT_REG, &phyreg);  
  101.             if ((phyreg != 0xFFFF) &&  
  102.                 ((phyreg & PHY_DETECT_MASK) == PHY_DETECT_MASK)) {  
  103.                 /* Found a valid PHY address */  
  104.                 priv->phyaddr = i;  
  105.                 printf("Found valid phy address, %d\n", i);  
  106.                 return;  
  107.             }  
  108.         }  
  109.     }  
  110.     priv->phyaddr = 0;  
  111.     printf("No PHY detected.  Assuming a PHY at address 0\r\n");      
  112. }  
  113.   
  114. static int zynq_gem_setup_mac(struct eth_device *dev)  
  115. {  
  116.     u32 i, macaddrlow, macaddrhigh;  
  117.     struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase;  
  118.   
  119.     /* Set the MAC bits [31:0] in BOT */  
  120.     macaddrlow = dev->enetaddr[0];  
  121.     macaddrlow |= dev->enetaddr[1] << 8;  
  122.     macaddrlow |= dev->enetaddr[2] << 16;  
  123.     macaddrlow |= dev->enetaddr[3] << 24;  
  124.   
  125.     /* Set MAC bits [47:32] in TOP */  
  126.     macaddrhigh = dev->enetaddr[4];  
  127.     macaddrhigh |= dev->enetaddr[5] << 8;  
  128.   
  129.     for (i = 0; i < 4; i++) {  
  130.         writel(0, &regs->laddr[i][LADDR_LOW]);  
  131.         writel(0, &regs->laddr[i][LADDR_HIGH]);  
  132.         /* Do not use MATCHx register */  
  133.         writel(0, &regs->match[i]);  
  134.     }  
  135.   
  136.     writel(macaddrlow, &regs->laddr[0][LADDR_LOW]);  
  137.     writel(macaddrhigh, &regs->laddr[0][LADDR_HIGH]);  
  138.   
  139.     return 0;  
  140. }  
  141.   
  142. static int zynq_gem_init(struct eth_device *dev, bd_t * bis)  
  143. {  
  144.     u32 i;  
  145.     u16 tmp;  
  146.     unsigned long clk_rate = 0;  
  147.     struct phy_device *phydev;  
  148.     const u32 stat_size = (sizeof(struct zynq_gem_regs) -  
  149.                 offsetof(struct zynq_gem_regs, stat)) / 4;  
  150.     struct zynq_gem_regs *regs = (struct zynq_gem_regs *)dev->iobase;  
  151.     struct zynq_gem_priv *priv = dev->priv;  
  152.     const u32 supported = SUPPORTED_10baseT_Half |  
  153.             SUPPORTED_10baseT_Full |  
  154.             SUPPORTED_100baseT_Half |  
  155.             SUPPORTED_100baseT_Full |  
  156.             SUPPORTED_1000baseT_Half |  
  157.             SUPPORTED_1000baseT_Full;  
  158.       
  159.     if (!priv->init) {  
  160.         /* Disable all interrupts */  
  161.         writel(0xFFFFFFFF, &regs->idr);  
  162.   
  163.         /* Disable the receiver & transmitter */  
  164.         writel(0, &regs->nwctrl);  
  165.         writel(0, &regs->txsr);  
  166.         writel(0, &regs->rxsr);  
  167.         writel(0, &regs->phymntnc);  
  168.   
  169.         /* Clear the Hash registers for the mac address 
  170.          * pointed by AddressPtr 
  171.          */  
  172.         writel(0x0, &regs->hashl);  
  173.         /* Write bits [63:32] in TOP */  
  174.         writel(0x0, &regs->hashh);  
  175.   
  176.         /* Clear all counters */  
  177.         for (i = 0; i <= stat_size; i++)  
  178.             readl(&regs->stat[i]);  
  179.   
  180.         /* Setup RxBD space */  
  181.         memset(priv->rx_bd, 0, RX_BUF * sizeof(struct emac_bd));  
  182.   
  183.         for (i = 0; i < RX_BUF; i++) {  
  184.             priv->rx_bd[i].status = 0xF0000000;  
  185.             priv->rx_bd[i].addr =  
  186.                     ((u32)(priv->rxbuffers) +  
  187.                             (i * PKTSIZE_ALIGN));  
  188.         }  
  189.         /* WRAP bit to last BD */  
  190.         priv->rx_bd[--i].addr |= ZYNQ_GEM_RXBUF_WRAP_MASK;  
  191.         /* Write RxBDs to IP */  
  192.         writel((u32)priv->rx_bd, &regs->rxqbase);  
  193.   
  194.         /* Setup for DMA Configuration register */  
  195.         writel(ZYNQ_GEM_DMACR_INIT, &regs->dmacr);  
  196.   
  197.         /* Setup for Network Control register, MDIO, Rx and Tx enable */  
  198.         setbits_le32(&regs->nwctrl, ZYNQ_GEM_NWCTRL_MDEN_MASK);  
  199.   
  200.         priv->init++;  
  201.     }  
  202.     printf("phy detection.\n");  
  203.     phy_detection(dev);  
  204.     phy_rst(dev);  
  205.     phy_negotiat(dev);  
  206.       
  207.   
  208.     printf("--------phyaddr : 0x%x----\r\n", priv->phyaddr);  
  209.     unsigned short PhyReg;  
  210.     //change to page 0  
  211.     phyread(dev, priv->phyaddr, 22, &PhyReg);  
  212.     PhyReg = PhyReg & 0xfffe;  
  213.     phywrite(dev, priv->phyaddr, 22, PhyReg);  
  214.   
  215.     phyread(dev, priv->phyaddr, 20, &PhyReg);  
  216.     PhyReg = PhyReg | 0x82;  
  217.     phywrite(dev, priv->phyaddr, 20, PhyReg);  
  218.   
  219.     /*  reset phy    */  
  220.     phyread(dev, priv->phyaddr, 0, &PhyReg);  
  221.     PhyReg |= 0x8000;  
  222.     phywrite(dev, priv->phyaddr, 0, PhyReg);  
  223.   
  224.   
  225.     puts("GEM link speed is 1000Mbps\n");  
  226.     writel(ZYNQ_GEM_NWCFG_INIT | ZYNQ_GEM_NWCFG_SPEED1000, &regs->nwcfg);  
  227.     setbits_le32(&regs->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK |  
  228.                     ZYNQ_GEM_NWCTRL_TXEN_MASK);   
  229.   
  230.     return 0;  
  231. }  


 

完成这三个地方配置后,重新编译u-boot,网络才算完成,可以通过tftp加载devicetree,uramdisk.image.gz,uImage,这样要比通过JTAG dow到内存中快很多,最后通过bootm启动就可以了。

[plain]  view plain  copy
 print ?
  1. zynq-uboot> tftp 0x2a00000 devicetree.dtb  
  2. Using zynq_gem device  
  3. TFTP from server 192.168.0.101; our IP address is 192.168.0.99  
  4. Filename 'devicetree.dtb'.  
  5. Load address: 0x2a00000  
  6. Loading: T #  
  7. done  
  8. Bytes transferred = 13222 (33a6 hex)  
  9. zynq-uboot> tftp 0x2000000 uramdisk.image.gz  
  10. Using zynq_gem device  
  11. TFTP from server 192.168.0.101; our IP address is 192.168.0.99  
  12. Filename 'uramdisk.image.gz'.  
  13. Load address: 0x2000000  
  14. Loading: #################################################################  
  15.          #################################################################  
  16.          #################################################################  
  17.          #################################################################  
  18.          #################################################################  
  19.          ####################################  
  20. done  
  21. Bytes transferred = 5289509 (50b625 hex)  
  22. zynq-uboot> tftp 0x3000000 uImage  
  23. Using zynq_gem device  
  24. TFTP from server 192.168.0.101; our IP address is 192.168.0.99  
  25. Filename 'uImage'.  
  26. Load address: 0x3000000  
  27. Loading: T #################################################################  
  28.          #################################################################  
  29.          #################################################################  
  30.          ##########################  
  31. done  
  32. Bytes transferred = 3230680 (314bd8 hex)  
  33. zynq-uboot> bootm 0x3000000 0x2000000 0x2a00000  
  34. ## Booting kernel from Legacy Image at 03000000 ...  
  35.    Image Name:   Linux-4.0.0-dayun  
  36.    Image Type:   ARM Linux Kernel Image (uncompressed)  
  37.    Data Size:    3230616 Bytes = 3.1 MiB  
  38.    Load Address: 00008000  
  39.    Entry Point:  00008000  
  40.    Verifying Checksum ... OK  
  41. ## Loading init Ramdisk from Legacy Image at 02000000 ...  
  42.    Image Name:     
  43.    Image Type:   ARM Linux RAMDisk Image (gzip compressed)  
  44.    Data Size:    5289445 Bytes = 5 MiB  
  45.    Load Address: 00800000  
  46.    Entry Point:  00800000  
  47.    Verifying Checksum ... OK  
  48. ## Flattened Device Tree blob at 02a00000  
  49.    Booting using the fdt blob at 0x02a00000  
  50.    Loading Kernel Image ... OK  
  51. OK  
  52.    Loading Ramdisk to 1faf4000, end 1ffff5e5 ... OK  
  53.    Loading Device Tree to 1faed000, end 1faf33a5 ... OK  
  54.   
  55. Starting kernel ...  
  56.   
  57. Uncompressing Linux... done, booting the kernel.  
  58. Booting Linux on physical CPU 0x0  
  59. Linux version 4.0.0-dayun (root@shenvpc) (gcc version 5.2.1 20151005 (Linaro GCC 5.2-2015.11-2) ) #1 SMP PREEMPT Fri Apr 7 02:03:21 Local time zone must be set--s  
  60. CPU: ARMv7 Processor [413fc090] revision 0 (ARMv7), cr=18c5387d  
  61. CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache  
  62. .......  
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: "Zynq-Linux移植学习笔记"是一篇关于在Zynq SoC平台上移植Linux操作系统的学习笔记。该笔记主要介绍了如何在Zynq平台上搭建交叉编译环境、编译内核、制作根文件系统以及启动Linux系统等方面的知识。通过学习这篇笔记,读者可以了解到如何将Linux操作系统移植Zynq平台上,并且可以通过实践来深入理解相关的知识和技 ### 回答2: Zynq Linux移植是搭建Zynq硬件平台和在该平台上运行Linux系统的过程。它包括了硬件的设计和软件的开发,这有助于实现在Zynq平台上开发Linux应用程序的目标。 首先,进行Zynq Linux移植前需要研究设备的结构和硬件构造。zynq硬件平台包含两个主要组成部分:PS和PL。PS负责处理器系统和外设的管理和控制,PL则是可编程逻辑,支持FPGA逻辑的定制化,同时也支持外设的实现。在移植时,需要设计PS的硬件架构和软件驱动程序,同时也需要配置PL。一般情况下,需要进行如(Xilinx SDK)和(Petalinux)等的软件开发环境安装和配置。 接下来,进行Linux系统的移植。这部分工作需要了解Linux内核的结构、功能和特性,然后根据硬件架构,对Linux系统进行调整和定制,构建出适合硬件平台的Linux系统。这个过程需要进行的工作包括:解编译适合SOC的内核、制定设备树、调整内核参数等。 最后,这些工作完成后,就可以在Zynq平台上编译和运行Linux应用程序了。开发者可以尝试通过开发板上的GPIO、I2C、SPI或UART等接口,学习Linux的设备驱动程序、网络编程、文件系统管理等知识点。可逐步学习如何掌握Linux的shell、打包工具、交叉编译工具等。 总结来说,Zynq Linux移植工作是基础的硬件构造、嵌入式软件和Linux知识的综合应用,需要开发者有至少三方面的技能。需要熟练编写硬件设计,熟练掌握Linux内核编程以及Linux系统软件的维护和管理。这些技能的应用能力对于移植Zynq平台Linux系统和应用程序的开发工程师来说是非常必要的。 ### 回答3: 随着嵌入式系统的广泛应用,zynq-linux移植成为了嵌入式开发的一个重要研究课题。zynq-linux移植涉及到许多方面的知识,在学习过程中需要注意以下几点: 一、zynq-linux移植前需要了解的基础知识 在开始进行zynq-linux移植之前,需要对Linux系统、ARM技术、FPGA开发、C语言等基础知识有一定的了解。同时需要熟悉zynq系列的基本架构和应用场景。 二、zynq-linux移植必要的步骤 zynq-linux移植的过程主要分为以下几个步骤:首先是确定硬件平台和环境搭建;其次是进行内核编译和配置;然后是uboot编译和烧录;最后是Linux文件系统的制作和烧录。在整个移植过程中,需要注意各个步骤的顺序和详细操作,确保每一步都正确完成。 三、zynq-linux移植中可能会遇到的问题 在zynq-linux移植过程中,可能会遇到各种问题,例如硬件平台的兼容性、内核配置的错误、uboot烧录问题、文件系统制作出错等。在遇到这些问题时,需要耐心地进行排查和解决,同时也可以借助搜索引擎和社区的技术支持。 四、zynq-linux移植之后的应用与拓展 zynq-linux移植成功之后,可以将其应用于各种嵌入式系统中,例如网络设备、智能家居、工业控制等领域。同时,还可以进行拓展和优化,例如添加各种驱动程序、优化系统性能等。 总之,在进行zynq-linux移植学习和实践中,需要认真学习基础知识,仔细操作每个步骤,及时排查并解决问题,并在成功移植之后持续进行应用与拓展。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值