搜索
bottom↓
回复: 2

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

[复制链接]

出70入0汤圆

发表于 2014-7-22 15:16:38 | 显示全部楼层 |阅读模式
本帖最后由 绿茶山人 于 2014-7-22 19:23 编辑

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

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

  34.         if (Rx_Byte != DM9000A_PKT_RDY)
  35.                 return 0; /* No packet received, ignore */
  36.        
  37.         /* A packet ready now  & Get status/length */       
  38.         IOWR(DM9000A_CMD_ADDR_1, DM9000A_MRCMD);        // 将 memory write cmd 写入 addr 上
  39.         Rx_Byte          = IORD(DM9000A_DAT_ADDR_1);
  40.         Rx_Status = IORD(DM9000A_DAT_ADDR_1) + (IORD(DM9000A_DAT_ADDR_1) << 8);
  41. //        Rx_Len    = IORD(DM9000A_DAT_ADDR_1) + (IORD(DM9000A_DAT_ADDR_1) << 8);
  42.         Rx_Len    = IORD(DM9000A_DAT_ADDR_1);
  43.         Rx_Len    |= (uu16)(IORD(DM9000A_DAT_ADDR_1) << 8);
  44.        

  45.         data_ptr = (uu8 *)eth_head;
  46.         for (i = 0; i < sizeof(ETH_HEADER); i++) {       
  47.                 *data_ptr++ = IORD(DM9000A_DAT_ADDR_1);
  48.         }
  49.         /* Move data from DM9000 Read received packet from RX SRAM */       
  50.         data_ptr = (uu8 *)pdata_buf;
  51.         for (i = 14; i < Rx_Len; i++) {
  52.                 *data_ptr++ = IORD(DM9000A_DAT_ADDR_1);
  53.         }

  54.         dm9000a_iow(DM9000A_ISR, 0x01);  /* clear PR status latched in bit 0 */
  55.         dm9000a_iow(DM9000A_IMR, 0x81); // 重新开启网卡中断接收
  56.         return Rx_Len;
  57. }
复制代码

  1. //==============================================================================================
  2. // 网卡初始化
  3. static void dm9000a_init(void)
  4. {
  5.         uu8   i = 0;
  6.         uu8   IO_Mode = 0;                // IO 口 模式 8/16bit
  7.         uu32  dm9000a_ID = 0;                // 低 16 位: vendor ID  高 16 位: product ID
  8.         uu32  dm9000aphy_ID = 0;
  9.         u8    link;
  10.         u8    speed;
  11.         u8    duplex;
  12.        
  13.         gio_clr(DM9000A_RST_ADDR_1);
  14.         delay_ms(5);
  15.         gio_set(DM9000A_RST_ADDR_1);
  16.         delay_ms(5);
  17.        
  18.         dm9000a_iow(DM9000A_GPR, 0);                 // 激活内部PHY
  19.         delay_ms(20);                                // 延时
  20.        
  21.        
  22.         dm9000a_iow(DM9000A_NCR, 0x03);                // 软复位第一次,mac lookback on
  23.         delay_ms(20);
  24.         dm9000aphy_iow(DM9000APHY_BMCR, 0x8000);//PHY复位
  25.         i = 0;  
  26.         do {
  27.                 delay_ms (1);
  28.         } while ( (i++ < 200) && !( dm9000a_ior(DM9000A_NSR) & 0x40) );
  29.        
  30.         dm9000aphy_iow(DM9000APHY_ANAR, 0x01E1 | 0x0400);  /* operating PHY media mode with H/W Flow-control */
  31.         dm9000aphy_iow(DM9000APHY_BMCR, 0x1200); //PHY复位
  32.        
  33.         i = 0;  
  34.         do {
  35.                 delay_ms (1);
  36.         } while ( (i++ < 200) && !( dm9000a_ior(DM9000A_NSR) & 0x40) );
  37.         delay_ms (5);
  38.        
  39.         /* set other registers depending on applications */
  40.         dm9000a_iow(DM9000A_IMR, 0x80);                /* IMR enable only Pointer Auto Return for RX/TX FIFO SRAM */
  41.         dm9000a_iow(DM9000A_BPTR, 0x3f);        /* BPTR REG.08(if necessary) High Water Overflow 3KB, 600us */
  42.         dm9000a_iow(DM9000A_FCTR, 0x5A);        /* FCTR REG.09 (if necessary) High/ Low Threshold 5KB/ 10KB */       
  43.         dm9000a_iow(DM9000A_RXTXFCR, 0x29);        /* FCR REG.0AH enable TXPEN, BKPM (for TX_half), FLCE (RX) */
  44.        
  45.         //dm9000a_addrset(ether_addrress);        ////设置MAC地址
  46.         for (i = 0; i < 6; i++) {
  47.                 dm9000a_iow(DM9000A_PAR + i, ether_addrress[i]);
  48.         }
  49.         dm9000a_addrfilterset((uu8 *)&multimac_mcastFilter[0]);        // 设置组播模式
  50.        
  51.         dm9000a_iow(DM9000A_NCR, 0);                /* enable chip functions and disable loopback back to normal*/
  52.        
  53.          /* clear any pending interrupt */
  54.         dm9000a_iow(DM9000A_NSR, 0x2c);                /* clear NSR 3bits status: TX1END, TX2END, WAKEST by RW/C1 */
  55.         dm9000a_iow(DM9000A_ISR, 0x3F);                /* clear ISR status: PR,PT, ROS,ROO, UDRUN, LNKCHG by RW/C1 */
  56.        
  57.         /* enable interrupts ~go */
  58.         dm9000a_iow(DM9000A_IMR, 0x81);                 /* IMR REG. FFH enable PAR+ PTI+PRI+ROI+ROOI+UDRUNI+LNKCHGI */
  59.        
  60.         /* enable RX Broadcast/ ALL MULTICAST to activate DM9000A ~go */
  61.         dm9000a_iow(DM9000A_RXCR, 0x31);
  62.        
  63.         /* initialize the driver variables or the user passed arguments */
  64.         IO_Mode = dm9000a_ior(DM9000A_ISR);        //最高位 1: 8bit  0: 16bit
  65.        
  66.         dm9000a_ID = dm9000a_Info();                //
  67. //         printf("DM9000A-1 Vendor ID and Product ID: %x", dm9000a_vendor_ID);
  68.         dm9000aphy_ID = dm9000aphy_Info();
  69. //         printf("DM9000A-1 PHY ID Identifier: %x", dm9000aphy_ID)
  70.         link  = (dm9000a_ior(DM9000A_NSR) & 0x40) ? 1 : 0;         // bit.6 = 1: link ok
  71.         speed = (dm9000a_ior(DM9000A_NSR) & 0x80) ? 10 : 100;          // bit.7 = 0: 100Mbps
  72.         duplex = (dm9000a_ior(DM9000A_NCR) & 0x8) ? 1 : 0;          // bit.3 = 1: Full Duplex mode
  73.         delay_ms(1);
  74. }
