In this short article I’ll look at how the support for modern system-on-chip devices in Wind River’s VxWorks 7 real-time operating system enables developers to get a kernel running a new board is a very short space of time.
Why use the Nitrogen8M SBC?
The Boundary Devices Nitrogen8M SBC is a great development board we’ve used on a number of Linux driver projects. It features a quad-core NXP i.MX8M quad-core processor, 2 GB RAM, Ethernet, USB 3 and much more.
My colleague Ian was recently working on VxWorks 7 project that involved a custom i.MX8M design and that made me think: how easily can we get VxWorks running on the Nitrogen8M?
VxWorks 7 on the NXP i.MX8M
We’ve been writing VxWorks board support packages (BSPs) and drivers since the early 90s so I knew it would be possible. One of the innovations in VxWorks 7 is the introduction of platform (processor) support layers for various system-on-chip (SoC) devices to make porting to new boards much easier. This is helped by moving the board-specific hardware configuration out of the BSP and into a device tree.
As most of the peripherals are integrated into the processor there is generally little do apart from setting up a device tree to get a basic kernel running. The devil is in the detail, of course. Most custom boards are designed for a job in a specific market so getting the kernel running is usually just the start of any project.
VxWorks 7 has support for the NXP i.MX8M SoC and a number of NXP evaluation boards. This was my starting point. I created a simple device tree for the Nitrogen8M and added some basic board definitions to the existing i.MX8M board files. I then built a kernel image which produced a U-Boot compatible ELF file with integrated device tree.
Loading the kernel
Now to load the VxWorks image onto the board using the U-Boot tftpboot command:
=> tftp 43000000 uVxWorks Using FEC device TFTP from server 192.168.10.20; our IP address is 192.168.10.10 Filename 'uVxWorks'. Load address: 0x43000000 Loading: ################################################################# ################################################################# ################################################################# ################################################################# ######################################## 7 MiB/s done Bytes transferred = 4395496 (4311e8 hex)
Now to run it using the bootm command. As the device tree was integrated into the kernel image I only needed to specify the load address:
=> bootm 43000000 ## Booting kernel from Legacy Image at 43000000 ... Image Name: vxworks Image Type: AArch64 VxWorks Kernel Image (uncompressed) Data Size: 4395432 Bytes = 4.2 MiB Load Address: 40100000 Entry Point: 40100000 Verifying Checksum ... OK Loading Kernel Image ... OK ## Starting vxWorks at 0x40100000, device tree at 0x00000000 ... Target Name: vxTarget _________ _________ \77777777\ /77777777/ \77777777\ /77777777/ \77777777\ /77777777/ \77777777\ /77777777/ \77777777\ \7777777/ \77777777\ \77777/ VxWorks 7 SMP 64-bit \77777777\ \777/ \77777777\ \7/ Core Kernel version: 3.1.1.0 \77777777\ - Build date: Apr 29 2020 10:55:31 \77777777\ \7777777/ Copyright Wind River Systems, Inc. \77777/ - 1984-2020 \777/ /7\ \7/ /777\ - ------- Board: Boundary Devices Nitrogen8M SBC - ARMv8 CPU Count: 4 OS Memory Size: 2048MB ED&R Policy Mode: Deployed
Adding 9129 symbols for standalone. ->
That was pretty straight-forward and took a couple of hours. However, all we had was a kernel and Ethernet support. It’s a start but not enough to support to complex application.
Adding USB3 support
How about adding USB 3 support? The USB host controllers are integrated into the processor. In principle that should be easy too. Just add the right driver to the kernel configuration and update the device tree.
I plugged in a USB memory stick expecting to see it detected and be able to list the contents. Nothing happened. I checked the driver and kernel configuration. Everything looked good. So what could be wrong?
I rebuilt the kernel with USB debug support and this confirmed the host controller was not seeing any device insertion events when I plugged in the memory stick.
Time to look more closely at the hardware.
Nitrogen8M USB3 host controllers
The Nitrogen8M has two USB3 host controllers. One is connected to USB3 mini type B connector, which is used for OTG connections. The other is connected to an on-board USB 3 hub (Renesas uPD720210) that provides the three ports on the board.
Fortunately, Boundary Devices provide schematics for the their boards. This was interesting bit:
The hub has a reset pin. The device datasheet said this was an active low reset signal. My guess was the hub was being held in reset so I needed to drive this signal high to take it out of reset.
Where does this reset signal come from? Back to the board schematic:
Not surprisingly it comes from an processor GPIO pin. Fortunately, the i.MX8M platform support included a GPIO driver. I added this to kernel configuration. I then added a pin configuration to set GPIO1 pin 14 high during startup in the Nitrogen8M device tree.
The device tree can be seen here.
After building a new kernel and rebooting I got the following:
## Starting vxWorks at 0x40100000, device tree at 0x00000000 ... Target Name: vxTarget _________ _________ \77777777\ /77777777/ \77777777\ /77777777/ \77777777\ /77777777/ \77777777\ /77777777/ \77777777\ \7777777/ \77777777\ \77777/ VxWorks 7 SMP 64-bit \77777777\ \777/ \77777777\ \7/ Core Kernel version: 3.1.1.0 \77777777\ - Build date: May 1 2020 13:59:07 \77777777\ \7777777/ Copyright Wind River Systems, Inc. \77777/ - 1984-2020 \777/ /7\ \7/ /777\ - ------- Board: Boundary Devices Nitrogen8M SBC - ARMv8 CPU Count: 4 OS Memory Size: 1984MB ED&R Policy Mode: Deployed Adding 10204 symbols for standalone. ->
As the board booted I saw a flicker of activity from the LED in the USB memory device. This was confirmed by the kernel device list that showed two mounted file system partitions present on the USB device.
-> devs drv refs name 1 [ 3] / 2 [ 3] /bd0:1 ==> /bd0a 2 [ 3] /bd0:2 ==> /bd0b 5 [ 3] /bd0a 6 [ 3] /bd0b 10 [ 3] /input/event 0 [ 3] /null 3 [ 3] /ttyS0 2 [ 3] /tyCo/0 ==> /ttyS0 12 [ 3] host: value = -140737484449152 = 0xffff8000003b9a80 ->
Moving forward
Getting this far took about a day in total. Full support for the on-board peripherals would require a lot more work. Even with SoC support in the VxWorks 7 kernel we generally find there is a lot of configuration and driver development work required to support the hardware designed by our clients.
Some things just don’t change.