/******************************************************************************
 * $Revision: 423 $
 * $Date:: 2017-04-07 16:03:30 +0900#$
 *****************************************************************************/
/* __DISCLAIMER_START__                                                      */
/******************************************************************************
* (c)2017, Cypress Semiconductor Corporation
* or a subsidiary of Cypress Semiconductor Corporation. All rights
* reserved.
*
* This software, including source code, documentation and related
* materials ( "Software" ), is owned by Cypress Semiconductor
* Corporation or one of its subsidiaries ( "Cypress" ) and is protected by
* and subject to worldwide patent protection (United States and foreign),
* United States copyright laws and international treaty provisions.
* Therefore, you may use this Software only as provided in the license
* agreement accompanying the software package from which you
* obtained this Software ( "EULA" ).
*
* If no EULA applies, Cypress hereby grants you a personal, nonexclusive,
* non-transferable license to copy, modify, and compile the
* Software source code solely for use in connection with Cypress' s
* integrated circuit products. Any reproduction, modification, translation,
* compilation, or representation of this Software except as specified
* above is prohibited without the express written permission of Cypress.
*
* Disclaimer: THIS SOFTWARE IS PROVIDED AS-IS, WITH NO
* WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING,
* BUT NOT LIMITED TO, NONINFRINGEMENT, IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. Cypress reserves the right to make
* changes to the Software without notice. Cypress does not assume any
* liability arising out of the application or use of the Software or any
* product or circuit described in the Software. Cypress does not
* authorize its products for use in any products where a malfunction or
* failure of the Cypress product may reasonably be expected to result in
* significant property damage, injury or death ( "High Risk Product" ). By
* including Cypress' s product in a High Risk Product, the manufacturer
* of such system or application assumes all risk of such use and in doing
* so agrees to indemnify Cypress against all liability.
******************************************************************************/
/* __DISCLAIMER_END__                                                        */
/*****************************************************************************/
/** \file exceptions.c
 **
 ** Definition of exception vectors initialization function and default
 ** exception handlers. The assignment of exception vectors must be done in
 ** exceptions.h.
 **
 ** \note Setting the exception vectors will only work if the high-boot
 **       option is enabled for the R5F core (HIVECS == 1, see ARM TRM). This
 **       means, the exception table is located at 0xFFFF0000, inside the
 **       build-in BootROM.
 **
 ** History:
 **   - 2015-09-01  0.01  HS  Initial version for Traveo
 *****************************************************************************/

/* File version 0xYYXX = vYY.XX */
#define EXCEPTIONS_C_VERSION          0x0001

#ifndef __FILE_VERSION_CHECK__

/*****************************************************************************/
/* Include files                                                             */
/*****************************************************************************/
#include "exceptions.h"
#include "abstract.h"
#include "Clock.h"
/*****************************************************************************/
/* Local pre-processor symbols/macros ('#define')                            */
/*****************************************************************************/

/** Key to unlock the BootROM Hardware Interface by writing to EXCFG_UNLOCK register */
#define BOOTROM_KEY_UNLOCK      0xACC5B007UL 
/** Key to lock the BootROM Hardware Interface by writing to EXCFG_UNLOCK register */
#define BOOTROM_KEY_LOCK        0xB007ECF6UL

/*****************************************************************************/
/* Global variable definitions (declared in header file with 'extern')       */
/*****************************************************************************/

/*****************************************************************************/
/* Local type definitions ('typedef')                                        */
/*****************************************************************************/

/*****************************************************************************/
/* Local function prototypes ('static')                                      */
/*****************************************************************************/
static void DefaultUndefinedInstructionExceptionHandler(void);
static void DefaultSupervisorCallExceptionHandler(void);
static void DefaultPrefetchAbortExceptionHandler(void);
void DefaultDataAbortExceptionIsr(void);
void DefaultDataAbortExceptionHandler(void);

/*****************************************************************************/
/* Local variable definitions ('static')                                     */
/*****************************************************************************/
/* Callback function pointer for the Supervisor Call (defined in exceptions.h) */
static const svc_hdl_func_ptr_t m_pfnSupervisorCallHandlerCallback = EXCEPTIONS_SVC_HANDLER_CB ;


/*****************************************************************************/
/* Function implementation - global ('extern') and local ('static')          */
/*****************************************************************************/

/**
 ******************************************************************************
 ** \brief Initialize the BootROM Hardware Interface
 **
 ** This function will re-map the exception vectors of the ARM exception table
 ** inside the BootROM to the handlers which are defined in exceptions.h.
 ** During this operation the BootROM Hardware Interface will be unlocked
 ** to enable write access to the exception vector configuration registers.
 ** Before leaving this function, the new exception vector configuration will be
 ** swapped with the current configuration.
 **
 ** \note Setting the exception vectors will only work if the high-boot
 **       option is enabled for the R5F core (HIVECS == 1, see ARM TRM). This
 **       means, the exception table is located at 0xFFFF0000, inside the
 **       build-in BootROM.
 **
 ** \pre Must be in system mode
 **
 ******************************************************************************/
