| /* ------------------------------------------ |
| * 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 |
| |
| #if defined(LIB_SECURESHIELD) && defined(LIB_SECURESHIELD_OVERRIDES) && (SECURESHIELD_VERSION == 1) |
| #define OVERRIDE_ARC_HAL_EXCEPTION_H |
| #include "secureshield_overrides.h" |
| #endif |
| |
| #endif /* _ARC_HAL_EXCEPTION_H_*/ |