319 lines
7.2 KiB
C
319 lines
7.2 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 <stdlib.h>
|
||
|
|
#include "os_types.h"
|
||
|
|
#include "iot_system_api.h"
|
||
|
|
#include "iot_config.h"
|
||
|
|
#include "iot_irq.h"
|
||
|
|
#include "iot_wdg.h"
|
||
|
|
#include "iot_clock.h"
|
||
|
|
#include "ledc.h"
|
||
|
|
#include "efuse.h"
|
||
|
|
#include "iot_gptmr.h"
|
||
|
|
#include "iot_system.h"
|
||
|
|
#include "iot_power_mgmt.h"
|
||
|
|
#include "iot_io.h"
|
||
|
|
#include "iot_board.h"
|
||
|
|
#include "os_mem.h"
|
||
|
|
#include "cpu.h"
|
||
|
|
#include "os_task.h"
|
||
|
|
|
||
|
|
#include "platform.h"
|
||
|
|
#include "encoding.h"
|
||
|
|
|
||
|
|
#include "sec_glb.h"
|
||
|
|
#include "ahb.h"
|
||
|
|
#include "iot_spinlock.h"
|
||
|
|
#include "intc.h"
|
||
|
|
#include "clk.h"
|
||
|
|
|
||
|
|
//////////////////////////////////////////////
|
||
|
|
typedef void (*func_ptr)(void);
|
||
|
|
|
||
|
|
extern func_ptr __init_array_start[0];
|
||
|
|
extern func_ptr __init_array_end[0];
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @brief Execute initialization routines referenced in .init_array section
|
||
|
|
*
|
||
|
|
* @return N/A
|
||
|
|
*/
|
||
|
|
void __do_init_array_aux(void)
|
||
|
|
{
|
||
|
|
for (func_ptr *func = __init_array_start;
|
||
|
|
func < __init_array_end;
|
||
|
|
func++) {
|
||
|
|
(*func)();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* What a constructor function pointer looks like */
|
||
|
|
|
||
|
|
typedef void (*CtorFuncPtr)(void);
|
||
|
|
|
||
|
|
/* Constructor function pointer list is generated by the linker script. */
|
||
|
|
|
||
|
|
extern CtorFuncPtr __CTOR_LIST__[];
|
||
|
|
extern CtorFuncPtr __CTOR_END__[];
|
||
|
|
|
||
|
|
/**
|
||
|
|
*
|
||
|
|
* @brief Invoke all C++ style global object constructors
|
||
|
|
*
|
||
|
|
* This routine is invoked by the kernel prior to the execution of the
|
||
|
|
* application's main().
|
||
|
|
*/
|
||
|
|
void __do_global_ctors_aux(void)
|
||
|
|
{
|
||
|
|
unsigned int nCtors;
|
||
|
|
|
||
|
|
nCtors = (unsigned int)__CTOR_LIST__[0];
|
||
|
|
|
||
|
|
while (nCtors >= 1) {
|
||
|
|
__CTOR_LIST__[nCtors--]();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
//////////////////////////////////////////////
|
||
|
|
|
||
|
|
extern void def_trap_entry();
|
||
|
|
extern void intc_handler(uint32_t cpu);
|
||
|
|
extern void trigger_zero_addr_access_detect();
|
||
|
|
extern exception_cb_t exception;
|
||
|
|
|
||
|
|
extern void ahb_core0_enable();
|
||
|
|
|
||
|
|
static uint32_t g_exception_nesting = 0;
|
||
|
|
|
||
|
|
extern uint8_t g_app_reg_done;
|
||
|
|
|
||
|
|
uintptr_t IRAM_ATTR handle_trap(uintptr_t mcause,
|
||
|
|
uintptr_t epc, saved_registers *reg)
|
||
|
|
{
|
||
|
|
if ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT) {
|
||
|
|
intc_handler(cpu_get_mhartid());
|
||
|
|
} else {
|
||
|
|
uint8_t toggle = 0;
|
||
|
|
g_exception_nesting++;
|
||
|
|
|
||
|
|
if( g_exception_nesting == 1) {
|
||
|
|
#if IOT_EXCEPTION_DEBUG
|
||
|
|
iot_led_gpio_on(IOT_PLC_TX_LED);
|
||
|
|
iot_led_gpio_off(IOT_PLC_RX_LED);
|
||
|
|
iot_led_gpio_on(IOT_RS485_LED);
|
||
|
|
iot_led_gpio_off(IOT_PLC_TR_LED);
|
||
|
|
#endif
|
||
|
|
exception.handler(mcause, epc, reg);
|
||
|
|
#if IOT_FULL_DUMP_DEBUG
|
||
|
|
exception.full_dump();
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if IOT_EXCEPTION_DEBUG
|
||
|
|
wdg_deinit(HAL_WDG_CPU_0);
|
||
|
|
#if DUAL_WDG_ON_ONE_CPU_ENABLE
|
||
|
|
wdg_deinit(HAL_WDG_CPU_1);
|
||
|
|
#endif
|
||
|
|
iot_power_mgmt_stop_charge();
|
||
|
|
#else
|
||
|
|
wdg_cpu_reset(HAL_WDG_CPU_0);
|
||
|
|
#endif
|
||
|
|
} else {
|
||
|
|
#if IOT_EXCEPTION_DEBUG
|
||
|
|
iot_led_gpio_on(IOT_PLC_TX_LED);
|
||
|
|
iot_led_gpio_off(IOT_PLC_RX_LED);
|
||
|
|
iot_led_gpio_on(IOT_RS485_LED);
|
||
|
|
iot_led_gpio_off(IOT_PLC_TR_LED);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if IOT_EXCEPTION_DEBUG
|
||
|
|
wdg_deinit(HAL_WDG_CPU_0);
|
||
|
|
#if DUAL_WDG_ON_ONE_CPU_ENABLE
|
||
|
|
wdg_deinit(HAL_WDG_CPU_1);
|
||
|
|
#endif
|
||
|
|
iot_power_mgmt_stop_charge();
|
||
|
|
#else
|
||
|
|
wdg_cpu_reset(HAL_WDG_CPU_0);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
while (1) {
|
||
|
|
volatile uint32_t i = 0;
|
||
|
|
|
||
|
|
if (g_exception_nesting == 1) {
|
||
|
|
/* 1s delay */
|
||
|
|
for(i = 0; i < 10000000; i++);
|
||
|
|
} else {
|
||
|
|
/* 5s delay */
|
||
|
|
for(i = 0; i < 50000000; i++);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!toggle) {
|
||
|
|
iot_led_gpio_on(IOT_PLC_RX_LED);
|
||
|
|
iot_led_gpio_on(IOT_PLC_TR_LED);
|
||
|
|
} else {
|
||
|
|
iot_led_gpio_off(IOT_PLC_RX_LED);
|
||
|
|
iot_led_gpio_off(IOT_PLC_TR_LED);
|
||
|
|
}
|
||
|
|
toggle = !toggle;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return epc;
|
||
|
|
}
|
||
|
|
|
||
|
|
#if RISCV_SMP_ENABLE
|
||
|
|
|
||
|
|
void core2_init()
|
||
|
|
{
|
||
|
|
cpu_early_init();
|
||
|
|
intc_init(cpu_get_mhartid());
|
||
|
|
}
|
||
|
|
|
||
|
|
int app_core2_start()
|
||
|
|
{
|
||
|
|
ahb_core2_set_start((uint32_t)&(_start)); //boot init is not necessary, so just jump to app init
|
||
|
|
|
||
|
|
ahb_core2_enable();
|
||
|
|
|
||
|
|
ahb_core2_reset();
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int get_main_core_status()
|
||
|
|
{
|
||
|
|
return g_app_reg_done;
|
||
|
|
}
|
||
|
|
|
||
|
|
void main_2()
|
||
|
|
{
|
||
|
|
core2_init();
|
||
|
|
while(1)
|
||
|
|
{
|
||
|
|
__asm volatile ("nop");
|
||
|
|
if( get_main_core_status())
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
os_start_scheduler();
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#if RUN_ON_CPU_1
|
||
|
|
|
||
|
|
extern void _start_2();
|
||
|
|
|
||
|
|
static const uint8_t sp_applet_bin[] = {
|
||
|
|
#include "sp_applet.txt"
|
||
|
|
};
|
||
|
|
|
||
|
|
#define SP_APPLET_WAIT_COUNT 10
|
||
|
|
#define SP_APPLET_WAIT_UNIT_TIME 500
|
||
|
|
|
||
|
|
int sp_applet_start()
|
||
|
|
{
|
||
|
|
uint8_t *dst = (uint8_t *)_start_2;
|
||
|
|
uint8_t *src = (uint8_t *)sp_applet_bin;
|
||
|
|
uint32_t len = sizeof(sp_applet_bin);
|
||
|
|
volatile int delay_cnt = SP_APPLET_WAIT_COUNT;
|
||
|
|
|
||
|
|
/* clean buffer of g_cpu1_state. */
|
||
|
|
os_mem_set(&g_cpu1_state, 0, sizeof(g_cpu1_state));
|
||
|
|
|
||
|
|
sec_glb_core1_disable();
|
||
|
|
os_mem_cpy(dst, src, len);
|
||
|
|
sec_glb_core1_set_start((uint32_t)_start_2);
|
||
|
|
sec_glb_core1_reset(1);
|
||
|
|
sec_glb_core1_enable();
|
||
|
|
|
||
|
|
/* wait until cpu1 running. */
|
||
|
|
while(delay_cnt--) {
|
||
|
|
if (CPU_FLAG_RUNNING == g_cpu1_state.flags) {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
iot_delay_us_cpu_cycle(SP_APPLET_WAIT_UNIT_TIME);
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
#else
|
||
|
|
|
||
|
|
int sp_applet_start()
|
||
|
|
{
|
||
|
|
g_cpu1_state.flags = CPU_FLAG_INVALID;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
#endif
|
||
|
|
|
||
|
|
void _init()
|
||
|
|
{
|
||
|
|
/* get and set reset reason */
|
||
|
|
iot_board_reset_get_and_set();
|
||
|
|
|
||
|
|
/* sp's applet load */
|
||
|
|
sp_applet_start();
|
||
|
|
|
||
|
|
// disable cpu1 branch prediction
|
||
|
|
sec_glb_core1_branch_pred_enable(0);
|
||
|
|
|
||
|
|
//disable cpu0, cpu2 instruction master access to dmc cache slave
|
||
|
|
sec_glb_mtx_mst_acc(19, 14, 0);
|
||
|
|
sec_glb_mtx_mst_acc(19, 16, 0);
|
||
|
|
|
||
|
|
sec_glb_mtx_mst_acc(20, 14, 0);
|
||
|
|
sec_glb_mtx_mst_acc(20, 16, 0);
|
||
|
|
|
||
|
|
write_csr(mtvec, &def_trap_entry);
|
||
|
|
|
||
|
|
clear_csr(mie, MIP_MEIP);
|
||
|
|
clear_csr(mie, MIP_MTIP);
|
||
|
|
|
||
|
|
iot_interrupt_init(cpu_get_mhartid());
|
||
|
|
|
||
|
|
set_csr(mie, MIP_MEIP);
|
||
|
|
|
||
|
|
// Enable interrupts in general.
|
||
|
|
set_csr(mstatus, MSTATUS_MIE);
|
||
|
|
|
||
|
|
//iot_gp_timer_init();
|
||
|
|
|
||
|
|
clk_core_freq_set(CPU_FREQ_150M);
|
||
|
|
|
||
|
|
// Enable trigger registers to detech zero address access
|
||
|
|
trigger_zero_addr_access_detect();
|
||
|
|
|
||
|
|
/* init global constructor for C++ */
|
||
|
|
__do_global_ctors_aux();
|
||
|
|
__do_init_array_aux();
|
||
|
|
|
||
|
|
/* enable log print */
|
||
|
|
iot_print_config(true);
|
||
|
|
|
||
|
|
/* spinlock init */
|
||
|
|
iot_spinlock_init();
|
||
|
|
|
||
|
|
#if RISCV_SMP_ENABLE
|
||
|
|
app_core2_start();
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
void _fini()
|
||
|
|
{
|
||
|
|
|
||
|
|
}
|
||
|
|
|