⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lpc177x_8x_emac.c

📁 NXPl788上lwip的无操作系统移植,基于Embest开发板
💻 C
📖 第 1 页 / 共 3 页
字号:
 * @brief		De-initializes the EMAC peripheral registers to their
*                  default reset values.
 * @param[in]	None
 * @return 		None
 **********************************************************************/
void EMAC_DeInit(void)
{
	// Disable all interrupt
	LPC_EMAC->IntEnable = 0x00;

	// Clear all pending interrupt
	LPC_EMAC->IntClear = (0xFF) | (EMAC_INT_SOFT_INT | EMAC_INT_WAKEUP);

	LPC_EMAC->Command = 0;

	/* TurnOff power for Ethernet module */
	CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCENET, DISABLE);
}

/*********************************************************************//**
 * @brief		EMAC TX API modules
 * @param[in]	None
 * @return 		None
 **********************************************************************/
void EMAC_TxEnable( void )
{
	LPC_EMAC->Command |= EMAC_CR_TX_EN;
	return;
}


/*********************************************************************//**
 * @brief		EMAC RX API modules
 * @param[in]	None
 * @return 		None
 **********************************************************************/
void EMAC_TxDisable( void )
{
	LPC_EMAC->Command &= ~EMAC_CR_TX_EN;
	return;
}

/*********************************************************************//**
 * @brief		EMAC RX API modules
 * @param[in]	None
 * @return 		None
 **********************************************************************/
void EMAC_RxEnable( void )
{
	LPC_EMAC->Command |= EMAC_CR_RX_EN;
	LPC_EMAC->MAC1 |= EMAC_MAC1_REC_EN;
	return;
}

/*********************************************************************//**
 * @brief		EMAC RX API modules
 * @param[in]	None
 * @return 		None
 **********************************************************************/
void EMAC_RxDisable( void )
{
	LPC_EMAC->Command &= ~EMAC_CR_RX_EN;
	LPC_EMAC->MAC1 &= ~EMAC_MAC1_REC_EN;
	return;
}

/*********************************************************************//**
 * @brief		Get the status of  given buffer.
 * @param[in]	 idx   Buffer index
 * @return	 EMAC_BUFF_AVAILABLE/EMAC_BUFF_FULL/EMAC_BUFF_PARTIAL_FULL
 *
 **********************************************************************/
EMAC_BUFF_STATUS EMAC_GetBufferSts(EMAC_BUFF_IDX idx)
{
    uint32_t consume_idx, produce_idx;
    uint32_t max_frag_num;

    // Get the consume index, produce index and the buffer size
    if(idx == EMAC_TX_BUFF)
    {
        consume_idx = LPC_EMAC->TxConsumeIndex;
        produce_idx = LPC_EMAC->TxProduceIndex;
        max_frag_num = LPC_EMAC->TxDescriptorNumber + 1;
    }
    else
    {
        consume_idx = LPC_EMAC->RxConsumeIndex;
        produce_idx = LPC_EMAC->RxProduceIndex;
        max_frag_num = LPC_EMAC->RxDescriptorNumber + 1;
    }

    // empty
    if(consume_idx == produce_idx)
        return EMAC_BUFF_EMPTY;

    // Full
    if(consume_idx == 0 &&
        produce_idx == max_frag_num - 1)
        return EMAC_BUFF_FULL;
	
    // Wrap-around
    if(consume_idx == produce_idx + 1)
        return EMAC_BUFF_FULL;	

    return EMAC_BUFF_PARTIAL_FULL;
}

/*********************************************************************//**
 * @brief		Allocate a descriptor for sending frame and get the coressponding buffer address
 * @param[in]	FrameSize		The size of frame you want to send
 * @return	Address of the TX_DESC_PACKET buffer
 **********************************************************************/
 uint32_t EMAC_AllocTxBuff(uint16_t nFrameSize, uint8_t bLastFrame)
{
    uint32_t idx;
    uint32_t  dp;
    uint32_t i;

    idx = LPC_EMAC->TxProduceIndex;

    while(EMAC_GetBufferSts(EMAC_TX_BUFF) == EMAC_BUFF_FULL)
    {
      for(i = 0; i < 1000000; i++) ; 
    }

    dp = TX_DESC_PACKET(idx);

    if(bLastFrame)
      TX_DESC_CTRL(idx) = ((nFrameSize-1) & EMAC_TCTRL_SIZE) | (EMAC_TCTRL_INT | EMAC_TCTRL_LAST);
    else
      TX_DESC_CTRL(idx) = ((nFrameSize-1) & EMAC_TCTRL_SIZE) | (EMAC_TCTRL_INT);

    return dp;
}

/*********************************************************************//**
 * @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 == LPC_EMAC->TxDescriptorNumber + 1) idx = 0;
	LPC_EMAC->TxProduceIndex = idx;
}

/*********************************************************************//**
 * @brief	Get current status value of receive data (due to TxProduceIndex)
 * @param[in]	None	
 * @return	Current value of receive data (due to TxProduceIndex)
 **********************************************************************/
uint32_t EMAC_GetTxFrameStatus(void)
{
	uint32_t idx;

	idx = LPC_EMAC->TxProduceIndex;
	return (TX_STAT_INFO(idx));
}

/*********************************************************************//**
 * @brief	Write data to Tx packet data buffer at current index due to
 * 				TxProduceIndex
 * @param[in]	pDataStruct	store the address and the size of buffer that saves data.
 * @return		None
 **********************************************************************/
