[PATCH rtems-lwip v3 3/7] Add STM32 Ethernet source
Kinsey Moore
kinsey.moore at oarcorp.com
Thu Sep 8 17:06:38 UTC 2022
lwip.h should also be removed as I believe it is unused except where
it's included in netstart.h which doesn't use anything declared there as
far as I can tell. The only thing I can tell that lwip.h provides that's
of any use is the extern declaration for heth and it isn't used for that.
Kinsey
On 9/8/2022 11:34, Duc Doan wrote:
> 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 ---------------------------------------------------------*/
> +/*
> + at 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.
> +
> + at 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 */
> +
> +/**
> + * @}
> + */
> +
> +/**
> + * @}
> + */
More information about the devel
mailing list