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.

[参考译文] TM4C123GH6PM:从应用中调用 TivaWare CAN 引导加载程序

Guru**** 2478765 points


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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/691118/tm4c123gh6pm-call-tivaware-can-bootloader-from-application

器件型号:TM4C123GH6PM
主题中讨论的其他器件:TM4C123

您好!

我正在尝试使用 TivaWare 引导加载程序代码来实现 CAN 引导加载程序。 到目前为止、我成功地通过 CAN 将应用刷写并执行到 TM4C、但无法返回到引导加载程序。 更准确地说、我可以使用 SVCall 返回到引导加载程序(即更新处理程序)、但"ProcessorInit"函数中的某个位置失败、导致程序跳转到 FaultISR。

//从 boot_demo.c 复制的函数
void JumpToBootLoader (void)
{
HWREG (NVIC_DIS0)= 0xffffffff;
HWREG (NVIC_DIS1)= 0xffffffff;

(*(void (*)(void))(*(uint32_t *) 0x2C))();
} 
//从 bl_config.h 定义
#define APP_START_ADDRESS 0x1000
#define VTABLE _START_ADDRESS 0x1000 

//链接器脚本
#define APP_BASE 0x00001000
#define RAM_BASE 0x20000000

MEMORY
{
闪存(RX):origin = APP_BASE,length = 0x3F000
SRAM (rwx):origin = RAM_base,length = 0x00008000
}

SECTIONS
{
.intvecs:> app_base
.text:> FLASH
.const:> FLASH
.cinit:>闪存
.pinit:> FLASH
init_array:> FLASH

.vtable:> RAM_base
.data :> SRAM
.bss:> SRAM
.sysmem:> SRAM
.stack:> SRAM
} 

上面、我提供了代码部分、我认为这些部分是导致此问题的最大可能。 我正在运行的应用程序只不过是让 LED 闪烁几次、而不是跳回引导加载程序。 配置通常是正确的吗? 我是否可以使用我的应用程序之一覆盖引导加载程序矢量表(在 SRAM 中)?  

如果有任何帮助,将不胜感激。  

此致、

