/**** Configure PHY to generate an interrupt when Eth Link state changes ****/ RES_CODE HAL_ETH_PHY_INTs(ETH_TypeDef* mac, const eth_mac_cfg_t* cfg) { uint32_t regvalue; RES_CODE res; // mask 30.4 // Source flag 29.4 Link Down // Interrupt source 1.2 Link Status // Event to assert Falling // Event to de-assert 1.2 Reading register 1 or Reading register 29 /* Read Register Configuration */ // HAL_ETH_ReadPHYRegister(mac, cfg, PHY_MICR, ®value); // regvalue |= (PHY_MICR_INT_EN | PHY_MICR_INT_OE); /* Enable Interrupts */ // HAL_ETH_WritePHYRegister(mac, cfg, PHY_MICR, regvalue ); /* Read Register Configuration */ res = HAL_ETH_ReadPHYRegister(mac, cfg, PHY_REG_IMR, ®value); if(res == RES_OK) { regvalue |= PHY_REG_IMR_LINK_STATUS; /* Enable Interrupt on change of link status */ res = HAL_ETH_WritePHYRegister(mac, cfg, PHY_REG_IMR, regvalue); } return res; }
// configure rj45 leds static void setPHYleds(ETH_HandleTypeDef * heth) { uint32_t regvalue; HAL_ETH_ReadPHYRegister(heth, PHY_CR, ®value); regvalue &= ~((1 << 5) | (1 << 6)); // mode 3 led -> orange->LINK , green -> FD/HD regvalue |= (1 << 6); HAL_ETH_WritePHYRegister(heth, PHY_CR, regvalue); }
static void low_level_init(struct netif *netif) { uint8_t macaddress[6]; uint32_t regvalue = 0; // Get Ethernet MAC address stm32f_set_mac_addr((uint8_t*) macaddress); EthHandle.Instance = ETH; EthHandle.Init.MACAddr = macaddress; EthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE; EthHandle.Init.Speed = ETH_SPEED_100M; EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX; EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII; EthHandle.Init.RxMode = ETH_RXINTERRUPT_MODE; EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE; EthHandle.Init.PhyAddress = DP83848_PHY_ADDRESS; /* configure ethernet peripheral (GPIOs, clocks, MAC, DMA) */ if (HAL_ETH_Init(&EthHandle) == HAL_OK) { /* Set netif link flag */ netif->flags |= NETIF_FLAG_LINK_UP; } /* Initialize Tx Descriptors list: Chain Mode */ HAL_ETH_DMATxDescListInit(&EthHandle, DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB); /* Initialize Rx Descriptors list: Chain Mode */ HAL_ETH_DMARxDescListInit(&EthHandle, DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB); /* set MAC hardware address length */ netif->hwaddr_len = ETHARP_HWADDR_LEN; /* set netif MAC hardware address */ stm32f_set_mac_addr((uint8_t*) netif->hwaddr); /* maximum transfer unit */ netif->mtu = 1500; /* device capabilities */ /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; /* Enable MAC and DMA transmission and reception */ HAL_ETH_Start(&EthHandle); /**** Configure PHY to generate an interrupt when Eth Link state changes ****/ /* Read Register Configuration */ HAL_ETH_ReadPHYRegister(&EthHandle, PHY_MICR, ®value); regvalue |= (PHY_MICR_INT_EN | PHY_MICR_INT_OE); /* Enable Interrupts */ HAL_ETH_WritePHYRegister(&EthHandle, PHY_MICR, regvalue ); /* Read Register Configuration */ HAL_ETH_ReadPHYRegister(&EthHandle, PHY_MISR, ®value); regvalue |= PHY_MISR_LINK_INT_EN; /* create a binary semaphore used for informing ethernetif of frame reception */ osSemaphoreDef( SEM , rtems_build_name( 'E', 'T', 'H', 'I' )); s_xSemaphore = osSemaphoreCreate( osSemaphore( SEM ), 0 ); /* create the task that handles the ETH_MAC */ osThreadDef( EthIf, ethernetif_input, osPriorityRealtime, 1, INTERFACE_THREAD_STACK_SIZE, rtems_build_name( 'E', 'T', 'H', 'I' )); osThreadCreate( osThread( EthIf ), netif ); /* Enable Interrupt on change of link status */ HAL_ETH_WritePHYRegister(&EthHandle, PHY_MISR, regvalue); }
status_t eth_init(const uint8_t *mac_addr, eth_phy_itf eth_phy) { LTRACE_ENTRY; DEBUG_ASSERT(mac_addr); eth.eth_phy = eth_phy; /* Enable ETHERNET clock */ __HAL_RCC_ETH_CLK_ENABLE(); eth.EthHandle.Instance = ETH; eth.EthHandle.Init.MACAddr = (uint8_t *)mac_addr; eth.EthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE; eth.EthHandle.Init.Speed = ETH_SPEED_100M; eth.EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX; switch (eth_phy) { case PHY_DP83848: eth.EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII; eth.EthHandle.Init.PhyAddress = DP83848_PHY_ADDRESS; break; case PHY_LAN8742A: eth.EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII; eth.EthHandle.Init.PhyAddress = LAN8742A_PHY_ADDRESS; break; case PHY_KSZ8721: eth.EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII; eth.EthHandle.Init.PhyAddress = KSZ8721_PHY_ADDRESS; break; default: return ERR_NOT_CONFIGURED; } eth.EthHandle.Init.RxMode = ETH_RXINTERRUPT_MODE; //eth.EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE; // XXX icmp checksums corrupted if stack stuff valid checksum eth.EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE; /* configure ethernet peripheral (GPIOs, clocks, MAC, DMA) */ if (HAL_ETH_Init(ð.EthHandle) != HAL_OK) return ERR_NOT_CONFIGURED; /* allocate descriptor and buffer memory from DTCM */ /* XXX do in a more generic way */ #if MEMBASE == 0x20000000 #error DTCM will collide with MEMBASE #endif addr_t tcm_ptr = RAMDTCM_BASE; eth.DMATxDscrTab = (void *)tcm_ptr; tcm_ptr += sizeof(*eth.DMATxDscrTab) * ETH_TXBUFNB; eth.DMARxDscrTab = (void *)tcm_ptr; tcm_ptr += sizeof(*eth.DMARxDscrTab) * ETH_RXBUFNB; eth.Tx_Buff = (void *)tcm_ptr; tcm_ptr += ETH_TX_BUF_SIZE * ETH_TXBUFNB; eth.Rx_Buff = (void *)tcm_ptr; tcm_ptr += ETH_RX_BUF_SIZE * ETH_RXBUFNB; /* Initialize Tx Descriptors list: Chain Mode */ HAL_ETH_DMATxDescListInit(ð.EthHandle, eth.DMATxDscrTab, eth.Tx_Buff, ETH_TXBUFNB); /* Initialize Rx Descriptors list: Chain Mode */ HAL_ETH_DMARxDescListInit(ð.EthHandle, eth.DMARxDscrTab, eth.Rx_Buff, ETH_RXBUFNB); /* Enable MAC and DMA transmission and reception */ HAL_ETH_Start(ð.EthHandle); #if 0 // XXX DP83848 specific /**** Configure PHY to generate an interrupt when Eth Link state changes ****/ /* Read Register Configuration */ uint32_t regvalue; HAL_ETH_ReadPHYRegister(ð.EthHandle, PHY_MICR, ®value); regvalue |= (PHY_MICR_INT_EN | PHY_MICR_INT_OE); /* Enable Interrupts */ HAL_ETH_WritePHYRegister(ð.EthHandle, PHY_MICR, regvalue ); /* Read Register Configuration */ HAL_ETH_ReadPHYRegister(ð.EthHandle, PHY_MISR, ®value); regvalue |= PHY_MISR_LINK_INT_EN; /* Enable Interrupt on change of link status */ HAL_ETH_WritePHYRegister(ð.EthHandle, PHY_MISR, regvalue); #endif /* set up an event to block the rx thread on */ event_init(ð.rx_event, false, EVENT_FLAG_AUTOUNSIGNAL); /* start worker thread */ thread_resume(thread_create("eth_rx", ð_rx_worker, NULL, HIGH_PRIORITY, DEFAULT_STACK_SIZE)); /* enable interrupts */ HAL_NVIC_EnableIRQ(ETH_IRQn); LTRACE_EXIT; return NO_ERROR; }
BaseType_t xNetworkInterfaceInitialise(void) { HAL_StatusTypeDef hal_eth_init_status; uint8_t status = 0; /* Init ETH */ heth_global.Instance = ETH; heth_global.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE; heth_global.Init.Speed = ETH_SPEED_100M; heth_global.Init.DuplexMode = ETH_MODE_FULLDUPLEX; heth_global.Init.PhyAddress = DP83848_PHY_ADDRESS; heth_global.Init.MACAddr = &ucMACAddress[0]; heth_global.Init.RxMode = ETH_RXINTERRUPT_MODE; #if (ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 1) && (ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 1) heth_global.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE; #else heth_global.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE; #endif heth_global.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII; hal_eth_init_status = HAL_ETH_Init(&heth_global); if (hal_eth_init_status == HAL_OK) { print_console(">> MAC init OK\r\n"); status = pdPASS; } else { return pdFAIL; print_console(">> MAC init failed\r\n"); } probePHY(&heth_global); /* Initialize Tx Descriptors list: Chain Mode */ HAL_ETH_DMATxDescListInit(&heth_global, DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB); //HAL_ETH_DMATxDescListInit(&heth_global, DMATxDscrTab, NULL, ETH_TXBUFNB); //InitializeZeroCopyBuffersTx(ETH_TXBUFNB,DMATxDscrTab); /* Initialize zero copy buffers */ //uint8_t* zerocopy_bufor_tab[ETH_RXBUFNB]; // tab to hold pointers to zero copy bufors /* Initialize Rx Descriptors list: Chain Mode */ HAL_ETH_DMARxDescListInit(&heth_global, DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB); /* Enable MAC and DMA transmission and reception */ HAL_ETH_Start(&heth_global); setPHYleds(&heth_global); #if PHY_LINK_CHANGE_INT uint32_t regvalue = 0; /**** Configure PHY to generate an interrupt when Eth Link state changes ****/ /* Read Register Configuration */ HAL_ETH_ReadPHYRegister(&heth_global, PHY_MICR, ®value); regvalue |= (PHY_MICR_INT_EN | PHY_MICR_INT_OE); /* Enable Interrupts */ HAL_ETH_WritePHYRegister(&heth_global, PHY_MICR, regvalue ); /* Read Register Configuration */ HAL_ETH_ReadPHYRegister(&heth_global, PHY_MISR, ®value); regvalue |= PHY_MISR_LINK_INT_EN; /* Enable Interrupt on change of link status */ HAL_ETH_WritePHYRegister(&heth_global, PHY_MISR, regvalue); #endif xTaskCreate(prvEMACDeferredInterruptHandlerTask, "EthRcvTask", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES-1, NULL); return status; }