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:从引导加载程序跳转到应用程序部分时出现问题

Guru**** 2528480 points


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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/672351/f28m35h52c-problem-in-making-a-jump-to-application-section-from-a-bootloader

器件型号:F28M35H52C

您好!

我几乎处于完成 C2000 Cortex M3内核的引导加载程序的最后阶段。 我需要一些帮助来解决我在从引导加载程序跳转到闪存的应用部分时遇到的问题。  

目前为止我拥有的内容:

现在、引导加载程序能够读取通过 UART 接收的数据、解析数据并使用 TI 闪存 API 库将数据闪存到相关地址。 为简单起见、我考虑使用 blinky m3示例从引导加载程序刷写。 我选择了32位宽 ROM 和内存范围的英特尔十六进制格式。 我正在尝试使用来自主机的 python 代码发送此生成的十六进制文件。  

考虑的闪存扇区:

Bootoader ->扇区 N、M 和 L

应用->扇区 K 到 A

我面临的问题:

在我将各自解析的十六进制文件写入闪存存储器并尝试跳转到闪烁应用程序后、控制台会抛出一条消息、提示"0xfffffffe"位置中没有内容。 但我的闪烁应用的复位矢量位于位置0x0022162B、这是我尝试跳转的位置。 我也可以在"Disassembly"窗口中看到内容。  

但没有意义的是闪烁应用的堆栈终端地址值。 闪存后、在存储器区域窗口内的矢量表中查看该特定值为0x20002358。 但是、当我尝试从引导加载程序读取该值时、该值为0x21002358!! 我无法理解这里的情况,因为我在闪存存储器区域看到了磁珠值,但通过软件读取时却看到了不同的值??

一些故障排除:

当我使用 TI 闪存实用程序将扇区 K 指定为 A 并刷写专为扇区 N 至 L 的 Bottloader、从而擦除闪烁应用时、我可以使用相同的复位矢量地址轻松跳转到闪烁应用。 但是、读出堆栈结束地址时出现问题、该地址看起来与矢量表中的相同。  

但是、如果我尝试通过引导加载程序擦除和写入闪存内容并尝试进行跳转、则问题似乎会发生。  

下面是一些屏幕截图。

这是我捕获 appstack 值的位置。 它显示了我读取的内容和矢量表地址中的内容的比较。   

  

2.从引导加载程序跳转时看到的内容

3.我尝试在0x0022162b 上设置断点以尝试反汇编中的分步调试、但这似乎对我也不起作用。  

  

