目录

概述

1 MCUboot的功能

1.1 代码包结构

1.2 限制

2 MCUboot Image

2.1 Image格式

2.2 Flash Map

2.3 Image 槽

2.4 使用scratch交换

 2.5 Image 尾部数据结构

3 交换区

3.1 单交换区

 3.2 Multiple Image boot 

3.3 Image交换

4  交换状态(swap status)

 5 复位覆盖


概述

本文主要介绍MCUboot的实现原理和Image的结构,主要包括MCUboot的Image的格式,交换区,Resetrecovery等概念,还介绍了使用Image进行代码更新的步骤。

1 MCUboot的功能

1.1 代码包结构

MCUboot包含两个代码包:

1)The bootutil library (boot/bootutil)

2)The boot application (each port has its own at boot/)

bootutil 库执行了引导加载程序的大部分功能。特别缺少的是实际跳转到主映像的最后一步。这最后一步则由引导应用程序来实现。以这种方式分离引导加载程序的功能是为了能够对引导加载程序进行单元测试。库可以进行单元测试,但应用程序不行。因此,只要有可能,功能就会委托给 bootutil 库。 

1.2 限制

当前,引导加载程序仅支持具有以下特征的映像:

1) Built to run from flash.

2)   Built to run from a fixed location (i.e., not position-independent).

2 MCUboot Image

2.1 Image格式

以下定义描述image格式:

#define IMAGE_MAGIC                 0x96f3b83d#define IMAGE_HEADER_SIZE           32struct image_version {uint8_t iv_major;uint8_t iv_minor;uint16_t iv_revision;uint32_t iv_build_num;
};/** Image header.  All fields are in little endian byte order. */
struct image_header {uint32_t ih_magic;uint32_t ih_load_addr;uint16_t ih_hdr_size;           /* Size of image header (bytes). */uint16_t ih_protect_tlv_size;   /* Size of protected TLV area (bytes). */uint32_t ih_img_size;           /* Does not include header. */uint32_t ih_flags;              /* IMAGE_F_[...]. */struct image_version ih_ver;uint32_t _pad1;
};#define IMAGE_TLV_INFO_MAGIC        0x6907
#define IMAGE_TLV_PROT_INFO_MAGIC   0x6908/** Image TLV header.  All fields in little endian. */
struct image_tlv_info {uint16_t it_magic;uint16_t it_tlv_tot;  /* size of TLV area (including tlv_info header) */
};/** Image trailer TLV format. All fields in little endian. */
struct image_tlv {uint8_t  it_type;   /* IMAGE_TLV_[...]. */uint8_t  _pad;uint16_t it_len;    /* Data length (not including TLV header). */
};/** Image header flags.*/
#define IMAGE_F_PIC                      0x00000001 /* Not supported. */
#define IMAGE_F_ENCRYPTED_AES128         0x00000004 /* Encrypted using AES128. */
#define IMAGE_F_ENCRYPTED_AES256         0x00000008 /* Encrypted using AES256. */
#define IMAGE_F_NON_BOOTABLE             0x00000010 /* Split image app. */
#define IMAGE_F_RAM_LOAD                 0x00000020/** Image trailer TLV types.*/
#define IMAGE_TLV_KEYHASH           0x01   /* hash of the public key */
#define IMAGE_TLV_SHA256            0x10   /* SHA256 of image hdr and body */
#define IMAGE_TLV_RSA2048_PSS       0x20   /* RSA2048 of hash output */
#define IMAGE_TLV_ECDSA224          0x21   /* ECDSA of hash output - Not supported anymore */
#define IMAGE_TLV_ECDSA_SIG         0x22   /* ECDSA of hash output */
#define IMAGE_TLV_RSA3072_PSS       0x23   /* RSA3072 of hash output */
#define IMAGE_TLV_ED25519           0x24   /* ED25519 of hash output */
#define IMAGE_TLV_SIG_PURE          0x25   /* If true then any signature found has beencalculated over image directly. */
#define IMAGE_TLV_ENC_RSA2048       0x30   /* Key encrypted with RSA-OAEP-2048 */
#define IMAGE_TLV_ENC_KW            0x31   /* Key encrypted with AES-KW-128 or256 */
#define IMAGE_TLV_ENC_EC256         0x32   /* Key encrypted with ECIES-P256 */
#define IMAGE_TLV_ENC_X25519        0x33   /* Key encrypted with ECIES-X25519 */
#define IMAGE_TLV_DEPENDENCY        0x40   /* Image depends on other image */
#define IMAGE_TLV_SEC_CNT           0x50   /* security counter */

