| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512 |
- /*
- * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
- * Copyright (c) 2019 Nuclei Limited. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the License); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /******************************************************************************
- * @file system_evalsoc.c
- * @brief NMSIS Nuclei Core Device Peripheral Access Layer Source File for
- * Nuclei Eval SoC which support Nuclei N/NX class cores
- * @version V1.00
- * @date 22. Nov 2019
- ******************************************************************************/
- #include <stdint.h>
- #include <stdio.h>
- #include "nuclei_sdk_hal.h"
- /*----------------------------------------------------------------------------
- Define clocks
- *----------------------------------------------------------------------------*/
- /* ToDo: add here your necessary defines for device initialization
- following is an example for different system frequencies */
- #ifndef SYSTEM_CLOCK
- #define SYSTEM_CLOCK (16000000UL)
- #endif
- #ifdef CFG_HAS_EXCP
- extern void exc_entry(void);
- #endif
- /**
- * \defgroup NMSIS_Core_SystemConfig System Device Configuration
- * \brief Functions for system and clock setup available in system_<device>.c.
- * \details
- * Nuclei provides a template file **system_Device.c** that must be adapted by
- * the silicon vendor to match their actual device. As a <b>minimum requirement</b>,
- * this file must provide:
- * - A device-specific system configuration function, \ref SystemInit.
- * - Global c library \ref _premain_init and \ref _postmain_fini functions called right before calling main function.
- * - A global variable that contains the system frequency, \ref SystemCoreClock.
- * - A global interrupt configuration initialization, \ref Interrupt_Init.
- * - A global exception and trap configuration initialization, \ref Trap_Init and \ref Exception_Init.
- * - Vendor customized interrupt, exception handling code, see \ref NMSIS_Core_IntExcNMI_Handling
- *
- * The file configures the device and, typically, initializes the oscillator (PLL) that is part
- * of the microcontroller device. This file might export other functions or variables that provide
- * a more flexible configuration of the microcontroller system.
- *
- * And this file also provided common interrupt, exception exception handling framework template,
- * Silicon vendor can customize these template code as they want.
- *
- * \note Please pay special attention to the static variable \c SystemCoreClock. This variable might be
- * used throughout the whole system initialization and runtime to calculate frequency/time related values.
- * Thus one must assure that the variable always reflects the actual system clock speed.
- *
- * \attention
- * Be aware that a value stored to \c SystemCoreClock during low level initialization (i.e. \c SystemInit()) might get
- * overwritten by C libray startup code and/or .bss section initialization.
- * Thus its highly recommended to call \ref SystemCoreClockUpdate at the beginning of the user \c main() routine.
- *
- * @{
- */
- /*----------------------------------------------------------------------------
- System Core Clock Variable
- *----------------------------------------------------------------------------*/
- /* ToDo: initialize SystemCoreClock with the system core clock frequency value
- achieved after system intitialization.
- This means system core clock frequency after call to SystemInit() */
- /**
- * \brief Variable to hold the system core clock value
- * \details
- * Holds the system core clock, which is the system clock frequency supplied to the SysTick
- * timer and the processor core clock. This variable can be used by debuggers to query the
- * frequency of the debug timer or to configure the trace clock speed.
- *
- * \attention
- * Compilers must be configured to avoid removing this variable in case the application
- * program is not using it. Debugging systems require the variable to be physically
- * present in memory so that it can be examined to configure the debugger.
- */
- volatile uint32_t SystemCoreClock = SYSTEM_CLOCK; /* System Clock Frequency (Core Clock) */
- /*----------------------------------------------------------------------------
- Clock functions
- *----------------------------------------------------------------------------*/
- /**
- * \brief Function to update the variable \ref SystemCoreClock
- * \details
- * Updates the variable \ref SystemCoreClock and must be called whenever the core clock is changed
- * during program execution. The function evaluates the clock register settings and calculates
- * the current core clock.
- */
- void SystemCoreClockUpdate(void) /* Get Core Clock Frequency */
- {
- /* ToDo: add code to calculate the system frequency based upon the current
- * register settings.
- * Note: This function can be used to retrieve the system core clock frequeny
- * after user changed register settings.
- */
- }
- /**
- * \brief Function to Initialize the system.
- * \details
- * Initializes the microcontroller system. Typically, this function configures the
- * oscillator (PLL) that is part of the microcontroller device. For systems
- * with a variable clock speed, it updates the variable \ref SystemCoreClock.
- * SystemInit is called from the file <b>startup<i>_device</i></b>.
- */
- void SystemInit(void)
- {
- /* ToDo: add code to initialize the system
- * Warn: do not use global variables because this function is called before
- * reaching pre-main. RW section maybe overwritten afterwards.
- */
- }
- /**
- * \defgroup NMSIS_Core_IntExcNMI_Handling Interrupt and Exception Handling
- * \brief Functions for interrupt, exception and nmi handle available in system_<device>.c.
- * \details
- * Nuclei provide a template for interrupt, exception handling. Silicon Vendor could adapat according
- * to their requirement. Silicon vendor could implement interface for different exception code and
- * replace current implementation.
- *
- * @{
- */
- // TODO If you don't want any exception handler print any thing, uncomment below macro
- // Define this will reduce code size and less debug message when exception happened
- //#define DISABLE_EXCEPTION_DEBUG
- #if defined(__IRQC_PRESENT) && (__IRQC_PRESENT == 1)
- extern __WEAK void irqc_mtip_handler(void);
- extern __WEAK void irqc_msip_handler(void);
- extern __WEAK void irqc_uart0_handler(void);
- extern void default_intexc_handler(void);
- typedef void (*__fp)(void);
- // TODO irqc vector table, you can change 32 to real value of our interrupt number
- // Please fill in this irq vector table with your real interrupt function name
- // MUST marked as __USED to avoid unused variable elimination
- static const __fp vector_base[__IRQC_INTNUM] __USED __attribute__((section (".mintvec"))) = {
- irqc_msip_handler, /* irq 0 , internal irq 0 */
- irqc_mtip_handler, /* irq 1 , internal irq 1 */
- /* TODO Below are external interrupt handlers, please define them as your requirements, you need to increase or decrease it, and define correct interrupt handler name */
- #if __IRQC_INTNUM > 2
- irqc_uart0_handler, /* irq 2 , ext_irq 0 */
- #endif
- };
- #endif
- #if defined(__EXCP_PRESENT) && (__EXCP_PRESENT == 1)
- /* TODO: Using default exception handling code provided by NMSIS Device Template.
- * If you want to disable it and use your own one, you can implement Exception_Init and core_exception_handler function
- */
- #if defined(__Vendor_EXCEPTION) && (__Vendor_EXCEPTION == 0)
- /** \brief Max exception handler number */
- #define MAX_SYSTEM_EXCEPTION_NUM 12
- /**
- * \brief Store the exception handlers for each exception ID
- * \note
- * - This SystemExceptionHandlers are used to store all the handlers for all
- * the exception codes Nuclei N100 core provided.
- * - Exception code 0 - 11, totally 12 exceptions are mapped to SystemExceptionHandlers[0:11]
- * - Exception code 0xFFF, represent NMI, mapped to SystemExceptionHandlers[12]
- */
- static unsigned long SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM + 1];
- /**
- * \brief Exception Handler Function Typedef
- * \note
- * This typedef is only used internal in this system_<Device>.c file.
- * It is used to do type conversion for registered exception handler before calling it.
- */
- typedef void (*EXC_HANDLER)(unsigned long cause, unsigned long sp);
- /**
- * \brief System Default Exception Handler
- * \details
- * This function provides a default exception handler for all exception ids.
- * By default, It will just print some information for debug, Vendor can customize it according to its requirements.
- * \param [in] mcause code indicating the reason that caused the trap in machine mode
- * \param [in] sp stack pointer
- */
- static void system_default_exception_handler(unsigned long mcause, unsigned long sp)
- {
- #if defined(CODESIZE) && (CODESIZE == 1)
- #else
- #ifndef DISABLE_EXCEPTION_DEBUG
- /* TODO: Uncomment this if you have implement NSDK_DEBUG function */
- NSDK_DEBUG("MCAUSE : 0x%lx\r\n", mcause);
- NSDK_DEBUG("MEPC : 0x%lx\r\n", __RV_CSR_READ(CSR_MEPC));
- NSDK_DEBUG("HARTID : %u\r\n", (unsigned int)__get_hart_id());
- Exception_DumpFrame(sp, PRV_M);
- #if defined(SIMULATION_MODE)
- // directly exit if in SIMULATION
- extern void simulation_exit(int status);
- simulation_exit(1);
- #endif
- #endif
- while (1) {
- __WFI();
- }
- #endif
- }
- /**
- * \brief Initialize all the default core exception handlers
- * \details
- * The core exception handler for each exception id will be initialized to \ref system_default_exception_handler.
- * \note
- * Called in \ref _premain_init function, used to initialize default exception handlers for all exception IDs
- */
- void Exception_Init(void)
- {
- #if defined(CODESIZE) && (CODESIZE == 1)
- #else
- #if defined(__EXCP_PRESENT) && (__EXCP_PRESENT == 1)
- #ifdef CFG_HAS_TRAP_CSR
- /* TODO when the exception entry csr MTVEC is writable, you can remap exception entry */
- /* but you need to handle the remap by yourself by update linker script */
- __RV_CSR_WRITE(CSR_MTVEC, (rv_csr_t)exc_entry);
- #endif
- #endif
- for (int i = 0; i < (MAX_SYSTEM_EXCEPTION_NUM + 1); i++) {
- SystemExceptionHandlers[i] = (unsigned long)system_default_exception_handler;
- }
- #endif
- }
- /**
- * \brief Dump Exception Frame
- * \details
- * This function provided feature to dump exception frame stored in stack.
- * \param [in] sp stackpoint
- * \param [in] mode privileged mode
- */
- void Exception_DumpFrame(unsigned long sp, uint8_t mode)
- {
- #if defined(CODESIZE) && (CODESIZE == 1)
- #else
- #ifndef DISABLE_EXCEPTION_DEBUG
- EXC_Frame_Type *exc_frame = (EXC_Frame_Type *)sp;
- #ifndef __riscv_32e
- NSDK_DEBUG("ra: 0x%lx, tp: 0x%lx, t0: 0x%lx, t1: 0x%lx, t2: 0x%lx, t3: 0x%lx, t4: 0x%lx, t5: 0x%lx, t6: 0x%lx\n" \
- "a0: 0x%lx, a1: 0x%lx, a2: 0x%lx, a3: 0x%lx, a4: 0x%lx, a5: 0x%lx, a6: 0x%lx, a7: 0x%lx\n" \
- "cause: 0x%lx, epc: 0x%lx\n", exc_frame->ra, exc_frame->tp, exc_frame->t0, \
- exc_frame->t1, exc_frame->t2, exc_frame->t3, exc_frame->t4, exc_frame->t5, exc_frame->t6, \
- exc_frame->a0, exc_frame->a1, exc_frame->a2, exc_frame->a3, exc_frame->a4, exc_frame->a5, \
- exc_frame->a6, exc_frame->a7, exc_frame->cause, exc_frame->epc);
- #else
- NSDK_DEBUG("ra: 0x%lx, tp: 0x%lx, t0: 0x%lx, t1: 0x%lx, t2: 0x%lx\n" \
- "a0: 0x%lx, a1: 0x%lx, a2: 0x%lx, a3: 0x%lx, a4: 0x%lx, a5: 0x%lx\n" \
- "cause: 0x%lx, epc: 0x%lx\n", exc_frame->ra, exc_frame->tp, exc_frame->t0, \
- exc_frame->t1, exc_frame->t2, exc_frame->a0, exc_frame->a1, exc_frame->a2, exc_frame->a3, \
- exc_frame->a4, exc_frame->a5, exc_frame->cause, exc_frame->epc);
- #endif
- #endif
- #endif
- }
- /**
- * \brief Register an exception handler for exception code EXCn
- * \details
- * - For EXCn < \ref MAX_SYSTEM_EXCEPTION_NUM, it will be registered into SystemExceptionHandlers[EXCn].
- * \param [in] EXCn See \ref EXCn_Type
- * \param [in] exc_handler The exception handler for this exception code EXCn
- */
- void Exception_Register_EXC(uint32_t EXCn, unsigned long exc_handler)
- {
- #if defined(CODESIZE) && (CODESIZE == 1)
- #else
- if (EXCn < MAX_SYSTEM_EXCEPTION_NUM) {
- SystemExceptionHandlers[EXCn] = exc_handler;
- } else if (EXCn == 0xFFF) {
- SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM] = exc_handler;
- }
- #endif
- }
- /**
- * \brief Get current exception handler for exception code EXCn
- * \details
- * - For EXCn < \ref MAX_SYSTEM_EXCEPTION_NUM, it will return SystemExceptionHandlers[EXCn].
- * \param [in] EXCn See \ref EXCn_Type
- * \return Current exception handler for exception code EXCn, if not found, return 0.
- */
- unsigned long Exception_Get_EXC(uint32_t EXCn)
- {
- #if defined(CODESIZE) && (CODESIZE == 1)
- #else
- if (EXCn < MAX_SYSTEM_EXCEPTION_NUM) {
- return SystemExceptionHandlers[EXCn];
- } else if (EXCn == 0xFFF) {
- return SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM];
- }
- #endif
- return 0;
- }
- /**
- * \brief Common Exception handler entry
- * \details
- * This function provided a command entry for exception. Silicon Vendor could modify
- * this template implementation according to requirement.
- * \param [in] mcause code indicating the reason that caused the trap in machine mode
- * \param [in] sp stack pointer
- * \remarks
- * - RISCV provided common entry for all types of exception. This is proposed code template
- * for exception entry function, Silicon Vendor could modify the implementation.
- * - For the core_exception_handler template, we provided exception register function \ref Exception_Register_EXC
- * which can help developer to register your exception handler for specific exception number.
- */
- uint32_t core_exception_handler(unsigned long mcause, unsigned long sp)
- {
- #if defined(CODESIZE) && (CODESIZE == 1)
- while(1);
- #else
- uint32_t EXCn = (uint32_t)(mcause & 0x00000fff);
- EXC_HANDLER exc_handler;
- if (EXCn < MAX_SYSTEM_EXCEPTION_NUM) {
- exc_handler = (EXC_HANDLER)SystemExceptionHandlers[EXCn];
- } else if (EXCn == 0xFFF) {
- exc_handler = (EXC_HANDLER)SystemExceptionHandlers[MAX_SYSTEM_EXCEPTION_NUM];
- } else {
- exc_handler = (EXC_HANDLER)system_default_exception_handler;
- }
- if (exc_handler != NULL) {
- exc_handler(mcause, sp);
- }
- return 0;
- #endif
- }
- #else /* Use Vendor implemented exception handling code __Vendor_EXCEPTION == 1 */
- // TODO implement core_exception_handler and Exception_Init if __Vendor_EXCEPTION == 1
- __WEAK uint32_t core_exception_handler(unsigned long mcause, unsigned long sp)
- {
- while (1) {
- __WFI();
- }
- }
- __WEAK void Exception_Init(void)
- {
- }
- #endif
- #endif
- /** @} */ /* End of Doxygen Group NMSIS_Core_ExceptionAndNMI */
- /** Banner Print for Nuclei SDK */
- void SystemBannerPrint(void)
- {
- #if defined(CODESIZE) && (CODESIZE == 1)
- #else
- // TODO to reduce code size and less message output.
- // you can set NUCLEI_BANNER to 0 in nuclei_sdk_hal.h
- // but it will show no messsage when bringup
- #if defined(NUCLEI_BANNER) && (NUCLEI_BANNER == 1)
- NSDK_DEBUG("N100 Nuclei SDK Build Time: %s, %s\r\n", __DATE__, __TIME__);
- #ifdef DOWNLOAD_MODE_STRING
- NSDK_DEBUG("Download Mode: %s\r\n", DOWNLOAD_MODE_STRING);
- #endif
- NSDK_DEBUG("CPU Frequency %u Hz\r\n", (unsigned int)SystemCoreClock);
- NSDK_DEBUG("CPU HartID: %u\r\n", (unsigned int)__get_hart_id());
- #endif
- #endif
- }
- /**
- * \brief initialize interrupt config
- * \details
- * interrupt needs be initialized after boot up
- */
- void Interrupt_Init(void)
- {
- #if defined(__IRQC_PRESENT) && (__IRQC_PRESENT == 1)
- #ifdef CFG_HAS_TRAP_CSR
- /* TODO when the interrupt vector entry csr MTVT is writable, you can remap your vector table */
- /* but you need to handle the remap by yourself by update linker script */
- __RV_CSR_WRITE(CSR_MTVT, (rv_csr_t)vector_base);
- #endif
- #endif
- }
- #if defined(__IRQC_PRESENT) && (__IRQC_PRESENT == 1)
- /**
- * \brief Initialize a specific IRQ and register the handler
- * \details
- * This function set vector mode, trigger mode and polarity, interrupt level and priority,
- * assign handler for specific IRQn.
- * \param [in] IRQn interrupt handler address
- * \param [in] handler interrupt handler, if NULL, handler will not be installed
- * \return -1 means invalid input parameter. 0 means successful.
- * \remarks
- * - This function use to configure specific irqc interrupt and register its interrupt handler and enable its interrupt.
- * - If the vector table is placed in read-only section, handler could not be installed
- */
- int32_t IRQC_Register_IRQ(IRQn_Type IRQn, void* handler)
- {
- if (IRQn >= SOC_INT_MAX) {
- return -1;
- }
- if (handler != NULL) {
- IRQC_SetVector(IRQn, (rv_csr_t)handler);
- }
- IRQC_EnableIRQ(IRQn);
- return 0;
- }
- #endif
- /**
- * \brief do the init for trap
- * \details
- */
- static void Trap_Init(void)
- {
- }
- /**
- * \brief early init function before main
- * \details
- * This function is executed right before main function.
- * For RISC-V gnu toolchain, _init function might not be called
- * by __libc_init_array function, so we defined a new function
- * to do initialization.
- */
- void _premain_init(void)
- {
- #if defined(CODESIZE) && (CODESIZE == 1)
- // TODO to reduce the code size of application
- // No need to do so complex premain initialization steps
- // You just need to initialize the cpu resource you need to use in your
- // application code.
- // TODO Still need to initialize uart for other code need to do printf
- // If you want to reduce more code, you can comment below code
- uart_init(SOC_DEBUG_UART, 115200);
- #else
- // TODO Code below used to do premain init, you can place pre main init code here
- // TODO implement get_cpu_freq function to get real cpu clock freq in HZ or directly give the real cpu HZ
- // Or directly give the correct freqency, no need to use this function
- SystemCoreClock = get_cpu_freq();
- uart_init(SOC_DEBUG_UART, 115200);
- /* Display banner after UART initialized */
- SystemBannerPrint();
- /* Initialize exception default handlers */
- #if defined(__EXCP_PRESENT) && (__EXCP_PRESENT == 1)
- Exception_Init();
- #endif
- /* Interrupt initialization, mainly MTH and NLBIT */
- #if defined(__IRQC_PRESENT) && (__IRQC_PRESENT == 1)
- Interrupt_Init();
- #endif
- Trap_Init();
- #endif
- }
- /**
- * \brief finish function after main
- * \param [in] status status code return from main
- * \details
- * This function is executed right after main function.
- * For RISC-V gnu toolchain, _fini function might not be called
- * by __libc_fini_array function, so we defined a new function
- * to do initialization
- */
- void _postmain_fini(int status)
- {
- #if defined(CODESIZE) && (CODESIZE == 1)
- #ifdef CFG_SIMULATION
- SIMULATION_EXIT(status);
- #endif
- #else
- /* TODO: Add your own finishing code here, called after main */
- extern void simulation_exit(int status);
- simulation_exit(status);
- #endif
- }
- /** @} */ /* End of Doxygen Group NMSIS_Core_SystemConfig */
|