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.

[参考译文] F28M35H52C:F28M35 M3引导加载器:如何跳至应用程序代码?

Guru**** 2538955 points
Other Parts Discussed in Thread: SYSBIOS, CONTROLSUITE

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/653838/f28m35h52c-f28m35-m3-bootloader-how-to-jump-to-application-code

部件号:F28M35H52C
在“线程:SysBIOS,controlSUITE”中讨论的其它部件

您好,亲爱的社区。

在我们的项目中,我们需要一个引导加载程序来更新存储在SD卡(SPI)上的M3固件。 我们还需要更新C28,但我们现在只关注M3。

我首先想尝试从引导加载程序跳到应用程序,作为第一次测试,在通过CCS和JTAG调试探头“手动”刷新两个固件之后。

我首先尝试了一种“天真”的方法:

我有两个CCS项目,一个用于bootloader,另一个用于应用程序。

booloader链接程序文件如下所示:

...
flash_boot (rwx): origin = 0x20.003万,length = 0x0.0004万 //不确定此部分中的内容,但我猜这是关键。 ?
闪存(rwx) : Origin = 0x20.0034万,length = 0x0001FFCC // Bootloader代码(我知道,这是bootloader的一个大部分。)
RSVD_firmware :原始= 0x22万,长度= 0x0005FF00 //为应用程序和主功能地址保留
...
文本 :> flash
.binit :> flash
.cinit :>闪存
.Pinit :>闪存
.const :>闪烁
... 


和应用程序链接程序文件:

... 
RSVD_bootloader :origin = 0x20.003万,length = 0x0001FFD0 flash_boot (rwx):origin = 0x22万,length = 0x0.0004万 //不确定此部分中放置的内容 flash (rwx)     :origin = 0x22.0004万,length = 0x0005FEF8 // Application code main_ADDR (rwx): Origin = 0x0027FEFC,length = 0x0.0004万 //存储应用程序的主功能地址 ... 文本 :> flash .binit :> flash .cinit :>闪存 .Pinit :>闪存 .const :>闪烁 ...


因此,在应用程序代码中,我将main函数指针地址存储在特定的闪存地址(本例中为0x0027FEFC)。
在bootloader代码中,我只需检索应用程序的主函数地址并尝试从那里调用函数。 我知道主函数的地址是正确的,但是当我调用应用程序主函数时,什么也没有。 它只是挂起,我没有在调试器中捕获任何异常消息。

我知道这是一个很天真的解决方案,但它看起来对另一平台上的某些人来说是可行的,正如OP HERE e2e.ti.com/.../11.3899万中所描述的那样

有人能给我指出正确的方向来解决我的问题吗? 任何建议或示例都将受到极大的感谢。

我搜索了很多,但没有找到Concerto芯片的任何示例。 我知道CodeSkins为我的平台提出了商业解决方案,但我们现在真的很想自己来做。


谢谢大家!
RIL

更新:

阅读此帖子后:e2e.ti.com/.../32.1081万

我还尝试了:

//将引导程序表设置为闪存中应用程序的开头。
HWREG (NVIC_vtable)= 0x2200万;//也尝试了0x22.0001万,0x22.0004万和0x22.0005万

//从应用程序的矢量表中加载堆栈指针。
//
_ASM (" LDR. R1,[r0]\n"\}
"移动 SP,R1");


//将初始PC从应用程序的矢量表和分支加载到
//应用程序的入口点。
//
_ASM (" LDR. r0,[r0,#4]\n"\}
" r0\n"); 

