• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &regvalue);
217 
218     /* enable phy interrupt */
219     HAL_ETH_ReadPHYRegister(&gEthHandle, PHY_MICR, &regvalue);
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, &regvalue);
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