ih_hdr_size: 

字段表示头部的长度,因此表示Image本身的偏移量。这个字段提供了向后兼容性,以防更改Image头的格式。


ih_protect_tlv_size:   

字段表示TLV保护区域的长度。如果存在受保护的TLV,则必须存在一个magic等于IMAGE_TLV_PROT_INFO_MAGIC的TLV信息头,并且受保护的TLV(加上信息头本身)必须包含在哈希计算中。否则,哈希值只计算Image标题和Image本身。

在此例中,ih_protect_tlv_size字段的值为0。

2.2 Flash Map

设备的闪存根据其闪存映射进行分区。在高层次上,flash映射将数字id映射到flash区域。闪存区是磁盘的一个区域,具有以下属性:

1) 一个区域可以完全擦除而不影响任何其他区域

2) 对一个区域的写入不限制对其他区域的写入。

引导加载程序使用以下flash区域id:

/* Independent from multiple image boot */
#define FLASH_AREA_BOOTLOADER         0
#define FLASH_AREA_IMAGE_SCRATCH      3
/* If the bootloader is working with the first image */
#define FLASH_AREA_IMAGE_PRIMARY      1
#define FLASH_AREA_IMAGE_SECONDARY    2
/* If the bootloader is working with the second image */
#define FLASH_AREA_IMAGE_PRIMARY      5
#define FLASH_AREA_IMAGE_SECONDARY    6

引导加载程序区域包含引导加载程序映像本身。其他方面将在后面的部分中描述。闪存可以包含多个可执行映像,因此主区域和辅助区域的闪存区域id是根据活动映像(引导加载程序当前正在其上工作)的数量映射的。

2.3 Image的槽

闪存的一部分可划分为多个Image区域,每个Image区域包含两个Image插槽:

1)主插槽

2)辅助插槽

正常情况下,引导加载程序只会从主插槽运行Image,因此必须构建映像,使它们能够从flash中的固定位置运行(这方面的例外是direct-xip和ram-load升级模式)。如果引导加载程序需要运行驻留在辅助插槽中的映像,那么它必须在这样做之前将其内容复制到主插槽中,要么交换两个映像,要么覆盖主插槽的内容。

2.4 使用scratch交换

当使用使用scratch交换算法时,除了Image区域的插槽之外,引导加载程序还需要scratch区域来允许可靠的Image交换。scratch区必须具有足够的大小,至少可以存储将要交换的最大扇区。许多设备都有同样大小的小扇区,例如4K,而其他设备则有可变大小的扇区,其中最大的扇区可能是128K或256K,因此scratch必须足够大才能存储这些扇区。

scratch只在交换固件时使用,这意味着只在进行升级时使用。考虑到这一点,使用更大尺寸的划痕的主要原因是闪存磨损将更均匀地分布,因为单个扇区的写入次数是使用两个扇区的两倍,例如。为您的用例评估划痕的理想大小,以下参数是相关的:

  • the ratio of image size / scratch size
  • the number of erase cycles supported by the flash hardware

 2.5 Image 尾部数据结构

为了使引导加载程序能够确定当前状态以及在当前引导操作期间应该采取什么操作,它使用存储在映像闪存区域中的元数据。在交换时,其中一些元数据被临时复制到刮痕区或从scratch区复制出来。

