添加PHY芯片驱动代码
我用的板子的PHY为LAN8720A,需要注意:我的PHY芯片是额外加的25MHZ的晶振,当然你也可以用芯片PA8引脚输出25MHZ的时钟,但需要添加PA8引脚作为MC0时钟输出。这个代码下面添加以太网中断的处理函数,驱动代码如下图所示:
#include "drv_ethernet.h"
#include "gd32f4xx_enet.h"
#include "sysytic.h"
static __IO uint32_t enet_init_status = 0;
enum
{
ETH_SUCCES=0,
ETH_ERROR
};
/* ENET RxDMA/TxDMA descriptor */
extern enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM], txdesc_tab[ENET_TXBUF_NUM];
/* ENET receive buffer */
extern uint8_t *rx_buff; //rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE];
/* ENET transmit buffer */
extern uint8_t *tx_buff; //tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE];
/*global transmit and receive descriptors pointers */
extern enet_descriptors_struct *dma_current_txdesc;
extern enet_descriptors_struct *dma_current_rxdesc;
uint8_t ETH_MACDMA_Config(void);
static void nvic_configuration(void);
/* 初始化ETH MAC层及DMA配置
返回值:ETH_ERROR 发送失败(0);ETH_SUCCESS,发送成功(1) */
uint8_t ETH_MACDMA_Config(void)
{
rcu_periph_clock_enable(RCU_ENET);
rcu_periph_clock_enable(RCU_ENETTX);
rcu_periph_clock_enable(RCU_ENETRX);
enet_deinit();/*AHB总线重启以太网*/
enet_software_reset(); /*软件重启网络*/
/*改为自动、强制模式切换*/
/*通过硬件计算和验证 IP、UDP、TCP 和 ICMP 校验和*/
enet_init_status = enet_init(ENET_AUTO_NEGOTIATION, ENET_AUTOCHECKSUM_DROP_FAILFRAMES, ENET_BROADCAST_FRAMES_PASS); /*不使用MAC地址过滤*/
if(SUCCESS == enet_init_status)
{
enet_interrupt_enable(ENET_DMA_INT_NIE);
enet_interrupt_enable(ENET_DMA_INT_RIE);
return ETH_SUCCES;
}
else
{
return ETH_ERROR;
}
}
/*!
\brief configures the nested vectored interrupt controller
\param[in] none
\param[out] none
\retval none
*/
static void nvic_configuration(void)
{
nvic_vector_table_set(NVIC_VECTTAB_FLASH, 0x0);
nvic_irq_enable(ENET_IRQn, 2, 0);
}
/* LAN8720初始化
返回值:0,成功;
其他,失败 */
uint8_t LAN8720_Init(void)
{
nvic_configuration();
uint8_t rval = ETH_ERROR;
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_GPIOC);
rcu_periph_clock_enable(RCU_GPIOD);
rcu_periph_clock_enable(RCU_GPIOG);
rcu_periph_clock_enable(RCU_GPIOH);
rcu_periph_clock_enable(RCU_GPIOI);
rcu_periph_clock_enable(RCU_SYSCFG);
/* choose DIV2 to get 50MHz from 200MHz on CKOUT0 pin (PA8) to clock the PHY */
// rcu_ckout0_config(RCU_CKOUT0SRC_PLLP, RCU_CKOUT0_DIV4);
syscfg_enet_phy_interface_config(SYSCFG_ENET_PHY_RMII);
/*复位引脚*/
gpio_af_set(GPIOC, GPIO_AF_0, GPIO_PIN_0);
gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_PIN_0);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_0);
/* PA1: ETH_RMII_REF_CLK */
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_1);
/* PA2: ETH_MDIO */
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_2);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_2);
/* PA7: ETH_RMII_CRS_DV */
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_7);
gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_1);
gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_2);
gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_7);
/* PB11: ETH_RMII_TX_EN */
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_11);
/* PB12: ETH_RMII_TXD0 */
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_12);
/* PB13: ETH_RMII_TXD1 */
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_13);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_13);
gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_11);
gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_12);
gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_13);
/* PC1: ETH_MDC */
gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_1);
/* PC4: ETH_RMII_RXD0 */
gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_4);
/* PC5: ETH_RMII_RXD1 */
gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_5);
gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_1);
gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_4);
gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_5);
LAN8720_RST(0); /*硬件复位LAN8720*/
delay_ms(50);
LAN8720_RST(1); /*硬件复位结束*/
rval = ETH_MACDMA_Config();/*配置MAC及DMA*/
return rval;
}
extern void lwip_pkt_handle(void); //在lwip_comm.c里面定义
/*!
\brief this function handles ethernet interrupt request
\param[in] none
\param[out] none
\retval none
*/
void ENET_IRQHandler(void)
{
uint32_t reval;
/* clear the enet DMA Rx interrupt pending bits */
enet_interrupt_flag_clear(ENET_DMA_INT_FLAG_RS_CLR);
enet_interrupt_flag_clear(ENET_DMA_INT_FLAG_NI_CLR);
/* handles all the received frames */
do {
reval = enet_rxframe_size_get();
if(reval > 1) {
lwip_pkt_handle();
}
} while(reval != 0);
}
|