Atmel SAM3X 双组切换不起作用

Posted

技术标签:

【中文标题】Atmel SAM3X 双组切换不起作用【英文标题】:Atmel SAM3X dual bank switching not working 【发布时间】:2017-11-02 14:54:57 【问题描述】:

我目前正在使用具有双组 2 x 256KB 闪存的 Atmel SAM3X8 ARM 微控制器。我正在尝试实现固件更新功能,将新固件放入当前未使用的闪存库中,并在完成后使用闪存重新映射交换库以运行新固件。

数据表指出,我需要设置 GPNVM2 位,然后 MCU 将重新映射内存,因此 Flash 1 现在位于 0x80000,Flash 0 位于 0xC0000。这也会导致 MCU 从 Flash 1 开始执行代码。

引用数据表:

GPNVM2 仅用于交换 Flash 0 和 Flash 1。如果 GPNVM2 为 ENABLE,则 Flash 1 映射到 地址 0x0008_0000(Flash 1 和 Flash 0 是连续的)。如果 GPNVM2 为 DISABLE,则 Flash 0 映射到 地址 0x0008_0000(Flash 0 和 Flash 1 是连续的)。

[...]

GPNVM2 可以选择是使用 Flash 0 还是 Flash 1 进行引导。 设置 GPNVM 位 2 选择从 Flash 1 启动,清除它选择从 Flash 0 启动。

但是当我通过 SAM-BA 或我自己的固件使用 flash_set_gpnvm(2) (ASF SAM Flash Service API) 设置 GPNVM2 时,它仍然会从 Flash 0 中的程序启动,并且新程序仍将驻留在 Flash 1 的偏移量 0xC0000 处。 GPNVM2 的状态已通过 flash_is_gpnvm_set(2)

验证

将固件本身刷入 Flash1 库可以完美运行,这已通过使用 SAM-BA 转储整个闪存来验证。

Atmel 提供了一个关于一个问题的勘误表,即闪存重新映射仅适用于小于 64KB 的部分。我的代码小于那个 (40KB),所以这应该不是问题。

我没有发现任何其他人遇到此问题,也没有任何示例如何使用它,所以也许有人可以告诉我我在这里做错了什么,或者还有什么要检查的。

【问题讨论】:

在切换到另一个闪存时,您没有从一个闪存运行代码,是吗?您在 ram 中使用蹦床在它们之间弹跳? 在设置/清除 GPNVM2 位以强制它运行新代码后,我确实重置了控制器(尝试了软件重置和断电)。反正我觉得remapping只是在开机的时候才做的,所以修改寄存器只有重启后才会生效 我同意您在数据表中看到的内容,如果您确实在读回 GPNVM 位并看到第 2 位设置但 0x0000 未映射到第二个银行,那么也许是时候联系 Atmel/Microchip 【参考方案1】:

我遇到了同样的问题(请参阅此处:Atmel SAM3X8E dual bank switching for booting different behaviour)。

经过更多研究,我发现了一个应用说明(链接:http://ww1.microchip.com/downloads/en/AppNotes/Atmel-42141-SAM-AT02333-Safe-and-Secure-Bootloader-Implementation-for-SAM3-4_Application-Note.pdf),它以更清晰的方式解释了 SAM3X 的启动行为。问题是数据表有点误导(至少我也很困惑)。 SAM3X 无法重新映射闪存组。引导行为有点不同(参见链接中的图片,它是从应用说明中截取的,第 33/34 页): Booting behaviour SAM3X

图 3-9 显示了 SAM3X 在启动时的行为。 GPNVM 位 1 和 2 仅确定哪个内存部分(ROM/Flash0/Flash1)镜像到引导内存(位于 0x00000000)。 Flash 库的映射没有改变。因此 Flash0 仍然映射到 0x00080000 和 Flash1 到 0x000C0000)。

正如应用笔记所述,其他一些 Atmel 微控制器能够真正重新映射闪存组(例如 SAM3SD8 和 SAM4SD32/16)。这些处理器改变了 Flash bank 的位置,如图 3-10 所示。

为了能够更新您的固件,因此有必要实现某种引导加载程序。我自己实现了一个,即使完全不使用 GPNVM 位也能够更新我的固件。我还在 Microchip 上开了一张支持票以澄清引导行为。当我收到答案时,我希望能告诉你更多。

编辑:

这是来自 Microchip 支持的答案:

在 SAM3X 中设置 GPNVM2 位只会使 CPU “跳转到”或从 flash bank 1 开始,即 0xC0000。 不会发生实际的内存地址交换。

要使用闪存库 1,您需要更改链接器文件 (flash.ld) 以反映闪存起始地址 0xC0000。

对于闪存库 0 应用程序,更改: rom (rx) : ORIGIN = 0x00080000, LENGTH = 0x00080000 /* Flash, 512K / 到: rom (rx) : ORIGIN = 0x00080000, LENGTH = 0x00040000 / Flash, 256K */

对于闪存库 1 应用程序,更改: rom (rx) : ORIGIN = 0x00080000, LENGTH = 0x00080000 /* Flash, 512K / 到: rom (rx) : ORIGIN = 0x000C0000, LENGTH = 0x00040000 / Flash, 256K */

如果不这样做,闪存 1 应用程序中的复位处理程序将指向闪存 0 应用程序中的地址。 因此,虽然代码会在 flash 1 中开始执行(如果设置了 GPNVM2),但它会跳回到 flash 0 应用程序。 说明 64kb 限制的勘误表可以忽略。

因此,应用说明是正确的,没有实际更改内存映射。

干杯 卢卡斯

【讨论】:

感谢@Lukas 的澄清,以及来自 Microchip 的信息。同时,我已经完全用软件实现了,所以也不要使用银行切换。

以上是关于Atmel SAM3X 双组切换不起作用的主要内容,如果未能解决你的问题,请参考以下文章

系统调用在 Atmel AVR Studio(使用 ASF)中不起作用

为啥segues不起作用?无法切换视图

为啥在模式内部切换在 laravel 中不起作用?

切换播放/暂停不起作用

为啥切换屏幕在 kivy 中不起作用?

jQuery .next('div') 切换不起作用