• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <string.h>
17 #include "lwip/opt.h"
18 #include "lwip/def.h"
19 #include "lwip/mem.h"
20 #include "lwip/pbuf.h"
21 #include "lwip/timeouts.h"
22 #include "netif/etharp.h"
23 #include "lwip/err.h"
24 #include "lwip_adapter.h"
25 #include "gd32f4xx_enet.h"
26 #include "cmsis_os2.h"
27 #include "los_interrupt.h"
28 #include "ethernetif.h"
29 
30 #define ETHERNETIF_INPUT_TASK_STACK_SIZE (1024)
31 #define ETHERNETIF_INPUT_TASK_PRIO (5)
32 #define LOWLEVEL_OUTPUT_WAITING_TIME (250)
33 /* The time to block waiting for input */
34 #define LOWLEVEL_INPUT_WAITING_TIME ((uint32_t)100)
35 #define ENET_MTU (1500)
36 
37 /* define those to better describe your network interface */
38 #define IFNAME0 'G'
39 #define IFNAME1 'D'
40 
41 /* preserve another ENET RxDMA/TxDMA ptp descriptor for normal mode */
42 enet_descriptors_struct ptp_txstructure[ENET_TXBUF_NUM];
43 enet_descriptors_struct ptp_rxstructure[ENET_RXBUF_NUM];
44 
45 void ethernetif_input(void *pvParameters);
46 
47 static struct netif *low_netif = NULL;
48 osSemaphoreId_t g_rx_semaphore = NULL;
49 
low_level_init(struct netif * netif)50 static void low_level_init(struct netif *netif)
51 {
52     uint32_t i;
53 
54     /* set netif MAC hardware address length */
55     netif->hwaddr_len = ETHARP_HWADDR_LEN;
56 
57     /* set netif MAC hardware address */
58     int index = 0;
59     netif->hwaddr[index++] = MAC_ADDR0;
60     netif->hwaddr[index++] = MAC_ADDR1;
61     netif->hwaddr[index++] = MAC_ADDR2;
62     netif->hwaddr[index++] = MAC_ADDR3;
63     netif->hwaddr[index++] = MAC_ADDR4;
64     netif->hwaddr[index++] = MAC_ADDR5;
65 
66     /* set netif maximum transfer unit */
67     netif->mtu = ENET_MTU;
68 
69     /* accept broadcast address and ARP traffic */
70     netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
71 
72     low_netif = netif;
73 
74     /* create binary semaphore used for informing ethernetif of frame reception */
75     if (g_rx_semaphore == NULL) {
76         g_rx_semaphore = osSemaphoreNew(1, 1, g_rx_semaphore);
77         osSemaphoreAcquire(g_rx_semaphore, 0);
78     }
79 
80     /* initialize MAC address in ethernet MAC */
81     enet_mac_address_set(ENET_MAC_ADDRESS0, netif->hwaddr);
82 
83     /* initialize descriptors list: chain/ring mode */
84 #ifdef SELECT_DESCRIPTORS_ENHANCED_MODE
85     enet_ptp_enhanced_descriptors_chain_init(ENET_DMA_TX);
86     enet_ptp_enhanced_descriptors_chain_init(ENET_DMA_RX);
87 #else
88     enet_descriptors_chain_init(ENET_DMA_TX);
89     enet_descriptors_chain_init(ENET_DMA_RX);
90 #endif
91 
92     for (i = 0; i < ENET_RXBUF_NUM; i++) {
93         enet_rx_desc_immediate_receive_complete_interrupt(&rxdesc_tab[i]);
94     }
95 
96 #ifdef CHECKSUM_BY_HARDWARE
97     /* enable the TCP, UDP and ICMP checksum insertion for the Tx frames */
98     for (i = 0; i < ENET_TXBUF_NUM; i++) {
99         enet_transmit_checksum_config(&txdesc_tab[i], ENET_CHECKSUM_TCPUDPICMP_FULL);
100     }
101 #endif
102 
103     /* create the task that handles the ETH_MAC */
104     osThreadAttr_t attr = {.name = "ETHERNETIF_INPUT",
105                            .attr_bits = 0U,
106                            .cb_mem = NULL,
107                            .stack_mem = NULL,
108                            .stack_size = ETHERNETIF_INPUT_TASK_STACK_SIZE,
109                            .priority = ETHERNETIF_INPUT_TASK_PRIO};
110     osThreadNew((osThreadFunc_t)ethernetif_input, (void *)netif, &attr);
111 
112     /* enable MAC and DMA transmission and reception */
113     enet_enable();
114 }
115 
low_level_output(struct netif * netif,struct pbuf * p)116 static err_t low_level_output(struct netif *netif, struct pbuf *p)
117 {
118     static osSemaphoreId_t s_tx_semaphore = NULL;
119     struct pbuf *q;
120     uint8_t *buffer;
121     uint16_t framelength = 0;
122     ErrStatus reval = ERROR;
123 
124     SYS_ARCH_DECL_PROTECT(sr);
125 
126     if (s_tx_semaphore == NULL) {
127         s_tx_semaphore = osSemaphoreNew(1, 1, NULL);
128     }
129 
130     if (osOK == osSemaphoreAcquire(s_tx_semaphore, LOWLEVEL_OUTPUT_WAITING_TIME)) {
131         sr = LOS_IntLock();
132         while ((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)) { }
133         buffer = (uint8_t *)(enet_desc_information_get(dma_current_txdesc, TXDESC_BUFFER_1_ADDR));
134 
135         for (q = p; q != NULL; q = q->next) {
136             memcpy_s((uint8_t *)&buffer[framelength], q->len, q->payload, q->len);
137             framelength = framelength + q->len;
138         }
139 
140         /* transmit descriptors to give to DMA */
141 #ifdef SELECT_DESCRIPTORS_ENHANCED_MODE
142         reval = ENET_NOCOPY_PTPFRAME_TRANSMIT_ENHANCED_MODE(framelength, NULL);
143 #else
144         reval = ENET_NOCOPY_FRAME_TRANSMIT(framelength);
145 #endif
146 
147         LOS_IntRestore(sr);
148 
149         osSemaphoreRelease(s_tx_semaphore);
150     }
151 
152     if (SUCCESS == reval) {
153         return ERR_OK;
154     } else {
155         while (1) { }
156     }
157 }
158 
low_level_input(struct netif * netif)159 static struct pbuf *low_level_input(struct netif *netif)
160 {
161     struct pbuf *p = NULL, *q;
162     uint32_t l = 0;
163     u16_t len;
164     uint8_t *buffer;
165 
166     /* obtain the size of the packet and put it into the "len" variable. */
167     len = enet_desc_information_get(dma_current_rxdesc, RXDESC_FRAME_LENGTH);
168     buffer = (uint8_t *)(enet_desc_information_get(dma_current_rxdesc, RXDESC_BUFFER_1_ADDR));
169 
170     if (len > 0) {
171         p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
172     }
173     if (p != NULL) {
174         for (q = p; q != NULL; q = q->next) {
175             memcpy_s((uint8_t *)q->payload, q->len, (u8_t *)&buffer[l], q->len);
176             l = l + q->len;
177         }
178     }
179 #ifdef SELECT_DESCRIPTORS_ENHANCED_MODE
180     ENET_NOCOPY_PTPFRAME_RECEIVE_ENHANCED_MODE(NULL);
181 #else
182     ENET_NOCOPY_FRAME_RECEIVE();
183 #endif
184 
185     return p;
186 }
187 
ethernetif_input(void * pvParameters)188 void ethernetif_input(void *pvParameters)
189 {
190     struct pbuf *p;
191     SYS_ARCH_DECL_PROTECT(sr);
192 
193     for (;;) {
194         if (osOK != osSemaphoreAcquire(g_rx_semaphore, LOWLEVEL_INPUT_WAITING_TIME)) {
195             continue;
196         }
197         while (1) {
198             sr = LOS_IntLock();
199             p = low_level_input(low_netif);
200             LOS_IntRestore(sr);
201 
202             if (p == NULL) {
203                 break;
204             }
205             if (ERR_OK != low_netif->input(p, low_netif)) {
206                 pbuf_free(p);
207                 break;
208             }
209         }
210     }
211 }
212 
ethernetif_init(struct netif * netif)213 err_t ethernetif_init(struct netif *netif)
214 {
215     LWIP_ASSERT("netif != NULL", (netif != NULL));
216 
217     netif->name[0] = IFNAME0;
218     netif->name[1] = IFNAME1;
219 
220     netif->output = etharp_output;
221     netif->linkoutput = low_level_output;
222 
223     /* initialize the hardware */
224     low_level_init(netif);
225 
226     return ERR_OK;
227 }
228 
ENET_IRQHandler_CB(void)229 void ENET_IRQHandler_CB(void)
230 {
231     /* frame received */
232     if (SET == enet_interrupt_flag_get(ENET_DMA_INT_FLAG_RS)) {
233         /* give the semaphore to wakeup LwIP task */
234         osSemaphoreRelease(g_rx_semaphore);
235     }
236     enet_interrupt_flag_clear(ENET_DMA_INT_FLAG_RS_CLR);
237     enet_interrupt_flag_clear(ENET_DMA_INT_FLAG_NI_CLR);
238 }