这个元数据位于Inage区域的末尾,称为Image trailer。其具体结构如下:

 0                   1                   2                   30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+~                                                               ~~    Swap status (BOOT_MAX_IMG_SECTORS * min-write-size * 3)    ~~                                                               ~+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                 Encryption key 0 (16 octets) [*]              ||                                                               |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                    0xff padding as needed                     ||  (BOOT_MAX_ALIGN minus 16 octets from Encryption key 0) [*]   |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                 Encryption key 1 (16 octets) [*]              ||                                                               |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                    0xff padding as needed                     ||  (BOOT_MAX_ALIGN minus 16 octets from Encryption key 1) [*]   |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                      Swap size (4 octets)                     |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                    0xff padding as needed                     ||        (BOOT_MAX_ALIGN minus 4 octets from Swap size)         |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|   Swap info   |  0xff padding (BOOT_MAX_ALIGN minus 1 octet)  |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|   Copy done   |  0xff padding (BOOT_MAX_ALIGN minus 1 octet)  |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|   Image OK    |  0xff padding (BOOT_MAX_ALIGN minus 1 octet)  |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                    0xff padding as needed                     ||         (BOOT_MAX_ALIGN minus 16 octets from MAGIC)           |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|                       MAGIC (16 octets)                       ||                                                               |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

 1)Swap info

交换信息:单个字节,编码以下信息:
交换类型:0 ~ 3位存储。指示正在进行的交换操作的类型。当MCUboot恢复被中断的交换时,它使用这个字段来确定要执行的操作类型。该字段包含下表中下列值之一。


图像号:存储在4-7位。它在单映像引导时总是0值。在多映像引导的情况下,它指示中断发生时交换了哪个映像。在所有图像交换操作期间使用相同的划痕区域。因此使用该字段

NameValue
BOOT_SWAP_TYPE_TEST2
BOOT_SWAP_TYPE_PERM3
BOOT_SWAP_TYPE_REVERT4

BOOT_SWAP_TYPE_TEST是嵌入式系统中固件升级机制的一部分,通常用于测试固件镜像的交换功能。以下是其主要功能的详细介绍:


BOOT_SWAP_TYPE_TEST是一种启动交换类型,主要用于:

  • 测试新固件镜像的可靠性

  • 验证固件升级流程

  • 在不永久提交新固件的情况下进行测试


典型工作流程

  1. 标记状态:系统将当前固件标记为"测试"状态

  2. 交换镜像:引导加载程序(bootloader)会加载新固件进行测试

  3. 验证阶段:新固件运行一段时间进行验证

  4. 结果处理

    • 如果测试成功,系统可能将状态改为永久

    • 如果测试失败,系统会回退到旧固件


使用场景

  • 安全关键的固件升级前验证

  • A/B分区系统中的测试启动

  • 开发阶段的固件验证

  • 现场设备的安全升级测试


优势

  1. 安全性:避免直接升级可能导致设备变砖

  2. 可靠性:确保新固件稳定后再永久应用

  3. 灵活性:开发人员可以测试不同版本的固件


实现细节

具体实现可能因系统而异,但通常涉及:

  • 引导加载程序中的特殊处理逻辑

  • 非易失性存储器中的状态标志

  • 镜像完整性检查机制

  • 超时或条件触发的回退机制

2)拷贝完成:单字节表示该槽中的映像是否完成(0x01=done;0 xff =没有完成)。

3)image OK:一个单字节,表示这个槽中的映像是否已被用户确认为好的(0x01=confirmed;0 xff =没有证实)。

4)MAGIC:标识Image trailer布局的16字节字段。它可以根据映像支持的最大写对齐(BOOT_MAX_ALIGN)假设不同的值,由以下结构定义:

union boot_img_magic_t
{struct {uint16_t align;uint8_t magic[14];};uint8_t val[16];
};

如果BOOT_MAX_ALIGN是8字节,那么MAGIC包含以下16字节:

