dm9k.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  1. /*
  2. *********************************************************************************************************
  3. *
  4. * 模块名称 : DM9000AEP 底层驱动模块(For STM32F4XX, uip)
  5. * 文件名称 : dm9k_uip.c
  6. * 版 本 : V1.1
  7. * 说 明 : 这是硬件底层驱动程序的主文件。每个c文件可以 #include "bsp.h" 来包含所有的外设驱动模块。
  8. * bsp = Borad surport packet 板级支持包
  9. * 修改记录 :
  10. * 版本号 日期 作者 说明
  11. * V1.0 2013-03-01 armfly 正式发布
  12. * V1.1 2013-06-20 armfly 规范注释,添加必要说明
  13. *
  14. * Copyright (C), 2013-2014, 安富莱电子 www.armfly.com
  15. *
  16. *********************************************************************************************************
  17. */
  18. #include "dm9k.h"
  19. #include "bsp.h"
  20. //#define DM9000A_FLOW_CONTROL
  21. //#define DM9000A_UPTO_100M
  22. //#define Fifo_Point_Check
  23. //#define Point_Error_Reset
  24. #define Fix_Note_Address
  25. //#define FifoPointCheck
  26. /* DM9000A 接收函数设置宏 */
  27. //#define Rx_Int_enable
  28. #define Max_Int_Count 1
  29. #define Max_Ethernet_Lenth 1536
  30. #define Broadcast_Jump
  31. #define Max_Broadcast_Lenth 500
  32. /* DM9000A 传送函数设置宏 */
  33. #define Max_Send_Pack 2
  34. #define NET_BASE_ADDR 0x68400000
  35. #define NET_REG_ADDR (*((volatile uint16_t *)NET_BASE_ADDR))
  36. #define NET_REG_DATA (*((volatile uint16_t *)(NET_BASE_ADDR + 0x00080000)))
  37. #define ETH_ADDR_LEN 6
  38. /* 定义网卡的 MAC 地址 */
  39. static unsigned char DEF_MAC_ADDR[ETH_ADDR_LEN] = {0x00, 0x60, 0x6e, 0x90, 0x00, 0xae};
  40. uint8_t SendPackOk = 0;
  41. uint8_t s_FSMC_Init_Ok = 0; /* 用于指示FSMC是否初始化 */
  42. //#define printk(...)
  43. #define printk printf
  44. void dm9k_debug_test(void);
  45. static void DM9K_CtrlLinesConfig(void);
  46. static void DM9K_FSMCConfig(void);
  47. static void dm9k_initnic(void);
  48. /*
  49. *********************************************************************************************************
  50. * 函 数 名: dm9k_init
  51. * 功能说明: uIP 接口函数,初始化网卡. uIP 接口函数.
  52. * 形 参: 无
  53. * 返 回 值: 无
  54. *********************************************************************************************************
  55. */
  56. void dm9k_init(void)
  57. {
  58. DM9K_CtrlLinesConfig();
  59. DM9K_FSMCConfig();
  60. s_FSMC_Init_Ok = 1;
  61. dm9k_initnic(); /* 配置DM9000 */
  62. }
  63. /*
  64. *********************************************************************************************************
  65. * 函 数 名: DM9K_CtrlLinesConfig
  66. * 功能说明: 配置DM9000AE控制口线,FSMC管脚设置为复用功能 (For SMT32F4)
  67. * 形 参: 无
  68. * 返 回 值: 无
  69. *********************************************************************************************************
  70. */
  71. static void DM9K_CtrlLinesConfig(void)
  72. {
  73. GPIO_InitTypeDef GPIO_InitStructure;
  74. /* 使能FSMC时钟 */
  75. RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE);
  76. /* 使能 GPIO时钟 */
  77. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOG, ENABLE);
  78. /* 设置 PD.00(D2), PD.01(D3), PD.04(NOE), PD.05(NWE), PD.08(D13), PD.09(D14),
  79. PD.10(D15), PD.14(D0), PD.15(D1) 为复用推挽输出 */
  80. GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_FSMC);
  81. GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_FSMC);
  82. GPIO_PinAFConfig(GPIOD, GPIO_PinSource4, GPIO_AF_FSMC);
  83. GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_FSMC);
  84. GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_FSMC);
  85. GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_FSMC);
  86. GPIO_PinAFConfig(GPIOD, GPIO_PinSource10, GPIO_AF_FSMC);
  87. GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_FSMC);
  88. GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_FSMC);
  89. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 |
  90. GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_14 |
  91. GPIO_Pin_15;
  92. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  93. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  94. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  95. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  96. GPIO_Init(GPIOD, &GPIO_InitStructure);
  97. /* 设置 PE.07(D4), PE.08(D5), PE.09(D6), PE.10(D7), PE.11(D8), PE.12(D9), PE.13(D10),
  98. PE.14(D11), PE.15(D12) 为复用推挽输出 */
  99. GPIO_PinAFConfig(GPIOE, GPIO_PinSource4, GPIO_AF_FSMC);
  100. GPIO_PinAFConfig(GPIOE, GPIO_PinSource5, GPIO_AF_FSMC);
  101. GPIO_PinAFConfig(GPIOE, GPIO_PinSource7, GPIO_AF_FSMC);
  102. GPIO_PinAFConfig(GPIOE, GPIO_PinSource8, GPIO_AF_FSMC);
  103. GPIO_PinAFConfig(GPIOE, GPIO_PinSource9, GPIO_AF_FSMC);
  104. GPIO_PinAFConfig(GPIOE, GPIO_PinSource10, GPIO_AF_FSMC);
  105. GPIO_PinAFConfig(GPIOE, GPIO_PinSource11, GPIO_AF_FSMC);
  106. GPIO_PinAFConfig(GPIOE, GPIO_PinSource12, GPIO_AF_FSMC);
  107. GPIO_PinAFConfig(GPIOE, GPIO_PinSource13, GPIO_AF_FSMC);
  108. GPIO_PinAFConfig(GPIOE, GPIO_PinSource14, GPIO_AF_FSMC);
  109. GPIO_PinAFConfig(GPIOE, GPIO_PinSource15, GPIO_AF_FSMC);
  110. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |
  111. GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 |
  112. GPIO_Pin_15;
  113. GPIO_Init(GPIOE, &GPIO_InitStructure);
  114. /* 设置 PD.13(A18 (RS)) 为复用推挽输出 */
  115. GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_FSMC);
  116. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
  117. GPIO_Init(GPIOD, &GPIO_InitStructure);
  118. /* 设置 PG10 (CS)) 为复用推挽输出 */
  119. GPIO_PinAFConfig(GPIOG, GPIO_PinSource10, GPIO_AF_FSMC);
  120. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  121. GPIO_Init(GPIOG, &GPIO_InitStructure);
  122. /* PA15 是DM9000_INT中断输入口(本程序未使用) */
  123. }
  124. /*
  125. *********************************************************************************************************
  126. * 函 数 名: DM9K_FSMCConfig
  127. * 功能说明: 配置FSMC并口访问时序
  128. * 形 参: 无
  129. * 返 回 值: 无
  130. *********************************************************************************************************
  131. */
  132. static void DM9K_FSMCConfig(void)
  133. {
  134. FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
  135. FSMC_NORSRAMTimingInitTypeDef p;
  136. /*-- FSMC Configuration ------------------------------------------------------*/
  137. /*----------------------- SRAM Bank 3 ----------------------------------------*/
  138. /*-- FSMC Configuration ------------------------------------------------------*/
  139. p.FSMC_AddressSetupTime = 6; /* 设置为2会出错; 3正常 */
  140. p.FSMC_AddressHoldTime = 2;
  141. p.FSMC_DataSetupTime = 4; /* 设置为1出错,2正常 */
  142. p.FSMC_BusTurnAroundDuration = 1;
  143. p.FSMC_CLKDivision = 0;
  144. p.FSMC_DataLatency = 0;
  145. p.FSMC_AccessMode = FSMC_AccessMode_A;
  146. FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM3;
  147. FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
  148. FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM; // FSMC_MemoryType_PSRAM;
  149. FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
  150. FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
  151. FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
  152. FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
  153. FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
  154. FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
  155. FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
  156. FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
  157. FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
  158. FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
  159. FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
  160. FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;
  161. FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);
  162. /*!< Enable FSMC Bank1_SRAM3 Bank */
  163. FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM3, ENABLE);
  164. }
  165. /*
  166. *********************************************************************************************************
  167. * 函 数 名: dm9k_ReadReg
  168. * 功能说明: 读出DM9000指定寄存器的值
  169. * 形 参: reg 寄存器地址
  170. * 返 回 值: 寄存器值
  171. *********************************************************************************************************
  172. */
  173. uint8_t dm9k_ReadReg(uint8_t reg)
  174. {
  175. NET_REG_ADDR = reg;
  176. return (NET_REG_DATA);
  177. }
  178. /*
  179. *********************************************************************************************************
  180. * 函 数 名: dm9k_WriteReg
  181. * 功能说明: 读出DM9000指定寄存器的值
  182. * 形 参: reg :寄存器地址
  183. * writedata : 写入的数据
  184. * 返 回 值: 无
  185. *********************************************************************************************************
  186. */
  187. void dm9k_WriteReg(uint8_t reg, uint8_t writedata)
  188. {
  189. NET_REG_ADDR = reg;
  190. NET_REG_DATA = writedata;
  191. }
  192. /*
  193. *********************************************************************************************************
  194. * 函 数 名: dm9k_hash_table
  195. * 功能说明: 设置 DM9000A MAC 、 广播 、 多播 寄存器
  196. * 形 参: 无
  197. * 返 回 值: 无
  198. *********************************************************************************************************
  199. */
  200. void dm9k_hash_table(void)
  201. {
  202. uint8_t i;
  203. /* 将MAC地址告诉uip */
  204. for (i = 0; i < 6; i++)
  205. {
  206. uip_ethaddr.addr[i] = DEF_MAC_ADDR[i];
  207. }
  208. /* 设置 网卡 MAC 位置,来自於 MyHardware */
  209. for (i = 0; i < 6; i++)
  210. {
  211. dm9k_WriteReg(DM9000_REG_PAR + i, DEF_MAC_ADDR[i]);
  212. }
  213. /* 清除 网卡多播设置 */
  214. for (i = 0; i < 8; i++)
  215. {
  216. dm9k_WriteReg(DM9000_REG_MAR + i, 0x00);
  217. }
  218. /* 设置 广播包 设置 */
  219. dm9k_WriteReg(DM9000_REG_MAR + 7, 0x80);
  220. }
  221. /*
  222. *********************************************************************************************************
  223. * 函 数 名: dm9k_reset
  224. * 功能说明: 软件复位DM9000AE
  225. * 形 参: 无
  226. * 返 回 值: 无
  227. *********************************************************************************************************
  228. */
  229. void dm9k_reset(void)
  230. {
  231. dm9k_WriteReg(DM9000_REG_NCR, DM9000_REG_RESET); /* 对 DM9000A 进行软件重置 */
  232. bsp_DelayUS(10); /* delay 10us */
  233. dm9k_WriteReg(DM9000_REG_NCR, DM9000_REG_RESET); /* 对 DM9000A 进行软件重置 */
  234. bsp_DelayUS(10); /* delay 10us */
  235. /* 基本记存器相关设置 */
  236. dm9k_WriteReg(DM9000_REG_IMR, DM9000_IMR_OFF); /* 开启内存自环模式 */
  237. dm9k_WriteReg(DM9000_REG_TCR2, DM9000_TCR2_SET); /* 设置 LED 显示模式1:全双工亮,半双工灭 */
  238. /* 清除多余资讯 */
  239. dm9k_WriteReg(DM9000_REG_NSR, 0x2c);
  240. dm9k_WriteReg(DM9000_REG_TCR, 0x00);
  241. dm9k_WriteReg(DM9000_REG_ISR, 0x3f);
  242. #ifdef DM9000A_FLOW_CONTROL
  243. dm9k_WriteReg(DM9000_REG_BPTR, DM9000_BPTR_SET); /* 半双工流控设置 */
  244. dm9k_WriteReg(DM9000_REG_FCTR, DM9000_FCTR_SET); /* 全双工流控设置 */
  245. dm9k_WriteReg(DM9000_REG_FCR, DM9000_FCR_SET); /* 开启流控设置 */
  246. #endif
  247. #ifdef DM9000A_UPTO_100M
  248. /* DM9000A无此寄存器 */
  249. dm9k_WriteReg(DM9000_REG_OTCR, DM9000_OTCR_SET); /* 工作频率到 100Mhz 设置 */
  250. #endif
  251. #ifdef Rx_Int_enable
  252. dm9k_WriteReg(DM9000_REG_IMR, DM9000_IMR_SET); /* 开启 中断模式 */
  253. #else
  254. dm9k_WriteReg(DM9000_REG_IMR, DM9000_IMR_OFF); /* 关闭 中断模式 */
  255. #endif
  256. dm9k_WriteReg(DM9000_REG_RCR, DM9000_RCR_SET); /* 开启 接收工能 */
  257. SendPackOk = 0;
  258. }
  259. /*
  260. *********************************************************************************************************
  261. * 函 数 名: dm9k_phy_write
  262. * 功能说明: 软件复位DM9000AE
  263. * 形 参: phy_reg : PHY寄存器地址
  264. * writedata : 写入的数据
  265. * 返 回 值: 无
  266. *********************************************************************************************************
  267. */
  268. void dm9k_phy_write(uint8_t phy_reg, uint16_t writedata)
  269. {
  270. /* 设置写入 PHY 寄存器的位置 */
  271. dm9k_WriteReg(DM9000_REG_EPAR, phy_reg | DM9000_PHY);
  272. /* 设置写入 PHY 寄存器的值 */
  273. dm9k_WriteReg(DM9000_REG_EPDRH, (writedata >> 8) & 0xff);
  274. dm9k_WriteReg(DM9000_REG_EPDRL, writedata & 0xff);
  275. dm9k_WriteReg(DM9000_REG_EPCR, 0x0a); /* 将资料写入 PHY 寄存器 */
  276. while (dm9k_ReadReg(DM9000_REG_EPCR) & 0x01)
  277. ; /* 查寻是否执行结束 */
  278. dm9k_WriteReg(DM9000_REG_EPCR, 0x08); /* 清除写入命令 */
  279. }
  280. /*
  281. *********************************************************************************************************
  282. * 函 数 名: dm9k_initnic
  283. * 功能说明: 配置DM9000AE芯片(初始化)
  284. * 形 参: 无
  285. * 返 回 值: 无
  286. *********************************************************************************************************
  287. */
  288. static void dm9k_initnic(void)
  289. {
  290. dm9k_WriteReg(DM9000_REG_NCR, DM9000_REG_RESET); /* 对 DM9000A 进行软件重置 */
  291. bsp_DelayUS(10); /* delay 10us */
  292. dm9k_hash_table(); /* 设置 DM9000A MAC 及 多播*/
  293. dm9k_reset(); /* 进行 DM9000A 软件设置 */
  294. dm9k_WriteReg(DM9000_REG_GPR, DM9000_PHY_OFF); /* 关闭 PHY ,进行 PHY 设置*/
  295. dm9k_phy_write(0x00, 0x8000); /* 重置 PHY 的寄存器 */
  296. #ifdef DM9000A_FLOW_CONTROL
  297. dm9k_phy_write(0x04, 0x01e1 | 0x0400); /* 设置 自适应模式相容表 */
  298. #else
  299. dm9k_phy_write(0x04, 0x01e1); /* 设置 自适应模式相容表 */
  300. #endif
  301. // dm9k_phy_write(0x00, 0x1000); /* 设置 基本连接模式 */
  302. /* 连接模式设置
  303. 0x0000 : 固定10M半双工
  304. 0x0100 : 固定10M全双工
  305. 0x2000 : 固定100M半双工
  306. 0x2100 : 固定100M全双工
  307. 0x1000 : 自适应模式
  308. */
  309. dm9k_phy_write(0x00, 0x1000); /* 设置 基本连接模式 */
  310. dm9k_WriteReg(DM9000_REG_GPR, DM9000_PHY_ON); /* 结束 PHY 设置, 开启 PHY */
  311. // dm9k_debug_test();
  312. }
  313. /*
  314. *********************************************************************************************************
  315. * 函 数 名: dm9k_receive_packet
  316. * 功能说明: 配置DM9000AE芯片(初始化)
  317. * 形 参: _uip_buf : 接收结果存放的缓冲区指针
  318. * 返 回 值: > 0 表示接收的数据长度, 0表示没有数据
  319. *********************************************************************************************************
  320. */
  321. uint16_t dm9k_receive_packet(uint8_t *_uip_buf)
  322. {
  323. uint16_t ReceiveLength;
  324. uint16_t *ReceiveData;
  325. uint8_t rx_int_count = 0;
  326. uint8_t rx_checkbyte;
  327. uint16_t rx_status, rx_length;
  328. uint8_t jump_packet;
  329. uint16_t i;
  330. uint16_t calc_len;
  331. uint16_t calc_MRR;
  332. do
  333. {
  334. ReceiveLength = 0; /* 清除接收的长度 */
  335. ReceiveData = (uint16_t *)_uip_buf;
  336. jump_packet = 0; /* 清除跳包动作 */
  337. dm9k_ReadReg(DM9000_REG_MRCMDX); /* 读取内存数据,地址不增加 */
  338. /* 计算内存数据位置 */
  339. calc_MRR = (dm9k_ReadReg(DM9000_REG_MRRH) << 8) + dm9k_ReadReg(DM9000_REG_MRRL);
  340. rx_checkbyte = dm9k_ReadReg(DM9000_REG_MRCMDX); /* */
  341. if (rx_checkbyte == DM9000_PKT_RDY) /* 取 */
  342. {
  343. /* 读取封包相关资讯 及 长度 */
  344. NET_REG_ADDR = DM9000_REG_MRCMD;
  345. rx_status = NET_REG_DATA;
  346. rx_length = NET_REG_DATA;
  347. /* 若收到超过系统可承受的封包,此包跳过 */
  348. if (rx_length > Max_Ethernet_Lenth)
  349. jump_packet = 1;
  350. #ifdef Broadcast_Jump
  351. /* 若收到的广播或多播包超过特定长度,此包跳过 */
  352. if (rx_status & 0x4000)
  353. {
  354. if (rx_length > Max_Broadcast_Lenth)
  355. jump_packet = 1;
  356. }
  357. #endif
  358. /* 计算下一个包的指针位 , 若接收长度为奇数,需加一对齐偶字节。*/
  359. /* 若是超过 0x3fff ,则需回归绕到 0x0c00 起始位置 */
  360. calc_MRR += (rx_length + 4);
  361. if (rx_length & 0x01)
  362. calc_MRR++;
  363. if (calc_MRR > 0x3fff)
  364. calc_MRR -= 0x3400;
  365. if (jump_packet == 0x01)
  366. {
  367. /* 将指针移到下一个包的包头位置 */
  368. dm9k_WriteReg(DM9000_REG_MRRH, (calc_MRR >> 8) & 0xff);
  369. dm9k_WriteReg(DM9000_REG_MRRL, calc_MRR & 0xff);
  370. continue;
  371. }
  372. /* 开始将内存的资料搬到到系统中,每次移动一个 word */
  373. calc_len = (rx_length + 1) >> 1;
  374. for (i = 0; i < calc_len; i++)
  375. ReceiveData[i] = NET_REG_DATA;
  376. /* 将包长回报给 TCP/IP 上层,并减去最後 4 BYTE 的 CRC-32 检核码 */
  377. ReceiveLength = rx_length - 4;
  378. rx_int_count++; /* 累计收包次数 */
  379. #ifdef FifoPointCheck
  380. if (calc_MRR != ((dm9k_ReadReg(DM9000_REG_MRRH) << 8) + dm9k_ReadReg(DM9000_REG_MRRL)))
  381. {
  382. #ifdef Point_Error_Reset
  383. dm9k_reset(); /* 若是指针出错,重置 */
  384. return ReceiveLength;
  385. #endif
  386. /*若是指针出错,将指针移到下一个包的包头位置 */
  387. dm9k_WriteReg(DM9000_REG_MRRH, (calc_MRR >> 8) & 0xff);
  388. dm9k_WriteReg(DM9000_REG_MRRL, calc_MRR & 0xff);
  389. }
  390. #endif
  391. return ReceiveLength;
  392. }
  393. else
  394. {
  395. if (rx_checkbyte == DM9000_PKT_NORDY) /* 未收到包 */
  396. {
  397. dm9k_WriteReg(DM9000_REG_ISR, 0x3f); /* */
  398. }
  399. else
  400. {
  401. dm9k_reset(); /* 接收指针出错,重置 */
  402. }
  403. return (0);
  404. }
  405. } while (rx_int_count < Max_Int_Count); /* 是否超过最多接收封包计数 */
  406. return 0;
  407. }
  408. /*
  409. *********************************************************************************************************
  410. * 函 数 名: dm9k_send_packet
  411. * 功能说明: 发送一包数据
  412. * 形 参: p_char : 发送数据缓冲区
  413. * 返 回 值: length : 数据长度
  414. *********************************************************************************************************
  415. */
  416. void dm9k_send_packet(uint8_t *p_char, uint16_t length)
  417. {
  418. uint16_t SendLength = length;
  419. uint16_t *SendData = (uint16_t *)p_char;
  420. uint16_t i;
  421. uint16_t calc_len;
  422. __IO uint16_t calc_MWR;
  423. /* 检查 DM9000A 是否还在传送中!若是等待直到传送结束 */
  424. if (SendPackOk == Max_Send_Pack)
  425. {
  426. while (dm9k_ReadReg(DM9000_REG_TCR) & DM9000_TCR_SET)
  427. {
  428. bsp_DelayUS(5);
  429. }
  430. SendPackOk = 0;
  431. }
  432. SendPackOk++; /* 设置传送计数 */
  433. #ifdef FifoPointCheck
  434. /* 计算下一个传送的指针位 , 若接收长度为奇数,需加一对齐偶字节。*/
  435. /* 若是超过 0x0bff ,则需回归绕到 0x0000 起始位置 */
  436. calc_MWR = (dm9k_ReadReg(DM9000_REG_MWRH) << 8) + dm9k_ReadReg(DM9000_REG_MWRL);
  437. calc_MWR += SendLength;
  438. if (SendLength & 0x01)
  439. calc_MWR++;
  440. if (calc_MWR > 0x0bff)
  441. calc_MWR -= 0x0c00;
  442. #endif
  443. dm9k_WriteReg(DM9000_REG_TXPLH, (SendLength >> 8) & 0xff); /* 设置传送封包的长度 */
  444. dm9k_WriteReg(DM9000_REG_TXPLL, SendLength & 0xff);
  445. /* 开始将系统的资料搬到到内存中,每次移动一个 word */
  446. NET_REG_ADDR = DM9000_REG_MWCMD;
  447. calc_len = (SendLength + 1) >> 1;
  448. for (i = 0; i < calc_len; i++)
  449. NET_REG_DATA = SendData[i];
  450. dm9k_WriteReg(DM9000_REG_TCR, DM9000_TCR_SET); /* 进行传送 */
  451. #ifdef FifoPointCheck
  452. if (calc_MWR != ((dm9k_ReadReg(DM9000_REG_MWRH) << 8) + dm9k_ReadReg(DM9000_REG_MWRL)))
  453. {
  454. #ifdef Point_Error_Reset
  455. /* 若是指针出错,等待此一封包送完 , 之後进行重置 */
  456. while (dm9k_ReadReg(DM9000_REG_TCR) & DM9000_TCR_SET)
  457. bsp_DelayUS(5);
  458. dm9k_reset();
  459. return;
  460. #endif
  461. /*若是指针出错,将指针移到下一个传送包的包头位置 */
  462. dm9k_WriteReg(DM9000_REG_MWRH, (calc_MWR >> 8) & 0xff);
  463. dm9k_WriteReg(DM9000_REG_MWRL, calc_MWR & 0xff);
  464. }
  465. #endif
  466. return;
  467. }
  468. /*
  469. *********************************************************************************************************
  470. * 函 数 名: dm9k_interrupt
  471. * 功能说明: 中断处理函数 (webserver例程未使用中断)
  472. * 形 参: 无
  473. * 返 回 值: 无
  474. *********************************************************************************************************
  475. */
  476. void dm9k_interrupt(void)
  477. {
  478. uint8_t save_reg;
  479. uint16_t isr_status;
  480. save_reg = NET_REG_ADDR; /* 暂存所使用的位置 */
  481. dm9k_WriteReg(DM9000_REG_IMR, DM9000_IMR_OFF); /* 关闭 DM9000A 中断 */
  482. isr_status = dm9k_ReadReg(DM9000_REG_ISR); /* 取得中断产生值 */
  483. if (isr_status & DM9000_RX_INTR)
  484. { /* 检查是否为接收中断 */
  485. // dm9k_receive_packet(); /* 执行接收处理程序 */
  486. }
  487. dm9k_WriteReg(DM9000_REG_IMR, DM9000_IMR_SET); /* 开启 DM9000A 中断 */
  488. NET_REG_ADDR = save_reg; /* 回复所使用的位置 */
  489. }
  490. /*******************************************************************************
  491. * 函数名: dm9k_ReadID
  492. * 参 数: 无
  493. * 返 回: 无
  494. * 功 能: 读取芯片ID
  495. */
  496. uint32_t dm9k_ReadID(void)
  497. {
  498. uint8_t vid1, vid2, pid1, pid2;
  499. if (s_FSMC_Init_Ok == 0)
  500. {
  501. DM9K_CtrlLinesConfig();
  502. DM9K_FSMCConfig();
  503. s_FSMC_Init_Ok = 1;
  504. }
  505. vid1 = dm9k_ReadReg(DM9000_REG_VID_L) & 0xFF;
  506. vid2 = dm9k_ReadReg(DM9000_REG_VID_H) & 0xFF;
  507. pid1 = dm9k_ReadReg(DM9000_REG_PID_L) & 0xFF;
  508. pid2 = dm9k_ReadReg(DM9000_REG_PID_H) & 0xFF;
  509. return (vid2 << 24) | (vid1 << 16) | (pid2 << 8) | pid1;
  510. }
  511. #if 0
  512. /*
  513. *********************************************************************************************************
  514. * 函 数 名: dm9k_debug_test
  515. * 功能说明: 测试DM9000AE的函数,用于排错
  516. * 形 参: 无
  517. * 返 回 值: 无
  518. *********************************************************************************************************
  519. */
  520. void dm9k_debug_test(void)
  521. {
  522. uint32_t check_device;
  523. uint8_t check_iomode;
  524. uint8_t check_reg_fail = 0;
  525. uint8_t check_fifo_fail = 0;
  526. uint16_t i;
  527. uint16_t j;
  528. dm9k_WriteReg(DM9000_REG_NCR, DM9000_REG_RESET); /* 对 DM9000A 进行软件重置 */
  529. bsp_DelayUS(10); /* delay 10us */
  530. dm9k_WriteReg(DM9000_REG_NCR, DM9000_REG_RESET); /* 对 DM9000A 进行软件重置 */
  531. bsp_DelayUS(10); /* delay 10us */
  532. check_device = dm9k_ReadReg(DM9000_REG_VID_L);
  533. check_device |= dm9k_ReadReg(DM9000_REG_VID_H) << 8;
  534. check_device |= dm9k_ReadReg(DM9000_REG_PID_L) << 16;
  535. check_device |= dm9k_ReadReg(DM9000_REG_PID_H) << 24;
  536. if(check_device != 0x90000A46)
  537. {
  538. printk("DM9K_DEBUG ==> DEIVCE NOT FOUND, SYSTEM HOLD !!\n");
  539. while(1);
  540. }
  541. else
  542. {
  543. printk("DM9K_DEBUG ==> DEIVCE FOUND !!\n");
  544. }
  545. check_iomode = dm9k_ReadReg(DM9000_REG_ISR) >> 6;
  546. if(check_iomode != DM9000_WORD_MODE)
  547. {
  548. printk("DM9K_DEBUG ==> DEIVCE NOT WORD MODE, SYSTEM HOLD !!\n");
  549. while(1);
  550. }
  551. else
  552. {
  553. printk("DM9K_DEBUG ==> DEIVCE IS WORD MODE !!\n");
  554. }
  555. printk("DM9K_DEBUG ==> REGISTER R/W TEST !!\n");
  556. NET_REG_ADDR = DM9000_REG_MAR;
  557. for(i = 0; i < 0x0100; i++)
  558. {
  559. NET_REG_DATA = i;
  560. if(i != (NET_REG_DATA & 0xff))
  561. {
  562. printk(" > error W %02x , R %02x \n", i , NET_REG_DATA);
  563. check_reg_fail = 1;
  564. }
  565. }
  566. if(check_reg_fail)
  567. {
  568. printk("DM9K_DEBUG ==> REGISTER R/W FAIL, SYSTEM HOLD !!\n");
  569. while(1);
  570. }
  571. printk("DM9K_DEBUG ==> FIFO R/W TEST !!\n");
  572. printk("DM9K_DEBUG ==> FIFO WRITE START POINT 0x%02x%02x \n",
  573. dm9k_ReadReg(DM9000_REG_MWRH), dm9k_ReadReg(DM9000_REG_MWRL));
  574. NET_REG_ADDR = DM9000_REG_MWCMD;
  575. for(i = 0; i < 0x1000; i++)
  576. NET_REG_DATA = ((i & 0xff) * 0x0101);
  577. printk("DM9K_DEBUG ==> FIFO WRITE END POINT 0x%02x%02x \n",
  578. dm9k_ReadReg(DM9000_REG_MWRH), dm9k_ReadReg(DM9000_REG_MWRL));
  579. if((dm9k_ReadReg(DM9000_REG_MWRH) != 0x20) || (dm9k_ReadReg(DM9000_REG_MWRL) != 0x00))
  580. {
  581. printk("DM9K_DEBUG ==> FIFO WRITE FAIL, SYSTEM HOLD !!\n");
  582. while(1);
  583. }
  584. dm9k_ReadReg(DM9000_REG_MRCMDX);
  585. printk("DM9K_DEBUG ==> FIFO READ START POINT 0x%02x%02x \n",
  586. dm9k_ReadReg(DM9000_REG_MRRH), dm9k_ReadReg(DM9000_REG_MRRL));
  587. dm9k_ReadReg(DM9000_REG_MRCMDX);
  588. NET_REG_ADDR = DM9000_REG_MRCMD;
  589. for(i = 0; i < 0x1000; i++)
  590. {
  591. j = NET_REG_DATA;
  592. if(((i & 0xff) * 0x0101) != j)
  593. {
  594. //printk(" > error W %04x , R %04x \n",
  595. // ((i & 0xff) * 0x0101) , j);
  596. check_fifo_fail = 1;
  597. }
  598. }
  599. printk("DM9K_DEBUG ==> FIFO READ END POINT 0x%02x%02x \n",
  600. dm9k_ReadReg(DM9000_REG_MRRH), dm9k_ReadReg(DM9000_REG_MRRL));
  601. if((dm9k_ReadReg(DM9000_REG_MRRH) != 0x20) || (dm9k_ReadReg(DM9000_REG_MRRL) != 0x00))
  602. {
  603. printk("DM9K_DEBUG ==> FIFO WRITE FAIL, SYSTEM HOLD !!\n");
  604. while(1);
  605. }
  606. if(check_fifo_fail)
  607. {
  608. printk("DM9K_DEBUG ==> FIFO R/W DATA FAIL, SYSTEM HOLD !!\n");
  609. while(1);
  610. }
  611. printk("DM9K_DEBUG ==> PACKET SEND & INT TEST !! \n");
  612. dm9k_WriteReg(DM9000_REG_NCR, DM9000_REG_RESET);
  613. bsp_DelayUS(10);
  614. dm9k_WriteReg(DM9000_REG_NCR, DM9000_REG_RESET);
  615. bsp_DelayUS(10);
  616. dm9k_WriteReg(DM9000_REG_IMR, DM9000_IMR_OFF | DM9000_TX_INTR);
  617. dm9k_WriteReg(DM9000_REG_TXPLH, 0x01);
  618. dm9k_WriteReg(DM9000_REG_TXPLL, 0x00);
  619. do
  620. {
  621. dm9k_WriteReg(DM9000_REG_ISR, DM9000_TX_INTR);
  622. printk("DM9K_DEBUG ==> INT PIN IS OFF\n");
  623. NET_REG_ADDR = DM9000_REG_MWCMD;
  624. for(i = 0; i < (0x0100 / 2); i++)
  625. {
  626. if(i < 3)
  627. NET_REG_DATA = 0xffff;
  628. else
  629. NET_REG_DATA = i * 0x0101;
  630. }
  631. printk("DM9K_DEBUG ==> PACKET IS SEND \n");
  632. dm9k_WriteReg(DM9000_REG_TCR, DM9000_TCR_SET);
  633. while(dm9k_ReadReg(DM9000_REG_TCR) & DM9000_TCR_SET) bsp_DelayUS (5);
  634. if(dm9k_ReadReg(DM9000_REG_ISR) & DM9000_TX_INTR)
  635. printk("DM9K_DEBUG ==> INT PIN IS ACTIVE \n");
  636. else
  637. printk("DM9K_DEBUG ==> INT PIN IS NOT ACTIVE \n");
  638. for(i = 0; i < 10; i++)
  639. bsp_DelayUS(1000);
  640. }while(1);
  641. }
  642. /*
  643. *********************************************************************************************************
  644. * 函 数 名: etherdev_chkmedia
  645. * 功能说明: 检测网络连接状态
  646. * 形 参: 无
  647. * 返 回 值: 无
  648. *********************************************************************************************************
  649. */
  650. void etherdev_chkmedia(void)
  651. {
  652. // uint8_t status;
  653. while(!(dm9k_ReadReg(DM9000_REG_NSR) & DM9000_PHY))
  654. {
  655. bsp_DelayUS(2000);
  656. }
  657. }
  658. /*******************************************************************************
  659. * 函数名: etherdev_poll
  660. * 参 数: 无
  661. * 返 回: 无
  662. * 功 能: uIP 接口函数, 采用查询方式接收一个IP包
  663. */
  664. /*
  665. etherdev_poll()
  666. This function will read an entire IP packet into the uip_buf.
  667. If it must wait for more than 0.5 seconds, it will return with
  668. the return value 0. Otherwise, when a full packet has been read
  669. into the uip_buf buffer, the length of the packet is returned.
  670. */
  671. uint16_t etherdev_poll(void)
  672. {
  673. uint16_t bytes_read = 0;
  674. #if 0
  675. /* tick_count threshold should be 12 for 0.5 sec bail-out
  676. One second (24) worked better for me, but socket recycling
  677. is then slower. I set UIP_TIME_WAIT_TIMEOUT 60 in uipopt.h
  678. to counter this. Retransmission timing etc. is affected also. */
  679. while ((!(bytes_read = etherdev_read())) && (timer0_tick() < 12)) continue;
  680. timer0_reset();
  681. #endif
  682. return bytes_read;
  683. }
  684. #endif