[bsp][stm32] update drv_eth
This commit is contained in:
parent
a80b272048
commit
7279078005
|
@ -33,7 +33,7 @@ if GetDepend(['RT_USING_I2C', 'RT_USING_I2C_BITOPS']):
|
|||
src += ['drv_soft_i2c.c']
|
||||
|
||||
if GetDepend('RT_USING_LWIP'):
|
||||
src += ['drv_emac.c']
|
||||
src += ['drv_eth.c']
|
||||
|
||||
if GetDepend(['RT_USING_ADC']):
|
||||
src += Glob('drv_adc.c')
|
||||
|
@ -44,6 +44,9 @@ if GetDepend('BSP_USING_SDRAM'):
|
|||
if GetDepend('BSP_USING_ONCHIP_RTC'):
|
||||
src += ['drv_rtc.c']
|
||||
|
||||
if GetDepend(['BSP_USING_ON_CHIP_FLASH', 'SOC_SERIES_STM32F0']):
|
||||
src += ['drv_flash/drv_flash_f0.c']
|
||||
|
||||
if GetDepend(['BSP_USING_ON_CHIP_FLASH', 'SOC_SERIES_STM32F1']):
|
||||
src += ['drv_flash/drv_flash_f1.c']
|
||||
|
||||
|
|
|
@ -6,12 +6,14 @@
|
|||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-11-19 SummerGift first version
|
||||
* 2018-12-25 zylx fix some bugs
|
||||
*/
|
||||
|
||||
#include "board.h"
|
||||
#include "drv_config.h"
|
||||
#include <netif/ethernetif.h>
|
||||
#include "lwipopts.h"
|
||||
#include "drv_eth.h"
|
||||
|
||||
/*
|
||||
* Emac driver uses CubeMX tool to generate emac and phy's configuration,
|
||||
|
@ -32,11 +34,12 @@ struct rt_stm32_eth
|
|||
/* inherit from ethernet device */
|
||||
struct eth_device parent;
|
||||
|
||||
/* interface address info. */
|
||||
rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* hw address */
|
||||
|
||||
uint32_t ETH_Speed; /*!< @ref ETH_Speed */
|
||||
uint32_t ETH_Mode; /*!< @ref ETH_Duplex_Mode */
|
||||
/* interface address info, hw address */
|
||||
rt_uint8_t dev_addr[MAX_ADDR_LEN];
|
||||
/* ETH_Speed */
|
||||
uint32_t ETH_Speed;
|
||||
/* ETH_Duplex_Mode */
|
||||
uint32_t ETH_Mode;
|
||||
};
|
||||
|
||||
static ETH_DMADescTypeDef *DMARxDscrTab, *DMATxDscrTab;
|
||||
|
@ -80,7 +83,7 @@ static rt_err_t rt_stm32_eth_init(rt_device_t dev)
|
|||
|
||||
phy_reset();
|
||||
|
||||
/* ETHERNET Configuration --------------------------------------------------*/
|
||||
/* ETHERNET Configuration */
|
||||
EthHandle.Instance = ETH;
|
||||
EthHandle.Init.MACAddr = (rt_uint8_t *)&stm32_eth_device.dev_addr[0];
|
||||
EthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
|
||||
|
@ -89,8 +92,6 @@ static rt_err_t rt_stm32_eth_init(rt_device_t dev)
|
|||
EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
|
||||
EthHandle.Init.RxMode = ETH_RXINTERRUPT_MODE;
|
||||
EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE;
|
||||
//EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
|
||||
EthHandle.Init.PhyAddress = EXTERNAL_PHY_ADDRESS;
|
||||
|
||||
HAL_ETH_DeInit(&EthHandle);
|
||||
|
||||
|
@ -101,7 +102,8 @@ static rt_err_t rt_stm32_eth_init(rt_device_t dev)
|
|||
}
|
||||
else
|
||||
{
|
||||
LOG_D("emac hardware init faild");
|
||||
LOG_E("emac hardware init faild");
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
/* Initialize Tx Descriptors list: Chain Mode */
|
||||
|
@ -110,6 +112,10 @@ static rt_err_t rt_stm32_eth_init(rt_device_t dev)
|
|||
/* Initialize Rx Descriptors list: Chain Mode */
|
||||
HAL_ETH_DMARxDescListInit(&EthHandle, DMARxDscrTab, Rx_Buff, ETH_RXBUFNB);
|
||||
|
||||
/* ETH interrupt Init */
|
||||
HAL_NVIC_SetPriority(ETH_IRQn, 0x07, 0);
|
||||
HAL_NVIC_EnableIRQ(ETH_IRQn);
|
||||
|
||||
/* Enable MAC and DMA transmission and reception */
|
||||
if (HAL_ETH_Start(&EthHandle) == HAL_OK)
|
||||
{
|
||||
|
@ -117,13 +123,10 @@ static rt_err_t rt_stm32_eth_init(rt_device_t dev)
|
|||
}
|
||||
else
|
||||
{
|
||||
LOG_D("emac hardware start faild");
|
||||
LOG_E("emac hardware start faild");
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
/* ETH interrupt Init */
|
||||
HAL_NVIC_SetPriority(ETH_IRQn, 0x07, 0);
|
||||
HAL_NVIC_EnableIRQ(ETH_IRQn);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
|
@ -209,7 +212,7 @@ rt_err_t rt_stm32_eth_tx( rt_device_t dev, struct pbuf* p)
|
|||
/* Is this buffer available? If not, goto error */
|
||||
if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET)
|
||||
{
|
||||
LOG_D("buffer not valid");
|
||||
LOG_E("buffer not valid");
|
||||
ret = ERR_USE;
|
||||
goto error;
|
||||
}
|
||||
|
@ -230,7 +233,7 @@ rt_err_t rt_stm32_eth_tx( rt_device_t dev, struct pbuf* p)
|
|||
/* Check if the buffer is available */
|
||||
if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET)
|
||||
{
|
||||
LOG_D("dma tx desc buffer is not valid");
|
||||
LOG_E("dma tx desc buffer is not valid");
|
||||
ret = ERR_USE;
|
||||
goto error;
|
||||
}
|
||||
|
@ -261,7 +264,7 @@ rt_err_t rt_stm32_eth_tx( rt_device_t dev, struct pbuf* p)
|
|||
state = HAL_ETH_TransmitFrame(&EthHandle, framelength);
|
||||
if (state != HAL_OK)
|
||||
{
|
||||
LOG_D("eth transmit frame faild: %d", state);
|
||||
LOG_E("eth transmit frame faild: %d", state);
|
||||
}
|
||||
|
||||
ret = ERR_OK;
|
||||
|
@ -400,29 +403,29 @@ void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
|
|||
rt_err_t result;
|
||||
result = eth_device_ready(&(stm32_eth_device.parent));
|
||||
if (result != RT_EOK)
|
||||
LOG_D("RX err = %d", result );
|
||||
LOG_E("RX err = %d", result);
|
||||
}
|
||||
|
||||
void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
LOG_D("eth err");
|
||||
LOG_E("eth err");
|
||||
}
|
||||
|
||||
/* PHY: LAN8720 */
|
||||
static uint8_t phy_speed = 0;
|
||||
#define PHY_LINK_MASK (1<<0)
|
||||
#define PHY_100M_MASK (1<<1)
|
||||
#define PHY_DUPLEX_MASK (1<<2)
|
||||
static void phy_monitor_thread_entry(void *parameter)
|
||||
{
|
||||
uint8_t phy_addr = 0xFF;
|
||||
uint8_t phy_speed_new = 0;
|
||||
rt_uint32_t status = 0;
|
||||
|
||||
/* phy search */
|
||||
rt_uint32_t i, temp;
|
||||
for (i = 0; i <= 0x1F; i++)
|
||||
{
|
||||
HAL_ETH_ReadPHYRegister(&EthHandle, 0x02, (uint32_t *)&temp);
|
||||
EthHandle.Init.PhyAddress = i;
|
||||
|
||||
HAL_ETH_ReadPHYRegister(&EthHandle, PHY_ID1_REG, (uint32_t *)&temp);
|
||||
|
||||
if (temp != 0xFFFF)
|
||||
{
|
||||
|
@ -433,7 +436,7 @@ static void phy_monitor_thread_entry(void *parameter)
|
|||
|
||||
if (phy_addr == 0xFF)
|
||||
{
|
||||
LOG_D("phy not probe!\r\n");
|
||||
LOG_E("phy not probe!\r\n");
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
@ -443,36 +446,38 @@ static void phy_monitor_thread_entry(void *parameter)
|
|||
|
||||
/* RESET PHY */
|
||||
LOG_D("RESET PHY!");
|
||||
HAL_ETH_WritePHYRegister(&EthHandle, PHY_BCR, PHY_RESET);
|
||||
rt_thread_delay(RT_TICK_PER_SECOND * 2);
|
||||
HAL_ETH_WritePHYRegister(&EthHandle, PHY_BCR, PHY_AUTONEGOTIATION);
|
||||
HAL_ETH_WritePHYRegister(&EthHandle, PHY_BASIC_CONTROL_REG, PHY_RESET_MASK);
|
||||
rt_thread_mdelay(2000);
|
||||
HAL_ETH_WritePHYRegister(&EthHandle, PHY_BASIC_CONTROL_REG, PHY_AUTO_NEGOTIATION_MASK);
|
||||
|
||||
while (1)
|
||||
{
|
||||
rt_uint32_t status;
|
||||
HAL_ETH_ReadPHYRegister(&EthHandle, PHY_BSR, (uint32_t *)&status);
|
||||
LOG_D("LAN8720 status:0x%04X\r\n", status);
|
||||
HAL_ETH_ReadPHYRegister(&EthHandle, PHY_BASIC_STATUS_REG, (uint32_t *)&status);
|
||||
LOG_D("PHY BASIC STATUS REG:0x%04X\r\n", status);
|
||||
|
||||
phy_speed_new = 0;
|
||||
|
||||
if(status & (PHY_AUTONEGO_COMPLETE | PHY_LINKED_STATUS))
|
||||
if (status & (PHY_AUTONEGO_COMPLETE_MASK | PHY_LINKED_STATUS_MASK))
|
||||
{
|
||||
rt_uint32_t SR;
|
||||
|
||||
SR = HAL_ETH_ReadPHYRegister(&EthHandle, 31, (uint32_t *)&SR);
|
||||
LOG_D("LAN8720 REG 31:0x%04X ", SR);
|
||||
|
||||
SR = (SR >> 2) & 0x07; /* LAN8720, REG31[4:2], Speed Indication. */
|
||||
phy_speed_new = PHY_LINK_MASK;
|
||||
|
||||
if((SR & 0x03) == 2)
|
||||
SR = HAL_ETH_ReadPHYRegister(&EthHandle, PHY_Status_REG, (uint32_t *)&SR);
|
||||
LOG_D("PHY Control/Status REG:0x%04X ", SR);
|
||||
|
||||
if (SR & PHY_100M_MASK)
|
||||
{
|
||||
phy_speed_new |= PHY_100M_MASK;
|
||||
}
|
||||
|
||||
if(SR & 0x04)
|
||||
else if (SR & PHY_10M_MASK)
|
||||
{
|
||||
phy_speed_new |= PHY_DUPLEX_MASK;
|
||||
phy_speed_new |= PHY_10M_MASK;
|
||||
}
|
||||
|
||||
if (SR & PHY_FULL_DUPLEX_MASK)
|
||||
{
|
||||
phy_speed_new |= PHY_FULL_DUPLEX_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -494,7 +499,7 @@ static void phy_monitor_thread_entry(void *parameter)
|
|||
LOG_D("10Mbps");
|
||||
}
|
||||
|
||||
if(phy_speed_new & PHY_DUPLEX_MASK)
|
||||
if (phy_speed_new & PHY_FULL_DUPLEX_MASK)
|
||||
{
|
||||
LOG_D("full-duplex");
|
||||
stm32_eth_device.ETH_Mode = ETH_MODE_FULLDUPLEX;
|
||||
|
@ -504,14 +509,20 @@ static void phy_monitor_thread_entry(void *parameter)
|
|||
LOG_D("half-duplex");
|
||||
stm32_eth_device.ETH_Mode = ETH_MODE_HALFDUPLEX;
|
||||
}
|
||||
rt_stm32_eth_init((rt_device_t)&stm32_eth_device);
|
||||
|
||||
if (rt_stm32_eth_init((rt_device_t)&stm32_eth_device) != RT_EOK)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* send link up. */
|
||||
eth_device_linkchange(&stm32_eth_device.parent, RT_TRUE);
|
||||
}
|
||||
} /* link up. */
|
||||
else
|
||||
{
|
||||
LOG_D("link down\r\n");
|
||||
LOG_I("link down\r\n");
|
||||
/* send link down. */
|
||||
eth_device_linkchange(&stm32_eth_device.parent, RT_FALSE);
|
||||
}
|
||||
|
@ -525,33 +536,41 @@ static void phy_monitor_thread_entry(void *parameter)
|
|||
/* Register the EMAC device */
|
||||
static int rt_hw_stm32_eth_init(void)
|
||||
{
|
||||
rt_err_t state = RT_EOK;
|
||||
|
||||
/* Prepare receive and send buffers */
|
||||
Rx_Buff = (rt_uint8_t *)rt_calloc(ETH_RXBUFNB, ETH_MAX_PACKET_SIZE);
|
||||
if (Rx_Buff == RT_NULL)
|
||||
{
|
||||
LOG_E("No memory");
|
||||
state = RT_ENOMEM;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
Tx_Buff = (rt_uint8_t *)rt_calloc(ETH_TXBUFNB, ETH_MAX_PACKET_SIZE);
|
||||
if (Rx_Buff == RT_NULL)
|
||||
{
|
||||
LOG_E("No memory");
|
||||
state = RT_ENOMEM;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
DMARxDscrTab = (ETH_DMADescTypeDef *)rt_calloc(ETH_RXBUFNB, sizeof(ETH_DMADescTypeDef));
|
||||
if (DMARxDscrTab == RT_NULL)
|
||||
{
|
||||
LOG_E("No memory");
|
||||
state = RT_ENOMEM;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
DMATxDscrTab = (ETH_DMADescTypeDef *)rt_calloc(ETH_TXBUFNB, sizeof(ETH_DMADescTypeDef));
|
||||
if (DMATxDscrTab == RT_NULL)
|
||||
{
|
||||
LOG_E("No memory");
|
||||
state = RT_ENOMEM;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
rt_err_t state;
|
||||
|
||||
stm32_eth_device.ETH_Speed = ETH_SPEED_100M;
|
||||
stm32_eth_device.ETH_Mode = ETH_MODE_FULLDUPLEX;
|
||||
|
||||
|
@ -587,7 +606,8 @@ static int rt_hw_stm32_eth_init(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
LOG_D("emac device init faild: %d", state);
|
||||
LOG_E("emac device init faild: %d", state);
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
/* start phy monitor */
|
||||
|
@ -602,6 +622,29 @@ static int rt_hw_stm32_eth_init(void)
|
|||
{
|
||||
rt_thread_startup(tid);
|
||||
}
|
||||
__exit:
|
||||
if (state != RT_EOK)
|
||||
{
|
||||
if (Rx_Buff)
|
||||
{
|
||||
rt_free(Rx_Buff);
|
||||
}
|
||||
|
||||
if (Tx_Buff)
|
||||
{
|
||||
rt_free(Tx_Buff);
|
||||
}
|
||||
|
||||
if (DMARxDscrTab)
|
||||
{
|
||||
rt_free(DMARxDscrTab);
|
||||
}
|
||||
|
||||
if (DMATxDscrTab)
|
||||
{
|
||||
rt_free(DMATxDscrTab);
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-12-25 zylx first version
|
||||
*/
|
||||
|
||||
#ifndef __DRV_ETH_H__
|
||||
#define __DRV_ETH_H__
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <rthw.h>
|
||||
#include <rtdevice.h>
|
||||
#include <board.h>
|
||||
|
||||
/* The PHY basic control register */
|
||||
#define PHY_BASIC_CONTROL_REG 0x00U
|
||||
#define PHY_RESET_MASK (1<<15)
|
||||
#define PHY_AUTO_NEGOTIATION_MASK (1<<12)
|
||||
|
||||
/* The PHY basic status register */
|
||||
#define PHY_BASIC_STATUS_REG 0x01U
|
||||
#define PHY_LINKED_STATUS_MASK (1<<2)
|
||||
#define PHY_AUTONEGO_COMPLETE_MASK (1<<5)
|
||||
|
||||
/* The PHY ID one register */
|
||||
#define PHY_ID1_REG 0x02U
|
||||
|
||||
/* The PHY ID two register */
|
||||
#define PHY_ID2_REG 0x03U
|
||||
|
||||
/* The PHY auto-negotiate advertise register */
|
||||
#define PHY_AUTONEG_ADVERTISE_REG 0x04U
|
||||
|
||||
#ifdef PHY_USING_LAN8720A
|
||||
/* The PHY interrupt source flag register. */
|
||||
#define PHY_INTERRUPT_FLAG_REG 0x1DU
|
||||
/* The PHY interrupt mask register. */
|
||||
#define PHY_INTERRUPT_MSAK_REG 0x1EU
|
||||
#define PHY_LINK_DOWN_MASK (1<<4)
|
||||
#define PHY_AUTO_NEGO_COMPLETE_MASK (1<<6)
|
||||
|
||||
/* The PHY status register. */
|
||||
#define PHY_Status_REG 0x1FU
|
||||
#define PHY_10M_MASK (1<<2)
|
||||
#define PHY_100M_MASK (1<<3)
|
||||
#define PHY_FULL_DUPLEX_MASK (1<<4)
|
||||
#endif /* PHY_USING_LAN8720A */
|
||||
|
||||
#endif /* __DRV_ETH_H__ */
|
Loading…
Reference in New Issue