复制代码


发送函数没有问题, 也一并贴了吧. 大家一起学习.
  1. //==============================================================================================
  2. // 描述: DM9000 底层发送函数
  3. uu8 dm9000a_1_ptran(uu8 *head, uu16 buflen, uu8 *pbuf)
  4. {
  5.         uu32  i;
  6.         uu16  tx_len;
  7.         uu8 * data_ptr;
  8.        
  9. //        P3 = 0x00;        // 测试发送时间,大约 5ms/1500 字节
  10.        
  11. //        dm9000a_iow(DM9000A_ISR, 0x02); /* Clear Tx bit in ISR */
  12.         dm9000a_iow(DM9000A_IMR, 0x80); // 关闭网卡中断
  13.         /* Move data to DM9000 TX RAM */
  14.         IOWR(DM9000A_CMD_ADDR_1, DM9000A_MWCMD); /* Prepare for TX-data */
  15.        
  16.         data_ptr = (uu8 *)head;
  17.         for (i = 0; i < sizeof(ETH_HEADER); i++) {
  18.                 IOWR(DM9000A_DAT_ADDR_1, *data_ptr++);
  19.         }
  20.        
  21.         data_ptr = (uu8 *)pbuf;
  22.         for (i = 0; i < buflen; i++) {
  23.                 IOWR(DM9000A_DAT_ADDR_1, *data_ptr++);
  24.         }
  25.        
  26.         tx_len = buflen + 14;
  27.         dm9000a_iow(DM9000A_TXPLL, (tx_len) & 0xff);
  28.         dm9000a_iow(DM9000A_TXPLH, tx_len >> 8);
  29.         dm9000a_iow(DM9000A_TXCR, 1 | DM9000A_TXCR_INIT_VAL);
  30.         while((dm9000a_ior(DM9000A_NSR) & 0x0c) == 0);
  31.         dm9000a_iow(DM9000A_NSR, 0x2c);
  32.         dm9000a_iow(DM9000A_IMR, 0x81); // 重新开启网卡中断接收
  33.        
  34. //        P3 = 0xFF;        // 测试发送时间
  35.        
  36.         return 0;
  37. }
复制代码

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

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

出70入0汤圆

 楼主| 发表于 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) .
搞不明白了.我晕.
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 12:23

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表