static BaseType_t prvGMACInit( void ) { uint32_t ncfgr; gmac_options_t gmac_option; memset( &gmac_option, '\0', sizeof( gmac_option ) ); gmac_option.uc_copy_all_frame = 0; gmac_option.uc_no_boardcast = 0; memcpy( gmac_option.uc_mac_addr, ucMACAddress, sizeof( gmac_option.uc_mac_addr ) ); gs_gmac_dev.p_hw = GMAC; gmac_dev_init( GMAC, &gs_gmac_dev, &gmac_option ); NVIC_SetPriority( GMAC_IRQn, configMAC_INTERRUPT_PRIORITY ); NVIC_EnableIRQ( GMAC_IRQn ); /* Contact the Ethernet PHY and store it's address in 'ethernet_phy_addr' */ ethernet_phy_init( GMAC, ETHERNET_CONF_PHY_ADDR, sysclk_get_cpu_hz() ); ethernet_phy_auto_negotiate( GMAC, ethernet_phy_addr ); ethernet_phy_set_link( GMAC, ethernet_phy_addr, 1 ); /* The GMAC driver will call a hook prvRxCallback(), which in turn will wake-up the task by calling vTaskNotifyGiveFromISR() */ gmac_dev_set_rx_callback( &gs_gmac_dev, prvRxCallback ); gmac_set_address( GMAC, 1, (uint8_t*)llmnr_mac_address ); ncfgr = GMAC_NCFGR_SPD | GMAC_NCFGR_FD; GMAC->GMAC_NCFGR = ( GMAC->GMAC_NCFGR & ~( GMAC_NCFGR_SPD | GMAC_NCFGR_FD ) ) | ncfgr; return 1; }
BaseType_t xNetworkInterfaceInitialise( void ) { gmac_options_t xGMACOptions; extern uint8_t ucMACAddress[ 6 ]; const TickType_t xPHYDelay_400ms = 400UL; BaseType_t xReturn = pdFALSE; /* Ensure PHY is ready. */ vTaskDelay( xPHYDelay_400ms / portTICK_RATE_MS ); /* Enable GMAC clock. */ pmc_enable_periph_clk( ID_GMAC ); /* Fill in GMAC options */ xGMACOptions.uc_copy_all_frame = 0; xGMACOptions.uc_no_boardcast = 0; memcpy( xGMACOptions.uc_mac_addr, ucMACAddress, sizeof( ucMACAddress ) ); xGMACStruct.p_hw = GMAC; /* Init GMAC driver structure. */ gmac_dev_init( GMAC, &xGMACStruct, &xGMACOptions ); /* Init MAC PHY driver. */ if( ethernet_phy_init( GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz() ) == GMAC_OK ) { /* Auto Negotiate, work in RMII mode. */ if( ethernet_phy_auto_negotiate( GMAC, BOARD_GMAC_PHY_ADDR ) == GMAC_OK ) { /* Establish Ethernet link. */ vTaskDelay( xPHYDelay_400ms * 2UL ); if( ethernet_phy_set_link( GMAC, BOARD_GMAC_PHY_ADDR, 1 ) == GMAC_OK ) { /* Register the callbacks. */ gmac_dev_set_rx_callback( &xGMACStruct, prvGMACRxCallback ); /* The Rx deferred interrupt handler task is created at the highest possible priority to ensure the interrupt handler can return directly to it no matter which task was running when the interrupt occurred. */ xTaskCreate( prvGMACDeferredInterruptHandlerTask,/* The function that implements the task. */ "MACTsk", configMINIMAL_STACK_SIZE, /* Stack allocated to the task (defined in words, not bytes). */ NULL, /* The task parameter is not used. */ configMAX_PRIORITIES - 1, /* The priority assigned to the task. */ &xMACEventHandlingTask ); /* The handle is stored so the ISR knows which task to notify. */ /* Enable the interrupt and set its priority as configured. THIS DRIVER REQUIRES configMAC_INTERRUPT_PRIORITY TO BE DEFINED, PREFERABLY IN FreeRTOSConfig.h. */ NVIC_SetPriority( GMAC_IRQn, configMAC_INTERRUPT_PRIORITY ); NVIC_EnableIRQ( GMAC_IRQn ); xReturn = pdPASS; } } } return xReturn; }
/** * \brief EMAC link test function. * * \param test Current test case. */ static void run_emac_link_test(const struct test_case *test) { volatile uint32_t ul_delay; emac_options_t emac_option; uint8_t uc_rc = 1; /* Reset PHY */ rstc_set_external_reset(RSTC, 13); /* (2^(13+1))/32768 */ rstc_reset_extern(RSTC); while (rstc_get_status(RSTC) & RSTC_SR_NRSTL) { }; rstc_set_external_reset(RSTC, 0); /* restore default */ /* Wait for PHY to be ready (CAT811: Max400ms) */ ul_delay = sysclk_get_cpu_hz() / 1000 / 3 * 400; while (ul_delay--); /* Enable EMAC clock */ pmc_enable_periph_clk(ID_EMAC); /* Fill in EMAC options */ emac_option.uc_copy_all_frame = 1; emac_option.uc_no_boardcast = 1; memcpy(emac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address)); gs_emac_dev.p_hw = EMAC; /* Init EMAC driver structure */ emac_dev_init(EMAC, &gs_emac_dev, &emac_option); /* Enable Interrupt */ NVIC_EnableIRQ(EMAC_IRQn); /* Init MAC PHY driver */ if (ethernet_phy_init(EMAC, BOARD_EMAC_PHY_ADDR, sysclk_get_cpu_hz()) != EMAC_OK) { uc_rc = 0; } /* Auto Negotiate, work in RMII mode */ if (ethernet_phy_auto_negotiate(EMAC, BOARD_EMAC_PHY_ADDR) != EMAC_OK) { uc_rc = 0; } /* Establish ethernet link */ while (ethernet_phy_set_link(EMAC, BOARD_EMAC_PHY_ADDR, 1) != EMAC_OK) { uc_rc = 0; } test_assert_true(test, uc_rc == 1, "Test EMAC: EMAC link test error!"); }
void ethernet_hardware_init(void) { /* Reset PHY */ //rstc_set_external_reset(RSTC, 13); /* (2^(13+1))/32768 */ // rstc_set_external_reset(RSTC, 15); // rstc_reset_extern(RSTC); // while (rstc_get_status(RSTC) & RSTC_SR_NRSTL) { // } // ResetEther(); while(ResettingEther()) {} /* Wait for PHY to be ready (CAT811: Max400ms) */ { volatile u32_t ul_dealy = SystemCoreClock / 6; while (ul_dealy--) { } } /* Enable EMAC clock */ pmc_enable_periph_clk(ID_EMAC); { emac_options_t emac_option; /* Fill in EMAC options */ emac_option.uc_copy_all_frame = 1; emac_option.uc_no_boardcast = 0; memcpy(emac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address)); gs_emac_dev.p_hw = EMAC; /* Init EMAC driver structure */ emac_dev_init(EMAC, &gs_emac_dev, &emac_option); } /* Enable Interrupt */ NVIC_EnableIRQ(EMAC_IRQn); /* Init MAC PHY driver */ if (ethernet_phy_init(EMAC, BOARD_EMAC_PHY_ADDR, SystemCoreClock) != EMAC_OK) { LWIP_DEBUGF(LWIP_DBG_TRACE, ("PHY Initialize ERROR!\r")); return; } }
/** * \brief GMAC link test function. * * \param test Current test case. */ static void run_gmac_link_test(const struct test_case *test) { gmac_options_t gmac_option; uint8_t uc_rc = 1; /* Enable GMAC clock */ pmc_enable_periph_clk(ID_GMAC); /* Fill in GMAC options */ gmac_option.uc_copy_all_frame = 1; gmac_option.uc_no_boardcast = 1; memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address)); gs_gmac_dev.p_hw = GMAC; /* Init GMAC driver structure */ gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option); /* Enable Interrupt */ NVIC_EnableIRQ(GMAC_IRQn); /* Init MAC PHY driver */ if (ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz()) != GMAC_OK) { uc_rc = 0; } /* Auto Negotiate, work in RMII mode */ if (ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR) != GMAC_OK) { uc_rc = 0; } /* Establish ethernet link */ while (ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1) != GMAC_OK) { uc_rc = 0; } test_assert_true(test, uc_rc == 1, "Test GMAC: GMAC link test error!"); }
/** * \brief In this function, the hardware should be initialized. * Called from ethernetif_init(). * * \param netif the already initialized lwip network interface structure * for this ethernetif */ static void low_level_init(struct netif *netif) { volatile uint32_t ul_dealy; emac_options_t emac_option; #ifdef FREERTOS_USED unsigned portBASE_TYPE uxPriority; #endif /* Set MAC hardware address length */ netif->hwaddr_len = sizeof(gs_uc_mac_address); /* Set MAC hardware address */ netif->hwaddr[0] = gs_uc_mac_address[0]; netif->hwaddr[1] = gs_uc_mac_address[1]; netif->hwaddr[2] = gs_uc_mac_address[2]; netif->hwaddr[3] = gs_uc_mac_address[3]; netif->hwaddr[4] = gs_uc_mac_address[4]; netif->hwaddr[5] = gs_uc_mac_address[5]; /* Maximum transfer unit */ netif->mtu = NET_MTU; /* Configure EMAC pins */ gpio_configure_pin(PIN_EEMAC_EREFCK, PIN_EMAC_FLAGS); gpio_configure_pin(PIN_EMAC_ETX0, PIN_EMAC_FLAGS); gpio_configure_pin(PIN_EMAC_ETX1, PIN_EMAC_FLAGS); gpio_configure_pin(PIN_EMAC_ETXEN, PIN_EMAC_FLAGS); gpio_configure_pin(PIN_EMAC_ECRSDV, PIN_EMAC_FLAGS); gpio_configure_pin(PIN_EMAC_ERX0, PIN_EMAC_FLAGS); gpio_configure_pin(PIN_EMAC_ERX1, PIN_EMAC_FLAGS); gpio_configure_pin(PIN_EMAC_ERXER, PIN_EMAC_FLAGS); gpio_configure_pin(PIN_EMAC_EMDC, PIN_EMAC_FLAGS); gpio_configure_pin(PIN_EMAC_EMDIO, PIN_EMAC_FLAGS); /* device capabilities */ /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP #if defined(DHCP_USED) | NETIF_FLAG_DHCP #endif ; #ifdef FREERTOS_USED /* * NOTE: This routine contains code that polls status bits. If the Ethernet * cable is not plugged in then this can take a considerable time. To prevent * this from starving lower priority tasks of processing time we lower our * priority prior to the call, then raise it back again once the initialization * is complete. */ /* Read the priority of the current task. */ uxPriority = uxTaskPriorityGet( NULL ); /* Set the priority of the current task to the lowest possible. */ vTaskPrioritySet( NULL, tskIDLE_PRIORITY ); #endif /* Reset PHY */ rstc_set_external_reset(RSTC, 13); /* (2^(13+1))/32768 */ rstc_reset_extern(RSTC); while (rstc_get_status(RSTC) & RSTC_SR_NRSTL) { } /* Wait for PHY to be ready (CAT811: Max400ms) */ ul_dealy = sysclk_get_cpu_hz() / 6; while (ul_dealy--) { } /* Enable EMAC clock */ pmc_enable_periph_clk(ID_EMAC); /* Fill in EMAC options */ emac_option.uc_copy_all_frame = 0; emac_option.uc_no_boardcast = 0; memcpy(emac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address)); gs_emac_dev.p_hw = EMAC; /* Init EMAC driver structure */ emac_dev_init(EMAC, &gs_emac_dev, &emac_option); /* Enable Interrupt */ NVIC_EnableIRQ(EMAC_IRQn); /* Init MAC PHY driver */ if (ethernet_phy_init(EMAC, BOARD_EMAC_PHY_ADDR, sysclk_get_cpu_hz()) != EMAC_OK) { LWIP_DEBUGF(LWIP_DBG_TRACE, "PHY Initialize ERROR!\r"); return; } /* Auto Negotiate, work in RMII mode */ if (ethernet_phy_auto_negotiate(EMAC, BOARD_EMAC_PHY_ADDR) != EMAC_OK) { LWIP_DEBUGF(LWIP_DBG_TRACE, "Auto Negotiate ERROR!\r"); return; } /* Establish ethernet link */ while (ethernet_phy_set_link(EMAC, BOARD_EMAC_PHY_ADDR, 1) != EMAC_OK) { LWIP_DEBUGF(LWIP_DBG_TRACE, "Set link ERROR!\r"); } #ifdef FREERTOS_USED /* Restore the priority of the current task. */ vTaskPrioritySet( NULL, uxPriority ); /* Create the task that handles the EMAC input packets. */ sys_thread_new( "ETHINT", ethernetif_input, netif, netifINTERFACE_TASK_STACK_SIZE, netifINTERFACE_TASK_PRIORITY ); #endif }
BaseType_t xNetworkInterfaceInitialise( void ) { gmac_options_t xGMACOptions; extern uint8_t ucMACAddress[ 6 ]; const TickType_t xPHYDelay_400ms = 400UL; BaseType_t xReturn = pdFALSE; /* Ensure PHY is ready. */ vTaskDelay( xPHYDelay_400ms / portTICK_RATE_MS ); /* Enable GMAC clock. */ pmc_enable_periph_clk( ID_GMAC ); /* Fill in GMAC options */ xGMACOptions.uc_copy_all_frame = 0; xGMACOptions.uc_no_boardcast = 0; memcpy( xGMACOptions.uc_mac_addr, ucMACAddress, sizeof( ucMACAddress ) ); xGMACStruct.p_hw = GMAC; /* Init GMAC driver structure. */ gmac_dev_init( GMAC, &xGMACStruct, &xGMACOptions ); /* Init MAC PHY driver. */ if( ethernet_phy_init( GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz() ) == GMAC_OK ) { /* Auto Negotiate, work in RMII mode. */ if( ethernet_phy_auto_negotiate( GMAC, BOARD_GMAC_PHY_ADDR ) == GMAC_OK ) { /* Establish Ethernet link. */ vTaskDelay( xPHYDelay_400ms * 2UL ); if( ethernet_phy_set_link( GMAC, BOARD_GMAC_PHY_ADDR, 1 ) == GMAC_OK ) { /* Create the event semaphore if it has not already been created. */ if( xGMACRxEventSemaphore == NULL ) { xGMACRxEventSemaphore = xSemaphoreCreateCounting( ULONG_MAX, 0 ); #if ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 { /* If the trace recorder code is included name the semaphore for viewing in FreeRTOS+Trace. */ vTraceSetQueueName( xGMACRxEventSemaphore, "MAC_RX" ); } #endif /* ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 */ } /* Register the callbacks. */ gmac_dev_set_rx_callback( &xGMACStruct, prvGMACRxCallback ); /* The Rx deferred interrupt handler task is created at the highest possible priority to ensure the interrupt handler can return directly to it no matter which task was running when the interrupt occurred. */ xTaskCreate( prvGMACDeferredInterruptHandlerTask,/* The function that implements the task. */ "MACTsk", configMINIMAL_STACK_SIZE, /* Stack allocated to the task (defined in words, not bytes). */ NULL, /* The task parameter is not used. */ configMAX_PRIORITIES - 1, /* The priority assigned to the task. */ NULL ); /* The handle is not required, so NULL is passed. */ /* Enable the interrupt and set its priority as configured. THIS DRIVER REQUIRES configMAC_INTERRUPT_PRIORITY TO BE DEFINED, PREFERABLY IN FreeRTOSConfig.h. */ NVIC_SetPriority( GMAC_IRQn, configMAC_INTERRUPT_PRIORITY ); NVIC_EnableIRQ( GMAC_IRQn ); xReturn = pdPASS; } } } return xReturn; }