ethernetif.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. /**
  2. * @file
  3. * Ethernet Interface Skeleton
  4. *
  5. */
  6. /*
  7. * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
  8. * All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without modification,
  11. * are permitted provided that the following conditions are met:
  12. *
  13. * 1. Redistributions of source code must retain the above copyright notice,
  14. * this list of conditions and the following disclaimer.
  15. * 2. Redistributions in binary form must reproduce the above copyright notice,
  16. * this list of conditions and the following disclaimer in the documentation
  17. * and/or other materials provided with the distribution.
  18. * 3. The name of the author may not be used to endorse or promote products
  19. * derived from this software without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  22. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  23. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
  24. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  26. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  27. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  29. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  30. * OF SUCH DAMAGE.
  31. *
  32. * This file is part of the lwIP TCP/IP stack.
  33. *
  34. * Author: Adam Dunkels <adam@sics.se>
  35. *
  36. */
  37. #include "lwip/opt.h"
  38. #include "lwip/def.h"
  39. #include "lwip/mem.h"
  40. #include "lwip/pbuf.h"
  41. #include "lwip/lwip_timers.h"
  42. #include "netif/etharp.h"
  43. #include "err.h"
  44. #include "ethernetif.h"
  45. #include "main.h"
  46. #include "gd32f30x_enet.h"
  47. #include <string.h>
  48. #define ETHERNETIF_INPUT_TASK_STACK_SIZE (350)
  49. #define ETHERNETIF_INPUT_TASK_PRIO (configMAX_PRIORITIES - 1)
  50. #define LOWLEVEL_OUTPUT_WAITING_TIME (250)
  51. /* The time to block waiting for input */
  52. #define LOWLEVEL_INPUT_WAITING_TIME ((portTickType )100)
  53. /* define those to better describe your network interface */
  54. #define IFNAME0 'G'
  55. #define IFNAME1 'D'
  56. /* ENET RxDMA/TxDMA descriptor */
  57. extern enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM], txdesc_tab[ENET_TXBUF_NUM];
  58. /* ENET receive buffer */
  59. extern uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE];
  60. /* ENET transmit buffer */
  61. extern uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE];
  62. /*global transmit and receive descriptors pointers */
  63. extern enet_descriptors_struct *dma_current_txdesc;
  64. extern enet_descriptors_struct *dma_current_rxdesc;
  65. /* preserve another ENET RxDMA/TxDMA ptp descriptor for normal mode */
  66. enet_descriptors_struct ptp_txstructure[ENET_TXBUF_NUM];
  67. enet_descriptors_struct ptp_rxstructure[ENET_RXBUF_NUM];
  68. static struct netif *low_netif = NULL;
  69. xSemaphoreHandle g_rx_semaphore = NULL;
  70. /**
  71. * In this function, the hardware should be initialized.
  72. * Called from ethernetif_init().
  73. *
  74. * @param netif the already initialized lwip network interface structure
  75. * for this ethernetif
  76. */
  77. void low_level_init(struct netif *netif)
  78. {
  79. uint32_t i;
  80. /* set netif MAC hardware address length */
  81. netif->hwaddr_len = ETHARP_HWADDR_LEN;
  82. /* set netif MAC hardware address */
  83. netif->hwaddr[0] = MAC_ADDR0;
  84. netif->hwaddr[1] = MAC_ADDR1;
  85. netif->hwaddr[2] = MAC_ADDR2;
  86. netif->hwaddr[3] = MAC_ADDR3;
  87. netif->hwaddr[4] = MAC_ADDR4;
  88. netif->hwaddr[5] = MAC_ADDR5;
  89. /* set netif maximum transfer unit */
  90. netif->mtu = 1500;
  91. /* accept broadcast address and ARP traffic */
  92. netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
  93. low_netif =netif;
  94. /* create binary semaphore used for informing ethernetif of frame reception */
  95. if (g_rx_semaphore == NULL){
  96. vSemaphoreCreateBinary(g_rx_semaphore);
  97. xSemaphoreTake( g_rx_semaphore, 0);
  98. }
  99. /* initialize MAC address in ethernet MAC */
  100. enet_mac_address_set(ENET_MAC_ADDRESS0, netif->hwaddr);
  101. /* initialize descriptors list: chain/ring mode */
  102. #ifdef SELECT_DESCRIPTORS_ENHANCED_MODE
  103. enet_ptp_enhanced_descriptors_chain_init(ENET_DMA_TX);
  104. enet_ptp_enhanced_descriptors_chain_init(ENET_DMA_RX);
  105. #else
  106. enet_descriptors_chain_init(ENET_DMA_TX);
  107. enet_descriptors_chain_init(ENET_DMA_RX);
  108. // enet_descriptors_ring_init(ENET_DMA_TX);
  109. // enet_descriptors_ring_init(ENET_DMA_RX);
  110. #endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */
  111. /* enable ethernet Rx interrrupt */
  112. { int i;
  113. for(i=0; i<ENET_RXBUF_NUM; i++){
  114. enet_rx_desc_immediate_receive_complete_interrupt(&rxdesc_tab[i]);
  115. }
  116. }
  117. #ifdef CHECKSUM_BY_HARDWARE
  118. /* enable the TCP, UDP and ICMP checksum insertion for the Tx frames */
  119. for(i=0; i < ENET_TXBUF_NUM; i++){
  120. enet_transmit_checksum_config(&txdesc_tab[i], ENET_CHECKSUM_TCPUDPICMP_FULL);
  121. }
  122. #endif /* CHECKSUM_BY_HARDWARE */
  123. /* create the task that handles the ETH_MAC */
  124. xTaskCreate(ethernetif_input, "ETHERNETIF_INPUT", ETHERNETIF_INPUT_TASK_STACK_SIZE, NULL,
  125. ETHERNETIF_INPUT_TASK_PRIO,NULL);
  126. /* enable MAC and DMA transmission and reception */
  127. enet_enable();
  128. }
  129. /**
  130. * This function should do the actual transmission of the packet. The packet is
  131. * contained in the pbuf that is passed to the function. This pbuf
  132. * might be chained.
  133. *
  134. * @param netif the lwip network interface structure for this ethernetif
  135. * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
  136. * @return ERR_OK if the packet could be sent
  137. * an err_t value if the packet couldn't be sent
  138. *
  139. * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
  140. * strange results. You might consider waiting for space in the DMA queue
  141. * to become availale since the stack doesn't retry to send a packet
  142. * dropped because of memory failure (except for the TCP timers).
  143. */
  144. static err_t low_level_output(struct netif *netif, struct pbuf *p)
  145. {
  146. static xSemaphoreHandle s_tx_semaphore = NULL;
  147. struct pbuf *q;
  148. uint8_t *buffer ;
  149. uint16_t framelength = 0;
  150. ErrStatus reval = ERROR;
  151. SYS_ARCH_DECL_PROTECT(sr);
  152. if (s_tx_semaphore == NULL){
  153. vSemaphoreCreateBinary (s_tx_semaphore);
  154. }
  155. if (xSemaphoreTake(s_tx_semaphore, LOWLEVEL_OUTPUT_WAITING_TIME)){
  156. SYS_ARCH_PROTECT(sr);
  157. while((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)){
  158. }
  159. buffer = (uint8_t *)(enet_desc_information_get(dma_current_txdesc, TXDESC_BUFFER_1_ADDR));
  160. for(q = p; q != NULL; q = q->next){
  161. memcpy((uint8_t *)&buffer[framelength], q->payload, q->len);
  162. framelength = framelength + q->len;
  163. }
  164. /* transmit descriptors to give to DMA */
  165. #ifdef SELECT_DESCRIPTORS_ENHANCED_MODE
  166. reval = ENET_NOCOPY_PTPFRAME_TRANSMIT_ENHANCED_MODE(framelength, NULL);
  167. #else
  168. reval = ENET_NOCOPY_FRAME_TRANSMIT(framelength);
  169. #endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */
  170. SYS_ARCH_UNPROTECT(sr);
  171. /* give semaphore and exit */
  172. xSemaphoreGive(s_tx_semaphore);
  173. }
  174. if(SUCCESS == reval){
  175. return ERR_OK;
  176. }else{
  177. while(1){
  178. }
  179. }
  180. }
  181. /**
  182. * Should allocate a pbuf and transfer the bytes of the incoming
  183. * packet from the interface into the pbuf.
  184. *
  185. * @param netif the lwip network interface structure for this ethernetif
  186. * @return a pbuf filled with the received packet (including MAC header)
  187. * NULL on memory error
  188. */
  189. static struct pbuf * low_level_input(struct netif *netif)
  190. {
  191. struct pbuf *p= NULL, *q;
  192. uint32_t l =0;
  193. u16_t len;
  194. uint8_t *buffer;
  195. /* obtain the size of the packet and put it into the "len" variable. */
  196. len = enet_desc_information_get(dma_current_rxdesc, RXDESC_FRAME_LENGTH);
  197. buffer = (uint8_t *)(enet_desc_information_get(dma_current_rxdesc, RXDESC_BUFFER_1_ADDR));
  198. if (len > 0){
  199. /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */
  200. p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
  201. }
  202. if (p != NULL){
  203. for(q = p; q != NULL; q = q->next){
  204. memcpy((uint8_t *)q->payload, (u8_t*)&buffer[l], q->len);
  205. l = l + q->len;
  206. }
  207. }
  208. #ifdef SELECT_DESCRIPTORS_ENHANCED_MODE
  209. ENET_NOCOPY_PTPFRAME_RECEIVE_ENHANCED_MODE(NULL);
  210. #else
  211. ENET_NOCOPY_FRAME_RECEIVE();
  212. #endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */
  213. return p;
  214. }
  215. /**
  216. * This function is the ethernetif_input task, it is processed when a packet
  217. * is ready to be read from the interface. It uses the function low_level_input()
  218. * that should handle the actual reception of bytes from the network
  219. * interface. Then the type of the received packet is determined and
  220. * the appropriate input function is called.
  221. *
  222. * @param netif the lwip network interface structure for this ethernetif
  223. */
  224. void ethernetif_input( void * pvParameters )
  225. {
  226. struct pbuf *p;
  227. SYS_ARCH_DECL_PROTECT(sr);
  228. for( ;; ){
  229. if(pdTRUE == xSemaphoreTake(g_rx_semaphore, LOWLEVEL_INPUT_WAITING_TIME)){
  230. TRY_GET_NEXT_FRAME:
  231. SYS_ARCH_PROTECT(sr);
  232. p = low_level_input( low_netif );
  233. SYS_ARCH_UNPROTECT(sr);
  234. if (p != NULL){
  235. if (ERR_OK != low_netif->input( p, low_netif)){
  236. pbuf_free(p);
  237. }else{
  238. goto TRY_GET_NEXT_FRAME;
  239. }
  240. }
  241. }
  242. }
  243. }
  244. /**
  245. * Should be called at the beginning of the program to set up the
  246. * network interface. It calls the function low_level_init() to do the
  247. * actual setup of the hardware.
  248. *
  249. * This function should be passed as a parameter to netif_add().
  250. *
  251. * @param netif the lwip network interface structure for this ethernetif
  252. * @return ERR_OK if the loopif is initialized
  253. * ERR_MEM if private data couldn't be allocated
  254. * any other err_t on error
  255. */
  256. err_t ethernetif_init(struct netif *netif)
  257. {
  258. LWIP_ASSERT("netif != NULL", (netif != NULL));
  259. #if LWIP_NETIF_HOSTNAME
  260. /* initialize interface hostname */
  261. netif->hostname = "lwip";
  262. #endif /* LWIP_NETIF_HOSTNAME */
  263. netif->name[0] = IFNAME0;
  264. netif->name[1] = IFNAME1;
  265. netif->output = etharp_output;
  266. netif->linkoutput = low_level_output;
  267. /* initialize the hardware */
  268. low_level_init(netif);
  269. return ERR_OK;
  270. }