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 <stdio.h>
17 #include "stdint.h"
18 #include "los_config.h"
19 #include "lwip/mem.h"
20 #include "lwip/memp.h"
21 #include "lwip/tcp.h"
22 #include "lwip/udp.h"
23 #include "netif/etharp.h"
24 #include "lwip/dhcp.h"
25 #include "lwip/tcpip.h"
26 #include "lwip/priv/tcp_priv.h"
27 #include "lwip/timeouts.h"
28 #include "lwip/netif.h"
29 #include "lwip/ip4_addr.h"
30 #include "lwip/sockets.h"
31 #include "gd32f4xx.h"
32 #include "gd32f4xx_enet_eval.h"
33 #include "gd32f4xx_enet.h"
34 #include "cmsis_os2.h"
35 #include "los_interrupt.h"
36 #include "ethernetif.h"
37 #include "lwip_adapter.h"
38
39 err_t ethernetif_init(struct netif *netif);
40 #define MAX_DHCP_TRIES 4
41 #define DELAY250_MS 250
42 #define DELAY1000_MS 1000
43 #define IRQ_PRIORITY 2
44 #define CREATE_IRQ_MODE 5
45 static EthLinkInfo gEthLinkInfo = {.useStaticIp = 1, .useStaticMac = 1};
46
47 typedef enum { DHCP_START = 0, DHCP_WAIT_ADDRESS, DHCP_ADDRESS_ASSIGNED, DHCP_TIMEOUT } dhcp_state_enum;
48
49 #ifdef USE_DHCP
50 dhcp_state_enum dhcp_state = DHCP_START;
51 #endif
52
53 struct netif g_mynetif;
54 unsigned int tcp_timer = 0;
55 unsigned int arp_timer = 0;
56 ip_addr_t ip_address = {0};
57
58 void lwip_dhcp_process_handle(void);
59
lwip_stack_init(void)60 void lwip_stack_init(void)
61 {
62 ip_addr_t ipaddr;
63 ip_addr_t netmask;
64 ip_addr_t gw;
65
66 tcpip_init(NULL, NULL);
67
68 #ifdef TIMEOUT_CHECK_USE_LWIP
69 sys_timeouts_init();
70 #endif
71
72 #ifdef USE_DHCP
73 ipaddr.addr = 0;
74 netmask.addr = 0;
75 gw.addr = 0;
76 #else
77 IP_ADDR4(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
78 IP_ADDR4(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
79 IP_ADDR4(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
80
81 #endif /* USE_DHCP */
82
83 netif_add(&g_mynetif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, &tcpip_input);
84 /* registers the default network interface */
85 netif_set_default(&g_mynetif);
86
87 /* when the netif is fully configured this function must be called */
88 netif_set_up(&g_mynetif);
89 }
90
91 #ifdef USE_DHCP
dhcp_task(void * pvParameters)92 void dhcp_task(void *pvParameters)
93 {
94 ip_addr_t ipaddr;
95 ip_addr_t netmask;
96 ip_addr_t gw;
97 struct dhcp *dhcp_client;
98
99 for (;;) {
100 switch (dhcp_state) {
101 case DHCP_START:
102 dhcp_start(&g_mynetif);
103 /* IP address should be set to 0 every time we want to assign a new DHCP address */
104 dhcp_state = DHCP_WAIT_ADDRESS;
105 printf("dhcp start\n");
106 break;
107
108 case DHCP_WAIT_ADDRESS:
109 /* read the new IP address */
110 ip_address.addr = g_mynetif.ip_addr.addr;
111 printf("dhcp wait addr\n");
112 if (ip_address.addr != 0) {
113 dhcp_state = DHCP_ADDRESS_ASSIGNED;
114 printf("\r\nDHCP -- eval board ip address: %d.%d.%d.%d \r\n", ip4_addr1_16(&ip_address),
115 ip4_addr2_16(&ip_address), ip4_addr3_16(&ip_address), ip4_addr4_16(&ip_address));
116 } else {
117 /* DHCP timeout */
118 dhcp_client = netif_dhcp_data(&g_mynetif);
119 if (dhcp_client->tries > MAX_DHCP_TRIES) {
120 dhcp_state = DHCP_TIMEOUT;
121 /* stop DHCP */
122 dhcp_stop(&g_mynetif);
123 printf("dhcp set static addr\n");
124 /* static address used */
125 IP4_ADDR(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
126 IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
127 IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
128 netif_set_addr(&g_mynetif, &ipaddr, &netmask, &gw);
129 }
130 }
131 break;
132
133 default:
134 break;
135 }
136 osDelay(DELAY250_MS);
137 }
138 }
139 #endif
140
141 #ifdef USE_ENET_INTERRUPT
nvic_configuration(void)142 static void nvic_configuration(void)
143 {
144 nvic_irq_enable(ENET_IRQn, IRQ_PRIORITY, 0);
145 }
146 #endif
147
148 static __IO UINT32 enet_init_status = 0;
149
enet_taskEntery(void * param)150 void enet_taskEntery(void *param)
151 {
152 ErrStatus reval_state = ERROR;
153
154 #ifdef USE_ENET_INTERRUPT
155 nvic_configuration();
156 #endif /* USE_ENET_INTERRUPT */
157
158 /* configure the GPIO ports for ethernet pins */
159 enet_gpio_config();
160
161 /* enable ethernet clock */
162 rcu_periph_clock_enable(RCU_ENET);
163 rcu_periph_clock_enable(RCU_ENETTX);
164 rcu_periph_clock_enable(RCU_ENETRX);
165
166 /* reset ethernet on AHB bus */
167 enet_deinit();
168 reval_state = enet_software_reset();
169 while (ERROR == reval_state) {
170 printf("enet reset \n");
171 osDelay(DELAY1000_MS);
172 }
173
174 #ifdef USE_ENET_INTERRUPT
175 enet_interrupt_enable(ENET_DMA_INT_NIE);
176 enet_interrupt_enable(ENET_DMA_INT_RIE);
177 #endif /* USE_ENET_INTERRUPT */
178
179 lwip_stack_init();
180 LOS_HwiCreate(ENET_IRQn, 0, CREATE_IRQ_MODE, (HWI_PROC_FUNC)ENET_IRQHandler_CB, 0);
181
182 net_state_callBack callback = (net_state_callBack)param;
183 uint16_t phy_value;
184 uint16_t status = 0;
185 while (1) {
186 enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value);
187 if (status == (phy_value & PHY_LINKED_STATUS)) {
188 osDelay(DELAY1000_MS);
189 continue;
190 }
191 status = phy_value & PHY_LINKED_STATUS;
192 if (status != RESET) { /* link status changes from down to up */
193 if (enet_init_status == 0) { /* init phy once */
194 #ifdef CHECKSUM_BY_HARDWARE
195 enet_init_status =
196 enet_init(ENET_AUTO_NEGOTIATION, ENET_AUTOCHECKSUM_DROP_FAILFRAMES, ENET_BROADCAST_FRAMES_PASS);
197 #else
198 enet_init_status =
199 enet_init(ENET_AUTO_NEGOTIATION, ENET_NO_AUTOCHECKSUM, ENET_BROADCAST_FRAMES_PASS);
200 #endif
201 }
202 PHY_STATUS_CALLBACK(callback, STATE_UPDATE_LINK_DOWN);
203 } else {
204 /* link status changes from up to down */
205 PHY_STATUS_CALLBACK(callback, STATE_UPDATE_LINK_UP);
206 }
207 osDelay(DELAY1000_MS);
208 }
209 }
210
enet_adapter_init(net_state_callBack callBack)211 void enet_adapter_init(net_state_callBack callBack)
212 {
213 osThreadAttr_t attr = {.name = "net_init",
214 .attr_bits = 0U,
215 .cb_mem = NULL,
216 .stack_mem = NULL,
217 .stack_size = ENET_TASK_STACK_SIZE,
218 .priority = ENET_TASK_PRIORITY};
219 if (osThreadNew((osThreadFunc_t)enet_taskEntery, (void *)callBack, &attr) == NULL) {
220 printf("Create net task failed! \n");
221 }
222
223 #ifdef USE_DHCP
224 /* start DHCP client */
225 osThreadAttr_t attr1 = {
226 .name = "DHCP", .attr_bits = 0U, .cb_mem = NULL, .stack_mem = NULL, .stack_size = 1024, .priority = 29};
227 if (osThreadNew((osThreadFunc_t)dhcp_task, NULL, &attr1) == NULL) {
228 printf("Create DHCP task failed! \n");
229 }
230 #endif
231 }
232