void Exceptions_Init(void)
{
    /* Unlock BootROM Hardware Interface registers */
    EXCFG_UNLOCK = BOOTROM_KEY_UNLOCK;
    
    /* Set exception vector registers in inactive configuration set */
    EXCFG_UNDEFINACT  = (uint32_t)EXCEPTIONS_EXC_HANDLER_UNDEF_INSTR;     /* Undefined instruction handler */
    EXCFG_SVCINACT    = (uint32_t)EXCEPTIONS_EXC_HANDLER_SVC;             /* Supervisor call handler */
    EXCFG_PABORTINACT = (uint32_t)EXCEPTIONS_EXC_HANDLER_PABORT;          /* Prefetch abort handler */
    EXCFG_DABORTINACT = (uint32_t)EXCEPTIONS_EXC_HANDLER_DABORT;          /* Data abort handler */
    /* Note: EXCFG_IRQINACT for interrupt exception vector
             is not available
       Note: EXCFG_NMIINACT for Non-maskable interrupt exception vector
             is not available due to Interrupt Controller providing
             the NMI (FIQ) vector at NMIVAS mirror register below BootROM */

    /* Swap inactive <-> active exception vector configuration sets */
    EXCFG_CNFG_SWAP = 1U;
    
    /* Finally lock BootROM Hardware Interface registers */
    EXCFG_UNLOCK = BOOTROM_KEY_LOCK;
}

/**
 ******************************************************************************
 ** \brief Default handler for Undefined Instruction Exception
 **
 ** ARM Cortex-R5(F) TRM: "When an instruction is encountered which is UNDEFINED,
 ** or is for the VFP when the VFP is not enabled, the processor takes the Undefined
 ** instruction exception. Software can use this mechanism to extend the ARM
 ** instruction set by emulating UNDEFINED coprocessor instructions. UNDEFINED
 ** exceptions also occur when a UDIV  or SDIV instruction is executed, the value
 ** in Rm is zero, and the DZ bit in the System Control Register is set."
 **
 ** If the handler is required to return after the instruction that caused the
 ** Undefined exception, please refer to the ARM Cortex-R5(F) TRM.
 **
 ** \todo add full implementation
 ******************************************************************************/
static void DefaultUndefinedInstructionExceptionHandler(void)
{
    /* IRQs are disabled now. */
    /* Please refer to the ARM documentation on how to handle this exception. */
    while (1)
    {
        NOP();
        Set_LED_Flag(0X99AAu);
    }
}

/**
 ******************************************************************************
 ** \brief Default handler for Supervisor Call Execution
 **
 ** This function is an internal wrapper and is called by the real SVC handler
 ** The callback function is user defined in exceptions.h and can be used to
 ** execute code in privileged mode.
 **
 ** \param u32ServiceNumber Number of SVC provided by the handler
 **
 ******************************************************************************/
/* GCC does not yet support switching instruction set by source file statements */
#ifdef __TOOLCHAIN_GCC__
    #ifdef __thumb__
        #warning "File must not be compiled with Thumb instruction set!"
    #endif
#endif
 
#ifdef __TOOLCHAIN_IAR__
    __arm void SupervisorCallHandler( uint32_t u32ServiceNumber );
    __arm
#elif defined __TOOLCHAIN_GHS_MULTI__
    #if defined(__THUMB_AWARE__) && defined(__THUMB__)   
        # pragma ghs nothumb   
    #endif /* defined(__THUMB_AWARE__) && defined(__THUMB__) */   
#endif
void SupervisorCallHandler( uint32_t u32ServiceNumber )
{
    if ( m_pfnSupervisorCallHandlerCallback != NULL )
    {
        m_pfnSupervisorCallHandlerCallback( u32ServiceNumber ) ;
    }
} /* SupervisorCallHandler */
#if defined __TOOLCHAIN_GHS_MULTI__
    #if defined(__THUMB_AWARE__) && defined(__THUMB__)   
        # pragma ghs thumb   
    #endif /* defined(__THUMB_AWARE__) && defined(__THUMB__) */   
#endif

/**
 ******************************************************************************
 ** \brief Default handler for Supervisor Call Exception
 **
 ** ARM Cortex-R5(F) TRM: "You can use the SuperVisor Call (SVC) instruction
 ** (formerly SWI) to enter Supervisor mode, usually to request a particular
 ** supervisor function. The SVC handler reads the opcode to extract the SVC
 ** function number. A SVC handler returns by executing the following instruction,
 ** irrespective of the processor operating state: MOVS PC, R14_svc
 ** This action restores the PC and CPSR, and returns to the instruction following
 ** the SVC."
 **
 ******************************************************************************/
#ifdef __TOOLCHAIN_IAR__
    #pragma required=SupervisorCallHandler
    __arm
#elif defined __TOOLCHAIN_GHS_MULTI__
    #if defined(__THUMB_AWARE__) && defined(__THUMB__)   
        # pragma ghs nothumb   
    #endif /* defined(__THUMB_AWARE__) && defined(__THUMB__) */   
