demonguy demonguy - 2 months ago 11
Linux Question

uboot tftpboot always timeout (using DM9000A NIC)

I use uboot and add tftpboot command into it.But it doesn't work well, though it can transfer data, there are always some timeout during the whole transmission. Console shows like this

My ethernet topology is : board with uboot connect to my router, and my PC connect to router .and my tftp server is on my VM linux of my PC, and the VM is using bridge mode to connect to ethernet

Of course , i tried to connect my board directly to PC, but the problem stood still

I've modified the dm9000x.c line 433, change

tmo = get_timer(0) + 5 * CONFIG_SYS_HZ; //


into

tmo = get_timer(0) + 200; //timeout 200 miliiseconds


The translation time is now endurable. But it still many transmission timeout, the logs show below

dm9000 i/o: 0x88000000, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 1a:2a:3a:4a:5a:6a
operating at 100M full duplex mode
Using dm9000 device
TFTP from server 192.168.0.15; our IP address is 192.168.0.12
Filename '/linux-3.14.24/fs/yaffs2/ubifs.img'.
Load address: 0x20000000
Loading: ################################################################transmission timeout
#
####transmission timeout
#############################################################
####################transmission timeout
##########transmission timeout
################transmission timeout
##################transmission timeout
#
#################################################################
#################################################################
#############################################################transmission timeout
####
#####################transmission timeout
######################transmission timeout
######################
#################################################################
###############################################################transmission timeout
##
##################################transmission timeout
#######transmission timeout
########################
#################################################################
#################################################################
#################################################################
###################transmission timeout
###################
61.5 KiB/s
done
Bytes transferred = 4515840 (44e800 hex)
4515840 bytes written to volume rootfs


I still don't know why, because it can actually transfer data. So is there any idea about this?

Answer

I've check my u-boot dm9000 driver and found this

static int dm9000_send(struct eth_device *netdev, void *packet, int length)
{
    int tmo;
    struct board_info *db = &dm9000_info;

    DM9000_DMP_PACKET(__func__ , packet, length);

    DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */

    /* Move data to DM9000 TX RAM */
    DM9000_outb(DM9000_MWCMD, DM9000_IO); /* Prepare for TX-data */

    /* push the data to the TX-fifo */
    (db->outblk)(packet, length);

    /* Set TX length to DM9000 */
    DM9000_iow(DM9000_TXPLL, length & 0xff);
    DM9000_iow(DM9000_TXPLH, (length >> 8) & 0xff);

    /* Issue TX polling command */
    DM9000_iow(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */

    /* wait for end of transmission */
    tmo = get_timer(0) + 10 * CONFIG_SYS_HZ;
    while ( !(DM9000_ior(DM9000_NSR) & (NSR_TX1END | NSR_TX2END)) ||
        !(DM9000_ior(DM9000_ISR) & IMR_PTM) ) {
        if (get_timer(0) >= tmo) {
            printf("NSR is 0x%x, ISR is 0x%x\n",DM9000_ior(DM9000_NSR),DM9000_ior(DM9000_ISR)); // this line is for debug use
            printf("transmission timeout\n");
            break;
        }
    }

    DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */

    DM9000_DBG("transmit done\n\n");
    return 0;
}

When timeout occured,

printf("NSR is 0x%x, ISR is 0x%x\n",DM9000_ior(DM9000_NSR),DM9000_ior(DM9000_ISR)); // this line is for debug use

this line shows that DM9000_ISR's second bit will never set to 1. I don't know why so i changed the codes like this

static int dm9000_send(struct eth_device *netdev, void *packet, int length)
{
    int tmo;
    struct board_info *db = &dm9000_info;

    DM9000_DMP_PACKET(__func__ , packet, length);

    DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */

    /* Move data to DM9000 TX RAM */
    DM9000_outb(DM9000_MWCMD, DM9000_IO); /* Prepare for TX-data */

    /* push the data to the TX-fifo */
    (db->outblk)(packet, length);

    /* Set TX length to DM9000 */
    DM9000_iow(DM9000_TXPLL, length & 0xff);
    DM9000_iow(DM9000_TXPLH, (length >> 8) & 0xff);

    /* Issue TX polling command */
    DM9000_iow(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */

    /* wait for end of transmission */
    tmo = get_timer(0) + 10 * CONFIG_SYS_HZ;

    while (DM9000_ior(DM9000_TCR) &TCR_TXREQ) {
        if (get_timer(0) >= tmo) {
            printf("transmission timeout\n");
            break;
        }
    }

    DM9000_iow(DM9000_ISR, IMR_PTM); /* Clear Tx bit in ISR */

    DM9000_DBG("transmit done\n\n");
    return 0;
}

Now ,everthing is OK. But i'm still confused about why DM9000_ISR's second bit goes wrong. Is it a DM9000 hardware BUG?

Comments