This patch adds ST's Ethernet and lwIP port and DP83848 driver. The files are generated using STM32CubeIDE with STM32F4 Cube FW v1.27.1, under RTOS mode. --- COPYING.stm32 | 28 ++ ORIGIN.stm32 | 2 + stm32/driver/dp83848.c | 664 +++++++++++++++++++++++++++++++ stm32/driver/dp83848.h | 436 ++++++++++++++++++++ stm32/ethernetif.c | 879 +++++++++++++++++++++++++++++++++++++++++ stm32/ethernetif.h | 47 +++ stm32/lwip.h | 76 ++++ 7 files changed, 2132 insertions(+) create mode 100644 COPYING.stm32 create mode 100644 ORIGIN.stm32 create mode 100644 stm32/driver/dp83848.c create mode 100644 stm32/driver/dp83848.h create mode 100644 stm32/ethernetif.c create mode 100644 stm32/ethernetif.h create mode 100644 stm32/lwip.h
diff --git a/COPYING.stm32 b/COPYING.stm32 new file mode 100644 index 0000000..f42052b --- /dev/null +++ b/COPYING.stm32 @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 STMicroelectronics. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + */ + + diff --git a/ORIGIN.stm32 b/ORIGIN.stm32 new file mode 100644 index 0000000..afc15ed --- /dev/null +++ b/ORIGIN.stm32 @@ -0,0 +1,2 @@ +The files under stm32/ directory are generated using STM32CubeIDE with +STM32F4 Cube FW v1.27.1, under RTOS mode. diff --git a/stm32/driver/dp83848.c b/stm32/driver/dp83848.c new file mode 100644 index 0000000..2c5d59b --- /dev/null +++ b/stm32/driver/dp83848.c @@ -0,0 +1,664 @@ +/** + ****************************************************************************** + * @file dp83848.c + * @author MCD Application Team + * @brief This file provides a set of functions needed to manage the DP83848 + * PHY devices. + ****************************************************************************** + * @attention + * + * <h2><center>© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.</center></h2> + * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "dp83848.h" + +/** @addtogroup BSP + * @{ + */ + +/** @addtogroup Component + * @{ + */ + +/** @defgroup DP83848 DP83848 + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @defgroup DP83848_Private_Defines DP83848 Private Defines + * @{ + */ +#define DP83848_SW_RESET_TO ((uint32_t)500U) +#define DP83848_INIT_TO ((uint32_t)2000U) +#define DP83848_MAX_DEV_ADDR ((uint32_t)31U) +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +/** @defgroup DP83848_Private_Functions DP83848 Private Functions + * @{ + */ + +/** + * @brief Register IO functions to component object + * @param pObj: device object of DP83848_Object_t. + * @param ioctx: holds device IO functions. + * @retval DP83848_STATUS_OK if OK + * DP83848_STATUS_ERROR if missing mandatory function + */ +int32_t DP83848_RegisterBusIO(dp83848_Object_t *pObj, dp83848_IOCtx_t *ioctx) +{ + if(!pObj || !ioctx->ReadReg || !ioctx->WriteReg || !ioctx->GetTick) + { + return DP83848_STATUS_ERROR; + } + + pObj->IO.Init = ioctx->Init; + pObj->IO.DeInit = ioctx->DeInit; + pObj->IO.ReadReg = ioctx->ReadReg; + pObj->IO.WriteReg = ioctx->WriteReg; + pObj->IO.GetTick = ioctx->GetTick; + + return DP83848_STATUS_OK; +} + +/** + * @brief Initialize the DP83848 and configure the needed hardware resources + * @param pObj: device object DP83848_Object_t. + * @retval DP83848_STATUS_OK if OK + * DP83848_STATUS_ADDRESS_ERROR if cannot find device address + * DP83848_STATUS_READ_ERROR if connot read register + * DP83848_STATUS_WRITE_ERROR if connot write to register + * DP83848_STATUS_RESET_TIMEOUT if cannot perform a software reset + */ + int32_t DP83848_Init(dp83848_Object_t *pObj) + { + uint32_t tickstart = 0, regvalue = 0, addr = 0; + int32_t status = DP83848_STATUS_OK; + + if(pObj->Is_Initialized == 0) + { + if(pObj->IO.Init != 0) + { + /* GPIO and Clocks initialization */ + pObj->IO.Init(); + } + + /* for later check */ + pObj->DevAddr = DP83848_MAX_DEV_ADDR + 1; + + /* Get the device address from special mode register */ + for(addr = 0; addr <= DP83848_MAX_DEV_ADDR; addr ++) + { + if(pObj->IO.ReadReg(addr, DP83848_SMR, ®value) < 0) + { + status = DP83848_STATUS_READ_ERROR; + /* Can't read from this device address + continue with next address */ + continue; + } + + if((regvalue & DP83848_SMR_PHY_ADDR) == addr) + { + pObj->DevAddr = addr; + status = DP83848_STATUS_OK; + break; + } + } + + if(pObj->DevAddr > DP83848_MAX_DEV_ADDR) + { + status = DP83848_STATUS_ADDRESS_ERROR; + } + + /* if device address is matched */ + if(status == DP83848_STATUS_OK) + { + /* set a software reset */ + if(pObj->IO.WriteReg(pObj->DevAddr, DP83848_BCR, DP83848_BCR_SOFT_RESET) >= 0) + { + /* get software reset status */ + if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_BCR, ®value) >= 0) + { + tickstart = pObj->IO.GetTick(); + + /* wait until software reset is done or timeout occured */ + while(regvalue & DP83848_BCR_SOFT_RESET) + { + if((pObj->IO.GetTick() - tickstart) <= DP83848_SW_RESET_TO) + { + if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_BCR, ®value) < 0) + { + status = DP83848_STATUS_READ_ERROR; + break; + } + } + else + { + status = DP83848_STATUS_RESET_TIMEOUT; + break; + } + } + } + else + { + status = DP83848_STATUS_READ_ERROR; + } + } + else + { + status = DP83848_STATUS_WRITE_ERROR; + } + } + } + + if(status == DP83848_STATUS_OK) + { + tickstart = pObj->IO.GetTick(); + + /* Wait for 2s to perform initialization */ + while((pObj->IO.GetTick() - tickstart) <= DP83848_INIT_TO) + { + } + pObj->Is_Initialized = 1; + } + + return status; + } + +/** + * @brief De-Initialize the dp83848 and it's hardware resources + * @param pObj: device object DP83848_Object_t. + * @retval None + */ +int32_t DP83848_DeInit(dp83848_Object_t *pObj) +{ + if(pObj->Is_Initialized) + { + if(pObj->IO.DeInit != 0) + { + if(pObj->IO.DeInit() < 0) + { + return DP83848_STATUS_ERROR; + } + } + + pObj->Is_Initialized = 0; + } + + return DP83848_STATUS_OK; +} + +/** + * @brief Disable the DP83848 power down mode. + * @param pObj: device object DP83848_Object_t. + * @retval DP83848_STATUS_OK if OK + * DP83848_STATUS_READ_ERROR if connot read register + * DP83848_STATUS_WRITE_ERROR if connot write to register + */ +int32_t DP83848_DisablePowerDownMode(dp83848_Object_t *pObj) +{ + uint32_t readval = 0; + int32_t status = DP83848_STATUS_OK; + + if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_BCR, &readval) >= 0) + { + readval &= ~DP83848_BCR_POWER_DOWN; + + /* Apply configuration */ + if(pObj->IO.WriteReg(pObj->DevAddr, DP83848_BCR, readval) < 0) + { + status = DP83848_STATUS_WRITE_ERROR; + } + } + else + { + status = DP83848_STATUS_READ_ERROR; + } + + return status; +} + +/** + * @brief Enable the DP83848 power down mode. + * @param pObj: device object DP83848_Object_t. + * @retval DP83848_STATUS_OK if OK + * DP83848_STATUS_READ_ERROR if connot read register + * DP83848_STATUS_WRITE_ERROR if connot write to register + */ +int32_t DP83848_EnablePowerDownMode(dp83848_Object_t *pObj) +{ + uint32_t readval = 0; + int32_t status = DP83848_STATUS_OK; + + if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_BCR, &readval) >= 0) + { + readval |= DP83848_BCR_POWER_DOWN; + + /* Apply configuration */ + if(pObj->IO.WriteReg(pObj->DevAddr, DP83848_BCR, readval) < 0) + { + status = DP83848_STATUS_WRITE_ERROR; + } + } + else + { + status = DP83848_STATUS_READ_ERROR; + } + + return status; +} + +/** + * @brief Start the auto negotiation process. + * @param pObj: device object DP83848_Object_t. + * @retval DP83848_STATUS_OK if OK + * DP83848_STATUS_READ_ERROR if connot read register + * DP83848_STATUS_WRITE_ERROR if connot write to register + */ +int32_t DP83848_StartAutoNego(dp83848_Object_t *pObj) +{ + uint32_t readval = 0; + int32_t status = DP83848_STATUS_OK; + + if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_BCR, &readval) >= 0) + { + readval |= DP83848_BCR_AUTONEGO_EN; + + /* Apply configuration */ + if(pObj->IO.WriteReg(pObj->DevAddr, DP83848_BCR, readval) < 0) + { + status = DP83848_STATUS_WRITE_ERROR; + } + } + else + { + status = DP83848_STATUS_READ_ERROR; + } + + return status; +} + +/** + * @brief Get the link state of DP83848 device. + * @param pObj: Pointer to device object. + * @param pLinkState: Pointer to link state + * @retval DP83848_STATUS_LINK_DOWN if link is down + * DP83848_STATUS_AUTONEGO_NOTDONE if Auto nego not completed + * DP83848_STATUS_100MBITS_FULLDUPLEX if 100Mb/s FD + * DP83848_STATUS_100MBITS_HALFDUPLEX if 100Mb/s HD + * DP83848_STATUS_10MBITS_FULLDUPLEX if 10Mb/s FD + * DP83848_STATUS_10MBITS_HALFDUPLEX if 10Mb/s HD + * DP83848_STATUS_READ_ERROR if connot read register + * DP83848_STATUS_WRITE_ERROR if connot write to register + */ +int32_t DP83848_GetLinkState(dp83848_Object_t *pObj) +{ + uint32_t readval = 0; + + /* Read Status register */ + if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_BSR, &readval) < 0) + { + return DP83848_STATUS_READ_ERROR; + } + + /* Read Status register again */ + if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_BSR, &readval) < 0) + { + return DP83848_STATUS_READ_ERROR; + } + + if((readval & DP83848_BSR_LINK_STATUS) == 0) + { + /* Return Link Down status */ + return DP83848_STATUS_LINK_DOWN; + } + + /* Check Auto negotiaition */ + if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_BCR, &readval) < 0) + { + return DP83848_STATUS_READ_ERROR; + } + + if((readval & DP83848_BCR_AUTONEGO_EN) != DP83848_BCR_AUTONEGO_EN) + { + if(((readval & DP83848_BCR_SPEED_SELECT) == DP83848_BCR_SPEED_SELECT) && ((readval & DP83848_BCR_DUPLEX_MODE) == DP83848_BCR_DUPLEX_MODE)) + { + return DP83848_STATUS_100MBITS_FULLDUPLEX; + } + else if ((readval & DP83848_BCR_SPEED_SELECT) == DP83848_BCR_SPEED_SELECT) + { + return DP83848_STATUS_100MBITS_HALFDUPLEX; + } + else if ((readval & DP83848_BCR_DUPLEX_MODE) == DP83848_BCR_DUPLEX_MODE) + { + return DP83848_STATUS_10MBITS_FULLDUPLEX; + } + else + { + return DP83848_STATUS_10MBITS_HALFDUPLEX; + } + } + else /* Auto Nego enabled */ + { + if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_PHYSCSR, &readval) < 0) + { + return DP83848_STATUS_READ_ERROR; + } + + /* Check if auto nego not done */ + if((readval & DP83848_PHYSCSR_AUTONEGO_DONE) == 0) + { + return DP83848_STATUS_AUTONEGO_NOTDONE; + } + + if((readval & DP83848_PHYSCSR_HCDSPEEDMASK) == DP83848_PHYSCSR_100BTX_FD) + { + return DP83848_STATUS_100MBITS_FULLDUPLEX; + } + else if ((readval & DP83848_PHYSCSR_HCDSPEEDMASK) == DP83848_PHYSCSR_100BTX_HD) + { + return DP83848_STATUS_100MBITS_HALFDUPLEX; + } + else if ((readval & DP83848_PHYSCSR_HCDSPEEDMASK) == DP83848_PHYSCSR_10BT_FD) + { + return DP83848_STATUS_10MBITS_FULLDUPLEX; + } + else + { + return DP83848_STATUS_10MBITS_HALFDUPLEX; + } + } +} + +/** + * @brief Set the link state of DP83848 device. + * @param pObj: Pointer to device object. + * @param pLinkState: link state can be one of the following + * DP83848_STATUS_100MBITS_FULLDUPLEX if 100Mb/s FD + * DP83848_STATUS_100MBITS_HALFDUPLEX if 100Mb/s HD + * DP83848_STATUS_10MBITS_FULLDUPLEX if 10Mb/s FD + * DP83848_STATUS_10MBITS_HALFDUPLEX if 10Mb/s HD + * @retval DP83848_STATUS_OK if OK + * DP83848_STATUS_ERROR if parameter error + * DP83848_STATUS_READ_ERROR if connot read register + * DP83848_STATUS_WRITE_ERROR if connot write to register + */ +int32_t DP83848_SetLinkState(dp83848_Object_t *pObj, uint32_t LinkState) +{ + uint32_t bcrvalue = 0; + int32_t status = DP83848_STATUS_OK; + + if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_BCR, &bcrvalue) >= 0) + { + /* Disable link config (Auto nego, speed and duplex) */ + bcrvalue &= ~(DP83848_BCR_AUTONEGO_EN | DP83848_BCR_SPEED_SELECT | DP83848_BCR_DUPLEX_MODE); + + if(LinkState == DP83848_STATUS_100MBITS_FULLDUPLEX) + { + bcrvalue |= (DP83848_BCR_SPEED_SELECT | DP83848_BCR_DUPLEX_MODE); + } + else if (LinkState == DP83848_STATUS_100MBITS_HALFDUPLEX) + { + bcrvalue |= DP83848_BCR_SPEED_SELECT; + } + else if (LinkState == DP83848_STATUS_10MBITS_FULLDUPLEX) + { + bcrvalue |= DP83848_BCR_DUPLEX_MODE; + } + else + { + /* Wrong link status parameter */ + status = DP83848_STATUS_ERROR; + } + } + else + { + status = DP83848_STATUS_READ_ERROR; + } + + if(status == DP83848_STATUS_OK) + { + /* Apply configuration */ + if(pObj->IO.WriteReg(pObj->DevAddr, DP83848_BCR, bcrvalue) < 0) + { + status = DP83848_STATUS_WRITE_ERROR; + } + } + + return status; +} + +/** + * @brief Enable loopback mode. + * @param pObj: Pointer to device object. + * @retval DP83848_STATUS_OK if OK + * DP83848_STATUS_READ_ERROR if connot read register + * DP83848_STATUS_WRITE_ERROR if connot write to register + */ +int32_t DP83848_EnableLoopbackMode(dp83848_Object_t *pObj) +{ + uint32_t readval = 0; + int32_t status = DP83848_STATUS_OK; + + if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_BCR, &readval) >= 0) + { + readval |= DP83848_BCR_LOOPBACK; + + /* Apply configuration */ + if(pObj->IO.WriteReg(pObj->DevAddr, DP83848_BCR, readval) < 0) + { + status = DP83848_STATUS_WRITE_ERROR; + } + } + else + { + status = DP83848_STATUS_READ_ERROR; + } + + return status; +} + +/** + * @brief Disable loopback mode. + * @param pObj: Pointer to device object. + * @retval DP83848_STATUS_OK if OK + * DP83848_STATUS_READ_ERROR if connot read register + * DP83848_STATUS_WRITE_ERROR if connot write to register + */ +int32_t DP83848_DisableLoopbackMode(dp83848_Object_t *pObj) +{ + uint32_t readval = 0; + int32_t status = DP83848_STATUS_OK; + + if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_BCR, &readval) >= 0) + { + readval &= ~DP83848_BCR_LOOPBACK; + + /* Apply configuration */ + if(pObj->IO.WriteReg(pObj->DevAddr, DP83848_BCR, readval) < 0) + { + status = DP83848_STATUS_WRITE_ERROR; + } + } + else + { + status = DP83848_STATUS_READ_ERROR; + } + + return status; +} + +/** + * @brief Enable IT source. + * @param pObj: Pointer to device object. + * @param Interrupt: IT source to be enabled + * should be a value or a combination of the following: + * DP83848_WOL_IT + * DP83848_ENERGYON_IT + * DP83848_AUTONEGO_COMPLETE_IT + * DP83848_REMOTE_FAULT_IT + * DP83848_LINK_DOWN_IT + * DP83848_AUTONEGO_LP_ACK_IT + * DP83848_PARALLEL_DETECTION_FAULT_IT + * DP83848_AUTONEGO_PAGE_RECEIVED_IT + * @retval DP83848_STATUS_OK if OK + * DP83848_STATUS_READ_ERROR if connot read register + * DP83848_STATUS_WRITE_ERROR if connot write to register + */ +int32_t DP83848_EnableIT(dp83848_Object_t *pObj, uint32_t Interrupt) +{ + uint32_t readval = 0; + int32_t status = DP83848_STATUS_OK; + + if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_IMR, &readval) >= 0) + { + readval |= Interrupt; + + /* Apply configuration */ + if(pObj->IO.WriteReg(pObj->DevAddr, DP83848_IMR, readval) < 0) + { + status = DP83848_STATUS_WRITE_ERROR; + } + } + else + { + status = DP83848_STATUS_READ_ERROR; + } + + return status; +} + +/** + * @brief Disable IT source. + * @param pObj: Pointer to device object. + * @param Interrupt: IT source to be disabled + * should be a value or a combination of the following: + * DP83848_WOL_IT + * DP83848_ENERGYON_IT + * DP83848_AUTONEGO_COMPLETE_IT + * DP83848_REMOTE_FAULT_IT + * DP83848_LINK_DOWN_IT + * DP83848_AUTONEGO_LP_ACK_IT + * DP83848_PARALLEL_DETECTION_FAULT_IT + * DP83848_AUTONEGO_PAGE_RECEIVED_IT + * @retval DP83848_STATUS_OK if OK + * DP83848_STATUS_READ_ERROR if connot read register + * DP83848_STATUS_WRITE_ERROR if connot write to register + */ +int32_t DP83848_DisableIT(dp83848_Object_t *pObj, uint32_t Interrupt) +{ + uint32_t readval = 0; + int32_t status = DP83848_STATUS_OK; + + if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_IMR, &readval) >= 0) + { + readval &= ~Interrupt; + + /* Apply configuration */ + if(pObj->IO.WriteReg(pObj->DevAddr, DP83848_IMR, readval) < 0) + { + status = DP83848_STATUS_WRITE_ERROR; + } + } + else + { + status = DP83848_STATUS_READ_ERROR; + } + + return status; +} + +/** + * @brief Clear IT flag. + * @param pObj: Pointer to device object. + * @param Interrupt: IT flag to be cleared + * should be a value or a combination of the following: + * DP83848_WOL_IT + * DP83848_ENERGYON_IT + * DP83848_AUTONEGO_COMPLETE_IT + * DP83848_REMOTE_FAULT_IT + * DP83848_LINK_DOWN_IT + * DP83848_AUTONEGO_LP_ACK_IT + * DP83848_PARALLEL_DETECTION_FAULT_IT + * DP83848_AUTONEGO_PAGE_RECEIVED_IT + * @retval DP83848_STATUS_OK if OK + * DP83848_STATUS_READ_ERROR if connot read register + */ +int32_t DP83848_ClearIT(dp83848_Object_t *pObj, uint32_t Interrupt) +{ + uint32_t readval = 0; + int32_t status = DP83848_STATUS_OK; + + if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_ISFR, &readval) < 0) + { + status = DP83848_STATUS_READ_ERROR; + } + + return status; +} + +/** + * @brief Get IT Flag status. + * @param pObj: Pointer to device object. + * @param Interrupt: IT Flag to be checked, + * should be a value or a combination of the following: + * DP83848_WOL_IT + * DP83848_ENERGYON_IT + * DP83848_AUTONEGO_COMPLETE_IT + * DP83848_REMOTE_FAULT_IT + * DP83848_LINK_DOWN_IT + * DP83848_AUTONEGO_LP_ACK_IT + * DP83848_PARALLEL_DETECTION_FAULT_IT + * DP83848_AUTONEGO_PAGE_RECEIVED_IT + * @retval 1 IT flag is SET + * 0 IT flag is RESET + * DP83848_STATUS_READ_ERROR if connot read register + */ +int32_t DP83848_GetITStatus(dp83848_Object_t *pObj, uint32_t Interrupt) +{ + uint32_t readval = 0; + int32_t status = 0; + + if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_ISFR, &readval) >= 0) + { + status = ((readval & Interrupt) == Interrupt); + } + else + { + status = DP83848_STATUS_READ_ERROR; + } + + return status; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + diff --git a/stm32/driver/dp83848.h b/stm32/driver/dp83848.h new file mode 100644 index 0000000..d49496d --- /dev/null +++ b/stm32/driver/dp83848.h @@ -0,0 +1,436 @@ +/** + ****************************************************************************** + * @file dp83848.h + * @author MCD Application Team + * @brief This file contains all the functions prototypes for the + * dp83848.c PHY driver. + ****************************************************************************** + * @attention + * + * <h2><center>© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.</center></h2> + * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef DP83848_H +#define DP83848_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include <stdint.h> + +/** @addtogroup BSP + * @{ + */ + +/** @addtogroup Component + * @{ + */ + +/** @defgroup DP83848 + * @{ + */ +/* Exported constants --------------------------------------------------------*/ +/** @defgroup DP83848_Exported_Constants DP83848 Exported Constants + * @{ + */ + +/** @defgroup DP83848_Registers_Mapping DP83848 Registers Mapping + * @{ + */ +#define DP83848_BCR ((uint16_t)0x0000U) +#define DP83848_BSR ((uint16_t)0x0001U) +#define DP83848_PHYI1R ((uint16_t)0x0002U) +#define DP83848_PHYI2R ((uint16_t)0x0003U) +#define DP83848_ANAR ((uint16_t)0x0004U) +#define DP83848_ANLPAR ((uint16_t)0x0005U) +#define DP83848_ANER ((uint16_t)0x0006U) +#define DP83848_ANNPTR ((uint16_t)0x0007U) +#define DP83848_SMR ((uint16_t)0x0019U) +#define DP83848_ISFR ((uint16_t)0x0012U) +#define DP83848_IMR ((uint16_t)0x0011U) +#define DP83848_PHYSCSR ((uint16_t)0x0010U) +/** + * @} + */ + +/** @defgroup DP83848_BCR_Bit_Definition DP83848 BCR Bit Definition + * @{ + */ +#define DP83848_BCR_SOFT_RESET ((uint16_t)0x8000U) +#define DP83848_BCR_LOOPBACK ((uint16_t)0x4000U) +#define DP83848_BCR_SPEED_SELECT ((uint16_t)0x2000U) +#define DP83848_BCR_AUTONEGO_EN ((uint16_t)0x1000U) +#define DP83848_BCR_POWER_DOWN ((uint16_t)0x0800U) +#define DP83848_BCR_ISOLATE ((uint16_t)0x0400U) +#define DP83848_BCR_RESTART_AUTONEGO ((uint16_t)0x0200U) +#define DP83848_BCR_DUPLEX_MODE ((uint16_t)0x0100U) +/** + * @} + */ + +/** @defgroup DP83848_BSR_Bit_Definition DP83848 BSR Bit Definition + * @{ + */ +#define DP83848_BSR_100BASE_T4 ((uint16_t)0x8000U) +#define DP83848_BSR_100BASE_TX_FD ((uint16_t)0x4000U) +#define DP83848_BSR_100BASE_TX_HD ((uint16_t)0x2000U) +#define DP83848_BSR_10BASE_T_FD ((uint16_t)0x1000U) +#define DP83848_BSR_10BASE_T_HD ((uint16_t)0x0800U) +#define DP83848_BSR_MF_PREAMBLE ((uint16_t)0x0040U) +#define DP83848_BSR_AUTONEGO_CPLT ((uint16_t)0x0020U) +#define DP83848_BSR_REMOTE_FAULT ((uint16_t)0x0010U) +#define DP83848_BSR_AUTONEGO_ABILITY ((uint16_t)0x0008U) +#define DP83848_BSR_LINK_STATUS ((uint16_t)0x0004U) +#define DP83848_BSR_JABBER_DETECT ((uint16_t)0x0002U) +#define DP83848_BSR_EXTENDED_CAP ((uint16_t)0x0001U) +/** + * @} + */ + +/** @defgroup DP83848_PHYI1R_Bit_Definition DP83848 PHYI1R Bit Definition + * @{ + */ +#define DP83848_PHYI1R_OUI_3_18 ((uint16_t)0xFFFFU) +/** + * @} + */ + +/** @defgroup DP83848_PHYI2R_Bit_Definition DP83848 PHYI2R Bit Definition + * @{ + */ +#define DP83848_PHYI2R_OUI_19_24 ((uint16_t)0xFC00U) +#define DP83848_PHYI2R_MODEL_NBR ((uint16_t)0x03F0U) +#define DP83848_PHYI2R_REVISION_NBR ((uint16_t)0x000FU) +/** + * @} + */ + +/** @defgroup DP83848_ANAR_Bit_Definition DP83848 ANAR Bit Definition + * @{ + */ +#define DP83848_ANAR_NEXT_PAGE ((uint16_t)0x8000U) +#define DP83848_ANAR_REMOTE_FAULT ((uint16_t)0x2000U) +#define DP83848_ANAR_PAUSE_OPERATION ((uint16_t)0x0C00U) +#define DP83848_ANAR_PO_NOPAUSE ((uint16_t)0x0000U) +#define DP83848_ANAR_PO_SYMMETRIC_PAUSE ((uint16_t)0x0400U) +#define DP83848_ANAR_PO_ASYMMETRIC_PAUSE ((uint16_t)0x0800U) +#define DP83848_ANAR_PO_ADVERTISE_SUPPORT ((uint16_t)0x0C00U) +#define DP83848_ANAR_100BASE_TX_FD ((uint16_t)0x0100U) +#define DP83848_ANAR_100BASE_TX ((uint16_t)0x0080U) +#define DP83848_ANAR_10BASE_T_FD ((uint16_t)0x0040U) +#define DP83848_ANAR_10BASE_T ((uint16_t)0x0020U) +#define DP83848_ANAR_SELECTOR_FIELD ((uint16_t)0x000FU) +/** + * @} + */ + +/** @defgroup DP83848_ANLPAR_Bit_Definition DP83848 ANLPAR Bit Definition + * @{ + */ +#define DP83848_ANLPAR_NEXT_PAGE ((uint16_t)0x8000U) +#define DP83848_ANLPAR_REMOTE_FAULT ((uint16_t)0x2000U) +#define DP83848_ANLPAR_PAUSE_OPERATION ((uint16_t)0x0C00U) +#define DP83848_ANLPAR_PO_NOPAUSE ((uint16_t)0x0000U) +#define DP83848_ANLPAR_PO_SYMMETRIC_PAUSE ((uint16_t)0x0400U) +#define DP83848_ANLPAR_PO_ASYMMETRIC_PAUSE ((uint16_t)0x0800U) +#define DP83848_ANLPAR_PO_ADVERTISE_SUPPORT ((uint16_t)0x0C00U) +#define DP83848_ANLPAR_100BASE_TX_FD ((uint16_t)0x0100U) +#define DP83848_ANLPAR_100BASE_TX ((uint16_t)0x0080U) +#define DP83848_ANLPAR_10BASE_T_FD ((uint16_t)0x0040U) +#define DP83848_ANLPAR_10BASE_T ((uint16_t)0x0020U) +#define DP83848_ANLPAR_SELECTOR_FIELD ((uint16_t)0x000FU) +/** + * @} + */ + +/** @defgroup DP83848_ANER_Bit_Definition DP83848 ANER Bit Definition + * @{ + */ +#define DP83848_ANER_RX_NP_LOCATION_ABLE ((uint16_t)0x0040U) +#define DP83848_ANER_RX_NP_STORAGE_LOCATION ((uint16_t)0x0020U) +#define DP83848_ANER_PARALLEL_DETECT_FAULT ((uint16_t)0x0010U) +#define DP83848_ANER_LP_NP_ABLE ((uint16_t)0x0008U) +#define DP83848_ANER_NP_ABLE ((uint16_t)0x0004U) +#define DP83848_ANER_PAGE_RECEIVED ((uint16_t)0x0002U) +#define DP83848_ANER_LP_AUTONEG_ABLE ((uint16_t)0x0001U) +/** + * @} + */ + +/** @defgroup DP83848_ANNPTR_Bit_Definition DP83848 ANNPTR Bit Definition + * @{ + */ +#define DP83848_ANNPTR_NEXT_PAGE ((uint16_t)0x8000U) +#define DP83848_ANNPTR_MESSAGE_PAGE ((uint16_t)0x2000U) +#define DP83848_ANNPTR_ACK2 ((uint16_t)0x1000U) +#define DP83848_ANNPTR_TOGGLE ((uint16_t)0x0800U) +#define DP83848_ANNPTR_MESSAGE_CODE ((uint16_t)0x07FFU) +/** + * @} + */ + +/** @defgroup DP83848_ANNPRR_Bit_Definition DP83848 ANNPRR Bit Definition + * @{ + */ +#define DP83848_ANNPRR_NEXT_PAGE ((uint16_t)0x8000U) +#define DP83848_ANNPRR_ACK ((uint16_t)0x4000U) +#define DP83848_ANNPRR_MESSAGE_PAGE ((uint16_t)0x2000U) +#define DP83848_ANNPRR_ACK2 ((uint16_t)0x1000U) +#define DP83848_ANNPRR_TOGGLE ((uint16_t)0x0800U) +#define DP83848_ANNPRR_MESSAGE_CODE ((uint16_t)0x07FFU) +/** + * @} + */ + +/** @defgroup DP83848_MMDACR_Bit_Definition DP83848 MMDACR Bit Definition + * @{ + */ +#define DP83848_MMDACR_MMD_FUNCTION ((uint16_t)0xC000U) +#define DP83848_MMDACR_MMD_FUNCTION_ADDR ((uint16_t)0x0000U) +#define DP83848_MMDACR_MMD_FUNCTION_DATA ((uint16_t)0x4000U) +#define DP83848_MMDACR_MMD_DEV_ADDR ((uint16_t)0x001FU) +/** + * @} + */ + +/** @defgroup DP83848_ENCTR_Bit_Definition DP83848 ENCTR Bit Definition + * @{ + */ +#define DP83848_ENCTR_TX_ENABLE ((uint16_t)0x8000U) +#define DP83848_ENCTR_TX_TIMER ((uint16_t)0x6000U) +#define DP83848_ENCTR_TX_TIMER_1S ((uint16_t)0x0000U) +#define DP83848_ENCTR_TX_TIMER_768MS ((uint16_t)0x2000U) +#define DP83848_ENCTR_TX_TIMER_512MS ((uint16_t)0x4000U) +#define DP83848_ENCTR_TX_TIMER_265MS ((uint16_t)0x6000U) +#define DP83848_ENCTR_RX_ENABLE ((uint16_t)0x1000U) +#define DP83848_ENCTR_RX_MAX_INTERVAL ((uint16_t)0x0C00U) +#define DP83848_ENCTR_RX_MAX_INTERVAL_64MS ((uint16_t)0x0000U) +#define DP83848_ENCTR_RX_MAX_INTERVAL_256MS ((uint16_t)0x0400U) +#define DP83848_ENCTR_RX_MAX_INTERVAL_512MS ((uint16_t)0x0800U) +#define DP83848_ENCTR_RX_MAX_INTERVAL_1S ((uint16_t)0x0C00U) +#define DP83848_ENCTR_EX_CROSS_OVER ((uint16_t)0x0002U) +#define DP83848_ENCTR_EX_MANUAL_CROSS_OVER ((uint16_t)0x0001U) +/** + * @} + */ + +/** @defgroup DP83848_MCSR_Bit_Definition DP83848 MCSR Bit Definition + * @{ + */ +#define DP83848_MCSR_EDPWRDOWN ((uint16_t)0x2000U) +#define DP83848_MCSR_FARLOOPBACK ((uint16_t)0x0200U) +#define DP83848_MCSR_ALTINT ((uint16_t)0x0040U) +#define DP83848_MCSR_ENERGYON ((uint16_t)0x0002U) +/** + * @} + */ + +/** @defgroup DP83848_SMR_Bit_Definition DP83848 SMR Bit Definition + * @{ + */ +#define DP83848_SMR_MODE ((uint16_t)0x00E0U) +#define DP83848_SMR_PHY_ADDR ((uint16_t)0x001FU) +/** + * @} + */ + +/** @defgroup DP83848_TPDCR_Bit_Definition DP83848 TPDCR Bit Definition + * @{ + */ +#define DP83848_TPDCR_DELAY_IN ((uint16_t)0x8000U) +#define DP83848_TPDCR_LINE_BREAK_COUNTER ((uint16_t)0x7000U) +#define DP83848_TPDCR_PATTERN_HIGH ((uint16_t)0x0FC0U) +#define DP83848_TPDCR_PATTERN_LOW ((uint16_t)0x003FU) +/** + * @} + */ + +/** @defgroup DP83848_TCSR_Bit_Definition DP83848 TCSR Bit Definition + * @{ + */ +#define DP83848_TCSR_TDR_ENABLE ((uint16_t)0x8000U) +#define DP83848_TCSR_TDR_AD_FILTER_ENABLE ((uint16_t)0x4000U) +#define DP83848_TCSR_TDR_CH_CABLE_TYPE ((uint16_t)0x0600U) +#define DP83848_TCSR_TDR_CH_CABLE_DEFAULT ((uint16_t)0x0000U) +#define DP83848_TCSR_TDR_CH_CABLE_SHORTED ((uint16_t)0x0200U) +#define DP83848_TCSR_TDR_CH_CABLE_OPEN ((uint16_t)0x0400U) +#define DP83848_TCSR_TDR_CH_CABLE_MATCH ((uint16_t)0x0600U) +#define DP83848_TCSR_TDR_CH_STATUS ((uint16_t)0x0100U) +#define DP83848_TCSR_TDR_CH_LENGTH ((uint16_t)0x00FFU) +/** + * @} + */ + +/** @defgroup DP83848_SCSIR_Bit_Definition DP83848 SCSIR Bit Definition + * @{ + */ +#define DP83848_SCSIR_AUTO_MDIX_ENABLE ((uint16_t)0x8000U) +#define DP83848_SCSIR_CHANNEL_SELECT ((uint16_t)0x2000U) +#define DP83848_SCSIR_SQE_DISABLE ((uint16_t)0x0800U) +#define DP83848_SCSIR_XPOLALITY ((uint16_t)0x0010U) +/** + * @} + */ + +/** @defgroup DP83848_CLR_Bit_Definition DP83848 CLR Bit Definition + * @{ + */ +#define DP83848_CLR_CABLE_LENGTH ((uint16_t)0xF000U) +/** + * @} + */ + +/** @defgroup DP83848_IMR_ISFR_Bit_Definition DP83848 IMR ISFR Bit Definition + * @{ + */ +#define DP83848_INT_8 ((uint16_t)0x0100U) +#define DP83848_INT_7 ((uint16_t)0x0080U) +#define DP83848_INT_6 ((uint16_t)0x0040U) +#define DP83848_INT_5 ((uint16_t)0x0020U) +#define DP83848_INT_4 ((uint16_t)0x0010U) +#define DP83848_INT_3 ((uint16_t)0x0008U) +#define DP83848_INT_2 ((uint16_t)0x0004U) +#define DP83848_INT_1 ((uint16_t)0x0002U) +/** + * @} + */ + +/** @defgroup DP83848_PHYSCSR_Bit_Definition DP83848 PHYSCSR Bit Definition + * @{ + */ +#define DP83848_PHYSCSR_AUTONEGO_DONE ((uint16_t)0x100U) +#define DP83848_PHYSCSR_HCDSPEEDMASK ((uint16_t)0x006U) +#define DP83848_PHYSCSR_10BT_HD ((uint16_t)0x002U) +#define DP83848_PHYSCSR_10BT_FD ((uint16_t)0x006U) +#define DP83848_PHYSCSR_100BTX_HD ((uint16_t)0x000U) +#define DP83848_PHYSCSR_100BTX_FD ((uint16_t)0x004U) +/** + * @} + */ + +/** @defgroup DP83848_Status DP83848 Status + * @{ + */ + +#define DP83848_STATUS_READ_ERROR ((int32_t)-5) +#define DP83848_STATUS_WRITE_ERROR ((int32_t)-4) +#define DP83848_STATUS_ADDRESS_ERROR ((int32_t)-3) +#define DP83848_STATUS_RESET_TIMEOUT ((int32_t)-2) +#define DP83848_STATUS_ERROR ((int32_t)-1) +#define DP83848_STATUS_OK ((int32_t) 0) +#define DP83848_STATUS_LINK_DOWN ((int32_t) 1) +#define DP83848_STATUS_100MBITS_FULLDUPLEX ((int32_t) 2) +#define DP83848_STATUS_100MBITS_HALFDUPLEX ((int32_t) 3) +#define DP83848_STATUS_10MBITS_FULLDUPLEX ((int32_t) 4) +#define DP83848_STATUS_10MBITS_HALFDUPLEX ((int32_t) 5) +#define DP83848_STATUS_AUTONEGO_NOTDONE ((int32_t) 6) +/** + * @} + */ + +/** @defgroup DP83848_IT_Flags DP83848 IT Flags + * @{ + */ +#define DP83848_WOL_IT DP83848_INT_8 +#define DP83848_ENERGYON_IT DP83848_INT_7 +#define DP83848_AUTONEGO_COMPLETE_IT DP83848_INT_6 +#define DP83848_REMOTE_FAULT_IT DP83848_INT_5 +#define DP83848_LINK_DOWN_IT DP83848_INT_4 +#define DP83848_AUTONEGO_LP_ACK_IT DP83848_INT_3 +#define DP83848_PARALLEL_DETECTION_FAULT_IT DP83848_INT_2 +#define DP83848_AUTONEGO_PAGE_RECEIVED_IT DP83848_INT_1 +/** + * @} + */ + +/** + * @} + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup DP83848_Exported_Types DP83848 Exported Types + * @{ + */ +typedef int32_t (*dp83848_Init_Func) (void); +typedef int32_t (*dp83848_DeInit_Func) (void); +typedef int32_t (*dp83848_ReadReg_Func) (uint32_t, uint32_t, uint32_t *); +typedef int32_t (*dp83848_WriteReg_Func) (uint32_t, uint32_t, uint32_t); +typedef int32_t (*dp83848_GetTick_Func) (void); + +typedef struct +{ + dp83848_Init_Func Init; + dp83848_DeInit_Func DeInit; + dp83848_WriteReg_Func WriteReg; + dp83848_ReadReg_Func ReadReg; + dp83848_GetTick_Func GetTick; +} dp83848_IOCtx_t; + + +typedef struct +{ + uint32_t DevAddr; + uint32_t Is_Initialized; + dp83848_IOCtx_t IO; + void *pData; +}dp83848_Object_t; +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ +/** @defgroup DP83848_Exported_Functions DP83848 Exported Functions + * @{ + */ +int32_t DP83848_RegisterBusIO(dp83848_Object_t *pObj, dp83848_IOCtx_t *ioctx); +int32_t DP83848_Init(dp83848_Object_t *pObj); +int32_t DP83848_DeInit(dp83848_Object_t *pObj); +int32_t DP83848_DisablePowerDownMode(dp83848_Object_t *pObj); +int32_t DP83848_EnablePowerDownMode(dp83848_Object_t *pObj); +int32_t DP83848_StartAutoNego(dp83848_Object_t *pObj); +int32_t DP83848_GetLinkState(dp83848_Object_t *pObj); +int32_t DP83848_SetLinkState(dp83848_Object_t *pObj, uint32_t LinkState); +int32_t DP83848_EnableLoopbackMode(dp83848_Object_t *pObj); +int32_t DP83848_DisableLoopbackMode(dp83848_Object_t *pObj); +int32_t DP83848_EnableIT(dp83848_Object_t *pObj, uint32_t Interrupt); +int32_t DP83848_DisableIT(dp83848_Object_t *pObj, uint32_t Interrupt); +int32_t DP83848_ClearIT(dp83848_Object_t *pObj, uint32_t Interrupt); +int32_t DP83848_GetITStatus(dp83848_Object_t *pObj, uint32_t Interrupt); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif +#endif /* DP83848_H */ + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + diff --git a/stm32/ethernetif.c b/stm32/ethernetif.c new file mode 100644 index 0000000..7a82c51 --- /dev/null +++ b/stm32/ethernetif.c @@ -0,0 +1,879 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * File Name : ethernetif.c + * Description : This file provides code for the configuration + * of the ethernetif.c MiddleWare. + ****************************************************************************** + * @attention + * + * Copyright (c) 2022 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" +#include "lwip/opt.h" +#include "lwip/timeouts.h" +#include "netif/ethernet.h" +#include "netif/etharp.h" +#include "lwip/ethip6.h" +#include "ethernetif.h" +#include "dp83848.h" +#include <string.h> +#include "cmsis_os.h" +#include "lwip/tcpip.h" + +/* Within 'USER CODE' section, code will be kept by default at each generation */ +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* Private define ------------------------------------------------------------*/ +/* The time to block waiting for input. */ +#define TIME_WAITING_FOR_INPUT ( portMAX_DELAY ) +/* USER CODE BEGIN OS_THREAD_STACK_SIZE_WITH_RTOS */ +/* Stack size of the interface thread */ +#define INTERFACE_THREAD_STACK_SIZE ( 350 ) +/* USER CODE END OS_THREAD_STACK_SIZE_WITH_RTOS */ +/* Network interface name */ +#define IFNAME0 's' +#define IFNAME1 't' + +/* ETH Setting */ +#define ETH_DMA_TRANSMIT_TIMEOUT ( 20U ) +#define ETH_TX_BUFFER_MAX ((ETH_TX_DESC_CNT) * 2U) +/* ETH_RX_BUFFER_SIZE parameter is defined in lwipopts.h */ + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ + +/* Private variables ---------------------------------------------------------*/ +/* +@Note: This interface is implemented to operate in zero-copy mode only: + - Rx buffers are allocated statically and passed directly to the LwIP stack + they will return back to ETH DMA after been processed by the stack. + - Tx Buffers will be allocated from LwIP stack memory heap, + then passed to ETH HAL driver. + +@Notes: + 1.a. ETH DMA Rx descriptors must be contiguous, the default count is 4, + to customize it please redefine ETH_RX_DESC_CNT in ETH GUI (Rx Descriptor Length) + so that updated value will be generated in stm32xxxx_hal_conf.h + 1.b. ETH DMA Tx descriptors must be contiguous, the default count is 4, + to customize it please redefine ETH_TX_DESC_CNT in ETH GUI (Tx Descriptor Length) + so that updated value will be generated in stm32xxxx_hal_conf.h + + 2.a. Rx Buffers number must be between ETH_RX_DESC_CNT and 2*ETH_RX_DESC_CNT + 2.b. Rx Buffers must have the same size: ETH_RX_BUFFER_SIZE, this value must + passed to ETH DMA in the init field (heth.Init.RxBuffLen) + 2.c The RX Ruffers addresses and sizes must be properly defined to be aligned + to L1-CACHE line size (32 bytes). +*/ + +/* Data Type Definitions */ +typedef enum +{ + RX_ALLOC_OK = 0x00, + RX_ALLOC_ERROR = 0x01 +} RxAllocStatusTypeDef; + +typedef struct +{ + struct pbuf_custom pbuf_custom; + uint8_t buff[(ETH_RX_BUFFER_SIZE + 31) & ~31] __ALIGNED(32); +} RxBuff_t; + +/* Memory Pool Declaration */ +#define ETH_RX_BUFFER_CNT 12U +LWIP_MEMPOOL_DECLARE(RX_POOL, ETH_RX_BUFFER_CNT, sizeof(RxBuff_t), "Zero-copy RX PBUF pool"); + +/* Variable Definitions */ +static uint8_t RxAllocStatus; + +__IO uint32_t TxPkt = 0; +__IO uint32_t RxPkt = 0; + +ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */ +ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */ + +/* USER CODE BEGIN 2 */ + +/* USER CODE END 2 */ + +osSemaphoreId RxPktSemaphore = NULL; /* Semaphore to signal incoming packets */ +osSemaphoreId TxPktSemaphore = NULL; /* Semaphore to signal transmit packet complete */ + +/* Global Ethernet handle */ +ETH_HandleTypeDef heth; +ETH_TxPacketConfig TxConfig; + +/* Private function prototypes -----------------------------------------------*/ +int32_t ETH_PHY_IO_Init(void); +int32_t ETH_PHY_IO_DeInit (void); +int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal); +int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal); +int32_t ETH_PHY_IO_GetTick(void); + +dp83848_Object_t DP83848; +dp83848_IOCtx_t DP83848_IOCtx = {ETH_PHY_IO_Init, + ETH_PHY_IO_DeInit, + ETH_PHY_IO_WriteReg, + ETH_PHY_IO_ReadReg, + ETH_PHY_IO_GetTick}; + +/* USER CODE BEGIN 3 */ + +/* USER CODE END 3 */ + +/* Private functions ---------------------------------------------------------*/ +void pbuf_free_custom(struct pbuf *p); + +/** + * @brief Ethernet Rx Transfer completed callback + * @param handlerEth: ETH handler + * @retval None + */ +void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *handlerEth) +{ + osSemaphoreRelease(RxPktSemaphore); +} +/** + * @brief Ethernet Tx Transfer completed callback + * @param handlerEth: ETH handler + * @retval None + */ +void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *handlerEth) +{ + osSemaphoreRelease(TxPktSemaphore); +} +/** + * @brief Ethernet DMA transfer error callback + * @param handlerEth: ETH handler + * @retval None + */ +void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *handlerEth) +{ + if((HAL_ETH_GetDMAError(handlerEth) & ETH_DMASR_RBUS) == ETH_DMASR_RBUS) + { + osSemaphoreRelease(RxPktSemaphore); + } +} + +/* USER CODE BEGIN 4 */ + +/* USER CODE END 4 */ + +/******************************************************************************* + LL Driver Interface ( LwIP stack --> ETH) +*******************************************************************************/ +/** + * @brief In this function, the hardware should be initialized. + * Called from ethernetif_init(). + * + * @param netif the already initialized lwip network interface structure + * for this ethernetif + */ +static void low_level_init(struct netif *netif) +{ + HAL_StatusTypeDef hal_eth_init_status = HAL_OK; +/* USER CODE BEGIN OS_THREAD_ATTR_CMSIS_RTOS_V2 */ + osThreadAttr_t attributes; +/* USER CODE END OS_THREAD_ATTR_CMSIS_RTOS_V2 */ + uint32_t duplex, speed = 0; + int32_t PHYLinkState = 0; + ETH_MACConfigTypeDef MACConf = {0}; + /* Start ETH HAL Init */ + + uint8_t MACAddr[6] ; + heth.Instance = ETH; + MACAddr[0] = 0x02; + MACAddr[1] = 0x00; + MACAddr[2] = 0x00; + MACAddr[3] = 0x00; + MACAddr[4] = 0x00; + MACAddr[5] = 0x01; + heth.Init.MACAddr = &MACAddr[0]; + heth.Init.MediaInterface = HAL_ETH_RMII_MODE; + heth.Init.TxDesc = DMATxDscrTab; + heth.Init.RxDesc = DMARxDscrTab; + heth.Init.RxBuffLen = 1536; + + /* USER CODE BEGIN MACADDRESS */ + + /* USER CODE END MACADDRESS */ + + hal_eth_init_status = HAL_ETH_Init(&heth); + + memset(&TxConfig, 0 , sizeof(ETH_TxPacketConfig)); + TxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD; + TxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC; + TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT; + + /* End ETH HAL Init */ + + /* Initialize the RX POOL */ + LWIP_MEMPOOL_INIT(RX_POOL); + +#if LWIP_ARP || LWIP_ETHERNET + + /* set MAC hardware address length */ + netif->hwaddr_len = ETH_HWADDR_LEN; + + /* set MAC hardware address */ + netif->hwaddr[0] = heth.Init.MACAddr[0]; + netif->hwaddr[1] = heth.Init.MACAddr[1]; + netif->hwaddr[2] = heth.Init.MACAddr[2]; + netif->hwaddr[3] = heth.Init.MACAddr[3]; + netif->hwaddr[4] = heth.Init.MACAddr[4]; + netif->hwaddr[5] = heth.Init.MACAddr[5]; + + /* maximum transfer unit */ + netif->mtu = ETH_MAX_PAYLOAD; + + /* Accept broadcast address and ARP traffic */ + /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ + #if LWIP_ARP + netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; + #else + netif->flags |= NETIF_FLAG_BROADCAST; + #endif /* LWIP_ARP */ + + /* create a binary semaphore used for informing ethernetif of frame reception */ + RxPktSemaphore = osSemaphoreNew(1, 1, NULL); + + /* create a binary semaphore used for informing ethernetif of frame transmission */ + TxPktSemaphore = osSemaphoreNew(1, 1, NULL); + + /* create the task that handles the ETH_MAC */ +/* USER CODE BEGIN OS_THREAD_NEW_CMSIS_RTOS_V2 */ + memset(&attributes, 0x0, sizeof(osThreadAttr_t)); + attributes.name = "EthIf"; + attributes.stack_size = INTERFACE_THREAD_STACK_SIZE; + attributes.priority = osPriorityRealtime; + osThreadNew(ethernetif_input, netif, &attributes); +/* USER CODE END OS_THREAD_NEW_CMSIS_RTOS_V2 */ + +/* USER CODE BEGIN PHY_PRE_CONFIG */ + +/* USER CODE END PHY_PRE_CONFIG */ + /* Set PHY IO functions */ + DP83848_RegisterBusIO(&DP83848, &DP83848_IOCtx); + + /* Initialize the DP83848 ETH PHY */ + DP83848_Init(&DP83848); + + if (hal_eth_init_status == HAL_OK) + { + PHYLinkState = DP83848_GetLinkState(&DP83848); + + /* Get link state */ + if(PHYLinkState <= DP83848_STATUS_LINK_DOWN) + { + netif_set_link_down(netif); + netif_set_down(netif); + } + else + { + switch (PHYLinkState) + { + case DP83848_STATUS_100MBITS_FULLDUPLEX: + duplex = ETH_FULLDUPLEX_MODE; + speed = ETH_SPEED_100M; + break; + case DP83848_STATUS_100MBITS_HALFDUPLEX: + duplex = ETH_HALFDUPLEX_MODE; + speed = ETH_SPEED_100M; + break; + case DP83848_STATUS_10MBITS_FULLDUPLEX: + duplex = ETH_FULLDUPLEX_MODE; + speed = ETH_SPEED_10M; + break; + case DP83848_STATUS_10MBITS_HALFDUPLEX: + duplex = ETH_HALFDUPLEX_MODE; + speed = ETH_SPEED_10M; + break; + default: + duplex = ETH_FULLDUPLEX_MODE; + speed = ETH_SPEED_100M; + break; + } + + /* Get MAC Config MAC */ + HAL_ETH_GetMACConfig(&heth, &MACConf); + MACConf.DuplexMode = duplex; + MACConf.Speed = speed; + HAL_ETH_SetMACConfig(&heth, &MACConf); + + HAL_ETH_Start_IT(&heth); + netif_set_up(netif); + netif_set_link_up(netif); + +/* USER CODE BEGIN PHY_POST_CONFIG */ + +/* USER CODE END PHY_POST_CONFIG */ + } + + } + else + { + Error_Handler(); + } +#endif /* LWIP_ARP || LWIP_ETHERNET */ + +/* USER CODE BEGIN LOW_LEVEL_INIT */ + +/* USER CODE END LOW_LEVEL_INIT */ +} + +/** + * This function should do the actual transmission of the packet. The packet is + * contained in the pbuf that is passed to the function. This pbuf + * might be chained. + * + * @param netif the lwip network interface structure for this ethernetif + * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) + * @return ERR_OK if the packet could be sent + * an err_t value if the packet couldn't be sent + * + * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to + * strange results. You might consider waiting for space in the DMA queue + * to become available since the stack doesn't retry to send a packet + * dropped because of memory failure (except for the TCP timers). + */ + +static err_t low_level_output(struct netif *netif, struct pbuf *p) +{ + uint32_t i = 0U; + struct pbuf *q = NULL; + err_t errval = ERR_OK; + ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT]; + + memset(Txbuffer, 0 , ETH_TX_DESC_CNT*sizeof(ETH_BufferTypeDef)); + + for(q = p; q != NULL; q = q->next) + { + if(i >= ETH_TX_DESC_CNT) + return ERR_IF; + + Txbuffer[i].buffer = q->payload; + Txbuffer[i].len = q->len; + + if(i>0) + { + Txbuffer[i-1].next = &Txbuffer[i]; + } + + if(q->next == NULL) + { + Txbuffer[i].next = NULL; + } + + i++; + } + + TxConfig.Length = p->tot_len; + TxConfig.TxBuffer = Txbuffer; + TxConfig.pData = p; + + pbuf_ref(p); + + HAL_ETH_Transmit_IT(&heth, &TxConfig); + while(osSemaphoreAcquire(TxPktSemaphore, TIME_WAITING_FOR_INPUT)!=osOK) + + { + } + + HAL_ETH_ReleaseTxPacket(&heth); + + return errval; +} + +/** + * Should allocate a pbuf and transfer the bytes of the incoming + * packet from the interface into the pbuf. + * + * @param netif the lwip network interface structure for this ethernetif + * @return a pbuf filled with the received packet (including MAC header) + * NULL on memory error + */ +static struct pbuf * low_level_input(struct netif *netif) +{ + struct pbuf *p = NULL; + + if(RxAllocStatus == RX_ALLOC_OK) + { + HAL_ETH_ReadData(&heth, (void **)&p); + } + + return p; +} + +/** + * This function should be called when a packet is ready to be read + * from the interface. It uses the function low_level_input() that + * should handle the actual reception of bytes from the network + * interface. Then the type of the received packet is determined and + * the appropriate input function is called. + * + * @param netif the lwip network interface structure for this ethernetif + */ +void ethernetif_input(void* argument) +{ + struct pbuf *p = NULL; + struct netif *netif = (struct netif *) argument; + + for( ;; ) + { + if (osSemaphoreAcquire(RxPktSemaphore, TIME_WAITING_FOR_INPUT) == osOK) + { + do + { + p = low_level_input( netif ); + if (p != NULL) + { + if (netif->input( p, netif) != ERR_OK ) + { + pbuf_free(p); + } + } + } while(p!=NULL); + } + } +} + +#if !LWIP_ARP +/** + * This function has to be completed by user in case of ARP OFF. + * + * @param netif the lwip network interface structure for this ethernetif + * @return ERR_OK if ... + */ +static err_t low_level_output_arp_off(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr) +{ + err_t errval; + errval = ERR_OK; + +/* USER CODE BEGIN 5 */ + +/* USER CODE END 5 */ + + return errval; + +} +#endif /* LWIP_ARP */ + +/** + * Should be called at the beginning of the program to set up the + * network interface. It calls the function low_level_init() to do the + * actual setup of the hardware. + * + * This function should be passed as a parameter to netif_add(). + * + * @param netif the lwip network interface structure for this ethernetif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + * any other err_t on error + */ +err_t ethernetif_init(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + netif->hostname = "lwip"; +#endif /* LWIP_NETIF_HOSTNAME */ + + /* + * Initialize the snmp variables and counters inside the struct netif. + * The last argument should be replaced with your link speed, in units + * of bits per second. + */ + // MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS); + + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; + /* We directly use etharp_output() here to save a function call. + * You can instead declare your own function an call etharp_output() + * from it if you have to do some checks before sending (e.g. if link + * is available...) */ + +#if LWIP_IPV4 +#if LWIP_ARP || LWIP_ETHERNET +#if LWIP_ARP + netif->output = etharp_output; +#else + /* The user should write its own code in low_level_output_arp_off function */ + netif->output = low_level_output_arp_off; +#endif /* LWIP_ARP */ +#endif /* LWIP_ARP || LWIP_ETHERNET */ +#endif /* LWIP_IPV4 */ + +#if LWIP_IPV6 + netif->output_ip6 = ethip6_output; +#endif /* LWIP_IPV6 */ + + netif->linkoutput = low_level_output; + + /* initialize the hardware */ + low_level_init(netif); + + return ERR_OK; +} + +/** + * @brief Custom Rx pbuf free callback + * @param pbuf: pbuf to be freed + * @retval None + */ +void pbuf_free_custom(struct pbuf *p) +{ + struct pbuf_custom* custom_pbuf = (struct pbuf_custom*)p; + LWIP_MEMPOOL_FREE(RX_POOL, custom_pbuf); + + /* If the Rx Buffer Pool was exhausted, signal the ethernetif_input task to + * call HAL_ETH_GetRxDataBuffer to rebuild the Rx descriptors. */ + + if (RxAllocStatus == RX_ALLOC_ERROR) + { + RxAllocStatus = RX_ALLOC_OK; + osSemaphoreRelease(RxPktSemaphore); + } +} + +/* USER CODE BEGIN 6 */ + +/** +* @brief Returns the current time in milliseconds +* when LWIP_TIMERS == 1 and NO_SYS == 1 +* @param None +* @retval Current Time value +*/ +u32_t sys_now(void) +{ + return HAL_GetTick(); +} + +/* USER CODE END 6 */ + +void HAL_ETH_MspInit(ETH_HandleTypeDef* ethHandle) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if(ethHandle->Instance==ETH) + { + /* USER CODE BEGIN ETH_MspInit 0 */ + + /* USER CODE END ETH_MspInit 0 */ + /* Enable Peripheral clock */ + __HAL_RCC_ETH_CLK_ENABLE(); + + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + /**ETH GPIO Configuration + PC1 ------> ETH_MDC + PA1 ------> ETH_REF_CLK + PA2 ------> ETH_MDIO + PA7 ------> ETH_CRS_DV + PC4 ------> ETH_RXD0 + PC5 ------> ETH_RXD1 + PB11 ------> ETH_TX_EN + PB12 ------> ETH_TXD0 + PB13 ------> ETH_TXD1 + */ + GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF11_ETH; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_7; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF11_ETH; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF11_ETH; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* Peripheral interrupt init */ + HAL_NVIC_SetPriority(ETH_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(ETH_IRQn); + /* USER CODE BEGIN ETH_MspInit 1 */ + + /* USER CODE END ETH_MspInit 1 */ + } +} + +void HAL_ETH_MspDeInit(ETH_HandleTypeDef* ethHandle) +{ + if(ethHandle->Instance==ETH) + { + /* USER CODE BEGIN ETH_MspDeInit 0 */ + + /* USER CODE END ETH_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_ETH_CLK_DISABLE(); + + /**ETH GPIO Configuration + PC1 ------> ETH_MDC + PA1 ------> ETH_REF_CLK + PA2 ------> ETH_MDIO + PA7 ------> ETH_CRS_DV + PC4 ------> ETH_RXD0 + PC5 ------> ETH_RXD1 + PB11 ------> ETH_TX_EN + PB12 ------> ETH_TXD0 + PB13 ------> ETH_TXD1 + */ + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5); + + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_7); + + HAL_GPIO_DeInit(GPIOB, GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13); + + /* Peripheral interrupt Deinit*/ + HAL_NVIC_DisableIRQ(ETH_IRQn); + + /* USER CODE BEGIN ETH_MspDeInit 1 */ + + /* USER CODE END ETH_MspDeInit 1 */ + } +} + +/******************************************************************************* + PHI IO Functions +*******************************************************************************/ +/** + * @brief Initializes the MDIO interface GPIO and clocks. + * @param None + * @retval 0 if OK, -1 if ERROR + */ +int32_t ETH_PHY_IO_Init(void) +{ + /* We assume that MDIO GPIO configuration is already done + in the ETH_MspInit() else it should be done here + */ + + /* Configure the MDIO Clock */ + HAL_ETH_SetMDIOClockRange(&heth); + + return 0; +} + +/** + * @brief De-Initializes the MDIO interface . + * @param None + * @retval 0 if OK, -1 if ERROR + */ +int32_t ETH_PHY_IO_DeInit (void) +{ + return 0; +} + +/** + * @brief Read a PHY register through the MDIO interface. + * @param DevAddr: PHY port address + * @param RegAddr: PHY register address + * @param pRegVal: pointer to hold the register value + * @retval 0 if OK -1 if Error + */ +int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal) +{ + if(HAL_ETH_ReadPHYRegister(&heth, DevAddr, RegAddr, pRegVal) != HAL_OK) + { + return -1; + } + + return 0; +} + +/** + * @brief Write a value to a PHY register through the MDIO interface. + * @param DevAddr: PHY port address + * @param RegAddr: PHY register address + * @param RegVal: Value to be written + * @retval 0 if OK -1 if Error + */ +int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal) +{ + if(HAL_ETH_WritePHYRegister(&heth, DevAddr, RegAddr, RegVal) != HAL_OK) + { + return -1; + } + + return 0; +} + +/** + * @brief Get the time in millisecons used for internal PHY driver process. + * @retval Time value + */ +int32_t ETH_PHY_IO_GetTick(void) +{ + return HAL_GetTick(); +} + +/** + * @brief Check the ETH link state then update ETH driver and netif link accordingly. + * @param argument: netif + * @retval None + */ +void ethernet_link_thread(void* argument) +{ + ETH_MACConfigTypeDef MACConf = {0}; + int32_t PHYLinkState = 0; + uint32_t linkchanged = 0U, speed = 0U, duplex = 0U; + + struct netif *netif = (struct netif *) argument; +/* USER CODE BEGIN ETH link init */ + +/* USER CODE END ETH link init */ + + for(;;) + { + PHYLinkState = DP83848_GetLinkState(&DP83848); + + if(netif_is_link_up(netif) && (PHYLinkState <= DP83848_STATUS_LINK_DOWN)) + { + HAL_ETH_Stop_IT(&heth); + netif_set_down(netif); + netif_set_link_down(netif); + } + else if(!netif_is_link_up(netif) && (PHYLinkState > DP83848_STATUS_LINK_DOWN)) + { + switch (PHYLinkState) + { + case DP83848_STATUS_100MBITS_FULLDUPLEX: + duplex = ETH_FULLDUPLEX_MODE; + speed = ETH_SPEED_100M; + linkchanged = 1; + break; + case DP83848_STATUS_100MBITS_HALFDUPLEX: + duplex = ETH_HALFDUPLEX_MODE; + speed = ETH_SPEED_100M; + linkchanged = 1; + break; + case DP83848_STATUS_10MBITS_FULLDUPLEX: + duplex = ETH_FULLDUPLEX_MODE; + speed = ETH_SPEED_10M; + linkchanged = 1; + break; + case DP83848_STATUS_10MBITS_HALFDUPLEX: + duplex = ETH_HALFDUPLEX_MODE; + speed = ETH_SPEED_10M; + linkchanged = 1; + break; + default: + break; + } + + if(linkchanged) + { + /* Get MAC Config MAC */ + HAL_ETH_GetMACConfig(&heth, &MACConf); + MACConf.DuplexMode = duplex; + MACConf.Speed = speed; + HAL_ETH_SetMACConfig(&heth, &MACConf); + HAL_ETH_Start(&heth); + netif_set_up(netif); + netif_set_link_up(netif); + } + } + +/* USER CODE BEGIN ETH link Thread core code for User BSP */ + +/* USER CODE END ETH link Thread core code for User BSP */ + + osDelay(100); + } +} + +void HAL_ETH_RxAllocateCallback(uint8_t **buff) +{ +/* USER CODE BEGIN HAL ETH RxAllocateCallback */ + + struct pbuf_custom *p = LWIP_MEMPOOL_ALLOC(RX_POOL); + if (p) + { + /* Get the buff from the struct pbuf address. */ + *buff = (uint8_t *)p + offsetof(RxBuff_t, buff); + p->custom_free_function = pbuf_free_custom; + /* Initialize the struct pbuf. + * This must be performed whenever a buffer's allocated because it may be + * changed by lwIP or the app, e.g., pbuf_free decrements ref. */ + pbuf_alloced_custom(PBUF_RAW, 0, PBUF_REF, p, *buff, ETH_RX_BUFFER_SIZE); + } + else + { + RxAllocStatus = RX_ALLOC_ERROR; + *buff = NULL; + } +/* USER CODE END HAL ETH RxAllocateCallback */ +} + +void HAL_ETH_RxLinkCallback(void **pStart, void **pEnd, uint8_t *buff, uint16_t Length) +{ +/* USER CODE BEGIN HAL ETH RxLinkCallback */ + + struct pbuf **ppStart = (struct pbuf **)pStart; + struct pbuf **ppEnd = (struct pbuf **)pEnd; + struct pbuf *p = NULL; + + /* Get the struct pbuf from the buff address. */ + p = (struct pbuf *)(buff - offsetof(RxBuff_t, buff)); + p->next = NULL; + p->tot_len = 0; + p->len = Length; + + /* Chain the buffer. */ + if (!*ppStart) + { + /* The first buffer of the packet. */ + *ppStart = p; + } + else + { + /* Chain the buffer to the end of the packet. */ + (*ppEnd)->next = p; + } + *ppEnd = 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 = *ppStart; p != NULL; p = p->next) + { + p->tot_len += Length; + } + +/* USER CODE END HAL ETH RxLinkCallback */ +} + +void HAL_ETH_TxFreeCallback(uint32_t * buff) +{ +/* USER CODE BEGIN HAL ETH TxFreeCallback */ + + pbuf_free((struct pbuf *)buff); + +/* USER CODE END HAL ETH TxFreeCallback */ +} + +/* USER CODE BEGIN 8 */ + +/* USER CODE END 8 */ + + diff --git a/stm32/ethernetif.h b/stm32/ethernetif.h new file mode 100644 index 0000000..85c1acf --- /dev/null +++ b/stm32/ethernetif.h @@ -0,0 +1,47 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * File Name : ethernetif.h + * Description : This file provides initialization code for LWIP + * middleWare. + ****************************************************************************** + * @attention + * + * Copyright (c) 2022 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +#ifndef __ETHERNETIF_H__ +#define __ETHERNETIF_H__ + +#include "lwip/err.h" +#include "lwip/netif.h" +#include "cmsis_os.h" + +/* Within 'USER CODE' section, code will be kept by default at each generation */ +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* Exported functions ------------------------------------------------------- */ +err_t ethernetif_init(struct netif *netif); + +void ethernetif_input(void* argument); +void ethernet_link_thread(void* argument ); + +void Error_Handler(void); +u32_t sys_jiffies(void); +u32_t sys_now(void); + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ +#endif + diff --git a/stm32/lwip.h b/stm32/lwip.h new file mode 100644 index 0000000..02df90e --- /dev/null +++ b/stm32/lwip.h @@ -0,0 +1,76 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * File Name : LWIP.h + * Description : This file provides code for the configuration + * of the LWIP. + ****************************************************************************** + * @attention + * + * Copyright (c) 2022 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ************************************************************************* + + */ +/* USER CODE END Header */ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __mx_lwip_H +#define __mx_lwip_H +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "lwip/opt.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "netif/etharp.h" +#include "lwip/dhcp.h" +#include "lwip/netif.h" +#include "lwip/timeouts.h" +#include "ethernetif.h" + +/* Includes for RTOS ---------------------------------------------------------*/ +#if WITH_RTOS +#include "lwip/tcpip.h" +#endif /* WITH_RTOS */ + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* Global Variables ----------------------------------------------------------*/ +extern ETH_HandleTypeDef heth; + +/* LWIP init function */ +void MX_LWIP_Init(void); + +#if !WITH_RTOS +/* USER CODE BEGIN 1 */ +/* Function defined in lwip.c to: + * - Read a received packet from the Ethernet buffers + * - Send it to the lwIP stack for handling + * - Handle timeouts if NO_SYS_NO_TIMERS not set + */ +void MX_LWIP_Process(void); + +/* USER CODE END 1 */ +#endif /* WITH_RTOS */ + +#ifdef __cplusplus +} +#endif +#endif /*__ mx_lwip_H */ + +/** + * @} + */ + +/** + * @} + */ -- 2.37.2 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel