Thumb 的 LPC4088 校验和值? [英] LPC4088 checksum value for Thumb?

查看:31
本文介绍了Thumb 的 LPC4088 校验和值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这看起来完全是胡说八道,我需要有人帮我解决问题......在ARM的世界里我听过无数次把向量表变成这样:

重置:b _start未定义:b 未定义软件中断:b 软件中断prefetch_abort: b prefetch_abort数据中止:b 数据中止没有中断请求:b 中断请求fast_interrupt_request: b fast_interrupt_request

正好在我的二进制文件中的 0x00000000 位置,但是如果这个位置在启动时被一个引导 ROM 向量表遮蔽了,我们为什么要这样做,因为它在读取时甚至无法更改 -只要?!那么我们可以把我们自己的向量表放在哪里呢?我想把它放在 0x1FFF0000 这样它会在重置时转移到位置 0x00000000 但由于只读区域而不能这样做......

现在进入第二部分.ARM 期望在 0x00000000 处准确找到 8 个向量,并且在重置引导 ROM 时检查 8 个向量的总和是否为零,并且仅当这是真正的用户时代码执行.要通过此检查,我们需要对前 7 个向量求和,并将其与最后一个向量的 2 的补码相加,最后一个向量是驻留在 0x0000001C 的快速中断请求的向量.好吧,这仅在您的代码是 4 字节对齐(ARM 编码)时才成立,但如果您的代码是 2 字节对齐(Thumb 编码),所有 Cortex-M4 内核都只能执行 Thumb 编码,则情况仍然如此操作码……那么为什么他们明确提到总和的 2 的补码必须在 0x0000001C 处,而 Cortex-M4 永远不会出现这种情况.0x0000000E 是将 2 的补码保存到的正确地址吗?

第三部分.当它们已经在引导 ROM 中时,为什么引导 ROM 还要检查前 8 个向量的总和是否为零?!并且是只读的!

你能看出这里有什么奇怪的地方吗?我需要有人向我解释以上三段中的不明确之处...

解决方案

您需要阅读 arm 文档以及 nxp 文档.非 cortex-m 内核的启动方式与您一直卡在那里的 cortex-m 内核不同.

cortex m 记录在 armv7m ARM ARM(架构参考手册)中.它基于向量而不是指令.处理程序的地址,而不是像全尺寸 arm 内核那样的指令.例外 7 被记录为保留(对于来自他们的基于 ARM7TDMI 的 mcus,它也是他们用于此校验和的保留向量).根据您使用的 arm 核心,他们预计多达 144 或 272 个(例外加上多达 128 或 256 个中断,具体取决于核心支持的内容).

(注意 aarch64 处理器,64 位模式下的 armv8 也与传统的全尺寸 32 位 arm 处理器不同,甚至更大的表).

这个校验和是经典的 NXP 并且是有道理的,没有理由启动到已擦除或未正确准备的闪存和砖块或挂起.

.cpu cortex-m0.拇指.thumb_func.globl _start_开始:.word 0x20001000 @ 0 SP 负载.word 重置 @ 1 重置.word 挂起@ 2 NMI.word 挂起 @ 3 HardFault.word 挂起@ 4 MemManage.word 挂起 @ 5 BusFault.word 挂起 @ 6 UsageFault.word 0x00000000 @ 7 保留.thumb_func挂:b 挂.thumb_func重启:b挂

给出:

 .text 节的反汇编:00000000 <_start>:0: 20001000 andcs r1, r0, r04: 00000023 andeq r0, r0, r3, lsr #328: 00000021 andeq r0, r0, r1, lsr #32c: 00000021 andeq r0, r0, r1, lsr #3210: 00000021 andeq r0, r0, r1, lsr #3214: 00000021 andeq r0, r0, r1, lsr #3218: 00000021 andeq r0, r0, r1, lsr #321c: 00000000 andeq r0, r0, r000000020 <挂>:20: e7fe b.n 20 <hang>00000022 <重置>:22: e7fd b.n 20 <hang>

现在制作一个专门的工具来执行校验和并将其添加到二进制文件中

把上面的程序看成文字就是这个程序:

0x200010000x000000230x000000210x000000210x000000210x000000210x000000210xDFFFEF380xE7FDE7FE

如果你刷入它,引导加载程序应该对它感到满意并让它运行.