const union boot_img_magic_t boot_img_magic = {.val = {0x77, 0xc2, 0x95, 0xf3,0x60, 0xd2, 0xef, 0x7f,0x35, 0x52, 0x50, 0x0f,0x2c, 0xb6, 0x79, 0x80}
};

如果BOOT_MAX_ALIGN被定义为任何不同于8的值,那么支持的最大写对齐值将在MAGIC字段中编码,后跟一个固定的14字节模式:

const union boot_img_magic_t boot_img_magic = {.align = BOOT_MAX_ALIGN,.magic = {0x2d, 0xe1,0x5d, 0x29, 0x41, 0x0b,0x8d, 0x77, 0x67, 0x9c,0x11, 0x0f, 0x1f, 0x8a}
};

3 交换区

3.1 单交换区

对于新的交换,MCUboot必须检查一个字段集合,以确定执行哪个交换操作。
Image trailers记录是围绕flash硬件施加的限制构建的。因此,它们没有一个非常直观的设计,并且很难通过查看图像预告片来了解设备的状态。最好通过一组表将所有可能的跟踪状态映射到上面描述的交换类型。这些表格转载如下。

    State I (swap using offset only)| primary slot | secondary slot |-----------------+--------------+----------------|magic | Any          | Good           |image-ok | Any          | Unset          |copy-done | Any          | Set            |-----------------+--------------+----------------'result: BOOT_SWAP_TYPE_REVERT                   |-------------------------------------------------'State II| primary slot | secondary slot |-----------------+--------------+----------------|magic | Any          | Good           |image-ok | Any          | Unset          |copy-done | Any          | Any            |-----------------+--------------+----------------'result: BOOT_SWAP_TYPE_TEST                     |-------------------------------------------------'State III| primary slot | secondary slot |-----------------+--------------+----------------|magic | Any          | Good           |image-ok | Any          | 0x01           |copy-done | Any          | Any            |-----------------+--------------+----------------'result: BOOT_SWAP_TYPE_PERM                     |-------------------------------------------------'State IV| primary slot | secondary slot |-----------------+--------------+----------------|magic | Good         | Any            |image-ok | 0xff         | Any            |copy-done | 0x01         | Any            |-----------------+--------------+----------------'result: BOOT_SWAP_TYPE_REVERT                   |-------------------------------------------------'

上述三种状态中的任何一种都会导致MCUboot尝试交换Image。否则,MCUboot不会尝试交换映像,从而导致其他三种交换类型之一,如状态IV所示。

    State V| primary slot | secondary slot |-----------------+--------------+----------------|magic | Any          | Any            |image-ok | Any          | Any            |copy-done | Any          | Any            |-----------------+--------------+----------------'result: BOOT_SWAP_TYPE_NONE,                    |BOOT_SWAP_TYPE_FAIL, or                 |BOOT_SWAP_TYPE_PANIC                    |-------------------------------------------------'

 3.2 Multiple Image boot 

当闪存包含多个可执行映像时,引导加载程序的操作稍微复杂一些,但与前面描述的使用一个映像的过程类似。每个图像都可以独立更新,因此闪存进一步分区,为每个图像安排两个插槽。

+--------------------+
| MCUboot            |
+--------------------+~~~~~            <- memory might be not contiguous
+--------------------+
| Image 0            |
| primary   slot     |
+--------------------+
| Image 0            |
| secondary slot     |
+--------------------+~~~~~            <- memory might be not contiguous
+--------------------+
| Image N            |
| primary   slot     |
+--------------------+
| Image N            |
| secondary slot     |
+--------------------+
| Scratch            |
+--------------------+

3.3 Image交换

 引导程序交换两个映像槽的内容有两个原因:
1) 用户发出了“设置挂起”操作;次要插槽中的映像应该运行一次(状态I)或重复运行一次(状态II),这取决于是否指定了永久交换。
2) 测试映像在未确认的情况下重启;引导加载程序应该恢复到当前在辅助插槽中的原始映像(状态III)。

 如果映像显示应该运行辅助插槽中的映像,则引导加载程序需要将其复制到主插槽。当前在主插槽中的映像也需要保留在flash中,以便以后使用。此外,如果引导加载程序在交换操作中重置,则两个映像都需要是可恢复的。按照以下步骤交换两个镜像:

