Contiki-NG
Loading...
Searching...
No Matches
hardfault-handler.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2020 Yago Fontoura do Rosario <yago.rosario@hotmail.com.br>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the copyright holder nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28 * OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31/**
32 * \addtogroup nrf
33 * @{
34 *
35 * \addtogroup nrf-arm ARM Handler
36 * @{
37 *
38 * \addtogroup nrf-hardfault Hardfault Handler
39 * @{
40 *
41 * \file
42 * Hardfault Handler implementation for the nRF.
43 * \author
44 * Yago Fontoura do Rosario <yago.rosario@hotmail.com.br>
45 *
46 */
47/*---------------------------------------------------------------------------*/
48#include "contiki.h"
49
50#include "cmsis_compiler.h"
51#include "nrf.h"
52
53/*---------------------------------------------------------------------------*/
54#if NRF_HARDFAULT_HANDLER_EXTENDED
55/*---------------------------------------------------------------------------*/
56#include "sys/log.h"
57
58#define LOG_MODULE "NRF HARDFAULT"
59#define LOG_LEVEL LOG_LEVEL_INFO
60/*---------------------------------------------------------------------------*/
61typedef struct HardFault_stack { /**< HardFault Stack */
62 uint32_t r0; /**< R0 register. */
63 uint32_t r1; /**< R1 register. */
64 uint32_t r2; /**< R2 register. */
65 uint32_t r3; /**< R3 register. */
66 uint32_t r12; /**< R12 register. */
67 uint32_t lr; /**< Link register. */
68 uint32_t pc; /**< Program counter. */
69 uint32_t psr; /**< Program status register. */
70} HardFault_stack_t;
71/*---------------------------------------------------------------------------*/
72/**
73 * @brief Hard fault final handling
74 *
75 */
76__WEAK void
77HardFault_process()
78{
79 NVIC_SystemReset();
80}
81/*---------------------------------------------------------------------------*/
82/**
83 * @brief Hard fault c handler
84 *
85 * @param p_stack_address Pointer to hard fault stack
86 */
87void
88HardFault_c_handler(uint32_t *p_stack_address)
89{
90#ifndef CFSR_MMARVALID
91#define CFSR_MMARVALID (1 << (0 + 7))
92#endif
93
94#ifndef CFSR_BFARVALID
95#define CFSR_BFARVALID (1 << (8 + 7))
96#endif
97
98 HardFault_stack_t *p_stack = (HardFault_stack_t *)p_stack_address;
99 static const char *cfsr_msgs[] = {
100 [0] = "The processor has attempted to execute an undefined instruction",
101 [1] = "The processor attempted a load or store at a location that does not permit the operation",
102 [2] = NULL,
103 [3] = "Unstack for an exception return has caused one or more access violations",
104 [4] = "Stacking for an exception entry has caused one or more access violations",
105 [5] = "A MemManage fault occurred during floating-point lazy state preservation",
106 [6] = NULL,
107 [7] = NULL,
108 [8] = "Instruction bus error",
109 [9] = "Data bus error (PC value stacked for the exception return points to the instruction that caused the fault)",
110 [10] = "Data bus error (return address in the stack frame is not related to the instruction that caused the error)",
111 [11] = "Unstack for an exception return has caused one or more BusFaults",
112 [12] = "Stacking for an exception entry has caused one or more BusFaults",
113 [13] = "A bus fault occurred during floating-point lazy state preservation",
114 [14] = NULL,
115 [15] = NULL,
116 [16] = "The processor has attempted to execute an undefined instruction",
117 [17] = "The processor has attempted to execute an instruction that makes illegal use of the EPSR",
118 [18] = "The processor has attempted an illegal load of EXC_RETURN to the PC, as a result of an invalid context, or an invalid EXC_RETURN value",
119 [19] = "The processor has attempted to access a coprocessor",
120 [20] = NULL,
121 [21] = NULL,
122 [22] = NULL,
123 [23] = NULL,
124 [24] = "The processor has made an unaligned memory access",
125 [25] = "The processor has executed an SDIV or UDIV instruction with a divisor of 0",
126 };
127
128 uint32_t cfsr = SCB->CFSR;
129
130 if(p_stack != NULL) {
131 /* Print information about error. */
132 LOG_INFO("HARD FAULT at 0x%08lX\n", p_stack->pc);
133 LOG_INFO(" R0: 0x%08lX R1: 0x%08lX R2: 0x%08lX R3: 0x%08lX\n",
134 p_stack->r0, p_stack->r1, p_stack->r2, p_stack->r3);
135 LOG_INFO(" R12: 0x%08lX LR: 0x%08lX PSR: 0x%08lX\n",
136 p_stack->r12, p_stack->lr, p_stack->psr);
137 } else {
138 LOG_INFO("Stack violation: stack pointer outside stack area.\n");
139 }
140
141 if(SCB->HFSR & SCB_HFSR_VECTTBL_Msk) {
142 LOG_INFO("Cause: BusFault on a vector table read during exception processing.\n");
143 }
144
145 for(uint32_t i = 0; i < sizeof(cfsr_msgs) / sizeof(cfsr_msgs[0]); i++) {
146 if(((cfsr & (1 << i)) != 0) && (cfsr_msgs[i] != NULL)) {
147 LOG_INFO("Cause: %s.\n", cfsr_msgs[i]);
148 }
149 }
150
151 if(cfsr & CFSR_MMARVALID) {
152 LOG_INFO("MemManage Fault Address: 0x%08lX\n", SCB->MMFAR);
153 }
154
155 if(cfsr & CFSR_BFARVALID) {
156 LOG_INFO("Bus Fault Address: 0x%08lX\n", SCB->BFAR);
157 }
158
159 HardFault_process();
160}
161/*---------------------------------------------------------------------------*/
162/**
163 * @brief Hardfault handler
164 *
165 */
166void HardFault_Handler(void) __attribute__((naked));
167/*---------------------------------------------------------------------------*/
168/**
169 * @brief Hardfault handler
170 *
171 */
172void
174{
175 __ASM volatile (
176 " .syntax unified \n"
177
178 " ldr r0, =0xFFFFFFFD \n"
179 " cmp r0, lr \n"
180 " bne HardFault_Handler_ChooseMSP \n"
181 /* Reading PSP into R0 */
182 " mrs r0, PSP \n"
183 " b HardFault_Handler_Continue \n"
184 "HardFault_Handler_ChooseMSP: \n"
185 /* Reading MSP into R0 */
186 " mrs r0, MSP \n"
187 /* -----------------------------------------------------------------
188 * If we have selected MSP check if we may use stack safetly.
189 * If not - reset the stack to the initial value. */
190 " ldr r1, =__StackTop \n"
191 " ldr r2, =__StackLimit \n"
192
193 /* MSP is in the range of the stack area */
194 " cmp r0, r1 \n"
195 " bhi HardFault_MoveSP \n"
196 " cmp r0, r2 \n"
197 " bhi HardFault_Handler_Continue \n"
198 /* ----------------------------------------------------------------- */
199 "HardFault_MoveSP: \n"
200 " mov SP, r1 \n"
201 " movs r0, #0 \n"
202
203 "HardFault_Handler_Continue: \n"
204 " ldr r3, =%0 \n"
205 " bx r3 \n"
206
207 " .ltorg \n"
208 : : "X" (HardFault_c_handler)
209 );
210}
211/*---------------------------------------------------------------------------*/
212#else /* NRF_HARDFAULT_HANDLER_EXTENDED */
213/*---------------------------------------------------------------------------*/
214/**
215 * @brief Hardfault handler
216 *
217 */
218void HardFault_Handler(void);
219/*---------------------------------------------------------------------------*/
220/**
221 * @brief Hardfault handler
222 *
223 */
224void
226{
227 NVIC_SystemReset();
228}
229#endif /* NRF_HARDFAULT_HANDLER_EXTENDED */
230/*---------------------------------------------------------------------------*/
231/**
232 * @}
233 * @}
234 * @}
235 */
void HardFault_Handler(void)
Hardfault handler.
Header file for the logging system.