现在假设校验和是基于字的,如果它是基于字节的,那么您需要一个不同的数字.

99% 的裸机编程都是阅读和研究.如果您已经构建了他们的二进制文件或使用了支持该处理器或系列的沙箱,您可以检查构建的二进制文件并查看所有这些是如何工作的.或者查看某人的 github 示例或博客以了解其工作原理.他们确实记录了这一点,并且在他们成为 NXP 之前,他们已经使用这个方案很多年了,所以没什么新鲜的……现在它是基于单词还是基于字节的校验和,文档暗示基于单词,这更有意义.但是一个简单的实验和/或查看沙箱生成的二进制文件就可以解决这个问题.

我是如何回答这个问题的.

#include 无符号整数数据[8]={0x20001000,0x00000023,0x00000021,0x00000021,0x00000021,0x00000021,0x00000021,0x00000000,};int main ( void ){无符号整数 ra;无符号整数 rb;rb=0;for(ra=0;ra<7;ra++){rb+=数据[ra];}数据[7]=(-rb);rb=0;for(ra=0;ra<8;ra++){rb+=数据[ra];printf("0x%08X 0x%08X\n",data[ra],rb);}返回(0);}

输出:

0x20001000 0x200010000x00000023 0x200010230x00000021 0x200010440x00000021 0x200010650x00000021 0x200010860x00000021 0x200010A70x00000021 0x200010C80xDFFFEF38 0x00000000

然后将内容剪切并粘贴到答案中.

我过去的做法是制作一个临时工具,我从我的 makefile 中调用它,该工具对 objcopied .bin 文件进行操作,然后修改该文件或创建一个应用了校验和的新 .bin 文件.您应该可以用 20 到 50 行代码编写,选择您喜欢的语言.

另一个评论问题:

.cpu cortex-m0.拇指.word 一.word 2.word 三.thumb_func一:没有二:.thumb_func三:没有.text 节的反汇编:00000000 <one-0xc>:0: 0000000d andeq r0, r0, sp4: 0000000e andeq r0, r0, lr8: 0000000f andeq r0, r0, pc0000000c<一>:c: 46c0 nop ;(移动 r8, r8)0000000e <三>:e: 46c0 nop ;(移动 r8, r8)

.thumb_func 影响标签 AFTER...

In the LPC4088 user manual (p. 876) we can read that LPC4088 microcontroler has a really extraordinary startup procedure:

This looks like a total nonsense and I need someone to help me clear things out... In the world of ARM I've heard countless times to put vector table looking like this:

reset:                  b _start
undefined:              b undefined
software_interrupt:     b software_interrupt
prefetch_abort:         b prefetch_abort
data_abort:             b data_abort
                        nop
interrupt_request:      b interrupt_request
fast_interrupt_request: b fast_interrupt_request

exactly at location 0x00000000 in my binary file, but why would we do that if this location is shadowed at boot with a boot ROM vector table which can't even be changed as it is read-only?! So where can we put our own vector table? I thought about putting it at 0x1FFF0000 so it would be transferred to location 0x00000000 at reset but can't do that because of read-only area...

Now to the second part. ARM expects to find exactly 8 vectors at 0x00000000 and at reset boot ROM checks if sum of 8 vectors is zero and only if this is true user code executes. To pass this check we need to sum up first 7 vectors and save it's 2's complement to the last vector which is a vector for fast interrupt requests residing at 0x0000001C. Well this is only true if your code is 4-bytes aligned (ARM encoding) but is it still true if your code is 2-bytes aligned (Thumb encoding) which is the case with all Cortex-M4 cores that can only execute Thumb encoded opcodes... So why did they explicitly mention that 2's complement of the sum has to be at 0x0000001C when this will never come in to play with Cortex-M4. Is 0x0000000E the proper address to save the 2's complement to?

And third part. Why would boot ROM even check if sum of first 8 vectors is zero when they are already in boot ROM?! And are read-only!

Can you see something is weird here? I need someone to explain to me the unclarities in the above three paragraphs...

解决方案

you need to read the arm documentation as well as the nxp documentation. The non-cortex-m cores boot differently than the cortex-m cores you keep getting stuck there.

The cortex m is documented in the armv7m ARM ARM (architectural reference manual). It is based on VECTORS not INSTRUCTIONS. An address to the handler not an instruction like in full sized arm cores. Exception 7 is documented as reserved (for the ARM7TDMI based mcus from them it was the reserved vector they used for this checksum as well). Depending on the arm core you are using they expect as many as 144 or 272 (exceptions plus up to 128 or 256 interrupts depending on what the core supports).

(note the aarch64 processor, armv8 in 64 bit mode also boots differently than the traditional full sized 32 bit arm processor, even bigger table).

This checksum thing is classic NXP and makes sense, no reason to launch into an erased or not properly prepared flash and brick or hang.

.cpu cortex-m0
.thumb
.thumb_func
.globl _start
_start:
.word 0x20001000 @ 0 SP load
.word reset @ 1 Reset
.word hang  @ 2 NMI
.word hang  @ 3 HardFault
.word hang  @ 4 MemManage
.word hang  @ 5 BusFault
.word hang  @ 6 UsageFault
.word 0x00000000 @ 7 Reserved

.thumb_func
hang: b hang
.thumb_func
reset:
    b hang

which gives:

Disassembly of section .text:

00000000 <_start>:
   0:   20001000    andcs   r1, r0, r0
   4:   00000023    andeq   r0, r0, r3, lsr #32
   8:   00000021    andeq   r0, r0, r1, lsr #32
   c:   00000021    andeq   r0, r0, r1, lsr #32
  10:   00000021    andeq   r0, r0, r1, lsr #32
  14:   00000021    andeq   r0, r0, r1, lsr #32
  18:   00000021    andeq   r0, r0, r1, lsr #32
  1c:   00000000    andeq   r0, r0, r0

00000020 <hang>:
  20:   e7fe        b.n 20 <hang>

00000022 <reset>:
  22:   e7fd        b.n 20 <hang>

now make an ad-hoc tool that does the checksum and adds it to the binary

Looking at the above program as words this is the program:

0x20001000
0x00000023
0x00000021
0x00000021
0x00000021
0x00000021
0x00000021
0xDFFFEF38
0xE7FDE7FE

and if you flash it the bootloader should be happy with it and let it run.

Now that is assuming the checksum is word based if it is byte based then you would want a different number.

99% of baremetal programming is reading and research. If you had a binary from them already built or used a sandbox that supports this processor or family you could examine the binary built and see how all of this works. Or look at someones github examples or blog to see how this works. They did document this, and they have used this scheme for many years now before they were NXP, so nothing really new...Now is it a word based or byte based checksum, the documentation implies word based and that makes more sense. but a simple experiment and/or looking at sandbox produced binaries would have resolved that.

How I did it for this answer.

#include <stdio.h>
unsigned int data[8]=
{
0x20001000,
0x00000023,
0x00000021,
0x00000021,
0x00000021,
0x00000021,
0x00000021,
0x00000000,
};
int main ( void )
{
    unsigned int ra;
    unsigned int rb;

    rb=0;
    for(ra=0;ra<7;ra++)
    {
        rb+=data[ra];
    }
    data[7]=(-rb);
    rb=0;
    for(ra=0;ra<8;ra++)
    {
        rb+=data[ra];
        printf("0x%08X 0x%08X\n",data[ra],rb);
    }
    return(0);
}

output:

0x20001000 0x20001000
0x00000023 0x20001023
0x00000021 0x20001044
0x00000021 0x20001065
0x00000021 0x20001086
0x00000021 0x200010A7
0x00000021 0x200010C8
0xDFFFEF38 0x00000000

then cut and pasted stuff into the answer.

How I have done it in the past is make an adhoc util that I call from my makefile that operates on the objcopied .bin file and either modifies that one or creates a new .bin file that has the checksum applied. You should be able to write that in 20-50 lines of code, choose your favorite language.

another comment question:

.cpu cortex-m0
.thumb

.word one
.word two
.word three

.thumb_func
one:
    nop
two:
.thumb_func
three:
    nop

Disassembly of section .text:

00000000 <one-0xc>:
   0:   0000000d    andeq   r0, r0, sp
   4:   0000000e    andeq   r0, r0, lr
   8:   0000000f    andeq   r0, r0, pc

0000000c <one>:
   c:   46c0        nop         ; (mov r8, r8)

0000000e <three>:
   e:   46c0        nop         ; (mov r8, r8)

the .thumb_func affects the label AFTER...

这篇关于Thumb 的 LPC4088 校验和值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