One of my reasons for fooling around with CubeMX was to find out if I could get CubeMX to setup code including an ethernet driver.
Doing so looks promising. I see that lwip is offered as "middleware". Also it seems possible to get an http server going "out of the box".
Note that the first two use RMII, while the third uses MII.
On my boards:
I see a warning for t he H747 Disco that the ETH_MDC pin is shared with the on-board digital microphone. This must be resolved by physical jumper (solder bridge) setup on the board itself.
Note that the usual thing is that a 25 Mhz crystal clocks the PHY, which in turn generates the 50 Mhz clock (RMII_REF_CLK) and passes it to the MAC on the STM32.
I don't resolve the HSE issue for now, (See below).
I decide to set a static IP 192.168.0.74 for lwip. This is easy to do.
I go to Project Manager and tell it to generate a Makefile, calling the project Net1. It warns me that some LwIP parameters may not be set up right. I go back under "platform parameters" and find that I need to select the 8742 PHY chip and the driver for it, which is easy.
I generate code!
I go to ~/Cube/Net1 and type "make". It builds clean and fairly quickly. Mostly I want to see two things. One is I want to see what it digs up as source for the ethernet drive. The other is I want to see how it handles it when I go back to change configuration and want to regenerate code.
I go back and type:
cd ~/Cube/Net1 make clean make >make.logThis gives me a file I can search using vim to see what components were used in the build and where they came from.
Now you can use the clock configuration tab. I have seen misinformation that this is 25/3 (8.33), but I don't believe it and enter 8.00. Then enter 480 for the desired CPU frequency, and it works out all the PLL settings and divisors.
The PLL takes the 8 Mhz unchanged (first divisor is 1) then multiplies by 120 and has a final divide by 2 to give 480. It divides by 2 (HPRE) to get 240, then again by 2 to give 120 for PCLK1,2,...
cd ~/Cube/Net1 make clean make -j20 cd build flash Net1.elfIt is still running the LED demo that changes when I press the user button. On my linux machine, I add an entry to my hosts file:
# 10-11-2026 Nucleo board 192.168.0.74 st743I find and connect a network cable. The LED on the RJ45 jack both begin to blink at about 1 Hz.
MX_LWIP_Init();I also see a call to printf() -- and I see the output on the USB console.
while (1) {
MX_LWIP_Process();
}
No ping yet running the code with this addition.
So we go back and start double-checking everything.
Note: Looking through the various LwiP settings in CubeMX, I see that it offers HTTPD (but it is currently disabled).
I don't see any place to configure the PHY address. Curiously, I configure the PHY device in the LwiP settings.
As recommended, I check the pin configuration. I start from ETH under Connectivity, which as a GPIO section. This shows several pins misconfigured, but you don't change them here. You go back to Core->GPIO and use the package diagram.
I see PB11 assigned to TX_EN, but it should be PG11
I see PB12 assigned to TXDO, but it should be PG13
By finding PG11 and PG13 on the edges of the package diagram, I can get a menu and select the desired function. When I do this, PB11 and PB12 get automatically deassigned, which is nice.
I use "generate code" then rebuild. I fully expected the small handful
of changes I made to main.c to be overwritten, but it seems to respect
the markings that say "USER CODE BEGIN" and "END".
No ping yet.
I go to LwiP and select the heap size under "Key Options", changing it from 1600 to 5000. I also change the LwiP debugging level to All.
Now I go to "System Core", "Cortex M7" and set up an MPU region. I see only MPU region 0 starting at 0 and 4G in size. I leave this be. I select MPU region 1 and enable it. Then I set up the following:
Base - 0x30000000 Size - 32KB (the default) TEX field level - level 1 Access permission - ALL Instruction access - disable Shareability - enable Cacheability - disable Bufferable - disableNext I am advised to add these lines to the linker script:
.lwip_sec (NOLOAD) : {
. = ABSOLUTE(0x30000000);
*(.RxDescripSection)
. = ABSOLUTE(0x30000080);
*(.TxDescripSection)
. = ABSOLUTE(0x30000100);
*(.Rx_PoolSection)
} >RAM_D2
I add this to STM32H743xx_FLASH.ld, generate code, and rebuild.
We have two starting points to dig into the source code, maybe three:
ETH_IRQHandler () MX_LWIP_Init () MX_LWIP_Process ()We find ETH_IRQHandler() in Src/stm32h7xx_it.c It simply bounces the call:
extern ETH_HandleTypeDef heth; HAL_ETH_IRQHandler(&heth);This is in Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_eth.c I add a line here to call printf("ETH") and see nothing on the console.
We find MX_LWIP_Init() in LWIP/App/lwip.c
We find MX_LWIP_Process() in LWIP/App/lwip.c
The process routine looks like:
void MX_LWIP_Process(void)
{
ethernetif_input(&gnetif);
sys_check_timeouts();
Ethernet_Link_Periodic_Handle(&gnetif);
}
So, it reads a packet if there is one, passing it to
Ethernet_Link_Periodic_Handle() -- apparently the status
of whether or not there actually is a packet is in the
structure. This function is in the same file and is
pretty simple.
static void Ethernet_Link_Periodic_Handle(struct netif *netif)
{
/* Ethernet Link every 100ms */
if (HAL_GetTick() - EthernetLinkTimer >= 100) {
EthernetLinkTimer = HAL_GetTick();
ethernet_link_check_state(netif);
}
}
In fact lwip.c is only 250 lines and is apparently generated by CubeMX as
a glue layer on top of LwiP itself..
Tom's software pages / tom@mmto.org