您可以将有问题的变量隔离在自己的部分。有不止一种方法可以做到这一点。这些工具正常构建并完成所有寻址工作。就像在编译域中使用结构一样,您需要非常小心,并且可能会检查代码,但是您可以构建二进制文件并仅加载它或除其他闪存内容之外的所有内容,然后在那个时候或以后您可以更改 VALUES其他部分中的变量,并将它们构建并隔离到它们自己的负载中。
测试理论
向量.s
.globl _start
_start:
.word 0x20001000
.word reset
.thumb_func
reset:
bl main
b .
.globl dummy
.thumb_func
dummy:
bx lr
so.c
extern volatile unsigned int x;
extern volatile unsigned short y;
extern volatile unsigned char z[7];
extern void dummy ( unsigned int );
int main ( void )
{
dummy(x);
dummy(y);
dummy(z[0]<<z[1]);
return(0);
}
flashvars.c
volatile unsigned int x=1;
volatile unsigned short y=3;
volatile unsigned char z[7]={1,2,3,4,5,6,7};
flash.ld
MEMORY
{
rom0 : ORIGIN = 0x08000000, LENGTH = 0x1000
rom1 : ORIGIN = 0x08002000, LENGTH = 0x1000
ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom0
.vars : { flashvars.o } > rom1
}
构建
arm-none-eabi-as --warn --fatal-warnings -mcpu=cortex-m0 vectors.s -o vectors.o
arm-none-eabi-ld -nostdlib -nostartfiles -T flash.ld vectors.o so.o flashvars.o -o so.elf
arm-none-eabi-objdump -D so.elf > so.list
arm-none-eabi-objcopy -R .vars -O binary so.elf so.bin
检查
Disassembly of section .text:
08000000 <_start>:
8000000: 20001000 andcs r1, r0, r0
8000004: 08000009 stmdaeq r0, {r0, r3}
08000008 <reset>:
8000008: f000 f802 bl 8000010 <main>
800000c: e7fe b.n 800000c <reset+0x4>
0800000e <dummy>:
800000e: 4770 bx lr
08000010 <main>:
8000010: 4b08 ldr r3, [pc, #32] ; (8000034 <main+0x24>)
8000012: b510 push {r4, lr}
8000014: 6818 ldr r0, [r3, #0]
8000016: f7ff fffa bl 800000e <dummy>
800001a: 4b07 ldr r3, [pc, #28] ; (8000038 <main+0x28>)
800001c: 8818 ldrh r0, [r3, #0]
800001e: b280 uxth r0, r0
8000020: f7ff fff5 bl 800000e <dummy>
8000024: 4b05 ldr r3, [pc, #20] ; (800003c <main+0x2c>)
8000026: 7818 ldrb r0, [r3, #0]
8000028: 785b ldrb r3, [r3, #1]
800002a: 4098 lsls r0, r3
800002c: f7ff ffef bl 800000e <dummy>
8000030: 2000 movs r0, #0
8000032: bd10 pop {r4, pc}
8000034: 0800200c stmdaeq r0, {r2, r3, sp}
8000038: 08002008 stmdaeq r0, {r3, sp}
800003c: 08002000 stmdaeq r0, {sp}
Disassembly of section .vars:
08002000 <z>:
8002000: 04030201 streq r0, [r3], #-513 ; 0xfffffdff
8002004: 00070605 andeq r0, r7, r5, lsl #12
08002008 <y>:
8002008: 00000003 andeq r0, r0, r3
0800200c <x>:
800200c: 00000001 andeq r0, r0, r1
看起来不错
hexdump -C so.bin
00000000 00 10 00 20 09 00 00 08 00 f0 02 f8 fe e7 70 47 |... ..........pG|
00000010 08 4b 10 b5 18 68 ff f7 fa ff 07 4b 18 88 80 b2 |.K...h.....K....|
00000020 ff f7 f5 ff 05 4b 18 78 5b 78 98 40 ff f7 ef ff |.....K.x[x.@....|
00000030 00 20 10 bd 0c 20 00 08 08 20 00 08 00 20 00 08 |. ... ... ... ..|
00000040
也是这样。
arm-none-eabi-objcopy -j .vars -O binary so.elf sovars.bin
hexdump -C sovars.bin
00000000 01 02 03 04 05 06 07 00 03 00 00 00 01 00 00 00 |................|
00000010 47 43 43 3a 20 28 47 4e 55 29 20 39 2e 33 2e 30 |GCC: (GNU) 9.3.0|
00000020 00 41 30 00 00 00 61 65 61 62 69 00 01 26 00 00 |.A0...aeabi..&..|
00000030 00 05 43 6f 72 74 65 78 2d 4d 30 00 06 0c 07 4d |..Cortex-M0....M|
00000040 09 01 12 04 14 01 15 01 17 03 18 01 19 01 1a 01 |................|
00000050 1e 02 |..|
00000052
哈,好吧,多做一点。
MEMORY
{
rom0 : ORIGIN = 0x08000000, LENGTH = 0x1000
rom1 : ORIGIN = 0x08002000, LENGTH = 0x1000
ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom0
.vars : { flashvars.o(.data) } > rom1
}
hexdump -C sovars.bin
00000000 01 02 03 04 05 06 07 00 03 00 00 00 01 00 00 00 |................|
00000010
好多了。
我强烈建议不要使用跨编译域的结构,这属于该类别,因为真实数据的构建是分开的,并且在代码构建和数据构建之间,当我这样做时,您可能会得到不同的数据像这样的事情,我在执行过程中采取了保护措施,以便在问题出轨之前(或者在构建时更好)。这不是如果它是何时的情况。实现定义意味着实现定义。
但是考虑到您的问题,这成为一个简单的解决方案。是的,从技术上讲,这些数据是只读的,const 这个或那个,但是 1) volatile 和 const 是否在一起? 2) 你真的想要/需要这样做吗?
它甚至需要是易失性的吗?可能不是,刚开始就敲了。将其切换为 const 工具会将它们放入 .rodata 中。好吧,我的工具确实取决于您如何编写链接器脚本,我认为是 binutils 的版本。
so.c
extern const unsigned int x;
extern const unsigned short y;
extern const unsigned char z[7];
extern void dummy ( unsigned int );
int main ( void )
{
dummy(x);
dummy(y);
dummy(z[0]<<z[1]);
return(0);
}
flashvars.c
const unsigned int x=1;
const unsigned short y=3;
const unsigned char z[7]={1,2,3,4,5,6,7};
flash.ld
MEMORY
{
rom0 : ORIGIN = 0x08000000, LENGTH = 0x1000
rom1 : ORIGIN = 0x08002000, LENGTH = 0x1000
ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom0
.vars : { flashvars.o(.rodata) } > rom1
}
输出
Disassembly of section .text:
08000000 <_start>:
8000000: 20001000 andcs r1, r0, r0
8000004: 08000009 stmdaeq r0, {r0, r3}
08000008 <reset>:
8000008: f000 f802 bl 8000010 <main>
800000c: e7fe b.n 800000c <reset+0x4>
0800000e <dummy>:
800000e: 4770 bx lr
08000010 <main>:
8000010: 4b08 ldr r3, [pc, #32] ; (8000034 <main+0x24>)
8000012: b510 push {r4, lr}
8000014: 6818 ldr r0, [r3, #0]
8000016: f7ff fffa bl 800000e <dummy>
800001a: 4b07 ldr r3, [pc, #28] ; (8000038 <main+0x28>)
800001c: 8818 ldrh r0, [r3, #0]
800001e: f7ff fff6 bl 800000e <dummy>
8000022: 4b06 ldr r3, [pc, #24] ; (800003c <main+0x2c>)
8000024: 7818 ldrb r0, [r3, #0]
8000026: 785b ldrb r3, [r3, #1]
8000028: 4098 lsls r0, r3
800002a: f7ff fff0 bl 800000e <dummy>
800002e: 2000 movs r0, #0
8000030: bd10 pop {r4, pc}
8000032: 46c0 nop ; (mov r8, r8)
8000034: 0800200c stmdaeq r0, {r2, r3, sp}
8000038: 08002008 stmdaeq r0, {r3, sp}
800003c: 08002000 stmdaeq r0, {sp}
Disassembly of section .vars:
08002000 <z>:
8002000: 04030201 streq r0, [r3], #-513 ; 0xfffffdff
8002004: 00070605 andeq r0, r7, r5, lsl #12
08002008 <y>:
8002008: 00000003 andeq r0, r0, r3
0800200c <x>:
800200c: 00000001 andeq r0, r0, r1
hexdump -C so.bin
00000000 00 10 00 20 09 00 00 08 00 f0 02 f8 fe e7 70 47 |... ..........pG|
00000010 08 4b 10 b5 18 68 ff f7 fa ff 07 4b 18 88 ff f7 |.K...h.....K....|
00000020 f6 ff 06 4b 18 78 5b 78 98 40 ff f7 f0 ff 00 20 |...K.x[x.@..... |
00000030 10 bd c0 46 0c 20 00 08 08 20 00 08 00 20 00 08 |...F. ... ... ..|
00000040
hexdump -C sovars.bin
00000000 01 02 03 04 05 06 07 00 03 00 00 00 01 00 00 00 |................|
00000010