exceptions.c 16.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
/******************************************************************************
 * $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 "mcu_settings.h"
#include "abstract.h"
//
/*****************************************************************************/
/* Local pre-processor symbols/macros ('#define')                            */
/*****************************************************************************/

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

/*****************************************************************************/
/* 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 = 1;
    
    // 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();
    }
}

/**
 ******************************************************************************
 ** \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)
{
    // 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 prefetch abort
    volatile uint32_t u32InstructionFaultStatus    = MRC( 15, 0,  5, 0, 1 );
    volatile uint32_t u32AuxInstructionFaultStatus = MRC( 15, 0,  5, 1, 1 );
    volatile uint32_t u32InstructionFaultAddress   = MRC( 15, 0,  6, 0, 2 );
    #endif // DEBUG

    while (1)
    {
        NOP();
    }
}
/**
 ******************************************************************************
 ** \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( 15, 0,  5, 0, 0 );
    volatile uint32_t u32AuxDataFaultStatus = MRC( 15, 0,  5, 1, 0 );
    volatile uint32_t u32DataFaultAddress   = MRC( 15, 0,  6, 0, 0 );
    #endif // DEBUG

    /*  DLP Error Fault flag is cleared for calibration of DLP.*/
    if(DDRHSSPI0_FAULTF_DLPFS)
    {
        DDRHSSPI0_FAULTC_DLPFC = 0x1;  /*DLP Error Fault Clear*/
    }
    else if(DDRHSSPI0_FAULTF_DRCBSFS)
    {
        DDRHSSPI0_FAULTC_DRCBSFC = 0x1; /*DMA Read Channel Block Size Fault Status Clear*/
    }
    else if(DDRHSSPI0_FAULTF_PVFS)
    {
        DDRHSSPI0_FAULTC_PVFC = 0x1; /*Protection Violation Fault Status Clear*/
    }
    else if(DDRHSSPI0_FAULTF_DWCBSFS)
    {
        DDRHSSPI0_FAULTC_DWCBSFC = 0x1; /*DMA Write Channel Block Size Fault Status Clear*/
    }
    else if(DDRHSSPI0_FAULTF_UMAFS)
    {
        DDRHSSPI0_FAULTC_UMAFC = 0x1; /*Unmapped Memory Access Fault Interrupt Clear*/
    }
    else
    {
         while (1)
         {
            NOP();
         }
    }
}

#endif /* __FILE_VERSION_CHECK__ */