Files
kunlun/driver/src/hal/system.c
2024-09-28 14:24:04 +08:00

689 lines
16 KiB
C

/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
/* os shim includes */
#include "os_types.h"
#include "os_timer.h"
#include "os_utils.h"
#include "os_mem.h"
#include "hw_reg_api.h"
#include "ahb.h"
#include "cpu.h"
#include "flash.h"
#include "iot_errno.h"
#include "iot_config.h"
#include "iot_io_api.h"
#include "iot_mtd.h"
#include "iot_dbglog_parser.h"
#include "iot_power_mgmt.h"
#include "iot_img_hdr.h"
#include "iot_efuse.h"
#include "iot_module_api.h"
#include "iot_dbglog_api.h"
#include "iot_board_api.h"
#include "iot_gpio_api.h"
#include "iot_utils_api.h"
#include "iot_plc_pm.h"
#include "system.h"
#include "iot_system.h"
/* meter reset signal and power recover detect time difference, unit ms*/
#define IOT_SYSTEM_RESET_SIGNAL_DIFF_TIME 5000
static uint8_t g_chip_pattern = IOT_CHIP_ID_UNKNOWN;
void iot_system_restart(uint8_t reason)
{
if (reason == IOT_SYS_RST_REASON_INVALID) {
iot_printf("set system restart reason is invaild.\n");
IOT_ASSERT(0);
}
system_set_restart_reason(reason);
iot_printf("soft reset, reason:%d\n", reason);
iot_log_save_done(1);
system_restart_chip_by_soft();
}
uint8_t iot_fastboot_scratch_set(uint8_t en)
{
if (en > 1 || en < 0) {
goto err_out;
}
scratch_p_set_fast_boot(en);
return ERR_OK;
err_out:
return ERR_FAIL;
}
uint8_t iot_fastboot_scratch_get(uint8_t* st)
{
uint8_t ret = scratch_p_get_fast_boot();
/* kl1/kl2 not support, return 2. */
if (ret > 1) {
goto err_out;
}
*st = ret;
return ERR_OK;
err_out:
return ERR_FAIL;
}
bool_t IRAM_ATTR iot_data_addr_legal(uint32_t addr)
{
uint32_t start = (uint32_t)&_data;
uint32_t end = (uint32_t)&_sp;
if (((addr < start) || (addr > end))
&& (!os_check_heap_address((void *)addr))) {
#if (DEBUG_INVAILD_ADDR == 0)
iot_printf("Data address[0x%08x] is illegal.\n", addr);
#endif
return false;
}
return true;
}
#if SYSTEM_GPIO_RESET_CONTROL
timer_id_t g_soft_reset_process_timer;
uint8_t g_soft_reset_gpio = 0;
typedef struct {
uint8_t signal_valid;
uint8_t stable_cnt;
} iot_soft_rst_ctrl_t;
iot_soft_rst_ctrl_t g_rst_ctrl = { 0 };
/* software reset process time out function(1s) */
static void iot_sys_reset_process_func(timer_id_t timer_id, void *arg)
{
(void)timer_id;
(void)arg;
uint32_t dur;
uint8_t val = iot_gpio_value_get(g_soft_reset_gpio);
uint64_t power_recover_time;
uint64_t time_diff;
if (g_rst_ctrl.signal_valid) {
if (val == 1 && iot_power_mgmt_check_low_power_mode() == 0) {
/* meter exception */
power_recover_time = iot_plc_pm_get_power_recover_time();
time_diff = os_boot_time64() - power_recover_time;
if (power_recover_time &&
(time_diff < IOT_SYSTEM_RESET_SIGNAL_DIFF_TIME)) {
iot_gpio_interrupt_enable(g_soft_reset_gpio, 1);
g_rst_ctrl.signal_valid = 0;
goto out;
} else {
iot_printf("[D_RESET]:soft reset\n");
iot_system_restart(IOT_SYS_RST_REASON_UNKNOWN);
}
} else {
iot_gpio_interrupt_enable(g_soft_reset_gpio, 1);
g_rst_ctrl.signal_valid = 0;
}
goto out;
}
if (val == 0) {
dur = 10 + g_rst_ctrl.stable_cnt;
g_rst_ctrl.stable_cnt++;
if (g_rst_ctrl.stable_cnt >= 11) {
g_rst_ctrl.stable_cnt = 0;
dur = 1000;
g_rst_ctrl.signal_valid = 1;
}
} else {
iot_gpio_interrupt_enable(g_soft_reset_gpio, 1);
g_rst_ctrl.stable_cnt = 0;
goto out;
}
os_start_timer(g_soft_reset_process_timer, dur);
out:
return;
}
static void iot_sys_reset_int_handle(int arg)
{
// restart chip or not
(void)arg;
iot_gpio_interrupt_enable(g_soft_reset_gpio, 0);
os_start_timer(g_soft_reset_process_timer, 10);
return;
}
#endif /* SYSTEM_GPIO_RESET_CONTROL */
uint8_t iot_sys_reset_ctrl()
{
#if SYSTEM_GPIO_RESET_CONTROL
uint8_t ret = ERR_FAIL;
g_soft_reset_gpio = iot_board_get_gpio(GPIO_RST_CTRL);
if (g_soft_reset_gpio == 0xff) {
return ret;
}
if (iot_gpio_open_as_interrupt(g_soft_reset_gpio)) {
goto out;
}
if (iot_gpio_set_pull_mode(g_soft_reset_gpio,GPIO_PULL_UP)) {
goto out;
}
if (iot_gpio_interrupt_config(g_soft_reset_gpio, GPIO_INT_EDGE_FALLING,
iot_sys_reset_int_handle, 0, GPIO_INT_FUNC_ENABLE_AUTOSTOP)) {
goto out;
}
iot_gpio_interrupt_enable(g_soft_reset_gpio, 1);
/* create delay timer */
g_soft_reset_process_timer = os_create_timer(IOT_DRIVER_MID, false,
iot_sys_reset_process_func, NULL);
if (g_soft_reset_process_timer == 0) {
iot_printf("soft reset process timer creat failed.\n");
goto out;
}
ret = ERR_OK;
out:
if (ret) {
iot_gpio_close(g_soft_reset_gpio);
}
return ret;
#else
return ERR_OK;
#endif
}
uint32_t iot_cpu1_count_get()
{
if (g_cpu1_state.flags == CPU_FLAG_RUNNING) {
return g_cpu1_state.count;
} else {
return 0;
}
}
uint32_t iot_cpu1_crash_get()
{
if (g_cpu1_state.flags == CPU_FLAG_RUNNING) {
return g_cpu1_state.crash;
} else {
return 0;
}
}
extern void assert_failed(unsigned char *pucFile, unsigned long ulLine);
void iot_cpu1_crash_dump()
{
iot_printf("CPU1: mcause: 0x%08x, mepc: 0x%08x\n", g_cpu1_state.mcause,
g_cpu1_state.mepc);
if(g_cpu1_state.assert_failed){
iot_printf("CPU1 %s:%d Asserted!\n", g_cpu1_state.assert_info.file,
g_cpu1_state.assert_info.line);
assert_failed(g_cpu1_state.assert_info.file, g_cpu1_state.assert_info.line);
}
}
void iot_switch_boot_part(void)
{
dev_switch_part_flag(DEV_SWITCH_PART_CAUSE_OTHER);
}
#if (HW_CHIP_ID == HW_CHIP_ID_HZ)
uint32_t iot_chip_id_check()
{
uint32_t pass = IOT_CHIP_ID_UNKNOWN;
uint32_t chip_id;
uint32_t chipid = iot_chip_get_chip_info();
uint32_t subid = iot_chip_get_chip_subid_info();
/* 检查HZ芯片的subid是否合法 */
switch (chipid) {
case CHIP_ID_HZ3201_V1A:
{
switch (subid) {
case 0:
case CHIP_ID_HZ3201_V1A:
case CHIP_ID_QJ5580D_V1A:
case CHIP_ID_FLX6710_V1A:
case CHIP_ID_SPE7303_V1A:
case CHIP_ID_GX2001_V1A:
case CHIP_ID_DT0530_V1A:
case CHIP_ID_YP8801_V1A:
break;
default:
IOT_ASSERT(0);
break;
}
break;
}
case CHIP_ID_HZ3211_V1A:
{
switch (subid) {
case 0:
case CHIP_ID_HZ3211_V1A:
case CHIP_ID_QJ5582D_V1A:
case CHIP_ID_FLX6711_V1A:
case CHIP_ID_SPE7301_V1A:
case CHIP_ID_GX2011_V1A:
case CHIP_ID_DT0531_V1A:
case CHIP_ID_YP8811_V1A:
break;
default:
IOT_ASSERT(0);
break;
}
break;
}
case CHIP_ID_HZ3201_RF_V1A:
{
switch (subid) {
case 0:
case CHIP_ID_HZ3201_RF_V1A:
case CHIP_ID_QJ5580D_V1A:
case CHIP_ID_FLX6710_V1A:
case CHIP_ID_SPE7303_V1A:
case CHIP_ID_GX2001_V1A:
case CHIP_ID_DT0530_V1A:
case CHIP_ID_YP8801_V1A:
break;
default:
IOT_ASSERT(0);
break;
}
break;
}
case CHIP_ID_HZ3211_RF_V1A:
{
switch (subid) {
case 0:
case CHIP_ID_HZ3211_RF_V1A:
case CHIP_ID_QJ5582D_V1A:
case CHIP_ID_FLX6711_V1A:
case CHIP_ID_SPE7301_V1A:
case CHIP_ID_GX2011_V1A:
case CHIP_ID_DT0531_V1A:
case CHIP_ID_YP8811_V1A:
break;
default:
IOT_ASSERT(0);
break;
}
break;
}
default:
break;
}
/* 检查非HZ芯片的chip id与subid是否匹配 */
if (chipid != CHIP_ID_HZ3201_V1A && chipid != CHIP_ID_HZ3211_V1A &&
chipid != CHIP_ID_HZ3201_RF_V1A && chipid != CHIP_ID_HZ3211_RF_V1A &&
subid != 0 && subid != chipid) {
iot_printf("chip id [0x%08X] and subid [0x%04X]do not matched.\n",
chipid, subid);
IOT_ASSERT(0);
}
if (subid) {
chip_id = subid;
} else {
chip_id = chipid;
}
switch(chip_id){
case CHIP_ID_HZ_K48V1A:
case CHIP_ID_HZ_K48V2A:
case CHIP_ID_HZ_K48V3A:
case CHIP_ID_HZ_K68V1A:
case CHIP_ID_HZ_K68V2A:
case CHIP_ID_HZ_K68V3A:
pass = IOT_CHIP_ID_HT_WQ;
break;
case CHIP_ID_WQ_K48V2A:
case CHIP_ID_WQ_K48V2A2:
case CHIP_ID_WQ_K48V3A:
case CHIP_ID_WQ_K48V3A2:
case CHIP_ID_WQ_K48V3A3:
case CHIP_ID_WQ_K68V3A:
case CHIP_ID_WQ_K68V3A2:
pass = IOT_CHIP_ID_HT_WQ;
break;
case CHIP_ID_MT_K68V1B:
case CHIP_ID_MT_K68V2B:
case CHIP_ID_MT_K68V3B:
case CHIP_ID_MT_K68V1BB:
case CHIP_ID_MT_K68V2BB:
case CHIP_ID_MT_K68V3BB:
case CHIP_ID_MT_K68V3A:
pass = IOT_CHIP_ID_MT;
break;
case CHIP_ID_FLX_K68:
case CHIP_ID_FLX_K48:
pass = IOT_CHIP_ID_HT_WQ;
break;
/* kl3 */
case CHIP_ID_HZ3201_V1A:
case CHIP_ID_HZ3211_V1A:
case CHIP_ID_HZ3201_RF_V1A:
case CHIP_ID_HZ3211_RF_V1A:
pass = IOT_CHIP_ID_HT_WQ;
break;
case CHIP_ID_WQ3031_V1A:
pass = IOT_CHIP_ID_HT_WQ;
break;
case CHIP_ID_QJ5580D_V1A:
case CHIP_ID_QJ5582D_V1A:
pass = IOT_CHIP_ID_QJ;
break;
case CHIP_ID_FLX6710_V1A:
case CHIP_ID_FLX6711_V1A:
pass = IOT_CHIP_ID_FLX;
break;
case CHIP_ID_SPE7301_V1A:
case CHIP_ID_SPE7303_V1A:
pass = IOT_CHIP_ID_SPE;
break;
case CHIP_ID_GX2001_V1A:
case CHIP_ID_GX2011_V1A:
pass = IOT_CHIP_ID_GX;
break;
case CHIP_ID_HZ5202_V1A:
pass = IOT_CHIP_ID_HT_WQ;
break;
case CHIP_ID_DT0530_V1A:
case CHIP_ID_DT0531_V1A:
pass = IOT_CHIP_ID_DT;
break;
case CHIP_ID_YP8801_V1A:
case CHIP_ID_YP8811_V1A:
pass = IOT_CHIP_ID_YP;
break;
default:
pass = IOT_CHIP_ID_UNKNOWN;
break;
}
if(pass == IOT_CHIP_ID_UNKNOWN){
iot_printf("chip pattern [0x%08X] is not matched.\n", chip_id);
IOT_ASSERT(0);
}
return pass;
}
#elif (HW_CHIP_ID == HW_CHIP_ID_WQ)
uint32_t iot_chip_id_check()
{
uint32_t pass = IOT_CHIP_ID_UNKNOWN;
uint32_t chip_id;
uint32_t chipid = iot_chip_get_chip_info();
uint32_t subid = iot_chip_get_chip_subid_info();
/* 检查HZ芯片的subid是否合法 */
switch (chipid) {
case CHIP_ID_HZ3201_V1A:
{
switch (subid) {
case 0:
case CHIP_ID_HZ3201_V1A:
case CHIP_ID_QJ5580D_V1A:
case CHIP_ID_FLX6710_V1A:
case CHIP_ID_SPE7303_V1A:
case CHIP_ID_GX2001_V1A:
case CHIP_ID_DT0530_V1A:
case CHIP_ID_YP8801_V1A:
break;
default:
IOT_ASSERT(0);
break;
}
break;
}
case CHIP_ID_HZ3211_V1A:
{
switch (subid) {
case 0:
case CHIP_ID_HZ3211_V1A:
case CHIP_ID_QJ5582D_V1A:
case CHIP_ID_FLX6711_V1A:
case CHIP_ID_SPE7301_V1A:
case CHIP_ID_GX2011_V1A:
case CHIP_ID_DT0531_V1A:
case CHIP_ID_YP8811_V1A:
break;
default:
IOT_ASSERT(0);
break;
}
break;
}
case CHIP_ID_HZ3201_RF_V1A:
{
switch (subid) {
case 0:
case CHIP_ID_HZ3201_RF_V1A:
case CHIP_ID_QJ5580D_V1A:
case CHIP_ID_FLX6710_V1A:
case CHIP_ID_SPE7303_V1A:
case CHIP_ID_GX2001_V1A:
case CHIP_ID_DT0530_V1A:
case CHIP_ID_YP8801_V1A:
break;
default:
IOT_ASSERT(0);
break;
}
break;
}
case CHIP_ID_HZ3211_RF_V1A:
{
switch (subid) {
case 0:
case CHIP_ID_HZ3211_RF_V1A:
case CHIP_ID_QJ5582D_V1A:
case CHIP_ID_FLX6711_V1A:
case CHIP_ID_SPE7301_V1A:
case CHIP_ID_GX2011_V1A:
case CHIP_ID_DT0531_V1A:
case CHIP_ID_YP8811_V1A:
break;
default:
IOT_ASSERT(0);
break;
}
break;
}
default:
break;
}
/* 检查非HZ芯片的chip id与subid是否匹配 */
if (chipid != CHIP_ID_HZ3201_V1A && chipid != CHIP_ID_HZ3211_V1A &&
chipid != CHIP_ID_HZ3201_RF_V1A && chipid != CHIP_ID_HZ3211_RF_V1A &&
subid != 0 && subid != chipid) {
iot_printf("chip id [0x%08X] and subid [0x%04X]do not matched.\n",
chipid, subid);
IOT_ASSERT(0);
}
if (subid) {
chip_id = subid;
} else {
chip_id = chipid;
}
switch(chip_id){
case CHIP_ID_WQ_K48V2A:
case CHIP_ID_WQ_K48V2A2:
case CHIP_ID_WQ_K48V3A:
case CHIP_ID_WQ_K48V3A2:
case CHIP_ID_WQ_K48V3A3:
case CHIP_ID_WQ_K68V3A:
case CHIP_ID_WQ_K68V3A2:
pass = IOT_CHIP_ID_HT_WQ;
break;
case CHIP_ID_HZ_K48V1A:
case CHIP_ID_HZ_K48V2A:
case CHIP_ID_HZ_K48V3A:
case CHIP_ID_HZ_K68V1A:
case CHIP_ID_HZ_K68V2A:
case CHIP_ID_HZ_K68V3A:
pass = IOT_CHIP_ID_HT_WQ;
break;
/* kl3 */
case CHIP_ID_HZ3201_V1A:
case CHIP_ID_HZ3211_V1A:
case CHIP_ID_HZ3201_RF_V1A:
case CHIP_ID_HZ3211_RF_V1A:
pass = IOT_CHIP_ID_HT_WQ;
break;
case CHIP_ID_WQ3031_V1A:
pass = IOT_CHIP_ID_HT_WQ;
break;
default:
pass = IOT_CHIP_ID_UNKNOWN;
break;
}
if(pass == IOT_CHIP_ID_UNKNOWN){
iot_printf("chip pattern [0x%08X] is not matched.\n", chip_id);
IOT_ASSERT(0);
}
return pass;
}
#else
uint32_t iot_chip_id_check()
{
return IOT_CHIP_ID_UNKNOWN;
}
#endif /* HW_CHIP_ID == HW_CHIP_ID_HZ */
uint8_t iot_chip_get_xor_value()
{
uint8_t xor_value;
if (!g_chip_pattern) {
g_chip_pattern = (uint8_t)iot_chip_id_check();
}
switch(g_chip_pattern) {
case IOT_CHIP_ID_FLX:
{
xor_value = IOT_XOR_VALUE_FLX;
break;
}
case IOT_CHIP_ID_MT:
{
xor_value = IOT_XOR_VALUE;
break;
}
case IOT_CHIP_ID_QJ:
{
xor_value = IOT_XOR_VALUE_QJ;
break;
}
case IOT_CHIP_ID_SPE:
{
xor_value = IOT_XOR_VALUE_SPE;
break;
}
case IOT_CHIP_ID_GX:
{
xor_value = IOT_XOR_VALUE_GX;
break;
}
case IOT_CHIP_ID_DT:
{
xor_value = IOT_XOR_VALUE_DT;
break;
}
case IOT_CHIP_ID_YP:
{
xor_value = IOT_XOR_VALUE_YP;
break;
}
default:
xor_value = 0;
break;
}
return xor_value;
}
uint32_t iot_chip_get_mac_addr(uint8_t *mac)
{
if (mac == NULL) {
return -1;
}
iot_efuse_get_mac_addr(mac);
return 0;
}
uint32_t iot_chip_get_chip_info()
{
return iot_efuse_get_chip_id();
}
uint32_t iot_chip_get_chip_subid_info()
{
return iot_efuse_get_sub_id();
}
uint8_t iot_chip_efuse_check()
{
return iot_efuse_check_data();
}
uint8_t iot_chip_check_lic()
{
return system_check_lic();
}
void iot_system_get_fw_boot_param(void *param)
{
system_get_fw_boot_param((sbl_param_input_t *)param);
}
uint32_t iot_system_get_rst_flag_reg()
{
return system_get_rst_flag_reg();
}