c-皮质M7:刚开始分支



我使用的是ATSAMV71Q21B MCU,它使用cortex-M7处理器。为了增加冗余,我希望有多个引导加载程序,并在启动微控制器后进入其中一个引导加载。至少,ARM处理器开始在重置矢量位置0x00000000执行。我无法选择从哪里开始。

我想知道是否可以使用一些指令来分支到我的一个引导加载程序。

目前,我尝试生成的所有解决方案都有一百条指令,这对我来说太多了。我想我需要手动添加向量位置为0x00000000的分支指令。尽管如此,我不确定我应该在哪里分支,也不确定这样做是否可以。

事实上,我不确定我是否真的理解生成的汇编代码的开头。因此,我不确定在哪里分支。

以下是程序开始的示例:

0x00400000  70 0a 40 20 d9 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 00 00 00 00  p.@ Ù.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.....
0x00400020  00 00 00 00 00 00 00 00 00 00 00 00 d5 01 40 00 d5 01 40 00 00 00 00 00 d5 01 40 00 d5 01 40 00  ............Õ.@.Õ.@.....Õ.@.Õ.@.
0x00400040  d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00  Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.
0x00400060  d5 01 40 00 00 00 00 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00  Õ.@.....Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.
0x00400080  d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00  Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.
0x004000A0  d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00  Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.
0x004000C0  d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00  Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.
0x004000E0  d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00  Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.
0x00400100  d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 00 00 00 00 00 00 00 00  Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.........
0x00400120  d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00  Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.
0x00400140  d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00  Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.
0x00400160  d5 01 40 00 d5 01 40 00 10 b5 05 4c 23 78 33 b9 04 4b 13 b1 04 48 af f3 00 80 01 23 23 70 10 bd  Õ.@.Õ.@..µ.L#x3..K.±.H¯ó.€.##p..
0x00400180  2c 04 40 20 00 00 00 00 28 04 40 00 0c 4b 43 b1 0c 48 0d 49 10 b5 af f3 00 80 0c 48 03 68 23 b9  ,.@ ....(.@..KC±.H.I.µ¯ó.€.H.h#.
0x004001A0  10 bd 0a 48 03 68 33 b9 70 47 09 4b 00 2b f7 d0 bd e8 10 40 18 47 06 4b 00 2b f5 d0 18 47 00 bf  ...H.h3.pG.K.+÷Ð.è.@.G.K.+õÐ.G.¿
0x004001C0  00 00 00 00 28 04 40 00 30 04 40 20 28 04 40 00 00 00 00 00 fe e7 00 bf 16 49 17 4a 91 42 08 b5  ....(.@.0.@ (.@.....þç.¿.I.J‘B.µ

如果我理解正确的话,这是一个向量表,我不应该在这里分支。这是正确的吗?

0x00400000  70 0a 40 20 d9 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 00 00 00 00  p.@ Ù.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.....
0x00400020  00 00 00 00 00 00 00 00 00 00 00 00 d5 01 40 00 d5 01 40 00 00 00 00 00 d5 01 40 00 d5 01 40 00  ............Õ.@.Õ.@.....Õ.@.Õ.@.
0x00400040  d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00  Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.
0x00400060  d5 01 40 00 00 00 00 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00  Õ.@.....Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.
0x00400080  d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00 d5 01 40 00  Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.Õ.@.

所以这些看起来很好第一个是堆栈指针加载值

0x20400a70 

这可能是一个奇怪的数字,但这部分有0x80000字节的内存,所以它是有效的。因此可能是链接器脚本生成的值(链接器脚本中的堆栈设置,而不是仅从ram顶部开始)。

重置矢量为

0x004001d9 

它是正确格式化的(设置了lsbit),它指向您没有提供的内容。

其他许多都是

0x004001d5

同样正确格式化的可能是一个无限循环,基于它与重置向量的接近程度,但谁知道呢,必须查看代码。这对启动来说并不重要。

芯片/家族文档表明用户闪存的地址为0x00400000,对于这些部分来说非常大,所以这个转储左侧的地址和重置矢量看起来都很好。

有迹象表明,在某个地址0x00800000或0x08000000有一个sam-ba引导程序,或者我不记得了,你可以查找它。现在,我使用了其他Atmel部件,这些部件没有在Atmel的闪存中刻录引导程序,而是源于一个你可以自己构建和使用的sam ba(为什么要麻烦让你自己的更简单、体积更小),但我对这种方法有问题,闪存是如何锁定还是不锁定的,解锁和擦除有多容易,这有什么意义?使用SWD。文档中的这条注释可能表示存在烧录,在这种情况下,您需要考虑如何选择启动该应用程序而不是用户应用程序,因为它们表示特定的地址。如果它是用户可更改的,那么这可能是你想要放置引导程序的地方,或者如果它是固定的,并且不可更改,那么就把它用作引导程序。

至于你通常把引导程序放在哪里,这就是你的全部,你可以选择你的设计,你所说的引导程序是什么意思,什么功能等等。经常被滥用,但这个术语意味着既要引导部件,也要有一种以某种方式加载其他应用程序的方法(在ram中运行一个,重新编程用户/boot/application flash,等等)。你需要了解的是,如果你想用新固件重写其中的一部分,闪存是如何在这个设备上工作的。有时你可以同时执行out和flash,但更可能的是,它们使用多个闪存组,这样你就可以在一个闪存组中运行并修改另一个,这就导致了他们的引导方案是什么?它总是只在一个上引导,而从不在另一个上启动,所以你要么永远保持引导加载程序不变,要么制定一个方案,还必须具有一种方案,用于在引导加载程序引导之后选择哪些存储体上的图像作为默认固件。

这些核心通常可以在ram中运行代码,没有理由期望不在这里运行(重要的不是核心,而是芯片供应商的实现),因此,将引导加载程序的一部分复制并跳转到ram以避免在flash上运行,这允许您重新编程任何flash,但如果它失败或断电,则可能会使您面临风险。

如果芯片供应商还没有使用工厂引导加载程序,并且该工厂加载程序适合现场使用,则可以使用I/O引脚来确定哪一个引导程序,必须查看文档。如果你自己选择这样做,让gpio引脚选择两个引导路径是不明智的,然后你可以有一个非常小的,理想情况下,十几行程序集可以读取gpio引脚并分支到闪存中的一个固定点,例如说0x00500000和0x00600000,这取决于你认为你的应用程序实际有多大。然后,如果用户想要加载闪存,你可以复制并跳入ram,然后你可以选择加载其中一个。为数不多的几行代码可能是几十行,并对选定的银行和未选定的银行进行校验和,如果选定的银行不好且不完整。或者您提供的第三个引导加载程序,以防两者不进行校验和。

大量的解决方案,通常情况下,如果你没有单独存储的闪存,你需要分支到ram,并在如何设计内存空间方面有更多的自由(假设闪存可以在页面中擦除)。否则,您可能只想使用芯片供应商的银行解决方案。

因此,所有这些都记录在arm和Atmel(微芯片)的文件中,在开始使用该设备之前,您应该拥有这些文件。在这一切中,唯一与arm相关的是向量表的工作方式。其余的,地址,大小等等都是芯片供应商实现的。因此,你的大部分阅读内容都在芯片供应商的文档中,在这种情况下,他们有庞大的数据表方法(而不是单独的数据表和参考手册方法)。

如果你想使用sam-ba,你需要重新阅读我发现的内容。如果它对你有用,闪存实现的性质,它在应用程序中可编程吗?等等。然后,你不仅设计了引导程序的功能,还设计了地址空间,无论它是在闪存还是ram中执行。

编辑

万一我不理解这个问题。

手臂重置矢量为0x00000004,而不是0x00000000(对于皮层ms),并且它是处理器的地址,用1 ORRED。地址0x00000000是堆栈指针初始化值,如果您选择在代码中初始化堆栈指针,而不使用此机制,则可以将您想要的任何内容放在那里。

如果你想更改重置处理程序地址,那么你必须修改0x00000004,在某些部分,你可以在不擦除的情况下更改0x00000004(通常通过擦除为全1来闪烁,然后你可以写0,不能写1,但可以在每个字节/字/块的基础上将1更改为0)。因此,要改变这一点,您可能需要保存它,擦除块/页,更改您想要的位并写回。例如,您可以将其从0x004001d9更改为sah 0x004101d9或0x004000d9,但不值得尝试这样做。该值是处理程序的地址,ORRED为1。

它不是一个分支,因为代码在这一点上没有执行(通常/假设),它是读取该位置并将其作为起点的逻辑,第一次获取不是分支。

如前所述,查看矢量表在项目中的位置,然后修改它以指向备用重置处理程序。它可能是看起来像这个的代码

.word STACK_END
.word reset_handler
.word 

在这种情况下,剩下的很多都是一些填充/伪向量。只需用处理程序替换reset_handler或你找到的任何东西,记住这是一个引导程序,如果你计划调用任何C函数,你需要引导C,如果是C++或其他语言,情况会更糟。

相关内容

最新更新