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()
 | 
						|
{
 | 
						|
 | 
						|
}
 | 
						|
 |