内部引导加载程序 ARM cortex M4 NRF52 芯片
In house bootloader ARM cortex M4 NRF52 chip
我正在为一个副项目制作引导加载程序。
我读入了一个 hex 文件,验证了校验和并将所有内容存储在闪存中,对应地址偏移量为 0x4000。我在跳转到我的应用程序时遇到问题。我已经阅读、搜索并尝试了很多不同的东西,比如这里的代码。
http://www.keil.com/support/docs/3913.htm
我现在的代码是这样的;
int binary_exec(void * Address){
int i;
__disable_irq();
// Disable IRQs
for (i = 0; i < 8; i ++) NVIC->ICER[i] = 0xFFFFFFFF;
// Clear pending IRQs
for (i = 0; i < 8; i ++) NVIC->ICPR[i] = 0xFFFFFFFF;
// -- Modify vector table location
// Barriars
__DSB();
__ISB();
// Change the vector table
SCB->VTOR = ((uint32_t)0x4000 & 0x1ffff80);
// Barriars
__DSB();
__ISB();
__enable_irq();
// -- Load Stack & PC
binExec(Address);
return 0;
}
__asm void binexec(uint32_t *address)
{
mov r1, r0
ldr r0, [r1, #4]
ldr sp, [r1]
blx r0"
}
这只是跳转到一个随机位置,并没有做任何事情。我已经使用 keil 的寄存器 window 手动将地址添加到 PC,它会直接跳转到我的应用程序,但我还没有找到使用代码来完成它的方法。有任何想法吗?提前谢谢你。
十六进制文件的倒数第二行还有起始线性地址记录:
http://www.keil.com/support/docs/1584.htm
有人知道如何处理这条线吗?
谢谢,
埃里克·米卡勒夫
这就是我所说的,你能给我们看一些看起来像这样的片段吗,这是一个完整的应用程序,只是没有做太多......
20004000 <_start>:
20004000: 20008000
20004004: 20004049
20004008: 2000404f
2000400c: 2000404f
20004010: 2000404f
20004014: 2000404f
20004018: 2000404f
2000401c: 2000404f
20004020: 2000404f
20004024: 2000404f
20004028: 2000404f
2000402c: 2000404f
20004030: 2000404f
20004034: 2000404f
20004038: 2000404f
2000403c: 20004055
20004040: 2000404f
20004044: 2000404f
20004048 <reset>:
20004048: f000 f806 bl 20004058 <notmain>
2000404c: e7ff b.n 2000404e <hang>
2000404e <hang>:
2000404e: e7fe b.n 2000404e <hang>
20004050 <dummy>:
20004050: 4770 bx lr
...
20004054 <systick_handler>:
20004054: 4770 bx lr
20004056: bf00 nop
20004058 <notmain>:
20004058: b510 push {r4, lr}
2000405a: 2400 movs r4, #0
2000405c: 4620 mov r0, r4
2000405e: 3401 adds r4, #1
20004060: f7ff fff6 bl 20004050 <dummy>
20004064: 2c64 cmp r4, #100 ; 0x64
20004066: d1f9 bne.n 2000405c <notmain+0x4>
20004068: 2000 movs r0, #0
2000406a: bd10 pop {r4, pc}
offset 0x00是栈指针
20004000: 20008000
偏移量 0x04 是复位向量或该程序的入口点
20004004: 20004049
我填充了未使用的,使它们无限循环
20004008: 2000404f
并扔进另一个只是为了展示
2000403c: 20004055
在这种情况下,VTOR 将设置为 0x2004000,我将从 0x20004004 读取 0x20004049,然后 BX 到该地址。
所以我的 binexec 将被提供地址 0x20004000,我会做这样的事情
ldr r1,[r0]
mov sp,r1
ldr r2,[r0,#4]
bx r2
如果我想在该代码中伪造一个重置。使用 thumb2 的 thumb 方法我假设你可以 ldr sp,[r0],我不会手写 thumb2 所以没有记住那些,并且有不同的 thumb2 扩展集,以及 gas 中的不同语法选项。
现在如果你不打算支持中断,或者出于其他原因(可能在你的闪存中携带一些你想要更好地执行的二进制代码,你将它从闪存复制到 ram 然后在 ram 中使用它)你可以下载到 ram 一个在入口点只有第一条指令的应用程序,没有向量 table:
20004000 <_start>:
20004000: f000 f804 bl 2000400c <notmain>
20004004: e7ff b.n 20004006 <hang>
20004006 <hang>:
20004006: e7fe b.n 20004006 <hang>
20004008 <dummy>:
20004008: 4770 bx lr
...
2000400c <notmain>:
2000400c: b510 push {r4, lr}
2000400e: 2400 movs r4, #0
20004010: 4620 mov r0, r4
20004012: 3401 adds r4, #1
20004014: f7ff fff8 bl 20004008 <dummy>
20004018: 2c64 cmp r4, #100 ; 0x64
2000401a: d1f9 bne.n 20004010 <notmain+0x4>
2000401c: 2000 movs r0, #0
2000401e: bd10 pop {r4, pc}
在这种情况下,需要同意下载的程序是为 0x20004000 构建的,您可以将数据下载到该地址,但是当您想要 运行 时,您可以这样做
.globl binexec
binexec:
bx r0
C
binexec(0x20004000|1);
或
.globl binexec
binexec:
orr r0,#1
bx r0
为了安全起见(r)。
在这两种情况下,如果您希望它们 运行,都需要正确构建二进制文件,两者都必须链接到目标地址,特别是向量 table 方法,因此问题,您能否向我们展示您下载的某个程序中的示例向量 table,即使是前几个字也可能就足够了...
我正在为一个副项目制作引导加载程序。
我读入了一个 hex 文件,验证了校验和并将所有内容存储在闪存中,对应地址偏移量为 0x4000。我在跳转到我的应用程序时遇到问题。我已经阅读、搜索并尝试了很多不同的东西,比如这里的代码。
http://www.keil.com/support/docs/3913.htm
我现在的代码是这样的;
int binary_exec(void * Address){
int i;
__disable_irq();
// Disable IRQs
for (i = 0; i < 8; i ++) NVIC->ICER[i] = 0xFFFFFFFF;
// Clear pending IRQs
for (i = 0; i < 8; i ++) NVIC->ICPR[i] = 0xFFFFFFFF;
// -- Modify vector table location
// Barriars
__DSB();
__ISB();
// Change the vector table
SCB->VTOR = ((uint32_t)0x4000 & 0x1ffff80);
// Barriars
__DSB();
__ISB();
__enable_irq();
// -- Load Stack & PC
binExec(Address);
return 0;
}
__asm void binexec(uint32_t *address)
{
mov r1, r0
ldr r0, [r1, #4]
ldr sp, [r1]
blx r0"
}
这只是跳转到一个随机位置,并没有做任何事情。我已经使用 keil 的寄存器 window 手动将地址添加到 PC,它会直接跳转到我的应用程序,但我还没有找到使用代码来完成它的方法。有任何想法吗?提前谢谢你。
十六进制文件的倒数第二行还有起始线性地址记录: http://www.keil.com/support/docs/1584.htm
有人知道如何处理这条线吗?
谢谢,
埃里克·米卡勒夫
这就是我所说的,你能给我们看一些看起来像这样的片段吗,这是一个完整的应用程序,只是没有做太多......
20004000 <_start>:
20004000: 20008000
20004004: 20004049
20004008: 2000404f
2000400c: 2000404f
20004010: 2000404f
20004014: 2000404f
20004018: 2000404f
2000401c: 2000404f
20004020: 2000404f
20004024: 2000404f
20004028: 2000404f
2000402c: 2000404f
20004030: 2000404f
20004034: 2000404f
20004038: 2000404f
2000403c: 20004055
20004040: 2000404f
20004044: 2000404f
20004048 <reset>:
20004048: f000 f806 bl 20004058 <notmain>
2000404c: e7ff b.n 2000404e <hang>
2000404e <hang>:
2000404e: e7fe b.n 2000404e <hang>
20004050 <dummy>:
20004050: 4770 bx lr
...
20004054 <systick_handler>:
20004054: 4770 bx lr
20004056: bf00 nop
20004058 <notmain>:
20004058: b510 push {r4, lr}
2000405a: 2400 movs r4, #0
2000405c: 4620 mov r0, r4
2000405e: 3401 adds r4, #1
20004060: f7ff fff6 bl 20004050 <dummy>
20004064: 2c64 cmp r4, #100 ; 0x64
20004066: d1f9 bne.n 2000405c <notmain+0x4>
20004068: 2000 movs r0, #0
2000406a: bd10 pop {r4, pc}
offset 0x00是栈指针
20004000: 20008000
偏移量 0x04 是复位向量或该程序的入口点
20004004: 20004049
我填充了未使用的,使它们无限循环
20004008: 2000404f
并扔进另一个只是为了展示
2000403c: 20004055
在这种情况下,VTOR 将设置为 0x2004000,我将从 0x20004004 读取 0x20004049,然后 BX 到该地址。
所以我的 binexec 将被提供地址 0x20004000,我会做这样的事情
ldr r1,[r0]
mov sp,r1
ldr r2,[r0,#4]
bx r2
如果我想在该代码中伪造一个重置。使用 thumb2 的 thumb 方法我假设你可以 ldr sp,[r0],我不会手写 thumb2 所以没有记住那些,并且有不同的 thumb2 扩展集,以及 gas 中的不同语法选项。
现在如果你不打算支持中断,或者出于其他原因(可能在你的闪存中携带一些你想要更好地执行的二进制代码,你将它从闪存复制到 ram 然后在 ram 中使用它)你可以下载到 ram 一个在入口点只有第一条指令的应用程序,没有向量 table:
20004000 <_start>:
20004000: f000 f804 bl 2000400c <notmain>
20004004: e7ff b.n 20004006 <hang>
20004006 <hang>:
20004006: e7fe b.n 20004006 <hang>
20004008 <dummy>:
20004008: 4770 bx lr
...
2000400c <notmain>:
2000400c: b510 push {r4, lr}
2000400e: 2400 movs r4, #0
20004010: 4620 mov r0, r4
20004012: 3401 adds r4, #1
20004014: f7ff fff8 bl 20004008 <dummy>
20004018: 2c64 cmp r4, #100 ; 0x64
2000401a: d1f9 bne.n 20004010 <notmain+0x4>
2000401c: 2000 movs r0, #0
2000401e: bd10 pop {r4, pc}
在这种情况下,需要同意下载的程序是为 0x20004000 构建的,您可以将数据下载到该地址,但是当您想要 运行 时,您可以这样做
.globl binexec
binexec:
bx r0
C
binexec(0x20004000|1);
或
.globl binexec
binexec:
orr r0,#1
bx r0
为了安全起见(r)。
在这两种情况下,如果您希望它们 运行,都需要正确构建二进制文件,两者都必须链接到目标地址,特别是向量 table 方法,因此问题,您能否向我们展示您下载的某个程序中的示例向量 table,即使是前几个字也可能就足够了...