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.

[参考译文] TM4C129XNCZAD:ROM 以太网引导加载程序导致不精确异常

Guru**** 2403135 points
Other Parts Discussed in Thread: EK-TM4C1294XL

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1120280/tm4c129xnczad-rom-ethernet-bootloader-leads-to-imprecise-exception

器件型号:TM4C129XNCZAD
Thread 中讨论的其他器件:EK-TM4C1294XL

您好!  

我遇到了以下与 ROM 引导加载程序相关的问题:

首先、如果我使用 调试器加载它、我的固件就能完美工作。

然而 、我使用 ROM 引导加载程序进行上载、在复位后、它会导致不精确异常。 (NVIC_FAULT_STAT = 0x400)

如果我在此之后执行下电上电、它将会非常完美。

如果我在固件生命周期的任何时刻使用函数 SysCtlReset()进行复位、它也总是能完美工作、器件总是初始化而不会出现任何问题。

我已经阅读 了 https://www.ti.com/lit/an/spma043/spma043.pdf?ts=1658473901542 、但仍然无法解决问题。

我检查 SP、R3是否符合预期、但 R2-R1-r0不正常。 此外、第2行中的第3个寄存器会将我引导至完全无关的位置。

您能不能帮助找出问题所在?

此致、

Erman

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

    引导加载程序的调用具有以下函数:

    void SoftwareUpdateTivaBegin (void)

    //
    //禁用所有处理器中断。 而不是禁用它们
    //一次一个(如果是新的源,可能会丢失一个中断
    //已添加)、直接写入 NVIC 即可禁用所有
    //外设中断。
    //
    HWREG (NVIC_DIS0)= 0xffffffff;
    HWREG (NVIC_DIS1)= 0xffffffff;
    HWREG (NVIC_DIS2)= 0xffffffff;
    HWREG (NVIC_DIS3)= 0xffffffff;
    HWREG (NVIC_DIS4)= 0xffffffff;

    //
    //也禁用 SysTick 中断。
    //
    SysTickIntDisable();
    SysTickDisable();

    //
    //将控制权返回给引导加载程序。 这是对 SVC 的调用
    //基于闪存的引导加载程序中的处理程序,或者如果配置了,则写入 ROM。
    //
    ROM_UpdateEMAC( 120000000UL );

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

    您好!

     不确定问题是什么。  

     您能回答几个问题吗?

     -我假设您的应用程序固件是从地址0x0开始构建的、对吧? 您能否显示链接器命令文件?

     -您能在不同的电路板上重复同样的问题吗?

     -您能否尝试 TivaWare 示例 C:\ti\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl\boot_demo_emac_rom。 这是一个将调用 ROM_UpdateEMAC 的以太网应用。 您是否会遇到相同的问题? 如果该示例不会产生相同的问题、请与您的固件进行比较。 也许有一些细微的差别。

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

    您好、Charles、

    它在不同电路板中是可重复的%100。

    链接器命令文件内容如下

    存储器

    闪存(RX):origin = 0x00000000,length = 0x00100000 // 1M 字节
    SRAM (rwx):origin = 0x20000000,length = 0x00040000 // 1/4 MB

    XRAM (rwx):origin = 0x60000000,length = 0x0003FFFF // 1/4 MB reserviert für GUI
    XRAM2 (rwx):origin = 0x60040000,length = 0x005BFFFF //位图,字体,数据
    XRAM3 (rwx):origin = 0x60600000,length = 0x00100000 // 1Mbyte reserviert für copy buffer SDRAM_copy_address
    // Ende 0x606FFFFF


    //内存中的段分配

    部分

    .text:> FLASH
    .const:> FLASH
    .cinit:>闪存
    .pinit:> FLASH
    init_array:> FLASH
    .data :> SRAM
    .bss:> SRAM
    .sysmem:> SRAM
    .stack:> SRAM
    .xRAM:>XRAM,类型= NoLoad // ohne Initializierung
    .xram2:> XRAM2,类型= NoLoad // ohne Initializierung
    .xram3:>XRAM3,类型= NoLoad // ohne Initializierung

    该示例有效、我的固件的某些旧版本也可以与更新程序一起使用。 我认为硬件问题不存在。

    如何在异常之后确定它的确切来源?

    此致、

    Erman

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

    您好!

     我实际上没有发现您的链接器文件有任何问题、但我也不知道问题是什么。 您能回答几个问题。

     -您的故障处理程序是否是一个简单的 while (1)? 或者您的故障处理程序添加了一些其他定制代码。 如果您阅读了应用手册、则需要对其进行调整。 请参见下面的。

    堆栈帧应从 SP 开始保存 R0-R3。 请参见下图。 但是、在您的捕获中、第一个位置已经是 R3、而不是 R0。 如果看一下捕获、地址0x2003737C 的值等于0x0007C43B。 这是否是有问题的 PC?  您需要检查其附近。 为了简化调试、您可能希望将故障处理程序恢复为 while 循环。 通过这种方法可以更轻松地查看和调试堆栈帧。  

     不精确的故障通常意味着它是由一个写入操作引起的。 读取故障始终精确。  

     -请仔细阅读应用手册的第3.3节。 本节讨论调试不精确中止。  

     -在发生故障之前、您是否在未完全初始化外部存储器时读取或写入外部存储器?  

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

    您好!

    我在项目中使用 TIRTOS。  问题是错误从 BIOS_start()开始。 因此、我无法从工程中删除操作系统并查看它、因为问题不会发生。

    我的故障处理程序是 tirtos 中的 Hwi_excHandler。 我在它的开头放置一个断点、它 SP 指向 R4。  下面是一个屏幕截图:

    故障发生在  BIOS_start()期间,因此不是,我认为我不是在读取或写入外部存储器。 我将断点放置到我的所有任务中、并且在断点、异常已经发生之前、所有断点都不会得到。

    在 BIOS_Start()之前我只有主板引脚初始化、然后我构建了3个任务 、如...

    Task_construct(&BootTaskStruct,(Task_Functr) BootTask,&taskParams, NULL);

    我查看了应用手册的第3.3节、但我现在不知道该怎么做。

    请注意、只有在使用引导加载程序更新固件后、我才会收到此错误。 使用 SysCtlReset()进行电源复位或软复位不会导致这种情况,我编写了一个脚本并尝试了100次,总是能正常成功地引导。

    我是否应该从 具有特定 primo 的任务中调用 rom_UpdateEMAC()?

    在调用  ROM_UpdateEMAC()之前,以下内容是否真的足够?

    HWREG (NVIC_DIS0)= 0xffffffff;
    HWREG (NVIC_DIS1)= 0xffffffff;
    HWREG (NVIC_DIS2)= 0xffffffff;
    HWREG (NVIC_DIS3)= 0xffffffff;
    HWREG (NVIC_DIS4)= 0xffffffff;
    SysTickIntDisable();
    SysTickDisable();

    此致、

    Erman

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

    您好、Erman、

     虽然我对您的问题没有一个好的答案、但我认为此帖子可能会有所帮助。 尽管调用 ROM_UpdateUART()而不是 ROM_UpdateEMAC(),但此帖子似乎有类似的问题。 这篇文章提到、加载新固件后、他们必须执行手动复位才能正确启动固件。  我认为值得尝试建议的解决方案、看看它是否会对您的项目产生影响。 转至帖子的末尾、其中 John 使用 单独的外设中断禁用替换了 HWREG (NVIC_DIS0)= 0xffffffff 和 HWREG (NVIC_DIS1)= 0xffffffff。  

    https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1025914/tm4c123gh6pm-invoke-rom_updateuart-programmatically

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

    您好、Charles、

    我已根据您发送的链接尝试了以下操作、但该链接不起作用  

    ROM_IntDisable (INT_GPIOA);
    ROM_IntDisable (INT_GPIOB);
    ROM_IntDisable (INT_GPIOC);
    ROM_IntDisable (INT_GPIOD);
    ROM_IntDisable (INT_GPIOE);
    ROM_IntDisable (INT_GPIOF);
    ROM_IntDisable (INT_UART0);
    ROM_IntDisable (INT_UART1);
    ROM_IntDisable (INT_TIMER0A);
    ROM_IntDisable (INT_TIMER0B);
    ROM_IntDisable (INT_TIMER1A);
    ROM_IntDisable (INT_TIMER1B);
    ROM_IntDisable (INT_TIMER2A);
    ROM_IntDisable (INT_TIMER2B);
    ROM_IntDisable (INT_TIMER3A);
    ROM_IntDisable (INT_TIMER3B);

    ROM_TimerIntDisable (Timer1_base、timer_TINA_TIMEOUT);
    ROM_TimerIntClear (Timer1_base、timer_TINA_TIMEOUT);
    ROM_TimerDisable (Timer1_base、timer_A);

    ROM_TimerIntDisable (TIMER2_base、TIMER_TINA_TIMEOUT);
    ROM_TimerIntClear (TIMER2_base、TIMER_TINA_TIMEOUT);
    ROM_TimerDisable (TIMER2_base、TIMER_A);

    ROM_TimerIntDisable (TIMER3_base、TIMER_TINA_TIMEOUT);
    ROM_TimerIntClear (TIMER3_base、TIMER_TINA_TIMEOUT);
    ROM_TimerDisable (TIMER3_base、TIMER_A);

    ROM_TimerIntDisable (TIMER7_BASE、TIMER_TINA_TIMEOUT);
    ROM_TimerIntClear (TIMER7_BASE、TIMER_TINA_TIMEOUT);
    ROM_TimerDisable (TIMER7_BASE、TIMER_A);
    ROM_IntPendClear (INT_TIMER1A);

    ROM_SysTickIntDisable();
    HWREG (NVIC_INT_CTRL)|= NVIC_INT_CTRL_PENDSTCLR;

    此外、正如您之前所问的、我已经用 while (1)循环替换了 tirtos 异常处理程序。 下面是我的寄存器。 SP 仍然不显示寄存器 R0-R1-R2-R3、而是显示 R0-R0-R0-R1-R2-R3。 请参见下图。

    现在哪个地址可以为我提供线索?  

    此致、

    Erman

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

    您好、Charles、

    我想我明白了。 根据有关禁用更多内容的提示、禁用 UART 端口似乎解决了问题。  

    UARTDisable (UART1_base);

    该端口不是调试端口、它连接到另一个 IC、通常具有连续通信功能。

    我需要进行一个夜间测试、以确保其工作非常可靠、但迄今为止的手动测试是良好的。

    不过,请告诉我原因  

    HWREG (NVIC_DIS0)= 0xffffffff;
    HWREG (NVIC_DIS1)= 0xffffffff;
    HWREG (NVIC_DIS2)= 0xffffffff;
    HWREG (NVIC_DIS3)= 0xffffffff;
    HWREG (NVIC_DIS4)= 0xffffffff;

    还不够、我必须特别调用 UARTDisable 函数吗?  

    如果我对所有外设实际使用所有禁用功能,会更安全吗?

    此致、

    Erman

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [~引脚 userid="301690" URL"/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1120280/tm4c129xnczad-rom-ethernet-bootloader-forse-TO-imm-exception/4159258#4159258"]

    我想我明白了。 根据有关禁用更多内容的提示、禁用 UART 端口似乎解决了问题。  

    UARTDisable (UART1_base);

    [/报价]

    您好、Erman、

     很高兴您解决了这个问题。 我不太确定我的理论是否正确、因为我不是 TI-RTOS 专家。 尽管您已清除 NVIC 中的中断使能,但可能发生的情况是 BIOS_start()以某种方式再次启用 NVIC。 这就是为什么在我们的非 RTOS 示例中、我们从未看到这个问题。   调用 ROM_UpdateEMAC()后,它将跳转到引导加载程序,引导加载程序不会重新启用中断,因为引导加载程序本身不会被写入以使用中断。  如 UARTDisable 中所示、当您禁用外设时、确保 UART 模块不会生成中断、无论中断是否已启用或未在 NVIC 级别。