2014-03-31 16:27:14 +00:00
/* mbed Microcontroller Library
* Copyright ( c ) 2006 - 2013 ARM Limited
2018-11-09 11:31:20 +00:00
* SPDX - License - Identifier : Apache - 2.0
2014-03-31 16:27:14 +00:00
*
* Licensed under the Apache License , Version 2.0 ( the " License " ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an " AS IS " BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
*/
# include <stdlib.h>
# include <stdarg.h>
2018-06-06 08:00:27 +00:00
# include <string.h>
2014-03-31 16:27:14 +00:00
# include "device.h"
2018-11-13 01:37:54 +00:00
# include "platform/mbed_crash_data_offsets.h"
# include "platform/mbed_retarget.h"
2019-01-22 14:09:25 +00:00
# include "platform/mbed_atomic.h"
2018-05-07 22:24:42 +00:00
# include "platform/mbed_critical.h"
2016-10-01 07:11:36 +00:00
# include "platform/mbed_error.h"
2018-05-23 00:25:46 +00:00
# include "platform/mbed_error_hist.h"
2016-10-01 07:11:36 +00:00
# include "platform/mbed_interface.h"
2018-11-13 01:37:54 +00:00
# include "platform/mbed_power_mgmt.h"
2018-12-21 22:17:15 +00:00
# include "platform/mbed_stats.h"
2018-06-27 14:09:15 +00:00
# ifdef MBED_CONF_RTOS_PRESENT
2018-05-23 00:25:46 +00:00
# include "rtx_os.h"
# endif
2018-05-12 15:26:09 +00:00
2014-03-31 16:27:14 +00:00
# if DEVICE_STDIO_MESSAGES
# include <stdio.h>
# endif
2018-09-12 09:15:51 +00:00
# ifndef __STDC_FORMAT_MACROS
# define __STDC_FORMAT_MACROS
# endif
# include <inttypes.h>
2014-03-31 16:27:14 +00:00
2018-07-05 16:50:49 +00:00
# ifndef NDEBUG
2018-11-19 02:38:18 +00:00
# define ERROR_REPORT(ctx, error_msg, error_filename, error_line) print_error_report(ctx, error_msg, error_filename, error_line)
static void print_error_report ( const mbed_error_ctx * ctx , const char * , const char * error_filename , int error_line ) ;
2018-07-05 16:50:49 +00:00
# else
2018-11-19 02:38:18 +00:00
# define ERROR_REPORT(ctx, error_msg, error_filename, error_line) ((void) 0)
2018-07-05 16:50:49 +00:00
# endif
2018-05-23 00:25:46 +00:00
2019-04-09 13:09:24 +00:00
static bool error_in_progress ;
2018-10-05 13:43:41 +00:00
static core_util_atomic_flag halt_in_progress = CORE_UTIL_ATOMIC_FLAG_INIT ;
2018-05-07 22:24:42 +00:00
static int error_count = 0 ;
static mbed_error_ctx first_error_ctx = { 0 } ;
2018-11-13 01:37:54 +00:00
2019-02-12 22:20:25 +00:00
static mbed_error_ctx last_error_ctx = { 0 } ;
static mbed_error_hook_t error_hook = NULL ;
static mbed_error_status_t handle_error ( mbed_error_status_t error_status , unsigned int error_value , const char * filename , int line_number , void * caller ) ;
2018-11-13 01:37:54 +00:00
# if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
2018-11-16 18:26:23 +00:00
//Global for populating the context in exception handler
static mbed_error_ctx * const report_error_ctx = ( mbed_error_ctx * ) ( ERROR_CONTEXT_LOCATION ) ;
static bool is_reboot_error_valid = false ;
2018-05-07 22:24:42 +00:00
2018-11-13 01:37:54 +00:00
//Helper function to calculate CRC
//NOTE: It would have been better to use MbedCRC implementation. But
//MbedCRC uses table based calculation and we dont want to keep that table memory
2018-11-16 18:26:23 +00:00
//used up for this purpose. Also we cannot force bitwise calculation in MbedCRC
2018-11-13 01:37:54 +00:00
//and it also requires a new wrapper to be called from C implementation. Since
//we dont have many uses cases to create a C wrapper for MbedCRC and the data
2018-11-16 18:26:23 +00:00
//we calculate CRC on in this context is very less we will use a local
2018-11-13 01:37:54 +00:00
//implementation here.
2018-11-16 18:26:23 +00:00
static unsigned int compute_crc32 ( const void * data , int datalen )
2018-11-13 01:37:54 +00:00
{
const unsigned int polynomial = 0x04C11DB7 ; /* divisor is 32bit */
unsigned int crc = 0 ; /* CRC value is 32bit */
2018-11-16 18:26:23 +00:00
unsigned char * buf = ( unsigned char * ) data ; //use a temp variable to make code readable and to avoid typecasting issues.
2018-11-19 02:38:18 +00:00
for ( ; datalen > 0 ; datalen - - ) {
2018-11-16 18:26:23 +00:00
unsigned char b = * buf + + ;
crc ^ = ( unsigned int ) ( b < < 24 ) ; /* move byte into upper 8bit */
2018-11-13 01:37:54 +00:00
for ( int i = 0 ; i < 8 ; i + + ) {
/* is MSB 1 */
if ( ( crc & 0x80000000 ) ! = 0 ) {
crc = ( unsigned int ) ( ( crc < < 1 ) ^ polynomial ) ;
} else {
crc < < = 1 ;
}
}
}
return crc ;
}
2019-02-12 22:20:25 +00:00
# endif
2018-11-13 01:37:54 +00:00
2018-05-07 22:24:42 +00:00
//Helper function to halt the system
2018-10-05 13:52:52 +00:00
static MBED_NORETURN void mbed_halt_system ( void )
2018-05-07 22:24:42 +00:00
{
2018-10-05 13:43:41 +00:00
// Prevent recursion if halt is called again during halt attempt - try
// something simple instead.
if ( core_util_atomic_flag_test_and_set ( & halt_in_progress ) ) {
core_util_critical_section_enter ( ) ;
__DSB ( ) ;
2018-06-27 14:09:15 +00:00
for ( ; ; ) {
2018-10-05 13:43:41 +00:00
__WFE ( ) ; // Not WFI, as don't want to wake for pending interrupts
2018-05-07 22:24:42 +00:00
}
}
2018-10-05 13:43:41 +00:00
//If in ISR context, call mbed_die directly
if ( core_util_is_isr_active ( ) | | ! core_util_are_interrupts_enabled ( ) ) {
mbed_die ( ) ;
}
// In normal context, try orderly exit(1), which eventually calls mbed_die
exit ( 1 ) ;
2018-05-07 22:24:42 +00:00
}
2017-06-01 20:53:06 +00:00
2018-10-05 13:52:52 +00:00
WEAK MBED_NORETURN void error ( const char * format , . . . )
2018-06-27 14:09:15 +00:00
{
2018-10-05 13:43:41 +00:00
// Prevent recursion if error is called again during store+print attempt
2019-04-09 13:09:24 +00:00
if ( ! core_util_atomic_exchange_bool ( & error_in_progress , true ) ) {
2018-10-05 13:43:41 +00:00
handle_error ( MBED_ERROR_UNKNOWN , 0 , NULL , 0 , MBED_CALLER_ADDR ( ) ) ;
2018-11-19 02:38:18 +00:00
ERROR_REPORT ( & last_error_ctx , " Fatal Run-time error " , NULL , 0 ) ;
2017-06-01 20:53:06 +00:00
2016-09-15 13:20:37 +00:00
# ifndef NDEBUG
2018-10-05 13:43:41 +00:00
va_list arg ;
va_start ( arg , format ) ;
mbed_error_vprintf ( format , arg ) ;
va_end ( arg ) ;
2016-09-15 13:20:37 +00:00
# endif
2018-10-05 13:43:41 +00:00
}
mbed_halt_system ( ) ;
2014-03-31 16:27:14 +00:00
}
2018-05-07 22:24:42 +00:00
//Set an error status with the error handling system
Make location meaningful in print_error_report
`handle_error` calls `MBED_CALLER_ADDR()`, but this is always a location from within platform/mbed_error.c. This is because `handle_error` is declared static. This does not cause the function to be inlined however. Instead, it is called by each function within mbed_error.c. For example, mbed_error yields this code:
```
000625c8 <mbed_error>:
625c8: b510 push {r4, lr}
625ca: 460c mov r4, r1
625cc: 4611 mov r1, r2
625ce: 461a mov r2, r3
625d0: 9b02 ldr r3, [sp, #8]
625d2: f7ff feff bl 623d4 <handle_error>
625d6: b968 cbnz r0, 625f4 <mbed_error+0x2c>
625d8: 4620 mov r0, r4
625da: f7ff ff67 bl 624ac <print_error_report.constprop.0>
625de: f7ff fea8 bl 62332 <core_util_is_isr_active>
625e2: b910 cbnz r0, 625ea <mbed_error+0x22>
625e4: f7ff fe9f bl 62326 <core_util_are_interrupts_enabled>
625e8: b908 cbnz r0, 625ee <mbed_error+0x26>
625ea: bf30 wfi
625ec: e7fd b.n 625ea <mbed_error+0x22>
625ee: 2001 movs r0, #1
625f0: f000 f948 bl 62884 <__wrap_exit>
625f4: 4800 ldr r0, [pc, #0] ; (625f8 <mbed_error+0x30>)
625f6: bd10 pop {r4, pc}
625f8: 80ff010f .word 0x80ff010f
```
Note that at `625d2` there is a bl to handle error. That replaces the LR, which means that ALL calls to mbed_error will report a location of 0x625d6 or 0x625d7 (user vs. supervisor). I do not expect that this was the intention of the code. The simplest fix is to change line 99:
```C
static inline mbed_error_status_t handle_error(mbed_error_status_t error_status, unsigned int error_value, const char *filename, int line_number)
```
Since `handle_error()` will be inlined, the link register will be kept the same, so `MBED_CALLER_ADDR()` will yield the expected result. However, there is no guarantee that the compiler will respect the `inline` keyword in all circumstances.
The result is that each function that wishes to report its caller must extract its caller. This code cannot be centralised.
I have modified `mbed_error.c` to report the caller of each error reporting function, rather than the error reporting function itself.
2018-07-26 15:21:17 +00:00
static mbed_error_status_t handle_error ( mbed_error_status_t error_status , unsigned int error_value , const char * filename , int line_number , void * caller )
2018-05-07 22:24:42 +00:00
{
2018-05-12 15:26:09 +00:00
mbed_error_ctx current_error_ctx ;
2018-06-27 14:09:15 +00:00
2018-05-07 22:24:42 +00:00
//Error status should always be < 0
2018-06-18 16:26:48 +00:00
if ( error_status > = 0 ) {
2018-05-21 13:57:50 +00:00
//This is a weird situation, someone called mbed_error with invalid error code.
2018-05-12 15:26:09 +00:00
//We will still handle the situation but change the error code to ERROR_INVALID_ARGUMENT, atleast the context will have info on who called it
2018-05-21 13:57:50 +00:00
error_status = MBED_ERROR_INVALID_ARGUMENT ;
2018-05-07 22:24:42 +00:00
}
2018-06-27 14:09:15 +00:00
2018-05-07 22:24:42 +00:00
//Clear the context capturing buffer
2018-09-07 12:30:59 +00:00
memset ( & current_error_ctx , 0 , sizeof ( mbed_error_ctx ) ) ;
2018-05-07 22:24:42 +00:00
//Capture error information
current_error_ctx . error_status = error_status ;
Make location meaningful in print_error_report
`handle_error` calls `MBED_CALLER_ADDR()`, but this is always a location from within platform/mbed_error.c. This is because `handle_error` is declared static. This does not cause the function to be inlined however. Instead, it is called by each function within mbed_error.c. For example, mbed_error yields this code:
```
000625c8 <mbed_error>:
625c8: b510 push {r4, lr}
625ca: 460c mov r4, r1
625cc: 4611 mov r1, r2
625ce: 461a mov r2, r3
625d0: 9b02 ldr r3, [sp, #8]
625d2: f7ff feff bl 623d4 <handle_error>
625d6: b968 cbnz r0, 625f4 <mbed_error+0x2c>
625d8: 4620 mov r0, r4
625da: f7ff ff67 bl 624ac <print_error_report.constprop.0>
625de: f7ff fea8 bl 62332 <core_util_is_isr_active>
625e2: b910 cbnz r0, 625ea <mbed_error+0x22>
625e4: f7ff fe9f bl 62326 <core_util_are_interrupts_enabled>
625e8: b908 cbnz r0, 625ee <mbed_error+0x26>
625ea: bf30 wfi
625ec: e7fd b.n 625ea <mbed_error+0x22>
625ee: 2001 movs r0, #1
625f0: f000 f948 bl 62884 <__wrap_exit>
625f4: 4800 ldr r0, [pc, #0] ; (625f8 <mbed_error+0x30>)
625f6: bd10 pop {r4, pc}
625f8: 80ff010f .word 0x80ff010f
```
Note that at `625d2` there is a bl to handle error. That replaces the LR, which means that ALL calls to mbed_error will report a location of 0x625d6 or 0x625d7 (user vs. supervisor). I do not expect that this was the intention of the code. The simplest fix is to change line 99:
```C
static inline mbed_error_status_t handle_error(mbed_error_status_t error_status, unsigned int error_value, const char *filename, int line_number)
```
Since `handle_error()` will be inlined, the link register will be kept the same, so `MBED_CALLER_ADDR()` will yield the expected result. However, there is no guarantee that the compiler will respect the `inline` keyword in all circumstances.
The result is that each function that wishes to report its caller must extract its caller. This code cannot be centralised.
I have modified `mbed_error.c` to report the caller of each error reporting function, rather than the error reporting function itself.
2018-07-26 15:21:17 +00:00
current_error_ctx . error_address = ( uint32_t ) caller ;
2018-05-07 22:24:42 +00:00
current_error_ctx . error_value = error_value ;
2018-06-27 14:09:15 +00:00
# ifdef MBED_CONF_RTOS_PRESENT
2018-05-23 00:25:46 +00:00
//Capture thread info
osRtxThread_t * current_thread = osRtxInfo . thread . run . curr ;
current_error_ctx . thread_id = ( uint32_t ) current_thread ;
current_error_ctx . thread_entry_address = ( uint32_t ) current_thread - > thread_addr ;
current_error_ctx . thread_stack_size = current_thread - > stack_size ;
current_error_ctx . thread_stack_mem = ( uint32_t ) current_thread - > stack_mem ;
2018-10-16 10:05:14 +00:00
current_error_ctx . thread_current_sp = ( uint32_t ) & current_error_ctx ; // Address local variable to get a stack pointer
2018-05-23 00:25:46 +00:00
# endif //MBED_CONF_RTOS_PRESENT
2018-05-07 22:24:42 +00:00
2018-07-03 19:00:46 +00:00
# if MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED
2018-05-07 22:24:42 +00:00
//Capture filename/linenumber if provided
2018-05-31 15:39:58 +00:00
//Index for tracking error_filename
2018-06-11 18:26:04 +00:00
strncpy ( current_error_ctx . error_filename , filename , MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN ) ;
2018-05-31 15:39:58 +00:00
current_error_ctx . error_line_number = line_number ;
2018-05-07 22:24:42 +00:00
# endif
2018-06-27 14:09:15 +00:00
2018-10-05 13:43:41 +00:00
//Prevent corruption by holding out other callers
core_util_critical_section_enter ( ) ;
//Increment error count
error_count + + ;
2018-11-13 23:21:30 +00:00
//Capture the first system error and store it
2018-06-18 16:26:48 +00:00
if ( error_count = = 1 ) { //first error
2018-05-07 22:24:42 +00:00
memcpy ( & first_error_ctx , & current_error_ctx , sizeof ( mbed_error_ctx ) ) ;
}
2018-06-27 14:09:15 +00:00
2018-05-12 15:26:09 +00:00
//copy this error to last error
memcpy ( & last_error_ctx , & current_error_ctx , sizeof ( mbed_error_ctx ) ) ;
2018-06-27 14:09:15 +00:00
2018-06-11 18:26:04 +00:00
# if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED
2018-05-14 13:27:17 +00:00
//Log the error with error log
2018-05-23 00:25:46 +00:00
mbed_error_hist_put ( & current_error_ctx ) ;
2018-06-27 14:09:15 +00:00
# endif
2018-05-12 15:26:09 +00:00
//Call the error hook if available
2018-06-18 16:26:48 +00:00
if ( error_hook ! = NULL ) {
2018-05-12 15:26:09 +00:00
error_hook ( & last_error_ctx ) ;
}
2018-06-27 14:09:15 +00:00
2018-10-05 13:43:41 +00:00
core_util_critical_section_exit ( ) ;
2018-06-27 14:09:15 +00:00
2018-05-21 13:57:50 +00:00
return MBED_SUCCESS ;
2018-05-07 22:24:42 +00:00
}
2018-11-16 18:26:23 +00:00
WEAK void mbed_error_reboot_callback ( mbed_error_ctx * error_context )
{
2018-11-13 01:37:54 +00:00
//Dont do anything here, let application override this if required.
}
//Initialize Error handling system and report any errors detected on rebooted
mbed_error_status_t mbed_error_initialize ( void )
{
# if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
uint32_t crc_val = 0 ;
2018-11-19 02:38:18 +00:00
2018-11-16 18:26:23 +00:00
//Just check if we have valid value for error_status, if error_status is positive(which is not valid), no need to check crc
if ( report_error_ctx - > error_status < 0 ) {
crc_val = compute_crc32 ( report_error_ctx , offsetof ( mbed_error_ctx , crc_error_ctx ) ) ;
//Read report_error_ctx and check if CRC is correct, and with valid status code
if ( ( report_error_ctx - > crc_error_ctx = = crc_val ) & & ( report_error_ctx - > is_error_processed = = 0 ) ) {
is_reboot_error_valid = true ;
2018-11-19 02:38:18 +00:00
2018-11-16 18:26:23 +00:00
//Call the mbed_error_reboot_callback, this enables applications to do some handling before we do the handling
mbed_error_reboot_callback ( report_error_ctx ) ;
2018-11-19 02:38:18 +00:00
//We let the callback reset the error info, so check if its still valid and do the rest only if its still valid.
2019-01-08 21:00:56 +00:00
if ( report_error_ctx - > error_reboot_count > 0 ) {
2018-11-19 02:38:18 +00:00
2019-01-30 10:58:25 +00:00
report_error_ctx - > is_error_processed = 1 ; //Set the flag that we already processed this error
crc_val = compute_crc32 ( report_error_ctx , offsetof ( mbed_error_ctx , crc_error_ctx ) ) ;
report_error_ctx - > crc_error_ctx = crc_val ;
2018-11-19 02:38:18 +00:00
//Enforce max-reboot only if auto reboot is enabled
2018-11-16 18:26:23 +00:00
# if MBED_CONF_PLATFORM_FATAL_ERROR_AUTO_REBOOT_ENABLED
2018-11-19 02:38:18 +00:00
if ( report_error_ctx - > error_reboot_count > = MBED_CONF_PLATFORM_ERROR_REBOOT_MAX ) {
mbed_halt_system ( ) ;
}
2018-11-16 18:26:23 +00:00
# endif
2018-11-19 02:38:18 +00:00
}
2018-11-13 01:37:54 +00:00
}
}
# endif
return MBED_SUCCESS ;
}
2018-05-07 22:24:42 +00:00
//Return the first error
2018-06-27 14:09:15 +00:00
mbed_error_status_t mbed_get_first_error ( void )
2018-05-07 22:24:42 +00:00
{
//return the first error recorded
return first_error_ctx . error_status ;
}
//Return the last error
2018-06-27 14:09:15 +00:00
mbed_error_status_t mbed_get_last_error ( void )
2018-05-07 22:24:42 +00:00
{
//return the last error recorded
2018-05-12 15:26:09 +00:00
return last_error_ctx . error_status ;
2018-05-07 22:24:42 +00:00
}
//Gets the current error count
2018-06-27 14:09:15 +00:00
int mbed_get_error_count ( void )
2018-05-07 22:24:42 +00:00
{
//return the current error count
return error_count ;
}
2019-04-09 13:09:24 +00:00
//Reads the fatal error occurred" flag
bool mbed_get_error_in_progress ( void )
{
return core_util_atomic_load_bool ( & error_in_progress ) ;
}
2018-10-05 13:52:52 +00:00
//Sets a non-fatal error
2018-06-27 14:09:15 +00:00
mbed_error_status_t mbed_warning ( mbed_error_status_t error_status , const char * error_msg , unsigned int error_value , const char * filename , int line_number )
2018-05-12 15:26:09 +00:00
{
Make location meaningful in print_error_report
`handle_error` calls `MBED_CALLER_ADDR()`, but this is always a location from within platform/mbed_error.c. This is because `handle_error` is declared static. This does not cause the function to be inlined however. Instead, it is called by each function within mbed_error.c. For example, mbed_error yields this code:
```
000625c8 <mbed_error>:
625c8: b510 push {r4, lr}
625ca: 460c mov r4, r1
625cc: 4611 mov r1, r2
625ce: 461a mov r2, r3
625d0: 9b02 ldr r3, [sp, #8]
625d2: f7ff feff bl 623d4 <handle_error>
625d6: b968 cbnz r0, 625f4 <mbed_error+0x2c>
625d8: 4620 mov r0, r4
625da: f7ff ff67 bl 624ac <print_error_report.constprop.0>
625de: f7ff fea8 bl 62332 <core_util_is_isr_active>
625e2: b910 cbnz r0, 625ea <mbed_error+0x22>
625e4: f7ff fe9f bl 62326 <core_util_are_interrupts_enabled>
625e8: b908 cbnz r0, 625ee <mbed_error+0x26>
625ea: bf30 wfi
625ec: e7fd b.n 625ea <mbed_error+0x22>
625ee: 2001 movs r0, #1
625f0: f000 f948 bl 62884 <__wrap_exit>
625f4: 4800 ldr r0, [pc, #0] ; (625f8 <mbed_error+0x30>)
625f6: bd10 pop {r4, pc}
625f8: 80ff010f .word 0x80ff010f
```
Note that at `625d2` there is a bl to handle error. That replaces the LR, which means that ALL calls to mbed_error will report a location of 0x625d6 or 0x625d7 (user vs. supervisor). I do not expect that this was the intention of the code. The simplest fix is to change line 99:
```C
static inline mbed_error_status_t handle_error(mbed_error_status_t error_status, unsigned int error_value, const char *filename, int line_number)
```
Since `handle_error()` will be inlined, the link register will be kept the same, so `MBED_CALLER_ADDR()` will yield the expected result. However, there is no guarantee that the compiler will respect the `inline` keyword in all circumstances.
The result is that each function that wishes to report its caller must extract its caller. This code cannot be centralised.
I have modified `mbed_error.c` to report the caller of each error reporting function, rather than the error reporting function itself.
2018-07-26 15:21:17 +00:00
return handle_error ( error_status , error_value , filename , line_number , MBED_CALLER_ADDR ( ) ) ;
2018-05-12 15:26:09 +00:00
}
2018-06-27 14:09:15 +00:00
//Sets a fatal error, this function is marked WEAK to be able to override this for some tests
2018-10-05 13:52:52 +00:00
WEAK MBED_NORETURN 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 )
2018-05-07 22:24:42 +00:00
{
2018-10-05 13:43:41 +00:00
// Prevent recursion if error is called again during store+print attempt
2019-04-09 13:09:24 +00:00
if ( ! core_util_atomic_exchange_bool ( & error_in_progress , true ) ) {
2018-10-05 13:43:41 +00:00
//set the error reported
( void ) handle_error ( error_status , error_value , filename , line_number , MBED_CALLER_ADDR ( ) ) ;
//On fatal errors print the error context/report
2018-11-19 02:38:18 +00:00
ERROR_REPORT ( & last_error_ctx , error_msg , filename , line_number ) ;
2018-11-13 01:37:54 +00:00
}
2018-11-16 18:26:23 +00:00
2018-11-13 01:37:54 +00:00
# if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
uint32_t crc_val = 0 ;
2018-11-16 18:26:23 +00:00
crc_val = compute_crc32 ( report_error_ctx , offsetof ( mbed_error_ctx , crc_error_ctx ) ) ;
2018-11-13 01:37:54 +00:00
//Read report_error_ctx and check if CRC is correct for report_error_ctx
2018-11-14 19:40:13 +00:00
if ( report_error_ctx - > crc_error_ctx = = crc_val ) {
2018-11-13 01:37:54 +00:00
uint32_t current_reboot_count = report_error_ctx - > error_reboot_count ;
last_error_ctx . error_reboot_count = current_reboot_count + 1 ;
} else {
last_error_ctx . error_reboot_count = 1 ;
2018-06-27 14:09:15 +00:00
}
2018-11-13 01:37:54 +00:00
last_error_ctx . is_error_processed = 0 ; //Set the flag that this is a new error
//Update the struct with crc
2018-11-16 18:26:23 +00:00
last_error_ctx . crc_error_ctx = compute_crc32 ( & last_error_ctx , offsetof ( mbed_error_ctx , crc_error_ctx ) ) ;
2018-11-13 23:21:30 +00:00
//Protect report_error_ctx while we update it
core_util_critical_section_enter ( ) ;
2018-11-13 01:37:54 +00:00
memcpy ( report_error_ctx , & last_error_ctx , sizeof ( mbed_error_ctx ) ) ;
2018-11-13 23:21:30 +00:00
core_util_critical_section_exit ( ) ;
2018-11-13 01:37:54 +00:00
//We need not call delete_mbed_crc(crc_obj) here as we are going to reset the system anyway, and calling delete while handling a fatal error may cause nested exception
2018-11-14 19:40:13 +00:00
# if MBED_CONF_PLATFORM_FATAL_ERROR_AUTO_REBOOT_ENABLED && (MBED_CONF_PLATFORM_ERROR_REBOOT_MAX > 0)
2019-01-23 23:33:10 +00:00
# ifndef NDEBUG
2019-01-08 21:00:56 +00:00
mbed_error_printf ( " \n = System will be rebooted due to a fatal error = \n " ) ;
if ( report_error_ctx - > error_reboot_count > = MBED_CONF_PLATFORM_ERROR_REBOOT_MAX ) {
//We have rebooted more than enough, hold the system here.
mbed_error_printf ( " = Reboot count(=%ld) reached maximum, system will halt after rebooting = \n " , report_error_ctx - > error_reboot_count ) ;
}
2019-01-23 23:33:10 +00:00
# endif
2018-11-13 01:37:54 +00:00
system_reset ( ) ; //do a system reset to get the system rebooted
# endif
# endif
2018-05-07 22:24:42 +00:00
mbed_halt_system ( ) ;
}
//Register an application defined callback with error handling
2018-06-27 14:09:15 +00:00
mbed_error_status_t mbed_set_error_hook ( mbed_error_hook_t error_hook_in )
2018-05-07 22:24:42 +00:00
{
//register the new hook/callback
2018-11-13 01:37:54 +00:00
if ( error_hook_in ! = NULL ) {
2018-05-07 22:24:42 +00:00
error_hook = error_hook_in ;
2018-05-21 13:57:50 +00:00
return MBED_SUCCESS ;
2018-06-27 14:09:15 +00:00
}
2018-05-21 13:57:50 +00:00
return MBED_ERROR_INVALID_ARGUMENT ;
2018-05-07 22:24:42 +00:00
}
2018-11-13 01:37:54 +00:00
//Reset the reboot error context
mbed_error_status_t mbed_reset_reboot_error_info ( )
{
# if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
2018-11-13 23:21:30 +00:00
//Protect for thread safety
core_util_critical_section_enter ( ) ;
2018-11-16 18:26:23 +00:00
memset ( report_error_ctx , 0 , sizeof ( mbed_error_ctx ) ) ;
2018-11-13 23:21:30 +00:00
core_util_critical_section_exit ( ) ;
2018-11-13 01:37:54 +00:00
# endif
2018-11-16 18:26:23 +00:00
return MBED_SUCCESS ;
2018-11-13 01:37:54 +00:00
}
//Reset the reboot error context
mbed_error_status_t mbed_reset_reboot_count ( )
{
# if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
2018-11-14 19:40:13 +00:00
if ( is_reboot_error_valid ) {
2018-11-13 01:37:54 +00:00
uint32_t crc_val = 0 ;
2018-11-13 23:21:30 +00:00
core_util_critical_section_enter ( ) ;
2018-11-13 01:37:54 +00:00
report_error_ctx - > error_reboot_count = 0 ; //Set reboot count to 0
//Update CRC
2018-11-16 18:26:23 +00:00
crc_val = compute_crc32 ( report_error_ctx , offsetof ( mbed_error_ctx , crc_error_ctx ) ) ;
2018-11-13 01:37:54 +00:00
report_error_ctx - > crc_error_ctx = crc_val ;
2018-11-13 23:21:30 +00:00
core_util_critical_section_exit ( ) ;
2018-11-13 01:37:54 +00:00
return MBED_SUCCESS ;
}
# endif
2018-11-16 18:26:23 +00:00
return MBED_ERROR_ITEM_NOT_FOUND ;
2018-11-13 01:37:54 +00:00
}
//Retrieve the reboot error context
mbed_error_status_t mbed_get_reboot_error_info ( mbed_error_ctx * error_info )
{
mbed_error_status_t status = MBED_ERROR_ITEM_NOT_FOUND ;
# if MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED
if ( is_reboot_error_valid ) {
2018-11-14 19:40:13 +00:00
if ( error_info ! = NULL ) {
2018-11-13 01:37:54 +00:00
memcpy ( error_info , report_error_ctx , sizeof ( mbed_error_ctx ) ) ;
status = MBED_SUCCESS ;
} else {
status = MBED_ERROR_INVALID_ARGUMENT ;
}
}
2018-11-16 18:26:23 +00:00
# endif
2018-11-13 01:37:54 +00:00
return status ;
}
2018-06-27 14:09:15 +00:00
//Retrieve the first error context from error log
mbed_error_status_t mbed_get_first_error_info ( mbed_error_ctx * error_info )
2018-05-07 22:24:42 +00:00
{
memcpy ( error_info , & first_error_ctx , sizeof ( first_error_ctx ) ) ;
2018-05-21 13:57:50 +00:00
return MBED_SUCCESS ;
2018-05-07 22:24:42 +00:00
}
2018-06-27 14:09:15 +00:00
//Retrieve the last error context from error log
mbed_error_status_t mbed_get_last_error_info ( mbed_error_ctx * error_info )
2018-05-07 22:24:42 +00:00
{
2018-05-12 15:26:09 +00:00
memcpy ( error_info , & last_error_ctx , sizeof ( mbed_error_ctx ) ) ;
2018-05-21 13:57:50 +00:00
return MBED_SUCCESS ;
2018-05-07 22:24:42 +00:00
}
2018-05-19 17:49:04 +00:00
//Makes an mbed_error_status_t value
2018-06-27 14:09:15 +00:00
mbed_error_status_t mbed_make_error ( mbed_error_type_t error_type , mbed_module_type_t entity , mbed_error_code_t error_code )
2018-05-07 22:24:42 +00:00
{
2018-06-27 14:09:15 +00:00
switch ( error_type ) {
2018-05-21 13:57:50 +00:00
case MBED_ERROR_TYPE_POSIX :
2018-06-27 14:09:15 +00:00
if ( error_code > = MBED_POSIX_ERROR_BASE & & error_code < = MBED_SYSTEM_ERROR_BASE ) {
2018-05-07 22:24:42 +00:00
return - error_code ;
2018-06-27 14:09:15 +00:00
}
2018-05-07 22:24:42 +00:00
break ;
2018-06-27 14:09:15 +00:00
2018-05-21 13:57:50 +00:00
case MBED_ERROR_TYPE_SYSTEM :
2018-06-27 14:09:15 +00:00
if ( error_code > = MBED_SYSTEM_ERROR_BASE & & error_code < = MBED_CUSTOM_ERROR_BASE ) {
2018-05-21 13:57:50 +00:00
return MAKE_MBED_ERROR ( MBED_ERROR_TYPE_SYSTEM , entity , error_code ) ;
2018-06-27 14:09:15 +00:00
}
2018-05-07 22:24:42 +00:00
break ;
2018-06-27 14:09:15 +00:00
2018-05-21 13:57:50 +00:00
case MBED_ERROR_TYPE_CUSTOM :
2018-06-27 14:09:15 +00:00
if ( error_code > = MBED_CUSTOM_ERROR_BASE ) {
2018-05-21 13:57:50 +00:00
return MAKE_MBED_ERROR ( MBED_ERROR_TYPE_CUSTOM , entity , error_code ) ;
2018-06-27 14:09:15 +00:00
}
2018-05-07 22:24:42 +00:00
break ;
2018-06-27 14:09:15 +00:00
2018-05-07 22:24:42 +00:00
default :
break ;
}
2018-06-27 14:09:15 +00:00
2018-05-07 22:24:42 +00:00
//If we are passed incorrect values return a generic system error
2018-05-22 17:28:57 +00:00
return MAKE_MBED_ERROR ( MBED_ERROR_TYPE_SYSTEM , MBED_MODULE_UNKNOWN , MBED_ERROR_CODE_UNKNOWN ) ;
2018-05-07 22:24:42 +00:00
}
/**
* Clears all the last error , error count and all entries in the error log .
2018-05-21 13:57:50 +00:00
* @ return 0 or MBED_SUCCESS on success .
2018-05-07 22:24:42 +00:00
*
*/
2018-06-27 14:09:15 +00:00
mbed_error_status_t mbed_clear_all_errors ( void )
2018-05-07 22:24:42 +00:00
{
2018-05-21 13:57:50 +00:00
mbed_error_status_t status = MBED_SUCCESS ;
2018-06-27 14:09:15 +00:00
2018-05-19 16:30:17 +00:00
//Make sure we dont multiple clients resetting
core_util_critical_section_enter ( ) ;
2018-05-07 22:24:42 +00:00
//Clear the error and context capturing buffer
2018-09-07 12:30:59 +00:00
memset ( & last_error_ctx , 0 , sizeof ( mbed_error_ctx ) ) ;
2018-05-07 22:24:42 +00:00
//reset error count to 0
error_count = 0 ;
2018-06-27 14:09:15 +00:00
# if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED
2018-05-23 00:25:46 +00:00
status = mbed_error_hist_reset ( ) ;
2018-05-19 16:30:17 +00:00
# endif
core_util_critical_section_exit ( ) ;
2018-06-27 14:09:15 +00:00
2018-05-07 22:24:42 +00:00
return status ;
}
2019-03-15 12:05:28 +00:00
static inline const char * name_or_unnamed ( const char * name )
2018-10-16 10:15:50 +00:00
{
return name ? name : " <unnamed> " ;
}
2018-06-11 18:26:04 +00:00
# if MBED_CONF_PLATFORM_ERROR_ALL_THREADS_INFO && defined(MBED_CONF_RTOS_PRESENT)
/* Prints info of a thread(using osRtxThread_t struct)*/
2018-10-16 10:07:31 +00:00
static void print_thread ( const osRtxThread_t * thread )
2018-06-11 18:26:04 +00:00
{
2018-09-12 09:15:51 +00:00
mbed_error_printf ( " \n %s State: 0x% " PRIX8 " Entry: 0x%08 " PRIX32 " Stack Size: 0x%08 " PRIX32 " Mem: 0x%08 " PRIX32 " SP: 0x%08 " PRIX32 , name_or_unnamed ( thread - > name ) , thread - > state , thread - > thread_addr , thread - > stack_size , ( uint32_t ) thread - > stack_mem , thread - > sp ) ;
2018-06-11 18:26:04 +00:00
}
/* Prints thread info from a list */
2018-10-16 10:07:31 +00:00
static void print_threads_info ( const osRtxThread_t * threads )
2018-06-11 18:26:04 +00:00
{
2018-06-18 16:26:48 +00:00
while ( threads ! = NULL ) {
2018-06-27 14:09:15 +00:00
print_thread ( threads ) ;
2018-06-11 18:26:04 +00:00
threads = threads - > thread_next ;
}
}
# endif
2018-07-05 16:50:49 +00:00
# ifndef NDEBUG
2018-12-21 22:17:15 +00:00
# define GET_TARGET_NAME_STR(tgt_name) #tgt_name
# define GET_TARGET_NAME(tgt_name) GET_TARGET_NAME_STR(tgt_name)
2018-11-19 02:38:18 +00:00
static void print_error_report ( const mbed_error_ctx * ctx , const char * error_msg , const char * error_filename , int error_line )
2018-06-11 18:26:04 +00:00
{
2018-09-12 09:15:51 +00:00
int error_code = MBED_GET_ERROR_CODE ( ctx - > error_status ) ;
int error_module = MBED_GET_ERROR_MODULE ( ctx - > error_status ) ;
2018-06-27 14:09:15 +00:00
2018-06-11 18:26:04 +00:00
mbed_error_printf ( " \n \n ++ MbedOS Error Info ++ \n Error Status: 0x%X Code: %d Module: %d \n Error Message: " , ctx - > error_status , error_code , error_module ) ;
2018-06-27 14:09:15 +00:00
2018-06-11 18:26:04 +00:00
switch ( error_code ) {
//These are errors reported by kernel handled from mbed_rtx_handlers
case MBED_ERROR_CODE_RTOS_EVENT :
2018-09-12 09:15:51 +00:00
mbed_error_printf ( " Kernel Error: 0x% " PRIX32 " , " , ctx - > error_value ) ;
2018-06-11 18:26:04 +00:00
break ;
2018-06-27 14:09:15 +00:00
2018-06-11 18:26:04 +00:00
case MBED_ERROR_CODE_RTOS_THREAD_EVENT :
2018-09-12 09:15:51 +00:00
mbed_error_printf ( " Thread: 0x% " PRIX32 " , " , ctx - > error_value ) ;
2018-06-11 18:26:04 +00:00
break ;
2018-06-27 14:09:15 +00:00
2018-06-11 18:26:04 +00:00
case MBED_ERROR_CODE_RTOS_MUTEX_EVENT :
2018-09-12 09:15:51 +00:00
mbed_error_printf ( " Mutex: 0x% " PRIX32 " , " , ctx - > error_value ) ;
2018-06-11 18:26:04 +00:00
break ;
2018-06-27 14:09:15 +00:00
2018-06-11 18:26:04 +00:00
case MBED_ERROR_CODE_RTOS_SEMAPHORE_EVENT :
2018-09-12 09:15:51 +00:00
mbed_error_printf ( " Semaphore: 0x% " PRIX32 " , " , ctx - > error_value ) ;
2018-06-11 18:26:04 +00:00
break ;
2018-06-27 14:09:15 +00:00
2018-06-11 18:26:04 +00:00
case MBED_ERROR_CODE_RTOS_MEMORY_POOL_EVENT :
2018-09-12 09:15:51 +00:00
mbed_error_printf ( " MemoryPool: 0x% " PRIX32 " , " , ctx - > error_value ) ;
2018-06-11 18:26:04 +00:00
break ;
2018-06-27 14:09:15 +00:00
2018-06-11 18:26:04 +00:00
case MBED_ERROR_CODE_RTOS_EVENT_FLAGS_EVENT :
2018-09-12 09:15:51 +00:00
mbed_error_printf ( " EventFlags: 0x% " PRIX32 " , " , ctx - > error_value ) ;
2018-06-11 18:26:04 +00:00
break ;
2018-06-27 14:09:15 +00:00
2018-06-11 18:26:04 +00:00
case MBED_ERROR_CODE_RTOS_TIMER_EVENT :
2018-09-12 09:15:51 +00:00
mbed_error_printf ( " Timer: 0x% " PRIX32 " , " , ctx - > error_value ) ;
2018-06-11 18:26:04 +00:00
break ;
2018-06-27 14:09:15 +00:00
case MBED_ERROR_CODE_RTOS_MESSAGE_QUEUE_EVENT :
2018-09-12 09:15:51 +00:00
mbed_error_printf ( " MessageQueue: 0x% " PRIX32 " , " , ctx - > error_value ) ;
2018-06-11 18:26:04 +00:00
break ;
2018-06-27 14:09:15 +00:00
2018-10-05 19:15:03 +00:00
case MBED_ERROR_CODE_ASSERTION_FAILED :
2018-10-09 16:49:47 +00:00
mbed_error_printf ( " Assertion failed: " ) ;
2018-10-05 19:15:03 +00:00
break ;
2018-06-11 18:26:04 +00:00
default :
//Nothing to do here, just print the error info down
break ;
}
2018-10-16 10:27:47 +00:00
mbed_error_puts ( error_msg ) ;
2018-09-12 09:15:51 +00:00
mbed_error_printf ( " \n Location: 0x% " PRIX32 , ctx - > error_address ) ;
2018-06-27 14:09:15 +00:00
2018-10-16 10:27:47 +00:00
/* We print the filename passed in, not any filename in the context. This
* avoids the console print for mbed_error being limited to the presence
* and length of the filename storage . Note that although the MBED_ERROR
* macro compiles out filenames unless platform . error - filename - capture - enabled
* is turned on , MBED_ASSERT always passes filenames , and other direct
* users of mbed_error ( ) may also choose to .
*/
if ( error_filename ) {
mbed_error_puts ( " \n File: " ) ;
mbed_error_puts ( error_filename ) ;
mbed_error_printf ( " +%d " , error_line ) ;
2018-06-11 18:26:04 +00:00
}
2018-06-27 14:09:15 +00:00
2018-09-12 09:15:51 +00:00
mbed_error_printf ( " \n Error Value: 0x% " PRIX32 , ctx - > error_value ) ;
2018-10-16 10:15:50 +00:00
# ifdef MBED_CONF_RTOS_PRESENT
2018-09-12 09:15:51 +00:00
mbed_error_printf ( " \n Current Thread: %s Id: 0x% " PRIX32 " Entry: 0x% " PRIX32 " StackSize: 0x% " PRIX32 " StackMem: 0x% " PRIX32 " SP: 0x% " PRIX32 " " ,
2018-10-16 10:15:50 +00:00
name_or_unnamed ( ( ( osRtxThread_t * ) ctx - > thread_id ) - > name ) ,
2018-06-27 14:09:15 +00:00
ctx - > thread_id , ctx - > thread_entry_address , ctx - > thread_stack_size , ctx - > thread_stack_mem , ctx - > thread_current_sp ) ;
2018-10-16 10:15:50 +00:00
# endif
2018-06-27 14:09:15 +00:00
2018-06-11 18:26:04 +00:00
# if MBED_CONF_PLATFORM_ERROR_ALL_THREADS_INFO && defined(MBED_CONF_RTOS_PRESENT)
2018-11-19 02:38:18 +00:00
mbed_error_printf ( " \n Next: " ) ;
print_thread ( osRtxInfo . thread . run . next ) ;
2018-06-27 14:09:15 +00:00
2018-11-19 02:38:18 +00:00
mbed_error_printf ( " \n Ready: " ) ;
print_threads_info ( osRtxInfo . thread . ready . thread_list ) ;
2018-10-16 10:07:31 +00:00
2018-11-19 02:38:18 +00:00
mbed_error_printf ( " \n Wait: " ) ;
print_threads_info ( osRtxInfo . thread . wait_list ) ;
2018-06-27 14:09:15 +00:00
2018-11-19 02:38:18 +00:00
mbed_error_printf ( " \n Delay: " ) ;
print_threads_info ( osRtxInfo . thread . delay_list ) ;
2018-06-11 18:26:04 +00:00
# endif
2018-12-21 22:17:15 +00:00
# if !defined(MBED_SYS_STATS_ENABLED)
mbed_error_printf ( " \n For more info, visit: https://mbed.com/s/error?error=0x%08X&tgt= " GET_TARGET_NAME ( TARGET_NAME ) , ctx - > error_status ) ;
# else
mbed_stats_sys_t sys_stats ;
mbed_stats_sys_get ( & sys_stats ) ;
2019-03-15 12:05:28 +00:00
mbed_error_printf ( " \n For more info, visit: https://mbed.com/s/error?error=0x%08X&osver=% " PRId32 " &core=0x%08 " PRIX32 " &comp=%d&ver=% " PRIu32 " &tgt= " GET_TARGET_NAME ( TARGET_NAME ) , ctx - > error_status , sys_stats . os_version , sys_stats . cpu_id , sys_stats . compiler_id , sys_stats . compiler_version ) ;
2018-12-21 22:17:15 +00:00
# endif
2018-06-11 18:26:04 +00:00
mbed_error_printf ( " \n -- MbedOS Error Info -- \n " ) ;
}
2018-07-05 16:50:49 +00:00
# endif //ifndef NDEBUG
2018-06-11 18:26:04 +00:00
2018-12-21 22:17:15 +00:00
2018-06-11 18:26:04 +00:00
# if MBED_CONF_PLATFORM_ERROR_HIST_ENABLED
2018-05-07 22:24:42 +00:00
//Retrieve the error context from error log at the specified index
2018-06-27 14:09:15 +00:00
mbed_error_status_t mbed_get_error_hist_info ( int index , mbed_error_ctx * error_info )
2018-05-07 22:24:42 +00:00
{
2018-05-23 00:25:46 +00:00
return mbed_error_hist_get ( index , error_info ) ;
2018-05-07 22:24:42 +00:00
}
//Retrieve the error log count
2018-06-27 14:09:15 +00:00
int mbed_get_error_hist_count ( void )
2018-05-07 22:24:42 +00:00
{
2018-05-23 00:25:46 +00:00
return mbed_error_hist_get_count ( ) ;
2018-05-07 22:24:42 +00:00
}
2018-05-09 19:30:20 +00:00
2018-05-23 00:25:46 +00:00
mbed_error_status_t mbed_save_error_hist ( const char * path )
2018-05-09 19:30:20 +00:00
{
2018-05-21 13:57:50 +00:00
mbed_error_status_t ret = MBED_SUCCESS ;
2018-05-09 19:30:20 +00:00
mbed_error_ctx ctx = { 0 } ;
2018-05-23 00:25:46 +00:00
int log_count = mbed_error_hist_get_count ( ) ;
2018-05-09 19:30:20 +00:00
FILE * error_log_file = NULL ;
2018-06-27 14:09:15 +00:00
2018-05-09 19:30:20 +00:00
//Ensure path is valid
2018-06-27 14:09:15 +00:00
if ( path = = NULL ) {
2018-05-22 17:28:57 +00:00
ret = MBED_MAKE_ERROR ( MBED_MODULE_PLATFORM , MBED_ERROR_CODE_INVALID_ARGUMENT ) ;
2018-05-09 19:30:20 +00:00
goto exit ;
}
2018-06-27 14:09:15 +00:00
2018-05-09 19:30:20 +00:00
//Open the file for saving the error log info
2018-06-27 14:09:15 +00:00
if ( ( error_log_file = fopen ( path , " w " ) ) = = NULL ) {
2018-05-22 17:28:57 +00:00
ret = MBED_MAKE_ERROR ( MBED_MODULE_PLATFORM , MBED_ERROR_CODE_OPEN_FAILED ) ;
2018-05-09 19:30:20 +00:00
goto exit ;
}
2018-06-27 14:09:15 +00:00
2018-05-09 19:30:20 +00:00
//First store the first and last errors
2018-06-27 14:09:15 +00:00
if ( fprintf ( error_log_file , " \n First Error: Status:0x%x ThreadId:0x%x Address:0x%x Value:0x%x \n " ,
( unsigned int ) first_error_ctx . error_status ,
( unsigned int ) first_error_ctx . thread_id ,
( unsigned int ) first_error_ctx . error_address ,
( unsigned int ) first_error_ctx . error_value ) < = 0 ) {
2018-05-22 17:28:57 +00:00
ret = MBED_MAKE_ERROR ( MBED_MODULE_PLATFORM , MBED_ERROR_CODE_WRITE_FAILED ) ;
2018-05-09 19:30:20 +00:00
goto exit ;
}
2018-06-27 14:09:15 +00:00
if ( fprintf ( error_log_file , " \n Last Error: Status:0x%x ThreadId:0x%x Address:0x%x Value:0x%x \n " ,
( unsigned int ) last_error_ctx . error_status ,
( unsigned int ) last_error_ctx . thread_id ,
( unsigned int ) last_error_ctx . error_address ,
( unsigned int ) last_error_ctx . error_value ) < = 0 ) {
2018-05-22 17:28:57 +00:00
ret = MBED_MAKE_ERROR ( MBED_MODULE_PLATFORM , MBED_ERROR_CODE_WRITE_FAILED ) ;
2018-05-09 19:30:20 +00:00
goto exit ;
}
2018-06-27 14:09:15 +00:00
2018-05-09 19:30:20 +00:00
//Update with error log info
2018-06-18 16:26:48 +00:00
while ( - - log_count > = 0 ) {
2018-05-23 00:25:46 +00:00
mbed_error_hist_get ( log_count , & ctx ) ;
2018-05-09 19:30:20 +00:00
//first line of file will be error log count
2018-06-27 14:09:15 +00:00
if ( fprintf ( error_log_file , " \n %d: Status:0x%x ThreadId:0x%x Address:0x%x Value:0x%x \n " ,
log_count ,
( unsigned int ) ctx . error_status ,
( unsigned int ) ctx . thread_id ,
( unsigned int ) ctx . error_address ,
( unsigned int ) ctx . error_value ) < = 0 ) {
2018-05-22 17:28:57 +00:00
ret = MBED_MAKE_ERROR ( MBED_MODULE_PLATFORM , MBED_ERROR_CODE_WRITE_FAILED ) ;
2018-05-09 19:30:20 +00:00
goto exit ;
}
}
2018-06-27 14:09:15 +00:00
2018-05-09 19:30:20 +00:00
exit :
fclose ( error_log_file ) ;
2018-06-27 14:09:15 +00:00
2018-05-09 19:30:20 +00:00
return ret ;
}
2018-05-07 22:24:42 +00:00
# endif