ethernetif.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. /**
  2. * @file
  3. * Ethernet Interface for standalone applications (without RTOS) - works only for
  4. * ethernet polling mode (polling for ethernet frame reception)
  5. *
  6. */
  7. /*
  8. * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
  9. * All rights reserved.
  10. *
  11. * Redistribution and use in source and binary forms, with or without modification,
  12. * are permitted provided that the following conditions are met:
  13. *
  14. * 1. Redistributions of source code must retain the above copyright notice,
  15. * this list of conditions and the following disclaimer.
  16. * 2. Redistributions in binary form must reproduce the above copyright notice,
  17. * this list of conditions and the following disclaimer in the documentation
  18. * and/or other materials provided with the distribution.
  19. * 3. The name of the author may not be used to endorse or promote products
  20. * derived from this software without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  23. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  24. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
  25. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  26. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  27. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  28. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  29. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  30. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  31. * OF SUCH DAMAGE.
  32. *
  33. * This file is part of the lwIP TCP/IP stack.
  34. *
  35. * Author: Adam Dunkels <adam@sics.se>
  36. *
  37. */
  38. #include "lwip/mem.h"
  39. #include "netif/etharp.h"
  40. #include "ethernetif.h"
  41. #include "at32f403a_407_emac.h"
  42. #include "common.h"
  43. #include "common_config.h"
  44. #include "settings_api.h"
  45. #include "utility.h"
  46. #include <string.h>
  47. // Network interface name
  48. #define IFNAME0 's'
  49. #define IFNAME1 't'
  50. #define EMAC_DMARxDesc_FrameLengthShift 16
  51. /**
  52. * Helper struct to hold private data used to operate your ethernet interface.
  53. * Keeping the ethernet address of the MAC in this struct is not necessary
  54. * as it is already kept in the struct netif.
  55. * But this is only an example, anyway...
  56. */
  57. struct ethernetif
  58. {
  59. struct eth_addr *ethaddr;
  60. /* Add whatever per-interface state that is needed here. */
  61. int unused;
  62. };
  63. #define EMAC_RXBUFNB 4
  64. #define EMAC_TXBUFNB 2
  65. // Ethernet Rx & Tx DMA Descriptors
  66. #pragma data_alignment = 4
  67. emac_dma_desc_type DMARxDscrTab[EMAC_RXBUFNB];
  68. #pragma data_alignment = 4
  69. emac_dma_desc_type DMATxDscrTab[EMAC_TXBUFNB];
  70. #pragma data_alignment = 4
  71. uint8_t Rx_Buff[EMAC_RXBUFNB][EMAC_MAX_PACKET_LENGTH];
  72. #pragma data_alignment = 4
  73. uint8_t Tx_Buff[EMAC_TXBUFNB][EMAC_MAX_PACKET_LENGTH];
  74. extern emac_dma_desc_type *dma_tx_desc_to_set;
  75. extern emac_dma_desc_type *dma_rx_desc_to_get;
  76. typedef struct
  77. {
  78. u32 length;
  79. u32 buffer;
  80. emac_dma_desc_type *descriptor;
  81. } FrameTypeDef;
  82. FrameTypeDef emac_rxpkt_chainmode(void);
  83. u32 emac_getcurrenttxbuffer(void);
  84. error_status emac_txpkt_chainmode(u16 FrameLength);
  85. #ifdef ETHERNETIF_RTOS
  86. #include "FreeRTOS.h"
  87. #include "task.h"
  88. SemaphoreHandle_t PHY_RX_xSemaphore;
  89. SemaphoreHandle_t PHY_TX_xSemaphore;
  90. #define PHY_PRIO (configMAX_PRIORITIES - 1)
  91. #define PHY_STK_SIZE 1024
  92. extern struct netif xnetif;
  93. struct netif *lwip_netif= &xnetif;
  94. TaskHandle_t PHY_Handler;
  95. void network_task(void *params);
  96. #endif
  97. /**
  98. * In this function, the hardware should be initialized.
  99. * Called from ethernetif_init().
  100. *
  101. * @param netif the already initialized lwip network interface structure
  102. * for this ethernetif
  103. */
  104. static void low_level_init(struct netif *netif)
  105. {
  106. uint8_t mac[6];
  107. // set MAC hardware address length
  108. netif->hwaddr_len = ETHARP_HWADDR_LEN;
  109. SETTINGS_GetMac(mac);
  110. emac_local_address_set(mac);
  111. netif->hwaddr[0] = mac[0];
  112. netif->hwaddr[1] = mac[1];
  113. netif->hwaddr[2] = mac[2];
  114. netif->hwaddr[3] = mac[3];
  115. netif->hwaddr[4] = mac[4];
  116. netif->hwaddr[5] = mac[5];
  117. // maximum transfer unit
  118. netif->mtu = 1500;
  119. // device capabilities
  120. // don't set NETIF_FLAG_ETHARP if this device is not an ethernet one
  121. netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
  122. // Initialize Tx Descriptors list: Chain Mode
  123. emac_dma_descriptor_list_address_set(EMAC_DMA_TRANSMIT, DMATxDscrTab, &Tx_Buff[0][0], EMAC_TXBUFNB);
  124. // Initialize Rx Descriptors list: Chain Mode
  125. emac_dma_descriptor_list_address_set(EMAC_DMA_RECEIVE, DMARxDscrTab, &Rx_Buff[0][0], EMAC_RXBUFNB);
  126. #ifdef ETHERNETIF_RTOS
  127. static bool task_eth_flag = false;
  128. if (PHY_RX_xSemaphore == NULL) {
  129. PHY_RX_xSemaphore = xSemaphoreCreateCounting(20,0);
  130. }
  131. /*
  132. if (PHY_TX_xSemaphore == NULL) {
  133. PHY_TX_xSemaphore = xSemaphoreCreateBinary();
  134. }
  135. */
  136. if (!task_eth_flag)
  137. {
  138. xTaskCreate((TaskFunction_t)network_task, (const char*)"PHY",(uint16_t)PHY_STK_SIZE,
  139. (void*)NULL, (UBaseType_t)PHY_PRIO, (TaskHandle_t*)&PHY_Handler);
  140. task_eth_flag = true;
  141. }
  142. #endif
  143. // Enable MAC and DMA transmission and reception
  144. emac_start();
  145. }
  146. /**
  147. * This function should do the actual transmission of the packet. The packet is
  148. * contained in the pbuf that is passed to the function. This pbuf
  149. * might be chained.
  150. *
  151. * @param netif the lwip network interface structure for this ethernetif
  152. * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
  153. * @return ERR_OK if the packet could be sent
  154. * an err_t value if the packet couldn't be sent
  155. *
  156. * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
  157. * strange results. You might consider waiting for space in the DMA queue
  158. * to become availale since the stack doesn't retry to send a packet
  159. * dropped because of memory failure (except for the TCP timers).
  160. */
  161. static err_t low_level_output(struct netif *netif, struct pbuf *p)
  162. {
  163. (void)netif;
  164. struct pbuf *q;
  165. int framelength = 0;
  166. u8 *buffer = (u8 *)(dma_tx_desc_to_set->buf1addr);
  167. /* copy frame from pbufs to driver buffers */
  168. for(q = p; q != NULL; q = q->next)
  169. {
  170. memcpy((u8_t*)&buffer[framelength], q->payload, q->len);
  171. framelength = framelength + q->len;
  172. }
  173. #if defined (TRAFFIC_ENABLE)
  174. trf_inc(TR_ETH_TX, framelength); // трафик (tx)
  175. #endif
  176. /* Note: padding and CRC for transmitted frame
  177. are automatically inserted by DMA */
  178. /* Prepare transmit descriptors to give to DMA*/
  179. if(emac_txpkt_chainmode(framelength) == ERROR)
  180. {
  181. return ERR_MEM;
  182. }
  183. return ERR_OK;
  184. }
  185. /**
  186. * Should allocate a pbuf and transfer the bytes of the incoming
  187. * packet from the interface into the pbuf.
  188. *
  189. * @param netif the lwip network interface structure for this ethernetif
  190. * @return a pbuf filled with the received packet (including MAC header)
  191. * NULL on memory error
  192. */
  193. static struct pbuf * low_level_input(struct netif *netif)
  194. {
  195. (void)netif;
  196. struct pbuf *p, *q;
  197. u16_t len;
  198. int l =0;
  199. FrameTypeDef frame;
  200. u8 *buffer;
  201. p = NULL;
  202. /* get received frame */
  203. frame = emac_rxpkt_chainmode();
  204. /* Obtain the size of the packet and put it into the "len" variable. */
  205. len = frame.length;
  206. buffer = (u8 *)frame.buffer;
  207. /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */
  208. p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
  209. /* copy received frame to pbuf chain */
  210. if (p != NULL)
  211. {
  212. for (q = p; q != NULL; q = q->next)
  213. {
  214. memcpy((u8_t*)q->payload, (u8_t*)&buffer[l], q->len);
  215. l = l + q->len;
  216. }
  217. #if defined (TRAFFIC_ENABLE)
  218. trf_inc(TR_ETH_RX, l); // трафик (rx)
  219. #endif
  220. }
  221. /* Set Own bit of the Rx descriptor Status: gives the buffer back to ETHERNET DMA */
  222. frame.descriptor->status = EMAC_DMARXDESC_OWN;
  223. /* When Rx Buffer unavailable flag is set: clear it and resume reception */
  224. if(emac_dma_flag_get(EMAC_DMA_RBU_FLAG))
  225. {
  226. /* Clear RBUS ETHERNET DMA flag */
  227. emac_dma_flag_clear(EMAC_DMA_RBU_FLAG);
  228. /* Resume DMA reception */
  229. EMAC_DMA->rpd_bit.rpd = FALSE;
  230. }
  231. return p;
  232. }
  233. /**
  234. * This function should be called when a packet is ready to be read
  235. * from the interface. It uses the function low_level_input() that
  236. * should handle the actual reception of bytes from the network
  237. * interface. Then the type of the received packet is determined and
  238. * the appropriate input function is called.
  239. *
  240. * @param netif the lwip network interface structure for this ethernetif
  241. */
  242. err_t ethernetif_input(struct netif *netif)
  243. {
  244. err_t err;
  245. struct pbuf *p;
  246. /* move received packet into a new pbuf */
  247. p = low_level_input(netif);
  248. /* no packet could be read, silently ignore this */
  249. if (p == NULL) return ERR_MEM;
  250. /* entry point to the LwIP stack */
  251. err = netif->input(p, netif);
  252. if (err != ERR_OK)
  253. {
  254. LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
  255. pbuf_free(p);
  256. p = NULL;
  257. }
  258. return err;
  259. }
  260. /**
  261. * Should be called at the beginning of the program to set up the
  262. * network interface. It calls the function low_level_init() to do the
  263. * actual setup of the hardware.
  264. *
  265. * This function should be passed as a parameter to netif_add().
  266. *
  267. * @param netif the lwip network interface structure for this ethernetif
  268. * @return ERR_OK if the loopif is initialized
  269. * ERR_MEM if private data couldn't be allocated
  270. * any other err_t on error
  271. */
  272. err_t ethernetif_init(struct netif *netif)
  273. {
  274. LWIP_ASSERT("netif != NULL", (netif != NULL));
  275. #if LWIP_NETIF_HOSTNAME
  276. /* Initialize interface hostname */
  277. netif->hostname = "lwip";
  278. #endif /* LWIP_NETIF_HOSTNAME */
  279. netif->name[0] = IFNAME0;
  280. netif->name[1] = IFNAME1;
  281. /* We directly use etharp_output() here to save a function call.
  282. * You can instead declare your own function an call etharp_output()
  283. * from it if you have to do some checks before sending (e.g. if link
  284. * is available...) */
  285. netif->output = etharp_output;
  286. netif->linkoutput = low_level_output;
  287. /* initialize the hardware */
  288. low_level_init(netif);
  289. return ERR_OK;
  290. }
  291. /*******************************************************************************
  292. * Function Name : emac_rxpkt_chainmode
  293. * Description : Receives a packet.
  294. * Input : None
  295. * Output : None
  296. * Return : frame: farme size and location
  297. *******************************************************************************/
  298. FrameTypeDef emac_rxpkt_chainmode(void)
  299. {
  300. u32 framelength = 0;
  301. FrameTypeDef frame = {0,0};
  302. /* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */
  303. if((dma_rx_desc_to_get->status & EMAC_DMARXDESC_OWN) != (u32)RESET)
  304. {
  305. frame.length = FALSE;
  306. if(emac_dma_flag_get(EMAC_DMA_RBU_FLAG))
  307. {
  308. /* Clear RBUS ETHERNET DMA flag */
  309. emac_dma_flag_clear(EMAC_DMA_RBU_FLAG);
  310. /* Resume DMA reception */
  311. EMAC_DMA->rpd_bit.rpd = FALSE;
  312. }
  313. /* Return error: OWN bit set */
  314. return frame;
  315. }
  316. if(((dma_rx_desc_to_get->status & EMAC_DMATXDESC_ES) == (u32)RESET) &&
  317. ((dma_rx_desc_to_get->status & EMAC_DMARXDESC_LS) != (u32)RESET) &&
  318. ((dma_rx_desc_to_get->status & EMAC_DMARXDESC_FS) != (u32)RESET))
  319. {
  320. /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
  321. framelength = ((dma_rx_desc_to_get->status & EMAC_DMARXDESC_FL) >> EMAC_DMARxDesc_FrameLengthShift) - 4;
  322. /* Get the addrees of the actual buffer */
  323. frame.buffer = dma_rx_desc_to_get->buf1addr;
  324. }
  325. else
  326. {
  327. /* Return ERROR */
  328. framelength = FALSE;
  329. }
  330. frame.length = framelength;
  331. frame.descriptor = dma_rx_desc_to_get;
  332. /* Update the ETHERNET DMA global Rx descriptor with next Rx decriptor */
  333. /* Chained Mode */
  334. /* Selects the next DMA Rx descriptor list for next buffer to read */
  335. dma_rx_desc_to_get = (emac_dma_desc_type*) (dma_rx_desc_to_get->buf2nextdescaddr);
  336. /* Return Frame */
  337. return (frame);
  338. }
  339. /*******************************************************************************
  340. * Function Name : emac_txpkt_chainmode
  341. * Description : Transmits a packet, from application buffer, pointed by ppkt.
  342. * Input : - FrameLength: Tx Packet size.
  343. * Output : None
  344. * Return : ERROR: in case of Tx desc owned by DMA
  345. * SUCCESS: for correct transmission
  346. *******************************************************************************/
  347. error_status emac_txpkt_chainmode(u16 FrameLength)
  348. {
  349. /* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */
  350. if((dma_tx_desc_to_set->status & EMAC_DMATXDESC_OWN) != (u32)RESET)
  351. {
  352. /* Return ERROR: OWN bit set */
  353. return ERROR;
  354. }
  355. /* Setting the Frame Length: bits[12:0] */
  356. dma_tx_desc_to_set->controlsize = (FrameLength & EMAC_DMATXDESC_TBS1);
  357. /* Setting the last segment and first segment bits (in this case a frame is transmitted in one descriptor) */
  358. dma_tx_desc_to_set->status |= EMAC_DMATXDESC_LS | EMAC_DMATXDESC_FS;
  359. /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
  360. dma_tx_desc_to_set->status |= EMAC_DMATXDESC_OWN;
  361. /* When Tx Buffer unavailable flag is set: clear it and resume transmission */
  362. if(emac_dma_flag_get(EMAC_DMA_TBU_FLAG))
  363. {
  364. /* Clear TBUS ETHERNET DMA flag */
  365. emac_dma_flag_clear(EMAC_DMA_TBU_FLAG);
  366. /* Resume DMA transmission*/
  367. EMAC_DMA->tpd_bit.tpd = 0;
  368. }
  369. /* Update the ETHERNET DMA global Tx descriptor with next Tx decriptor */
  370. /* Chained Mode */
  371. /* Selects the next DMA Tx descriptor list for next buffer to send */
  372. dma_tx_desc_to_set = (emac_dma_desc_type*) (dma_tx_desc_to_set->buf2nextdescaddr);
  373. /* Return SUCCESS */
  374. return SUCCESS;
  375. }
  376. #ifdef ETHERNETIF_RTOS
  377. //
  378. void network_task(void *params)
  379. {
  380. struct pbuf *p;
  381. err_t err;
  382. for (;;)
  383. {
  384. if (xSemaphoreTake(PHY_RX_xSemaphore, portMAX_DELAY) == pdTRUE)
  385. {
  386. p = low_level_input(lwip_netif);
  387. }
  388. if (p != NULL)
  389. {
  390. err = lwip_netif->input(p, lwip_netif);
  391. if (err != ERR_OK)
  392. {
  393. pbuf_free(p);
  394. p = NULL;
  395. }
  396. }
  397. }
  398. }
  399. #endif