/* ------------------------------------------ * Copyright (c) 2016, Synopsys, Inc. All rights reserved. * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1) Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * 2) Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * \version 2016.05 * \date 2014-07-15 * \author Wayne Ren(Wei.Ren@synopsys.com) --------------------------------------------- */ /** * \file * \ingroup ARC_HAL_EXCEPTION_CPU ARC_HAL_EXCEPTION_INTERRUPT * \brief header file of exception and interrupt management module */ #ifndef _ARC_HAL_EXCEPTION_H_ #define _ARC_HAL_EXCEPTION_H_ #include "inc/embARC_toolchain.h" #include "inc/arc/arc.h" #include "inc/arc/arc_builtin.h" #ifdef __cplusplus extern "C" { #endif /** * \addtogroup ARC_HAL_EXCEPTION_CPU * @{ * \todo need a conf.h from application or board to define the * features of processor, such as number of exception, code * density and FIQ. */ #ifndef NUM_EXC_CPU #define NUM_EXC_CPU 16 /*!< number of CPU exceptions */ #endif #ifndef NUM_EXC_INT #define NUM_EXC_INT 9 /*!< number of interrupt exceptions, defined by users*/ #endif #define NUM_EXC_ALL (NUM_EXC_CPU + NUM_EXC_INT) /*!< total number of exceptions */ #ifdef ARC_FEATURE_SEC_PRESENT typedef struct int_exc_frame { uint32_t erbta; uint32_t r30; /* r30 is useless, skipped? */ uint32_t ilink; /* r29 is useless, skipped?*/ /* r28 is sp, saved other place */ uint32_t fp; /* r27 */ uint32_t gp; /* r26 */ uint32_t r12; uint32_t lp_end, lp_start, lp_count; #ifdef ARC_FEATURE_CODE_DENSITY uint32_t ei, ldi, jli; #endif uint32_t r0, r1, r2, r3; #ifndef ARC_FEATURE_RF16 uint32_t r4, r5, r6, r7, r8, r9; #endif uint32_t r10, r11; uint32_t blink; /* r31 */ uint32_t ret; uint32_t sec_stat; uint32_t status32; } EMBARC_PACKED INT_EXC_FRAME; #else typedef struct int_exc_frame { uint32_t erbta; uint32_t r30; /* r30 is useless, skipped? */ uint32_t ilink; /* r29 is useless, skipped?*/ /* r28 is sp, saved other place */ uint32_t fp; /* r27 */ uint32_t gp; /* r26 */ uint32_t r12; uint32_t r0, r1, r2, r3; #ifndef ARC_FEATURE_RF16 uint32_t r4, r5, r6, r7, r8, r9; #endif uint32_t r10, r11; uint32_t blink; /* r31 */ uint32_t lp_end, lp_start, lp_count; #ifdef ARC_FEATURE_CODE_DENSITY uint32_t ei, ldi, jli; #endif uint32_t ret; uint32_t status32; } EMBARC_PACKED INT_EXC_FRAME; #endif typedef struct callee_frame { #ifndef ARC_FEATURE_RF16 uint32_t r25; uint32_t r24; uint32_t r23; uint32_t r22; uint32_t r21; uint32_t r20; uint32_t r19; uint32_t r18; uint32_t r17; uint32_t r16; #endif uint32_t r15; uint32_t r14; uint32_t r13; } EMBARC_PACKED CALLEE_FRAME; typedef struct processor_frame { CALLEE_FRAME callee_regs; INT_EXC_FRAME exc_frame; } EMBARC_PACKED PROCESSOR_FRAME; #define ARC_PROCESSOR_FRAME_SIZE (sizeof(PROCESSOR_FRAME) / sizeof(uint32_t)) #define ARC_EXC_FRAME_SIZE (sizeof(INT_EXC_FRAME) / sizeof(uint32_t)) #define ARC_CALLEE_FRAME_SIZE (sizeof(CALLEE_FRAME) / sizeof(uint32_t)) extern uint32_t exc_nest_count; /** * \brief write the exception vector base * * \param[in] vec_base the target vector base */ Inline void arc_vector_base_write(const void * vec_base) { _arc_aux_write(AUX_INT_VECT_BASE, (uint32_t)vec_base); } /** * \brief read current exception vector base * * \returns exception vector base (uint32_t) */ Inline uint32_t arc_vector_base_read(void) { return _arc_aux_read(AUX_INT_VECT_BASE); } /** * \brief sense whether in exc/interrupt processing * * \retval 0 not in exc/interrupt processing * \retval 1 in exc/interrupt processing */ Inline uint32_t exc_sense(void) { return (exc_nest_count > 0U); } /** @}*/ /** * \addtogroup ARC_HAL_EXCEPTION_INTERRUPT * @{ */ #ifndef INT_PRI_MIN #define INT_PRI_MIN (-2) /*!< the minimum interrupt priority */ #endif #define INT_PRI_MAX (-1) /*!< the maximum interrupt priority */ /** * \brief disable the specific interrupt * * \param[in] intno interrupt number */ Inline void arc_int_disable(const uint32_t intno) { _arc_aux_write(AUX_IRQ_SELECT, intno); _arc_aux_write(AUX_IRQ_ENABLE, 0); } /** * \brief enable the specific int * * \param[in] intno interrupt number */ Inline void arc_int_enable(const uint32_t intno) { _arc_aux_write(AUX_IRQ_SELECT, intno); _arc_aux_write(AUX_IRQ_ENABLE, 1); } /** * \brief check whether the specific int is enabled * * \param[in] intno interrupt number * \return 0 disabled, 1 enabled */ Inline uint32_t arc_int_enabled(const uint32_t intno) { _arc_aux_write(AUX_IRQ_SELECT, intno); return _arc_aux_read(AUX_IRQ_ENABLE); } /** * \brief get the interrupt priority mask * * \returns interrupt priority mask, negative num */ Inline uint32_t arc_int_ipm_get(void) { return ((_arc_aux_read(AUX_STATUS32) >> 1) & 0x0f); } /** * \brief set the interrupt priority mask * * \param[in] intpri interrupt priority */ Inline void arc_int_ipm_set(uint32_t intpri) { volatile uint32_t status; status = _arc_aux_read(AUX_STATUS32) & ~0x1e; status = status | ((intpri << 1) & 0x1e); /* sr cannot write AUX_STATUS32 */ Asm("kflag %0"::"ir"(status)); } /** * \brief get current interrupt priority mask * * \param[in] intno interrupt number */ Inline uint32_t arc_int_pri_get(const uint32_t intno) { _arc_aux_write(AUX_IRQ_SELECT, intno); return _arc_aux_read(AUX_IRQ_PRIORITY); } /** * \brief set interrupt priority * * \param[in] intno interrupt number * \param[in] intpri interrupt priority */ Inline void arc_int_pri_set(const uint32_t intno, uint32_t intpri) { _arc_aux_write(AUX_IRQ_SELECT, intno); _arc_aux_write(AUX_IRQ_PRIORITY, intpri | (_arc_aux_read(AUX_IRQ_PRIORITY) & 0xfffffff0)); } /** * \brief set interrupt secure or not secure * * \param[in] intno interrupt number * \param[in] secure, 0 for normal, >0 for secure */ Inline void arc_int_secure_set(const uint32_t intno, uint32_t secure) { _arc_aux_write(AUX_IRQ_SELECT, intno); if (secure) { _arc_aux_write(AUX_IRQ_PRIORITY, _arc_aux_read(AUX_IRQ_PRIORITY) | (1 << AUX_IRQ_PRIORITY_BIT_S)); } else { _arc_aux_write(AUX_IRQ_PRIORITY, _arc_aux_read(AUX_IRQ_PRIORITY) & 0xf); } } /** * \brief probe the pending status of interrupt * * \param[in] intno interrupt number * * \returns 1 pending, 0 no pending */ Inline uint32_t arc_int_probe(const uint32_t intno) { _arc_aux_write(AUX_IRQ_SELECT, intno); return _arc_aux_read(AUX_IRQ_PENDING); } /** * \brief trigger the interrupt in software * * \param[in] intno interrupt number */ Inline void arc_int_sw_trigger(const uint32_t intno) { _arc_aux_write(AUX_IRQ_HINT, intno); } /** * \brief config the interrupt level triggered or pulse triggered * * \param[in] intno interrupt number * \param[in] level, 0-level trigger, 1-pluse triggered */ Inline void arc_int_level_config(const uint32_t intno, const uint32_t level) { _arc_aux_write(AUX_IRQ_SELECT, intno); _arc_aux_write(AUX_IRQ_TRIGGER, level); } /** * \brief lock cpu, disable interrupts */ Inline void arc_lock(void) { Asm("clri"); Asm("":::"memory"); } /** * \brief unlock cpu, enable interrupts to happen */ Inline void arc_unlock(void) { Asm("":::"memory"); Asm("seti"); } /** * \brief lock cpu and staus * * \returns cpu status */ Inline uint32_t arc_lock_save(void) { return _arc_clri(); } /** * \brief unlock cpu with the specific status * * \param[in] status cpu status saved by cpu_lock_save */ Inline void arc_unlock_restore(const uint32_t status) { _arc_seti(status); } /** @}*/ /** * \addtogroup ARC_HAL_EXCEPTION_CPU * @{ */ /** * \typedef EXC_ENTRY * \brief the data type for exception entry */ typedef void (*EXC_ENTRY) (void); /** * \typedef EXC_HANDLER * \brief the data type for exception handler */ typedef void (*EXC_HANDLER) (void *exc_frame); /** @}*/ /** * \ingroup ARC_HAL_EXCEPTION_INTERRUPT * \typedef INT_HANDLER * \brief the data type for interrupt handler */ typedef void (*INT_HANDLER) (void *ptr); extern EXC_ENTRY exc_entry_table[NUM_EXC_ALL]; extern EXC_HANDLER exc_int_handler_table[NUM_EXC_ALL]; /** \ingroup ARC_HAL_EXCEPTION_CPU * @{ */ /** * \fn _arc_reset * \brief the reset entry */ extern void _arc_reset(void); /** * \fn exc_entry_cpu * \brief the default CPU exception entry */ extern void exc_entry_cpu(void); /** * \fn exc_entry_firq * \brief the fast interrupt exception entry */ extern void exc_entry_firq(void); /** * \fn exc_entry_int * \brief the interrupt exception entry */ extern void exc_entry_int(void); /** @}*/ /* excetpion related apis */ extern void exc_int_init(void); extern int32_t exc_entry_install(const uint32_t excno, EXC_ENTRY entry); extern EXC_ENTRY exc_entry_get(const uint32_t excno); extern int32_t exc_handler_install(const uint32_t excno, EXC_HANDLER handler); extern EXC_HANDLER exc_handler_get(const uint32_t excno); /* interrupt related apis */ extern int32_t int_disable(const uint32_t intno); extern int32_t int_enable(const uint32_t intno); extern int32_t int_enabled(const uint32_t intno); extern int32_t int_ipm_get(void); extern int32_t int_ipm_set(int32_t intpri); extern int32_t int_pri_get(const uint32_t intno); extern int32_t int_pri_set(const uint32_t intno, int32_t intpri); extern int32_t int_probe(const uint32_t intno); extern int32_t int_sw_trigger(const uint32_t intno); extern int32_t int_level_config(const uint32_t intno, const uint32_t level); extern void cpu_lock(void); extern void cpu_unlock(void); extern uint32_t cpu_lock_save(void); extern void cpu_unlock_restore(const uint32_t status); extern int32_t int_handler_install(const uint32_t intno, INT_HANDLER handler); extern INT_HANDLER int_handler_get(const uint32_t intno); extern int32_t int_secure_set(const uint32_t intno, uint32_t secure); #ifdef __cplusplus } #endif #endif /* _ARC_HAL_EXCEPTION_H_*/