#endif
static void DefaultSupervisorCallExceptionHandler(void)
{
    ASM_INLINE( "STMFD   sp!, {r0-r12, r14}    " ) ; /* Store registers */
    ASM_INLINE( "MOV     r1, sp                " ) ; /* Set pointer to parameters */
    ASM_INLINE( "MRS     r0, spsr              " ) ; /* Move SPSR into general purpose register */
    ASM_INLINE( "TST     r0, #0x20             " ) ; /* Test if bit 5 is set (THUMB mode) */
    ASM_INLINE( "LDRNEH  r0, [lr, #-2]         " ) ; /* T_bit set so load halfword (Thumb) */
    ASM_INLINE( "BICNE   r0, r0, #0xFF00       " ) ; /*  and clear top 8 bits of halfword */
    ASM_INLINE( "LDREQ   r0, [lr, #-4]         " ) ; /* T_bit clear so load word (ARM) */
    ASM_INLINE( "BICEQ   r0, r0, #0xFF000000   " ) ; /*  and clear top 8 bits of word */

    /* r0 now contains SVC number */
    /* r1 now contains pointer to stacked registers */
    ASM_INLINE( "BL      SupervisorCallHandler       " ) ; /* Call main SVC handler */

    ASM_INLINE( "LDMFD   sp!, {r0-r12, r14}    " ) ; /* Restore registers and return */
    ASM_INLINE( "MOVS    PC, R14               " ) ; /* Return from SVC exception (no re-execution, next instruction) */

    /* ToDo reenable IRQs */
} /* DefaultSupervisorCallExceptionHandler */
#if defined __TOOLCHAIN_GHS_MULTI__
    #if defined(__THUMB_AWARE__) && defined(__THUMB__)   
        # pragma ghs thumb   
    #endif /* defined(__THUMB_AWARE__) && defined(__THUMB__) */   
#endif

/**
 ******************************************************************************
 ** \brief Default handler for Prefetch Abort Exception
 **
 ** ARM Cortex-R5(F) TRM: "When the processor's memory system cannot complete
 ** a memory access successfully, an abort is generated. Aborts can occur for
 ** a number of reasons, for example:
 **     - a permission fault indicated by the MPU
 **     - an error response to a transaction on the AXI memory bus
 **     - an error detected in the data by the ECC checking logic.
 ** An error occurring on an instruction fetch generates a prefetch abort.
 ** When a Prefetch Abort (PABT) occurs, the processor marks the prefetched
 ** instruction as invalid, but does not take the exception until the instruction
 ** is to be executed. If the instruction is not executed, for example because
 ** a branch occurs while it is in the pipeline, the abort does not take place.
 ** All prefetch aborts are precise."
 **
 ** \todo add full implementation
 ******************************************************************************/
static void DefaultPrefetchAbortExceptionHandler(void)
{
    #ifdef __DEBUG
    /* Collect some information about the cause of the prefetch abort */
    volatile uint32_t u32InstructionFaultStatus    = MRC( 15U, 0U,  5U, 0U, 1U );
    volatile uint32_t u32AuxInstructionFaultStatus = MRC( 15U, 0U,  5U, 1U, 1U );
    volatile uint32_t u32InstructionFaultAddress   = MRC( 15U, 0U,  6U, 0U, 2U );
    #endif /* __DEBUG */

Set_LED_Flag(0X3377u);
}
/**
 ******************************************************************************
 ** \brief Default handler for Prefetch Abort Exception
 **
 ** ARM Cortex-R5(F) TRM: "When the processor's memory system cannot complete
 ** a memory access successfully, an abort is generated. Aborts can occur for
 ** a number of reasons, for example:
 **     - a permission fault indicated by the MPU
 **     - an error response to a transaction on the AXI memory bus
 **     - an error detected in the data by the ECC checking logic.
 ** An error occurring on a data memory access can generate a data abort. [...]
 ** A Data Abort (DABT) can be either precise or imprecise, depending on the type
 ** of fault that caused it."
 **
 ** \todo add full implementation
 ******************************************************************************/
void DefaultDataAbortExceptionIsr(void)
{
    /* IRQs are disabled now. */
    /* Please refer to the ARM documentation on how to handle this exception. */

    /* For debugging purpose only */
    #ifdef __DEBUG
    /* Collect some information about the cause of the data abort */
    volatile uint32_t u32DataFaultStatus    = MRC( 15U, 0U,  5U, 0U, 0U );
    volatile uint32_t u32AuxDataFaultStatus = MRC( 15U, 0U,  5U, 1U, 0U );
    volatile uint32_t u32DataFaultAddress   = MRC( 15U, 0U,  6U, 0U, 0U );
    #endif /* __DEBUG */
Set_LED_Flag(0X7373u);
    /*  DLP Error Fault flag is cleared for calibration of DLP.*/
    if(DDRHSSPI0_FAULTF_DLPFS){
        DDRHSSPI0_FAULTC_DLPFC = 0x1U;
    }
    else
    {

    }
}

#endif /* __FILE_VERSION_CHECK__ */

