@@ -36,7 +36,8 @@ static void print_error_report(const mbed_error_ctx *ctx, const char *, const ch
36
36
#define ERROR_REPORT (ctx , error_msg , error_filename , error_line ) ((void) 0)
37
37
#endif
38
38
39
- static uint8_t error_in_progress = 0 ;
39
+ static core_util_atomic_flag error_in_progress = CORE_UTIL_ATOMIC_FLAG_INIT ;
40
+ static core_util_atomic_flag halt_in_progress = CORE_UTIL_ATOMIC_FLAG_INIT ;
40
41
static int error_count = 0 ;
41
42
static mbed_error_ctx first_error_ctx = {0 };
42
43
static mbed_error_ctx last_error_ctx = {0 };
@@ -46,37 +47,41 @@ static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsign
46
47
//Helper function to halt the system
47
48
static void mbed_halt_system (void )
48
49
{
49
- //If not in ISR context exit, otherwise spin on WFI
50
- if (core_util_is_isr_active () || !core_util_are_interrupts_enabled ()) {
50
+ // Prevent recursion if halt is called again during halt attempt - try
51
+ // something simple instead.
52
+ if (core_util_atomic_flag_test_and_set (& halt_in_progress )) {
53
+ core_util_critical_section_enter ();
54
+ __DSB ();
51
55
for (;;) {
52
- __WFI ();
56
+ __WFE (); // Not WFI, as don't want to wake for pending interrupts
53
57
}
54
- } else {
55
- //exit eventually calls mbed_die
56
- exit (1 );
57
58
}
59
+
60
+ //If in ISR context, call mbed_die directly
61
+ if (core_util_is_isr_active () || !core_util_are_interrupts_enabled ()) {
62
+ mbed_die ();
63
+ }
64
+
65
+ // In normal context, try orderly exit(1), which eventually calls mbed_die
66
+ exit (1 );
58
67
}
59
68
60
69
WEAK void error (const char * format , ...)
61
70
{
62
-
63
- // Prevent recursion if error is called again
64
- if (error_in_progress ) {
65
- return ;
66
- }
67
-
68
- //Call handle_error/print_error_report permanently setting error_in_progress flag
69
- handle_error (MBED_ERROR_UNKNOWN , 0 , NULL , 0 , MBED_CALLER_ADDR ());
70
- ERROR_REPORT (& last_error_ctx , "Fatal Run-time error" , NULL , 0 );
71
- error_in_progress = 1 ;
71
+ // Prevent recursion if error is called again during store+print attempt
72
+ if (!core_util_atomic_flag_test_and_set (& error_in_progress )) {
73
+ handle_error (MBED_ERROR_UNKNOWN , 0 , NULL , 0 , MBED_CALLER_ADDR ());
74
+ ERROR_REPORT (& last_error_ctx , "Fatal Run-time error" , NULL , 0 );
72
75
73
76
#ifndef NDEBUG
74
- va_list arg ;
75
- va_start (arg , format );
76
- mbed_error_vprintf (format , arg );
77
- va_end (arg );
77
+ va_list arg ;
78
+ va_start (arg , format );
79
+ mbed_error_vprintf (format , arg );
80
+ va_end (arg );
78
81
#endif
79
- exit (1 );
82
+ }
83
+
84
+ mbed_halt_system ();
80
85
}
81
86
82
87
//Set an error status with the error handling system
@@ -91,18 +96,6 @@ static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsign
91
96
error_status = MBED_ERROR_INVALID_ARGUMENT ;
92
97
}
93
98
94
- //Prevent corruption by holding out other callers
95
- //and we also need this until we remove the "error" call completely
96
- while (error_in_progress == 1 );
97
-
98
- //Use critsect here, as we don't want inadvertant modification of this global variable
99
- core_util_critical_section_enter ();
100
- error_in_progress = 1 ;
101
- core_util_critical_section_exit ();
102
-
103
- //Increment error count
104
- error_count ++ ;
105
-
106
99
//Clear the context capturing buffer
107
100
memset (& current_error_ctx , 0 , sizeof (mbed_error_ctx ));
108
101
//Capture error information
@@ -126,6 +119,12 @@ static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsign
126
119
current_error_ctx .error_line_number = line_number ;
127
120
#endif
128
121
122
+ //Prevent corruption by holding out other callers
123
+ core_util_critical_section_enter ();
124
+
125
+ //Increment error count
126
+ error_count ++ ;
127
+
129
128
//Capture the fist system error and store it
130
129
if (error_count == 1 ) { //first error
131
130
memcpy (& first_error_ctx , & current_error_ctx , sizeof (mbed_error_ctx ));
@@ -144,7 +143,7 @@ static mbed_error_status_t handle_error(mbed_error_status_t error_status, unsign
144
143
error_hook (& last_error_ctx );
145
144
}
146
145
147
- error_in_progress = 0 ;
146
+ core_util_critical_section_exit () ;
148
147
149
148
return MBED_SUCCESS ;
150
149
}
@@ -179,13 +178,15 @@ mbed_error_status_t mbed_warning(mbed_error_status_t error_status, const char *e
179
178
//Sets a fatal error, this function is marked WEAK to be able to override this for some tests
180
179
WEAK mbed_error_status_t mbed_error (mbed_error_status_t error_status , const char * error_msg , unsigned int error_value , const char * filename , int line_number )
181
180
{
182
- //set the error reported and then halt the system
183
- if (MBED_SUCCESS != handle_error (error_status , error_value , filename , line_number , MBED_CALLER_ADDR ())) {
184
- return MBED_ERROR_FAILED_OPERATION ;
181
+ // Prevent recursion if error is called again during store+print attempt
182
+ if (!core_util_atomic_flag_test_and_set (& error_in_progress )) {
183
+ //set the error reported
184
+ (void ) handle_error (error_status , error_value , filename , line_number , MBED_CALLER_ADDR ());
185
+
186
+ //On fatal errors print the error context/report
187
+ ERROR_REPORT (& last_error_ctx , error_msg , filename , line_number );
185
188
}
186
189
187
- //On fatal errors print the error context/report
188
- ERROR_REPORT (& last_error_ctx , error_msg , filename , line_number );
189
190
mbed_halt_system ();
190
191
191
192
return MBED_ERROR_FAILED_OPERATION ;
0 commit comments