- /**************************************************************************//**
- * [url=home.php?mod=space&uid=288409]@file[/url] main.c
- * [url=home.php?mod=space&uid=895143]@version[/url] V1.00
- * [url=home.php?mod=space&uid=247401]@brief[/url] Show hard fault information when hard fault happened.
- *
- *
- * [url=home.php?mod=space&uid=17282]@CopyRight[/url] (C) 2016 Nuvoton Technology Corp. All rights reserved.
- *****************************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdint.h>
- #include "NuMicro.h"
- #include "uart.h"
- /*
- The ARM Generic User Guide lists the following sources for a hard fault:
- All faults result in the HardFault exception being taken or cause lockup if
- they occur in the NMI or HardFault handler. The faults are:
- - execution of an SVC instruction at a priority equal or higher than SVCall
- - execution of a BKPT instruction without a debugger attached
- - a system-generated bus error on a load or store
- - execution of an instruction from an XN memory address
- - execution of an instruction from a location for which the system generates a bus fault
- - a system-generated bus error on a vector fetch execution of an Undefined instruction
- - execution of an instruction when not in Thumb-State as a result of the T-bit being previously cleared to 0
- - an attempted load or store to an unaligned address.
- In this sample code, we will show you some information to debug with hardfault exception.
- - Default Hard Fault Handler
- The default hard fault handler is implement in retarget.c and called Hard_Fault_Handler
- By default, Hard_Fault_Handler will print out the information of r0, r1, r2, r3, r12, lr, pc and psr.
- - Overwrite the default Hard Fault Handler
- The default Hard_Fault_Handler is a weak function.
- User can over write it by implementing their own Hard_Fault_Handler.
- NOTE:
- Because hard fault exception will cause data stacking.
- User must make sure SP is pointing to an valid memory location.
- Otherwise, it may cause system lockup and reset when hard fault.
- */
- #define USE_MY_HARDFAULT 1 /* Select to use default hard fault handler or not. 0: Default 1: User define */
- void SYS_Init(void)
- {
- /*---------------------------------------------------------------------------------------------------------*/
- /* Init System Clock */
- /*---------------------------------------------------------------------------------------------------------*/
- /* Unlock protected registers */
- SYS_UnlockReg();
- /* Set XT1_OUT(PF.2) and XT1_IN(PF.3) to input mode */
- PF->MODE &= ~(GPIO_MODE_MODE2_Msk | GPIO_MODE_MODE3_Msk);
- /* Enable External XTAL (4~24 MHz) */
- CLK->PWRCTL |= CLK_PWRCTL_HXTEN_Msk; // XTAL12M (HXT) Enabled
- /* Waiting for 12MHz clock ready */
- CLK_WaitClockReady(CLK_STATUS_HXTSTB_Msk);
- /* Switch HCLK clock source to XTAL */
- CLK->CLKSEL0 &= ~CLK_CLKSEL0_HCLKSEL_Msk;
- CLK->CLKSEL0 |= CLK_CLKSEL0_HCLKSEL_HXT;
- /* Enable IP clock */
- CLK->APBCLK0 |= CLK_APBCLK0_UART0CKEN_Msk; // UART0 Clock Enable
- CLK->APBCLK0 |= CLK_APBCLK0_UART0CKEN_Msk | CLK_APBCLK0_TMR1CKEN_Msk;
- /* Select IP clock source */
- CLK->CLKSEL1 &= ~CLK_CLKSEL1_UART0SEL_Msk;
- CLK->CLKSEL1 |= (0x0 << CLK_CLKSEL1_UART0SEL_Pos);// Clock source from external 12 MHz crystal clock
- /* Update System Core Clock */
- /* User can use SystemCoreClockUpdate() to calculate PllClock, SystemCoreClock and CycylesPerUs automatically. */
- SystemCoreClockUpdate();
- /* Set GPB multi-function pins for UART0 RXD and TXD */
- SYS->GPB_MFPH &= ~(SYS_GPB_MFPH_PB12MFP_Msk | SYS_GPB_MFPH_PB13MFP_Msk);
- SYS->GPB_MFPH |= (SYS_GPB_MFPH_PB12MFP_UART0_RXD | SYS_GPB_MFPH_PB13MFP_UART0_TXD);
- /* Lock protected registers */
- SYS_LockReg();
- }
- void UART0_Init()
- {
- UART_Open(UART0, 115200);
- }
- #if USE_MY_HARDFAULT
- /**
- * @brief User defined hard fault handler
- * @param stack A pointer to current stack
- * [url=home.php?mod=space&uid=266161]@return[/url] None
- * [url=home.php?mod=space&uid=1543424]@Details[/url] This function is an example to show how to implement user's hard fault handler
- *
- */
- void ProcessHardFault(uint32_t lr, uint32_t msp, uint32_t psp)
- {
- uint32_t exception_num;
- uint32_t r0, r1, r2, r3, r12, pc, psr;
- uint32_t *stack;
- stack = (uint32_t *)msp;
- /* Get information from stack */
- r0 = stack[0];
- r1 = stack[1];
- r2 = stack[2];
- r3 = stack[3];
- r12 = stack[4];
- lr = stack[5];
- pc = stack[6];
- psr = stack[7];
- /* Check T bit of psr */
- if((psr & (1 << 24)) == 0)
- {
- printf("PSR T bit is 0.\nHard fault caused by changing to ARM mode!\n");
- while(1);
- }
- /* Check hard fault caused by ISR */
- exception_num = psr & xPSR_ISR_Msk;
- if(exception_num > 0)
- {
- /*
- Exception number
- 0 = Thread mode
- 1 = Reserved
- 2 = NMI
- 3 = HardFault
- 4-10 = Reserved11 = SVCall
- 12, 13 = Reserved
- 14 = PendSV
- 15 = SysTick, if implemented[a]
- 16 = IRQ0.
- .
- .
- n+15 = IRQ(n-1)[b]
- (n+16) to 63 = Reserved.
- The number of interrupts, n, is 32
- */
- printf("Hard fault is caused in IRQ #%d\n", exception_num - 16);
- while(1);
- }
- printf("Hard fault location is at 0x%08x\n", pc);
- /*
- If the hard fault location is a memory access instruction, You may debug the load/store issues.
- Memory access faults can be caused by:
- Invalid address - read/write wrong address
- Data alignment issue - Violate alignment rule of Cortex-M processor
- Memory access permission - MPU violations or unprivileged access (Cortex-M0+)
- Bus components or peripheral returned an error response.
- */
- printf("r0 = 0x%x\n", r0);
- printf("r1 = 0x%x\n", r1);
- printf("r2 = 0x%x\n", r2);
- printf("r3 = 0x%x\n", r3);
- printf("r12 = 0x%x\n", r12);
- printf("lr = 0x%x\n", lr);
- printf("pc = 0x%x\n", pc);
- printf("psr = 0x%x\n", psr);
- while(1);
- }
- #endif
- void TMR1_IRQHandler(void)
- {
- printf("This is exception n = %d\n", TMR1_IRQn);
- M32(0) = 0;
- TIMER1->INTSTS = TIMER_INTSTS_TIF_Msk;
- }
- int32_t main(void)
- {
- void (*func)(void) = (void (*)(void))0x1000;
- char ch;
- /* Init System, peripheral clock and multi-function I/O */
- SYS_Init();
- /* Init UART0 for printf */
- UART0_Init();
- while(1)
- {
- printf("\n\n");
- printf("+----------------------------------------------------+\n");
- printf("| Hard Fault Handler Sample Code |\n");
- printf("+----------------------------------------------------+\n");
- printf("| [0] Test Load/Store Hard Fault |\n");
- printf("| [1] Test Thumb/ARM mode Hard Fault |\n");
- printf("| [2] Test Hard Fault in ISR |\n");
- printf("+----------------------------------------------------+\n");
- ch = getchar();
- switch(ch)
- {
- case '0':
- /* Write APROM will cause hard fault exception. (Memory access hard fault) */
- M32(0) = 0;
- break;
- case '1':
- /* Call function with bit0 = 0 will cause hard fault. (Change to ARM mode hard fault) */
- func();
- break;
- case '2':
- /* Generate Timer Interrupt to test hard fault in ISR */
- NVIC_EnableIRQ(TMR1_IRQn);
- TIMER1->CMP = 3;
- TIMER1->CTL = TIMER_CTL_INTEN_Msk | TIMER_CTL_CNTEN_Msk | TIMER_CTL_ACTSTS_Msk | TIMER_ONESHOT_MODE;
- break;
- default:
- break;
- }
- }
- }
|