绿茶山人 发表于 2014-7-22 15:16:38

DM9000网卡芯片 8bit 模式时接收数据长度错误.

本帖最后由 绿茶山人 于 2014-7-22 19:23 编辑

项目需要用 51 来连接 DM9000. 所以用的是 8bit 模式.
但是写好了驱动程序, 发现发送没有问题, 接收的数据长度, 读上来的 length 一直是 96(60h) 字节. 偶尔出现 114(72h) 字节的情况,
看了下程序没有发现问题, 难道 DM9000 8bit 模式有 bug??? 或者是有假货?
谢谢大侠指点.

// DM9000 底层接收函数
uu16 dm9000a_1_prcv(uu8 *eth_head, uu8 *pdata_buf)
{
        uu16i;
        uu8   Rx_Byte;
        uu16   Rx_Status;
        uu16Rx_Len = 0;
        uu8 * data_ptr;
       
       /* Rx-ISR bit must be set. */
        if (!(dm9000a_ior(DM9000A_ISR) & 0x01)) {
                return 0;
        }
//        dm9000a_iow(DM9000A_ISR, 0x01);/* clear PR status latched in bit 0 */
        dm9000a_iow(DM9000A_IMR, 0x80); // 关闭网卡中断
        /*****************************************************************************************
        * DM9000从网络中接到一个数据包后,会在数据包前面加上 4 个字节,分别为 “01H”、
        * “status”(同RSR寄存器的值)、“LENL”(数据包长度低 8 位)、“LENH”(数据包长度高 8 位)。
        * 所以首先要读取这 4 个字节来确定数据包的状态,第一个字节 “01H” 表示接下来的是有效数据包,
        * 若为“00H”则表示没有数据包,若为其它值则表示网卡没有正确初始化,需要从新初始化。
        * 如果接收到的数据包长度小于 60 字节,则 DM9000 会自动为不足的字节补上 0,使其达到 60 字节。
        * 同时,在接收到的数据包后 DM9000 还会自动添加 4 个 CRC 校验字节。可以不予处理。
        * 于是,接收到的数据包的最小长度也会是 64 字节。
        ******************************************************************************************/
        /* Get most updated data, only look at bits 0:1, See application notes DM9000 */
        dm9000a_ior(DM9000A_MRCMDX); // 第一次读取一般都是 0x00
        Rx_Byte = IORD(DM9000A_DAT_ADDR_1) & 0x03;        // 第二次总能读到数据
        /* Status check: this byte must be 0 or 1 */
        if(Rx_Byte > DM9000A_PKT_RDY) {
                dm9000a_iow(DM9000A_RXCR, 0x00); /* Stop Device */
                dm9000a_iow(DM9000A_ISR, 0x80);/* Stop INT request */
                return 0;
        }

        if (Rx_Byte != DM9000A_PKT_RDY)
                return 0; /* No packet received, ignore */
       
        /* A packet ready now& Get status/length */       
        IOWR(DM9000A_CMD_ADDR_1, DM9000A_MRCMD);        // 将 memory write cmd 写入 addr 上
        Rx_Byte          = IORD(DM9000A_DAT_ADDR_1);
        Rx_Status = IORD(DM9000A_DAT_ADDR_1) + (IORD(DM9000A_DAT_ADDR_1) << 8);
//        Rx_Len    = IORD(DM9000A_DAT_ADDR_1) + (IORD(DM9000A_DAT_ADDR_1) << 8);
        Rx_Len    = IORD(DM9000A_DAT_ADDR_1);
        Rx_Len    |= (uu16)(IORD(DM9000A_DAT_ADDR_1) << 8);
       

        data_ptr = (uu8 *)eth_head;
        for (i = 0; i < sizeof(ETH_HEADER); i++) {       
                *data_ptr++ = IORD(DM9000A_DAT_ADDR_1);
        }
        /* Move data from DM9000 Read received packet from RX SRAM */       
        data_ptr = (uu8 *)pdata_buf;
        for (i = 14; i < Rx_Len; i++) {
                *data_ptr++ = IORD(DM9000A_DAT_ADDR_1);
        }

        dm9000a_iow(DM9000A_ISR, 0x01);/* clear PR status latched in bit 0 */
        dm9000a_iow(DM9000A_IMR, 0x81); // 重新开启网卡中断接收
        return Rx_Len;
}

