mcu_hi3321_watch/bootloader/flashboot/brandy/main.c
2025-05-26 20:15:20 +08:00

854 lines
26 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) @CompanyNameMagicTag 2021-2021. All rights reserved.
* Description: Main boot for Second Stage Bootloader (SSB).
* Author: @CompanyNameTag
* Create: 2021-03-09
*/
#include <stdbool.h>
#include "codeloader.h"
#include "hal_cpu_core.h"
#include "hal_reboot.h"
#include "hal_sectors.h"
#include "pinctrl_porting.h"
#include "watchdog.h"
#include "watchdog_porting.h"
#include "clocks.h"
#include "bootloader_utils.h"
#include "codeloader_version.h"
#include "codeloader_configuration.h"
#include "bootloader_configuration.h"
#include "otp.h"
#include "application_version.h"
#include "memory_core.h"
#include "irmalloc.h"
#include "tcxo.h"
#include "vectors.h"
#include "non_os.h"
#include "chip_io.h"
#include "hal_qspi.h"
#include "securec.h"
#include "flash_common_config.h"
#include "flash.h"
#include "gpio.h"
#include "preserve.h"
#include "sha256/sha256.h"
#include "qspi.h"
#include "ulp_aon_control.h"
#include "hal_pmu_ldo.h"
#include "pmu.h"
#include "otp_map.h"
#include "flash_config_info.h"
#include "pmu_ldo.h"
#include "sec_boot_fota.h"
#include "cpu_utils.h"
#include "sec_boot_public.h"
#include "clocks_core_common.h"
#include "psram_drv.h"
#include "partition.h"
#include "soc_errno.h"
#include "upg_definitions.h"
#include "hal_xip.h"
#include "pinctrl.h"
#include "systick.h"
#include "boot_ulp.h"
#include "flash_porting.h"
#include "clocks_switch_priv.h"
#include "main.h"
#include "hal_uart_v120_regs_op.h"
#include "hal_pmu_vdd.h"
#ifdef CFG_DRIVERS_NANDFLASH
#include "nandflash_config.h"
#endif
#ifdef CFG_DRIVERS_MMC
#include "drv_mmc_adapter.h"
#endif
#define CFG_PMU_PROTECT_WDT_RESET 1
#define FLASH_INIT_DATA 0xff
#define FLASH_CHECK_LEN 16
#define FLASH_FIRST_PAGE 0
#define COPY_ONE_WORD_LEN 4
#define FLASH_READ_QE_CMD 0x35
#define FLASH_READ_QE_CMD_BIT 0x1
#define FLASH_READ_QE_CMD_VALUE 0x2 // QSPI mode
#define FLASH_SET_QE_CMD_COUNT 0xa
#define READ_FLASH_ID_COUNT 0xa
#define TCXO_REBOOT_DELAY 500ULL
#define TCXO_UART_DELAY 200ULL
#define READ_FLASH_ID_DELAY 20ULL
#define STARTUP_FIRST_INSTRUCTION 0x40006f
#define XIP_READ_QSPI_SYNC_0_OFF 0x304
#define XIP_READ_OVER_TIME_L_0_OFF 0x31c
#define XIP_READ_OVER_TIME_L (XIP_CACHE_CTL + XIP_READ_OVER_TIME_L_0_OFF)
#define XIP_READ_QSPI_SYNC (XIP_CACHE_CTL + XIP_READ_QSPI_SYNC_0_OFF)
#define XIP_READ_OVER_TIME_PERIOD 0x900
#define XIP_READ_QSPI_SYN_EN 0x1
#define PSRAM_XIP_START 0x6c000000
#define PSRAM_XIP_VALUE 0xdeadbeef
#define PSRAM_OPI_DQ 0x57008288
#define PSRAM_OPI_DQ_VAL 0x44
#define PSRAM_CMD_REG_MR01 0x0d8d // cmd:c0c0 addr:0 reg:mr0+mr1
#define PSRAM_EXIST 1U
#define PSRAM_NOT_EXIST 0U
#define UPG_FLAG_OFFSET_OF_FOTA_DATA (0x1000 * 2)
#define UPG_UNFINISHED_FLAG 0xFFFFFFFF
#define DELAY_TIME_30US 30
#define FLASH_PAGE_NUMS_2 2
#define FLASH_PAGE_NUMS_3 3
uint32_t g_psram_exist = PSRAM_NOT_EXIST;
uint8_t g_flash_contents[FLASH_PAGE_SIZE];
void clocks_system_init(void);
/*
* -- Private function definitions
*/
typedef void (*RESET_HANDLER_WITH_ARGS)(uint32_t *table_addr, uint32_t length, uint32_t params);
static bool code_is_valid(const uint32_t *buff)
{
/* g_RamExceptionTable data fit this feature */
/* The APP start address does not locate the interrupt vector table for linx170. */
/* Adaptation is required for this */
if (buff[0] == STARTUP_FIRST_INSTRUCTION) {
return true;
}
return false;
}
/**
* check flash is empty
*/
static bool flash_is_empty(void)
{
if (non_os_is_aon_flag_initialised(AON_ROMLOADER_DOWNLOAD_KEY_MODE) ||
non_os_is_aon_flag_initialised(AON_FLASH_BACKUP_MODE)) {
return true;
}
uint8_t buff[FLASH_CHECK_LEN] = { 0 };
if (uapi_flash_read_data(0, 0, buff, FLASH_CHECK_LEN) == FLASH_CHECK_LEN) {
/* flash init state */
if (buff[0] == FLASH_INIT_DATA) {
return true;
}
if (code_is_valid((uint32_t *)buff)) {
return false;
} else {
PRINT("code valid fail\r\n");
}
}
return true;
}
static bool is_rom_codeloadered(void)
{
hal_uart_regs_init(UART_BUS_1);
uint32_t vali = hal_uart_uartibrd_get_baud_divint(UART_BUS_1);
uint32_t valf = hal_uart_uartfbrd_get_baud_divfrac(UART_BUS_1);
if (vali == 0 && valf == 0) {
return false;
}
return true;
}
/**
* save ssb image to ram for boot
*/
static bool ssb_save_image_in_flash(void)
{
uint8_t *dsc = (uint8_t *)APP_ITCM_ORIGIN;
dsc = dsc + SSB_FLASH_REGION_LENGTH;
uint32_t i = SSB_FLASH_REGION_LENGTH;
if (uapi_flash_block_erase(0, 0, SSB_FLASH_REGION_LENGTH, true) != ERRCODE_SUCC) {
PRINT("SSB ERASE error" NEWLINE);
return false;
}
PRINT("SSB ERASE OK" NEWLINE);
do {
i -= FLASH_PAGE_SIZE;
dsc -= FLASH_PAGE_SIZE;
if (i == FLASH_FIRST_PAGE) {
if (uapi_flash_write_data(0, COPY_ONE_WORD_LEN, (uint8_t *)(dsc + COPY_ONE_WORD_LEN),
(FLASH_PAGE_SIZE - COPY_ONE_WORD_LEN)) != (FLASH_PAGE_SIZE - COPY_ONE_WORD_LEN)) {
PRINT("copy ssb into first word of flash error" NEWLINE);
return false;
}
if (uapi_flash_write_data(0, 0, dsc, COPY_ONE_WORD_LEN) != COPY_ONE_WORD_LEN) {
PRINT("copy ssb into first page of flash error" NEWLINE);
return false;
}
} else {
if (uapi_flash_write_data(0, i, dsc, FLASH_PAGE_SIZE) != FLASH_PAGE_SIZE) {
PRINT("copy ssb into flash error, addr = %x\r\n", (FLASH_START + i));
return false;
}
}
// check flash contents
if (uapi_flash_read_data(0, i, g_flash_contents, FLASH_PAGE_SIZE) != FLASH_PAGE_SIZE) {
PRINT("read flash error, addr = %x\r\n", (FLASH_START + i));
return false;
}
if (memcmp((void *)g_flash_contents, (void *)dsc, FLASH_PAGE_SIZE) != 0) {
PRINT("flash check error. i:%d\n\r\n", i);
return false;
}
uapi_watchdog_kick();
} while (i > 0);
uapi_tcxo_delay_ms(1000ULL);
PRINT("Copy ssb into flash success" NEWLINE);
return true;
}
/**
* save ssb image to ram for boot
*/
static bool ssb_save_sign_in_flash(void)
{
if (!non_os_is_aon_flag_initialised(AON_ROMLOADER_DOWNLOAD_KEY_MODE) &&
!non_os_is_aon_flag_initialised(AON_FLASH_BACKUP_MODE)) {
return true;
}
if (non_os_is_aon_flag_initialised(AON_FLASH_BACKUP_MODE)) {
if (uapi_flash_read_data(0, (MCU_SUB_PUBKEY_BACKUP_START - FLASH_START),
(uint8_t*)(uintptr_t)ROMLOADER_USE_CERT_ORIGIN, ROMLOADER_USE_CERT_LENGTH) != ROMLOADER_USE_CERT_LENGTH) {
PRINT("copy backup subkey to subkey error" NEWLINE);
return false;
}
if (uapi_flash_read_data(0, (MCU_SSB_IMAGE_SIGN_BACKUP_START - FLASH_START),
(uint8_t *)(uintptr_t)ROMLOADER_USE_SSB_SIGN_ORIGIN, ROMLOADER_USE_SSB_SIGN_LENGTH) !=
ROMLOADER_USE_SSB_SIGN_LENGTH) {
PRINT("copy backup sign to ssb sign error" NEWLINE);
return false;
}
// erase 2 flash pages(subpubkey, ssb image sign)
if (uapi_flash_block_erase(0, MCU_SUB_PUBKEY_START - FLASH_START,
(FLASH_PAGE_NUMS_2 * FLASH_PAGE_SIZE), true) != ERRCODE_SUCC) {
PRINT("copy backup sign to ssb sign" NEWLINE);
return false;
}
PRINT("backup: erase subpubkey and ssb image region!!!" NEWLINE);
} else {
// erase 3 flash pages(rootkey, subpubkey, ssb image sign)
if (uapi_flash_block_erase(0, MCU_ROOT_PUBKEY_START - FLASH_START,
(FLASH_PAGE_NUMS_3 * FLASH_PAGE_SIZE), true) != ERRCODE_SUCC) {
PRINT("flash erase rootkey error" NEWLINE);
return false;
}
if (uapi_flash_write_data(0, MCU_ROOT_PUBKEY_START - FLASH_START,
(uint8_t *)(uintptr_t)ROMLOADER_USE_ROOTKEY_ORIGIN, ROMLOADER_USE_ROOTKEY_LENGTH) !=
ROMLOADER_USE_ROOTKEY_LENGTH) {
PRINT("copy rootkey into flash error" NEWLINE);
return false;
}
}
if (uapi_flash_write_data(0, MCU_SUB_PUBKEY_START - FLASH_START, (uint8_t *)(uintptr_t)ROMLOADER_USE_CERT_ORIGIN,
ROMLOADER_USE_CERT_LENGTH) != ROMLOADER_USE_CERT_LENGTH) {
PRINT("copy subkey certificate into flash error" NEWLINE);
return false;
}
if (uapi_flash_write_data(0, MCU_SSB_IMAGE_SIGN_START - FLASH_START,
(uint8_t *)(uintptr_t)ROMLOADER_USE_SSB_SIGN_ORIGIN, ROMLOADER_USE_SSB_SIGN_LENGTH) !=
ROMLOADER_USE_SSB_SIGN_LENGTH) {
PRINT("copy ssb image sign into flash error" NEWLINE);
return false;
}
PRINT("copy sec boot sign info succ" NEWLINE);
return true;
}
static void jump_to_cimage(core_images_e cimage)
{
uint32_t *table_addr = NULL;
uint32_t table_length;
if ((cimage != CORE_IMAGES_APPS) && (cimage != CORE_IMAGES_RECOVERY)) {
PRINT("cimage param error");
return;
}
uint32_t jump_addr = (cimage == CORE_IMAGES_APPS) ? APP_VECTORS_LOAD_ORIGIN : RECOVERY_FLASH_REGION_START;
// 暂时copy 64k到itcm
errno_t sec_ret = memcpy_s((void *)(uintptr_t)APP_VECTORS_ORIGIN, APP_VECTORS_LENGTH,
(void *)(uintptr_t)jump_addr, APP_VECTORS_LENGTH);
if (sec_ret != EOK) {
PRINT("Memory process is error, jump_addr 0x%x, sec_ret %d", jump_addr, sec_ret);
return;
}
hal_xip_clear_tag();
get_ssb_application_table(&table_addr, &table_length);
PRINT("jump_to_cimage :%d, addr:0x%x" NEWLINE, cimage, APP_ITCM_ORIGIN);
if (code_is_valid((uint32_t *)APP_ITCM_ORIGIN) &&
((cimage == CORE_IMAGES_APPS) || (cimage == CORE_IMAGES_RECOVERY))) {
((RESET_HANDLER_WITH_ARGS)(APP_VECTORS_ORIGIN))(table_addr, table_length, g_psram_exist);
} else {
watchdog_turnoff_clk();
while (1) { //lint !e716
}
}
}
static void ssb_invoke_codeloader(void)
{
PRINT("code start codeloader\r\n");
#if defined(SW_UART_DEBUG) && defined(CODELOADER_UART_BUS)
if ((SW_UART_DEBUG == UART_BUS_0 && CODELOADER_UART_BUS == UART_BUS_0) ||
(SW_UART_DEBUG == UART_BUS_1 && CODELOADER_UART_BUS == UART_BUS_1)) {
while (uapi_uart_has_pending_transmissions(SW_DEBUG_UART_BUS)) { }
sw_debug_uart_deinit();
}
#endif
codeloader_options_t cl_options;
memset_s(&cl_options, sizeof(codeloader_options_t), 0, sizeof(codeloader_options_t));
cl_options.info.codeloader_type = CODELOADER_TYPE_SSB;
cl_options.info.rom_code_version = bootloader_utils_get_rom_version();
cl_options.info.chip = CODELOADER_CHIP_CURRENT_CHIP;
cl_options.info.codeloader_version = CODELOADER_VERSION;
cl_options.use_long_timeout = false;
codeloader_configuration_get_permissions(&(cl_options.security_core_allowed),
&(cl_options.protocol_core_allowed), &(cl_options.apps_core_allowed));
// If the code loader is allowed load it
if (cl_options.security_core_allowed || cl_options.protocol_core_allowed || cl_options.apps_core_allowed) {
codeloader_retp_t cl_retp;
(void)codeloader_main_loop(&cl_options, &cl_retp);
}
#if defined(SW_UART_DEBUG) && (SW_DEBUG_UART_BUS == CODELOADER_UART_BUS)
sw_debug_uart_init(UART_L_BAUDRATE);
#endif
PRINT("code finish codeloader" NEWLINE);
}
static void ssb_set_flash_qe(uint32_t flash_set_qe_index)
{
errcode_t loop_flag;
uint8_t i = 0;
PRINT("Set FLASH:%x QE\r\n", g_flash_need_set_qe[flash_set_qe_index].manufacturer_id);
do {
i++;
loop_flag = uapi_flash_send_cmd_exe(0, g_flash_need_set_qe[flash_set_qe_index].flash_set_qe_cmd);
if (i > FLASH_SET_QE_CMD_COUNT) {
break;
}
} while (loop_flag != ERRCODE_SUCC);
if (i > FLASH_SET_QE_CMD_COUNT) {
PRINT("SET QE FAIL!\r\n");
cpu_utils_set_system_status_by_cause(REBOOT_CAUSE_BT_SYSRESETREQ);
hal_reboot_chip();
} else {
PRINT("SET QE SUCESS!\r\n");
}
}
static void ssb_enable_qe_mode_if_need(uint32_t manufacture_id)
{
uint32_t ssb_need_set_qe_num = sizeof(g_flash_need_set_qe) / sizeof(g_flash_need_set_qe[0]);
for (uint32_t i = 0; i < ssb_need_set_qe_num; i++) {
if (manufacture_id == g_flash_need_set_qe[i].manufacturer_id) {
ssb_set_flash_qe(i);
break;
}
}
}
static void hw_init(void)
{
panic_init();
uapi_gpio_init();
uapi_pin_set_mode(ULP_GPIO5, (pin_mode_t)HAL_PIO_FUNC_SWD);
uapi_pin_set_mode(ULP_GPIO6, (pin_mode_t)HAL_PIO_FUNC_SWD);
uapi_pin_set_ds(ULP_GPIO5, (pin_drive_strength_t)HAL_PIO_DRIVE_3);
uapi_pin_set_ds(ULP_GPIO6, (pin_drive_strength_t)HAL_PIO_DRIVE_3);
uapi_pin_set_ds(S_EGPIO0, (pin_drive_strength_t)HAL_PIO_DRIVE_0);
uapi_pin_set_ds(S_EGPIO1, (pin_drive_strength_t)HAL_PIO_DRIVE_0);
uapi_pin_set_ds(S_EGPIO2, (pin_drive_strength_t)HAL_PIO_DRIVE_0);
uapi_pin_set_ds(S_EGPIO3, (pin_drive_strength_t)HAL_PIO_DRIVE_0);
uapi_pin_set_ds(S_EGPIO4, (pin_drive_strength_t)HAL_PIO_DRIVE_0);
uapi_pin_set_ds(S_EGPIO5, (pin_drive_strength_t)HAL_PIO_DRIVE_0);
}
static bool upg_need_upgrade(fota_upgrade_flag_area_t *upg_flag_info)
{
bool ret = false;
uint32_t fota_address = 0;
partition_information_t info;
flash_info_t flash_info;
uint32_t real_read = 0;
uapi_flash_get_info(0, &flash_info);
errcode_t ret_val = uapi_partition_get_info(PARTITION_FOTA_DATA, &info);
if (ret_val != ERRCODE_SUCC || info.type != PARTITION_BY_ADDRESS) {
return false;
}
fota_address = info.part_info.addr_info.addr;
fota_address += UPG_FLAG_OFFSET_OF_FOTA_DATA;
non_os_enter_critical();
if ((errcode_t)uapi_flash_exit_from_xip_mode(0) != ERRCODE_SUCC) {
goto end;
}
if (flash_info.flash_id == FLASH_MANUFACTURER_PUYA_P25Q64SL) {
real_read = uapi_flash_read_data_without_align(0, fota_address, (uint8_t *)(upg_flag_info),
sizeof(fota_upgrade_flag_area_t));
} else {
real_read = uapi_flash_read_data(0, fota_address, (uint8_t *)(upg_flag_info),
sizeof(fota_upgrade_flag_area_t));
}
if (real_read != sizeof(fota_upgrade_flag_area_t)) {
goto end;
}
if (!(upg_flag_info->head_magic == UPG_HEAD_MAGIC &&
upg_flag_info->head_end_magic == UPG_END_MAGIC &&
upg_flag_info->complete_flag != 0)) {
/* 不需要升级直接返回 */
PRINT("No need to upgrade...\r\n");
goto end;
}
ret = true;
end:
uapi_flash_switch_to_xip_mode(0);
non_os_exit_critical();
return ret;
}
static void ssb_erase_upg_flag(void)
{
uint32_t flag_offsets = 0;
partition_information_t info;
errcode_t ret = uapi_partition_get_info(PARTITION_FOTA_DATA, &info);
if (ret != ERRCODE_SUCC || info.type != PARTITION_BY_ADDRESS) {
return;
}
flag_offsets = info.part_info.addr_info.addr + UPG_FLAG_OFFSET_OF_FOTA_DATA;
non_os_enter_critical();
if ((errcode_t)uapi_flash_exit_from_xip_mode(0) != ERRCODE_SUCC) {
goto erase_end;
}
uapi_flash_sector_erase(0, flag_offsets, true);
erase_end:
uapi_flash_switch_to_xip_mode(0);
non_os_exit_critical();
return;
}
static core_images_e ssb_get_jump_image(void)
{
fota_upgrade_flag_area_t upg_flag_info;
// 不需要升级跳转APP
if (!upg_need_upgrade(&upg_flag_info)) {
return CORE_IMAGES_APPS;
}
// APP升级未完成跳转APP
if (upg_flag_info.complete_flag == UPG_UNFINISHED_FLAG) {
return CORE_IMAGES_APPS;
}
// recovery升级未完成跳转Recovery
return CORE_IMAGES_RECOVERY;
}
static void ssb_enter_app(void)
{
core_images_e cimage = ssb_get_jump_image();
if (cimage == CORE_IMAGES_RECOVERY) {
if (!sec_boot_verify_recovery_image()) {
cimage = CORE_IMAGES_APPS;
ssb_erase_upg_flag();
} else {
jump_to_cimage(cimage);
}
}
if (sec_boot_verify_standard_image()) {
jump_to_cimage(cimage);
}
}
static void watchdog_init(void)
{
watchdog_turnon_clk();
#ifdef NO_TIMEOUT
uapi_watchdog_disable();
watchdog_turnoff_clk();
#endif
}
static void ssb_try_read_flash_id(uint32_t *manufacture_id)
{
uint8_t i = 0;
non_os_set_driver_initalised(DRIVER_INIT_FLASH, true); // flash has been initialized in ROM, so initial flag bit
uapi_flash_read_id(0, manufacture_id);
while (*manufacture_id == 0x0 && i < READ_FLASH_ID_COUNT) {
flash_porting_power_off(0);
flash_porting_power_on(0);
uapi_tcxo_delay_ms(READ_FLASH_ID_DELAY);
uapi_flash_read_id(0, manufacture_id);
i++;
}
PRINT("manufacture_id = 0x%x, read id count = 0x%x\r\n", *manufacture_id, i);
}
/* The qspi speed is too slow.
* The xip overtime is too fast, and timeout is easy. */
static void ssb_adjust_xip_over_time(void)
{
writew(XIP_READ_OVER_TIME_L, XIP_READ_OVER_TIME_PERIOD);
writew(XIP_READ_QSPI_SYNC, XIP_READ_QSPI_SYN_EN);
}
static bool psram_is_exist(void)
{
uint32_t val = 0;
(void)uapi_psram_read_reg(0, &val);
if ((uint16_t)val != PSRAM_CMD_REG_MR01) {
PRINT("No psram exists on the current board, skipping psram init."NEWLINE);
return false;
}
return true;
}
static void get_psram_density(void)
{
uint32_t val = 0;
uint32_t density = 0;
if (uapi_psram_read_reg(1, &val) != ERRCODE_SUCC) {
PRINT("get_psram_density fail."NEWLINE);
}
/* The lowest three bits indicate the psram capacity. */
density = val & 0x7;
PRINT("get_psram_density succ, MR1MR2 is 0x%x, density is 0x%x."NEWLINE, val, density);
if (density == PSRAM_DENSITY_16M) {
g_psram_exist = PSRAM_DENSITY_16M;
} else if (density == PSRAM_DENSITY_64M) {
g_psram_exist = PSRAM_DENSITY_64M;
} else if (density == PSRAM_DENSITY_32M) {
g_psram_exist = PSRAM_DENSITY_32M;
} else {
PRINT("psram density unknows, density is 0x%x."NEWLINE, density);
}
}
static void init_psram_section(void)
{
writel(PSRAM_OPI_DQ, PSRAM_OPI_DQ_VAL);
uapi_psram_reset();
uapi_psram_init();
bool ret = psram_is_exist();
if (ret == true) {
g_psram_exist = PSRAM_EXIST;
get_psram_density();
uapi_psram_enter_xip();
writel(PSRAM_XIP_START, PSRAM_XIP_VALUE);
PRINT("Enter PSRAM XIP with value: 0x%x is %s\r\n",\
readl(PSRAM_XIP_START), (readl(PSRAM_XIP_START) == PSRAM_XIP_VALUE) ? "Succ" : "Fail");
hal_xip_clear_tag();
} else {
PRINT("PSRAM is not exist.\r\n");
}
}
static void xip_init(void)
{
// Switch flash to qspi mode in ssb, to enable xip
errcode_t ret;
ret = uapi_flash_switch_to_qspi_init(0);
if (ret != ERRCODE_SUCC) {
PRINT("Switch to qspi init fail\r\n");
return;
}
ret = uapi_flash_switch_to_cache_mode(0);
if (ret != ERRCODE_SUCC) {
PRINT("Switch to cache mode\r\n");
return;
}
ssb_adjust_xip_over_time();
PRINT("Enter XIP with value: 0x%x is %s\r\n", readl(FLASH_START), (readb(FLASH_START) == 0x6f) ? "Succ" : "Fail");
init_psram_section();
}
static void ssb_hold_flash_pin(void)
{
/* In standard mode, when the IO2 and IO3 pins are at low level,
* the flash will ignores the input signals and is suspended.
*/
uapi_pin_set_mode(QSPI0_D2, (pin_mode_t)HAL_PIO_FUNC_GPIO);
uapi_pin_set_mode(QSPI0_D3, (pin_mode_t)HAL_PIO_FUNC_GPIO);
uapi_gpio_set_dir(QSPI0_D2, GPIO_DIRECTION_OUTPUT);
uapi_gpio_set_dir(QSPI0_D3, GPIO_DIRECTION_OUTPUT);
uapi_gpio_set_val(QSPI0_D2, GPIO_LEVEL_HIGH);
uapi_gpio_set_val(QSPI0_D3, GPIO_LEVEL_HIGH);
}
static void ssb_resume_flash_pin(void)
{
uapi_pin_set_mode(QSPI0_D2, (pin_mode_t)HAL_PIO_FUNC_QSPI0);
uapi_pin_set_mode(QSPI0_D3, (pin_mode_t)HAL_PIO_FUNC_QSPI0);
}
#if CFG_PMU_PROTECT_WDT_RESET == 1
void software_delay_us(uint32_t delay)
{
#define SOFT_DELAY_COUNT 40
volatile uint32_t val = delay;
volatile uint32_t count;
while (--val > 0) {
count = SOFT_DELAY_COUNT;
while (count-- > 0) {
;
}
}
}
static void clear_wdt_reset_cause(void)
{
for (uint16_t i = 0; i < UINT16_MAX; i++) {
writew(0x57004304, 0x1);
if (reg16_getbit(0x57004300, 0) == 0) {
break;
}
}
}
static void pmu_protect_config_and_reset(bool rom_codeloadered)
{
// codeloader
if (rom_codeloadered == true) {
writew(0x5702c010, 0x0);
return;
}
// wdt reset
if (reg16_getbit(0x57004300, 0) == 1) {
if (readw(0x5702c010) == 0x5a00) {
clear_wdt_reset_cause();
writew(0x5702c010, 0x0);
}
return;
}
if (readw(0x5702c010) == 0x5a00) {
writew(0x5702c010, 0x0);
return;
}
PRINT("first reset, 0x%x \r\n", readw(0x5702c010));
writew(0x5702c010, 0x5a00);
uapi_tcxo_delay_ms(10ULL);
writew(0x52000700, 0x0); // disable nmi int
watchdog_turnon_clk();
uapi_watchdog_init(CHIP_WDT_TIMEOUT_2S);
uapi_watchdog_enable(WDT_MODE_RESET);
pmu_vdd0p8_power_vset(HAL_PMU_VDD0P8_1P0_1P100V);
writew(0x57028104, 0xF);
writew(0x57028184, 0x1);
hal_pmu_intldo1_set_voltage(HAL_PMU_INTLDO1_LEVEL_1P92V);
writew(0x5700412c, 0x1e); // set short_pd and softtime_adj
writew(0x57004138, 0x1e);
// DBB CCRG 16M
writew(0x5500060c, 0x103); // cpu 8 div
writew(0x5500060c, 0x113);
writew(0x55000614, 0x13); // perp ls 16M
writew(0x55000618, 0x13); // perp uart 16M
writew(0x5500061c, 0x13); // perp spi 16M
writew(0x55000620, 0x13); // combus ch0 16M
writew(0x55000624, 0x13); // combus ch0 16M
writew(0x5500062c, 0x13); // membus 16M
writew(0x55000630, 0x13); // xip opi 16M
writew(0x55000634, 0x13); // xip qspi 16M
hal_clocks_set_aon_bus_div(4); // aon bus 8M
writew(0x57004130, 0x1822); // 1.9->2.0v
reg16_setbit(0x57004124, POS_14); // vo_det 0->1
writew(0x57004108, 0x14C0); // detect threshodd 1.85->1.7v
uapi_tcxo_delay_ms(100UL);
// 32k -> 1M 2s -> 64ms
writew(0x57000060, 0x1820);
writew(0x57000064, 0x601);
writew(0x57000068, 0x1601);
writew(0x57004110, 0x3);
software_delay_us(5UL);
writew(0x57004110, 0x7);
// wait wdt reset
while (1) {
}
}
#endif
static void chip_init(bool rom_codeloadered)
{
int_setup();
uapi_pin_init();
uapi_tcxo_init();
uapi_systick_init();
watchdog_init();
hal_xip_init();
#ifdef SW_UART_DEBUG
sw_debug_uart_init(UART_L_BAUDRATE);
PRINT("SSb Debug uart init succ\r\n");
#endif
#if CFG_PMU_PROTECT_WDT_RESET == 1
pmu_protect_config_and_reset(rom_codeloadered);
#endif
hw_init();
uapi_ulp_systick_self_verification();
// TODO: TJD:打开总电源
#define VDD_PSRAM_EN (S_AGPIO_L11)//使能口
#ifdef VDD_PSRAM_EN
uapi_pin_set_mode(VDD_PSRAM_EN, (pin_mode_t)HAL_PIO_FUNC_GPIO);
uapi_gpio_set_dir(VDD_PSRAM_EN, GPIO_DIRECTION_OUTPUT);
uapi_gpio_set_val(VDD_PSRAM_EN, GPIO_LEVEL_HIGH);
//uapi_pin_set_pull(VDD_PSRAM_EN, PIN_PULL_DOWN);
PRINT("vdd psram poweron\r\n");
#endif
show_reboot_info();
otp_init();
irmalloc_init_default();
}
static void flash_init(void)
{
uint32_t manufacture_id = 0;
uint8_t unique_id = 0;
ssb_hold_flash_pin();
uapi_flash_init(0);
ssb_try_read_flash_id(&manufacture_id);
flash_read_unique_id(0, &unique_id);
#ifdef SW_UART_DEBUG
PRINT("flash unique_id = %d.\r\n", unique_id);
#endif
uapi_flash_config_cmd_at_xip_mode(0, unique_id);
ssb_enable_qe_mode_if_need(manufacture_id);
ssb_resume_flash_pin();
}
static void xip_and_save_ssb(void)
{
xip_init();
bootloader_configuration_init();
create_ssb_to_application_table(hal_reboot_get_reset_reason());
// Save flash information
flash_config_save_info();
#ifndef SSB_EDA_VERSION
uapi_flash_exit_from_xip_mode(0);
ssb_invoke_codeloader();
uapi_flash_switch_to_xip_mode(0);
while (uapi_uart_has_pending_transmissions(SW_DEBUG_UART_BUS)) { }
system_ccrg_clock_config(CLOCKS_CCRG_MODULE_MCU_PERP_UART, CLOCKS_CLK_SRC_TCXO, CLOCK_DIV_1);
#ifdef SW_UART_DEBUG
sw_debug_uart_reset_baund();
#endif
#endif
set_ssb_to_application_image_vaild(true, true);
uapi_partition_init();
}
static void fs_init(void)
{
#ifdef CFG_DRIVERS_NANDFLASH
nandflash_qspi_init();
#endif
#ifdef CFG_DRIVERS_MMC
ssb_emmc_init();
#endif
}
#ifdef SW_RTT_DEBUG
extern uint32_t __rtt_bss_end;
extern uint32_t __rtt_bss_start;
#endif
void main(void)
{
errno_t ret = 0;
bool rom_codeloadered = is_rom_codeloadered();
#ifdef SW_RTT_DEBUG
uint32_t size = (uint32_t)(&__rtt_bss_end) - (uint32_t)(&__rtt_bss_start);
ret = memset_s((void *)((uint32_t)(&__rtt_bss_start)), size, 0, size);
if (ret != EOK) {
PRINT("rtt bss memset fail."NEWLINE);
}
#endif
chip_init(rom_codeloadered);
flash_init();
while (uapi_uart_has_pending_transmissions(SW_DEBUG_UART_BUS)) { }
#ifdef PRE_ASIC
pmu_init();
clocks_system_init();
#endif
#ifdef SW_UART_DEBUG
sw_debug_uart_reset_baund();
#endif
if ((flash_is_empty() || (rom_codeloadered == true)) && ssb_save_sign_in_flash()) {
PRINT("flash is empty, save image into flash" NEWLINE);
ret = ssb_save_image_in_flash();
if (ret == false) {
PRINT("save ssb into flash err" NEWLINE);
uapi_tcxo_delay_ms((uint64_t)TCXO_REBOOT_DELAY);
cpu_utils_set_system_status_by_cause(REBOOT_CAUSE_BT_SSB_EXCEPTION_REBOOT);
// This will reset the aliased regions, you will go to ROM
hal_reboot_chip();
}
}
fs_init();
xip_and_save_ssb();
if (non_os_is_driver_initialised(DRIVER_INIT_OTP) == true) { otp_deinit(); }
ssb_enter_app();
PRINT("No jump, reset now" NEWLINE);
uapi_tcxo_delay_ms((uint64_t)TCXO_REBOOT_DELAY);
cpu_utils_set_system_status_by_cause(REBOOT_CAUSE_BT_SSB_EXCEPTION_REBOOT);
// This will reset the aliased regions, you will go to ROM
hal_reboot_chip();
}