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

📄 lpc177x_8x_emac.c

📁 LPC1788的USBHOST的FATFS移植
💻 C
📖 第 1 页 / 共 3 页
字号:

	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 + -