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

📄 lpc17xx_emac.c

📁 uCOSII_lwip_lpc1768
💻 C
📖 第 1 页 / 共 3 页
字号:
	// Write to MAC configuration register and reset
	LPC_EMAC->MCFG = EMAC_MCFG_CLK_SEL(tout) | EMAC_MCFG_RES_MII;
	// release reset
	LPC_EMAC->MCFG &= ~(EMAC_MCFG_RES_MII);
	LPC_EMAC->CLRT = EMAC_CLRT_DEF;
	LPC_EMAC->IPGR = EMAC_IPGR_P2_DEF;

	/* Enable Reduced MII interface. */
	LPC_EMAC->Command = EMAC_CR_RMII | EMAC_CR_PASS_RUNT_FRM;

	/* Reset Reduced MII Logic. */
	LPC_EMAC->SUPP = EMAC_SUPP_RES_RMII;

	for (tout = 100; tout; tout--);
	LPC_EMAC->SUPP = 0;

	/* Put the DP83848C in reset mode */
	write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_BMCR_RESET);

	/* Wait for hardware reset to end. */
	for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) {
		regv = read_PHY (EMAC_PHY_REG_BMCR);
		if (!(regv & (EMAC_PHY_BMCR_RESET | EMAC_PHY_BMCR_POWERDOWN))) {
			/* Reset complete, device not Power Down. */
			break;
		}
		if (tout == 0){
			// Time out, return ERROR
			return (ERROR);
		}
	}

	// Set PHY mode
	if (EMAC_SetPHYMode(EMAC_ConfigStruct->Mode) < 0){
		return (ERROR);
	}

	// Set EMAC address
	setEmacAddr(EMAC_ConfigStruct->pbEMAC_Addr);

	/* Initialize Tx and Rx DMA Descriptors */
	rx_descr_init ();
	tx_descr_init ();

	// Set Receive Filter register: enable broadcast and multicast
	LPC_EMAC->RxFilterCtrl = EMAC_RFC_MCAST_EN | EMAC_RFC_BCAST_EN | EMAC_RFC_PERFECT_EN;

	/* Enable Rx Done and Tx Done interrupt for EMAC */
	LPC_EMAC->IntEnable = EMAC_INT_RX_DONE | EMAC_INT_TX_DONE;

	/* Reset all interrupts */
	LPC_EMAC->IntClear  = 0xFFFF;

	/* Enable receive and transmit mode of MAC Ethernet core */
	LPC_EMAC->Command  |= (EMAC_CR_RX_EN | EMAC_CR_TX_EN);
	LPC_EMAC->MAC1     |= EMAC_MAC1_REC_EN;

	return SUCCESS;
}


/*********************************************************************//**
 * @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);

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


/*********************************************************************//**
 * @brief		Check specified PHY status in EMAC peripheral
 * @param[in]	ulPHYState	Specified PHY Status Type, should be:
 * 							- EMAC_PHY_STAT_LINK: Link Status
 * 							- EMAC_PHY_STAT_SPEED: Speed Status
 * 							- EMAC_PHY_STAT_DUP: Duplex Status
 * @return		Status of specified PHY status (0 or 1).
 * 				(-1) if error.
 *
 * Note:
 * For EMAC_PHY_STAT_LINK, return value:
 * - 0: Link Down
 * - 1: Link Up
 * For EMAC_PHY_STAT_SPEED, return value:
 * - 0: 10Mbps
 * - 1: 100Mbps
 * For EMAC_PHY_STAT_DUP, return value:
 * - 0: Half-Duplex
 * - 1: Full-Duplex
 **********************************************************************/
int32_t EMAC_CheckPHYStatus(uint32_t ulPHYState)
{
	int32_t regv, tmp;
#ifdef MCB_LPC_1768
	regv = read_PHY (EMAC_PHY_REG_STS);
	switch(ulPHYState){
	case EMAC_PHY_STAT_LINK:
		tmp = (regv & EMAC_PHY_SR_LINK) ? 1 : 0;
		break;
	case EMAC_PHY_STAT_SPEED:
		tmp = (regv & EMAC_PHY_SR_SPEED) ? 0 : 1;
		break;
	case EMAC_PHY_STAT_DUP:
		tmp = (regv & EMAC_PHY_SR_FULL_DUP) ? 1 : 0;
		break;
#elif defined(IAR_LPC_1768)
	/* Use IAR_LPC_1768 board:
	 * FSZ8721BL doesn't have Status Register
	 * so we read Basic Mode Status Register (0x01h) instead
	 */
	regv = read_PHY (EMAC_PHY_REG_BMSR);
	switch(ulPHYState){
	case EMAC_PHY_STAT_LINK:
		tmp = (regv & EMAC_PHY_BMSR_LINK_STATUS) ? 1 : 0;
		break;
	case EMAC_PHY_STAT_SPEED:
		tmp = (regv & EMAC_PHY_SR_100_SPEED) ? 1 : 0;
		break;
	case EMAC_PHY_STAT_DUP:
		tmp = (regv & EMAC_PHY_SR_FULL_DUP) ? 1 : 0;
		break;
#endif
	default:
		tmp = -1;
		break;
	}
	return (tmp);
}


/*********************************************************************//**
 * @brief		Set specified PHY mode in EMAC peripheral
 * @param[in]	ulPHYMode	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);

#ifdef MCB_LPC_1768
	if (((id1 << 16) | (id2 & 0xFFF0)) == EMAC_DP83848C_ID) {
		switch(ulPHYMode){
		case EMAC_MODE_AUTO:
			write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_AUTO_NEG);
#elif defined(IAR_LPC_1768) /* Use IAR LPC1768 KickStart board */
	if (((id1 << 16) | id2) == EMAC_KSZ8721BL_ID) {
		/* 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);
//			write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_BMCR_AN);
#endif
			/* 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);
				}
				/* *wait for link */
				OSTimeDlyHMSM(0, 0, 0, 50);	 /* 50 MS  */
			}
			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. */
#ifdef MCB_LPC_1768
	for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) {
		regv = read_PHY (EMAC_PHY_REG_STS);
		if (regv & EMAC_PHY_SR_LINK) {
			/* Link is on. */
			break;
		}
		if (tout == 0){
			// time out
			return (-1);
		}
	}
	/* Configure Full/Half Duplex mode. */
	if (regv & EMAC_PHY_SR_DUP) {
	/* 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 {
		/* Half duplex mode. */
		LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP;
	}
	if (regv & EMAC_PHY_SR_SPEED) {
	/* 10MBit mode. */
		LPC_EMAC->SUPP = 0;
	} else {
		/* 100MBit mode. */
		LPC_EMAC->SUPP = EMAC_SUPP_SPEED;
	}
#elif defined(IAR_LPC_1768)
	for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) {
		regv = read_PHY (EMAC_PHY_REG_BMSR);
		if (regv & EMAC_PHY_BMSR_LINK_STATUS) {
			/* Link is on. */
			break;
		}
		if (tout == 0){
			// time out
			return (-1);
		}
	}

	/* Configure Full/Half Duplex mode. */
	if (regv & EMAC_PHY_SR_FULL_DUP) {
		/* 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 {
		/* Half duplex mode. */
		LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP;
	}

	/* Configure 100MBit/10MBit mode. */
	if (!(regv & EMAC_PHY_SR_100_SPEED)) {
		/* 10MBit mode. */
		LPC_EMAC->SUPP = 0;
	} else {
		/* 100MBit mode. */
		LPC_EMAC->SUPP = EMAC_SUPP_SPEED;
	}
#endif
	// 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

⌨️ 快捷键说明

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