1 /*
2 * Copyright (c) 2022 Talkweb 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 "ethernetif.h"
17 #include "app_ethernet.h"
18 #include "los_interrupt.h"
19 #include "los_tick.h"
20
21 #define GPIO_AFx_ETH GPIO_AF11_ETH
22 #define ETH_RCC_CLK_ENABLE() __HAL_RCC_ETH_CLK_ENABLE()
23 #define ETH_GPIO_ClK_ENABLE() \
24 { \
25 __HAL_RCC_GPIOA_CLK_ENABLE(); \
26 __HAL_RCC_GPIOC_CLK_ENABLE(); \
27 __HAL_RCC_GPIOB_CLK_ENABLE(); \
28 __HAL_RCC_GPIOG_CLK_ENABLE(); \
29 }
30
31 #define IFNAME0 't'
32 #define IFNAME1 'w'
33
34 struct netif gNetif;
35 ETH_HandleTypeDef gEthHandle;
36 osThreadId_t gEthTaskID = NULL;
37 osSemaphoreId_t gEthSemaphore = NULL;
38
39 __ALIGN_BEGIN ETH_DMADescTypeDef DMARxDscrTab[ETH_RXBUFNB] __ALIGN_END;
40 __ALIGN_BEGIN ETH_DMADescTypeDef DMATxDscrTab[ETH_TXBUFNB] __ALIGN_END;
41 __ALIGN_BEGIN uint8_t DMARx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE] __ALIGN_END;
42 __ALIGN_BEGIN uint8_t DMATx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE] __ALIGN_END;
43
ETH_IPC_Create(void)44 void ETH_IPC_Create(void)
45 {
46 if (gEthSemaphore == NULL) {
47 gEthSemaphore = osSemaphoreNew(1, 0, NULL);
48 if (gEthSemaphore == NULL) {
49 ETH_DEBUG("ETH_IPC_Create gEthSemaphore failed!\r\n");
50 return;
51 }
52 }
53
54 if (gEthTaskID == NULL) {
55 osThreadAttr_t attr = {.name = "ETH_Input", .attr_bits = 0U, .cb_mem = NULL, .stack_mem = NULL, .stack_size = 3072, .priority = 5};
56 gEthTaskID = osThreadNew((osThreadFunc_t)ethernetif_input, NULL, &attr);
57 if (gEthTaskID == NULL) {
58 ETH_DEBUG("ETH_IPC_Create gEthTaskID failed!\r\n");
59 }
60 }
61 }
62
63 extern void ETH_IRQHandler(void);
HAL_ETH_MspInit(ETH_HandleTypeDef * heth)64 void HAL_ETH_MspInit(ETH_HandleTypeDef *heth)
65 {
66 GPIO_InitTypeDef GPIO_InitStructure;
67
68 ETH_GPIO_ClK_ENABLE();
69 ETH_RCC_CLK_ENABLE();
70
71 /**ETH GPIO Configuration
72 PA0 ------> ETH_RST
73 PC1 ------> ETH_MDC
74 PA1 ------> ETH_REF_CLK
75 PA2 ------> ETH_MDIO
76 PA7 ------> ETH_CRS_DV
77 PC4 ------> ETH_RXD0
78 PC5 ------> ETH_RXD1
79 PG11 ------> ETH_TX_EN
80 PG13 ------> ETH_TXD0
81 PG14 ------> ETH_TXD1
82 */
83 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);
84 GPIO_InitStructure.Pin = GPIO_PIN_0;
85 GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
86 GPIO_InitStructure.Pull = GPIO_NOPULL;
87 GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
88 GPIO_InitStructure.Alternate = GPIO_AF0_TRACE;
89 HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
90
91 GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
92 GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
93 GPIO_InitStructure.Pull = GPIO_NOPULL;
94 GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
95 GPIO_InitStructure.Alternate = GPIO_AFx_ETH;
96 HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
97
98 GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
99 GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
100 GPIO_InitStructure.Pull = GPIO_NOPULL;
101 GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
102 GPIO_InitStructure.Alternate = GPIO_AFx_ETH;
103 HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
104
105 GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14;
106 GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
107 GPIO_InitStructure.Pull = GPIO_NOPULL;
108 GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
109 GPIO_InitStructure.Alternate = GPIO_AFx_ETH;
110 HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
111
112 LOS_HwiCreate(ETH_IRQn, 0, 5, (HWI_PROC_FUNC)USER_IRQHandler, 0);
113 }
114
getmac(uint8_t * pMacBuf)115 void getmac(uint8_t *pMacBuf)
116 {
117 if (pMacBuf == NULL)
118 return;
119
120 uint32_t uiMcuId = 0;
121 uint8_t pMcuID[15] = {0};
122 int i = 0;
123 uint32_t CpuID[3] = {0};
124
125 CpuID[0] = *(uint32_t *)(0x1fff7a10);
126 CpuID[1] = *(uint32_t *)(0x1fff7a14);
127 CpuID[2] = *(uint32_t *)(0x1fff7a18);
128 ETH_DEBUG("MCU UID: %08X-%08X-%08X\r\n",CpuID[0],CpuID[1],CpuID[2]);
129
130 pMcuID[0] = (uint8_t)(CpuID[0] & 0x000000FF);
131 pMcuID[1] = (uint8_t)((CpuID[0] & 0xFF00) >> 8);
132 pMcuID[2] = (uint8_t)((CpuID[0] & 0xFF0000) >> 16);
133 pMcuID[3] = (uint8_t)((CpuID[0] & 0xFF000000) >> 24);
134
135 pMcuID[4] = (uint8_t)(CpuID[1] & 0xFF);
136 pMcuID[5] = (uint8_t)((CpuID[1] & 0xFF00) >> 8);
137 pMcuID[6] = (uint8_t)((CpuID[1] & 0xFF0000) >> 16);
138 pMcuID[7] = (uint8_t)((CpuID[1] & 0xFF000000) >> 24);
139
140 pMcuID[8] = (uint8_t)(CpuID[2] & 0xFF);
141 pMcuID[9] = (uint8_t)((CpuID[2] & 0xFF00) >> 8);
142 pMcuID[10] = (uint8_t)((CpuID[2] & 0xFF0000) >> 16);
143 pMcuID[11] = (uint8_t)((CpuID[2] & 0xFF000000) >> 24);
144
145 uiMcuId = (CpuID[0] >> 1) + (CpuID[1] >> 2) + (CpuID[2] >> 3);
146
147 for (i = 0; i < 12; i++) {
148 pMcuID[12] += pMcuID[i];
149 }
150 for (i = 0; i < 12; i++) {
151 pMcuID[13] ^= pMcuID[i];
152 }
153
154 pMacBuf[0] = pMcuID[12] & 0xFE;
155 pMacBuf[1] = (uint8_t)(uiMcuId & 0xFF);
156 pMacBuf[2] = (uint8_t)((uiMcuId & 0xFF00) >> 8);
157 pMacBuf[3] = (uint8_t)((uiMcuId & 0xFF0000) >> 16);
158 pMacBuf[4] = (uint8_t)((uiMcuId & 0xFF000000) >> 24);
159 pMacBuf[5] = pMcuID[13];
160 return;
161 }
162
low_level_init(struct netif * netif)163 void low_level_init(struct netif *netif)
164 {
165 uint32_t regvalue = 0;
166 uint8_t macaddress[6] = {0};
167 EthLinkInfo linkInfo = {0};
168
169 get_ethernet_link_info(&linkInfo);
170 if (linkInfo.useStaticMac == 1) {
171 memcpy(macaddress, linkInfo.macAddr, 6);
172 } else {
173 getmac(macaddress);
174 memcpy(linkInfo.macAddr, macaddress, 6);
175 set_ethernet_link_info(&linkInfo);
176 }
177
178 ETH_DEBUG("MacADDR: %02X-%02X-%02X-%02X-%02X-%02X\n", macaddress[0], macaddress[1],
179 macaddress[2], macaddress[3],
180 macaddress[4], macaddress[5]);
181
182 gEthHandle.Instance = ETH;
183 gEthHandle.Init.MACAddr = macaddress;
184 gEthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
185 gEthHandle.Init.Speed = ETH_SPEED_100M;
186 gEthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
187 gEthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
188 gEthHandle.Init.RxMode = ETH_RXINTERRUPT_MODE;
189 gEthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
190 gEthHandle.Init.PhyAddress = LAN8720_PHY_ADDRESS;
191 if (HAL_ETH_Init(&gEthHandle) == HAL_OK) {
192 ETH_DEBUG("ETH Init Success!\r\n");
193 netif->flags |= NETIF_FLAG_LINK_UP;
194 } else {
195 ETH_DEBUG("ETH Init Fail!\r\n");
196 netif->flags &= ~NETIF_FLAG_LINK_UP;
197 }
198
199 HAL_ETH_DMATxDescListInit(&gEthHandle, DMATxDscrTab, &DMATx_Buff[0][0], ETH_TXBUFNB);
200 HAL_ETH_DMARxDescListInit(&gEthHandle, DMARxDscrTab, &DMARx_Buff[0][0], ETH_RXBUFNB);
201
202 netif->hwaddr_len = ETH_HWADDR_LEN;
203 netif->hwaddr[0] = macaddress[0];
204 netif->hwaddr[1] = macaddress[1];
205 netif->hwaddr[2] = macaddress[2];
206 netif->hwaddr[3] = macaddress[3];
207 netif->hwaddr[4] = macaddress[4];
208 netif->hwaddr[5] = macaddress[5];
209
210 netif->mtu = 1500;
211 netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
212
213 ETH_IPC_Create();
214
215 HAL_ETH_Start(&gEthHandle);
216 HAL_ETH_ReadPHYRegister(&gEthHandle, 0x02, ®value);
217
218 /* enable phy interrupt */
219 HAL_ETH_ReadPHYRegister(&gEthHandle, PHY_MICR, ®value);
220 regvalue |= (PHY_MICR_INT_EN | PHY_MICR_INT_OE);
221 HAL_ETH_WritePHYRegister(&gEthHandle, PHY_MICR, regvalue);
222
223 HAL_ETH_ReadPHYRegister(&gEthHandle, PHY_MISR, ®value);
224 regvalue |= PHY_MISR_LINK_INT_EN;
225 HAL_ETH_WritePHYRegister(&gEthHandle, PHY_MISR, regvalue);
226 }
227
low_level_input(struct netif * netif)228 struct pbuf *low_level_input(struct netif *netif)
229 {
230 struct pbuf *p = NULL, *q = NULL;
231 volatile ETH_DMADescTypeDef *dmarxdesc;
232 uint32_t bufferoffset = 0;
233 uint32_t payloadoffset = 0;
234 uint32_t byteslefttocopy = 0;
235 if (HAL_ETH_GetReceivedFrame_IT(&gEthHandle) != HAL_OK) {
236 return NULL;
237 }
238 uint16_t len = gEthHandle.RxFrameInfos.length;
239 uint8_t *buffer = (uint8_t *)gEthHandle.RxFrameInfos.buffer;
240
241 if (len > 0) {
242 p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
243 }
244
245 if (p != NULL) {
246 dmarxdesc = gEthHandle.RxFrameInfos.FSRxDesc;
247 bufferoffset = 0;
248 for (q = p; q != NULL; q = q->next) {
249 byteslefttocopy = q->len;
250 payloadoffset = 0;
251 while ((byteslefttocopy + bufferoffset) > ETH_RX_BUF_SIZE) {
252 memcpy((uint8_t *)((uint8_t *)q->payload + payloadoffset), (uint8_t *)((uint8_t *)buffer + bufferoffset), (ETH_RX_BUF_SIZE - bufferoffset));
253 dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr);
254 buffer = (uint8_t *)(dmarxdesc->Buffer1Addr);
255
256 byteslefttocopy = byteslefttocopy - (ETH_RX_BUF_SIZE - bufferoffset);
257 payloadoffset = payloadoffset + (ETH_RX_BUF_SIZE - bufferoffset);
258 bufferoffset = 0;
259 }
260 memcpy((uint8_t *)((uint8_t *)q->payload + payloadoffset), (uint8_t *)((uint8_t *)buffer + bufferoffset), byteslefttocopy);
261 bufferoffset = bufferoffset + byteslefttocopy;
262 }
263 }
264 dmarxdesc = gEthHandle.RxFrameInfos.FSRxDesc;
265 for (uint32_t i = 0; i < gEthHandle.RxFrameInfos.SegCount; i++) {
266 dmarxdesc->Status |= ETH_DMARXDESC_OWN;
267 dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr);
268 }
269 gEthHandle.RxFrameInfos.SegCount = 0;
270 if ((gEthHandle.Instance->DMASR & ETH_DMASR_RBUS) != (uint32_t)RESET) {
271 gEthHandle.Instance->DMASR = ETH_DMASR_RBUS;
272 gEthHandle.Instance->DMARPDR = 0;
273 }
274 return p;
275 }
276
low_level_output(struct netif * netif,struct pbuf * p)277 err_t low_level_output(struct netif *netif, struct pbuf *p)
278 {
279 err_t errval;
280 struct pbuf *q;
281 uint8_t *buffer = (uint8_t *)(gEthHandle.TxDesc->Buffer1Addr);
282 volatile ETH_DMADescTypeDef *DmaTxDesc;
283 uint32_t framelength = 0;
284 uint32_t bufferoffset = 0;
285 uint32_t payloadoffset = 0;
286 uint32_t byteslefttocopy = 0;
287
288 DmaTxDesc = gEthHandle.TxDesc;
289 for (q = p; q != NULL; q = q->next) {
290 if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET) {
291 errval = ERR_USE;
292 goto error;
293 }
294
295 byteslefttocopy = q->len;
296 bufferoffset = 0;
297 while ((byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE) {
298 memcpy((uint8_t *)((uint8_t *)buffer + bufferoffset), (uint8_t *)((uint8_t *)q->payload + payloadoffset), (ETH_TX_BUF_SIZE - bufferoffset));
299 DmaTxDesc = (ETH_DMADescTypeDef *)(DmaTxDesc->Buffer2NextDescAddr);
300 if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET) {
301 errval = ERR_USE;
302 goto error;
303 }
304
305 buffer = (uint8_t *)(DmaTxDesc->Buffer1Addr);
306 byteslefttocopy = byteslefttocopy - (ETH_TX_BUF_SIZE - bufferoffset);
307 payloadoffset = payloadoffset + (ETH_TX_BUF_SIZE - bufferoffset);
308 framelength = framelength + (ETH_TX_BUF_SIZE - bufferoffset);
309 bufferoffset = 0;
310 }
311
312 memcpy((uint8_t *)((uint8_t *)buffer + bufferoffset), (uint8_t *)((uint8_t *)q->payload + payloadoffset), byteslefttocopy);
313 bufferoffset = bufferoffset + byteslefttocopy;
314 framelength = framelength + byteslefttocopy;
315 }
316 HAL_ETH_TransmitFrame(&gEthHandle, framelength);
317 errval = ERR_OK;
318
319 error:
320 if ((gEthHandle.Instance->DMASR & ETH_DMASR_TUS) != (uint32_t)RESET) {
321 gEthHandle.Instance->DMASR = ETH_DMASR_TUS;
322 gEthHandle.Instance->DMATPDR = 0;
323 }
324 return errval;
325 }
326
HAL_ETH_RxCpltCallback(ETH_HandleTypeDef * heth)327 void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
328 {
329 osSemaphoreRelease(gEthSemaphore);
330 }
331
ethernetif_input(void const * argument)332 void ethernetif_input(void const *argument)
333 {
334 struct pbuf *p;
335 struct netif *netif = (struct netif *)&gNetif;
336
337 for (;;) {
338 if (osSemaphoreAcquire(gEthSemaphore, osWaitForever) == osOK) {
339 do {
340 p = low_level_input(netif);
341 if (p != NULL) {
342 if (netif->input(p, netif) != ERR_OK) {
343 pbuf_free(p);
344 }
345 }
346 } while (p != NULL);
347 }
348 }
349 }
350
ethernetif_init(struct netif * netif)351 err_t ethernetif_init(struct netif *netif)
352 {
353 #if LWIP_NETIF_HOSTNAME
354 netif->hostname = "talkweb_stm32";
355 #endif
356
357 netif->name[0] = IFNAME0;
358 netif->name[1] = IFNAME1;
359
360 netif->output = etharp_output;
361 netif->linkoutput = low_level_output;
362
363 low_level_init(netif);
364
365 return ERR_OK;
366 }
367
USER_IRQHandler(void)368 void USER_IRQHandler(void)
369 {
370 osKernelLock();
371 HAL_ETH_IRQHandler(&gEthHandle);
372 osKernelUnlock();
373 }
374