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 }