NXP i.MXRT10XX: Running TCP/IP Stack in Linux

NXP i.MXRT10XX: Running TCP/IP Stack in Linux

With uClinux running on the i.MX RT10XX, 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 i.MX RT10XX. The device driver is linux/drivers/net/ethernet/freescale/fec_main.c configured in the kernel using the CONFIG_FEC build time option in Device Drivers -> Network device support -> Ethernet driver support -> Freescale devices -> FEC ethernet controller (of ColdFire and some i.MX CPUs).

For the run-time configuration of the kernel, Ethernet is enabled in rootfs.dts.IMXRT102X_NXPEVK or rootfs.dts.IMXRT105X_NXPEVK or rootfs.dts.IMXRT106X_NXPEVK in projects/rootfs as follows, for example:

 &fec { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_fec>; status = "okay"; assigned-clocks = <&clks IMXRT1050_CLK_ENET_REF>, <&clks IMXRT1050_CLK_PLL6_BYPASS>; assigned-clock-rates = <50000000>; assigned-clock-parents = <0>, <&clks IMXRT1050_CLK_PLL6>; clocks = <&clks IMXRT1050_CLK_ENET>, <&clks IMXRT1050_CLK_AHB_PODF>, <&clks IMXRT1050_CLK_ENET_REF>; clock-names = "ipg", "ahb", "enet_clk_ref"; fsl,ref-clk-dir = <&gpr 4 17 1>; phy-mode = "rmii"; phy-handle = <&ethphy0>; phy-reset-duration = <1>; phy-reset-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; mdio { #address-cells = <1>; #size-cells = <0>; ethphy0: ethernet-phy@0 { reg = <2>; clocks = <&clks IMXRT1050_CLK_ENET_REF>; clock-names = "rmii-ref"; }; }; };

This will register a platform device for the i.MX RT10XX Ethernet controller with the Ethernet driver.

The Linux project provided by Emcraft in the distribution (refer to projects/rootfs) includes the TCP/IP stack and various network related capabilities.

The target address reaches Linux on the kernel command line. Each of the U-Boot boot commands (mmcboot, sfboot, netboot) runs addip, which appends an ip= string to bootargs in the standard <client>:<server>:<gateway>:<netmask>:<hostname>:<device>:<autoconf> form, built from the ipaddr, serverip, gatewayip and netmask variables of the U-Boot environment. Change those variables in U-Boot to give the target a different address.

The kernel itself does not consume ip=, so the message about an unknown parameter is expected. Parameters the kernel does not recognise are handed to the init process as environment variables, which is what lets etc/netstart.sh act on this one. The script re-reads the string from /proc/cmdline and uses four of its fields: it configures <device> with <client> and <netmask>, and installs <gateway> as the default route. The <server> and <hostname> fields are parsed but not acted on, and <autoconf> is ignored altogether - no DHCP or BOOTP autoconfiguration is performed whatever its value.

The network-related messages printed by Linux as it boots are as follows:

Kernel command line: root=/dev/mmcblk0p2 rw rootwait ip=192.168.1.82:192.168.1.86:192.168.1.254:255.255.255.0::eth0:off Unknown kernel command line parameters "ip=192.168.1.82:192.168.1.86:192.168.1.254:255.255.255.0::eth0:off", will be passed to user space. ... Starting inetd: OK / # Micrel KSZ8081 or KSZ8091 402d8000.ethernet-1:02: attached PHY driver (mii_bus:phy_addr=402d8000.ethernet-1:02, irq=POLL) fec 402d8000.ethernet eth0: Link is Up - 100Mbps/Full - flow control off / #

Let's test the TCP/IP stack on the i.MX RT10XX.

From the development host validate that the target is visible using ping:

$ ping -c 5 192.168.1.82 PING 192.168.1.82 (192.168.1.82) 56(84) bytes of data. 64 bytes from 192.168.1.82: icmp_seq=1 ttl=64 time=0.688 ms 64 bytes from 192.168.1.82: icmp_seq=2 ttl=64 time=0.382 ms 64 bytes from 192.168.1.82: icmp_seq=3 ttl=64 time=0.402 ms 64 bytes from 192.168.1.82: icmp_seq=4 ttl=64 time=0.412 ms 64 bytes from 192.168.1.82: icmp_seq=5 ttl=64 time=0.411 ms --- 192.168.1.82 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4128ms rtt min/avg/max/mdev = 0.382/0.459/0.688/0.115 ms

ping the development host from the target:

/ # ping -c 5 192.168.1.86 PING 192.168.1.86 (192.168.1.86): 56 data bytes 64 bytes from 192.168.1.86: seq=0 ttl=64 time=0.734 ms 64 bytes from 192.168.1.86: seq=1 ttl=64 time=0.909 ms 64 bytes from 192.168.1.86: seq=2 ttl=64 time=0.823 ms 64 bytes from 192.168.1.86: seq=3 ttl=64 time=0.828 ms 64 bytes from 192.168.1.86: seq=4 ttl=64 time=0.814 ms --- 192.168.1.86 ping statistics --- 5 packets transmitted, 5 packets received, 0% packet loss round-trip min/avg/max = 0.734/0.821/0.909 ms

On the target, start the telnetd daemon to allow connections to the i.MX RT10XX:

/ # telnetd / # ps | grep telnetd 78 root 864 S telnetd 80 root 864 S grep telnetd / #

Connect to the target from the development host using telnet. The target is configured to accept the 123 password for root

$ telnet 192.168.1.82 Trying 192.168.1.82... Connected to 192.168.1.82. Escape character is '^]'. (none) login: root Password: / # ls bin etc httpd lib mnt root sbin tmp var dev hello.ko init linuxrc proc run sys usr / # exit Connection closed by foreign host. $

The dropbear SSH daemon is not a standing process; it is started on demand by inetd, which is configured as follows:

/ # cat /etc/inetd.conf ssh stream tcp nowait root /usr/sbin/dropbear dropbear -i -R / #

Connect to the target from the development host using ssh. The first connection takes several seconds to establish as the i.MX RT10XX runs computation-extensive key calculations. Again, enter 123 on the password prompt:

$ ssh root@192.168.1.82 The authenticity of host '192.168.1.82 (192.168.1.82)' can't be established. ED25519 key fingerprint is SHA256:/XK4PN+GGXJXs/F+wXhsv2T7sFJbu+Sx0bazmZZra54. This key is not known by any other names. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '192.168.1.82' (ED25519) to the list of known hosts. root@192.168.1.82's password: / # ls bin etc httpd lib mnt root sbin tmp var dev hello.ko init linuxrc proc run sys usr / # exit Connection to 192.168.1.82 closed. $

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:

/ # cat /etc/resolv.conf # This configuration makes use of the Google public DNS server. # If you would like to use something else, replace with the IP # of your DNS server nameserver 8.8.8.8 / #

Use ntpd to synchronize the time on the target with the time provided by a public server:

/ # date Thu Jan 1 17:40:57 UTC 1970 / # ntpd -p 0.fedora.pool.ntp.org / # sleep 5; date Sat Dec 6 07:53:53 UTC 2025 / #

Use wget to download a file from a remote server:

/ # wget ftp://ftp.gnu.org/README Connecting to http://ftp.gnu.org (209.51.188.20:21) saving to 'README' README 100% |********************************| 2748 0:00:00 ETA 'README' saved / # cat README This is http://ftp.gnu.org , the FTP server of the the GNU project. ...

Mount a directory exported by a development host over NFS:

/ # mount -o nolock,rsize=1024 192.168.1.86:/srv/homes /mnt/nfs / # ls /mnt/nfs/ 512kB.host check_float.c linux-dp.c SimpleClass check_float_soft test SimpleClass.cc check_float_softfp test.encoded app eclipse-workspace uartboot.script app.c fs.jffs2 widgets_gui_demo busybox linux-dp / # cp /bin/busybox /mnt/nfs / # cp /mnt/nfs/busybox /tmp / # md5sum /bin/busybox /tmp/busybox aa40e58bd2e79cfd23692c58088e3386 /bin/busybox aa40e58bd2e79cfd23692c58088e3386 /tmp/busybox

Start the HTTP daemon:

/ # httpd -h /httpd/html/

From a local host, open a Web browser to the target and watch the demo web page provided by the target. The target shows the current time and date as well as the list of the currently running processes: