Which Techniques Does QNX Use to Optimize Boot Time?

icon

ABOUT THE AUTHOR

Picture of Bhavin Sharma
Bhavin Sharma
Bhavin Sharma is a Linux kernel and BSP engineer specializing in embedded systems development for platforms like Rockchip and i.MX8. He possesses deep expertise in device drivers, board bring-up, and boot time optimisation. He is an active Linux kernel contributor.

Check out our QNX BSP Demo in the NXP platform here, live in action – Click Here

The boot time in the real-time systems should be faster to achieve systems objectives and be reliable enough to meet its demand. QNX Real Time Operating System is a leader in the operating systems market and achieves great results applying advanced methods in boot enhancing without losing functionality and performance. This blog takes a look at six tried and tested strategies QNX normally employs in order to reduce boot time further helping developers create solutions that are always primed and ready for action.

QNX Boot Time Optimization Techniques Explained!

To optimise boot time, we need to juggle between a variety of techniques to suit the different requirements. Here are listed all the techniques that QNX uses to optimise boot time:

  1.  Optimise the bootloader
  2. Optimise the startup
  3. Reduce the size of the IFS
  4. Optimise the use of the system and secondary disks
  5. Remove unnecessary debug printing
  6. Use compression strategies

1. Optimize the bootloader (IPL)

QNX reduces the bootloader runtime to the bare minimum possible, reduces or eliminates many of the bootloader’s initialisation steps, and focuses on critical operations that are required before the machine is handed off to the kernel. Check out how we do it – 

  • Enable the data and instruction cache in the IPL source as shown in the code snippet:
				
					/**
 * Setting IMX_CACHE_EN to 1 enables I/D caches feature
 * (improve QNX-IFS scan or authentication time).
 */
#define IMX_CACHE_EN                    1


				
			
  •  IPL scans for an image within the boot device. This image scan assumes that there is more than one bootable image and copies the most recent image into the RAM.
  • If the location of the image is known, we can scan a small area and directly copy the image present in that region. Refer to the below code snap in main.c of your IPL source:
				
					/* Scan loaded image in DDR RAM memory */
image = image_scan(image, image + IMX_QNX_IMAGE_SCAN_SIZE, 1);


				
			

2. Optimize the startup

Critical services are launched during booting, while unimportant processes are either slowed down or run concurrently, shortening booting time. QNX does it by following the below given steps below – 

  • Remove the hard-coded delays that are unnecessary, as shown in the code snippet below (the snapshot is of the init_pads.c.c in the startup source):
				
					/* Configure GPIO1_IO12 to control ENET Reset pin*/
out32(IMX_IOMUXC_BASE + IMX_IOMUXC_SW_MUX_CTL_PADx(IMX_IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO12), IMX_MUX_CTL_MUX_MODE_ALT0);
out32(IMX_GPIO1_BASE + IMX_GPIO_DR,   in32(IMX_GPIO1_BASE + IMX_GPIO_DR)   & ~(1 << 12U)); /* Set the pad to the high level */
out32(IMX_GPIO1_BASE + IMX_GPIO_GDIR, in32(IMX_GPIO1_BASE + IMX_GPIO_GDIR) | (1 << 12U)); /* Set output direction */
//imx_usleep(10 * 1000);
out32(IMX_GPIO1_BASE + IMX_GPIO_DR,   in32(IMX_GPIO1_BASE + IMX_GPIO_DR)   | (1 << 12U)); /* Set the pad to the high level */


				
			

Note: 

Be careful while removing any hard-coded delays, as they may be essential for properly achieving a specific state or for waiting during the peripheral bring-up process. Ensure thorough testing of the peripherals before determining whether the delays can be removed or reduced, or if they are necessary as they currently are.

3. Reduce the size of the IFS

Maintaining what goes within the IFS is very important as it increases the size of the IFS, and also it is the one that consumes most of the boot time. QNX can eliminate applications and libraries imposed on IFS, and can compress files to decrease IFS’s size, which decreases boot time.

  • Remove the unnecessary executables or binaries from the build file of the image as shown in the below code snap.
				
					##################################################################
