August 08, 2022, 04:44:13 pm

Ethernet on the LPC-P2378

Started by gimme_bottles, August 27, 2013, 02:50:31 am

Previous topic - Next topic

gimme_bottles

August 27, 2013, 02:50:31 am Last Edit: August 27, 2013, 02:55:40 am by gimme_bottles
Hey,

I am trying to get Ethernet working on my  LPC-P2378. My problem is that it seems that I get no link. I've hooked up my board directly to my laptop.

My code to initialize the KS8721 (see below) hangs when it reaches the auto negotation. The "auto negotation complete"-bit in the KS8721 won't get set.

To anyone with the same board: If you flash the board with a program that doesn't touch the KS8721 at all and you plug in an ethernet cable connected to a PC, will the link-led light up? Because mine doesn't. I've used other PHYs before, and they all indicate a link even when they were not configured yet.

Another thing: If I instruct the KS8721 to use the "force link"-feature before trying to auto negotate, the initialisation completes successfully and I am able to send packets, but I can't receive any (or they don't pass the LPC2378's MAC).


Thanks for your help in advance  ;)


My code (I use arm-elf-gcc):

int emac_init(uint8_t * mac_addr)
{
    // for counting timeouts
    volatile uint32_t tmp;
    //char buf[100];
    uint16_t reg;
    // send power to MAC module
    PCONP |= BIT(30);

    // reset pins to default function
    PINSEL2 &= ~0xF03F330F; // reset P1[0,1,4,6,8,9,10,14,15]
    PINSEL3 &= ~0x0000000F; // reset P1[16,17]

  // acording to LPC2366 errata, this fixes setting RMII with old devices
  if(MAC_MODULEID == OLD_EMAC_MODULE_ID)
    PINSEL2 |= 0x50151105; // configure P1[0,1,4,6,8,9,10,14,15]
  else
    PINSEL2 |= 0x50150105; // configure P1[0,1,4,8,9,10,14,15]

    PINSEL3 |= 0x00000005; // configure P1[16,17]

    // reset everything (which can be reset :))
    MAC_MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX |
               MAC1_SIM_RES | MAC1_SOFT_RES;
    MAC_COMMAND = CR_REG_RES | CR_TX_RES | CR_RX_RES;

    // sleep a shot time after reset
    for(tmp = 100; tmp; tmp--);

    // set mac registers
    MAC_MAC1 = MAC1_PASS_ALL;
    MAC_MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;
    MAC_MAXF = ETH_MAX_FLEN;
    MAC_CLRT = CLRT_DEF;
    MAC_IPGR = IPGR_DEF;

    // mac address configuration
    MAC_SA0 = (mac_addr[1] << 8) | mac_addr[0];
    MAC_SA1 = (mac_addr[3] << 8) | mac_addr[2];
    MAC_SA2 = (mac_addr[5] << 8) | mac_addr[4];

    // reset and configure MII management
    MAC_MCFG = MCFG_CLK_DIV20 | MCFG_RES_MII;
    for(tmp = 100; tmp; tmp--);
    MAC_MCFG = MCFG_CLK_DIV20;

    // enables RMII, disables filtering and allows runt frames to pass
    MAC_COMMAND = CR_RMII | CR_PASS_RUNT_FRM | CR_PASS_RX_FILT;

    // set 100Mbit
    MAC_SUPP = BIT(8);
    for(tmp = 100; tmp; tmp--);

    // -- PHY configuration --

    // reset PHY
    emac_write_phy(KS8721_ADDR, PHY_REG_BMCR, BIT(15));
    for(tmp = 10000; tmp; tmp--);

    // wait for reset to finish
    for(tmp = 0x100000; tmp; tmp--) {
        reg = emac_read_phy(KS8721_ADDR, PHY_REG_BMCR);
        if(!(reg & BIT(15)))
            break;
    }
    if(!tmp)
        return EMAC_ERR_PHYNA;

    emac_write_phy(KS8721_ADDR, PHY_REG_BMCR, BIT(12));  //Enable auto negotation


    // read our PHY id and check it
    uint16_t id1 = emac_read_phy(KS8721_ADDR, PHY_REG_IDR1);
    uint16_t id2 = emac_read_phy(KS8721_ADDR, PHY_REG_IDR2);
    if((id1 << 16 | id2) != KS8721_ID)
        return EMAC_ERR_PHYINV;

    emac_write_phy(KS8721_ADDR, PHY_REG_ANAR, (0x01 | BIT(5) | BIT(6) | BIT(7) | BIT(8))); //Advertize connection modes


    // use auto negotation TODO: use config instead of hardcode
    emac_write_phy(KS8721_ADDR, PHY_REG_BMCR, BIT(9));
    for(tmp = 0x200; tmp; tmp--);
    for(tmp = 0x200000; tmp; tmp--) {
        reg = emac_read_phy(KS8721_ADDR, PHY_REG_BMSR);
        if (reg & BIT(5))
            break;
    }
    if(!tmp)
        return EMAC_ERR_AUTONEG;


    // get the link status
    uint16_t link = 0;
    for(tmp = 0x100000; tmp; tmp--) {
        link = emac_read_phy(KS8721_ADDR, PHY_REG_BMSR);
        if (link & 0x4)
            break;
    }
    if(!tmp)
        return EMAC_ERR_LINK;

    // full duplex?
    if(link & (BIT(12) | BIT(14))) {
        MAC_MAC2 |= MAC2_FULL_DUP;
        MAC_COMMAND |= CR_FULL_DUP;
        MAC_IPGT = IPGT_FULL_DUP;
    } else
        MAC_IPGT = IPGT_HALF_DUP;

    if(link & BIT(1))
        MAC_SUPP = 0;
    else // TODO: do we need this?
        MAC_SUPP = BIT(8);

    // init descriptors
    emac_init_rx();
    emac_init_tx();

    // accept broadcasts and our packets
    MAC_RXFILTERCTRL = RFC_BCAST_EN | RFC_PERFECT_EN;

    // enable rx and tx function
    MAC_COMMAND |= (CR_RX_EN | CR_TX_EN);
    MAC_MAC1 |= MAC1_REC_EN;

    return 0;
}

