💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
在前面的4.4 章节与6.8 章节中已经讲解了关于底层驱动的函数,这些函数在网卡中至关重要,而ethernetif.c文件就是存放这些函数的,LwIP的contrib包中就包含这个文件的模板,我们直接拿过来修改即可,该文件的路径为“contrib-2.1.0\\examples\\ethernetif”,然后我们拷贝到arch文件夹下,并且创建一个ethernetif.h文件,一同添加到我们的工程中即可。我们直接使用4.4 章节与6.8 章节编写的网卡驱动代码,在编写完成的ethernetif.c文件内容具体见代码清单 7‑4: ``` 1 #include "main.h" 2 #include "lwip/opt.h" 3 #include "lwip/mem.h" 4 #include "lwip/memp.h" 5 #include "lwip/timeouts.h" 6 #include "netif/ethernet.h" 7 #include "netif/etharp.h" 8 #include "lwip/ethip6.h" 9 #include "ethernetif.h" 10 #include <string.h> 11 12 13 /* Network interface name */ 14 #define IFNAME0 's' 15 #define IFNAME1 't' 16 17 18 struct ethernetif 19 { 20 struct eth_addr *ethaddr; 21 /* Add whatever per-interface state that is needed here. */ 22 }; 23 24 25 extern ETH_HandleTypeDef heth; 26 27 static void arp_timer(void *arg); 28 29 30 static void low_level_init(struct netif *netif) 31 { 32 HAL_StatusTypeDef hal_eth_init_status; 33 34 //初始化bsp—eth 35 hal_eth_init_status = Bsp_Eth_Init(); 36 37 if (hal_eth_init_status == HAL_OK) 38 { 39 /* Set netif link flag */ 40 netif->flags |= NETIF_FLAG_LINK_UP; 41 } 42 43 #if LWIP_ARP || LWIP_ETHERNET 44 45 /* set MAC hardware address length */ 46 netif->hwaddr_len = ETH_HWADDR_LEN; 47 48 /* set MAC hardware address */ 49 netif->hwaddr[0] = heth.Init.MACAddr[0]; 50 netif->hwaddr[1] = heth.Init.MACAddr[1]; 51 netif->hwaddr[2] = heth.Init.MACAddr[2]; 52 netif->hwaddr[3] = heth.Init.MACAddr[3]; 53 netif->hwaddr[4] = heth.Init.MACAddr[4]; 54 netif->hwaddr[5] = heth.Init.MACAddr[5]; 55 56 /* maximum transfer unit */ 57 netif->mtu = NETIF_MTU; 58 59 #if LWIP_ARP 60 netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; 61 #else 62 netif->flags |= NETIF_FLAG_BROADCAST; 63 #endif /* LWIP_ARP */ 64 65 #endif /* LWIP_ARP || LWIP_ETHERNET */ 66 67 HAL_ETH_Start(&heth); 68 } 69 70 71 static err_t low_level_output(struct netif *netif, struct pbuf *p) 72 { 73 74 err_t errval; 75 struct pbuf *q; 76 77 uint8_t *buffer = (uint8_t *)(heth.TxDesc->Buffer1Addr); 78 79 __IO ETH_DMADescTypeDef *DmaTxDesc; 80 81 uint32_t bufferoffset = 0; 82 uint32_t framelength = 0; 83 84 uint32_t byteslefttocopy = 0; 85 86 uint32_t payloadoffset = 0; 87 88 DmaTxDesc = heth.TxDesc; 89 bufferoffset = 0; 90 91 if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET) 92 { 93 errval = ERR_USE; 94 goto error; 95 } 96 97 98 /* copy frame from pbufs to driver buffers */ 99 for (q = p; q != NULL; q = q->next) 100 { 101 /* Get bytes in current lwIP buffer */ 102 byteslefttocopy = q->len; 103 payloadoffset = 0; 104 105 /*Check if the length of data to copy is bigger than Tx buffer size*/ 106 while ( (byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE ) 107 { 108 /* Copy data to Tx buffer*/ 109 memcpy( (uint8_t*)((uint8_t*)buffer + bufferoffset), 110 (uint8_t*)((uint8_t*)q->payload + payloadoffset), 111 (ETH_TX_BUF_SIZE - bufferoffset) ); 112 113 /* Point to next descriptor */ 114 DmaTxDesc = (ETH_DMADescTypeDef *)(DmaTxDesc->Buffer2NextDescAddr); 115 116 /* Check if the buffer is available */ 117 if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET) 118 { 119 errval = ERR_USE; 120 goto error; 121 } 122 123 buffer = (uint8_t *)(DmaTxDesc->Buffer1Addr); 124 125 byteslefttocopy = byteslefttocopy - (ETH_TX_BUF_SIZE - bufferoffset); 126 payloadoffset = payloadoffset + (ETH_TX_BUF_SIZE - bufferoffset); 127 framelength = framelength + (ETH_TX_BUF_SIZE - bufferoffset); 128 bufferoffset = 0; 129 } 130 131 /* Copy the remaining bytes */ 132 memcpy( (uint8_t*)((uint8_t*)buffer + bufferoffset), 133 (uint8_t*)((uint8_t*)q->payload + payloadoffset), byteslefttocopy ); 134 bufferoffset = bufferoffset + byteslefttocopy; 135 framelength = framelength + byteslefttocopy; 136 } 137 138 /* Prepare transmit descriptors to give to DMA */ 139 HAL_ETH_TransmitFrame(&heth, framelength); 140 141 errval = ERR_OK; 142 143 error: 144 145 if ((heth.Instance->DMASR & ETH_DMASR_TUS) != (uint32_t)RESET) 146 { 147 /* Clear TUS ETHERNET DMA flag */ 148 heth.Instance->DMASR = ETH_DMASR_TUS; 149 150 /* Resume DMA transmission*/ 151 heth.Instance->DMATPDR = 0; 152 } 153 154 155 156 return errval; 157 } 158 159 160 static struct pbuf * low_level_input(struct netif *netif) 161 { 162 struct pbuf *p = NULL; 163 struct pbuf *q = NULL; 164 uint16_t len = 0; 165 uint8_t *buffer; 166 __IO ETH_DMADescTypeDef *dmarxdesc; 167 uint32_t bufferoffset = 0; 168 uint32_t payloadoffset = 0; 169 uint32_t byteslefttocopy = 0; 170 uint32_t i=0; 171 172 173 /* get received frame */ 174 if (HAL_ETH_GetReceivedFrame(&heth) != HAL_OK) 175 { 176 PRINT_ERR("receive frame faild\n"); 177 return NULL; 178 } 179 /*Obtain the size of the packet and put it into the "len" variable.*/ 180 len = heth.RxFrameInfos.length; 181 buffer = (uint8_t *)heth.RxFrameInfos.buffer; 182 183 PRINT_INFO("receive frame len : %d\n", len); 184 185 if (len > 0) 186 { 187 /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */ 188 p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); 189 } 190 191 if (p != NULL) 192 { 193 dmarxdesc = heth.RxFrameInfos.FSRxDesc; 194 bufferoffset = 0; 195 for (q = p; q != NULL; q = q->next) 196 { 197 byteslefttocopy = q->len; 198 payloadoffset = 0; 199 200 201 while ( (byteslefttocopy + bufferoffset) > ETH_RX_BUF_SIZE ) 202 { 203 /* Copy data to pbuf */ 204 memcpy( (uint8_t*)((uint8_t*)q->payload + payloadoffset), 205 (uint8_t*)((uint8_t*)buffer + bufferoffset), 206 (ETH_RX_BUF_SIZE - bufferoffset)); 207 208 /* Point to next descriptor */ 209 dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr); 210 buffer = (uint8_t *)(dmarxdesc->Buffer1Addr); 211 212 byteslefttocopy = byteslefttocopy - (ETH_RX_BUF_SIZE - bufferoffset); 213 payloadoffset = payloadoffset + (ETH_RX_BUF_SIZE - bufferoffset); 214 bufferoffset = 0; 215 } 216 /* Copy remaining data in pbuf */ 217 memcpy( (uint8_t*)((uint8_t*)q->payload + payloadoffset), 218 (uint8_t*)((uint8_t*)buffer + bufferoffset), byteslefttocopy); 219 bufferoffset = bufferoffset + byteslefttocopy; 220 } 221 } 222 223 /* Release descriptors to DMA */ 224 /* Point to first descriptor */ 225 dmarxdesc = heth.RxFrameInfos.FSRxDesc; 226 /* Set Own bit in Rx descriptors: gives the buffers back to DMA */ 227 for (i=0; i< heth.RxFrameInfos.SegCount; i++) 228 { 229 dmarxdesc->Status |= ETH_DMARXDESC_OWN; 230 dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr); 231 } 232 233 /* Clear Segment_Count */ 234 heth.RxFrameInfos.SegCount =0; 235 236 /* When Rx Buffer unavailable flag is set: clear it and resume reception */ 237 if ((heth.Instance->DMASR & ETH_DMASR_RBUS) != (uint32_t)RESET) 238 { 239 /* Clear RBUS ETHERNET DMA flag */ 240 heth.Instance->DMASR = ETH_DMASR_RBUS; 241 /* Resume DMA reception */ 242 heth.Instance->DMARPDR = 0; 243 } 244 return p; 245 } 246 247 248 void ethernetif_input(struct netif *netif) 249 { 250 err_t err; 251 struct pbuf *p; 252 253 /* move received packet into a new pbuf */ 254 p = low_level_input(netif); 255 256 /* no packet could be read, silently ignore this */ 257 if (p == NULL) return; 258 259 /* entry point to the LwIP stack */ 260 err = netif->input(p, netif); 261 262 if (err != ERR_OK) 263 { 264 LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); 265 pbuf_free(p); 266 p = NULL; 267 } 268 } 269 270 271 #if !LWIP_ARP 272 273 static err_t low_level_output_arp_off(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) 274 { 275 err_t errval; 276 errval = ERR_OK; 277 278 return errval; 279 280 } 281 #endif /* LWIP_ARP */ 282 283 err_t ethernetif_init(struct netif *netif) 284 { 285 struct ethernetif *ethernetif; 286 287 // LWIP_ASSERT("netif != NULL", (netif != NULL)); 288 289 ethernetif = mem_malloc(sizeof(struct ethernetif)); 290 291 if (ethernetif == NULL) 292 { 293 PRINT_ERR("ethernetif_init: out of memory\n"); 294 return ERR_MEM; 295 } 296 297 LWIP_ASSERT("netif != NULL", (netif != NULL)); 298 // 299 #if LWIP_NETIF_HOSTNAME 300 /* Initialize interface hostname */ 301 netif->hostname = "lwip"; 302 #endif /* LWIP_NETIF_HOSTNAME */ 303 netif->state = ethernetif; 304 netif->name[0] = IFNAME0; 305 netif->name[1] = IFNAME1; 306 307 #if LWIP_IPV4 308 #if LWIP_ARP || LWIP_ETHERNET 309 #if LWIP_ARP 310 netif->output = etharp_output; 311 #else 312 netif->output = low_level_output_arp_off; 313 #endif /* LWIP_ARP */ 314 #endif /* LWIP_ARP || LWIP_ETHERNET */ 315 #endif /* LWIP_IPV4 */ 316 317 #if LWIP_IPV6 318 netif->output_ip6 = ethip6_output; 319 #endif /* LWIP_IPV6 */ 320 321 netif->linkoutput = low_level_output; 322 323 /* initialize the hardware */ 324 low_level_init(netif); 325 ethernetif->ethaddr = (struct eth_addr *) &(netif->hwaddr[0]); 326 327 return ERR_OK; 328 } 329 330 static void arp_timer(void *arg) 331 { 332 etharp_tmr(); 333 sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); 334 } 335 336 /* USER CODE BEGIN 6 */ 337 338 339 void ethernetif_update_config(struct netif *netif) 340 { 341 __IO uint32_t tickstart = 0; 342 uint32_t regvalue = 0; 343 344 if (netif_is_link_up(netif)) 345 { 346 /* Restart the auto-negotiation */ 347 if (heth.Init.AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE) 348 { 349 /* Enable Auto-Negotiation */ 350 HAL_ETH_WritePHYRegister(&heth, PHY_BCR, PHY_AUTONEGOTIATION); 351 352 /* Get tick */ 353 tickstart = HAL_GetTick(); 354 355 /* Wait until the auto-negotiation will be completed */ 356 do 357 { 358 HAL_ETH_ReadPHYRegister(&heth, PHY_BSR, &regvalue); 359 360 /* Check for the Timeout ( 1s ) */ 361 if ((HAL_GetTick() - tickstart ) > 1000) 362 { 363 /* In case of timeout */ 364 goto error; 365 } 366 } 367 while (((regvalue & PHY_AUTONEGO_COMPLETE) != PHY_AUTONEGO_COMPLETE)); 368 369 /* Read the result of the auto-negotiation */ 370 HAL_ETH_ReadPHYRegister(&heth, PHY_SR, &regvalue); 371 372 373 if ((regvalue & PHY_DUPLEX_STATUS) != (uint32_t)RESET) 374 { 375 376 heth.Init.DuplexMode = ETH_MODE_FULLDUPLEX; 377 } 378 else 379 { 380 381 heth.Init.DuplexMode = ETH_MODE_HALFDUPLEX; 382 } 383 384 if (regvalue & PHY_SPEED_STATUS) 385 { 386 /* Set Ethernet speed to 10M following the auto-negotiation */ 387 heth.Init.Speed = ETH_SPEED_10M; 388 } 389 else 390 { 391 /* Set Ethernet speed to 100M following the auto-negotiation */ 392 heth.Init.Speed = ETH_SPEED_100M; 393 } 394 } 395 else /* AutoNegotiation Disable */ 396 { 397 error : 398 /* Check parameters */ 399 assert_param(IS_ETH_SPEED(heth.Init.Speed)); 400 assert_param(IS_ETH_DUPLEX_MODE(heth.Init.DuplexMode)); 401 402 /* Set MAC Speed and Duplex Mode to PHY */ 403 HAL_ETH_WritePHYRegister(&heth, PHY_BCR, 404 ((uint16_t)(heth.Init.DuplexMode >> 3) | 405 (uint16_t)(heth.Init.Speed >> 1))); 406 } 407 408 /* ETHERNET MAC Re-Configuration */ 409 HAL_ETH_ConfigMAC(&heth, (ETH_MACInitTypeDef *) NULL); 410 411 /* Restart MAC interface */ 412 HAL_ETH_Start(&heth); 413 } 414 else 415 { 416 /* Stop MAC interface */ 417 HAL_ETH_Stop(&heth); 418 } 419 420 ethernetif_notify_conn_changed(netif); 421 } ``` 当然,我们还需要一个ethernetif.h文件,主要是对函数的一些声明,其内容具体见代码清单 7‑5。 ``` 1 #ifndef __ETHERNETIF_H__ 2 #define __ETHERNETIF_H__ 3 4 #include "lwip/err.h" 5 #include "lwip/netif.h" 6 7 err_t ethernetif_init(struct netif *netif); 8 9 void ethernetif_input(struct netif *netif); 10 void ethernetif_update_config(struct netif *netif); 11 void ethernetif_notify_conn_changed(struct netif *netif); 12 13 #endif ```