📄 lpc177x_8x_emac.c
字号:
ulErrCode |= (ulFrameSts & EMAC_TINFO_LATE_COL) ? EMAC_LATE_COLLISION_ERR:0;
ulErrCode |= (ulFrameSts & EMAC_TINFO_UNDERRUN) ? EMAC_UNDERRUN_ERR:0;
ulErrCode |= (ulFrameSts & EMAC_TINFO_NO_DESCR) ? EMAC_TX_NO_DESC_ERR:0;
if(EMAC_Configs.pfnErrorReceive != NULL)
EMAC_Configs.pfnErrorReceive(ulErrCode);
}
if(int_stat & EMAC_INT_RX_DONE)
{
/* Packet received. */
if(EMAC_GetBufferSts(EMAC_RX_BUFF) != EMAC_BUFF_EMPTY)
{
// Get data size
RxLen = EMAC_GetRxFrameSize();
if(RxLen > 0)
{
// trip out 4-bytes CRC field, note that length in (-1) style format
RxLen -= 3;
if((EMAC_GetRxFrameStatus() & EMAC_RINFO_ERR_MASK )== 0)
{
uint16_t *pDest = (uint16_t*) &saFrameBuffers[sbCurrFrameID][sulCurrFrameSz];
uint16_t *pSource = (uint16_t*)EMAC_GetRxBuffer();
sulCurrFrameSz += RxLen;
if(sulCurrFrameSz >= EMAC_MAX_FRAME_SIZE)
{
sulCurrFrameSz = 0;
if(EMAC_Configs.pfnErrorReceive != NULL)
EMAC_Configs.pfnErrorReceive(EMAC_LENGTH_ERR);
}
else
{
// Copy data
while (RxLen > 0)
{
*pDest++ = *pSource++;
RxLen -= 2;
}
if(EMAC_GetRxFrameStatus() & EMAC_RINFO_LAST_FLAG)
{
if(EMAC_Configs.pfnFrameReceive != NULL)
{
EMAC_Configs.pfnFrameReceive((uint16_t*)saFrameBuffers[sbCurrFrameID], sulCurrFrameSz);
}
sulCurrFrameSz = 0;
sbCurrFrameID ++;
if(sbCurrFrameID >= EMAC_MAX_FRAME_NUM)
sbCurrFrameID = 0;
}
/* Release frame from EMAC buffer */
EMAC_UpdateRxConsumeIndex();
}
}
}
}
}
if(int_stat & EMAC_INT_TX_FIN && (EMAC_Configs.pfnTransmitFinish != NULL))
{
EMAC_Configs.pfnTransmitFinish();
}
if(int_stat & EMAC_INT_SOFT_INT && (EMAC_Configs.pfnSoftInt!= NULL))
{
EMAC_Configs.pfnSoftInt();
}
if(int_stat & EMAC_INT_WAKEUP && (EMAC_Configs.pfnWakeup!= NULL))
{
EMAC_Configs.pfnWakeup();
}
}
}
/*********************************************************************//**
* @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;
if((ulFilterMode & EMAC_RFC_MCAST_HASH_EN) &&
((ulFilterMode & EMAC_RFC_MCAST_EN) == 0))
{
LPC_EMAC->RxFilterCtrl &= ~EMAC_RFC_MCAST_EN;
}
if((ulFilterMode & EMAC_RFC_UCAST_HASH_EN) &&
((ulFilterMode & EMAC_RFC_UCAST_EN) == 0))
{
LPC_EMAC->RxFilterCtrl &= ~EMAC_RFC_UCAST_EN;
}
}
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 Enable/Disable interrupt for each type in EMAC
* @param[in] ulIntType Interrupt Type, should be:
* - EMAC_INT_RX_OVERRUN: Receive Overrun
* - EMAC_INT_RX_ERR: Receive Error
* - EMAC_INT_RX_FIN: Receive Descriptor Finish
* - EMAC_INT_RX_DONE: Receive Done
* - EMAC_INT_TX_UNDERRUN: Transmit Under-run
* - EMAC_INT_TX_ERR: Transmit Error
* - EMAC_INT_TX_FIN: Transmit descriptor finish
* - EMAC_INT_TX_DONE: Transmit Done
* - EMAC_INT_SOFT_INT: Software interrupt
* - EMAC_INT_WAKEUP: Wakeup interrupt
* @param[in] NewState New State of this function, should be:
* - ENABLE.
* - DISABLE.
* @return None
**********************************************************************/
void EMAC_IntCmd(uint32_t ulIntType, FunctionalState NewState)
{
if (NewState == ENABLE)
{
LPC_EMAC->IntEnable |= ulIntType;
}
else
{
LPC_EMAC->IntEnable &= ~(ulIntType);
}
}
/*********************************************************************//**
* @brief Check whether if specified interrupt flag is set or not
* for each interrupt type in EMAC and clear interrupt pending
* if it is set.
* @param[in] ulIntType Interrupt Type, should be:
* - EMAC_INT_RX_OVERRUN: Receive Overrun
* - EMAC_INT_RX_ERR: Receive Error
* - EMAC_INT_RX_FIN: Receive Descriptor Finish
* - EMAC_INT_RX_DONE: Receive Done
* - EMAC_INT_TX_UNDERRUN: Transmit Under-run
* - EMAC_INT_TX_ERR: Transmit Error
* - EMAC_INT_TX_FIN: Transmit descriptor finish
* - EMAC_INT_TX_DONE: Transmit Done
* - EMAC_INT_SOFT_INT: Software interrupt
* - EMAC_INT_WAKEUP: Wakeup interrupt
* @return New state of specified interrupt (SET or RESET)
**********************************************************************/
IntStatus EMAC_IntGetStatus(uint32_t ulIntType)
{
if (LPC_EMAC->IntStatus & ulIntType)
{
LPC_EMAC->IntClear = ulIntType;
return SET;
}
else
{
return RESET;
}
}
/**
* @}
*/
/**
* @}
*/
#endif /*_EMAC*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -