I have an RT1024 on a custom board, but the hardware regarding the ethernet and memory is the same. Phy ksz8081, dram IS42S16160-6 at 125MHz. My issue is that for some reason, I never see any data coming out of the MAC over the RMII interface, and as a result, no data is ever transmitted to the network. I receive zero errors regarding this, and the phy registers/configuration matches the SDK example for the given connection (10Mbps half duplex vs 100Mbps full duplex, etc). I am confident that the phy is able to establish a link with the other side of the network, indicated by lights on both ends, and the fact that the link waiting period goes by and passes (see code below).
Physically, I have verified that there is no data on the TX lines of the RMII, and that the RMII clock output from the CPU is a clean 50MHz (both verified with scope). I have defined "FSL_FEATURE_PHYKSZ8081_USE_RMII50M_MODE", and like I said earlier, the phy registers match what I would expect.
I've also verified that it is not a hardware problem. If I modify the lwip_ping_freertos sdk example to link to RAM (DRAM), it runs perfectly. I have compared the register stacks for the ENET module between my code and the SDK example, and the only differences were the TDAR, MII data register, MIB (which I set to enable the counters), RDSR, and TDSR.
My memory map is setup like this:
- Code/data: SDRAM loaded/copied by uTasker bootloader
- Stack/Heap: DTCM, which has been resized to take the full 256k on the CPU. Heap size is 64k, stack is only 4k but the rtos task stack is derived from the heap so it's ok.
- Cache is disabled globally in main(), right after the MPU configuration. I have also tried this with the driver cache control enable define, but there was no change.
class Hardware {
........
public:
/**
* Phy resource object for the phy.
* Must be public so that the LWIP task can get it
*/
phy_ksz8081_resource_t g_phy_resource;
/**
* Phy Handle
*/
phy_handle_t phyHandle;
netif lwip_netif;
}
extern const phy_operations_t phyksz8081_ops;
static void lwIP_init(void *arg) {
Hardware * hw = (Hardware *)arg;
hw->g_phy_resource.write = MDIO_Write;
hw->g_phy_resource.read = MDIO_Read;
// Enable the 50MHz RMII Clock derived from ENET PLL
IOMUXC_EnableMode(IOMUXC_GPR, kIOMUXC_GPR_ENET1TxClkOutputDir, true);
ethernetif_config_t lwIP_netif0_enet_config = {
.phyHandle = &hw->phyHandle,
.phyAddr = BECK_PHYKSZ8081_ADDRESS,
.phyOps = &phyksz8081_ops,
.phyResource = &hw->g_phy_resource,
.srcClockHz = 125000000UL,
};
// gotta memcpy in the MAC address
// though we could just directly bit bang the registers later
memcpy(&lwIP_netif0_enet_config.macAddress, hw->GetMACAddr(), 6);
uint8_t * ip_addr = hw->GetIPAddr();
uint8_t * ip_netmask = hw->GetSubnetMask();
uint8_t * ip_gateway = hw->GetGateway();
/* lwIP IP address initialization */
IP4_ADDR(&lwIP_netif0_ipaddr, ip_addr[0], ip_addr[1],
ip_addr[2], ip_addr[3]);
/* lwIP netmask initialization */
IP4_ADDR(&lwIP_netif0_netmask, ip_netmask[0], ip_netmask[1],
ip_netmask[2], ip_netmask[3]);
/* lwIP gateway initialization */
IP4_ADDR(&lwIP_netif0_gw, ip_gateway[0], ip_gateway[1], ip_gateway[2],
ip_gateway[3]);
/* lwIP module initialization */
tcpip_init(tcpip_init_done, NULL);
/* ENET peripheral initialization */
/* ENET clock enable */
(void)CLOCK_EnableClock(s_enetClock[ENET_GetInstance(ENET)]);
/* ENET set SMI (serial management interface) */
ENET_SetSMI(ENET, CLOCK_GetFreq(kCLOCK_IpgClk), false);
/* lwIP network interface initialization */
netifapi_netif_add(&hw->lwip_netif, &lwIP_netif0_ipaddr, &lwIP_netif0_netmask,
&lwIP_netif0_gw, &lwIP_netif0_enet_config, ethernetif0_init,
tcpip_input);
netifapi_netif_set_default(&hw->lwip_netif);
netifapi_netif_set_up(&hw->lwip_netif);
#if (BECK_BOARD_REVISION_MAJOR == 1U) // Board Revision A
#warning Forcing Ethernet Phy RMII Mode (BA5533A)
// Strapping options are f'd up
// Force RMII mode override
MDIO_Write(1, 0x16, 2);
#endif
#ifdef DEBUG
xTaskCreate(get_phyregs, "Phy Debug", 128, NULL,0, NULL);
// enable the ethenet statistics counters
ENET->MIBC &= 0x7FFF; // set b31 0
#endif
/* lwIP interface auto-negotiation check */
while (ethernetif_wait_linkup(&hw->lwip_netif, 5000UL) != ERR_OK) {
PRINTF(
"PHY Auto-negotiation failed. Please check the cable connection and link partner setting.\r\n");
}
// link status is now UP
// print debug stuff
PRINTF("\r\n************************************************\r\n");
PRINTF(" BA-5533 Network Configuration\r\n");
PRINTF("************************************************\r\n");
PRINTF(" IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t *)&lwIP_netif0_ipaddr)[0], ((u8_t *)&lwIP_netif0_ipaddr)[1],
((u8_t *)&lwIP_netif0_ipaddr)[2], ((u8_t *)&lwIP_netif0_ipaddr)[3]);
PRINTF(" IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t *)&lwIP_netif0_netmask)[0], ((u8_t *)&lwIP_netif0_netmask)[1],
((u8_t *)&lwIP_netif0_netmask)[2], ((u8_t *)&lwIP_netif0_netmask)[3]);
PRINTF(" IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t *)&lwIP_netif0_gw)[0], ((u8_t *)&lwIP_netif0_gw)[1],
((u8_t *)&lwIP_netif0_gw)[2], ((u8_t *)&lwIP_netif0_gw)[3]);
/*PRINTF(" MAC Address : %02X:%02X:%02X:%02X:%02X:%02X\r\n", (u8_t *)(&hw->lwip_netif.hwaddr[0]), &hw->lwip_netif.hwaddr[1],
&hw->lwip_netif.hwaddr[2], &hw->lwip_netif.hwaddr[3], &hw->lwip_netif.hwaddr[4], &hw->lwip_netif.hwaddr[5]);
*/
PRINTF("************************************************\r\n");
ping_init(&lwIP_netif0_gw);
// because tasks must not return, call task delete
vTaskDelete(NULL);
}
the stack size for the init task is 512, but I don't think it really needs all that much. The TCPIP thread spawns just fine, as well as the LWIP RX thread.
Any help or insight is appreciated.