static long prvPHY_ISR_NonNakedBehaviour(void) { // Variable definitions can be made now. volatile unsigned long ulIntStatus, ulEventStatus; long xSwitchRequired = false; // read Phy Interrupt register Status ulIntStatus = ulReadMDIO(&AVR32_MACB, PHY_MISR); // read Phy status register ulEventStatus = ulReadMDIO(&AVR32_MACB, PHY_BMSR); // dummy read ulEventStatus = ulReadMDIO(&AVR32_MACB, PHY_BMSR); if(ulEventStatus & BMSR_LSTATUS) { prvSetupMACBConfig(&AVR32_MACB); } #if EXTPHY_MACB_USE_EXTINT eic_clear_interrupt_line(&AVR32_EIC, EXTPHY_MACB_INTERRUPT); #else volatile avr32_gpio_t *gpio = &AVR32_GPIO; volatile avr32_gpio_port_t *gpio_port = &gpio->port[EXTPHY_MACB_INTERRUPT_PIN/32]; // clear interrupt flag on GPIO gpio_port->ifrc = 1 << (EXTPHY_MACB_INTERRUPT_PIN%32); #endif return ( xSwitchRequired ); }
static long prvPHY_ISR_NonNakedBehaviour(void) { // Variable definitions can be made now. volatile unsigned long ulIntStatus, ulEventStatus; long xSwitchRequired = false; volatile avr32_gpio_t *gpio = &AVR32_GPIO; volatile avr32_gpio_port_t *gpio_port = &gpio->port[EXTPHY_MACB_INTERRUPT_PIN/32]; // read Phy Interrupt register Status ulIntStatus = ulReadMDIO(&AVR32_MACB, PHY_MISR); // read Phy status register ulEventStatus = ulReadMDIO(&AVR32_MACB, PHY_BMSR); // dummy read ulEventStatus = ulReadMDIO(&AVR32_MACB, PHY_BMSR); // clear interrupt flag on GPIO gpio_port->ifrc = 1 << (EXTPHY_MACB_INTERRUPT_PIN%32); return ( xSwitchRequired ); }
static void prvSetupMACBConfig(volatile avr32_macb_t *macb) { volatile unsigned long lpa, config, advertise; // read the LPA configuration of the PHY lpa = ulReadMDIO(macb, PHY_LPA); // read the MACB config register config = macb->ncfgr; // set advertise register #if ETHERNET_CONF_AN_ENABLE == 1 advertise = ADVERTISE_CSMA | ADVERTISE_ALL; #else advertise = ADVERTISE_CSMA; #if ETHERNET_CONF_USE_100MB #if ETHERNET_CONF_USE_FULL_DUPLEX advertise |= ADVERTISE_100FULL; #else advertise |= ADVERTISE_100HALF; #endif #else #if ETHERNET_CONF_USE_FULL_DUPLEX advertise |= ADVERTISE_10FULL; #else advertise |= ADVERTISE_10HALF; #endif #endif #endif // if 100MB needed if ((lpa & advertise) & (LPA_100HALF | LPA_100FULL)) { config |= AVR32_MACB_SPD_MASK; } else { config &= ~(AVR32_MACB_SPD_MASK); } // if FULL DUPLEX needed if ((lpa & advertise) & (LPA_10FULL | LPA_100FULL)) { config |= AVR32_MACB_FD_MASK; } else { config &= ~(AVR32_MACB_FD_MASK); } // write the MACB config register macb->ncfgr = config; }
static BaseType_t xGMACWaitLS( TickType_t xMaxTime ) { TickType_t xStartTime = xTaskGetTickCount(); TickType_t xEndTime; BaseType_t xReturn; const TickType_t xShortTime = pdMS_TO_TICKS( 100UL ); for( ;; ) { xEndTime = xTaskGetTickCount(); if( ( xEndTime - xStartTime ) > xMaxTime ) { /* Wated more than xMaxTime, return. */ xReturn = pdFALSE; break; } /* Check the link status again. */ ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR ); if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) { /* Link is up - return. */ xReturn = pdTRUE; break; } /* Link is down - wait in the Blocked state for a short while (to allow other tasks to execute) before checking again. */ vTaskDelay( xShortTime ); } FreeRTOS_printf( ( "xGMACWaitLS: %ld (PHY %d) freq %lu Mz\n", xReturn, ethernet_phy_addr, sysclk_get_cpu_hz() / HZ_PER_MHZ ) ); return xReturn; }
static bool prvProbePHY(volatile avr32_macb_t *macb) { volatile unsigned long mii_status; volatile unsigned long config; unsigned long upper, lower, advertise, lpa; volatile unsigned long physID; // Read Phy Identifier register 1 & 2 lower = ulReadMDIO(macb, PHY_PHYSID2); upper = ulReadMDIO(macb, PHY_PHYSID1); // get Phy ID, ignore Revision physID = ((upper << 16) & 0xFFFF0000) | (lower & 0xFFF0); // check if it match config if (physID == EXTPHY_PHY_ID) { #if ETHERNET_CONF_USE_RMII_INTERFACE // setup rmii mode ethernet_phy_setup_rmii(macb); #endif // set advertise register #if ETHERNET_CONF_AN_ENABLE == 1 advertise = ADVERTISE_CSMA | ADVERTISE_ALL; #else advertise = ADVERTISE_CSMA; #if ETHERNET_CONF_USE_100MB #if ETHERNET_CONF_USE_FULL_DUPLEX advertise |= ADVERTISE_100FULL; #else advertise |= ADVERTISE_100HALF; #endif #else #if ETHERNET_CONF_USE_FULL_DUPLEX advertise |= ADVERTISE_10FULL; #else advertise |= ADVERTISE_10HALF; #endif #endif #endif // write advertise register vWriteMDIO(macb, PHY_ADVERTISE, advertise); // read Control register config = ulReadMDIO(macb, PHY_BMCR); // setup auto negociation ethernet_phy_setup_auto_negociation(macb, &config); // update ctrl register vWriteMDIO(macb, PHY_BMCR, config); // loop while link status isn't OK do { mii_status = ulReadMDIO(macb, PHY_BMSR); } while (!(mii_status & BMSR_LSTATUS)); // read the LPA configuration of the PHY lpa = ulReadMDIO(macb, PHY_LPA); // read the MACB config register config = AVR32_MACB.ncfgr; // if 100MB needed if ((lpa & advertise) & (LPA_100HALF | LPA_100FULL)) { config |= AVR32_MACB_SPD_MASK; } else { config &= ~(AVR32_MACB_SPD_MASK); } // if FULL DUPLEX needed if ((lpa & advertise) & (LPA_10FULL | LPA_100FULL)) { config |= AVR32_MACB_FD_MASK; } else { config &= ~(AVR32_MACB_FD_MASK); } // write the MACB config register macb->ncfgr = config; return true; } return false; }
static bool prvProbePHY(volatile avr32_macb_t *macb) { volatile unsigned long config; unsigned long upper, lower, advertise; volatile unsigned long physID; // Read Phy Identifier register 1 & 2 lower = ulReadMDIO(macb, PHY_PHYSID2); upper = ulReadMDIO(macb, PHY_PHYSID1); // get Phy ID, ignore Revision physID = ((upper << 16) & 0xFFFF0000) | (lower & 0xFFF0); // check if it match config if (physID == EXTPHY_PHY_ID) { #if ETHERNET_CONF_USE_RMII_INTERFACE // setup rmii mode ethernet_phy_setup_rmii(macb); #endif // set advertise register #if ETHERNET_CONF_AN_ENABLE == 1 advertise = ADVERTISE_CSMA | ADVERTISE_ALL; #else advertise = ADVERTISE_CSMA; #if ETHERNET_CONF_USE_100MB #if ETHERNET_CONF_USE_FULL_DUPLEX advertise |= ADVERTISE_100FULL; #else advertise |= ADVERTISE_100HALF; #endif #else #if ETHERNET_CONF_USE_FULL_DUPLEX advertise |= ADVERTISE_10FULL; #else advertise |= ADVERTISE_10HALF; #endif #endif #endif // write advertise register vWriteMDIO(macb, PHY_ADVERTISE, advertise); // read Control register config = ulReadMDIO(macb, PHY_BMCR); // setup auto negotiation ethernet_phy_setup_auto_negotiation(macb, &config); // update ctrl register vWriteMDIO(macb, PHY_BMCR, config); #if (ETHERNET_CONF_USE_PHY_IT == 0) volatile unsigned long mii_status; // loop while link status isn't OK do { mii_status = ulReadMDIO(macb, PHY_BMSR); } while (!(mii_status & BMSR_LSTATUS)); prvSetupMACBConfig(macb); #endif /* ETHERNET_CONF_USE_PHY_IT == 0 */ return true; } return false; }
static Bool prvProbePHY( volatile avr32_macb_t * macb ) { volatile unsigned long mii_status, phy_ctrl; volatile unsigned long config; unsigned long upper, lower, mode, advertise, lpa; volatile unsigned long physID; // Read Phy Identifier register 1 & 2 lower = ulReadMDIO(macb, PHY_PHYSID2); upper = ulReadMDIO(macb, PHY_PHYSID1); // get Phy ID, ignore Revision physID = ((upper << 16) & 0xFFFF0000) | (lower & 0xFFF0); // check if it match config if (physID == ETHERNET_CONF_PHY_ID) { // read RBR mode = ulReadMDIO(macb, PHY_RBR); // set RMII mode if not done if ((mode & RBR_RMII) != RBR_RMII) { // force RMII flag if strap options are wrong mode |= RBR_RMII; vWriteMDIO(macb, PHY_RBR, mode); } // set advertise register #if ETHERNET_CONF_AN_ENABLE == 1 advertise = ADVERTISE_CSMA | ADVERTISE_ALL; #else advertise = ADVERTISE_CSMA; #if ETHERNET_CONF_USE_100MB #if ETHERNET_CONF_USE_FULL_DUPLEX advertise |= ADVERTISE_100FULL; #else advertise |= ADVERTISE_100HALF; #endif #else #if ETHERNET_CONF_USE_FULL_DUPLEX advertise |= ADVERTISE_10FULL; #else advertise |= ADVERTISE_10HALF; #endif #endif #endif // write advertise register vWriteMDIO(macb, PHY_ADVERTISE, advertise); // read Control register config = ulReadMDIO(macb, PHY_BMCR); // read Phy Control register phy_ctrl = ulReadMDIO(macb, PHY_PHYCR); #if ETHERNET_CONF_AN_ENABLE #if ETHERNET_CONF_AUTO_CROSS_ENABLE // enable Auto MDIX phy_ctrl |= PHYCR_MDIX_EN; #else // disable Auto MDIX phy_ctrl &= ~PHYCR_MDIX_EN; #if ETHERNET_CONF_CROSSED_LINK // force direct link = Use crossed RJ45 cable phy_ctrl &= ~PHYCR_MDIX_FORCE; #else // force crossed link = Use direct RJ45 cable phy_ctrl |= PHYCR_MDIX_FORCE; #endif #endif // reset auto-negociation capability config |= (BMCR_ANRESTART | BMCR_ANENABLE); #else // disable Auto MDIX phy_ctrl &= ~PHYCR_MDIX_EN; #if ETHERNET_CONF_CROSSED_LINK // force direct link = Use crossed RJ45 cable phy_ctrl &= ~PHYCR_MDIX_FORCE; #else // force crossed link = Use direct RJ45 cable phy_ctrl |= PHYCR_MDIX_FORCE; #endif // clear AN bit config &= ~BMCR_ANENABLE; #if ETHERNET_CONF_USE_100MB config |= BMCR_SPEED100; #else config &= ~BMCR_SPEED100; #endif #if ETHERNET_CONF_USE_FULL_DUPLEX config |= BMCR_FULLDPLX; #else config &= ~BMCR_FULLDPLX; #endif #endif // update Phy ctrl register vWriteMDIO(macb, PHY_PHYCR, phy_ctrl); // update ctrl register vWriteMDIO(macb, PHY_BMCR, config); // loop while link status isn't OK do { mii_status = ulReadMDIO(macb, PHY_BMSR); } while (!(mii_status & BMSR_LSTATUS)); // read the LPA configuration of the PHY lpa = ulReadMDIO(macb, PHY_LPA); // read the MACB config register config = AVR32_MACB.ncfgr; // if 100MB needed if ((lpa & advertise) & (LPA_100HALF | LPA_100FULL)) { config |= AVR32_MACB_SPD_MASK; } else { config &= ~(AVR32_MACB_SPD_MASK); } // if FULL DUPLEX needed if ((lpa & advertise) & (LPA_10FULL | LPA_100FULL)) { config |= AVR32_MACB_FD_MASK; } else { config &= ~(AVR32_MACB_FD_MASK); } // write the MACB config register macb->ncfgr = config; return TRUE; } return FALSE; }
static void prvEMACHandlerTask( void *pvParameters ) { TimeOut_t xPhyTime; TickType_t xPhyRemTime; UBaseType_t uxCount; #if( ipconfigZERO_COPY_TX_DRIVER != 0 ) NetworkBufferDescriptor_t *pxBuffer; #endif uint8_t *pucBuffer; BaseType_t xResult = 0; uint32_t xStatus; const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( EMAC_MAX_BLOCK_TIME_MS ); /* Remove compiler warnings about unused parameters. */ ( void ) pvParameters; configASSERT( xEMACTaskHandle ); vTaskSetTimeOutState( &xPhyTime ); xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS ); for( ;; ) { vCheckBuffersAndQueue(); if( ( ulISREvents & EMAC_IF_ALL_EVENT ) == 0 ) { /* No events to process now, wait for the next. */ ulTaskNotifyTake( pdFALSE, ulMaxBlockTime ); } if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 ) { ulISREvents &= ~EMAC_IF_RX_EVENT; /* Wait for the EMAC interrupt to indicate that another packet has been received. */ xResult = prvEMACRxPoll(); } if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 ) { /* Future extension: code to release TX buffers if zero-copy is used. */ ulISREvents &= ~EMAC_IF_TX_EVENT; while( xQueueReceive( xTxBufferQueue, &pucBuffer, 0 ) != pdFALSE ) { #if( ipconfigZERO_COPY_TX_DRIVER != 0 ) { pxBuffer = pxPacketBuffer_to_NetworkBuffer( pucBuffer ); if( pxBuffer != NULL ) { vReleaseNetworkBufferAndDescriptor( pxBuffer ); tx_release_count[ 0 ]++; } else { tx_release_count[ 1 ]++; } } #else { tx_release_count[ 0 ]++; } #endif uxCount = uxQueueMessagesWaiting( ( QueueHandle_t ) xTXDescriptorSemaphore ); if( uxCount < GMAC_TX_BUFFERS ) { /* Tell the counting semaphore that one more TX descriptor is available. */ xSemaphoreGive( xTXDescriptorSemaphore ); } } } if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 ) { /* Future extension: logging about errors that occurred. */ ulISREvents &= ~EMAC_IF_ERR_EVENT; } if( xResult > 0 ) { /* A packet was received. No need to check for the PHY status now, but set a timer to check it later on. */ vTaskSetTimeOutState( &xPhyTime ); xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS ); xResult = 0; } else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE ) { /* Check the link status again. */ xStatus = ulReadMDIO( PHY_REG_01_BMSR ); if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) ) { ulPHYLinkStatus = xStatus; FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) ); } vTaskSetTimeOutState( &xPhyTime ); if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) { xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS ); } else { xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS ); } } } }