技术笔记20230718 rBoot学习4

技术笔记20230719 rBoot学习4

  继续昨天的学习。

在GPIO引导中擦除SDK配置(rom mode或skip mode)

  如果我们在配置中像这样设置MODE_GPIO_ERASES_SDKCONFIG标志:conf.mode = MODE_GPIO_ROM | MODE_GPIO_ERASES_SDKCONFIG;然后GPIO引导将会擦除存储在最后16KB闪存中的Expressif SDK持久设置。其中包括删除校准常数、删除ssid等。
  注意,MODE_GPIO_ERASES_SDKCONFIG是一个标志位,它必须与MODE_GPIO_ROM一起配置才能生效。

链接用户代码

  每一个rom都需要用适当的链接脚本来链接,指定它在Flash上保存的位置。如果我们只想把一个rom写入到Flash上的多个位置,那么它必须被多次链接来产生一组rom镜像。这与SDK加载程序相同。
  因为Flash布局有无限的可能,所以该项目中没有提供链接脚本示例。相反,该项目将会告诉我们如何去编写链接脚本。
  对于Flash上的每个rom插槽(slot),分别从SDK中获取eagle.app.v6.ld的副本。然后,我们只需要为每个rom修改其中的一行:irom0_0_seg:org = 0x40240000, len = 3C000
  将org地址更改为0x40200000(Flash的基本内存映射位置)+Flash地址+0x10(向后偏移一个数据头的长度)。例如,我们想将第一个rom存放在第三扇区,地址为0x2000的位置,那么org应该改为:0x40200000+0x2000+0x10=0x40202010。如果我们使用默认生成的配置,bootloader将希望在Flash大小的一半的位置+0x2000处找到第二个rom。例如1MB大小Flash上的0x82000。因此irom0_0_seg应该是:0x40200000+0x82000+0x10=0x40282010。由于最大映射1MB大小Flash的限制,如果我们使用更大容量的Flash并且没有启用大Flash支持,则默认配置中的第二个rom仍将被放置在0x82000的位置,而不是真正的Flash大小一半+0x2000。理想情况下,我们还需要调整len在链接时帮助检测过大的部分。但是,更重要的是,我们需要确保rom的整体大小不超过我们在Flash布局中为它分配的空间。
  然后简单地编译和链接,就像我们平时使用SDK引导加载程序进行OTA升级一样。除了使用我们刚刚准备的链接脚本替代SDK提供的链接脚本以外并无不同。注意,在构建空间时将他们创建为’new’类型的rom,用于SDK bootloader v1.2+。或者使用本项目作者的esptool2,使用-boot2选项。注意:rBoot中包含的测试bootloader是使用-boot0编译的,因为他们不包含.irom0.text段,因此链接脚本中的irom0_0_seg的值没有意义。对于我们正常使用来说,需要使用-boot2选项来编译。

irom校验

  SDK的bootloader校验只覆盖加载到ram中的一部分data段与代码段数据。大多数SDK和用户代码保留在Flash中,没有进行校验。这意味着我们可以尝试加载已经损坏的rom,并且由于bootloader检测校验正常,因此不会进行切换备份rom的操作。rBoot通过允许将.irom0.text段包含在校验中来解决这一问题。要启用这一功能,需要取消在rboot.h#define BOOT_IROM_CHKSUM的注释,并使用-iromchksum选项通过esptool2来编译我们的rom。

大容量Flash支持

  只有当我们希望内存映射超过Flash的前1MB时,才需要启用该功能。注意,每次仍然只能映射1MB。如果我们希望拥有多个1MB的rom,或者比1MB更小的空间,请启用此功能。如果我们有一个很大容量的Flash,但是只需要两个512KB的空间,就不需要启用此功能。
  通过取消rBoot.h中对#define BOOT_BIG_FLASH的注释来启动rBoot中的支持。
  考虑到我们对Flash的使用,链接脚本可能因此变得更简单,也有可能变得更复杂。如果我们打算使用多个1MB的空间,则只需要一个链接脚本,并且只需要为OTA更新而链接一次。尽管在执行OTA更新时,将把该rom写到Flash上的不同位置,但是每个1MB的Flash都单独地映射到0x40200000。因此,当任何rom运行时,代码都将出现在内存中的同一位置,而不管它在Flash上的位置。我们的连接器的基地址将会是0x40202010。实际上,除了第一个rom外,所有的rom都可以将0x40200010作为基地址,因为rom不需要为rBoot和配置留出空间。但是这样做只会让项目逻辑变得更加复杂。
  如果我们需要8个512KB的rom,就需要两个链接脚本,一个用于1MB大小Flash的前半部分,另一些用于后半部分。记住,我们实际上是在一个1MB的区域内布局,然后可以多次从Flash上向内存中加载rom。
  现在,最妙的来了。rBoot需要劫持内存映射代码来选择映射Flash上的哪1MB程序到内存中。没有任何API提供给我们,但是我么可以覆盖SDK中的函数。首先,我们需要稍微修改一下SDK库中的libmain.a,如下所示:
xtensa-lx106-elf-objcopy -W Cache_Read_Enable_New libmain.a libmain2.a
  这将产生一个带有‘weakened’特性的Cache_Read_Enable_New函数的libmain版本,然后我们就可以用自己的函数来覆盖它。修改Makefile来链接库main2而不是main
  接下来将appcode目录中的rboot-bigflash.crboot.h添加到我们的项目中——这会将替换后的Cache_Read_Enable_New添加到我们的代码中。
  让gcc正确地覆盖原函数可能有些棘手,原作者也不确定为什么难以实现覆盖。一种选择是在我们的LD_FLAGS中添加-u Cache_Read_Enable_New,并在LD命令中改变对象的顺序,使我们的对object/.a文件位于其他库之前。另一种似乎更容易的方法是在main.c中#include boot-bigflash.c,而不是将其编译到一个独立的object文件中。该项目的作者不能对这两种做法做出解释,但是他建议我们添加一些标志信息在Cache_Read_Enable_New函数中。当我们第一次编译时,确保我们编写的函数被编译进了rom。
  现在,当rBoot启动我们的rom时,通常会执行内存中映射的SDK代码。而SDK中选择如何映射Flash的部分代码又被rBoot取代了(链接在我们的rom中,而不是在rBoot里)。

你可能感兴趣的:(技术笔记,笔记,学习)