Startup

Updated: April 19, 2023

This module takes over after the first-stage bootloader (BIOS, UEFI, U-boot, or IPL) has finished executing. The startup code executes after it has been copied from the boot device into the system’s DRAM. The startup code sets up a number of in-memory data structures by populating them with information about the hardware, so that the QNX kernel and other device drivers can run. Collectively, these data structures are known as the QNX system page (syspage).

When you adapt startup code from an existing BSP to a new target board, ensure your investigation includes the following system elements:

DRAM memory size

The startup code usually has a routine that determines how much DRAM is installed in the system based on information that U-Boot or the IPL passes to it. However, in some cases, you need to manually specify how much DRAM is present in the system.

For example, the target system that the original BSP was written for has 2 gigabytes of DRAM, but your custom target has only 1 gigabyte of DRAM. To ensure that the startup code doesn’t populate the system page with incorrect information, update it to specify the correct DRAM size. (If the QNX kernel thinks there is 2 gigabytes of DRAM present when there is actually only 1 gigabyte present, the kernel crashes as soon as you try to boot the system.)

CPU Frequency and clocks

As with DRAM memory size, it is important to go through the startup code to ensure that the clock initialization is correct for your target board, if the CPU core frequency or any of the peripheral clocks differ from the reference BSP.

Pinmux and GPIO configuration

Although a variety of common peripherals can be built into the SoC, the method that internally connects these peripheral blocks to the CPU core can sometimes be configurable by the software.

For example, a peripheral such as a UART interface can have the option of using two or three different sets of multiplexed pins that transmit UARTsignals from the SoC to external devices. Unless the custom board you are porting to uses exactly the same pin configuration as the reference board, you need to modify the startup code’s init_pinmux() routine to ensure that each peripheral’s signals are routed to the correct sets of external pins on the SoC.

Similarly, some peripherals utilize GPIO (general purpose input/output) pins on the SoC for particular functionality. To accommodate any differences in GPIO pin utilization between the reference hardware and the custom hardware, ensure that you examine the portion of the startup code that initializes the GPIO pins and modify it if necessary.

Note: Different revisions of SoC can have different DRAM, clocks, and Pinmux.

Unlike many other operating systems that perform most initialization tasks after the OS is running, QNX Neutrino performs many key initializations using its startup program. These initializations include timers, interrupt controllers, and cache controllers. Custom board projects can require modifications to the following board and startup code elements:

For a discussion of modifying or creating the startup code, see “Modifying the startup” in the Startup Programs chapter of Building Embedded Systems.

Memory mapping

Your custom board’s hardware determines the memory configuration options that are available to you.

Some boards expect the startup code to load the OS at a specific address (for example, SABRE platforms).

Not all boards support compression, which prevents you from compressing the IFS to improve performance or conserve memory.

The type of media used to store the IPL and the IFS affects the IPL design. The most common type of media used are non-linearly-mapped devices (for example, an eMMC, SD card, or SPI NOR Flash device). The storage provided by these devices can't be mapped directly into the processor's address space. Because the processor can't address the OS image, the IPL needs to copy the entire image (including the startup code) into RAM. For more information, see “Image storage” in the Initial Program Loaders (IPLs) chapter of Building Embedded Systems.

Voltages

A system that uses the QNX Graphics Framework (GF) needs to power up the GPU before it initializes the graphics functionality. Refer to the hardware specifications for your board to determine whether your GPU requires the startup code to perform this task. For example, some boards enable the GPU by default and others require you to set the voltage and enable it.

Depending on your system’s requirements, you can configure the startup code to turn on only some graphics resources (for example, the display controller only). Other graphics resources can then be turned on after startup when they are needed (for example, using a driver).

Callouts

The kernel uses callouts to provide the QNX Neutrino kernel and process manager with hardware-specific code. If your hardware platform isn't supported by the callouts in the startup library, or by any of the available board-specific callouts, you write your own.

For information about the callouts and how to write a kernel callout, see Kernel Callouts in Building Embedded Systems.