DM9006 在Lwip 下带FreeRTOS驱动
最近调试了DM9006的驱动,发现网上参考的代码较少,在F4平台上费了很久时间总是调试通了,这里贴上适合FreeRTOS加lwip的代码,为后来人提供方便,这个芯片是接FSMC几口驱动的,我也是用FSMC驱动的,当然可以特定拿出单片机的16个IO口出来,当作数据传输线进行驱动。
bsp_dm9006.c
1 #include "bsp_dm9006.h" 2 3 #include "systick.h" 4 #include "global.h" 5 #include "netconf.h" 6 7 #include "FreeRTOS.h" 8 #include "task.h" 9 10 #ifdef UIP 11 12 /* DM9006A 接收函数设置宏 */ 13 //#define Rx_Int_enable 14 #define Max_Int_Count 1 15 #define Max_Broadcast_Lenth 500 16 #define Broadcast_Jump 17 18 /* DM9006A 传送函数设置宏 */ 19 #define Max_Send_Pack 2 20 #define Fix_Note_Address 21 22 #endif 23 24 /********************************************************************************************************** 25 * 全局变量参数细分 26 **********************************************************************************************************/ 27 28 uint8_t SendPackOk = 0; 29 uint8_t s_FSMC_Init_Ok = 0; // 用于指示FSMC是否初始化 30 31 /* 32 * 函数名: dm9k_udelay 33 * 参 数: time : 延迟时间,不精确,us级别 34 * 返 回: 无 35 * 功 能: 延迟函数 36 */ 37 void dm9k_udelay(uint16_t time) 38 { 39 CPU_TS_Tmr_Delay_US(time); 40 } 41 42 /* 43 * 函数名: ior 44 * 参 数: reg :寄存器地址 45 * 返 回: 无 46 * 功 能: 读出寄存器的值 47 */ 48 uint8_t DM9k_ior(uint8_t reg) 49 { 50 NET_REG_ADDR = reg; 51 return (NET_REG_DATA); 52 } 53 54 /* 55 * 函数名: iow 56 * 参 数: reg :寄存器地址 57 * writedata : 写入的数据 58 * 返 回: 无 59 * 功 能: 写DM9006AE寄存器的值 60 */ 61 void DM9k_iow(uint8_t reg, uint8_t writedata) 62 { 63 NET_REG_ADDR = reg; 64 NET_REG_DATA = writedata; 65 } 66 67 /* 68 * 函数名: DM9k_WaitBitClear 69 * 参 数: reg :寄存器地址 70 * bit : 数据位 71 * 返 回: 无 72 * 功 能: 等待写寄存器完成 73 */ 74 void DM9k_WaitBitClear(uint8_t reg, uint8_t bit) 75 { 76 uint32_t timeout = 10000; 77 78 while (timeout--) 79 { 80 if (!DM9k_ior(reg) & (1 << bit)) 81 break; 82 } 83 } 84 85 /* 86 * 函数名: DM9k_WaitBitClear 87 * 参 数: phy_id PHY ID 88 * reg :寄存器地址 89 * bit : 数据位 90 * 返 回: 无 91 * 功 能: 等待PHY寄存器清除完成 92 */ 93 void DM9k_WaitPhyBitClear(uint8_t phy_id, uint8_t reg, uint8_t bit) 94 { 95 uint32_t timeout = 10000; 96 97 while (timeout--) 98 { 99 if (!(dm9k_phy_read(reg, phy_id) & (1 << bit))) 100 break; 101 } 102 } 103 104 /* 105 * 函数名: dm9k_hash_table 106 * 参 数: 无 107 * 返 回: 无 108 * 功 能: 设置 DM9006A MAC 、 广播 、 多播 寄存器 109 */ 110 void dm9k_hash_table(uint8_t *MacAdd) 111 { 112 uint8_t i; 113 114 // printf(">>DM9006A write mac:"); 115 // 设置 网卡 MAC 位置,来自於 MyHardware 116 for(i = 0; i < 6; i++) 117 { 118 DM9k_iow(DM9006_REG_PAR + i, MacAdd[i]); 119 // printf("0x%X ",MacAdd[i]); 120 } 121 // printf("\r\n"); 122 // 清除 网卡多播设置 123 for(i = 0; i < 8; i++) 124 DM9k_iow(DM9006_REG_MAR + i, 0xff); 125 } 126 127 /* 128 * 函数名: dm9k_reset 129 * 参 数: 无 130 * 返 回: 无 131 * 功 能: 对DM9006AE进行软件复位 132 */ 133 void dm9k_reset(void) 134 { 135 uint8_t data = NET_REG_ADDR; // 暂存所使用的位置 136 137 dm9k_init(); 138 139 NET_REG_ADDR = data; // 恢复所使用的位置 140 141 SendPackOk = 0; 142 } 143 144 /* 145 * 函数名: dm9k_phy_write 146 * 参 数: phy_reg : 寄存器地址 147 * writedata : 写入的数据 148 * port : 端口编号 149 * 返 回: 无 150 * 功 能: 写DM9006A PHY 寄存器 151 */ 152 void dm9k_phy_write(uint8_t phy_reg, uint16_t writedata,uint8_t port) 153 { 154 155 // 设置写入 PHY 寄存器的位置 156 DM9k_iow(DM9006_REG_EPAR, ( phy_reg | (port << 6)) ); 157 158 // 设置写入 PHY 寄存器的值 159 DM9k_iow(DM9006_REG_EPDRH, (writedata >> 8) & 0xff); 160 DM9k_iow(DM9006_REG_EPDRL, writedata & 0xff); 161 162 DM9k_iow(DM9006_REG_EPCR, 0x08); // Clear phyxcer write command 163 DM9k_iow(DM9006_REG_EPCR, 0x0A); // 将资料写入 PHY 寄存器 164 DM9k_iow(DM9006_REG_EPCR, 0x08); // Clear phyxcer write command 165 166 // 查寻是否执行结束 167 do { 168 if (!(DM9k_ior(DM9006_REG_EPCR) & 0x01)) 169 break; 170 }while(1); 171 172 } 173 174 /* 175 * 函数名: dm9k_phy_read 176 * 参 数: phy_reg : 寄存器地址 177 * port : 端口编号 178 * 返 回: 无 179 * 功 能: 读DM9006A PHY 寄存器 180 */ 181 uint16_t dm9k_phy_read(uint8_t phy_reg,uint8_t port) 182 { 183 uint16_t temp; 184 185 // 设置写入 PHY 寄存器的位置 186 DM9k_iow(DM9006_REG_EPAR, ( phy_reg | (port << 6))); // Fill the phyxcer register into REG_0C 187 188 // 设置写入 PHY 寄存器的值 189 DM9k_iow(DM9006_REG_EPCR, 0x08); //Clear phyxcer read command 190 DM9k_iow(DM9006_REG_EPCR, 0x0C); //选中PHY,发送读命令 191 DM9k_iow(DM9006_REG_EPCR, 0x08); //Clear phyxcer read command 192 193 while(DM9k_ior(DM9006_REG_EPCR) & 0x01); // 查寻是否执行结束 194 195 temp = (DM9k_ior(DM9006_REG_EPDRH) << 8) | (DM9k_ior(DM9006_REG_EPDRL)); 196 197 return temp; 198 } 199 200 /* 201 * 函数名: DM9006_LinkStat 202 * 参 数: 无 203 * 返 回: 0,未连接 204 * 1,已连接 205 * 功 能: 获取DM9006的连接状态 206 */ 207 uint8_t DM9006_LinkStat(void) 208 { 209 static uint8_t timer = 0; 210 uint8_t linkchanged = 0; 211 212 // Link Change Status.This bit is set after port 0 or 1 link changed. This bit is cleared by write 1 213 // linkchanged = (DM9k_ior(DM9006_REG_NSR) >> 5) & 0x01; 214 // printf(">>DM9006_REG_NSR 0x%X\r\n",DM9k_ior(DM9006_REG_NSR)); 215 // printf(">>DM9006_REG_ISR 0x%X\r\n",DM9k_ior(DM9006_REG_ISR)); 216 217 // printf(">>DM9006_REG_WAR 0x%X\r\n",DM9k_ior(DM9006_REG_WAR)); 218 linkchanged =(DM9k_ior(DM9006_REG_WAR) >> 2) & 0x01; 219 if(linkchanged) 220 { 221 timer ++; 222 // 清除链接查询标志位 223 DM9k_iow(DM9006_REG_NSR, 0x20); 224 } 225 // DM9006 只能记录链接状态的标志位,不能记录各个端口的连接状态 226 if( timer % 2) 227 { 228 return 1; 229 }else 230 { 231 return 1; 232 } 233 234 } 235 236 /* 237 * 函数名: DM9006_Set_PHYMode 238 * 参 数: mode 模式设置 239 * 返 回: void 240 * 功 能: 设置DM9006的连接模式 241 */ 242 void DM9006_Set_PHYMode(uint8_t mode) 243 { 244 uint16_t BMCR_Val, ANAR_Val; 245 246 /* 连接模式设置 247 0x0000 : 固定10M半双工 ANAR_Value:0x21 248 0x0100 : 固定10M全双工 ANAR_Value:0x41 249 0x2000 : 固定100M半双工 ANAR_Value:0x81 250 0x2100 : 固定100M全双工 ANAR_Value:0x0101 251 0x1000 : 自适应模式 ANAR_Value:0x01E1 252 */ 253 switch (mode) 254 { 255 case DM9006_10MHD: 256 BMCR_Val = 0x0000; 257 ANAR_Val = 0x21; 258 break; 259 case DM9006_10MFD: 260 BMCR_Val = 0x0100; 261 ANAR_Val = 0x41; 262 break; 263 264 case DM9006_100MHD: 265 BMCR_Val = 0x2000; 266 ANAR_Val = 0x81; 267 break; 268 269 case DM9006_100MFD: 270 BMCR_Val = 0x2100; 271 ANAR_Val = 0x101; 272 break; 273 274 case DM9006_AUTO: 275 BMCR_Val = 0x1000; 276 ANAR_Val = 0x01E1; 277 break; 278 } 279 DM9k_iow(DM9006_PHY_BMCR, BMCR_Val); 280 DM9k_iow(DM9006_PHY_ANAR, ANAR_Val); 281 } 282 283 /* 284 * 函数名: DM9006_Get_SpeedAndDuplex 285 * 参 数: 无 286 * 返 回: 0,100M半双工 287 * 1,100M全双工 288 * 2,10M半双工 289 * 3,10M全双工 290 * 0XFF,连接失败! 291 * 功 能: 获取DM9006的连接速度和双工模式 292 */ 293 uint8_t DM9006_Get_SpeedAndDuplex(void) 294 { 295 uint8_t temp; 296 uint8_t i = 0; 297 298 //等待自动协商完成 299 while( !(dm9k_phy_read(DM9006_PHY_BMSR & 0x0020, 0)) ) 300 { 301 HAL_Delay(100); 302 i++; 303 304 if(i > 100) 305 return 0xFF; //自动协商失败 306 } 307 308 //这里查询数据手册发现读取这两个寄存器只适合DM9000 309 //获取DM9006的连接速度 0:100M 1:10M 310 temp = ((DM9k_ior(DM9006_REG_NSR) >> 6) & 0x02); 311 //获取DM9006的双工状态 312 temp |= ((DM9k_ior(DM9006_REG_NCR) >> 3) & 0x01); 313 314 //这里查询数据手册发现读取这两个寄存器只适合DM9006 315 // printf(">>DM9006_REG_P_INDEX 0x%X\r\n",DM9k_ior(DM9006_REG_P_INDEX)); 316 // 317 // DM9k_iow(DM9006_REG_P_INDEX, 0x00); // 0 号端口 318 // 319 // printf(">>DM9006_REG_P_INDEX 0x%X\r\n",DM9k_ior(DM9006_REG_P_INDEX)); 320 // 321 // DM9k_iow(DM9006_REG_P_CTRL, 0x00); // 0 号端口 322 // 323 // temp = ((DM9k_ior(DM9006_REG_P_STUS) >> 1) & 0x03); 324 // 325 // printf(">>DM9006_REG_P_STUS 0x%X\r\n",temp); 326 327 return temp; 328 } 329 330 /* 331 * 函数名: dm9k_init 332 * 参 数: 无 333 * 返 回: 无 334 * 功 能: 初始化DM9006AE 335 */ 336 void dm9k_init(void) 337 { 338 uint8_t temp = 0; 339 340 // switch reset 341 DM9k_iow(DM9006_REG_SWITCHCR, 0x40); // Reset Switch Core and auto clear after 10us 342 DM9k_WaitBitClear(DM9006_REG_SWITCHCR,6); 343 344 // software reset 345 DM9k_iow(DM9006_REG_NCR, 1); //Software reset and auto clear after 10us. 346 DM9k_WaitBitClear(DM9006_REG_NCR,0); 347 348 /* 连接模式设置 349 0x0000 : 固定10M半双工 ANAR_Value:0x21 350 0x0100 : 固定10M全双工 ANAR_Value:0x41 351 0x2000 : 固定100M半双工 ANAR_Value:0x81 352 0x2100 : 固定100M全双工 ANAR_Value:0x0101 353 0x1000 : 自适应模式 ANAR_Value:0x01E1 354 */ 355 // reset & wait for PHY ready 356 for (temp = 0; temp < 2; temp ++) 357 { 358 // reset & wait for PHY ready 重置 PHY 的寄存器 359 dm9k_phy_write(DM9006_PHY_BMCR, 0x8000, temp); // PHY软件复位 360 DM9k_WaitPhyBitClear(temp, DM9006_PHY_BMCR, 15); // 等待位清除完成 361 dm9k_phy_write(DM9006_PHY_SCR, 0x0C80, temp); // (Specified config)Reg 10BAST-T mode,Enable Transmit power sacing in 10BASR-T mode,MDIX mode 362 // 设置 基本连接模式 363 dm9k_phy_write(DM9006_PHY_BMCR, 0x1200, temp); // Auto-negotiation, Restart auto-negotiation 364 // dm9k_phy_write(DM9006_PHY_ANAR, 0x01E1, temp); // 设置 自适应模式相容表 365 } 366 367 // Program operating register 368 DM9k_iow(DM9006_REG_NCR, 0x20); // reg.01 cleared by write 1 369 DM9k_iow(DM9006_REG_FCR, 0x20); // RX Flow Control Enable 370 // DM9k_iow(DM9006_REG_NCR, 0x60); // reg.01 cleared by write 1 371 // DM9k_iow(DM9006_REG_WAR, 0x20); // Link Change Event Enable 372 // DM9k_iow(DM9006_REG_FCR, 0x20); // RX Flow Control Enable 373 374 #if CHECKSUM 375 DM9k_iow(DM9006_REG_TCSCR, 0x07); /* TX checksum enable */ 376 DM9k_iow(DM9006_REG_RCSCSR, 0x02); /* RX checksum enable */ 377 #if 0 378 /* switch config */ 379 /* If using EEPROM sets switch functions, 380 don't execute dm9013_switch_config() function */ 381 if (db->HasEEPROM) 382 DM9k_iow(db, DM9013_EPCR, (1<<5));/* reload EEPROM */ 383 else 384 dm9013_switch_config(db); 385 #endif 386 #endif 387 388 #if ENABLE_VLAN 389 /* reset VLAN mapping table */ 390 for (i=0xB0; i<=0xBF; i++) 391 DM9k_iow(i, 0x0F); 392 /* reset Per-Port VID*/ 393 for(i = 0; i < 4; i++) 394 { 395 DM9k_iow(0x60, i); 396 DM9k_iow(0x6E, 1); 397 } 398 /* reset VLAN control */ 399 DM9k_iow (VLANCR, 0); 400 /* reset Per-Port switch control */ 401 for(i=0; i<4; i++) 402 { 403 DM9k_iow(0x60, i); 404 DM9k_iow(0x61, 0); 405 DM9k_iow(0x66, 0); 406 DM9k_iow(0x67, 0); 407 DM9k_iow(0x6D, 0); 408 DM9k_iow(0x6F, 0); 409 } 410 #endif 411 412 // Set Physical Address 413 dm9k_hash_table(lwipdev.mac); // 设置 DM9006A MAC 及 多播 414 415 // 基本记存器相关设置 416 DM9k_iow(DM9006_REG_RCR, 0x09); //Filter all address in Hash Table. RX Enable 417 // 开启内存自环模式,设置中断 418 DM9k_iow(DM9006_REG_IMR, 0x83); //(Interrupt mask reg) Enable the SRAM read/write pointer used as transmit/receive address. Enable Packet Rx/Tx Interrupt 419 // DM9k_iow(DM9006_REG_IMR, 0xA3); 420 421 } 422 423 424 /* 425 * 函数名: dm9k_initnic 426 * 参 数: 无 427 * 返 回: 无 428 * 功 能: 初始化DM9006AE 429 */ 430 void dm9k_initnic(void) 431 { 432 uint8_t temp; 433 434 //读厂商ID,产品ID,版本信息 435 if(DM9006A_ID != dm9k_ReadID()) /* 进行 设备ID读取判断 */ 436 { 437 printf(">>DM9006A_ID fault 0x%X\r\n",dm9k_ReadID()); 438 return; 439 }else 440 { 441 //模块检测正常, 初始化模块 442 printf(">>DM9006A_ID true 0x%X\r\n",DM9006A_ID); 443 dm9k_init(); 444 445 //读取MAC地址 446 // printf(">>DM9006A read DM9006_REG_PAR mac:"); 447 // for (temp = 0; temp < 6; temp++) 448 // { 449 // lwipdev.mac[temp] = DM9k_ior(DM9006_REG_PAR + temp); //DM9006_REG_PAR 450 // } 451 // for (temp = 0; temp < 6; temp++) 452 // { 453 // printf("0x%X ",lwipdev.mac[temp]); 454 // } 455 // printf("\r\n"); 456 457 // //读取内部MAC地址 458 // DM9k_iow(DM9006_REG_P_INDEX, 0x00); 459 // printf(">>DM9006A read DM9006_REG_EAD0 mac:"); 460 // for (temp = 0; temp < 6; temp++) 461 // { 462 // lwipdev.mac[temp] = DM9k_ior(DM9006_REG_EAD0 + temp); //DM9006_REG_PAR 463 // } 464 // for (temp = 0; temp < 6; temp++) 465 // { 466 // printf("0x%X ",lwipdev.mac[temp]); 467 // } 468 // printf("\r\n"); 469 470 } 471 472 temp = DM9006_Get_SpeedAndDuplex(); // 获取DM9006的连接速度和双工状态 473 if(temp != 0xFF) // 连接成功,通过串口显示连接速度和双工状态 474 { 475 printf(">>DM9006 Speed:%dMbps,Duplex:%s duplex mode\r\n", (temp & 0x02) ? 10 : 100, (temp & 0x01) ? "Full" : "Half"); 476 }else 477 { 478 printf(">>DM9006 Establish Link Failed!\r\n"); 479 } 480 481 bsp_exti_init(DM9006_INTPORT, DM9006_INTPIN, GPIO_Mode_IN, 8, 0); 482 483 SendPackOk = 0; 484 } 485 486 /* 487 * 函 数 名: bsp_exti_init 488 * 功能说明: 使能 EXTI 489 * 形 参: GPIOx:端口 pin 脚 490 * 返 回 值: 无 491 */ 492 void bsp_exti_init(GPIO_TypeDef *_GPIOx, uint32_t _pin, uint32_t _mode, uint8_t _Priority, uint8_t _SubPriority) 493 { 494 EXTI_InitTypeDef EXTI_InitStructure; 495 GPIO_InitTypeDef GPIO_InitStructure; 496 NVIC_InitTypeDef NVIC_InitStructure; 497 498 /* Enable GPIOG clock */ 499 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE); 500 /* Enable SYSCFG clock */ 501 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); 502 503 /* Configure PD1 pin as input floating */ 504 GPIO_InitStructure.GPIO_Mode = _mode; 505 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; 506 GPIO_InitStructure.GPIO_Pin = _pin; 507 GPIO_Init(_GPIOx, &GPIO_InitStructure); 508 509 /* Connect EXTI Line0 to PG13 pin */ 510 SYSCFG_EXTILineConfig(ETH_EXTI_PORT_SOURCE, ETH_EXTI_PIN_SOURCE); 511 512 /* Configure EXTI Line13 */ 513 EXTI_InitStructure.EXTI_Line = ETH_EXTI_LINE; 514 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; 515 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; // EXTI_Trigger_Rising 上升沿中断,EXTI_Trigger_Falling,下降沿沿触发 516 EXTI_InitStructure.EXTI_LineCmd = ENABLE; 517 EXTI_Init(&EXTI_InitStructure); 518 519 /* Enable and set EXTI Line0 Interrupt to the lowest priority */ 520 NVIC_InitStructure.NVIC_IRQChannel = ETH_EXTI_IRQn; 521 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = _Priority; 522 NVIC_InitStructure.NVIC_IRQChannelSubPriority = _SubPriority; 523 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 524 NVIC_Init(&NVIC_InitStructure); 525 526 } 527 528 /* 529 * 函数名: ETH_NRST_PIN_LOW 530 * 参 数: 无 531 * 返 回: 无 532 * 功 能: 初始化DM9006AE 复位引脚 533 */ 534 void ETH_NRST_PIN_LOW(void) 535 { 536 GPIO_ResetBits(DM9006_NRSTPORT, DM9006_NRSTPIN); 537 } 538 539 /* 540 * 函数名: ETH_NRST_PIN_HIGH 541 * 参 数: 无 542 * 返 回: 无 543 * 功 能: 初始化DM9006AE 复位引脚 544 */ 545 void ETH_NRST_PIN_HIGH(void) 546 { 547 GPIO_SetBits(DM9006_NRSTPORT, DM9006_NRSTPIN); 548 } 549 550 /* 551 * 函数名: DM9006_Receive_Packet 552 * 参 数: void 553 * 返 回: pbuf格式的接收到的数据包 554 * 功 能: DM9006 接收数据包 555 接收到的数据包存放在 DM9006 的RX FIFO中,地址为0X0C00~0X3FFF 556 接收到的数据包的前四个字节并不是真实的数据,而是有特定含义的 557 byte1:表明是否接收到数据,为0x00或者0X01,如果两个都不是的话一定要软件复位 DM9006 558 0x01,接收到数据 559 0x00,未接收到数据 560 byte2:第二个字节表示一些状态信息,和 DM9006 的RSR(0X06)寄存器一致的 561 byte3:本帧数据长度的低字节 562 byte4:本帧数据长度的高字节 563 */ 564 struct pbuf *DM9006_Receive_Packet(void) 565 { 566 struct pbuf* p; 567 struct pbuf* q; 568 u32 rxbyte; 569 vu16 rx_status, rx_length; 570 u16* data; 571 u16 dummy; 572 int len; 573 // u8 err; 574 575 p = NULL; 576 577 // OSMutexPend(dm9000lock,0,&err); //请求互斥信号量,锁定DM9000 578 579 // DM9k_ior(DM9006_REG_MRRH); 580 // DM9k_ior(DM9006_REG_MRRL); 581 582 __error_retry: 583 584 // 假读,读取内存数据,地址不增加 585 DM9k_ior( DM9006_REG_MRCMDX ); 586 // 进行第二次读取 587 // rxbyte = NET_REG_DATA; 588 rxbyte = (uint8_t) DM9k_ior(DM9006_REG_MRCMDX); // 这里只识别低8位 589 590 if( rxbyte == DM9006_PKT_RDY ) // 接收到数据 591 { 592 // templength = DM9k_ior(DM9006_REG_RXPLHR) << 8 | DM9k_ior(DM9006_REG_RXPLLR); 593 // A packet ready now & Get status/length 594 NET_REG_ADDR = DM9006_REG_MRCMD; 595 rx_status = NET_REG_DATA; // 只有高八位有效 &0xFF00 596 rx_length = NET_REG_DATA; 597 598 // //if(rx_length>512)printf("rxlen:%d\r\n",rx_length); 599 p = pbuf_alloc(PBUF_RAW,rx_length,PBUF_POOL); //pbufs内存池分配pbuf 600 if(p != NULL) //内存申请成功 601 { 602 for(q = p;q != NULL;q = q->next) 603 { 604 data = (u16*)q->payload; 605 len = q->len; 606 while( len > 0 ) 607 { 608 *data = NET_REG_DATA; 609 data ++; 610 len -= 2; 611 } 612 } 613 }else //内存申请失败 614 { 615 printf(">>pbuf内存申请失败:%d\r\n",rx_length); 616 data =& dummy; 617 len = rx_length; 618 while(len) 619 { 620 *data = NET_REG_DATA; 621 len-=2; 622 } 623 } 624 //根据rx_status判断接收数据是否出现如下错误:FIFO溢出、CRC错误 625 //对齐错误、物理层错误,如果有任何一个出现的话丢弃该数据帧, 626 //当rx_length小于64或者大于最大数据长度的时候也丢弃该数据帧 627 if( (rx_length < 0x40) || (rx_length > Max_Ethernet_Lenth)) // (rx_status & 0XBF00) || 628 { 629 printf(">>dm9006 rx_status:%#x\r\n",rx_status); 630 if (rx_status & 0x100) 631 printf(">>dm9006 rx fifo error\r\n"); 632 if (rx_status & 0x200) 633 printf(">>dm9006 rx crc error\r\n"); 634 if (rx_status & 0x8000) 635 printf(">>dm9006 rx length error\r\n"); 636 637 if (rx_length > Max_Ethernet_Lenth) 638 { 639 printf(">>dm9006 rx length too big\r\n"); 640 DM9k_iow(DM9006_REG_NCR, NCR_RST); //复位DM9006 641 HAL_Delay(5); 642 } 643 if(p != NULL) 644 pbuf_free((struct pbuf*)p); //释放内存 645 p = NULL; 646 goto __error_retry; 647 } 648 }else 649 { 650 if( rxbyte > 1 )// rxbyte大于1,接收到的数据错误,挂了 651 { 652 printf(">>dm9006 rx: rx error, stop device 0x%X\r\n",rxbyte); 653 654 DM9k_iow(DM9006_REG_RCR,0x00); 655 DM9k_iow(DM9006_REG_ISR,0x80); 656 // DM9k_iow(DM9006_REG_RCR,0x09); 657 // DM9k_iow(DM9006_REG_ISR,0x83); 658 659 return (struct pbuf*)p; 660 } 661 if(rxbyte == DM9006_PKT_NORDY) // 0x00,未收到包 662 { 663 // printf(">>dm9006 Not yet received data package\r\n"); 664 // 清除所有中断标志位 665 DM9k_iow(DM9006_REG_ISR, ISR_LKNCHG | ISR_UDRUN | ISR_ROO | ISR_ROS | ISR_PT | ISR_PR); 666 }else 667 { 668 // dm9k_reset(); 669 DM9k_iow(DM9006_REG_ISR,ISR_PT); //清除所有中断标志位 670 DM9k_iow(DM9006_REG_IMR, IMR_PAR | IMR_PRI); // 重新开启 DM9006A 中断 671 } 672 } 673 674 // OSMutexPost(dm9000lock); //发送互斥信号量,解锁DM9000 675 return (struct pbuf*)p; 676 } 677 678 /* 679 * 函数名: dm9k_ReadID 680 * 参 数: 无 681 * 返 回: 无 682 * 功 能: 读取芯片ID 683 */ 684 uint32_t dm9k_ReadID(void) 685 { 686 uint8_t vid1, vid2, pid1, pid2; 687 688 if(s_FSMC_Init_Ok == 0) 689 { 690 DM9K_CtrlLinesConfig(); 691 DM9K_FSMCConfig(); 692 693 s_FSMC_Init_Ok = 1; 694 } 695 696 vid1 = DM9k_ior(DM9006_REG_VID_L) & 0xFF; 697 vid2 = DM9k_ior(DM9006_REG_VID_H) & 0xFF; 698 pid1 = DM9k_ior(DM9006_REG_PID_L) & 0xFF; 699 pid2 = DM9k_ior(DM9006_REG_PID_H) & 0xFF; 700 701 return (pid2 << 24) | (pid1 << 16) | (vid2 << 8) | vid1; 702 } 703 704 /* 705 * 函数名: etherdev_init 706 * 参 数: 无 707 * 返 回: 无 708 * 功 能: uIP 接口函数,初始化网卡 709 */ 710 void etherdev_init(void) 711 { 712 DM9K_CtrlLinesConfig(); 713 DM9K_FSMCConfig(); 714 715 s_FSMC_Init_Ok = 1; 716 717 dm9k_initnic(); 718 } 719 720 /* 721 * 函数名: DM9006AE_CtrlLinesConfig 722 * 参 数: 无 723 * 返 回: 无 724 * 功 能: 配置DM9000AE控制口线,FSMC管脚设置为复用功能 (For SMT32F4) 725 */ 726 static void DM9K_CtrlLinesConfig(void) 727 { 728 GPIO_InitTypeDef GPIO_InitStructure; 729 730 /* 使能FSMC时钟 */ 731 RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE); 732 /* 使能 GPIO时钟 */ 733 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOG, ENABLE); 734 735 /* 设置 PD.00(D2), PD.01(D3), PD.04(NOE), PD.05(NWE), PD.08(D13), PD.09(D14), 736 PD.10(D15), PD.14(D0), PD.15(D1) 为复用推挽输出 */ 737 738 GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_FSMC); 739 GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_FSMC); 740 GPIO_PinAFConfig(GPIOD, GPIO_PinSource4, GPIO_AF_FSMC); 741 GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_FSMC); 742 GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_FSMC); 743 GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_FSMC); 744 GPIO_PinAFConfig(GPIOD, GPIO_PinSource10, GPIO_AF_FSMC); 745 GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_FSMC); 746 GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_FSMC); 747 748 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | 749 GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_14 | 750 GPIO_Pin_15; 751 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; 752 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; 753 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 754 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; 755 GPIO_Init(GPIOD, &GPIO_InitStructure); 756 757 /* 设置 PE.07(D4), PE.08(D5), PE.09(D6), PE.10(D7), PE.11(D8), PE.12(D9), PE.13(D10), 758 PE.14(D11), PE.15(D12) 为复用推挽输出 */ 759 760 GPIO_PinAFConfig(GPIOE, GPIO_PinSource4 , GPIO_AF_FSMC); 761 GPIO_PinAFConfig(GPIOE, GPIO_PinSource5 , GPIO_AF_FSMC); 762 763 GPIO_PinAFConfig(GPIOE, GPIO_PinSource7 , GPIO_AF_FSMC); 764 GPIO_PinAFConfig(GPIOE, GPIO_PinSource8 , GPIO_AF_FSMC); 765 GPIO_PinAFConfig(GPIOE, GPIO_PinSource9 , GPIO_AF_FSMC); 766 GPIO_PinAFConfig(GPIOE, GPIO_PinSource10 , GPIO_AF_FSMC); 767 GPIO_PinAFConfig(GPIOE, GPIO_PinSource11 , GPIO_AF_FSMC); 768 GPIO_PinAFConfig(GPIOE, GPIO_PinSource12 , GPIO_AF_FSMC); 769 GPIO_PinAFConfig(GPIOE, GPIO_PinSource13 , GPIO_AF_FSMC); 770 GPIO_PinAFConfig(GPIOE, GPIO_PinSource14 , GPIO_AF_FSMC); 771 GPIO_PinAFConfig(GPIOE, GPIO_PinSource15 , GPIO_AF_FSMC); 772 773 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | 774 GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | 775 GPIO_Pin_15; // GPIO_Pin_4 | GPIO_Pin_5 | 776 GPIO_Init(GPIOE, &GPIO_InitStructure); 777 778 /* 设置 PD.13(A18 (RS)) 为复用推挽输出 */ 779 GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_FSMC); 780 781 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; 782 GPIO_Init(GPIOD, &GPIO_InitStructure); 783 784 /* 设置 PG10 (CS)) 为复用推挽输出 */ 785 GPIO_PinAFConfig(GPIOG, GPIO_PinSource10, GPIO_AF_FSMC); 786 787 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; 788 GPIO_Init(GPIOG, &GPIO_InitStructure); 789 790 /* PB12 是DM9006_NRST复位输入口(本程序使用) */ 791 GPIO_InitStructure.GPIO_Pin = DM9006_NRSTPIN; 792 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; // 普通输出模式 793 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // 推挽输出 794 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; // 100MHz 795 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; 796 GPIO_Init(DM9006_NRSTPORT, &GPIO_InitStructure); // 初始化 797 798 // 对DM9006进行硬件复位 799 ETH_NRST_PIN_LOW();// 硬件复位 800 HAL_Delay(30); 801 ETH_NRST_PIN_HIGH(); // 硬件复位结束 802 HAL_Delay(30); // 等待DM9006准备就绪 803 804 // PG13 是DM9006_INT中断输入口(本程序使用) 805 806 } 807 808 /* 809 * 函数名: DM9K_FSMCConfig 810 * 参 数: 无 811 * 返 回: 无 812 * 功 能: 配置FSMC并口访问时序 813 */ 814 static void DM9K_FSMCConfig(void) 815 { 816 FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure; 817 FSMC_NORSRAMTimingInitTypeDef readWriteTiming; 818 819 /*-- FSMC Configuration ------------------------------------------------------*/ 820 /*----------------------- SRAM Bank 3 ----------------------------------------*/ 821 /*-- FSMC Configuration ------------------------------------------------------*/ 822 readWriteTiming.FSMC_AddressSetupTime = 3; // 6 设置为2会出错; 3正常 地址建立时间(ADDSET)为1个HCLK 1/36M=27ns 823 readWriteTiming.FSMC_AddressHoldTime = 2; // 地址保持时间(ADDHLD)模式A未用到 824 readWriteTiming.FSMC_DataSetupTime = 4; // 设置为1出错,2正常 数据保持时间(DATAST)为9个HCLK 6*9=54ns 825 readWriteTiming.FSMC_BusTurnAroundDuration = 1; 826 readWriteTiming.FSMC_CLKDivision = 0; 827 readWriteTiming.FSMC_DataLatency = 0; 828 readWriteTiming.FSMC_AccessMode = FSMC_AccessMode_A; //模式A 829 830 FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM3; // 这里我们使用NE3,也就对应BTCR[4],[5] 831 FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; 832 FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM; // FSMC_MemoryType_PSRAM; 833 FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b; // 存储器数据宽度为16bit 834 FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable; 835 FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable; 836 FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; 837 FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable; 838 FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState; 839 FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable; // 存储器写使能 840 FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable; 841 FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable; // 读写使用相同的时序 842 FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable; 843 844 FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &readWriteTiming; 845 FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &readWriteTiming; //读写同样时序 846 847 FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); // 初始化FSMC配置 848 /*!< Enable FSMC Bank1_SRAM3 Bank */ 849 FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM3, ENABLE); // 使能BANK3 850 851 } 852 853 #ifdef UIP 854 855 /* 856 * 函数名: dm9k_send_packet 857 * 参 数: p_char : 发送数据缓冲区 858 * length : 数据长度 859 * 返 回: 无 860 * 功 能: 发送一包数据 861 */ 862 void dm9k_send_packet(uint8_t *p_char, uint16_t length) 863 { 864 uint16_t SendLength = length; 865 uint16_t *SendData = (uint16_t *) p_char; 866 uint16_t i; 867 uint16_t calc_len; 868 __IO uint16_t calc_MWR; 869 870 #ifdef FifoPointCheck 871 /* 计算下一个传送的指针位 , 若接收长度为奇数,需加一对齐偶字节。*/ 872 /* 若是超过 0x0bff ,则需回归绕到 0x0000 起始位置 */ 873 calc_MWR = (DM9k_ior(DM9006_REG_MWRH) << 8) + DM9k_ior(DM9006_REG_MWRL); 874 calc_MWR += SendLength; 875 876 if(SendLength & 0x01) calc_MWR++; 877 878 if(calc_MWR > 0x0bff) calc_MWR -= 0x0c00; 879 880 #endif 881 882 DM9k_iow(DM9006_REG_IMR, DM9006_IMR_OFF); // 关闭 DM9006A 中断 883 884 // 设置传送封包的长度 885 DM9k_iow(DM9006_REG_TXPLH, (SendLength >> 8) & 0xff); 886 DM9k_iow(DM9006_REG_TXPLL, SendLength & 0xff); 887 888 // 开始将系统的资料搬到到内存中,每次移动一个 word 889 NET_REG_ADDR = DM9006_REG_MWCMD; 890 calc_len = (SendLength + 1) >> 1; 891 892 for(i = 0; i < calc_len; i++) 893 { 894 NET_REG_DATA = SendData[i]; 895 } 896 897 // 进行传送 898 DM9k_iow(DM9006_REG_TCR, DM9006_TCR_SET); 899 DM9k_iow(DM9006_REG_IMR, 0x83); // 开启 DM9006A 中断 900 // DM9k_iow(DM9006_REG_IMR, 0xA3); 901 902 #ifdef FifoPointCheck 903 904 if(calc_MWR != ((DM9k_ior(DM9006_REG_MWRH) << 8) + DM9k_ior(DM9006_REG_MWRL))) 905 { 906 #ifdef Point_Error_Reset 907 908 /* 若是指针出错,等待此一封包送完 , 之後进行重置 */ 909 while(DM9k_ior(DM9006_REG_TCR) & DM9006_TCR_SET) dm9k_udelay(5); 910 911 dm9k_reset(); 912 return; 913 #endif 914 /*若是指针出错,将指针移到下一个传送包的包头位置 */ 915 DM9k_iow(DM9006_REG_MWRH, (calc_MWR >> 8) & 0xff); 916 DM9k_iow(DM9006_REG_MWRL, calc_MWR & 0xff); 917 } 918 919 #endif 920 return; 921 } 922 923 /* 924 * 函数名: dm9k_receive_packet 925 * 参 数: _uip_buf : 接收缓冲区 926 * 返 回: > 0 表示接收的数据长度, 0表示没有数据 927 * 功 能: 读取一包数据 928 */ 929 uint16_t dm9k_receive_packet(uint8_t *_uip_buf) 930 { 931 uint16_t ReceiveLength; 932 uint16_t *ReceiveData; 933 uint8_t rx_int_count = 0; 934 uint8_t rx_checkbyte; 935 uint16_t rx_status, rx_length; 936 uint8_t jump_packet; 937 uint16_t i; 938 uint16_t calc_len; 939 uint16_t calc_MRR; 940 941 do 942 { 943 ReceiveLength = 0; // 清除接收的长度 944 ReceiveData = (uint16_t *)_uip_buf; 945 jump_packet = 0; // 清除跳包动作 946 DM9k_ior(DM9006_REG_MRCMDX); // 读取内存数据,地址不增加 947 948 // 计算内存数据位置 949 calc_MRR = (DM9k_ior(DM9006_REG_MRRH) << 8) + DM9k_ior(DM9006_REG_MRRL); 950 rx_checkbyte = DM9k_ior(DM9006_REG_MRCMDX); 951 952 if(rx_checkbyte == DM9006_PKT_RDY) /* 取 */ 953 { 954 // 读取封包相关资讯 及 长度 955 NET_REG_ADDR = DM9006_REG_MRCMD; 956 rx_status = NET_REG_DATA; 957 rx_length = NET_REG_DATA; 958 959 // 若收到超过系统可承受的封包,此包跳过 960 if(rx_length > Max_Ethernet_Lenth) 961 jump_packet = 1; 962 963 #ifdef Broadcast_Jump 964 // 若收到的广播或多播包超过特定长度,此包跳过 965 if(rx_status & 0x4000) 966 { 967 if(rx_length > Max_Broadcast_Lenth) 968 jump_packet = 1; 969 } 970 #endif 971 // 计算下一个包的指针位 , 若接收长度为奇数,需加一对齐偶字节 972 // 若是超过 0x3fff,则需回归绕到 0x0c00 起始位置 973 calc_MRR += (rx_length + 4); 974 975 if(rx_length & 0x01) calc_MRR ++; 976 977 if(calc_MRR > 0x3fff) calc_MRR -= 0x3400; 978 979 if( jump_packet == 0x01 ) 980 { 981 // 将指针移到下一个包的包头位置 982 DM9k_iow(DM9006_REG_MRRH, (calc_MRR >> 8) & 0xff); 983 DM9k_iow(DM9006_REG_MRRL, calc_MRR & 0xff); 984 continue; 985 } 986 987 // 开始将内存的资料搬到到系统中,每次移动一个 word 988 calc_len = (rx_length + 1) >> 1; 989 990 for(i = 0 ; i < calc_len ; i++) 991 ReceiveData[i] = NET_REG_DATA; 992 993 // 将包长回报给 TCP/IP 上层,并减去最後 4 BYTE 的 CRC-32 检核码 994 ReceiveLength = rx_length - 4; 995 996 rx_int_count++; /* 累计收包次数 */ 997 998 #ifdef FifoPointCheck 999 1000 if(calc_MRR != ((DM9k_ior(DM9006_REG_MRRH) << 8) + DM9k_ior(DM9006_REG_MRRL))) 1001 { 1002 #ifdef Point_Error_Reset 1003 dm9k_reset(); /* 若是指针出错,重置 */ 1004 return ReceiveLength; 1005 #endif 1006 /*若是指针出错,将指针移到下一个包的包头位置 */ 1007 DM9k_iow(DM9006_REG_MRRH, (calc_MRR >> 8) & 0xff); 1008 DM9k_iow(DM9006_REG_MRRL, calc_MRR & 0xff); 1009 } 1010 1011 #endif 1012 return ReceiveLength; 1013 }else 1014 { 1015 if(rx_checkbyte == DM9006_PKT_NORDY) /* 未收到包 */ 1016 { 1017 DM9k_iow(DM9006_REG_ISR, 0x3f); /* */ 1018 }else 1019 { 1020 dm9k_initnic(); // 接收指针出错,重置 1021 } 1022 1023 return (0); 1024 } 1025 } while(rx_int_count < Max_Int_Count); // 是否超过最多接收封包计数 1026 1027 return 0; 1028 } 1029 1030 /* 1031 * 函数名: etherdev_send 1032 * 参 数: p_char : 数据缓冲区 1033 * length : 数据长度 1034 * 返 回: 无 1035 * 功 能: uIP 接口函数,发送一包数据 1036 */ 1037 void etherdev_send(uint8_t *p_char, uint16_t length) 1038 { 1039 dm9k_send_packet(p_char, length); 1040 } 1041 1042 /* 1043 * 函数名: etherdev_read 1044 * 参 数: p_char : 数据缓冲区 1045 * 返 回: 无 1046 * 功 能: uIP 接口函数,发送一包数据 1047 */ 1048 uint16_t etherdev_read(uint8_t *p_char) 1049 { 1050 return dm9k_receive_packet(p_char); 1051 } 1052 1053 /* 1054 * 函数名: etherdev_chkmedia 1055 * 参 数: 无 1056 * 返 回: 无 1057 * 功 能: uIP 接口函数, 检测网络连接状态 1058 */ 1059 void etherdev_chkmedia(void) 1060 { 1061 // uint8_t status; 1062 1063 while( !(DM9k_ior( DM9006_REG_NSR) & DM9006_PHY) ) 1064 { 1065 dm9k_udelay(2000); 1066 } 1067 } 1068 1069 #endif
bsp_dm9006.h
1 #define EPCR_EETYPE (1<<7) // EEPROM Type 0:3C46 1:93C56 2 #define EPCR_REEP (1<<5) // Reload EEPROM.Driver needs to clear it up after the operation completes 3 #define EPCR_WEP (1<<4) // Write EEPROM Enable 4 #define EPCR_EPOS (1<<3) // EEPROM or PHY Operation Select 5 #define EPCR_ERPRR (1<<2) // EEPROM Read or PHY Reister Read Command 6 #define EPCR_ERORW (1<<1) // EEPROM Write or PHY Register Write Command 7 #define EPCR_ERRE (1<<0) // EEPROM Access Status or PHY Access Status 8 /*EEPROM & PHY Address Register*/ 9 #define EPAR_PHY_ADR (3<<6) // PHY Address bit 1 and 0; the PHY address bit[4:2] is force to 0 10 #define EPAR_EPOA (0x1F) // EEPROM Word Address or PHY Register Address 11 /*EEPROM & PHY Data Register*/ 12 #define EPDR_EPDR (0xFF) 13 /*Link Change Control Register*/ 14 #define LCCR_LINKEN (1<<5) // Link Change Event Enable 15 #define LCCR_LINKST (1<<2) // Link Change Event Status 16 /*Processor Port Physical Address Register*/ 17 #define PPPAR_PAB5 (0xFF) 18 #define PPPAR_PAB4 (0xFF) 19 #define PPPAR_PAB3 (0xFF) 20 #define PPPAR_PAB2 (0xFF) 21 #define PPPAR_PAB1 (0xFF) 22 #define PPPAR_PAB0 (0xFF) 23 /*Processor Port Multicast Address Register*/ 24 #define PPMAR_MAB7 (0xFF) 25 #define PPMAR_MAB6 (0xFF) 26 #define PPMAR_MAB5 (0xFF) 27 #define PPMAR_MAB4 (0xFF) 28 #define PPMAR_MAB3 (0xFF) 29 #define PPMAR_MAB2 (0xFF) 30 #define PPMAR_MAB1 (0xFF) 31 #define PPMAR_MAB0 (0xFF) 32 /*RX Packet Length Low Register*/ 33 #define RXPLLR_RXPLL (0xFF) 34 /*RX Packet Length High Register*/ 35 #define RXPLHR_RXPLH (0xFF) 36 /*RX Additional Status Register*/ 37 #define RXASR_RPTRS (3<<0) 38 /*RX Additional Control Register*/ 39 #define RXACR_RPRD (1<<7) // RX Pointer Restriction Disable 40 /*Verdor ID Registers*/ 41 #define VIDR_VIDH (0xFF) // Verdor ID High Byte 42 #define VIDR_VIDL (0xFF) // Verdor ID Low Byte 43 /*Product ID Register*/ 44 #define PIDR_PIDH (0xFF) 45 #define PIDR_PIDL (0xFF) 46 /*Chip Revision Register*/ 47 #define CRR_PR (0xFF) // CHIP Revision 48 /*Transmit Check Sum Control Register*/ 49 #define TCSCR_UDPCSE (1<<2) // UDP Checksum Generation Enable 50 #define TCSCR_TCPCSE (1<<1) // TCP_Checksum Generation Enable 51 #define TCSCR_IPCSE (1<<0) // IP Chechsum Generation Enable 52 /*Recevice Check Sum Control Status Register*/ 53 #define RCCSR_UDPS (1<<7) // UDP Checksum Status.1:UDP Packet Checksum is Fail;0:UDP Packet Checksum is OK or it is not a UDP Packet 54 #define RCCSR_TCPS (1<<6) // TCP Checksum Status.1:TCP Packet Checksum is Fail;0:TCP Packet Checksum is OK or it is not a TCP Packet 55 #define RCCSR_IPS (1<<5) // IP Checksum Status.1:IP Packet Checksum is Fail;0:IP Packet Checksum is OK or it is not a IP Packet 56 #define RCCSR_UDPP (1<<4) // This is an UDP Packet 57 #define RCCSR_TCPP (1<<3) // This is a TCP Packet 58 #define RCCSR_IPP (1<<2) // This is a an Packet 59 #define RCCSR_RCSEN (1<<1) // Receive Checksum Checking Enable 60 #define RCCSR_DCSE (1<<0) // Discard Checksum Error Packet 61 /*Up Data Bus Driving Capability Register*/ 62 #define UDBCR_ISA_CURR (3<<5) // SD Bus Current Driving/Sinking Capability 63 #define UDBCR_STEP (1<<2) // Data Bus Output Stepping 64 #define UDBCR_IOW_SPIKE (1<<1) // Eliminate IOW Spike 65 #define UDBCR_IOR_SPIKE (1<<0) // Eliminate IOR Spike 66 /*IRQ Pin Control Register*/ 67 #define IRQPCR_DELAY (7<<5) // IRQ Delayed Output Interval 68 #define IRQPCR_TYPE (1<<1) // IRQ Pin Output Type Control.1:IRQ Open-collector output;0:IRQ Direct Output 69 #define IRQPCR_POL (1<<0) // IRQ Pin Polarity Control.1:IRQ Active Low;0:IRQ Active High 70 /*TX/RX Memory Size Control Register*/ 71 #define TRMSCE_TX_SIZE (0x1F) 72 /* 73 TX Block Size 74 This Value Defines the Transmit Block Size In 256-Byte unit. 75 TX Memory Size = TX_SIZE * 256 Bytes 76 And Then 77 RX Memory Size = 16KB - (TX_SIZE + 1) * 256-Byte 78 Note:The Value of TX_SIZE Should be Between 14H and 30H 79 NOte2:If the Default Value is Changed, the reset switch command(REG52H bit 6)Should be set to initialize DM9006 Memory Allocation 80 */ 81 /*Switch Control Register*/ 82 #define SCR_MEM_BIST (1<<7) // Address Memory Test BIST Status 83 #define SCR_RST_SW (1<<6) // Reset Switch Core and Auto Clear After 10us 84 #define SCR_RST_ANLG (1<<5) // Reset Analog PHY Core and Auto Clear After 10us 85 #define SCR_SNF_PORT (3<<3) // Sniffer Port Number 86 #define SCR_CRC_DIS (1<<2) // CRC Checking Disable 87 /*VLAN Control Register*/ 88 #define VLCR_TOS6 (1<<7) // Full ToS Using Enable 89 #define VLCR_UNICASR (1<<5) // Unicast Packet Can Across VLAN Boundary 90 #define VLCR_VIDFFF (1<<4) // Replace VID FFF 91 #define VLCR_VID1 (1<<3) // Replace VID 001 92 #define VLCR_VID0 (1<<2) // Replace VID 000 93 #define VLCR_PRI (1<<1) // Replace priority field in the tag with value define in Reg 6FH bit 7~5 94 #define VLCR_VLAN (1<<0) // VLAN Mode Enable 95 /*DSP PHY Control Register*/ 96 #define DSPCR_DSP_CTL1 (0xFF) // DSP Control Register 1 for testing only(58H) 97 #define DSPCR_DSP_CTL2 (0xFF) // DSP Control Register 2 for testing only(59H) 98 /*Per Port Control/Status Index Register*/ 99 #define PCSIR_IDX (3<<0) // Port Index For Register 61H~84H 100 /*Per Port Control Data Register*/ 101 #define PCDR_FAST_LEV (1<<7) // IGMP Snooping Fast Leave Enable 102 #define PCDR_PARTI_EN (1<<6) // Enable Partition Detection 103 #define PCDR_NO_DIS_RX (1<<5) // Don't Discard RX Packets when Ingress Bandwidth Control 104 #define PCDR_FLOW_DIS (1<<4) // Flow Control In Full Duplex Mode, or back Presure In Half Duplex Mode Enable.0:Enable, 1:Diasble 105 #define PCDR_BANDWIDTH (1<<3) // Bandwidth Control.0:Control with Ingress and Egress separately, ref to Register 66H;1:Control with Ingress or Egress, ref to Register 67H 106 #define PCDR_BP_DIS (1<<2) // Broadcasr Packet Filter.0:Accept Broadcast Packets;1:Reject Broadcast Packets 107 #define PCDR_MP_DIS (1<<1) // Multicast Packet Filter.0:Accept Multicast Packet;1:Reject Multicast Packets 108 #define PCDR_MP_STORM (1<<0) // Broadcast Storm Control.0:Only Broadcast Packets Storm are Controlled;1:Multicast packets also same as broadcast storm control 109 /*Per Port Status Data Register*/ 110 #define PSDR_LP_FCS (1<<5) // Link Partner Flow Control Enable Status 111 #define PSDR_BIST (1<<4) // BIST Status.1:SRAM BIST Fail;0:SRAM BIST Pass 112 #define PSDR_SPEED2 (1<<2) // PHY Speed Status.0:10Mbps;1:100Mbps 113 #define PSDR_FDX2 (1<<1) // PHY Duplex Status.0:half-duplex;1:full-duplex 114 #define PSDR_LINK2 (1<<0) // PHY Link Status.0:Link Fail; 1:Link OK 115 /*Per Port Forward Control Register*/ 116 #define PFCR_LOOPBACK (1<<7) // Loop-Back Mode 117 #define PFCR_MONI_TX (1<<6) // TX Packet Monitored 118 #define PFCR_MONI_RX (1<<5) // RX Packet Monitored 119 #define PFCR_DISC_BMP (1<<4) // Broad/Multicast not Monitored 120 #define PFCR_TX_DIS (1<<2) // Packet Transmit Disabled 121 #define PFCR_RX_DIS (1<<1) // Packet Receive Disabled 122 #define PFCR_ADR_DIS (1<<0) // Address Learning Disabled, 123 /*Per Port Ingress and Egress Control Register*/ 124 #define PPIECR_IGS (0x0F<<4) // Ingress Rate Control 125 #define PIECR_EGS (0x0F) // Egress Rate Control 126 /*Per Port Bandwidth Control Setting Register*/ 127 #define PBCSR_BSTH (0x0F<<4) // Broad Storm Threshold 128 #define PBCSR_BW_CTRL (0x0F) // Received Pakcer Length Counted.Bandwidth Table Below 129 /*Per Port Block Unicast Ports Control Register*/ 130 #define PBUPCR_BLK_UP (0x0F) // Ports of Unicast Packet Be Blocked 131 /*Per Port Block Multicast Ports Control Register*/ 132 #define PBMPCR_BLK_MP (0x0F) // Ports of Multicast Packet Be Blocked 133 /*Per Port Block Broadcast Ports Control Register*/ 134 #define PBBPCR_BLK_BP (0x0F) // Ports of Broadcast Packet Be Blocked 135 /*Per Port Security & STP Register*/ 136 #define PSSR_STPS (3<<4) // Spanning Tree State 137 #define PSSE_PS_UNK (1<<2) // Unknown Source Address Handling When Port Security is Enabled.0:Discardd Unknown(Default);1:Unknown to UP Port 138 #define PSSE_PS_EN (3<<0) // Port Security Enable.00:Port Security Disable(Default);1:First Lock;2:First Link Lock;3:Assign Lock 139 /*Per Port Priority Queue Control Register*/ 140 #define PPQCR_TAG_OUT (1<<7) // Output Packet Tagging Enable 141 #define PPQCR_PRI_DIS (1<<6) // Priority Queue Disable 142 #define PPQCR_WFQUE (1<<5) // Weighted Round_Robin Queuing 143 #define PPQCR_TOS_PRI (1<<4) // Priority ToS Over VLAN 144 #define PPQCR_TOS_OFF (1<<3) // ToS Priority Classification Disable 145 #define PPACR_PRI_OFF (1<<2) // 802.1 p Priority Classification Disable 146 #define PPACR_P_PRI (3<<0) // Port Base Priority 147 /*Per Port VLAN Tag Low Byte Register*/ 148 #define PVTLB_VID70 (0xFF) // VID[7:0] 149 /*Per Port VLAN Tag High Byte Register*/ 150 #define PVTHB_PRI (0x07<<5) // Tag[15:13] 151 #define PVTHB_CFI (1<<4) // Tag[12] 152 #define PVTHB_VID118 (0x0F) // VID[11:8] 153 /*Ethernet Address Control/Status Register1*/ 154 #define EACS_EACS (3<<5) // Status of Ethernet Address Command.00:Command OK,Entry Non-Exist;01:Command OK,Entry Exist;1X:Command Error 155 #define EACS_EAI (3<<3) // Ethernet Address Table Index.0:Unicast Address Table;1:Multicast Address Table;2:IGMP Table(Read Only);3:Reserved 156 #define EACS_EAC (3<<1) // Ethernet Address Command.0:Read;1:Write;2:Delete;3:Search 157 #define EACS_EAS (1<<0) // Ethernet Address Table Status.0:Available;1:Busy 158 /*Ethernet Address Data Register(71H~76H)*/ 159 #define EADR_EAD0 (0xFF) // MAC Address bit 07~00 160 #define EADR_EAD1 (0xFF) // MAC Address bit 15~08 161 #define EADR_EAD2 (0xFF) // MAC Address bit 23~16 162 #define EADR_EAD3 (0xFF) // MAC Address bit 31~24 163 #define EADR_EAD4 (0xFF) // MAC Address bit 39~32 164 #define EADR_EAD5 (0xFF) // MAC Address bit 47~40 165 /*Ethernet Address Control/Status Registe*/ 166 #define EACR_OVERRIDE (1<<6) 167 #define EACR_IGMPE (1<<5) // When Reading Multicast Address Table, This bie Indicated the entry is IGMP entry or Not.0:Non-IGMP Entry;1:IGMP Entry 168 #define EACR_EA_STATIC (1<<4) // 0:Entry is Dynamic;1:Entry is Static,never be Age-out 169 #define EACR_PORT (0x0F) 170 /*Snooping Control Register*/ 171 #define SCR_UIPMPC (3<<5) // Unregistered IP Multicast Packet Control 172 #define SCR_UD_IGP (1<<4) // User-defined IGMP Router Port configutation Enable.0:Disable; 1:Enable 173 #define SCR_SIGS2UP (1<<3) // IGMP Packet Forward to UP Port only when SoftWare-IGS 174 #define SCR_HIGS2UP (1<<2) // IGMP Packet Forward to UP Port Also WHen Hardware-IGS 175 #define SCR_SIGS_EN (1<<1) // Software-based IGMP Snooping Enable.0:Hardware based IGMP Snooping, without software intervention(Defualt);1:Software based IGMP Snooping 176 #define SCR_IGS_EN (1<<0) // IGMP Snooping Enable. 0:Disable; 1:Enable. 177 /*Snooping Control Register2*/ 178 #define SCR2_SCP_PE (1<<7) // Snooping Control Packet Priority Enable.0:Disable;1:Enable 179 #define SCR2_SCP_PRI (3<<5) // Snooping Control Packet Prioeity 180 #define SCR2_SCP_OTC (3<<3) // Snooping Control Packet Output Tag Control 181 #define SCR2_RPP (7<<0) // Router Port Portmap 182 /*Snooping Control Register3*/ 183 #define SCR3_QI (0xFF) // Query Interval.Define Query Interval when Hardware-IGS is Enabled 184 /*Snooping Control Register4*/ 185 #define SCR4_RV (3<<0) // Robustness Variable.Define Robustness Variable when Hardware-IGS is Enabled.0:REserved;1:1times:2:2times(default);3:3times 186 /*Snooping Control Register5*/ 187 #define SCR5_MLD2UP (1<<1) // MLD Packet Forward to UP Port Only 188 #define SCR5_MLDS_EN (1<<0) // MLD Snooping Enable.0:Disable;1:Enable 189 /*MIB Counter Port Index Register*/ 190 #define MIBCPI_READY (1<<7) // MIB Counter Data is Ready 191 #define MIBCPI_MIB_DIS (1<<6) // When Write 0:Enabled,1:Disabled;When Read 0:Disabled,1:Enabled 192 #define MIBCPI_INDEX (0x1F) // MIB Counter Index 0~9,each Counter is 32-bit in Register 81h~84h 193 /*Interrupt Status Register*/ 194 #define ISR_IOMODE (1<<7) // 0:16bit mode; 1:8bit mode 195 #define ISR_LKNCHG (1<<5) // Link Status Change of port 0 or 1 196 #define ISR_UDRUN (1<<4) // Memory Management error 197 #define ISR_ROO (1<<3) // Receive Overflow Counter Overflow 198 #define ISR_ROS (1<<2) // Receive Overflow 199 #define ISR_PT (1<<1) // Packet Transmit 200 #define ISR_PR (1<<0) // Packet Received 201 /*Interrupt Mask Register*/ 202 #define IMR_PAR (1<<7) 203 #define IMR_LNKCHFI (1<<5) // Enable Link Status Change Interrupt 204 #define IMR_UDRUNI (1<<4) // Enable Transmit Under-run Interrupt 205 #define IMR_ROOI (1<<3) // Enable Receive Overflow Counter Overflow Interrupt 206 #define IMR_POI (1<<2) // Enable Receive Overflow Interrupt 207 #define IMR_PTI (1<<1) // Enable Packet Transmit Interrupt 208 #define IMR_PRI (1<<0) // Enable Packet Received Interrupt 209 210 /* DM9006 REGISTER LIST */ 211 #define DM9006_REG_NCR 0x00 //Network Control Register 212 #define DM9006_REG_NSR 0x01 //Network Status Register 213 #define DM9006_REG_TCR 0x02 //TX Control Register 214 #define DM9006_REG_RCR 0x05 //RX Control Register 215 #define DM9006_REG_RSR 0x06 //RX Status Register 216 #define DM9006_REG_ROCR 0x07 //Receive Overflow Counter Register 217 #define DM9006_REG_BPTR 0x08 218 #define DM9006_REG_FCTR 0x09 219 #define DM9006_REG_FCR 0x0A //Flow Control Register 220 #define DM9006_REG_EPCR 0x0B //EEPROM & PHY Control Register 221 #define DM9006_REG_EPAR 0x0C //EEPROM & PHY Address Register 222 #define DM9006_REG_EPDRL 0x0D //EEPROM & PHY Low Byte Data Register 223 #define DM9006_REG_EPDRH 0x0E //EEPROM & PHY Hign Byte Data Register 224 #define DM9006_REG_WAR 0x0F //Link Change Control Register 225 #define DM9006_REG_PAR 0x10 //Processor Port Physical Address Registers 226 #define DM9006_REG_MAR 0x16 //Processor Port Multicast Address Registers 227 //#define DM9006_REG_MAR7 0x1D 228 //#define DM9006_REG_GPCR 0x1E 229 //#define DM9006_REG_GPR 0x1F 230 #define DM9006_REG_RXPLLR 0x20 //RX Packet Length Low Register 231 #define DM9006_REG_RXPLHR 0x21 //RX Packet Length High Register 232 #define DM9006_REG_RASR 0x26 //RX Additional Status Register 233 #define DM9006_REG_RACR 0x27 //RX Additional Control Register 234 #define DM9006_REG_VID_L 0x28 //Vendor ID Register 235 #define DM9006_REG_VID_H 0x29 236 #define DM9006_REG_PID_L 0x2A //Product ID Register 237 #define DM9006_REG_PID_H 0x2B 238 #define DM9006_REG_CHIPR 0x2C //CHIP Revision Register 239 //#define DM9006_REG_TCR2 0x2D 240 //#define DM9006_REG_OTCR 0x2E 241 //#define DM9006_REG_SMCR 0x2F 242 //#define DM9006_REG_ETXCSR 0x30 //early transmit control/status register 243 #define DM9006_REG_TCSCR 0x31 //Transmit Check Sum Control Register 244 #define DM9006_REG_RCSCSR 0x32 //Receive Check Sum Control Status Register 245 #define DM9006_REG_DRIVER 0x38 //uP Data Bus driving capability Register 246 #define DM9006_REG_IRQCR 0x39 //IRQ Pin Control Register 247 #define DM9006_REG_TRMSCR 0x3F //TX/RX Memory Size Control Register 248 #define DM9006_REG_SWITCHCR 0x52 //Switch Control Register 249 #define DM9006_REG_VLANCR 0x53 //VLAN Control Register 250 #define DM9006_REG_DSP1 0x58 //DSP Control Register I 251 #define DM9006_REG_DSP2 0x59 //DSP Control Register II 252 #define DM9006_REG_P_INDEX 0x60 //Per Port Control/Status Index Registe 253 #define DM9006_REG_P_CTRL 0x61 //Per Port Control Data Register 254 #define DM9006_REG_P_STUS 0x62 //Per Port Status Data Register 255 #define DM9006_REG_P_RATE 0x66 //Per Port Ingress and Egress Rate Control Register 256 #define DM9006_REG_P_BW 0x67 //Per Port Bandwidth Control Setting Register 257 #define DM9006_REG_P_UNICAST 0x68 //Per Port Block Unicast Ports Control Register 258 #define DM9006_REG_P_MULTI 0x69 //Per Port Block Multicast Ports Control Register 259 #define DM9006_REG_P_BCAST 0x6A //Per Port Block Broadcast Ports Control Register 260 #define DM9006_REG_P_UNKNWN 0x6B //Per Port Block Unknown Ports Control Register 261 #define DM9006_REG_P_SSTPR 0x6C //Per Port Security & STP Register 262 #define DM9006_REG_P_PRI 0x6D //Per Port Priority Queue Control Register 263 #define DM9006_REG_VLAN_TAGL 0x6E //Per Port VLAN Tag Low Byte Register 264 #define DM9006_REG_VLAN_TAGH 0x6F //Per Port VLAN Tag High Byte Register 265 #define DM9006_REG_EAD0 0x71 //Ethernet Address Data Register (71H~76H) 266 #define DM9006_REG_EAD1 0x72 267 #define DM9006_REG_EAD2 0x73 268 #define DM9006_REG_EAD3 0x74 269 #define DM9006_REG_EAD4 0x75 270 #define DM9006_REG_EAD5 0x76 271 #define DM9006_REG_P_MIB_IDX 0x80 //Per Port MIB counter Index Register 272 #define DM9006_REG_MIB_DAT1 0x81 //MIB counter Data Register bit 0~7 273 #define DM9006_REG_MIB_DAT2 0x82 //MIB counter Data Register bit 8~15 274 #define DM9006_REG_MIB_DAT3 0x83 //MIB counter Data Register bit 16~23 275 #define DM9006_REG_MIB_DAT4 0x84 //MIB counter Data Register bit 24~31 276 #define DM9006_REG_PVLAN 0xB0 //Port-based VLAN mapping table registers B0-BFH 277 #define DM9006_REG_TOS_MAP 0xC0 //TOS Priority Map Registers C0-CFH 278 #define DM9006_REG_VLAN_MAP 0xD0 //VLAN Priority Map Registers D0-D1H 279 #define DM9006_REG_MRCMDX 0xF0 //Memory Data Pre-Fetch Read Command Without Address Increment Register 280 #define DM9006_REG_MRCMD 0xF2 //Memory Data Read Command With Address Increment 281 #define DM9006_REG_MRRL 0xF4 //Memory Data Read_address Register Low Byte 282 #define DM9006_REG_MRRH 0xF5 //Memory Data Read_address Register High Byte 283 #define DM9006_REG_MWCMDX 0xF6 //Memory Data Write Command Without Address Increment 284 #define DM9006_REG_MWCMD 0xF8 //Memory Data Write Command With Address Increment Register 285 #define DM9006_REG_MWRL 0xFA //Memory Data Write_address Register Low Byte 286 #define DM9006_REG_MWRH 0xFB //Memory Data Write_address Register High Byte 287 #define DM9006_REG_TXPLL 0xFC //TX Packet Length Low Byte Register 288 #define DM9006_REG_TXPLH 0xFD //TX Packet Length High Byte Register 289 #define DM9006_REG_ISR 0xFE //Interrupt Status Register 290 #define DM9006_REG_IMR 0xFF //Interrupt Mask Register 291 292 /* 相关宏设置 */ 293 #define DM9000A_ID 0x90000A46 294 #define DM9006A_ID 0x90060A46 295 #define Max_Ethernet_Lenth 1536 296 #define MAXPACKAGESIZE 1518 297 298 #define DM9006_BYTE_MODE 0x01 299 #define DM9006_WORD_MODE 0x00 300 #define DM9006_PHY 0x20 301 #define DM9006_PKT_RDY 0x01 302 #define DM9006_PKT_NORDY 0x00 303 #define DM9006_REG_RESET 0x03 304 305 #define DM9006_RX_INTR 0x01 /* 接收中断判断 bit */ 306 #define DM9006_TX_INTR 0x02 /* 传送中断判断 bit */ 307 #define DM9006_OVERFLOW_INTR 0x04 /* 内存溢出中断判断 bit */ 308 #define DM9006_LINK_CHANG 0x20 /* 连接变动中断判断 bit */ 309 310 #define DM9006_PHY_ON 0x00 /* 设定 PHY 开启 */ 311 #define DM9006_PHY_OFF 0x01 /* 设定 PHY 关闭 */ 312 #define DM9006_RCR_SET 0x31 /* 设定 接收功能 (不收 CRC 及 超长包) */ 313 #define DM9006_TCR_SET 0x01 /* 设定 传送功能 */ 314 #define DM9006_RCR_OFF 0x00 /* 设定 接收功能关关闭设置 */ 315 #define DM9006_BPTR_SET 0x37 /* 设定 Back Pressure 条件设置 */ 316 #define DM9006_FCTR_SET 0x38 /* 设定 Flow Control 条件设置 */ 317 #define DM9006_TCR2_SET 0x80 /* 设置 LED 显示模式 */ 318 #define DM9006_OTCR_SET 0x80 /* 设置 DM9006 工作频率 0x80 = 100Mhz */ 319 #define DM9006_ETXCSR_SET 0x83 /* 设置 Early Tramsmit 条件设置 */ 320 #define DM9006_FCR_SET 0x28 /* 开启 网络流控功能设置 */ 321 #define DM9006_TCSCR_SET 0x07 /* 设定 CHECKSUM 传送运算 设置 */ 322 #define DM9006_RCSCSR_SET 0x03 /* 设定 CHECKSUM 接收检查 设置 */ 323 #define DM9006_IMR_SET 0x81 /* 设定 启用中断使能 条件设置 */ 324 #define DM9006_IMR_OFF 0x80 /* 设定 关闭中断使能 条件设置 */ 325 326 //DM9006内部PHY寄存器 327 #define DM9006_PHY_BMCR 0x00 //Basic Mode Control Register (BMCR) 328 #define DM9006_PHY_BMSR 0x01 //Basic Mode Status Register (BMSR) 329 #define DM9006_PHY_PHYID1 0x02 //PHY ID Identifier Register #1 (PHYID1) 330 #define DM9006_PHY_PHYID2 0x03 //PHY ID Identifier Register #2 (PHYID2) 331 #define DM9006_PHY_ANAR 0x04 //Auto-negotiation Advertisement Register (ANAR) 332 #define DM9006_PHY_ANLPAR 0x05 //Auto-negotiation Link Partner Ability Register (ANLPAR) 333 #define DM9006_PHY_ANER 0x06 //Auto-negotiation Expansion Register (ANER) 334 #define DM9006_PHY_DSCR 0x10 //DAVICOM Specified Configuration Register (DSCR 335 #define DM9006_PHY_DSCSR 0x11 //DAVICOM Specified Configuration and Status Register (DSCSR) 336 #define DM9006_PHY_10BTCSR 0x12 //10BASE-T Configuration/Status (10BTCSR) 337 #define DM9006_PHY_PWDOR 0x13 //Power Down Control Register (PWDOR) 338 #define DM9006_PHY_SCR 0x14 //(Specified config) Register 339 #define DM9006_PHY_RECR 0x16 //DAVICOM Specified Receive Error Counter Register (RECR) 340 #define DM9006_PHY_DSICR 0x17 //DAVICOM Specified Disconnect Counter Register (DISCR) 341 #define DM9006_PHY_PSCR 0x1D //Power Saving Control Register (PSCR) 342 #define DM9006_PHY_DATA 0x1E //DAVICOM indirect DATA Register (DATA) 343 #define DM9006_PHY_ADDR 0x1F //DAVICOM indirect ADDR Register (ADDR) 344 #define DM9006_PHY_TX_OUT_CNTL 0x04 //DAVICOM indirect TX Amplitude Control Register (TX_OUT_CNTL) – indirect-04H 345 346 #define ETH_EXTI_LINE EXTI_Line13 347 #define ETH_EXTI_PORT_SOURCE EXTI_PortSourceGPIOG 348 #define ETH_EXTI_PIN_SOURCE EXTI_PinSource13 349 #define ETH_EXTI_IRQn EXTI15_10_IRQn 350 351 #define DM9006_INTPORT GPIOG 352 #define DM9006_INTPIN GPIO_Pin_13 353 354 #define DM9006_NRSTPORT GPIOB 355 #define DM9006_NRSTPIN GPIO_Pin_12 356 357 #define FSMC_NE1_ADDR (0x60000000) 358 #define FSMC_NE2_ADDR (0x64000000) 359 #define FSMC_NE3_ADDR (0x68000000) 360 #define FSMC_NE4_ADDR (0x6C000000) 361 362 // 分配地址参考链接: 363 // https://blog.csdn.net/u011878611/article/details/107317741/ 364 // http://www.armbbs.cn/forum.php?mod=viewthread&tid=14566 365 // 地址由FSMC_NE3 + A18共同决定, DM9006 网卡地址: 0x6800 0000 ~ 0x6808 0000 366 #define NET_BASE_ADDR (FSMC_NE3_ADDR) 367 #define NET_REG_ADDR (*((volatile uint16_t *) (NET_BASE_ADDR | (1<<1)) )) // | (1<<1) 368 #define NET_REG_DATA (*((volatile uint16_t *) (NET_BASE_ADDR | (1<<19)) )) 369 370 /* 371 ********************************************************************************************************* 372 * 全局结构体 373 ********************************************************************************************************* 374 */ 375 enum DM9006_PHY_MODE{ 376 DM9006_10MHD = 0, 377 DM9006_100MHD = 1, 378 DM9006_10MFD = 4, 379 DM9006_100MFD = 5, 380 DM9006_AUTO = 8, 381 }; 382 383 384 /********************************************************************************************************** 385 * 参数细分 386 **********************************************************************************************************/ 387 388 389 390 391 /********************************************************************************************************** 392 * 外部全局变量参数细分 393 **********************************************************************************************************/ 394 395 396 397 /* 398 ********************************************************************************************************* 399 * 函数声明 400 * 401 ********************************************************************************************************* 402 */ 403 404 void bsp_exti_init(GPIO_TypeDef *_GPIOx, uint32_t _pin, uint32_t _mode, uint8_t _Priority, uint8_t _SubPriority); 405 406 void dm9k_phy_write(uint8_t phy_reg, uint16_t writedata,uint8_t port); 407 uint16_t dm9k_phy_read(uint8_t phy_reg,uint8_t port); 408 409 uint8_t DM9k_ior(uint8_t reg); 410 void DM9k_iow(uint8_t reg, uint8_t writedata); 411 void DM9k_WaitBitClear(uint8_t reg, uint8_t bit); 412 413 void etherdev_send(uint8_t *p_char, uint16_t length); 414 uint16_t etherdev_read(uint8_t *p_char); 415 uint16_t dm9k_receive_packet(uint8_t *_uip_buf); 416 417 static void DM9K_CtrlLinesConfig(void); 418 static void DM9K_FSMCConfig(void); 419 420 void etherdev_chkmedia(void); 421 uint32_t dm9k_ReadID(void); 422 423 void etherdev_init(void); 424 uint8_t DM9006_LinkStat(void); 425 426 void dm9k_debug_test(void); 427 428 void dm9k_init(void); 429 430 struct pbuf *DM9006_Receive_Packet(void); 431 432 #ifdef __cplusplus 433 } 434 #endif 435 436 #endif /* __DM9006_H */ 437 438 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
最后在添加到lwip支持网卡数据收发的文件ethetnetif.c文件,
1 /** 2 * @file 3 * Ethernet Interface Skeleton 4 * 5 */ 6 7 /* 8 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without modification, 12 * are permitted provided that the following conditions are met: 13 * 14 * 1. Redistributions of source code must retain the above copyright notice, 15 * this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright notice, 17 * this list of conditions and the following disclaimer in the documentation 18 * and/or other materials provided with the distribution. 19 * 3. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 25 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 27 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 31 * OF SUCH DAMAGE. 32 * 33 * This file is part of the lwIP TCP/IP stack. 34 * 35 * Author: Adam Dunkels <adam@sics.se> 36 * 37 */ 38 39 /* 40 * This file is a skeleton for developing Ethernet network interface 41 * drivers for lwIP. Add code to the low_level functions and do a 42 * search-and-replace for the word "ethernetif" to replace it with 43 * something that better describes your network interface. 44 */ 45 46 #include "lwip/opt.h" 47 #include "lwip/def.h" 48 #include "lwip/mem.h" 49 #include "lwip/pbuf.h" 50 #include "lwip/timers.h" 51 #include "netif/etharp.h" 52 #include "lwip/stats.h" 53 #include "lwip/snmp.h" 54 #include "lwip/tcpip.h" 55 #include "err.h" 56 #include "ethernetif.h" 57 #include "netconf.h" 58 #include <string.h> 59 60 #include "global.h" 61 #include "malloc.h" 62 #include "bsp_dm9006.h" 63 64 /* 65 ********************************************************************************************************* 66 * 全局宏定义 67 ********************************************************************************************************* 68 */ 69 70 #define netifINTERFACE_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE * 2 ) 71 #define netifINTERFACE_TASK_PRIORITY ( configMAX_PRIORITIES - 3 ) 72 #define netifGUARD_BLOCK_TIME ( 1000 ) 73 /* The time to block waiting for input. */ 74 #define emacBLOCK_TIME_WAITING_FOR_INPUT ( ( portTickType ) 100 ) 75 76 /* Define those to better describe your network interface. */ 77 #define IFNAME0 'e' 78 #define IFNAME1 'n' 79 80 xSemaphoreHandle s_xSemaphore = NULL; 81 static void arp_timer(void *arg); 82 83 /** 84 * In this function, the hardware should be initialized. 85 * Called from ethernetif_init(). 86 * 87 * @param netif the already initialized lwip network interface structure 88 * for this ethernetif 89 */ 90 static void low_level_init(struct netif *netif) 91 { 92 uint32_t i; 93 94 // VariableMemInit(); 95 96 /* set netif MAC hardware address length */ 97 netif->hwaddr_len = ETHARP_HWADDR_LEN; 98 99 /* set netif MAC hardware address */ 100 // netif->hwaddr[0] = MAC_ADDR0; 101 // netif->hwaddr[1] = MAC_ADDR1; 102 // netif->hwaddr[2] = MAC_ADDR2; 103 // netif->hwaddr[3] = MAC_ADDR3; 104 // netif->hwaddr[4] = MAC_ADDR4; 105 // netif->hwaddr[5] = MAC_ADDR5; 106 107 netif->hwaddr[0] = lwipdev.mac[0]; 108 netif->hwaddr[1] = lwipdev.mac[1]; 109 netif->hwaddr[2] = lwipdev.mac[2]; 110 netif->hwaddr[3] = lwipdev.mac[3]; 111 netif->hwaddr[4] = lwipdev.mac[4]; 112 netif->hwaddr[5] = lwipdev.mac[5]; 113 114 /* set netif maximum transfer unit */ 115 netif->mtu = 1500; //最大允许传输单元,允许该网卡广播和ARP功能 116 117 /* Accept broadcast address and ARP traffic */ 118 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; 119 120 //添加IGMP,实现网络组播时开启 121 // netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP | NETIF_FLAG_IGMP; 122 123 //添加IGMP,实现网络组播时开启,不标记已连接 124 // netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP; 125 126 127 /* create binary semaphore used for informing ethernetif of frame reception */ 128 if (s_xSemaphore == NULL) 129 { 130 vSemaphoreCreateBinary(s_xSemaphore); 131 xSemaphoreTake(s_xSemaphore, 0); 132 } 133 134 /* create the task that handles the ETH_MAC */ 135 xTaskCreate(ethernetif_input, (const char *)"Eth_if", netifINTERFACE_TASK_STACK_SIZE, 136 (void *)netif, // 传递给任务函数的参数 137 netifINTERFACE_TASK_PRIORITY, 138 NULL); 139 140 ethernet_link_check_state(netif); 141 } 142 143 144 /** 145 * This function should do the actual transmission of the packet. The packet is 146 * contained in the pbuf that is passed to the function. This pbuf 147 * might be chained. 148 * 149 * @param netif the lwip network interface structure for this ethernetif 150 * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) 151 * @return ERR_OK if the packet could be sent 152 * an err_t value if the packet couldn't be sent 153 * 154 * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to 155 * strange results. You might consider waiting for space in the DMA queue 156 * to become availale since the stack doesn't retry to send a packet 157 * dropped because of memory failure (except for the TCP timers). 158 */ 159 160 static err_t low_level_output(struct netif *netif, struct pbuf *p) 161 { 162 static xSemaphoreHandle xTxSemaphore = NULL; 163 struct pbuf *q = NULL; 164 165 uint16_t pbuf_index = 0; 166 uint8_t word[2], word_index = 0; 167 168 if (xTxSemaphore == NULL) 169 { 170 vSemaphoreCreateBinary(xTxSemaphore); 171 } 172 173 if (xSemaphoreTake(xTxSemaphore, netifGUARD_BLOCK_TIME)) 174 { 175 176 DM9k_iow(DM9006_REG_IMR, DM9006_IMR_OFF); // 关闭 DM9006A 中断 177 NET_REG_ADDR = DM9006_REG_MWCMD; 178 179 q = p; 180 //向DM9006的TX SRAM中写入数据,一次写入两个字节数据 181 //当要发送的数据长度为奇数的时候,我们需要将最后一个字节单独写入DM9006的TX SRAM中 182 while(q) 183 { 184 if (pbuf_index < q->len) 185 { 186 word[word_index++] = ((u8_t*)q->payload)[pbuf_index++]; 187 if (word_index == 2) 188 { 189 NET_REG_DATA = ((u16)word[1]<<8) | word[0]; 190 word_index = 0; 191 } 192 }else 193 { 194 q = q->next; 195 pbuf_index = 0; 196 } 197 } 198 199 //还有一个字节未写入TX SRAM 200 if( word_index == 1) 201 NET_REG_DATA = word[0]; 202 //向DM9000写入发送长度 203 DM9k_iow(DM9006_REG_TXPLH, (p->tot_len >> 8) & 0xff); // 设置传送封包的长度 204 DM9k_iow(DM9006_REG_TXPLL, p->tot_len & 0xff); 205 206 DM9k_iow(DM9006_REG_TCR, DM9006_TCR_SET); // 进行传送 207 while( (DM9k_ior(DM9006_REG_ISR) & DM9006_TX_INTR ) == 0); // 等待发送完成 208 DM9k_iow(DM9006_REG_ISR, DM9006_TX_INTR); // 清除发送完成中断 209 DM9k_iow(DM9006_REG_IMR, IMR_PAR | IMR_PRI); // 开启 DM9006A 中断 210 211 xSemaphoreGive(xTxSemaphore); 212 } 213 214 return ERR_OK; 215 } 216 217 /** 218 * Should allocate a pbuf and transfer the bytes of the incoming 219 * packet from the interface into the pbuf. 220 * 221 * @param netif the lwip network interface structure for this ethernetif 222 * @return a pbuf filled with the received packet (including MAC header) 223 * NULL on memory error 224 */ 225 static struct pbuf *low_level_input(struct netif *netif) 226 { 227 struct pbuf *p = NULL; 228 229 p = DM9006_Receive_Packet(); 230 231 return p; 232 } 233 234 235 /** 236 * This function is the ethernetif_input task, it is processed when a packet 237 * is ready to be read from the interface. It uses the function low_level_input() 238 * that should handle the actual reception of bytes from the network 239 * interface. Then the type of the received packet is determined and 240 * the appropriate input function is called. 241 * 242 * @param netif the lwip network interface structure for this ethernetif 243 */ 244 void ethernetif_input(void *pvParameters) 245 { 246 struct pbuf *p; 247 struct netif *netif = (struct netif *) pvParameters; 248 249 for (;;) 250 { 251 // 请求信号量 252 if (xSemaphoreTake(s_xSemaphore, emacBLOCK_TIME_WAITING_FOR_INPUT) == pdTRUE) 253 { 254 do 255 { 256 // LOCK_TCPIP_CORE(); 257 p = low_level_input(netif); //调用low_level_input函数接收数据 258 if(p != NULL) 259 { 260 if(netif->input(p, netif) != ERR_OK) //调用netif结构体中的input字段(一个函数)来处理数据包 261 { 262 LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); 263 pbuf_free(p); 264 } 265 } 266 // UNLOCK_TCPIP_CORE(); 267 } while(p != NULL); 268 } 269 } 270 } 271 272 /** 273 * Should be called at the beginning of the program to set up the 274 * network interface. It calls the function low_level_init() to do the 275 * actual setup of the hardware. 276 * 277 * This function should be passed as a parameter to netif_add(). 278 * 279 * @param netif the lwip network interface structure for this ethernetif 280 * @return ERR_OK if the loopif is initialized 281 * ERR_MEM if private data couldn't be allocated 282 * any other err_t on error 283 */ 284 err_t ethernetif_init(struct netif *netif) 285 { 286 LWIP_ASSERT("netif != NULL", (netif != NULL)); 287 288 #if LWIP_NETIF_HOSTNAME 289 /* Initialize interface hostname */ 290 netif->hostname = "lwip"; 291 #endif /* LWIP_NETIF_HOSTNAME */ 292 293 netif->name[0] = IFNAME0; //初始化变量netif的name字段 294 netif->name[1] = IFNAME1; //在文件外定义这里不用关心具体值 295 296 netif->output = etharp_output; //IP层发送数据包函数 297 netif->linkoutput = low_level_output; //ARP模块发送数据包函数 298 299 /* initialize the hardware */ 300 low_level_init(netif); //底层硬件初始化函数 301 302 etharp_init(); 303 sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); 304 305 return ERR_OK; 306 } 307 308 /** 309 * @brief Custom Rx pbuf free callback 310 * @param pbuf: pbuf to be freed 311 * @retval None 312 */ 313 static void pbuf_free_custom(struct pbuf *p) 314 { 315 if(p != NULL) 316 { 317 memset(p, 0, sizeof(struct pbuf)); 318 } 319 } 320 321 /** 322 * @brief arp_timer 323 * @param void 324 * @retval None 325 */ 326 static void arp_timer(void *arg) 327 { 328 etharp_tmr(); 329 sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); 330 } 331 332 333 /** 334 * @brief Ethernet Rx Transfer completed callback 335 * @param heth: ETH handle 336 * @retval None 337 */ 338 void EXTI15_10_IRQHandler(void) 339 { 340 uint16_t save_reg; 341 uint16_t int_status; 342 343 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; 344 345 if ( EXTI_GetITStatus(ETH_EXTI_LINE) != RESET ) 346 { 347 // Clear interrupt pending bit 348 EXTI_ClearITPendingBit(ETH_EXTI_LINE); 349 350 save_reg = NET_REG_ADDR; // 暂存所使用的位置 351 352 DM9k_iow(DM9006_REG_IMR, DM9006_IMR_OFF); // 关发送和接收中断 353 354 // got DM9006 interrupt status 355 int_status = DM9k_ior(DM9006_REG_ISR); // Got ISR,取得中断产生值 356 // 清除中断标志位,DM9006的ISR寄存器的bit0~bit5写1清零 357 DM9k_iow(DM9006_REG_ISR, int_status); // Clear ISR status,清除中断产生值 358 359 // overflow 360 if(int_status & ISR_ROS) 361 { 362 printf(">>DM9006 overflow \r\n"); 363 } 364 // overflow counter overflow 365 if(int_status & ISR_ROO) 366 { 367 printf(">>DM9006 overflow counter overflow \r\n"); 368 } 369 // Receive the coming packet 370 if (int_status & DM9006_RX_INTR) // 检查是否为接收中断 371 { 372 // printf(">>DM9006A_EXTI RX\r\n"); 373 // Give the semaphore to wakeup LwIP task 374 xSemaphoreGiveFromISR( s_xSemaphore, &xHigherPriorityTaskWoken ); 375 // DM9006_Receive_Packet(); 376 } 377 378 // Transmit interrupt check 379 if (int_status & DM9006_TX_INTR) // 检查是否为发送中断 380 { 381 //发送中断处理,这里没用到 382 // printf(">>DM9006A_EXTI TX\r\n"); 383 // DM9006_TxDone(); 384 } 385 386 DM9k_iow(DM9006_REG_IMR, IMR_PAR | IMR_PRI); 387 // DM9k_iow(DM9006_REG_IMR, 0xA3); 388 389 NET_REG_ADDR = save_reg; // 恢复所使用的位置 390 391 } 392 393 /* Switch tasks if necessary. */ 394 if (xHigherPriorityTaskWoken != pdFALSE) 395 { 396 portEND_SWITCHING_ISR(xHigherPriorityTaskWoken); 397 } 398 } 399 400 401 /** 402 * @brief Check the ETH link state and update netif accordingly. 403 * @param argument: netif 404 * @retval None 405 */ 406 void ethernet_link_check_state(struct netif *netif) 407 { 408 uint8_t linkchanged = 0; 409 410 linkchanged = DM9006_LinkStat(); 411 412 if( netif_is_link_up(netif) && (linkchanged == 0) ) 413 { 414 netif_set_down(netif); 415 netif_set_link_down(netif); 416 } 417 else if( !netif_is_link_up(netif) && (linkchanged == 1)) 418 { 419 netif_set_up(netif); 420 netif_set_link_up(netif); 421 } 422 } 423 424 /** 425 * @brief Check the ETH link state and update netif accordingly. 426 * @param argument: netif 427 * @retval None 428 */ 429 void ethernet_dm9006_link_thread(void *pvParameters) 430 { 431 struct netif *netif = (struct netif *) pvParameters; 432 433 for(;;) 434 { 435 ethernet_link_check_state(netif); 436 vTaskDelay(200); 437 } 438 }
剩下初始化,按照默认的套路来,就可以,下载,插入网线板子自动获取到IP地址,不过时间测试最大网速也就是83Mbps,查看数据手册发现,这个片子最大也就支持到88Mbps.
本文来自博客园,作者:求隐,转载请注明原文链接:https://www.cnblogs.com/duguqiuying/articles/13638862.html