Skip to content

Commit dcdd616

Browse files
committed
Update exception handling code to remove dedicated fault safe printfs and use mbed_error_printf to optimize memory usage.
Dedicated safe printfs were originally developed to print data over serial with minimal resources. But this adds more code space, so we are switching to use mbed_error_printf.
1 parent cbb12e3 commit dcdd616

File tree

2 files changed

+50
-211
lines changed

2 files changed

+50
-211
lines changed

rtos/TARGET_CORTEX/TARGET_CORTEX_M/mbed_rtx_fault_handler.c

Lines changed: 49 additions & 210 deletions
Original file line numberDiff line numberDiff line change
@@ -17,278 +17,117 @@
1717
#include "rtx_os.h"
1818
#include "device.h"
1919
#include "platform/mbed_error.h"
20+
#include "platform/mbed_interface.h"
2021
#include "hal/serial_api.h"
21-
#include "hal/itm_api.h"
2222

2323
#ifndef MBED_FAULT_HANDLER_DISABLED
2424
#include "mbed_rtx_fault_handler.h"
2525

26-
#ifdef DEVICE_SERIAL
27-
extern int stdio_uart_inited;
28-
extern serial_t stdio_uart;
29-
#endif
30-
3126
//Functions Prototypes
3227
void print_context_info(void);
3328

3429
//Global for populating the context in exception handler
3530
mbed_fault_context_t mbed_fault_context;
3631

37-
/* Converts a uint32 to hex char string */
38-
static void value_to_hex_str(uint32_t value, char *hex_str)
39-
{
40-
char hex_char_map[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
41-
int i = 0;
42-
43-
//Return without converting if hex_str is not provided
44-
if(hex_str == NULL) return;
45-
46-
for(i=7; i>=0; i--) {
47-
hex_str[i] = hex_char_map[(value & (0xf << (i * 4))) >> (i * 4)];
48-
}
49-
}
50-
51-
static void fault_print_init(void)
52-
{
53-
#if DEVICE_SERIAL
54-
/* Initializes std uart if not init-ed yet */
55-
if (!stdio_uart_inited) {
56-
serial_init(&stdio_uart, STDIO_UART_TX, STDIO_UART_RX);
57-
}
58-
#endif
59-
60-
#if DEVICE_ITM
61-
/*Initialize ITM interfaces*/
62-
mbed_itm_init();
63-
#endif
64-
}
65-
66-
static void fault_putc(char ch)
67-
{
68-
#if DEVICE_SERIAL
69-
serial_putc(&stdio_uart, ch);
70-
#endif
71-
72-
#if DEVICE_ITM
73-
/*Initialize ITM interfaces*/
74-
mbed_itm_send(ITM_PORT_SWO, ch);
75-
#endif
76-
}
77-
78-
/* Limited print functionality which prints the string out to
79-
stdout/uart without using stdlib by directly calling serial-api
80-
and also uses less resources
81-
The fmtstr contains the format string for printing and for every %
82-
found in that it fetches a uint32 value from values buffer
83-
and prints it in hex format.
84-
*/
85-
static void fault_print(char *fmtstr, uint32_t *values)
86-
{
87-
#if DEVICE_SERIAL || DEVICE_ITM
88-
int i = 0;
89-
int idx = 0;
90-
int vidx = 0;
91-
char num_str[9]={0};
92-
char *str=NULL;
93-
94-
//Init error reporting interfaces
95-
fault_print_init();
96-
97-
while(fmtstr[i] != '\0') {
98-
if(fmtstr[i]=='%') {
99-
i++;
100-
if(fmtstr[i]=='x') {
101-
//print the number in hex format
102-
value_to_hex_str(values[vidx++],num_str);
103-
for(idx=7; idx>=0; idx--) {
104-
fault_putc(num_str[idx]);
105-
}
106-
}
107-
else if(fmtstr[i]=='s') {
108-
//print the string
109-
str = (char *)((uint32_t)values[vidx++]);
110-
while(*str != '\0') {
111-
fault_putc(*str);
112-
str++;
113-
}
114-
str = NULL;
115-
} else {
116-
//Do not handle any other % formatting and keep going
117-
}
118-
} else {
119-
//handle carriage returns
120-
if (fmtstr[i] == '\n') {
121-
fault_putc('\r');
122-
}
123-
fault_putc(fmtstr[i]);
124-
}
125-
i++;
126-
}
127-
#endif
128-
}
129-
130-
#ifdef MBED_CONF_RTOS_PRESENT
131-
/* Prints info of a thread(using osRtxThread_t struct)*/
132-
static void print_thread(osRtxThread_t *thread)
133-
{
134-
uint32_t data[5];
135-
136-
data[0]=thread->state;
137-
data[1]=thread->thread_addr;
138-
data[2]=thread->stack_size;
139-
data[3]=(uint32_t)thread->stack_mem;
140-
data[4]=thread->sp;
141-
fault_print("\nState: 0x%x Entry: 0x%x Stack Size: 0x%x Mem: 0x%x SP: 0x%x", data);
142-
}
143-
144-
/* Prints thread info from a list */
145-
static void print_threads_info(osRtxThread_t *threads)
146-
{
147-
while(threads != NULL) {
148-
print_thread( threads );
149-
threads = threads->thread_next;
150-
}
151-
}
152-
153-
#endif
154-
15532
//This is a handler function called from Fault handler to print the error information out.
15633
//This runs in fault context and uses special functions(defined in mbed_rtx_fault_handler.c) to print the information without using C-lib support.
157-
__NO_RETURN void mbed_fault_handler (uint32_t fault_type, void *mbed_fault_context_in, void *osRtxInfoIn)
34+
void mbed_fault_handler (uint32_t fault_type, void *mbed_fault_context_in, void *osRtxInfoIn)
15835
{
15936
mbed_error_status_t faultStatus = MBED_SUCCESS;
16037

161-
fault_print("\n++ MbedOS Fault Handler ++\n\nFaultType: ",NULL);
38+
mbed_error_printf("\n++ MbedOS Fault Handler ++\n\nFaultType: ");
16239

16340
switch( fault_type ) {
164-
case HARD_FAULT_EXCEPTION:
165-
fault_print("HardFault",NULL);
166-
faultStatus = MBED_ERROR_HARDFAULT_EXCEPTION;
167-
break;
16841
case MEMMANAGE_FAULT_EXCEPTION:
169-
fault_print("MemManageFault",NULL);
42+
mbed_error_printf("MemManageFault");
17043
faultStatus = MBED_ERROR_MEMMANAGE_EXCEPTION;
17144
break;
45+
17246
case BUS_FAULT_EXCEPTION:
173-
fault_print("BusFault",NULL);
47+
mbed_error_printf("BusFault");
17448
faultStatus = MBED_ERROR_BUSFAULT_EXCEPTION;
17549
break;
50+
17651
case USAGE_FAULT_EXCEPTION:
177-
fault_print("UsageFault",NULL);
52+
mbed_error_printf("UsageFault");
17853
faultStatus = MBED_ERROR_USAGEFAULT_EXCEPTION;
17954
break;
180-
default:
181-
fault_print("Unknown Fault",NULL);
182-
faultStatus = MBED_ERROR_UNKNOWN;
55+
56+
//There is no way we can hit this code without getting an exception, so we have the default treated like hardfault
57+
case HARD_FAULT_EXCEPTION:
58+
default:
59+
mbed_error_printf("HardFault");
60+
faultStatus = MBED_ERROR_HARDFAULT_EXCEPTION;
18361
break;
18462
}
185-
fault_print("\n\nContext:",NULL);
63+
mbed_error_printf("\n\nContext:");
18664
print_context_info();
187-
188-
fault_print("\n\nThreads Info:\nCurrent:",NULL);
189-
print_thread(((osRtxInfo_t *)osRtxInfoIn)->thread.run.curr);
190-
191-
fault_print("\nNext:",NULL);
192-
print_thread(((osRtxInfo_t *)osRtxInfoIn)->thread.run.next);
193-
194-
fault_print("\nWait:",NULL);
195-
osRtxThread_t *threads = ((osRtxInfo_t *)osRtxInfoIn)->thread.wait_list;
196-
print_threads_info(threads);
197-
198-
fault_print("\nDelay:",NULL);
199-
threads = ((osRtxInfo_t *)osRtxInfoIn)->thread.delay_list;
200-
print_threads_info(threads);
20165

202-
fault_print("\nIdle:",NULL);
203-
threads = ((osRtxInfo_t *)osRtxInfoIn)->thread.idle;
204-
print_threads_info(threads);
205-
206-
fault_print("\n\n-- MbedOS Fault Handler --\n\n",NULL);
66+
mbed_error_printf("\n\n-- MbedOS Fault Handler --\n\n");
20767

20868
//Now call mbed_error, to log the error and halt the system
209-
mbed_error( MBED_MAKE_ERROR( MBED_MODULE_UNKNOWN, faultStatus ), "System encountered an unrecoverable fault exception, halting system.", mbed_fault_context.PC_reg, NULL, 0 );
69+
mbed_error( faultStatus, "Unrecoverable fault excaption.", mbed_fault_context.PC_reg, NULL, 0 );
21070

211-
/* In case we return, just spin here, we have already crashed */
212-
for (;;) {
213-
__WFI();
214-
}
21571
}
21672

217-
void print_context_info(void)
73+
MBED_NOINLINE void print_context_info(void)
21874
{
21975
//Context Regs
220-
fault_print("\nR0 : %x"
221-
"\nR1 : %x"
222-
"\nR2 : %x"
223-
"\nR3 : %x"
224-
"\nR4 : %x"
225-
"\nR5 : %x"
226-
"\nR6 : %x"
227-
"\nR7 : %x"
228-
"\nR8 : %x"
229-
"\nR9 : %x"
230-
"\nR10 : %x"
231-
"\nR11 : %x"
232-
"\nR12 : %x"
233-
"\nSP : %x"
234-
"\nLR : %x"
235-
"\nPC : %x"
236-
"\nxPSR : %x"
237-
"\nPSP : %x"
238-
"\nMSP : %x", (uint32_t *)&mbed_fault_context);
76+
for(int i=0;i<13;i++) {
77+
mbed_error_printf("\nR%-4d: %08X", i, ((uint32_t *)&mbed_fault_context)[i]);
78+
}
79+
80+
mbed_error_printf("\nSP : %08X"
81+
"\nLR : %08X"
82+
"\nPC : %08X"
83+
"\nxPSR : %08X"
84+
"\nPSP : %08X"
85+
"\nMSP : %08X", mbed_fault_context.SP_reg, mbed_fault_context.LR_reg, mbed_fault_context.PC_reg,
86+
mbed_fault_context.xPSR, mbed_fault_context.PSP, mbed_fault_context.MSP );
23987

24088
//Capture CPUID to get core/cpu info
241-
fault_print("\nCPUID: %x",(uint32_t *)&SCB->CPUID);
89+
mbed_error_printf("\nCPUID: %08X", SCB->CPUID);
24290

24391
#if !defined(TARGET_M0) && !defined(TARGET_M0P)
24492
//Capture fault information registers to infer the cause of exception
245-
uint32_t FSR[7] = {0};
246-
247-
FSR[0] = SCB->HFSR;
248-
//Split/Capture CFSR into MMFSR, BFSR, UFSR
249-
FSR[1] = 0xFF & SCB->CFSR;//MMFSR
250-
FSR[2] = (0xFF00 & SCB->CFSR) >> 8;//BFSR
251-
FSR[3] = (0xFFFF0000 & SCB->CFSR) >> 16;//UFSR
252-
FSR[4] = SCB->DFSR;
253-
FSR[5] = SCB->AFSR;
254-
FSR[6] = SCB->SHCSR;
255-
fault_print("\nHFSR : %x"
256-
"\nMMFSR: %x"
257-
"\nBFSR : %x"
258-
"\nUFSR : %x"
259-
"\nDFSR : %x"
260-
"\nAFSR : %x"
261-
"\nSHCSR: %x",FSR);
93+
mbed_error_printf("\nHFSR : %08X"
94+
"\nMMFSR: %08X"
95+
"\nBFSR : %08X"
96+
"\nUFSR : %08X"
97+
"\nDFSR : %08X"
98+
"\nAFSR : %08X" ////Split/Capture CFSR into MMFSR, BFSR, UFSR
99+
,SCB->HFSR, (0xFF & SCB->CFSR), ((0xFF00 & SCB->CFSR) >> 8), ((0xFFFF0000 & SCB->CFSR) >> 16), SCB->DFSR, SCB->AFSR );
262100

263101
//Print MMFAR only if its valid as indicated by MMFSR
264-
if(FSR[1] & 0x80) {
265-
fault_print("\nMMFAR: %x",(uint32_t *)&SCB->MMFAR);
102+
if((0xFF & SCB->CFSR) & 0x80) {
103+
mbed_error_printf("\nMMFAR: %08X",SCB->MMFAR);
266104
}
267105
//Print BFAR only if its valid as indicated by BFSR
268-
if(FSR[2] & 0x80) {
269-
fault_print("\nBFAR : %x",(uint32_t *)&SCB->BFAR);
106+
if(((0xFF00 & SCB->CFSR) >> 8) & 0x80) {
107+
mbed_error_printf("\nBFAR : %08X",SCB->BFAR);
270108
}
271109
#endif
110+
272111
//Print Mode
273112
if(mbed_fault_context.EXC_RETURN & 0x8) {
274-
fault_print("\nMode : Thread", NULL);
113+
mbed_error_printf("\nMode : Thread");
275114
//Print Priv level in Thread mode - We capture CONTROL reg which reflects the privilege.
276115
//Note that the CONTROL register captured still reflects the privilege status of the
277116
//thread mode eventhough we are in Handler mode by the time we capture it.
278117
if(mbed_fault_context.CONTROL & 0x1) {
279-
fault_print("\nPriv : User", NULL);
118+
mbed_error_printf("\nPriv : User");
280119
} else {
281-
fault_print("\nPriv : Privileged", NULL);
120+
mbed_error_printf("\nPriv : Privileged");
282121
}
283122
} else {
284-
fault_print("\nMode : Handler", NULL);
285-
fault_print("\nPriv : Privileged", NULL);
123+
mbed_error_printf("\nMode : Handler");
124+
mbed_error_printf("\nPriv : Privileged");
286125
}
287126
//Print Return Stack
288127
if(mbed_fault_context.EXC_RETURN & 0x4) {
289-
fault_print("\nStack: PSP", NULL);
128+
mbed_error_printf("\nStack: PSP");
290129
} else {
291-
fault_print("\nStack: MSP", NULL);
130+
mbed_error_printf("\nStack: MSP");
292131
}
293132
}
294133

rtos/TARGET_CORTEX/TARGET_CORTEX_M/mbed_rtx_fault_handler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,6 @@ typedef struct {
5353

5454
//This is a handler function called from Fault handler to print the error information out.
5555
//This runs in fault context and uses special functions(defined in mbed_rtx_fault_handler.c) to print the information without using C-lib support.
56-
__NO_RETURN void mbed_fault_handler (uint32_t fault_type, void *mbed_fault_context_in, void *osRtxInfoIn);
56+
void mbed_fault_handler (uint32_t fault_type, void *mbed_fault_context_in, void *osRtxInfoIn);
5757

5858
#endif

0 commit comments

Comments
 (0)