野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 2753|回复: 1

KEIL 编译后STM32 Flash的 RO 与 RW 数据堆叠问题

[复制链接]
发表于 2023-5-16 13:16:21 | 显示全部楼层 |阅读模式

正在开发个鼠标,开源的,哈哈哈,有兴趣的可以拿代码去跑跑。Github:https://github.com/Ghost-Girls

MCU:CH32/STM32/APM32

传感器:PMW3360 PMW3389 PAW3395

有上位机,有下位机,目前的话正在正在联调,然后发现了这么一个奇怪的问题。

想要实现上位机发数据之后,MCU将更改的数据写入到FLASH,然后这个数据呢,在开机的时候,就已经指定在Flash的位置,也不难理解这个程序的逻辑。

说明一下问题:

  1. 开发环境:KEIL MKD
  2. MCU:STM32F042F6P6,32K Flash,Paga = 1Kb,Sector = 4Kb.
  3. 我的编译的程序存放在0x08000000 ~ 0x0800 50a8中,0x080050a8~ 0x08006000之间的地址全部填0.
  4. 而我使用attribute特性定义了一个【需要读写】数组到指定的地址,地址为0x08006000. uint8_tattribute(( section(".ARM.__at_0x08006000") )) flash_writeread_test[28] = {}
  5. 我的这个数组的只有28个成员,而且是 unsigned char 类型的,28byte 也才占用到 0x0800601f,而后面的0x08006020就跟着 RW 的数据。问题来了,我这个数据如果要进行读写,就需要将整个Page擦除,如果没有将整个页读出来之后然后再写回去,那么必然会造成程序跑死。
  6. 我能想到的处理办法:
    1. 读出来,改需要修改的部分,然后写回去。 > 虽然读写1Kb不算什么问题,但是,要是碰到了,读写个256Kb的Sector的,那不得卡上天。 >
    2. 直接定义为1024个成员的数组,填充完1Kb的Page。 > 目前我使用的确实就是这个办法,但是,也有不好的地方,就是使用memcpy()的时候,都不能愉快的使用sizeof()了。 >
    3. 或是创建28个成员的数组,然后,再在数组地址的0x0800602c创建996byte个成员的数组占满整个Page。
    4. GCC编译器说是可以改.LD编译的链接文件实现指定地址写入数据。
    5. 既然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的空间:

image.png

> RW的数据的执行地址是固定的 0x2000 0000,可以通过KEIL分配或者进行便宜什么的。 > > 但是,RW的Load base加载地址,好像不能手动分配映射到具体地址?只能推挤在RO后面? > > 也就是下图中的RW INIT 的地址只能记在RO的后面。 > > image.png >

回复

使用道具 举报

发表于 2023-5-17 09:05:38 | 显示全部楼层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-11-23 02:43 , Processed in 0.039202 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表