dm9000.c 25 KB

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