Step-1: 确定两个插槽是否足够兼容以交换它们的映像。为了兼容,两者都必须只有能够容纳划痕区域的扇区,如果其中一个扇区比另一个扇区大,它必须能够完全容纳来自另一个插槽的某些四舍五入扇区。在接下来的步骤中,我们将使用术语“区域”来表示复制/擦除的数据总量,因为这可以是任何数量的扇区,这取决于有多少扇区能够适合某些交换操作。

Step-2: 按降序迭代区域索引列表(即从最大索引开始);仅复制预定为图像一部分的区域;当前元素= "index"。

a.擦除划痕区域。
b.将secondary_slot[index]拷贝到划痕区。
如果这是槽中的最后一个区域,则刮擦区域具有初始化以存储初始状态的临时状态区域,因为必须擦除主槽的最后一个区域。在这种情况下,只复制计算为图像的数据。
否则,如果这是交换的第一个区域,但不是槽中的最后一个区域,则初始化主槽中的状态区域并复制完整的区域内容。否则,复制整个区域的内容。

c.写入更新后的swap状态(i)。
d.擦除secondary_slot[index]

e.将primary_slot[index]拷贝到secondary_slot[index]。
如果这不是槽中的最后一个区域,则擦除辅助槽中的预告片,以始终使用主槽中的预告片。
f.写入更新后的swap状态(ii)。
g.擦除primary_slot[index]。
h.将刮痕区复制到primary_slot[index]中,根据之前在步骤b中复制的数量。如果这是槽中的最后一个区域,则从头读取状态(它临时存储在那里),然后在主槽中重新写入状态

Step-3:  将交换过程的完成持久化到主插槽映像 trailer。

注意点: 

步骤2-f中的附加警告是必要的,以便用户可以在稍后的时间写入辅助插槽映像预告片。在不写入映像预告片的情况下,用户可以在二级插槽中测试映像(即切换到状态I)。

步骤3的细节取决于是否正在测试映像、永久使用映像、恢复映像或在请求交换时发生了辅助插槽的验证失败:

* test:o Write primary_slot.copy_done = 1(swap caused the following values to be written:primary_slot.magic = BOOT_MAGICsecondary_slot.magic = UNSETprimary_slot.image_ok = Unset)* permanent:o Write primary_slot.copy_done = 1(swap caused the following values to be written:primary_slot.magic = BOOT_MAGICsecondary_slot.magic = UNSETprimary_slot.image_ok = 0x01)* revert:o Write primary_slot.copy_done = 1o Write primary_slot.image_ok = 1(swap caused the following values to be written:primary_slot.magic = BOOT_MAGIC)* failure to validate the secondary slot:o Write primary_slot.image_ok = 1

4  交换状态(swap status)

