[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']
|
src += ['drv_soft_i2c.c']
|
||||||
|
|
||||||
if GetDepend('RT_USING_LWIP'):
|
if GetDepend('RT_USING_LWIP'):
|
||||||
src += ['drv_emac.c']
|
src += ['drv_eth.c']
|
||||||
|
|
||||||
if GetDepend(['RT_USING_ADC']):
|
if GetDepend(['RT_USING_ADC']):
|
||||||
src += Glob('drv_adc.c')
|
src += Glob('drv_adc.c')
|
||||||
|
@ -43,13 +43,16 @@ if GetDepend('BSP_USING_SDRAM'):
|
||||||
|
|
||||||
if GetDepend('BSP_USING_ONCHIP_RTC'):
|
if GetDepend('BSP_USING_ONCHIP_RTC'):
|
||||||
src += ['drv_rtc.c']
|
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']):
|
if GetDepend(['BSP_USING_ON_CHIP_FLASH', 'SOC_SERIES_STM32F1']):
|
||||||
src += ['drv_flash/drv_flash_f1.c']
|
src += ['drv_flash/drv_flash_f1.c']
|
||||||
|
|
||||||
if GetDepend(['BSP_USING_ON_CHIP_FLASH', 'SOC_SERIES_STM32F4']):
|
if GetDepend(['BSP_USING_ON_CHIP_FLASH', 'SOC_SERIES_STM32F4']):
|
||||||
src += ['drv_flash/drv_flash_f4.c']
|
src += ['drv_flash/drv_flash_f4.c']
|
||||||
|
|
||||||
if GetDepend(['BSP_USING_ON_CHIP_FLASH', 'SOC_SERIES_STM32F7']):
|
if GetDepend(['BSP_USING_ON_CHIP_FLASH', 'SOC_SERIES_STM32F7']):
|
||||||
src += ['drv_flash/drv_flash_f7.c']
|
src += ['drv_flash/drv_flash_f7.c']
|
||||||
|
|
||||||
|
|
|
@ -6,12 +6,14 @@
|
||||||
* Change Logs:
|
* Change Logs:
|
||||||
* Date Author Notes
|
* Date Author Notes
|
||||||
* 2018-11-19 SummerGift first version
|
* 2018-11-19 SummerGift first version
|
||||||
|
* 2018-12-25 zylx fix some bugs
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "board.h"
|
#include "board.h"
|
||||||
#include "drv_config.h"
|
#include "drv_config.h"
|
||||||
#include <netif/ethernetif.h>
|
#include <netif/ethernetif.h>
|
||||||
#include "lwipopts.h"
|
#include "lwipopts.h"
|
||||||
|
#include "drv_eth.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Emac driver uses CubeMX tool to generate emac and phy's configuration,
|
* Emac driver uses CubeMX tool to generate emac and phy's configuration,
|
||||||
|
@ -32,11 +34,12 @@ struct rt_stm32_eth
|
||||||
/* inherit from ethernet device */
|
/* inherit from ethernet device */
|
||||||
struct eth_device parent;
|
struct eth_device parent;
|
||||||
|
|
||||||
/* interface address info. */
|
/* interface address info, hw address */
|
||||||
rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* hw address */
|
rt_uint8_t dev_addr[MAX_ADDR_LEN];
|
||||||
|
/* ETH_Speed */
|
||||||
uint32_t ETH_Speed; /*!< @ref ETH_Speed */
|
uint32_t ETH_Speed;
|
||||||
uint32_t ETH_Mode; /*!< @ref ETH_Duplex_Mode */
|
/* ETH_Duplex_Mode */
|
||||||
|
uint32_t ETH_Mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
static ETH_DMADescTypeDef *DMARxDscrTab, *DMATxDscrTab;
|
static ETH_DMADescTypeDef *DMARxDscrTab, *DMATxDscrTab;
|
||||||
|
@ -50,7 +53,7 @@ static struct rt_semaphore tx_wait;
|
||||||
#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
|
#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
|
||||||
static void dump_hex(const rt_uint8_t *ptr, rt_size_t buflen)
|
static void dump_hex(const rt_uint8_t *ptr, rt_size_t buflen)
|
||||||
{
|
{
|
||||||
unsigned char *buf = (unsigned char*)ptr;
|
unsigned char *buf = (unsigned char *)ptr;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
for (i = 0; i < buflen; i += 16)
|
for (i = 0; i < buflen; i += 16)
|
||||||
|
@ -73,24 +76,22 @@ static void dump_hex(const rt_uint8_t *ptr, rt_size_t buflen)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void phy_reset(void);
|
extern void phy_reset(void);
|
||||||
/* EMAC initialization function */
|
/* EMAC initialization function */
|
||||||
static rt_err_t rt_stm32_eth_init(rt_device_t dev)
|
static rt_err_t rt_stm32_eth_init(rt_device_t dev)
|
||||||
{
|
{
|
||||||
__HAL_RCC_ETH_CLK_ENABLE();
|
__HAL_RCC_ETH_CLK_ENABLE();
|
||||||
|
|
||||||
phy_reset();
|
phy_reset();
|
||||||
|
|
||||||
/* ETHERNET Configuration --------------------------------------------------*/
|
/* ETHERNET Configuration */
|
||||||
EthHandle.Instance = ETH;
|
EthHandle.Instance = ETH;
|
||||||
EthHandle.Init.MACAddr = (rt_uint8_t*)&stm32_eth_device.dev_addr[0];
|
EthHandle.Init.MACAddr = (rt_uint8_t *)&stm32_eth_device.dev_addr[0];
|
||||||
EthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
|
EthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
|
||||||
EthHandle.Init.Speed = ETH_SPEED_100M;
|
EthHandle.Init.Speed = ETH_SPEED_100M;
|
||||||
EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
|
EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
|
||||||
EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
|
EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
|
||||||
EthHandle.Init.RxMode = ETH_RXINTERRUPT_MODE;
|
EthHandle.Init.RxMode = ETH_RXINTERRUPT_MODE;
|
||||||
EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE;
|
EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE;
|
||||||
//EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
|
|
||||||
EthHandle.Init.PhyAddress = EXTERNAL_PHY_ADDRESS;
|
|
||||||
|
|
||||||
HAL_ETH_DeInit(&EthHandle);
|
HAL_ETH_DeInit(&EthHandle);
|
||||||
|
|
||||||
|
@ -101,7 +102,8 @@ static rt_err_t rt_stm32_eth_init(rt_device_t dev)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG_D("emac hardware init faild");
|
LOG_E("emac hardware init faild");
|
||||||
|
return -RT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize Tx Descriptors list: Chain Mode */
|
/* 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 */
|
/* Initialize Rx Descriptors list: Chain Mode */
|
||||||
HAL_ETH_DMARxDescListInit(&EthHandle, DMARxDscrTab, Rx_Buff, ETH_RXBUFNB);
|
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 */
|
/* Enable MAC and DMA transmission and reception */
|
||||||
if (HAL_ETH_Start(&EthHandle) == HAL_OK)
|
if (HAL_ETH_Start(&EthHandle) == HAL_OK)
|
||||||
{
|
{
|
||||||
|
@ -117,13 +123,10 @@ static rt_err_t rt_stm32_eth_init(rt_device_t dev)
|
||||||
}
|
}
|
||||||
else
|
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;
|
return RT_EOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,14 +142,14 @@ static rt_err_t rt_stm32_eth_close(rt_device_t dev)
|
||||||
return RT_EOK;
|
return RT_EOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static rt_size_t rt_stm32_eth_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
|
static rt_size_t rt_stm32_eth_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
|
||||||
{
|
{
|
||||||
LOG_D("emac read");
|
LOG_D("emac read");
|
||||||
rt_set_errno(-RT_ENOSYS);
|
rt_set_errno(-RT_ENOSYS);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static rt_size_t rt_stm32_eth_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
|
static rt_size_t rt_stm32_eth_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
|
||||||
{
|
{
|
||||||
LOG_D("emac write");
|
LOG_D("emac write");
|
||||||
rt_set_errno(-RT_ENOSYS);
|
rt_set_errno(-RT_ENOSYS);
|
||||||
|
@ -155,11 +158,11 @@ static rt_size_t rt_stm32_eth_write (rt_device_t dev, rt_off_t pos, const void*
|
||||||
|
|
||||||
static rt_err_t rt_stm32_eth_control(rt_device_t dev, int cmd, void *args)
|
static rt_err_t rt_stm32_eth_control(rt_device_t dev, int cmd, void *args)
|
||||||
{
|
{
|
||||||
switch(cmd)
|
switch (cmd)
|
||||||
{
|
{
|
||||||
case NIOCTL_GADDR:
|
case NIOCTL_GADDR:
|
||||||
/* get mac address */
|
/* get mac address */
|
||||||
if(args) rt_memcpy(args, stm32_eth_device.dev_addr, 6);
|
if (args) rt_memcpy(args, stm32_eth_device.dev_addr, 6);
|
||||||
else return -RT_ERROR;
|
else return -RT_ERROR;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -172,7 +175,7 @@ static rt_err_t rt_stm32_eth_control(rt_device_t dev, int cmd, void *args)
|
||||||
|
|
||||||
/* ethernet device interface */
|
/* ethernet device interface */
|
||||||
/* transmit data*/
|
/* transmit data*/
|
||||||
rt_err_t rt_stm32_eth_tx( rt_device_t dev, struct pbuf* p)
|
rt_err_t rt_stm32_eth_tx(rt_device_t dev, struct pbuf *p)
|
||||||
{
|
{
|
||||||
rt_err_t ret = RT_ERROR;
|
rt_err_t ret = RT_ERROR;
|
||||||
HAL_StatusTypeDef state;
|
HAL_StatusTypeDef state;
|
||||||
|
@ -204,12 +207,12 @@ rt_err_t rt_stm32_eth_tx( rt_device_t dev, struct pbuf* p)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy frame from pbufs to driver buffers */
|
/* copy frame from pbufs to driver buffers */
|
||||||
for(q = p; q != NULL; q = q->next)
|
for (q = p; q != NULL; q = q->next)
|
||||||
{
|
{
|
||||||
/* Is this buffer available? If not, goto error */
|
/* Is this buffer available? If not, goto error */
|
||||||
if((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET)
|
if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET)
|
||||||
{
|
{
|
||||||
LOG_D("buffer not valid");
|
LOG_E("buffer not valid");
|
||||||
ret = ERR_USE;
|
ret = ERR_USE;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -219,18 +222,18 @@ rt_err_t rt_stm32_eth_tx( rt_device_t dev, struct pbuf* p)
|
||||||
payloadoffset = 0;
|
payloadoffset = 0;
|
||||||
|
|
||||||
/* Check if the length of data to copy is bigger than Tx buffer size*/
|
/* Check if the length of data to copy is bigger than Tx buffer size*/
|
||||||
while( (byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE )
|
while ((byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE)
|
||||||
{
|
{
|
||||||
/* Copy data to Tx buffer*/
|
/* Copy data to Tx buffer*/
|
||||||
memcpy( (uint8_t*)((uint8_t*)buffer + bufferoffset), (uint8_t*)((uint8_t*)q->payload + payloadoffset), (ETH_TX_BUF_SIZE - bufferoffset) );
|
memcpy((uint8_t *)((uint8_t *)buffer + bufferoffset), (uint8_t *)((uint8_t *)q->payload + payloadoffset), (ETH_TX_BUF_SIZE - bufferoffset));
|
||||||
|
|
||||||
/* Point to next descriptor */
|
/* Point to next descriptor */
|
||||||
DmaTxDesc = (ETH_DMADescTypeDef *)(DmaTxDesc->Buffer2NextDescAddr);
|
DmaTxDesc = (ETH_DMADescTypeDef *)(DmaTxDesc->Buffer2NextDescAddr);
|
||||||
|
|
||||||
/* Check if the buffer is available */
|
/* Check if the buffer is available */
|
||||||
if((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET)
|
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;
|
ret = ERR_USE;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -244,7 +247,7 @@ rt_err_t rt_stm32_eth_tx( rt_device_t dev, struct pbuf* p)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy the remaining bytes */
|
/* Copy the remaining bytes */
|
||||||
memcpy( (uint8_t*)((uint8_t*)buffer + bufferoffset), (uint8_t*)((uint8_t*)q->payload + payloadoffset), byteslefttocopy );
|
memcpy((uint8_t *)((uint8_t *)buffer + bufferoffset), (uint8_t *)((uint8_t *)q->payload + payloadoffset), byteslefttocopy);
|
||||||
bufferoffset = bufferoffset + byteslefttocopy;
|
bufferoffset = bufferoffset + byteslefttocopy;
|
||||||
framelength = framelength + byteslefttocopy;
|
framelength = framelength + byteslefttocopy;
|
||||||
}
|
}
|
||||||
|
@ -261,7 +264,7 @@ rt_err_t rt_stm32_eth_tx( rt_device_t dev, struct pbuf* p)
|
||||||
state = HAL_ETH_TransmitFrame(&EthHandle, framelength);
|
state = HAL_ETH_TransmitFrame(&EthHandle, framelength);
|
||||||
if (state != HAL_OK)
|
if (state != HAL_OK)
|
||||||
{
|
{
|
||||||
LOG_D("eth transmit frame faild: %d", state);
|
LOG_E("eth transmit frame faild: %d", state);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ERR_OK;
|
ret = ERR_OK;
|
||||||
|
@ -324,16 +327,16 @@ struct pbuf *rt_stm32_eth_rx(rt_device_t dev)
|
||||||
{
|
{
|
||||||
dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc;
|
dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc;
|
||||||
bufferoffset = 0;
|
bufferoffset = 0;
|
||||||
for(q = p; q != NULL; q = q->next)
|
for (q = p; q != NULL; q = q->next)
|
||||||
{
|
{
|
||||||
byteslefttocopy = q->len;
|
byteslefttocopy = q->len;
|
||||||
payloadoffset = 0;
|
payloadoffset = 0;
|
||||||
|
|
||||||
/* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/
|
/* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/
|
||||||
while( (byteslefttocopy + bufferoffset) > ETH_RX_BUF_SIZE )
|
while ((byteslefttocopy + bufferoffset) > ETH_RX_BUF_SIZE)
|
||||||
{
|
{
|
||||||
/* Copy data to pbuf */
|
/* Copy data to pbuf */
|
||||||
memcpy( (uint8_t*)((uint8_t*)q->payload + payloadoffset), (uint8_t*)((uint8_t*)buffer + bufferoffset), (ETH_RX_BUF_SIZE - bufferoffset));
|
memcpy((uint8_t *)((uint8_t *)q->payload + payloadoffset), (uint8_t *)((uint8_t *)buffer + bufferoffset), (ETH_RX_BUF_SIZE - bufferoffset));
|
||||||
|
|
||||||
/* Point to next descriptor */
|
/* Point to next descriptor */
|
||||||
dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr);
|
dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr);
|
||||||
|
@ -344,7 +347,7 @@ struct pbuf *rt_stm32_eth_rx(rt_device_t dev)
|
||||||
bufferoffset = 0;
|
bufferoffset = 0;
|
||||||
}
|
}
|
||||||
/* Copy remaining data in pbuf */
|
/* Copy remaining data in pbuf */
|
||||||
memcpy( (uint8_t*)((uint8_t*)q->payload + payloadoffset), (uint8_t*)((uint8_t*)buffer + bufferoffset), byteslefttocopy);
|
memcpy((uint8_t *)((uint8_t *)q->payload + payloadoffset), (uint8_t *)((uint8_t *)buffer + bufferoffset), byteslefttocopy);
|
||||||
bufferoffset = bufferoffset + byteslefttocopy;
|
bufferoffset = bufferoffset + byteslefttocopy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -399,41 +402,41 @@ void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
|
||||||
{
|
{
|
||||||
rt_err_t result;
|
rt_err_t result;
|
||||||
result = eth_device_ready(&(stm32_eth_device.parent));
|
result = eth_device_ready(&(stm32_eth_device.parent));
|
||||||
if( result != RT_EOK )
|
if (result != RT_EOK)
|
||||||
LOG_D("RX err = %d", result );
|
LOG_E("RX err = %d", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth)
|
void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth)
|
||||||
{
|
{
|
||||||
LOG_D("eth err");
|
LOG_E("eth err");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PHY: LAN8720 */
|
|
||||||
static uint8_t phy_speed = 0;
|
static uint8_t phy_speed = 0;
|
||||||
#define PHY_LINK_MASK (1<<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)
|
static void phy_monitor_thread_entry(void *parameter)
|
||||||
{
|
{
|
||||||
uint8_t phy_addr = 0xFF;
|
uint8_t phy_addr = 0xFF;
|
||||||
uint8_t phy_speed_new = 0;
|
uint8_t phy_speed_new = 0;
|
||||||
|
rt_uint32_t status = 0;
|
||||||
|
|
||||||
/* phy search */
|
/* phy search */
|
||||||
rt_uint32_t i, temp;
|
rt_uint32_t i, temp;
|
||||||
for(i=0; i<=0x1F; i++)
|
for (i = 0; i <= 0x1F; i++)
|
||||||
{
|
{
|
||||||
HAL_ETH_ReadPHYRegister(&EthHandle, 0x02, (uint32_t *)&temp);
|
EthHandle.Init.PhyAddress = i;
|
||||||
|
|
||||||
if( temp != 0xFFFF )
|
HAL_ETH_ReadPHYRegister(&EthHandle, PHY_ID1_REG, (uint32_t *)&temp);
|
||||||
|
|
||||||
|
if (temp != 0xFFFF)
|
||||||
{
|
{
|
||||||
phy_addr = i;
|
phy_addr = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(phy_addr == 0xFF)
|
if (phy_addr == 0xFF)
|
||||||
{
|
{
|
||||||
LOG_D("phy not probe!\r\n");
|
LOG_E("phy not probe!\r\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -443,47 +446,49 @@ static void phy_monitor_thread_entry(void *parameter)
|
||||||
|
|
||||||
/* RESET PHY */
|
/* RESET PHY */
|
||||||
LOG_D("RESET PHY!");
|
LOG_D("RESET PHY!");
|
||||||
HAL_ETH_WritePHYRegister(&EthHandle, PHY_BCR, PHY_RESET);
|
HAL_ETH_WritePHYRegister(&EthHandle, PHY_BASIC_CONTROL_REG, PHY_RESET_MASK);
|
||||||
rt_thread_delay(RT_TICK_PER_SECOND * 2);
|
rt_thread_mdelay(2000);
|
||||||
HAL_ETH_WritePHYRegister(&EthHandle, PHY_BCR, PHY_AUTONEGOTIATION);
|
HAL_ETH_WritePHYRegister(&EthHandle, PHY_BASIC_CONTROL_REG, PHY_AUTO_NEGOTIATION_MASK);
|
||||||
|
|
||||||
while(1)
|
while (1)
|
||||||
{
|
{
|
||||||
rt_uint32_t status;
|
HAL_ETH_ReadPHYRegister(&EthHandle, PHY_BASIC_STATUS_REG, (uint32_t *)&status);
|
||||||
HAL_ETH_ReadPHYRegister(&EthHandle, PHY_BSR, (uint32_t *)&status);
|
LOG_D("PHY BASIC STATUS REG:0x%04X\r\n", status);
|
||||||
LOG_D("LAN8720 status:0x%04X\r\n", status);
|
|
||||||
|
|
||||||
phy_speed_new = 0;
|
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;
|
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;
|
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;
|
phy_speed_new |= PHY_100M_MASK;
|
||||||
}
|
}
|
||||||
|
else if (SR & PHY_10M_MASK)
|
||||||
if(SR & 0x04)
|
|
||||||
{
|
{
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* linkchange */
|
/* linkchange */
|
||||||
if(phy_speed_new != phy_speed)
|
if (phy_speed_new != phy_speed)
|
||||||
{
|
{
|
||||||
if(phy_speed_new & PHY_LINK_MASK)
|
if (phy_speed_new & PHY_LINK_MASK)
|
||||||
{
|
{
|
||||||
LOG_D("link up ");
|
LOG_D("link up ");
|
||||||
|
|
||||||
if(phy_speed_new & PHY_100M_MASK)
|
if (phy_speed_new & PHY_100M_MASK)
|
||||||
{
|
{
|
||||||
LOG_D("100Mbps");
|
LOG_D("100Mbps");
|
||||||
stm32_eth_device.ETH_Speed = ETH_SPEED_100M;
|
stm32_eth_device.ETH_Speed = ETH_SPEED_100M;
|
||||||
|
@ -494,7 +499,7 @@ static void phy_monitor_thread_entry(void *parameter)
|
||||||
LOG_D("10Mbps");
|
LOG_D("10Mbps");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(phy_speed_new & PHY_DUPLEX_MASK)
|
if (phy_speed_new & PHY_FULL_DUPLEX_MASK)
|
||||||
{
|
{
|
||||||
LOG_D("full-duplex");
|
LOG_D("full-duplex");
|
||||||
stm32_eth_device.ETH_Mode = ETH_MODE_FULLDUPLEX;
|
stm32_eth_device.ETH_Mode = ETH_MODE_FULLDUPLEX;
|
||||||
|
@ -504,54 +509,68 @@ static void phy_monitor_thread_entry(void *parameter)
|
||||||
LOG_D("half-duplex");
|
LOG_D("half-duplex");
|
||||||
stm32_eth_device.ETH_Mode = ETH_MODE_HALFDUPLEX;
|
stm32_eth_device.ETH_Mode = ETH_MODE_HALFDUPLEX;
|
||||||
}
|
}
|
||||||
rt_stm32_eth_init((rt_device_t)&stm32_eth_device);
|
|
||||||
|
|
||||||
/* send link up. */
|
if (rt_stm32_eth_init((rt_device_t)&stm32_eth_device) != RT_EOK)
|
||||||
eth_device_linkchange(&stm32_eth_device.parent, RT_TRUE);
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* send link up. */
|
||||||
|
eth_device_linkchange(&stm32_eth_device.parent, RT_TRUE);
|
||||||
|
}
|
||||||
} /* link up. */
|
} /* link up. */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG_D("link down\r\n");
|
LOG_I("link down\r\n");
|
||||||
/* send link down. */
|
/* send link down. */
|
||||||
eth_device_linkchange(&stm32_eth_device.parent, RT_FALSE);
|
eth_device_linkchange(&stm32_eth_device.parent, RT_FALSE);
|
||||||
}
|
}
|
||||||
phy_speed = phy_speed_new;
|
phy_speed = phy_speed_new;
|
||||||
}
|
}
|
||||||
|
|
||||||
rt_thread_delay(RT_TICK_PER_SECOND);
|
rt_thread_delay(RT_TICK_PER_SECOND);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Register the EMAC device */
|
/* Register the EMAC device */
|
||||||
static int rt_hw_stm32_eth_init(void)
|
static int rt_hw_stm32_eth_init(void)
|
||||||
{
|
{
|
||||||
|
rt_err_t state = RT_EOK;
|
||||||
|
|
||||||
/* Prepare receive and send buffers */
|
/* Prepare receive and send buffers */
|
||||||
Rx_Buff = (rt_uint8_t *)rt_calloc(ETH_RXBUFNB, ETH_MAX_PACKET_SIZE);
|
Rx_Buff = (rt_uint8_t *)rt_calloc(ETH_RXBUFNB, ETH_MAX_PACKET_SIZE);
|
||||||
if (Rx_Buff == RT_NULL)
|
if (Rx_Buff == RT_NULL)
|
||||||
{
|
{
|
||||||
LOG_E("No memory");
|
LOG_E("No memory");
|
||||||
|
state = RT_ENOMEM;
|
||||||
|
goto __exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tx_Buff = (rt_uint8_t *)rt_calloc(ETH_TXBUFNB, ETH_MAX_PACKET_SIZE);
|
Tx_Buff = (rt_uint8_t *)rt_calloc(ETH_TXBUFNB, ETH_MAX_PACKET_SIZE);
|
||||||
if (Rx_Buff == RT_NULL)
|
if (Rx_Buff == RT_NULL)
|
||||||
{
|
{
|
||||||
LOG_E("No memory");
|
LOG_E("No memory");
|
||||||
|
state = RT_ENOMEM;
|
||||||
|
goto __exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
DMARxDscrTab = (ETH_DMADescTypeDef * )rt_calloc(ETH_RXBUFNB, sizeof(ETH_DMADescTypeDef));
|
DMARxDscrTab = (ETH_DMADescTypeDef *)rt_calloc(ETH_RXBUFNB, sizeof(ETH_DMADescTypeDef));
|
||||||
if (DMARxDscrTab == RT_NULL)
|
if (DMARxDscrTab == RT_NULL)
|
||||||
{
|
{
|
||||||
LOG_E("No memory");
|
LOG_E("No memory");
|
||||||
|
state = RT_ENOMEM;
|
||||||
|
goto __exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
DMATxDscrTab = (ETH_DMADescTypeDef * )rt_calloc(ETH_TXBUFNB, sizeof(ETH_DMADescTypeDef));
|
DMATxDscrTab = (ETH_DMADescTypeDef *)rt_calloc(ETH_TXBUFNB, sizeof(ETH_DMADescTypeDef));
|
||||||
if (DMATxDscrTab == RT_NULL)
|
if (DMATxDscrTab == RT_NULL)
|
||||||
{
|
{
|
||||||
LOG_E("No memory");
|
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_Speed = ETH_SPEED_100M;
|
||||||
stm32_eth_device.ETH_Mode = ETH_MODE_FULLDUPLEX;
|
stm32_eth_device.ETH_Mode = ETH_MODE_FULLDUPLEX;
|
||||||
|
|
||||||
|
@ -560,9 +579,9 @@ static int rt_hw_stm32_eth_init(void)
|
||||||
stm32_eth_device.dev_addr[1] = 0x80;
|
stm32_eth_device.dev_addr[1] = 0x80;
|
||||||
stm32_eth_device.dev_addr[2] = 0xE1;
|
stm32_eth_device.dev_addr[2] = 0xE1;
|
||||||
/* generate MAC addr from 96bit unique ID (only for test). */
|
/* generate MAC addr from 96bit unique ID (only for test). */
|
||||||
stm32_eth_device.dev_addr[3] = *(rt_uint8_t*)(UID_BASE + 4);
|
stm32_eth_device.dev_addr[3] = *(rt_uint8_t *)(UID_BASE + 4);
|
||||||
stm32_eth_device.dev_addr[4] = *(rt_uint8_t*)(UID_BASE + 2);
|
stm32_eth_device.dev_addr[4] = *(rt_uint8_t *)(UID_BASE + 2);
|
||||||
stm32_eth_device.dev_addr[5] = *(rt_uint8_t*)(UID_BASE + 0);
|
stm32_eth_device.dev_addr[5] = *(rt_uint8_t *)(UID_BASE + 0);
|
||||||
|
|
||||||
stm32_eth_device.parent.parent.init = rt_stm32_eth_init;
|
stm32_eth_device.parent.parent.init = rt_stm32_eth_init;
|
||||||
stm32_eth_device.parent.parent.open = rt_stm32_eth_open;
|
stm32_eth_device.parent.parent.open = rt_stm32_eth_open;
|
||||||
|
@ -587,9 +606,10 @@ static int rt_hw_stm32_eth_init(void)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG_D("emac device init faild: %d", state);
|
LOG_E("emac device init faild: %d", state);
|
||||||
|
return -RT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* start phy monitor */
|
/* start phy monitor */
|
||||||
rt_thread_t tid;
|
rt_thread_t tid;
|
||||||
tid = rt_thread_create("phy",
|
tid = rt_thread_create("phy",
|
||||||
|
@ -600,9 +620,32 @@ static int rt_hw_stm32_eth_init(void)
|
||||||
2);
|
2);
|
||||||
if (tid != RT_NULL)
|
if (tid != RT_NULL)
|
||||||
{
|
{
|
||||||
rt_thread_startup(tid);
|
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;
|
return state;
|
||||||
}
|
}
|
||||||
INIT_APP_EXPORT(rt_hw_stm32_eth_init);
|
INIT_APP_EXPORT(rt_hw_stm32_eth_init);
|
|
@ -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