## DMA library
##################################################################
#/lib/libdma-edma.so=libdma-edma.so
#/lib/libdma-sdma-imx8mp1.so=libdma-sdma-imx8mp1.so
#/lib/libdma-sdma-imx8mp2.so=libdma-sdma-imx8mp2.so
#/lib/libdma-sdma-imx8mp3.so=libdma-sdma-imx8mp3.so


				
			

Limit the use of wait for and sleep to states that rely on specific paths or where their necessity is justified.

				
					#######################################################################
## Serial driver
#######################################################################
## UART1 is used for the QNX console
display_msg Starting Serial driver (/dev/ser1)...
devc-sermx1 -e -F -S -u 1 -c 24000000 0x30890000,59
waitfor /dev/ser1


############################################################################################
## SD memory card / eMMC driver
############################################################################################
## SD card uses USDHC2
display_msg Starting SD1 memory card driver (/dev/sd0)...
devb-sdmmc-mx8x cam pnp,cache,quiet blk ra=64k:2048k,memory="sysram&below4G:sysram",maxio=256,\
cache=4m disk name=sd sdio idx=1,bs=cd=0x30210000^12^588,verbose=1


				
			
  • If possible, start the device drivers or execute the scripts with having long execution time in the background.
				
					###########################################
## RTC
###########################################
display_msg Starting RTC utility...
gpio-mcp23018 -a 0x20 -b 6 -p 6 -w1
rtc rv3028 &


###########################################
## Storage service
###########################################
/proc/boot/.storage-server.sh &


###########################################
## Mount secondary IFS
###########################################
/proc/boot/.mount-ifs2.sh &


				
			
  • Another effective approach to reduce the size of the Image File System (IFS) is to create a secondary IFS stored on a disk, drive, emmc, or flash memory. Essential binaries, drivers, and libraries can be stored in the primary IFS to ensure that only the necessary drivers are loaded during the early stages of booting. Once the initial setup is complete, a secondary IFS can be mounted to facilitate the background initialisation of the remaining device drivers. Follow the steps below to create a secondary IFS:
  • Create a secondary.build file in the images directory of the BSP. Add the path from where the files need to be found and also the prefix where files will be mounted, as shown in the snap below.
				
					#################################################################
## START OF SECONDARY IFS BUILD SCRIPT for Nitrogen8MP-SMARC board
################################################################# 
# Specify the search path
[search=${QNX_TARGET}/aarch64le/bin:${QNX_TARGET}/aarch64le/usr/bin:${QNX_TARGET}\
/aarch64le/sbin:${QNX_TARGET}/aarch64le/usr/sbin:../install/aarch64le/bin:../install\
/aarch64le/usr/bin:../install/aarch64le/sbin:../install/aarch64le/usr/sbin:${QNX_TARGET}\
/aarch64le/lib:${QNX_TARGET}/aarch64le/lib/dll:${QNX_TARGET}/aarch64le/usr/lib:${QNX_TARGET}\
/aarch64le/usr/lib/graphics/iMX8MP/:../install/aarch64le/lib/dll/:../install/aarch64le/lib/:\
../install/aarch64le/usr/lib/:../install/aarch64le/usr/lib/graphics/iMX8MP/]

# Where the files will be mounted at boot time
[prefix=/ifs2]


				
			
  • After this, the binaries and libraries can be added as below.
				
					############################################
## Network driver files
############################################
/ifs2/lib/devs-ffec.so=devs-ffec.so
/ifs2/lib/devs-dwceqos.so=devs-dwceqos.so


				
			
  • After all the required binaries and libraries are added, we need to edit the Makefile for images directory as below:
				
					qnx-ifs-graphics-secondary:  $(BOARD)-graphics-secondary.build
        $(HOST_MKIFS) -vvv -r $(INSTALL) $(MKIFSFLAGS) $^ $@


				
			
  • Incorporating the above lines into the Makefile will facilitate the building of the secondary IFS for the board each time an image is generated.
  • To store the IFS on the disk, a QNX6 filesystem partition must be created directly on the board. The following commands will help in creating one on an emmc:
  1.     fdisk /dev/emmc0 add -t 11 -l -c2048,2099199 -> creates a 1024MB partition.
  2.     mount -e /dev/emmc0 -> mounts emmc
  3.     mkqnx6fs /dev/emmc0t11 -> formats a qnx6 filesystem on created partition.
  4.     mount -t qnx6 /dev/emmc0t11 /emmc -> mounts the created partition to “/emmc”. The secondary IFS can be copied to this path, and the partition can be unmounted after that using the command below.
  5.     Umount/emmc -> unmounts the mounted partition.
  • Now that we know the secondary IFS is available within EMMC, we can create a script to mount the partition and subsequently mount the secondary IFS. This script can be executed during the boot process for seamless integration.
  • Below is an example of a script that mounts the secondary IFS and initialises the remaining drivers and services. While these components are not essential for the device to boot, they are necessary for activating the peripherals.
				
					################################################################################################
