Contiki-NG
exceptions.c
1 /*
2  * Copyright (c) 2015 NXP B.V.
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 NXP B.V. nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY NXP B.V. AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL NXP B.V. OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  * Author: Thomas Haydon
32  * Integrated into Contiki by Beshr Al Nahas
33  *
34  */
35 
36 #include <jendefs.h>
37 #include <AppHardwareApi.h>
38 #include <MicroInt.h>
39 #include "contiki.h"
40 #include "exceptions.h"
41 
42 #ifndef EXCEPTION_STALLS_SYSTEM
43 #define EXCEPTION_STALLS_SYSTEM 0
44 #endif /* EXCEPTION_STALLS_SYSTEM */
45 
46 #ifndef PRINT_STACK_ON_REBOOT
47 #define PRINT_STACK_ON_REBOOT 1
48 #endif /* PRINT_STACK_ON_REBOOT */
49 
50 /** Define to dump the stack on exception */
51 #ifndef EXC_DUMP_STACK
52 #define EXC_DUMP_STACK
53 #endif /* EXC_DUMP_STACK */
54 
55 /** Define to dump registers on exception */
56 #ifndef EXC_DUMP_REGS
57 /* #define EXC_DUMP_REGS */
58 #endif /* EXC_DUMP_REGS */
59 
60 /* Select whether exception vectors should be in RAM or Flash based on chip family */
61 #if (defined JENNIC_CHIP_FAMILY_JN514x)
62 #define EXCEPTION_VECTORS_LOCATION_RAM
63 #elif (defined JENNIC_CHIP_FAMILY_JN516x)
64 #define EXCEPTION_VECTORS_LOCATION_FLASH
65 #else
66 #error Unsupported chip family selected
67 #endif /* JENNIC_CHIP_FAMILY */
68 
69 #if (defined EXCEPTION_VECTORS_LOCATION_RAM)
70 /* RAM exception vectors are set up at run time */
71 /* Addresses of exception vectors in RAM */
72 #define BUS_ERROR *((volatile uint32 *)(0x4000000))
73 #define TICK_TIMER *((volatile uint32 *)(0x4000004))
74 #define UNALIGNED_ACCESS *((volatile uint32 *)(0x4000008))
75 #define ILLEGAL_INSTRUCTION *((volatile uint32 *)(0x400000c))
76 #define EXTERNAL_INTERRUPT *((volatile uint32 *)(0x4000010))
77 #define SYSCALL *((volatile uint32 *)(0x4000014))
78 #define TRAP *((volatile uint32 *)(0x4000018))
79 #define GENERIC *((volatile uint32 *)(0x400001c))
80 #define STACK_OVERFLOW *((volatile uint32 *)(0x4000020))
81 #elif (defined EXCEPTION_VECTORS_LOCATION_FLASH)
82 /* Flash exception vectors are set up at compile time */
83 #else
84 #error Unknown exception vector location
85 #endif /* EXCEPTION_VECTORS_LOCATION */
86 
87 /* Locations in stack trace of important information */
88 #define STACK_REG 1
89 #define PROGRAM_COUNTER 18
90 #define EFFECTIVE_ADDR 19
91 
92 /* Number of registers */
93 #define REG_COUNT 16
94 
95 /* Chip dependant RAM size */
96 #if defined(JENNIC_CHIP_JN5148) || defined(JENNIC_CHIP_JN5148J01)
97 #define EXCEPTION_RAM_TOP 0x04020000
98 #else
99 #define EXCEPTION_RAM_TOP 0x04008000
100 #endif
101 
102 static void exception_handler(uint32 *pu32Stack, eExceptionType eType);
103 static void *heap_alloc_overflow_protect(void *pvPointer, uint32 u32Size, bool_t bClear);
104 /*---------------------------------------------------------------------------*/
105 #if PRINT_STACK_ON_REBOOT
106 static void hexprint(uint8 v);
107 static void hexprint32(uint32 v);
108 static void printstring(const char *s);
109 #endif /* PRINT_STACK_ON_REBOOT */
110 
111 /* For debugging */
112 static const char *debug_filename = "nothing";
113 static int debug_line = -1;
114 
115 void
116 debug_file_line(const char *file, int line)
117 {
118  debug_filename = file;
119  debug_line = line;
120 }
121 extern uint32 heap_location;
122 extern void *(*prHeap_AllocFunc)(void *, uint32, bool_t);
123 PRIVATE void *(*prHeap_AllocOrig)(void *, uint32, bool_t);
124 
125 /* Symbol defined by the linker script */
126 /* marks the end of the stack */
127 extern void *stack_low_water_mark;
128 
129 /****************************************************************************/
130 /*** Local Functions ***/
131 /****************************************************************************/
132 /*---------------------------------------------------------------------------*/
133 #if PRINT_STACK_ON_REBOOT
134 #include "dev/uart0.h"
135 #define printchar(X) uart0_write_direct(X)
136 /*---------------------------------------------------------------------------*/
137 static void
138 hexprint(uint8 v)
139 {
140  const char hexconv[] = "0123456789abcdef";
141  printchar(hexconv[v >> 4]);
142  printchar(hexconv[v & 0x0f]);
143 }
144 /*---------------------------------------------------------------------------*/
145 static void
146 hexprint32(uint32 v)
147 {
148  hexprint(((uint32)v) >> (uint32)24);
149  hexprint(((uint32)v) >> (uint32)16);
150  hexprint(((uint32)v) >> (uint32)8);
151  hexprint((v) & 0xff);
152 }
153 /*---------------------------------------------------------------------------*/
154 static void
155 printstring(const char *s)
156 {
157  while(*s) {
158  printchar(*s++);
159  }
160 }
161 #endif /* PRINT_STACK_ON_REBOOT */
162 
163 /****************************************************************************
164  *
165  * NAME: vEXC_Register
166  *
167  * DESCRIPTION:
168  * Set up exceptions. When in RAM, overwrite the default vectors with ours.
169  * We also patch the heap allocation function so that we can keep tabs on
170  * the amount of free heap.
171  *
172  * PARAMETERS: None
173  *
174  * RETURNS:
175  * None
176  *
177  ****************************************************************************/
178 PUBLIC void
179 vEXC_Register(void)
180 {
181 #ifdef EXCEPTION_VECTORS_LOCATION_RAM
182  /* Overwrite exception vectors, pointing them all at the generic handler */
183  BUS_ERROR = (uint32)exception_handler;
184  UNALIGNED_ACCESS = (uint32)exception_handler;
185  ILLEGAL_INSTRUCTION = (uint32)exception_handler;
186  SYSCALL = (uint32)exception_handler;
187  TRAP = (uint32)exception_handler;
188  GENERIC = (uint32)exception_handler;
189  STACK_OVERFLOW = (uint32)exception_handler;
190 #endif /* EXCEPTION_VECTORS_LOCATION */
191 
192  prHeap_AllocOrig = prHeap_AllocFunc;
193  prHeap_AllocFunc = heap_alloc_overflow_protect;
194 }
195 #ifdef EXCEPTION_VECTORS_LOCATION_FLASH
196 /* If exception vectors are in flash, define the handler functions here to be linked in */
197 /* These function names are defined in the 6x linker script for the various exceptions */
198 /* Point them all at the generic handler */
199 PUBLIC void
200 vException_BusError(uint32 *pu32Stack, eExceptionType eType)
201 {
202  exception_handler(pu32Stack, eType);
203 }
204 PUBLIC void
205 vException_UnalignedAccess(uint32 *pu32Stack, eExceptionType eType)
206 {
207  exception_handler(pu32Stack, eType);
208 }
209 PUBLIC void
210 vException_IllegalInstruction(uint32 *pu32Stack, eExceptionType eType)
211 {
212  exception_handler(pu32Stack, eType);
213 }
214 PUBLIC void
215 vException_SysCall(uint32 *pu32Stack, eExceptionType eType)
216 {
217  exception_handler(pu32Stack, eType);
218 }
219 PUBLIC void
220 vException_Trap(uint32 *pu32Stack, eExceptionType eType)
221 {
222  exception_handler(pu32Stack, eType);
223 }
224 PUBLIC void
225 vException_StackOverflow(uint32 *pu32Stack, eExceptionType eType)
226 {
227  exception_handler(pu32Stack, eType);
228 }
229 #endif /* EXCEPTION_VECTORS_LOCATION_FLASH */
230 
231 /****************************************************************************
232  *
233  * NAME: exception_handler
234  *
235  * DESCRIPTION:
236  * Generic exception handler which is called whether the vectors are in RAM or flash
237  *
238  * PARAMETERS: None
239  *
240  * RETURNS:
241  * None
242  *
243  ****************************************************************************/
244 static void
245 exception_handler(uint32 *pu32Stack, eExceptionType eType)
246 {
247 #if (defined EXC_DUMP_STACK) || (defined EXC_DUMP_REGS)
248  int i;
249 #endif
250  uint32 u32EPCR, u32EEAR, u32Stack;
251  char *pcString;
252 
253  MICRO_DISABLE_INTERRUPTS();
254 
255  switch(eType) {
256  case E_EXC_BUS_ERROR:
257  pcString = "BUS";
258  break;
259 
260  case E_EXC_UNALIGNED_ACCESS:
261  pcString = "ALIGN";
262  break;
263 
264  case E_EXC_ILLEGAL_INSTRUCTION:
265  pcString = "ILLEGAL";
266  break;
267 
268  case E_EXC_SYSCALL:
269  pcString = "SYSCALL";
270  break;
271 
272  case E_EXC_TRAP:
273  pcString = "TRAP";
274  break;
275 
276  case E_EXC_GENERIC:
277  pcString = "GENERIC";
278  break;
279 
280  case E_EXC_STACK_OVERFLOW:
281  pcString = "STACK";
282  break;
283 
284  default:
285  pcString = "UNKNOWN";
286  break;
287  }
288 
289  if(bAHI_WatchdogResetEvent()) {
290  pcString = "WATCHDOG";
291  }
292  vAHI_WatchdogStop();
293 
294  /* Pull the EPCR and EEAR values from where they've been saved by the ROM exception handler */
295  u32EPCR = pu32Stack[PROGRAM_COUNTER];
296  u32EEAR = pu32Stack[EFFECTIVE_ADDR];
297  u32Stack = pu32Stack[STACK_REG];
298 
299  /* Log the exception */
300  printstring("\n\n\n");
301  printstring(pcString);
302  printstring(" EXCEPTION @ $");
303  hexprint32(u32EPCR);
304  printstring(" EA: ");
305  hexprint32(u32EEAR);
306  printstring(" SK: ");
307  hexprint32(u32Stack);
308  printstring(" HP: ");
309  hexprint32(((uint32 *)&heap_location)[0]);
310  printstring("\n");
311  printstring(" File: ");
312  printstring(debug_filename);
313  printstring(" Line: ");
314  hexprint32(debug_line);
315  printstring("\n");
316 
317 #ifdef EXC_DUMP_REGS
318  printstring("\nREGS: ");
319  /* Pull and print the registers from saved locations */
320  for(i = 0; i < REG_COUNT; i += 4) {
321  printstring("R");
322  hexprint(i);
323  printstring("-");
324  hexprint(i + 3);
325  printstring(": ");
326  hexprint(pu32Stack[i]);
327  printstring(" ");
328  hexprint32(pu32Stack[i + 1]);
329  printstring(" ");
330  hexprint32(pu32Stack[i + 2]);
331  printstring(" ");
332  hexprint32(pu32Stack[i + 3]);
333  printstring("\n");
334  }
335 #endif
336 
337 #ifdef EXC_DUMP_STACK
338  /* Print the stack */
339  printstring("\nRAM top: ");
340  hexprint32(EXCEPTION_RAM_TOP);
341  printstring("\nSTACK: \n");
342  pu32Stack = (uint32 *)(u32Stack & 0xFFFFFFF0);
343  for(i = 0; (pu32Stack + i) < (uint32 *)(EXCEPTION_RAM_TOP); i += 4) {
344  printstring("@");
345  hexprint32((uint32)(pu32Stack + i));
346  printstring(": ");
347  hexprint32(pu32Stack[i]);
348  printstring(" ");
349  hexprint32(pu32Stack[i + 1]);
350  printstring(" ");
351  hexprint32(pu32Stack[i + 2]);
352  printstring(" ");
353  hexprint32(pu32Stack[i + 3]);
354  printstring("\n");
355  }
356 #endif
357 
358  if(eType == E_EXC_SYSCALL) {
359  return;
360  }
361 
362 #if EXCEPTION_STALLS_SYSTEM
363  while(1) {
364  }
365 #else /* EXCEPTION_STALLS_SYSTEM */
366  /* Software reset */
367  vAHI_WatchdogException(0);
368  vAHI_SwReset();
369 #endif /* EXCEPTION_STALLS_SYSTEM */
370 }
371 /****************************************************************************
372  *
373  * NAME: heap_alloc_overflow_protect
374  *
375  * DESCRIPTION:
376  * New heap allocation function that sets the stack overflow location to the new
377  * top address of the heap.
378  *
379  * PARAMETERS: Name RW Usage
380  * pvPointer W Location of allocated heap memory
381  * u32Size R Number of bytes to allocate
382  * bClear R Flag to set new memory to 0
383  *
384  * RETURNS:
385  * Pointer to new memory
386  *
387  ****************************************************************************/
388 static void *
389 heap_alloc_overflow_protect(void *pvPointer, uint32 u32Size, bool_t bClear)
390 {
391  void *pvAlloc;
392  /* Call original heap allocation function */
393  pvAlloc = prHeap_AllocOrig(pvPointer, u32Size, bClear);
394  /*
395  * Initialise the stack overflow exception to trigger if the end of the
396  * stack is reached. See the linker command file to adjust the allocated
397  * stack size.
398  */
399  /* Set stack overflow address */
400  vAHI_SetStackOverflow(TRUE, ((uint32 *)&heap_location)[0]);
401  return pvAlloc;
402 }