summaryrefslogtreecommitdiff
path: root/core/cortex-m/panic.S
blob: 766af751439638ce71beef6c3dbbcdb8e25301ad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * Fatal exception handling and debug tracing
 */

#include "config.h"

.text

.syntax unified
.code 16

.macro hex_reg r, offset                      @ prepare to build
    add r1, r3, #\offset                      @ .. hexadecimal string
    mov r0, \r                                @ .. from the reg value
    bl buildhex
.endm

/* fatal exception handler */
.global panic
.thumb_func
panic:
#ifndef CONFIG_DEBUG
    b EcSystemReset                           @ Reboot the system
#else /* CONFIG_DEBUG */
    /* check that the exception stack pointer is valid */
    ldr r0, =CONFIG_RAM_BASE                  @ start of RAM
    ldr r1, =CONFIG_RAM_BASE+CONFIG_RAM_SIZE  @ end of RAM
    mrs r12, psp                              @ process stack pointer
    cmp r12, r0                               @ is sp >= RAM start ?
    it  ge
    cmpge r1, r12                             @ is sp < RAM end ?
    blt panic_print                           @ no => no values to read
    /* output registers value */
    ldr r3, =msg_excep                        @ pointer to the text buffer
    mrs r2, ipsr                              @ get exception num from IPSR
    bfc r2, #9, #23                           @ the exception is the 3 LSB
    hex_reg r2, 18                            @ prepare hexa for excep number
    hex_reg r4, 119                           @ prepare hexa for R4
    hex_reg r5, 132                           @ prepare hexa for R5
    hex_reg r6, 145                           @ prepare hexa for R6
    hex_reg r7, 156                           @ prepare hexa for R7
    hex_reg r8, 171                           @ prepare hexa for R8
    hex_reg r9, 184                           @ prepare hexa for R9
    hex_reg r10, 197                          @ prepare hexa for R10
    hex_reg r11, 210                          @ prepare hexa for R11
    ldmia r12!, {r4-r11}                      @ load saved r0-r3,r12,lr,pc,psr
    hex_reg r4, 66                            @ prepare hexa for R0
    hex_reg r5, 79                            @ prepare hexa for R1
    hex_reg r6, 92                            @ prepare hexa for R2
    hex_reg r7, 105                           @ prepare hexa for R3
    hex_reg r8, 225                           @ prepare hexa for R12
    hex_reg r12, 238                          @ prepare hexa for SP
    hex_reg r9, 251                           @ prepare hexa for LR
    hex_reg r10, 264                          @ prepare hexa for PC
    hex_reg r11, 40                           @ prepare hexa for xPSR
    /* print exception trace */
panic_print:
    ldr r0, =msg_excep                        @ pointer to the text buffer
    bl emergency_puts                         @ print the banner
    b system_reset                            @ Reboot the system

/* Helpers for exception trace */
/* print a string on the UART
 * r0: asciiZ string pointer
 */
emergency_puts:
    ldr r1, =CONFIG_UART_ADDRESS              @ UART base address
1:
    ldrb r3, [r0], #1                         @ read one character
    cmp r3, #0                                @ end of the string ?
    beq 3f                                    @ if yes, return
2:  /* putchar */
    ldr r2, [r1, #CONFIG_UART_SR_OFFSET]      @ read UART status
    tst r2, #CONFIG_UART_SR_TXEMPTY           @ free space on TX ?
    beq 2b                                    @ if no, wait
    str r3, [r1, #CONFIG_UART_DR_OFFSET]      @ send character to UART DR
    b 1b                                      @ goto next character
3:  /* return */
    bx lr

/* write a number in hexadecimal in a text buffer
 * r0: number to print
 * r1: pointer to *end* of the buffer (filled with '0')
 */
buildhex:
    cmp r0, #0
    it  eq
    bxeq lr
    and r2, r0, #0xf
    cmp r2, #10
    ite  lt
    addlt r2, #'0'
    addge r2, #'A'-10
    strb r2, [r1],#-1
    lsr r0, #4
    b buildhex

.data
msg_excep: .ascii "\r\n=== EXCEPTION: 00 ====== xPSR: 00000000 ===========\r\n"
msg_reg0:  .ascii "R0 :00000000 R1 :00000000 R2 :00000000 R3 :00000000\r\n"
msg_reg1:  .ascii "R4 :00000000 R5 :00000000 R6 :00000000 R7 :00000000\r\n"
msg_reg2:  .ascii "R8 :00000000 R9 :00000000 R10:00000000 R11:00000000\r\n"
msg_reg3:  .ascii "R12:00000000 SP :00000000 LR :00000000 PC :00000000\r\n\0"
.align 4
#endif /* CONFIG_DEBUG */