blob: 19c87a9fb93e5acd8f8efe2b03db4582355f905e [file] [log] [blame]
/* ------------------------------------------
* 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_*/