void EMAC_WritePacketBuffer(EMAC_PACKETBUF_Type *pDataStruct)
{
   uint16_t* pDest;
   uint16_t* pSource = (uint16_t*)pDataStruct->pbDataBuf;
   uint32_t  size = pDataStruct->ulDataLen;
   int32_t  frame_num;
   uint32_t tmp;
   uint32_t max_frame_size = LPC_EMAC->MAXF;
   
   size = (size + 1) & 0xFFFE;    // round Size up to next even number
   frame_num = size/max_frame_size;

   if(size == 0)
   	return;

   while(frame_num >= 0)
   {
     tmp = (frame_num > 0)? max_frame_size:size;

     if(tmp == 0)
	    break;
	 
     // Setup descriptors and data
     if(frame_num == 0)
       pDest = (uint16_t*)EMAC_AllocTxBuff(tmp, 1);  // last frame
     else
       pDest = (uint16_t*)EMAC_AllocTxBuff(tmp, 0);
	 
     // Copy data
     while (tmp > 0)
     {
       *pDest++ = *pSource++;
       tmp -= 2;
     }
     frame_num--;
     size -= tmp;

     // Update produce index
     EMAC_UpdateTxProduceIndex();
   } 
}


/*********************************************************************//**
 * @brief		Get current status value of receive data (due to RxConsumeIndex)
 * @param[in]	None	
 * @return	Current value of receive data (due to RxConsumeIndex)
 **********************************************************************/
uint32_t EMAC_GetRxFrameStatus(void)
{
	uint32_t idx;

	idx = LPC_EMAC->RxConsumeIndex;
	return (RX_STAT_INFO(idx));
}


/*********************************************************************//**
 * @brief		Get size of current Received data in received buffer (due to
 * 				RxConsumeIndex)
 * @param[in]	None
 * @return		Size of received data
 **********************************************************************/
uint32_t EMAC_GetRxFrameSize(void)
{
	uint32_t idx;

	idx = LPC_EMAC->RxConsumeIndex;

	return (((RX_STAT_INFO(idx)) & EMAC_RINFO_SIZE)+1);
}


/*********************************************************************//**
 * @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_GetRxBuffer(void)
{
	uint32_t idx;

	idx = LPC_EMAC->RxConsumeIndex;

  	return RX_DESC_PACKET(idx);
 }


/*********************************************************************//**
 * @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		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: Read received frame to the internal buffer
 * 				- 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 ENET_IRQHandler(void)
{
	/* EMAC Ethernet Controller Interrupt function. */
	uint32_t int_stat;
	int32_t RxLen;
	
	// Get EMAC interrupt status
	while ((int_stat = (LPC_EMAC->IntStatus & LPC_EMAC->IntEnable)) != 0)
	{
		// Clear interrupt status
		LPC_EMAC->IntClear = int_stat;
	 
	    if(int_stat & (EMAC_INT_RX_OVERRUN |EMAC_INT_RX_ERR ))
		{
		   uint32_t ulFrameSts = EMAC_GetRxFrameStatus();
		   uint32_t ulErrCode = 0;

		   ulErrCode |= (ulFrameSts & EMAC_RINFO_CRC_ERR) ? EMAC_CRC_ERR:0;
		   ulErrCode |= (ulFrameSts & EMAC_RINFO_SYM_ERR) ? EMAC_SYMBOL_ERR:0;
		   ulErrCode |= (ulFrameSts & EMAC_RINFO_LEN_ERR) ? EMAC_LENGTH_ERR:0;
		   ulErrCode |= (ulFrameSts & EMAC_RINFO_ALIGN_ERR) ? EMAC_ALIGN_ERR:0;
		   ulErrCode |= (ulFrameSts & EMAC_RINFO_OVERRUN) ? EMAC_OVERRUN_ERR:0;
		   ulErrCode |= (ulFrameSts & EMAC_RINFO_NO_DESCR) ? EMAC_RX_NO_DESC_ERR:0;
		   ulErrCode |= (ulFrameSts & EMAC_RINFO_FAIL_FILT) ? EMAC_FILTER_FAILED_ERR:0;
		   
		   if(ulErrCode == 0)
		   {
		      /* Note:
		          * The EMAC doesn't distinguish the frame type and frame length,
		          * so, e.g. when the IP(0x8000) or ARP(0x0806) packets are received,
		          * it compares the frame type with the max length and gives the
		          * "Range" error. In fact, this bit is not an error indication,
		          * but simply a statement by the chip regarding the status of
		          * the received frame
		          */
		      int_stat &= ~EMAC_INT_RX_ERR;
		   }
		   else
		   {
		     if(EMAC_Configs.pfnErrorReceive != NULL)
		       EMAC_Configs.pfnErrorReceive(ulErrCode);
		   	}
		}

		if(int_stat & (EMAC_INT_TX_UNDERRUN|EMAC_INT_TX_ERR ))
		{
		   uint32_t ulFrameSts = EMAC_GetTxFrameStatus();
		   uint32_t ulErrCode = 0;

		   ulErrCode |= (ulFrameSts & EMAC_TINFO_EXCESS_DEF) ? EMAC_EXCESSIVE_DEFER_ERR:0;
		   ulErrCode |= (ulFrameSts & EMAC_TINFO_EXCESS_COL) ? EMAC_EXCESSIVE_COLLISION_ERR:0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -