APP烧录测试OK

This commit is contained in:
sunbeam 2025-05-26 10:37:37 +08:00
parent 29dfb90276
commit 7f68333205
16 changed files with 337 additions and 72 deletions

6
.clangd Normal file
View File

@ -0,0 +1,6 @@
CompileFlags:
Add: [
"-isystem", "D:/tool/arm-gnu-toolchain-14.2/arm-none-eabi/include",
"-isystem", "D:/tool/arm-gnu-toolchain-14.2/lib/gcc/arm-none-eabi/14.2.1/include",
"-isystem", "D:/tool/arm-gnu-toolchain-14.2/lib/gcc/arm-none-eabi/14.2.1/include-fixed"
]

View File

@ -25,7 +25,7 @@ set(CMAKE_PROJECT_NAME bootloader)
include("cmake/gcc-arm-none-eabi.cmake")
# Enable compile command to ease indexing with e.g. clangd
set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Core project settings
project(${CMAKE_PROJECT_NAME})
@ -37,6 +37,11 @@ enable_language(C ASM)
# Create an executable object type
add_executable(${CMAKE_PROJECT_NAME})
add_custom_command(TARGET bootloader POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -O ihex $<TARGET_FILE:bootloader> $<TARGET_FILE_DIR:bootloader>/bootloader.hex
COMMENT "Generate HEX file from ELF"
)
# Add STM32CubeMX generated sources
add_subdirectory(cmake/stm32cubemx)

View File

@ -23,6 +23,9 @@
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "appTask.h"
#include "stdio.h"
#include <stdio.h>
#include "bootapp.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
@ -71,7 +74,7 @@ extern UART_HandleTypeDef huart1;
void NMI_Handler(void)
{
/* USER CODE BEGIN NonMaskableInt_IRQn 0 */
printf("NMI_Handler\r\n");
/* USER CODE END NonMaskableInt_IRQn 0 */
/* USER CODE BEGIN NonMaskableInt_IRQn 1 */
while (1)
@ -86,7 +89,8 @@ void NMI_Handler(void)
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
printf("HardFault_Handler\r\n");
bootApp_WriteHardFaultData(0x80000001);
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
@ -101,7 +105,8 @@ void HardFault_Handler(void)
void MemManage_Handler(void)
{
/* USER CODE BEGIN MemoryManagement_IRQn 0 */
printf("MemManage_Handler\r\n");
bootApp_WriteHardFaultData(0x80000002);
/* USER CODE END MemoryManagement_IRQn 0 */
while (1)
{
@ -116,7 +121,8 @@ void MemManage_Handler(void)
void BusFault_Handler(void)
{
/* USER CODE BEGIN BusFault_IRQn 0 */
printf("BusFault_Handler\r\n");
bootApp_WriteHardFaultData(0x80000003);
/* USER CODE END BusFault_IRQn 0 */
while (1)
{
@ -131,7 +137,8 @@ void BusFault_Handler(void)
void UsageFault_Handler(void)
{
/* USER CODE BEGIN UsageFault_IRQn 0 */
printf("UsageFault_Handler\r\n");
bootApp_WriteHardFaultData(0x80000004);
/* USER CODE END UsageFault_IRQn 0 */
while (1)
{

View File

@ -1,6 +1,7 @@
#include "norflash.h"
#include "qspi.h"
#include "stdio.h"
#include <stdint.h>
u16 NORFLASH_TYPE = W25Q64; // 默认是W25Q128
u8 NORFLASH_QPI_MODE = 0; // QSPI模式标志:0,SPI模式;1,QPI模式.
@ -345,6 +346,16 @@ void NORFLASH_Erase_Sector(u32 Dst_Addr)
QSPI_Send_CMD(W25X_SectorErase, Dst_Addr, (0 << 6) | (2 << 4) | (3 << 2) | (3 << 0), 0); // QPI,写扇区擦除指令,地址为0,无数据_24位地址_4线传输地址_4线传输指令,无空周期,0个字节数据
NORFLASH_Wait_Busy(); // 等待擦除完成
}
void NORFLASH_Erase_Block(u32 blockid)
{
uint32_t Dst_Addr = 0;
// printf("fe:%x\r\n",Dst_Addr); //监视falsh擦除情况,测试用
Dst_Addr = 0x1000UL<<blockid;
NORFLASH_Write_Enable(); // SET WEL
NORFLASH_Wait_Busy();
QSPI_Send_CMD(W25X_BlockErase, Dst_Addr, (0 << 6) | (2 << 4) | (3 << 2) | (3 << 0), 0); // QPI,写扇区擦除指令,地址为0,无数据_24位地址_4线传输地址_4线传输指令,无空周期,0个字节数据
//NORFLASH_Wait_Busy(); // 等待擦除完成
}
// 等待空闲
void NORFLASH_Wait_Busy(void)
@ -389,7 +400,7 @@ void norflash_test(void)
printf("\r\ndata read from norflash:\r\n");
for (int i = 0; i < 256; i++)
{
printf("%x\t", *(aspi_addr++));
printf("%lx\t", *(aspi_addr++));
}
printf("\r\n");
}

View File

@ -22,10 +22,13 @@ extern "C"{
#define W25Q256 0XEF18
#define EX_FLASH_START_ADDR 0x90000000
#define EX_FLASH_APPINFO_ADDR 0x90000100
#define EX_FLASH_APP_ADDR 0x90000200
#define EX_FLASH_SIZE 0x00800000
#define EX_FLASH_END_ADDR (EX_FLASH_START_ADDR+EX_FLASH_SIZE)
#define EX_FLASH_CRC_ADDR (EX_FLASH_END_ADDR - 0X100)
#define EX_FLASH_CRC_ADDR EX_FLASH_START_ADDR
#define W26Q64_CRC_ADDR 0
extern u16 NORFLASH_TYPE; //定义W25QXX芯片型号
//////////////////////////////////////////////////////////////////////////////////
@ -82,7 +85,7 @@ void NORFLASH_MemroyMapMode(void);
void NORFLASH_QuitMemroyMapMode(void);
void norflash_test(void);
uint8_t NORFLASH_Check_Busy(void);
void NORFLASH_Erase_Block(u32 blockid);
#ifdef __cplusplus
}

View File

@ -115,7 +115,7 @@ u8 QSPI_Receive(u8* buf,u32 datalen)
u8 QSPI_Transmit(u8* buf,u32 datalen)
{
u32 tempreg=QUADSPI->CCR;
u32 addrreg=QUADSPI->AR;
//u32 addrreg=QUADSPI->AR;
u8 status;
vu32 *data_reg=&QUADSPI->DR;
QUADSPI->DLR=datalen-1; //设置数据传输长度

View File

@ -62,7 +62,9 @@ MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 48K
RAM2 (xrw) : ORIGIN = 0x10000000, LENGTH = 16K
RAM_BOOT (xrw) : ORIGIN = 0x10003FC0, LENGTH = 0x40
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 256K
}
/* Define output sections */
@ -193,6 +195,12 @@ SECTIONS
. = ALIGN(8);
} >RAM
.boot_flags (NOLOAD) :
{
. = ALIGN(4);
KEEP(*(.boot_flags))
. = ALIGN(4);
} >RAM_BOOT
/* Remove information from the standard libraries */

View File

@ -36,6 +36,7 @@
#include "stdio.h"
#include "norflash.h"
#include "uartapp.h"
#include "bootapp.h"
/*---------------------------------------------------------------------------
- D E F I N E S / M A C R O S
----------------------------------------------------------------------------*/
@ -88,6 +89,8 @@ void apptask_init(void)
//norflash_test();
printf("apptask_init finashed\n");
//toggle_led();
bootApp_init();//bootapp_init
}
extern UART_HandleTypeDef huart1;
@ -101,7 +104,8 @@ void apptask_maintask(void)
//1mstsk
uartapp_maintask();
bootApp_mainTask();
if (timebase_counter >= 1000000)
{
timebase_counter = 0;
@ -113,7 +117,7 @@ void apptask_maintask(void)
//toggle_led();
}
if (timebase_counter %1000 == 0)
if (timebase_counter %500 == 0)
{
//HAL_UART_Transmit(&huart1,uart_tx_buf,8,100);
//printf("test\n");

View File

@ -3,7 +3,15 @@
******************************************************************************/
#include "bootapp.h"
#include "norflash.h"
#include "stm32l4xx_hal_crc.h"
#include "stm32l4xx_hal_dma.h"
#include "stm32l4xx_hal_gpio.h"
#include "stm32l4xx_hal_uart.h"
#include "uartapp.h"
#include "stdio.h"
#include "hardware.h"
#include <stdint.h>
#include <stdio.h>
/*******************************************************************************
* the defines
******************************************************************************/
@ -20,11 +28,44 @@ typedef struct
uint32_t AppCRC;
uint32_t reverse;
} APPCRC_type;
typedef struct
{
uint32_t startflag;
uint32_t sBootloader_Req;
uint32_t reboot_times;
uint32_t hardfault_data;
uint32_t reverse[12];
}NO_INIT_DATA_Type;
typedef struct
{
uint8_t reqFlag;
uint8_t eraseState;
uint8_t eraseLen;
uint8_t eraseStep;
}EraseReq_Type;
typedef enum {
BOOT_INIT,
BOOT_WAIT,
BOOT_APP_CHECK,
BOOT_APP_JUMP,
BOOT_STOP,
BOOT_ERASE,
BOOT_STATE_NUM,
}BOOT_STATE_Type;
/*******************************************************************************
* the globals
******************************************************************************/
volatile NO_INIT_DATA_Type noInitData __attribute__((section(".boot_flags")));
static uint8_t bootflag = 0;
static BOOT_STATE_Type bootState = BOOT_INIT;
extern UART_HandleTypeDef huart1;
extern DMA_HandleTypeDef hdma_usart1_rx;
extern CRC_HandleTypeDef hcrc;
static EraseReq_Type eraseReq;
/*******************************************************************************
* the const
******************************************************************************/
@ -32,19 +73,27 @@ typedef struct
/*******************************************************************************
* the functions
******************************************************************************/
static void bootApp_EraseTask(void);
void BspQspiBoot_JumpToApp(void)
static void BspQspiBoot_JumpToApp(void)
{
uint32_t i = 0;
void (*AppJump)(void); /* 声明一个函数指针 */
__IO uint32_t AppAddr = 0x90000000; /* APP 地址 */
__IO uint32_t AppAddr = EX_FLASH_APP_ADDR; /* APP 地址 */
/* 关闭全局中断 */
DISABLE_INT();
/* 设置所有时钟到默认状态使用HSI时钟 */
HAL_RCC_DeInit();
HAL_UART_DeInit(&huart1);
HAL_DMA_DeInit(&hdma_usart1_rx);
HAL_CRC_DeInit(&hcrc);
// __HAL_RCC_SPI1_FORCE_RESET();
// __HAL_RCC_SPI1_RELEASE_RESET();
// HAL_GPIO_DeInit(GPIOB, GPIO_PIN_3|GPIO_PIN_5);
/* 关闭滴答定时器,复位到默认值 */
SysTick->CTRL = 0;
SysTick->LOAD = 0;
@ -82,7 +131,7 @@ void WriteCRCInfo(uint32_t len, uint32_t crc)
appcrc.len = len;
appcrc.AppCRC = crc;
appcrc.reverse = 0xAAAAAAAA;
NORFLASH_Write_NoCheck((uint8_t*)&appcrc, EX_FLASH_CRC_ADDR, 0x10);
NORFLASH_Write_NoCheck((uint8_t*)&appcrc, W26Q64_CRC_ADDR, 0x10);
}
uint8_t ReadCRCInfo(uint32_t* len, uint32_t* crc)
@ -105,7 +154,7 @@ uint8_t Boot_checkApp(void)
uint32_t len, crc;
if (ReadCRCInfo(&len, &crc) == 1)
{
if (crc_calc(EX_FLASH_START_ADDR, len) == crc)
if (crc_calc(EX_FLASH_APPINFO_ADDR, len) == crc)
{
return 1;
}
@ -115,4 +164,160 @@ uint8_t Boot_checkApp(void)
}
}
return 0;
}
}
void bootApp_init(void)
{
if (noInitData.startflag != 0xAA5555AA) {
printf("init bootflag\n");
noInitData.startflag = 0xAA5555AA;
noInitData.sBootloader_Req = 0;
noInitData.reboot_times = 0;
noInitData.hardfault_data = 0;
}
else {
noInitData.reboot_times++;
printf("reboot_times = %d\n", noInitData.reboot_times);
if (noInitData.sBootloader_Req == 0x778899AA) {
noInitData.sBootloader_Req = 0;
bootflag = 1;
}
else {//if(noInitData.sBootloader_Req != 0)
printf("bootreq = %lx\n",noInitData.sBootloader_Req);
}
if (noInitData.hardfault_data != 0) {
printf("hardfault_data = %lx\n", noInitData.hardfault_data);
}
}
}
void bootApp_mainTask(void)//1ms
{
static uint16_t timeout_count = 0,bootkey_delay=0;
switch (bootState) {
case BOOT_INIT: {
bootState = BOOT_WAIT;
break;
}
case BOOT_WAIT: {
if (bootflag == 1) {
bootState = BOOT_STOP;
printf("get_bootreq,stop in boot\n");
break;
}
if (timeout_count++ > 100) {//100ms
timeout_count = 0;
bootState = BOOT_APP_CHECK;
NORFLASH_MemroyMapMode();
break;
}
if (get_BOOTKEY() == 1) {
bootkey_delay++;
if (bootkey_delay > 5) {//5ms
bootkey_delay = 0;
bootState = BOOT_STOP;
printf("get_BOOTKEY,stop in boot\n");
break;
}
}
else {
bootkey_delay = 0;
}
break;
}
case BOOT_APP_CHECK: {
if (Boot_checkApp() == 1) {
bootState = BOOT_APP_JUMP;
break;
}
else {
printf("app not found\n");
NORFLASH_QuitMemroyMapMode();
bootState = BOOT_STOP;
break;
}
}
case BOOT_APP_JUMP: {
printf("jump to app\n");
BspQspiBoot_JumpToApp();
break;
}
case BOOT_STOP: {
timeout_count++;
if (timeout_count >= 10) {//1000ms
timeout_count = 0;
bootApp_EraseTask();
}
break;
}
default: {
break;
}
}
}
void bootApp_WriteHardFaultData(uint32_t data)
{
noInitData.hardfault_data = data;
}
void bootApp_ReqErase(uint8_t block_len)
{
if (block_len > 128) {
printf("block_len error\n");
return;
}
if (eraseReq.eraseState != 0) {
printf("erase is running\n");
return;
}
if (block_len == 0) {
NORFLASH_Erase_Chip();
}
else {
NORFLASH_Erase_Block(0);
}
eraseReq.reqFlag = 1;
eraseReq.eraseState = 1;
eraseReq.eraseLen = block_len;
eraseReq.eraseStep = 0;
}
static void bootApp_EraseTask(void)//10ms task
{
static uint32_t erase_count = 0;
if (eraseReq.reqFlag == 1) {
if (NORFLASH_Check_Busy() == 0) {
eraseReq.eraseStep++;
if (eraseReq.eraseStep > eraseReq.eraseLen) {
eraseReq.reqFlag = 0;
eraseReq.eraseState = 0;
eraseReq.eraseLen = 0;
printf("erase finashed %d ms\n",erase_count*10);
}
else {
NORFLASH_Erase_Block(eraseReq.eraseStep);
}
}
erase_count++;
if (erase_count % 400 == 0) {
printf("wait erase\n");
}
if (erase_count > 3000) {
erase_count = 0;
eraseReq.reqFlag = 0;
eraseReq.eraseState = 0;
eraseReq.eraseLen = 0;
printf("erase timeout\n");
}
}
else {
erase_count = 0;
}
}