但它不起作用。

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

    我对拖延表示歉意。 您是否有任何成功分支到入口点?

    分支到地址时,如果bit[0]为0,BLX指令将产生缺省值。
    要分支到某个地址,我使用了以下内容:

    entry_addr = 0x1234;//这是我要分支到的函数的地址
    entry_addr |= 0x1;//这满足我刚才提到的条件
    ((void (*)(void)))entry_addr)();//这将调用该地址的函数

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

    您好,Chris,感谢您的回答。

    我仍然没有取得任何成功。

    当您谈论entry_addr时,您指的是应用程序权限的主要功能地址? 是否可以这么简单? 何时初始化全局变量和静态变量?

    如果我在没有其他任何操作的情况下执行此操作,我在调试器中收到以下错误:

    ""

    TI.SysBIOS.family.arm.m3.Hwi:行1087:e_hardFault:Forced
    TI.SysBIOS.family.arm.m3.Hwi:line 1199:e_usageFault:INVSTATE:无效的EPSR和指令组合
    在PC = 0x0万处的后台线程中发生异常。
    核心0:ThreadType_Task中出现异常。
    任务名称:{unknown-instance-name},句柄:0x2000.0238万。
    任务堆栈库:0x2000.0288万。
    任务堆栈大小:0x800。
    R0 = 0x0万 R8 = 0xffffffff
    R1 = 0x0万 R9 = 0xffffffff
    R2 = 0x0.0075万 R10 = 0xffffffff
    R3 = 0x0.0001万 R11 = 0xffffffff
    R4 = 0x0.0001万 R12 = 0x0万
    R5 = 0x0.0075万 SP (R13)= 0x20.0009万b0
    R6 = 0x0万 LR (R14)= 0x0.0224万cc3
    R7 = 0xffffffff PC (R15)= 0x0万
    PSR = 0x0万
    ICSR = 0x0440f803
    MMFSR = 0x00
    BFSR = 0x00
    UFSR = 0x0002
    HFSR = 0x4000万
    DFSR = 0x0.0001万
    MMAR = 0xe000ed34
    BFAR = 0xe000ed38
    AFSR = 0x0万
    正在终止执行...

    ""

    如果我在该字之前添加:

    HWREG (NVIC_vtable)= APP_FLASH_START;//尝试的值为0x22万,0x22.0004万,0x22.0005万... 

    我没有看到明显的错误,但调试器显示/.../ti/ccsv6/tools/compiler/arm_ugl.3.ls/lib/src/trgmsg.c的第117行15.12 :

    用于(i = 0;i < length;i++) PACKCHAR (* data++,p,i+8); 

    没有发生任何其他情况。

    您能否提供一个更完整的例子来说明您所做的事情? 显然,它对你很有用。

    如果您还能告诉我如何将固件编程为闪存,我将非常感激。

    再次感谢您的支持。

    RIL

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

    您应该分支到_c_int00 (请参见controlSUITE examples' statup_CCS.c),这是RTS库的此过程部分,执行所有的变量前设置,然后在末尾分支到"main"符号。

    我使用这种分支方法作为启动代码的一部分,而不是用于固件更新。 有关编程闪存的信息,请参阅controlSUITE示例。 我会看到是否可以找到任何固件更新代码,不确定是否有。

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

    克里斯托弗

    您是否有机会在某处找到此示例?

    我们尝试了以下操作,但没有成功:

    //在b.cmd中等同于flash_boot (参见下文)
    //我们还尝试了0x22.0004万,相当于b.cmd中的flash
    #define app_start 0x22万
    
    void JumpToFlashB()
    {
    UINT32_t entry_addr = 0x23A9ED;//这是另一个应用
    程序条目_addr_adv1中函数_c_int00的地址; HWIC_start_ved=
    //包含或不包含此行
    ((void (*)(void))entry_addr)();}
    

    我想知道我将各个阶段联系起来的方式是否会导致错误。

    下面是我的cmd文件中的内容(简化):

    A.cmd

    内存
    {
    flash_boot (rwx):origin = 0x20.003万,length = 0x0.0004万
    flash (rwx) :原点= 0x20.0034万,长度= 0x0001FFCC
    RSVD_B (rwx):原点= 0x22万,长度= 0x0005FF00 //使用JumpToFlashB()
    }跳至此扇区 

    B.cmd

    内存
    {
    RSVD_A (R):原点= 0x20.003万,长度= 0x0001FD0
    flash_boot (rwx):原点= 0x22万,长度= 0x0.0004万
    flash (rwx) :原点= 0x22.0004万,长度= 0x0005FEF8 //从扇区xxx开始
    } 

    您自己有什么想法或功能示例?

    谢谢,

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

    抱歉,我没有找到示例。 看起来我们目前还没有。
    您正在呼叫的地址具有(或已尝试)一个调用c_int00的函数。
    例如,controlSUITE中的"STARTUP_CCS.c":
    void myfunc()

    //跳至CCS C初始化例程。
    __ASM(".global _c_int00\n"
    " b.w _c_int00");
    }

    您收到的错误与您之前提到的错误相同吗?

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

    您好Chris,

    [报价用户="Christopher Chiarella"]
    您收到的错误与您之前提到的错误相同吗?

    [/引述]

    是的,我在进行呼叫时也有同样的行为。

    查看以下帖子后: https://e2e.ti.com/support/microcontrollers/c2000/f/171/t/660862  ,66.0862万,我可以重现相同的行为:我在呼叫时设置了一个中断点,然后执行‘开始’,应用程序代码开始(有几个驱动程序问题)。 有什么想法吗?

    我觉得还有其他事情要做,比如设置中断矢量?  

    在另一个注释中,我可以通过调用_c_int00来自动重启,但从第二阶段调用相同的函数时失败。

    感谢您的帮助Chris。

    RIL

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

    RIL,

      您指出,我在论坛帖子e2e.ti.com/.../660862上66.0862万上发布了几个调试步骤。

    我不认为分支本身有任何问题,它可能在到达main()之后和之前失败。 请查看您是否可以执行我在链接的帖子中建议的相同调试步骤。

    希望这有所帮助。

    此致
    Santosh Athuru

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

    您好,Santosh:

    很抱歉回复延迟。 我最近没有时间处理这个问题,但我关注了您提到的帖子的讨论,它解决了我的问题!

    特别是,由于我还在运行TI-RTOS,我需要这样做

    HWI_DisableInterrupt (FAULT_Systick); 

    在跳至主应用程序之前。

    感谢您的支持。

    RIL