📄 stm32_eth.c
字号:
/**
******************************************************************************
* @file stm32_eth.c
* @author MCD Application Team
* @version V1.0.0
* @date 06/19/2009
* @brief This file provides all the ETH firmware functions.
******************************************************************************
* @copy
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>© COPYRIGHT 2009 STMicroelectronics</center></h2>
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32_eth.h"
#include "stm32f10x_rcc.h"
/** @addtogroup STM32_ETH_Driver
* @brief ETH driver modules
* @{
*/
/** @defgroup ETH_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup ETH_Private_Defines
* @{
*/
/* Global pointers on Tx and Rx descriptor used to track transmit and receive descriptors */
ETH_DMADESCTypeDef *DMATxDescToSet;
ETH_DMADESCTypeDef *DMARxDescToGet;
ETH_DMADESCTypeDef *DMAPTPTxDescToSet;
ETH_DMADESCTypeDef *DMAPTPRxDescToGet;
/* ETHERNET MAC address offsets */
#define ETH_MAC_AddrHighBase (ETH_MAC_BASE + 0x40) /* ETHERNET MAC address high offset */
#define ETH_MAC_AddrLowBase (ETH_MAC_BASE + 0x44) /* ETHERNET MAC address low offset */
/* ETHERNET MACMIIAR register Mask */
#define MACMIIAR_CR_Mask ((uint32_t)0xFFFFFFE3)
/* ETHERNET MACCR register Mask */
#define MACCR_CLEAR_Mask ((uint32_t)0xFF20810F)
/* ETHERNET MACFCR register Mask */
#define MACFCR_CLEAR_Mask ((uint32_t)0x0000FF41)
/* ETHERNET DMAOMR register Mask */
#define DMAOMR_CLEAR_Mask ((uint32_t)0xF8DE3F23)
/* ETHERNET Remote Wake-up frame register length */
#define ETH_WakeupRegisterLength 8
/* ETHERNET Missed frames counter Shift */
#define ETH_DMA_RxOverflowMissedFramesCounterShift 17
/* ETHERNET DMA Tx descriptors Collision Count Shift */
#define ETH_DMATxDesc_CollisionCountShift 3
/* ETHERNET DMA Tx descriptors Buffer2 Size Shift */
#define ETH_DMATxDesc_BufferSize2Shift 16
/* ETHERNET DMA Rx descriptors Frame Length Shift */
#define ETH_DMARxDesc_FrameLengthShift 16
/* ETHERNET DMA Rx descriptors Buffer2 Size Shift */
#define ETH_DMARxDesc_Buffer2SizeShift 16
/* ETHERNET errors */
#define ETH_ERROR ((uint32_t)0)
#define ETH_SUCCESS ((uint32_t)1)
/**
* @}
*/
/** @defgroup ETH_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup ETH_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup ETH_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup ETH_Private_Functions
* @{
*/
/**
* @brief Deinitializes the ETHERNET peripheral registers to their
* default reset values.
* @param None
* @retval : None
*/
void ETH_DeInit(void)
{
RCC_AHBPeriphResetCmd(RCC_AHBPeriph_ETH_MAC, ENABLE);
RCC_AHBPeriphResetCmd(RCC_AHBPeriph_ETH_MAC, DISABLE);
}
/**
* @brief Initializes the ETHERNET peripheral according to the specified
* parameters in the ETH_InitStruct .
* @param ETH_InitStruct: pointer to a ETH_InitTypeDef structure
* that contains the configuration information for the
* specified ETHERNET peripheral.
* @param PHYAddress: external PHY address
* @retval : ETH_ERROR: Ethernet initialization failed
* ETH_SUCCESS: Ethernet successfully initialized
*/
uint32_t ETH_Init(ETH_InitTypeDef* ETH_InitStruct, uint16_t PHYAddress)
{
uint32_t RegValue = 0, tmpreg = 0;
__IO uint32_t i = 0;
RCC_ClocksTypeDef rcc_clocks;
uint32_t hclk = 60000000;
__IO uint32_t timeout = 0;
/* Check the parameters */
/* MAC --------------------------*/
assert_param(IS_ETH_AUTONEGOTIATION(ETH_InitStruct->ETH_AutoNegotiation));
assert_param(IS_ETH_WATCHDOG(ETH_InitStruct->ETH_Watchdog));
assert_param(IS_ETH_JABBER(ETH_InitStruct->ETH_Jabber));
assert_param(IS_ETH_INTER_FRAME_GAP(ETH_InitStruct->ETH_InterFrameGap));
assert_param(IS_ETH_CARRIER_SENSE(ETH_InitStruct->ETH_CarrierSense));
assert_param(IS_ETH_SPEED(ETH_InitStruct->ETH_Speed));
assert_param(IS_ETH_RECEIVE_OWN(ETH_InitStruct->ETH_ReceiveOwn));
assert_param(IS_ETH_LOOPBACK_MODE(ETH_InitStruct->ETH_LoopbackMode));
assert_param(IS_ETH_DUPLEX_MODE(ETH_InitStruct->ETH_Mode));
assert_param(IS_ETH_CHECKSUM_OFFLOAD(ETH_InitStruct->ETH_ChecksumOffload));
assert_param(IS_ETH_RETRY_TRANSMISSION(ETH_InitStruct->ETH_RetryTransmission));
assert_param(IS_ETH_AUTOMATIC_PADCRC_STRIP(ETH_InitStruct->ETH_AutomaticPadCRCStrip));
assert_param(IS_ETH_BACKOFF_LIMIT(ETH_InitStruct->ETH_BackOffLimit));
assert_param(IS_ETH_DEFERRAL_CHECK(ETH_InitStruct->ETH_DeferralCheck));
assert_param(IS_ETH_RECEIVE_ALL(ETH_InitStruct->ETH_ReceiveAll));
assert_param(IS_ETH_SOURCE_ADDR_FILTER(ETH_InitStruct->ETH_SourceAddrFilter));
assert_param(IS_ETH_CONTROL_FRAMES(ETH_InitStruct->ETH_PassControlFrames));
assert_param(IS_ETH_BROADCAST_FRAMES_RECEPTION(ETH_InitStruct->ETH_BroadcastFramesReception));
assert_param(IS_ETH_DESTINATION_ADDR_FILTER(ETH_InitStruct->ETH_DestinationAddrFilter));
assert_param(IS_ETH_PROMISCUOUS_MODE(ETH_InitStruct->ETH_PromiscuousMode));
assert_param(IS_ETH_MULTICAST_FRAMES_FILTER(ETH_InitStruct->ETH_MulticastFramesFilter));
assert_param(IS_ETH_UNICAST_FRAMES_FILTER(ETH_InitStruct->ETH_UnicastFramesFilter));
assert_param(IS_ETH_PAUSE_TIME(ETH_InitStruct->ETH_PauseTime));
assert_param(IS_ETH_ZEROQUANTA_PAUSE(ETH_InitStruct->ETH_ZeroQuantaPause));
assert_param(IS_ETH_PAUSE_LOW_THRESHOLD(ETH_InitStruct->ETH_PauseLowThreshold));
assert_param(IS_ETH_UNICAST_PAUSE_FRAME_DETECT(ETH_InitStruct->ETH_UnicastPauseFrameDetect));
assert_param(IS_ETH_RECEIVE_FLOWCONTROL(ETH_InitStruct->ETH_ReceiveFlowControl));
assert_param(IS_ETH_TRANSMIT_FLOWCONTROL(ETH_InitStruct->ETH_TransmitFlowControl));
assert_param(IS_ETH_VLAN_TAG_COMPARISON(ETH_InitStruct->ETH_VLANTagComparison));
assert_param(IS_ETH_VLAN_TAG_IDENTIFIER(ETH_InitStruct->ETH_VLANTagIdentifier));
/* DMA --------------------------*/
assert_param(IS_ETH_DROP_TCPIP_CHECKSUM_FRAME(ETH_InitStruct->ETH_DropTCPIPChecksumErrorFrame));
assert_param(IS_ETH_RECEIVE_STORE_FORWARD(ETH_InitStruct->ETH_ReceiveStoreForward));
assert_param(IS_ETH_FLUSH_RECEIVE_FRAME(ETH_InitStruct->ETH_FlushReceivedFrame));
assert_param(IS_ETH_TRANSMIT_STORE_FORWARD(ETH_InitStruct->ETH_TransmitStoreForward));
assert_param(IS_ETH_TRANSMIT_THRESHOLD_CONTROL(ETH_InitStruct->ETH_TransmitThresholdControl));
assert_param(IS_ETH_FORWARD_ERROR_FRAMES(ETH_InitStruct->ETH_ForwardErrorFrames));
assert_param(IS_ETH_FORWARD_UNDERSIZED_GOOD_FRAMES(ETH_InitStruct->ETH_ForwardUndersizedGoodFrames));
assert_param(IS_ETH_RECEIVE_THRESHOLD_CONTROL(ETH_InitStruct->ETH_ReceiveThresholdControl));
assert_param(IS_ETH_SECOND_FRAME_OPERATE(ETH_InitStruct->ETH_SecondFrameOperate));
assert_param(IS_ETH_ADDRESS_ALIGNED_BEATS(ETH_InitStruct->ETH_AddressAlignedBeats));
assert_param(IS_ETH_FIXED_BURST(ETH_InitStruct->ETH_FixedBurst));
assert_param(IS_ETH_RXDMA_BURST_LENGTH(ETH_InitStruct->ETH_RxDMABurstLength));
assert_param(IS_ETH_TXDMA_BURST_LENGTH(ETH_InitStruct->ETH_TxDMABurstLength));
assert_param(IS_ETH_DMA_DESC_SKIP_LENGTH(ETH_InitStruct->ETH_DescriptorSkipLength));
assert_param(IS_ETH_DMA_ARBITRATION_ROUNDROBIN_RXTX(ETH_InitStruct->ETH_DMAArbitration));
/*-------------------------------- MAC Config ------------------------------*/
/*---------------------- ETHERNET MACMIIAR Configuration -------------------*/
/* Get the ETHERNET MACMIIAR value */
tmpreg = ETH->MACMIIAR;
/* Clear CSR Clock Range CR[2:0] bits */
tmpreg &= MACMIIAR_CR_Mask;
/* Get hclk frequency value */
RCC_GetClocksFreq(&rcc_clocks);
hclk = rcc_clocks.HCLK_Frequency;
/* Set CR bits depending on hclk value */
if((hclk >= 20000000)&&(hclk < 35000000))
{
/* CSR Clock Range between 20-35 MHz */
tmpreg |= (uint32_t)ETH_MACMIIAR_CR_Div16;
}
else if((hclk >= 35000000)&&(hclk < 60000000))
{
/* CSR Clock Range between 35-60 MHz */
tmpreg |= (uint32_t)ETH_MACMIIAR_CR_Div26;
}
else /* ((hclk >= 60000000)&&(hclk <= 72000000)) */
{
/* CSR Clock Range between 60-72 MHz */
tmpreg |= (uint32_t)ETH_MACMIIAR_CR_Div42;
}
/* Write to ETHERNET MAC MIIAR: Configure the ETHERNET CSR Clock Range */
ETH->MACMIIAR = (uint32_t)tmpreg;
/*-------------------- PHY initialization and configuration ----------------*/
/* Put the PHY in reset mode */
if(!(ETH_WritePHYRegister(PHYAddress, PHY_BCR, PHY_Reset)))
{
/* Return ERROR in case of write timeout */
return ETH_ERROR;
}
/* Delay to assure PHY reset */
for(i = PHY_ResetDelay; i != 0; i--)
{
}
if(ETH_InitStruct->ETH_AutoNegotiation != ETH_AutoNegotiation_Disable)
{
/* We wait for linked satus... */
do
{
timeout++;
} while (!(ETH_ReadPHYRegister(PHYAddress, PHY_BSR) & PHY_Linked_Status) && (timeout < PHY_READ_TO));
/* Return ERROR in case of timeout */
if(timeout == PHY_READ_TO)
{
return ETH_ERROR;
}
/* Reset Timeout counter */
timeout = 0;
/* Enable Auto-Negotiation */
if(!(ETH_WritePHYRegister(PHYAddress, PHY_BCR, PHY_AutoNegotiation)))
{
/* Return ERROR in case of write timeout */
return ETH_ERROR;
}
/* Wait until the autonegotiation will be completed */
do
{
timeout++;
} while (!(ETH_ReadPHYRegister(PHYAddress, PHY_BSR) & PHY_AutoNego_Complete) && (timeout < (uint32_t)PHY_READ_TO));
/* Return ERROR in case of timeout */
if(timeout == PHY_READ_TO)
{
return ETH_ERROR;
}
/* Reset Timeout counter */
timeout = 0;
/* Read the result of the autonegotiation */
RegValue = ETH_ReadPHYRegister(PHYAddress, PHY_SR);
/* Configure the MAC with the Duplex Mode fixed by the autonegotiation process */
if((RegValue & PHY_Duplex_Status) != (uint32_t)RESET)
{
/* Set Ethernet duplex mode to FullDuplex following the autonegotiation */
ETH_InitStruct->ETH_Mode = ETH_Mode_FullDuplex;
}
else
{
/* Set Ethernet duplex mode to HalfDuplex following the autonegotiation */
ETH_InitStruct->ETH_Mode = ETH_Mode_HalfDuplex;
}
/* Configure the MAC with the speed fixed by the autonegotiation process */
if(RegValue & PHY_Speed_Status)
{
/* Set Ethernet speed to 10M following the autonegotiation */
ETH_InitStruct->ETH_Speed = ETH_Speed_10M;
}
else
{
/* Set Ethernet speed to 100M following the autonegotiation */
ETH_InitStruct->ETH_Speed = ETH_Speed_100M;
}
}
else
{
if(!ETH_WritePHYRegister(PHYAddress, PHY_BCR, ((uint16_t)(ETH_InitStruct->ETH_Mode >> 3) |
(uint16_t)(ETH_InitStruct->ETH_Speed >> 1))))
{
/* Return ERROR in case of write timeout */
return ETH_ERROR;
}
/* Delay to assure PHY configuration */
for(i = PHY_ConfigDelay; i != 0; i--)
{
}
}
/*------------------------ ETHERNET MACCR Configuration --------------------*/
/* Get the ETHERNET MACCR value */
tmpreg = ETH->MACCR;
/* Clear WD, PCE, PS, TE and RE bits */
tmpreg &= MACCR_CLEAR_Mask;
/* Set the WD bit according to ETH_Watchdog value */
/* Set the JD: bit according to ETH_Jabber value */
/* Set the IFG bit according to ETH_InterFrameGap value */
/* Set the DCRS bit according to ETH_CarrierSense value */
/* Set the FES bit according to ETH_Speed value */
/* Set the DO bit according to ETH_ReceiveOwn value */
/* Set the LM bit according to ETH_LoopbackMode value */
/* Set the DM bit according to ETH_Mode value */
/* Set the IPC bit according to ETH_ChecksumOffload value */
/* Set the DR bit according to ETH_RetryTransmission value */
/* Set the ACS bit according to ETH_AutomaticPadCRCStrip value */
/* Set the BL bit according to ETH_BackOffLimit value */
/* Set the DC bit according to ETH_DeferralCheck value */
tmpreg |= (uint32_t)(ETH_InitStruct->ETH_Watchdog |
ETH_InitStruct->ETH_Jabber |
ETH_InitStruct->ETH_InterFrameGap |
ETH_InitStruct->ETH_CarrierSense |
ETH_InitStruct->ETH_Speed |
ETH_InitStruct->ETH_ReceiveOwn |
ETH_InitStruct->ETH_LoopbackMode |
ETH_InitStruct->ETH_Mode |
ETH_InitStruct->ETH_ChecksumOffload |
ETH_InitStruct->ETH_RetryTransmission |
ETH_InitStruct->ETH_AutomaticPadCRCStrip |
ETH_InitStruct->ETH_BackOffLimit |
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -