📄 lpc177x_8x_emac.c
字号:
switch(ulPHYState)
{
case EMAC_PHY_STAT_LINK:
tmp = (regv & EMAC_PHY_REG_BMSR) ? 1 : 0;
break;
case EMAC_PHY_STAT_SPEED:
tmp = ((regv & EMAC_PHY_BMSR_100BT4)
|| (regv & EMAC_PHY_BMSR_100TX_FULL)
|| (regv & EMAC_PHY_BMSR_100TX_HALF)) ? 1 : 0;
break;
case EMAC_PHY_STAT_DUP:
tmp = ((regv & EMAC_PHY_BMSR_100TX_FULL)
|| (regv & EMAC_PHY_BMSR_10BT_FULL)) ? 1 : 0;
break;
default:
tmp = -1;
break;
}
return (tmp);
}
/*********************************************************************//**
* @brief Set specified PHY mode in EMAC peripheral
* @param[in] ulPHYState Specified PHY mode, should be:
* - EMAC_MODE_AUTO
* - EMAC_MODE_10M_FULL
* - EMAC_MODE_10M_HALF
* - EMAC_MODE_100M_FULL
* - EMAC_MODE_100M_HALF
* @return Return (0) if no error, otherwise return (-1)
**********************************************************************/
int32_t EMAC_SetPHYMode(uint32_t ulPHYMode)
{
int32_t id1, id2, tout, regv;
/* Check if this is a DP83848C PHY. */
id1 = read_PHY (EMAC_PHY_REG_IDR1);
id2 = read_PHY (EMAC_PHY_REG_IDR2);
if ((id1 == EMAC_PHY_ID1_CRIT) && ((id2 >> 4) == EMAC_PHY_ID2_CRIT))
{
/* Configure the PHY device */
switch(ulPHYMode)
{
case EMAC_MODE_AUTO:
/* Use auto-negotiation about the link speed. */
write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_AUTO_NEG);
/* Wait to complete Auto_Negotiation */
for (tout = EMAC_PHY_RESP_TOUT; tout; tout--)
{
regv = read_PHY (EMAC_PHY_REG_BMSR);
if (regv & EMAC_PHY_BMSR_AUTO_DONE)
{
/* Auto-negotiation Complete. */
break;
}
if (tout == 0)
{
// Time out, return error
return (-1);
}
}
break;
case EMAC_MODE_10M_FULL:
/* Connect at 10MBit full-duplex */
write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_FULLD_10M);
break;
case EMAC_MODE_10M_HALF:
/* Connect at 10MBit half-duplex */
write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_HALFD_10M);
break;
case EMAC_MODE_100M_FULL:
/* Connect at 100MBit full-duplex */
write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_FULLD_100M);
break;
case EMAC_MODE_100M_HALF:
/* Connect at 100MBit half-duplex */
write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_HALFD_100M);
break;
default:
// un-supported
return (-1);
}
}
// It's not correct module ID
else
{
return (-1);
}
// Update EMAC configuration with current PHY status
if (EMAC_UpdatePHYStatus() < 0)
{
return (-1);
}
// Complete
return (0);
}
/*********************************************************************//**
* @brief Auto-Configures value for the EMAC configuration register to
* match with current PHY mode
* @param[in] None
* @return Return (0) if no error, otherwise return (-1)
*
* Note: The EMAC configuration will be auto-configured:
* - Speed mode.
* - Half/Full duplex mode
**********************************************************************/
int32_t EMAC_UpdatePHYStatus(void)
{
int32_t regv, tout;
/* Check the link status. */
for (tout = EMAC_PHY_RESP_TOUT; tout; tout--)
{
regv = read_PHY (EMAC_PHY_REG_BMSR);
//Check Link Status
if (regv & EMAC_PHY_BMSR_LINK_ESTABLISHED)
{
/* Link is on. */
break;
}
if (tout == 0)
{
// time out
return (-1);
}
}
/* Configure Full/Half Duplex mode. */
if((regv & EMAC_PHY_BMSR_100TX_FULL) || (regv & EMAC_PHY_BMSR_10BT_FULL))
{
/* Full duplex is enabled. */
LPC_EMAC->MAC2 |= EMAC_MAC2_FULL_DUP;
LPC_EMAC->Command |= EMAC_CR_FULL_DUP;
LPC_EMAC->IPGT = EMAC_IPGT_FULL_DUP;
}
else if ((regv & EMAC_PHY_BMSR_100TX_HALF) || (regv & EMAC_PHY_BMSR_10BT_HALF))
{
/* Half duplex mode. */
LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP;
}
/* Configure 100MBit/10MBit mode. */
if ((regv & EMAC_PHY_BMSR_100BT4)
|| (regv & EMAC_PHY_BMSR_100TX_FULL)
|| (regv & EMAC_PHY_BMSR_100TX_HALF))
{
/* 100MBit mode. */
LPC_EMAC->SUPP = EMAC_SUPP_SPEED;
}
else if((regv & EMAC_PHY_BMSR_10BT_FULL) || (regv & EMAC_PHY_BMSR_10BT_HALF))
{
/* 10MBit mode. */
LPC_EMAC->SUPP = 0;
}
// Complete
return (0);
}
/*********************************************************************//**
* @brief Enable/Disable hash filter functionality for specified destination
* MAC address in EMAC module
* @param[in] dstMAC_addr Pointer to the first MAC destination address, should
* be 6-bytes length, in order LSB to the MSB
* @param[in] NewState New State of this command, should be:
* - ENABLE.
* - DISABLE.
* @return None
*
* Note:
* The standard Ethernet cyclic redundancy check (CRC) function is calculated from
* the 6 byte destination address in the Ethernet frame (this CRC is calculated
* anyway as part of calculating the CRC of the whole frame), then bits [28:23] out of
* the 32 bits CRC result are taken to form the hash. The 6 bit hash is used to access
* the hash table: it is used as an index in the 64 bit HashFilter register that has been
* programmed with accept values. If the selected accept value is 1, the frame is
* accepted.
**********************************************************************/
void EMAC_SetHashFilter(uint8_t dstMAC_addr[], FunctionalState NewState)
{
uint32_t *pReg;
uint32_t tmp;
int32_t crc;
// Calculate the CRC from the destination MAC address
crc = EMAC_CRCCalc(dstMAC_addr, 6);
// Extract the value from CRC to get index value for hash filter table
crc = (crc >> 23) & 0x3F;
pReg = (crc > 31) ? ((uint32_t *)&LPC_EMAC->HashFilterH) \
: ((uint32_t *)&LPC_EMAC->HashFilterL);
tmp = (crc > 31) ? (crc - 32) : crc;
if (NewState == ENABLE)
{
(*pReg) |= (1UL << tmp);
}
else
{
(*pReg) &= ~(1UL << tmp);
}
}
/*********************************************************************//**
* @brief Calculates CRC code for number of bytes in the frame
* @param[in] frame_no_fcs Pointer to the first byte of the frame
* @param[in] frame_len length of the frame without the FCS
* @return the CRC as a 32 bit integer
**********************************************************************/
int32_t EMAC_CRCCalc(uint8_t frame_no_fcs[], int32_t frame_len)
{
int i; // iterator
int j; // another iterator
char byte; // current byte
int crc; // CRC result
int q0, q1, q2, q3; // temporary variables
crc = 0xFFFFFFFF;
for (i = 0; i < frame_len; i++)
{
byte = *frame_no_fcs++;
for (j = 0; j < 2; j++)
{
if (((crc >> 28) ^ (byte >> 3)) & 0x00000001)
{
q3 = 0x04C11DB7;
}
else
{
q3 = 0x00000000;
}
if (((crc >> 29) ^ (byte >> 2)) & 0x00000001)
{
q2 = 0x09823B6E;
}
else
{
q2 = 0x00000000;
}
if (((crc >> 30) ^ (byte >> 1)) & 0x00000001)
{
q1 = 0x130476DC;
}
else
{
q1 = 0x00000000;
}
if (((crc >> 31) ^ (byte >> 0)) & 0x00000001)
{
q0 = 0x2608EDB8;
}
else
{
q0 = 0x00000000;
}
crc = (crc << 4) ^ q3 ^ q2 ^ q1 ^ q0;
byte >>= 4;
}
}
return crc;
}
/*********************************************************************//**
* @brief Enable/Disable Filter mode for each specified type EMAC peripheral
* @param[in] ulFilterMode Filter mode, should be:
* - EMAC_RFC_UCAST_EN: all frames of unicast types
* will be accepted
* - EMAC_RFC_BCAST_EN: broadcast frame will be
* accepted
* - EMAC_RFC_MCAST_EN: all frames of multicast
* types will be accepted
* - EMAC_RFC_UCAST_HASH_EN: The imperfect hash
* filter will be applied to unicast addresses
* - EMAC_RFC_MCAST_HASH_EN: The imperfect hash
* filter will be applied to multicast addresses
* - EMAC_RFC_PERFECT_EN: the destination address
* will be compared with the 6 byte station address
* programmed in the station address by the filter
* - EMAC_RFC_MAGP_WOL_EN: the result of the magic
* packet filter will generate a WoL interrupt when
* there is a match
* - EMAC_RFC_PFILT_WOL_EN: the result of the perfect address
* matching filter and the imperfect hash filter will
* generate a WoL interrupt when there is a match
* @param[in] NewState New State of this command, should be:
* - ENABLE
* - DISABLE
* @return None
**********************************************************************/
void EMAC_SetFilterMode(uint32_t ulFilterMode, FunctionalState NewState)
{
if (NewState == ENABLE)
{
LPC_EMAC->RxFilterCtrl |= ulFilterMode;
}
else
{
LPC_EMAC->RxFilterCtrl &= ~ulFilterMode;
}
}
/*********************************************************************//**
* @brief Get status of Wake On LAN Filter for each specified
* type in EMAC peripheral, clear this status if it is set
* @param[in] ulFilterMode WoL Filter mode, should be:
* - EMAC_WOL_UCAST: unicast frames caused WoL
* - EMAC_WOL_UCAST: broadcast frame caused WoL
* - EMAC_WOL_MCAST: multicast frame caused WoL
* - EMAC_WOL_UCAST_HASH: unicast frame that passes the
* imperfect hash filter caused WoL
* - EMAC_WOL_MCAST_HASH: multicast frame that passes the
* imperfect hash filter caused WoL
* - EMAC_WOL_PERFECT:perfect address matching filter
* caused WoL
* - EMAC_WOL_RX_FILTER: the receive filter caused WoL
* - EMAC_WOL_MAG_PACKET: the magic packet filter caused WoL
* @return SET/RESET
**********************************************************************/
FlagStatus EMAC_GetWoLStatus(uint32_t ulWoLMode)
{
if (LPC_EMAC->RxFilterWoLStatus & ulWoLMode)
{
LPC_EMAC->RxFilterWoLClear = ulWoLMode;
return SET;
}
else
{
return RESET;
}
}
/*********************************************************************//**
* @brief Write data to Tx packet data buffer at current index due to
* TxProduceIndex
* @param[in] pDataStruct Pointer to a EMAC_PACKETBUF_Type structure
* data that contain specified information about
* Packet data buffer.
* @return None
**********************************************************************/
void EMAC_WritePacketBuffer(EMAC_PACKETBUF_Type *pDataStruct)
{
uint32_t idx,len;
uint32_t *sp,*dp;
idx = LPC_EMAC->TxProduceIndex;
sp = (uint32_t *)pDataStruct->pbDataBuf;
dp = (uint32_t *)TX_DESC_PACKET(idx);
/* Copy frame data to EMAC packet buffers. */
for (len = (pDataStruct->ulDataLen + 3) >> 2; len; len--)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -