#ifndef __APP_CONFIG_H__ #define __APP_CONFIG_H__ #define VERSION_MAIN 1 #define VERSION_SUB 0 #define VERSION_FIX 0 #define BOOT_VERSION ((VERSION_MAIN<<16)|(VERSION_SUB<<8)|VERSION_FIX) #define BUILD_TIMESTAMP __DATE__", "__TIME__ #define NAME_PART_APPLICATION "app" #define NAME_PART_DOWNLOAD "download" #define NAME_PART_FACTORY "factory" /** 配置各个分区的大小 需页对齐, 分区首地址必须是 Flash 的 每个独立 page 或 sector 的首地址,否则固件无法运行 */ #if defined(STM32F405xx) #define NAME_CHIP "STM32F405xx" #define SIZE_ONCHIP_FLASH (1024 * 1024ul) // 片上 flash 总容量 #else #error "no chip size defined" #endif #define SIZE_PART_BOOTLOADER (64 * 1024ul) // bootloader 占用空间(需要大于本程序bin大小) #define SIZE_PART_PARAMETERS (64 * 1024ul) // 参数 占用空间 #define SIZE_PART_LOG (128 * 1024ul) // 日志 占用空间 #define SIZE_PART_APPLICATION (SIZE_ONCHIP_FLASH/4) // app 占用空间 #define SIZE_PART_DOWNLOAD (SIZE_PART_APPLICATION) // download 占用空间 #define SIZE_PART_FACTORY (SIZE_PART_APPLICATION) // factory 占用空间 #define BASE_ONCHIP_FLASH (FLASH_BASE) // on chip flash 首地址 #define OFFSET_ONCHIP_FLASH_END (BASE_ONCHIP_FLASH + SIZE_ONCHIP_FLASH) /* chipsize eg: 1024KB 64KB - bootloader = 0x00000 + 64*1024 64KB - parameter = 0x10000 + 64*1024 128KB - log = 0x20000 + 128*1024 256KB - application = 0x40000 + 256*1024 256KB - download = 0x80000 + 256*1024 256KB - factory = 0xC0000 + 256*1024 */ #define BASE_BOOTLOADER (BASE_ONCHIP_FLASH) #define BASE_PARAMETERS (BASE_BOOTLOADER + SIZE_PART_BOOTLOADER) // 参数分区起始地址 #define BASE_LOG (BASE_PARAMETERS + SIZE_PART_PARAMETERS) #define BASE_APPLICATION (BASE_ONCHIP_FLASH + SIZE_PART_BOOTLOADER+SIZE_PART_PARAMETERS+SIZE_PART_LOG) // app 分区起始地址 #define BASE_DOWNLOAD (BASE_ONCHIP_FLASH + SIZE_ONCHIP_FLASH/2) // download 分区起始地址 #define BASE_FACTORY (BASE_DOWNLOAD + SIZE_PART_DOWNLOAD) // factory 分区起始地址 /* 片上分区数量选项 * app: 可运行的固件区域 * download: 用于更新固件时的固件临时存放区域 * factory: 用于存放可在紧急情况下恢复固件使用的区域 */ #define USE_SINGLE_PARTITION 0 // 单分区方案 仅 app #define USE_DOUBLE_PARTITION 1 // 双分区方案 含 app + download #define USE_TRIPLE_PARTITION 2 // 三分区方案 含 app + download + factory #define CONFIG_CHIP_PARTS USE_TRIPLE_PARTITION #define ENABLE_ASSERT 0 /* 是否使能函数入口参数检查 */ #define ENABLE_DEBUG_PRINT 1 /* 是否使能调试信息打印 */ #define MAX_NAME_LEN 8 // 本 bootloader 运行窗口最小时间 #define CONFIG_TIMEOUT_HOST_START (5*1000) // 设置等待主机数据的最大等待时间,单位 ms #define CONFIG_DECRYPT 1 #if (CONFIG_DECRYPT) // 以下同步给 upk 打包工具 #define AES256_KEY "0123456789ABCDEF0123456789ABCDEF" // 必须是 32 字节 #define AES256_IV "0123456789ABCDEF" // 必须是 16 字节 #endif /* 判断固件包是否超过分区大小 */ #define CONFIG_CHECK_SIZE 1 /* 单次写入的最小字节数*/ #define CONFIG_WRITE_BYTES_LEASET 4 /* 自动更新固件的处理选项 * 1. 在固件更新过程中设备异常断电或重启后,选择是否自动更新已下载好的固件以及自动更新的处理方案 * 2. 该选项的执行优先级低于上位机更新的方式,这意味着除非上位机超时未发送数据,否则将会优先执行上位机的固件更新 * * MODE_NOT_AUTO_UPDATE: 不需要自动更新,不希望有这种断电恢复固件的机制 * MODE_CLEAR_DOWNLOAD_PART: 更新完成后擦除 download 分区。设备上电时会通过检测 download 分区有无可用固件 * 以判断是否需要自动更新固件 * 选择此方案后,将无法选择是否在上电后对 APP 的固件进行安规校验( CONFIG_CHECK_APP_SECURITY )。 * 因为 APP 固件安规校验的数据来源是 download 分区的固件包。 * MODE_UPDATE_DOWNLOAD_HEAD: 更新完成后修改 download 分区的固件表头的版本信息。设备上电时会对比 download 分区固件包头记录的新旧版本, * 若新旧版本不一致,则开始自动更新固件 * 此种方式需要修改 download 分区的数据,有以下优劣势: * 1. 优势:上电时可校验 APP 分区的固件数据正确性和完整性,以提高 APP 固件有损坏或遭篡改时的安全性,甚至 * 可以将固件恢复正常,有效提高系统的安全等级 * 2. 劣势:需要对表头所在的 flash sector 擦除后再重新写入,这意味着每次更新都会擦除同个 sector 两次。 * MODE_APPEND_TO_APP: 更新完成后将新的固件版本写进 APP 分区的尾部,占用 16 byte ,设备上电时会对比 download 分区固件包头 * 记录的版本和 APP 存放的版本,若两个版本不一致,则开始自动更新固件 * 此种方式有以下优劣势: * 1. 优势:上电时可校验 APP 分区的固件数据正确性和完整性,以提高 APP 固件有损坏或遭篡改时的安全性,甚至 * 可以将固件恢复正常,有效提高系统的安全等级 * 2. 劣势:需要占用 APP 分区 16 byte 的空间 */ #define MODE_NOT_AUTO_UPDATE 0 #define MODE_CLEAR_DOWNLOAD_PART 1 #define MODE_UPDATE_DOWNLOAD_HEAD 2 #define MODE_APPEND_TO_APP 3 #if (CONFIG_CHIP_PARTS > USE_SINGLE_PARTITION) #define CONFIG_AUTO_UPDATE_MODE MODE_APPEND_TO_APP #endif /** 是否在上电后对 APP 的固件进行安规校验 及 APP 固件检查有问题时的操作 * 1. CONFIG_AUTO_UPDATE_MODE = MODE_UPDATE_DOWNLOAD_HEAD 时,本配置才会起效 * 2. 部分产品对固件的完整性有安规等级要求,本组件支持 APP 固件的数据完整性检查,通过配置以选择是否启用 * 3. 当启用时,通过配置 USING_APP_SAFETY_PROJECT 可选择 APP 固件检查有问题时的操作方案 * DO_NOT_CHECK : 不校验 APP 固件,即不启用 * CHECK_UNLESS_EMPTY: 校验 APP 固件,但无法校验时不校验,确保能运行 APP 而不至于等在 bootloader 中。若 APP 固件校验错误,将会 * 自动把可用和正确的固件更新至 APP * * 无法进行 APP 固件校验的情况是: download 分区和 factory 分区均无可用固件包 * AUTO_UPDATE_APP : APP 固件校验错误后自动将可用和正确的固件更新至 APP * * 需要注意的是,当选择了本选项,意味着你十分重视 APP 的数据完整性,也就是说,当 APP 固件校验不通过或 * 无法校验时,若 download 分区和 factory 分区均无可用固件包,则会停留在 bootloader 中,不会跳转至 APP , * 即便 APP 存在固件 * * 需要特别声明的是,有一种情况会导致 APP 无法被执行,那便是通过烧录器将固件烧录进 MCU 的 flash 中, * 因为此时不是通过正常的固件更新程序执行, download 分区和 factory 分区均无可用固件包, APP 固件无法进行 * 完整性校验,建议采用正常的固件更新流程,即由 bootloader 处理固件更新,或选择 CHECK_UNLESS_EMPTY 选型 * * 此处的自动更新和 CONFIG_AUTO_UPDATE_MODE 的不同,本选项仅在 APP 固件校验不通过时才会 * 自动更新,而 CONFIG_AUTO_UPDATE_MODE 则是无视本选项进行固件自动更新 * DO_NOT_DO_ANYTHING: APP固件校验错误后不要做任何操作,停在 bootloader 即可,即便 download 分区或 factory 分区有可用的固件包 * * 需要注意的是, DO_NOT_DO_ANYTHING 这个选项并不能阻止 APP 分区为空时且 CONFIG_AUTO_UPDATE_MODE 启用了 * 自动更新的情况, DO_NOT_DO_ANYTHING 只能阻拦APP分区不为空且校验不通过的情况,要阻止自动更新,需要修改 * 上方的 CONFIG_AUTO_UPDATE_MODE 选项为 DO_NOT_AUTO_UPDATE */ #define DO_NOT_CHECK 0 #define CHECK_UNLESS_EMPTY 1 #define AUTO_UPDATE_APP 2 #define DO_NOT_DO_ANYTHING 3 #if ((CONFIG_CHIP_PARTS > USE_SINGLE_PARTITION) \ &&((CONFIG_AUTO_UPDATE_MODE == MODE_UPDATE_DOWNLOAD_HEAD) \ ||(CONFIG_AUTO_UPDATE_MODE == MODE_APPEND_TO_APP))) #define CONFIG_CHECK_APP_SECURITY CHECK_UNLESS_EMPTY #endif /** * 【选择是否可以使用 factory 分区的固件包】 * 说明: * 当启用自动更新或校验 APP 固件完整性时,若 APP 固件不可用,且 download 分区没有可用的固件时,假设有 factory 分区, * 且 factory 分区有可用的固件,选择是否将 factory 的固件更新至 APP 中 * 选项: * 0: 不使用 * 1: 使用 */ #if ((CONFIG_CHIP_PARTS == USE_TRIPLE_PARTITION) \ &&((CONFIG_CHECK_APP_SECURITY == CHECK_UNLESS_EMPTY) \ ||(CONFIG_CHECK_APP_SECURITY == AUTO_UPDATE_APP))) #define CONFIG_FACTORY_RESTORE 1 #endif /** 是否自动纠正固件的分区 * 说明: * 该选项是为了修正人为的将分区名写错的情况,是一种能最大程度保证固件更新正常的挽救措施 * 单分区方案下,无论本功能是否启用,固件包指定的其它分区名都会被修正为 APP 分区,使其可以正常更新 * 多分区方案下,启用后,固件包指定为 APP 分区时将会被修正为 download 分区,使其可以正常更新 * 多分区方案下,若不启用,固件包指定为 APP 分区时将会报错,并标记为更新失败 * 选项: * 0: 不启用 * 1: 启用 */ #if (CONFIG_CHIP_PARTS > USE_SINGLE_PARTITION) #define CONFIG_AUTO_CORRECT 1 #endif /** * 【选择是否使用按键恢复出厂固件的选项】 * 说明: * 1. 使用本选项的前提是三分区方案,本选项能起效的前提是正确配置了按键且 factory 分区有可用的固件 * 2. 选择使用按键恢复出厂固件时,需要配置按键的引脚,如使用的按键和本案例不同,则需要自己配置和初始化 GPIO * 3. 本选项仅设备在运行 bootloader 时,可通过按键恢复出厂固件,若设备运行着 APP ,则本选项是无法起效的,因此需要 APP 也同步配置 * 4. 本选项和通过指令恢复出厂固件的方式不冲突,可以同时使用,也可以不启用本选项 * 5. 当无 factory 或 factory 无可用固件时,强行恢复出厂固件,将会触发 FACTORY_NO_FIRMWARE_SOLUTION 选项 * 解释: * ENABLE_FACTORY_FIRMWARE_BUTTON: 选择是否启用长按按键恢复出厂固件 * FACTORY_FIRMWARE_BUTTON_PRESS: 按键按下时的电平逻辑 * FACTORY_FIRMWARE_BUTTON_TIME: 按键长按的持续时间,单位 ms * 选项: * ENABLE_FACTORY_FIRMWARE_BUTTON 选项: * 0: 不启用 * 1: 启用 * FACTORY_FIRMWARE_BUTTON_PRESS 选项: * KEY_PRESS_LOW: 表示按下时为低电平 * KEY_PRESS_HIGH: 表示按下时为高电平 * FACTORY_FIRMWARE_BUTTON_TIME 选项: * 按键长按的持续时间,单位 ms ,不能大于 65535 */ #if (CONFIG_CHIP_PARTS == USE_TRIPLE_PARTITION) #define ENABLE_FACTORY_FIRMWARE_BUTTON 0 #define FACTORY_FIRMWARE_BUTTON_PRESS KEY_PRESS_LOW #define FACTORY_FIRMWARE_BUTTON_TIME 3000 #endif /** * 【片内 Flash 放置固件包所在 sector 的擦除粒度 ( TODO: 暂未实现 )】 * 说明: * CONFIG_AUTO_UPDATE_MODE = MODE_UPDATE_DOWNLOAD_HEAD 时,需要给出固件包所在 sector 的擦除粒度,单位是 byte */ #if (CONFIG_AUTO_UPDATE_MODE == MODE_UPDATE_DOWNLOAD_HEAD) #define ONCHIP_FLASH_ERASE_GRANULARITY UPK_LEAST_HANDLE_BYTE #endif #endif