STM32 BootLoader 刷新项目 (十二) Option Byte之FLASH_OPTCR-命令0x58
STM32 BootLoader 刷新项目 (十二) Option Byte之FLASH_OPTCR-命令0x58
STM32F407芯片的OPTION Byte全面解析
STM32F407芯片是STMicroelectronics推出的一款功能强大的微控制器,广泛应用于工业控制、通信和消费电子等领域。其中,OPTION Byte(选项字节)是STM32系列芯片的重要配置功能,允许用户通过配置特定的寄存器,控制芯片的关键特性,例如启动模式、读保护和写保护等。
本文将分为8个章节,全面解析STM32F407芯片的OPTION Byte功能。
第一章:OPTION Byte 概述
1.1 什么是OPTION Byte?
OPTION Byte 是 STM32 系列芯片中一种特殊的配置区域,存储在片内闪存(Flash memory)中。它的主要作用是提供芯片启动、保护和工作模式等关键参数的配置选项。这些字节在系统启动时被加载到对应的配置寄存器中,影响芯片的行为。
1.2 OPTION Byte 的作用
OPTION Byte 的主要功能包括:
- 启动模式配置:选择芯片从主Flash、系统存储器或SRAM启动。
- 读保护(Read Out Protection, ROP):保护芯片中的数据不被非法读取。
- 写保护(Write Protection, WP):保护指定的Flash区域不被擦除或写入。
- BOR(Brown-Out Reset)电压等级:设置芯片的掉电检测电压等级。
- Watchdog配置:使能或禁止独立看门狗(IWDG)在芯片复位后启动。
Option Byte由最终用户根据应用需求进行配置。表14显示了这些字节在用户配置扇区内的组织结构。
1.3 Programming user option bytes
要在该扇区上执行任何操作,必须清除Flash选项控制寄存器(FLASH_OPTCR)中的选项锁定位(OPTLOCK)。为了允许清除此位,您需要按照以下步骤进行操作:
-
将Flash选项密钥寄存器(FLASH_OPTKEYR)中的OPTKEY1设置为0x0819 2A3B。
-
将Flash选项密钥寄存器(FLASH_OPTKEYR)中的OPTKEY2设置为0x4C5D 6E7F。
用户选项字节可以通过软件设置OPTLOCK位来防止不必要的擦除/编程操作。
Modifying user option bytes on STM32F405xx/07xx and STM32F415xx/17xx
要修改用户选项值,请按照以下顺序进行操作:
- 检查FLASH_SR寄存器中的BSY位,确保没有正在进行的Flash内存操作。
- 将所需的选项值写入FLASH_OPTCR寄存器。
- 在FLASH_OPTCR寄存器中设置选项启动位(OPTSTRT)。
- 等待BSY位被清除。
1.4 Write protections
FLASH_OPTCR
是 STM32F407 芯片中用于控制和配置 Option Byte 的关键寄存器。通过操作该寄存器,可以设置各种与芯片启动模式、安全性以及电压保护相关的功能。以下是对 FLASH_OPTCR
寄存器的详细介绍。
Flash存储器中最多可以保护24个用户扇区,以防止由于程序计数器上下文丢失而导致的不必要写操作。当FLASH_OPTCR或FLASH_OPTCR1寄存器中的非写保护nWRPi位(0 ≤ i ≤ 11)为低电平时,相应的扇区将无法被擦除或编程。因此,如果其中一个扇区受到写保护,则无法进行全片擦除。如果尝试对Flash存储器中受写保护部分(由写保护位、OTP部分锁定或永远不能被写入的ICP组成)进行擦除/编程操作,则会在FLASH_SR寄存器中设置写保护错误标志(WRPERR)。
FLASH_OPTCR 寄存器定义
FLASH_OPTCR
是一个 32 位寄存器,其各位或各位段控制特定的 Option Byte 配置。
位段 | 名称 | 说明 |
---|---|---|
[0] | OPTLOCK | 选项锁位(Option Lock) |
[1] | OPTSTRT | 选项启动位(Option Start) |
[2:3] | BOR_LEV | 掉电复位电压等级(Brown-Out Reset Level) |
[4] | Reserved | 保留位 |
[5] | WDG_SW | 独立看门狗模式选择(Software or Hardware IWDG) |
[6] | nRST_STOP | STOP模式复位禁用 |
[7] | nRST_STDBY | Standby模式复位禁用 |
[8:15] | RDP | 读保护等级(Read Protection Level) |
[16:27] | WRP | 写保护配置(Write Protection for Flash Sectors) |
[28:31] | Reserved | 保留位 |
各字段详细解析
1. OPTLOCK(Option Lock) [0]
- 说明:选项字节锁定位,用于保护
FLASH_OPTCR
寄存器不被意外修改。 - 值:
1
:锁定 Option Byte。0
:解锁 Option Byte。
- 操作:需要先写入解锁密钥到
FLASH_OPTKEYR
寄存器,才能将此位清零解锁。
2. OPTSTRT(Option Start) [1]
- 说明:选项启动位,用于触发 Option Byte 的写入操作。
- 值:
1
:启动 Option Byte 写入。0
:无操作。
- 操作:在修改完 Option Byte 配置后,需将该位设置为
1
以启动写入。
3. BOR_LEV(Brown-Out Reset Level) [2:3]
- 说明:配置 BOR 掉电复位的电压阈值。
- 值:
0000
:BOR Level 0(最低电压复位,1.8V 至 2.1V)。0001
:BOR Level 1(1.9V 至 2.4V)。0010
:BOR Level 2(2.1V 至 2.7V)。0011
:BOR Level 3(2.4V 至 2.9V)。- 其他值:保留。
- 应用:在电源不稳定的场景中,可通过调整 BOR Level 确保 MCU 在电压异常时安全复位。
4. WDG_SW(Independent Watchdog Selection) [5]
- 说明:独立看门狗模式选择。
- 值:
0
:硬件模式(独立看门狗由硬件启动,不能由软件禁用)。1
:软件模式(独立看门狗由软件启动,可以由软件控制)。
- 应用:在安全关键场景中,硬件模式更可靠;而软件模式适合需要灵活控制的应用。
5. nRST_STOP(Stop Mode Reset Disable) [6]
- 说明:STOP模式复位禁用。
- 值:
0
:启用 STOP 模式下的复位。1
:禁用 STOP 模式下的复位。
- 应用:用于控制在进入 STOP 模式后,是否允许复位信号。
6. nRST_STDBY(Standby Mode Reset Disable) [7]
- 说明:Standby模式复位禁用。
- 值:
0
:启用 Standby 模式下的复位。1
:禁用 Standby 模式下的复位。
- 应用:与 nRST_STOP 类似,用于控制芯片在 Standby 模式的复位行为。
7. RDP(Read Protection Level) [8:15]
- 说明:读保护等级。
- 值:
0xAA
:无保护(Level 0)。0xBB
:读保护(Level 1)。其他
:高强度保护(Level 2,数据不可访问且不可恢复)。
- 注意:
- 一旦进入 Level 2,芯片的 Flash 区域永久锁定。
- 从 Level 1 回到 Level 0 需要擦除整个 Flash。
8. WRP(Write Protection) [16:27]
- 说明:写保护设置,指定哪些 Flash 扇区受写保护。
- 值:每个位对应一个扇区,
1
表示受保护,0
表示不受保护。 - 应用:在固件更新或调试时防止误擦写关键代码区域。
使用 FLASH_OPTCR 的关键操作
1. 解锁 OPTION Byte
在写入 FLASH_OPTCR
之前,必须解锁 Option Byte:
FLASH->OPTKEYR = 0x08192A3B; // 解锁密钥1
FLASH->OPTKEYR = 0x4C5D6E7F; // 解锁密钥2
2. 配置 FLASH_OPTCR
修改寄存器中对应的字段。例如,启用读保护并设置 BOR 为 Level 3:
FLASH->OPTCR |= FLASH_OPTCR_RDP_0; // 设置 RDP 为 Level 1
FLASH->OPTCR &= ~FLASH_OPTCR_BOR_LEV; // 清除 BOR 配置
FLASH->OPTCR |= FLASH_OPTCR_BOR_LEV_2; // 设置 BOR 为 Level 3
3. 启动写入
完成配置后,启动 Option Byte 写入:
FLASH->OPTCR |= FLASH_OPTCR_OPTSTRT; // 启动写入
while (FLASH->SR & FLASH_SR_BSY); // 等待操作完成
4. 锁定 OPTION Byte
写入完成后,重新锁定寄存器:
FLASH->OPTCR |= FLASH_OPTCR_OPTLOCK;
注意事项
-
配置不可逆性:
- 启用高强度读保护(RDP Level 2)后,Flash 数据无法访问且不可恢复。
- 写保护或 RDP 配置的更改可能需要擦除整个芯片。
-
操作期间电源稳定:
- 写入 FLASH_OPTCR 时,如果电源中断可能导致芯片配置不完整,甚至不可用。
-
调试工具可能受限:
- 启用读保护或写保护后,调试接口(如 JTAG/SWD)可能受限或失效。
总结
FLASH_OPTCR
是 STM32F407 OPTION Byte 配置的核心寄存器,允许用户灵活控制芯片的关键功能。通过正确配置该寄存器,可以在安全性、电源稳定性和启动模式等方面大大增强 STM32 应用的可靠性。
第二章:OPTION Byte 的应用场景
1. 安全数据保护
在需要对数据高度保护的场景,例如密码存储或商业机密数据处理,启用读保护功能(ROP)可以有效防止未经授权的访问。
2. 启动模式选择
在嵌入式开发中,不同应用可能需要芯片从不同的存储介质启动。例如:
- 开发阶段,可以选择从系统存储器启动,以便使用ST的内置Bootloader进行固件更新。
- 生产阶段,可以配置从主Flash启动,以运行正式固件。
3. 固件更新保护
通过启用写保护功能(WP),开发者可以锁定Flash的某些区域,防止意外或恶意擦写,从而保护固件的完整性。
4. 电源稳定性管理
在电源波动较大的场景中,通过调整BOR电压等级,确保芯片在特定电压下安全复位,避免错误行为。
第三章:OPTION Byte 配置操作步骤
1. 确认配置需求
在更改OPTION Byte之前,确定需要配置的功能,例如启用读保护或调整BOR电压等级。
2. 解锁Flash控制器
在STM32F407中,OPTION Byte 存储在Flash中,因此需要解锁Flash控制器(Flash Control Register, FLASH_CR)以允许修改。
3. 修改OPTION Byte
通过操作特定寄存器(FLASH_OPTCR 或 FLASH_OPTCR1),将所需的配置值写入OPTION Byte。
4. 启动OPTION Byte 加载
配置完成后,触发重新加载以使更改生效。
5. 验证配置
通过读取相关寄存器,确认OPTION Byte的配置已成功应用。
第四章:代码实现(详细注释)Demo示例
以下代码展示如何配置STM32F407的OPTION Byte,以启用读保护和调整BOR电压等级。
#include "stm32f4xx.h"// 函数声明
void Flash_Unlock(void);
void Configure_OPTION_Bytes(void);int main(void) {// 解锁Flash控制器Flash_Unlock();// 配置OPTION ByteConfigure_OPTION_Bytes();while (1) {// 主循环}
}// 解锁Flash控制器函数
void Flash_Unlock(void) {if ((FLASH->CR & FLASH_CR_LOCK) != 0) {// 解锁KEY1FLASH->KEYR = 0x45670123;// 解锁KEY2FLASH->KEYR = 0xCDEF89AB;}
}// 配置OPTION Byte函数
void Configure_OPTION_Bytes(void) {// 解锁OPTION Byteif ((FLASH->OPTCR & FLASH_OPTCR_OPTLOCK) != 0) {FLASH->OPTKEYR = 0x08192A3B; // 解锁KEY1FLASH->OPTKEYR = 0x4C5D6E7F; // 解锁KEY2}// 修改OPTION Byte// 启用读保护(Level 1)FLASH->OPTCR |= FLASH_OPTCR_RDP_0; // 配置BOR电压为Level 3(最严格)FLASH->OPTCR &= ~FLASH_OPTCR_BOR_LEV; // 清除BOR配置FLASH->OPTCR |= FLASH_OPTCR_BOR_LEV_2; // 设置BOR为Level 3// 启动OPTION Byte写入FLASH->OPTCR |= FLASH_OPTCR_OPTSTRT;// 等待操作完成while ((FLASH->SR & FLASH_SR_BSY) != 0);// 锁定OPTION ByteFLASH->OPTCR |= FLASH_OPTCR_OPTLOCK;
}
代码解析
-
解锁Flash控制器和OPTION Byte
- STM32的Flash和OPTION Byte均受锁机制保护,需先解锁后才能修改。
-
设置读保护和BOR等级
- 使用
FLASH_OPTCR
寄存器进行配置。 - 读保护(RDP)设为 Level 1(禁止非法读取)。
- BOR电压配置为 Level 3(最高复位电压)。
- 使用
-
触发写入并等待完成
- 设置
OPTSTRT
位后,硬件会自动将更改写入Flash。
- 设置
第五章:使用OPTION Byte的注意事项
1. 配置的不可逆性
某些配置(如读保护启用)具有不可逆性。一旦启用,降低保护等级可能需要擦除整个芯片数据。
2. 注意芯片的电源状态
在配置OPTION Byte时,确保芯片电源稳定,否则可能导致写入失败或数据损坏。
3. 调试时的风险
调试过程中,不建议随意更改OPTION Byte,尤其是启用读保护后,调试接口可能失效。
4. 启用写保护的影响
启用写保护后,程序固件的某些部分将无法更新。需提前规划好保护区域。
总结
STM32F407芯片的OPTION Byte功能强大,提供了多种关键配置选项。在实际应用中,开发者需要根据需求谨慎配置,以确保芯片的安全性和稳定性。通过本教程的详细步骤和代码示例,相信您已经掌握了如何在STM32F407上高效使用OPTION Byte功能,为嵌入式项目提供强有力的支持。
下面我们开始介绍BootLoader的使能读写保护命令。
第六章:0x58命令介绍–使能读写保护
在本篇文章,我们的主要是介绍0x58的命令,这个命令主要是在BootLoader中使能Flash Sector的读写保护。
通过上位机发送8 Byte的数据,其中第1 Byte为整个数据的长度,第2Byte为指令码,第3 Byte为写入要保护Sector段,第4 Byte是保护模式,1是写保护,2是读写保护,5-8 Byte为前4 Byte的CRC校验值,上位机通过串口UART发送给下位机,下位机回复地址是否写入成功的标志。
下面是发送命令过程中上位机与BootLoader之间的交互。
第七章:使能读写保护-0x58 命令BootLoader程序设计
代码逻辑和功能解释
1. bootloader_uart_read_data()
函数
void bootloader_uart_read_data(void)
{ uint8_t rcv_len = 0; printmsg_Host("BL_DEBUG_MSG: Receive CMD\n\r"); // 调试信息:接收命令 while (1) { // 点亮LED,表示进入命令处理HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET); // 清空接收缓冲区memset(bl_rx_buffer, 0, 200); // 步骤1:接收命令包的第一个字节(长度字段)HAL_UART_Receive(C_UART, bl_rx_buffer, 1, HAL_MAX_DELAY); rcv_len = bl_rx_buffer[0]; // 步骤2:根据长度字段接收剩余的命令包HAL_UART_Receive(C_UART, &bl_rx_buffer[1], rcv_len, HAL_MAX_DELAY); // 步骤3:根据命令代码调用对应的命令处理函数switch (bl_rx_buffer[1]) { case BL_GET_VER: bootloader_handle_getver_cmd(bl_rx_buffer); break; case BL_GET_HELP: bootloader_handle_gethelp_cmd(bl_rx_buffer); break; case BL_GET_CID: bootloader_handle_getcid_cmd(bl_rx_buffer); break; case BL_GET_RDP_STATUS: bootloader_handle_getrdp_cmd(bl_rx_buffer); break; case BL_GO_TO_ADDR: bootloader_handle_go_cmd(bl_rx_buffer); break; case BL_FLASH_ERASE: bootloader_handle_flash_erase_cmd(bl_rx_buffer); break; case BL_MEM_WRITE: bootloader_handle_mem_write_cmd(bl_rx_buffer); break; case BL_EN_RW_PROTECT: bootloader_handle_en_rw_protect(bl_rx_buffer); break; case BL_MEM_READ: bootloader_handle_mem_read(bl_rx_buffer); break; default: // 如果命令无效,打印调试信息printmsg("BL_DEBUG_MSG: Invalid command code received from host \n"); break; } }
}
功能:
- 这是引导程序的主要任务循环,负责接收主机通过 UART 发来的命令数据包并调用相应的处理函数。
逻辑解析:
-
命令接收:
- 使用
HAL_UART_Receive
接收数据:- 首先接收数据包长度字段(
bl_rx_buffer[0]
)。 - 然后根据长度接收完整的命令数据包。
- 首先接收数据包长度字段(
- 通过命令码(
bl_rx_buffer[1]
)解析当前命令。
- 使用
-
命令分发:
- 根据命令码,调用相应的处理函数:
- 如
BL_GET_VER
调用bootloader_handle_getver_cmd()
。 BL_EN_RW_PROTECT
调用bootloader_handle_en_rw_protect()
。
- 如
- 如果命令码无效,则打印调试信息。
- 根据命令码,调用相应的处理函数:
总结:
bootloader_uart_read_data()
是引导程序的任务调度中心,通过 UART 接收命令并分发到相应的处理逻辑。
2. bootloader_handle_en_rw_protect(uint8_t *pBuffer)
函数
void bootloader_handle_en_rw_protect(uint8_t *pBuffer)
{ uint8_t status = 0x00; printmsg("BL_DEBUG_MSG: bootloader_handle_endis_rw_protect\n"); // 调试信息:处理读写保护命令 // 计算命令包的总长度uint32_t command_packet_len = bl_rx_buffer[0] + 1; // 提取主机发送的CRC32校验码uint32_t host_crc = *((uint32_t *)(bl_rx_buffer + command_packet_len - 4)); // 步骤1:校验CRC是否正确if (!bootloader_verify_crc(&bl_rx_buffer[0], command_packet_len - 4, host_crc)) { printmsg("BL_DEBUG_MSG: checksum success !!\n"); // CRC校验成功 // 发送ACK响应主机bootloader_send_ack(pBuffer[0], 1); // 步骤2:配置Flash扇区的读写保护status = configure_flash_sector_rw_protection(pBuffer[2], pBuffer[3], 0); printmsg("BL_DEBUG_MSG: flash erase status: %#x\n", status); // 打印保护配置状态 // 步骤3:将配置状态返回给主机bootloader_uart_write_data(&status, 1); } else { printmsg("BL_DEBUG_MSG: checksum fail !!\n"); // CRC校验失败 // 如果校验失败,发送NACKbootloader_send_nack(); }
}
功能:
- 解析和处理
BL_EN_RW_PROTECT
命令,用于对闪存扇区进行读写保护的启用。
逻辑解析:
-
解析命令数据包:
- 计算数据包总长度:
command_packet_len = bl_rx_buffer[0] + 1
。 - 提取数据包中的 CRC 校验值(末尾 4 字节)。
- 计算数据包总长度:
-
校验数据完整性:
- 调用
bootloader_verify_crc
对数据包进行 CRC 校验:- 如果校验成功:
- 调用
bootloader_send_ack()
发送 ACK。 - 调用
configure_flash_sector_rw_protection()
配置扇区保护。 - 返回操作状态。
- 调用
- 如果校验失败:
- 调用
bootloader_send_nack()
发送 NACK。
- 调用
- 如果校验成功:
- 调用
-
处理闪存保护配置:
- 从数据包中解析
pBuffer[2]
和pBuffer[3]
,确定扇区选择和保护模式。
- 从数据包中解析
总结:
bootloader_handle_en_rw_protect()
负责解析 BL_EN_RW_PROTECT
命令,实现对闪存扇区的读写保护配置,并通过 CRC 校验确保命令数据的完整性。
3. configure_flash_sector_rw_protection(uint8_t sector_details, uint8_t protection_mode, uint8_t disable)
函数
uint8_t configure_flash_sector_rw_protection(uint8_t sector_details, uint8_t protection_mode, uint8_t disable)
{// Flash选项控制寄存器地址volatile uint32_t *pOPTCR = (uint32_t*) 0x40023C14;if(disable){// 禁用所有扇区的读写保护// 解锁选项字节配置HAL_FLASH_OB_Unlock();// 等待Flash完成当前操作while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY) != RESET);// 清除OPTCR寄存器的第31位以禁用保护*pOPTCR &= ~(1 << 31);// 将所有与扇区相关的保护位设置为1(无保护)*pOPTCR |= (0xFF << 16);// 设置OPTSTRT位以启动选项字节编程*pOPTCR |= (1 << 1);// 等待Flash完成当前操作while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY) != RESET);// 锁定选项字节配置HAL_FLASH_OB_Lock();return 0;}if(protection_mode == (uint8_t) 1){// 设置仅写保护// 解锁选项字节配置HAL_FLASH_OB_Unlock();// 等待Flash完成当前操作while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY) != RESET);// 清除OPTCR寄存器的第31位*pOPTCR &= ~(1 << 31);// 设置写保护,修改相应扇区的位(sector_details指定了具体的扇区)*pOPTCR &= ~(sector_details << 16);// 设置OPTSTRT位以启动选项字节编程*pOPTCR |= (1 << 1);// 等待Flash完成当前操作while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY) != RESET);// 锁定选项字节配置HAL_FLASH_OB_Lock();}else if (protection_mode == (uint8_t) 2){// 设置读写保护// 解锁选项字节配置HAL_FLASH_OB_Unlock();// 等待Flash完成当前操作while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY) != RESET);// 设置OPTCR寄存器的第31位以启用读写保护*pOPTCR |= (1 << 31);// 配置选定扇区的读写保护*pOPTCR &= ~(0xff << 16);*pOPTCR |= (sector_details << 16);// 设置OPTSTRT位以启动选项字节编程*pOPTCR |= (1 << 1);// 等待Flash完成当前操作while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY) != RESET);// 锁定选项字节配置HAL_FLASH_OB_Lock();}return 0;
}
功能:
- 通过修改 FLASH 选项控制寄存器(
OPTCR
)实现对闪存扇区的读写保护配置。
逻辑解析:
-
参数解析:
sector_details
:扇区选择(通过每个位表示不同扇区)。protection_mode
:保护模式:- 1 表示仅写保护。
- 2 表示读写保护。
disable
:是否禁用所有保护。
-
禁用保护:
- 解锁选项字节(
HAL_FLASH_OB_Unlock()
)。 - 清除保护位:
- 清除 OPTCR 寄存器的第 31 位。
- 设置扇区保护位为默认值(所有扇区解除保护)。
- 启动保护配置(设置
OPTSTRT
位)。 - 等待操作完成(检查
FLASH_FLAG_BSY
标志)。
- 解锁选项字节(
-
写保护:
- 解锁选项字节。
- 清除第 31 位,表示启用写保护模式。
- 修改目标扇区的保护位。
- 设置
OPTSTRT
位,启动保护配置。
-
读写保护:
- 解锁选项字节。
- 设置第 31 位,表示启用读写保护模式。
- 修改目标扇区的保护位。
- 设置
OPTSTRT
位,启动保护配置。
总结:
configure_flash_sector_rw_protection()
实现了对闪存扇区保护配置的底层操作,包括禁用保护、写保护和读写保护的具体实现,直接操控 STM32 的 FLASH 寄存器。
综合总结
- 任务调度:
bootloader_uart_read_data()
是主任务函数,负责接收主机命令并调用对应处理逻辑。
- 命令解析:
bootloader_handle_en_rw_protect()
是特定命令处理函数,用于启用闪存扇区保护,包含数据解析、CRC 校验及状态返回。
- 硬件操作:
configure_flash_sector_rw_protection()
是底层函数,通过直接操作 FLASH 控制寄存器完成保护配置。
通过以上函数协同工作,STM32 引导程序能够接收主机命令并对闪存扇区实现灵活的保护管理。
第八章:BootLoader实战操作
下面是上位机的命令菜单,通过在终端调用Python脚本,然后在终端输入下位机连接的串口号,即可进入命令界面,目前可支持如下命令:
下面选择命令9,输入要保护的Flash的段,向下位机发送信息。
下面判断Flash保护是否成功,发送命令11,读出保护状态,发现Secotr 3,4,5处于写保护状态Write Protection。
下面输入命令13,关闭所有的段保护
在一次判断段保护状态,输入命令11,发现读写保护状态,发现所有保护状态处于No Protection,发现之前的命令13成功。
第九章. 系列文章
STM32 BootLoader 刷新项目 (一) STM32CubeMX UART串口通信工程搭建
STM32 BootLoader 刷新项目 (二) 方案介绍
STM32 BootLoader 刷新项目 (三) 程序框架搭建及刷新演示
STM32 BootLoader 刷新项目 (四) 通信协议
STM32 BootLoader 刷新项目 (五) 获取软件版本号-命令0x51
STM32 BootLoader 刷新项目 (六) 获取帮助-命令0x52
STM32 BootLoader 刷新项目 (七) 获取芯片ID-0x53
STM32 BootLoader 刷新项目 (八) 读取Flash保护ROP-0x54
STM32 BootLoader 刷新项目 (九) 跳转指定地址-命令0x55
[STM32 BootLoader 刷新项目 (十) Flash擦除-命令0x56](STM32 BootLoader 刷新项目 (十) Flash擦除-命令0x56-CSDN博客)
STM32 BootLoader 刷新项目 (十一) Flash写操作-命令0x57
相关文章:
STM32 BootLoader 刷新项目 (十二) Option Byte之FLASH_OPTCR-命令0x58
STM32 BootLoader 刷新项目 (十二) Option Byte之FLASH_OPTCR-命令0x58 STM32F407芯片的OPTION Byte全面解析 STM32F407芯片是STMicroelectronics推出的一款功能强大的微控制器,广泛应用于工业控制、通信和消费电子等领域。其中,OPTION Byte࿰…...
MySQL主从复制
华子目录 实验环境准备修改配置文件 实验主开启bin-log日志创建用于主从复制的用户master配置salve配置 测试 添加一台新的slave,如何实现数据的全部同步呢什么环境下主比较多,什么环境下从比较多?延迟复制测试 并行复制gtid模式未启用gtid时…...
贝叶斯统计:高斯分布均值μ的后验分布推导
使用贝叶斯统计方法 均值 ( μ \mu μ ) 的后验分布解析 在贝叶斯统计中,后验分布表示在观察到数据后,对参数的更新后的信念。本篇文章将结合高斯分布的假设,详细解析均值 ( μ \mu μ ) 的后验分布推导过程,并对 ( μ \mu μ…...
linux常用指令都是工作中遇到的
前端打war包 jar -cvf dist.war *创建 WAR 文件的命令 jar -cvf dist.war * 用于将当前目录下的所有文件和文件夹打包成一个名为 dist.war 的 WAR 文件。以下是该命令的详细解释: jar: Java Archive 工具,用于创建 JAR、WAR 或 EAR 文件。 -c: 创建新的…...
亚马逊自研大语言模型 Olympus 即将亮相,或将在 LLM 竞赛中掀起新波澜
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...
droppath
DropPath 是一种用于正则化深度学习模型的技术,它在训练过程中随机丢弃路径(或者说随机让某些部分的输出变为零),从而增强模型的鲁棒性和泛化能力。 代码解释: import torch import torch.nn as nn # 定义 DropPath…...
通信与网络安全之IPSEC
IPSec(IP Security)是IETF制定的为保证在Internet上传送数据的安全保密性能的三层隧道加密协议。IPSec在网络层对IP报文提供安全服务。IPSec协议本身定义了如何在IP数据包中增加字段来保证IP包的完整性、 私有性和真实性,以及如何加密数据包。…...
Linux内核编译流程(Ubuntu24.04+Linux Kernel 6.8.12)
万恶的拯救者,使用Ubuntu没有声音,必须要自己修改一下Linux内核中的相关驱动逻辑才可以,所以被迫学习怎么修改内核&编译内核,记录如下 准备工作 下载Linux源码:在Linux发布页下载并使用gpg签名验证 即:…...
什么是GAN?
一、基本概念 生成对抗网络(Generative Adversarial Network,GAN)是一种由两个神经网络共同组成深度学习模型:生成器(Generator)和判别器(Discriminator)。这两个网络通过对抗的方式…...
torch_geometric使用手册-Creating Graph Datasets(专题四)
虽然 PyG 已经提供了很多有用的数据集,但你可能希望创建自己的数据集,使用自己收集的数据或非公开的数据。 自己实现数据集是非常简单的,你可能想查看源代码,了解各种数据集是如何实现的。然而,这里简要介绍一下如何设置你自己的数据集。 我们提供了两个抽象类用于数据集…...
编程语言之Python
Python是一种高级编程语言,自其诞生以来,便因其简洁明了的语法、强大的功能和广泛的应用领域而备受青睐。以下是对Python的详细介绍,包括其历史、特点、应用领域,以及通过代码示例展示其语法、库、函数等关键概念。同时࿰…...
【Go】-调度器简介
目录 数据结构 G M P 调度器启动 创建 Goroutine 初始化结构体 运行队列 调度信息 调度循环 小结 数据结构 Go的运行时调度器的三个重要组成部分 — 线程 M、Goroutine G 和处理器 P: 图 6-29 Go 语言调度器 G — 表示 Goroutine,它是一个待…...
在Ubuntu 22.04上设置Python 3的Jupyter Notebook
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 简介 Jupyter Notebook 是一个作为 Web 应用程序的交互式计算命令 shell。该工具可与多种语言一起使用,包括 Python、Julia…...
通讯专题4.1——CAN通信之计算机网络与现场总线
从通讯专题4开始,来学习CAN总线的内容。 为了更好的学习CAN,先从计算机网络与现场总线开始了解。 1 计算机网络体系的结构 在我们生活当中,有许多的网络,如交通网(铁路、公路等)、通信网(电信、…...
将jar包导入maven
1.将jar包放repository 2.执行命令:mvn install:install-file -DgroupIdcom.oracle -DartifactIdojdbc7 -Dversion12.1.0.2 -Dpackagingjar -DfileD:\dev\utils\idea\repository\ojdbc7.jar -Dfile: 指定要安装的JAR文件的路径。 -DgroupId: 指定项目的groupId。 -…...
Mysql实现定时自动备份(Windows环境)
一.新建数据库备份目录 二.新建批处理文件 创建批处理文件mysql_backup.bat echo off set BACKUP_DIRD:\backup set MYSQL_USERroot set MYSQL_PASS123456 set MYSQL_HOSTlocalhost set DATABASE_NAMEphoenix set DATE%date:~0,4%-%date:~5,2%-%date:~8,2%_%time:~0,2%-%time…...
kafka数据在服务端时怎么写入的
学习背景 接着上篇,我们来聊聊kafka数据在服务端怎么写入的 服务端写入 在介绍服务端的写流程之前,我们先要理解服务端的几个角色之间的关系。 假设我们有一个由3个broker组成的kafka集群,我们在这个集群上创建一个topic叫做shitu-topic&…...
2024算法基础公选课练习七(BFS1)
一、前言 还是偏基础的bfs,但是有几个题不是很好写 二、题目总览 三、具体题目 3.1 问题 A: 数据结构-队列-奇怪的电梯 我的代码 可以看成求一维平面的bfs最短路 #include <bits/stdc.h> using i64 long long; using pii std::pair<int,int>; co…...
算法刷题Day1
BM47 寻找第k大 第一天就随便记录吧,万事开头难,我好不容易开的头,就别难为自己,去追求高质量了。嘿嘿嘿 题目 传送门 解题思路一:维护一个大小为k的最小堆。最后返回堆顶元素。 代码: # # 代码中的类名…...
你还没有将 Siri 接入GPT对话功能吗?
由于各种原因,国内ios用户目前无缘自带 AI 功能,但是这并不代表国内 ios 无法接入 AI 功能,接下来手把手带你为iPhone siri 接入 gpt 对话功能。 siri 接入 chatGPT 暂时还无法下载 ChatGPT app,或者没有账号的读者可以直接跳到…...
LabVIEW 标准状态机设计模式
LabVIEW 标准状态机设计模式 LabVIEW 软件框架介绍LabVIEW编程模式及其应用分析状态机模式的类型分析标准状态机设计模式及状态机应用学习顺序结构它的一个缺点是什么? 状态机结构 LabVIEW 软件框架介绍 源于虚拟仪器技术的LabVIEW程序设计语言,从被创建…...
Scala学习记录,统计成绩
统计成绩练习 1.计算每个同学的总分和平均分 2.统计每个科目的平均分 3.列出总分前三名和单科前三名,并保存结果到文件中 解题思路如下: 1.读入txt文件,按行读入 2.处理数据 (1)计算每个同学的总分平均分 import s…...
使用 client-go 实现 Kubernetes 节点 Drain:详解与实战教程
在 Kubernetes 中使用 client-go 实现 drain 功能涉及多个步骤,需要模仿 kubectl drain 的行为。这包括将节点标记为不可调度(cordon)、驱逐 Pod,并处理 DaemonSet 和不可驱逐 Pod 的逻辑。以下是实现 drain 的主要步骤࿱…...
C#VB.Net项目一键多国语言显示
如何在项目什么都不做一键支持多国语言显示 开始我们的一键快捷使用之旅 01.创建多语言项目 02.一键批量窗口开启本地化,添加选中内容添加Mu方法 03.一键快捷翻译 04.运行查看效果 01.创建多语言项目 创建多语言项目前,请先下载安装,注册并登录. 为了便于演示这…...
【关闭or开启电脑自带的数字键盘】
目录 一、按数字键盘左上角的按键【NumLK Scroll】 二、修改注册表中数字键盘对应的数值【InitialKeyboardIndicators】 1、步骤: 2、知识点: 一、按数字键盘左上角的按键【NumLK Scroll】 这是最简单快捷的方法。 关闭后若想开启,再按一…...
如何在Bash中等待多个子进程完成,并且当其中任何一个子进程以非零退出状态结束时,使主进程也返回一个非零的退出码?
文章目录 问题回答参考 问题 如何在 Bash 脚本中等待该脚本启动的多个子进程完成,并且当这其中任意一个子进程以非零退出码结束时,让该脚本也返回一个非零的退出码? 简单的脚本: #!/bin/bash for i in seq 0 9; docalculations $i & d…...
Asio2网络库
header only,不依赖boost库,不需要单独编译,在工程的Include目录中添加asio2路径,在源码中#include <asio2/asio2.hpp>即可使用;支持tcp, udp, http, websocket, rpc, ssl, icmp, serial_port;支持可靠UDP(基于KCP),支持SSL;TCP支持各种数据拆包功能(单个字符或字符串或用…...
Uniapp 微信小程序内打开web网页
技术栈:Uniapp Vue3 简介 实际业务中有时候会需要在本微信小程序内打开web页面,这时候可以封装一个路由页面专门用于此场景。 在路由跳转的时候携带路由参数,拼接上web url,接收页面进行参数接收即可。 实现 webview页面 新…...
学习线性表_3
单链表的删除 直接删除即可删除后要free //删除第i个位置的元素 //删除时L是不会变的,所以不需要加引用 bool ListDelect(LinkList L,int i) {//i 1,即删除头指针//拿到要删除结点的前一个结点LinkList p GetElem(L,i-1);if(NULLp){return false;}//拿到要删除的结…...
智能桥梁安全运行监测系统守护桥梁安全卫士
一、方案背景 桥梁作为交通基础设施中不可或缺的重要组成部分,其安全稳定的运行直接关联到广大人民群众的生命财产安全以及整个社会的稳定与和谐。桥梁不仅是连接两地的通道,更是经济发展和社会进步的重要纽带。为了确保桥梁的安全运行,桥梁安…...
Arrays.asList()新增报错,该怎么解决
一、前言 在 Java 开发中,Arrays.asList() 是一个常用的工具方法,它允许开发者快速将数组转换为列表。尽管这个方法非常方便,但许多开发者在使用时可能会遭遇一个常见的错误:尝试向由 Arrays.asList() 返回的列表中添加元素时抛出…...
28.UE5实现对话系统
目录 1.对话结构的设计(重点) 2.NPC对话接口的实现 2.1创建类型为pawn的蓝图 2.2创建对话接口 3.对话组件的创建 4.对话的UI设计 4.1UI_对话内容 4.2UI_对话选项 4.3UI_对话选项框 5.对话组件的逻辑实现 通过组件蓝图,也就是下图中的…...
会议直击|美格智能亮相2024紫光展锐全球合作伙伴大会,融合5G+AI共拓全球市场
11月26日,2024紫光展锐全球合作伙伴大会在上海举办,作为紫光展锐年度盛会,吸引来自全球的众多合作伙伴和行业专家、学者共同参与。美格智能与紫光展锐竭诚合作多年,共同面向5G、AI和卫星通信为代表的前沿科技,聚焦技术…...
IDEA报错: java: JPS incremental annotation processing is disabled 解决
起因 换了个电脑打开了之前某个老项目IDEA启动springcloud其中某个服务直接报错,信息如下 java: JPS incremental annotation processing is disabled. Compilation results on partial recompilation may be inaccurate. Use build process “jps.track.ap.depen…...
面对深度伪造:OWASP发布专业应对指南
从美国大选造谣视频到AI编写的网络钓鱼邮件,深度伪造(deepfake)诈骗和生成式人工智能攻击日益猖獗,人眼越来越难以辨识,企业迫切需要为网络安全团队制定AI安全事件响应指南。 深度伪造攻击威胁日益增加 全球范围内&…...
IDEA全局设置-解决maven加载过慢的问题
一、IDEA全局设置 注意:如果不是全局设置,仅仅针对某个项目有效;例在利用网上教程解决maven加载过慢的问题时,按步骤设置却得不到解决,原因就是没有在全局设置。 1.如何进行全局设置 a.在项目页面,点击f…...
【阅读笔记】Android广播的处理流程
关于Android的解析,有很多优质内容,看了后记录一下阅读笔记,也是一种有意义的事情, 今天就看看“那个写代码的”这位大佬关于广播的梳理, https://blog.csdn.net/a572423926/category_11509429.html https://blog.c…...
queue 和 Stack
import scala.collection.mutable //queue:队列.排队打饭.... //特点:先进先出 //Stack:栈 //特点:先进后出 class ob5 { def main(args: Array[String]): Unit { val q1 mutable.Queue(1) q1.enqueue(2)//入队 q1.enqueue(3)//入队 q1.enqueue(4)…...
C#窗体小程序计算器
使其能完成2个数的加、减、乘、除基本运算。界面如下图,单击相应的运算符按钮,则完成相应的运算,并将结果显示出来,同时不允许在结果栏中输入内容 代码如下: private void button1_Click(object sender, EventArgs e)…...
Linux——自定义简单shell
shell 自定义shell目标普通命令和内建命令(补充) shell实现实现原理实现代码 自定义shell 目标 能处理普通命令能处理内建命令要能帮助我们理解内建命令/本地变量/环境变量这些概念理解shell的运行 普通命令和内建命令(补充) …...
大模型开发和微调工具Llama-Factory-->WebUI
WebUI LLaMA-Factory 支持通过 WebUI 零代码微调大模型。 通过如下指令进入 WebUI llamafactory-cli webui# 如果是国内, # USE_MODELSCOPE_HUB 设为 1,表示模型从 ModelScope 魔搭社区下载。 # 避免从 HuggingFace 下载模型导致网速不畅 USE_MODELSC…...
【网络】应用层协议HTTPHTTPcookie与sessionHTTPS协议原理
主页:醋溜马桶圈-CSDN博客 专栏:计算机网络原理_醋溜马桶圈的博客-CSDN博客 gitee:mnxcc (mnxcc) - Gitee.com 目录 1.应用层协议HTTP 2.认识 URL 2.1 urlencode 和 urldecode 3.HTTP 协议请求与响应格式 3.1 HTTP 请求 3.2 HTTP 响应 …...
基于LSTM的文本多分类任务
概述: LSTM(Long Short-Term Memory,长短时记忆)模型是一种特殊的循环神经网络(RNN)架构,由Hochreiter和Schmidhuber于1997年提出。LSTM被设计来解决标准RNN在处理序列数据时遇到的长期依赖问题…...
Git忽略文件
在Git中,你可以通过修改 .gitignore 文件来忽略整个文件夹。以下是具体步骤: 打开或创建 .gitignore 文件 确保你的项目根目录下有一个 .gitignore 文件。如果没有,创建一个: touch .gitignore 在 .gitignore 文件中添加要忽略…...
Spring的事务管理
tx标签用于配置事务管理用于声明和配置事务的相关属性 transaction-manager指定一个事务管理器的引用,用于管理事务的生命周期。propagation指定事务的传播属性,决定了在嵌套事务中如何处理事务。isolation指定事务的隔离级别,用于控制事务之…...
java int值可以直接赋值给char类型 详解
在 Java 中,int 值可以直接赋值给 char 类型,但有一定的限制和机制。以下是详细的解释: 1. Java 中的 char 和 int 类型关系 char 的本质 char 是一个 16 位无符号整数类型,用于表示 Unicode 字符。范围为 0 到 65535࿰…...
淘宝商品数据获取:Python爬虫技术的应用与实践
引言 随着电子商务的蓬勃发展,淘宝作为中国最大的电商平台之一,拥有海量的商品数据。这些数据对于市场分析、消费者行为研究、商品推荐系统等领域具有极高的价值。然而,如何高效、合法地从淘宝平台获取这些数据,成为了一个技术挑…...
【力扣】389.找不同
问题描述 思路解析 只有小写字母,这种设计参数小的,直接桶排序我最开始的想法是使用两个不同的数组,分别存入他们单个字符转换后的值,然后比较是否相同。也确实通过了 看了题解后,发现可以优化,首先因为t相…...
何时在 SQL 中使用 CHAR、VARCHAR 和 VARCHAR(MAX)
在管理数据库表时,考虑 CHAR、VARCHAR 和 VARCHAR(MAX) 是必不可少的。此外,使用正确的工具(例如dbForge Studio for SQL Server) ,与数据库相关的任务都会变得更加容易。它是针对 SQL Server 专业人员的强大的一体化解…...
pnpm安装electron出现postinstall$ node install.js报错
pnpm install --registryhttp://registry.npm.taobao.org安装依赖包的时候出现了postinstall$ node install.js报错 找到install.js 找到downloadArtifact方法,添加如下代码 mirrorOptions:{mirror:"http://npmmirror.com/mirrors/electron/"}http://n…...