diff --git a/mpfs_hal/common/mss_util.c b/mpfs_hal/common/mss_util.c index ac38f0b..938667d 100644 --- a/mpfs_hal/common/mss_util.c +++ b/mpfs_hal/common/mss_util.c @@ -204,6 +204,24 @@ void display_address_of_interest(uint64_t * address_of_interest, int nb_location } #endif +/*------------------------------------------------------------------------------ + * This function disables dynamic branch prediction on the hart from which it + * executes. It is enabled by default. + */ +void disable_branch_prediction(void) +{ + write_csr(0x7C0, 0x1u); +} + +/*------------------------------------------------------------------------------ + * This function enables dynamic branch prediction on the hart from which it + * executes. + */ +void enable_branch_prediction(void) +{ + write_csr(0x7C0, 0x0u); +} + #ifdef __cplusplus } #endif diff --git a/mpfs_hal/common/mss_util.h b/mpfs_hal/common/mss_util.h index 2293d17..957f26c 100644 --- a/mpfs_hal/common/mss_util.h +++ b/mpfs_hal/common/mss_util.h @@ -70,6 +70,8 @@ void __disable_all_irqs(void); void __enable_irq(void); void __enable_local_irq(uint8_t local_interrupt); void __disable_local_irq(uint8_t local_interrupt); +void disable_branch_prediction(void); +void enable_branch_prediction(void); static inline void spinunlock(volatile long *pLock) { diff --git a/mpfs_hal/common/nwc/mss_ddr.c b/mpfs_hal/common/nwc/mss_ddr.c index 0baf801..381ff41 100644 --- a/mpfs_hal/common/nwc/mss_ddr.c +++ b/mpfs_hal/common/nwc/mss_ddr.c @@ -32,9 +32,13 @@ * Local Defines */ /* This string is updated if any change to ddr driver */ -#define DDR_DRIVER_VERSION_STRING "0.4.015" +#define DDR_DRIVER_VERSION_STRING "0.4.018" /* Version | Comment */ -/* 0.4.015 | Added some debug feedback in verify state . */ +/* 0.4.018 | Corrected error introduced for DDR3 in 0.4.14 */ +/* 0.4.017 | made SW_TRAING_BCLK_SCLK_OFFSET seperate for each mem type */ +/* 0.4.016 | DDR3-Added support for DDR3L removed in v0.3.027 */ +/* | Corrected dpc value update during write leveling */ +/* 0.4.015 | Added some debug feedback in verify state. */ /* 0.4.014 | Tidy-up, replace some majic numbers.No functional change. */ /* 0.4.013 | ddr3- Corrected dpc value update during write leveling */ /* 0.4.012 | ADD_CMD_CLK_MOVE_ORDER 0,1,2 for 1333Mhz, 1,2,0 for 1600MHz */ @@ -194,6 +198,7 @@ static void set_ddr_rpc_regs(DDR_TYPE ddr_type); static uint8_t get_num_lanes(void); static void load_dq(uint8_t lane); static uint8_t use_software_bclk_sclk_training(DDR_TYPE ddr_type); +static uint8_t bclk_sclk_offset(DDR_TYPE ddr_type); static void config_ddr_io_pull_up_downs_rpc_bits(DDR_TYPE ddr_type); #ifdef MANUAL_ADDCMD_TRAINIG static uint8_t ddr_manual_addcmd_refclk_offset(DDR_TYPE ddr_type, uint8_t * refclk_sweep_index); @@ -533,13 +538,14 @@ static uint32_t ddr_setup(void) if (ddr_type == LPDDR4) { /* vrgen, modify during write leveling, turns off ODT */ - CFG_DDR_SGMII_PHY->DPC_BITS.DPC_BITS = (dpc_bits & ~DDR_DPC_VRGEN_H_MASK)| (0x5U<DPC_BITS.DPC_BITS =\ + (dpc_bits & ~DDR_DPC_VRGEN_H_MASK)| (DPC_VRGEN_H_LPDDR4_WR_LVL_VAL << DDR_DPC_VRGEN_H_SHIFT); CFG_DDR_SGMII_PHY->rpc3_ODT.rpc3_ODT = 0x0; } - else if (ddr_type == DDR3) + else if ((ddr_type == DDR3)||(ddr_type == DDR3L)) { /* vrgen, modify during write leveling */ - CFG_DDR_SGMII_PHY->DPC_BITS.DPC_BITS = dpc_bits | (0x2U<DPC_BITS.DPC_BITS = dpc_bits | (DPC_VRGEN_H_DDR3_WR_LVL_VAL<training_reset.training_reset =\ 0x00000000U; @@ -897,8 +903,8 @@ static uint32_t ddr_setup(void) * BCLK_SCLK_OFFSET_BASE */ { - bclk_phase = ((bclk_answer+SW_TRAING_BCLK_SCLK_OFFSET) & 0x07UL ) << 8U; - bclk90_phase=((bclk_answer+SW_TRAING_BCLK_SCLK_OFFSET+2U) & 0x07UL ) << 11U; + bclk_phase = ((bclk_answer+bclk_sclk_offset(ddr_type)) & 0x07UL ) << 8U; + bclk90_phase=((bclk_answer+bclk_sclk_offset(ddr_type)+2U) & 0x07UL ) << 11U; MSS_SCB_DDR_PLL->PLL_PHADJ = (0x00004003UL | bclk_phase | bclk90_phase); MSS_SCB_DDR_PLL->PLL_PHADJ = (0x00000003UL | bclk_phase | bclk90_phase); MSS_SCB_DDR_PLL->PLL_PHADJ = (0x00004003UL | bclk_phase | bclk90_phase); @@ -906,7 +912,7 @@ static uint32_t ddr_setup(void) } #ifdef DEBUG_DDR_INIT (void)uprint32(g_debug_uart, "\n\r bclk_phase ", bclk_phase); - (void)uprint32(g_debug_uart, "\n\r SW_TRAING_BCLK_SCLK_OFFSET value ", SW_TRAING_BCLK_SCLK_OFFSET); + (void)uprint32(g_debug_uart, "\n\r bclk_sclk_offset value ", bclk_sclk_offset(ddr_type)); #endif /* SET Store DRV & VREF initial values (to be re-applied after CA training) */ uint32_t ca_drv=CFG_DDR_SGMII_PHY->rpc1_DRV.rpc1_DRV; @@ -1111,7 +1117,7 @@ static uint32_t ddr_setup(void) }/* end vref_training; */ - if (ddr_type == DDR3) + if ((ddr_type == DDR3)||(ddr_type == DDR3L)) { ddr3_address_cmd_training(ddr_type, &refclk_sweep_index, retry_count, &bclk_phase, &bclk90_phase, &refclk_phase, &refclk_offset ); } @@ -1157,7 +1163,7 @@ static uint32_t ddr_setup(void) { CFG_DDR_SGMII_PHY->training_skip.training_skip =\ LIBERO_SETTING_TRAINING_SKIP_SETTING; - if ((ddr_type == DDR3)||(ddr_type == LPDDR3)||(ddr_type == LPDDR4)||(ddr_type == DDR4)) + if ((ddr_type == DDR3)||(ddr_type == DDR3L)||(ddr_type == LPDDR3)||(ddr_type == LPDDR4)||(ddr_type == DDR4)) { /* RX_MD_CLKN */ CFG_DDR_SGMII_PHY->rpc168.rpc168 = 0x0U; @@ -1575,7 +1581,7 @@ static uint32_t ddr_setup(void) CFG_DDR_SGMII_PHY->expert_mode_en.expert_mode_en = 0x0000008U; if(error == 0U) { - if(ddr_type == DDR3) /* Changing WPU and WPD */ + if((ddr_type == DDR3)||(ddr_type == DDR3L)) /* Changing WPU and WPD */ { /* only run when ECC is on - sar121393 */ if (LIBERO_SETTING_DDRPHY_MODE & DDRPHY_MODE_ECC_MASK) @@ -4401,6 +4407,39 @@ static uint8_t use_software_bclk_sclk_training(DDR_TYPE ddr_type) return(result); } +/** + * bclk_sclk_offset() + * @param ddr_type + * @return + */ +static uint8_t bclk_sclk_offset(DDR_TYPE ddr_type) +{ + uint8_t result = 0U; + switch (ddr_type) + { + default: + case DDR_OFF_MODE: + result = LIBERO_SETTING_SW_TRAING_BCLK_SCLK_OFFSET_LPDDR4; + break; + case DDR3L: + result = LIBERO_SETTING_SW_TRAING_BCLK_SCLK_OFFSET_DDR3L; + break; + case DDR3: + result = LIBERO_SETTING_SW_TRAING_BCLK_SCLK_OFFSET_DDR3; + break; + case DDR4: + result = LIBERO_SETTING_SW_TRAING_BCLK_SCLK_OFFSET_DDR4; + break; + case LPDDR3: + result = LIBERO_SETTING_SW_TRAING_BCLK_SCLK_OFFSET_LPDDR3; + break; + case LPDDR4: + result = LIBERO_SETTING_SW_TRAING_BCLK_SCLK_OFFSET_LPDDR4; + break; + } + return(result); +} + /** * config_ddr_io_pull_up_downs_rpc_bits() * @@ -5751,11 +5790,11 @@ static void ddr3_address_cmd_training(DDR_TYPE ddr_type, uint8_t * refclk_sweep_ a5_offset_status = DDR_ADD_CMD_A5_OFFSET_FAIL; #ifdef DEBUG_DDR_INIT (void)uprint32(g_debug_uart, "\n\r\n\r\r ADDCMD_OFFSET used in this testing ", *refclk_offset); - (void)uprint32(g_debug_uart, "\n\r\n\r\r BCLK_OFFSET used in this testing ",SW_TRAING_BCLK_SCLK_OFFSET); + (void)uprint32(g_debug_uart, "\n\r\n\r\r BCLK_OFFSET used in this testing ",bclk_sclk_offset(ddr_type)); #endif while(a5_offset_status != DDR_ADD_CMD_A5_OFFSET_PASS) { - a5_offset_status = DDR_ADD_CMD_A5_OFFSET_FAIL; + a5_offset_status = DDR_ADD_CMD_A5_OFFSET_PASS; //ADDCMD Training improvement , adds delay on DDR clock loopback path CFG_DDR_SGMII_PHY->rpc147.rpc147 = init_del_offset + rpc147_offset; //ADDCMD Training improvement , adds delay on A9 loopback path diff --git a/mpfs_hal/common/nwc/mss_ddr.h b/mpfs_hal/common/nwc/mss_ddr.h index 9882152..d6c806e 100644 --- a/mpfs_hal/common/nwc/mss_ddr.h +++ b/mpfs_hal/common/nwc/mss_ddr.h @@ -437,6 +437,15 @@ typedef enum DDR_MEMORY_ACCESS_ #define TRANSITION_A5_THRESHOLD 18U #endif +/* Value used during write leveling */ +#ifndef DPC_VRGEN_H_LPDDR4_WR_LVL_VAL +#define DPC_VRGEN_H_LPDDR4_WR_LVL_VAL 0x5U +#endif +/* Value used during write leveling */ +#ifndef DPC_VRGEN_H_DDR3_WR_LVL_VAL +#define DPC_VRGEN_H_DDR3_WR_LVL_VAL 0x2U +#endif + #if !defined (DDR_FULL_32BIT_NC_CHECK_EN) #define DDR_FULL_32BIT_NC_CHECK_EN 1 #endif @@ -476,9 +485,21 @@ typedef enum DDR_MEMORY_ACCESS_ #define NUM_RPC_166_VALUES (MAX_RPC_166_VALUE - MIN_RPC_166_VALUE) -/* This is a fixed setting, will move into driver in next commit */ -#if !defined (SW_TRAING_BCLK_SCLK_OFFSET) -#define SW_TRAING_BCLK_SCLK_OFFSET 0x00000005UL +/* Offsets for each mem type- fixed values */ +#if !defined (LIBERO_SETTING_SW_TRAING_BCLK_SCLK_OFFSET_LPDDR4) +#define LIBERO_SETTING_SW_TRAING_BCLK_SCLK_OFFSET_LPDDR4 0x00000005UL +#endif +#if !defined (LIBERO_SETTING_SW_TRAING_BCLK_SCLK_OFFSET_LPDDR3) +#define LIBERO_SETTING_SW_TRAING_BCLK_SCLK_OFFSET_LPDDR3 0x00000007UL +#endif +#if !defined (LIBERO_SETTING_SW_TRAING_BCLK_SCLK_OFFSET_DDR4) +#define LIBERO_SETTING_SW_TRAING_BCLK_SCLK_OFFSET_DDR4 0x00000006UL +#endif +#if !defined (LIBERO_SETTING_SW_TRAING_BCLK_SCLK_OFFSET_DDR3) +#define LIBERO_SETTING_SW_TRAING_BCLK_SCLK_OFFSET_DDR3 0x00000006UL +#endif +#if !defined (LIBERO_SETTING_SW_TRAING_BCLK_SCLK_OFFSET_DDR3L) +#define LIBERO_SETTING_SW_TRAING_BCLK_SCLK_OFFSET_DDR3L 0x00000006UL #endif /* * 0x6DU => setting vref_ca to 40% diff --git a/mpfs_hal/mpfs_hal_version.h b/mpfs_hal/mpfs_hal_version.h index c79c5bf..078fab9 100644 --- a/mpfs_hal/mpfs_hal_version.h +++ b/mpfs_hal/mpfs_hal_version.h @@ -39,9 +39,9 @@ extern "C" { #endif -#define MPFS_HAL_VERSION_MAJOR 1 -#define MPFS_HAL_VERSION_MINOR 8 -#define MPFS_HAL_VERSION_PATCH 146 +#define MPFS_HAL_VERSION_MAJOR 2 +#define MPFS_HAL_VERSION_MINOR 0 +#define MPFS_HAL_VERSION_PATCH 102 #ifdef __cplusplus } diff --git a/mpfs_hal/startup_gcc/mss_entry.S b/mpfs_hal/startup_gcc/mss_entry.S index 5ff6d95..2fad16b 100644 --- a/mpfs_hal/startup_gcc/mss_entry.S +++ b/mpfs_hal/startup_gcc/mss_entry.S @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright 2019-2021 Microchip Corporation. + * Copyright 2019-2022 Microchip Corporation. * * SPDX-License-Identifier: MIT * @@ -273,70 +273,47 @@ _start: nop j .LoopForeverOther -#else /* IMAGE_LOADED_BY_BOOTLOADER == 1 */ -/*********************************************************************************** +#else /* IMAGE_LOADED_BY_BOOTLOADER == 1 */ +/******************************************************************************* *The program has been loaded by a bootloader * a0 - contains the hart ID * a1 - contains pointer to bootloader -Hart Local Storage, for this hart. */ -_start_non_bootloader_image: - /* ebreak called at the start of the program if required when debuging. */ - /* DEBUG_EBREAK_AT_START is set to one in the debug build, 0 in the */ - /* release build */ - /* uncomment the 3 lines below if you want to use this method to for */ - /* debugging */ - /* li a2, DEBUG_EBREAK_AT_START - beq x0, a2, 1f - ebreak */ -1: - /* store the value here received from boot-loader */ - /* a0 will always contain the hart ID */ - /* If a1 is null, boot-loader is not passing pointer to the HLS */ - /* If this is the case, point HLS to out own and fill with hart ID */ +_start_non_bootloader_amp_image: /* Setup trap handler */ - /* we are currently only supporting mmode */ - /* m-mode/s-mode set-up option will be added here */ la a4, trap_vector csrw mtvec, a4 # initalise machine trap vector address /* Make sure that mtvec is updated before continuing */ -2: + 1: csrr a5, mtvec - bne a4, a5, 2b - /* Disable and clear all interrupts */ - /* assumption is this has been done by the Boot-loader */ - # Init delegation registers, mideleg, medeleg, if a U54 - # These are not initialised by the hardware and come up in a random state - # mhartid is in a0 - beqz a0, 3f - csrw mideleg, 0 - csrw medeleg, 0 -3: - # mscratch must be init to zero- we are not using scratch memory - csrw mscratch, zero - csrw mcause, zero - csrw mepc, zero + bne a4, a5, 1b + /* assume ints in init state */ + /* assume PMP's set as required */ + # enable FPU and accelerator if present, setting ignored on E51 + li t0, MSTATUS_FS | MSTATUS_XS + csrs mstatus, t0 # Init floating point control register to zero # skip if e51 - # mhartid is in a0 - beqz a0, 1f + csrr a0, mhartid + beqz a0, .no_float #ifdef __riscv_flen - # enable FPU and accelerator - li t0, MSTATUS_FS | MSTATUS_XS - csrs mstatus, t0 fscsr x0 #endif -1: # no float - # make sure XLEN agrees with compilation choice, if not will loop here +.no_float: + + # make sure XLEN agrees with compilation choice, if not will loop here +.LxlenCheck: csrr t0, misa #if __riscv_xlen == 64 - bltz t0, 2f + bltz t0, .LxlenPass #else - bgez t0, 2f + bgez t0, .LxlenPass #endif - j 1b -2: + j .LxlenCheck +.LxlenPass: + # initialize global pointer, global data # The __global_pointer is allocated in the linker script. It points to a # location 2k after sdata start as the offsets used in the gp are +/- 2k @@ -347,38 +324,153 @@ _start_non_bootloader_image: la gp, __global_pointer$ .option pop - la a4, __app_stack_bottom # keep bottom of stack in a5 so we can init later - la a5, __app_stack_top - la sp, __app_stack_top -1: + # get core id + csrr a0, mhartid + li a1, 0 + beq a0, a1, .hart0 + li a1, 1 + beq a0, a1, .hart1 + li a1, 2 + beq a0, a1, .hart2 + li a1, 3 + beq a0, a1, .hart3 + li a1, 4 + beq a0, a1, .hart4 + +.hart0: + la a4, __stack_bottom_h0$ # keep bottom of stack in a5 so we can init later + la sp, __stack_top_h0$ + j .continue +.hart1: + la a4, __stack_bottom_h1$ # keep bottom of stack in a5 so we can init later + la sp, __stack_top_h1$ + j .continue +.hart2: + la a4, __stack_bottom_h2$ # keep bottom of stack in a5 so we can init later + la sp, __stack_top_h2$ + j .continue +.hart3: + la a4, __stack_bottom_h3$ # keep bottom of stack in a5 so we can init later + la sp, __stack_top_h3$ + j .continue +.hart4: + la a4, __stack_bottom_h4$ # keep bottom of stack in a5 so we can init later + la sp, __stack_top_h4$ + +.continue: + # clear HLS and stack + mv a5, sp +.init_stack: + #csrw mepc, zero STORE x0, 0(a4) add a4, a4, __SIZEOF_POINTER__ - blt a4, a5, 1b + blt a4, a5, .init_stack + # Allocate some space at top of stack for the HLS + addi sp, sp, -HLS_DEBUG_AREA_SIZE + # HLS grows up from new top of stack + mv tp, sp + # get core id + csrr a0, mhartid + li a1, MPFS_HAL_FIRST_HART + bne a0, a1, .LOtherHartstoWFI # clear the common heap la a4, __heap_start la a5, __heap_end -2: +.init_heap: + #csrw mepc, zero STORE x0, 0(a4) add a4, a4, __SIZEOF_POINTER__ - blt a4, a5, 2b - # check if HLS passed by BL, if not allocate one here - bnez a1, 1f - # Allocate some space at top of stack for the HLS, as HLS mem not passed - addi sp, sp, -HLS_DEBUG_AREA_SIZE - # HLS grows up from new top of stack - mv tp, sp - mv a0, tp - j u54_single_hart + blt a4, a5, .init_heap + # now core MPFS_HAL_FIRST_HART jumps to main_first_hart +.main_hart: + # pass HLS address + mv a0, tp + j main_first_hart_app +.LoopForeverMain: + #in case of return, loop forever. nop's added so can be seen in debugger + nop + nop + j .LoopForeverMain + +.LOtherHartstoWFI: + li a2, MSTATUS_MIE + csrc mstatus, a2 # clear interrupt enable bit + csrw mie, zero + csrw mip, zero + li a2, MIP_MSIP + csrw mie, a2 # Set MSIE bit to receive IPI. This needs to be + # enabled- otherwise stays in wfi. + # Other interrupts appera to bring out of wfi,even if + # not enabled. + # + # Wait here until main hart is up and running + # + # get core id + la a2, MPFS_HAL_FIRST_HART + li a3, 0 + beq a3, a2, .main_hart0 + li a3, 1 + beq a3, a2, .main_hart1 + li a3, 2 + beq a3, a2, .main_hart2 + li a3, 3 + beq a3, a2, .main_hart3 + li a3, 4 + beq a3, a2, .main_hart4 + +.main_hart0: + la a4, (__stack_top_h0$ - HLS_DEBUG_AREA_SIZE) + j 1f +.main_hart1: + la a4, (__stack_top_h1$ - HLS_DEBUG_AREA_SIZE) + j 1f +.main_hart2: + la a4, (__stack_top_h2$ - HLS_DEBUG_AREA_SIZE) + j 1f +.main_hart3: + la a4, (__stack_top_h3$ - HLS_DEBUG_AREA_SIZE) + j 1f +.main_hart4: + la a4, (__stack_top_h4$ - HLS_DEBUG_AREA_SIZE) 1: - # pass HLS address from the boot-loader - mv a0, a1 - j u54_single_hart -2: - # in case of return, loop forever. nop's added so can be seen in debugger + li a3, HLS_MAIN_HART_STARTED +.wait_main_hart: + LWU a2, 0(a4) + bne a3, a2, .wait_main_hart + # Flag we are here to the main hart + li a1, HLS_OTHER_HART_IN_WFI + sw a1, 0(tp) + /* flush the instruction cache */ + fence.i +.LwaitOtherHart: + # We assume wfi instruction will be run before main hart attampts to take + # out of wfi + wfi + # Only start if MIP_MSIP is set - the wfi will ensure this, but adding + # breakpoints in the debugger (halt) + # will wakeup wfi, so the following code will make sure we remain here until + # we get a software interrupt + csrr a2, mip + andi a2, a2, MIP_MSIP + beqz a2, .LwaitOtherHart + /* Disable and clear all interrupts- should be only a sw interrupt */ + li a2, MSTATUS_MIE + csrc mstatus, a2 # clear interrupt enable bit + csrw mie, zero + csrw mip, zero + # set marker as to where we are + li a1, HLS_OTHER_HART_PASSED_WFI + sw a1, 0(tp) + # pass HLS address + mv a0, tp + j main_other_hart +.LoopForeverOther: + #in case of return, loop forever. nop's added so can be seen in debugger nop nop - j 2b -#endif /* IMAGE_LOADED_BY_BOOTLOADER */ + j .LoopForeverOther + +#endif /* IMAGE_LOADED_BY_BOOTLOADER == 0 */ /******************************************************************************/ /******************************interrupt handeling below here******************/ @@ -561,7 +653,7 @@ copy_section: ret -/*********************************************************************************** +/******************************************************************************* * * The following copy_switch_code() symbol overrides the weak symbol in the HAL and does * a safe copy of HW config data diff --git a/mpfs_hal/startup_gcc/system_startup.c b/mpfs_hal/startup_gcc/system_startup.c index ad079de..c95ae5c 100644 --- a/mpfs_hal/startup_gcc/system_startup.c +++ b/mpfs_hal/startup_gcc/system_startup.c @@ -32,13 +32,14 @@ #include "mpfs_hal/mss_hal.h" #ifdef MPFS_HAL_HW_CONFIG #include "../common/nwc/mss_nwc_init.h" -#include "system_startup_defs.h" #endif +#include "system_startup_defs.h" /*============================================================================== * This function is called by the lowest enabled hart (MPFS_HAL_FIRST_HART) in - * the configuration file (platform/config/software/mpfs_hal/mss_sw_config.h ) + * the configuration file : + * (src/boards/my_hart_id = MPFS_HAL_FIRST_HART; -#ifdef MPFS_HAL_SHARED_MEM_ENABLED - /* if shared memory enabled, pointer from Boot-loader in the HLS should be - * non-zero */ - ASSERT(hls->shared_mem != NULL); -#endif - switch(hls->my_hart_id) + uint64_t hartid = read_csr(mhartid); + + if(hartid == MPFS_HAL_FIRST_HART) { - case 0U: - e51(); - break; + uint8_t hart_id; + ptrdiff_t stack_top; - case 1U: - u54_1(); - break; + init_memory(); - case 2U: - u54_2(); - break; + hls->my_hart_id = MPFS_HAL_FIRST_HART; + hls->in_wfi_indicator = HLS_MAIN_HART_STARTED; + WFI_SM sm_check_thread = INIT_THREAD_PR; + hart_id = MPFS_HAL_FIRST_HART + 1U; + while( hart_id <= MPFS_HAL_LAST_HART) + { + uint32_t wait_count = 0U; - case 3U: - u54_3(); - break; + switch(sm_check_thread) + { + default: + case INIT_THREAD_PR: + + switch (hart_id) + { + case 1: + stack_top = (ptrdiff_t)((uint8_t*)&__stack_top_h1$); + break; + case 2: + stack_top = (ptrdiff_t)((uint8_t*)&__stack_top_h2$); + break; + case 3: + stack_top = (ptrdiff_t)((uint8_t*)&__stack_top_h3$); + break; + case 4: + stack_top = (ptrdiff_t)((uint8_t*)&__stack_top_h4$); + break; + } + hls = (HLS_DATA*)(stack_top - HLS_DEBUG_AREA_SIZE); + sm_check_thread = CHECK_WFI; + wait_count = 0U; + break; - case 4U: - u54_4(); - break; + case CHECK_WFI: + if( hls->in_wfi_indicator == HLS_OTHER_HART_IN_WFI ) + { + /* Separate state- to add a little delay */ + sm_check_thread = SEND_WFI; + } + break; - default: - /* no more harts */ - break; + case SEND_WFI: + hls->my_hart_id = hart_id; /* record hartid locally */ + raise_soft_interrupt(hart_id); + sm_check_thread = CHECK_WAKE; + wait_count = 0UL; + break; + + case CHECK_WAKE: + if( hls->in_wfi_indicator == HLS_OTHER_HART_PASSED_WFI ) + { + sm_check_thread = INIT_THREAD_PR; + hart_id++; + wait_count = 0UL; + } + else + { + wait_count++; + if(wait_count > 0x10U) + { + if( hls->in_wfi_indicator == HLS_OTHER_HART_IN_WFI ) + { + hls->my_hart_id = hart_id; /* record hartid locally */ + raise_soft_interrupt(hart_id); + wait_count = 0UL; + } + } + } + break; + } + } + stack_top = (ptrdiff_t)((uint8_t*)&__stack_top_h1$); + hls = (HLS_DATA*)(stack_top - HLS_DEBUG_AREA_SIZE); + hls->in_wfi_indicator = HLS_MAIN_HART_FIN_INIT; + (void)main_other_hart(hls); } + __builtin_unreachable(); /* should never get here */ while(true) { @@ -268,6 +316,7 @@ __attribute__((weak)) int u54_single_hart(HLS_DATA* hls) return (0); } +#endif /*============================================================================== * U54s startup. @@ -284,7 +333,7 @@ __attribute__((weak)) int u54_single_hart(HLS_DATA* hls) */ __attribute__((weak)) int main_other_hart(HLS_DATA* hls) { -#ifdef MPFS_HAL_HW_CONFIG +#if (IMAGE_LOADED_BY_BOOTLOADER == 0) // This also means no hardware init is required extern char __app_stack_top_h0; extern char __app_stack_top_h1; extern char __app_stack_top_h2; @@ -369,7 +418,40 @@ __attribute__((weak)) int main_other_hart(HLS_DATA* hls) /* Added some code as debugger hangs if in loop doing nothing */ counter = counter + 1U; } +#else /* (IMAGE_LOADED_BY_BOOTLOADER == 0) */ + + + uint64_t hartid = read_csr(mhartid); + + switch(hartid) + { + + case 0U: + e51(); + break; + + case 1U: + u54_1(); + break; + + case 2U: + u54_2(); + break; + + case 3U: + u54_3(); + break; + + case 4U: + u54_4(); + break; + + default: + /* no more harts */ + break; + } #endif + return (0); } @@ -563,3 +645,4 @@ __attribute__((weak)) uint8_t init_pmp(uint8_t hart_id) return (0U); } + diff --git a/mpfs_hal/startup_gcc/system_startup.h b/mpfs_hal/startup_gcc/system_startup.h index 772e688..7abdaaa 100644 --- a/mpfs_hal/startup_gcc/system_startup.h +++ b/mpfs_hal/startup_gcc/system_startup.h @@ -116,6 +116,7 @@ extern unsigned long __uninit_top$; * Function Declarations */ int main_first_hart(HLS_DATA* hls); +int main_first_hart_app(HLS_DATA* hls); int main_other_hart(HLS_DATA* hls); int u54_single_hart(HLS_DATA* hls); void e51(void);