gimme_bottles

Quote from: gimme_bottles on August 27, 2013, 02:50:31 am
To anyone with the same board: If you flash the board with a program that doesn't touch the KS8721 at all and you plug in an ethernet cable connected to a PC, will the link-led light up? Because mine doesn't. I've used other PHYs before, and they all indicate a link even when they were not configured yet.


can someone (maybe from olimex themself) answer on this? because i have no other way to tell if my ks8721 is broken or not...

LubOlimex

September 04, 2013, 02:29:30 pm #2 Last Edit: September 04, 2013, 02:49:12 pm by LubOlimex
Hello gimme_bottles,

It is unlikely that the Ethernet controller is broken. We test all board on hardware and software level. The test of LPC-2378 includes a small web-server test. If you haven't programmed the board you might perform the test out-of-the-box yourself. If you have already please download this binary file and program the board: https://docs.google.com/file/d/0B7WHuNCASY8cZHl3eW5aTk8ydlk/edit?usp=sharing.

To perform the test you will need RS232 cable. Plug it to RS232_0 and open jumpers ISP_E and RST_E. Plug the Ethernet cable. Open your favorite terminal program on the RS232 port. Power the board. The Ethernet connector LEDs should turn on (the PWR LED should stay on and the STAT LED should blink) and you should receive a test menu on the screen. Press "L" to test the Ethernet and open an Internet Browser. Visit 192.168.0.100 (ensure your network/router/switch settings doesn't block anything) and you will see small web page. You can click the links to ensure it works. The image below shows what you should expect:

http://i.imgur.com/bJnaze4.png

It is ok if some of the other tests fail since we use additional hardware for performing some of the tests.

Best regards,
Lub/OLIMEX
Technical support and documentation manager at Olimex

gimme_bottles

Thank you for the reply.

I flashed the test program, but no success  :(

After I press 'L', the green LED at the ethernet connector lights up, but the yellow one does not.
dmesg shows me the following error over and over, so I assume something is wrong with getting a link between the board and my laptop. I also tried hooking both up to a router, but with the same results.


[ 2268.190106] atl1c 0000:06:00.0: atl1c: eth21 NIC Link is Up<100 Mbps Half Duplex>
[ 2268.515697] atl1c 0000:06:00.0: atl1c: eth21 NIC Link is Down
[ 2275.053292] IPv6: ADDRCONF(NETDEV_UP): eth21: link is not ready