diff --git a/.gitignore b/.gitignore index 1726afd..bf2f1e5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,6 @@ *.so *.bin output -bootloader libs_url open_source temp diff --git a/bootloader/flashboot_ws63/CMakeLists.txt b/bootloader/flashboot_ws63/CMakeLists.txt new file mode 100755 index 0000000..567b026 --- /dev/null +++ b/bootloader/flashboot_ws63/CMakeLists.txt @@ -0,0 +1,55 @@ +#=============================================================================== +# @brief cmake file +# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2022-2022. All rights reserved. +#=============================================================================== +set(COMPONENT_NAME "flashboot_common") + +if("flashboot" IN_LIST BIN_NAME) + set(SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/startup/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/startup/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/startup/riscv_init.S + ${CMAKE_CURRENT_SOURCE_DIR}/../commonboot/src/secure_verify_boot.c + ) + + set(PUBLIC_HEADER + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_SOURCE_DIR}/../commonboot/include + ) +elseif ("ssb" IN_LIST BIN_NAME) + set(SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/ssb/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/ssb/riscv_init.S + ${CMAKE_CURRENT_SOURCE_DIR}/../commonboot/src/secure_verify_boot.c + ) + + set(PUBLIC_HEADER + ${CMAKE_CURRENT_SOURCE_DIR}/../commonboot/include + ) +endif() + +set(PRIVATE_HEADER +) + +set(PRIVATE_DEFINES +) + +set(PUBLIC_DEFINES +) + +# use this when you want to add ccflags like -include xxx +set(COMPONENT_PUBLIC_CCFLAGS +) + +set(COMPONENT_CCFLAGS +) + +set(WHOLE_LINK + true +) + +set(MAIN_COMPONENT + false +) + +build_component() \ No newline at end of file diff --git a/bootloader/flashboot_ws63/startup/main.c b/bootloader/flashboot_ws63/startup/main.c new file mode 100755 index 0000000..267ec15 --- /dev/null +++ b/bootloader/flashboot_ws63/startup/main.c @@ -0,0 +1,1203 @@ +/* + * 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); +} diff --git a/bootloader/flashboot_ws63/startup/riscv_init.S b/bootloader/flashboot_ws63/startup/riscv_init.S new file mode 100755 index 0000000..87fb2c7 --- /dev/null +++ b/bootloader/flashboot_ws63/startup/riscv_init.S @@ -0,0 +1,93 @@ +/* + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2021-2021. All rights reserved. + * Description: main + * + * Create: 2021-03-09 + */ + + .section .text.entry + .global _start + .option norvc +_start: + j Reset_Handler + +Reset_Handler: + li t0,0x0 + csrw pmpcfg0,t0 + li t0,0x0 + csrw pmpcfg1,t0 + li t0,0x0 + csrw pmpcfg2,t0 + li t0,0x0 + csrw pmpcfg3,t0 + li t0,0x0 + csrw 0x7d9,t0 + la t0, __flash_boot_flag_begin__ + mv t1, a0 + lw t3, (t1) + sw t3, (t0) + la t0, trap_vector + addi t0, t0, 1 + csrw mtvec, t0 + csrwi mstatus, 0 + csrwi mie, 0 + + # initialize global pointer + la gp, _gp_ + + # initialize stack pointer + la sp, __stack_top__ + + /* init stack */ + la t0, g_system_stack_begin + la t1, g_system_stack_end + beq t0, t1, end_set_stack_loop + li t2, 0xefbeadde + +set_stack_loop: + sw t2, (t0) + addi t0, t0, 4 + blt t0, t1, set_stack_loop +end_set_stack_loop: + + /* clear reg */ + li ra, 0 + li tp, 0 + li s0, 0 + li s1, 0 + li a0, 0 + li a1, 0 + li a2, 0 + li a3, 0 + li a4, 0 + li a5, 0 + li a6, 0 + li a7, 0 + li s2, 0 + li s3, 0 + li s4, 0 + li s5, 0 + li s6, 0 + li s7, 0 + li s8, 0 + li s9, 0 + li s10, 0 + li s11, 0 + li t3, 0 + li t4, 0 + li t5, 0 + li t6, 0 + + /* clear bss section */ + la t0, __bss_begin__ + la t1, __bss_end__ + beq t0, t1, end_clear_bss_loop + li t2, 0x00000000 + +clear_bss_loop: + sw t2, (t0) + addi t0, t0, 4 + blt t0, t1, clear_bss_loop +end_clear_bss_loop: + + j start_fastboot diff --git a/build/config/target_config/ws63/fota/__pycache__/fota_format_st.cpython-39.pyc b/build/config/target_config/ws63/fota/__pycache__/fota_format_st.cpython-39.pyc deleted file mode 100644 index 79baaa6..0000000 Binary files a/build/config/target_config/ws63/fota/__pycache__/fota_format_st.cpython-39.pyc and /dev/null differ diff --git a/drivers/chips/ws63/porting/pwm/pwm_porting.c b/drivers/chips/ws63/porting/pwm/pwm_porting.c new file mode 100755 index 0000000..1b3e88e --- /dev/null +++ b/drivers/chips/ws63/porting/pwm/pwm_porting.c @@ -0,0 +1,181 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2022-2022. All rights reserved. + * + * Description: Provides pwm port \n + * + * History: \n + * 2022-09-16, Create file. \n + */ + + #include "chip_core_irq.h" + #include "soc_osal.h" + #include "common_def.h" + #include "hal_pwm_v151.h" + #include "platform_core.h" + #include "chip_io.h" + #include "soc_porting.h" + #include "pwm_porting.h" + + #define BUS_CLOCK_TIME_40M 40000000UL + #define BIT_WIDTH_LIMIT 0xFFFF + #define CLDO_CRG_CLK_SEL 0x44001134 + #define PWM_CKSEL_BIT 7 + + #define CLDO_SUB_CRG_CKEN_CTL0 0x44001100 + #define CLDO_CRG_DIV_CTL3 0x44001114 + #define CLDO_CRG_DIV_CTL4 0x44001118 + #define CLDO_CRG_DIV_CTL5 0x4400111C + + #define PWM_BUS_CKEN 2 + #define PWM_CHANNEL_CKEN_LEN 9 + + #define PWM0_LOAD_DIV_EN 20 + #define PWM0_DIV1_CFG 16 + #define PWM0_DIV1_CFG_LEN 4 + #define PWM1_LOAD_DIV_EN 30 + #define PWM1_DIV1_CFG 26 + #define PWM1_DIV1_CFG_LEN 4 + #define PWM2_LOAD_DIV_EN 8 + #define PWM2_DIV1_CFG 4 + #define PWM2_DIV1_CFG_LEN 4 + #define PWM3_LOAD_DIV_EN 18 + #define PWM3_DIV1_CFG 14 + #define PWM3_DIV1_CFG_LEN 4 + #define PWM4_LOAD_DIV_EN 28 + #define PWM4_DIV1_CFG 24 + #define PWM4_DIV1_CFG_LEN 4 + #define PWM5_LOAD_DIV_EN 8 + #define PWM5_DIV1_CFG 4 + #define PWM5_DIV1_CFG_LEN 4 + #define PWM6_LOAD_DIV_EN 18 + #define PWM6_DIV1_CFG 14 + #define PWM6_DIV1_CFG_LEN 4 + #define PWM7_LOAD_DIV_EN 28 + #define PWM7_DIV1_CFG 24 + #define PWM7_DIV1_CFG_LEN 4 + + #define PWM_DIV_6 6 + #define PWM_DIV_10 10 + + uintptr_t g_pwm_base_addr = (uintptr_t)PWM_0_BASE; + + uintptr_t pwm_porting_base_addr_get(void) + { + return g_pwm_base_addr; + } + + static int pwm_handler(int a, const void *tmp) + { + unused(a); + unused(tmp); + hal_pwm_v151_irq_handler(); + return 0; + } + void pwm_port_register_hal_funcs(void) + { + hal_pwm_register_funcs(hal_pwm_v151_funcs_get()); + } + + void pwm_port_unregister_hal_funcs(void) + { + hal_pwm_unregister_funcs(); + } + + void pwm_port_clock_enable(bool on) + { + if (on == true) { + uint32_t div_cfg = PWM_DIV_6; + #ifdef CONFIG_HIGH_FREQUENCY + uapi_reg_setbit(CLDO_CRG_CLK_SEL, PWM_CKSEL_BIT); + #elif defined(CONFIG_LOW_FREQUENCY) + uapi_reg_clrbit(CLDO_CRG_CLK_SEL, PWM_CKSEL_BIT); + if (get_tcxo_freq() == CLK24M_TCXO) { + div_cfg = PWM_DIV_6; + } else { + div_cfg = PWM_DIV_10; + } + #endif + reg32_setbits(CLDO_SUB_CRG_CKEN_CTL0, PWM_BUS_CKEN, PWM_CHANNEL_CKEN_LEN, 0x1FF); + + reg32_clrbit(CLDO_CRG_DIV_CTL3, PWM0_LOAD_DIV_EN); + reg32_setbits(CLDO_CRG_DIV_CTL3, PWM0_DIV1_CFG, PWM0_DIV1_CFG_LEN, div_cfg); + reg32_setbit(CLDO_CRG_DIV_CTL3, PWM0_LOAD_DIV_EN); + + reg32_clrbit(CLDO_CRG_DIV_CTL3, PWM1_LOAD_DIV_EN); + reg32_setbits(CLDO_CRG_DIV_CTL3, PWM1_DIV1_CFG, PWM1_DIV1_CFG_LEN, div_cfg); + reg32_setbit(CLDO_CRG_DIV_CTL3, PWM1_LOAD_DIV_EN); + + reg32_clrbit(CLDO_CRG_DIV_CTL4, PWM2_LOAD_DIV_EN); + reg32_setbits(CLDO_CRG_DIV_CTL4, PWM2_DIV1_CFG, PWM2_DIV1_CFG_LEN, div_cfg); + reg32_setbit(CLDO_CRG_DIV_CTL4, PWM2_LOAD_DIV_EN); + + reg32_clrbit(CLDO_CRG_DIV_CTL4, PWM3_LOAD_DIV_EN); + reg32_setbits(CLDO_CRG_DIV_CTL4, PWM3_DIV1_CFG, PWM3_DIV1_CFG_LEN, div_cfg); + reg32_setbit(CLDO_CRG_DIV_CTL4, PWM3_LOAD_DIV_EN); + + reg32_clrbit(CLDO_CRG_DIV_CTL4, PWM4_LOAD_DIV_EN); + reg32_setbits(CLDO_CRG_DIV_CTL4, PWM4_DIV1_CFG, PWM4_DIV1_CFG_LEN, div_cfg); + reg32_setbit(CLDO_CRG_DIV_CTL4, PWM4_LOAD_DIV_EN); + + reg32_clrbit(CLDO_CRG_DIV_CTL5, PWM5_LOAD_DIV_EN); + reg32_setbits(CLDO_CRG_DIV_CTL5, PWM5_DIV1_CFG, PWM5_DIV1_CFG_LEN, div_cfg); + reg32_setbit(CLDO_CRG_DIV_CTL5, PWM5_LOAD_DIV_EN); + + reg32_clrbit(CLDO_CRG_DIV_CTL5, PWM6_LOAD_DIV_EN); + reg32_setbits(CLDO_CRG_DIV_CTL5, PWM6_DIV1_CFG, PWM6_DIV1_CFG_LEN, div_cfg); + reg32_setbit(CLDO_CRG_DIV_CTL5, PWM6_LOAD_DIV_EN); + + reg32_clrbit(CLDO_CRG_DIV_CTL5, PWM7_LOAD_DIV_EN); + reg32_setbits(CLDO_CRG_DIV_CTL5, PWM7_DIV1_CFG, PWM7_DIV1_CFG_LEN, div_cfg); + reg32_setbit(CLDO_CRG_DIV_CTL5, PWM7_LOAD_DIV_EN); + } else { + reg32_clrbits(CLDO_SUB_CRG_CKEN_CTL0, PWM_BUS_CKEN, PWM_CHANNEL_CKEN_LEN); + } + } + + void pwm_port_register_irq(pwm_channel_t channel) + { + unused(channel); + osal_irq_request((uintptr_t)PWM_ABNOR_IRQN, (osal_irq_handler)pwm_handler, NULL, NULL, NULL); + + osal_irq_enable((uintptr_t)PWM_ABNOR_IRQN); + } + + void pwm_port_unregister_irq(pwm_channel_t channel) + { + unused(channel); + #ifndef BUILD_NOOSAL + osal_irq_disable((uintptr_t)PWM_ABNOR_IRQN); + osal_irq_disable((uintptr_t)PWM_CFG_IRQN); + osal_irq_free((uintptr_t)PWM_ABNOR_IRQN, NULL); + osal_irq_free((uintptr_t)PWM_CFG_IRQN, NULL); + #endif + } + + void pwm_irq_lock(uint8_t channel) + { + unused(channel); + osal_irq_lock(); + } + + void pwm_irq_unlock(uint8_t channel) + { + unused(channel); + osal_irq_unlock(); + } + + uint32_t pwm_port_get_clock_value(pwm_channel_t channel) + { + if (channel >= PWM_MAX_NUMBER) { + return 0; + } + return BUS_CLOCK_TIME_40M; + } + + errcode_t pwm_port_param_check(const pwm_config_t *cfg) + { + if ((cfg->low_time + cfg->high_time > BIT_WIDTH_LIMIT) || (cfg->offset_time > cfg->low_time)) { + return ERRCODE_PWM_INVALID_PARAMETER; + } + return ERRCODE_SUCC; + } \ No newline at end of file