谢谢   

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Preetham、
    我不完全理解矢量表中的栈指针的问题。 矢量表中的 SP 仅在复位时初始化? 如果要在分支到应用程序入口点之前更改 SP,必须在 SW 中执行此操作。

    其次、在引导加载程序结束时、您应该能够简单地向应用程序入口点进行分支。 您能否检查您分支到的地址是否已将 LSB 设置为"1"? 我相信您将使用硬编码地址作为您的应用程序入口点。

    您能否在引导加载程序中显示分支到应用程序的汇编或 C 代码? 从拆分代码段中、您似乎没有地址集的 LSB。

    希望这对您有所帮助。

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

    您好、Santosh、

    以下是我的回复:

    [引用 user="Santosh Athuru"]我不能完全理解矢量表中栈指针的问题。 矢量表中的 SP 仅在复位时初始化? 如果要在分支到应用程序入口点之前更改 SP,必须在 SW 中执行此操作。[/QUERP]

    如果我的问题有误导性,我很抱歉。 到目前为止、我还没有尝试在引导加载程序应用程序中更改堆栈指针值。 我现在要做的就是通过引导加载程序使用 Blinky 应用程序擦除和写入闪存内容、并跳转到 Blinky 应用程序的复位矢量函数、应用程序应从该位置旋转。  

    [引用 user="Santosh Athuru"]其次,在引导加载程序结束时,您应该能够简单地向应用程序入口点进行分支。 您能否检查您分支到的地址是否已将 LSB 设置为"1"? 我相信您将使用硬编码地址作为您的应用程序入口点。

    在我将闪存内容写入特定地址之前、我没有想到这一点。 我们应该这样做,因为 ARM 内核程序计数器需要这个吗??

    [引用 user="Santosh Athuru"]能否在引导加载程序中显示分支到应用程序的汇编或 C 代码? 从拆分代码段中、您似乎没有地址集的 LSB。 [/报价]

    下面是我在跳转到应用软件之前遵循的代码行。  

    其中 application_address 是值为0x0020C000的#define。 现在、这是 Blinky 应用程序矢量表的起始地址。 下面的应用条目值将是 Blinky Application ResetISR 地址、即0x0022162b。 我甚至从 Blinky 应用程序映射文件中验证了此符号地址。  

    在执行跳转之前、我现在是否应该将 appentry 的值更改为0x0022162C? 正如您所说、我需要将地址的 LSB 设置为1。  

    /*
    *获取应用程序栈指针(应用程序矢量表中的第一个条目)
    *
    appstack =*(uint32_t*)(application_address);

    /*
    *获取应用程序入口点(应用程序矢量表中的第二个入口)
    *
    appentry =(funcptr)*(uint32_t*)(application_address + 4);

    /*
    *重新配置矢量表偏移寄存器以匹配应用程序位置
    *
    SCB->VTOR =应用程序地址;

    现在、当我尝试读取位于0x0020C000的闪烁应用程序的__STACK_END 的值(appstack)时、它的读数为0x21002358、但该值实际上是0x20002358、这两个值都是从存储器视图和闪烁映射文件中确认的。 这就是我在问题中试图解释的内容。  

    现在、这看起来像是堆栈溢出、您能否确认这是否正确。 这可能是我无法跳转到闪烁应用的原因。  

    谢谢  

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

    据我所知,您非常接近使您的应用软件正常工作,只需几个步骤即可修复/更正:-)

    下面是分支到地址时我在 M3上使用的代码。 尝试更新您的软件以使用如下所示的软件。


    entry_addr = 0x20004000;//只是一个示例

    //对于 blx 指令
    //如果 RM 的位[0]为0,BLX 指令会导致 UsageFault 异常。
    entry_addr |= 0x1;
    ((void (*)(void)) entry_addr)();


    更改向量表偏移量不会更改栈指针。 堆栈指针仅由 MCU 在复位向量获取时从矢量表偏移位置更新。 当您更新矢量表偏移量时、如果您希望使用不同的 SP、您应该在 SW 代码中手动更改 SP。

    应提供有关如何更新 SP 的组装说明、请参阅 ARM 文档。

    希望这对您有所帮助。

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

    Santosh、

    我尝试了这种方法、它将增加应用程序恢复 ISR 的地址。 (从0x0022162B 到0x0022162C)。

    但我仍然无法 跳转到"RestISR"、我仍然收到与我的第一个问题中发布的相同的错误消息。  


    但我不理解的是、当内存窗口中的实际值为0x20002358时、读取时栈指针的值为什么显示为0x21002358?

    我的观察结果:
    因此、当我仅尝试读取如下堆栈指针值时

    appstack =*(uint32_t*)(0x0020C000);

    我应该读取0x20002358、而是读取0x21002358。 我想问题就在这里。 能不能帮助我理解这种情况。

    谢谢

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

    0x22162B 实际上是 LSB (位0)设置为'1'的地址,因此您应该能够分支到该地址。 您不必增加地址、如果 LSB (位0)已设置为"1"、则我放置的代码片段会保留地址不变、不会使地址递增。 从您在第一个帖子中放置的上述拆分代码段中、您似乎拥有有效的代码。

    您能否在切换 VTABLE 之前检查是否禁用了所有中断?

    如果通过从 CCS 修改 PC 寄存器强制 PC 为0x2216A、会发生什么情况? 并尝试在0x22162A 处执行 B.W 指令? 而不更改 SP?

    在切换 VTABLE 偏移之前、SP 的值是多少? 您看到的是0x21002358而不是0x20002358、这是一种奇怪的情况。
    您拥有的任何其他器件/电路板上是否会发生同样的情况? 您也在特权模式下更改 VTABLE 偏移量、因为我可以从快照中的寄存器窗口中看到这一点、所以这也是正确的。

    您能否在执行分支和执行分支到复位矢量之后、先放置 SP 和 CPU 寄存器窗口的快照?
    地址范围0x21xx_xxxx 无效。 在切换 VTABLE 之前和切换 VTABLE 之后?

    我同意,我们需要先了解 SP 的问题。 这是否发生在任何其他项目中? 例如:-如果您只更改 VTABLE 偏移量


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

    Santosh、

    只是为了让您了解我使用两种不同的方法从引导加载程序分支到应用程序恢复 ISR。

    这是我使用 TI 的 CCS 集成闪存实用程序工具只在所选闪存扇区中写入内容的地方。 我通过选择项目属性->调试->闪存设置->在擦除设置选项下、选择"仅选定扇区"并检查 Blinky 应用程序的扇区 A 至 K、然后按下调试按钮、该按钮将只擦除和写入这些特定扇区。 现在、我将结束 Blinky 应用的调试分离、并开始调试我的引导加载程序应用程序、该应用程序将擦除和写入闪存扇区 N、M 和 L、而不会干扰已经很 Blinky 的应用扇区。 这种方法对我来说非常有用、这意味着我可以顺利地从引导加载程序跳转到 Blinky Reset 矢量、而不会出现任何问题。 此外、当我读取堆栈指针值时、它是0x20002358、而不是0x21002358。 复位矢量地址保持相同的0x22162b。  

    现在第二种方法是通过引导加载程序应用程序对 Blinky 应用程序进行擦除和写入。 其中、引导加载程序应用程序会擦除扇区 A 至 K、并将适当接收到的数据从 Secotor K 写入到 A 的以下地址。当我开始遇到上述问题中所述的问题时。 因此、我不知道当我从引导加载程序应用程序写入内容时会出现什么问题。 我已经验证了闪存 API 命令、在使用它们的方式上没有问题、并且还负责为用于闪存操作的函数分配 RAM 空间。

    好的、现在回到您之前的问题:

    [引用 user="Santosh Athuru"]在切换 VTABLE 之前,您能否检查是否禁用了所有中断?

    我以前没有这样做,但现在添加了对 IntMasterDisable()的调用;在我切换 VTABLE 之前,如下所示。  

    IntMasterDisable();
    SCB->VTOR =应用程序地址;

    但这并没有改善这种情况。  

    [引用 user="Santosh Athuru"]\n 如果通过从 CCS 修改 PC 寄存器将 PC 强制为0x2216A、会发生什么情况? 并尝试在0x22162A 处执行 B.W 指令? 而不更改任何 SP?[/QUERP]

    我尝试从"Registers"部分和分支中将 PC 值更改为0x2216A、但结果相同。 SP 没有改变!!  

    但是我应该如何尝试执行 B.W 指令?? 您是说我应该使用 C 程序中的 ASM 调用吗??

    [引用 user="Santosh Athuru"]在切换 VTABLE 偏移量之前,SP 的值是多少? 您看到的是0x21002358而不是0x20002358、这是一种奇怪的情况。
    您拥有的任何其他器件/电路板上是否会发生同样的情况? 您也在特权模式下更改 VTABLE 偏移量、因为我可以从快照中的寄存器窗口中看到这一点、所以这也是正确的。

    I 切换到 VTABLE 之前和 I switch 之后的 SP 值保持为0x20002188。

    答案是肯定的、我在不同的评估板上也面临同样的行为!!!  

     [引用 user="Santosh Athuru"]在执行分支和执行分支到复位矢量之后、您能否对 SP 和 CPU 寄存器窗口进行快照?
    地址范围0x21xx_xxxx 无效。 在切换 VTABLE 之前和切换 VTABLE 之后?[/quot]

    此快照显示了分支之前但 VTABLE 开关之后的 sp 和 CPU 寄存器值。  

    下面的快照显示了分支之后的 sp 和 CPU 寄存器  

    下面的快照显示了 VTABLE 开关之前的 sp 和 CPU 寄存器  

    [引用 user="Santosh Athuru"]我同意我们需要先了解 SP 问题。 这是否发生在任何其他项目中? 例如:-如果您只更改 VTABLE 偏移量

    我尝试在切换 VTABLE 之前读取 SP 值!!  

    谢谢

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Preetham、
    通过引导加载程序对闪烁应用程序进行编程时、是否也启用 ECC 和自动编程 ECC?

    此致
    桑托什
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我有两个不同的函数来处理擦除和写入操作。

    在擦除操作期间、我不启用或禁用 ECC。 因此、我在开始写入之前完全擦除所有扇区。

    现在在写入操作期间。 我先禁用 ECC、写入成功后、我将重新启用 ECC。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Preetham、
    我认为在使用引导加载程序(使用闪存 API)对应用程序进行编程时、应该具有启用自动 ECC 的选项。 编程时不启用 ECC 是否有任何原因、在使用闪存 API 时必须简单地使用启用的自动 ECC? 您可以尝试启用 ECC 的编程、看看它是否有所不同?

    在使用 CCS 加载闪烁模式时、是否正确启用了 ECC?



    此致
    Santosh Athuru

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

    我不小心按下了绿色按钮!!!! 问题仍未解决。 您能帮我重置吗?

    在写入前启用 ECC 时、我现在会遇到一些不同的错误。 当我调用闪存 API "Fapi_doVerifyByByByByByByByByByByByByByByByByByByByByByByByByByByByByByByByByByByByByByByByByByByByBy  

    我参考了控制套件中的闪存 API 代码、这就是它的实现方式。 在调用此 API "Fapi_issueProgrammingCommand"之前禁用 ECC、并在完成后再次启用 ECC。

    我不在 Blinky 应用程序中使用 ECC、因此我想在使用 CCS 加载时应该默认启用 ECC

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

    Santosh 没有谈到闪存读取的 ECC 检查。 这就是您在 API 使用示例中被称为启用/禁用的内容。

    Santosh 所问的是在使用 Fapi_issueProgrammingCommand()时对 ECC 进行编程。 您为此函数传递的最后一个参数是什么? 如果您将 AutoEccGeneration 模式用于编程模式(最后一个参数)、则会对 ECC 进行编程。 这将避免 ECC 错误。

    有关 ECC 的更多详细信息、请通读此 wiki: processors.wiki.ti.com/.../C2000_Flash_FAQ

    此外、以下是 F28M35x 闪存 API 参考指南的链接: www.ti.com/.../spnu595。 请查看本指南中的第3.2.3节 Fapi_issueProgrammingCommand()。

    希望您阅读 TRM 中的闪存和 OTP 存储器一章。 它对 ECC 进行了很好的解释。

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

    Vamsi、

    让我检查一下这些信息,并在一天之内与您联系!  

    谢谢

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

    Vamsi 和 Santosh、

    当我详细介绍闪存 API 文档时、我尝试了 一些你们建议的东西。 我将 Fapi_AutoEccGeneration 传递到 Fapi_issueProgramming Command API 的最后一个参数、与之前一样、我传递 Fapi_DataOnly。  

    现在、在进行上述更改后、我开始看到如下所述的不同行为。

    在我开始使用 Fapi_AutoEccGeneration 对闪存进行编程后、我开始从 闪存位置0x0020C000进行写入、并转至0x0020C00C。 在20C00C 之前、我将有效数据编程到每个闪存字节位置。 但是当我将地址和数据传递给 Fapi_issueProgramming Command 时,正好在该位置返回 Fapi_Status_Success,但当我实际查看闪存位置时,不会写入什么?? 下面是一些屏幕截图。

    您能帮助我理解为什么我看到上述行为吗?

     在下面的屏幕截图中、我尝试使用数据变量验证闪存内容时、我遇到错误、并在我循环的过程中不停地降落。  

    谢谢

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

    您好、Pretham、

    您可以尝试将16个字节而不是4个字节写入4次吗? 它还将减少函数调用的数量。
    如果您仍然看到问题、请告知我们。

    谢谢、
    Katta

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

    搜索"使用 Fapi_AutoEccGeneration 模式时、可编程的16位字的最小数量是多少?" 在闪存常见问题解答页面中: processors.wiki.ti.com/.../Flash_FAQ

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

    谢谢 Vamsi、

    我怀疑问题可能出在我传递要编程的数据位数的方式上。 让我尝试更改我的软件、一次至少对64位进行编程、看看如何进行编程。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢你们的所有支持! 真的很感谢耐心和时间! 最后、我的项目的第一个修订版开始工作。

    会保持联系!

    此致
    Preetham