当前位置: 首页 > news >正文

技术笔记2023076 rBoot学习7

技术笔记2023076 rBoot学习7

  继续之前的学习。

代码分析:函数find_image()

// prevent this function being placed inline with main
// to keep main's stack size as small as possible
// don't mark as static or it'll be optimised out when
// using the assembler stub

  首先看一下作者给这个函数写下的注释。为了避免此函数内嵌入main函数而占用main函数的栈空间,此函数被关键字NOINLINE修饰。为了避免此函数在使用汇编存根(stub)时被优化,不能使用static来修饰此函数。

	uint8_t  flag;uint32_t  loadAddr;uint32_t  flashsize;int32_t  romToBoot;uint8_t  updateConfig  =  0;uint8_t  buffer[SECTOR_SIZE];rboot_config  *romconf  = (rboot_config*)buffer;rom_header  *header  = (rom_header*)buffer;

  此函数先声明了一些变量,其中的变量buffer数组的大小是SECTOR_SIZE,也就是Flash一个扇区的大小,此处为4KB

#ifdef BOOT_BAUDRATE// soft reset doesn't reset PLL/divider, so leave as configuredif (get_reset_reason() != REASON_SOFT_RESTART) {uart_div_modify( 0, UART_CLK_FREQ / BOOT_BAUDRATE);}
#endif

  此处建议在Makefile中定义变量RBOOT_BAUDRATE,因为ESP-12F模组上电默认的74880波特率太过奇怪。此处我将变量RBOOT_BAUDRATE定义在了变量RBOOT_FW_BASE的后面,并赋值为115200。

#if  defined  BOOT_DELAY_MICROS  &&  BOOT_DELAY_MICROS  >  0// delay to slow boot (help see messages when debugging)ets_delay_us(BOOT_DELAY_MICROS);
#endifets_printf("\r\nrBoot v1.4.2 - richardaburton@gmail.com\r\n");

  此处建议去掉rboot.h//#define BOOT_DELAY_MICROS 2000000的注释去掉,并给宏定义设置一个合适的值,我将其设置为20000(单位为us)。这样做可以做到等待系统稳定再进行后面的操作。如果我们想设置rBoot阶段串口输出的波特率,就需要在这里等待系统串口稳定。

	// read rom headerSPIRead(0, header, sizeof(rom_header));// print and get flash sizeets_printf("Flash Size: ");flag  =  header->flags2  >>  4;if (flag  ==  0) {ets_printf("4 Mbit\r\n");flashsize  =  0x80000;} else  if (flag  ==  1) {ets_printf("2 Mbit\r\n");flashsize  =  0x40000;} else  if (flag  ==  2) {ets_printf("8 Mbit\r\n");flashsize  =  0x100000;} else  if (flag  ==  3  ||  flag  ==  5) {ets_printf("16 Mbit\r\n");
