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

📄 lpc177x_8x_emac.c

📁 NXPl788上lwip的无操作系统移植,基于Embest开发板
💻 C
📖 第 1 页 / 共 3 页
字号:
		   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 + -