Running TCP/IP Stack in Linux
With uClinux running on the STM32H7, you get the full Linux TCP/IP stack. Userspace POSIX APIs are provided by the uClibc library. Key user-space networking tools and utilities are available from the multi-call busybox. Additional tools and packages, such as for instance the SSH dropbear server, can be built specifically for uClinux. All in all, you have the powerful Linux TCP/IP stack at your disposal.
There is a full-functioning Ethernet device driver available in the kernel tree for the STM32H7 SOM. The device driver is linux/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
configured in the kernel using the CONFIG_DWMAC_STM32
build time option in Device Drivers -> Network device support -> Ethernet driver support -> STMicroelectronics devices -> STM32 DWMAC support.
For the run-time configuration of the kernel, Ethernet is enabled in rootfs.dts.STM32H7
in projects/rootfs
as follows:
&mac {
status = "okay";
pinctrl-0 = <ðernet_rmii>;
pinctrl-names = "default";
phy-mode = "rmii";
phy-handle = <&phy0>;
mdio0 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "snps,dwmac-mdio";
phy0: ethernet-phy@0 {
reg = <1>;
};
};
};
This will register a platform device for the STM32H7 SOM Ethernet controller with the Ethernet driver.
The Linux project provided by Emcraft in the distribution (refer to projects/rootfs
) and installed on each shipping module and kit includes the TCP/IP stack and various network related capabilities. The following snapshot shows the full Linux bootstrap sequence from power-on to the Linux shell:
U-Boot SPL 2019.04- (Jul 07 2023 - 11:10:24 +0000)
Hit 's' key to enter spl shell:
Trying to boot from SPI
U-Boot 2019.04- (Jul 07 2023 - 11:10:24 +0000)
Model: STMicroelectronics STM32H7 SOM
DRAM: 64 MiB
SF: Detected n25q512ax3 with page size 256 Bytes, erase size 4 KiB, total 64 MiB
Flash: 128 KiB
MMC: STM32 SDMMC2: 0
Loading Environment from UBI... ubi0: default fastmap pool size: 256
ubi0: default fastmap WL pool size: 128
ubi0: attaching mtd2
ubi0: scanning is finished
ubi0: attached mtd2 (name "system", size 23 MiB)
ubi0: PEB size: 4096 bytes (4 KiB), LEB size: 3968 bytes
ubi0: min./max. I/O unit sizes: 1/256, sub-page size 1
ubi0: VID header offset: 64 (aligned 64), data offset: 128
ubi0: good PEBs: 5888, bad PEBs: 0, corrupted PEBs: 0
ubi0: user volume: 5, internal volumes: 1, max. volumes count: 23
ubi0: max/mean erase counter: 2/1, WL threshold: 4096, image sequence number: 0
ubi0: available PEBs: 1067, total reserved PEBs: 4821, PEBs reserved for bad
PEB handling: 0
Read 16384 bytes from volume env1 to d396f620
Read 16384 bytes from volume env2 to d3973640
OK
In: serial
Out: serial
Err: serial
No size specified -> Using max size (2099072)
Read 2099072 bytes from volume splash to d0c00000
Net: eth0: ethernet@40028000
Hit any key to stop autoboot: 0
Booting Image #1
No size specified -> Using max size (8392320)
Read 8392320 bytes from volume rtos1 to d0c00000
## Booting kernel from Legacy Image at d0c00000 ...
Image Name: Linux-5.15.67
Image Type: ARM Linux Multi-File Image (uncompressed)
Data Size: 6447130 Bytes = 6.1 MiB
Load Address: d0008000
Entry Point: d0008001
Contents:
Image 0: 6432192 Bytes = 6.1 MiB
Image 1: 14926 Bytes = 14.6 KiB
Verifying Checksum ... OK
## Loading init Ramdisk from multi component Legacy Image at d0c00000 ...
## Flattened Device Tree from multi component Image at D0C00000
Booting using the fdt at 0xd122260c
Loading Multi-File Image ... OK
Loading Ramdisk to d3972000, end d3975a4e ... OK
Loading Device Tree to d396b000, end d3971a4d ... OK
Starting kernel ...
[ 0.000000] Booting Linux on physical CPU 0x0
[ 0.000000] Linux version 5.15.67 (sasha@workbench.emcraft.com)
(arm-none-eabi-gcc (GNU Arm Embedded Toolchain
10.3-2021.10) 10.3.1 20210824 (release), GNU ld (GNU Arm Embedded Toolchain
10.3-2021.10) 2.36.1.20210621)
#2 PREEMPT Fri Jul 7 11:02:11 UTC 2023
[ 0.000000] CPU: ARMv7-M [411fc271] revision 1 (ARMv7M), cr=00000000
[ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, PIPT instruction cache
[ 0.000000] OF: fdt: Machine model: STM32H7 SOM Starter Kit
[ 0.000000] printk: bootconsole [earlycon0] enabled
[ 0.000000] printk: debug: ignoring loglevel setting.
[ 0.000000] Reserved memory: created DMA memory pool at 0xd3f00000, size 1 MiB
[ 0.000000] OF: reserved mem: initialized node dmapool, compatible id
shared-dma-pool
[ 0.000000] Zone ranges:
[ 0.000000] Normal [mem 0x00000000d0000000-0x00000000d3ffffff]
[ 0.000000] Movable zone start for each node
[ 0.000000] Early memory node ranges
[ 0.000000] node 0: [mem 0x00000000d0000000-0x00000000d3bfffff]
[ 0.000000] node 0: [mem 0x00000000d3c00000-0x00000000d3ffffff]
[ 0.000000] Initmem setup node 0 [mem 0x00000000d0000000-0x00000000d3ffffff]
[ 0.000000] pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
[ 0.000000] pcpu-alloc: [0] 0
[ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 16256
[ 0.000000] Kernel command line: console=ttySTM0,115200 earlyprintk
consoleblank=0 panic=3 ignore_loglevel
ip=172.17.0.66:172.17.0.1::::eth0:off
[ 0.000000] Unknown kernel command line parameters "consoleblank=0
ip=172.17.0.66:172.17.0.1::::eth0:off",
will be passed to user space.
[ 0.000000] Dentry cache hash table entries: 8192 (order: 3, 32768 bytes,
linear)
[ 0.000000] Inode-cache hash table entries: 4096 (order: 2, 16384 bytes,
linear)
[ 0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
[ 0.000000] Memory: 54356K/65536K available (2472K kernel code, 313K rwdata,
1100K rodata, 2240K init, 122K bss,
11180K reserved, 0K cma-reserved)
[ 0.000000] SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[ 0.000000] rcu: Preemptible hierarchical RCU implementation.
[ 0.000000] rcu: RCU event tracing is enabled.
[ 0.000000] Trampoline variant of Tasks RCU enabled.
[ 0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 10
jiffies.
[ 0.000000] NR_IRQS: 16, nr_irqs: 16, preallocated irqs: 16
[ 0.000000] /soc/interrupt-controller@58000000: bank0
[ 0.000000] /soc/interrupt-controller@58000000: bank1
[ 0.000000] /soc/interrupt-controller@58000000: bank2
[ 0.000000] clocksource: arm_system_timer: mask: 0xffffff max_cycles:
0xffffff, max_idle_ns: 29863442 ns
[ 0.000000] ARM System timer initialized as clocksource
[ 0.000012] sched_clock: 32 bits at 200MHz, resolution 5ns, wraps every
10737418237ns
[ 0.007939] timer@40000c00: STM32 sched_clock registered
[ 0.013294] Switching to timer-based delay loop, resolution 5ns
[ 0.019243] timer@40000c00: STM32 delay timer registered
[ 0.024598] clocksource: timer@40000c00: mask: 0xffffffff max_cycles:
0xffffffff, max_idle_ns: 9556302233 ns
[ 0.034508] /soc/timer@40000c00: STM32 clockevent driver initialized (32 bits)
[ 0.042665] Calibrating delay loop (skipped), value calculated using timer
frequency.. 400.00
BogoMIPS (lpj=2000000)
[ 0.053397] pid_max: default: 4096 minimum: 301
[ 0.058758] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
[ 0.066352] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes,
linear)
[ 0.082295] rcu: Hierarchical SRCU implementation.
[ 0.089681] devtmpfs: initialized
[ 0.118466] DMA: default coherent area is set
[ 0.122921] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff,
max_idle_ns: 19112604462750000 ns
[ 0.133076] pinctrl core: initialized pinctrl subsystem
[ 0.143231] NET: Registered PF_NETLINK/PF_ROUTE protocol family
[ 0.180330] stm32h743-pinctrl soc:pin-controller@58020000: GPIOA bank added
[ 0.189425] stm32h743-pinctrl soc:pin-controller@58020000: GPIOB bank added
[ 0.198466] stm32h743-pinctrl soc:pin-controller@58020000: GPIOC bank added
[ 0.207591] stm32h743-pinctrl soc:pin-controller@58020000: GPIOD bank added
[ 0.216689] stm32h743-pinctrl soc:pin-controller@58020000: GPIOE bank added
[ 0.225964] stm32h743-pinctrl soc:pin-controller@58020000: GPIOF bank added
[ 0.235219] stm32h743-pinctrl soc:pin-controller@58020000: GPIOG bank added
[ 0.244763] stm32h743-pinctrl soc:pin-controller@58020000: GPIOH bank added
[ 0.254189] stm32h743-pinctrl soc:pin-controller@58020000: GPIOI bank added
[ 0.263413] stm32h743-pinctrl soc:pin-controller@58020000: GPIOJ bank added
[ 0.272836] stm32h743-pinctrl soc:pin-controller@58020000: GPIOK bank added
[ 0.279930] stm32h743-pinctrl soc:pin-controller@58020000: Pinctrl
STM32 initialized
[ 0.322332] stm32-mdma 52000000.dma-controller: STM32 MDMA driver registered
[ 0.332046] pps_core: LinuxPPS API ver. 1 registered
[ 0.337097] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo
Giometti <
giometti@linux.it>
[ 0.346595] PTP clock support registered
[ 0.355718] clocksource: Switched to clocksource timer@40000c00
[ 0.370121] NET: Registered PF_INET protocol family
[ 0.375946] IP idents hash table entries: 2048 (order: 2, 16384 bytes, linear)
[ 0.386209] tcp_listen_portaddr_hash hash table entries: 512 (order: 0,
4096 bytes, linear)
[ 0.394752] Table-perturb hash table entries: 65536 (order: 6, 262144 bytes,
linear)
[ 0.403085] TCP established hash table entries: 1024 (order: 0, 4096 bytes,
linear)
[ 0.411156] TCP bind hash table entries: 1024 (order: 0, 4096 bytes, linear)
[ 0.418582] TCP: Hash tables configured (established 1024 bind 1024)
[ 0.425522] UDP hash table entries: 256 (order: 0, 4096 bytes, linear)
[ 0.432493] UDP-Lite hash table entries: 256 (order: 0, 4096 bytes, linear)
[ 0.440671] NET: Registered PF_UNIX/PF_LOCAL protocol family
[ 0.456203] workingset: timestamp_bits=30 max_order=14 bucket_order=0
[ 0.523138] io scheduler mq-deadline registered
[ 0.535965] io scheduler kyber registered
[ 0.557198] STM32 USART driver initialized
[ 0.562753] stm32-usart 40011000.serial: interrupt mode for rx (no dma)
[ 0.576839] stm32-usart 40011000.serial: interrupt mode for tx (no dma)
[ 0.583632] 40011000.serial: ttySTM0 at MMIO 0x40011000 (irq = 30, base_baud =
12500000) is a stm32-usart
[ 0.609685] printk: console [ttySTM0] enabled
[ 0.609685] printk: console [ttySTM0] enabled
[ 0.638237] printk: bootconsole [earlycon0] disabled
[ 0.638237] printk: bootconsole [earlycon0] disabled
[ 0.667402] stm32-dwmac 40028000.ethernet: IRQ eth_wake_irq not found
[ 0.672549] stm32-dwmac 40028000.ethernet: IRQ eth_lpi not found
[ 0.696974] stm32-dwmac 40028000.ethernet: PTP uses main clock
[ 0.706411] stm32-dwmac 40028000.ethernet: User ID: 0x31, Synopsys ID: 0x42
[ 0.712088] stm32-dwmac 40028000.ethernet: DWMAC4/5
[ 0.737006] stm32-dwmac 40028000.ethernet: DMA HW capability register
supported
[ 0.742966] stm32-dwmac 40028000.ethernet: RX Checksum Offload Engine
supported
[ 0.766116] stm32-dwmac 40028000.ethernet: TX Checksum insertion supported
[ 0.771656] stm32-dwmac 40028000.ethernet: Wake-Up On Lan supported
[ 0.786546] stm32-dwmac 40028000.ethernet: TSO supported
[ 0.790569] stm32-dwmac 40028000.ethernet: Enable RX Mitigation via
HW Watchdog Timer
[ 0.818708] stm32-dwmac 40028000.ethernet: device MAC address b6:9c:51:c9:a2:
3f
[ 0.824692] stm32-dwmac 40028000.ethernet: Enabled L3L4 Flow TC (entries=2)
[ 0.846095] stm32-dwmac 40028000.ethernet: Enabled RFS Flow TC (entries=8)
[ 0.851667] stm32-dwmac 40028000.ethernet: Using 32 bits DMA width
[ 1.153156] Unpacking initramfs...
[ 1.155275] Initramfs unpacking failed: invalid magic at start of compressed
archive
[ 1.163609] Freeing initrd memory: 16K
[ 1.176665] i2c_dev: i2c /dev entries driver
[ 1.182850] mmci-pl18x 52007000.mmc: failed to get pinctrl
[ 2.207936] NET: Registered PF_INET6 protocol family
[ 2.217643] Segment Routing with IPv6
[ 2.220347] In-situ OAM (IOAM) with IPv6
[ 2.224219] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
[ 2.233229] NET: Registered PF_PACKET protocol family
[ 2.251070] Freeing unused kernel image (initmem) memory: 2240K
[ 2.255676] This architecture does not have kernel memory protection.
[ 2.262220] Run /init as init process
[ 2.265995] with arguments:
[ 2.268703] /init
[ 2.270976] with environment:
[ 2.274056] HOME=/
[ 2.276533] TERM=linux
[ 2.279125] consoleblank=0
[ 2.282109] ip=172.17.0.66:172.17.0.1::::eth0:off
init started: BusyBox v1.24.2 (2023-07-07 11:01:57 UTC)
[38] Jan 01 00:00:02 Running in background
/ # [ 2.527312] stm32-dwmac 40028000.ethernet eth0: PHY [stmmac-0:01] driver
[SMSC LAN8710/LAN8720] (irq=POLL)
[ 2.536356] stm32-dwmac 40028000.ethernet eth0: Register MEM_TYPE_PAGE_POOL
RxQ-0
[ 2.545894] stm32-dwmac 40028000.ethernet eth0: No Safety Features support
found
[ 2.551950] stm32-dwmac 40028000.ethernet eth0: IEEE 1588-2008 Advanced
Timestamp supported
[ 2.561350] stm32-dwmac 40028000.ethernet eth0: registered PTP clock
[ 2.568913] stm32-dwmac 40028000.ethernet eth0: configuring for phy/rmii
link mode
[ 4.649596] stm32-dwmac 40028000.ethernet eth0: Link is Up - 100Mbps/Full
- flow control rx/tx
[ 4.657026] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
/ #
Let's test the TCP/IP stack on the STM32H7-SOM.
From the development host validate that the STM32H7-SOM is visible using ping
:
$ ping -c 5 172.17.0.66
PING 172.17.0.66 (172.17.0.66) 56(84) bytes of data.
64 bytes from 172.17.0.66: icmp_seq=1 ttl=64 time=1.37 ms
64 bytes from 172.17.0.66: icmp_seq=2 ttl=64 time=0.750 ms
64 bytes from 172.17.0.66: icmp_seq=3 ttl=64 time=0.747 ms
64 bytes from 172.17.0.66: icmp_seq=4 ttl=64 time=0.734 ms
64 bytes from 172.17.0.66: icmp_seq=5 ttl=64 time=0.734 ms
--- 172.17.0.66 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4054ms
rtt min/avg/max/mdev = 0.734/0.866/1.369/0.251 ms$
ping
the development host from the STM32H7 SOM:
On the target, start the telnetd
daemon to allow connections to the STM32H7:
Connect to the target from the development host using telnet
. The target is configured to accept the 123
password for root
:
The dropbear
SSH daemon starts automatically on the target. Verify that dropbear
allows secure connections to the target:
Connect to the target from the development host using ssh
. The first connection takes several seconds to establish as the STM32H7 runs computation-extensive key calculations. Again, enter 123 on the password prompt:
On the target, enable access to the Internet by configuring a default gateway. Note also that the system makes use of the public name server provided by Google:
Use ntpd
to synchronize the time on the target with the time provided by a public server:
Use wget
to download a file from a remote server:
Mount a directory exported by a development host over NFS:
Start the HTTP daemon:
From a local host, open a Web browser to the STM32H7-SOM and watch the demo web page provided by the target. The STM32H7-SOM shows the current time and date as well as the list of the currently running processes: