文章目录
- PHY——LAN8720A 寄存器读写 (二)
- 工程配置
- 引脚初始化代码
- 以太网初始化代码
- PHY 接口实现
- LAN8720 接口实现
- PHY 接口测试
PHY——LAN8720A 寄存器读写 (二)
工程配置
这里以野火电子的 F429 开发板为例,配置以太网外设
这里有一点需要注意原理图 RMII_TXD0, RMII_TXD1 使用的分别是 PG13, PG14
,如下图
但是当 CubeMx 使能 ETH 外设的 RMII 时候,默认使用的引脚是 PB12 和 PB13
这里需要手动修改
这样 RMII 的引脚和以太网相关时钟就配置好了,这里我们只借助 CubeMx 配置这两个,PHY的驱动自己来实现
引脚初始化代码
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 */
/* ETH clock enable */
__HAL_RCC_ETH_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOG_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
PG13 ------> ETH_TXD0
PG14 ------> 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_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);
GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14;
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(GPIOG, &GPIO_InitStruct);
/* USER CODE BEGIN ETH_MspInit 1 */
/* USER CODE END ETH_MspInit 1 */
}
}
以太网初始化代码
void MX_ETH_Init(void)
{
/* USER CODE BEGIN ETH_Init 0 */
/* USER CODE END ETH_Init 0 */
static uint8_t MACAddr[6];
/* USER CODE BEGIN ETH_Init 1 */
/* USER CODE END ETH_Init 1 */
heth.Instance = ETH;
MACAddr[0] = 0x00;
MACAddr[1] = 0x80;
MACAddr[2] = 0xE1;
MACAddr[3] = 0x00;
MACAddr[4] = 0x00;
MACAddr[5] = 0x00;
heth.Init.MACAddr = &MACAddr[0];
heth.Init.MediaInterface = HAL_ETH_RMII_MODE;
heth.Init.TxDesc = DMATxDscrTab;
heth.Init.RxDesc = DMARxDscrTab;
heth.Init.RxBuffLen = 1524;
/* USER CODE BEGIN MACADDRESS */
/* USER CODE END MACADDRESS */
if (HAL_ETH_Init(&heth) != HAL_OK)
{
Error_Handler();
}
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;
/* USER CODE BEGIN ETH_Init 2 */
/* USER CODE END ETH_Init 2 */
}
PHY 接口实现
ethernetif.c
这个文件其实主要实现了两个接口 ETH_PHY_IO_ReadReg
和 ETH_PHY_IO_WriteReg
/* USER CODE BEGIN Header */
/**
******************************************************************************
* File Name : ethernetif.c
* Description : This file provides code for the configuration
* of the ethernetif.c MiddleWare.
******************************************************************************
* @attention
*
* Copyright (c) 2025 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 "ethernetif.h"
#include "lan8720.h"
#include <string.h>
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* 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);
lan8720_Object_t LAN8720;
lan8720_IOCtx_t LAN8720_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 */
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/* USER CODE END 6 */
/*******************************************************************************
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();
}
/* USER CODE BEGIN 8 */
/* USER CODE END 8 */
ethernetif.h 文件
/* USER CODE BEGIN Header */
/**
******************************************************************************
* File Name : ethernetif.h
* Description : This file provides initialization code for LWIP
* middleWare.
******************************************************************************
* @attention
*
* Copyright (c) 2025 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__
/* USER CODE BEGIN 0 */
#include "main.h"
#include "lan8720.h"
extern ETH_HandleTypeDef heth;
extern lan8720_Object_t LAN8720;
extern lan8720_IOCtx_t LAN8720_IOCtx;
/* USER CODE END 0 */
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
#endif
LAN8720 接口实现
lan8720.c
/**
******************************************************************************
* @file lan8720.c
* @author MCD Application Team
* @brief This file provides a set of functions needed to manage the LAN742
* PHY devices.
******************************************************************************
* @attention
*
* Copyright (c) 2017 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.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "lan8720.h"
/** @addtogroup BSP
* @{
*/
/** @addtogroup Component
* @{
*/
/** @defgroup LAN8720 LAN8720
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/** @defgroup LAN8720_Private_Defines LAN8720 Private Defines
* @{
*/
#define LAN8720_MAX_DEV_ADDR ((uint32_t)31U)
/**
* @}
*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/** @defgroup LAN8720_Private_Functions LAN8720 Private Functions
* @{
*/
/**
* @brief Register IO functions to component object
* @param pObj: device object of LAN8720_Object_t.
* @param ioctx: holds device IO functions.
* @retval LAN8720_STATUS_OK if OK
* LAN8720_STATUS_ERROR if missing mandatory function
*/
int32_t LAN8720_RegisterBusIO(lan8720_Object_t *pObj, lan8720_IOCtx_t *ioctx)
{
if(!pObj || !ioctx->ReadReg || !ioctx->WriteReg || !ioctx->GetTick)
{
return LAN8720_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 LAN8720_STATUS_OK;
}
/**
* @brief Initialize the lan8720 and configure the needed hardware resources
* @param pObj: device object LAN8720_Object_t.
* @retval LAN8720_STATUS_OK if OK
* LAN8720_STATUS_ADDRESS_ERROR if cannot find device address
* LAN8720_STATUS_READ_ERROR if cannot read register
*/
int32_t LAN8720_Init(lan8720_Object_t *pObj)
{
uint32_t regvalue = 0, addr = 0;
int32_t status = LAN8720_STATUS_OK;
if(pObj->Is_Initialized == 0)
{
if(pObj->IO.Init != 0)
{
/* GPIO and Clocks initialization */
pObj->IO.Init();
}
/* for later check */
pObj->DevAddr = LAN8720_MAX_DEV_ADDR + 1;
/* Get the device address from special mode register */
for(addr = 0; addr <= LAN8720_MAX_DEV_ADDR; addr ++)
{
if(pObj->IO.ReadReg(addr, LAN8720_SMR, ®value) < 0)
{
status = LAN8720_STATUS_READ_ERROR;
/* Can't read from this device address
continue with next address */
continue;
}
if((regvalue & LAN8720_SMR_PHY_ADDR) == addr)
{
pObj->DevAddr = addr;
status = LAN8720_STATUS_OK;
break;
}
}
if(pObj->DevAddr > LAN8720_MAX_DEV_ADDR)
{
status = LAN8720_STATUS_ADDRESS_ERROR;
}
/* if device address is matched */
if(status == LAN8720_STATUS_OK)
{
pObj->Is_Initialized = 1;
}
}
return status;
}
/**
* @brief De-Initialize the lan8720 and it's hardware resources
* @param pObj: device object LAN8720_Object_t.
* @retval None
*/
int32_t LAN8720_DeInit(lan8720_Object_t *pObj)
{
if(pObj->Is_Initialized)
{
if(pObj->IO.DeInit != 0)
{
if(pObj->IO.DeInit() < 0)
{
return LAN8720_STATUS_ERROR;
}
}
pObj->Is_Initialized = 0;
}
return LAN8720_STATUS_OK;
}
/**
* @brief Disable the LAN8720 power down mode.
* @param pObj: device object LAN8720_Object_t.
* @retval LAN8720_STATUS_OK if OK
* LAN8720_STATUS_READ_ERROR if cannot read register
* LAN8720_STATUS_WRITE_ERROR if cannot write to register
*/
int32_t LAN8720_DisablePowerDownMode(lan8720_Object_t *pObj)
{
uint32_t readval = 0;
int32_t status = LAN8720_STATUS_OK;
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_BCR, &readval) >= 0)
{
readval &= ~LAN8720_BCR_POWER_DOWN;
/* Apply configuration */
if(pObj->IO.WriteReg(pObj->DevAddr, LAN8720_BCR, readval) < 0)
{
status = LAN8720_STATUS_WRITE_ERROR;
}
}
else
{
status = LAN8720_STATUS_READ_ERROR;
}
return status;
}
/**
* @brief Enable the LAN8720 power down mode.
* @param pObj: device object LAN8720_Object_t.
* @retval LAN8720_STATUS_OK if OK
* LAN8720_STATUS_READ_ERROR if cannot read register
* LAN8720_STATUS_WRITE_ERROR if cannot write to register
*/
int32_t LAN8720_EnablePowerDownMode(lan8720_Object_t *pObj)
{
uint32_t readval = 0;
int32_t status = LAN8720_STATUS_OK;
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_BCR, &readval) >= 0)
{
readval |= LAN8720_BCR_POWER_DOWN;
/* Apply configuration */
if(pObj->IO.WriteReg(pObj->DevAddr, LAN8720_BCR, readval) < 0)
{
status = LAN8720_STATUS_WRITE_ERROR;
}
}
else
{
status = LAN8720_STATUS_READ_ERROR;
}
return status;
}
/**
* @brief Start the auto negotiation process.
* @param pObj: device object LAN8720_Object_t.
* @retval LAN8720_STATUS_OK if OK
* LAN8720_STATUS_READ_ERROR if cannot read register
* LAN8720_STATUS_WRITE_ERROR if cannot write to register
*/
int32_t LAN8720_StartAutoNego(lan8720_Object_t *pObj)
{
uint32_t readval = 0;
int32_t status = LAN8720_STATUS_OK;
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_BCR, &readval) >= 0)
{
readval |= LAN8720_BCR_AUTONEGO_EN;
/* Apply configuration */
if(pObj->IO.WriteReg(pObj->DevAddr, LAN8720_BCR, readval) < 0)
{
status = LAN8720_STATUS_WRITE_ERROR;
}
}
else
{
status = LAN8720_STATUS_READ_ERROR;
}
return status;
}
/**
* @brief Get the link state of LAN8720 device.
* @param pObj: Pointer to device object.
* @param pLinkState: Pointer to link state
* @retval LAN8720_STATUS_LINK_DOWN if link is down
* LAN8720_STATUS_AUTONEGO_NOTDONE if Auto nego not completed
* LAN8720_STATUS_100MBITS_FULLDUPLEX if 100Mb/s FD
* LAN8720_STATUS_100MBITS_HALFDUPLEX if 100Mb/s HD
* LAN8720_STATUS_10MBITS_FULLDUPLEX if 10Mb/s FD
* LAN8720_STATUS_10MBITS_HALFDUPLEX if 10Mb/s HD
* LAN8720_STATUS_READ_ERROR if cannot read register
* LAN8720_STATUS_WRITE_ERROR if cannot write to register
*/
int32_t LAN8720_GetLinkState(lan8720_Object_t *pObj)
{
uint32_t readval = 0;
/* Read Status register */
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_BSR, &readval) < 0)
{
return LAN8720_STATUS_READ_ERROR;
}
/* Read Status register again */
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_BSR, &readval) < 0)
{
return LAN8720_STATUS_READ_ERROR;
}
if((readval & LAN8720_BSR_LINK_STATUS) == 0)
{
/* Return Link Down status */
return LAN8720_STATUS_LINK_DOWN;
}
/* Check Auto negotiation */
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_BCR, &readval) < 0)
{
return LAN8720_STATUS_READ_ERROR;
}
if((readval & LAN8720_BCR_AUTONEGO_EN) != LAN8720_BCR_AUTONEGO_EN)
{
if(((readval & LAN8720_BCR_SPEED_SELECT) == LAN8720_BCR_SPEED_SELECT) && ((readval & LAN8720_BCR_DUPLEX_MODE) == LAN8720_BCR_DUPLEX_MODE))
{
return LAN8720_STATUS_100MBITS_FULLDUPLEX;
}
else if ((readval & LAN8720_BCR_SPEED_SELECT) == LAN8720_BCR_SPEED_SELECT)
{
return LAN8720_STATUS_100MBITS_HALFDUPLEX;
}
else if ((readval & LAN8720_BCR_DUPLEX_MODE) == LAN8720_BCR_DUPLEX_MODE)
{
return LAN8720_STATUS_10MBITS_FULLDUPLEX;
}
else
{
return LAN8720_STATUS_10MBITS_HALFDUPLEX;
}
}
else /* Auto Nego enabled */
{
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_PHYSCSR, &readval) < 0)
{
return LAN8720_STATUS_READ_ERROR;
}
/* Check if auto nego not done */
if((readval & LAN8720_PHYSCSR_AUTONEGO_DONE) == 0)
{
return LAN8720_STATUS_AUTONEGO_NOTDONE;
}
if((readval & LAN8720_PHYSCSR_HCDSPEEDMASK) == LAN8720_PHYSCSR_100BTX_FD)
{
return LAN8720_STATUS_100MBITS_FULLDUPLEX;
}
else if ((readval & LAN8720_PHYSCSR_HCDSPEEDMASK) == LAN8720_PHYSCSR_100BTX_HD)
{
return LAN8720_STATUS_100MBITS_HALFDUPLEX;
}
else if ((readval & LAN8720_PHYSCSR_HCDSPEEDMASK) == LAN8720_PHYSCSR_10BT_FD)
{
return LAN8720_STATUS_10MBITS_FULLDUPLEX;
}
else
{
return LAN8720_STATUS_10MBITS_HALFDUPLEX;
}
}
}
/**
* @brief Set the link state of LAN8720 device.
* @param pObj: Pointer to device object.
* @param pLinkState: link state can be one of the following
* LAN8720_STATUS_100MBITS_FULLDUPLEX if 100Mb/s FD
* LAN8720_STATUS_100MBITS_HALFDUPLEX if 100Mb/s HD
* LAN8720_STATUS_10MBITS_FULLDUPLEX if 10Mb/s FD
* LAN8720_STATUS_10MBITS_HALFDUPLEX if 10Mb/s HD
* @retval LAN8720_STATUS_OK if OK
* LAN8720_STATUS_ERROR if parameter error
* LAN8720_STATUS_READ_ERROR if cannot read register
* LAN8720_STATUS_WRITE_ERROR if cannot write to register
*/
int32_t LAN8720_SetLinkState(lan8720_Object_t *pObj, uint32_t LinkState)
{
uint32_t bcrvalue = 0;
int32_t status = LAN8720_STATUS_OK;
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_BCR, &bcrvalue) >= 0)
{
/* Disable link config (Auto nego, speed and duplex) */
bcrvalue &= ~(LAN8720_BCR_AUTONEGO_EN | LAN8720_BCR_SPEED_SELECT | LAN8720_BCR_DUPLEX_MODE);
if(LinkState == LAN8720_STATUS_100MBITS_FULLDUPLEX)
{
bcrvalue |= (LAN8720_BCR_SPEED_SELECT | LAN8720_BCR_DUPLEX_MODE);
}
else if (LinkState == LAN8720_STATUS_100MBITS_HALFDUPLEX)
{
bcrvalue |= LAN8720_BCR_SPEED_SELECT;
}
else if (LinkState == LAN8720_STATUS_10MBITS_FULLDUPLEX)
{
bcrvalue |= LAN8720_BCR_DUPLEX_MODE;
}
else
{
/* Wrong link status parameter */
status = LAN8720_STATUS_ERROR;
}
}
else
{
status = LAN8720_STATUS_READ_ERROR;
}
if(status == LAN8720_STATUS_OK)
{
/* Apply configuration */
if(pObj->IO.WriteReg(pObj->DevAddr, LAN8720_BCR, bcrvalue) < 0)
{
status = LAN8720_STATUS_WRITE_ERROR;
}
}
return status;
}
/**
* @brief Enable loopback mode.
* @param pObj: Pointer to device object.
* @retval LAN8720_STATUS_OK if OK
* LAN8720_STATUS_READ_ERROR if cannot read register
* LAN8720_STATUS_WRITE_ERROR if cannot write to register
*/
int32_t LAN8720_EnableLoopbackMode(lan8720_Object_t *pObj)
{
uint32_t readval = 0;
int32_t status = LAN8720_STATUS_OK;
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_BCR, &readval) >= 0)
{
readval |= LAN8720_BCR_LOOPBACK;
/* Apply configuration */
if(pObj->IO.WriteReg(pObj->DevAddr, LAN8720_BCR, readval) < 0)
{
status = LAN8720_STATUS_WRITE_ERROR;
}
}
else
{
status = LAN8720_STATUS_READ_ERROR;
}
return status;
}
/**
* @brief Disable loopback mode.
* @param pObj: Pointer to device object.
* @retval LAN8720_STATUS_OK if OK
* LAN8720_STATUS_READ_ERROR if cannot read register
* LAN8720_STATUS_WRITE_ERROR if cannot write to register
*/
int32_t LAN8720_DisableLoopbackMode(lan8720_Object_t *pObj)
{
uint32_t readval = 0;
int32_t status = LAN8720_STATUS_OK;
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_BCR, &readval) >= 0)
{
readval &= ~LAN8720_BCR_LOOPBACK;
/* Apply configuration */
if(pObj->IO.WriteReg(pObj->DevAddr, LAN8720_BCR, readval) < 0)
{
status = LAN8720_STATUS_WRITE_ERROR;
}
}
else
{
status = LAN8720_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:
* LAN8720_WOL_IT
* LAN8720_ENERGYON_IT
* LAN8720_AUTONEGO_COMPLETE_IT
* LAN8720_REMOTE_FAULT_IT
* LAN8720_LINK_DOWN_IT
* LAN8720_AUTONEGO_LP_ACK_IT
* LAN8720_PARALLEL_DETECTION_FAULT_IT
* LAN8720_AUTONEGO_PAGE_RECEIVED_IT
* @retval LAN8720_STATUS_OK if OK
* LAN8720_STATUS_READ_ERROR if cannot read register
* LAN8720_STATUS_WRITE_ERROR if cannot write to register
*/
int32_t LAN8720_EnableIT(lan8720_Object_t *pObj, uint32_t Interrupt)
{
uint32_t readval = 0;
int32_t status = LAN8720_STATUS_OK;
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_IMR, &readval) >= 0)
{
readval |= Interrupt;
/* Apply configuration */
if(pObj->IO.WriteReg(pObj->DevAddr, LAN8720_IMR, readval) < 0)
{
status = LAN8720_STATUS_WRITE_ERROR;
}
}
else
{
status = LAN8720_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:
* LAN8720_WOL_IT
* LAN8720_ENERGYON_IT
* LAN8720_AUTONEGO_COMPLETE_IT
* LAN8720_REMOTE_FAULT_IT
* LAN8720_LINK_DOWN_IT
* LAN8720_AUTONEGO_LP_ACK_IT
* LAN8720_PARALLEL_DETECTION_FAULT_IT
* LAN8720_AUTONEGO_PAGE_RECEIVED_IT
* @retval LAN8720_STATUS_OK if OK
* LAN8720_STATUS_READ_ERROR if cannot read register
* LAN8720_STATUS_WRITE_ERROR if cannot write to register
*/
int32_t LAN8720_DisableIT(lan8720_Object_t *pObj, uint32_t Interrupt)
{
uint32_t readval = 0;
int32_t status = LAN8720_STATUS_OK;
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_IMR, &readval) >= 0)
{
readval &= ~Interrupt;
/* Apply configuration */
if(pObj->IO.WriteReg(pObj->DevAddr, LAN8720_IMR, readval) < 0)
{
status = LAN8720_STATUS_WRITE_ERROR;
}
}
else
{
status = LAN8720_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:
* LAN8720_WOL_IT
* LAN8720_ENERGYON_IT
* LAN8720_AUTONEGO_COMPLETE_IT
* LAN8720_REMOTE_FAULT_IT
* LAN8720_LINK_DOWN_IT
* LAN8720_AUTONEGO_LP_ACK_IT
* LAN8720_PARALLEL_DETECTION_FAULT_IT
* LAN8720_AUTONEGO_PAGE_RECEIVED_IT
* @retval LAN8720_STATUS_OK if OK
* LAN8720_STATUS_READ_ERROR if cannot read register
*/
int32_t LAN8720_ClearIT(lan8720_Object_t *pObj, uint32_t Interrupt)
{
uint32_t readval = 0;
int32_t status = LAN8720_STATUS_OK;
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_ISFR, &readval) < 0)
{
status = LAN8720_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:
* LAN8720_WOL_IT
* LAN8720_ENERGYON_IT
* LAN8720_AUTONEGO_COMPLETE_IT
* LAN8720_REMOTE_FAULT_IT
* LAN8720_LINK_DOWN_IT
* LAN8720_AUTONEGO_LP_ACK_IT
* LAN8720_PARALLEL_DETECTION_FAULT_IT
* LAN8720_AUTONEGO_PAGE_RECEIVED_IT
* @retval 1 IT flag is SET
* 0 IT flag is RESET
* LAN8720_STATUS_READ_ERROR if cannot read register
*/
int32_t LAN8720_GetITStatus(lan8720_Object_t *pObj, uint32_t Interrupt)
{
uint32_t readval = 0;
int32_t status = 0;
if(pObj->IO.ReadReg(pObj->DevAddr, LAN8720_ISFR, &readval) >= 0)
{
status = ((readval & Interrupt) == Interrupt);
}
else
{
status = LAN8720_STATUS_READ_ERROR;
}
return status;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
lan8720.h
这个文件主要定义 PHY 的相关寄存器以及各个 bit,例如 LAN8720_BCR
, LAN8720_BSR
和 LAN8720_BCR_SOFT_RESET
等
/**
******************************************************************************
* @file lan8720.h
* @author MCD Application Team
* @brief This file contains all the functions prototypes for the
* lan8720.c PHY driver.
******************************************************************************
* @attention
*
* Copyright (c) 2017 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.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef LAN8720_H
#define LAN8720_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
/** @addtogroup BSP
* @{
*/
/** @addtogroup Component
* @{
*/
/** @defgroup LAN8720
* @{
*/
/* Exported constants --------------------------------------------------------*/
/** @defgroup LAN8720_Exported_Constants LAN8720 Exported Constants
* @{
*/
/** @defgroup LAN8720_Registers_Mapping LAN8720 Registers Mapping
* @{
*/
#define LAN8720_BCR ((uint16_t)0x0000U)
#define LAN8720_BSR ((uint16_t)0x0001U)
#define LAN8720_PHYI1R ((uint16_t)0x0002U)
#define LAN8720_PHYI2R ((uint16_t)0x0003U)
#define LAN8720_ANAR ((uint16_t)0x0004U)
#define LAN8720_ANLPAR ((uint16_t)0x0005U)
#define LAN8720_ANER ((uint16_t)0x0006U)
#define LAN8720_ANNPTR ((uint16_t)0x0007U)
#define LAN8720_ANNPRR ((uint16_t)0x0008U)
#define LAN8720_MMDACR ((uint16_t)0x000DU)
#define LAN8720_MMDAADR ((uint16_t)0x000EU)
#define LAN8720_ENCTR ((uint16_t)0x0010U)
#define LAN8720_MCSR ((uint16_t)0x0011U)
#define LAN8720_SMR ((uint16_t)0x0012U)
#define LAN8720_TPDCR ((uint16_t)0x0018U)
#define LAN8720_TCSR ((uint16_t)0x0019U)
#define LAN8720_SECR ((uint16_t)0x001AU)
#define LAN8720_SCSIR ((uint16_t)0x001BU)
#define LAN8720_CLR ((uint16_t)0x001CU)
#define LAN8720_ISFR ((uint16_t)0x001DU)
#define LAN8720_IMR ((uint16_t)0x001EU)
#define LAN8720_PHYSCSR ((uint16_t)0x001FU)
/**
* @}
*/
/** @defgroup LAN8720_BCR_Bit_Definition LAN8720 BCR Bit Definition
* @{
*/
#define LAN8720_BCR_SOFT_RESET ((uint16_t)0x8000U)
#define LAN8720_BCR_LOOPBACK ((uint16_t)0x4000U)
#define LAN8720_BCR_SPEED_SELECT ((uint16_t)0x2000U)
#define LAN8720_BCR_AUTONEGO_EN ((uint16_t)0x1000U)
#define LAN8720_BCR_POWER_DOWN ((uint16_t)0x0800U)
#define LAN8720_BCR_ISOLATE ((uint16_t)0x0400U)
#define LAN8720_BCR_RESTART_AUTONEGO ((uint16_t)0x0200U)
#define LAN8720_BCR_DUPLEX_MODE ((uint16_t)0x0100U)
/**
* @}
*/
/** @defgroup LAN8720_BSR_Bit_Definition LAN8720 BSR Bit Definition
* @{
*/
#define LAN8720_BSR_100BASE_T4 ((uint16_t)0x8000U)
#define LAN8720_BSR_100BASE_TX_FD ((uint16_t)0x4000U)
#define LAN8720_BSR_100BASE_TX_HD ((uint16_t)0x2000U)
#define LAN8720_BSR_10BASE_T_FD ((uint16_t)0x1000U)
#define LAN8720_BSR_10BASE_T_HD ((uint16_t)0x0800U)
#define LAN8720_BSR_100BASE_T2_FD ((uint16_t)0x0400U)
#define LAN8720_BSR_100BASE_T2_HD ((uint16_t)0x0200U)
#define LAN8720_BSR_EXTENDED_STATUS ((uint16_t)0x0100U)
#define LAN8720_BSR_AUTONEGO_CPLT ((uint16_t)0x0020U)
#define LAN8720_BSR_REMOTE_FAULT ((uint16_t)0x0010U)
#define LAN8720_BSR_AUTONEGO_ABILITY ((uint16_t)0x0008U)
#define LAN8720_BSR_LINK_STATUS ((uint16_t)0x0004U)
#define LAN8720_BSR_JABBER_DETECT ((uint16_t)0x0002U)
#define LAN8720_BSR_EXTENDED_CAP ((uint16_t)0x0001U)
/**
* @}
*/
/** @defgroup LAN8720_PHYI1R_Bit_Definition LAN8720 PHYI1R Bit Definition
* @{
*/
#define LAN8720_PHYI1R_OUI_3_18 ((uint16_t)0xFFFFU)
/**
* @}
*/
/** @defgroup LAN8720_PHYI2R_Bit_Definition LAN8720 PHYI2R Bit Definition
* @{
*/
#define LAN8720_PHYI2R_OUI_19_24 ((uint16_t)0xFC00U)
#define LAN8720_PHYI2R_MODEL_NBR ((uint16_t)0x03F0U)
#define LAN8720_PHYI2R_REVISION_NBR ((uint16_t)0x000FU)
/**
* @}
*/
/** @defgroup LAN8720_ANAR_Bit_Definition LAN8720 ANAR Bit Definition
* @{
*/
#define LAN8720_ANAR_NEXT_PAGE ((uint16_t)0x8000U)
#define LAN8720_ANAR_REMOTE_FAULT ((uint16_t)0x2000U)
#define LAN8720_ANAR_PAUSE_OPERATION ((uint16_t)0x0C00U)
#define LAN8720_ANAR_PO_NOPAUSE ((uint16_t)0x0000U)
#define LAN8720_ANAR_PO_SYMMETRIC_PAUSE ((uint16_t)0x0400U)
#define LAN8720_ANAR_PO_ASYMMETRIC_PAUSE ((uint16_t)0x0800U)
#define LAN8720_ANAR_PO_ADVERTISE_SUPPORT ((uint16_t)0x0C00U)
#define LAN8720_ANAR_100BASE_TX_FD ((uint16_t)0x0100U)
#define LAN8720_ANAR_100BASE_TX ((uint16_t)0x0080U)
#define LAN8720_ANAR_10BASE_T_FD ((uint16_t)0x0040U)
#define LAN8720_ANAR_10BASE_T ((uint16_t)0x0020U)
#define LAN8720_ANAR_SELECTOR_FIELD ((uint16_t)0x000FU)
/**
* @}
*/
/** @defgroup LAN8720_ANLPAR_Bit_Definition LAN8720 ANLPAR Bit Definition
* @{
*/
#define LAN8720_ANLPAR_NEXT_PAGE ((uint16_t)0x8000U)
#define LAN8720_ANLPAR_REMOTE_FAULT ((uint16_t)0x2000U)
#define LAN8720_ANLPAR_PAUSE_OPERATION ((uint16_t)0x0C00U)
#define LAN8720_ANLPAR_PO_NOPAUSE ((uint16_t)0x0000U)
#define LAN8720_ANLPAR_PO_SYMMETRIC_PAUSE ((uint16_t)0x0400U)
#define LAN8720_ANLPAR_PO_ASYMMETRIC_PAUSE ((uint16_t)0x0800U)
#define LAN8720_ANLPAR_PO_ADVERTISE_SUPPORT ((uint16_t)0x0C00U)
#define LAN8720_ANLPAR_100BASE_TX_FD ((uint16_t)0x0100U)
#define LAN8720_ANLPAR_100BASE_TX ((uint16_t)0x0080U)
#define LAN8720_ANLPAR_10BASE_T_FD ((uint16_t)0x0040U)
#define LAN8720_ANLPAR_10BASE_T ((uint16_t)0x0020U)
#define LAN8720_ANLPAR_SELECTOR_FIELD ((uint16_t)0x000FU)
/**
* @}
*/
/** @defgroup LAN8720_ANER_Bit_Definition LAN8720 ANER Bit Definition
* @{
*/
#define LAN8720_ANER_RX_NP_LOCATION_ABLE ((uint16_t)0x0040U)
#define LAN8720_ANER_RX_NP_STORAGE_LOCATION ((uint16_t)0x0020U)
#define LAN8720_ANER_PARALLEL_DETECT_FAULT ((uint16_t)0x0010U)
#define LAN8720_ANER_LP_NP_ABLE ((uint16_t)0x0008U)
#define LAN8720_ANER_NP_ABLE ((uint16_t)0x0004U)
#define LAN8720_ANER_PAGE_RECEIVED ((uint16_t)0x0002U)
#define LAN8720_ANER_LP_AUTONEG_ABLE ((uint16_t)0x0001U)
/**
* @}
*/
/** @defgroup LAN8720_ANNPTR_Bit_Definition LAN8720 ANNPTR Bit Definition
* @{
*/
#define LAN8720_ANNPTR_NEXT_PAGE ((uint16_t)0x8000U)
#define LAN8720_ANNPTR_MESSAGE_PAGE ((uint16_t)0x2000U)
#define LAN8720_ANNPTR_ACK2 ((uint16_t)0x1000U)
#define LAN8720_ANNPTR_TOGGLE ((uint16_t)0x0800U)
#define LAN8720_ANNPTR_MESSAGGE_CODE ((uint16_t)0x07FFU)
/**
* @}
*/
/** @defgroup LAN8720_ANNPRR_Bit_Definition LAN8720 ANNPRR Bit Definition
* @{
*/
#define LAN8720_ANNPTR_NEXT_PAGE ((uint16_t)0x8000U)
#define LAN8720_ANNPRR_ACK ((uint16_t)0x4000U)
#define LAN8720_ANNPRR_MESSAGE_PAGE ((uint16_t)0x2000U)
#define LAN8720_ANNPRR_ACK2 ((uint16_t)0x1000U)
#define LAN8720_ANNPRR_TOGGLE ((uint16_t)0x0800U)
#define LAN8720_ANNPRR_MESSAGGE_CODE ((uint16_t)0x07FFU)
/**
* @}
*/
/** @defgroup LAN8720_MMDACR_Bit_Definition LAN8720 MMDACR Bit Definition
* @{
*/
#define LAN8720_MMDACR_MMD_FUNCTION ((uint16_t)0xC000U)
#define LAN8720_MMDACR_MMD_FUNCTION_ADDR ((uint16_t)0x0000U)
#define LAN8720_MMDACR_MMD_FUNCTION_DATA ((uint16_t)0x4000U)
#define LAN8720_MMDACR_MMD_DEV_ADDR ((uint16_t)0x001FU)
/**
* @}
*/
/** @defgroup LAN8720_ENCTR_Bit_Definition LAN8720 ENCTR Bit Definition
* @{
*/
#define LAN8720_ENCTR_TX_ENABLE ((uint16_t)0x8000U)
#define LAN8720_ENCTR_TX_TIMER ((uint16_t)0x6000U)
#define LAN8720_ENCTR_TX_TIMER_1S ((uint16_t)0x0000U)
#define LAN8720_ENCTR_TX_TIMER_768MS ((uint16_t)0x2000U)
#define LAN8720_ENCTR_TX_TIMER_512MS ((uint16_t)0x4000U)
#define LAN8720_ENCTR_TX_TIMER_265MS ((uint16_t)0x6000U)
#define LAN8720_ENCTR_RX_ENABLE ((uint16_t)0x1000U)
#define LAN8720_ENCTR_RX_MAX_INTERVAL ((uint16_t)0x0C00U)
#define LAN8720_ENCTR_RX_MAX_INTERVAL_64MS ((uint16_t)0x0000U)
#define LAN8720_ENCTR_RX_MAX_INTERVAL_256MS ((uint16_t)0x0400U)
#define LAN8720_ENCTR_RX_MAX_INTERVAL_512MS ((uint16_t)0x0800U)
#define LAN8720_ENCTR_RX_MAX_INTERVAL_1S ((uint16_t)0x0C00U)
#define LAN8720_ENCTR_EX_CROSS_OVER ((uint16_t)0x0002U)
#define LAN8720_ENCTR_EX_MANUAL_CROSS_OVER ((uint16_t)0x0001U)
/**
* @}
*/
/** @defgroup LAN8720_MCSR_Bit_Definition LAN8720 MCSR Bit Definition
* @{
*/
#define LAN8720_MCSR_EDPWRDOWN ((uint16_t)0x2000U)
#define LAN8720_MCSR_FARLOOPBACK ((uint16_t)0x0200U)
#define LAN8720_MCSR_ALTINT ((uint16_t)0x0040U)
#define LAN8720_MCSR_ENERGYON ((uint16_t)0x0002U)
/**
* @}
*/
/** @defgroup LAN8720_SMR_Bit_Definition LAN8720 SMR Bit Definition
* @{
*/
#define LAN8720_SMR_MODE ((uint16_t)0x00E0U)
#define LAN8720_SMR_PHY_ADDR ((uint16_t)0x001FU)
/**
* @}
*/
/** @defgroup LAN8720_TPDCR_Bit_Definition LAN8720 TPDCR Bit Definition
* @{
*/
#define LAN8720_TPDCR_DELAY_IN ((uint16_t)0x8000U)
#define LAN8720_TPDCR_LINE_BREAK_COUNTER ((uint16_t)0x7000U)
#define LAN8720_TPDCR_PATTERN_HIGH ((uint16_t)0x0FC0U)
#define LAN8720_TPDCR_PATTERN_LOW ((uint16_t)0x003FU)
/**
* @}
*/
/** @defgroup LAN8720_TCSR_Bit_Definition LAN8720 TCSR Bit Definition
* @{
*/
#define LAN8720_TCSR_TDR_ENABLE ((uint16_t)0x8000U)
#define LAN8720_TCSR_TDR_AD_FILTER_ENABLE ((uint16_t)0x4000U)
#define LAN8720_TCSR_TDR_CH_CABLE_TYPE ((uint16_t)0x0600U)
#define LAN8720_TCSR_TDR_CH_CABLE_DEFAULT ((uint16_t)0x0000U)
#define LAN8720_TCSR_TDR_CH_CABLE_SHORTED ((uint16_t)0x0200U)
#define LAN8720_TCSR_TDR_CH_CABLE_OPEN ((uint16_t)0x0400U)
#define LAN8720_TCSR_TDR_CH_CABLE_MATCH ((uint16_t)0x0600U)
#define LAN8720_TCSR_TDR_CH_STATUS ((uint16_t)0x0100U)
#define LAN8720_TCSR_TDR_CH_LENGTH ((uint16_t)0x00FFU)
/**
* @}
*/
/** @defgroup LAN8720_SCSIR_Bit_Definition LAN8720 SCSIR Bit Definition
* @{
*/
#define LAN8720_SCSIR_AUTO_MDIX_ENABLE ((uint16_t)0x8000U)
#define LAN8720_SCSIR_CHANNEL_SELECT ((uint16_t)0x2000U)
#define LAN8720_SCSIR_SQE_DISABLE ((uint16_t)0x0800U)
#define LAN8720_SCSIR_XPOLALITY ((uint16_t)0x0010U)
/**
* @}
*/
/** @defgroup LAN8720_CLR_Bit_Definition LAN8720 CLR Bit Definition
* @{
*/
#define LAN8720_CLR_CABLE_LENGTH ((uint16_t)0xF000U)
/**
* @}
*/
/** @defgroup LAN8720_IMR_ISFR_Bit_Definition LAN8720 IMR ISFR Bit Definition
* @{
*/
#define LAN8720_INT_8 ((uint16_t)0x0100U)
#define LAN8720_INT_7 ((uint16_t)0x0080U)
#define LAN8720_INT_6 ((uint16_t)0x0040U)
#define LAN8720_INT_5 ((uint16_t)0x0020U)
#define LAN8720_INT_4 ((uint16_t)0x0010U)
#define LAN8720_INT_3 ((uint16_t)0x0008U)
#define LAN8720_INT_2 ((uint16_t)0x0004U)
#define LAN8720_INT_1 ((uint16_t)0x0002U)
/**
* @}
*/
/** @defgroup LAN8720_PHYSCSR_Bit_Definition LAN8720 PHYSCSR Bit Definition
* @{
*/
#define LAN8720_PHYSCSR_AUTONEGO_DONE ((uint16_t)0x1000U)
#define LAN8720_PHYSCSR_HCDSPEEDMASK ((uint16_t)0x001CU)
#define LAN8720_PHYSCSR_10BT_HD ((uint16_t)0x0004U)
#define LAN8720_PHYSCSR_10BT_FD ((uint16_t)0x0014U)
#define LAN8720_PHYSCSR_100BTX_HD ((uint16_t)0x0008U)
#define LAN8720_PHYSCSR_100BTX_FD ((uint16_t)0x0018U)
/**
* @}
*/
/** @defgroup LAN8720_Status LAN8720 Status
* @{
*/
#define LAN8720_STATUS_READ_ERROR ((int32_t)-5)
#define LAN8720_STATUS_WRITE_ERROR ((int32_t)-4)
#define LAN8720_STATUS_ADDRESS_ERROR ((int32_t)-3)
#define LAN8720_STATUS_RESET_TIMEOUT ((int32_t)-2)
#define LAN8720_STATUS_ERROR ((int32_t)-1)
#define LAN8720_STATUS_OK ((int32_t) 0)
#define LAN8720_STATUS_LINK_DOWN ((int32_t) 1)
#define LAN8720_STATUS_100MBITS_FULLDUPLEX ((int32_t) 2)
#define LAN8720_STATUS_100MBITS_HALFDUPLEX ((int32_t) 3)
#define LAN8720_STATUS_10MBITS_FULLDUPLEX ((int32_t) 4)
#define LAN8720_STATUS_10MBITS_HALFDUPLEX ((int32_t) 5)
#define LAN8720_STATUS_AUTONEGO_NOTDONE ((int32_t) 6)
/**
* @}
*/
/** @defgroup LAN8720_IT_Flags LAN8720 IT Flags
* @{
*/
#define LAN8720_WOL_IT LAN8720_INT_8
#define LAN8720_ENERGYON_IT LAN8720_INT_7
#define LAN8720_AUTONEGO_COMPLETE_IT LAN8720_INT_6
#define LAN8720_REMOTE_FAULT_IT LAN8720_INT_5
#define LAN8720_LINK_DOWN_IT LAN8720_INT_4
#define LAN8720_AUTONEGO_LP_ACK_IT LAN8720_INT_3
#define LAN8720_PARALLEL_DETECTION_FAULT_IT LAN8720_INT_2
#define LAN8720_AUTONEGO_PAGE_RECEIVED_IT LAN8720_INT_1
/**
* @}
*/
/**
* @}
*/
/* Exported types ------------------------------------------------------------*/
/** @defgroup LAN8720_Exported_Types LAN8720 Exported Types
* @{
*/
typedef int32_t (*lan8720_Init_Func) (void);
typedef int32_t (*lan8720_DeInit_Func) (void);
typedef int32_t (*lan8720_ReadReg_Func) (uint32_t, uint32_t, uint32_t *);
typedef int32_t (*lan8720_WriteReg_Func) (uint32_t, uint32_t, uint32_t);
typedef int32_t (*lan8720_GetTick_Func) (void);
typedef struct
{
lan8720_Init_Func Init;
lan8720_DeInit_Func DeInit;
lan8720_WriteReg_Func WriteReg;
lan8720_ReadReg_Func ReadReg;
lan8720_GetTick_Func GetTick;
} lan8720_IOCtx_t;
typedef struct
{
uint32_t DevAddr;
uint32_t Is_Initialized;
lan8720_IOCtx_t IO;
void *pData;
}lan8720_Object_t;
/**
* @}
*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/** @defgroup LAN8720_Exported_Functions LAN8720 Exported Functions
* @{
*/
int32_t LAN8720_RegisterBusIO(lan8720_Object_t *pObj, lan8720_IOCtx_t *ioctx);
int32_t LAN8720_Init(lan8720_Object_t *pObj);
int32_t LAN8720_DeInit(lan8720_Object_t *pObj);
int32_t LAN8720_DisablePowerDownMode(lan8720_Object_t *pObj);
int32_t LAN8720_EnablePowerDownMode(lan8720_Object_t *pObj);
int32_t LAN8720_StartAutoNego(lan8720_Object_t *pObj);
int32_t LAN8720_GetLinkState(lan8720_Object_t *pObj);
int32_t LAN8720_SetLinkState(lan8720_Object_t *pObj, uint32_t LinkState);
int32_t LAN8720_EnableLoopbackMode(lan8720_Object_t *pObj);
int32_t LAN8720_DisableLoopbackMode(lan8720_Object_t *pObj);
int32_t LAN8720_EnableIT(lan8720_Object_t *pObj, uint32_t Interrupt);
int32_t LAN8720_DisableIT(lan8720_Object_t *pObj, uint32_t Interrupt);
int32_t LAN8720_ClearIT(lan8720_Object_t *pObj, uint32_t Interrupt);
int32_t LAN8720_GetITStatus(lan8720_Object_t *pObj, uint32_t Interrupt);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* LAN8720_H */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
PHY 接口测试
前面分别实现了 PHY 的读写接口,以及 LAN8720 相关的接口,这里简单测试一下,LAN8720
寄存器的读写功能
/* USER CODE BEGIN 0 */
static void print_binary(int value, int bits)
{
for (int i = bits - 1; i >= 0; i--)
{
printf("%d", (value >> i) & 1);
}
printf("b\r\n");
}
static void MY_PHY_LAN8720_INIT(void)
{
/* Set PHY IO functions */
LAN8720_RegisterBusIO(&LAN8720, &LAN8720_IOCtx);
/* Initialize the LAN8742 ETH PHY */
if(LAN8720_Init(&LAN8720) != LAN8720_STATUS_OK)
{
printf("init lan8720 error\r\n");
while(1);
}
printf("my phy addr = %d\r\n", LAN8720.DevAddr);
uint32_t readval = 0;
if(LAN8720_IOCtx.ReadReg(LAN8720.DevAddr, LAN8720_PHYI1R, &readval) < 0)
{
printf("read lan8720 error\r\n");
while(1);
}
printf("LAN8720_PHYI1R PHY ID Number = %d\r\n", readval);
readval = 0;
if(LAN8720_IOCtx.ReadReg(LAN8720.DevAddr, LAN8720_PHYI2R, &readval) < 0)
{
printf("read lan8720 error\r\n");
while(1);
}
uint32_t bits_15_10 = (readval >> 10) & 0x3F; // 提取 bit15:10
printf("LAN8720_PHYI2R PHY ID Number = ");
print_binary(bits_15_10, 6); // bit15:10 共 6 位
uint32_t bits_9_4 = (readval >> 4) & 0x3F; // 提取 bit9:4 (6 位)
printf("LAN8720_PHYI2R Model Number = ");
print_binary(bits_9_4, 6); // bit15:10 共 6 位
readval = 0;
if(LAN8720_IOCtx.ReadReg(LAN8720.DevAddr, LAN8720_BCR, &readval) < 0)
{
printf("read lan8720 error\r\n");
while(1);
}
printf("before write: %d\r\n", readval);
readval |= LAN8720_BCR_LOOPBACK;
if(LAN8720_IOCtx.WriteReg(LAN8720.DevAddr, LAN8720_BCR, readval) < 0)
{
printf("write lan8720 error\r\n");
while(1);
}
readval = 0;
if(LAN8720_IOCtx.ReadReg(LAN8720.DevAddr, LAN8720_BCR, &readval) < 0)
{
printf("read lan8720 error\r\n");
while(1);
}
printf("after bit14 set = ");
print_binary(readval, 16); // 共 16 位
}
/* USER CODE END 0 */
/* USER CODE BEGIN 2 */
MY_PHY_LAN8720_INIT();
printf("this is eht example\r\n");
/* USER CODE END 2 */
- 代码中先读取了 PHY 的地址
- 读取
LAN8720_PHYI1R
寄存器获取PHY ID Number
- 读取
LAN8720_PHYI2R
寄存器获取PHY ID Number
和Model Number
- 最后对
LAN8720_BCR
的bit14
进行了读写
部分地址的描述如下
效果如下
my phy addr = 0
PHY ID Number = 110000b
Model Number = 001111b
before write: 0
after bit14 set = 0100000000000000b
this is eht example