#ifdef BOOT_BIG_FLASHflashsize =  0x200000;
#elseflashsize  =  0x100000; // limit to 8Mbit
#endif} else  if (flag  ==  4  ||  flag  ==  6) {ets_printf("32 Mbit\r\n");
#ifdef BOOT_BIG_FLASHflashsize =  0x400000;
#elseflashsize  =  0x100000; // limit to 8Mbit
#endif} else  if (flag  ==  8) {ets_printf("64 Mbit\r\n");
#ifdef BOOT_BIG_FLASHflashsize =  0x800000;
#elseflashsize  =  0x100000; // limit to 8Mbit
#endif} else  if (flag  ==  9) {ets_printf("128 Mbit\r\n");
#ifdef BOOT_BIG_FLASHflashsize =  0x1000000;
#elseflashsize  =  0x100000; // limit to 8Mbit
#endif} else {ets_printf("unknown\r\n");// assume at least 4mbitflashsize  =  0x80000;}// print spi modeets_printf("Flash Mode: ");if (header->flags1  ==  0) {ets_printf("QIO\r\n");} else  if (header->flags1  ==  1) {ets_printf("QOUT\r\n");} else  if (header->flags1  ==  2) {ets_printf("DIO\r\n");} else  if (header->flags1  ==  3) {ets_printf("DOUT\r\n");} else {ets_printf("unknown\r\n");}// print spi speedets_printf("Flash Speed: ");flag  =  header->flags2  &  0x0f;if (flag  ==  0) ets_printf("40 MHz\r\n");else  if (flag  ==  1) ets_printf("26.7 MHz\r\n");else  if (flag  ==  2) ets_printf("20 MHz\r\n");else  if (flag  ==  0x0f) ets_printf("80 MHz\r\n");else  ets_printf("unknown\r\n");

  这里使用SPI接口将Flash上的头部信息读出并保存在变量header中。其中包含有Flash大小、模式和速度信息。这些信息我们都可以在Makefile中设置,设置好以后会被编译进bin文件中。对于ESP-12F来说,应该这样设置:SPI_SIZE ?= 4MSPIMODE ?= DOUTSPI_SPEED ?= 40

	// read boot configSPIRead(BOOT_CONFIG_SECTOR  *  SECTOR_SIZE, buffer, SECTOR_SIZE);// fresh install or old version?if (romconf->magic  !=  BOOT_CONFIG_MAGIC  ||  romconf->version  !=  BOOT_CONFIG_VERSION) {// create a default config for a standard 2 rom setupets_printf("Writing default boot config.\r\n");ets_memset(romconf, 0x00, sizeof(rboot_config));romconf->magic  =  BOOT_CONFIG_MAGIC;romconf->version  =  BOOT_CONFIG_VERSION;default_config(romconf, flashsize);// write new config sectorSPIEraseSector(BOOT_CONFIG_SECTOR);SPIWrite(BOOT_CONFIG_SECTOR  *  SECTOR_SIZE, buffer, SECTOR_SIZE);}// try rom selected in the config, unless overriden by gpio/temp bootromToBoot  =  romconf->current_rom;

  这里先将Flash第一个扇区的数据读入缓冲区buffer中,而前面romconf指向了buffer。那么此时romconf就读出了rBoot的配置结构体信息。接着,我们比较magicversion是否与之前的宏定义相同。按照rBoot项目的readme中说的,我们在进行boot版本迭代时,可以通过修改version来区分新旧版本。如果此处if为真,则说明Flash中存在新的boot,此时要将Flash的第一个扇区覆盖。之后获取当前需要加载的rom的索引。

	// check valid rom number// gpio/temp boots will have already validated thisif (romconf->current_rom  >=  romconf->count) {// if invalid rom selected try rom 0ets_printf("Invalid rom selected, defaulting to 0.\r\n");romToBoot  =  0;romconf->current_rom  =  0;updateConfig  =  1;}// check rom is validloadAddr  =  check_image(romconf->roms[romToBoot]);// check we have a good romwhile (loadAddr  ==  0) {ets_printf("Rom %d at %x is bad.\r\n", romToBoot, romconf->roms[romToBoot]);// for normal mode try each previous rom// until we find a good one or run outupdateConfig  =  1;romToBoot--;if (romToBoot  <  0) romToBoot  =  romconf->count  -  1;if (romToBoot  ==  romconf->current_rom) {// tried them all and all are bad!ets_printf("No good rom available.\r\n");return  0;}loadAddr  =  check_image(romconf->roms[romToBoot]);
}

  之前拿到了当前需要加载的rom的索引。如果之前拿到的索引是否超出rom总数,则认为此索引是无效的,并默认加载第一个rom。之后再去获取rom的地址。如果获取rom地址失败,则说明此rom已经被损坏了。如果所有rom都已经损坏了,那么只能直接返回0,代表没有找到image了。

	// re-write config, if requiredif (updateConfig) {romconf->current_rom  =  romToBoot;SPIEraseSector(BOOT_CONFIG_SECTOR);SPIWrite(BOOT_CONFIG_SECTOR  *  SECTOR_SIZE, buffer, SECTOR_SIZE);}ets_printf("Booting rom %d at %x, load addr %x.\r\n", romToBoot, romconf->roms[romToBoot], loadAddr);// copy the loader to top of iramets_memcpy((void*)_text_addr, _text_data, _text_len);// return address to load fromreturn  loadAddr;

  获取到rom的地址后,将当前的rom的索引写入配置结构体中。随后将buffer写入boot所在的扇区,覆盖了之前的配置,在下次启动时将使用当前的配置。然后,将_text_data位置,长度为_text_len的数据加载到_text_addr中。最后返回rom的地址,find_image()函数就结束了。

