C

Linker script setup

Linker script is a file containing information about the platform's memory configuration. It also specifies regions where application code and data resides. The linker script is used by the toolchain's linker to organize the data and code in the final binary at appropriate memory addresses. In this section, you will get to know what needs to be configured in your linker script to get Qt Quick Ultralite working.

Adding your linker script

cmake\<YOUR_COMPILER>\<YOUR_LINKER_SCRIPT> is the linker script your platform uses. Qt Quick Ultralite uses the linker script to organize the data and code in the final binary to appropriate memory addresses.

A default linker script can be set in LinkerScriptConfig.cmake to be used by CMake. example-baremetal platform:

if(IAR)
    qul_platform_add_default_linker_script("${QUL_PRIVATE_PLATFORM_BOARD_CMAKE_DIR}/${QUL_COMPILER_NAME}/example-platform.icf")
else()
    qul_platform_add_default_linker_script("${QUL_PRIVATE_PLATFORM_BOARD_CMAKE_DIR}/${QUL_COMPILER_NAME}/example-platform.ld")
endif()

The argument defines the linker script to use. For more information, see Using a custom toolchain.

Creating the linker script

Following examples are snippets from platform\boards\qt\example-baremetal\cmake\armgcc\example-platform.ld. There is also a variant for IAR linkers available at platform\boards\qt\example-baremetal\cmake\iar\example-platform.icf for your reference. You can copy these files to your project to use as a basis for your own linker script. However, it is recommended that you have your own linker script where you insert additional memory sections explained here.

Note: The examples use GNU linker script syntax. Some things may be implemented differently between different toolchain linker scripts. Refer your toolchain's manual for more information about the syntax for linker scripts.

In order to assign program sections to the device, its memory layout must be configured:

MEMORY
{
  FLASH (rx)               : ORIGIN = 0x08000000, LENGTH = 2048K /* internal flash */
  RAM (xrw)                : ORIGIN = 0x20000000, LENGTH = 512K /* internal sram */
  SDRAM (xrw)              : ORIGIN = 0xc0400000, LENGTH = 6M /* external sdram memory */
  SDRAM_PRELOAD (xrw)      : ORIGIN = 0xc0a00000, LENGTH = 2M /* external sdram memory - preload */
  QSPI (rx)                : ORIGIN = 0x90000000, LENGTH = 64M /* external flash */
}

This layout has five regions: FLASH, RAM, SDRAM, SDRAM_PRELOAD and QSPI. RAM, SDRAM and SDRAM_PRELOAD have execute, read, and write access. Whereas, FLASH and QSPI are read-only flash memories and thus have only read and execute access.

Note: Avoid using this layout as-is for your platform's memory layout, as it may lead to errors when flashing the binary or attempting to run it on the device. Refer your target platform's manual for the memory layout and appropriate memory addresses for your device.

In this example resource data is stored in the QSPI flash memory region. QulResourceData name is hardcoded and represents the default section for the image resources. For adding additional resource sections see Managing Resources.

QulFontResourceData name is hardcoded and represents the default section for the font files and glyph data. Custom font files section is configured with MCU.Config.fontFilesStorageSection property and glyphs section with MCU.Config.glyphsStorageSection.

The QulModuleResourceData section is reserved by Qt Quick Ultralite to place its internal resources. User-specified resources should not be placed in it.

    QulFontResourceData :
    {
        . = ALIGN(4);
        *(QulFontResourceData)
    } > QSPI

    QulModuleResourceData :
    {
        . = ALIGN(4);
        __ModuleResourceDataCacheStart = .;
        *(QulModuleResourceData)
        . = ALIGN(4);
        __ModuleResourceDataCacheEnd = .;
    } > SDRAM AT> QSPI

    __ModuleResourceDataStart = LOADADDR(QulModuleResourceData);

    QulResourceData :
    {
        . = ALIGN(4);
        *(QulResourceData)
    } > QSPI

This example reserves space from the SDRAM for the preloadable resources with SDRAM_PRELOAD region. Symbols __preloadSdramStart and __preloadSdramEnd are defined for the resource preloading to determine the start and end address of the preload section:

    __preloadSdramStart = ORIGIN(SDRAM_PRELOAD);
    __preloadSdramEnd = ORIGIN(SDRAM_PRELOAD) + LENGTH(SDRAM_PRELOAD);

Example platform adaptation creates pointers to the linker symbols:

extern uint8_t __preloadSdramStart;
extern uint8_t __preloadSdramEnd;
void *preloadSdramStart = &__preloadSdramStart;
void *preloadSdramEnd = &__preloadSdramEnd;

By default the resources use DefaultPreload allocation type. Preload start and end address are used by the ExampleReversePreloadAllocator to determine the maximum size of the preload section.

PlatformInterface::MemoryAllocator *ExamplePlatform::memoryAllocator(
    PlatformInterface::MemoryAllocator::AllocationType type)
{
    static ExampleMemoryAllocator exampleMemoryAllocator;
    static ExampleReversePreloadAllocator<4> examplePreloadAllocator(preloadSdramEnd, preloadSdramStart);
    static PlatformInterface::MemoryAllocator defaultMemoryAllocator;

    switch (type) {
    case PlatformInterface::MemoryAllocator::Image:
        return &exampleMemoryAllocator;
    case PlatformInterface::MemoryAllocator::DefaultPreload:
        return &examplePreloadAllocator;
    default:
        return &defaultMemoryAllocator;
    }
}

Preloading can be disabled by returning nullptr from the memory allocator for the DefaultPreload allocation type.

Preloading Qt Quick Ultralite internal resources

Qt Quick Ultralite internal resources contain the image data for example for the dials and buttons that are linked to the application from Qul::Controls library. Internal resources do not support preloading with Qul::PlatformInterface::MemoryAllocator.

In this example preloadable internal resource data is copied from the QSPI flash memory region to SDRAM.

__ModuleResourceDataCacheStart, __ModuleResourceDataCacheEnd, and __ModuleResourceDataStart must also be defined. They are used in the platform code to load the resources from QSPI to SDRAM:

extern unsigned char __ModuleResourceDataStart;
extern unsigned char __ModuleResourceDataCacheStart;
extern unsigned char __ModuleResourceDataCacheEnd;
memcpy(&__ModuleResourceDataCacheStart,
       &__ModuleResourceDataStart,
       &__ModuleResourceDataCacheEnd - &__ModuleResourceDataCacheStart);

For IAR compilers there need to be some section declarations included

#pragma section = "QulModuleResourceData"
#pragma section = "QulModuleResourceData_init"
char *__ModuleResourceDataStart = (char *) (__section_begin("QulModuleResourceData_init"));
char *__ModuleResourceDataCacheStart = (char *) (__section_begin("QulModuleResourceData"));
char *__ModuleResourceDataCacheEnd = (char *) (__section_end("QulModuleResourceData"));
memcpy(__ModuleResourceDataCacheStart,
       __ModuleResourceDataStart,
       (unsigned) __ModuleResourceDataCacheEnd - (unsigned) __ModuleResourceDataCacheStart);

Make sure to check the example IAR linker script to see how to place these sections in your device memory.

Note: If preloading is not used, QulModuleResourceData can be added to the linker script in the same way as QulResourceData. In this case __ModuleResourceData* symbols and memcpy are not needed.

Available under certain Qt licenses.
Find out more.