//==============================================================================================
// 网卡初始化
static void dm9000a_init(void)
{
        uu8   i = 0;
        uu8   IO_Mode = 0;                // IO 口 模式 8/16bit
        uu32dm9000a_ID = 0;                // 低 16 位: vendor ID高 16 位: product ID
        uu32dm9000aphy_ID = 0;
        u8    link;
        u8    speed;
        u8    duplex;
       
        gio_clr(DM9000A_RST_ADDR_1);
        delay_ms(5);
        gio_set(DM9000A_RST_ADDR_1);
        delay_ms(5);
       
        dm9000a_iow(DM9000A_GPR, 0);                 // 激活内部PHY
        delay_ms(20);                                // 延时
       
       
        dm9000a_iow(DM9000A_NCR, 0x03);                // 软复位第一次,mac lookback on
        delay_ms(20);
        dm9000aphy_iow(DM9000APHY_BMCR, 0x8000);//PHY复位
        i = 0;
        do {
                delay_ms (1);
        } while ( (i++ < 200) && !( dm9000a_ior(DM9000A_NSR) & 0x40) );
       
        dm9000aphy_iow(DM9000APHY_ANAR, 0x01E1 | 0x0400);/* operating PHY media mode with H/W Flow-control */
        dm9000aphy_iow(DM9000APHY_BMCR, 0x1200); //PHY复位
       
        i = 0;
        do {
                delay_ms (1);
        } while ( (i++ < 200) && !( dm9000a_ior(DM9000A_NSR) & 0x40) );
        delay_ms (5);
       
        /* set other registers depending on applications */
        dm9000a_iow(DM9000A_IMR, 0x80);                /* IMR enable only Pointer Auto Return for RX/TX FIFO SRAM */
        dm9000a_iow(DM9000A_BPTR, 0x3f);        /* BPTR REG.08(if necessary) High Water Overflow 3KB, 600us */
        dm9000a_iow(DM9000A_FCTR, 0x5A);        /* FCTR REG.09 (if necessary) High/ Low Threshold 5KB/ 10KB */       
        dm9000a_iow(DM9000A_RXTXFCR, 0x29);        /* FCR REG.0AH enable TXPEN, BKPM (for TX_half), FLCE (RX) */
       
        //dm9000a_addrset(ether_addrress);        ////设置MAC地址
        for (i = 0; i < 6; i++) {
                dm9000a_iow(DM9000A_PAR + i, ether_addrress);
        }
        dm9000a_addrfilterset((uu8 *)&multimac_mcastFilter);        // 设置组播模式
       
        dm9000a_iow(DM9000A_NCR, 0);                /* enable chip functions and disable loopback back to normal*/
       
       /* clear any pending interrupt */
        dm9000a_iow(DM9000A_NSR, 0x2c);                /* clear NSR 3bits status: TX1END, TX2END, WAKEST by RW/C1 */
        dm9000a_iow(DM9000A_ISR, 0x3F);                /* clear ISR status: PR,PT, ROS,ROO, UDRUN, LNKCHG by RW/C1 */
       
        /* enable interrupts ~go */
        dm9000a_iow(DM9000A_IMR, 0x81);               /* IMR REG. FFH enable PAR+ PTI+PRI+ROI+ROOI+UDRUNI+LNKCHGI */
       
        /* enable RX Broadcast/ ALL MULTICAST to activate DM9000A ~go */
        dm9000a_iow(DM9000A_RXCR, 0x31);
       
        /* initialize the driver variables or the user passed arguments */
        IO_Mode = dm9000a_ior(DM9000A_ISR);        //最高位 1: 8bit0: 16bit
       
        dm9000a_ID = dm9000a_Info();                //
//         printf("DM9000A-1 Vendor ID and Product ID: %x", dm9000a_vendor_ID);
        dm9000aphy_ID = dm9000aphy_Info();
//         printf("DM9000A-1 PHY ID Identifier: %x", dm9000aphy_ID)
        link= (dm9000a_ior(DM9000A_NSR) & 0x40) ? 1 : 0;       // bit.6 = 1: link ok
        speed = (dm9000a_ior(DM9000A_NSR) & 0x80) ? 10 : 100;        // bit.7 = 0: 100Mbps
        duplex = (dm9000a_ior(DM9000A_NCR) & 0x8) ? 1 : 0;        // bit.3 = 1: Full Duplex mode
        delay_ms(1);
}

发送函数没有问题, 也一并贴了吧. 大家一起学习.
//==============================================================================================
// 描述: DM9000 底层发送函数
uu8 dm9000a_1_ptran(uu8 *head, uu16 buflen, uu8 *pbuf)
{
        uu32i;
        uu16tx_len;
        uu8 * data_ptr;
       
//        P3 = 0x00;        // 测试发送时间,大约 5ms/1500 字节
       
//        dm9000a_iow(DM9000A_ISR, 0x02); /* Clear Tx bit in ISR */
        dm9000a_iow(DM9000A_IMR, 0x80); // 关闭网卡中断
        /* Move data to DM9000 TX RAM */
        IOWR(DM9000A_CMD_ADDR_1, DM9000A_MWCMD); /* Prepare for TX-data */
       
        data_ptr = (uu8 *)head;
        for (i = 0; i < sizeof(ETH_HEADER); i++) {
                IOWR(DM9000A_DAT_ADDR_1, *data_ptr++);
        }
       
        data_ptr = (uu8 *)pbuf;
        for (i = 0; i < buflen; i++) {
                IOWR(DM9000A_DAT_ADDR_1, *data_ptr++);
        }
       
        tx_len = buflen + 14;
        dm9000a_iow(DM9000A_TXPLL, (tx_len) & 0xff);
        dm9000a_iow(DM9000A_TXPLH, tx_len >> 8);
        dm9000a_iow(DM9000A_TXCR, 1 | DM9000A_TXCR_INIT_VAL);
        while((dm9000a_ior(DM9000A_NSR) & 0x0c) == 0);
        dm9000a_iow(DM9000A_NSR, 0x2c);
        dm9000a_iow(DM9000A_IMR, 0x81); // 重新开启网卡中断接收
       
//        P3 = 0xFF;        // 测试发送时间
       
        return 0;
}

javenreal 发表于 2014-7-22 16:47:25

64应该是很正常的,如果我没记错,DM9000如果收到小于64字节的数据包,会自动填充到64字节。

绿茶山人 发表于 2014-7-22 19:21:10

javenreal 发表于 2014-7-22 16:47
64应该是很正常的,如果我没记错,DM9000如果收到小于64字节的数据包,会自动填充到64字节。 ...

关键是, ping 的时候指定了 50/100/300/500 字节后, 长度还是 96(60H, 题目描述错误了, 不好意思), 偶尔出现 114 (72H) .
搞不明白了.我晕.
页: [1]
查看完整版本: DM9000网卡芯片 8bit 模式时接收数据长度错误.