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
102static void exception_handler(uint32 *pu32Stack, eExceptionType eType);
103static void *heap_alloc_overflow_protect(void *pvPointer, uint32 u32Size, bool_t bClear);
104/*---------------------------------------------------------------------------*/
105#if PRINT_STACK_ON_REBOOT
106static void hexprint(uint8 v);
107static void hexprint32(uint32 v);
108static void printstring(const char *s);
109#endif /* PRINT_STACK_ON_REBOOT */
110
111/* For debugging */
112static const char *debug_filename = "nothing";
113static int debug_line = -1;
114
115void
116debug_file_line(const char *file, int line)
117{
118 debug_filename = file;
119 debug_line = line;
120}
121extern uint32 heap_location;
122extern void *(*prHeap_AllocFunc)(void *, uint32, bool_t);
123PRIVATE void *(*prHeap_AllocOrig)(void *, uint32, bool_t);
124
125/* Symbol defined by the linker script */
126/* marks the end of the stack */
127extern 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/*---------------------------------------------------------------------------*/
137static void
138hexprint(uint8 v)
139{
140 const char hexconv[] = "0123456789abcdef";
141 printchar(hexconv[v >> 4]);
142 printchar(hexconv[v & 0x0f]);
143}
144/*---------------------------------------------------------------------------*/
145static void
146hexprint32(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/*---------------------------------------------------------------------------*/
154static void
155printstring(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 ****************************************************************************/
178PUBLIC void
179vEXC_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 */
199PUBLIC void
200vException_BusError(uint32 *pu32Stack, eExceptionType eType)
201{
202 exception_handler(pu32Stack, eType);
203}
204PUBLIC void
205vException_UnalignedAccess(uint32 *pu32Stack, eExceptionType eType)
206{
207 exception_handler(pu32Stack, eType);
208}
209PUBLIC void
210vException_IllegalInstruction(uint32 *pu32Stack, eExceptionType eType)
211{
212 exception_handler(pu32Stack, eType);
213}
214PUBLIC void
215vException_SysCall(uint32 *pu32Stack, eExceptionType eType)
216{
217 exception_handler(pu32Stack, eType);
218}
219PUBLIC void
220vException_Trap(uint32 *pu32Stack, eExceptionType eType)
221{
222 exception_handler(pu32Stack, eType);
223}
224PUBLIC void
225vException_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 ****************************************************************************/
244static void
245exception_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 ****************************************************************************/
388static void *
389heap_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}