本帖最后由 灰常时刻 于 2021-9-16 11:05 编辑
最近用M487调试LAN8720A PHY芯片,网口初始化正常,发送数据包也能用WireShark接收到。但M487就是没有触发RX中断。我测量了一下PHY的RX0/RX1是有波形的,现在不知道如何确认问题了。请大神赐教。
以下是EMAC初始化和操作代码,参考的是官方 ‘M480_BSP_CMSIS_V3.05.001\SampleCode\StdDriver\EMAC_TxRx’例程,使用描述符来管理发送和接收数据。
void EMAC_PhyInit(void)
{
uint32_t reg;
uint32_t i = 0UL;
/* Reset Phy Chip */
EMAC_MdioWrite(PHY_CNTL_REG, EMAC_PHY_ADDR, PHY_CNTL_RESET_PHY);
/* Wait until reset complete */
while (1)
{
reg = EMAC_MdioRead(PHY_CNTL_REG, EMAC_PHY_ADDR) ;
if ((reg & PHY_CNTL_RESET_PHY)==0UL)
{
break;
}
}
while(!(EMAC_MdioRead(PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_LINK_VALID))
{
if(i++ > 80000UL) /* Cable not connected */
{
EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
break;
}
}
if(i <= 80000UL)
{
/* Configure auto negotiation capability */
EMAC_MdioWrite(PHY_ANA_REG, EMAC_PHY_ADDR, PHY_ANA_DR100_TX_FULL |
PHY_ANA_DR100_TX_HALF |
PHY_ANA_DR10_TX_FULL |
PHY_ANA_DR10_TX_HALF |
PHY_ANA_IEEE_802_3_CSMA_CD);
/* Restart auto negotiation */
EMAC_MdioWrite(PHY_CNTL_REG, EMAC_PHY_ADDR, EMAC_MdioRead(PHY_CNTL_REG, EMAC_PHY_ADDR) | PHY_CNTL_RESTART_AN);
/* Wait for auto-negotiation complete */
while(!(EMAC_MdioRead(PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_AN_COMPLETE))
{
;
}
/* Check link valid again. Some PHYs needs to check result after link valid bit set */
while(!(EMAC_MdioRead(PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_LINK_VALID))
{
;
}
/* Check link partner capability */
reg = EMAC_MdioRead(PHY_ANLPA_REG, EMAC_PHY_ADDR) ;
if (reg & PHY_ANLPA_DR100_TX_FULL)
{
EMAC->CTL |= EMAC_CTL_OPMODE_Msk;
EMAC->CTL |= EMAC_CTL_FUDUP_Msk;
}
else if (reg & PHY_ANLPA_DR100_TX_HALF)
{
EMAC->CTL |= EMAC_CTL_OPMODE_Msk;
EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
}
else if (reg & PHY_ANLPA_DR10_TX_FULL)
{
EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
EMAC->CTL |= EMAC_CTL_FUDUP_Msk;
}
else
{
EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
}
}
}
int main(void)
{
SYS_Init();
UART_Open(UART0, 115200);
// Select RMII interface by default
EMAC_Open(g_au8MacAddr);
// Init phy
EMAC_PhyInit();
NVIC_EnableIRQ(EMAC_TX_IRQn);
NVIC_EnableIRQ(EMAC_RX_IRQn);
EMAC_ENABLE_RX();
EMAC_ENABLE_TX();
if (dhcp_start() < 0)
{
// Cannot get a DHCP lease, use static IP.
printf("DHCP failed, use static IP 192.168.10.10\n");
g_au8IpAddr[0] = 0xC0;//192
g_au8IpAddr[1] = 0xA8;//168
g_au8IpAddr[2] = 0x0A;//10
g_au8IpAddr[3] = 0x0A;//10
}
while(1);
}
//EMAC初始化
void SYS_Init(void)
{
/* Unlock protected registers */
SYS_UnlockReg();
/* Set XT1_OUT(PF.2) and XT1_IN(PF.3) to input mode */
PF->MODE &= ~(GPIO_MODE_MODE2_Msk | GPIO_MODE_MODE3_Msk);
/* Enable External XTAL (4~24 MHz) */
CLK_EnableXtalRC(CLK_PWRCTL_HXTEN_Msk);
/* Waiting for 12MHz clock ready */
CLK_WaitClockReady( CLK_STATUS_HXTSTB_Msk);
/* Switch HCLK clock source to HXT */
CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_HXT,CLK_CLKDIV0_HCLK(1));
/* Set core clock as PLL_CLOCK from PLL */
CLK_SetCoreClock(FREQ_192MHZ);
/* Set both PCLK0 and PCLK1 as HCLK/2 */
CLK->PCLKDIV = CLK_PCLKDIV_APB0DIV_DIV2 | CLK_PCLKDIV_APB1DIV_DIV2;
/* Enable IP clock */
CLK_EnableModuleClock(UART0_MODULE);
CLK_EnableModuleClock(EMAC_MODULE);
/* Select IP clock source */
CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART0SEL_HXT, CLK_CLKDIV0_UART0(1));
// Configure MDC clock rate to HCLK / (127 + 1) = 1.5 MHz if system is running at 192 MHz
CLK_SetModuleClock(EMAC_MODULE, 0, CLK_CLKDIV3_EMAC(127));
/* Update System Core Clock */
/* User can use SystemCoreClockUpdate() to calculate SystemCoreClock. */
SystemCoreClockUpdate();
/* Set GPB multi-function pins for UART0 RXD and TXD */
SYS->GPB_MFPH &= ~(SYS_GPB_MFPH_PB12MFP_Msk | SYS_GPB_MFPH_PB13MFP_Msk);
SYS->GPB_MFPH |= (SYS_GPB_MFPH_PB12MFP_UART0_RXD | SYS_GPB_MFPH_PB13MFP_UART0_TXD);
// Configure RMII pins
SYS->GPA_MFPL |= SYS_GPA_MFPL_PA6MFP_EMAC_RMII_RXERR | SYS_GPA_MFPL_PA7MFP_EMAC_RMII_CRSDV;
SYS->GPC_MFPL |= SYS_GPC_MFPL_PC6MFP_EMAC_RMII_RXD1 | SYS_GPC_MFPL_PC7MFP_EMAC_RMII_RXD0;
SYS->GPC_MFPH |= SYS_GPC_MFPH_PC8MFP_EMAC_RMII_REFCLK;
SYS->GPE_MFPH |= SYS_GPE_MFPH_PE8MFP_EMAC_RMII_MDC |
SYS_GPE_MFPH_PE9MFP_EMAC_RMII_MDIO |
SYS_GPE_MFPH_PE10MFP_EMAC_RMII_TXD0 |
SYS_GPE_MFPH_PE11MFP_EMAC_RMII_TXD1 |
SYS_GPE_MFPH_PE12MFP_EMAC_RMII_TXEN;
// Enable high slew rate on all RMII TX output pins
PE->SLEWCTL = (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN10_Pos) |
(GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN11_Pos) |
(GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN12_Pos);
/* Lock protected registers */
SYS_LockReg();
}
/**
* @brief EMAC Tx interrupt handler.
* @param None
* @return None
*/
void EMAC_TX_IRQHandler(void)
{
// Clean up Tx resource occupied by previous sent packet(s)
EMAC_SendPktDone();
}
/**
* @brief EMAC Rx interrupt handler.
* @param None
* @return None
*/
void EMAC_RX_IRQHandler(void)
{
while(1)
{
// Check if there's any packets available
if(EMAC_RecvPkt(auPkt, &u32PktLen) == 0)
break;
// Process receive packet
process_rx_packet(auPkt, u32PktLen);
// Clean up Rx resource occupied by previous received packet
EMAC_RecvPktDone();
}
}
PHY原理图:
|