const  uint32_t  entry_addr  =  0x4010fcb4;const  uint32_t  _text_addr  =  0x4010fc00;
const  uint32_t  _text_len  =  192;
const  uint8_t  _text_data[]  = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x10, 0x00, 0x00, 0x1c, 0x4b, 0x00, 0x40, 0x12, 0xc1, 0xc0, 0xc9, 0xe1, 0x8b, 0x31, 0xcd,
0x02, 0x0c, 0x84, 0xe9, 0xc1, 0xf9, 0xb1, 0x09, 0xf1, 0xd9, 0xd1, 0xc2, 0xcc, 0x08, 0x01, 0xf9,
0xff, 0xc0, 0x00, 0x00, 0xf8, 0x31, 0xe2, 0x01, 0x09, 0x86, 0x10, 0x00, 0x2d, 0x0c, 0x3d, 0x01,
0x0c, 0x84, 0x01, 0xf4, 0xff, 0xc0, 0x00, 0x00, 0x8b, 0xcc, 0x78, 0x01, 0xd8, 0x11, 0x46, 0x09,
0x00, 0x21, 0xef, 0xff, 0x5d, 0x0d, 0xd7, 0xb2, 0x02, 0x20, 0x52, 0x20, 0x2d, 0x0c, 0x3d, 0x07,
0x4d, 0x05, 0x59, 0x51, 0x79, 0x41, 0x01, 0xeb, 0xff, 0xc0, 0x00, 0x00, 0x58, 0x51, 0x78, 0x41,
0x5a, 0xcc, 0x5a, 0x77, 0x50, 0xdd, 0xc0, 0x56, 0x6d, 0xfd, 0x0b, 0x6e, 0x60, 0xe0, 0x74, 0x56,
0x9e, 0xfb, 0x08, 0xf1, 0x2d, 0x0f, 0xc8, 0xe1, 0xd8, 0xd1, 0xe8, 0xc1, 0xf8, 0xb1, 0x12, 0xc1,
0x40, 0x0d, 0xf0, 0x00, 0xfd, 0x00, 0x05, 0xf8, 0xff, 0x0d, 0x0f, 0xa0, 0x02, 0x00, 0x0d, 0xf0,
};

  _text_data_text_len_text_addr等变量都可以在build目录下的rboot-hex2a.h中找到。令人意外的是,此文件竟然处于build目录下,这就说明它不是写出来的,而是通过某种方式生成的。

$(RBOOT_BUILD_BASE)/rboot-hex2a.h: $(RBOOT_BUILD_BASE)/rboot-stage2a.elf@echo "E2 $@"$(Q)  $(ESPTOOL2) -quiet -header $<  $@ .text

  通过分析Makefile,我们可以看到,rboot-hex2a.h依赖于rboot-stage2a.elf,并通过esptool2生成的。关于生成rboot-hex2a.h的具体过程,可以参考这篇文章:ESP8266 Bootloader开源代码解析之rboot(一)。

相关文章:

技术笔记2023076 rBoot学习7

技术笔记2023076 rBoot学习7 继续之前的学习。 代码分析&#xff1a;函数find_image() // prevent this function being placed inline with main // to keep mains stack size as small as possible // dont mark as static or itll be optimised out when // using the ass…...

收藏这6个抠图工具,一键抠图不用愁!

