网站内容与模板设计方案,代做网页,公司网站制作税目,购买云服务器之后怎么使用从8051到stm32, 从串口下载到JLINK调试#xff0c;从keil到arm-none-eabi-gcc,从Hello wrold到通信协议#xff0c;一路起来已学会很多#xff0c;是时候写一下bootloader了。 基本原理
单片机代码编译完后可以生成.hex和.bin文件从keil到arm-none-eabi-gcc,从Hello wrold到通信协议一路起来已学会很多是时候写一下bootloader了。 基本原理
单片机代码编译完后可以生成.hex和.bin文件而bin文件写入到单片机的FLASH里面单片机就能正常运行了。单片机启动后会从0x0800 0000地址开始运行。bootloader的程序从0x0800 000开始。bootloader功能就是开机在固定时内比如100ms内检测是否需要升级否则跳转到APP地址上。
如何升级
上位机只要把bin文件通过通讯接口串口、USB、WIFI...)发送到单片机单机将收到的bin文件数据存到FLASH里面就能完成升级。bin文件很大单片机RAM不够大不能一次性接收需要将bin拆包。单片机擦除FLASH时需要一定的时间写入速度较快。所以最好只擦除bin需要的大小。单片机需要确保收到的数据是正确的因此需要数据检验。上位机需要查询、写入、擦除、读取、跳转等的功能每次通讯都需要回应以确保成功。
数据包格式
[4byte:CRC][1byte:CMD][1byte:~CMD][2byte:dataSize][nbyte:data]
因为使用空闲中断来收到数据并且通讯都是独占的不会中断因此不需要帧头和帧尾统一使用crc32来校验所是32位的放前面可以更方便来做不定长数据包。FRAME_DATA_SIZE 一般为flash页大小因为需要按页擦除因此擦一页发一页。不同单片机的页大小是不一样的。
struct pack_info
{union{struct{uint32_t crc;uint32_t addr;uint32_t cmd1 : 8;uint32_t cmd2 : 8;uint32_t data_size : 16;uint8_t data[FRAME_DATA_SIZE];};uint8_t buffer[FRAME_DATA_SIZE 12];};uint32_t buffer_size;
}; 固件信息
代码可不能随便刷的否则容易变砖。如果不担心变砖可以不需要这个因此我们需要知道bin文件是针对哪个型号的单片机又是什么型号的。最好还能知道已经刷进去的程序是什么版本的等等因此需要把固件信息存下来。所以要在单片机上分配块FLASH页面而bin文件上又保存这些信息呢总不能上传时再输入吧。 typedef union bootloader
{struct{uint32_t infoCrc;//固件信息校验uint32_t magic;//固件信息标志固定为0x5A1234A5代码里写入uint32_t start_addr;//固件起始地址uint32_t size;//固件大小uint32_t FWcrc;//固件校验uint32_t version;//版本号格式为主版本号.子版本号.编译号.序号uint32_t pid;//产品ID格式为主板ID.核心ID.产品ID.功能IDuint32_t date;//编译日期uint32_t bootTimes;//启动次数AT32_MCU_TYPE whoAmI;char name[256];//固件名称代码里写入后面再改也行};uint8_t buffer[FLASH_SectorSize];
} firmware_info_t;
FLASH分区 以AT32F413RCT7为例它FLASH大小为256kb,页大小为2kb。数据手册上有。
代码从0x0800 000开始如果只用串口通讯则bootloader程序约为4kb,如果使用USB通讯则会有14kb左右以编译器为准。因为FLASH划分为如下
【bootloader区】【固件信息区】【用户代码区】【用户配置区0】【用户配置区1】
/*** brief* TOTAL FLASH SIZE: 256Kb* [Bloader:0-14Kb][FWINFO:14-16Kb][APP:16-252Kb][CONFIG0:252-254Kb][CONFIG2:254-256Kb]*/
#define FLASH_SECTOR_COUNT 128
#define FLASH_SectorSize (uint32_t)2048
#define FLASH_Base_Addr (uint32_t)0x08000000
#define FLASH_IAP_Size (uint32_t)0x4000 // 0x08004000~0x0800FFFF
#define FLASH_APP_ADDR (uint32_t)(FLASH_Base_Addr | FLASH_IAP_Size)#define FLASH_TOTAL_SIZE (FLASH_SECTOR_COUNT * FLASH_SectorSize)
#define FLASH_END_ADDR (FLASH_Base_Addr FLASH_TOTAL_SIZE)#define FLASH_APP_END_ADDR (FLASH_END_ADDR - FLASH_SectorSize * 2)
#define FLASH_APP_SIZE (FLASH_TOTAL_SIZE - FLASH_SectorSize * 3 - FLASH_IAP_Size)#define FLASH_FWINFO_ADDR (FLASH_APP_ADDR - FLASH_SectorSize)
#define FLASH_CONFIG_ADDR0 (FLASH_APP_END_ADDR FLASH_SectorSize)
#define FLASH_CONFIG_ADDR1 (FLASH_CONFIG_ADDR0 FLASH_SectorSize)
*.ld文件数据分区 ld文件是编译器编译代码时用来划分数据对应flash位置的gcc编译器才有的。可以将代码的数据安排到指定FLASH位置上。
bootlader的*.ld文件 只要改变memory就分配完了整个bootlaoder程序不能超过16Kb.如下
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN 0x08000000, LENGTH 14K
FWINFO (rx) : ORIGIN 0x08003800, LENGTH 2K
RAM (xrw) : ORIGIN 0x20000000, LENGTH 32K
SPIM (rx) : ORIGIN 0x08400000, LENGTH 16384K
}
APP的*.ld文件
分配flash
/* Program Entry, set to mark it as used and avoid gc */
MEMORY
{
FWINFO (rx) : ORIGIN 0x08003800,LENGTH 2k
ROM (rx) : ORIGIN 0x08004000,LENGTH 236k
RAM (rw) : ORIGIN 0x20000000,LENGTH 32k
}
将变量分配到flash上
SECTIONS
{.firemware_info : ALIGN(4){KEEP(*(firemware_info))} FWINFO 定义固件信息
#include bootloader.h
const firmware_info_t zino_firemware_info __attribute__((section(firemware_info))) {.infoCrc ~FLASH_FW_MAGIC,.magic FLASH_FW_MAGIC,.start_addr 0x08004000,.size 0,.FWcrc 0,.version VESION2INT(0,0,0,1),.pid PID2INT(1,2,3,4),.name ZINO Digital Power Supply V0.1,.date DATE2INT(2024,11,19),.whoAmI.ID 0x30240,.whoAmI.Serial AT32F413xxx7,.whoAmI.Model__AT32F413RCT7,.whoAmI.Flash _256KB,.whoAmI.Footprint LQFP64,
}; 这样编译好后bin文件的前2kb就是固件信息的结构体数据 bin文件可以查看 添加固件校验值 bin文件被编译完成后并不会自己计算固件信息里面的固件CRC,因此需要另一个程序来计算这个值并重新写入到固件里面。这样就能得到一个带有校验值、MCU型号、程序版本等等的固件了。
固件生成工具 只需要会一点c语言就行fopen bin文件读取前面一部分固件信息再把后一部分真正的代码计算出CRC32,然后再写回去生成一个新的文件。。。用gcc编译超方便的 ~~~
/** Author: LVGRAPE* LastEditors: LVGRAPE*/
#include bootloader.h
#include stdio.h
#include stdlib.h
#include string.h
#include stdbool.h#define CRC32_INIT_VALUE 0xFFFFFFFF
#define CRC32_XOR_VALUE 0xFFFFFFFFuint32_t crc32_cal(const uint8_t *pdata, int32_t len, uint32_t initial, uint32_t finalXor, bool inputReflected, bool resultReflected);/*** brief* make -f ./win_iap_tool/firminfo.mk* ./win_iap_tool/makefirmware.exe ./win_iap_tool/ZINO_FC_V4_V1.0.1_20241115.bin test* param argc* param argv* return int*/
int main(int argc, char *argv[])
{char *newName NULL;if (argc 2){printf(Usage: %s *.bin newName(optional) %d\n, argv[0], argc);return -1;}if (argc 3){newName argv[2];}firmware_info_t firmInfo;at32_mcu_init_model(firmInfo.whoAmI, argv[1]);FILE *fw fopen(argv[1], rb);if (fw NULL){printf(open file error\n);return -1;}size_t thisRead fread(firmInfo, 1, sizeof(firmInfo), fw);if (thisRead ! sizeof(firmInfo)){printf(read firmInfo size error\n);return -1;}printf(name:%s\n, firmInfo.name);printf(infoCrc: 0x%08X\n, firmInfo.infoCrc);printf(magic: 0x%08X\n, firmInfo.magic);printf(startAddr: 0x%08X\n, firmInfo.start_addr);printf(size: 0x%08X\n, firmInfo.size);printf(version: 0x%08X\n, firmInfo.version);printf(pid: 0x%08X\n, firmInfo.pid);printf(date: 0x%08X\n, firmInfo.date);printf(Serial: 0x%08X\n, firmInfo.whoAmI.Serial);printf(ID: 0x%08X\n, firmInfo.whoAmI.ID);printf(Model: 0x%08X, %s\n, firmInfo.whoAmI.Model, at32_mcu_mode2str(firmInfo.whoAmI));printf(Flash: 0x%08X, %s\n, firmInfo.whoAmI.Flash, at32_mcu_flash2str(firmInfo.whoAmI));printf(Footprint: 0x%08X, %s\n, firmInfo.whoAmI.Footprint, at32_mcu_footprint2str(firmInfo.whoAmI));if (firmInfo.magic ! FLASH_FW_MAGIC firmInfo.infoCrc ! ~FLASH_FW_MAGIC){printf(firmware magic error\n);return -1;}if (firmInfo.whoAmI.Model AT32_MCU_MODEL_COUNT){printf(mcu model unknow!\n);return -1;}AT32_MCU_TYPE mcuType AT32_MCU_LIST[firmInfo.whoAmI.Model];if (mcuType.Model ! firmInfo.whoAmI.Model){printf(mcu model error!\n);return -1;}if (mcuType.Flash ! firmInfo.whoAmI.Flash){printf(mcu flash error!\n);return -1;}if (mcuType.Footprint ! firmInfo.whoAmI.Footprint){printf(mcu footprint error!\n);return -1;}if (mcuType.Serial ! firmInfo.whoAmI.Serial){printf(mcu Serial error!\n);return -1;}if (mcuType.ID ! firmInfo.whoAmI.ID){printf(mcu ID error!\n);return -1;}fseek(fw, 0, SEEK_SET);fseek(fw, 0, SEEK_END);size_t fwSize ftell(fw);size_t fwTotalsize fwSize - sizeof(firmInfo);size_t fwEndAddr firmInfo.start_addr firmInfo.size;fseek(fw, 0, SEEK_SET);printf(fwTotalsize(without fwInfo): 0x%08X\n, fwTotalsize);size_t flashToalSize at32_mcu_flash_size[firmInfo.whoAmI.Flash];size_t flashEndAddr FLASH_Base_Addr flashToalSize;printf(flashToalSize: %d,[0x%08X-0x%08X]\n, flashToalSize, FLASH_Base_Addr, flashEndAddr);if (fwEndAddr flashEndAddr){printf(firmware size overflow!\n);return -1;}firmInfo.size fwTotalsize;uint8_t *fwBuf (uint8_t *)malloc(fwSize);thisRead fread(fwBuf, 1, fwSize, fw);if (thisRead ! fwSize){printf(firmware read fwSize error!\n);return -1;}/**use new name */if (newName){memset(firmInfo.name, 0, sizeof(firmInfo.name));memcpy(firmInfo.name, newName, strlen(newName));printf(get new name: %s\n, firmInfo.name);}char *newFwname;size_t newFwnameLen strlen(firmInfo.name);const char *src firmInfo.name;if(strcmp(src[newFwnameLen - 4], .bin) ! 0){newFwname (char *)malloc(newFwnameLen 5);strcpy(newFwname, src);strcat(newFwname, .bin);printf(newFwname: %s\n, newFwname);}else{newFwname (char *)malloc(newFwnameLen 1);strcpy(newFwname, src);printf(newFwname: %s\n, newFwname);}/**update fw crc, info crc */firmInfo.FWcrc crc32_cal(fwBuf[FLASH_SectorSize], fwTotalsize, CRC32_INIT_VALUE, CRC32_XOR_VALUE, 1, 1);firmInfo.infoCrc crc32_cal((const uint8_t *)firmInfo4, sizeof(firmInfo) - 4, CRC32_INIT_VALUE, CRC32_XOR_VALUE, 1, 1);printf(FWcrc: 0x%08X, infoCrc:0x%08X\n, firmInfo.FWcrc, firmInfo.infoCrc);/**updata firmInfo with crc*/memcpy(fwBuf, firmInfo, sizeof(firmInfo));/**write new firmware */FILE *fwOut fopen(newFwname, wb);if (!fwOut){printf(new firmware creat error!\n);return -1;}size_t thisWrite fwrite(fwBuf, 1, fwSize, fwOut);if (thisWrite ! fwSize){printf(firmware write fwSize error!\n);return -1;}printf(Success! New: %s\n, newFwname);fclose(fwOut);free(fwBuf);return 0;
}运行结果
make firmare
./UploadTool/makeFirmware.exe ./build/ZINO_POWER_V1.0.1_20250110.bin ZINO_DPS_ZINO_POWER_V1.0.1_20250110.bin
name:ZINO Digital Power Supply V0.1
infoCrc: 0xA5EDCB5A
magic: 0x5A1234A5
startAddr: 0x08004000
size: 0x00000000
version: 0x00000001
pid: 0x01020304
date: 0x07E80B13
Serial: 0x00000047
ID: 0x00030240
Model: 0x0000000F, AT32F413RCT7
Flash: 0x00000002, 256KB
Footprint: 0x00000003, LQFP64
fwTotalsize(without fwInfo): 0x00015EFC
flashToalSize: 262144,[0x08000000-0x08040000]
get new name: ZINO_DPS_ZINO_POWER_V1.0.1_20250110.bin
newFwname: ZINO_DPS_ZINO_POWER_V1.0.1_20250110.bin
FWcrc: 0xFF0BC36F, infoCrc:0x40693BE8
Success! New: ZINO_DPS_ZINO_POWER_V1.0.1_20250110.bin
单片机型号信息 at32单片机上有一个装置存储了具体的型号信息可以读出来. 文档找不到了可找他们工程师要。我把他们当时的型号都搞进来了。可以通过读flash识别出来型号。可以通过型号来定义单片机。固件生成时通过型号来定义单片机那么固件信息就带型号了。烧录时通过读flash来识别型号那可以知道固件和单片机匹配与否了。
/** Author: LVGRAPE* LastEditors: LVGRAPE*/
/** Author: LVGRAPE* LastEditors: LVGRAPE*/#pragma once#ifdef __cplusplusextern C {
#endif#include stdint.h
typedef uint32_t AT32_MCU_ID;
typedef enum
{AT32F403xxx6 0x27, //0X27,AT32F413xxx7 0x47, //0X47,AT32F415xxx7 0x57, //0X57,AT32F403Axxx7 0x77, //0X77,AT32F407xxx7 0x87, //0X87,
} AT32_MCU_Serial;typedef enum AT32_MCU_MODEL_LIST
{__AT32F403ZCT6 0,__AT32F403VCT6,__AT32F403RCT6,__AT32F403CCT6,__AT32F403ZGT6,__AT32F403VGT6,__AT32F403RGT6,__AT32F403CGT6,__AT32F403ZET6,__AT32F403VET6,__AT32F403RET6,__AT32F403CET6,__AT32F403CGU6,__AT32F403CEU6,__AT32F403CCU6,__AT32F413RCT7,__AT32F413RBT7,__AT32F413CCT7,__AT32F413CBT7,__AT32F413KCU7_4,__AT32F413KBU7_4,__AT32F413C8T7,__AT32F413CCU7,__AT32F413CBU7,__AT32F415RCT7,__AT32F415CCT7,__AT32F415KCU7_4,__AT32F415RCT7_7,__AT32F415RBT7,__AT32F415CBT7,__AT32F415KBU7_4,__AT32F415RBT7_7,__AT32F415R8T7,__AT32F415C8T7,__AT32F415R8T7_7,__AT32F415K8U7_4,__AT32F415CBU7,__AT32F415CCU7,__AT32F403AVCT7,__AT32F403ARCT7,__AT32F403ACCT7,__AT32F403ACCU7,__AT32F403AVGT7,__AT32F403ARGT7,__AT32F403ACGT7,__AT32F403ACGU7,__AT32F403AVET7,__AT32F403ARET7,__AT32F403ACET7,__AT32F403ACEU7,__AT32F407VCT7,__AT32F407RCT7,__AT32F407VGT7,__AT32F407RGT7,__AT32F407VET7,__AT32F407RET7,AT32_MCU_MODEL_COUNT,
} AT32_MCU_MODEL;
typedef enum
{_64KB 0,_128KB,_256KB,_512KB,_1024KB,AT32_MCU_FLASH_COUNT,
} AT32_MCU_FLASH;
typedef enum
{QFN32 0,QFN48,LQFP48,LQFP64,LQFP100,LQFP144,AT32_MCU_Footprint_COUNT,
} AT32_MCU_Footprint;
typedef struct mcuInfo
{AT32_MCU_Serial Serial:8;AT32_MCU_ID ID;AT32_MCU_MODEL Model:8;AT32_MCU_FLASH Flash:8;AT32_MCU_Footprint Footprint:8;uint8_t UID[12];
} AT32_MCU_TYPE;
typedef enum
{Cortex_M0_r0p0 0,Cortex_M0plus_r0p0,Cortex_M1_r0p0,Cortex_M1_r0p1,Cortex_M1_r1p0,Cortex_M3_r0p0,Cortex_M3_r1p0,Cortex_M3_r1p1,Cortex_M3_r2p0,Cortex_M3_r2p1,Cortex_M4_r0p0,Cortex_M4_r0p1,Cortex_count,
}AT32_MCU_Cortex;typedef struct at32_mcu_core_info
{AT32_MCU_Cortex core;uint32_t id;
}at32_mcu_core;#define AT32MCU_FOREACH(x) for (uint8_t(x) 0; (x) AT32_MCU_MODEL_COUNT; (x))#define MCU_UNIQUE_96BIT_ID_BASE_ADDR_31_0 ((uint32_t)0x1FFFF7E8)
#define MCU_UNIQUE_96BIT_ID_BASE_ADDR_63_32 ((uint32_t)0x1FFFF7EC)
#define MCU_UNIQUE_96BIT_ID_BASE_ADDR_95_64 ((uint32_t)0x1FFFF7F0)
#define AT32_MCU_SERIAL_ADDR 0x1FFFF7F3
#define AT32_MCU_PID_BASE_ADDR 0xE0042000
#define AT32_MCU_SERIAL_ID (*(uint8_t*)AT32_MCU_SERIAL_ADDR)
#define AT32_MCU_PID (*(uint32_t*)AT32_MCU_PID_BASE_ADDR)extern const char AT32_MCU_Cortex_str[Cortex_count1][16];
extern const AT32_MCU_TYPE AT32_MCU_LIST[AT32_MCU_MODEL_COUNT];
extern const char AT32_MCU_Model_str[AT32_MCU_MODEL_COUNT 1][16];
extern const char AT32_MCU_FLASH_str[AT32_MCU_FLASH_COUNT 1][8];
extern const char AT32_MCU_Footprint_str[AT32_MCU_Footprint_COUNT 1][8];
extern const uint32_t at32_mcu_flash_size[AT32_MCU_FLASH_COUNT];
extern AT32_MCU_TYPE whoAmI;
// char *at32_mcu_core2str(at32_mcu_core *core);
char *at32_mcu_mode2str(AT32_MCU_TYPE *mcu);
char *at32_mcu_flash2str(AT32_MCU_TYPE *mcu);
char *at32_mcu_footprint2str(AT32_MCU_TYPE *mcu);
char *at32_mcu_core2str(uint32_t id);
uint32_t at32_mcu_get_coreID(void);
uint8_t at32_mcu_who_am_i(AT32_MCU_TYPE *mcu);
uint8_t at32_mcu_init_model(AT32_MCU_TYPE *mcu, char *model);
#ifdef __cplusplus}
#endif/** Author: LVGRAPE* LastEditors: LVGRAPE*/
/** Author: LVGRAPE* LastEditors: LVGRAPE*/
#include AT32Models.h
#include string.h
// #include USART_Configuration.h
const AT32_MCU_TYPE AT32_MCU_LIST[AT32_MCU_MODEL_COUNT] {{0x27, 0x50240, __AT32F403ZCT6, _256KB, LQFP144},{0x27, 0x50241, __AT32F403VCT6, _256KB, LQFP100},{0x27, 0x50242, __AT32F403RCT6, _256KB, LQFP64},{0x27, 0x50243, __AT32F403CCT6, _256KB, LQFP48},{0x27, 0x50344, __AT32F403ZGT6, _1024KB, LQFP144},{0x27, 0x50345, __AT32F403VGT6, _1024KB, LQFP100},{0x27, 0x50346, __AT32F403RGT6, _1024KB, LQFP64},{0x27, 0x50347, __AT32F403CGT6, _1024KB, LQFP48},{0x27, 0x502C8, __AT32F403ZET6, _512KB, LQFP144},{0x27, 0x502C9, __AT32F403VET6, _512KB, LQFP100},{0x27, 0x502CA, __AT32F403RET6, _512KB, LQFP64},{0x27, 0x502CB, __AT32F403CET6, _512KB, LQFP48},{0x27, 0x5034C, __AT32F403CGU6, _1024KB, QFN48},{0x27, 0x502CD, __AT32F403CEU6, _512KB, QFN48},{0x27, 0x5024E, __AT32F403CCU6, _256KB, QFN48},{0x47, 0x30240, __AT32F413RCT7, _256KB, LQFP64},{0x47, 0x301C1, __AT32F413RBT7, _128KB, LQFP64},{0x47, 0x30242, __AT32F413CCT7, _256KB, LQFP48},{0x47, 0x301C3, __AT32F413CBT7, _128KB, LQFP48},{0x47, 0x30244, __AT32F413KCU7_4, _256KB, QFN32},{0x47, 0x301C5, __AT32F413KBU7_4, _128KB, QFN32},{0x47, 0x30106, __AT32F413C8T7, _64KB, LQFP48},{0x47, 0x30247, __AT32F413CCU7, _256KB, QFN48},{0x47, 0x301C0, __AT32F413CBU7, _128KB, QFN48},{0x57, 0x30240, __AT32F415RCT7, _256KB, LQFP64},{0x57, 0x30241, __AT32F415CCT7, _256KB, LQFP48},{0x57, 0x30242, __AT32F415KCU7_4, _256KB, QFN32},{0x57, 0x30243, __AT32F415RCT7_7, _256KB, LQFP64},{0x57, 0x301C4, __AT32F415RBT7, _128KB, LQFP64},{0x57, 0x301C5, __AT32F415CBT7, _128KB, LQFP48},{0x57, 0x301C6, __AT32F415KBU7_4, _128KB, QFN32},{0x57, 0x301C7, __AT32F415RBT7_7, _128KB, LQFP64},{0x57, 0x30108, __AT32F415R8T7, _64KB, LQFP64},{0x57, 0x30109, __AT32F415C8T7, _64KB, LQFP48},{0x57, 0x3010B, __AT32F415R8T7_7, _64KB, QFN32},{0x57, 0x3010A, __AT32F415K8U7_4, _64KB, LQFP64},{0x57, 0x301CD, __AT32F415CBU7, _128KB, QFN48},{0x57, 0x3024C, __AT32F415CCU7, _256KB, QFN48},{0x77, 0x50240, __AT32F403AVCT7, _256KB, LQFP100},{0x77, 0x50241, __AT32F403ARCT7, _256KB, LQFP64},{0x77, 0x50242, __AT32F403ACCT7, _256KB, LQFP48},{0x77, 0x50243, __AT32F403ACCU7, _256KB, QFN48},{0x77, 0x50344, __AT32F403AVGT7, _1024KB, LQFP100},{0x77, 0x50345, __AT32F403ARGT7, _1024KB, LQFP64},{0x77, 0x50346, __AT32F403ACGT7, _1024KB, LQFP48},{0x77, 0x50347, __AT32F403ACGU7, _1024KB, QFN48},{0x77, 0x502CD, __AT32F403AVET7, _512KB, LQFP100},{0x77, 0x502CE, __AT32F403ARET7, _512KB, LQFP64},{0x77, 0x503CF, __AT32F403ACET7, _512KB, LQFP48},{0x77, 0x503D0, __AT32F403ACEU7, _512KB, QFN48},{0x87, 0x50249, __AT32F407VCT7, _256KB, LQFP100},{0x87, 0x5024A, __AT32F407RCT7, _256KB, LQFP64},{0x87, 0x5034B, __AT32F407VGT7, _1024KB, LQFP100},{0x87, 0x5034C, __AT32F407RGT7, _1024KB, LQFP64},{0x87, 0x502D1, __AT32F407VET7, _512KB, LQFP100},{0x87, 0x502D2, __AT32F407RET7, _512KB, LQFP64},
};
const uint32_t at32_mcu_flash_size[AT32_MCU_FLASH_COUNT]
{0x10000,0x20000,0x40000,0x80000,0x100000,
};
const char AT32_MCU_Model_str[AT32_MCU_MODEL_COUNT 1][16] {AT32F403ZCT6,AT32F403VCT6,AT32F403RCT6,AT32F403CCT6,AT32F403ZGT6,AT32F403VGT6,AT32F403RGT6,AT32F403CGT6,AT32F403ZET6,AT32F403VET6,AT32F403RET6,AT32F403CET6,AT32F403CGU6,AT32F403CEU6,AT32F403CCU6,AT32F413RCT7,AT32F413RBT7,AT32F413CCT7,AT32F413CBT7,AT32F413KCU7-4,AT32F413KBU7-4,AT32F413C8T7,AT32F413CCU7,AT32F413CBU7,AT32F415RCT7,AT32F415CCT7,AT32F415KCU7-4,AT32F415RCT7-7,AT32F415RBT7,AT32F415CBT7,AT32F415KBU7-4,AT32F415RBT7-7,AT32F415R8T7,AT32F415C8T7,AT32F415R8T7-7,AT32F415K8U7-4,AT32F415CBU7,AT32F415CCU7,AT32F403AVCT7,AT32F403ARCT7,AT32F403ACCT7,AT32F403ACCU7,AT32F403AVGT7,AT32F403ARGT7,AT32F403ACGT7,AT32F403ACGU7,AT32F403AVET7,AT32F403ARET7,AT32F403ACET7,AT32F403ACEU7,AT32F407VCT7,AT32F407RCT7,AT32F407VGT7,AT32F407RGT7,AT32F407VET7,AT32F407RET7,unknown,
};
const char AT32_MCU_FLASH_str[AT32_MCU_FLASH_COUNT 1][8] {64KB,128KB,256KB,512KB,1024KB,unknown,
};
const char AT32_MCU_Footprint_str[AT32_MCU_Footprint_COUNT 1][8] {QFN32,QFN48,LQFP48,LQFP64,LQFP100,LQFP144,unknown,
};
const char AT32_MCU_Cortex_str[Cortex_count 1][16] {Cortex-M0-r0p0,Cortex-M0-r0p0,Cortex-M1-r0p1,Cortex-M1-r0p1,Cortex-M1-r1p0,Cortex-M3-r0p0,Cortex-M3-r1p0,Cortex-M3-r1p1,Cortex-M3-r2p0,Cortex-M3-r2p1,Cortex-M4-r0p0,Cortex-M4-r0p1,unknown,
};
const uint32_t AT32_MCU_CORE_ID[Cortex_count] {0x410CC200,0x410CC600,0x410CC210,0x410CC211,0x411CC210,0x410FC230,0x410FC231,0x411FC231,0x412FC230,0x412FC231,0x410FC240,0x410FC241,};
char *at32_mcu_mode2str(AT32_MCU_TYPE *mcu)
{if (mcu-Model AT32_MCU_MODEL_COUNT)return (char *)AT32_MCU_Model_str[mcu-Model];elsereturn (char *)AT32_MCU_Model_str[AT32_MCU_MODEL_COUNT];
}
char *at32_mcu_flash2str(AT32_MCU_TYPE *mcu)
{if (mcu-Flash AT32_MCU_FLASH_COUNT)return (char *)AT32_MCU_FLASH_str[mcu-Flash];elsereturn (char *)AT32_MCU_FLASH_str[AT32_MCU_FLASH_COUNT];
}
char *at32_mcu_footprint2str(AT32_MCU_TYPE *mcu)
{if (mcu-Footprint AT32_MCU_Footprint_COUNT)return (char *)AT32_MCU_Footprint_str[mcu-Footprint];elsereturn (char *)AT32_MCU_Footprint_str[AT32_MCU_Footprint_COUNT];
}
uint8_t at32_mcu_who_am_i(AT32_MCU_TYPE *mcu)
{uint8_t serial AT32_MCU_SERIAL_ID;uint32_t id AT32_MCU_PID;serial ((id 28) | (serial 4));id id 0xFFFFF;// usartPrintf(s:%d - id:%d\n\n, serial, id);AT32MCU_FOREACH(i){// usartPrintf(s:%d - %d\n\n, AT32_MCU_LIST[i].Serial, AT32_MCU_LIST[i].ID);if ((AT32_MCU_LIST[i].Serial serial) (AT32_MCU_LIST[i].ID id)){mcu-Serial serial;mcu-ID id;mcu-Model AT32_MCU_LIST[i].Model;mcu-Flash AT32_MCU_LIST[i].Flash;mcu-Footprint AT32_MCU_LIST[i].Footprint;return 0;}}mcu-Serial serial;mcu-ID id;mcu-Model AT32_MCU_MODEL_COUNT;mcu-Flash AT32_MCU_Footprint_COUNT;mcu-Footprint AT32_MCU_Footprint_COUNT;return 1;
}
uint32_t at32_mcu_get_coreID(void)
{/*内核的系统控制块SCB 中存在一个名为CPU ID基本寄存器的寄存器 它是只读的 其中包括处理器类型和版本号。该寄存器的地址为0XE000ED00只支持特权访问在程序中 可以利用SCB-CPUID访问该寄存器也可通过绝对地址访问如*(uint32_t *)0xE000ED00。*/return *(uint32_t *)0xE000ED00;
}
char *at32_mcu_core2str(uint32_t id)
{for (uint16_t i 0; i Cortex_count; i){if (id AT32_MCU_CORE_ID[i])return (char *)AT32_MCU_Cortex_str[i];}return (char *)AT32_MCU_Cortex_str[Cortex_count];
}
uint8_t at32_mcu_init_model(AT32_MCU_TYPE *mcu, char *model)
{for(uint16_t i 0; i AT32_MCU_MODEL_COUNT; i){if(strcmp(model, AT32_MCU_Model_str[i]) 0){memcpy(mcu, AT32_MCU_LIST[i], sizeof(AT32_MCU_TYPE));return 0;}}mcu-Serial 0;mcu-ID 0;mcu-Model AT32_MCU_MODEL_COUNT;mcu-Flash AT32_MCU_Footprint_COUNT;mcu-Footprint AT32_MCU_Footprint_COUNT;return 1;
}BOOTLOADER程序
通过以上信息整理我们就能知道bootloader需要一些什么操作了
typedef struct bootloader_info
{uint32_t version;uint32_t currentAddr;uint32_t totalSize;uint32_t SizeLeft;uint32_t timeOut;uint32_t dt;uint32_t appAddr;uint32_t appSize;uint32_t fwInfoAddr;uint32_t sectorSize : 16;uint32_t sectorCount : 16;uint16_t (*read)(uint8_t *buf);uint16_t (*write)(uint8_t *buf, uint16_t len);uint32_t (*millis)(void);void (*flashLock)(void);void (*flashUnlock)(void);void (*flashSectorErase)(uint32_t addr);void (*flashRead)(uint32_t addr, uint8_t *buf, uint32_t len);void (*flashWrite)(uint32_t addr, uint8_t *buf, uint32_t len);void (*jumpToAddr)(uint32_t addr);void (*reset)(void);struct pack_info pack;firmware_info_t fw_info;AT32_MCU_TYPE whoAmI;bool synecd;
} bl_info_t; 程序跳转
我这里用了usb,需要关闭usb,不然usb硬件还在和电脑连接cpu又不在了会出大事。
typedef void (*iapfun)(void);
volatile iapfun jump2app;
void IAP_Load_APP(uint32_t appxaddr)
{SysTick-CTRL 0; // stop systickusbd_disconnect(usb_core_dev);crm_periph_clock_enable(CRM_USB_PERIPH_CLOCK, FALSE);crm_periph_clock_enable(CRM_GPIOD_PERIPH_CLOCK, FALSE);nvic_irq_disable(USBFS_L_CAN1_RX0_IRQn);__disable_irq();jump2app (iapfun) (* (volatile uint32_t *)(appxaddr 4)); // 用户代码区第二个字为程序开始地址(复位地址)__set_MSP(*(volatile uint32_t *)appxaddr);__set_PSP(*(volatile uint32_t *)appxaddr); //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)__set_CONTROL(0);jump2app(); // 跳转到APP.
}
单片机bootloader代码
/** Author: LVGRAPE* LastEditors: LVGRAPE*/#ifndef __BOOTLOADER_H
#define __BOOTLOADER_H
#include stdint.h
#include stdbool.h
#include AT32Models.h#define Version_ID1 0x10
#define Version_ID2 0x1C/*** brief* TOTAL FLASH SIZE: 256Kb* [Bloader:0-14Kb][FWINFO:14-16Kb][APP:16-252Kb][CONFIG0:252-254Kb][CONFIG2:254-256Kb]*/
#define FLASH_SECTOR_COUNT 128
#define FLASH_SectorSize (uint32_t)2048
#define FLASH_Base_Addr (uint32_t)0x08000000
#define FLASH_IAP_Size (uint32_t)0x4000 // 0x08004000~0x0800FFFF
#define FLASH_APP_ADDR (uint32_t)(FLASH_Base_Addr | FLASH_IAP_Size)#define FLASH_TOTAL_SIZE (FLASH_SECTOR_COUNT * FLASH_SectorSize)
#define FLASH_END_ADDR (FLASH_Base_Addr FLASH_TOTAL_SIZE)#define FLASH_APP_END_ADDR (FLASH_END_ADDR - FLASH_SectorSize * 2)
#define FLASH_APP_SIZE (FLASH_TOTAL_SIZE - FLASH_SectorSize * 3 - FLASH_IAP_Size)#define FLASH_FWINFO_ADDR (FLASH_APP_ADDR - FLASH_SectorSize)
#define FLASH_CONFIG_ADDR0 (FLASH_APP_END_ADDR FLASH_SectorSize)
#define FLASH_CONFIG_ADDR1 (FLASH_CONFIG_ADDR0 FLASH_SectorSize)#define FRAME_DATA_SIZE 2048
#define FLASH_FW_MAGIC 0x5A1234A5#define VESION2INT(MAIN, SUB, BUILD, NUM) (uint32_t)(((MAIN) 24) | ((SUB) 16) | ((BUILD) 8) | (NUM))
#define PID2INT(board, core, product, function) (uint32_t)(((board) 24) | ((core) 16) | ((product) 8) | (function))
#define DATE2INT(YEAR, MONTH, DAY) (uint32_t)(((YEAR) 16) | ((MONTH) 8) | (DAY))
enum
{CMD_SYNC 0XF4,CMD_ACK 0XAF,CMD_NACK 0XFC,CMD_VERSION 0X01,CMD_GETID 0X02,CMD_WRITE 0X03,CMD_READ 0X04,CMD_RESET 0X05,CMD_JUMP 0X06,CMD_ERASE 0X07,CMD_W_FW_INFO 0X08,CMD_R_FW_INFO 0X09,CMD_LOG 0X0A,
};typedef union bootloader
{struct{uint32_t infoCrc;//固件信息校验uint32_t magic;//固件信息标志固定为0x5A1234A5代码里写入uint32_t start_addr;//固件起始地址uint32_t size;//固件大小uint32_t FWcrc;//固件校验uint32_t version;//版本号格式为主版本号.子版本号.编译号.序号uint32_t pid;//产品ID格式为主板ID.核心ID.产品ID.功能IDuint32_t date;//编译日期uint32_t bootTimes;//启动次数AT32_MCU_TYPE whoAmI;char name[256];//固件名称代码里写入后面再改也行};uint8_t buffer[FLASH_SectorSize];
} firmware_info_t;struct pack_info
{union{struct{uint32_t crc;uint32_t addr;uint32_t cmd1 : 8;uint32_t cmd2 : 8;uint32_t data_size : 16;uint8_t data[FRAME_DATA_SIZE];};uint8_t buffer[FRAME_DATA_SIZE 12];};uint32_t buffer_size;
};
typedef struct bootloader_info
{uint32_t version;uint32_t currentAddr;uint32_t totalSize;uint32_t SizeLeft;uint32_t timeOut;uint32_t dt;uint32_t appAddr;uint32_t appSize;uint32_t fwInfoAddr;uint32_t sectorSize : 16;uint32_t sectorCount : 16;uint16_t (*read)(uint8_t *buf);uint16_t (*write)(uint8_t *buf, uint16_t len);uint32_t (*millis)(void);void (*flashLock)(void);void (*flashUnlock)(void);void (*flashSectorErase)(uint32_t addr);void (*flashRead)(uint32_t addr, uint8_t *buf, uint32_t len);void (*flashWrite)(uint32_t addr, uint8_t *buf, uint32_t len);void (*jumpToAddr)(uint32_t addr);void (*reset)(void);struct pack_info pack;firmware_info_t fw_info;AT32_MCU_TYPE whoAmI;bool synecd;
} bl_info_t;void bl_pack_clear(bl_info_t *bl);
uint32_t bl_pack_recv(bl_info_t *bl);
void bl_pack_send(bl_info_t *bl, uint8_t cmd, uint32_t addr, uint8_t *data, uint16_t data_size);void bootloader_handle(bl_info_t *bl);
#endif/** Author: LVGRAPE* LastEditors: LVGRAPE*/
// #include at32f413.h
#include stdbool.h
#include systick.h
#include string.h
#include bootloader.h
#include crc_func_def.h
#include CRC32.h#define SERIAL_BUG 0
#define CRC32_INIT_VALUE 0xFFFFFFFF
#define CRC32_XOR_VALUE 0xFFFFFFFFuint32_t crc32_cal(const uint8_t *pdata, uint32_t len, uint32_t initial, uint32_t finalXor, bool inputReflected, bool resultReflected)
{uint32_t crc initial;uint32_t temp1 0, temp2 0, pos 0;const uint32_t *pTable crc32__table;for (int i 0; i len; i){uint32_t curByte pdata[i];if (inputReflected){curByte Reflect8(pdata[i]);}temp1 (crc ^ (curByte (32 - 8)));pos (temp1 (32 - 8)) 0xFF;temp2 (temp1 8);crc (temp2 ^ pTable[pos]);}if (resultReflected){crc Reflect32(crc);}return (crc ^ finalXor);
}void bl_pack_clear(bl_info_t *bl)
{memset(bl-pack.buffer, 0, sizeof(bl-pack.buffer));bl-pack.buffer_size 0;
}
void bl_pack_send(bl_info_t *bl, uint8_t cmd, uint32_t addr, uint8_t *data, uint16_t data_size)
{uint32_t crc 0;bl_pack_clear(bl);bl-pack.cmd1 cmd;bl-pack.cmd2 (uint8_t)~cmd;bl-pack.addr addr;memcpy(bl-pack.data, data, data_size);bl-pack.data_size data_size;bl-pack.buffer_size 12 bl-pack.data_size;crc crc32_cal(bl-pack.buffer 4, bl-pack.buffer_size - 4, CRC32_INIT_VALUE, CRC32_XOR_VALUE, 1, 1);bl-pack.crc crc;bl-write(bl-pack.buffer, bl-pack.buffer_size);bl-write((uint8_t *)crc, 0); /**FIXME USB-CDC BUG! */
#if (SERIAL_BUG)/**FIXME 长度是64的倍数时会卡住不发送 */#endif
}
uint32_t bl_pack_recv(bl_info_t *bl)
{uint32_t crc -1;bl_pack_clear(bl);bl-pack.buffer_size bl-read(bl-pack.buffer);if (bl-pack.buffer_size 0){uint32_t crcLen bl-pack.buffer_size - 4;
#if (SERIAL_BUG)crcLen - 4;
#endifcrc crc32_cal(bl-pack.buffer 4, crcLen, CRC32_INIT_VALUE, CRC32_XOR_VALUE, 1, 1);if (crc bl-pack.crc){return 0;}}return crc;
}
void bl_write_handle(bl_info_t *bl)
{if (bl-pack.addr bl-appAddr bl-pack.addr (bl-appAddr bl-appSize)){bl-flashWrite(bl-pack.addr, bl-pack.data, bl-pack.data_size);bl_pack_send(bl, CMD_ACK, 0, NULL, 0);}else{bl_pack_send(bl, CMD_NACK, 0, NULL, 51);}
}
void bl_read_handle(bl_info_t *bl)
{uint8_t readBuffer[FLASH_SectorSize];if (bl-pack.addr bl-appAddr bl-pack.addr (bl-appAddr bl-appSize)){uint32_t sizeRemain bl-appAddr bl-appSize - bl-pack.addr;uint32_t readSize bl-pack.data[0] | (bl-pack.data[1] 8) | (bl-pack.data[2] 16) | (bl-pack.data[3] 24);readSize readSize sizeRemain ? sizeRemain : readSize;bl-flashRead(bl-pack.addr, readBuffer, readSize);bl_pack_send(bl, CMD_ACK, bl-pack.addr, readBuffer, readSize);}else{bl_pack_send(bl, CMD_NACK, 0, NULL, 41);}
}void bl_erase_handle(bl_info_t *bl)
{if (bl-pack.addr bl-appAddr bl-pack.addr (bl-appAddr bl-appSize)){uint32_t sizeRemain bl-appAddr bl-appSize - bl-pack.addr;uint32_t eraseSize 0;eraseSize bl-pack.data[0] | (bl-pack.data[1] 8) | (bl-pack.data[2] 16) | (bl-pack.data[3] 24);eraseSize eraseSize sizeRemain ? sizeRemain : eraseSize;uint32_t endAddr bl-pack.addr eraseSize;bl-flashUnlock();uint32_t eraseAddr bl-pack.addr;for (; eraseAddr endAddr; eraseAddr bl-sectorSize){bl_pack_send(bl, CMD_ACK, eraseAddr, (uint8_t *)endAddr, 4);bl-flashSectorErase(eraseAddr);}bl_pack_send(bl, CMD_ACK, eraseAddr, (uint8_t *)endAddr, 4);bl-flashLock();}else{bl_pack_send(bl, CMD_NACK, 0, NULL, 21);}
}void bl_jump_handle(bl_info_t *bl)
{if (bl-pack.addr bl-appAddr bl-pack.addr (bl-appAddr bl-appSize)){bl_pack_send(bl, CMD_ACK, bl-pack.addr, NULL, 0);if (bl-jumpToAddr)bl-jumpToAddr(bl-pack.addr);}else{bl_pack_send(bl, CMD_NACK, bl-appAddr, NULL, 31);}
}
void bl_W_fwInfo_handle(bl_info_t *bl)
{int err 0;memset(bl-fw_info, 0, sizeof(firmware_info_t));memcpy(bl-fw_info, bl-pack.data, bl-pack.data_size);uint32_t crc crc32_cal((const uint8_t *)bl-fw_info 4, sizeof(firmware_info_t) - 4, CRC32_INIT_VALUE, CRC32_XOR_VALUE, 1, 1);if (crc ! bl-fw_info.infoCrc){err 11;goto NackExit;}if (bl-fw_info.magic ! FLASH_FW_MAGIC){err 12;goto NackExit;}if (bl-fw_info.size bl-appSize || bl-fw_info.size 0){err 13;goto NackExit;}if (bl-fw_info.start_addr bl-appAddr || bl-fw_info.start_addr (bl-appAddr bl-appSize)){err 14;goto NackExit;}if (bl-fw_info.whoAmI.ID ! bl-whoAmI.ID || bl-fw_info.whoAmI.Serial ! bl-whoAmI.Serial){err 15;goto NackExit;}bl-flashUnlock();bl-flashSectorErase(bl-fwInfoAddr);bl-flashWrite(bl-fwInfoAddr, (uint8_t *)bl-fw_info, sizeof(firmware_info_t));bl-flashLock();bl_pack_send(bl, CMD_ACK, 0, NULL, 0);return;NackExit:bl_pack_send(bl, CMD_NACK, 0, NULL, err);
}
void bl_R_fwInfo_handle(bl_info_t *bl)
{uint16_t dataSize bl-pack.addr ! 0 ? bl-pack.addr : sizeof(firmware_info_t);bl-flashRead(bl-fwInfoAddr, (uint8_t *)bl-fw_info, sizeof(firmware_info_t));bl_pack_send(bl, CMD_ACK, bl-fwInfoAddr, (uint8_t *)bl-fw_info, dataSize);
}
uint32_t bl_check_fw(bl_info_t *bl)
{uint32_t crc 0;bl-flashRead(bl-fwInfoAddr, (uint8_t *)bl-fw_info, sizeof(firmware_info_t));crc crc32_cal((uint8_t *)bl-fw_info 4, sizeof(firmware_info_t) - 4, CRC32_INIT_VALUE, CRC32_XOR_VALUE, 1, 1);if (bl-fw_info.magic FLASH_FW_MAGIC bl-fw_info.size bl-appSize crc bl-fw_info.infoCrc){const uint8_t *fwData (const uint8_t *)bl-fw_info.start_addr;if (bl-fw_info.bootTimes 0){/**First time, check crc*/crc crc32_cal(fwData, bl-fw_info.size, CRC32_INIT_VALUE, CRC32_XOR_VALUE, 1, 1);if (crc bl-fw_info.FWcrc){// bl_pack_send(bl, CMD_LOG, bl-appAddr, (uint8_t *)bl-jumpToAddr\r\n, 17);bl-jumpToAddr(bl-appAddr);return 0;}}else if (bl-fw_info.bootTimes 0xFFFFFFFF){// bl_pack_send(bl, CMD_LOG, bl-fwInfoAddr, (uint8_t *)system failure\r\n, 17);/**system failure*/return 0;}else{bl-jumpToAddr(bl-appAddr);return 0;}}// bl_pack_send(bl, CMD_LOG, bl-fwInfoAddr, (uint8_t *)fw crc error\r\n, 15);return 1;
}void bootloader_handle(bl_info_t *bl)
{
#if 1bl-pack.buffer_size bl-read(bl-pack.buffer);if (bl-pack.buffer_size ! 0){uint32_t crcLen bl-pack.buffer_size - 4;uint32_t crc crc32_cal(bl-pack.buffer 4, crcLen, CRC32_INIT_VALUE, CRC32_XOR_VALUE, 1, 1);uint8_t cmd2 ~bl-pack.cmd2;if (bl-pack.crc crc){if (bl-pack.cmd1 cmd2){if(!bl-synecd){if(bl-pack.cmd1 CMD_SYNC){bl-synecd true;bl_pack_send(bl, CMD_ACK, 0, NULL, 0);}else{bl_pack_send(bl, CMD_NACK, 0, NULL, 3);}}else{/**NOTE SYNC */switch (bl-pack.cmd1){case CMD_SYNC:bl-synecd true;bl_pack_send(bl, CMD_ACK, 0, NULL, 0);break;case CMD_VERSION:bl_pack_send(bl, CMD_ACK, 0, (uint8_t *)bl-version, 4);break;case CMD_GETID:bl_pack_send(bl, CMD_ACK, 0, (uint8_t *)bl-whoAmI, sizeof(bl-whoAmI));break;case CMD_WRITE:bl_write_handle(bl);break;case CMD_READ:bl_read_handle(bl);break;case CMD_RESET:bl_pack_send(bl, CMD_ACK, 0, NULL, 0);if (bl-reset)bl-reset();break;case CMD_JUMP:bl_jump_handle(bl);break;case CMD_ERASE:bl_erase_handle(bl);break;case CMD_W_FW_INFO:bl_W_fwInfo_handle(bl);break;case CMD_R_FW_INFO:bl_R_fwInfo_handle(bl);break;default:/** unknown cmd */bl_pack_send(bl, CMD_NACK, 0, NULL, 1);break;}}}else{/**NOTE cmd error */bl_pack_send(bl, CMD_NACK, 0, NULL, 2);}}else{/**NOTE crc error */bl_pack_send(bl, CMD_NACK, 0, NULL, 3);}memset(bl-pack.buffer, 0, bl-pack.buffer_size);bl-pack.buffer_size 0;}
#endifif (bl-synecd false){if (bl-millis() (bl-dt 100)){// NOTE IAP timeout. Exit.bl_check_fw(bl);bl-dt bl-millis();}}
}上位机代码
(使用Linux gcc编译或者cygwin编译)
/** Author: LVGRAPE* LastEditors: LVGRAPE*/#include stdint.h
#include stdio.h
#include string.h
#include termios.h
#include unistd.h
#include fcntl.h
#include string.h
#include stdlib.h
#include errno.h
#include time.h
#include bootloader.h
#include AT32Models.h#define CRC32_INIT_VALUE 0xFFFFFFFF
#define CRC32_XOR_VALUE 0xFFFFFFFFuint32_t crc32_cal(const uint8_t *pdata, int32_t len, uint32_t initial, uint32_t finalXor, bool inputReflected, bool resultReflected);firmware_info_t firmware;
bl_info_t bootloader;
bl_info_t *bl bootloader;
uint8_t *firmware_data NULL;
int f_com 0;
uint16_t SetSize 0;
int readout 0;uint16_t bl_write(uint8_t *buff, uint16_t len)
{if (f_com 0){printf(bl_write error, f_com: 0x%08X\n, f_com);return 0;}uint16_t ret write(f_com, buff, len);// tcflush(f_com, TCIOFLUSH);if (ret ! len)printf(bl_write error, ret:%d\n, ret);return ret;
}
uint16_t bl_read(uint8_t *buff)
{if (!f_com){printf(bl_read error, f_com: 0x%08X\n, f_com);return 0;}uint16_t len 0;for (;;){if (read(f_com, buff, 1) 1){buff;len;}else{return len;}}return len;
}
int firmware_extract(FILE *f, firmware_info_t *i)
{if (!f)return -1;size_t readsize fread(i, 1, sizeof(firmware_info_t), f);if (readsize ! sizeof(firmware_info_t)){printf(firmware_extract error, readsize:%d\n, readsize);return -1;}// printf(readsize:%d\n,readsize);uint32_t crc crc32_cal((const uint8_t *)i 4, sizeof(firmware_info_t) - 4, CRC32_INIT_VALUE, CRC32_XOR_VALUE, 1, 1);if (crc ! i-infoCrc){printf(firmware_extract error, crc: 0x%08X, infoCrc: 0x%08X\n, crc, i-infoCrc);return -1;}printf( *name : %s\n, i-name);printf( *infoCrc : 0x%08X\n, i-infoCrc);printf( *magic : 0x%08X\n, i-magic);printf( *startAddr: 0x%08X\n, i-start_addr);printf( *size : 0x%08X\n, i-size);printf( *FWcrc : 0x%08X\n, i-FWcrc);printf( *version : 0x%08X\n, i-version);printf( *pid : 0x%08X\n, i-pid);printf( *date : 0x%08X\n, i-date);printf( *Serial : 0x%08X\n, i-whoAmI.Serial);printf( *ID : 0x%08X\n, i-whoAmI.ID);printf( *Model : 0x%08X\n, i-whoAmI.Model);printf( *Flash : 0x%08X\n, i-whoAmI.Flash);printf( *Footprint: 0x%08X\n, i-whoAmI.Footprint);firmware_data (uint8_t *)malloc(i-size);if(!firmware_data){printf(firmware_extract error, malloc failed\n);return -1;}readsize fread(firmware_data, 1, i-size, f);// FILE *fw fopen(./write.bin, wb);// fwrite(firmware_data, 1, i-size, fw);// fclose(fw);if (readsize ! i-size){printf(firmware_extract error, readsize:%d/%d\n, readsize, i-size);return -1;}crc crc32_cal(firmware_data, i-size, CRC32_INIT_VALUE, CRC32_XOR_VALUE, 1, 1);if (crc ! i-FWcrc){printf(firmware_extract error, crc:%x, FWcrc:%x\n, crc, i-FWcrc);return -1;}printf(FWcrc: 0x%08X\n, crc);return 0;
}
void delay_ms(uint32_t ms)
{usleep(ms * 1000);
}
int serial_init(int *fcom, char *com, int baudrate)
{/**get com num */char linuxCom[12] /dev/ttyS;int comIndex -1;if (strncmp(com, COM, 3) 0){comIndex atoi(com 3) - 1;if (comIndex 9)linuxCom[9] comIndex 0;else if (comIndex 100){linuxCom[9] comIndex / 10 0;linuxCom[10] comIndex % 10 0;}else{printf(com error!\n);return -1;}printf(\ncomIndex %d\n, comIndex);printf(com %s\n, linuxCom);}else{printf(com error!\n);return -1;}/**get baudrate */printf(baudrate:%d \n, baudrate);/**open and init com port*/*fcom open(linuxCom, O_RDWR | O_NOCTTY | O_NDELAY);if (*fcom -1){printf(com port open error! %s\n, strerror(errno));return -1;}printf(serial open\n);struct termios options;tcgetattr(*fcom, options);switch (baudrate){case 9600:cfsetispeed(options, B9600); // 设置输入波特率为921600cfsetospeed(options, B9600); // 设置输出波特率为921600break;case 115200:cfsetispeed(options, B115200); // 设置输入波特率为921600cfsetospeed(options, B115200); // 设置输出波特率为921600break;case 921600:cfsetispeed(options, B921600); // 设置输入波特率为921600cfsetospeed(options, B921600); // 设置输出波特率为921600break;default:cfsetispeed(options, B921600); // 设置输入波特率为921600cfsetospeed(options, B921600); // 设置输出波特率为921600break;}options.c_cflag | (CLOCAL | CREAD); // 忽略调制解调器控制线启用接收器options.c_cflag ~PARENB; // 无奇偶校验options.c_cflag ~CSTOPB; // 1位停止位options.c_cflag ~CSIZE; // 清除数据位设置options.c_cflag | CS8; // 设置数据位为8位options.c_lflag ~(ICANON | ECHO | ECHOE | ISIG); // 非规范模式禁止options.c_oflag ~OPOST; // 原始输出options.c_cc[VTIME] 1; // 设置超时1options.c_cc[VMIN] 1; // 设置最小字符为1tcsetattr(*fcom, TCSANOW, options);printf(serial init done\n);return 0;
}
int dev_sync(bl_info_t *bl)
{int sendtry 0;printf(\nTry to sync);while (1){tcflush(f_com, TCIOFLUSH);bl_pack_send(bl, CMD_SYNC, 0, NULL, 0);// printf(\nsending:);// for (int i 0; i bl-pack.buffer_size; i)// {// if (i % 16 0)// printf(\n);// printf(%02X , bl-pack.buffer[i]);// }// printf(\n);delay_ms(1);if (bl_pack_recv(bl) 0 bl-pack.cmd1 CMD_ACK){printf(Sync success!\n);// break;return 0;}else{delay_ms(10);sendtry;if (sendtry 300){printf(sync timeout! exit!\n);return -2;}}printf(\nrev: %d, bl-pack.buffer_size);for (int i 0; i bl-pack.buffer_size; i){if (i % 16 0)printf(\n);printf(%02X , bl-pack.buffer[i]);}printf(\n);}printf(\n);return -1;
}
int getVersion(bl_info_t *bl)
{printf(\nget version\n);int sendtry 0;while (1){tcflush(f_com, TCIOFLUSH);bl_pack_send(bl, CMD_VERSION, 0, NULL, 0);// printf(\nsending:);// for (int i 0; i bl-pack.buffer_size; i)// {// if (i % 16 0)// printf(\n);// printf(%02X , bl-pack.buffer[i]);// }// printf(\n);delay_ms(1);if (bl_pack_recv(bl) 0 bl-pack.cmd1 CMD_ACK){if (bl-pack.cmd1 CMD_ACK){printf(get version success\n);memcpy(bl-version, bl-pack.data, bl-pack.data_size);printf(version:0x%08X\n, bl-version);return 0;}}delay_ms(1);if (sendtry 3){printf(get version timeout! exit!\n);return -1;}printf(.);}printf(\n);
}
int getId(bl_info_t *bl)
{printf(\nget id...\n);int sendtry 0;while (1){tcflush(f_com, TCIOFLUSH);bl_pack_send(bl, CMD_GETID, 0, NULL, 0);// printf(\nsending:);// for (int i 0; i bl-pack.buffer_size; i)// {// if (i % 16 0)// printf(\n);// printf(%02X , bl-pack.buffer[i]);// }// printf(\n);delay_ms(1);if (bl_pack_recv(bl) 0 bl-pack.cmd1 CMD_ACK){if (bl-pack.cmd1 CMD_ACK){printf(get id success\n);memcpy(bl-whoAmI, bl-pack.data, bl-pack.data_size);printf( *Serial : 0x%08X\n, bl-whoAmI.Serial);printf( *ID : 0x%08X\n, bl-whoAmI.ID);printf( *Model : 0x%08X\n, bl-whoAmI.Model);printf( *Flash : 0x%08X\n, bl-whoAmI.Flash);printf( *Footprint: 0x%08X\n, bl-whoAmI.Footprint);printf( *UID : );for (int i 0; i sizeof(bl-whoAmI.UID); i){printf(%02X, bl-whoAmI.UID[i]);}printf(\n);int mcuMatch 0;if (bl-whoAmI.Serial ! firmware.whoAmI.Serial){printf(whoAmI Serial not match!\n);mcuMatch;}if (bl-whoAmI.Model ! firmware.whoAmI.Model){printf(whoAmI Model not match!\n);mcuMatch;}if (bl-whoAmI.Flash ! firmware.whoAmI.Flash){printf(whoAmI Flash not match!\n);mcuMatch;}if (mcuMatch ! 0){printf(MCU not match!\n);return -1;}printf( - - - MCU match! - - - \n\n\n);// memcpy(firmware.whoAmI.UID, bl-whoAmI.UID, sizeof(bl-whoAmI.UID));return 0;}}delay_ms(1);if (sendtry 3){printf(get version timeout! exit!\n);return -1;}printf(.);}printf(\n\n);return -1;
}
int get_fwInfo(bl_info_t *bl)
{printf(get fwInfo...\n);int sendtry 0;while (1){tcflush(f_com, TCIOFLUSH);bl_pack_send(bl, CMD_R_FW_INFO, SetSize, NULL, 0);// printf(\nSending:);// for (int i 0; i bl-pack.buffer_size; i)// {// if (i % 16 0)// printf(\n);// printf(%02X , bl-pack.buffer[i]);// }// printf(\n);delay_ms(10);uint32_t ret bl_pack_recv(bl);if (ret 0){if (bl-pack.cmd1 CMD_ACK bl-pack.data_size sizeof(firmware_info_t)){firmware_info_t onchipFW;printf(get fwInfo success:crc 0x%08X\n, bl-pack.crc);memcpy(onchipFW, bl-pack.data, sizeof(firmware_info_t));uint32_t iCrc crc32_cal((uint8_t *)onchipFW 4, sizeof(firmware_info_t) - 4, CRC32_INIT_VALUE, CRC32_XOR_VALUE, 1, 1);if (iCrc onchipFW.infoCrc){int b3, b2, b1, b0;printf(get onchip fwInfo:\n);printf(name: %s\n, onchipFW.name);b3 onchipFW.version 24;b2 (onchipFW.version 16) 0xFF;b1 (onchipFW.version 8) 0xFF;b0 onchipFW.version 0xFF;printf(version: V%d.%d.%d.%d\n, b3, b2, b1, b0);b3 onchipFW.pid 24;b2 (onchipFW.pid 16) 0xFF;b1 (onchipFW.pid 8) 0xFF;b0 onchipFW.pid 0xFF;printf(pid: %d,%d,%d,%d\n, b3, b2, b1, b0);int y, m, d;y onchipFW.date 16;m (onchipFW.date 8) 0xFF;d onchipFW.date 0xFF;printf(date: %d-%d-%d\n, y, m, d);printf(bootTimes:%d\n\n, onchipFW.bootTimes);}else{printf(iCrc error! 0x%08X,%08X\n, iCrc, onchipFW.infoCrc);printf(onchip fw empty!\n);}// for(int i0;ibl-pack.data_size;i)// {// if(i%160)printf(\n);// printf(%02X ,bl-pack.data[i]);// }return 0;}}printf(\n reving: %d,0x%08X\n, bl-pack.buffer_size, ret);for (int i 0; i bl-pack.buffer_size; i){if (i % 16 0)printf(\n);printf(%02X , bl-pack.buffer[i]);}printf(\n);delay_ms(1);if (sendtry 1){printf(get fwInfo timeout! exit!\n);return -1;}printf(.);}printf(\n);return -2;
}
int erase_flash(bl_info_t *bl)
{printf(\n\nerase flash...\n);int sendtry 0;uint32_t erase_size firmware.size;uint32_t erase_addr firmware.start_addr;uint32_t sectorCount erase_size / bl-sectorSize;sectorCount ((erase_size % bl-sectorSize) ? 1 : 0);printf(erase addr: 0x%08X, erase size: %d, sector count: %d %d\n, erase_addr, erase_size, sectorCount, bl-sectorSize);while (1){tcflush(f_com, TCIOFLUSH);bl_pack_send(bl, CMD_ERASE, erase_addr, (uint8_t *)erase_size, 4);// printf(Sending:);// for (int i 0; i bl-pack.buffer_size; i)// {// if (i % 16 0)// printf(\n);// printf(%02X , bl-pack.buffer[i]);// }// printf(\n);uint32_t endAddr 0;int waittry 0;printf(erasing...\n);for (int i 0; i sectorCount; i){printf();}printf(\n);while (1){delay_ms(10);uint32_t ret bl_pack_recv(bl);if (ret 0 bl-pack.cmd1 CMD_ACK){endAddr bl-pack.data[0] | (bl-pack.data[1] 8) | (bl-pack.data[2] 16) | (bl-pack.data[3] 24);printf(#);fflush(stdout);// delay_ms(1);// printf(erase addr: 0x%08X, endAddr: 0x%08X\n, bl-pack.addr, endAddr);if (bl-pack.addr endAddr){printf(\n);for (int i 0; i sectorCount; i){printf();}printf(\n);printf(erase success!\n\n);return 0;}waittry 0;}else{if (waittry 10){printf(eraser error at 0x%08X\n, bl-pack.addr);return -1;}}}if (sendtry 2){printf(erase timeout! exit!\n);return -2;}}return -3;
}
int write_firmware(bl_info_t *bl)
{uint32_t write_already 0;uint32_t write_remain firmware.size;uint32_t write_addr firmware.start_addr;uint32_t write_size 0;uint32_t sendtry 0;uint32_t stepPercent 0;uint32_t stepPercentPre 0;uint32_t stepMax (firmware.size) / bl-sectorSize;stepMax stepMax 100 ? 100 : stepMax;printf(programming...\n);for (int i 0; i stepMax; i){printf();}printf(\n);while (1){write_size write_remain bl-sectorSize ? bl-sectorSize : write_remain;bl_pack_send(bl, CMD_WRITE, write_addr, firmware_data[write_already], write_size);int ret bl_pack_recv(bl);int waitry 0;while (ret ! 0){delay_ms(1);ret bl_pack_recv(bl);if (waitry 100){printf(write error [%08X] at 0x%08X, crc error\n, ret, write_addr);return -1;}}delay_ms(1);if (ret 0 bl-pack.cmd1 CMD_ACK){write_already write_size;write_remain - write_size;write_addr write_size;stepPercent (write_already * 100) / firmware.size;if (stepPercent ! stepPercentPre){stepPercentPre stepPercent;printf();// printf(%d%%\n,stepPercent);fflush(stdout);}// printf(write addr: 0x%08X, write_size: %d write_remain:%d\n, write_addr, write_size, write_remain);if (write_remain 0){printf(\n);for (int i 0; i stepMax; i){printf();}printf(\n);printf(Done!\n\n);return 0;}}else{printf(write error [%08X] at 0x%08X\n rev: [%d] \n, ret, write_addr, bl-pack.buffer_size);for (int i 0; i bl-pack.buffer_size; i){printf(0x%02X , bl-pack.buffer[i]);}printf(\n);if (sendtry 10){printf(write timeout! exit!\n);return -1;}}}return -2;
}
int read_firmware(bl_info_t *bl)
{uint32_t read_total 0;uint32_t read_size 0;uint32_t sendtry 0;uint32_t read_addr firmware.start_addr;uint32_t read_remain firmware.size;uint8_t *firmwareRead malloc(firmware.size);if(!firmwareRead){printf(malloc error\n);return -1;}uint32_t packCount firmware.size / bl-sectorSize;packCount packCount 100 ? 100 : packCount;uint32_t curPack0,prePack0;printf(Verifying...\n);for (int i 0; i packCount; i){printf();// fflush(stdout);}printf(\n);while (1){read_size read_remain bl-sectorSize ? bl-sectorSize : read_remain;bl_pack_send(bl, CMD_READ, read_addr, (uint8_t *)read_size, 4);int waitting 0;while (1) // wait ack{delay_ms(2);int ret bl_pack_recv(bl);if (ret 0 bl-pack.cmd1 CMD_ACK){memcpy(firmwareRead[read_total], bl-pack.data, bl-pack.data_size);// printf(read addr: 0x%08X, read_size: %d\n, read_addr, read_size);if (read_size ! bl-pack.data_size){printf(read error at 0x%08X! wanted[%d] get[%d]\n, read_addr, read_size, bl-pack.data_size);}read_total read_size;read_remain - read_size;read_addr read_size;sendtry 0;curPack read_total*100/firmware.size;if(curPack ! prePack){prePack curPack;printf();fflush(stdout);}break;}else{// printf(rev: 0x%08X, [%d], ret, bl-pack.buffer_size);// for (int i 0; i bl-pack.buffer_size; i)// {// if (i % 32 0)// printf(\n);// printf(%02X , bl-pack.buffer[i]);// }// printf(\n);if (waitting 10){printf(read timeout! exit! at: 0x%08X\n, read_addr);return -2;}}}if (read_remain 0){printf(\n);for (int i 0; i packCount; i){printf();// fflush(stdout);}printf(\n);printf(done!\n);break;}if (sendtry 3){printf(read timeout! exit!\n);return -1;}}if(readout!0){FILE *f_read fopen(./verify.bin, wb);if (!f_read){printf(open file error!\n);}size_t writeSize fwrite(firmwareRead, 1, firmware.size, f_read);if (writeSize ! firmware.size){printf(write file error! %d,%d\n, writeSize, firmware.size);}fclose(f_read);}uint32_t crc crc32_cal(firmwareRead, firmware.size, CRC32_INIT_VALUE, CRC32_XOR_VALUE, 1, 1);printf(read crc: 0x%08X\n, crc);if (crc ! firmware.FWcrc){printf(crc error! read crc: 0x%08X, firmware crc: 0x%08X\n, crc, firmware.FWcrc);for (size_t i 0; i firmware.size; i){if (firmware_data[i] ! firmwareRead[i]){printf(read error at 0x%08X, [%02X] [%02X]\n, i, firmware_data[i], firmwareRead[i]);return -1;}}return -1;}free(firmwareRead);printf(crc ok!\n);return 0;
}
int write_fwInfo(bl_info_t *bl)
{uint32_t sendtry 0;printf(\nUpdating firmware info...\n);while (1){bl_pack_send(bl, CMD_W_FW_INFO, 0, (uint8_t *)firmware, sizeof(firmware));int waitting 0;while (1) // wait ack{// printf(send: [%D]\n, bl-pack.buffer_size);// for(int i 0; i bl-pack.buffer_size; i)// {// if(i % 32 0)// printf(\n);// printf(%02X , bl-pack.buffer[i]);// }delay_ms(10);int ret bl_pack_recv(bl);if (ret 0 bl-pack.cmd1 CMD_ACK){printf(Done!\n\n);return 0;}else if (ret 0 bl-pack.cmd1 CMD_NACK){printf(nack! error:%d\n, bl-pack.data_size);break;}else{// printf(rev: 0x%08X, [%d], ret, bl-pack.buffer_size);// for (int i 0; i bl-pack.buffer_size; i)// {// if (i % 32 0)// printf(\n);// printf(%02X , bl-pack.buffer[i]);// }// printf(\n);if (waitting 10){printf(wait ack on write fw info timeout!\n);break;}}}if (sendtry 2){printf(write fw info timeout! exit!\n);return -1;}}return 0;
}
int reset(bl_info_t *bl)
{uint32_t sendtry 0;printf(\nResetting...\n);while (1){bl_pack_send(bl, CMD_RESET, 0, NULL, 0);int waitting 0;while (1) // wait ack{delay_ms(10);int ret bl_pack_recv(bl);if (ret 0 bl-pack.cmd1 CMD_ACK){printf(Done!\n\n);return 0;}else if (ret 0 bl-pack.cmd1 CMD_NACK){printf(nack! error:%d\n, bl-pack.data_size);}else{if (waitting 10){printf(wait ack on reset timeout!\n);break;}}}}if (sendtry 2){printf(reset timeout! exit!\n);return -1;}
}
/*** brief* make -f ./win_iap_tool/makefile* ./win_iap_tool/win_iap_tool.exe COM1 921600 ./ZINO PREMIUM RT DRONE V4.0.0.0.bin* ./win_iap_tool/win_iap_tool.exe COM5 921600 ./ZINO_PREMIUM_ZINO_FC_V4_V1.0.1_20241119.bin* ./win_iap_tool/win_iap_tool.exe COM3 921600 ./ZINO_PREMIUM_ZINO_FC_V4_V1.0.1_20241120.bin* ./win_iap_tool/win_iap_tool.exe COM5 921600 ./ZINO_DPS_ZINO_POWER_V1.0.1_20241224.bin* param argc 4* param argv [com] [baudrate] [firmware]* return int*/
int main(int argc, char *argv[])
{bootloader.read bl_read;bootloader.write bl_write;bootloader.sectorSize FLASH_SectorSize;// ffmpeg -i ./wav/happy_new_year.wav ./wav/happyNewYear.sbc -ar 8000
//ls /dev/tty*可扫描口列表
// gcc ./AromatherapyDiffuser/hardware/W25QXX/loadSbc.c -o loadsbc
// printf(system run \n);
#if 0/**NOTE 使用 -来区分指令,不过没有必要 */struct{char *cmd;char *param[16];uint8_t paramCount;} cmdlist[16] {0};uint8_t cmdlistCount 0;uint8_t cmdParamCount 0;for (int i 1; i argc; i){if (argv[i][0] -){cmdlist[cmdlistCount].cmd argv[i];cmdlist[cmdlistCount].paramCount 0;cmdParamCount 0;cmdlistCount;}else{if (cmdlistCount ! 0){cmdlist[cmdlistCount - 1].param[cmdParamCount] argv[i];cmdParamCount;cmdlist[cmdlistCount - 1].paramCount cmdParamCount;}}}printf(cmdlistCount:%d\n, cmdlistCount);for (int i 0; i cmdlistCount; i){printf(cmdlist[%d]:%s, i, cmdlist[i].cmd);if (cmdlist[i].paramCount ! 0){for (int j 0; j cmdlist[i].paramCount; j){printf( %s, cmdlist[i].param[j]);}}printf(\n);}
#endifif (argc 4){printf(Usage:%s [com] [baudrate] [firmware]\n, argv[0]);printf(Example:\n ./win_iap_tool COM9 921600 \./ZINO PREMIUM RT DRONE V4.0.0.0.bin\\n);return -1;}if (argc 5){SetSize atoi(argv[4]);}if(argc 6){readout atoi(argv[5]);}printf(\n\n * * * * * * ZINO Firmware Burning Tool V2.0.0 * * * * * * \n\n);/**serial port init */int baudrate atoi(argv[2]);char *com argv[1];if (serial_init(f_com, com, baudrate) ! 0){printf(serial init error!\n);return -1;}// 判断文件尾缀是否为.binchar *fw_file argv[3];int fw_file_len strlen(fw_file);if (strcmp(fw_file fw_file_len - 4, .bin) ! 0){printf(bin file error! Only accept *.bin file!\n);return -1;}printf(\nbin file:%s\n, fw_file);FILE *f_fw fopen(fw_file, r);if (f_fw NULL){printf(bin file open error! %s\n, strerror(errno));return -1;}printf(firmware extract...\n);if (firmware_extract(f_fw, firmware) ! 0){printf(firmware extract error!\n);return -1;}size_t sector_size FLASH_SectorSize;size_t read_size 0;size_t total_write 0;size_t total_pack firmware.size / sector_size (firmware.size % sector_size ? 1 : 0);size_t pack_count 0;uint32_t write_addr firmware.start_addr;uint32_t sector_count 0;// printf(total_pack:%d\n, total_pack);timer_t startTime time(NULL);timer_t frameTime time(NULL);timer_t frameTimeUsed time(NULL);timer_t totalTime time(NULL);timer_t totalTimeUsed time(NULL);/**NOTE SYNC */if (dev_sync(bl) ! 0){printf(dev_sync error!\n);return -1;}/**NOTE GET VERSION */if (getVersion(bl) ! 0){printf(dev_get_version error!\n);return -1;}/**NOTE GET ID */if (getId(bl) ! 0){printf(dev_get_id error!\n);return -1;}/**NOTE GET fwInfo */if (get_fwInfo(bl) ! 0){printf(dev_get_fwinfo error!\n);return -1;}/**NOTE ERASE FLASH */if (erase_flash(bl) ! 0){printf(erase_flash error!\n);return -1;}/** NOTE WRITE FLASH */if (write_firmware(bl) ! 0){printf(write_firmware error!\n);return -1;}/** NOTE read FLASH */if (read_firmware(bl) ! 0){printf(read_firmware error!\n);return -1;}/**NOTE write fwInfo */if (write_fwInfo(bl) ! 0){printf(write_fwInfo error!\n);return -1;}/**NOTE RESET */if (reset(bl) ! 0){printf(reset error!\n);return -1;}free(firmware_data);tcflush(f_com, TCIOFLUSH); // 刷新输入输出缓冲区close(f_com);return 0;
}运行结果
$ make -j16 dl
./UploadTool/win_iap_tool.exe COM3 921600 ZINO_DPS_ZINO_POWER_V1.0.1_20250110.bin* * * * * * ZINO Firmware Burning Tool V2.0.0 * * * * * * comIndex 2
com /dev/ttyS2
baudrate:921600
serial open
serial init donebin file:ZINO_DPS_ZINO_POWER_V1.0.1_20250110.bin
firmware extract...*name : ZINO_DPS_ZINO_POWER_V1.0.1_20250110.bin*infoCrc : 0x40693BE8*magic : 0x5A1234A5*startAddr: 0x08004000*size : 0x00015EFC*FWcrc : 0xFF0BC36F*version : 0x00000001*pid : 0x01020304*date : 0x07E80B13*Serial : 0x00000047*ID : 0x00030240*Model : 0x0000000F*Flash : 0x00000002*Footprint: 0x00000003
FWcrc: 0xFF0BC36FTry to sync
rev: 0
Sync success!get version
get version success
version:0x02000000get id...
get id success*Serial : 0x00000047*ID : 0x00030240*Model : 0x0000000F*Flash : 0x00000002*Footprint: 0x00000003*UID : 488D3504000064710917D904- - - MCU match! - - -get fwInfo...
get fwInfo success:crc 0xF974C5F7
get onchip fwInfo:
name: ZINO_DPS_ZINO_POWER_V1.0.1_20250110.bin
version: V0.0.0.1
pid: 1,2,3,4
date: 2024-11-19
bootTimes:0erase flash...
erase addr: 0x08004000, erase size: 89852, sector count: 44 2048
erasing...#############################################erase success!programming...Done!Verifying...rev: 0xFFFFFFFF, [0]
rev: 0xFFFFFFFF, [0]done!
read crc: 0xFF0BC36F
crc ok!Updating firmware info...
Done!Resetting...
Done!