View File

@ -30,7 +30,11 @@
******************************************************************************/
void WriteCRCInfo(uint32_t len, uint32_t crc);
uint8_t ReadCRCInfo(uint32_t* len, uint32_t* crc);
void bootApp_init(void);
void bootApp_mainTask(void);
void bootApp_WriteHardFaultData(uint32_t data);
void bootApp_ReqErase(uint8_t block_len);

View File

@ -65,3 +65,7 @@ void toggle_led(void)
HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
}
uint8_t get_BOOTKEY(void)
{
return HAL_GPIO_ReadPin(BOOTKEY_GPIO_Port,BOOTKEY_Pin);
}

View File

@ -57,7 +57,7 @@
- F U N C T I O N P R O T O T Y P E
----------------------------------------------------------------------------*/
void toggle_led(void);
uint8_t get_BOOTKEY(void);
#endif /*DEFINES_NAME*/

View File

@ -46,6 +46,8 @@
#define LCD_BL_GPIO_Port GPIOC
#define LCD_DX_Pin GPIO_PIN_7
#define LCD_DX_GPIO_Port GPIOC
#define BOOTKEY_GPIO_Port GPIOH
#define BOOTKEY_Pin GPIO_PIN_3
/*---------------------------------------------------------------------------
- T Y P E D E F I N I T I O N S

View File

@ -35,6 +35,8 @@
#include "stdio.h"
#include "norflash.h"
#include "hardware.h"
#include "bootapp.h"
#include <stdint.h>
/*---------------------------------------------------------------------------
- D E F I N E S / M A C R O S
----------------------------------------------------------------------------*/
@ -50,7 +52,6 @@ typedef enum
UARTAPP_RXCMD,
UARTAPP_RXSPIDATA,
UARTAPP_STOPRX,
UARTAPP_ERASING,
UARTAPP_CRC,
UARTAPP_STATENUM,
}uartapp_mainstate_type;
@ -59,20 +60,22 @@ typedef enum
CMD31_Idle,
CMD31_Erase,
CMD31_ReqDownload,
CMD31_CRC,
CMD31_WriteCRC,
CMD31_MapMode,
CMD31_CRC,
CMD31_QuitMapMode,
CMD31_MapModeTest,
CMD31_WriteCRC,
CMD31_NUM,
}CMD31_type;
/*---------------------------------------------------------------------------
- S T A T I C V A R I A B L E S
----------------------------------------------------------------------------*/
static uartapp_mainstate_type task_state;
static uint8_t rxCpltFlag = 0,idleReqFlag=0,downloadReqFlag=0,eraseReqFlag = 0;
static uint8_t rxCpltFlag = 0,idleReqFlag=0,downloadReqFlag=0;
static uint8_t rxbuf[512],txbuf[10];
static uint8_t rxbuf[512];
static uint16_t rxsize = 0,timeout_count=0;
static uint32_t writeaddr = 0;
@ -96,13 +99,15 @@ static void uartapp_cmd31(uint8_t *data,uint16_t len);
//重定向用于printf
#if 0
#if __GNUC__
int _write(int fd, char *ptr, int len)
{
(void)fd;
//toggle_led(); // 这里测试是否走通
HAL_UART_Transmit(&huart1, (uint8_t *)ptr, len, HAL_MAX_DELAY);
return len;
}
#else
int __write(int handle, char *buf, int size) {
if (handle == 1 || handle == 2) { // stdout 或 stderr
@ -188,13 +193,6 @@ void uartapp_maintask(void)
HAL_UARTEx_ReceiveToIdle_DMA(&huart1,rxbuf,512);
timeout_count = 0;
}
else if (eraseReqFlag == 1)
{
eraseReqFlag = 0;
task_state = UARTAPP_ERASING;
timeout_count = 0;
}
else
{
maintask_gotoidle();
@ -211,7 +209,7 @@ void uartapp_maintask(void)
if (rxsize > 0)
{
NORFLASH_Write_NoCheck(rxbuf,writeaddr,rxsize);
printf("write 0x%06X,0x%03X,delay %d\n",writeaddr,rxsize,delaytest);
printf("write 0x%06X,0x%03X,delay %lu\n",writeaddr,rxsize,delaytest);
}
HAL_UARTEx_ReceiveToIdle_DMA(&huart1,rxbuf,512);
rxCpltFlag = 0;
@ -232,30 +230,6 @@ void uartapp_maintask(void)
}
break;
case UARTAPP_ERASING:
timeout_count++;
if (timeout_count > 30000)
{
maintask_gotoidle();
printf("erase err timeout\n");
break;
}
if (timeout_count % 100 == 0)
{
if (NORFLASH_Check_Busy() == 0)
{
maintask_gotoidle();
printf("erase success\n");
break;
}
}
if (timeout_count % 4000 == 0)
{
printf("wait erase\n");
}
break;
default:
@ -304,6 +278,9 @@ static void uartapp_cmdpro(uint8_t *data,uint16_t len)
static void uartapp_cmd31(uint8_t *data,uint16_t len)
{
if (len < 1) {
return;
}
CMD31_type subid = data[0];
switch (subid)
{
@ -314,24 +291,42 @@ static void uartapp_cmd31(uint8_t *data,uint16_t len)
if (mapModeFlag == 0)
{
NORFLASH_Erase_Chip();
eraseReqFlag = 1;
printf("erasing Chip\n");
if (len >= 2) {
bootApp_ReqErase(data[1]);
}
else {
bootApp_ReqErase(0);
}
printf("start erase\n");
}
break;
case CMD31_ReqDownload:
writeaddr = 0;
writeaddr = 0x100;
downloadReqFlag = 1;
break;
case CMD31_CRC:
delaytest = 0;
uint32_t starttime = SysTick->VAL;
uint32_t crcvalue = crc_calc(EX_FLASH_START_ADDR,0x32C50);
uint32_t endtime = (SysTick->VAL);
uint32_t usedtime = delaytest*(SysTick->LOAD + 1) + endtime - starttime;
printf("crc= %08X,time=%d\n",crcvalue,usedtime);
printf("starttime= %d,endtime=%d,delaytest=%d\n",starttime,endtime,delaytest);
uint32_t localcrc = 0,locallen = 0;
if (ReadCRCInfo(&locallen,&localcrc)) {
delaytest = 0;
uint32_t starttime = SysTick->VAL;
uint32_t crcvalue = crc_calc(EX_FLASH_APPINFO_ADDR,locallen);
uint32_t endtime = (SysTick->VAL);
uint32_t usedtime = delaytest*(SysTick->LOAD + 1) + endtime - starttime;
printf("crc= %08lX,time=%ld\n",crcvalue,usedtime);
printf("starttime= %ld,endtime=%ld,delaytest=%ld\n",starttime,endtime,delaytest);
if (crcvalue == localcrc) {
printf("crc ok\n");
}
else {
printf("crc err\n");
}
}
else {
printf("no crc info\n");
}
//crcReqFlag = 1;
break;
case CMD31_MapMode:
@ -345,7 +340,15 @@ static void uartapp_cmd31(uint8_t *data,uint16_t len)
norflash_test();
break;
case CMD31_WriteCRC:
if (len == 9) {
uint32_t datalen = (data[1]<<24) | (data[2]<<16) | (data[3]<<8) | data[4];
uint32_t crc = (data[5]<<24) | (data[6]<<16) | (data[7]<<8) | data[8];
WriteCRCInfo(datalen, crc);
printf("write crc ok\n");
}
else {
printf("err len\n");
}
break;
default:
break;

View File

@ -26,7 +26,7 @@ set(TARGET_FLAGS "-mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard ")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${TARGET_FLAGS}")
set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp -MMD -MP")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wpedantic -fdata-sections -ffunction-sections")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wpedantic -fdata-sections -ffunction-sections -Wno-format")
set(CMAKE_C_FLAGS_DEBUG "-O0 -g3")
set(CMAKE_C_FLAGS_RELEASE "-Os -g0")

3
烧录CMAKE.bat Normal file
View File

@ -0,0 +1,3 @@
::pyocd flash --erase chip --target CVM0144 -f 10m .\Debug_FLASH\Exe\cva_bootloader_m0146.hex --pack=.\SDK\CVA.M01.1.7.1.pack -u 000000800671ff515256656767161348a5a5a5a597969908
pyocd flash --erase chip --target stm32l431rctx -f 10m .\build\debug\bootloader.hex -W
pause