static void k64f_phy_task(void *data) { struct netif *netif = (struct netif*)data; bool connection_status; enet_dev_if_t * enetIfPtr = (enet_dev_if_t*)&enetDevIf[BOARD_DEBUG_ENET_INSTANCE]; PHY_STATE crt_state = {STATE_UNKNOWN, (enet_phy_speed_t)STATE_UNKNOWN, (enet_phy_duplex_t)STATE_UNKNOWN}; PHY_STATE prev_state; prev_state = crt_state; while (true) { // Get current status phy_get_link_status(enetIfPtr, &connection_status); crt_state.connected = connection_status ? 1 : 0; phy_get_link_speed(enetIfPtr, &crt_state.speed); phy_get_link_duplex(enetIfPtr, &crt_state.duplex); // Compare with previous state if (crt_state.connected != prev_state.connected) { if (crt_state.connected) tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_up, (void*) netif, 1); else tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_down, (void*) netif, 1); } if (crt_state.speed != prev_state.speed) BW_ENET_RCR_RMII_10T(enetIfPtr->deviceNumber, crt_state.speed == kEnetSpeed10M ? kEnetCfgSpeed10M : kEnetCfgSpeed100M); // TODO: duplex change requires disable/enable of Ethernet interface, to be implemented prev_state = crt_state; osDelay(PHY_TASK_PERIOD_MS); } }
/****************************************************************************** Functions (for system that has no ET_LINKSTA pin using) ******************************************************************************/ static void polling_link_status_(void) { static uint16_t timer_1s = 0; static int16_t pre_link_stat = R_PHY_ERROR; int16_t link_stat; if((timer_1s % 100) == 0) { link_stat = phy_get_link_status(); if(pre_link_stat != link_stat) { if(link_stat == R_PHY_OK) { g_ether_LchngFlag = ETHER_FLAG_ON_LINK_ON; } else { g_ether_LchngFlag = ETHER_FLAG_ON_LINK_OFF; } } pre_link_stat = link_stat; } timer_1s++; }
static void k64f_phy_task(void *data) { struct netif *netif = (struct netif*)data; bool connection_status; enet_dev_if_t * enetIfPtr = (enet_dev_if_t*)&enetDevIf[BOARD_DEBUG_ENET_INSTANCE]; PHY_STATE crt_state = {STATE_UNKNOWN, (enet_phy_speed_t)STATE_UNKNOWN, (enet_phy_duplex_t)STATE_UNKNOWN}; PHY_STATE prev_state; prev_state = crt_state; // TODO: this can't be an infinite loop anymore. Events, people. Give me events. WHERE ARE MY EVENTS ?! // TODO: maybe this should also be called from the Ethernet interrupt handler ? (probably not thouogh, since the interrupt // handler doesn't seem to have a PHY-related source (but check this!)) // TODO: +--> what actually happens is that the requests to read/write PHY registers via the MII interface should be // asynchronous (and their completion can generate an interrupt), so completely ignore this for now and assume // that the Ethernet cable is always connected and the link speed never changes. Yuck. while (true) { // Get current status phy_get_link_status(enetIfPtr, &connection_status); crt_state.connected = connection_status ? 1 : 0; phy_get_link_speed(enetIfPtr, &crt_state.speed); phy_get_link_duplex(enetIfPtr, &crt_state.duplex); // Compare with previous state if (crt_state.connected != prev_state.connected) { if (crt_state.connected) tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_up, (void*) netif, 1); else tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_down, (void*) netif, 1); } if (crt_state.speed != prev_state.speed) BW_ENET_RCR_RMII_10T(enetIfPtr->deviceNumber, crt_state.speed == kEnetSpeed10M ? kEnetCfgSpeed10M : kEnetCfgSpeed100M); // TODO: duplex change requires disable/enable of Ethernet interface, to be implemented prev_state = crt_state; osDelay(PHY_TASK_PERIOD_MS); } }
int phy_link_status() { bool connection_status; enet_dev_if_t * enetIfPtr = (enet_dev_if_t*)&enetDevIf[BOARD_DEBUG_ENET_INSTANCE]; phy_get_link_status(enetIfPtr, &connection_status); return (int)connection_status; }
//------------------------------------------------------------------------------ int HWInit(bd_t * bd) { int btemp; unsigned int duplex, speed; unsigned long tmp1, mst = 250; // Enable MAC interface CLKPWR->clkpwr_macclk_ctrl = (CLKPWR_MACCTRL_HRCCLK_EN | CLKPWR_MACCTRL_MMIOCLK_EN | CLKPWR_MACCTRL_DMACLK_EN | #ifdef USE_PHY_RMII CLKPWR_MACCTRL_USE_RMII_PINS); #else CLKPWR_MACCTRL_USE_MII_PINS); #endif // Set RMII management clock rate. This clock should be slower // than 12.5MHz (for NXP PHYs only). For a divider of 28, the // clock rate when HCLK is 150MHz will be 5.4MHz ENETMAC->mcfg = MCFG_CLOCK_SELECT(MCFG_CLOCK_HOST_DIV_28); // Reset all MAC logic ENETMAC->mac1 = (MAC1_SOFT_RESET | MAC1_SIMULATION_RESET | MAC1_RESET_MCS_TX | MAC1_RESET_TX | MAC1_RESET_MCS_RX | MAC1_RESET_RX); ENETMAC->command = (COMMAND_REG_RESET | COMMAND_TXRESET | COMMAND_RXRESET); msDelay(10); // Initial MAC initialization ENETMAC->mac1 = MAC1_PASS_ALL_RX_FRAMES; ENETMAC->mac2 = (MAC2_PAD_CRC_ENABLE | MAC2_CRC_ENABLE); ENETMAC->maxf = ENET_MAXF_SIZE; // Maximum number of retries, 0x37 collision window, gap */ ENETMAC->clrt = (CLRT_LOAD_RETRY_MAX(0xF) | CLRT_LOAD_COLLISION_WINDOW(0x37)); ENETMAC->ipgr = IPGR_LOAD_PART2(0x12); #ifdef USE_PHY_RMII // RMII setup ENETMAC->command = (COMMAND_RMII | COMMAND_PASSRUNTFRAME); ENETMAC->supp = SUPP_RESET_RMII; msDelay(10); #else // MII setup ENETMAC->command = COMMAND_PASSRUNTFRAME; #endif // Enable rate auto-negotiation for the link if (RMII_Write(PHY_BMCR, (PHY_BMCR_100MB | PHY_BMCR_AUTON)) == 0) { return 0; } mst = 1000; btemp = 1; while(mst > 0) { /* Wait for Link status to set UP or Timeout */ if(phy_get_link_status() == 0) { mst = 0; btemp = 0; printf("ENET:auto-negotiation complete#$\n"); } else { mst--; msDelay(1); } } if(btemp) { printf("ENET:auto-negotiation failed#$\n"); return 0; } /* Read PHY Status Register to determine Ethernet Configuration */ tmp1 = 0; RMII_Read (DP83848_PHY_STATUS,&tmp1); duplex = (tmp1 & 0x0004) >> 2; speed = (tmp1 & 0x0002) >> 1; // Configure Full/Half Duplex mode if (duplex == 1) { // 10MBase full duplex is supported ENETMAC->mac2 |= MAC2_FULL_DUPLEX; ENETMAC->command |= COMMAND_FULLDUPLEX; ENETMAC->ipgt = IPGT_LOAD(0x15); printf("ENET:FULL DUPLEX\n"); } else { ENETMAC->ipgt = IPGT_LOAD(0x12); printf("ENET:HALF DUPLEX\n"); } // Configure 100MBit/10MBit mode if (speed == 0) { // 100MBase mode ENETMAC->supp = SUPP_SPEED; printf("ENET:100MBase\n"); } else { // 10MBase mode ENETMAC->supp = 0; printf("ENET:10Base\n"); } // Save station address ENETMAC->sa [2] = (unsigned long) (bd->bi_enetaddr[0] | (bd->bi_enetaddr[1] << 8)); ENETMAC->sa [1] = (unsigned long) (bd->bi_enetaddr[2] | (bd->bi_enetaddr[3] << 8)); ENETMAC->sa [0] = (unsigned long) (bd->bi_enetaddr[4] | (bd->bi_enetaddr[5] << 8)); // Setup TX and RX descriptors txrx_setup(); // Enable broadcast and matching address packets ENETMAC->rxfliterctrl = (RXFLTRW_ACCEPTUBROADCAST | RXFLTRW_ACCEPTPERFECT); // Clear and enable interrupts ENETMAC->intclear = 0xFFFF; ENETMAC->intenable = 0; // Enable receive and transmit mode of MAC ethernet core ENETMAC->command |= (COMMAND_RXENABLE | COMMAND_TXENABLE); ENETMAC->mac1 |= MAC1_RECV_ENABLE; // Perform a 'dummy' send of the first ethernet frame with a size of 0 // to 'prime' the MAC. The first packet after a reset seems to wait // until at least 2 packets are ready to go. tmp1 = 0; eth_send(&tmp1, 4); return 1; }