/* * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2021-2021. All rights reserved. * Description: main * * Create: 2021-03-09 */ #include "boot_serial.h" #include "boot_init.h" #include "boot_reset.h" #include "boot_verify.h" #include "secure_verify_boot.h" #include "efuse.h" #include "efuse_porting.h" #include "chip_io.h" #include "pinctrl.h" #include "boot_flash.h" #include "sfc.h" #include "boot_delay.h" #include "boot_jump.h" #include "tcxo.h" #include "watchdog.h" #include "drv_pmp.h" #include "pmp_cfg.h" #include "malloc_porting.h" #include "upg_porting.h" #include "upg_common.h" #include "upg_alloc.h" #include "soc_porting.h" #include "drv_flashboot_cipher.h" #ifdef CONFIG_MIDDLEWARE_SUPPORT_UPG_AB #include "upg_ab.h" #endif #include "factory.h" #include "sfc_protect.h" #include "reset_porting.h" #define FLASHBOOT_UART_DEFAULT_PARAM {115200, 8, 1, 0, 0, 2, 1, 4, 0} #define APP_START_INSTRUCTION 0x40006f #define DELAY_100MS 100 #define REG_CMU_CFG0 0x40003408 #define APP_IMAGE_HEADER_LEN ((KEY_AREA_STRUCTURE_LENGTH) + (CODE_INFO_STRUCTURE_LENGTH)) #define BOOT_WATCH_DOG_TIMOUT 7 // 7s #define FLASH_KEY_SALT_LEN 28 #define FLASH_ENCRY_ADDR_ALINE 256 #define FLASH_NO_ENCRY_FLAG 0x3C7896E1 #define FLASHBOOT_RAM_ADDR 0xA28000 #define FLASH_BOOT_TYPE_REG 0x40000024 #define FLASH_BOOT_TYPE_REG_MAIN 0xA5A5A5A5 #define FLASH_BOOT_TYPE_REG_BKUP 0x5A5A5A5A const sfc_flash_config_t sfc_cfg = { .read_type = FAST_READ_QUAD_OUTPUT, .write_type = PAGE_PROGRAM, .mapping_addr = 0x200000, .mapping_size = 0x800000, }; #if 1 //ADD LYL 2024 1122 -------- #define USERPAGE 0x003F2000 //AT参数存储区 #define BLE_CONKEYLEN 16 #pragma pack(push) #pragma pack(1) typedef struct { int8_t updateflag; //update flag int8_t validflag; //valid flag int8_t tmode_mode; int8_t wmode_mode; //STA, 140 bytes uint8_t sta_ssid[33]; uint8_t sta_key[65]; int8_t wsauth; int8_t wsencry; uint8_t wslko; uint8_t pmk_av; uint8_t sta_padding[6]; uint8_t pmk[32]; //AP, 144 bytes int8_t wap_mode; int8_t wap_channel; int8_t waauth; int8_t waencry; uint8_t walk_led; uint8_t max_sta_num; uint8_t ap_enable_hide; uint8_t ap_ssid[33]; uint8_t ap_key[65]; uint8_t ap_pmk_av; uint8_t ap_pmk[32]; uint8_t ap_padding[6]; //UART, 20 bytes int8_t baudrate; int8_t data_bits; int8_t stop_bits; int8_t parity; int8_t ctsrts; int8_t uart1_baudrate; int8_t uart1_data_bits; int8_t uart1_stop_bits; int8_t uart1_parity; int8_t uart1_debug; int8_t uartfable; int8_t fuartte_mode; uint16_t uarttm; uint16_t uartbuf; uint8_t uart_padding[4]; //NETP, 108 bytes int8_t protocol; int8_t app_mode; uint8_t maxsocket; char cipadd[101]; uint16_t pro_port; uint16_t tcpto; //SOCKB, 112 bytes uint16_t sockb_port; uint16_t sockb_tcpto; int8_t sockb_pro; char sockb_cipadd[101]; int8_t tcpdis; int8_t tcpdisb; uint16_t udp_localporta; uint16_t udp_localportb; //NETWORK, 108 bytes char wann_ipaddr[16]; char wann_mask[16]; char wann_gateway[16]; char lann_ipaddr[16]; char lann_mask[16]; uint8_t wann_mode; uint8_t network_padding[2]; uint8_t domain_name[21]; uint32_t dns_addr; //UTILS, 124 bytes int8_t echo; int8_t rlden; uint8_t debug_level; char wel_msg[11]; uint8_t event_onoff; uint8_t noise_filter; uint8_t wifi_switch; uint8_t sta_dtim; uint8_t utils_padding[40]; uint8_t dis_power_saving; int8_t modechange; uint8_t ps_interval; uint8_t mid[21]; uint8_t aswd[21]; uint8_t cmdpw[21]; //HTTPD, 36 bytes char user_name[16]; char user_password[16]; int8_t web_switch; uint8_t web_language; uint8_t web_encode_format; uint8_t httpd_padding; //DHCPD, 4 bytes int8_t dhcpsw; uint8_t dhcpd_addr_start; uint8_t dhcpd_addr_end; uint8_t dhcpd_padding; //UPDATE, 124 bytes char update_url[101]; char update_file[21]; uint8_t update_padding[2]; //NTP, 8 bytes uint8_t ntp_time; uint8_t ntp_enable; uint8_t ntp_padding; int8_t time_zone; uint32_t ntpserver; //SMTLK, 16 bytes uint32_t smtlk_sign; uint8_t smtlk_mode; uint8_t smtlk_protocol; uint8_t smtlk_rtype; uint8_t smtlk_ak_random; uint8_t connect_flag; uint8_t sta_channel; uint8_t sta_bssid[6]; //SMARTAPLINK, 44 bytes uint8_t smartaplink_enable; uint8_t smartaplink_padding; uint8_t smartaplink_prefix[21]; uint8_t smartaplink_key[21]; //NETPID, 24 bytes uint8_t netpa_iden; char netpa_id[11]; uint8_t netpb_iden; char netpb_id[11]; //NETPREG, 264 bytes uint8_t netpa_regen; uint8_t netpa_regtype; uint8_t netpa_reg_padding; char netpa_regdata[129]; uint8_t netpb_regen; uint8_t netpb_regtype; uint8_t netpb_reg_padding; char netpb_regdata[129]; //HEART, 124 bytes uint16_t heart_netp_time; uint16_t heart_sockb_time; uint16_t heart_uart_time; char heart_netp_data[39]; char heart_sockb_data[39]; char heart_uart_data[39]; uint8_t heart_padding; //HTTP, 236 bytes uint8_t http_type; uint8_t http_version; uint8_t http_connect_type; uint8_t http_recv_time; char http_url[51]; char http_header[181]; //MQTT, 224 bytes char mqtt_username[33]; char mqtt_password[33]; char mqtt_clientid[33]; char mqtt_pub_topic[61]; char mqtt_sub_topic[61]; uint8_t mqtt_qos; uint16_t mqtt_heart_time; //BLE, 188 bytes uint16_t conn_min; uint16_t conn_max; uint16_t conn_latency; uint16_t supervisionTO; uint16_t adver_min; uint16_t adver_max; uint8_t ble_name[27]; //BLE广播名 uint8_t ble_dms_name[27]; //BLE配网名 uint8_t ble_adver_data[27]; uint8_t ble_adver_data_len; uint8_t ble_switch; uint8_t ble_uuid_server; uint8_t dms_type; uint8_t ble_padding; uint8_t uuid_ntf_server[17]; uint8_t uuid_ntf_read[17]; uint8_t uuid_ntf_write[17]; uint8_t uuid_ind_server[17]; uint8_t uuid_ind_read[17]; uint8_t uuid_ind_write[17]; uint8_t adver_type; uint8_t adver_channel; uint8_t ble_ind; uint8_t smartconfiglink; uint8_t ble_conenable; uint8_t ble_conkey[BLE_CONKEYLEN]; uint8_t ble_contimeout; uint8_t netpc_iden; char netpc_id[11]; uint8_t netpc_idflag; uint8_t ble_padding2[17]; uint8_t mqtt_tls; uint8_t mqtt_padding[3]; char iot_productkey[12]; char iot_devicename[48]; char iot_devicesecret[48]; char iot_pubtopic[96]; char iot_subtopic[96]; char iot_mode; char iot_padding[3]; uint8_t product_mode; int8_t ctsrts_pin; char instance_flag; char instance_id[32]; char ntp_domain_server[33]; int8_t smk_find; uint32_t mcu_ota_size; uint8_t scan_ch14; uint32_t module_reset_reason; uint8_t reserved1[60+512-4]; uint8_t validflag_magic; int8_t validflag_end; //valid flag }HF_CONFIG_FILE; #pragma pack(pop) HF_CONFIG_FILE g_hf_config_file_boot = {0}; int hfdbg_get_sw(void) { if(g_hf_config_file_boot.debug_level > 0 && g_hf_config_file_boot.debug_level<=20) //1~20允许打印 return 0; if(g_hf_config_file_boot.uart1_debug == 1) //1允许打印 return 1; return 0; } #endif static uint32_t sfc_flash_init(void) { return uapi_sfc_init((sfc_flash_config_t *)&sfc_cfg); } static uint32_t sfc_flash_read(uint32_t flash_addr, uint32_t read_size, uint8_t *read_buffer) { return uapi_sfc_reg_read(flash_addr, read_buffer, read_size); } static uint32_t sfc_flash_write(uint32_t flash_addr, uint32_t flash_write_size, const uint8_t *p_flash_write_data, bool do_erase) { unused(do_erase); return uapi_sfc_reg_write(flash_addr, (uint8_t *)p_flash_write_data, flash_write_size); } static uint32_t sfc_flash_erase(uint32_t flash_addr, uint32_t flash_erase_size) { return uapi_sfc_reg_erase(flash_addr - sfc_cfg.mapping_addr, flash_erase_size); } static void boot_flash_init(void) { flash_cmd_func flash_funcs = {0}; flash_funcs.init = sfc_flash_init; flash_funcs.read = sfc_flash_read; flash_funcs.write = sfc_flash_write; flash_funcs.erase = sfc_flash_erase; boot_regist_flash_cmd(&flash_funcs); uint32_t ret = sfc_flash_init(); if (ret != ERRCODE_SUCC) { boot_msg1("Flash Init Fail! ret = ", ret); } else { uapi_sfc_reg_read(USERPAGE, (unsigned char *)&g_hf_config_file_boot, sizeof(HF_CONFIG_FILE)); boot_msg0("Flash Init Succ!"); } hf_boot_msg1("BootLoader debug_level = ", g_hf_config_file_boot.debug_level); switch_flash_clock_to_pll(); config_sfc_ctrl_ds(); } #define FAMA_REMAP_SRC_BASE_ADDR 0x44007800 #define FAMA_REMAP_LEN_BASE_ADDR 0x44007820 #define FAMA_REMAP_DST_BASE_ADDR 0x44007840 #define FAMA_REMAP_REGION_OFFSET 0x4 #define FAMA_REMAP_LOW_BITS 12 static void dmmu_set(uint32_t src_start_addr, uint32_t src_end_addr, uint32_t dst_start_addr, uint32_t region) { uint32_t src_reg_addr = FAMA_REMAP_SRC_BASE_ADDR + region * FAMA_REMAP_REGION_OFFSET; uint32_t len_reg_addr = FAMA_REMAP_LEN_BASE_ADDR + region * FAMA_REMAP_REGION_OFFSET; uint32_t dst_reg_addr = FAMA_REMAP_DST_BASE_ADDR + region * FAMA_REMAP_REGION_OFFSET; uint32_t src_start_align_addr = src_start_addr >> FAMA_REMAP_LOW_BITS; uint32_t src_end_align_addr = src_end_addr >> FAMA_REMAP_LOW_BITS; uint32_t dst_start_align_addr = dst_start_addr >> FAMA_REMAP_LOW_BITS; uint32_t dst_src_offset = 0; if (region >= FAMA_REMAP_LOW_BITS) { return ; } writel(src_reg_addr, src_start_align_addr); writel(len_reg_addr, src_end_align_addr); if (src_start_align_addr > dst_start_align_addr) { dst_src_offset = src_start_align_addr - dst_start_align_addr; dst_src_offset = ~dst_src_offset; dst_src_offset = dst_src_offset + 1; } else { dst_src_offset = dst_start_align_addr - src_start_align_addr; } writel(dst_reg_addr, dst_src_offset); } static bool flashboot_need_recovery(void) { uint32_t reg = readl(FLASH_BOOT_TYPE_REG); writel(FLASH_BOOT_TYPE_REG, 0); return (reg == FLASH_BOOT_TYPE_REG_BKUP) ? true : false; } static void ws63_flashboot_recovery(void) { if (!flashboot_need_recovery()) { return; } uapi_watchdog_kick(); boot_msg0("Flashboot backup is working!"); partition_information_t src_img_info = {0}; partition_information_t dst_img_info = {0}; errcode_t ret; ret = uapi_partition_get_info(PARTITION_FLASH_BOOT_IMAGE_BACKUP, &src_img_info); ret |= uapi_partition_get_info(PARTITION_FLASH_BOOT_IMAGE, &dst_img_info); if (ret != ERRCODE_SUCC) { boot_msg0("Flashboot partition info get fail!"); return; } ret = uapi_sfc_reg_erase(dst_img_info.part_info.addr_info.addr, dst_img_info.part_info.addr_info.size); if (ret != ERRCODE_SUCC) { boot_msg1("flashboot recovery erase failed!! ret = ", ret); } ret = uapi_sfc_reg_write(dst_img_info.part_info.addr_info.addr, (uint8_t *)(uintptr_t)(src_img_info.part_info.addr_info.addr + FLASH_START), src_img_info.part_info.addr_info.size); if (ret != ERRCODE_SUCC) { boot_msg1("flashboot recovery write failed!! ret = ", ret); } boot_msg0("Flashboot fix ok!"); } #define UPG_FIX_RETRY_CNT_REG RESET_COUNT_REG #define VERIFY_RETRY_CNT_THRES 0x3 #define UPG_FIX_RETRY_CNT_THRES (VERIFY_RETRY_CNT_THRES + 0x3) #define UPG_AB_RETRY_CNT_THRES (VERIFY_RETRY_CNT_THRES + 0x3) static uint8_t ws63_get_try_fix_cnt(void) { gp_reg1_union gp; gp.u32 = readl(UPG_FIX_RETRY_CNT_REG); return gp.bits.fota_fix_app_cnt; } static void ws63_set_try_fix_cnt(uint8_t cnt) { gp_reg1_union gp; gp.u32 = readl(UPG_FIX_RETRY_CNT_REG); gp.bits.fota_fix_app_cnt = cnt & 0xF; writel(UPG_FIX_RETRY_CNT_REG, gp.u32); } #ifdef CONFIG_MIDDLEWARE_SUPPORT_UPG_AB static void ws63_try_fix_app(void) { uint8_t try_cnt = ws63_get_try_fix_cnt() + 1; ws63_set_try_fix_cnt(try_cnt); /* 启动分区连续验签失败次数等于阈值倍数时,切换启动分区 */ if (try_cnt % VERIFY_RETRY_CNT_THRES) { // 1 2 4 5 7 8 a b d e return; } else { // 3 6 9 c f boot_msg0("switch booting"); upg_set_run_region(upg_get_upg_region()); return; } } #else // 压缩 /* 尝试ota修复运行区镜像 */ static void ws63_try_fix_app(void) { uint8_t try_cnt = ws63_get_try_fix_cnt(); /* 连续验签失败次数小于阈值不做处理 */ if (try_cnt < VERIFY_RETRY_CNT_THRES) { ws63_set_try_fix_cnt(try_cnt + 1); return; } /* 修复app超次数阈值后不再尝试 */ if (try_cnt >= UPG_FIX_RETRY_CNT_THRES) { return; } ws63_set_try_fix_cnt(try_cnt + 1); /* 重置升级标记 */ errcode_t ret = uapi_upg_reset_upgrade_flag(); if (ret != ERRCODE_SUCC) { boot_msg1("reset_upgrade_flag fail, ret = ", ret); return; } /* 请求升级 */ ret = uapi_upg_request_upgrade(false); if (ret != ERRCODE_SUCC) { boot_msg0("request_upgrade fail, fota_pkt_not_exit."); return; } boot_msg0("fota_pkt exit, try_fota_fix_app."); } #endif static bool ws63_upg_need_upgrade(void) { uint32_t fota_address = 0; partition_information_t info; errcode_t ret_val = uapi_partition_get_info(PARTITION_FOTA_DATA, &info); if (ret_val != ERRCODE_SUCC || info.type != PARTITION_BY_ADDRESS) { boot_msg1("uapi_partition_get_info failed ", __LINE__); return false; } upg_get_upgrade_flag_flash_start_addr(&fota_address); fota_upgrade_flag_area_t upg_flag_info; ret_val = upg_flash_read(fota_address, sizeof(fota_upgrade_flag_area_t), (uint8_t *)(&upg_flag_info)); if (ret_val != ERRCODE_SUCC) { boot_msg1("upg_flash_read failed ", ret_val); return false; } if (!(upg_flag_info.head_magic == UPG_HEAD_MAGIC && upg_flag_info.head_end_magic == UPG_END_MAGIC && upg_flag_info.complete_flag != 0)) { /* 不需要升级直接返回 */ boot_msg0("No need to upgrade..."); return false; } return true; } static void ws63_upg_check(void) { (void)ws63_upg_init(); #ifdef CONFIG_MIDDLEWARE_SUPPORT_UPG_AB return; #endif if (ws63_upg_need_upgrade()) { boot_msg0("need upgrade"); errcode_t ret = uapi_upg_start(); // 1, 没有升级包、或者升级标记区结果已经设置的情况不需要重启 // 2, 升级模块没有初始化不需要重启 // 3, 升级成功需要重启 // 4, 升级失败的时候需要重启重新进入升级流程,尝试三次未成功,后会变为1的情况 if (!(ret == ERRCODE_UPG_NOT_NEED_TO_UPDATE || ret == ERRCODE_UPG_NOT_INIT || ret == ERRCODE_SUCC)) { boot_msg0("--------------------------"); boot_msg0("upgrade failed, reset now"); } else { // 升级后重启 boot_msg0("--------------------------"); boot_msg0("upgrade success, reset now"); } reset(); } } #define PMU_CMU_CTL_POC_COEX 0x40003238 #define RG_POC_SEL_SW_MODE 0x2 #define PMU_VDD_FLAG_3V3 0 #define POC_SEL_SW_MODE 1 #define POC_VALUE_3V3 0 #define LEVEL_3V3 0x33 #define LEVEL_1V8 0x18 typedef union { struct { uint32_t rg_poc_value : 1; /* [0] */ uint32_t rg_poc_sel : 1; /* [1] */ uint32_t pmu_vdd3318_flag : 1; /* [2] */ uint32_t ms1c : 1; /* [3] */ uint32_t rsv : 28; /* [31:4] */ } bits; uint32_t u32; } u_poc_coex; static void fix_io_level(void) { u_poc_coex poc_coex = {0}; poc_coex.u32 = readl(PMU_CMU_CTL_POC_COEX); if (poc_coex.bits.ms1c == poc_coex.bits.pmu_vdd3318_flag) { return; } if (poc_coex.bits.pmu_vdd3318_flag != PMU_VDD_FLAG_3V3) { return; } poc_coex.bits.rg_poc_value = POC_VALUE_3V3; poc_coex.bits.rg_poc_sel = POC_SEL_SW_MODE; writel(PMU_CMU_CTL_POC_COEX, poc_coex.u32); } static void dump_io_level(void) { u_poc_coex poc_coex = {0}; uint32_t chip_level = LEVEL_3V3; uint32_t sw_level = LEVEL_3V3; poc_coex.u32 = readl(PMU_CMU_CTL_POC_COEX); if (poc_coex.bits.rg_poc_sel == POC_SEL_SW_MODE) { sw_level = (poc_coex.bits.rg_poc_value == POC_VALUE_3V3) ? LEVEL_3V3 : LEVEL_1V8; chip_level = (poc_coex.bits.ms1c == POC_VALUE_3V3) ? LEVEL_3V3 : LEVEL_1V8; boot_msg2("io level work in sw mode, level[sw:chip]:", sw_level, chip_level); } else { chip_level = (poc_coex.bits.ms1c == POC_VALUE_3V3) ? LEVEL_3V3 : LEVEL_1V8; boot_msg1("io level work in hw mode, level[chip]:", chip_level); } } #define FASTBOOT_PWM 1 //CONFIG_PWM_USING_V151 #if FASTBOOT_PWM #define e_printf print_str #include "pwm.h" #ifndef __SPOTLIGHT_H__ #define __SPOTLIGHT_H__ typedef enum elightMode { LIGHT_MODE_CUSTOMER = 0, // 非情景模式 LIGHT_MODE_RELAX, // 休闲模式 LIGHT_MODE_MOVIE, // 观影模式 LIGHT_MODE_DINING, // 用餐模式 LIGHT_MODE_HOME, // 回家模式 LIGHT_MODE_WINTER, // 冬天模式 LIGHT_MODE_SUMMER, // 夏天模式 LIGHT_MODE_LEAVE, // 离家模式 LIGHT_MODE_MAX // 模式数量 } lightMode_e; // 位掩码定义 #define LIGHT_MODE_LEAVE_BIT (1 << 7) // 离家模式位 #define LIGHT_MODE_MASK (0x7F) // 基础模式掩码(7位) #define LIGHT_MODE_IS_LEAVE(mode) ((mode) & LIGHT_MODE_LEAVE_BIT) #define LIGHT_MODE_GET_BASE(mode) ((mode) & LIGHT_MODE_MASK) #define LIGHT_MODE_SET_LEAVE(base_mode) ((base_mode) | LIGHT_MODE_LEAVE_BIT) typedef enum { INIT_POWER_ON, NET_CONFIGING, BIND_OK, }eDeviceBindStatus; // 服务ID定义 #define SVC_ID_SWITCH "switch" // 开关控制 #define SVC_ID_BRIGHTNESS "brightness" // 亮度控制 #define SVC_ID_CCT "cct" // 色温控制 #define SVC_ID_LIGHT_MODE "lightMode" // 场景模式控制 #define SVC_ID_FADE_TIME "progressSwitch" // 渐变时长的控制 #define SVC_ID_COLOUR_MODE "colourMode" // 色温模式控制 // JSON字段名定义 #define JSON_FIELD_ON "on" // 开关状态字段 #define JSON_FIELD_BRIGHTNESS "brightness" // 亮度字段 #define JSON_FIELD_CCT "colorTemperature" // 色温字段 #define JSON_FIELD_MODE "mode" // 场景模式字段 #define JSON_FIELD_FADE_TIME "fadeTime" // 渐变时长字段 #define JSON_FIELD_COLOUR_MODE "mode" // 色温模式字段 typedef enum { REPORT_SWITCH = 1 << 0, REPORT_BRIGHTNESS = 1 << 1, REPORT_CCT = 1 << 2, REPORT_LIGHT_MODE = 1 << 3, REPORT_FADE_TIME = 1 << 4, REPORT_COLOUR_MODE = 1 << 5, REPORT_ALL = REPORT_SWITCH | REPORT_BRIGHTNESS | REPORT_CCT | REPORT_LIGHT_MODE | REPORT_FADE_TIME | REPORT_COLOUR_MODE, } report_mask_e; // 色温模式定义 typedef enum { COLOUR_MODE_SINGLE = 0, // 单色温模式 COLOUR_MODE_DUAL = 1, // 双色温模式 } colourMode_e; // 当前亮度和色温状态 typedef struct __attribute__((packed, aligned(1))) { // 物模型同步需要 持久化维持 uint8_t on; // 开关状态 lightMode_e elightMode; uint16_t brightness_local; // 当前亮度 (0-1000) uint16_t fade_time; // 渐变时长(s) uint16_t cct_local; // 当前色温 (2700-6500) uint8_t colourMode; // 色温模式 (0:单色温, 1:双色温) // 持久化维持 int32_t power_on_cnt; // 上电次数计数 uint8_t is_networked; // 是否已配网 uint8_t is_net_configured; // 设备是否曾经配网成功过 uint32_t reserve[10]; // 保留字段 //运行时的数据 uint16_t duty_cw; // 冷白LED占空比 uint16_t duty_ww; // 暖白LED占空比 uint8_t read_done; // 读取数据done } device_control_t; // 色温范围定义 #define CCT_MIN 2700 // 最小色温 2700K (暖白) #define CCT_MAX 6000 // 最大色温 6000K (冷白) #define CCT_RANGE (CCT_MAX - CCT_MIN) #define CCT_LOCAL_MIN 0 // 最小色温 0K (暖白) #define CCT_LOCAL_MAX (CCT_LOCAL_MIN + CCT_RANGE) // 最大色温 6000K (冷白) #define CCT_LOCAL2REMOTE(x) (x + (CCT_MIN - CCT_LOCAL_MIN)) #define CCT_REMOTE2LOCAL(x) (x - (CCT_MIN - CCT_LOCAL_MIN)) #define CCT_LITME_RANGE(x) do { \ if (x > CCT_LOCAL_MAX) x = CCT_LOCAL_MAX; \ if (x < CCT_LOCAL_MIN) x = CCT_LOCAL_MIN; \ } while (0) // 亮度范围定义 #define BRIGHTNESS_MIN 0 // 最小亮度 #define BRIGHTNESS_MAX 100 // 最大亮度 #define BRIGHTNESS_LOCAL_MIN 0 // 最小亮度 #define BRIGHTNESS_LOCAL_MAX 1000 // 最大亮度 #define BRIGHTNESS_REMOTE2LOCAL(x) (x * 10) //变化范围0 -1000 #define BRIGHTNESS_LOCAL2REMOTE(x) (x / 10) #define BRIGHTNESS_LITME_RANGE(x) do { \ if (x > BRIGHTNESS_LOCAL_MAX) x = BRIGHTNESS_LOCAL_MAX; \ if (x < BRIGHTNESS_LOCAL_MIN) x = BRIGHTNESS_LOCAL_MIN; \ } while (0) // 设备上电并未进入配网的状态 #define INIT_STA__LIGHT_MODE LIGHT_MODE_CUSTOMER #define INIT_STA__BRIGHTNESS 50 #define INIT_STA__CCT 4000 #define INIT_NET_CFG_PWOER_ON_KEEP_TIME (5 * 1000) // 统计进入配网每次打开状态的保持时间 #define NET_CFG_ENTRY_CNT 6 // 配网进入的上电次数 #define NET_CFG_BREATH_DURATION 1*60*1000 // 配网呼吸灯持续时间(ms) #define NET_CFG_TOTAL_TIMEOUT 10*60*1000 // 配网总超时时间(ms) // 配网成功后的默认值 #define NET_CFG_DEFAULT_BRIGHTNESS 80 // 默认亮度 #define NET_CFG_DEFAULT_CCT 6000 // 默认色温 #define NET_CFG_DEFAULT_FADE_TIME 1 // 默认渐变时长(s) #define NET_CFG_DEFAULT_LIGHTMODE LIGHT_MODE_CUSTOMER // 默认模式 // 配网超时后的默认值 #define NET_CFG_TIMEOUT_BRIGHTNESS 50 // 呼吸灯超时后的亮度 #define NET_CFG_TIMEOUT_CCT 4000 // 呼吸灯超时后的色温 #define FADE_INTERVAL_MIN (10*1000) //us #define NORMAL_FADE_TIME 3 //s #define PWM_DUTY_RATIO_MAX 1000 //呼吸灯定义 #define BREARTH_PERIOD (3*1000*1000) //呼吸灯周期(Us) #define BREARTH_INTERVAL (3*1000) //更新pwm的间隔 us #define BREARTH_STEP ((PWM_DUTY_RATIO_MAX) * 2) / (BREARTH_PERIOD / BREARTH_INTERVAL) //每次变化的幅度 // PWM频率和周期定义 #define PWM_FREQUENCY 3000 // PWM频率 2KHz //渐变范围 #define SMOOTH_TIME_MAX 30 #define SMOOTH_TIME_MIN 0 #define SUPPORT_SAVE_TO_FLASH 1 // 定义Flash存储地址和大小 #define DEVICE_DATA_FLASH_ADDR 0x000000 // 主数据区地址 #define DEVICE_DATA_BACKUP_ADDR 0x001000 // 备份数据区地址 #define DEVICE_DATA_FLASH_SIZE 0x001000 // 使用一个页的大小 // 设备数据结构 typedef struct __attribute__((packed, aligned(1))) { uint8_t checksum; // 校验和 uint32_t magic; // 魔数,用于验证数据有效性 uint32_t version; // 数据版本号 device_control_t control; // 设备控制状态 } device_data_t; #define DEVICE_DATA_MAGIC 0x4C505426 // "LPT&"的ASCII码 #define DEVICE_DATA_VERSION 1 // 数据版本号 // 保存任务相关定义 #define SAVE_TASK_PRIO 25 #define SAVE_TASK_STACK_SIZE 0x1000 #define SAVE_TASK_SLEEP_TIME 100 // 100ms // 保存任务状态 typedef enum { SAVE_STATE_IDLE = 0, // 空闲状态 SAVE_STATE_SAVING, // 正在保存 SAVE_STATE_WAITING // 等待保存 } save_state_e; typedef enum { APP_CHANGE_LIGHT_MODE = 0, APP_CHANGE_LIGHT_BRIGHTNESS_CCT, APP_CLOSE_LIGHT, APP_OPEN_LIGHT, DEV_POWER_ON, } light_ctrl_source_e; // 单色温模式的固定色温值 #define SINGLE_COLOUR_CCT 6000 // 单色温模式固定色温 6000K #define SINGLE_COLOUR_CCT_LOCAL CCT_REMOTE2LOCAL(SINGLE_COLOUR_CCT) // 转换为本地值 #define BRIGHTNESS_PIN GPIO_04 // 冷白LED (CW) #define CCT_PIN GPIO_00 // 暖白LED (WW) #define SWITCH_PIN GPIO_13 #define CONFIG_PWM_GROUP_ID 2 #define DEFAULT_DEVICE_DATA { \ .read_done = false, \ .on = true, \ .elightMode = INIT_STA__LIGHT_MODE, \ .cct_local = CCT_REMOTE2LOCAL(INIT_STA__CCT), \ .brightness_local = BRIGHTNESS_REMOTE2LOCAL(INIT_STA__BRIGHTNESS), \ .fade_time = NET_CFG_DEFAULT_FADE_TIME, \ .colourMode = COLOUR_MODE_DUAL, \ .is_networked = false, \ .is_net_configured = false, \ .duty_cw = 0, \ .duty_ww = 0, \ }; int spotlight_main(void); int set_light(light_ctrl_source_e source, int32_t brightness_local_target, int32_t cct_local_target); int set_smooth_time(uint32_t smooth_time); // 设置渐变时长 void update_pwm_output(bool on_state, uint16_t duty_cw, uint16_t duty_ww); // 模式转换函数 lightMode_e convert_mode_for_report(lightMode_e current_mode); // 将bitmask转换为上报用的枚举值 void stop_net_config(void); extern int fast_report(const char* svc_id); #endif // __SPOTLIGHT_H__ device_control_t g_device_control = DEFAULT_DEVICE_DATA; static uint32_t pwm_period_cnt = 0; // PWM周期 40us static uint8_t channel_id_cw = 0; // 冷白LED通道ID static uint8_t channel_id_ww = 0; // 暖白LED通道ID // 计算PWM占空比 void calculate_pwm_duty(device_control_t* pdevice_control) { // 如果开关关闭,则占空比为0 uint32_t total_brightness_pwm = pdevice_control->brightness_local; if (pdevice_control->colourMode == COLOUR_MODE_SINGLE) { // 单色模式,色温设置为最大值 pdevice_control->cct_local = SINGLE_COLOUR_CCT_LOCAL; } // 根据色温比例计算CW和WW的占空比 // 计算色温比例 (0-10000) uint16_t cct_ratio = ((pdevice_control->cct_local - CCT_LOCAL_MIN) * 10000) / CCT_RANGE; // 根据色温比例计算CW和WW的占空比 // 总亮度保持不变,只调整CW和WW的比例 pdevice_control->duty_cw = (total_brightness_pwm * cct_ratio) / 10000; pdevice_control->duty_ww = total_brightness_pwm - pdevice_control->duty_cw; } // 更新PWM输出 void update_pwm_output(bool on_state, uint16_t duty_cw_val, uint16_t duty_ww_val) { pwm_config_t cfg_repeat = {0}; cfg_repeat.repeat = true; uint16_t current_duty_cw = duty_cw_val; uint16_t current_duty_ww = duty_ww_val; if (current_duty_cw > PWM_DUTY_RATIO_MAX) { current_duty_cw = PWM_DUTY_RATIO_MAX; } if (current_duty_ww > PWM_DUTY_RATIO_MAX) { current_duty_ww = PWM_DUTY_RATIO_MAX; } uint32_t high_cnt_cw = (pwm_period_cnt * current_duty_cw) / PWM_DUTY_RATIO_MAX; uint32_t low_cnt_cw = pwm_period_cnt - high_cnt_cw; uint32_t high_cnt_ww = (pwm_period_cnt * current_duty_ww) / PWM_DUTY_RATIO_MAX; uint32_t low_cnt_ww = pwm_period_cnt - high_cnt_ww; if (!on_state) { high_cnt_cw = 0; low_cnt_cw = pwm_period_cnt; // Ensure low_cnt is full period if off high_cnt_ww = 0; low_cnt_ww = pwm_period_cnt; // Ensure low_cnt is full period if off } // uapi_pwm_stop_group(CONFIG_PWM_GROUP_ID); cfg_repeat.high_time = high_cnt_cw; cfg_repeat.low_time = low_cnt_cw; uapi_pwm_open(channel_id_cw, &cfg_repeat); // uapi_pwm_update_duty_ratio(channel_id_cw, cfg_repeat.low_time, cfg_repeat.high_time); cfg_repeat.high_time = high_cnt_ww; cfg_repeat.low_time = low_cnt_ww; cfg_repeat.offset_time = high_cnt_cw; // WW PWM starts after CW PWM high time uapi_pwm_open(channel_id_ww, &cfg_repeat); // uapi_pwm_update_duty_ratio(channel_id_ww, cfg_repeat.low_time, cfg_repeat.high_time); uapi_pwm_start_group(CONFIG_PWM_GROUP_ID); } static void pwm_init(pin_t pin, pin_t pin1) { // uapi_pin_set_mode(pin, PIN_MODE_1); // uapi_pin_set_mode(pin1, PIN_MODE_1); writel(0x4400d000, 1); //设置GPIO00引脚PWM输出 寄存器地址和io复用号参考文档 writel(0x4400d010, 1); //设置GPIO04引脚PWM输出 寄存器地址和io复用号参考文档 uapi_pwm_init(); // uint32_t frequency = uapi_pwm_get_frequency(pin%8); // uint32_t pwm_base_period_ns = 1000 * 1000 * 1000 / frequency; // uint32_t pwm_base_period_ns = 1000 * 1000 * 1000 / (80 * 1000 * 1000);// 80MHZ // uint32_t pwm_target_period_ns = 1000 * 1000 * 1000 / PWM_FREQUENCY; pwm_period_cnt = ((80 * 1000 * 1000) / PWM_FREQUENCY); // 设置PWM组 channel_id_cw = pin%8; channel_id_ww = pin1%8; uint8_t channel_ids[2] = {channel_id_cw, channel_id_ww}; pwm_config_t cfg_repeat = {0}; cfg_repeat.repeat = true; cfg_repeat.low_time = pwm_period_cnt; uapi_pwm_open(channel_id_cw, &cfg_repeat); uapi_pwm_open(channel_id_ww, &cfg_repeat); uapi_pwm_set_group(CONFIG_PWM_GROUP_ID, channel_ids, sizeof(channel_ids)); uapi_pwm_start_group(CONFIG_PWM_GROUP_ID); // 计算PWM占空比 calculate_pwm_duty(&g_device_control); // 更新PWM输出 update_pwm_output(g_device_control.on, g_device_control.duty_cw, g_device_control.duty_ww); boot_msg0("PWM init success!"); } // 计算校验和 static uint8_t calculate_checksum(const device_data_t* data) { uint8_t sum = 0; const uint8_t* ptr = (const uint8_t*)(((char*)data) + sizeof(data->checksum)); size_t len = sizeof(device_data_t) - sizeof(data->checksum); // 减去checksum字段的大小 for (size_t i = 0; i < len; i++) { sum ^= ptr[i]; } return sum; } // 验证数据有效性 static bool verify_device_data(const device_data_t* data) { if (data->magic != DEVICE_DATA_MAGIC) { e_printf("magic error:%x\n", data->magic); return false; } if (data->version > DEVICE_DATA_VERSION) { e_printf("versoin missmatch:%x\n", data->version); return false; } uint8_t checksum = calculate_checksum(data); if (checksum != data->checksum) { e_printf("check sum error:%x\n", data->version); return false; } return true; } // 从指定地址读取设备数据 static bool read_device_data_from_addr(uint32_t addr, device_data_t* data) { int ret = uapi_sfc_reg_read(addr, (uint8_t*)data, sizeof(device_data_t)); if (ret != 0) { print_str("read device data from address 0x%x failed, actual read length: %d\r\n", addr, ret); return false; } if (!verify_device_data(data)) { print_str("address 0x%x data is invalid\r\n", addr); return false; } return true; } void read_device_data(void) { #if SUPPORT_SAVE_TO_FLASH device_data_t data; bool main_valid = false; bool backup_valid = false; // 尝试读取主数据区 main_valid = read_device_data_from_addr(DEVICE_DATA_FLASH_ADDR + 0x003DE000, &data); // 如果主数据区无效,尝试读取备份区 if (!main_valid) { backup_valid = read_device_data_from_addr(DEVICE_DATA_BACKUP_ADDR + 0x003DE000, &data); } if (!main_valid && backup_valid) { // 如果主数据区无效但备份区有效,从备份区恢复 print_str("restore data from backup\r\n"); } else if (!main_valid && !backup_valid) { // 如果两个区域都无效,使用默认值 print_str("main and backup data are invalid, use default value\r\n"); goto lab_exit; } // 更新设备控制状态 print_str("restore device status:\r\n"); print_str("on: %d => %d\r\n", g_device_control.on, data.control.on); print_str("brightness: %d => %d\r\n", g_device_control.brightness_local, data.control.brightness_local); print_str("cct: %d => %d\r\n", g_device_control.cct_local, data.control.cct_local); e_printf("colourMode: %d => %d\r\n", g_device_control.colourMode, data.control.colourMode); data.control.read_done = false; g_device_control = data.control; lab_exit: #endif g_device_control.read_done = true; print_str("read device data success\r\n"); } #endif // end of FASTBOOT_PWM static uint32_t ws63_flashboot_init(void) { errcode_t err; uart_param_stru uart_param = FLASHBOOT_UART_DEFAULT_PARAM; uapi_tcxo_init(); hiburn_uart_init(uart_param, HIBURN_CODELOADER_UART); boot_msg0("Flashboot Uart Init Succ!"); uapi_partition_init(); pmp_enable(); malloc_port_init(); boot_flash_init(); boot_msg0("Flashboot Uart Init Succ!"); boot_msg0("Flashboot Malloc Init Succ!"); err = sfc_port_fix_sr(); if (err != ERRCODE_SUCC) { boot_msg1("SFC fix SR ret =", err); } dump_io_level(); #if FASTBOOT_PWM read_device_data(); pwm_init(BRIGHTNESS_PIN, CCT_PIN); #endif print_str("flashboot version : %s\r\n", SDK_VERSION); return 0; } static errcode_t ws63_verify_app(uint32_t addr) { errcode_t ret = ERRCODE_SUCC; image_key_area_t *flashboot_key_area = (image_key_area_t *)(FLASHBOOT_RAM_ADDR); ret = verify_image_head(APP_BOOT_TYPE, (uint32_t)(uintptr_t)flashboot_key_area->ext_pulic_key_area, addr); if (ret != ERRCODE_SUCC) { boot_msg1("flashboot verify_image_app_head failed!! ret = ", ret); return ret; } ret = verify_image_body(addr, addr + APP_IMAGE_HEADER_LEN); if (ret != ERRCODE_SUCC) { boot_msg1("verify_image_app_body failed!! ret = ", ret); return ret; } return ERRCODE_SUCC; } static void ws63_verify_app_handle(uint32_t addr) { errcode_t ret = ws63_verify_app(addr); if (ret != ERRCODE_SUCC) { ws63_try_fix_app(); reset(); } set_reset_count(0); ws63_set_try_fix_cnt(0); } static void ws63_flash_encrypt_config(uint32_t image_addr, uint32_t image_size) { image_code_info_t *img_info = (image_code_info_t *)(uintptr_t)(image_addr + sizeof(image_key_area_t)); crypto_klad_effective_key flash_key = {0}; uint32_t start_addr = image_addr + APP_IMAGE_HEADER_LEN; uint32_t end_addr = image_addr + image_size; int32_t ret = ERRCODE_SUCC; if (img_info->code_enc_flag == FLASH_NO_ENCRY_FLAG) { boot_msg0("flash_encrypt disable."); return; } if (start_addr % FLASH_ENCRY_ADDR_ALINE != 0 || end_addr % FLASH_ENCRY_ADDR_ALINE != 0) { boot_msg2("app_image start or end addr err, must 256byte alignment ", image_addr, end_addr); reset(); } boot_msg0("flash_encrypt enable."); flash_key.kdf_hard_alg = CRYPTO_KDF_HARD_ALG_SHA256; flash_key.key_parity = TD_FALSE; flash_key.key_size = CRYPTO_KLAD_KEY_SIZE_128BIT; flash_key.salt = img_info->protection_key_l1; flash_key.salt_length = FLASH_KEY_SALT_LEN; flash_key.oneway = TD_TRUE; ret = drv_rom_cipher_config_odrk1(flash_key); if (ret != ERRCODE_SUCC) { boot_msg1("fapc_set_config drv_rom_cipher_config_odrk1 err = ", (uint32_t)ret); reset(); } ret = drv_rom_cipher_fapc_config(0, start_addr, end_addr, img_info->iv, IV_LEN); if (ret != ERRCODE_SUCC) { boot_msg1("fapc_set_config drv_rom_cipher_fapc_config err = ", (uint32_t)ret); reset(); } ret = drv_rom_cipher_fapc_bypass_config(1, end_addr, FLASH_MAX_END, TD_TRUE); if (ret != ERRCODE_SUCC) { boot_msg1("fapc_set_config drv_rom_cipher_fapc_bypass_config err = ", (uint32_t)ret); reset(); } } static uint32_t ws63_ftm_mode_init(uint32_t image_addr) { uint32_t image_size = 0; uint32_t jump_addr = 0; mfg_factory_config_t mfg_factory_cfg = {0}; uint32_t run_region = mfg_get_ftm_run_region(&mfg_factory_cfg); if (run_region == FTM_REGION_SERVICE) { return 0; } jump_addr = mfg_factory_cfg.factory_addr_start; image_size = mfg_factory_cfg.factory_size; image_key_area_t *mfg_key_area = (image_key_area_t *)(uintptr_t)(jump_addr); if (mfg_key_area->image_id == FACTORYBOOT_KEY_AREA_IMAGE_ID && mfg_factory_cfg.factory_valid == MFG_FACTORY_VALID) { dmmu_set(image_addr, image_addr + image_size, jump_addr, 0); } return 0; } /* the entry of C. */ void start_fastboot(void) { partition_information_t img_info = {0}; uint32_t image_addr = 0; uint32_t image_size = 0; errcode_t err; fix_io_level(); // 关闭CMU假负载 uapi_reg_setbits(REG_CMU_CFG0, 3, 3, 0x7); // 0x7 -> 0x40003408 bit 5:3 (3 bits) boot_clock_adapt(); dmmu_set(0, 0, 0, FAMA_REMAP_LOW_BITS); uapi_watchdog_init(BOOT_WATCH_DOG_TIMOUT); uapi_watchdog_enable(WDT_MODE_RESET); ws63_flashboot_init(); set_efuse_period(); uapi_efuse_init(); ws63_upg_check(); // 升级模式判断 err = uapi_partition_get_info(PARTITION_APP_IMAGE, &img_info); if (err != ERRCODE_SUCC) { boot_msg0("Flashboot get app partition failed!, boot abort!"); reset(); } image_addr = img_info.part_info.addr_info.addr + FLASH_START; image_size = img_info.part_info.addr_info.size; #ifdef CONFIG_MIDDLEWARE_SUPPORT_UPG_AB char *boot_str = "A"; uint32_t jump_addr = upg_get_region_addr(upg_get_run_region()) + FLASH_START; *boot_str = (image_addr == jump_addr) ? 'A' : 'B'; boot_msg0(boot_str); ws63_flash_encrypt_config(jump_addr, image_size); // flash在线加解密配置 ws63_verify_app_handle(jump_addr); // A/B验签 if (image_addr != jump_addr) { // 0x1000: dmmu配置都是闭区间,且需要是4K对齐的地址, 0: 第0组dmmu配置 dmmu_set(image_addr, image_addr + image_size - 0x1000, jump_addr, 0); // 0x1000: dmmu配置都是闭区间,且需要是4K对齐的地址, 1: 第1组dmmu配置 dmmu_set(jump_addr, jump_addr + image_size - 0x1000, image_addr, 1); } #else // 压缩 ws63_flash_encrypt_config(image_addr, image_size); // flash在线加解密配置 ws63_verify_app_handle(image_addr); // app验签 #endif ws63_ftm_mode_init(image_addr); ws63_flashboot_recovery(); uapi_watchdog_kick(); jump_to_execute_addr(image_addr + APP_IMAGE_HEADER_LEN); }