正在开发个鼠标,开源的,哈哈哈,有兴趣的可以拿代码去跑跑。Github:https://github.com/Ghost-Girls
MCU:CH32/STM32/APM32
传感器:PMW3360 PMW3389 PAW3395
有上位机,有下位机,目前的话正在正在联调,然后发现了这么一个奇怪的问题。
想要实现上位机发数据之后,MCU将更改的数据写入到FLASH,然后这个数据呢,在开机的时候,就已经指定在Flash的位置,也不难理解这个程序的逻辑。
说明一下问题:
- 开发环境:KEIL MKD
- MCU:STM32F042F6P6,32K Flash,Paga = 1Kb,Sector = 4Kb.
- 我的编译的程序存放在0x08000000 ~ 0x0800 50a8中,0x080050a8~ 0x08006000之间的地址全部填0.
- 而我使用attribute特性定义了一个【需要读写】数组到指定的地址,地址为0x08006000.
uint8_tattribute(( section(".ARM.__at_0x08006000") )) flash_writeread_test[28] = {}
- 我的这个数组的只有28个成员,而且是 unsigned char 类型的,28byte 也才占用到 0x0800601f,而后面的0x08006020就跟着 RW 的数据。问题来了,我这个数据如果要进行读写,就需要将整个Page擦除,如果没有将整个页读出来之后然后再写回去,那么必然会造成程序跑死。
- 我能想到的处理办法:
- 读出来,改需要修改的部分,然后写回去。
> 虽然读写1Kb不算什么问题,但是,要是碰到了,读写个256Kb的Sector的,那不得卡上天。
>
- 直接定义为1024个成员的数组,填充完1Kb的Page。
> 目前我使用的确实就是这个办法,但是,也有不好的地方,就是使用memcpy()的时候,都不能愉快的使用sizeof()了。
>
- 或是创建28个成员的数组,然后,再在数组地址的0x0800602c创建996byte个成员的数组占满整个Page。
- GCC编译器说是可以改.LD编译的链接文件实现指定地址写入数据。
- 既然GCC编译器可以修改编译链接问文件,那么KIEL应该也有类似的操作吧?
比如,能否通过修改分散加载文件(.sct)实现这个操作?(我个人认为是可以的,但是我不知道怎么实现。)https://www.stmcu.org.cn/module/forum/forum.php?mod=viewthread&tid=619873
下面这个代码是STMM32社区那边找到的,但据说没法实现功能。后面提问的,只能勾选了IROM2才能分配空间。
LR_IROM1 0x08003000 0x0003CFFC { ; load region size_region
ER_IROM1 0x08003000 0x0003CFFC { ; load address = execution address
*.o (RESET, +First)
*(InRoot$Sections)
.ANY (+RO)
}
API_IROM1 0x0803FFFC 0x00000004 {
*.o(apiSection)
}
RW_IRAM1 0x200000BC 0x00007F44 { ; RW data
.ANY (+RW +ZI)
}
}
下面是编译后,数据的空间占用情况:
Memory Map of the image
Image Entry point : 0x080000c1
Load Region LR_IROM1 (Base: 0x08000000, Size: 0x00006618, Max: 0x00008000, ABSOLUTE, COMPRESSED[0x00006530])
Execution Region ER_IROM1 (Exec base: 0x08000000, Load base: 0x08000000, Size: 0x00006400, Max: 0x00008000, ABSOLUTE)
省略掉上面的一串代码
0x08003e54 0x08003e54 0x0000001a Code RO 91 .text.spi_write main.o
0x08003e6e 0x08003e6e 0x000001f6 Code RO 1491 .text_divfast c_p.l(aeabi_sdivfast.o)
0x08004064 0x08004064 0x00000005 Data RO 127 .rodata.btn_keys main.o
0x08004069 0x08004069 0x00000ffe Data RO 109 .rodata.srom main.o
0x08005067 0x08005067 0x00000001 PAD
0x08005068 0x08005068 0x00000040 Data RO 1674 Region$$Table anon$$obj.o
0x080050a8 0x080050a8 0x00000f58 PAD
0x08006000 0x08006000 0x00000400 Data RW 110 .ARM.__at_0x08006000 main.o
Execution Region RW_IRAM1 (Exec base: 0x20000000, Load base: 0x08006400, Size: 0x000010c0, Max: 0x00001800, ABSOLUTE, COMPRESSED[0x00000130])
还有个问题,就是它这个填0太过于占空间了,硬生生的多了20K的空间:
> RW的数据的执行地址是固定的 0x2000 0000,可以通过KEIL分配或者进行便宜什么的。
>
> 但是,RW的Load base加载地址,好像不能手动分配映射到具体地址?只能推挤在RO后面?
>
> 也就是下图中的RW INIT 的地址只能记在RO的后面。
>
>
> |