mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-01-03 06:28:27 -04:00
bb1b2dafae
a user recently had a flow of control panic in quadplane in cygwin/missionplanner SITL. The panic this caused means we don't get logging information on what line of code was triggered the panic in SITL for internal errors is only useful if you have debug information and can then attach a debugger. Without debug information it is much better to behave the same as a real vehicle and report an internal error (with line number)
137 lines
4.3 KiB
C++
137 lines
4.3 KiB
C++
#include "AP_InternalError.h"
|
|
|
|
#include <AP_BoardConfig/AP_BoardConfig.h>
|
|
#include <stdio.h>
|
|
|
|
extern const AP_HAL::HAL &hal;
|
|
|
|
// actually create the instance:
|
|
static AP_InternalError instance;
|
|
|
|
void AP_InternalError::error(const AP_InternalError::error_t e, uint16_t line) {
|
|
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL && defined(HAL_DEBUG_BUILD)
|
|
switch (e) {
|
|
case AP_InternalError::error_t::watchdog_reset:
|
|
case AP_InternalError::error_t::main_loop_stuck:
|
|
case AP_InternalError::error_t::params_restored:
|
|
// don't panic on these to facilitate watchdog testing
|
|
break;
|
|
default:
|
|
char buffer[50];
|
|
AP::internalerror().error_to_string(buffer, ARRAY_SIZE(buffer), e);
|
|
AP_HAL::panic("AP_InternalError::error_t::%s", buffer);
|
|
}
|
|
#endif
|
|
internal_errors |= uint32_t(e);
|
|
total_error_count++;
|
|
last_line = line;
|
|
|
|
hal.util->persistent_data.internal_errors = internal_errors;
|
|
hal.util->persistent_data.internal_error_count = total_error_count;
|
|
hal.util->persistent_data.internal_error_last_line = line;
|
|
}
|
|
|
|
static const char * const error_bit_descriptions[] {
|
|
"mapfailure", // logger_mapfailure
|
|
"miss_struct", // logger_missing_logstructure
|
|
"write_mssfmt", // logger_logwrite_missingfmt
|
|
"many_deletes", // logger_too_many_deletions
|
|
"bad_getfile", // logger_bad_getfilename
|
|
"panic",
|
|
"flush_no_sem", // logger_flushing_without_sem
|
|
"bad_curr_blk", // logger_bad_current_block
|
|
"blkcnt_bad", // logger_blockcount_mismatch
|
|
"dq_failure", // logger_dequeue_failure
|
|
"cnstring_nan", // constraining_nan
|
|
"watchdog_rst", // watchdog_reset
|
|
"iomcu_reset",
|
|
"iomcu_fail",
|
|
"spi_fail",
|
|
"main_loop_stk", // main_loop_stuck
|
|
"gcs_bad_link", // gcs_bad_missionprotocol_link
|
|
"bitmask_range",
|
|
"gcs_offset",
|
|
"i2c_isr",
|
|
"flow_of_ctrl", // flow_of_control
|
|
"sfs_recursion", // switch_full_sector_recursion
|
|
"bad_rotation",
|
|
"stack_ovrflw", // stack_overflow
|
|
"imu_reset", // imu_reset
|
|
"gpio_isr",
|
|
"mem_guard",
|
|
"dma_fail",
|
|
"params_restored",
|
|
"invalid arguments",
|
|
};
|
|
|
|
static_assert((1U<<(ARRAY_SIZE(error_bit_descriptions))) == uint32_t(AP_InternalError::error_t::__LAST__), "too few descriptions for bits");
|
|
|
|
void AP_InternalError::error_to_string(char *buffer, const uint16_t len, error_t error_code) const
|
|
{
|
|
uint32_t temp = log2f(int(error_code));
|
|
strncpy(buffer, error_bit_descriptions[temp], len - 1);
|
|
}
|
|
|
|
void AP_InternalError::errors_as_string(uint8_t *buffer, const uint16_t len) const
|
|
{
|
|
buffer[0] = 0;
|
|
uint32_t buffer_used = 0;
|
|
for (uint8_t i=0; i<ARRAY_SIZE(error_bit_descriptions); i++) {
|
|
if (buffer_used >= len) {
|
|
break;
|
|
}
|
|
if (internal_errors & (1U<<i)) {
|
|
const char *format;
|
|
if (buffer_used == 0) {
|
|
format = "%s";
|
|
} else {
|
|
format = ",%s";
|
|
}
|
|
const size_t written = hal.util->snprintf((char*)&buffer[buffer_used],
|
|
len-buffer_used,
|
|
format,
|
|
error_bit_descriptions[i]);
|
|
if (written <= 0) {
|
|
break;
|
|
}
|
|
buffer_used += written;
|
|
}
|
|
}
|
|
}
|
|
|
|
namespace AP {
|
|
|
|
AP_InternalError &internalerror()
|
|
{
|
|
return instance;
|
|
}
|
|
|
|
};
|
|
|
|
// stack overflow hook for low level RTOS code, C binding
|
|
void AP_stack_overflow(const char *thread_name)
|
|
{
|
|
static bool done_stack_overflow;
|
|
INTERNAL_ERROR(AP_InternalError::error_t::stack_overflow);
|
|
if (!done_stack_overflow) {
|
|
// we don't want to record the thread name more than once, as
|
|
// first overflow can trigger a 2nd
|
|
strncpy_noterm(hal.util->persistent_data.thread_name4, thread_name, 4);
|
|
done_stack_overflow = true;
|
|
}
|
|
hal.util->persistent_data.fault_type = 42; // magic value
|
|
if (!hal.util->get_soft_armed()) {
|
|
AP_HAL::panic("stack overflow %s\n", thread_name);
|
|
}
|
|
}
|
|
|
|
// hook for memory guard errors with --enable-memory-guard
|
|
void AP_memory_guard_error(uint32_t size)
|
|
{
|
|
INTERNAL_ERROR(AP_InternalError::error_t::mem_guard);
|
|
if (!hal.util->get_soft_armed()) {
|
|
::printf("memory guard error size=%u\n", unsigned(size));
|
|
AP_HAL::panic("memory guard size=%u\n", unsigned(size));
|
|
}
|
|
}
|