C语言 Hard fault RP2040 pico Zephyr



我在Zephyr和MCUboot下使用RP2040。最终目标是能够通过UART总线使用MCUMGR更新固件。MCUboot采用A/B无缝(双插槽内存)方式,提供安全的更新算法。当设备重新启动时,MCUboot检查是否有新的固件可用,在这种情况下,在新的固件上启动。为此,交换算法将目标固件放在槽位0中。由于该算法操作flash,必须将某些函数映射到SRAM中,以确保该函数不会擦除自己的代码。通常,由于RP2040上的Direct-XIP,代码直接从flash执行。问题是SRAM似乎不是可执行的。当程序进入位于SRAM中的函数并执行第一条指令时,这会导致硬故障:

0x2000c144 : push {r4, r5, r6, r7, lr}

幸运的是,Zephyr crash的处理程序给出了一些信息:

E: ***** HARD FAULT *****
E: r0/a1:  0x0003d000  r1/a2:  0x00002000  r2/a3:  0x00002000
E: r3/a4:  0x00000000 r12/ip:  0x2000c145 r14/lr:  0x100022e5
E:  xpsr:  0x21000000
E: Faulting instruction address (r15/pc): 0x2000c144
E: >>> ZEPHYR FATAL ERROR 0: CPU exception on CPU 0
E: Current thread: 0x2000c3d0 (unknown)
E: Halting system

一切正常,电脑地址正确。我强烈怀疑是MPU配置错误导致程序在执行位于SRAM中的代码时崩溃。

我的问题是:

MPU会导致Hardfault吗?如何在Zephyr中配置SRAM以执行SRAM中的代码?

首先,我试图检查相同的功能是否可从flash执行。我删除了指示位于flash上的宏。

:

void __no_inline_not_in_flash_func(flash_range_erase)(uint32_t flash_offs, size_t count) {
...

:后

void flash_range_erase(uint32_t flash_offs, size_t count) {
...

…它有效!函数按预期执行。我现在很确定MPU不愿意让我在SRAM内执行代码。

我搜索了有关如何配置MPU以让我在SRAM中执行代码的信息,我发现此页面:https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/hardware/arch/arm_cortex_m.html解释了如何配置固定区域。我在我的设备树叠加中添加了以下几行:

&sram0 {
    /delete-property/ compatible ;
    /delete-property/ reg ;
    compatible = "zephyr,memory-region", "mmio-sram";
    zephyr,memory-region = "RAM_EXECUTABLE";
    zephyr,memory-region-mpu = "RAM";
    reg = < 0x20000000 0x10000 >; //Configure SRAM for MCUboot fixed for MPU
    // RAM size has to match with BOOTLOADER_SRAM_SIZE (see menuconfig)
};

但这并没有解决问题。

这是Zephyr中RP2040的flash控制器的问题。

flash控制器必须禁用XiP才能运行flash操作(r/w)。在此过程中,控制器试图运行未链接到RAM(在闪存中)的函数。

要恢复,控制器在禁用flash执行后试图调用flash中的函数。我可能很快会发布一个补丁。

更多关于西风之神不和的信息在这里:https://discord.com/channels/720317445772017664/938474761405726800/1060917537405157446

注意在我的问题中,我试图使用MPU,但我不得不禁用引导加载程序配置。

相关内容

  • 没有找到相关文章

最新更新