HMILY_YLIMH

    1. 代码其中之一:                                                        //----------------------------------------------------------------------------- // \file    evmomapl138_emac.c // \brief   implementation of the emac/mdio driver for the OMAP-L138 EVM. // //----------------------------------------------------------------------------- #include "stdio.h" #include "string.h" #include "os_cpu_isr.h" #include "includes.h" #include "inc/evmomapl138_emac.h" #include "inc/types.h" #include "evmomapl138.h" #include "evmomapl138_timer.h" #include "inc/ethernet_smsc.h" #include "inc/evmomapl138_gpio.h" #include "inc/evmomapl138_i2c_gpio.h" #include "inc/evmomapl138_cdce913.h" #include "evmomapl138_aintc.h"   // add_ISR需要 #include "netif/etharp.h" #include "Emac_des.h" #include "ethernetif.h" #ifndef USE_HDTIME_DLY #define USTIMER_delay(x)                #endif //USE_HDTIME_DLY #define MAX_POLLING_NUM                (0x0FFFFFFF) //----------------------------------------------------------------------------- // Private Defines and Macros //----------------------------------------------------------------------------- // INTCONTROL >> INTPRESCALE , number of EMAC clk period within a 4 us time window #define NUM_INTPRESCALE    (4*SYSCLOCK4_HZ/1000000)  //4/(1000000/SYSCLOCK4_HZ) , 4us // mdio clock divide down value. #define MDIO_CLK_FREQ_HZ   (2000000)  //2M HZ #define MDIO_CLK_DIVISOR   ((SYSCLOCK4_HZ / MDIO_CLK_FREQ_HZ) - 1) // rx / tx desriptor memory offsets. #define RX_DESC_OFFSET     (0) #define TX_DESC_OFFSET     (0x1000) //MII pinmux #define PINMUX_MII_REG_0         (2) #define PINMUX_MII_MASK_0        (0xFFFFFFF0) #define PINMUX_MII_VAL_0         (0x88888880) #define PINMUX_MII_REG_1         (3) #define PINMUX_MII_MASK_1        (0xFFFFFFFF) #define PINMUX_MII_VAL_1         (0x88888888) //RMII pinmux #define PINMUX_RMII_REG_0        (14) #define PINMUX_RMII_MASK_0       (0xFFFFFF00) #define PINMUX_RMII_VAL_0        (0x88888800) #define PINMUX_RMII_REG_1        (15) #define PINMUX_RMII_MASK_1       (0x000000FF) #define PINMUX_RMII_VAL_1        (0x00000080) //MDIO pinmux #define PINMUX_MDIO_REG          (4) #define PINMUX_MDIO_MASK         (0x000000FF) #define PINMUX_MDIO_VAL          (0x00000088) //GPIO pinmux #define PINMUX_MII_MDIO_EN_REG         (6) #define PINMUX_MII_MDIO_EN_MASK         (0x000000F0) #define PINMUX_MII_MDIO_EN_VAL         (0x00000080) // #define EMAC_RMII_SPEED_100                 (0x00008000) //----------------------------------------------------------------------------- // Private Static Variables //----------------------------------------------------------------------------- static uint8_t g_active_phy_id = 0x0; //我们选用的L138是phy_id是为0的 //----------------------------------------------------------------------------- // Private Function Prototypes //----------------------------------------------------------------------------- static uint32_t initMdioPhy(void); static uint8_t isLinkActive(uint8_t in_phy); static uint16_t phyRegRead(uint8_t in_phy, uint8_t in_reg); static void phyRegWrite(uint8_t in_phy, uint8_t in_reg, uint16_t in_data); //---------------------------------------------------------------------------- //Public value definitions //---------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Public Function Definitions //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // \brief   initialize the EMAC and MDIO for use. // // \param   none. // // \return  uint32_t //    ERR_NO_ERROR - everything is ok...emac ready to use. //    ERR_INIT_FAIL - something happened during initialization. //----------------------------------------------------------------------------- uint32_t Lowlevel_Emac_Init(void) {    uint32_t rtn = 0;    uint32_t i;   SYS_ARCH_DECL_PROTECT(sr);   SYS_ARCH_PROTECT(sr);    // reset emac module.    EMAC->SOFTRESET = 1;         while (EMAC->SOFTRESET != 0) {;}         //init emac control module         //----------------------------------------         // AddISR() -- configuration of the interrupt to the CPU.         //AINTC --Number34 core0 Receive Interrupt         AddISR(34,L138Ethif_RxHandler,(void *)0);         aintcRegs->SICR = 34; //clear index status         aintcRegs->CMR8 = 0x00170000;//(Sets channel map, system interrupt --> host channel interrupt )     aintcRegs->EISR = 34; //Enable Index Set Register         aintcRegs->SECR2 = 0x00000004; //34 status clear           //configure Tx Interrupt Handler         AddISR(35,L138Ethif_TxHandler,(void *)0);         aintcRegs->SICR = 35; //clear index status         aintcRegs->CMR8 = 0x18000000; //SETS CHannel map         aintcRegs->EISR = 35; //Enable Index Set Register         aintcRegs->SECR2 = 0x00000008; //clear 35 status register ...         // configure INTCONTORL , CnRXIMAX, CnTXIMAX,         EMAC_CTRL->INTCTL = (NUM_INTPRESCALE| 0x00000300);         EMAC_CTRL->C0RXIMAX = 2;         EMAC_CTRL->C0TXIMAX = 2;         //--& init emac module.    //------------------             // make sure emac control interrupts are disabled.    EMAC_CTRL->C0RXTHRESHEN = 0;    EMAC_CTRL->C1RXTHRESHEN = 0;    EMAC_CTRL->C2RXTHRESHEN = 0;    EMAC_CTRL->C0RXEN = 0;    EMAC_CTRL->C1RXEN = 0;    EMAC_CTRL->C2RXEN = 0;    EMAC_CTRL->C0TXEN = 0;    EMAC_CTRL->C1TXEN = 0;    EMAC_CTRL->C2TXEN = 0;    EMAC_CTRL->C0MISCEN = 0;    EMAC_CTRL->C1MISCEN = 0;    EMAC_CTRL->C2MISCEN = 0;    EVMOMAPL138_pinmuxConfig(PINMUX_MDIO_REG, PINMUX_MDIO_MASK, PINMUX_MDIO_VAL);                                           //MDIO shared by both RMII and MII //   EVMOMAPL138_pinmuxConfig(PINMUX_MII_MDIO_EN_REG, PINMUX_MII_MDIO_EN_MASK, PINMUX_MII_MDIO_EN_VAL); //pinmux to select gpio bank2 pin6                        //PINMUXING     EVMOMAPL138_pinmuxConfig(PINMUX_MII_REG_0, PINMUX_MII_MASK_0, PINMUX_MII_VAL_0);     EVMOMAPL138_pinmuxConfig(PINMUX_MII_REG_1, PINMUX_MII_MASK_1, PINMUX_MII_VAL_1);            SYSCONFIG->KICKR[0] = KICK0R_UNLOCK;     SYSCONFIG->KICKR[1] = KICK1R_UNLOCK;     CLRBIT(SYSCONFIG->CFGCHIP[3], 0x00000100); //select mii mode !         //as software reset consideration, do this here    EVMOMAPL138_lpscTransition(PSC1, DOMAIN0, LPSC_EMAC, PSC_ENABLE);    // clear MAC control register, receive control register, transmiter control register         EMAC->MACCONTROL = 0;         EMAC->RXCONTROL = 0;         EMAC->TXCONTROL = 0;   // init header descriptor pointer regs to 0.      for (i = 0; i < 8; i++)      {        EMAC->TXHDP[i] = 0;        EMAC->RXHDP[i] = 0;      }    // clear all statistic register #ifndef BOOT    memset((uint8_t *)NET_STAT_REG_BASE, 0, NET_STAT_REG_NUM_BYTES); #endif    // setup local MAC address, only channel 0 is valid.    // program all 8, only need to set MACADDRHI for index = 0.    // use duplicate address for all unused channels.    // TODO: read MAC address from SPI flash.    //写的顺序是MACINDEX, ADDRHI, ADDRLO,由于高40bits是共享的    //只用了通道0,EMAC->MACADDRLO = 0X000000506 |VALID|MATCHFILT    for (i = 1; i < 8; i++)    {       EMAC->MACINDEX = i;           EMAC->MACADDRHI = 0x42020304; //index -> hi -> lo       EMAC->MACADDRLO = 0x00000506;              }    EMAC->MACINDEX = 0;    EMAC->MACADDRHI = 0x42020304;    // channel bit = 0, match mac address = 1    EMAC->MACADDRLO = 0x00000506 | MACADDRLO_VALID | MACADDRLO_MATCHFILT;     // for use tx DMA descriptor configuration:     EMAC->MACSRCADDRHI = 0x42020304;         EMAC->MACSRCADDRLO = 0x00000506;    // initialize receive channel free buffer count regs, if buffer flow    // control is to be enabled.    // NOTE: this example does not use buffer flow control.    // enable unicast chan 0 only.    EMAC->RXUNICASTSET = 0x01;        // no multicast addresses, clear MAC address hash registers.    EMAC->MACHASH1 = 0;    EMAC->MACHASH2 = 0;    // 只允许broadcast的ARP数据包,和发给自己的包,以太网的其他数据不放入Memmory里去.    //但是我单独设置RxBroadEn却没有作用。    EMAC->RXMBPENABLE = 0;    SETBIT(EMAC->RXMBPENABLE, (RXBROADEN|RXCAFEN)); // EMAC->RXMBPENABLE = 0x01E02020;                //enable reception of almost all frames inc error        //11. configure MACCONTROL (Don't set GMIIEN Bit)    SETBIT(EMAC->MACCONTROL, (RMIISPEED|FULLDUPLEX|TXPACE)); //RMII_SPEED,为了适应RMII            // 12. Clear all unused channel interrupt bits by writing the receive interrupt mask clear register         //(RXINTMASKCLEAR) and the transmit interrupt mask clear register (TXINTMASKCLEAR).         EMAC->RXINTMASKCLEAR |= 0xFE; //RX channel 0的中断不屏蔽         EMAC->TXINTMASKCLEAR |= 0xFE; //TX CH0 中断屏蔽         //13. Modify RXINTMASKSET, TXINTMASKSET,MACINTMASKSET         EMAC->RXINTMASKSET |= 0x01;         EMAC->TXINTMASKSET |= 0x01;         EMAC->MACINTMASKCLR = 0x03; //disabled host mask , stat interrupt        //14 init receive buffer offset and max length.    EMAC->RXBUFFEROFFSET = 0;    EMAC->RXMAXLEN = MAX_PACKET_SIZE;        // initialize receive/transmit descriptor list queues.    Emac_des_init(); //modify 04/18    //16 enable receive / transmit DMA controllers...set GMIIEN.    EMAC->RXCONTROL = 1;    EMAC->TXCONTROL = 1;    SETBIT(EMAC->MACCONTROL, GMIIEN ); #if 1   //文档说未经测试,删除貌似没效果啊,先不管它    SETBIT(EMAC->EMCONTROL, SOFT); #endif    // -->& init mdio / phy, 再加上MAC中断    //-----------------    rtn = initMdioPhy(); //   if (rtn != ERR_NO_ERROR) //      return (rtn);     SYS_ARCH_UNPROTECT(sr);    //17>Enable the device interrupt in EMAC control module registers CnRXTHRESHEN, CnRXEN, CnTXEN,    //and CnMISCEN. -- LP Add         EMAC_CTRL->C0RXEN = 1; //C0RXPULSE Is Enabled for RX channel 0            EMAC_CTRL->C0TXEN = 1; //C0TXPULSE IS enabled for tx channel 0         return (rtn); } //----------------------------------------------------------------------------- // \brief   power on the phy. // // \param   none. // // \return  uint32_t //    ERR_NO_ERROR - everything is ok...phy is on. //    ERR_FAIL - something happened and could not power on. //----------------------------------------------------------------------------- uint32_t EMAC_phyPowerOn(void) {    uint32_t rtn;    uint16_t ctrl_reg;    ctrl_reg = phyRegRead(g_active_phy_id, SMSC_REG_BASIC_CTRL);    if (!CHKBIT(ctrl_reg, BASIC_CTRL_POWER_DOWN))    {       // phy is already on...nothing left to do.       #if DEBUG       printf("phy powered, basic ctrl reg: %04x\n", ctrl_reg);       #endif       rtn = ERR_NO_ERROR;    }    else    {       // clear power down bit and write back to phy.       CLRBIT(ctrl_reg, BASIC_CTRL_POWER_DOWN);       phyRegWrite(g_active_phy_id, SMSC_REG_BASIC_CTRL, ctrl_reg);       // short delay, then read the reg back to verify loopback is enabled.       USTIMER_delay(500);       ctrl_reg = phyRegRead(g_active_phy_id, SMSC_REG_BASIC_CTRL);       if (!CHKBIT(ctrl_reg, BASIC_CTRL_POWER_DOWN))       {          // phy is powered...return success.          #if DEBUG          printf("phy powered, basic ctrl reg: %04x\n", ctrl_reg);          #endif          rtn = ERR_NO_ERROR;       }       else       {          // power down bit did not clear...return error.          #if DEBUG          printf("power down did not clear: %04x\n", ctrl_reg);          #endif          rtn = ERR_FAIL;       }    }    return (rtn); } //----------------------------------------------------------------------------- // \brief   power down the phy. // // \param   none. // // \return  uint32_t //    ERR_NO_ERROR - everything is ok...phy is powered down. //    ERR_FAIL - something happened and could not power down. //----------------------------------------------------------------------------- uint32_t EMAC_phyPowerDown(void) {    uint32_t rtn;    uint16_t ctrl_reg;    ctrl_reg = phyRegRead(g_active_phy_id, SMSC_REG_BASIC_CTRL);    if(CHKBIT(ctrl_reg, BASIC_CTRL_ISOLATE) && CHKBIT(ctrl_reg, BASIC_CTRL_POWER_DOWN))    {       // phy is already powered down...nothing left to do.       #if DEBUG       printf("phy powered down, basic ctrl reg: %04x\n", ctrl_reg);       #endif       rtn = ERR_NO_ERROR;    }    else    {       // set power down bit and write back to phy.       SETBIT(ctrl_reg, BASIC_CTRL_ISOLATE | BASIC_CTRL_POWER_DOWN);       phyRegWrite(g_active_phy_id, SMSC_REG_BASIC_CTRL, ctrl_reg);       // short delay, then read the reg back to verify loopback is disabled.       USTIMER_delay(500);       ctrl_reg = phyRegRead(g_active_phy_id, SMSC_REG_BASIC_CTRL);       if(CHKBIT(ctrl_reg, BASIC_CTRL_ISOLATE) && CHKBIT(ctrl_reg, BASIC_CTRL_POWER_DOWN))       {          // phy is powered down...return success.          #if DEBUG          printf("phy powered down, basic ctrl reg: %04x\n", ctrl_reg);          #endif          rtn = ERR_NO_ERROR;       }       else       {          // power down bit did not set...return error.          #if DEBUG          printf("power down bit did not set: %04x\n", ctrl_reg);          #endif          rtn = ERR_FAIL;       }    }    return (rtn); } //----------------------------------------------------------------------------- // \brief   put the phy into loopback mode. // // \param   none. // // \return  uint32_t //    ERR_NO_ERROR - everything is ok...phy is in loopback mode. //    ERR_FAIL - something happened and could not enter loopback. //----------------------------------------------------------------------------- uint32_t EMAC_phyEnterLoopback(void) {    uint32_t rtn;    uint16_t ctrl_reg;    ctrl_reg = phyRegRead(g_active_phy_id, SMSC_REG_BASIC_CTRL);    rtn = ERR_NO_ERROR;    if (ctrl_reg & BASIC_CTRL_LOOPBACK)    {       // loopback is already enabled...nothing left to do.       #if DEBUG       printf("loopback enabled, basic ctrl reg: %04x\n", ctrl_reg);       #endif       rtn = ERR_NO_ERROR;    }    else    {       // set loopback bit and write back to phy.       ctrl_reg |= BASIC_CTRL_LOOPBACK;       phyRegWrite(g_active_phy_id, SMSC_REG_BASIC_CTRL, ctrl_reg);       // short delay, then read the reg back to verify loopback is enabled.       USTIMER_delay(500);       ctrl_reg = phyRegRead(g_active_phy_id, SMSC_REG_BASIC_CTRL);       if (ctrl_reg & BASIC_CTRL_LOOPBACK)       {          // loopback is enabled...return success.          #if DEBUG          printf("loopback enabled , basic ctrl reg: %04x\n", ctrl_reg);          #endif          rtn = ERR_NO_ERROR;       }       else       {          // loopback bit did not get set...return error.          #if DEBUG          printf("loopback did not set: %04x\n", ctrl_reg);          #endif          rtn = ERR_FAIL;       }    }    return (rtn); } //----------------------------------------------------------------------------- // \brief   remove the phy from loopback mode. // // \param   none. // // \return  uint32_t //    ERR_NO_ERROR - everything is ok...phy is out of loopback mode. //    ERR_FAIL - something happened and could not disable loopback. //----------------------------------------------------------------------------- uint32_t EMAC_phyExitLoopback(void) {    uint32_t rtn;    uint16_t ctrl_reg;    ctrl_reg = phyRegRead(g_active_phy_id, SMSC_REG_BASIC_CTRL);    if (!(ctrl_reg & BASIC_CTRL_LOOPBACK))    {       // loopback is already disabled...nothing left to do.       #if DEBUG       printf("loopback disabled, basic ctrl reg: %04x\n", ctrl_reg);       #endif       rtn = ERR_NO_ERROR;    }    else    {       // clear loopback bit and write back to phy.       ctrl_reg &= ~BASIC_CTRL_LOOPBACK;       phyRegWrite(g_active_phy_id, SMSC_REG_BASIC_CTRL, ctrl_reg);       // short delay, then read the reg back to verify loopback is disabled.       USTIMER_delay(5);       ctrl_reg = phyRegRead(g_active_phy_id, SMSC_REG_BASIC_CTRL);       if (!(ctrl_reg & BASIC_CTRL_LOOPBACK))       {          // loopback is disabled...return success.          #if DEBUG          printf("loopback disabled , basic ctrl reg: %04x\n", ctrl_reg);          #endif          rtn = ERR_NO_ERROR;       }       else       {          // loopback bit did not clear...return error.          #if DEBUG          printf("loopback did not clear: %04x\n", ctrl_reg);          #endif          rtn = ERR_FAIL;       }    }    return (rtn); } //----------------------------------------------------------------------------- // Private Function Definitions //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // initialize the mdio module and identify the active phy. //----------------------------------------------------------------------------- uint32_t initMdioPhy(void) {    uint32_t i = 0;    uint16_t phy_reg;    // init the mdio regs.    MDIO->CONTROL = MDIO_CTRL_ENABLE |                      MDIO_CTRL_FAULT |                      MDIO_CTRL_FAULTENB |                      MDIO_CLK_DIVISOR;    while (CHKBIT(MDIO->CONTROL, MDIO_CTRL_IDLE)) {;} #if DEBUG_MDIO_LINK    // look for an active phy...takes up to 50 us for each phy to be checked.    //以下只是调试时有用,真正烧入程序中去时,是不行的,因为没插上网线,AddISR还要上的。    for (i = 0; i < MAX_POLLING_NUM; i++)    {       if (MDIO->ALIVE)       {          // at least one phy has acknowledged us...break the loop.          break;       }       USTIMER_delay(50);  // polling , 采用polling方式,LP- delete    }    while(!(MDIO->ALIVE)); //还是没有找到PHY,它就在此处挂住 #else         while(!(MDIO->ALIVE)) //没有网线连接         {                 i++;                 if(i >= MAX_POLLING_NUM)                 {                         break;                 }         }//只是为了延时让phy与PC自适应的时涞却?? #endif //    g_active_phy_id = 0; //确实是个发生错误,现在可以读到PHY。    MDIO->USERPHYSEL0 = 0;        //USERPHYSEL0 = 0,表示PHY0被选中监控。 #if DEBUG_MDIO_LINK    phy_reg = phyRegRead(g_active_phy_id,0x02); //phy-id,查看phyRegRead是否正确;    if(phy_reg != 0x0022) //不等则芯片焊错    {         while(1);    } #endif    return (ERR_NO_ERROR); } //----------------------------------------------------------------------------- // returns if the link is currently active...1 -> active, 0 -> not active. //----------------------------------------------------------------------------- uint8_t isLinkActive(uint8_t in_phy) {    uint16_t status;    status = phyRegRead(in_phy, SMSC_REG_BASIC_STAT);        if (CHKBIT(status, BASIC_STAT_LINK_STAT))       return (1);    else       return (0); } //----------------------------------------------------------------------------- // read a phy register using the MDIO. //----------------------------------------------------------------------------- uint16_t phyRegRead(uint8_t in_phy, uint8_t in_reg) {    // make sure mdio is not busy.    while (CHKBIT(MDIO->USERACCESS0, USERACC_GO)) {}    MDIO->USERACCESS0 = USERACC_GO |                         (in_reg USERACCESS0 & USERACC_MASK_DATA)); } //----------------------------------------------------------------------------- // write a phy register using the MDIO. //----------------------------------------------------------------------------- void phyRegWrite(uint8_t in_phy, uint8_t in_reg, uint16_t in_data) {    // make sure mdio is not busy.    while (CHKBIT(MDIO->USERACCESS0, USERACC_GO)) {}    MDIO->USERACCESS0 = USERACC_GO |                         USERACC_WRITE |                         (in_reg free_head = (volatile struct cpdma_tx_bd*)(EMAC_RAM_BASE);   txch->next_bd_to_process = txch->free_head;   txch->active_tail = (volatile struct cpdma_tx_bd *)NULL; //多少个buffer desc, tx_bd... 特意SIZE_CPPI_RAM/2   num_bd = (SIZE_CPPI_RAM >> 1) / sizeof(cpdma_tx_bd);      curr_txbd = txch->free_head;   /* Initialize all the TX buffer Descriptors */   while(num_bd--) {     curr_txbd->next = curr_txbd + 1;         curr_txbd->bufptr = 0; //初始化为0     curr_txbd->bufoff_len = 0; //也初始化为0     curr_txbd->flags_pktlen = 0;     curr_txbd->pbuf = 0;//现在还并没有pbuf要准备发送     last_txbd = curr_txbd;     curr_txbd = curr_txbd->next;   }   last_txbd->next = txch->free_head;      /* Initialize the descriptors for the RX channel */   rxch = &(emac_trif.rxch);   rxch->active_head = (volatile struct cpdma_rx_bd*)(curr_txbd + 1);      rxch->free_head = (volatile struct cpdma_rx_bd *)NULL;   rxch->freed_pbuf_len = 0;   num_bd = ((SIZE_CPPI_RAM >> 1) / sizeof(cpdma_rx_bd) - 1);   curr_bd = rxch->active_head;   last_bd = curr_bd;   /* ** 该驱动一个最大的不同就在此处,将接收的数据直接用DMA传送到pbuf, ** 以前我们都是用全局ram接收,而后拷贝至pbuf,还有一个不同就是 ** 这里使用了EMAC部的CPPI_RAM空间,这样达到最好的效率。 ** 但是为了考虑字节对齐的问题,还需要做点小小的修改   */   while(pbuf_cnt < MAX_RX_PBUF_ALLOC) {//产生10个pbuf..供接收DMA传送 #if ETH_PAD_SIZE     p = pbuf_alloc(PBUF_RAW,(PBUF_LEN_MAX+ETH_PAD_SIZE), PBUF_POOL); //10 * 1500         pbuf_header(p, -ETH_PAD_SIZE); //向后移2个字节,接收过后,刚刚好 #endif //ETH_PAD_SIZE     pbuf_cnt++;         if(p != NULL) {       /* write the descriptors if there are enough numbers to hold the pbuf*/       if(((u32_t)pbuf_clen(p)) next) {           curr_bd->bufptr = (u32_t)(q->payload); //buffer_ptr           curr_bd->bufoff_len = q->len; //buffoff & buffer_len           curr_bd->next = curr_bd + 1; //next buffer descriptor           curr_bd->flags_pktlen = CPDMA_BUF_DESC_OWNER; //flag set or clear                     /* Save the pbuf */           curr_bd->pbuf = q;           last_bd = curr_bd;           curr_bd = curr_bd->next;           num_bd--;         }//for       }//if num_bd     }//if p != NULL     else {       break;     }//else p== NULL   }//while 产生10个   last_bd->next = (volatile struct cpdma_rx_bd *)NULL; //buff des chain 构造完成   rxch->active_tail = last_bd; //rxch控制着整个rxch的接收方式   EMAC->RXHDP[0] = (u32_t)(rxch->active_head); //add - lp   return ERR_OK; } /** ** 使用该rx_inhandler处理接收中断 ** 每个pbuf链在处理之前必须要向前移ETH_PAD_SIZE个字节,以便4字节对齐 ** 当你还要产生pbuf的时候,也要向后移ETH_PAD_SIZE个字节,以便接收。 * @param netif the lwip network interface structure for this ethernetif * @return none */ void Emac_rxint_handler(struct netif *netif) {   struct rxch *rxch;   volatile struct cpdma_rx_bd *curr_bd, *processed_bd, *curr_tail, *last_bd;   volatile struct pbuf *pbuf, *q, *new_pbuf;   u32_t ex_len = 0, len_to_alloc = 0;   u16_t tot_len; //  sitaraif = netif->state;   rxch = &(emac_trif.rxch);   //得到当前的rxch buffer desc   curr_bd = rxch->active_head;   last_bd = rxch->active_tail;      //pbuf链中,SOP只出现一次,但是curr_bd已将buffer链推向下一个可能出现   //SOP的开头,所以这种方式更加严谨和有效。           while(curr_bd->flags_pktlen & CPDMA_BUF_DESC_SOP) {   //用while是因为pbuf链来处理的     ex_len = 0;     len_to_alloc = 0;     //当OWNER被EMAC清掉的时候,EMAC就放弃了buff desc,可以做一些处理     if((curr_bd->flags_pktlen & CPDMA_BUF_DESC_OWNER)        != CPDMA_BUF_DESC_OWNER) {       if(rxch->free_head == NULL) {         /* this bd chain will be freed after processing */         rxch->free_head = curr_bd;            }//if NULL                 //得到该接收到packet_len的长度       tot_len = (curr_bd->flags_pktlen) & 0xFFFF;       //保存当前接收的起始pbuf       q = curr_bd->pbuf;          //以下循环体为了更新除pbuf->payload除外,在结构体pbuf中          //的len,tot_len数据       do {                 //得到当前pbuf地址         pbuf = curr_bd->pbuf;                  /* If the earlier pbuf ended, update the chain */         if(pbuf->next == NULL) {           pbuf->next = (struct pbuf*)(curr_bd->next)->pbuf;         } //if Null                        //len_to_alloc , pbuf链中的len的总和         len_to_alloc += pbuf->len;         /* Update the len and tot_len fields for the pbuf in the chain*/         pbuf->len = (curr_bd->bufoff_len) & 0xFFFF; //当前pbuf长度         pbuf->tot_len = tot_len - ex_len ; //当前pbuf后的tot_len长度(含自己)         processed_bd = curr_bd; //处理中的desc         ex_len += pbuf->len;         curr_bd = curr_bd->next;       } while((processed_bd->flags_pktlen & CPDMA_BUF_DESC_EOP)               != CPDMA_BUF_DESC_EOP);       /**        * Close the chain for this pbuf. A full packet is received in        * this pbuf chain. Now this pbuf can be given to upper layers for        * processing. The start of the pbuf chain is now 'q'.       */       pbuf->next = (struct pbuf *)NULL;    //在q处理之前,需要加上ETH_PAD_SIZE个空间,以便4字节对齐 #if ETH_PAD_SIZE         if(q != NULL)         {             pbuf_header((struct pbuf *)q, ETH_PAD_SIZE); #endif //ETH_PAD_SIZE //为了节省中断的处理效率,这里节省时间,直接post msg给tcpip_thread                 if((netif->input((struct pbuf *)q,netif)) != ERR_OK)                 {                         pbuf_free((struct pbuf *)q);                         q = (volatile struct pbuf *)NULL;                 } #if ETH_PAD_SIZE         } //ETH_PAD_SIZE #endif //ETH_PAD_SIZE       /* Acknowledge that this packet is processed */ //      CPSWCPDMARxCPWrite(sitaraif->cpsw_cpdma_base, 0, (unsigned int)processed_bd);           EMAC->RXCP[0] = (u32_t)processed_bd;       rxch->active_head = curr_bd;           /**        * The earlier pbuf chain is freed from the upper layer. So, we need to        * allocate a new pbuf chain and update the descriptors with the pbuf info.        * To support chaining, the total length freed by the upper layer is tracked.        * Care should be taken even if the allocation fails.        */          /**        * now len_to_alloc will contain the length of the pbuf which was freed        * from the upper layer        */       rxch->freed_pbuf_len += len_to_alloc;       new_pbuf = pbuf_alloc(PBUF_RAW, ((rxch->freed_pbuf_len)+ETH_PAD_SIZE), PBUF_POOL);       /* Write the descriptors with the pbuf info till either of them expires */       if(new_pbuf != NULL) { #if ETH_PAD_SIZE                    pbuf_header((struct pbuf *)new_pbuf, -ETH_PAD_SIZE); #endif //ETH_PAD_SIZE         curr_bd = rxch->free_head; //free_head,已经被释放的head,需要重新set                 //以下循环体添加新的pbuf到curr_bd中去         for(q = new_pbuf; (q != NULL) && (curr_bd != rxch->active_head); q = q->next) {           curr_bd->bufptr = (u32_t)(q->payload);                     /* no support for buf_offset. RXBUFFEROFFEST register is 0 */           curr_bd->bufoff_len = (q->len) & 0xFFFF;           curr_bd->flags_pktlen = CPDMA_BUF_DESC_OWNER;                     rxch->freed_pbuf_len -= q->len;                     /* Save the pbuf */           curr_bd->pbuf = q;           last_bd = curr_bd;           curr_bd = curr_bd->next;         }//for                   /**          * At this point either pbuf expired or no rxbd to allocate. If          * there are no, enough rx bds to allocate all pbufs in the chain,          * free the rest of the pbuf          */         if(q != NULL) {           pbuf_free((struct pbuf *)q);         }                curr_tail = rxch->active_tail;         last_bd->next = (volatile struct cpdma_rx_bd *)NULL;                curr_tail->next = rxch->free_head;                  /**          * Check if the reception has ended. If the EOQ flag is set, the NULL          * Pointer is taken by the DMA engine. So we need to write the RX HDP          * with the next descriptor.          */         if(curr_tail->flags_pktlen & CPDMA_BUF_DESC_EOQ) { //          CPSWCPDMARxHdrDescPtrWrite(sitaraif->cpsw_cpdma_base, //                                   (u32_t)(rxch->free_head), 0);                         EMAC->RXHDP[0] = (u32_t)(rxch->free_head);         }//if EOQ         rxch->free_head  = curr_bd;         rxch->active_tail = last_bd;       }//if new_pbuf     }//if OWNER     curr_bd = rxch->active_head; //以下这句,L138未做要求. //    CPSWCPDMANumFreeBufSet(sitaraif->cpsw_cpdma_base, 0, 1); // -----------括号不要删-------------------------------   }//While .... //------------------------------------------- // 以下在外面写 //  CPSWCPDMAEndOfIntVectorWrite(sitaraif->cpsw_cpdma_base, CPSW_EOI_TX_PULSE);   //  CPSWCPDMAEndOfIntVectorWrite(sitaraif->cpsw_cpdma_base, CPSW_EOI_RX_PULSE);   } //--------------------------------------------------------------- //以下是发送部分 //--------------------------------------------------------------- /** ** 这个函数将pbuf链的数据发送给物理层,可能buffer_des连接多处,因为是 ** pbuf链连接而成的 * @return None **/ void Emac_transmit(struct pbuf *pbuf) {   struct pbuf *q;   struct txch *txch;   volatile struct cpdma_tx_bd *curr_bd, *active_head, *bd_end; // 取地址。   txch = &(emac_trif.txch); //得到可以使用的空闲head   curr_bd = txch->free_head;   //激活的head   active_head = curr_bd;   //更新该头的packet len 字段   curr_bd->flags_pktlen &= ~0xFFFF;   curr_bd->flags_pktlen |= pbuf->tot_len;   //交给EMAC之前,置位flags, SOP,OWNER   curr_bd->flags_pktlen |= (CPDMA_BUF_DESC_SOP | CPDMA_BUF_DESC_OWNER);   //把pbuf信息构建成buffer desc 链   for(q = pbuf; q != NULL; q = q->next) {     /* Intialize the buffer pointer and length */     curr_bd->bufptr = (u32_t)(q->payload);     curr_bd->bufoff_len = (q->len) & 0xFFFF;     bd_end = curr_bd;     curr_bd->pbuf = pbuf;     curr_bd = curr_bd->next;   }   //将buffer desc结尾   bd_end->next = (volatile struct cpdma_tx_bd *)NULL;   bd_end->flags_pktlen |= CPDMA_BUF_DESC_EOP;   //free_head指向下一个空的buff descriptor 处   txch->free_head = curr_bd;   //经过初始化之后,txch->active_tail指向NULL,但是发送buffer desc是一个   //单向的循环链表。所以这也是上面为什么bd_end->next要赋NULL值   if(txch->active_tail == NULL) { // 第一次发送active_head                 EMAC->TXHDP[0] = (u32_t)active_head;   }   /*   **第1次发送过后,假如发送完了,那么transmiter 将会halt,这样CPU在   **发送之前必须确认EOQ是否set,如果set,那么对于CPU来讲可以写HDP启动   **TXDMA发送了。   */   else {     curr_bd = txch->active_tail;     curr_bd->next = active_head;     if(curr_bd->flags_pktlen & CPDMA_BUF_DESC_EOQ) {      //假如EOQ被EMAC set之后,就启动tx DMA                 EMAC->TXHDP[0] = (u32_t)active_head;     }   }   txch->active_tail = bd_end; } /** * This function will send a packet through the emac if the channel is * available. Otherwise, the packet will be queued in a pbuf queue. * * @param netif the lwip network interface structure for this ethernetif * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) * @return ERR_OK if the packet could be sent *         an err_t value if the packet couldn't be sent * */ err_t OmapEmac_output(struct netif *netif, struct pbuf *p) {   INT8U os_err = 0;   SYS_ARCH_DECL_PROTECT(lev);   //等待有效的信号量才能发送 //  OSSemPend(TxCmpSem, 1000, &os_err); // --LP , 2012/04/28 DLT   /**    * This entire function must run within a "critical section" to preserve    * the integrity of the transmit pbuf queue.    *    */   SYS_ARCH_PROTECT(lev); //在选择发送之前,要调整p->payload的两字节,因为它们不能发送出去 #if ETH_PAD_SIZE   pbuf_header(p, -ETH_PAD_SIZE); #endif   /* adjust the packet length if less than minimum required */   if(p->tot_len < MIN_PKT_LEN) {      p->tot_len = MIN_PKT_LEN;      p->len = MIN_PKT_LEN;   }   /**    * Bump the reference count on the pbuf to prevent it from being    * freed till we are done with it.    *    */   pbuf_ref(p);       //Emac物理层的发送。DMA 用了TX中断的方式   Emac_transmit(p);   /* Return to prior interrupt state and return. */   SYS_ARCH_UNPROTECT(lev);      return ERR_OK; } /** ** lower level 已经启动DMA发送了吗,这里是为了软件清掉SOP和EOP,然后就是pbuf ** 链表的回收。 * @param netif the lwip network interface structure for this ethernetif * @return none */ void Emac_txint_handler(struct netif *netif) {   struct txch *txch;   volatile struct cpdma_tx_bd *curr_bd, *next_bd_to_process;      //取txch结构体的地址   txch = &(emac_trif.txch); //下一待处理的buff des, next_bd_to_process被初始化为(EMAC_RAM_BASE)      next_bd_to_process = txch->next_bd_to_process; // 用curr_bd来处理     curr_bd = next_bd_to_process;      /* Check for correct start of packet */   while((curr_bd->flags_pktlen) & CPDMA_BUF_DESC_SOP) {         /* Make sure that the transmission is over */     while((curr_bd->flags_pktlen & CPDMA_BUF_DESC_OWNER)           == CPDMA_BUF_DESC_OWNER);         /* Traverse till the end of packet is reached */     while(((curr_bd->flags_pktlen) & CPDMA_BUF_DESC_EOP) != CPDMA_BUF_DESC_EOP) {        curr_bd = curr_bd->next;     }//while(!EOP)     next_bd_to_process->flags_pktlen &= ~(CPDMA_BUF_DESC_SOP);     curr_bd->flags_pktlen &= ~(CPDMA_BUF_DESC_EOP);     /**      * If there are no more data transmitted, the next interrupt      * shall happen with the pbuf associated with the free_head      */     if(curr_bd->next == NULL) {       txch->next_bd_to_process = txch->free_head;     }        else {       txch->next_bd_to_process = curr_bd->next; //接着处理下一帧数据包     }         //写TXCP[],该帧数据包已经写完 //    CPSWCPDMATxCPWrite(sitaraif->cpsw_cpdma_base, 0, (u32_t)curr_bd);         EMAC->TXCP[0] = (u32_t)curr_bd;     pbuf_free((struct pbuf *)curr_bd->pbuf); //    LINK_STATS_INC(link.xmit);         next_bd_to_process = txch->next_bd_to_process;     curr_bd = next_bd_to_process;   }   //发送信号量给发送部分保证发送的完整性。 //        OSSemPost(TxCmpSem);  //--lp , 2012/04/28 delete,查看效果。 //在外面写的 //  CPSWCPDMAEndOfIntVectorWrite(sitaraif->cpsw_cpdma_base, CPSW_EOI_TX_PULSE); //  CPSWCPDMAEndOfIntVectorWrite(sitaraif->cpsw_cpdma_base, CPSW_EOI_RX_PULSE); } /********************* this file is end ****************************/ 代码其中之三: /************************************************************************** *                                                                         * *   PROJECT     : TMON (Transparent monitor)                              * *                                                                         * *   MODULE      : LWIP.c                                                  * *                                                                         * *   AUTHOR      : Michael Anburaj                                         * *                 URL  : http://geocities.com/michaelanburaj/             * *                 EMAIL: michaelanburaj@hotmail.com                       * *                                                                         * *   PROCESSOR   : Any                                                     * *                                                                         * *   Tool-chain  : gcc                                                     * *                                                                         * *   DESCRIPTION :                                                         * *   LwIP master source file.                                              * *                                                                         * **************************************************************************/ #include "tcpip.h" #include "ethernetif.h" #include "netconf.h" /* ********************************************************************* */ /* Global definitions */ netif_t     main_net; /* ********************************************************************* */ /* File local definitions */ /* ********************************************************************* */ /** *** 初始化LwIP的协议栈   */ void LwIP_Init( void ) {   struct ip_addr ipaddr;   struct ip_addr netmask;   struct ip_addr gw;          tcpip_init(NULL, NULL);    /** 在此处初始化IP地址 **/   IP4_ADDR(&ipaddr,192,168,1,88); //该宏需要执行的!   IP4_ADDR(&netmask,255,255,255,0);   IP4_ADDR(&gw,192,168,0,1);   MEMCPY(main_net.name,"glzn",4); #if LWIP_NETIF_HOSTNAME     main_net.hostname = GetHostName(); #endif   /* - netif_add(struct netif *netif, struct ip_addr *ipaddr,             struct ip_addr *netmask, struct ip_addr *gw,             void *state, err_t (* init)(struct netif *netif),             err_t (* input)(struct pbuf *p, struct netif *netif))        Adds your network interface to the netif_list. Allocate a struct   netif and pass a pointer to this structure as the first argument.   Give pointers to cleared ip_addr structures when using DHCP,   or fill them with sane numbers otherwise. The state pointer may be NULL.   The init function pointer must point to a initialization function for   your ethernet netif interface. The following code illustrates it's use.*/         netif_add(&main_net, &ipaddr, &netmask, &gw, NULL, ðernetif_init, &tcpip_input);   /*  Registers the default network interface.*/   netif_set_default(&main_net);  //可以删除 --2012/02/02, netif_default   /*  When the netif is fully configured this function must be called.*/    netif_set_up(&main_net); //this functional } /* ********************************************************************* */ 代码其中之四: //主程序 //修改成适应LwIP v140的协议,此为系统main主函数 #include #include #include "dspint.h" #include "sample.h" #include "edma.h" #include "norflash.h" #include "evmomapl138.h" #include "evmomapl138_gpio.h" #include "evmomapl138_uart.h" #include "evmomapl138_rtc.h" #include "io.h" #include "fpga_emifa.h" #include "test_fpga.h" //推荐的任务堆栈区大小为2048 OS_STK,即8192 byte #define COMMON_STACK_LEN 2048 //给各个任务分配的堆栈区 OS_STK  TaskLWIPStk[COMMON_STACK_LEN]; OS_STK        TaskAppMainStk[COMMON_STACK_LEN]; OS_STK        TaskMMIStk[COMMON_STACK_LEN]; OS_STK        TaskFpgaUPPStk[COMMON_STACK_LEN]; OS_STK        TaskFpgaEMIFAStk[COMMON_STACK_LEN * 32]; //OS_STK        TaskTestStk[COMMON_STACK_LEN]; //各个任务进程主函数 void TaskAppMain(void *pd); void TaskMMI(void *pd);//通过upp总线刷液晶数据,触发dsp中断,启动upp发送 extern void TaskLWIP(void *p_arg); //TaskLWIP任务 //extern void TaskTest(void *pd); int main() {         //初始化中断向量         OS_CPU_InitExceptVect();         //初始化uC/OS-II实时内核     OSInit();         //创建系统主进程任务(放在最高优先级,包括装置定值、参数自检测,并作为其他任务的WatchDog。)         OSTaskCreate(TaskAppMain, (void *)0, (OS_STK*)&TaskAppMainStk[COMMON_STACK_LEN-1], 2);     //启动操作系统内核         OSStart(); } //系统主进程任务 void TaskAppMain(void *pd) {         unsigned char ucErr;         tmr0_init();         GPIOInit();         chipint_init();         memset((unsigned char *)TaskLWIPStk, 0, (COMMON_STACK_LEN*sizeof(OS_STK))); //初始化由Lwip任务堆栈开辟的堆栈区域         //INT8U enledflag = /;         //INT32U counter = 0;         //创建任务         //OSTaskCreate(TaskFPGA_UPP, (void *)0, (OS_STK*)&TaskFpgaUPPStk[COMMON_STACK_LEN-1], 11); //        OSTaskCreate(TaskFPGA_EMIFA, (void *)0, (OS_STK*)&TaskFpgaEMIFAStk[COMMON_STACK_LEN-1], 12); //        OSTaskCreate(TaskMMI, (void *)0, (OS_STK*)&TaskMMIStk[COMMON_STACK_LEN-1], 13);         //OSTaskCreate(TaskTest, (void *)0, (OS_STK*)&TaskTestStk[COMMON_STACK_LEN-1],100);         OSTaskCreate(TaskLWIP,(void *)0,(OS_STK *)&TaskLWIPStk[COMMON_STACK_LEN -1],10);         while(1)         {                   /*asm(" nop");         counter++;                 if(counter >=20)                 {                    enledflag ^=0x01;            inb(ARM_DSP_CMD) = enledflag;                    DspintArmtrip(DSPINTTYPE_2);            counter = 0;                 }                 if(enledflag == 0)                 {                         ledchange();                 }*/ //                OSTimeDly(500); //                OSMboxPend(RxCntMbox,0,&ucErr);             OSTimeDly(1000);                 asm(" nop");         } } // #define  SHAREMMI_ADR    (0x80000200)     //共享液晶显示数据区地址 #define  MMI_LNUM        (240)            //液晶显示一屏数据的行数目 #define  MMI_LBYTE       (40)             //液晶显示一屏数据的行字节数目320/8 #define  MMI_DATALEN     (MMI_LNUM*MMI_LBYTE) //液晶显示缓冲区长度 #define  SHARERAW_ADR    (0x8002800)     //共享原始数据区地址 #define  SHAREMEA_ADR    (0x8001f000)     //共享测量结果区地址 //显存 #define LCD_XSIZE        (320)       // X方向像素 #define LCD_YSIZE        (240)       // Y方向像素 #define LCDMLEN ((LCD_XSIZE*LCD_YSIZE)/8) INT8U LcdMemory[LCDMLEN]; void loadMMIdata() {    INT8U *pobject;    INT16U i;    static INT8U showdata = 0;    static INT8U changeflag = 0;    changeflag++;    if(changeflag==6)    {                 changeflag=0;                 showdata++;    }    pobject =LcdMemory;//(INT8U*)SHAREMMI_ADR;    if(showdata == 0)    {                 for(i=0;i
    2. 关键我现在没有在linux下用,只在平常的PC机上用CCS,而且程序里面移植了Ucos代码,现在不知道从何下手了,网络部分初始化都是按照MDIO&EMAC文档上面操作的,其他的话,也不知道从何调试开始。

最近访客

< 1/1 >

统计信息

已有365人来访过

  • 芯积分:--
  • 好友:--
  • 主题:3
  • 回复:2

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言