1204 lines
38 KiB
C
Executable File
1204 lines
38 KiB
C
Executable File
/*
|
||
* 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_bound; // 是否已配网
|
||
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_bound = 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);
|
||
}
|