在图片编辑工作中&#xff0c;抠图是设计师常用的操作。随着设计工具的不断增加&#xff0c;抠图操作摆脱了过去繁琐的操作步骤&#xff0c;几乎可以一键完成。今天本文将为大家介绍6个好用的抠图工具&#xff0c;一起来看看吧&#xff01; 1、皮卡智能抠图 皮卡智能抠图是一…...

四,Eureka 第四章

2.1.3 增加依赖 <!--添加依赖--><dependencies><!--Eureka Server--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency>&l…...

k8s常见的资源对象使用

目录 一、kubernetes内置资源对象 1.1、kubernetes内置资源对象介绍 1.2、kubernetes资源对象操作命令 二、job与cronjob计划任务 2.1、job计划任务 2.2、cronjob计划任务 三、RC/RS副本控制器 3.1、RC副本控制器 3.2、RS副本控制器 3.3、RS更新pod 四、Deployment副…...

JavaScript 简单实现观察者模式和发布订阅模式

JavaScript 简单实现观察者模式和发布订阅模式 1. 观察者模式1.1 如何理解1.2 代码实现 2. 发布订阅模式2.1 如何理解2.2 代码实现 1. 观察者模式 1.1 如何理解 概念&#xff1a;观察者模式定义对象间的一种一对多的依赖关系&#xff0c;当一个对象的状态发生改变时&#xff…...

高通WLAN框架学习(37)-- TDLS(Tunneled Direct Link Setup)通道直接链路建立

