【极海APM32F407 Tiny Board】7. 以太网LAN8720驱动以及Lwip移植
[复制链接]
由于mcu内部集成了以太网Mac,一般很少有人用得到,但是用起来非常方便,而且只要外部连接一个PHY芯片即可。
极海mcu板子上使用的是LAN8720,这种方案比直接使用W5500 要便宜很多。
LAN8720A/LAN8720Ai是一个低功耗的可变I/O电压的10/100M PHY收发器,符合IEEE 802.3-2005标准,支持通过RMII接口与以太网MAC通信。LAN8720A/LAN8720Ai实现自动协商,自动确定最佳可能的速度和双工操作模式。HP Auto-MDIX支持允许使用直接连接或交叉局域网电缆。LAN8720A/LAN8720Ai既支持IEEE 802.3-2005标准,又支持厂商特有的注册功能。但是,操作不需要访问寄存器。初始配置可以通过“配置带”中描述的配置引脚选择。 可以寄存器选择的配置选项可用于进一步定义收发器的功能。
由于历程中使用的是DP83848芯片,如果直接跑历程会直接卡死,因此只能字节写驱动了:
/*!
* [url=home.php?mod=space&uid=1307177]@File[/url] BOARD_LAN8720A.c
*
* [url=home.php?mod=space&uid=159083]@brief[/url] This file provides all the config LAN8720A functions
*
* [url=home.php?mod=space&uid=252314]@version[/url] V1.0.0
*
* [url=home.php?mod=space&uid=311857]@date[/url] 2022-05-25
*
*/
#include "lwip/opt.h"
#include "lwip/netif.h"
#include "main.h"
#include "Board.h"
#include "apm32f4xx_eth.h"
#include "board_LAN8720A.h"
/** ETH Init Structure */
ETH_Config_T ETH_InitStructure;
/** lwip network interface structure for ethernetif */
extern struct netif UserNetif;
/** Configure the GPIO ports for ethernet pins */
static void ConfigEthernetGPIO(void);
/** Configure the Ethernet MAC/DMA */
static void ConfigEthernetMACDMA(void);
/** Ethernet Reset Delay */
static void EthResetDelay(__IO uint32_t count);
/*!
* @brief configurate Ethernet.
*
* @param None
*
* @retval None
*
* @note
*/
void ConfigEthernet(void)
{
/** Configure the GPIO ports for ethernet pins */
ConfigEthernetGPIO();
/** Configure the Ethernet MAC/DMA */
ConfigEthernetMACDMA();
}
/*!
* @brief configurate Ethernet Interface.
*
* @param None
*
* @retval None
*
* @note
*/
static void ConfigEthernetMACDMA(void)
{
/** Enable ETHERNET clock */
RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_ETH_MAC | RCM_AHB1_PERIPH_ETH_MAC_Tx |
RCM_AHB1_PERIPH_ETH_MAC_Rx);
/** Reset ETH on AHB Bus */
ETH_Reset();
/** Software reset */
ETH_SoftwareReset();
/** Wait for software reset */
while(ETH_ReadSoftwareReset() == SET);
/** ETH Config Struct */
ETH_ConfigStructInit(Ð_InitStructure);
/** ETH Config MAC */
/**
*ETH_InitStructure.autoNegotiation = ETH_AUTONEGOTIATION_DISABLE;
*ETH_InitStructure.speed = ETH_SPEED_100M;
*ETH_InitStructure.mode = ETH_MODE_FULLDUPLEX;
*/
ETH_InitStructure.autoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
ETH_InitStructure.loopbackMode = ETH_LOOPBACKMODE_DISABLE;
ETH_InitStructure.retryTransmission = ETH_RETRYTRANSMISSION_DISABLE;
ETH_InitStructure.automaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE;
ETH_InitStructure.receiveAll = ETH_RECEIVEAll_DISABLE;
ETH_InitStructure.broadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_ENABLE;
ETH_InitStructure.promiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE;
ETH_InitStructure.multicastFramesFilter = ETH_MULTICASTFRAMESFILTER_PERFECT;
ETH_InitStructure.unicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT;
#ifdef HARDWARE_CHECKSUM
ETH_InitStructure.checksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE;
#endif
/** ETH Config DMA */
ETH_InitStructure.dropTCPIPChecksumErrorFrame = ETH_DROPTCPIPCHECKSUMERRORFRAME_ENABLE;
ETH_InitStructure.receiveStoreForward = ETH_RECEIVESTOREFORWARD_ENABLE;
ETH_InitStructure.flushReceivedFrame = ETH_FLUSHRECEIVEDFRAME_DISABLE;
ETH_InitStructure.transmitStoreForward = ETH_TRANSMITSTOREFORWARD_ENABLE;
ETH_InitStructure.forwardErrorFrames = ETH_FORWARDERRORFRAMES_DISABLE;
ETH_InitStructure.forwardUndersizedGoodFrames = ETH_FORWARDUNDERSIZEDGOODFRAMES_DISABLE;
ETH_InitStructure.secondFrameOperate = ETH_SECONDFRAMEOPERARTE_ENABLE;
ETH_InitStructure.addressAlignedBeats = ETH_ADDRESSALIGNEDBEATS_ENABLE;
ETH_InitStructure.fixedBurst = ETH_FIXEDBURST_ENABLE;
ETH_InitStructure.rxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT;
ETH_InitStructure.txDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT;
ETH_InitStructure.DMAArbitration = ETH_DMAARBITRATION_ROUNDROBIN_RXTX_2_1;
/** Configure Ethernet */
ETH_Config(Ð_InitStructure, LAN8720A_PHY_ADDRESS);
}
/*!
* @brief configurate Ethernet GPIO.
*
* @param None
*
* @retval None
*
* @note
*/
void ConfigEthernetGPIO(void)
{
GPIO_Config_T configStruct;
/**
* ETH_RESET# PD11
* ETH_MDIO PA2
* ETH_MDC PC1
*/
/** Enable GPIOs clocks */
RCM_EnableAHB1PeriphClock(ETH_MDC_GPIO_CLK | ETH_MDIO_GPIO_CLK |
ETH_RESET_GPIO_CLK);
/** Enable SYSCFG clock */
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SYSCFG);
/** Configure ETH_RESET# */
GPIO_ConfigStructInit(&configStruct);
configStruct.pin = ETH_RESET_PIN;
configStruct.speed = GPIO_SPEED_100MHz;
configStruct.mode = GPIO_MODE_OUT;
configStruct.otype = GPIO_OTYPE_PP;
configStruct.pupd = GPIO_PUPD_NOPULL;
GPIO_Config(ETH_RESET_PORT, &configStruct);
/** Configure ETH_MDC */
configStruct.pin = ETH_MDC_PIN;
configStruct.mode = GPIO_MODE_AF;
GPIO_Config(ETH_MDC_PORT, &configStruct);
GPIO_ConfigPinAF(ETH_MDC_PORT, ETH_MDC_SOURCE, ETH_MDC_AF);
/** Configure ETH_MDIO */
configStruct.pin = ETH_MDIO_PIN;
GPIO_Config(ETH_MDIO_PORT, &configStruct);
GPIO_ConfigPinAF(ETH_MDIO_PORT, ETH_MDIO_SOURCE, ETH_MDIO_AF);
/** RESET ETH PHY */
ETH_RESET_PIN_LOW();
EthResetDelay(LAN8720A_RESET_DELAY);
ETH_RESET_PIN_HIGH();
EthResetDelay(LAN8720A_RESET_DELAY);
/** if BOARD_LAN8720A.h define MII_MODE, this function configurate MII_MODE */
#ifdef MII_MODE /** Mode MII */
#elif defined RMII_MODE /** Mode RMII */
/**
* ETH_RMII_REF_CLK PA1
* ETH_RMII_CRS_DV PA7
* ETH_RMII_RXD0 PC4
* ETH_RMII_RXD1 PC5
* ETH_RMII_TX_EN PB11
* ETH_RMII_TXD0 PB12
* ETH_RMII_TXD1 PB13
*/
/** Enable GPIOs clocks */
RCM_EnableAHB1PeriphClock(ETH_RMII_REF_CLK_GPIO_CLK | ETH_RMII_CRS_DV_GPIO_CLK |
ETH_RMII_RXD0_GPIO_CLK | ETH_RMII_RXD1_GPIO_CLK |
ETH_RMII_TX_EN_GPIO_CLK | ETH_RMII_TXD0_GPIO_CLK |
ETH_RMII_TXD1_GPIO_CLK);
/** Configure ETH_RMII_REF_CLK */
configStruct.pin = ETH_RMII_REF_CLK_PIN;
configStruct.mode = GPIO_MODE_AF;
configStruct.speed = GPIO_SPEED_100MHz;
GPIO_Config(ETH_RMII_REF_CLK_PORT, &configStruct);
GPIO_ConfigPinAF(ETH_RMII_REF_CLK_PORT, ETH_RMII_REF_CLK_SOURCE, ETH_RMII_REF_CLK_AF);
/** Configure ETH_RMII_CRS_DV */
configStruct.pin = ETH_RMII_CRS_DV_PIN;
GPIO_Config(ETH_RMII_CRS_DV_PORT, &configStruct);
GPIO_ConfigPinAF(ETH_RMII_CRS_DV_PORT, ETH_RMII_CRS_DV_SOURCE, ETH_RMII_CRS_DV_AF);
/** Configure ETH_RMII_RXD0 */
configStruct.pin = ETH_RMII_RXD0_PIN;
GPIO_Config(ETH_RMII_RXD0_PORT, &configStruct);
GPIO_ConfigPinAF(ETH_RMII_RXD0_PORT, ETH_RMII_RXD0_SOURCE, ETH_RMII_RXD0_AF);
/** Configure ETH_RMII_RXD1 */
configStruct.pin = ETH_RMII_RXD1_PIN;
GPIO_Config(ETH_RMII_RXD1_PORT, &configStruct);
GPIO_ConfigPinAF(ETH_RMII_RXD1_PORT, ETH_RMII_RXD1_SOURCE, ETH_RMII_RXD1_AF);
/** Configure ETH_RMII_TX_EN */
configStruct.pin = ETH_RMII_TX_EN_PIN;
GPIO_Config(ETH_RMII_TX_EN_PORT, &configStruct);
GPIO_ConfigPinAF(ETH_RMII_TX_EN_PORT, ETH_RMII_TX_EN_SOURCE, ETH_RMII_TX_EN_AF);
/** Configure ETH_RMII_TXD0 */
configStruct.pin = ETH_RMII_TXD0_PIN;
GPIO_Config(ETH_RMII_TXD0_PORT, &configStruct);
GPIO_ConfigPinAF(ETH_RMII_TXD0_PORT, ETH_RMII_TXD0_SOURCE, ETH_RMII_TXD0_AF);
/** Configure ETH_RMII_TXD1 */
configStruct.pin = ETH_RMII_TXD1_PIN;
GPIO_Config(ETH_RMII_TXD1_PORT, &configStruct);
GPIO_ConfigPinAF(ETH_RMII_TXD1_PORT, ETH_RMII_TXD1_SOURCE, ETH_RMII_TXD1_AF);
SYSCFG_ConfigMediaInterface(SYSCFG_INTERFACE_RMII);
#endif
}
/*!
* @brief Ethernet Reset Delay.
*
* @param count Reset Delay Time
*
* @retval None
*
* @note
*/
void EthResetDelay(__IO uint32_t count)
{
__IO uint32_t i = 0;
for(i = count; i!= 0; i--)
{
}
}
头文件如下:
#ifndef __BOARD_LAN8720A_H
#define __BOARD_LAN8720A_H
#ifdef __cplusplus
extern "C" {
#endif
#include "apm32f4xx_eth.h"
//#include "netif.h"
#include "lwip/netif.h"
/** LAN8720A_PHY_ADDRESS */
#define LAN8720A_PHY_ADDRESS 0x00
/** MII and RMII mode selection */
#if defined (APM32F407_MINI)
#define RMII_MODE
#elif defined (APM32F407_ELE_HUETB)
#define MII_MODE
#elif defined (APM32F407_EVAL)
#define RMII_MODE
#else
#error "Please select first the APM32 board to be used (in board.h)"
#endif
/** Reset delay */
#define LAN8720A_RESET_DELAY PHY_RESET_DELAY
/** define LAN8720A GPIO */
#ifdef MII_MODE
#elif defined RMII_MODE
/**
* ETH_RMII_REF_CLK PA1
* ETH_RMII_CRS_DV PA7
* ETH_RMII_RXD0 PC4
* ETH_RMII_RXD1 PC5
* ETH_RMII_TX_EN PG11
* ETH_RMII_TXD0 PG13
* ETH_RMII_TXD1 PG14
*/
/** ETH_RMII_REF_CLK PA1 */
#define ETH_RMII_REF_CLK_GPIO_CLK RCM_AHB1_PERIPH_GPIOA
#define ETH_RMII_REF_CLK_PORT GPIOA
#define ETH_RMII_REF_CLK_PIN GPIO_PIN_1
#define ETH_RMII_REF_CLK_AF GPIO_AF_ETH
#define ETH_RMII_REF_CLK_SOURCE GPIO_PIN_SOURCE_1
/** ETH_RMII_CRS_DV PA7 */
#define ETH_RMII_CRS_DV_GPIO_CLK RCM_AHB1_PERIPH_GPIOA
#define ETH_RMII_CRS_DV_PORT GPIOA
#define ETH_RMII_CRS_DV_PIN GPIO_PIN_7
#define ETH_RMII_CRS_DV_AF GPIO_AF_ETH
#define ETH_RMII_CRS_DV_SOURCE GPIO_PIN_SOURCE_7
/** ETH_RMII_RXD0 PC4 */
#define ETH_RMII_RXD0_GPIO_CLK RCM_AHB1_PERIPH_GPIOC
#define ETH_RMII_RXD0_PORT GPIOC
#define ETH_RMII_RXD0_PIN GPIO_PIN_4
#define ETH_RMII_RXD0_AF GPIO_AF_ETH
#define ETH_RMII_RXD0_SOURCE GPIO_PIN_SOURCE_4
/** ETH_RMII_RXD1 PC5 */
#define ETH_RMII_RXD1_GPIO_CLK RCM_AHB1_PERIPH_GPIOC
#define ETH_RMII_RXD1_PORT GPIOC
#define ETH_RMII_RXD1_PIN GPIO_PIN_5
#define ETH_RMII_RXD1_AF GPIO_AF_ETH
#define ETH_RMII_RXD1_SOURCE GPIO_PIN_SOURCE_5
/** ETH_RMII_TX_EN PG11 */
#define ETH_RMII_TX_EN_GPIO_CLK RCM_AHB1_PERIPH_GPIOG
#define ETH_RMII_TX_EN_PORT GPIOG
#define ETH_RMII_TX_EN_PIN GPIO_PIN_11
#define ETH_RMII_TX_EN_AF GPIO_AF_ETH
#define ETH_RMII_TX_EN_SOURCE GPIO_PIN_SOURCE_11
/** ETH_RMII_TXD0 PG13 */
#define ETH_RMII_TXD0_GPIO_CLK RCM_AHB1_PERIPH_GPIOG
#define ETH_RMII_TXD0_PORT GPIOG
#define ETH_RMII_TXD0_PIN GPIO_PIN_13
#define ETH_RMII_TXD0_AF GPIO_AF_ETH
#define ETH_RMII_TXD0_SOURCE GPIO_PIN_SOURCE_13
/** ETH_RMII_TXD1 PG14 */
#define ETH_RMII_TXD1_GPIO_CLK RCM_AHB1_PERIPH_GPIOG
#define ETH_RMII_TXD1_PORT GPIOG
#define ETH_RMII_TXD1_PIN GPIO_PIN_14
#define ETH_RMII_TXD1_AF GPIO_AF_ETH
#define ETH_RMII_TXD1_SOURCE GPIO_PIN_SOURCE_14
#endif
/**
* ETH_RESET# PD11
* ETH_MDIO PA2
* ETH_MDC PC1
*/
/** ETH_RESET# PD3 */
#define ETH_RESET_GPIO_CLK RCM_AHB1_PERIPH_GPIOD
#define ETH_RESET_PORT GPIOD
#define ETH_RESET_PIN GPIO_PIN_11
#define ETH_RESET_PIN_HIGH() GPIO_SetBit(ETH_RESET_PORT,ETH_RESET_PIN)
#define ETH_RESET_PIN_LOW() GPIO_ResetBit(ETH_RESET_PORT,ETH_RESET_PIN)
/** ETH_MII_MDC PC1 */
#define ETH_MDC_GPIO_CLK RCM_AHB1_PERIPH_GPIOC
#define ETH_MDC_PORT GPIOC
#define ETH_MDC_PIN GPIO_PIN_1
#define ETH_MDC_AF GPIO_AF_ETH
#define ETH_MDC_SOURCE GPIO_PIN_SOURCE_1
/** ETH_MII_MDIO PA2 */
#define ETH_MDIO_GPIO_CLK RCM_AHB1_PERIPH_GPIOA
#define ETH_MDIO_PORT GPIOA
#define ETH_MDIO_PIN GPIO_PIN_2
#define ETH_MDIO_AF GPIO_AF_ETH
#define ETH_MDIO_SOURCE GPIO_PIN_SOURCE_2
void ConfigEthernet(void);
#ifdef __cplusplus
}
#endif
#endif /** __BOARD_LAN8720A_H */
用此两个文件添加到ETH历程中,加入到工程,据可以成功运行了!
|