📄 lpc177x_8x_emac.c
字号:
*dp++ = *sp++;
}
TX_DESC_CTRL(idx) = (pDataStruct->ulDataLen - 1) | (EMAC_TCTRL_INT | EMAC_TCTRL_LAST);
}
/*********************************************************************//**
* @brief Read data from Rx packet data buffer at current index due
* to RxConsumeIndex
* @param[in] pDataStruct Pointer to a EMAC_PACKETBUF_Type structure
* data that contain specified information about
* Packet data buffer.
* @return None
**********************************************************************/
void EMAC_ReadPacketBuffer(EMAC_PACKETBUF_Type *pDataStruct)
{
uint32_t idx, len;
uint32_t *dp, *sp;
idx = LPC_EMAC->RxConsumeIndex;
dp = (uint32_t *)pDataStruct->pbDataBuf;
sp = (uint32_t *)RX_DESC_PACKET(idx);
if (pDataStruct->pbDataBuf != NULL)
{
for (len = (pDataStruct->ulDataLen + 3) >> 2; len; len--)
{
*dp++ = *sp++;
}
}
}
/*********************************************************************//**
* @brief Configure the TX Descript control and return the address of
* TX_DESC_PACKET buffer
* @param[in] FrameSize The size of frame you want to send
* @return Address of the TX_DESC_PACKET buffer
**********************************************************************/
uint32_t EMAC_RequestSend(uint16_t FrameSize)
{
uint32_t idx;
uint32_t dp;
idx = LPC_EMAC->TxProduceIndex;
dp = TX_DESC_PACKET(idx);
TX_DESC_CTRL(idx) = (FrameSize) | (EMAC_TCTRL_INT | EMAC_TCTRL_LAST);
return dp;
}
/*********************************************************************//**
* @brief Get the address of TX_DESC_PACKET buffer so that user can access from application
* @param[in] None
* @return Address of the TX_DESC_PACKET buffer
**********************************************************************/
uint32_t EMAC_GetReadPacketBuffer(void)
{
uint32_t idx;
idx = LPC_EMAC->RxConsumeIndex;
return RX_DESC_PACKET(idx);
}
/*********************************************************************//**
* @brief Get the address of TX_DESC_PACKET buffer so that user can access from application
* @param[in] None
* @return Address of the TX_DESC_PACKET buffer
**********************************************************************/
uint32_t EMAC_GetWritePacketBuffer(void)
{
uint32_t idx;
idx = LPC_EMAC->TxProduceIndex;
return TX_DESC_PACKET(idx);
}
/*********************************************************************//**
* @brief Standard EMAC IRQ Handler. This sub-routine will check
* these following interrupt and call the call-back function
* if they're already installed:
* - Overrun Error interrupt in RX Queue
* - Receive Error interrupt: AlignmentError, RangeError,
* LengthError, SymbolError, CRCError or NoDescriptor or Overrun
* - RX Finished Process Descriptors interrupt (ProduceIndex == ConsumeIndex)
* - Receive Done interrupt
* - Transmit Under-run interrupt
* - Transmit errors interrupt : LateCollision, ExcessiveCollision
* and ExcessiveDefer, NoDescriptor or Under-run
* - TX Finished Process Descriptors interrupt (ProduceIndex == ConsumeIndex)
* - Transmit Done interrupt
* - Interrupt triggered by software
* - Interrupt triggered by a Wakeup event detected by the receive filter
* @param[in] None
* @return None
**********************************************************************/
void EMAC_StandardIRQHandler(void)
{
/* EMAC Ethernet Controller Interrupt function. */
uint32_t n, int_stat;
// Get EMAC interrupt status
while ((int_stat = (LPC_EMAC->IntStatus & LPC_EMAC->IntEnable)) != 0)
{
// Clear interrupt status
LPC_EMAC->IntClear = int_stat;
// Execute call-back function
for (n = 0; n <= 7; n++)
{
if ((int_stat & (1 << n)) && (_pfnIntCbDat[n] != NULL))
{
_pfnIntCbDat[n]();
}
}
// Soft interrupt
if ((int_stat & EMAC_INT_SOFT_INT) && (_pfnIntCbDat[8] != NULL))
{
_pfnIntCbDat[8]();
}
// WakeUp interrupt
if ((int_stat & EMAC_INT_WAKEUP) && (_pfnIntCbDat[9] != NULL))
{
// Clear WoL interrupt
LPC_EMAC->RxFilterWoLClear = EMAC_WOL_BITMASK;
_pfnIntCbDat[9]();
}
}
}
/*********************************************************************//**
* @brief Setup/register Call-back function for each interrupt type
* in EMAC module.
* @param[in] ulIntType Interrupt type, should be one of the following:
* - 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] pfnIntCb Pointer to Call-back function used for this
* interrupt type
* @return None
**********************************************************************/
void EMAC_SetupIntCBS(uint32_t ulIntType, EMAC_IntCBSType *pfnIntCb)
{
/* EMAC Ethernet Controller Interrupt function. */
uint32_t n;
if (ulIntType <= EMAC_INT_TX_DONE)
{
for (n = 0; n <= 7; n++)
{
// Found it, install cbs now
if (ulIntType & (1 << n))
{
_pfnIntCbDat[n] = pfnIntCb;
// Don't install cbs any more
break;
}
}
}
else if (ulIntType & EMAC_INT_SOFT_INT)
{
_pfnIntCbDat[8] = pfnIntCb;
}
else if (ulIntType & EMAC_INT_WAKEUP)
{
_pfnIntCbDat[9] = pfnIntCb;
}
}
/*********************************************************************//**
* @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;
}
}
/*********************************************************************//**
* @brief Check whether if the current RxConsumeIndex is not equal to the
* current RxProduceIndex.
* @param[in] None
* @return TRUE if they're not equal, otherwise return FALSE
*
* Note: In case the RxConsumeIndex is not equal to the RxProduceIndex,
* it means there're available data has been received. They should be read
* out and released the Receive Data Buffer by updating the RxConsumeIndex value.
**********************************************************************/
int32_t EMAC_CheckReceiveIndex(void)
{
if (LPC_EMAC->RxConsumeIndex != LPC_EMAC->RxProduceIndex)
{
return TRUE;
}
else
{
return FALSE;
}
}
/*********************************************************************//**
* @brief Check whether if the current TxProduceIndex is not equal to the
* current RxProduceIndex - 1.
* @param[in] None
* @return TRUE if they're not equal, otherwise return FALSE
*
* Note: In case the RxConsumeIndex is equal to the RxProduceIndex - 1,
* it means the transmit buffer is available and data can be written to transmit
* buffer to be sent.
**********************************************************************/
int32_t EMAC_CheckTransmitIndex(void)
{
uint32_t tmp = LPC_EMAC->TxConsumeIndex -1;
if (LPC_EMAC->TxProduceIndex == tmp)
{
return FALSE;
}
else
{
return TRUE;
}
}
/*********************************************************************//**
* @brief Get current status value of receive data (due to RxConsumeIndex)
* @param[in] ulRxDatStat Received Status type, should be one of following:
* - EMAC_RINFO_CTRL_FRAME: Control Frame
* - EMAC_RINFO_VLAN: VLAN Frame
* - EMAC_RINFO_FAIL_FILT: RX Filter Failed
* - EMAC_RINFO_MCAST: Multicast Frame
* - EMAC_RINFO_BCAST: Broadcast Frame
* - EMAC_RINFO_CRC_ERR: CRC Error in Frame
* - EMAC_RINFO_SYM_ERR: Symbol Error from PHY
* - EMAC_RINFO_LEN_ERR: Length Error
* - EMAC_RINFO_RANGE_ERR: Range error(exceeded max size)
* - EMAC_RINFO_ALIGN_ERR: Alignment error
* - EMAC_RINFO_OVERRUN: Receive overrun
* - EMAC_RINFO_NO_DESCR: No new Descriptor available
* - EMAC_RINFO_LAST_FLAG: last Fragment in Frame
* - EMAC_RINFO_ERR: Error Occurred (OR of all error)
* @return Current value of receive data (due to RxConsumeIndex)
**********************************************************************/
FlagStatus EMAC_CheckReceiveDataStatus(uint32_t ulRxStatType)
{
uint32_t idx;
idx = LPC_EMAC->RxConsumeIndex;
return (((RX_STAT_INFO(idx)) & ulRxStatType) ? SET : RESET);
}
/*********************************************************************//**
* @brief Get size of current Received data in received buffer (due to
* RxConsumeIndex)
* @param[in] None
* @return Size of received data
**********************************************************************/
uint32_t EMAC_GetReceiveDataSize(void)
{
uint32_t idx;
idx = LPC_EMAC->RxConsumeIndex;
return ((RX_STAT_INFO(idx)) & EMAC_RINFO_SIZE);
}
/*********************************************************************//**
* @brief Increase the RxConsumeIndex (after reading the Receive buffer
* to release the Receive buffer) and wrap-around the index if
* it reaches the maximum Receive Number
* @param[in] None
* @return None
**********************************************************************/
void EMAC_UpdateRxConsumeIndex(void)
{
// Get current Rx consume index
uint32_t idx = LPC_EMAC->RxConsumeIndex;
/* Release frame from EMAC buffer */
if (++idx == EMAC_NUM_RX_FRAG) idx = 0;
LPC_EMAC->RxConsumeIndex = idx;
}
/*********************************************************************//**
* @brief Increase the TxProduceIndex (after writting to the Transmit buffer
* to enable the Transmit buffer) and wrap-around the index if
* it reaches the maximum Transmit Number
* @param[in] None
* @return None
**********************************************************************/
void EMAC_UpdateTxProduceIndex(void)
{
// Get current Tx produce index
uint32_t idx = LPC_EMAC->TxProduceIndex;
/* Start frame transmission */
if (++idx == EMAC_NUM_TX_FRAG) idx = 0;
LPC_EMAC->TxProduceIndex = idx;
}
/**
* @}
*/
/**
* @}
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -