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

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

问题描述



这看起来像是一团废话,我需要有人来帮助我清除所有问题......在ARM的世界中,我听到无数次将矢量表放置如下:

  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

确切地说在我的二进制文件中位置 0x00000000 ,但为什么我们要这样做,如果这个位置在启动时被映射到一个启动ROM矢量表,它甚至不能被更改,因为它是只读?!那么我们可以在哪里放置我们自己的矢量表?我曾考虑将它放在 0x1FFF0000 ,所以它会在重置时转移到位置 0x00000000 ,但不能这样做,因为的只读区域...



现在到第二部分。 ARM期望在 0x00000000 处准确找到 8 向量,并且在复位引导ROM检查 8 向量的和是否为零,只有当这是真实的用户代码执行。为了通过这个检查,我们需要总结第一个 7 向量,并将它的2补码保存到最后一个向量,它是驻留在 0x0000001C 。那么这只有在你的代码是4字节对齐(ARM编码)的情况下才是正确的,但是如果你的代码是2字节对齐的(Thumb编码),它仍然是真的,所有只能执行Thumb编码的Cortex-M4核心opcodes ...那么为什么他们明确提到,当它永远不会与Cortex-M4一起玩时,总和的二进制补码必须位于 0x0000001C 。是 0x0000000E 将2的补码保存到正确的地址?

第三部分。为什么启动ROM甚至会在启动ROM中检查第一个 8 向量的总和是否为零?并且是只读的!



你能看到这里有什么奇怪的东西吗?我需要有人向我解释上述三段中的不明之处...... 解决方案

你需要阅读arm文档以及nxp文档。非皮质m型芯的引导方式与您一直卡在那里的cortex-m型芯不同。

armortex ARM架构参考手册)。它基于矢量而不是指令。处理程序的地址不是像全尺寸手臂内核那样的指令。例外7被记录为保留(对于基于ARM7TDMI的mcus而言,它是它们用于此校验和的保留向量)。根据您使用的arm核心,他们预计多达144或272个(例外,根据内核支持的情况,最多可以有128或256个中断)。

(note aarch64处理器,armv8在64位模式下的启动方式也不同于传统的全尺寸32位处理器,甚至更大的表)。

这个校验和是经典的恩智浦,感觉,没有理由启动到已擦除或未正确准备好的闪存和砖块或挂起。

  .cpu cortex-m0 
.thumb
.thumb_func
.globl _start
_start:
.word 0x20001000 @ 0 SP加载
.word复位@ 1复位
.word hang @ 2 NMI
.word hang @ 3 HardFault
.word hang @ 4 MemManage
.word hang @ 5 BusFault
.word hang @ 6 UsageFault
.word 0x00000000 @ 7保留

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



给出:

 反汇编部分.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 bn 20< hang>

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

现在创建一个临时工具,执行校验和并将其添加到二进制文件中



以程序的形式看这段程序:

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

并且如果您将其刷新,引导加载程序应该对它感到满意并让它运行。



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



裸机编程的99%是阅读和研究。如果你已经构建了一个二进制文件,或者使用了支持这个处理器或系列的沙箱,那么你可以检查构建的二进制文件,看看它们是如何工作的。或者查看某人的github示例或博客,了解其工作原理。他们确实记录了这一点,他们在恩智浦之前已经使用了这种方案很多年,所以没有什么新的东西......现在是基于字或字节的校验和,文档意味着基于字的并且更有意义。但一个简单的实验和/或看沙箱制作的二进制文件将解决这个问题。



我是如何做这个答案的。

  #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; (ra = 0; ra< 7; ra ++)
{
rb + = data [ra];
}
data [7] =( - rb);
rb = 0; (ra = 0; ra <8; ra ++)
{
rb + = data [ra];
printf(0x%08X 0x%08X \ n,data [ra],rb);
}
return(0);
}

输出:

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

然后剪切并粘贴到答案中。



我过去的做法是制作一个adhoc util,我从我的makefile调用的objcopied .bin文件上运行,并修改该文件或创建一个新的.bin文件,其中包含校验和应用。您应该能够在20-50行代码中编写代码,选择您喜欢的语言。

另一个评论问题:

  .cpu cortex-m0 
.thumb

.word one
.word two
.word three

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

反汇编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)

.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天全站免登陆