Contiki-NG
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 /*---------------------------------------------------------------------------*/
61 typedef 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
77 HardFault_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  */
87 void
88 HardFault_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  */
166 void HardFault_Handler(void) __attribute__((naked));
167 /*---------------------------------------------------------------------------*/
168 /**
169  * @brief Hardfault handler
170  *
171  */
172 void
173 HardFault_Handler(void)
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  */
218 void HardFault_Handler(void) __attribute__((naked));
219 /*---------------------------------------------------------------------------*/
220 /**
221  * @brief Hardfault handler
222  *
223  */
224 void
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