交换状态区域允许引导加载程序在映像交换操作中间重新启动时进行恢复。交换状态区域由一系列单字节记录组成。这些记录是独立写入的,因此必须根据flash硬件施加的最小写入大小进行填充。交换状态区域的结构如下所示。在该图中,为了简单起见,假设最小写大小为1,该图显示了每个扇区的3种状态,适用于使用scratch交换和使用move交换,但是在使用offset交换模式中只有3种状态。

     0                   1                   2                   30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|sec127,state 0 |sec127,state 1 |sec127,state 2 |sec126,state 0 |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|sec126,state 1 |sec126,state 2 |sec125,state 0 |sec125,state 1 |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|sec125,state 2 |                                               |+-+-+-+-+-+-+-+-+                                               +~                                                               ~~               [Records for indices 124 through 1              ~~                                                               ~~               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+~               |sec000,state 0 |sec000,state 1 |sec000,state 2 |+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

 以上可能一点帮助都没有;这里有一段英文描述。
每个映像槽被划分成一系列的闪存扇区。如果我们枚举单个槽中的扇区,从0开始,我们将得到一个扇区索引列表。由于有两个映像槽,每个扇区索引将对应一对扇区。例如,扇区索引0分别对应主槽位的第一个扇区和从槽位的第一个扇区。最后,反转索引列表,使列表以索引BOOT_MAX_IMG_SECTORS - 1开始,以0结束。

在交换操作期间,每个扇区索引通过四个不同的状态转换:

0. primary slot: image 0,   secondary slot: image 1,   scratch: N/A
1. primary slot: image 0,   secondary slot: N/A,       scratch: image 1 (1->s, erase 1)
2. primary slot: N/A,       secondary slot: image 0,   scratch: image 1 (0->1, erase 0)
3. primary slot: image 1,   secondary slot: image 0,   scratch: N/A     (s->0)

 每次扇区索引转换到新状态时,引导加载程序都会向交换状态区域写入一条记录。逻辑上,引导加载程序只需要每个扇区索引一个记录来跟踪当前的交换状态。然而,由于flash硬件的限制,当索引状态改变时,不能重写记录。为了解决这个问题,引导加载程序为每个扇区索引使用三条记录,而不是一条。

每个部门-状态对表示为一组三条记录。记录值映射到上述四种状态如下所示:

            | rec0 | rec1 | rec2--------+------+------+------state 0 | 0xff | 0xff | 0xffstate 1 | 0x01 | 0xff | 0xffstate 2 | 0x01 | 0x02 | 0xffstate 3 | 0x01 | 0x02 | 0x03

 5 复位覆盖

如果引导加载程序在交换操作中重置,则两个Image可能在flash中不连续。Bootutil通过使用Image起始数据来确定Image部分如何在flash中分布来从这种情况中恢复。

第一步是确定相关交换状态区域的位置。由于该区域嵌入到映像槽中,因此在交换操作期间,它在闪存中的位置会发生变化。下面的一组表将图像预告片内容映射到交换状态位置。在这些表中,“source”字段表示交换状态区域的位置。在多IMage启动的情况下,总是成对地检查图像的主区和单划痕区。如果在划痕区域找到交换状态,那么它可能不属于当前IMage。交换状态的swap_info字段存储相应的信息.

              | primary slot | scratch      |----------+--------------+--------------|magic | Good         | Any          |copy-done | 0x01         | N/A          |----------+--------------+--------------'source: none                            |----------------------------------------'| primary slot | scratch      |----------+--------------+--------------|magic | Good         | Any          |copy-done | 0xff         | N/A          |----------+--------------+--------------'source: primary slot                    |----------------------------------------'| primary slot | scratch      |----------+--------------+--------------|magic | Any          | Good         |copy-done | Any          | N/A          |----------+--------------+--------------'source: scratch                         |----------------------------------------'| primary slot | scratch      |----------+--------------+--------------|magic | Unset        | Any          |copy-done | 0xff         | N/A          |----------+--------------+--------------|source: primary slot                    |----------------------------------------+------------------------------+This represents one of two cases:                                      |o No swaps ever (no status to read, so no harm in checking).           |o Mid-revert; status in the primary slot.                              |For this reason we assume the primary slot as source, to trigger a     |check of the status area and find out if there was swapping under way. |-----------------------------------------------------------------------'

如果交换状态区域表明映像不是连续的,那么MCUboot通过读取活动映像尾片中的交换信息字段并从0-3位提取交换类型来确定被中断的交换操作的类型,然后恢复操作。换句话说,它应用前一节中定义的过程,将映像1移动到主插槽中,将映像0移动到辅助插槽中。如果引导状态表明在刮擦区域中存在映像部分,则从区域交换过程中的步骤e或步骤h开始将该部分复制到正确的位置。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/91968.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/91968.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/91968.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv8目标检测项目代码详解与习题

YOLOv8目标检测项目代码详解与习题一、项目代码详解该代码是基于 YOLOv8 和 OpenCV 实现的图像目标检测项目&#xff0c;核心功能是加载预训练的 YOLOv8 模型&#xff0c;对指定图像进行目标检测&#xff0c;然后可视化检测结果并保存或显示。以下是逐行解析&#xff1a;# -*- …

gradle关于dependency-management的使用

1、相关文档Spring官方文档&#xff1a;https://docs.spring.io/dependency-management-plugin/docs/current-SNAPSHOT/reference/html/#introduction仓库版本查看&#xff1a;https://mvnrepository.com/artifact/io.spring.gradle/dependency-management-plugin/1.0.15.RELEA…

Java SpringBoot 对接FreeSwitch

1.增加Maven依赖<dependency><groupId>org.freeswitch.esl.client</groupId><artifactId>org.freeswitch.esl.client</artifactId><version>0.9.2</version></dependency><!-- XML-RPC --><dependency><groupI…

限流算法与实现

费曼学习法学习限流算法为什么要限流mysql插入600次/秒超过这个阈值&#xff0c;要么使用mysql集群、要么限流&#xff0c;防止宕机有哪些算法固定窗口就是个计数器&#xff0c;一秒内超过阈值&#xff0c;不允许访问缺点&#xff1a;不均匀&#xff0c;跨越临界点的一秒内&…

Android本地浏览PDF(Android PDF.js 简要学习手册)

环境 Min SDK: 21 依赖&#xff1a; implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1" implementation "androidx.webkit:webkit:1.12.0"权限&#xff1a; <uses-permission android:name"android.permission.INTERNE…

CVE-2022-41128

概述CVE-2022-41128 是 Microsoft Internet Explorer&#xff08;IE&#xff09;浏览器中 JavaScript 引擎&#xff08;JScript/Chakra&#xff09;的一个 0day 漏洞&#xff08;披露时无官方补丁&#xff09;&#xff0c;属于内存破坏类漏洞&#xff0c;可被用于远程代码执行&…

基于LSTM的时间序列到时间序列的回归模拟

获取项目源码点击文末名片项目背景与目标 本项目旨在开发一种基于长短期记忆网络&#xff08;LSTM&#xff09;的模型&#xff0c;用于时间序列到时间序列的回归模拟任务。通过处理多组不同来源的时间序列数据&#xff0c;本模型的目标是从给定的输入序列中预测相应的输出序列。…

Linux基础命令详解:从入门到精通

本文整理了Linux系统中最常用的基础命令&#xff0c;每个命令都配有详细说明和具体示例&#xff0c;帮助你快速掌握Linux操作技巧。文章中用的终端是XShell,系统是Centos&#x1f4c1; 1. ls - 列出目录&#xff08;文件夹&#xff09;内容 功能&#xff1a;显示当前目录下的文…

正点原子stm32F407学习笔记10——输入捕获实验

一、输入捕获简介 输入捕获模式可以用来测量脉冲宽度或者测量频率。我们以测量脉宽为例&#xff0c;用一个简图来 说明输入捕获的原理&#xff0c;如图所示&#xff1a;假定定时器工作在向上计数模式&#xff0c;图中 t1到t2 时间&#xff0c;就是我们需要测量的高电平时间。测…

深入理解设计模式:状态模式(State Pattern)

在软件开发中&#xff0c;我们经常会遇到对象的行为随着其内部状态的变化而变化的情况。例如&#xff0c;一个订单可能处于"待支付"、"已支付"、"已发货"或"已完成"等不同状态&#xff0c;每个状态下订单的操作逻辑可能完全不同。如果…

企业级网络综合集成实践:VLAN、Trunk、STP、路由协议(OSPF/RIP)、PPP、服务管理(TELNET/FTP)与安全(ACL)

NE综合实验4 一、实验拓扑二、实验需求 按照图示配置IP地址。Sw7和sw8之间的直连链路配置链路聚合。公司内部业务网段为vlan10和vlan20&#xff0c;vlan10是市场部&#xff0c;vlan20是技术部&#xff0c;要求对vlan进行命名以便区分识别&#xff1b;pc10属于vlan10&#xff0c…

小架构step系列20:请求和响应的扩展点

1 概述通过上一篇了解请求和响应的流程&#xff0c;Spring在设计上留了不少扩展点。里面通过查找接口的方式获取的地方&#xff0c;都可以成为一种扩展点&#xff0c;因为只要实现这类接口就可以成为Spring加载的一部分。本文了解一下这些扩展点&#xff0c;方便后面进行扩展。…

模型材质一键替换~轻松还原多种三维场景

1. 概述模型的材质决定了三维场景的整体视效&#xff0c;山海鲸可视化不仅支持模型材质的替换与编辑&#xff0c;而且提供了大量现成的模型材质供大家使用&#xff0c;能够帮助大家实现更高效的三维场景搭建。模型材质主要分为PBR材质和水面材质两个部分。其中大部分静态模型都…

【JS逆向基础】数据库之mysql

前言&#xff1a;mysql数据库管理系统&#xff0c;由瑞典MySQL AB 公司开发&#xff0c;目前属于 Oracle 旗下公司。MySQL 最流行的关MySQL是一个开源免费的关系型数据库管系型数据库管理系统&#xff0c;在 WEB 应用方面ySQL是最好的 RDBMS (Relational Database Management S…

金融工程、金融与经济学知识点

本文整理了20个金融工程、金融和经济学知识点及逻辑&#xff0c;这些是理解金融市场运作和进行量化分析的基石。 1. 金融工程 - 远期与期权&#xff08;Forward & Option&#xff09;的定价与风险管理 远期定价&#xff1a; 利用无套利原则&#xff0c;远期合约的价格应等…

Vue 3 中导出 Excel 文件

在 Vue 3 中导出 Excel 文件&#xff0c;通常可以使用一些流行的 JavaScript 库&#xff0c;如 SheetJS (xlsx) 或者 exceljs。这里我将分别介绍如何使用这两个库来在 Vue 3 应用中导出 Excel 文件。方法 1&#xff1a;使用 SheetJS (xlsx)安装 SheetJS首先&#xff0c;你需要安…

奇麟大数据:前端大文件上传解决方案

在奇麟大数据业务系统的开发及使用过程中&#xff0c;例如OBS对象存储文件管理、流计算DSC依赖管理&#xff0c;经常会遇到上传文件这样的基础需求&#xff0c;一般情况下&#xff0c;前端上传文件就是new FormData&#xff0c;然后把文件 append 进去&#xff0c;然后post发送…

立创EDA中双层PCB叠层分析

立创EDA中双层PCB叠层分析 结论&#xff1a;立创EDA中的双层 PCB 叠层视图相比传统视图&#xff0c;多出一个焊盘层&#xff08;博主命名&#xff09;&#xff1b; 1. 传统双层 PCB 叠层示意图 丝印层 印刷元件标识、极性标记及厂商信息 辅助组装与后期维护 阻焊层 覆盖铜层表…

深入理解进程:从底层原理到硬件系统实战

深入理解进程&#xff1a;从底层原理到嵌入式实战&#xff08;3-4 万字详解&#xff09; 前言&#xff1a;为什么硬件开发者必须吃透进程&#xff1f; 作为嵌入式开发者&#xff0c;你可能会说&#xff1a;“我平时用的 RTOS 里只有任务&#xff08;Task&#xff09;&#xff0…

Elasticsearch 简化指南:GCP Google Compute Engine

作者&#xff1a;来自 Elastic Eduard Martin 系列内容的一部分&#xff1a;开始使用 Elasticsearch&#xff1a;GCP 想获得 Elastic 认证&#xff1f;看看下一期 Elasticsearch Engineer 培训什么时候开始&#xff01; Elasticsearch 拥有丰富的新功能&#xff0c;帮助你根据…