OMAPL138以太网通讯无法ping通,烦烦烦,求大神帮忙

2019-03-26 16:25发布

我用的是OMAPL138的芯片,网卡是KSZ8041FTL,用的平台是CCS3.3,调试dsp,并且移植了Ucos操作系统,我把板子的网口和主机的网口用网线连起来,然后在主机的cmd中ping板子的IP地址,到目前为止就出现2次ping通,而且ping通了一下就超时了,一次丢包率是50%,另一次是75%。到目前为止我还找不到啥问题,可否请知道的人士请帮忙啊,可以直接QQ联系744936375. 此帖出自小平头技术问答
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
4条回答
HMILY_YLIMH
2019-03-27 13:09
  1. 代码其中之一:                                                        //-----------------------------------------------------------------------------
  2. // file    evmomapl138_emac.c
  3. // rief   implementation of the emac/mdio driver for the OMAP-L138 EVM.
  4. //
  5. //-----------------------------------------------------------------------------

  6. #include "stdio.h"
  7. #include "string.h"
  8. #include "os_cpu_isr.h"
  9. #include "includes.h"
  10. #include "inc/evmomapl138_emac.h"
  11. #include "inc/types.h"
  12. #include "evmomapl138.h"
  13. #include "evmomapl138_timer.h"
  14. #include "inc/ethernet_smsc.h"
  15. #include "inc/evmomapl138_gpio.h"
  16. #include "inc/evmomapl138_i2c_gpio.h"
  17. #include "inc/evmomapl138_cdce913.h"
  18. #include "evmomapl138_aintc.h"   // add_ISR需要
  19. #include "netif/etharp.h"
  20. #include "Emac_des.h"
  21. #include "ethernetif.h"
  22. #ifndef USE_HDTIME_DLY
  23. #define USTIMER_delay(x)               
  24. #endif //USE_HDTIME_DLY
  25. #define MAX_POLLING_NUM                (0x0FFFFFFF)
  26. //-----------------------------------------------------------------------------
  27. // Private Defines and Macros
  28. //-----------------------------------------------------------------------------
  29. // INTCONTROL >> INTPRESCALE , number of EMAC clk period within a 4 us time window
  30. #define NUM_INTPRESCALE    (4*SYSCLOCK4_HZ/1000000)  //4/(1000000/SYSCLOCK4_HZ) , 4us
  31. // mdio clock divide down value.
  32. #define MDIO_CLK_FREQ_HZ   (2000000)  //2M HZ
  33. #define MDIO_CLK_DIVISOR   ((SYSCLOCK4_HZ / MDIO_CLK_FREQ_HZ) - 1)
  34. // rx / tx desriptor memory offsets.
  35. #define RX_DESC_OFFSET     (0)
  36. #define TX_DESC_OFFSET     (0x1000)
  37. //MII pinmux
  38. #define PINMUX_MII_REG_0         (2)
  39. #define PINMUX_MII_MASK_0        (0xFFFFFFF0)
  40. #define PINMUX_MII_VAL_0         (0x88888880)
  41. #define PINMUX_MII_REG_1         (3)
  42. #define PINMUX_MII_MASK_1        (0xFFFFFFFF)
  43. #define PINMUX_MII_VAL_1         (0x88888888)
  44. //RMII pinmux
  45. #define PINMUX_RMII_REG_0        (14)
  46. #define PINMUX_RMII_MASK_0       (0xFFFFFF00)
  47. #define PINMUX_RMII_VAL_0        (0x88888800)
  48. #define PINMUX_RMII_REG_1        (15)
  49. #define PINMUX_RMII_MASK_1       (0x000000FF)
  50. #define PINMUX_RMII_VAL_1        (0x00000080)
  51. //MDIO pinmux
  52. #define PINMUX_MDIO_REG          (4)
  53. #define PINMUX_MDIO_MASK         (0x000000FF)
  54. #define PINMUX_MDIO_VAL          (0x00000088)
  55. //GPIO pinmux
  56. #define PINMUX_MII_MDIO_EN_REG         (6)
  57. #define PINMUX_MII_MDIO_EN_MASK         (0x000000F0)
  58. #define PINMUX_MII_MDIO_EN_VAL         (0x00000080)
  59. //
  60. #define EMAC_RMII_SPEED_100                 (0x00008000)
  61. //-----------------------------------------------------------------------------
  62. // Private Static Variables
  63. //-----------------------------------------------------------------------------
  64. static uint8_t g_active_phy_id = 0x0; //我们选用的L138是phy_id是为0的

  65. //-----------------------------------------------------------------------------
  66. // Private Function Prototypes
  67. //-----------------------------------------------------------------------------
  68. static uint32_t initMdioPhy(void);
  69. static uint8_t isLinkActive(uint8_t in_phy);
  70. static uint16_t phyRegRead(uint8_t in_phy, uint8_t in_reg);
  71. static void phyRegWrite(uint8_t in_phy, uint8_t in_reg, uint16_t in_data);

  72. //----------------------------------------------------------------------------
  73. //Public value definitions
  74. //----------------------------------------------------------------------------

  75. //-----------------------------------------------------------------------------
  76. // Public Function Definitions
  77. //-----------------------------------------------------------------------------

  78. //-----------------------------------------------------------------------------
  79. // rief   initialize the EMAC and MDIO for use.
  80. //
  81. // param   none.
  82. //
  83. // eturn  uint32_t
  84. //    ERR_NO_ERROR - everything is ok...emac ready to use.
  85. //    ERR_INIT_FAIL - something happened during initialization.
  86. //-----------------------------------------------------------------------------
  87. uint32_t Lowlevel_Emac_Init(void)
  88. {
  89.    uint32_t rtn = 0;
  90.    uint32_t i;
  91.   SYS_ARCH_DECL_PROTECT(sr);
  92.   SYS_ARCH_PROTECT(sr);

  93.    // reset emac module.
  94.    EMAC->SOFTRESET = 1;
  95.         while (EMAC->SOFTRESET != 0) {;}

  96.         //init emac control module
  97.         //----------------------------------------
  98.         // AddISR() -- configuration of the interrupt to the CPU.
  99.         //AINTC --Number34 core0 Receive Interrupt
  100.         AddISR(34,L138Ethif_RxHandler,(void *)0);
  101.         aintcRegs->SICR = 34; //clear index status
  102.         aintcRegs->CMR8 = 0x00170000;//(Sets channel map, system interrupt --> host channel interrupt )
  103.     aintcRegs->EISR = 34; //Enable Index Set Register
  104.         aintcRegs->SECR2 = 0x00000004; //34 status clear  

  105.         //configure Tx Interrupt Handler
  106.         AddISR(35,L138Ethif_TxHandler,(void *)0);
  107.         aintcRegs->SICR = 35; //clear index status
  108.         aintcRegs->CMR8 = 0x18000000; //SETS CHannel map
  109.         aintcRegs->EISR = 35; //Enable Index Set Register
  110.         aintcRegs->SECR2 = 0x00000008; //clear 35 status register ...

  111.         // configure INTCONTORL , CnRXIMAX, CnTXIMAX,
  112.         EMAC_CTRL->INTCTL = (NUM_INTPRESCALE| 0x00000300);
  113.         EMAC_CTRL->C0RXIMAX = 2;
  114.         EMAC_CTRL->C0TXIMAX = 2;
  115.         //--& init emac module.
  116.    //------------------
  117.    
  118.         // make sure emac control interrupts are disabled.
  119.    EMAC_CTRL->C0RXTHRESHEN = 0;
  120.    EMAC_CTRL->C1RXTHRESHEN = 0;
  121.    EMAC_CTRL->C2RXTHRESHEN = 0;
  122.    EMAC_CTRL->C0RXEN = 0;
  123.    EMAC_CTRL->C1RXEN = 0;
  124.    EMAC_CTRL->C2RXEN = 0;
  125.    EMAC_CTRL->C0TXEN = 0;
  126.    EMAC_CTRL->C1TXEN = 0;
  127.    EMAC_CTRL->C2TXEN = 0;
  128.    EMAC_CTRL->C0MISCEN = 0;
  129.    EMAC_CTRL->C1MISCEN = 0;
  130.    EMAC_CTRL->C2MISCEN = 0;

  131.    EVMOMAPL138_pinmuxConfig(PINMUX_MDIO_REG, PINMUX_MDIO_MASK, PINMUX_MDIO_VAL);                                           //MDIO shared by both RMII and MII
  132. //   EVMOMAPL138_pinmuxConfig(PINMUX_MII_MDIO_EN_REG, PINMUX_MII_MDIO_EN_MASK, PINMUX_MII_MDIO_EN_VAL); //pinmux to select gpio bank2 pin6
  133.            
  134.            //PINMUXING
  135.     EVMOMAPL138_pinmuxConfig(PINMUX_MII_REG_0, PINMUX_MII_MASK_0, PINMUX_MII_VAL_0);
  136.     EVMOMAPL138_pinmuxConfig(PINMUX_MII_REG_1, PINMUX_MII_MASK_1, PINMUX_MII_VAL_1);
  137.       
  138.     SYSCONFIG->KICKR[0] = KICK0R_UNLOCK;
  139.     SYSCONFIG->KICKR[1] = KICK1R_UNLOCK;
  140.     CLRBIT(SYSCONFIG->CFGCHIP[3], 0x00000100); //select mii mode !

  141.         //as software reset consideration, do this here
  142.    EVMOMAPL138_lpscTransition(PSC1, DOMAIN0, LPSC_EMAC, PSC_ENABLE);

  143.    // clear MAC control register, receive control register, transmiter control register
  144.         EMAC->MACCONTROL = 0;
  145.         EMAC->RXCONTROL = 0;
  146.         EMAC->TXCONTROL = 0;
  147.   // init header descriptor pointer regs to 0.
  148.      for (i = 0; i < 8; i++)
  149.      {
  150.        EMAC->TXHDP[i] = 0;
  151.        EMAC->RXHDP[i] = 0;
  152.      }
  153.    // clear all statistic register
  154. #ifndef BOOT
  155.    memset((uint8_t *)NET_STAT_REG_BASE, 0, NET_STAT_REG_NUM_BYTES);
  156. #endif
  157.    // setup local MAC address, only channel 0 is valid.
  158.    // program all 8, only need to set MACADDRHI for index = 0.
  159.    // use duplicate address for all unused channels.
  160.    // TODO: read MAC address from SPI flash.
  161.    //写的顺序是MACINDEX, ADDRHI, ADDRLO,由于高40bits是共享的
  162.    //只用了通道0,EMAC->MACADDRLO = 0X000000506 |VALID|MATCHFILT
  163.    for (i = 1; i < 8; i++)
  164.    {
  165.       EMAC->MACINDEX = i;
  166.           EMAC->MACADDRHI = 0x42020304; //index -> hi -> lo
  167.       EMAC->MACADDRLO = 0x00000506;          
  168.    }
  169.    EMAC->MACINDEX = 0;
  170.    EMAC->MACADDRHI = 0x42020304;
  171.    // channel bit = 0, match mac address = 1
  172.    EMAC->MACADDRLO = 0x00000506 | MACADDRLO_VALID | MACADDRLO_MATCHFILT;

  173.     // for use tx DMA descriptor configuration:
  174.     EMAC->MACSRCADDRHI = 0x42020304;
  175.         EMAC->MACSRCADDRLO = 0x00000506;
  176.    // initialize receive channel free buffer count regs, if buffer flow
  177.    // control is to be enabled.
  178.    // NOTE: this example does not use buffer flow control.

  179.    // enable unicast chan 0 only.
  180.    EMAC->RXUNICASTSET = 0x01;
  181.    
  182.    // no multicast addresses, clear MAC address hash registers.
  183.    EMAC->MACHASH1 = 0;
  184.    EMAC->MACHASH2 = 0;

  185.    // 只允许broadcast的ARP数据包,和发给自己的包,以太网的其他数据不放入Memmory里去.
  186.    //但是我单独设置RxBroadEn却没有作用。
  187.    EMAC->RXMBPENABLE = 0;
  188.    SETBIT(EMAC->RXMBPENABLE, (RXBROADEN|RXCAFEN));
  189. // EMAC->RXMBPENABLE = 0x01E02020;                //enable reception of almost all frames inc error
  190.    
  191.    //11. configure MACCONTROL (Don't set GMIIEN Bit)
  192.    SETBIT(EMAC->MACCONTROL, (RMIISPEED|FULLDUPLEX|TXPACE)); //RMII_SPEED,为了适应RMII
  193.   
  194.         // 12. Clear all unused channel interrupt bits by writing the receive interrupt mask clear register
  195.         //(RXINTMASKCLEAR) and the transmit interrupt mask clear register (TXINTMASKCLEAR).
  196.         EMAC->RXINTMASKCLEAR |= 0xFE; //RX channel 0的中断不屏蔽
  197.         EMAC->TXINTMASKCLEAR |= 0xFE; //TX CH0 中断屏蔽
  198.         //13. Modify RXINTMASKSET, TXINTMASKSET,MACINTMASKSET
  199.         EMAC->RXINTMASKSET |= 0x01;
  200.         EMAC->TXINTMASKSET |= 0x01;
  201.         EMAC->MACINTMASKCLR = 0x03; //disabled host mask , stat interrupt
  202.    
  203.    //14 init receive buffer offset and max length.
  204.    EMAC->RXBUFFEROFFSET = 0;
  205.    EMAC->RXMAXLEN = MAX_PACKET_SIZE;
  206.    
  207.    // initialize receive/transmit descriptor list queues.
  208.    Emac_des_init(); //modify 04/18

  209.    //16 enable receive / transmit DMA controllers...set GMIIEN.
  210.    EMAC->RXCONTROL = 1;
  211.    EMAC->TXCONTROL = 1;
  212.    SETBIT(EMAC->MACCONTROL, GMIIEN );
  213. #if 1   //文档说未经测试,删除貌似没效果啊,先不管它
  214.    SETBIT(EMAC->EMCONTROL, SOFT);
  215. #endif
  216.    // -->& init mdio / phy, 再加上MAC中断
  217.    //-----------------
  218.    rtn = initMdioPhy();
  219. //   if (rtn != ERR_NO_ERROR)
  220. //      return (rtn);
  221.     SYS_ARCH_UNPROTECT(sr);
  222.    //17>Enable the device interrupt in EMAC control module registers CnRXTHRESHEN, CnRXEN, CnTXEN,
  223.    //and CnMISCEN. -- LP Add
  224.         EMAC_CTRL->C0RXEN = 1; //C0RXPULSE Is Enabled for RX channel 0   
  225.         EMAC_CTRL->C0TXEN = 1; //C0TXPULSE IS enabled for tx channel 0
  226.         return (rtn);
  227. }

  228. //-----------------------------------------------------------------------------
  229. // rief   power on the phy.
  230. //
  231. // param   none.
  232. //
  233. // eturn  uint32_t
  234. //    ERR_NO_ERROR - everything is ok...phy is on.
  235. //    ERR_FAIL - something happened and could not power on.
  236. //-----------------------------------------------------------------------------
  237. uint32_t EMAC_phyPowerOn(void)
  238. {
  239.    uint32_t rtn;
  240.    uint16_t ctrl_reg;

  241.    ctrl_reg = phyRegRead(g_active_phy_id, SMSC_REG_BASIC_CTRL);

  242.    if (!CHKBIT(ctrl_reg, BASIC_CTRL_POWER_DOWN))
  243.    {
  244.       // phy is already on...nothing left to do.
  245.       #if DEBUG
  246.       printf("phy powered, basic ctrl reg: %04x ", ctrl_reg);
  247.       #endif
  248.       rtn = ERR_NO_ERROR;
  249.    }
  250.    else
  251.    {
  252.       // clear power down bit and write back to phy.
  253.       CLRBIT(ctrl_reg, BASIC_CTRL_POWER_DOWN);
  254.       phyRegWrite(g_active_phy_id, SMSC_REG_BASIC_CTRL, ctrl_reg);

  255.       // short delay, then read the reg back to verify loopback is enabled.
  256.       USTIMER_delay(500);
  257.       ctrl_reg = phyRegRead(g_active_phy_id, SMSC_REG_BASIC_CTRL);
  258.       if (!CHKBIT(ctrl_reg, BASIC_CTRL_POWER_DOWN))
  259.       {
  260.          // phy is powered...return success.
  261.          #if DEBUG
  262.          printf("phy powered, basic ctrl reg: %04x ", ctrl_reg);
  263.          #endif
  264.          rtn = ERR_NO_ERROR;
  265.       }
  266.       else
  267.       {
  268.          // power down bit did not clear...return error.
  269.          #if DEBUG
  270.          printf("power down did not clear: %04x ", ctrl_reg);
  271.          #endif
  272.          rtn = ERR_FAIL;
  273.       }
  274.    }

  275.    return (rtn);
  276. }

  277. //-----------------------------------------------------------------------------
  278. // rief   power down the phy.
  279. //
  280. // param   none.
  281. //
  282. // eturn  uint32_t
  283. //    ERR_NO_ERROR - everything is ok...phy is powered down.
  284. //    ERR_FAIL - something happened and could not power down.
  285. //-----------------------------------------------------------------------------
  286. uint32_t EMAC_phyPowerDown(void)
  287. {
  288.    uint32_t rtn;
  289.    uint16_t ctrl_reg;

  290.    ctrl_reg = phyRegRead(g_active_phy_id, SMSC_REG_BASIC_CTRL);

  291.    if(CHKBIT(ctrl_reg, BASIC_CTRL_ISOLATE) && CHKBIT(ctrl_reg, BASIC_CTRL_POWER_DOWN))
  292.    {
  293.       // phy is already powered down...nothing left to do.
  294.       #if DEBUG
  295.       printf("phy powered down, basic ctrl reg: %04x ", ctrl_reg);
  296.       #endif
  297.       rtn = ERR_NO_ERROR;
  298.    }
  299.    else
  300.    {
  301.       // set power down bit and write back to phy.
  302.       SETBIT(ctrl_reg, BASIC_CTRL_ISOLATE | BASIC_CTRL_POWER_DOWN);
  303.       phyRegWrite(g_active_phy_id, SMSC_REG_BASIC_CTRL, ctrl_reg);

  304.       // short delay, then read the reg back to verify loopback is disabled.
  305.       USTIMER_delay(500);
  306.       ctrl_reg = phyRegRead(g_active_phy_id, SMSC_REG_BASIC_CTRL);

  307.       if(CHKBIT(ctrl_reg, BASIC_CTRL_ISOLATE) && CHKBIT(ctrl_reg, BASIC_CTRL_POWER_DOWN))
  308.       {
  309.          // phy is powered down...return success.
  310.          #if DEBUG
  311.          printf("phy powered down, basic ctrl reg: %04x ", ctrl_reg);
  312.          #endif
  313.          rtn = ERR_NO_ERROR;
  314.       }
  315.       else
  316.       {
  317.          // power down bit did not set...return error.
  318.          #if DEBUG
  319.          printf("power down bit did not set: %04x ", ctrl_reg);
  320.          #endif
  321.          rtn = ERR_FAIL;
  322.       }
  323.    }

  324.    return (rtn);
  325. }

  326. //-----------------------------------------------------------------------------
  327. // rief   put the phy into loopback mode.
  328. //
  329. // param   none.
  330. //
  331. // eturn  uint32_t
  332. //    ERR_NO_ERROR - everything is ok...phy is in loopback mode.
  333. //    ERR_FAIL - something happened and could not enter loopback.
  334. //-----------------------------------------------------------------------------
  335. uint32_t EMAC_phyEnterLoopback(void)
  336. {
  337.    uint32_t rtn;
  338.    uint16_t ctrl_reg;


  339.    ctrl_reg = phyRegRead(g_active_phy_id, SMSC_REG_BASIC_CTRL);
  340.    rtn = ERR_NO_ERROR;

  341.    if (ctrl_reg & BASIC_CTRL_LOOPBACK)
  342.    {
  343.       // loopback is already enabled...nothing left to do.
  344.       #if DEBUG
  345.       printf("loopback enabled, basic ctrl reg: %04x ", ctrl_reg);
  346.       #endif
  347.       rtn = ERR_NO_ERROR;
  348.    }
  349.    else
  350.    {
  351.       // set loopback bit and write back to phy.
  352.       ctrl_reg |= BASIC_CTRL_LOOPBACK;
  353.       phyRegWrite(g_active_phy_id, SMSC_REG_BASIC_CTRL, ctrl_reg);

  354.       // short delay, then read the reg back to verify loopback is enabled.
  355.       USTIMER_delay(500);
  356.       ctrl_reg = phyRegRead(g_active_phy_id, SMSC_REG_BASIC_CTRL);
  357.       if (ctrl_reg & BASIC_CTRL_LOOPBACK)
  358.       {
  359.          // loopback is enabled...return success.
  360.          #if DEBUG
  361.          printf("loopback enabled , basic ctrl reg: %04x ", ctrl_reg);
  362.          #endif
  363.          rtn = ERR_NO_ERROR;
  364.       }
  365.       else
  366.       {
  367.          // loopback bit did not get set...return error.
  368.          #if DEBUG
  369.          printf("loopback did not set: %04x ", ctrl_reg);
  370.          #endif
  371.          rtn = ERR_FAIL;
  372.       }
  373.    }
  374.    return (rtn);
  375. }

  376. //-----------------------------------------------------------------------------
  377. // rief   remove the phy from loopback mode.
  378. //
  379. // param   none.
  380. //
  381. // eturn  uint32_t
  382. //    ERR_NO_ERROR - everything is ok...phy is out of loopback mode.
  383. //    ERR_FAIL - something happened and could not disable loopback.
  384. //-----------------------------------------------------------------------------
  385. uint32_t EMAC_phyExitLoopback(void)
  386. {
  387.    uint32_t rtn;
  388.    uint16_t ctrl_reg;

  389.    ctrl_reg = phyRegRead(g_active_phy_id, SMSC_REG_BASIC_CTRL);

  390.    if (!(ctrl_reg & BASIC_CTRL_LOOPBACK))
  391.    {
  392.       // loopback is already disabled...nothing left to do.
  393.       #if DEBUG
  394.       printf("loopback disabled, basic ctrl reg: %04x ", ctrl_reg);
  395.       #endif
  396.       rtn = ERR_NO_ERROR;
  397.    }
  398.    else
  399.    {
  400.       // clear loopback bit and write back to phy.
  401.       ctrl_reg &= ~BASIC_CTRL_LOOPBACK;
  402.       phyRegWrite(g_active_phy_id, SMSC_REG_BASIC_CTRL, ctrl_reg);

  403.       // short delay, then read the reg back to verify loopback is disabled.
  404.       USTIMER_delay(5);
  405.       ctrl_reg = phyRegRead(g_active_phy_id, SMSC_REG_BASIC_CTRL);
  406.       if (!(ctrl_reg & BASIC_CTRL_LOOPBACK))
  407.       {
  408.          // loopback is disabled...return success.
  409.          #if DEBUG
  410.          printf("loopback disabled , basic ctrl reg: %04x ", ctrl_reg);
  411.          #endif
  412.          rtn = ERR_NO_ERROR;
  413.       }
  414.       else
  415.       {
  416.          // loopback bit did not clear...return error.
  417.          #if DEBUG
  418.          printf("loopback did not clear: %04x ", ctrl_reg);
  419.          #endif
  420.          rtn = ERR_FAIL;
  421.       }
  422.    }

  423.    return (rtn);
  424. }

  425. //-----------------------------------------------------------------------------
  426. // Private Function Definitions
  427. //-----------------------------------------------------------------------------

  428. //-----------------------------------------------------------------------------
  429. // initialize the mdio module and identify the active phy.
  430. //-----------------------------------------------------------------------------
  431. uint32_t initMdioPhy(void)
  432. {
  433.    uint32_t i = 0;
  434.    uint16_t phy_reg;

  435.    // init the mdio regs.
  436.    MDIO->CONTROL = MDIO_CTRL_ENABLE |
  437.                      MDIO_CTRL_FAULT |
  438.                      MDIO_CTRL_FAULTENB |
  439.                      MDIO_CLK_DIVISOR;
  440.    while (CHKBIT(MDIO->CONTROL, MDIO_CTRL_IDLE)) {;}
  441. #if DEBUG_MDIO_LINK
  442.    // look for an active phy...takes up to 50 us for each phy to be checked.
  443.    //以下只是调试时有用,真正烧入程序中去时,是不行的,因为没插上网线,AddISR还要上的。
  444.    for (i = 0; i < MAX_POLLING_NUM; i++)
  445.    {
  446.       if (MDIO->ALIVE)
  447.       {
  448.          // at least one phy has acknowledged us...break the loop.
  449.          break;
  450.       }
  451.       USTIMER_delay(50);  // polling , 采用polling方式,LP- delete
  452.    }
  453.    while(!(MDIO->ALIVE)); //还是没有找到PHY,它就在此处挂住
  454. #else
  455.         while(!(MDIO->ALIVE)) //没有网线连接
  456.         {
  457.                 i++;
  458.                 if(i >= MAX_POLLING_NUM)
  459.                 {
  460.                         break;
  461.                 }
  462.         }//只是为了延时让phy与PC自适应的时涞却??
  463. #endif
  464. //
  465.    g_active_phy_id = 0; //确实是个发生错误,现在可以读到PHY。
  466.    MDIO->USERPHYSEL0 = 0;        //USERPHYSEL0 = 0,表示PHY0被选中监控。
  467. #if DEBUG_MDIO_LINK
  468.    phy_reg = phyRegRead(g_active_phy_id,0x02); //phy-id,查看phyRegRead是否正确;
  469.    if(phy_reg != 0x0022) //不等则芯片焊错
  470.    {
  471.         while(1);
  472.    }
  473. #endif

  474.    return (ERR_NO_ERROR);
  475. }

  476. //-----------------------------------------------------------------------------
  477. // returns if the link is currently active...1 -> active, 0 -> not active.
  478. //-----------------------------------------------------------------------------
  479. uint8_t isLinkActive(uint8_t in_phy)
  480. {
  481.    uint16_t status;

  482.    status = phyRegRead(in_phy, SMSC_REG_BASIC_STAT);
  483.    
  484.    if (CHKBIT(status, BASIC_STAT_LINK_STAT))
  485.       return (1);
  486.    else
  487.       return (0);
  488. }

  489. //-----------------------------------------------------------------------------
  490. // read a phy register using the MDIO.
  491. //-----------------------------------------------------------------------------
  492. uint16_t phyRegRead(uint8_t in_phy, uint8_t in_reg)
  493. {
  494.    // make sure mdio is not busy.
  495.    while (CHKBIT(MDIO->USERACCESS0, USERACC_GO)) {}

  496.    MDIO->USERACCESS0 = USERACC_GO |
  497.                         (in_reg << USERACC_SHIFT_REG) |
  498.                         (in_phy << USERACC_SHIFT_PHY);

  499.    while (CHKBIT(MDIO->USERACCESS0, USERACC_GO)) {}

  500.    return ((uint16_t)(MDIO->USERACCESS0 & USERACC_MASK_DATA));
  501. }

  502. //-----------------------------------------------------------------------------
  503. // write a phy register using the MDIO.
  504. //-----------------------------------------------------------------------------
  505. void phyRegWrite(uint8_t in_phy, uint8_t in_reg, uint16_t in_data)
  506. {
  507.    // make sure mdio is not busy.
  508.    while (CHKBIT(MDIO->USERACCESS0, USERACC_GO)) {}

  509.    MDIO->USERACCESS0 = USERACC_GO |
  510.                         USERACC_WRITE |
  511.                         (in_reg << USERACC_SHIFT_REG) |
  512.                         (in_phy << USERACC_SHIFT_PHY) |
  513.                         in_data;
  514. }


  515. 代码其中之二:
  516. /** Emac_des.c
  517. ** 由于在接收的过程中,可能存在一定的descriptor 问题,同时在与pbuf结合的情况
  518. ** 也存在着一些问题,故作如下修改。
  519. ** 现在决定作如下修改:
  520. ************************************/
  521. #include "includes.h"
  522. #include "Emac_des.h"
  523. #include "evmomapl138.h"
  524. #include "lwip/def.h"
  525. #include "lwip/pbuf.h"
  526. #include "lwip/sys.h"
  527. #include "lwip/opt.h"
  528. #include "inc/evmomapl138_emac.h"
  529. #include "etharp.h"
  530. #include "ethernetif.h"

  531. /* CPPI RAM size in bytes */
  532. #ifndef SIZE_CPPI_RAM
  533. #define SIZE_CPPI_RAM              0x2000   //8K, L138也一样
  534. #endif


  535. #define MAX_ALE_ENTRIES            1024
  536. #define ENTRY_TYPE                 0x30
  537. #define ENTRY_TYPE_IDX             7
  538. #define ENTRY_FREE                 0

  539. /* MDIO input and output frequencies in Hz */
  540. #define MDIO_FREQ_INPUT            125000000
  541. #define MDIO_FREQ_OUTPUT           1000000
  542. //flag --> 一样的描述
  543. #define CPDMA_BUF_DESC_OWNER       0x20000000
  544. #define CPDMA_BUF_DESC_SOP         0x80000000
  545. #define CPDMA_BUF_DESC_EOP         0x40000000
  546. #define CPDMA_BUF_DESC_EOQ         0x10000000

  547. #define MAX_TRANSFER_UNIT          1518 // Lp modified
  548. #define PBUF_LEN_MAX               MAX_TRANSFER_UNIT

  549. #define MAX_RX_PBUF_ALLOC          20   //使用20个看看
  550. #define MIN_PKT_LEN                60

  551. /* Define those to better describe the network interface. */
  552. #define IFNAME0                   'e'
  553. #define IFNAME1                   'n'


  554. /* TX Buffer descriptor data structure */
  555. struct cpdma_tx_bd {
  556.   volatile struct cpdma_tx_bd *next;
  557.   volatile u32_t bufptr;
  558.   volatile u32_t bufoff_len;
  559.   volatile u32_t flags_pktlen;
  560.   
  561.   /* 添加了一个这样的数据结构 */
  562.   volatile struct pbuf *pbuf;
  563. }cpdma_tx_bd;

  564. /* RX Buffer descriptor data structure */
  565. struct cpdma_rx_bd {
  566.   volatile struct cpdma_rx_bd *next;
  567.   volatile u32_t bufptr;
  568.   volatile u32_t bufoff_len;
  569.   volatile u32_t flags_pktlen;

  570.   /*添加了pbuf数据结构*/
  571.   volatile struct pbuf *pbuf;
  572. }cpdma_rx_bd;

  573. /**为的是编程者更好的处理RX channel发生的事件。***/
  574. struct rxch {
  575.   volatile struct cpdma_rx_bd *free_head;
  576.   volatile struct cpdma_rx_bd *active_head;
  577.   volatile struct cpdma_rx_bd *active_tail;
  578.   u32_t freed_pbuf_len;
  579. }rxch;

  580. /** 是TX Channel 更好的处理事件 ***/
  581. struct txch {
  582.   volatile struct cpdma_tx_bd *free_head;
  583.   volatile struct cpdma_tx_bd *active_tail;
  584.   volatile struct cpdma_tx_bd *next_bd_to_process;
  585. }txch;


  586. /**
  587. ** 这个是整个EMAC的操作界面数据结构 -- 不需要
  588. */
  589. struct emac_trif {
  590.   /* The tx/rx channels for the interface */
  591.   struct txch txch;
  592.   struct rxch rxch;
  593. }emac_trif;

  594. /*
  595. ** 初始化buffer descriptor
  596. ** 换了一个方式,用一个pbuf 链的方式来接收,免去拷贝。
  597. */
  598. err_t
  599. Emac_des_init( void )
  600. {
  601.   u32_t num_bd, pbuf_cnt = 0;
  602.   volatile struct cpdma_tx_bd *curr_txbd, *last_txbd;
  603.   volatile struct cpdma_rx_bd *curr_bd, *last_bd;
  604.   struct txch *txch;
  605.   struct rxch *rxch;
  606.   struct pbuf *p, *q;

  607.   //初始化.... 结构体..
  608.   //struct emac_trif {
  609.   memset((u8_t *)&emac_trif, 0, sizeof(emac_trif));
  610.   //struct txch {
  611.   memset((u8_t *)&txch, 0, sizeof(txch));
  612.   //struct rxch
  613.   memset((u8_t *)&rxch, 0, sizeof(rxch));
  614.   //struct cpdma_rx_bd {
  615.   memset((u8_t *)&cpdma_rx_bd, 0, sizeof(cpdma_rx_bd));
  616.   //struct cpdma_tx_bd {
  617.   memset((u8_t *)&cpdma_tx_bd, 0, sizeof(cpdma_rx_bd));
  618.   //取出txch的地址,以便操作
  619.   txch = &(emac_trif.txch);

  620. //EMAC_RAM_BASE是L138的buffer descriptor 所在CPPI RAM的起始地址
  621.   txch->free_head = (volatile struct cpdma_tx_bd*)(EMAC_RAM_BASE);
  622.   txch->next_bd_to_process = txch->free_head;
  623.   txch->active_tail = (volatile struct cpdma_tx_bd *)NULL;

  624. //多少个buffer desc, tx_bd... 特意SIZE_CPPI_RAM/2
  625.   num_bd = (SIZE_CPPI_RAM >> 1) / sizeof(cpdma_tx_bd);
  626.   
  627.   curr_txbd = txch->free_head;

  628.   /* Initialize all the TX buffer Descriptors */
  629.   while(num_bd--) {
  630.     curr_txbd->next = curr_txbd + 1;
  631.         curr_txbd->bufptr = 0; //初始化为0
  632.     curr_txbd->bufoff_len = 0; //也初始化为0
  633.     curr_txbd->flags_pktlen = 0;
  634.     curr_txbd->pbuf = 0;//现在还并没有pbuf要准备发送

  635.     last_txbd = curr_txbd;
  636.     curr_txbd = curr_txbd->next;
  637.   }
  638.   last_txbd->next = txch->free_head;
  639.   
  640.   /* Initialize the descriptors for the RX channel */
  641.   rxch = &(emac_trif.rxch);

  642.   rxch->active_head = (volatile struct cpdma_rx_bd*)(curr_txbd + 1);
  643.   
  644.   rxch->free_head = (volatile struct cpdma_rx_bd *)NULL;
  645.   rxch->freed_pbuf_len = 0;
  646.   num_bd = ((SIZE_CPPI_RAM >> 1) / sizeof(cpdma_rx_bd) - 1);
  647.   curr_bd = rxch->active_head;
  648.   last_bd = curr_bd;

  649.   /*
  650. ** 该驱动一个最大的不同就在此处,将接收的数据直接用DMA传送到pbuf,
  651. ** 以前我们都是用全局ram接收,而后拷贝至pbuf,还有一个不同就是
  652. ** 这里使用了EMAC部的CPPI_RAM空间,这样达到最好的效率。
  653. ** 但是为了考虑字节对齐的问题,还需要做点小小的修改
  654.   */
  655.   while(pbuf_cnt < MAX_RX_PBUF_ALLOC) {//产生10个pbuf..供接收DMA传送
  656. #if ETH_PAD_SIZE
  657.     p = pbuf_alloc(PBUF_RAW,(PBUF_LEN_MAX+ETH_PAD_SIZE), PBUF_POOL); //10 * 1500
  658.         pbuf_header(p, -ETH_PAD_SIZE); //向后移2个字节,接收过后,刚刚好
  659. #endif //ETH_PAD_SIZE
  660.     pbuf_cnt++;
  661.    
  662.     if(p != NULL) {
  663.       /* write the descriptors if there are enough numbers to hold the pbuf*/
  664.       if(((u32_t)pbuf_clen(p)) <= num_bd) {
  665.           // pbuf_clen(p)计算从p开始,pbuf链的长度
  666.           //如果pbuf_alloc产生比num_bd更大长度的描述符,那么就是个悲剧了。
  667.         for(q = p; q != NULL; q = q->next) {
  668.           curr_bd->bufptr = (u32_t)(q->payload); //buffer_ptr
  669.           curr_bd->bufoff_len = q->len; //buffoff & buffer_len
  670.           curr_bd->next = curr_bd + 1; //next buffer descriptor
  671.           curr_bd->flags_pktlen = CPDMA_BUF_DESC_OWNER; //flag set or clear
  672.          
  673.           /* Save the pbuf */
  674.           curr_bd->pbuf = q;
  675.           last_bd = curr_bd;
  676.           curr_bd = curr_bd->next;
  677.           num_bd--;
  678.         }//for
  679.       }//if <= num_bd
  680.    
  681.       /* free the allocated pbuf if no free descriptors are left */
  682.       else {
  683.         pbuf_free(p);
  684.         break;
  685.       }//else pbuf chain len > num_bd
  686.     }//if p != NULL
  687.     else {
  688.       break;
  689.     }//else p== NULL
  690.   }//while 产生10个

  691.   last_bd->next = (volatile struct cpdma_rx_bd *)NULL; //buff des chain 构造完成
  692.   rxch->active_tail = last_bd; //rxch控制着整个rxch的接收方式

  693.   EMAC->RXHDP[0] = (u32_t)(rxch->active_head); //add - lp
  694.   return ERR_OK;
  695. }



  696. /**
  697. ** 使用该rx_inhandler处理接收中断
  698. ** 每个pbuf链在处理之前必须要向前移ETH_PAD_SIZE个字节,以便4字节对齐
  699. ** 当你还要产生pbuf的时候,也要向后移ETH_PAD_SIZE个字节,以便接收。
  700. * @param netif the lwip network interface structure for this ethernetif
  701. * @return none
  702. */
  703. void
  704. Emac_rxint_handler(struct netif *netif) {
  705.   struct rxch *rxch;
  706.   volatile struct cpdma_rx_bd *curr_bd, *processed_bd, *curr_tail, *last_bd;
  707.   volatile struct pbuf *pbuf, *q, *new_pbuf;
  708.   u32_t ex_len = 0, len_to_alloc = 0;
  709.   u16_t tot_len;

  710. //  sitaraif = netif->state;
  711.   rxch = &(emac_trif.rxch);

  712.   //得到当前的rxch buffer desc
  713.   curr_bd = rxch->active_head;
  714.   last_bd = rxch->active_tail;
  715.   
  716.   //pbuf链中,SOP只出现一次,但是curr_bd已将buffer链推向下一个可能出现
  717.   //SOP的开头,所以这种方式更加严谨和有效。       
  718.    while(curr_bd->flags_pktlen & CPDMA_BUF_DESC_SOP) {
  719.   //用while是因为pbuf链来处理的
  720.     ex_len = 0;
  721.     len_to_alloc = 0;

  722.     //当OWNER被EMAC清掉的时候,EMAC就放弃了buff desc,可以做一些处理
  723.     if((curr_bd->flags_pktlen & CPDMA_BUF_DESC_OWNER)
  724.        != CPDMA_BUF_DESC_OWNER) {

  725.       if(rxch->free_head == NULL) {
  726.         /* this bd chain will be freed after processing */
  727.         rxch->free_head = curr_bd;     
  728.       }//if NULL
  729.      
  730.           //得到该接收到packet_len的长度
  731.       tot_len = (curr_bd->flags_pktlen) & 0xFFFF;

  732.       //保存当前接收的起始pbuf
  733.       q = curr_bd->pbuf;
  734.          //以下循环体为了更新除pbuf->payload除外,在结构体pbuf中
  735.          //的len,tot_len数据
  736.       do {
  737.                 //得到当前pbuf地址
  738.         pbuf = curr_bd->pbuf;
  739.         
  740.         /* If the earlier pbuf ended, update the chain */
  741.         if(pbuf->next == NULL) {
  742.           pbuf->next = (struct pbuf*)(curr_bd->next)->pbuf;
  743.         } //if Null
  744.       
  745.                 //len_to_alloc , pbuf链中的len的总和
  746.         len_to_alloc += pbuf->len;
  747.         /* Update the len and tot_len fields for the pbuf in the chain*/
  748.         pbuf->len = (curr_bd->bufoff_len) & 0xFFFF; //当前pbuf长度
  749.         pbuf->tot_len = tot_len - ex_len ; //当前pbuf后的tot_len长度(含自己)
  750.         processed_bd = curr_bd; //处理中的desc
  751.         ex_len += pbuf->len;
  752.         curr_bd = curr_bd->next;
  753.       } while((processed_bd->flags_pktlen & CPDMA_BUF_DESC_EOP)
  754.               != CPDMA_BUF_DESC_EOP);

  755.       /**
  756.        * Close the chain for this pbuf. A full packet is received in
  757.        * this pbuf chain. Now this pbuf can be given to upper layers for
  758.        * processing. The start of the pbuf chain is now 'q'.
  759.       */
  760.       pbuf->next = (struct pbuf *)NULL;
  761.   
  762. //在q处理之前,需要加上ETH_PAD_SIZE个空间,以便4字节对齐
  763. #if ETH_PAD_SIZE
  764.         if(q != NULL)
  765.         {
  766.             pbuf_header((struct pbuf *)q, ETH_PAD_SIZE);
  767. #endif //ETH_PAD_SIZE

  768. //为了节省中断的处理效率,这里节省时间,直接post msg给tcpip_thread
  769.                 if((netif->input((struct pbuf *)q,netif)) != ERR_OK)
  770.                 {
  771.                         pbuf_free((struct pbuf *)q);
  772.                         q = (volatile struct pbuf *)NULL;
  773.                 }
  774. #if ETH_PAD_SIZE
  775.         } //ETH_PAD_SIZE
  776. #endif //ETH_PAD_SIZE
  777.       /* Acknowledge that this packet is processed */
  778. //      CPSWCPDMARxCPWrite(sitaraif->cpsw_cpdma_base, 0, (unsigned int)processed_bd);
  779.           EMAC->RXCP[0] = (u32_t)processed_bd;
  780.       rxch->active_head = curr_bd;
  781.    
  782.       /**
  783.        * The earlier pbuf chain is freed from the upper layer. So, we need to
  784.        * allocate a new pbuf chain and update the descriptors with the pbuf info.
  785.        * To support chaining, the total length freed by the upper layer is tracked.
  786.        * Care should be taken even if the allocation fails.
  787.        */   
  788.       /**
  789.        * now len_to_alloc will contain the length of the pbuf which was freed
  790.        * from the upper layer
  791.        */
  792.       rxch->freed_pbuf_len += len_to_alloc;
  793.       new_pbuf = pbuf_alloc(PBUF_RAW, ((rxch->freed_pbuf_len)+ETH_PAD_SIZE), PBUF_POOL);

  794.       /* Write the descriptors with the pbuf info till either of them expires */
  795.       if(new_pbuf != NULL) {
  796. #if ETH_PAD_SIZE
  797.                    pbuf_header((struct pbuf *)new_pbuf, -ETH_PAD_SIZE);
  798. #endif //ETH_PAD_SIZE
  799.         curr_bd = rxch->free_head; //free_head,已经被释放的head,需要重新set
  800.                 //以下循环体添加新的pbuf到curr_bd中去
  801.         for(q = new_pbuf; (q != NULL) && (curr_bd != rxch->active_head); q = q->next) {
  802.           curr_bd->bufptr = (u32_t)(q->payload);
  803.          
  804.           /* no support for buf_offset. RXBUFFEROFFEST register is 0 */
  805.           curr_bd->bufoff_len = (q->len) & 0xFFFF;
  806.           curr_bd->flags_pktlen = CPDMA_BUF_DESC_OWNER;
  807.          
  808.           rxch->freed_pbuf_len -= q->len;
  809.          
  810.           /* Save the pbuf */
  811.           curr_bd->pbuf = q;
  812.           last_bd = curr_bd;
  813.           curr_bd = curr_bd->next;
  814.         }//for
  815.          
  816.         /**
  817.          * At this point either pbuf expired or no rxbd to allocate. If
  818.          * there are no, enough rx bds to allocate all pbufs in the chain,
  819.          * free the rest of the pbuf
  820.          */
  821.         if(q != NULL) {
  822.           pbuf_free((struct pbuf *)q);
  823.         }
  824.       
  825.         curr_tail = rxch->active_tail;
  826.         last_bd->next = (volatile struct cpdma_rx_bd *)NULL;
  827.       
  828.         curr_tail->next = rxch->free_head;
  829.         
  830.         /**
  831.          * Check if the reception has ended. If the EOQ flag is set, the NULL
  832.          * Pointer is taken by the DMA engine. So we need to write the RX HDP
  833.          * with the next descriptor.
  834.          */
  835.         if(curr_tail->flags_pktlen & CPDMA_BUF_DESC_EOQ) {
  836. //          CPSWCPDMARxHdrDescPtrWrite(sitaraif->cpsw_cpdma_base,
  837. //                                   (u32_t)(rxch->free_head), 0);
  838.                         EMAC->RXHDP[0] = (u32_t)(rxch->free_head);
  839.         }//if EOQ

  840.         rxch->free_head  = curr_bd;
  841.         rxch->active_tail = last_bd;
  842.       }//if new_pbuf
  843.     }//if OWNER
  844.     curr_bd = rxch->active_head;
  845. //以下这句,L138未做要求.
  846. //    CPSWCPDMANumFreeBufSet(sitaraif->cpsw_cpdma_base, 0, 1);
  847. // -----------括号不要删-------------------------------
  848.   }//While ....
  849. //-------------------------------------------
  850. // 以下在外面写
  851. //  CPSWCPDMAEndOfIntVectorWrite(sitaraif->cpsw_cpdma_base, CPSW_EOI_TX_PULSE);  
  852. //  CPSWCPDMAEndOfIntVectorWrite(sitaraif->cpsw_cpdma_base, CPSW_EOI_RX_PULSE);  
  853. }

  854. //---------------------------------------------------------------
  855. //以下是发送部分
  856. //---------------------------------------------------------------
  857. /**
  858. ** 这个函数将pbuf链的数据发送给物理层,可能buffer_des连接多处,因为是
  859. ** pbuf链连接而成的
  860. * @return None
  861. **/
  862. void Emac_transmit(struct pbuf *pbuf) {
  863.   struct pbuf *q;
  864.   struct txch *txch;
  865.   volatile struct cpdma_tx_bd *curr_bd, *active_head, *bd_end;
  866. // 取地址。
  867.   txch = &(emac_trif.txch);

  868. //得到可以使用的空闲head
  869.   curr_bd = txch->free_head;
  870.   //激活的head
  871.   active_head = curr_bd;

  872.   //更新该头的packet len 字段
  873.   curr_bd->flags_pktlen &= ~0xFFFF;
  874.   curr_bd->flags_pktlen |= pbuf->tot_len;

  875.   //交给EMAC之前,置位flags, SOP,OWNER
  876.   curr_bd->flags_pktlen |= (CPDMA_BUF_DESC_SOP | CPDMA_BUF_DESC_OWNER);

  877.   //把pbuf信息构建成buffer desc 链
  878.   for(q = pbuf; q != NULL; q = q->next) {

  879.     /* Intialize the buffer pointer and length */
  880.     curr_bd->bufptr = (u32_t)(q->payload);
  881.     curr_bd->bufoff_len = (q->len) & 0xFFFF;
  882.     bd_end = curr_bd;
  883.     curr_bd->pbuf = pbuf;
  884.     curr_bd = curr_bd->next;
  885.   }

  886.   //将buffer desc结尾
  887.   bd_end->next = (volatile struct cpdma_tx_bd *)NULL;
  888.   bd_end->flags_pktlen |= CPDMA_BUF_DESC_EOP;
  889.   //free_head指向下一个空的buff descriptor 处
  890.   txch->free_head = curr_bd;

  891.   //经过初始化之后,txch->active_tail指向NULL,但是发送buffer desc是一个
  892.   //单向的循环链表。所以这也是上面为什么bd_end->next要赋NULL值
  893.   if(txch->active_tail == NULL) {
  894. // 第一次发送active_head
  895.                 EMAC->TXHDP[0] = (u32_t)active_head;
  896.   }

  897.   /*
  898.   **第1次发送过后,假如发送完了,那么transmiter 将会halt,这样CPU在
  899.   **发送之前必须确认EOQ是否set,如果set,那么对于CPU来讲可以写HDP启动
  900.   **TXDMA发送了。
  901.   */
  902.   else {
  903.     curr_bd = txch->active_tail;
  904.     curr_bd->next = active_head;

  905.     if(curr_bd->flags_pktlen & CPDMA_BUF_DESC_EOQ) {
  906.      //假如EOQ被EMAC set之后,就启动tx DMA
  907.                 EMAC->TXHDP[0] = (u32_t)active_head;
  908.     }
  909.   }

  910.   txch->active_tail = bd_end;
  911. }

  912. /**
  913. * This function will send a packet through the emac if the channel is
  914. * available. Otherwise, the packet will be queued in a pbuf queue.
  915. *
  916. * @param netif the lwip network interface structure for this ethernetif
  917. * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
  918. * @return ERR_OK if the packet could be sent
  919. *         an err_t value if the packet couldn't be sent
  920. *
  921. */
  922. err_t
  923. OmapEmac_output(struct netif *netif, struct pbuf *p)
  924. {
  925.   INT8U os_err = 0;
  926.   SYS_ARCH_DECL_PROTECT(lev);

  927.   //等待有效的信号量才能发送
  928. //  OSSemPend(TxCmpSem, 1000, &os_err); // --LP , 2012/04/28 DLT

  929.   /**
  930.    * This entire function must run within a "critical section" to preserve
  931.    * the integrity of the transmit pbuf queue.
  932.    *
  933.    */
  934.   SYS_ARCH_PROTECT(lev);
  935. //在选择发送之前,要调整p->payload的两字节,因为它们不能发送出去
  936. #if ETH_PAD_SIZE
  937.   pbuf_header(p, -ETH_PAD_SIZE);
  938. #endif
  939.   /* adjust the packet length if less than minimum required */
  940.   if(p->tot_len < MIN_PKT_LEN) {
  941.      p->tot_len = MIN_PKT_LEN;
  942.      p->len = MIN_PKT_LEN;
  943.   }

  944.   /**
  945.    * Bump the reference count on the pbuf to prevent it from being
  946.    * freed till we are done with it.
  947.    *
  948.    */
  949.   pbuf_ref(p);
  950.    
  951.   //Emac物理层的发送。DMA 用了TX中断的方式
  952.   Emac_transmit(p);

  953.   /* Return to prior interrupt state and return. */
  954.   SYS_ARCH_UNPROTECT(lev);
  955.   
  956.   return ERR_OK;
  957. }

  958. /**
  959. ** lower level 已经启动DMA发送了吗,这里是为了软件清掉SOP和EOP,然后就是pbuf
  960. ** 链表的回收。
  961. * @param netif the lwip network interface structure for this ethernetif
  962. * @return none
  963. */
  964. void
  965. Emac_txint_handler(struct netif *netif) {
  966.   struct txch *txch;
  967.   volatile struct cpdma_tx_bd *curr_bd, *next_bd_to_process;  
  968.   
  969. //取txch结构体的地址
  970.   txch = &(emac_trif.txch);
  971. //下一待处理的buff des, next_bd_to_process被初始化为(EMAC_RAM_BASE)   
  972.   next_bd_to_process = txch->next_bd_to_process;
  973. // 用curr_bd来处理  
  974.   curr_bd = next_bd_to_process;
  975.   
  976.   /* Check for correct start of packet */
  977.   while((curr_bd->flags_pktlen) & CPDMA_BUF_DESC_SOP) {
  978.    
  979.     /* Make sure that the transmission is over */
  980.     while((curr_bd->flags_pktlen & CPDMA_BUF_DESC_OWNER)
  981.           == CPDMA_BUF_DESC_OWNER);
  982.    
  983.     /* Traverse till the end of packet is reached */
  984.     while(((curr_bd->flags_pktlen) & CPDMA_BUF_DESC_EOP) != CPDMA_BUF_DESC_EOP) {
  985.        curr_bd = curr_bd->next;
  986.     }//while(!EOP)

  987.     next_bd_to_process->flags_pktlen &= ~(CPDMA_BUF_DESC_SOP);
  988.     curr_bd->flags_pktlen &= ~(CPDMA_BUF_DESC_EOP);

  989.     /**
  990.      * If there are no more data transmitted, the next interrupt
  991.      * shall happen with the pbuf associated with the free_head
  992.      */
  993.     if(curr_bd->next == NULL) {
  994.       txch->next_bd_to_process = txch->free_head;
  995.     }
  996.   
  997.     else {
  998.       txch->next_bd_to_process = curr_bd->next; //接着处理下一帧数据包
  999.     }
  1000.    
  1001.     //写TXCP[],该帧数据包已经写完
  1002. //    CPSWCPDMATxCPWrite(sitaraif->cpsw_cpdma_base, 0, (u32_t)curr_bd);
  1003.         EMAC->TXCP[0] = (u32_t)curr_bd;
  1004.     pbuf_free((struct pbuf *)curr_bd->pbuf);

  1005. //    LINK_STATS_INC(link.xmit);
  1006.    
  1007.     next_bd_to_process = txch->next_bd_to_process;
  1008.     curr_bd = next_bd_to_process;
  1009.   }
  1010.   //发送信号量给发送部分保证发送的完整性。
  1011. //        OSSemPost(TxCmpSem);  //--lp , 2012/04/28 delete,查看效果。
  1012. //在外面写的
  1013. //  CPSWCPDMAEndOfIntVectorWrite(sitaraif->cpsw_cpdma_base, CPSW_EOI_TX_PULSE);
  1014. //  CPSWCPDMAEndOfIntVectorWrite(sitaraif->cpsw_cpdma_base, CPSW_EOI_RX_PULSE);
  1015. }

  1016. /********************* this file is end ****************************/

  1017. 代码其中之三:
  1018. /**************************************************************************
  1019. *                                                                         *
  1020. *   PROJECT     : TMON (Transparent monitor)                              *
  1021. *                                                                         *
  1022. *   MODULE      : LWIP.c                                                  *
  1023. *                                                                         *
  1024. *   AUTHOR      : Michael Anburaj                                         *
  1025. *                 URL  : http://geocities.com/michaelanburaj/             *
  1026. *                 EMAIL: michaelanburaj@hotmail.com                       *
  1027. *                                                                         *
  1028. *   PROCESSOR   : Any                                                     *
  1029. *                                                                         *
  1030. *   Tool-chain  : gcc                                                     *
  1031. *                                                                         *
  1032. *   DESCRIPTION :                                                         *
  1033. *   LwIP master source file.                                              *
  1034. *                                                                         *
  1035. **************************************************************************/

  1036. #include "tcpip.h"
  1037. #include "ethernetif.h"
  1038. #include "netconf.h"

  1039. /* ********************************************************************* */
  1040. /* Global definitions */
  1041. netif_t     main_net;

  1042. /* ********************************************************************* */
  1043. /* File local definitions */


  1044. /* ********************************************************************* */

  1045. /**
  1046. *** 初始化LwIP的协议栈
  1047.   */
  1048. void LwIP_Init( void )
  1049. {
  1050.   struct ip_addr ipaddr;
  1051.   struct ip_addr netmask;
  1052.   struct ip_addr gw;
  1053.       
  1054.   tcpip_init(NULL, NULL);
  1055.   
  1056. /** 在此处初始化IP地址 **/

  1057.   IP4_ADDR(&ipaddr,192,168,1,88); //该宏需要执行的!
  1058.   IP4_ADDR(&netmask,255,255,255,0);
  1059.   IP4_ADDR(&gw,192,168,0,1);

  1060.   MEMCPY(main_net.name,"glzn",4);
  1061. #if LWIP_NETIF_HOSTNAME  
  1062.   main_net.hostname = GetHostName();
  1063. #endif
  1064.   /* - netif_add(struct netif *netif, struct ip_addr *ipaddr,
  1065.             struct ip_addr *netmask, struct ip_addr *gw,
  1066.             void *state, err_t (* init)(struct netif *netif),
  1067.             err_t (* input)(struct pbuf *p, struct netif *netif))
  1068.    
  1069.    Adds your network interface to the netif_list. Allocate a struct
  1070.   netif and pass a pointer to this structure as the first argument.
  1071.   Give pointers to cleared ip_addr structures when using DHCP,
  1072.   or fill them with sane numbers otherwise. The state pointer may be NULL.

  1073.   The init function pointer must point to a initialization function for
  1074.   your ethernet netif interface. The following code illustrates it's use.*/
  1075.   
  1076.   
  1077.   netif_add(&main_net, &ipaddr, &netmask, &gw, NULL, ðernetif_init, &tcpip_input);
  1078.   /*  Registers the default network interface.*/
  1079.   netif_set_default(&main_net);  //可以删除 --2012/02/02, netif_default

  1080.   /*  When the netif is fully configured this function must be called.*/
  1081.    netif_set_up(&main_net); //this functional
  1082. }




  1083. /* ********************************************************************* */

  1084. 代码其中之四:
  1085. //主程序
  1086. //修改成适应LwIP v140的协议,此为系统main主函数
  1087. #include
  1088. #include
  1089. #include "dspint.h"
  1090. #include "sample.h"
  1091. #include "edma.h"
  1092. #include "norflash.h"
  1093. #include "evmomapl138.h"
  1094. #include "evmomapl138_gpio.h"
  1095. #include "evmomapl138_uart.h"
  1096. #include "evmomapl138_rtc.h"
  1097. #include "io.h"
  1098. #include "fpga_emifa.h"
  1099. #include "test_fpga.h"

  1100. //推荐的任务堆栈区大小为2048 OS_STK,即8192 byte
  1101. #define COMMON_STACK_LEN 2048

  1102. //给各个任务分配的堆栈区
  1103. OS_STK  TaskLWIPStk[COMMON_STACK_LEN];
  1104. OS_STK        TaskAppMainStk[COMMON_STACK_LEN];
  1105. OS_STK        TaskMMIStk[COMMON_STACK_LEN];
  1106. OS_STK        TaskFpgaUPPStk[COMMON_STACK_LEN];
  1107. OS_STK        TaskFpgaEMIFAStk[COMMON_STACK_LEN * 32];
  1108. //OS_STK        TaskTestStk[COMMON_STACK_LEN];
  1109. //各个任务进程主函数
  1110. void TaskAppMain(void *pd);
  1111. void TaskMMI(void *pd);//通过upp总线刷液晶数据,触发dsp中断,启动upp发送
  1112. extern void TaskLWIP(void *p_arg); //TaskLWIP任务
  1113. //extern void TaskTest(void *pd);


  1114. int main()
  1115. {
  1116.         //初始化中断向量
  1117.         OS_CPU_InitExceptVect();
  1118.         //初始化uC/OS-II实时内核
  1119.     OSInit();
  1120.         //创建系统主进程任务(放在最高优先级,包括装置定值、参数自检测,并作为其他任务的WatchDog。)
  1121.         OSTaskCreate(TaskAppMain, (void *)0, (OS_STK*)&TaskAppMainStk[COMMON_STACK_LEN-1], 2);
  1122.     //启动操作系统内核
  1123.         OSStart();
  1124. }

  1125. //系统主进程任务
  1126. void TaskAppMain(void *pd)
  1127. {
  1128.         unsigned char ucErr;
  1129.         tmr0_init();
  1130.         GPIOInit();
  1131.         chipint_init();
  1132.         memset((unsigned char *)TaskLWIPStk, 0, (COMMON_STACK_LEN*sizeof(OS_STK)));
  1133. //初始化由Lwip任务堆栈开辟的堆栈区域

  1134.         //INT8U enledflag = /;
  1135.         //INT32U counter = 0;
  1136.         //创建任务
  1137.         //OSTaskCreate(TaskFPGA_UPP, (void *)0, (OS_STK*)&TaskFpgaUPPStk[COMMON_STACK_LEN-1], 11);
  1138. //        OSTaskCreate(TaskFPGA_EMIFA, (void *)0, (OS_STK*)&TaskFpgaEMIFAStk[COMMON_STACK_LEN-1], 12);
  1139. //        OSTaskCreate(TaskMMI, (void *)0, (OS_STK*)&TaskMMIStk[COMMON_STACK_LEN-1], 13);
  1140.         //OSTaskCreate(TaskTest, (void *)0, (OS_STK*)&TaskTestStk[COMMON_STACK_LEN-1],100);
  1141.         OSTaskCreate(TaskLWIP,(void *)0,(OS_STK *)&TaskLWIPStk[COMMON_STACK_LEN -1],10);
  1142.         while(1)
  1143.         {
  1144.                   /*asm(" nop");
  1145.         counter++;
  1146.                 if(counter >=20)
  1147.                 {
  1148.                    enledflag ^=0x01;
  1149.            inb(ARM_DSP_CMD) = enledflag;
  1150.                    DspintArmtrip(DSPINTTYPE_2);
  1151.            counter = 0;
  1152.                 }
  1153.                 if(enledflag == 0)
  1154.                 {
  1155.                         ledchange();
  1156.                 }*/
  1157. //                OSTimeDly(500);
  1158. //                OSMboxPend(RxCntMbox,0,&ucErr);
  1159.             OSTimeDly(1000);
  1160.                 asm(" nop");
  1161.         }
  1162. }

  1163. //
  1164. #define  SHAREMMI_ADR    (0x80000200)     //共享液晶显示数据区地址
  1165. #define  MMI_LNUM        (240)            //液晶显示一屏数据的行数目
  1166. #define  MMI_LBYTE       (40)             //液晶显示一屏数据的行字节数目320/8
  1167. #define  MMI_DATALEN     (MMI_LNUM*MMI_LBYTE) //液晶显示缓冲区长度
  1168. #define  SHARERAW_ADR    (0x8002800)     //共享原始数据区地址
  1169. #define  SHAREMEA_ADR    (0x8001f000)     //共享测量结果区地址
  1170. //显存
  1171. #define LCD_XSIZE        (320)       // X方向像素
  1172. #define LCD_YSIZE        (240)       // Y方向像素
  1173. #define LCDMLEN ((LCD_XSIZE*LCD_YSIZE)/8)
  1174. INT8U LcdMemory[LCDMLEN];

  1175. void loadMMIdata()
  1176. {
  1177.    INT8U *pobject;
  1178.    INT16U i;
  1179.    static INT8U showdata = 0;
  1180.    static INT8U changeflag = 0;
  1181.    changeflag++;
  1182.    if(changeflag==6)
  1183.    {
  1184.                 changeflag=0;
  1185.                 showdata++;
  1186.    }
  1187.    pobject =LcdMemory;//(INT8U*)SHAREMMI_ADR;
  1188.    if(showdata == 0)
  1189.    {
  1190.                 for(i=0;i
  1191.             {
  1192.                *pobject++ = (i+1)&0xff;
  1193.             }
  1194.    }
  1195.    else
  1196.    {
  1197.                 for(i=0;i
  1198.            {
  1199.                *pobject++ = showdata;
  1200.            }
  1201.    }   
  1202. }

  1203. void TaskMMI(void *pd)
  1204. {
  1205.         while(1)
  1206.         {
  1207.             
  1208.                 //pushus(0);
  1209.         //loadMMIdata();
  1210.                 //EDMA0config(0,(void*)LcdMemory,(void*)SHAREMMI_ADR,LCDMLEN);
  1211.                
  1212.                 //pushus(1);
  1213.                 RelayTest();
  1214.                 OSTimeDly(100);
  1215.         }
  1216. }


  1217. 代码其中之五:
  1218. /* main.c
  1219. ** test lwip
  1220. ***************************************************/
  1221. #include
  1222. #include "evmomapl138.h"

  1223. #include
  1224. #include
  1225. #include
  1226. #include "lwip/mem.h"
  1227. #include "lwip/memp.h"
  1228. #include "lwip/netif.h"
  1229. #include "lwip/tcpip.h"
  1230. #include "lwip.h"
  1231. // LwIP task stk Information

  1232. /**
  1233. ** DEBUG Information
  1234. ****************************************************/

  1235. /**
  1236. ** global value
  1237. ***************************************************/

  1238. /**
  1239. ** function decl
  1240. **************************************************/
  1241. static void BSP_Init(void );
  1242. void tcpip_init_done(void *arg);

  1243. /* App_LwipTask
  1244. **
  1245. ************************************************************************/
  1246. void TaskLWIP(void *parg)
  1247. {
  1248.         //加载网卡驱动
  1249.         //加载L138本身自带的EMAC驱动
  1250.         //Lwip_v140使用lwip.c处理初始化网口的信息,主任务只要调用lwip_Init()即可
  1251.         LwIP_Init();
  1252.         while(1)
  1253.         {
  1254.                 OSTimeDly(2000);
  1255.         }
  1256. }

  1257. /* BSP_Init()
  1258. ** 配置启动的时钟,貌似omapL138_app/boot.asm 中
  1259. ** 有初始化STACK等配置,但是没有见到其内有时钟配置,工程初始化时也没有发现。
  1260. ** 故要初始化PLL
  1261. ********************************************/
  1262. void BSP_Init(void)
  1263. {
  1264.         EVMOMAPL138_Init();
  1265. }

  1266. 我贴了一些代码,请看看帮帮忙,我真不知道该如何解决啦...
复制代码

一周热门 更多>