582 lines
18 KiB
C
582 lines
18 KiB
C
|
/*
|
||
|
* STM32 Eth Driver for RT-Thread
|
||
|
* Change Logs:
|
||
|
* Date Author Notes
|
||
|
* 2009-10-05 Bernard eth interface driver for STM32F107 CL
|
||
|
*/
|
||
|
#include <rtthread.h>
|
||
|
#include <netif/ethernetif.h>
|
||
|
#include "lwipopts.h"
|
||
|
#include "stm32f2x7_eth.h"
|
||
|
#include "stm32f2x7_eth_conf.h"
|
||
|
|
||
|
#define STM32_ETH_DEBUG 0
|
||
|
#define CHECKSUM_BY_HARDWARE
|
||
|
|
||
|
/* MII and RMII mode selection, for STM322xG-EVAL Board(MB786) RevB ***********/
|
||
|
//#define MII_MODE
|
||
|
|
||
|
#define RMII_MODE // In this case the System clock frequency is configured
|
||
|
// to 100 MHz, for more details refer to system_stm32f2xx.c
|
||
|
|
||
|
#define DP83848_PHY_ADDRESS 0x01 /* Relative to STM322xG-EVAL Board */
|
||
|
|
||
|
#define netifGUARD_BLOCK_TIME 250
|
||
|
|
||
|
/* Ethernet Rx & Tx DMA Descriptors */
|
||
|
extern ETH_DMADESCTypeDef DMARxDscrTab[ETH_RXBUFNB], DMATxDscrTab[ETH_TXBUFNB];
|
||
|
|
||
|
/* Ethernet Receive buffers */
|
||
|
extern uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE];
|
||
|
|
||
|
/* Ethernet Transmit buffers */
|
||
|
extern uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE];
|
||
|
|
||
|
/* Global pointers to track current transmit and receive descriptors */
|
||
|
extern ETH_DMADESCTypeDef *DMATxDescToSet;
|
||
|
extern ETH_DMADESCTypeDef *DMARxDescToGet;
|
||
|
|
||
|
/* Global pointer for last received frame infos */
|
||
|
extern ETH_DMA_Rx_Frame_infos *DMA_RX_FRAME_infos;
|
||
|
|
||
|
#define MAX_ADDR_LEN 6
|
||
|
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 */
|
||
|
};
|
||
|
static struct rt_stm32_eth stm32_eth_device;
|
||
|
static struct rt_semaphore tx_wait;
|
||
|
static rt_bool_t tx_is_waiting = RT_FALSE;
|
||
|
|
||
|
static void ETH_MACDMA_Config(void);
|
||
|
|
||
|
static struct rt_semaphore tx_wait;
|
||
|
|
||
|
/* interrupt service routine */
|
||
|
void ETH_IRQHandler(void)
|
||
|
{
|
||
|
rt_uint32_t status;
|
||
|
|
||
|
status = ETH->DMASR;
|
||
|
|
||
|
/* Frame received */
|
||
|
if ( ETH_GetDMAFlagStatus(ETH_DMA_FLAG_R) == SET)
|
||
|
{
|
||
|
rt_err_t result;
|
||
|
//rt_kprintf("Frame comming\n");
|
||
|
/* Clear the interrupt flags. */
|
||
|
/* Clear the Eth DMA Rx IT pending bits */
|
||
|
ETH_DMAClearITPendingBit(ETH_DMA_IT_R);
|
||
|
|
||
|
/* a frame has been received */
|
||
|
result = eth_device_ready(&(stm32_eth_device.parent));
|
||
|
if( result != RT_EOK ) rt_kprintf("RX err =%d\n", result );
|
||
|
//RT_ASSERT(result == RT_EOK);
|
||
|
}
|
||
|
if (ETH_GetDMAITStatus(ETH_DMA_IT_T) == SET) /* packet transmission */
|
||
|
{
|
||
|
ETH_DMAClearITPendingBit(ETH_DMA_IT_T);
|
||
|
}
|
||
|
|
||
|
ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS);
|
||
|
//
|
||
|
|
||
|
}
|
||
|
|
||
|
/* RT-Thread Device Interface */
|
||
|
/* initialize the interface */
|
||
|
static rt_err_t rt_stm32_eth_init(rt_device_t dev)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
/* MAC address configuration */
|
||
|
ETH_MACAddressConfig(ETH_MAC_Address0, (u8*)&stm32_eth_device.dev_addr[0]);
|
||
|
|
||
|
/* Initialize Tx Descriptors list: Chain Mode */
|
||
|
ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
|
||
|
/* Initialize Rx Descriptors list: Chain Mode */
|
||
|
ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);
|
||
|
|
||
|
/* Enable Ethernet Rx interrrupt */
|
||
|
{
|
||
|
for(i=0; i<ETH_RXBUFNB; i++)
|
||
|
{
|
||
|
ETH_DMARxDescReceiveITConfig(&DMARxDscrTab[i], ENABLE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#ifdef CHECKSUM_BY_HARDWARE
|
||
|
/* Enable the checksum insertion for the Tx frames */
|
||
|
{
|
||
|
for(i=0; i<ETH_TXBUFNB; i++)
|
||
|
{
|
||
|
ETH_DMATxDescChecksumInsertionConfig(&DMATxDscrTab[i], ETH_DMATxDesc_ChecksumTCPUDPICMPFull);
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
{
|
||
|
uint16_t tmp, i=10000;
|
||
|
|
||
|
tmp = ETH_ReadPHYRegister(DP83848_PHY_ADDRESS, PHY_CR);
|
||
|
ETH_WritePHYRegister(DP83848_PHY_ADDRESS, PHY_CDCTRL1, BIST_CONT_MODE );
|
||
|
ETH_WritePHYRegister(DP83848_PHY_ADDRESS, PHY_CR, tmp | BIST_START );//BIST_START
|
||
|
|
||
|
while(i--);
|
||
|
|
||
|
//tmp = ETH_ReadPHYRegister(DP83848_PHY_ADDRESS, PHY_CR);
|
||
|
|
||
|
if( ETH_ReadPHYRegister(DP83848_PHY_ADDRESS, PHY_CR) & BIST_STATUS == BIST_STATUS )
|
||
|
{
|
||
|
rt_kprintf("BIST pass\n");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
uint16_t ctrl;
|
||
|
|
||
|
ctrl = ETH_ReadPHYRegister(DP83848_PHY_ADDRESS, PHY_CDCTRL1);
|
||
|
rt_kprintf("BIST faild count =%d\n", BIST_ERROR_COUNT(ctrl) );
|
||
|
}
|
||
|
tmp &= ~BIST_START; //Stop BIST
|
||
|
ETH_WritePHYRegister(DP83848_PHY_ADDRESS, PHY_CR, tmp);
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
/* Enable MAC and DMA transmission and reception */
|
||
|
ETH_Start();
|
||
|
|
||
|
//rt_kprintf("DMASR = 0x%X\n", ETH->DMASR );
|
||
|
// rt_kprintf("ETH Init\n");
|
||
|
|
||
|
return RT_EOK;
|
||
|
}
|
||
|
|
||
|
static rt_err_t rt_stm32_eth_open(rt_device_t dev, rt_uint16_t oflag)
|
||
|
{
|
||
|
return RT_EOK;
|
||
|
}
|
||
|
|
||
|
static rt_err_t rt_stm32_eth_close(rt_device_t dev)
|
||
|
{
|
||
|
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)
|
||
|
{
|
||
|
rt_set_errno(-RT_ENOSYS);
|
||
|
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)
|
||
|
{
|
||
|
rt_set_errno(-RT_ENOSYS);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static rt_err_t rt_stm32_eth_control(rt_device_t dev, rt_uint8_t cmd, void *args)
|
||
|
{
|
||
|
switch(cmd)
|
||
|
{
|
||
|
case NIOCTL_GADDR:
|
||
|
/* get mac address */
|
||
|
if(args) rt_memcpy(args, stm32_eth_device.dev_addr, 6);
|
||
|
else return -RT_ERROR;
|
||
|
break;
|
||
|
|
||
|
default :
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return RT_EOK;
|
||
|
}
|
||
|
|
||
|
void show_frame(struct pbuf *q)
|
||
|
{
|
||
|
int i = 0;
|
||
|
int j = 0;
|
||
|
char *ptr = q->payload;
|
||
|
|
||
|
for( i = 0; i < q->len; i++ )
|
||
|
rt_kprintf("0x%02X ", *(ptr++));
|
||
|
rt_kprintf("\n");
|
||
|
}
|
||
|
|
||
|
/* ethernet device interface */
|
||
|
/* transmit packet. */
|
||
|
rt_err_t rt_stm32_eth_tx( rt_device_t dev, struct pbuf* p)
|
||
|
{
|
||
|
rt_err_t ret;
|
||
|
struct pbuf *q;
|
||
|
uint32_t l = 0;
|
||
|
u8 *buffer ;
|
||
|
|
||
|
if (( ret = rt_sem_take(&tx_wait, netifGUARD_BLOCK_TIME) ) == RT_EOK)
|
||
|
{
|
||
|
buffer = (u8 *)(DMATxDescToSet->Buffer1Addr);
|
||
|
for(q = p; q != NULL; q = q->next)
|
||
|
{
|
||
|
//show_frame(q);
|
||
|
rt_memcpy((u8_t*)&buffer[l], q->payload, q->len);
|
||
|
l = l + q->len;
|
||
|
}
|
||
|
if( ETH_Prepare_Transmit_Descriptors(l) == ETH_ERROR )
|
||
|
rt_kprintf("Tx Error\n");
|
||
|
//rt_sem_release(xTxSemaphore);
|
||
|
rt_sem_release(&tx_wait);
|
||
|
//rt_kprintf("Tx packet, len = %d\n", l);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
rt_kprintf("Tx Timeout\n");
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/* Return SUCCESS */
|
||
|
return RT_EOK;
|
||
|
}
|
||
|
|
||
|
/* reception packet. */
|
||
|
struct pbuf *rt_stm32_eth_rx(rt_device_t dev)
|
||
|
{
|
||
|
struct pbuf *p, *q;
|
||
|
u16_t len;
|
||
|
uint32_t l=0,i =0;
|
||
|
FrameTypeDef frame;
|
||
|
static framecnt = 1;
|
||
|
u8 *buffer;
|
||
|
__IO ETH_DMADESCTypeDef *DMARxNextDesc;
|
||
|
|
||
|
p = RT_NULL;
|
||
|
|
||
|
// rt_kprintf("ETH rx\n");
|
||
|
/* Get received frame */
|
||
|
frame = ETH_Get_Received_Frame_interrupt();
|
||
|
|
||
|
if( frame.length > 0 )
|
||
|
{
|
||
|
/* check that frame has no error */
|
||
|
if ((frame.descriptor->Status & ETH_DMARxDesc_ES) == (uint32_t)RESET)
|
||
|
{
|
||
|
//rt_kprintf("Get a frame %d buf = 0x%X, len= %d\n", framecnt++, frame.buffer, frame.length);
|
||
|
/* Obtain the size of the packet and put it into the "len" variable. */
|
||
|
len = frame.length;
|
||
|
buffer = (u8 *)frame.buffer;
|
||
|
|
||
|
/* We allocate a pbuf chain of pbufs from the pool. */
|
||
|
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
|
||
|
//p = pbuf_alloc(PBUF_LINK, len, PBUF_RAM);
|
||
|
|
||
|
/* Copy received frame from ethernet driver buffer to stack buffer */
|
||
|
if (p != NULL)
|
||
|
{
|
||
|
for (q = p; q != NULL; q = q->next)
|
||
|
{
|
||
|
rt_memcpy((u8_t*)q->payload, (u8_t*)&buffer[l], q->len);
|
||
|
l = l + q->len;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Release descriptors to DMA */
|
||
|
/* Check if received frame with multiple DMA buffer segments */
|
||
|
if (DMA_RX_FRAME_infos->Seg_Count > 1)
|
||
|
{
|
||
|
DMARxNextDesc = DMA_RX_FRAME_infos->FS_Rx_Desc;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
DMARxNextDesc = frame.descriptor;
|
||
|
}
|
||
|
|
||
|
/* Set Own bit in Rx descriptors: gives the buffers back to DMA */
|
||
|
for (i=0; i<DMA_RX_FRAME_infos->Seg_Count; i++)
|
||
|
{
|
||
|
DMARxNextDesc->Status = ETH_DMARxDesc_OWN;
|
||
|
DMARxNextDesc = (ETH_DMADESCTypeDef *)(DMARxNextDesc->Buffer2NextDescAddr);
|
||
|
}
|
||
|
|
||
|
/* Clear Segment_Count */
|
||
|
DMA_RX_FRAME_infos->Seg_Count =0;
|
||
|
|
||
|
|
||
|
/* When Rx Buffer unavailable flag is set: clear it and resume reception */
|
||
|
if ((ETH->DMASR & ETH_DMASR_RBUS) != (u32)RESET)
|
||
|
{
|
||
|
/* Clear RBUS ETHERNET DMA flag */
|
||
|
ETH->DMASR = ETH_DMASR_RBUS;
|
||
|
|
||
|
/* Resume DMA reception */
|
||
|
ETH->DMARPDR = 0;
|
||
|
}
|
||
|
}
|
||
|
return p;
|
||
|
}
|
||
|
|
||
|
static void NVIC_Configuration(void)
|
||
|
{
|
||
|
NVIC_InitTypeDef NVIC_InitStructure;
|
||
|
|
||
|
/* 2 bit for pre-emption priority, 2 bits for subpriority */
|
||
|
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
|
||
|
/* Enable the Ethernet global Interrupt */
|
||
|
NVIC_InitStructure.NVIC_IRQChannel = ETH_IRQn;
|
||
|
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
|
||
|
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
||
|
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||
|
NVIC_Init(&NVIC_InitStructure);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* GPIO Configuration for ETH
|
||
|
*/
|
||
|
static void GPIO_Configuration(void)
|
||
|
{
|
||
|
|
||
|
GPIO_InitTypeDef GPIO_InitStructure;
|
||
|
|
||
|
/* Enable GPIOs clocks */
|
||
|
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB |
|
||
|
RCC_AHB1Periph_GPIOC
|
||
|
, ENABLE);
|
||
|
|
||
|
/* Enable SYSCFG clock */
|
||
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
|
||
|
|
||
|
/* Configure MCO (PA8) */
|
||
|
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
|
||
|
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
|
||
|
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||
|
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||
|
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||
|
//GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||
|
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||
|
|
||
|
GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_MCO );
|
||
|
|
||
|
#ifdef MII_MODE
|
||
|
/* Output PLL clock divided by 2 (25MHz) on MCO pin (PA8) to clock the PHY */
|
||
|
RCC_MCO1Config(RCC_MCO1Source_HSE, RCC_MCO1Div_1);
|
||
|
|
||
|
SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_MII);
|
||
|
#elif defined RMII_MODE
|
||
|
/* Output PLL clock divided by 2 (50MHz) on MCO pin (PA8) to clock the PHY */
|
||
|
//RCC_MCO1Config(RCC_MCO1Source_PLLCLK, RCC_MCO1Div_2);
|
||
|
|
||
|
SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_RMII);
|
||
|
#endif
|
||
|
|
||
|
/* Ethernet pins configuration ************************************************/
|
||
|
|
||
|
/*
|
||
|
ETH_MDIO -------------------------> PA2
|
||
|
ETH_MDC --------------------------> PC1
|
||
|
ETH_MII_RX_CLK/ETH_RMII_REF_CLK---> PA1
|
||
|
ETH_MII_RX_DV/ETH_RMII_CRS_DV ----> PA7
|
||
|
ETH_MII_RXD0/ETH_RMII_RXD0 -------> PC4
|
||
|
ETH_MII_RXD1/ETH_RMII_RXD1 -------> PC5
|
||
|
ETH_MII_TX_EN/ETH_RMII_TX_EN -----> PB11
|
||
|
ETH_MII_TXD0/ETH_RMII_TXD0 -------> PB12
|
||
|
ETH_MII_TXD1/ETH_RMII_TXD1 -------> PB13
|
||
|
|
||
|
**** Just for MII Mode ****
|
||
|
ETH_MII_CRS ----------------------> PA0
|
||
|
ETH_MII_COL ----------------------> PA3
|
||
|
ETH_MII_TX_CLK -------------------> PC3
|
||
|
ETH_MII_RX_ER --------------------> PB10
|
||
|
ETH_MII_RXD2 ---------------------> PB0
|
||
|
ETH_MII_RXD3 ---------------------> PB1
|
||
|
ETH_MII_TXD2 ---------------------> PC2
|
||
|
ETH_MII_TXD3 ---------------------> PB8
|
||
|
*/
|
||
|
/* Configure PC1, PC4 and PC5 */
|
||
|
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 |GPIO_Pin_4 | GPIO_Pin_5;
|
||
|
GPIO_Init(GPIOC, &GPIO_InitStructure);
|
||
|
GPIO_PinAFConfig(GPIOC, GPIO_PinSource1, GPIO_AF_ETH);
|
||
|
GPIO_PinAFConfig(GPIOC, GPIO_PinSource4, GPIO_AF_ETH);
|
||
|
GPIO_PinAFConfig(GPIOC, GPIO_PinSource5, GPIO_AF_ETH);
|
||
|
|
||
|
/* Configure PB11, PB12 and PB13 */
|
||
|
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13;
|
||
|
GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||
|
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_ETH);
|
||
|
GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_ETH);
|
||
|
GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_ETH);
|
||
|
|
||
|
/* Configure PA1, PA2 and PA7 */
|
||
|
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2 | GPIO_Pin_7;
|
||
|
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||
|
GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_ETH);
|
||
|
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_ETH);
|
||
|
GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_ETH);
|
||
|
|
||
|
#ifdef MII_MODE
|
||
|
/* Configure PC2, PC3 */
|
||
|
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 |GPIO_Pin_3;
|
||
|
GPIO_Init(GPIOC, &GPIO_InitStructure);
|
||
|
GPIO_PinAFConfig(GPIOC, GPIO_PinSource2, GPIO_AF_ETH);
|
||
|
GPIO_PinAFConfig(GPIOC, GPIO_PinSource3, GPIO_AF_ETH);
|
||
|
|
||
|
/* Configure PB0, PB1, PB10 and PB8 */
|
||
|
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1, GPIO_Pin_10 | GPIO_Pin_8;
|
||
|
GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||
|
GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, GPIO_AF_ETH);
|
||
|
GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_ETH);
|
||
|
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_ETH);
|
||
|
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_ETH);
|
||
|
|
||
|
/* Configure PA0, PA3 */
|
||
|
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_3;
|
||
|
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||
|
GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_ETH);
|
||
|
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_ETH);
|
||
|
#endif
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Configures the Ethernet Interface
|
||
|
* @param None
|
||
|
* @retval None
|
||
|
*/
|
||
|
static void ETH_MACDMA_Config(void)
|
||
|
{
|
||
|
ETH_InitTypeDef ETH_InitStructure;
|
||
|
|
||
|
/* Enable ETHERNET clock */
|
||
|
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_ETH_MAC | RCC_AHB1Periph_ETH_MAC_Tx |
|
||
|
RCC_AHB1Periph_ETH_MAC_Rx, ENABLE);
|
||
|
|
||
|
/* Reset ETHERNET on AHB Bus */
|
||
|
ETH_DeInit();
|
||
|
|
||
|
/* Software reset */
|
||
|
ETH_SoftwareReset();
|
||
|
|
||
|
/* Wait for software reset */
|
||
|
while (ETH_GetSoftwareResetStatus() == SET);
|
||
|
|
||
|
/* ETHERNET Configuration --------------------------------------------------*/
|
||
|
/* Call ETH_StructInit if you don't like to configure all ETH_InitStructure parameter */
|
||
|
ETH_StructInit(Ð_InitStructure);
|
||
|
|
||
|
/* Fill ETH_InitStructure parametrs */
|
||
|
/*------------------------ MAC -----------------------------------*/
|
||
|
ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Enable;
|
||
|
//ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Disable;
|
||
|
// ETH_InitStructure.ETH_Speed = ETH_Speed_10M;
|
||
|
// ETH_InitStructure.ETH_Mode = ETH_Mode_FullDuplex;
|
||
|
|
||
|
ETH_InitStructure.ETH_LoopbackMode = ETH_LoopbackMode_Disable;
|
||
|
ETH_InitStructure.ETH_RetryTransmission = ETH_RetryTransmission_Disable;
|
||
|
ETH_InitStructure.ETH_AutomaticPadCRCStrip = ETH_AutomaticPadCRCStrip_Disable;
|
||
|
ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Disable;
|
||
|
ETH_InitStructure.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Enable;
|
||
|
ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable;
|
||
|
ETH_InitStructure.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect;
|
||
|
ETH_InitStructure.ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect;
|
||
|
#ifdef CHECKSUM_BY_HARDWARE
|
||
|
ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable;
|
||
|
#endif
|
||
|
|
||
|
/*------------------------ DMA -----------------------------------*/
|
||
|
|
||
|
/* When we use the Checksum offload feature, we need to enable the Store and Forward mode:
|
||
|
the store and forward guarantee that a whole frame is stored in the FIFO, so the MAC can insert/verify the checksum,
|
||
|
if the checksum is OK the DMA can handle the frame otherwise the frame is dropped */
|
||
|
ETH_InitStructure.ETH_DropTCPIPChecksumErrorFrame = ETH_DropTCPIPChecksumErrorFrame_Enable;
|
||
|
ETH_InitStructure.ETH_ReceiveStoreForward = ETH_ReceiveStoreForward_Enable;
|
||
|
ETH_InitStructure.ETH_TransmitStoreForward = ETH_TransmitStoreForward_Enable;
|
||
|
|
||
|
ETH_InitStructure.ETH_ForwardErrorFrames = ETH_ForwardErrorFrames_Disable;
|
||
|
ETH_InitStructure.ETH_ForwardUndersizedGoodFrames = ETH_ForwardUndersizedGoodFrames_Disable;
|
||
|
ETH_InitStructure.ETH_SecondFrameOperate = ETH_SecondFrameOperate_Enable;
|
||
|
ETH_InitStructure.ETH_AddressAlignedBeats = ETH_AddressAlignedBeats_Enable;
|
||
|
ETH_InitStructure.ETH_FixedBurst = ETH_FixedBurst_Enable;
|
||
|
ETH_InitStructure.ETH_RxDMABurstLength = ETH_RxDMABurstLength_32Beat;
|
||
|
ETH_InitStructure.ETH_TxDMABurstLength = ETH_TxDMABurstLength_32Beat;
|
||
|
ETH_InitStructure.ETH_DMAArbitration = ETH_DMAArbitration_RoundRobin_RxTx_2_1;
|
||
|
|
||
|
/* Configure Ethernet */
|
||
|
if( ETH_Init(Ð_InitStructure, DP83848_PHY_ADDRESS) == ETH_ERROR )
|
||
|
rt_kprintf("ETH init error, may be no link\n");
|
||
|
|
||
|
/* Enable the Ethernet Rx Interrupt */
|
||
|
ETH_DMAITConfig(ETH_DMA_IT_NIS | ETH_DMA_IT_R , ENABLE);
|
||
|
}
|
||
|
|
||
|
#define DevID_SNo0 (*((rt_uint32_t *)0x1FFF7A10));
|
||
|
#define DevID_SNo1 (*((rt_uint32_t *)0x1FFF7A10+32));
|
||
|
#define DevID_SNo2 (*((rt_uint32_t *)0x1FFF7A10+64));
|
||
|
void rt_hw_stm32_eth_init(void)
|
||
|
{
|
||
|
GPIO_Configuration();
|
||
|
NVIC_Configuration();
|
||
|
ETH_MACDMA_Config();
|
||
|
|
||
|
stm32_eth_device.dev_addr[0] = 0x00;
|
||
|
stm32_eth_device.dev_addr[1] = 0x60;
|
||
|
stm32_eth_device.dev_addr[2] = 0x6e;
|
||
|
{
|
||
|
uint32_t cpu_id[3] = {0};
|
||
|
cpu_id[2] = DevID_SNo2; cpu_id[1] = DevID_SNo1; cpu_id[0] = DevID_SNo0;
|
||
|
|
||
|
// generate MAC addr from 96bit unique ID (only for test)
|
||
|
stm32_eth_device.dev_addr[3] = (uint8_t)((cpu_id[0]>>16)&0xFF);
|
||
|
stm32_eth_device.dev_addr[4] = (uint8_t)((cpu_id[0]>>8)&0xFF);
|
||
|
stm32_eth_device.dev_addr[5] = (uint8_t)(cpu_id[0]&0xFF);
|
||
|
|
||
|
// stm32_eth_device.dev_addr[3] = *(rt_uint8_t*)(0x1FFF7A10+7);
|
||
|
// stm32_eth_device.dev_addr[4] = *(rt_uint8_t*)(0x1FFF7A10+8);
|
||
|
// stm32_eth_device.dev_addr[5] = *(rt_uint8_t*)(0x1FFF7A10+9);
|
||
|
}
|
||
|
|
||
|
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.close = rt_stm32_eth_close;
|
||
|
stm32_eth_device.parent.parent.read = rt_stm32_eth_read;
|
||
|
stm32_eth_device.parent.parent.write = rt_stm32_eth_write;
|
||
|
stm32_eth_device.parent.parent.control = rt_stm32_eth_control;
|
||
|
stm32_eth_device.parent.parent.user_data = RT_NULL;
|
||
|
|
||
|
stm32_eth_device.parent.eth_rx = rt_stm32_eth_rx;
|
||
|
stm32_eth_device.parent.eth_tx = rt_stm32_eth_tx;
|
||
|
|
||
|
/* init tx semaphore */
|
||
|
rt_sem_init(&tx_wait, "tx_wait", 1, RT_IPC_FLAG_FIFO);
|
||
|
|
||
|
/* register eth device */
|
||
|
eth_device_init(&(stm32_eth_device.parent), "e0");
|
||
|
}
|
||
|
static char led = 0;
|
||
|
|
||
|
void dp83483()
|
||
|
{
|
||
|
uint16_t bsr,sts, bcr, phycr;
|
||
|
|
||
|
bsr = ETH_ReadPHYRegister(DP83848_PHY_ADDRESS, PHY_BSR);
|
||
|
sts = ETH_ReadPHYRegister(DP83848_PHY_ADDRESS, PHY_SR);
|
||
|
bcr = ETH_ReadPHYRegister(DP83848_PHY_ADDRESS, PHY_BCR);
|
||
|
phycr = ETH_ReadPHYRegister(DP83848_PHY_ADDRESS, PHY_CR);
|
||
|
|
||
|
rt_kprintf("BCR = 0x%X\tBSR = 0x%X\tPHY_STS = 0x%X\tPHY_CR = 0x%X\n", bcr,bsr,sts, phycr);
|
||
|
|
||
|
rt_kprintf("PHY_FCSCR = 0x%X\n", ETH_ReadPHYRegister(DP83848_PHY_ADDRESS, PHY_FCSCR ) );
|
||
|
rt_kprintf("PHY_MISR = 0x%X\n", ETH_ReadPHYRegister(DP83848_PHY_ADDRESS, PHY_MISR ) );
|
||
|
|
||
|
rt_kprintf("DMASR = 0x%X\n", ETH->DMASR );
|
||
|
|
||
|
//ETH_WritePHYRegister(DP83848_PHY_ADDRESS, PHY_LEDCR, (uint16_t)(0x38 | led));
|
||
|
led = (led==7)?0:7;
|
||
|
|
||
|
}
|
||
|
#ifdef RT_USING_FINSH
|
||
|
#include <finsh.h>
|
||
|
FINSH_FUNCTION_EXPORT(dp83483, Show PHY register.);
|
||
|
#endif
|