void vuIP_Task( void *pvParameters ) { portBASE_TYPE i; uip_ipaddr_t xIPAddr; struct timer periodic_timer, arp_timer; /* Create the semaphore used by the ISR to wake this task. */ vSemaphoreCreateBinary( xSemaphore ); /* Initialise the uIP stack. */ timer_set( &periodic_timer, configTICK_RATE_HZ / 2 ); timer_set( &arp_timer, configTICK_RATE_HZ * 10 ); uip_init(); uip_ipaddr( xIPAddr, uipIP_ADDR0, uipIP_ADDR1, uipIP_ADDR2, uipIP_ADDR3 ); uip_sethostaddr( xIPAddr ); uip_ipaddr( xIPAddr, uipNET_MASK0, uipNET_MASK1, uipNET_MASK2, uipNET_MASK3 ); uip_setnetmask( xIPAddr ); uip_ipaddr( xIPAddr, uipGATEWAY_ADDR0, uipGATEWAY_ADDR1, uipGATEWAY_ADDR2, uipGATEWAY_ADDR3 ); uip_setdraddr( xIPAddr ); httpd_init(); /* Initialise the MAC. */ ENET_InitClocksGPIO(); ENET_Init(); portENTER_CRITICAL(); { ENET_Start(); prvSetMACAddress(); VIC_Config( ENET_ITLine, VIC_IRQ, 1 ); VIC_ITCmd( ENET_ITLine, ENABLE ); ENET_DMA->ISR = uipDMI_RX_CURRENT_DONE; ENET_DMA->IER = uipDMI_RX_CURRENT_DONE; } portEXIT_CRITICAL(); while(1) { /* Is there received data ready to be processed? */ uip_len = ENET_HandleRxPkt( uip_buf ); if( uip_len > 0 ) { /* Standard uIP loop taken from the uIP manual. */ if( xHeader->type == htons( UIP_ETHTYPE_IP ) ) { uip_arp_ipin(); uip_input(); /* If the above function invocation resulted in data that should be sent out on the network, the global variable uip_len is set to a value > 0. */ if( uip_len > 0 ) { uip_arp_out(); prvENET_Send(); } } else if( xHeader->type == htons( UIP_ETHTYPE_ARP ) ) { uip_arp_arpin(); /* If the above function invocation resulted in data that should be sent out on the network, the global variable uip_len is set to a value > 0. */ if( uip_len > 0 ) { prvENET_Send(); } } } else { if( timer_expired( &periodic_timer ) ) { timer_reset( &periodic_timer ); for( i = 0; i < UIP_CONNS; i++ ) { uip_periodic( i ); /* If the above function invocation resulted in data that should be sent out on the network, the global variable uip_len is set to a value > 0. */ if( uip_len > 0 ) { uip_arp_out(); prvENET_Send(); } } /* Call the ARP timer function every 10 seconds. */ if( timer_expired( &arp_timer ) ) { timer_reset( &arp_timer ); uip_arp_timer(); } } else { /* We did not receive a packet, and there was no periodic processing to perform. Block for a fixed period. If a packet is received during this period we will be woken by the ISR giving us the Semaphore. */ xSemaphoreTake( xSemaphore, configTICK_RATE_HZ / 2 ); } } } }
/** \brief Low level init of the MAC and PHY. * * \param[in] netif Pointer to LWIP netif structure */ static err_t low_level_init(struct netif *netif) { struct k64f_enetdata *k64f_enet = netif->state; uint8_t i; uint32_t sysClock; phy_speed_t phy_speed; phy_duplex_t phy_duplex; uint32_t phyAddr = 0; bool link = false; enet_config_t config; // Allocate RX descriptors rx_desc_start_addr = (uint8_t *)calloc(1, sizeof(enet_rx_bd_struct_t) * ENET_RX_RING_LEN + ENET_BUFF_ALIGNMENT); if(!rx_desc_start_addr) return ERR_MEM; // Allocate TX descriptors tx_desc_start_addr = (uint8_t *)calloc(1, sizeof(enet_tx_bd_struct_t) * ENET_TX_RING_LEN + ENET_BUFF_ALIGNMENT); if(!tx_desc_start_addr) return ERR_MEM; rx_desc_start_addr = (uint8_t *)ENET_ALIGN(rx_desc_start_addr, ENET_BUFF_ALIGNMENT); tx_desc_start_addr = (uint8_t *)ENET_ALIGN(tx_desc_start_addr, ENET_BUFF_ALIGNMENT); /* Create buffers for each receive BD */ for (i = 0; i < ENET_RX_RING_LEN; i++) { rx_buff[i] = pbuf_alloc(PBUF_RAW, ENET_ETH_MAX_FLEN + ENET_BUFF_ALIGNMENT, PBUF_RAM); if (NULL == rx_buff[i]) return ERR_MEM; /* K64F note: the next line ensures that the RX buffer is properly aligned for the K64F RX descriptors (16 bytes alignment). However, by doing so, we're effectively changing a data structure which is internal to lwIP. This might not prove to be a good idea in the long run, but a better fix would probably involve modifying lwIP itself */ rx_buff[i]->payload = (void*)ENET_ALIGN((uint32_t)rx_buff[i]->payload, ENET_BUFF_ALIGNMENT); rx_ptr[i] = rx_buff[i]->payload; } k64f_enet->tx_consume_index = k64f_enet->tx_produce_index = 0; /* prepare the buffer configuration. */ enet_buffer_config_t buffCfg = { ENET_RX_RING_LEN, ENET_TX_RING_LEN, ENET_ALIGN(ENET_ETH_MAX_FLEN, ENET_BUFF_ALIGNMENT), 0, (volatile enet_rx_bd_struct_t *)rx_desc_start_addr, (volatile enet_tx_bd_struct_t *)tx_desc_start_addr, (uint8_t *)&rx_ptr, NULL, }; #if (defined(TARGET_K64F) && (defined(TARGET_FRDM))) k64f_init_eth_hardware(); #endif #if (defined(TARGET_K66F) && (defined(TARGET_FRDM))) k66f_init_eth_hardware(); #endif sysClock = CLOCK_GetFreq(kCLOCK_CoreSysClk); ENET_GetDefaultConfig(&config); PHY_Init(ENET, 0, sysClock); PHY_GetLinkStatus(ENET, phyAddr, &link); if (link) { /* Get link information from PHY */ PHY_GetLinkSpeedDuplex(ENET, phyAddr, &phy_speed, &phy_duplex); /* Change the MII speed and duplex for actual link status. */ config.miiSpeed = (enet_mii_speed_t)phy_speed; config.miiDuplex = (enet_mii_duplex_t)phy_duplex; config.interrupt = kENET_RxFrameInterrupt | kENET_TxFrameInterrupt; } config.rxMaxFrameLen = ENET_ETH_MAX_FLEN; config.macSpecialConfig = kENET_ControlFlowControlEnable; config.txAccelerConfig = kENET_TxAccelIsShift16Enabled; config.rxAccelerConfig = kENET_RxAccelisShift16Enabled | kENET_RxAccelMacCheckEnabled; ENET_Init(ENET, &g_handle, &config, &buffCfg, netif->hwaddr, sysClock); ENET_SetCallback(&g_handle, ethernet_callback, netif); ENET_ActiveRead(ENET); return ERR_OK; }