C

链接脚本设置

链接脚本是一个包含有关平台内存配置信息的文件。它还指定了应用程序代码和数据驻留的区域。链接脚本由工具链中的链接器用于在最终的二进制文件中按照适当的内存地址组织数据和代码。在本节中,您将了解在您的链接脚本中需要配置什么以使 Qt Quick Ultralite 正常工作。

添加您的链接脚本

cmake\<YOUR_COMPILER>\<YOUR_LINKER_SCRIPT> 是您平台使用的链接脚本。Qt Quick Ultralite 使用链接脚本来组织最终二进制文件中的数据和代码到合适的内存地址。

可以在 LinkerScriptConfig.cmake 中设置默认链接脚本以供 CMake 使用。针对 example-baremetal 平台的

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()

参数定义要使用的链接脚本。有关更多信息,请参阅 使用自定义工具链

创建链接脚本

以下示例是从 platform\boards\qt\example-baremetal\cmake\armgcc\example-platform.ld 等到的片段。还有一份针对 IAR 链接器在 platform\boards\qt\example-baremetal\cmake\iar\example-platform.icf 可供参考的变体。您可以复制这些文件到您的项目中,用作您自己的链接脚本的起点。然而,建议您有自己的链接脚本,在那里您可以插入这里解释的附加内存部分。

注意:示例使用的是 GNU 链接脚本语法。在不同的工具链链接脚本中,某些事物可能实现方式不同。请参考您工具链的手册以获取有关链接脚本语法的更多信息。

为了将程序部分分配给设备,必须配置它的内存布局

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 */
}

此布局有五个区域:FLASH、RAM、SDRAM、SDRAM_PRELOAD 和 QSPI。RAM、SDRAM 和 SDRAM_PRELOAD 具有执行、读取和写入访问权限。而 FLASH 和 QSPI 是只读闪存内存,因此只有读取和执行访问。

注意:避免直接使用此布局作为您平台内存布局,因为它可能在 flashing 二进制文件或尝试在设备上运行时导致错误。请参阅您的目标平台手册以获取有关您设备的内存布局和适当内存地址的信息。

在这个例子中,资源数据存储在QSPI闪存区域。名称QulResourceData是硬编码的,代表图像资源的默认部分。有关添加额外的资源部分,请参阅管理资源

名称QulFontResourceData是硬编码的,代表字体文件和字形数据的默认部分。自定义字体文件部分由MCU.Config.fontFilesStorageSection属性配置,字形部分由MCU.Config.glyphsStorageSection配置。

Qt Quick Ultralite将QulModuleResourceData部分保留下来以放置其内部资源。应该不在其中放置用户指定的资源。

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

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

    __ModuleResourceDataStart = LOADADDR(QulModuleResourceData);

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

此示例使用SDRAM_PRELOAD区域从SDRAM中保留空间以预载资源。符号__preloadSdramStart__preloadSdramEnd定义资源预加载,以确定预载部分的起始和结束地址。

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

示例平台适应创建链接器符号的指针

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

默认情况下,资源使用DefaultPreload分配类型。预载起始和结束地址由示例反向预载分配器使用,以确定预载部分的最大大小。

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;
    }
}

可以通过从DefaultPreload内存分配类型的内存分配器中返回nullptr来禁用预加载。

预载Qt Quick Ultralite内部资源

Qt Quick Ultralite内部资源包含图像数据,例如与Qul::Controls库中的应用关联的仪表和按钮。内部资源不支持使用Qul::PlatformInterface::MemoryAllocator预加载。

在此示例中,预载内部资源数据从QSPI闪存区域复制到SDRAM。

__ModuleResourceDataCacheStart__ModuleResourceDataCacheEnd__ModuleResourceDataStart也必须定义。它们在平台代码中使用,以从QSPI加载资源到SDRAM。

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

对于IAR编译器,需要在某些部分声明中包含一些声明

#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);

请确保查看示例IAR链接脚本,了解如何在您的设备内存中放置这些部分。

注意:如果不使用预加载,则可以将QulModuleResourceData以与QulResourceData相同的方式添加到链接脚本中。在这种情况下,不需要__ModuleResourceData*符号和memcpy

在某些Qt许可下提供。
了解更多信息。