约苏阿

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

    您使用的是 ROM 引导加载程序还是闪存引导加载程序?

    "我使用我的应用程序之一覆盖引导加载程序矢量表(在 SRAM 中)"是什么意思? 它何时被覆盖?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Ralph、

    就我从 TivaWare 引导加载程序用户指南和数据表中可以看出、CAN 没有 ROM 引导加载程序(仅适用于串行接口)。

    因此、我将使用闪存引导加载程序。

    引导加载程序从闪存中的0x00开始执行,然后调用 ProcessorInit()函数,该函数将引导加载程序从闪存复制到 SRAM 并从 SRAM 继续执行。 因此、引导加载程序矢量表现在位于 SRAM 的开头、位置为0x20000000。 引导加载程序成功下载应用程序后、应用程序的矢量表会复制到此地址、从而覆盖引导加载程序 VTABLE。 至少、这是我对引导加载程序操作的理解。 如果我错了、请纠正我的问题。

    基本上,调用 UpdateHander()将引导加载程序复制回 SRAM 并恢复其 VTABLE,因此这不会成为问题。 但是,我不知道还有什么可能导致此问题(除了我发布的配置之外)。

    此致、

    约苏阿

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

    您正是因为没有 CAN 引导加载程序、抱歉、这让我觉得 CAN 就是其中一种情况、即 ROM 引导加载程序不存在、但闪存引导加载程序存在!

    您对引导加载程序如何将闪存复制到 SRAM 并从 SRAM 执行的理解是正确的。

    您使用的 TM4C123与 TM4C129器件不符? 我只想确保、因为对于 TM4C129、如果它是 TM4C129器件、那么我会非常清楚错误的发生。

    由于您登录 FaultISR、我认为解决此问题的最快方法是获取有关导致 FaultISR 的原因的更多信息。 可通过执行本文档中的步骤来找到这一点: www.ti.com/.../spma043

    请报告导致 FaultISR 发生的设置结果、然后我可以进一步帮助您!
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用 user="Josua Janus"]复制了应用程序的矢量表
    TI-RTOS 应用程序也是如此、但一般情况下不是如此。 您是否正在使用 TI_RTOS 或其他一些声称将矢量表复制到 SRAM 的代码?

    无论如何、这可能不是导致故障的原因、因为引导加载程序在调用时会重新复制其矢量表。 任何应用程序修改都将被覆盖。

    Ralph 的文档将建议您从异常堆栈中捕获 PC 值。

    另一种方法是单步执行代码、直到您遇到违规函数。 为此、您需要遵循以下指南: https://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/t/691665

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

    感谢您的回复。

    是的、我使用的是 TM4C123、而不是 TM4C129、而且我也不使用任何形式的 RTOS 或以任何方式复杂的代码(至少现在)。

    我确实尝试单步执行代码、但我还不太确定有问题的指令。

    让我来描述一下我的方法:

    首先、我在 CCS 中以调试模式启动了引导加载程序、并通过 CAN 刷写了演示应用程序。 下载成功后、我在演示应用中的 SVCall 指令上设置了一个断点。

    000015d8:202C MOV R0、#0x2C 

    然后、我开始逐步执行反汇编。 由于闪存中没有定义调试符号、我将地址与 SRAM 中具有相同偏移的地址进行了比较、以确定调用的函数(例如0x0000076c -> 0x2000076c)。  
    SVC 调用 UpdateHander()函数,该函数又调用 bootloader 的 ProcessorInit()函数。

    0000076c:F7FFFFC4 BL #0x200006f8// UpdateHandler()
    000006f8:2000 MOV R0、#0// ProcessorInit() 

    ProcessorInit()函数执行了几条指令,而不是循环执行一次复制循环。 此时、我有一点怀疑。 虽然我在汇编器方面没有真正的线索、但我认为将所有代码从闪存复制到 SRAM 的循环应该重复多次。

    ;;将代码映像从闪存复制到 SRAM。
    ;
    MOV r0、#0x0000
    MOV R1、#0x0000
    MOVt R1、#0x2000
    LDR R2、BSS_START
    COPY_LOOP:
    LDR r3、[r0]、#4
    结构 R3、[R1]、#4
    CMP R1、R2
    BLT COPY_LOOP 

    之后、调用了零循环、我尝试单步执行它、但我无法在合理的时间内手动退出它。 我也不知道它在做什么、因为没有任何内核寄存器发生更改(当然、PC 除外)。

    ;
    ;零填充.bss 段。
    ;
    MOV r0、#0x0000
    LDR R2、BSS_END
    ZERO LOOP:
    结构 R0、[R1]、#4
    CMP R1、R2
    BLT zero_loop
    
    ;
    ;;将矢量表指针设置为 SRAM 的开头。
    ;
    movw r0、#(NVIC_vtable & 0xFFFF)//此处的断点在循环中停止
    MOVt r0、#(NVIC_vtable >> 16)//在此指令中设置了断点 

    不管怎样、我尝试在循环之后的第一条指令上设置一个断点、这导致程序在循环中仍然停止。 因此、我在循环之后的第二条指令处设置断点、但程序永远不会达到这个点。

    当我暂停程序时,我在演示应用程序(!)的 FaulISR()中 FaultStatus 寄存器的值为1、表示指令访问违反。 数据表(0xE000EDF8)中未列出 NVIC_FAULT_ADDR 寄存器中的地址、但该地址属于 cortex-M4F 外设(NVIC 等)。

    接下来、我将尝试按照指南中的说明检查异常堆栈并发布结果。 在平均时间里,我认为我赞同我迄今所作的见解。 此外、如果有人能让我对这两个环路的功能有一点了解、我也会很感激。

    此致、

    约苏阿

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

    您好、Josua、

    您可以从地址0xE000ED28的故障状态寄存器中找到更多信息。 该寄存器具有异常原因。 NVIC 具有"正常"外设中断。 数据表的第3节中应记录这些内容。 请尝试在 pdf 中搜索偏移(d28)、而不是整个地址。 该寄存器的值很有价值、并在指南中进行了讨论。

    编辑:您是要键入 0xE000ED28而不是 0xE000EDF8? 我们可能会在这里查看同一个寄存器。

    两次发生的循环实际上是我的错误假设。 Ralph 和我不确定调试会话在 SRAM 中开始执行(PC)时、为什么调试器第二次通过此循环。 实际操作应该是在闪存中发生循环、然后汇编代码恰好通过复制循环(BX LR)分支到 SRAM 中。 这解释了您能够达到基于闪存的硬件断点的原因。

    Miles 的这一解释提供了一些背景信息: https://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/p/295119/1033395#1033395

    我的错误假设是基于" 因此从_c_int00 ()单步执行将不起作用"的矛盾。 对我来说很好!