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.

[参考译文] RM48L940:从引导加载程序跳转到应用程序

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/703538/rm48l940-jump-from-bootloader-to-application

器件型号:RM48L940

我正在尝试执行一个引导加载程序、该引导加载程序会跳转到应用程序。 以下是我到目前为止所做的工作:

  1. 创建了一个引导加载程序项目、用于配置某些外设并使某些 LED 闪烁。 这工作正常。
  2. 创建了一个用户应用程序项目、我希望引导加载程序跳转到该项目(我还不想从 SPI 或 UART 等外部源加载;我只需强制将应用程序二进制文件放入闪存、并希望跳转到该项目)。

用户应用程序执行不正确。  当我单步执行引导加载程序时、我可以看到它跳转到我为用户应用程序0x00020000指定的地址。  

当我单步执行我的应用程序起始地址 0x00020000时  、我运行到 undefEntry 中(在地址 x4处)。 这可能是因为我的引导加载程序工程没有适用于我的应用程序的符号、但我不确定。 无论如何、即使我只是加电并希望它运行、我的应用程序也不会继续运行。 请注意、我的应用程序不配置任何器件-它只是尝试写入 GPIO、与引导加载程序配置并成功使用的器件相同。 如果我需要在引导加载程序完成后重新初始化任何外设并跳转到应用程序、请更正我的错误。

以下是我的链接器脚本。 因为您可以告诉我正在尝试将我的用户应用程序定位在 0x00020000。 我已经尝试将引导和应用程序输出转换为原始二进制文件、并 分别将它们加载到地址0x0和0x00020000、这没什么区别。 引导加载程序始终运行正常、但不运行应用程序。 感谢您在调试此内容或解决遗漏的任何问题方面提供的帮助。

boot_linker.cmd

