/* ---------------------------------------------------------------------------- */
/* Atmel Microcontroller Software Support */
/* SAM Software Package License */
/* ---------------------------------------------------------------------------- */
/* Copyright (c) 2015, Atmel Corporation */
/* */
/* All rights reserved. */
/* */
/* Redistribution and use in source and binary forms, with or without */
/* modification, are permitted provided that the following condition is met: */
/* */
/* - Redistributions of source code must retain the above copyright notice, */
/* this list of conditions and the disclaimer below. */
/* */
/* Atmel's name may not be used to endorse or promote products derived from */
/* this software without specific prior written permission. */
/* */
/* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR */
/* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE */
/* DISCLAIMED. IN NO EVENT SHALL ATMEL 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. */
/* ---------------------------------------------------------------------------- */
/**
* \file
* This file contains the default exception handlers.
*
* \note
* The exception handler has weak aliases.
* As they are weak aliases, any function with the same name will override
* this definition.
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Default NMI interrupt handler.
*/
void NMI_Handler(void)
{
printf("\r\n-E- Enter NMI_Handler!");
while (1);
}
/**
* \brief This function back trace the stack to give exact address where fault
happened
**/
__STATIC_INLINE uint32_t StackUnwind(void)
{
uint32_t Fault_Add;
#if defined (__CC_ARM)
uint32_t temp;
__ASM("mrs temp, msp ");
__ASM{ ldr Fault_Add, [temp, #28]}
#else
__ASM("mrs r0, msp ");
__ASM("ldr %0, [r0,#28]" : "=r" (Fault_Add));
#endif
return Fault_Add;
}
/**
* \brief If Other Faults are enabled then HardFault error will look for those
* errors to give more detail about fault
**/
static void HardFault_reason(void)
{
uint32_t CFSRValue;
TRACE_DEBUG("In Hard Fault Handler\n\r");
TRACE_DEBUG("SCB->HFSR = 0x%08x\n\r", SCB->HFSR);
if ((SCB->HFSR & SCB_HFSR_DEBUGEVT_Msk)) {
TRACE_DEBUG("Debug Event Hard Fault\n\r");
TRACE_DEBUG("SCB->DFSR = 0x%08x\n", SCB->DFSR);
}
if ((SCB->HFSR & SCB_HFSR_VECTTBL_Msk)) {
TRACE_DEBUG("Fault was due to vector table read on \
exception processing\n\r");
}
// Forced HardFault
if ((SCB->HFSR & SCB_HFSR_FORCED_Msk)) {
TRACE_DEBUG("Forced Hard Fault\n\r");
TRACE_DEBUG("SCB->CFSR = 0x%08x\n\r", SCB->CFSR);
// Usage Fault
if ((SCB->CFSR & SCB_CFSR_USGFAULTSR_Msk)) {
CFSRValue = SCB->CFSR;
TRACE_DEBUG("Usage fault: ");
CFSRValue >>= SCB_CFSR_USGFAULTSR_Pos;
if ((CFSRValue & (1 << 9)))
TRACE_DEBUG("Divide by zero\n\r");
if ((CFSRValue & (1 << 8)))
TRACE_DEBUG("Unaligned access error\n\r");
if ((CFSRValue & (1 << 3)))
TRACE_DEBUG("Coprocessor access error\n\r");
if ((CFSRValue & (1 << 2)))
TRACE_DEBUG("Integrity check error on EXC_RETURN\n\r");
}
// Bus Fault
if ((SCB->CFSR & SCB_CFSR_BUSFAULTSR_Msk)) {
CFSRValue = SCB->CFSR;
TRACE_DEBUG("Bus fault: ");
CFSRValue >>= SCB_CFSR_BUSFAULTSR_Pos;
if ((CFSRValue & (1 << 7)) && (CFSRValue & (1 << 1))) {
TRACE_DEBUG("Precise data access error. Bus Fault Address \
Register is: %x \n\r", SCB->BFAR);
}
if ((CFSRValue & (1 << 4)))
TRACE_DEBUG("Bus fault has occurred on exception entry\n\r");
if ((CFSRValue & (1 << 3)))
TRACE_DEBUG("bus fault has occurred on exception return\n\r");
if ((CFSRValue & (1 << 2)))
TRACE_DEBUG("Imprecise data access error\n\r");
if ((CFSRValue & (1 << 0))) {
TRACE_DEBUG("This bit indicates a bus fault on an instruction \
pre-fetch. \n\r");
}
}
}
// MemoryFault
if ((SCB->CFSR & SCB_CFSR_MEMFAULTSR_Msk)) {
CFSRValue = SCB->CFSR;
TRACE_DEBUG("Memory fault: ");
CFSRValue >>= SCB_CFSR_MEMFAULTSR_Pos;
if ((CFSRValue & (1 << 9)) != 0)
TRACE_DEBUG("Divide by zero\n\r");
}
__ISB();
__DMB();
__ASM volatile("BKPT #01");
}
/**
* \brief Default HardFault interrupt handler.
*/
void HardFault_Handler(void)
{
printf("\n\rHardFault at address 0X%x\n\r", (int)StackUnwind());
__ISB();
__DMB();
HardFault_reason();
}
#ifndef MPU_EXAMPLE_FEATURE
/**
* \brief Default MemManage interrupt handler.
*/
void MemManage_Handler(void)
{
printf("\n\rMemoryMemFault (MPU fault) at address 0X%x\n\r",
(int)StackUnwind());
__ISB();
__DMB();
__ASM volatile("BKPT #01");
}
#endif
/**
* \brief Default BusFault interrupt handler.
*/
void BusFault_Handler(void)
{
__ASM("nop");
__ASM("nop");
printf("\n\rBus Fault at address 0X%x\n\r", (int)StackUnwind());
__ISB();
__DMB();
__ASM volatile("BKPT #01");
}
/**
* \brief Default UsageFault interrupt handler.
*/
void UsageFault_Handler(void)
{
printf("\r\nUsage fault at address 0X%x", (int)StackUnwind());
__ISB();
__DMB();
__ASM volatile("BKPT #01");
}