一 TDLS概述 隧道直连设置(TDLS)基于IEEE 802.11z-2010IEEE标准802.11z标准(无线局域网介质访问控制(MAC)和物理层(PHY)规范。 TDLS允许与同一AP关联的设备之间建立直接链路。Wi-Fi Direct允许设备之间直接连接,而不需要AP。Wi-Fi联盟认证可用于IEEE 802.11a和802.11g设备的T…...

高算力AI模组前沿应用:基于ARM架构的SoC阵列式服务器

本期我们带来高算力AI模组前沿应用&#xff0c;基于ARM架构的SoC阵列式服务器相关内容。澎湃算力、创新架构、异构计算&#xff0c;有望成为未来信息化社会的智能算力底座。 ▌性能优势AI驱动&#xff0c;ARM架构服务器加速渗透 一直以来&#xff0c;基于ARM架构的各类处理器…...

老年公寓人员定位管理系统:提升安全与关怀的智能解决方案

老年公寓作为提供安全居住环境和关怀服务的重要场所&#xff0c;面临着人员管理和安全控制的挑战。为了解决这些问题&#xff0c;老年公寓人员定位管理系统应运而生。基于为提供全面的安全管理和个性化关怀服务&#xff0c;华安联大便通过老年公寓人员定位管理系统的技术原理、…...

每日一题之两个字符串的删除操作

题目链接 给定两个单词 word1 和 word2 &#xff0c;返回使得 word1 和 word2 **相同所需的最小步数。 每步 可以删除任意一个字符串中的一个字符。 示例 1&#xff1a; 输入: word1 "sea", word2 "eat" 输出: 2 解释: 第一步将 "sea" 变…...

nacos安装与基础配置

源码 https://github.com/alibaba/nacos https://gitee.com/mirrors/Nacos 编译 git clone https://github.com/alibaba/nacos.git cd nacos/ mvn -Prelease-nacos -Dmaven.test.skiptrue clean install -U ls -al distribution/target/// change the $version to your ac…...

GitHub Copilot:让开发编程变得像说话一样简单

引用&#xff1a; 人类天生就梦想、创造、创新。但今天&#xff0c;我们花太多时间被繁重的工作所消耗&#xff0c;花在消耗我们时间、创造力和精力的任务上。为了重新连接我们工作的灵魂&#xff0c;我们不仅需要一种更好的方式来做同样的事情&#xff0c;更需要一种全新的工…...

并发编程中锁的优化

在 Java 并发编程中&#xff0c;锁是一种常用的同步机制&#xff0c;用于控制对共享资源的访问。使用锁可以确保多个线程之间的互斥访问&#xff0c;避免数据竞争和并发问题。 然而&#xff0c;锁的使用可能会带来一定的性能开销&#xff0c;特别是在高并发场景下。 为了优化…...

笔试题:统计字符串中某字符串在其出现的字符个数

笔试题&#xff1a;统计字符串中某一子串的字符个数&#xff1a;例如字符串aabbcd,有aabb:4,ab:2 哈哈&#xff0c;这道题是小编面试音视频龙头企业的笔试题&#xff0c;以下是我写的代码&#xff1a;如果有错误&#xff0c;希望可以指正!!! 解题思路&#xff1a;利用双指针i和…...

Java NIO Files类读取文件流方式详解

Java NIO Files类读取文件流方式详解 Files类原理概述 java.nio.file.Files是Java标准库提供的一个工具类&#xff0c;用于操作文件和目录。它提供了一系列静态方法&#xff0c;可以用于创建、复制、删除、移动、重命名、读取、写入文件和目录等常见的文件系统操作。同时&…...

Mybatis快速入门,Mybatis的核心配置文件

Mybatis快速入门 一、Mybatis简介1.1Mybatis简化JDBC 二、Mybatis快速入门2.1创建user表&#xff0c;添加数据2.2创建模块&#xff0c;导入坐标2.3编写Mybatis核心配置文件 --> 替换连接信息&#xff0c;解决硬编码问题2.4编写SQL映射文件 --> 统一管理sql语句&#xff0…...

go语言中defer执行顺序

defer 执行顺序和调用顺序相反&#xff0c;类似于栈后进先出。 defer在 return 之后执行&#xff0c;但在函数推出之前&#xff0c;defer可以修改返回值。 func test() int {i : 0defer func() {fmt.Println("defer1")}()defer func() {i 1fmt.Println("defe…...

webpack xxx is not a constructor

环境 webpack5.88.2 vue-router 按需引入 原因 模块循环引用导致 有A B C三个模块 A B模块import C 中导出的class c又依赖B 中Class 的方法 B 又依赖C中的class 此时会导致import 的 C 为undefined...

安装支持vs2019的MFC(解决MSBuild 错误 MSB8041、MSB8042)

安装支持MFC的vs2019&#xff08;解决MSBuild 错误 MSB8041、MSB8042&#xff09; 常用安装选项解决MSBuild 错误 常用安装选项 解决MSBuild 错误 安装上述勾选内容后&#xff0c;即可解决MSBuild 错误 MSB8041 MSB8041&#xff1a;此项目需要 MFC/ATL 库。 https://learn.mic…...

校园电气安全风险分析及预防措施 安科瑞 许敏

摘要:校园属于人员密集场所&#xff0c;若安全风险排查、管控不到位&#xff0c;可能导致安全事故发生&#xff0c;造成严重事故后果。校园电气设备设施引起的电气火灾和触电等事故&#xff0c;是构成校园安全威胁之一&#xff0c;笔者通过对校园发生的电气安全事故案例原因分析…...

机器学习之十大经典算法

机器学习算法是计算机科学和人工智能领域的关键组成部分&#xff0c;它们用于从数据中学习模式并作出预测或做出决策。本文将为大家介绍十大经典机器学习算法&#xff0c;其中包括了线性回归、逻辑回归、支持向量机、朴素贝叶斯、决策树等算法&#xff0c;每种算法都在特定的领…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

shell脚本--常见案例

1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件&#xff1a; 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

selenium学习实战【Python爬虫】

selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

安卓基础(aar)

重新设置java21的环境&#xff0c;临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的&#xff1a; MyApp/ ├── app/ …...

【生成模型】视频生成论文调研

工作清单 上游应用方向&#xff1a;控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...

STM32---外部32.768K晶振(LSE)无法起振问题

晶振是否起振主要就检查两个1、晶振与MCU是否兼容&#xff1b;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容&#xff08;CL&#xff09;与匹配电容&#xff08;CL1、CL2&#xff09;的关系 2. 如何选择 CL1 和 CL…...