FLASH不够用——非零等待FLASH搬到RAM运行

发布时间 2023-04-20 16:41:34作者: WCH_CH32

本文主要实现将FLASH中的代码搬运到RAM运行

我们的CH32V2/3系列MCU有几十K,几百K的非零等待FLASH,遇到FLASH不够用的情况实在可惜。主要以V307举例,针对零等待FLASH不够用的情况。

典型应用:

1.IAP占用了几K空间,搬到RAM后,可以让IAP所占零等待FLASH大幅降低,接近忽略

2.切换功能的代码,不会同时使用的分块的代码,切换的时间几十ms级别

实现思路:

1.将要搬到RAM里的代码在编译阶段用RAM地址编译,原因是code运行的时候,地址是绝对地址

LD文件中修改FLASH和RAM起始地址以及长度

此处需要注意的是RAM的起始地址+长度不能超过实际RAM的大小,否则会进Hardfault,因为堆栈是从RAM最后面往前的

这一步的必要条件是,编译的代码需要能在RAM里放的下,否则的话就需要在零等待的FLASH里放一部分

然后生成bin文件,之后放到非零等待的地址上烧到MCU里

2.编写 从FLASH搬到RAM的代码

这部分代码是放在零等待FLASH的,此处仅实现简单的搬运,没有条件判断等操作,所以选择直接修改启动文件里的handle_reset,不涉及C的部分,LD不需要改

handle_reset:
.option push
.option norelax
  la gp, __global_pointer$
.option pop
1:
  la sp, _eusrstack

2:
  /* 把flash里的代码搬到RAM,这里只搬code,跳转到code后,code的代码会自己搬data*/
  la a0, 0x08020000/*flash起始地址128K*/
  la a1, 0x20000000/*RAM起始地址0K*/
  la a2, 0x20005000/*RAM结束地址20K*/
  bgeu a1, a2, 2f
1:
  lw t0, (a0)
  sw t0, (a1)
  addi a0, a0, 4
  addi a1, a1, 4
  bltu a1, a2, 1b

2:
  li t0, 0x1f
  csrw 0xbc0, t0

 

  la a0,0x20000000
  jr 0(a0)/* 跳转到RAM中的起始地址 */

3.烧录

第1步要运行的主体的bin烧录地址是非零等待区0x20000第2步搬运代码的地址是正常的零等待区地址0x0。合并后一起烧录,即可实现。

总结:

本文实现了最简单的从flash搬运到ram运行,汇编生成的代码大概是120字节远远小于IAP的几K字节。

如果不用汇编搬运,进入C的世界也是可以的,还可以进行复杂的判断,选择不同功能代码搬运,不过这里要注意的是:进入了C的世界,堆栈会起作用,所以搬运的时候要注意预留搬运时的堆栈的RAM开销。C的世界里跳转  和  IAP跳APP一样,需要用软件中断。

这里的主要思想来源于堆栈的动态内存,利用代码可以在RAM运行,一样可以有动态的代码空间。

其它注意事项:

1.如果开启了读保护,FLASH前4K自动写保护,所以在用IAP的时候要注意,即使有空间了,也要注意前4KFLASH在读保护使能的情况下是无法擦写的。