/*------------------ *

定义大小为4G 的存储器内存内存;

define region vectors = mem:[来自0x00000000大小0x00000020];
定义区域闪存=内存:[0x00000020大小0x0017FFE0]
| mem:[来自0x00180000大小0x00180000];
define region stack = mem:[从0x08000000开始、大小为0x00001500];
定义区域 RAM =内存:[自0x08001500大小0x0003eb00];
定义块堆、大小= 0x800、对齐= 8{};

通过副本{readwrite}进行初始化;
不初始化{section.noinit};

放入向量{readonly section .intvecs};
置于闪存{readonly}中;
放入 RAM{readwrite};
放入 RAM{block heap};
/*------------------ *

app_linker.cmd

/*------------------ *

定义大小为4G 的存储器内存内存;

define region vectors = mem:[自0x00020000大小0x00000020];
定义区域闪存=内存:[从0x00020020大小0x0017FFE0]
| mem:[来自0x00180000大小0x00180000];
define region stack = mem:[从0x08000000开始、大小为0x00001500];
定义区域 RAM =内存:[自0x08001500大小0x0003eb00];
定义块堆、大小= 0x800、对齐= 8{};

通过副本{readwrite}进行初始化;
不初始化{section.noinit};

放入向量{readonly section .intvecs};
置于闪存{readonly}中;
放入 RAM{readwrite};
放入 RAM{block heap};
/*------------------ *

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

    引导加载程序和应用程序的 inline cmd 文件没有问题。 您能否为应用发布异常矢量表(sys_intvecs.asm)和 sys_start.c?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!

    我编写了两段代码来测试"bootloader"和应用程序。 第一段代码充当位于0x00000000的引导加载程序、第二段代码充当编程到闪存0x20000的应用程序。 这两个器件均使用 CCS8编程为闪存。

    Bootloader"代码在 main()中分支到0x20000
    void main (void)

    /*用户代码开始(3)*/
    ''

    ((void (*)(void)) 0x00020000)();


    应用切换 GIO 以打开/关闭 RM48 HDK 上的一个 LED。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这些引导加载程序+应用程序正常工作;

    e2e.ti.com/.../1665.RM48HDK_5F00_bootloader_5F00_test.7z

    e2e.ti.com/.../1464.RM48HDK_5F00_bootloader_5F00_appTest.7z

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

    感谢您的回复。 上周我已经解决了初始问题、能够从启动转到应用程序。 但是、这仍然是通过引导代码分支到 undefEntry 来完成的、并且由于引导加载程序矢量表中的 undefEntry 具有指向0x00200000处应用程序映像的分支、因此它会找到应用程序并正常工作。 什么会导致引导跳转至解 defEntry?为什么不能 按照下面的 bootlaoder main 中的预期直接从应用程序 resetEntry 启动?

    其次、我想使用引导来配置/设置各种硬件资源、而不必在应用中执行相同的操作。 但是、我看到在应用中 、我仍然需要重新配置用于 GIO 的端口、以驱动 LED、即使已配置引导、也要成功使用相同的端口。 什么是可行的?

    我的引导加载程序 main 为:

    void main (void)
    {
    
    //跳转到系统应用;SYS_START_ADDRESS = 0x00200000
    G_ulTransferAddress =(uint32_t) SYS_START_ADDRESS;
    (((void (*)(void)) g_ulTransferAddress)();
    } 

    引导加载程序的矢量表如下所示;我尝试了0x001FFFF8 (即0x00200000 - 8) 、但它不起作用。 此外、使用#表示 immediate 会导致语法错误。 不确定这是否只是 IAR 汇编器:

    ;------------------------------------------------------------------ 
    ;中断向量 resetEntry b _c_int00;0x00引导加载程序复位 undefEntry b 0x00200000;0x04 undefined_instruction、分支到应用 程序 svcEntry b svcEntry;0x08 software_interrupt、分支到应用 程序预取指令 b prefetchEntry;0x0C prefetch_abort、 b _dabort;0x10 data_abort b phantomInterrupt;保留 LDR PC、[PC、#-0x1b0] ;0x18 LDR PC、[PC、#-0x1b0] ;0x1C 结束 ;----------------------------------------------------------------

    应用程序的矢量表为:

    ;------------------------------------------------------------------
    ;中断向量
    
    resetEntry
    b _c_int00
    undefEntry
    b undefEntry
    svcEntry
    b svcEntry
    预取 Entry
    B prefetchEntry
    b _dabort
    b 相位中断
    LDR PC、[PC、#-0x1b0]
    LDR PC、[PC、#-0x1b0]
    
    结束
    ;---------------------------------------------------------------- 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我解决了 undefEntry 问题(是由于代码和矢量表之间的地址不匹配)。

    因此、我的两个问题仍然存在:

    1.我想使用引导来配置/设置各种硬件资源、而不必在应用中执行相同的操作。 但是、我看到在应用中、我仍然需要重新配置用于 GIO 的端口以驱动 LED、即使引导代码已在引导加载程序中成功配置和使用相同的端口。 什么是可行的?

    2.不是一个问题,而是一个问题。 在我看到的许多示例中、建议将矢量表中的应用程序地址设置为地址8。 在我的示例中、这将是0x0001FFF8。 但是、在向量表中、唯一对我有效的地址是0x00020000 (实际应用程序起始地址)。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!

    1.是的、您不必在应用程序中重新配置与引导加载程序中配置相同的外设。 但我建议在应用程序中重新进行配置。 当需要不同的设置时、您不必同时更新应用程序和引导加载程序。 代码跳转到应用程序后、您无法调用引导加载程序中的函数。

    2.程序计数器(PC)始终将两条指令指针指向当前已执行指令之外的指令。 因此、如果要分支到0x200000、引导加载程序中的值应为0x200000-0x08
    b #0x1FFFF8

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

    感谢您的回复。

    关于#2、我使用的是 IAR 版本8.22.1。 让我知道要寻找什么来解决这一问题。

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

    您好!

    您是否检查了反汇编或0x00000004 (闪存地址)处的内容? 如果使用 BL #0x20000、0x04处的值应为 EA008000

    0xE 表示 ALWay (无条件)。 没有链接的平均分支。

    偏移量为0x8000 (0x20000向右移位2位)

    分支偏移量必须考虑预取操作、这会导致 PC 在当前指令之前为2个字(8个字节)。 当在0x04 (b #20000)上执行指令时、PC = 0x04+0x08。 在0x04 (b #20000)被执行后、PC=0x04+0x08+0x20000 = 0x2000B

    这意味着将调用应用程序代码中的"预取异常处理程序"、而不是调用"undef 异常处理程序"(位于0x20000 + 0x04)。