This is an automated email from the ASF dual-hosted git repository. mgorecki pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 9fbe172c3602f94df5caaa676b39376dc752a5a4 Author: Michal Gorecki <[email protected]> AuthorDate: Tue Feb 25 10:17:47 2025 +0100 hw/drivers: Migrate STM32 Ethernet driver to new HAL --- hw/drivers/lwip/stm32_eth/src/stm32_eth.c | 334 ++++++++++++------------------ hw/drivers/lwip/stm32_eth/syscfg.yml | 4 + 2 files changed, 135 insertions(+), 203 deletions(-) diff --git a/hw/drivers/lwip/stm32_eth/src/stm32_eth.c b/hw/drivers/lwip/stm32_eth/src/stm32_eth.c index 245606c43..4d48d9dde 100644 --- a/hw/drivers/lwip/stm32_eth/src/stm32_eth.c +++ b/hw/drivers/lwip/stm32_eth/src/stm32_eth.c @@ -49,6 +49,7 @@ * This shows up as MMCRFCECR going up, and no valid RX happening. */ #define STM32_PHY_POLL_FREQ os_cputime_usecs_to_ticks(1500000) /* 1.5 secs */ +#define STM32_ETH_RX_BUFFER_CNT MYNEWT_VAL(STM32_ETH_RX_BUFFER_CNT) /* * Phy specific registers @@ -59,129 +60,108 @@ #define SMSC_8710_ISR_AUTO_DONE 0x40 #define SMSC_8710_ISR_LINK_DOWN 0x10 -#define STM32_ETH_RX_DESC_SZ 3 -#define STM32_ETH_TX_DESC_SZ 4 - -struct stm32_eth_desc { - volatile ETH_DMADescTypeDef desc; - struct pbuf *p; +struct rx_buff { + struct pbuf_custom pbuf_custom; + uint8_t buff[(ETH_RX_BUF_SIZE + 31) & ~31]; }; struct stm32_eth_state { struct netif st_nif; ETH_HandleTypeDef st_eth; - struct stm32_eth_desc st_rx_descs[STM32_ETH_RX_DESC_SZ]; - struct stm32_eth_desc st_tx_descs[STM32_ETH_TX_DESC_SZ]; - uint8_t st_rx_head; - uint8_t st_rx_tail; - uint8_t st_tx_head; - uint8_t st_tx_tail; + ETH_DMADescTypeDef st_rx_descs[ETH_RX_DESC_CNT]; + ETH_DMADescTypeDef st_tx_descs[ETH_TX_DESC_CNT]; + ETH_TxPacketConfig st_tx_cfg; + ETH_MACConfigTypeDef st_mac_cfg; struct hal_timer st_phy_tmr; const struct stm32_eth_cfg *cfg; }; -struct stm32_eth_stats { - uint32_t oframe; - uint32_t odone; - uint32_t oerr; - uint32_t iframe; - uint32_t imem; -} stm32_eth_stats; - static struct stm32_eth_state stm32_eth_state; +static bool rx_alloc_failed; + +LWIP_MEMPOOL_DECLARE(RX_POOL, STM32_ETH_RX_BUFFER_CNT, sizeof(struct rx_buff), "Zero-copy RX PBUF pool"); static void -stm32_eth_setup_descs(struct stm32_eth_desc *descs, int cnt) +stm32_eth_input(struct stm32_eth_state *ses) { - int i; + struct pbuf *p = NULL; - for (i = 0; i < cnt - 1; i++) { - descs[i].desc.Status = 0; - descs[i].desc.Buffer2NextDescAddr = (uint32_t)&descs[i + 1].desc; + if (rx_alloc_failed) { + return; } - descs[cnt - 1].desc.Status = 0; - descs[cnt - 1].desc.Buffer2NextDescAddr = (uint32_t)&descs[0].desc; -} -static void -stm32_eth_fill_rx(struct stm32_eth_state *ses) -{ - struct stm32_eth_desc *sed; - struct pbuf *p; - - while (1) { - sed = &ses->st_rx_descs[ses->st_rx_tail]; - if (sed->p) { - break; - } - p = pbuf_alloc(PBUF_RAW, ETH_MAX_PACKET_SIZE, PBUF_POOL); - if (!p) { - ++stm32_eth_stats.imem; - break; - } - sed->p = p; - sed->desc.Status = 0; - sed->desc.ControlBufferSize = ETH_DMARXDESC_RCH | ETH_MAX_PACKET_SIZE; - sed->desc.Buffer1Addr = (uint32_t)p->payload; - sed->desc.Status = ETH_DMARXDESC_OWN; - - ses->st_rx_tail++; - if (ses->st_rx_tail >= STM32_ETH_RX_DESC_SZ) { - ses->st_rx_tail = 0; + HAL_ETH_ReadData(&ses->st_eth, (void **)&p); + if (p != NULL) { + if (ses->st_nif.input(p, &ses->st_nif) != ERR_OK) { + pbuf_free(p); } } } -static void -stm32_eth_input(struct stm32_eth_state *ses) +void +HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth) { - struct stm32_eth_desc *sed; - struct pbuf *p; - struct netif *nif; + struct stm32_eth_state *ses = &stm32_eth_state; - nif = &ses->st_nif; + stm32_eth_input(ses); +} - while (1) { - sed = &ses->st_rx_descs[ses->st_rx_head]; - if (!sed->p) { - break; - } - if (sed->desc.Status & ETH_DMARXDESC_OWN) { - break; - } - p = sed->p; - sed->p = NULL; - if (!(sed->desc.Status & ETH_DMARXDESC_LS)) { - /* - * Incoming data spans multiple pbufs. XXX support later - */ - pbuf_free(p); - continue; - } - p->len = p->tot_len = (sed->desc.Status & ETH_DMARXDESC_FL) >> 16; - ++stm32_eth_stats.iframe; - nif->input(p, nif); - ses->st_rx_head++; - if (ses->st_rx_head >= STM32_ETH_RX_DESC_SZ) { - ses->st_rx_head = 0; - } +void +pbuf_free_custom(struct pbuf *p) +{ + struct pbuf_custom *custom_pbuf = (struct pbuf_custom *)p; + struct stm32_eth_state *ses = &stm32_eth_state; + LWIP_MEMPOOL_FREE(RX_POOL, custom_pbuf); + + if (rx_alloc_failed) { + rx_alloc_failed = 0; + stm32_eth_input(ses); } +} - stm32_eth_fill_rx(ses); +void +HAL_ETH_RxAllocateCallback(uint8_t **buff) +{ + struct pbuf_custom *p; - if (ses->st_eth.Instance->DMASR & ETH_DMASR_RBUS) { - /* - * Resume DMA reception - */ - ses->st_eth.Instance->DMASR = ETH_DMASR_RBUS; - ses->st_eth.Instance->DMARPDR = 0; + p = LWIP_MEMPOOL_ALLOC(RX_POOL); + if (p != NULL) { + *buff = ((struct rx_buff *)p)->buff; + p->custom_free_function = pbuf_free_custom; + pbuf_alloced_custom(PBUF_RAW, 0, PBUF_REF, p, *buff, ETH_RX_BUF_SIZE); + } else { + rx_alloc_failed = 1; } } void -HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth) +HAL_ETH_RxLinkCallback(void **p_start, void **p_end, uint8_t *buff, uint16_t len) { - stm32_eth_input(&stm32_eth_state); + struct pbuf **pp_start = (struct pbuf **)p_start; + struct pbuf **pp_end = (struct pbuf **)p_end; + struct pbuf *p = NULL; + + /* Get the struct pbuf from the buff address. */ + p = (struct pbuf *)(buff - offsetof(struct rx_buff, buff)); + p->next = NULL; + p->tot_len = 0; + p->len = len; + + /* Chain the buffer. */ + if (!*pp_start) { + /* The first buffer of the packet. */ + *pp_start = p; + } else { + /* Chain the buffer to the end of the packet. */ + (*pp_end)->next = p; + } + *pp_end = p; + + /* Update the total length of all the buffers of the chain. Each pbuf in the chain should have its tot_len + * set to its own length, plus the length of all the following pbufs in the chain. */ + for (p = *pp_start; p != NULL; p = p->next) { + p->tot_len += len; + } } /* @@ -215,99 +195,42 @@ stm32_mld_mac_filter(struct netif *nif, const ip6_addr_t *group, } #endif -static void -stm32_eth_output_done(struct stm32_eth_state *ses) -{ - struct stm32_eth_desc *sed; - - while (1) { - sed = &ses->st_tx_descs[ses->st_tx_tail]; - if (!sed->p) { - break; - } - if (sed->desc.Status & ETH_DMATXDESC_OWN) { - /* - * Belongs to board - */ - break; - } - if (sed->desc.Status & ETH_DMATXDESC_ES) { - ++stm32_eth_stats.oerr; - } else { - ++stm32_eth_stats.odone; - } - pbuf_free(sed->p); - sed->p = NULL; - ses->st_tx_tail++; - if (ses->st_tx_tail >= STM32_ETH_TX_DESC_SZ) { - ses->st_tx_tail = 0; - } - } -} - static err_t stm32_eth_output(struct netif *nif, struct pbuf *p) { - struct stm32_eth_state *ses = (struct stm32_eth_state *)nif; - struct stm32_eth_desc *sed; - uint32_t reg; + int i = 0; struct pbuf *q; - err_t errval; + err_t errval = ERR_OK; + ETH_BufferTypeDef tx_buffer[ETH_TX_DESC_CNT] = {0}; + struct stm32_eth_state *ses = &stm32_eth_state; - stm32_eth_output_done(ses); + memset(tx_buffer, 0, ETH_TX_DESC_CNT * sizeof(ETH_BufferTypeDef)); - ++stm32_eth_stats.oframe; - sed = &ses->st_tx_descs[ses->st_tx_head]; - for (q = p; q; q = q->next) { - if (!q->len) { - continue; - } - if (sed->desc.Status & ETH_DMATXDESC_OWN) { - /* - * Not enough space. - */ - errval = ERR_MEM; - goto error; + for (q = p; q != NULL; q = q->next) { + if (i >= ETH_TX_DESC_CNT) { + return ERR_IF; } - sed = (struct stm32_eth_desc *)sed->desc.Buffer2NextDescAddr; - } - for (q = p; q; q = q->next) { - if (!q->len) { - continue; - } - sed = &ses->st_tx_descs[ses->st_tx_head]; - if (q == p) { - reg = ETH_DMATXDESC_FS | ETH_DMATXDESC_TCH; - } else { - reg = ETH_DMATXDESC_TCH; + tx_buffer[i].buffer = q->payload; + tx_buffer[i].len = q->len; + + if (i > 0) { + tx_buffer[i - 1].next = &tx_buffer[i]; } + if (q->next == NULL) { - reg |= ETH_DMATXDESC_LS; - } - sed->desc.Status = reg; - sed->desc.ControlBufferSize = p->len; - sed->desc.Buffer1Addr = (uint32_t)p->payload; - sed->p = p; - pbuf_ref(p); - sed->desc.Status = reg | ETH_DMATXDESC_OWN; - ses->st_tx_head++; - if (ses->st_tx_head >= STM32_ETH_TX_DESC_SZ) { - ses->st_tx_head = 0; + tx_buffer[i].next = NULL; } - } - if (ses->st_eth.Instance->DMASR & ETH_DMASR_TBUS) { - /* - * Resume DMA transmission. - */ - ses->st_eth.Instance->DMASR = ETH_DMASR_TBUS; - ses->st_eth.Instance->DMATPDR = 0U; + i++; } - return ERR_OK; -error: - ++stm32_eth_stats.oerr; + ses->st_tx_cfg.Length = p->tot_len; + ses->st_tx_cfg.TxBuffer = tx_buffer; + ses->st_tx_cfg.pData = p; + + HAL_ETH_Transmit(&ses->st_eth, &ses->st_tx_cfg, 20); + return errval; } @@ -321,10 +244,14 @@ static void stm32_phy_isr(void *arg) { struct stm32_eth_state *ses = (void *)arg; + const struct stm32_eth_cfg *cfg; uint32_t reg; - HAL_ETH_ReadPHYRegister(&ses->st_eth, PHY_BSR, ®); - if (reg & PHY_LINKED_STATUS && + cfg = ses->cfg; + + HAL_ETH_ReadPHYRegister(&ses->st_eth, cfg->sec_phy_addr, PHY_BSR, ®); + + if ((reg & PHY_LINKED_STATUS) && (ses->st_nif.flags & NETIF_FLAG_LINK_UP) == 0) { netif_set_link_up(&ses->st_nif); } else if ((reg & PHY_LINKED_STATUS) == 0 && @@ -334,7 +261,7 @@ stm32_phy_isr(void *arg) switch (ses->cfg->sec_phy_type) { case SMSC_8710_RMII: case LAN_8742_RMII: - HAL_ETH_ReadPHYRegister(&ses->st_eth, SMSC_8710_ISR, ®); + HAL_ETH_ReadPHYRegister(&ses->st_eth, cfg->sec_phy_addr, SMSC_8710_ISR, ®); } } @@ -378,6 +305,8 @@ stm32_lwip_init(struct netif *nif) nif->mld_mac_filter = stm32_mld_mac_filter; #endif + LWIP_MEMPOOL_INIT(RX_POOL); + cfg = ses->cfg; /* @@ -396,39 +325,27 @@ stm32_lwip_init(struct netif *nif) __HAL_RCC_ETH_CLK_ENABLE(); ses->st_eth.Instance = ETH; - - ses->st_eth.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE; - ses->st_eth.Init.Speed = ETH_SPEED_100M; - ses->st_eth.Init.DuplexMode = ETH_MODE_FULLDUPLEX; - ses->st_eth.Init.PhyAddress = cfg->sec_phy_addr; - ses->st_eth.Init.RxMode = ETH_RXINTERRUPT_MODE; - ses->st_eth.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE; + ses->st_eth.Init.RxDesc = ses->st_rx_descs; + ses->st_eth.Init.TxDesc = ses->st_tx_descs; + ses->st_eth.Init.RxBuffLen = ETH_RX_BUF_SIZE; switch (cfg->sec_phy_type) { case SMSC_8710_RMII: case LAN_8742_RMII: - ses->st_eth.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII; - } - - ses->st_rx_head = 0; - ses->st_rx_tail = 0; - ses->st_tx_head = 0; - ses->st_tx_tail = 0; - - stm32_eth_setup_descs(ses->st_rx_descs, STM32_ETH_RX_DESC_SZ); - stm32_eth_setup_descs(ses->st_tx_descs, STM32_ETH_TX_DESC_SZ); - stm32_eth_fill_rx(ses); - - if (HAL_ETH_Init(&ses->st_eth) == HAL_ERROR) { - return ERR_IF; + ses->st_eth.Init.MediaInterface = HAL_ETH_RMII_MODE; } + ses->st_tx_cfg.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD; + ses->st_tx_cfg.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC; + ses->st_tx_cfg.CRCPadCtrl = ETH_CRC_PAD_INSERT; /* * XXX pass all multicast traffic for now */ ses->st_eth.Instance->MACFFR |= ETH_MULTICASTFRAMESFILTER_NONE; - ses->st_eth.Instance->DMATDLAR = (uint32_t)ses->st_tx_descs; - ses->st_eth.Instance->DMARDLAR = (uint32_t)ses->st_rx_descs; + + if (HAL_ETH_Init(&ses->st_eth) == HAL_ERROR) { + return ERR_IF; + } /* * Generate an interrupt when link state changes @@ -436,9 +353,9 @@ stm32_lwip_init(struct netif *nif) if (cfg->sec_phy_irq >= 0) { switch (cfg->sec_phy_type) { case SMSC_8710_RMII: - HAL_ETH_ReadPHYRegister(&ses->st_eth, SMSC_8710_IMR, ®); + HAL_ETH_ReadPHYRegister(&ses->st_eth, cfg->sec_phy_addr, SMSC_8710_IMR, ®); reg |= (SMSC_8710_ISR_AUTO_DONE | SMSC_8710_ISR_LINK_DOWN); - HAL_ETH_WritePHYRegister(&ses->st_eth, SMSC_8710_IMR, reg); + HAL_ETH_WritePHYRegister(&ses->st_eth, cfg->sec_phy_addr, SMSC_8710_IMR, reg); case LAN_8742_RMII: /* XXX */ break; @@ -447,8 +364,16 @@ stm32_lwip_init(struct netif *nif) os_cputime_timer_init(&ses->st_phy_tmr, stm32_phy_poll, ses); os_cputime_timer_relative(&ses->st_phy_tmr, STM32_PHY_POLL_FREQ); } + + HAL_ETH_GetMACConfig(&ses->st_eth, &ses->st_mac_cfg); + ses->st_mac_cfg.DuplexMode = ETH_FULLDUPLEX_MODE; + ses->st_mac_cfg.Speed = ETH_SPEED_100M; + HAL_ETH_SetMACConfig(&ses->st_eth, &ses->st_mac_cfg); + NVIC_EnableIRQ(ETH_IRQn); - HAL_ETH_Start(&ses->st_eth); + if (HAL_ETH_Start_IT(&ses->st_eth) == HAL_ERROR) { + return ERR_IF; + } /* * Check for link. @@ -462,19 +387,22 @@ stm32_mii_dump(int (*func)(const char *fmt, ...)) { int i; struct stm32_eth_state *ses = &stm32_eth_state; + const struct stm32_eth_cfg *cfg; uint32_t reg; int rc; + cfg = ses->cfg; + for (i = 0; i <= 6; i++) { - rc = HAL_ETH_ReadPHYRegister(&ses->st_eth, i, ®); + rc = HAL_ETH_ReadPHYRegister(&ses->st_eth, cfg->sec_phy_addr, i, ®); func("%d: %x (%d)\n", i, reg, rc); } for (i = 17; i <= 18; i++) { - rc = HAL_ETH_ReadPHYRegister(&ses->st_eth, i, ®); + rc = HAL_ETH_ReadPHYRegister(&ses->st_eth, cfg->sec_phy_addr, i, ®); func("%d: %x (%d)\n", i, reg, rc); } for (i = 26; i <= 31; i++) { - rc = HAL_ETH_ReadPHYRegister(&ses->st_eth, i, ®); + rc = HAL_ETH_ReadPHYRegister(&ses->st_eth, cfg->sec_phy_addr, i, ®); func("%d: %x (%d)\n", i, reg, rc); } return 0; diff --git a/hw/drivers/lwip/stm32_eth/syscfg.yml b/hw/drivers/lwip/stm32_eth/syscfg.yml index 6f8819526..9fc306941 100644 --- a/hw/drivers/lwip/stm32_eth/syscfg.yml +++ b/hw/drivers/lwip/stm32_eth/syscfg.yml @@ -26,3 +26,7 @@ syscfg.defs: STM32_MAC_ADDR: description: "Use given array of 6 bytes for MAC address." value: ((uint8_t[6]){0x00, 0x01, 0x01, 0x02, 0x02, 0x03}) + + STM32_ETH_RX_BUFFER_CNT: + description: "Number of buffers to store RX packets" + value: 10
