15.11.2011
Komunikacja sieciowa z wykorzystaniem mikrokontrolerów Freescale Kinetis
Zarządzanie interfejsem PHY
Moduł MAC-NET wykorzystuje interfejs PHY do komunikacji z układem PHY. Dzięki temu interfejsowi istnieje dostęp do rejestrów kontrolnych i statusowych układu PHY. Komunikacja przebiega z wykorzystaniem dwóch linii:
- Linii zegarowej, na której sygnał zegarowy generowany jest przez moduł MAC-NET. Częstotliwość sygnału zegarowego nie może być większa niż 2.5 MHz,
- Dwukierunkowej linii danych, która służy do przesyłania informacji między modułem ENET i układem PHY.
Przykładowy kod źródłowy do zarządzania PHY i rozpoczęcia auto-negocjacji z siecią przedstawiono w listingu:
void enet_start_mii(void) { PORTB_PCR0 = PORT_PCR_MUX(4);//GPIO;//RMII0_MDIO/MII0_MDIO PORTB_PCR1 = PORT_PCR_MUX(4);//GPIO;//RMII0_MDC/MII0_MDC /*FSL: start MII interface*/ mii_init(0, periph_clk_khz/1000/*MHz*/); /* Can we talk to the PHY? */ do { vTaskDelay( netifLINK_DELAY ); usData = 0xffff; mii_read( 0, configPHY_ADDRESS, PHY_PHYIDR1, &usData ); } while( usData == 0xffff ); /* Start auto negotiate. */ mii_write( 0, configPHY_ADDRESS, PHY_BMCR, ( PHY_BMCR_AN_RESTART | PHY_BMCR_AN_ENABLE ) ); } void mii_init(int ch, int sys_clk_mhz) { ENET_MSCR/*(ch)*/ = 0 #ifdef TSIEVB/*TSI EVB requires a longer hold time than default 10 ns*/ | ENET_MSCR_HOLDTIME(2) #endif | ENET_MSCR_MII_SPEED((2*sys_clk_mhz/5)+1) ; } int mii_write(int ch, int phy_addr, int reg_addr, int data) { int timeout; /* Clear the MII interrupt bit */ ENET_EIR/*(ch)*/ = ENET_EIR_MII_MASK; /* Initiatate the MII Management write */ ENET_MMFR/*(ch)*/ = 0 | ENET_MMFR_ST(0x01) | ENET_MMFR_OP(0x01) | ENET_MMFR_PA(phy_addr) | ENET_MMFR_RA(reg_addr) | ENET_MMFR_TA(0x02) | ENET_MMFR_DATA(data); /* Poll for the MII interrupt (interrupt should be masked) */ for (timeout = 0; timeout < MII_TIMEOUT; timeout++) { if (ENET_EIR/*(ch)*/ & ENET_EIR_MII_MASK) break; } if(timeout == MII_TIMEOUT) return 1; /* Clear the MII interrupt bit */ ENET_EIR/*(ch)*/ = ENET_EIR_MII_MASK; return 0; } /********************************************************************/ int mii_read(int ch, int phy_addr, int reg_addr, int *data) { int timeout; /* Clear the MII interrupt bit */ ENET_EIR/*(ch)*/ = ENET_EIR_MII_MASK; /* Initiatate the MII Management read */ ENET_MMFR/*(ch)*/ = 0 | ENET_MMFR_ST(0x01) | ENET_MMFR_OP(0x2) | ENET_MMFR_PA(phy_addr) | ENET_MMFR_RA(reg_addr) | ENET_MMFR_TA(0x02); /* Poll for the MII interrupt (interrupt should be masked) */ for (timeout = 0; timeout < MII_TIMEOUT; timeout++) { if (ENET_EIR/*(ch)*/ & ENET_EIR_MII_MASK) break; } if(timeout == MII_TIMEOUT) return 1; /* Clear the MII interrupt bit */ ENET_EIR/*(ch)*/ = ENET_EIR_MII_MASK; *data = ENET_MMFR/*(ch)*/ & 0x0000FFFF; return 0; }