This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[FAQ] [参考译文] [常见问题解答] SK-AM62:如何使用 M4F 内核从外部存储器执行代码?

Guru**** 657500 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1187962/faq-sk-am62-how-to-execute-code-from-external-memory-using-m4f-core

器件型号:SK-AM62

如何使用 M4F 内核从外部存储器执行代码?

 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    注意:当从 DDR 执行代码时、M4F 的性能将 明显低于(~100倍)从 M4F IRAM 执行代码。

    要使用 M4F 从外部存储器中执行代码、请在 linker.cmd 中指定 MEMORY 区域以加载和运行程序、并在 example.syscfg 文件中添加 RAT 和 MPU 配置。 需要进行这些更改、因为 M4F 微控制器内核本身就是32b 处理器。 添加了专用 RAT 模块、允许 M4F 处理器访问完整的36B 通用 SoC 地址映射。

     从外部存储器执行代码所需的步骤

    1. 从 M4F 的示例中导入"Hello world"程序  

      • ${SDK 路径}\examples\hello_world\am62x-sk\m4fss0-0_freertos

    2. 在 linker.cmd 中为 DDR 指定存储器区域以运行和加载程序。
    3. 在 example.syscfg 中添加 M4F 的 RAT 配置以访问 DDR。
    4. 在 example.syscfg 中添加 MPU 区域以允许从 DDR 执行代码
    5. 构建并运行程序。

    下面给出了每个步骤的说明:

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    在 linker.cmd 中为 DDR 指定存储器区域以运行和加载程序

    /* make sure below retain is there in your linker command file, it keeps the vector table in the final binary */
    --retain="*(.vectors)"
    /* This is the stack that is used by code running within main()
     * In case of NORTOS,
     * - This means all the code outside of ISR uses this stack
     * In case of FreeRTOS
     * - This means all the code until vTaskStartScheduler() is called in main()
     *   uses this stack.
     * - After vTaskStartScheduler() each task created in FreeRTOS has its own stack
     */
    --stack_size=16384
    /* This is the heap size for malloc() API in NORTOS and FreeRTOS
     * This is also the heap used by pvPortMalloc in FreeRTOS
     */
    --heap_size=32768
    
    
    SECTIONS
    {
        /* This has the M4F entry point and vector table, this MUST be at 0x0 */
        .vectors:{} palign(8) > M4F_VECS
    
        .text: 	 {} palign(8) > DDR_1     /* This is where code resides */
    
        .bss:    {} palign(8) > DDR_1     /* This is where uninitialized globals go */
        RUN_START(__BSS_START)
        RUN_END(__BSS_END)
    
        .data:   {} palign(8) > DDR_1     /* This is where initialized globals and static go */
        .rodata: {} palign(8) > DDR_1     /* This is where const's go */
        .sysmem: {} palign(8) > DDR_1     /* This is where the malloc heap goes */
        .stack:  {} palign(8) > DDR_1     /* This is where the main() stack goes */
    
        GROUP {
            /* This is the resource table used by linux to know where the IPC "VRINGs" are located */
            .resource_table: {} palign(4096)
        } > DDR_0
    
        /* Sections needed for C++ projects */
        .ARM.exidx:     {} palign(8) > DDR_1  /* Needed for C++ exception handling */
        .init_array:    {} palign(8) > DDR_1  /* Contains function pointers called before main */
        .fini_array:    {} palign(8) > DDR_1  /* Contains function pointers called after main */
    }
    
    MEMORY
    {
        M4F_VECS : ORIGIN = 0x00000000 , LENGTH = 0x00000200
        M4F_IRAM : ORIGIN = 0x00000200 , LENGTH = 0x0002FE00
        M4F_DRAM : ORIGIN = 0x00030000 , LENGTH = 0x00010000
    
        /* when using multi-core application's i.e more than one R5F/M4F active, make sure
         * this memory does not overlap with R5F's
         */
        /* Resource table must be placed at the start of DDR_0 when M4 core is early booting with Linux */
        DDR_0       : ORIGIN = 0x9CC00000 , LENGTH = 0x1000
        DDR_1       : ORIGIN = 0x9CB00000 , LENGTH = 0x100000
    
    }

    章节说明:  

    代码是使用 ARM Cortex-M4F 微控制器的系统的链接器脚本。 链接器脚本用于指定系统的存储器布局、它告诉链接器在何处将代码和数据的不同部分放入存储器中。

    链接器脚本定义了多个段、例如:

    • `.vectors`:这被指定为 M4F 的入口点和矢量表、并且它必须位于存储器地址0x0。
    • `.text`:包含代码。
    • `.bss`:包含未初始化的全局变量。
    • `.data`:包含初始化的全局变量和静态变量。
    • `.rodata`:包含常量数据。
    • `.sysmem`:这是 malloc 堆。
    • `.stack`:这是主堆栈。

    它将这些段分配给系统中的不同存储器区域(DDR_1、DDR_0)。  Linux 使用 μ`.resource_table`部分在存储器中定位 IPC"VRINGs"、并将其分配给 DDR_0存储器区域。

    此外、脚本还定义了 C++项目的段、例如`.arm.exidx``.init_array``.fini_array`。 这些段用于异常处理和 C++对象的初始化/清理、并分配给 DDR_1存储器区域。


    该脚本使用"Group"和"run_start"/"run_end"命令将段组合在一起并为它们分配特定的存储器地址。 "palign"命令用于指定每个段的对齐方式。


    脚本``` DDR_1`将段放置在 DDR_1存储器中、使用 DDR_0将段放置在 DDR_0存储器中。


    该脚本还为`、vectors``、`、`、BSS``、data``、rodata``.sysmem``.stack`、这样系统就知道段在存储器中的位置。


    它还使用`run_start (__bss_start)``run_end (__bss_end)` 来指定`.bss`段的起始地址和结束地址。

    内存说明:

    上述代码是使用 ARM Cortex-M4F 微控制器的系统的存储器映射。 存储器映射定义了系统的不同存储器区域及其特定的存储器地址。

    它定义了四个存储器区域:

    • `M4F_VECS`这是 M4F 的入口点和向量表所在的区域,其原点为0x00000000,长度为0x00000200。
    • `M4F_IRAM` 这是指令 RAM 所在的区域,位于0x00000200的原点,长度为0x0002FE00。
    • `M4F_DRAM`这是数据 RAM 所在的区域,其原始地址为0x00030000,长度为0x00010000。
    • `DDR_0` 这是 DDR_0存储器的区域,其原始地址为0x9CC00000,长度为0x1000。
    • `DDR_1`这是 DDR_1存储器的区域,其原始地址为0x9CB00000,长度为0x100000。

    指定在使用多核应用时、例如多个处于活动状态的 R5F/M4F、请确保该存储器不会与 R5F 重叠。

    它还指定当 M4内核使用 Linux 进行早期引导时、必须将资源表放置在 DDR_0的开头。

    存储器区域的原点和长度以十六进制表示法定义。 存储器映射用于确保链接器脚本中定义的不同段被放置在正确的存储器区域和正确的存储器地址中。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    在 example.syscfg 中添加 M4F 的 RAT 配置以访问 DDR

    有关何时配置 RAT 以及如何使用转换后的地址的更多信息、请参阅更新基于区域的地址转换(RAT)设置的常见问题解答。

    《MCU+SDK 用户指南》中的 RAT 配置详细信息: https://software-dl.ti.com/mcu-plus-sdk/esd/AM62X/08_05_00_14/exports/docs/api_guide_am62x/KERNEL_DPL_ADDR_TRANSLATE_PAGE.html

    基于区域的地址转换(RAT)是 AM62x SOC 中的存储器管理功能、允许将存储器区域映射到特定存储器地址。 这样可以创建多个虚拟存储器空间、供 SoC 的不同组件和子系统使用。

    RAT 使用存储器区域表和相应的存储器地址来执行转换。 每个区域都由起始地址、结束地址和一组属性定义、这些属性指定区域的访问权限和其他属性。

    RAT 可用于创建多个虚拟内存空间、每个虚拟内存空间都有自己的一组内存区域。 这样可以隔离不同的组件和子系统、并提供一种控制对存储器资源的访问的方法。

    有关详细说明、请参阅 TRM 的第9.2.1节。  AM62x TRM  

    如何配置 RAT:

    •将 CONFIG_ADDR_translation_region_0的大小从512MB 更改为256MB。


    •按照以下屏幕截图中的定义、添加新的 RAT 区域 CONFIG_ADDR_TRANSLATE_4。


  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    在 example.syscfg 中添加 MPU 区域以允许从 DDR 执行代码

    内存保护单元(MPU)是一个模块,用于修改处理器内存排序模型中定义的内存类型和属性。 MPU 特定于系统中的每个内核、只能修改其所连接 CPU 的存储器顺序模型。




  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    示例项目:  

    我已附上 Hello World M4F 的示例项目供您参考。

    M4F Hello World 代码:

    大家好、世界 M4F freertos.zip