## Secondary IFS mount script
################################################################################################
[perms=0744] .mount-ifs2.sh = {
#!/bin/ksh

    ############################################################################################
    ## SD memory card / eMMC driver
    ############################################################################################
    #Initialize eMMC driver
    ## eMMC uses USDHC1 controller
    devb-sdmmc-mx8x blk cache=64m cam bounce=128k mem name=below4G sdmmc partitions=on sdio idx=0, \
    emmc,timing=~ddr,timing=~hs200,timing=~hs400,timing=~hs400es disk name=emmc  > /dev/null 2>&1
    waitfor /dev/emmc0

    #Mount eMMC partition "/dev/emmc0t11.1" consisting secondary IFS
    mount -t qnx6 /dev/emmc0t11.1 /emmc
    waitfor /emmc
    #Mount secondary IFS
    mount_ifs -f /emmc/qnx-ifs2 -m /proc/boot
    waitfor /proc/boot/ifs2
    #Unmount the eMMC partition
    umount /emmc/

    /proc/boot/.network.sh &
    #######################################################################
    ## CAN driver
    #######################################################################
    devcan-flexcan -h -M -b250K -u0 can0
    devcan-flexcan -h -M -b250K -u1 can1
				
			
  • To execute the below script in the background during the boot process, the following command needs to be added within the boot script of the primary IFS build file.
				
					#################################
## Mount secondary IFS
#################################
/proc/boot/.mount-ifs2.sh &
				
			

4. Optimize use of system and secondary disks

QNX helps to tune up both the first and the second-level storage system to increase loading of the key files. It helps at least time consumption in disk reading by prioritizing system-critical files and modules, and increases the boot component access time as required. The second disks may remain with non vital services so that the main disk remains free for critical and vital processes and has a faster boot time.

5. Remove unnecessary debug printing

While a program is being developed, debug printing helps to trace the work of the system, but it negatively affects the boot time. Production versions of QNX systems mute or delete such statements and the difference between the startup of the two interfaces consists in the number of I/O operations, which is much lesser in the case of QNX systems boosting the booting time.

6. Use compression strategies

QNX has figured out how to reduce boot files with the application of compression methods. The operation of compressing system files and then using them only when they must be decompressed means that the disk only needs to accept a certain number of calls for data. This not only minimises the amount of disk read time that is required, but also makes good usage of the CPU to complete decompression quickly and ensure the advancement of boot performance.

We have implemented the discussed techniques on the QNX provided BSP of an IMX8MP-based SOC board, and a boot time of <400ms was achieved. Apart from the ways discussed above, you can follow the qnx-boot-time-optimisation-guide for more details.

Conclusion

Reducing boot time in QNX software systems is especially important for those that are part of critical infrastructure. Limit the number of non-essential bootloader functions and stick to essential and important ones, do not use debug prints in applications. Use techniques like data loading file compression for fast loading and other tricks of QNX to view the information on disks along with tweaking on kernel chops. These steps make for a lean setup and assists to get into faster boot times with a good feeling that everything’s in order.

 

Sustaining a close working relationship with the QNX tools and its documentation will also assist diffuse further and tailor the disk usage and kernel settings for optimum performance from your QNX system. In this way, you can confidently move towards achieving your early boot time goals with a lean setup of your QNX operating system.

Let’s Get In Touch

Interested in collaborating with Silicon Signals on your next big idea? Please contact us and let us know how we can help you.

    Name
    Email
    Subject
    Message