My Marlin configs for Fabrikator Mini and CTC i3 Pro B
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lpc17xx_emac.c 31KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963
  1. /**********************************************************************
  2. * $Id$ lpc17xx_emac.c 2010-05-21
  3. *//**
  4. * @file lpc17xx_emac.c
  5. * @brief Contains all functions support for Ethernet MAC firmware
  6. * library on LPC17xx
  7. * @version 2.0
  8. * @date 21. May. 2010
  9. * @author NXP MCU SW Application Team
  10. *
  11. * Copyright(C) 2010, NXP Semiconductor
  12. * All rights reserved.
  13. *
  14. ***********************************************************************
  15. * Software that is described herein is for illustrative purposes only
  16. * which provides customers with programming information regarding the
  17. * products. This software is supplied "AS IS" without any warranties.
  18. * NXP Semiconductors assumes no responsibility or liability for the
  19. * use of the software, conveys no license or title under any patent,
  20. * copyright, or mask work right to the product. NXP Semiconductors
  21. * reserves the right to make changes in the software without
  22. * notification. NXP Semiconductors also make no representation or
  23. * warranty that such application will be suitable for the specified
  24. * use without further testing or modification.
  25. * Permission to use, copy, modify, and distribute this software and its
  26. * documentation is hereby granted, under NXP Semiconductors'
  27. * relevant copyright in the software, without fee, provided that it
  28. * is used in conjunction with NXP Semiconductors microcontrollers. This
  29. * copyright, permission, and disclaimer notice must appear in all copies of
  30. * this code.
  31. **********************************************************************/
  32. /* Peripheral group ----------------------------------------------------------- */
  33. /** @addtogroup EMAC
  34. * @{
  35. */
  36. /* Includes ------------------------------------------------------------------- */
  37. #include "lpc17xx_emac.h"
  38. #include "lpc17xx_clkpwr.h"
  39. /* If this source file built with example, the LPC17xx FW library configuration
  40. * file in each example directory ("lpc17xx_libcfg.h") must be included,
  41. * otherwise the default FW library configuration file must be included instead
  42. */
  43. #ifdef __BUILD_WITH_EXAMPLE__
  44. #include "lpc17xx_libcfg.h"
  45. #else
  46. #include "lpc17xx_libcfg_default.h"
  47. #endif /* __BUILD_WITH_EXAMPLE__ */
  48. #ifdef _EMAC
  49. /* Private Variables ---------------------------------------------------------- */
  50. /** @defgroup EMAC_Private_Variables EMAC Private Variables
  51. * @{
  52. */
  53. /* MII Mgmt Configuration register - Clock divider setting */
  54. const uint8_t EMAC_clkdiv[] = { 4, 6, 8, 10, 14, 20, 28, 36, 40, 44, 48, 52, 56, 60, 64};
  55. /* EMAC local DMA Descriptors */
  56. /** Rx Descriptor data array */
  57. static RX_Desc Rx_Desc[EMAC_NUM_RX_FRAG];
  58. /** Rx Status data array - Must be 8-Byte aligned */
  59. #if defined ( __CC_ARM )
  60. static __align(8) RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG];
  61. #elif defined ( __ICCARM__ )
  62. #pragma data_alignment=8
  63. static RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG];
  64. #elif defined ( __GNUC__ )
  65. static __attribute__ ((aligned (8))) RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG];
  66. #endif
  67. /** Tx Descriptor data array */
  68. static TX_Desc Tx_Desc[EMAC_NUM_TX_FRAG];
  69. /** Tx Status data array */
  70. static TX_Stat Tx_Stat[EMAC_NUM_TX_FRAG];
  71. /* EMAC local DMA buffers */
  72. /** Rx buffer data */
  73. static uint32_t rx_buf[EMAC_NUM_RX_FRAG][EMAC_ETH_MAX_FLEN>>2];
  74. /** Tx buffer data */
  75. static uint32_t tx_buf[EMAC_NUM_TX_FRAG][EMAC_ETH_MAX_FLEN>>2];
  76. /**
  77. * @}
  78. */
  79. /* Private Functions ---------------------------------------------------------- */
  80. static void rx_descr_init (void);
  81. static void tx_descr_init (void);
  82. static int32_t write_PHY (uint32_t PhyReg, uint16_t Value);
  83. static int32_t read_PHY (uint32_t PhyReg);
  84. static void setEmacAddr(uint8_t abStationAddr[]);
  85. static int32_t emac_CRCCalc(uint8_t frame_no_fcs[], int32_t frame_len);
  86. /*--------------------------- rx_descr_init ---------------------------------*/
  87. /*********************************************************************//**
  88. * @brief Initializes RX Descriptor
  89. * @param[in] None
  90. * @return None
  91. ***********************************************************************/
  92. static void rx_descr_init (void)
  93. {
  94. /* Initialize Receive Descriptor and Status array. */
  95. uint32_t i;
  96. for (i = 0; i < EMAC_NUM_RX_FRAG; i++) {
  97. Rx_Desc[i].Packet = (uint32_t)&rx_buf[i];
  98. Rx_Desc[i].Ctrl = EMAC_RCTRL_INT | (EMAC_ETH_MAX_FLEN - 1);
  99. Rx_Stat[i].Info = 0;
  100. Rx_Stat[i].HashCRC = 0;
  101. }
  102. /* Set EMAC Receive Descriptor Registers. */
  103. LPC_EMAC->RxDescriptor = (uint32_t)&Rx_Desc[0];
  104. LPC_EMAC->RxStatus = (uint32_t)&Rx_Stat[0];
  105. LPC_EMAC->RxDescriptorNumber = EMAC_NUM_RX_FRAG - 1;
  106. /* Rx Descriptors Point to 0 */
  107. LPC_EMAC->RxConsumeIndex = 0;
  108. }
  109. /*--------------------------- tx_descr_init ---- ----------------------------*/
  110. /*********************************************************************//**
  111. * @brief Initializes TX Descriptor
  112. * @param[in] None
  113. * @return None
  114. ***********************************************************************/
  115. static void tx_descr_init (void) {
  116. /* Initialize Transmit Descriptor and Status array. */
  117. uint32_t i;
  118. for (i = 0; i < EMAC_NUM_TX_FRAG; i++) {
  119. Tx_Desc[i].Packet = (uint32_t)&tx_buf[i];
  120. Tx_Desc[i].Ctrl = 0;
  121. Tx_Stat[i].Info = 0;
  122. }
  123. /* Set EMAC Transmit Descriptor Registers. */
  124. LPC_EMAC->TxDescriptor = (uint32_t)&Tx_Desc[0];
  125. LPC_EMAC->TxStatus = (uint32_t)&Tx_Stat[0];
  126. LPC_EMAC->TxDescriptorNumber = EMAC_NUM_TX_FRAG - 1;
  127. /* Tx Descriptors Point to 0 */
  128. LPC_EMAC->TxProduceIndex = 0;
  129. }
  130. /*--------------------------- write_PHY -------------------------------------*/
  131. /*********************************************************************//**
  132. * @brief Write value to PHY device
  133. * @param[in] PhyReg: PHY Register address
  134. * @param[in] Value: Value to write
  135. * @return 0 - if success
  136. * 1 - if fail
  137. ***********************************************************************/
  138. static int32_t write_PHY (uint32_t PhyReg, uint16_t Value)
  139. {
  140. /* Write a data 'Value' to PHY register 'PhyReg'. */
  141. uint32_t tout;
  142. LPC_EMAC->MADR = EMAC_DEF_ADR | PhyReg;
  143. LPC_EMAC->MWTD = Value;
  144. /* Wait until operation completed */
  145. tout = 0;
  146. for (tout = 0; tout < EMAC_MII_WR_TOUT; tout++) {
  147. if ((LPC_EMAC->MIND & EMAC_MIND_BUSY) == 0) {
  148. return (0);
  149. }
  150. }
  151. // Time out!
  152. return (-1);
  153. }
  154. /*--------------------------- read_PHY --------------------------------------*/
  155. /*********************************************************************//**
  156. * @brief Read value from PHY device
  157. * @param[in] PhyReg: PHY Register address
  158. * @return 0 - if success
  159. * 1 - if fail
  160. ***********************************************************************/
  161. static int32_t read_PHY (uint32_t PhyReg)
  162. {
  163. /* Read a PHY register 'PhyReg'. */
  164. uint32_t tout;
  165. LPC_EMAC->MADR = EMAC_DEF_ADR | PhyReg;
  166. LPC_EMAC->MCMD = EMAC_MCMD_READ;
  167. /* Wait until operation completed */
  168. tout = 0;
  169. for (tout = 0; tout < EMAC_MII_RD_TOUT; tout++) {
  170. if ((LPC_EMAC->MIND & EMAC_MIND_BUSY) == 0) {
  171. LPC_EMAC->MCMD = 0;
  172. return (LPC_EMAC->MRDD);
  173. }
  174. }
  175. // Time out!
  176. return (-1);
  177. }
  178. /*********************************************************************//**
  179. * @brief Set Station MAC address for EMAC module
  180. * @param[in] abStationAddr Pointer to Station address that contains 6-bytes
  181. * of MAC address (should be in order from MAC Address 1 to MAC Address 6)
  182. * @return None
  183. **********************************************************************/
  184. static void setEmacAddr(uint8_t abStationAddr[])
  185. {
  186. /* Set the Ethernet MAC Address registers */
  187. LPC_EMAC->SA0 = ((uint32_t)abStationAddr[5] << 8) | (uint32_t)abStationAddr[4];
  188. LPC_EMAC->SA1 = ((uint32_t)abStationAddr[3] << 8) | (uint32_t)abStationAddr[2];
  189. LPC_EMAC->SA2 = ((uint32_t)abStationAddr[1] << 8) | (uint32_t)abStationAddr[0];
  190. }
  191. /*********************************************************************//**
  192. * @brief Calculates CRC code for number of bytes in the frame
  193. * @param[in] frame_no_fcs Pointer to the first byte of the frame
  194. * @param[in] frame_len length of the frame without the FCS
  195. * @return the CRC as a 32 bit integer
  196. **********************************************************************/
  197. static int32_t emac_CRCCalc(uint8_t frame_no_fcs[], int32_t frame_len)
  198. {
  199. int i; // iterator
  200. int j; // another iterator
  201. char byte; // current byte
  202. int crc; // CRC result
  203. int q0, q1, q2, q3; // temporary variables
  204. crc = 0xFFFFFFFF;
  205. for (i = 0; i < frame_len; i++) {
  206. byte = *frame_no_fcs++;
  207. for (j = 0; j < 2; j++) {
  208. if (((crc >> 28) ^ (byte >> 3)) & 0x00000001) {
  209. q3 = 0x04C11DB7;
  210. } else {
  211. q3 = 0x00000000;
  212. }
  213. if (((crc >> 29) ^ (byte >> 2)) & 0x00000001) {
  214. q2 = 0x09823B6E;
  215. } else {
  216. q2 = 0x00000000;
  217. }
  218. if (((crc >> 30) ^ (byte >> 1)) & 0x00000001) {
  219. q1 = 0x130476DC;
  220. } else {
  221. q1 = 0x00000000;
  222. }
  223. if (((crc >> 31) ^ (byte >> 0)) & 0x00000001) {
  224. q0 = 0x2608EDB8;
  225. } else {
  226. q0 = 0x00000000;
  227. }
  228. crc = (crc << 4) ^ q3 ^ q2 ^ q1 ^ q0;
  229. byte >>= 4;
  230. }
  231. }
  232. return crc;
  233. }
  234. /* End of Private Functions --------------------------------------------------- */
  235. /* Public Functions ----------------------------------------------------------- */
  236. /** @addtogroup EMAC_Public_Functions
  237. * @{
  238. */
  239. /*********************************************************************//**
  240. * @brief Initializes the EMAC peripheral according to the specified
  241. * parameters in the EMAC_ConfigStruct.
  242. * @param[in] EMAC_ConfigStruct Pointer to a EMAC_CFG_Type structure
  243. * that contains the configuration information for the
  244. * specified EMAC peripheral.
  245. * @return None
  246. *
  247. * Note: This function will initialize EMAC module according to procedure below:
  248. * - Remove the soft reset condition from the MAC
  249. * - Configure the PHY via the MIIM interface of the MAC
  250. * - Select RMII mode
  251. * - Configure the transmit and receive DMA engines, including the descriptor arrays
  252. * - Configure the host registers (MAC1,MAC2 etc.) in the MAC
  253. * - Enable the receive and transmit data paths
  254. * In default state after initializing, only Rx Done and Tx Done interrupt are enabled,
  255. * all remain interrupts are disabled
  256. * (Ref. from LPC17xx UM)
  257. **********************************************************************/
  258. Status EMAC_Init(EMAC_CFG_Type *EMAC_ConfigStruct)
  259. {
  260. /* Initialize the EMAC Ethernet controller. */
  261. int32_t regv,tout, tmp;
  262. /* Set up clock and power for Ethernet module */
  263. CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCENET, ENABLE);
  264. /* Reset all EMAC internal modules */
  265. LPC_EMAC->MAC1 = EMAC_MAC1_RES_TX | EMAC_MAC1_RES_MCS_TX | EMAC_MAC1_RES_RX |
  266. EMAC_MAC1_RES_MCS_RX | EMAC_MAC1_SIM_RES | EMAC_MAC1_SOFT_RES;
  267. LPC_EMAC->Command = EMAC_CR_REG_RES | EMAC_CR_TX_RES | EMAC_CR_RX_RES | EMAC_CR_PASS_RUNT_FRM;
  268. /* A short delay after reset. */
  269. for (tout = 100; tout; tout--);
  270. /* Initialize MAC control registers. */
  271. LPC_EMAC->MAC1 = EMAC_MAC1_PASS_ALL;
  272. LPC_EMAC->MAC2 = EMAC_MAC2_CRC_EN | EMAC_MAC2_PAD_EN;
  273. LPC_EMAC->MAXF = EMAC_ETH_MAX_FLEN;
  274. /*
  275. * Find the clock that close to desired target clock
  276. */
  277. tmp = SystemCoreClock / EMAC_MCFG_MII_MAXCLK;
  278. for (tout = 0; tout < sizeof (EMAC_clkdiv); tout++){
  279. if (EMAC_clkdiv[tout] >= tmp) break;
  280. }
  281. tout++;
  282. // Write to MAC configuration register and reset
  283. LPC_EMAC->MCFG = EMAC_MCFG_CLK_SEL(tout) | EMAC_MCFG_RES_MII;
  284. // release reset
  285. LPC_EMAC->MCFG &= ~(EMAC_MCFG_RES_MII);
  286. LPC_EMAC->CLRT = EMAC_CLRT_DEF;
  287. LPC_EMAC->IPGR = EMAC_IPGR_P2_DEF;
  288. /* Enable Reduced MII interface. */
  289. LPC_EMAC->Command = EMAC_CR_RMII | EMAC_CR_PASS_RUNT_FRM;
  290. /* Reset Reduced MII Logic. */
  291. // LPC_EMAC->SUPP = EMAC_SUPP_RES_RMII;
  292. for (tout = 100; tout; tout--);
  293. LPC_EMAC->SUPP = 0;
  294. /* Put the DP83848C in reset mode */
  295. write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_BMCR_RESET);
  296. /* Wait for hardware reset to end. */
  297. for (tout = EMAC_PHY_RESP_TOUT; tout>=0; tout--) {
  298. regv = read_PHY (EMAC_PHY_REG_BMCR);
  299. if (!(regv & (EMAC_PHY_BMCR_RESET | EMAC_PHY_BMCR_POWERDOWN))) {
  300. /* Reset complete, device not Power Down. */
  301. break;
  302. }
  303. if (tout == 0){
  304. // Time out, return ERROR
  305. return (ERROR);
  306. }
  307. }
  308. // Set PHY mode
  309. if (EMAC_SetPHYMode(EMAC_ConfigStruct->Mode) < 0){
  310. return (ERROR);
  311. }
  312. // Set EMAC address
  313. setEmacAddr(EMAC_ConfigStruct->pbEMAC_Addr);
  314. /* Initialize Tx and Rx DMA Descriptors */
  315. rx_descr_init ();
  316. tx_descr_init ();
  317. // Set Receive Filter register: enable broadcast and multicast
  318. LPC_EMAC->RxFilterCtrl = EMAC_RFC_MCAST_EN | EMAC_RFC_BCAST_EN | EMAC_RFC_PERFECT_EN;
  319. /* Enable Rx Done and Tx Done interrupt for EMAC */
  320. LPC_EMAC->IntEnable = EMAC_INT_RX_DONE | EMAC_INT_TX_DONE;
  321. /* Reset all interrupts */
  322. LPC_EMAC->IntClear = 0xFFFF;
  323. /* Enable receive and transmit mode of MAC Ethernet core */
  324. LPC_EMAC->Command |= (EMAC_CR_RX_EN | EMAC_CR_TX_EN);
  325. LPC_EMAC->MAC1 |= EMAC_MAC1_REC_EN;
  326. return SUCCESS;
  327. }
  328. /*********************************************************************//**
  329. * @brief De-initializes the EMAC peripheral registers to their
  330. * default reset values.
  331. * @param[in] None
  332. * @return None
  333. **********************************************************************/
  334. void EMAC_DeInit(void)
  335. {
  336. // Disable all interrupt
  337. LPC_EMAC->IntEnable = 0x00;
  338. // Clear all pending interrupt
  339. LPC_EMAC->IntClear = (0xFF) | (EMAC_INT_SOFT_INT | EMAC_INT_WAKEUP);
  340. /* TurnOff clock and power for Ethernet module */
  341. CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCENET, DISABLE);
  342. }
  343. /*********************************************************************//**
  344. * @brief Check specified PHY status in EMAC peripheral
  345. * @param[in] ulPHYState Specified PHY Status Type, should be:
  346. * - EMAC_PHY_STAT_LINK: Link Status
  347. * - EMAC_PHY_STAT_SPEED: Speed Status
  348. * - EMAC_PHY_STAT_DUP: Duplex Status
  349. * @return Status of specified PHY status (0 or 1).
  350. * (-1) if error.
  351. *
  352. * Note:
  353. * For EMAC_PHY_STAT_LINK, return value:
  354. * - 0: Link Down
  355. * - 1: Link Up
  356. * For EMAC_PHY_STAT_SPEED, return value:
  357. * - 0: 10Mbps
  358. * - 1: 100Mbps
  359. * For EMAC_PHY_STAT_DUP, return value:
  360. * - 0: Half-Duplex
  361. * - 1: Full-Duplex
  362. **********************************************************************/
  363. int32_t EMAC_CheckPHYStatus(uint32_t ulPHYState)
  364. {
  365. int32_t regv, tmp;
  366. #ifdef MCB_LPC_1768
  367. regv = read_PHY (EMAC_PHY_REG_STS);
  368. switch(ulPHYState){
  369. case EMAC_PHY_STAT_LINK:
  370. tmp = (regv & EMAC_PHY_SR_LINK) ? 1 : 0;
  371. break;
  372. case EMAC_PHY_STAT_SPEED:
  373. tmp = (regv & EMAC_PHY_SR_SPEED) ? 0 : 1;
  374. break;
  375. case EMAC_PHY_STAT_DUP:
  376. tmp = (regv & EMAC_PHY_SR_FULL_DUP) ? 1 : 0;
  377. break;
  378. #elif defined(IAR_LPC_1768)
  379. /* Use IAR_LPC_1768 board:
  380. * FSZ8721BL doesn't have Status Register
  381. * so we read Basic Mode Status Register (0x01h) instead
  382. */
  383. regv = read_PHY (EMAC_PHY_REG_BMSR);
  384. switch(ulPHYState){
  385. case EMAC_PHY_STAT_LINK:
  386. tmp = (regv & EMAC_PHY_BMSR_LINK_STATUS) ? 1 : 0;
  387. break;
  388. case EMAC_PHY_STAT_SPEED:
  389. tmp = (regv & EMAC_PHY_SR_100_SPEED) ? 1 : 0;
  390. break;
  391. case EMAC_PHY_STAT_DUP:
  392. tmp = (regv & EMAC_PHY_SR_FULL_DUP) ? 1 : 0;
  393. break;
  394. #endif
  395. default:
  396. tmp = -1;
  397. break;
  398. }
  399. return (tmp);
  400. }
  401. /*********************************************************************//**
  402. * @brief Set specified PHY mode in EMAC peripheral
  403. * @param[in] ulPHYMode Specified PHY mode, should be:
  404. * - EMAC_MODE_AUTO
  405. * - EMAC_MODE_10M_FULL
  406. * - EMAC_MODE_10M_HALF
  407. * - EMAC_MODE_100M_FULL
  408. * - EMAC_MODE_100M_HALF
  409. * @return Return (0) if no error, otherwise return (-1)
  410. **********************************************************************/
  411. int32_t EMAC_SetPHYMode(uint32_t ulPHYMode)
  412. {
  413. int32_t id1, id2, tout;
  414. /* Check if this is a DP83848C PHY. */
  415. id1 = read_PHY (EMAC_PHY_REG_IDR1);
  416. id2 = read_PHY (EMAC_PHY_REG_IDR2);
  417. #ifdef MCB_LPC_1768
  418. if (((id1 << 16) | (id2 & 0xFFF0)) == EMAC_DP83848C_ID) {
  419. switch(ulPHYMode){
  420. case EMAC_MODE_AUTO:
  421. write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_AUTO_NEG);
  422. #elif defined(IAR_LPC_1768) /* Use IAR LPC1768 KickStart board */
  423. if (((id1 << 16) | id2) == EMAC_KSZ8721BL_ID) {
  424. /* Configure the PHY device */
  425. switch(ulPHYMode){
  426. case EMAC_MODE_AUTO:
  427. /* Use auto-negotiation about the link speed. */
  428. write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_AUTO_NEG);
  429. // write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_BMCR_AN);
  430. #endif
  431. /* Wait to complete Auto_Negotiation */
  432. for (tout = EMAC_PHY_RESP_TOUT; tout>=0; tout--) {
  433. }
  434. break;
  435. case EMAC_MODE_10M_FULL:
  436. /* Connect at 10MBit full-duplex */
  437. write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_FULLD_10M);
  438. break;
  439. case EMAC_MODE_10M_HALF:
  440. /* Connect at 10MBit half-duplex */
  441. write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_HALFD_10M);
  442. break;
  443. case EMAC_MODE_100M_FULL:
  444. /* Connect at 100MBit full-duplex */
  445. write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_FULLD_100M);
  446. break;
  447. case EMAC_MODE_100M_HALF:
  448. /* Connect at 100MBit half-duplex */
  449. write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_HALFD_100M);
  450. break;
  451. default:
  452. // un-supported
  453. return (-1);
  454. }
  455. }
  456. // It's not correct module ID
  457. else {
  458. return (-1);
  459. }
  460. // Update EMAC configuration with current PHY status
  461. if (EMAC_UpdatePHYStatus() < 0){
  462. return (-1);
  463. }
  464. // Complete
  465. return (0);
  466. }
  467. /*********************************************************************//**
  468. * @brief Auto-Configures value for the EMAC configuration register to
  469. * match with current PHY mode
  470. * @param[in] None
  471. * @return Return (0) if no error, otherwise return (-1)
  472. *
  473. * Note: The EMAC configuration will be auto-configured:
  474. * - Speed mode.
  475. * - Half/Full duplex mode
  476. **********************************************************************/
  477. int32_t EMAC_UpdatePHYStatus(void)
  478. {
  479. int32_t regv, tout;
  480. /* Check the link status. */
  481. #ifdef MCB_LPC_1768
  482. for (tout = EMAC_PHY_RESP_TOUT; tout>=0; tout--) {
  483. regv = read_PHY (EMAC_PHY_REG_STS);
  484. if (regv & EMAC_PHY_SR_LINK) {
  485. /* Link is on. */
  486. break;
  487. }
  488. if (tout == 0){
  489. // time out
  490. return (-1);
  491. }
  492. }
  493. /* Configure Full/Half Duplex mode. */
  494. if (regv & EMAC_PHY_SR_DUP) {
  495. /* Full duplex is enabled. */
  496. LPC_EMAC->MAC2 |= EMAC_MAC2_FULL_DUP;
  497. LPC_EMAC->Command |= EMAC_CR_FULL_DUP;
  498. LPC_EMAC->IPGT = EMAC_IPGT_FULL_DUP;
  499. } else {
  500. /* Half duplex mode. */
  501. LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP;
  502. }
  503. if (regv & EMAC_PHY_SR_SPEED) {
  504. /* 10MBit mode. */
  505. LPC_EMAC->SUPP = 0;
  506. } else {
  507. /* 100MBit mode. */
  508. LPC_EMAC->SUPP = EMAC_SUPP_SPEED;
  509. }
  510. #elif defined(IAR_LPC_1768)
  511. for (tout = EMAC_PHY_RESP_TOUT; tout>=0; tout--) {
  512. regv = read_PHY (EMAC_PHY_REG_BMSR);
  513. if (regv & EMAC_PHY_BMSR_LINK_STATUS) {
  514. /* Link is on. */
  515. break;
  516. }
  517. if (tout == 0){
  518. // time out
  519. return (-1);
  520. }
  521. }
  522. /* Configure Full/Half Duplex mode. */
  523. if (regv & EMAC_PHY_SR_FULL_DUP) {
  524. /* Full duplex is enabled. */
  525. LPC_EMAC->MAC2 |= EMAC_MAC2_FULL_DUP;
  526. LPC_EMAC->Command |= EMAC_CR_FULL_DUP;
  527. LPC_EMAC->IPGT = EMAC_IPGT_FULL_DUP;
  528. } else {
  529. /* Half duplex mode. */
  530. LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP;
  531. }
  532. /* Configure 100MBit/10MBit mode. */
  533. if (!(regv & EMAC_PHY_SR_100_SPEED)) {
  534. /* 10MBit mode. */
  535. LPC_EMAC->SUPP = 0;
  536. } else {
  537. /* 100MBit mode. */
  538. LPC_EMAC->SUPP = EMAC_SUPP_SPEED;
  539. }
  540. #endif
  541. // Complete
  542. return (0);
  543. }
  544. /*********************************************************************//**
  545. * @brief Enable/Disable hash filter functionality for specified destination
  546. * MAC address in EMAC module
  547. * @param[in] dstMAC_addr Pointer to the first MAC destination address, should
  548. * be 6-bytes length, in order LSB to the MSB
  549. * @param[in] NewState New State of this command, should be:
  550. * - ENABLE.
  551. * - DISABLE.
  552. * @return None
  553. *
  554. * Note:
  555. * The standard Ethernet cyclic redundancy check (CRC) function is calculated from
  556. * the 6 byte destination address in the Ethernet frame (this CRC is calculated
  557. * anyway as part of calculating the CRC of the whole frame), then bits [28:23] out of
  558. * the 32 bits CRC result are taken to form the hash. The 6 bit hash is used to access
  559. * the hash table: it is used as an index in the 64 bit HashFilter register that has been
  560. * programmed with accept values. If the selected accept value is 1, the frame is
  561. * accepted.
  562. **********************************************************************/
  563. void EMAC_SetHashFilter(uint8_t dstMAC_addr[], FunctionalState NewState)
  564. {
  565. uint32_t *pReg;
  566. uint32_t tmp;
  567. int32_t crc;
  568. // Calculate the CRC from the destination MAC address
  569. crc = emac_CRCCalc(dstMAC_addr, 6);
  570. // Extract the value from CRC to get index value for hash filter table
  571. crc = (crc >> 23) & 0x3F;
  572. pReg = (crc > 31) ? ((uint32_t *)&LPC_EMAC->HashFilterH) \
  573. : ((uint32_t *)&LPC_EMAC->HashFilterL);
  574. tmp = (crc > 31) ? (crc - 32) : crc;
  575. if (NewState == ENABLE) {
  576. (*pReg) |= (1UL << tmp);
  577. } else {
  578. (*pReg) &= ~(1UL << tmp);
  579. }
  580. // Enable Rx Filter
  581. LPC_EMAC->Command &= ~EMAC_CR_PASS_RX_FILT;
  582. }
  583. /*********************************************************************//**
  584. * @brief Enable/Disable Filter mode for each specified type EMAC peripheral
  585. * @param[in] ulFilterMode Filter mode, should be:
  586. * - EMAC_RFC_UCAST_EN: all frames of unicast types
  587. * will be accepted
  588. * - EMAC_RFC_BCAST_EN: broadcast frame will be
  589. * accepted
  590. * - EMAC_RFC_MCAST_EN: all frames of multicast
  591. * types will be accepted
  592. * - EMAC_RFC_UCAST_HASH_EN: The imperfect hash
  593. * filter will be applied to unicast addresses
  594. * - EMAC_RFC_MCAST_HASH_EN: The imperfect hash
  595. * filter will be applied to multicast addresses
  596. * - EMAC_RFC_PERFECT_EN: the destination address
  597. * will be compared with the 6 byte station address
  598. * programmed in the station address by the filter
  599. * - EMAC_RFC_MAGP_WOL_EN: the result of the magic
  600. * packet filter will generate a WoL interrupt when
  601. * there is a match
  602. * - EMAC_RFC_PFILT_WOL_EN: the result of the perfect address
  603. * matching filter and the imperfect hash filter will
  604. * generate a WoL interrupt when there is a match
  605. * @param[in] NewState New State of this command, should be:
  606. * - ENABLE
  607. * - DISABLE
  608. * @return None
  609. **********************************************************************/
  610. void EMAC_SetFilterMode(uint32_t ulFilterMode, FunctionalState NewState)
  611. {
  612. if (NewState == ENABLE){
  613. LPC_EMAC->RxFilterCtrl |= ulFilterMode;
  614. } else {
  615. LPC_EMAC->RxFilterCtrl &= ~ulFilterMode;
  616. }
  617. }
  618. /*********************************************************************//**
  619. * @brief Get status of Wake On LAN Filter for each specified
  620. * type in EMAC peripheral, clear this status if it is set
  621. * @param[in] ulWoLMode WoL Filter mode, should be:
  622. * - EMAC_WOL_UCAST: unicast frames caused WoL
  623. * - EMAC_WOL_UCAST: broadcast frame caused WoL
  624. * - EMAC_WOL_MCAST: multicast frame caused WoL
  625. * - EMAC_WOL_UCAST_HASH: unicast frame that passes the
  626. * imperfect hash filter caused WoL
  627. * - EMAC_WOL_MCAST_HASH: multicast frame that passes the
  628. * imperfect hash filter caused WoL
  629. * - EMAC_WOL_PERFECT:perfect address matching filter
  630. * caused WoL
  631. * - EMAC_WOL_RX_FILTER: the receive filter caused WoL
  632. * - EMAC_WOL_MAG_PACKET: the magic packet filter caused WoL
  633. * @return SET/RESET
  634. **********************************************************************/
  635. FlagStatus EMAC_GetWoLStatus(uint32_t ulWoLMode)
  636. {
  637. if (LPC_EMAC->RxFilterWoLStatus & ulWoLMode) {
  638. LPC_EMAC->RxFilterWoLClear = ulWoLMode;
  639. return SET;
  640. } else {
  641. return RESET;
  642. }
  643. }
  644. /*********************************************************************//**
  645. * @brief Write data to Tx packet data buffer at current index due to
  646. * TxProduceIndex
  647. * @param[in] pDataStruct Pointer to a EMAC_PACKETBUF_Type structure
  648. * data that contain specified information about
  649. * Packet data buffer.
  650. * @return None
  651. **********************************************************************/
  652. void EMAC_WritePacketBuffer(EMAC_PACKETBUF_Type *pDataStruct)
  653. {
  654. uint32_t idx,len;
  655. uint32_t *sp,*dp;
  656. idx = LPC_EMAC->TxProduceIndex;
  657. sp = (uint32_t *)pDataStruct->pbDataBuf;
  658. dp = (uint32_t *)Tx_Desc[idx].Packet;
  659. /* Copy frame data to EMAC packet buffers. */
  660. for (len = (pDataStruct->ulDataLen + 3) >> 2; len; len--) {
  661. *dp++ = *sp++;
  662. }
  663. Tx_Desc[idx].Ctrl = (pDataStruct->ulDataLen - 1) | (EMAC_TCTRL_INT | EMAC_TCTRL_LAST);
  664. }
  665. /*********************************************************************//**
  666. * @brief Read data from Rx packet data buffer at current index due
  667. * to RxConsumeIndex
  668. * @param[in] pDataStruct Pointer to a EMAC_PACKETBUF_Type structure
  669. * data that contain specified information about
  670. * Packet data buffer.
  671. * @return None
  672. **********************************************************************/
  673. void EMAC_ReadPacketBuffer(EMAC_PACKETBUF_Type *pDataStruct)
  674. {
  675. uint32_t idx, len;
  676. uint32_t *dp, *sp;
  677. idx = LPC_EMAC->RxConsumeIndex;
  678. dp = (uint32_t *)pDataStruct->pbDataBuf;
  679. sp = (uint32_t *)Rx_Desc[idx].Packet;
  680. if (pDataStruct->pbDataBuf != NULL) {
  681. for (len = (pDataStruct->ulDataLen + 3) >> 2; len; len--) {
  682. *dp++ = *sp++;
  683. }
  684. }
  685. }
  686. /*********************************************************************//**
  687. * @brief Enable/Disable interrupt for each type in EMAC
  688. * @param[in] ulIntType Interrupt Type, should be:
  689. * - EMAC_INT_RX_OVERRUN: Receive Overrun
  690. * - EMAC_INT_RX_ERR: Receive Error
  691. * - EMAC_INT_RX_FIN: Receive Descriptor Finish
  692. * - EMAC_INT_RX_DONE: Receive Done
  693. * - EMAC_INT_TX_UNDERRUN: Transmit Under-run
  694. * - EMAC_INT_TX_ERR: Transmit Error
  695. * - EMAC_INT_TX_FIN: Transmit descriptor finish
  696. * - EMAC_INT_TX_DONE: Transmit Done
  697. * - EMAC_INT_SOFT_INT: Software interrupt
  698. * - EMAC_INT_WAKEUP: Wakeup interrupt
  699. * @param[in] NewState New State of this function, should be:
  700. * - ENABLE.
  701. * - DISABLE.
  702. * @return None
  703. **********************************************************************/
  704. void EMAC_IntCmd(uint32_t ulIntType, FunctionalState NewState)
  705. {
  706. if (NewState == ENABLE) {
  707. LPC_EMAC->IntEnable |= ulIntType;
  708. } else {
  709. LPC_EMAC->IntEnable &= ~(ulIntType);
  710. }
  711. }
  712. /*********************************************************************//**
  713. * @brief Check whether if specified interrupt flag is set or not
  714. * for each interrupt type in EMAC and clear interrupt pending
  715. * if it is set.
  716. * @param[in] ulIntType Interrupt Type, should be:
  717. * - EMAC_INT_RX_OVERRUN: Receive Overrun
  718. * - EMAC_INT_RX_ERR: Receive Error
  719. * - EMAC_INT_RX_FIN: Receive Descriptor Finish
  720. * - EMAC_INT_RX_DONE: Receive Done
  721. * - EMAC_INT_TX_UNDERRUN: Transmit Under-run
  722. * - EMAC_INT_TX_ERR: Transmit Error
  723. * - EMAC_INT_TX_FIN: Transmit descriptor finish
  724. * - EMAC_INT_TX_DONE: Transmit Done
  725. * - EMAC_INT_SOFT_INT: Software interrupt
  726. * - EMAC_INT_WAKEUP: Wakeup interrupt
  727. * @return New state of specified interrupt (SET or RESET)
  728. **********************************************************************/
  729. IntStatus EMAC_IntGetStatus(uint32_t ulIntType)
  730. {
  731. if (LPC_EMAC->IntStatus & ulIntType) {
  732. LPC_EMAC->IntClear = ulIntType;
  733. return SET;
  734. } else {
  735. return RESET;
  736. }
  737. }
  738. /*********************************************************************//**
  739. * @brief Check whether if the current RxConsumeIndex is not equal to the
  740. * current RxProduceIndex.
  741. * @param[in] None
  742. * @return TRUE if they're not equal, otherwise return FALSE
  743. *
  744. * Note: In case the RxConsumeIndex is not equal to the RxProduceIndex,
  745. * it means there're available data has been received. They should be read
  746. * out and released the Receive Data Buffer by updating the RxConsumeIndex value.
  747. **********************************************************************/
  748. Bool EMAC_CheckReceiveIndex(void)
  749. {
  750. if (LPC_EMAC->RxConsumeIndex != LPC_EMAC->RxProduceIndex) {
  751. return TRUE;
  752. } else {
  753. return FALSE;
  754. }
  755. }
  756. /*********************************************************************//**
  757. * @brief Check whether if the current TxProduceIndex is not equal to the
  758. * current RxProduceIndex - 1.
  759. * @param[in] None
  760. * @return TRUE if they're not equal, otherwise return FALSE
  761. *
  762. * Note: In case the RxConsumeIndex is equal to the RxProduceIndex - 1,
  763. * it means the transmit buffer is available and data can be written to transmit
  764. * buffer to be sent.
  765. **********************************************************************/
  766. Bool EMAC_CheckTransmitIndex(void)
  767. {
  768. uint32_t tmp = LPC_EMAC->TxConsumeIndex;
  769. if (LPC_EMAC->TxProduceIndex == ( tmp - 1 ))
  770. {
  771. return FALSE;
  772. }
  773. else if( ( tmp == 0 ) && ( LPC_EMAC->TxProduceIndex == ( EMAC_NUM_TX_FRAG - 1 ) ) )
  774. {
  775. return FALSE;
  776. }
  777. else
  778. {
  779. return TRUE;
  780. }
  781. }
  782. /*********************************************************************//**
  783. * @brief Get current status value of receive data (due to RxConsumeIndex)
  784. * @param[in] ulRxStatType Received Status type, should be one of following:
  785. * - EMAC_RINFO_CTRL_FRAME: Control Frame
  786. * - EMAC_RINFO_VLAN: VLAN Frame
  787. * - EMAC_RINFO_FAIL_FILT: RX Filter Failed
  788. * - EMAC_RINFO_MCAST: Multicast Frame
  789. * - EMAC_RINFO_BCAST: Broadcast Frame
  790. * - EMAC_RINFO_CRC_ERR: CRC Error in Frame
  791. * - EMAC_RINFO_SYM_ERR: Symbol Error from PHY
  792. * - EMAC_RINFO_LEN_ERR: Length Error
  793. * - EMAC_RINFO_RANGE_ERR: Range error(exceeded max size)
  794. * - EMAC_RINFO_ALIGN_ERR: Alignment error
  795. * - EMAC_RINFO_OVERRUN: Receive overrun
  796. * - EMAC_RINFO_NO_DESCR: No new Descriptor available
  797. * - EMAC_RINFO_LAST_FLAG: last Fragment in Frame
  798. * - EMAC_RINFO_ERR: Error Occurred (OR of all error)
  799. * @return Current value of receive data (due to RxConsumeIndex)
  800. **********************************************************************/
  801. FlagStatus EMAC_CheckReceiveDataStatus(uint32_t ulRxStatType)
  802. {
  803. uint32_t idx;
  804. idx = LPC_EMAC->RxConsumeIndex;
  805. return (((Rx_Stat[idx].Info) & ulRxStatType) ? SET : RESET);
  806. }
  807. /*********************************************************************//**
  808. * @brief Get size of current Received data in received buffer (due to
  809. * RxConsumeIndex)
  810. * @param[in] None
  811. * @return Size of received data
  812. **********************************************************************/
  813. uint32_t EMAC_GetReceiveDataSize(void)
  814. {
  815. uint32_t idx;
  816. idx =LPC_EMAC->RxConsumeIndex;
  817. return ((Rx_Stat[idx].Info) & EMAC_RINFO_SIZE);
  818. }
  819. /*********************************************************************//**
  820. * @brief Increase the RxConsumeIndex (after reading the Receive buffer
  821. * to release the Receive buffer) and wrap-around the index if
  822. * it reaches the maximum Receive Number
  823. * @param[in] None
  824. * @return None
  825. **********************************************************************/
  826. void EMAC_UpdateRxConsumeIndex(void)
  827. {
  828. // Get current Rx consume index
  829. uint32_t idx = LPC_EMAC->RxConsumeIndex;
  830. /* Release frame from EMAC buffer */
  831. if (++idx == EMAC_NUM_RX_FRAG) idx = 0;
  832. LPC_EMAC->RxConsumeIndex = idx;
  833. }
  834. /*********************************************************************//**
  835. * @brief Increase the TxProduceIndex (after writting to the Transmit buffer
  836. * to enable the Transmit buffer) and wrap-around the index if
  837. * it reaches the maximum Transmit Number
  838. * @param[in] None
  839. * @return None
  840. **********************************************************************/
  841. void EMAC_UpdateTxProduceIndex(void)
  842. {
  843. // Get current Tx produce index
  844. uint32_t idx = LPC_EMAC->TxProduceIndex;
  845. /* Start frame transmission */
  846. if (++idx == EMAC_NUM_TX_FRAG) idx = 0;
  847. LPC_EMAC->TxProduceIndex = idx;
  848. }
  849. /**
  850. * @}
  851. */
  852. #endif /* _EMAC */
  853. /**
  854. * @}
  855. */
  856. /* --------------------------------- End Of File ------------------------------ */