[bsp][stm32] update drv_eth

This commit is contained in:
SummerGift 2018-12-26 10:17:11 +08:00
parent a80b272048
commit 7279078005
3 changed files with 189 additions and 90 deletions

View File

@ -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']

View File

@ -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;
}

View File

@ -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__ */