39 #include <px4_platform_common/px4_config.h> 40 #include <px4_platform_common/module.h> 41 #include <nuttx/compiler.h> 42 #include <nuttx/arch.h> 44 #include <sys/ioctl.h> 56 #include <stm32_bbsram.h> 71 #define OUT_BUFFER_LEN 200 99 uint32_t *pCCR = (uint32_t *)0xE000ED14;
101 static volatile int k = 0;
139 static int format_fault_time(
char *format,
struct timespec *ts,
char *buffer,
unsigned int maxsz)
143 if (buffer != NULL && format != NULL) {
148 time_t time_sec = ts->tv_sec + (ts->tv_nsec / 1e9);
149 gmtime_r(&time_sec, &tt);
151 if (
TIME_FMT_LEN == strftime(buffer, maxsz, format, &tt)) {
180 int n = snprintf(&buffer[plen], maxsz,
LOG_NAME_FMT, fmtbuff);
198 syslog(LOG_INFO,
"[%s] ", caller);
214 syslog(LOG_INFO,
"Failed to open Fault Log file [%s] (%d)\n",
HARDFAULT_PATH, fd);
219 int rv = ioctl(fd, PX4_BBSRAM_GETDESC_IOCTL, (
unsigned long)((uintptr_t)desc));
226 syslog(LOG_INFO,
"Failed to get Fault Log descriptor (%d)\n", rv);
237 char *buffer,
int max,
int fd)
241 uint32_t sbot = si->
top - si->
size;
242 n = snprintf(&buffer[n], max - n,
" %s stack: \n", sp_name);
243 n += snprintf(&buffer[n], max - n,
" top: 0x%08x\n", si->
top);
244 n += snprintf(&buffer[n], max - n,
" sp: 0x%08x %s\n", si->
sp, (inValid ?
"Invalid" :
"Valid"));
246 if (n !=
write(fd, buffer, n)) {
251 n += snprintf(&buffer[n], max - n,
" bottom: 0x%08x\n", sbot);
252 n += snprintf(&buffer[n], max - n,
" size: 0x%08x\n", si->
size);
254 if (n !=
write(fd, buffer, n)) {
258 #ifdef CONFIG_STACK_COLORATION 259 FAR
struct tcb_s tcb;
260 tcb.stack_alloc_ptr = (
void *) sbot;
261 tcb.adj_stack_size = si->
size;
262 n = snprintf(buffer, max,
" used: %08x\n", up_check_tcbstack(&tcb));
264 if (n !=
write(fd, buffer, n)) {
285 static int write_stack(
bool inValid,
int winsize, uint32_t wtopaddr,
286 uint32_t topaddr, uint32_t spaddr, uint32_t botaddr,
287 char *sp_name,
char *buffer,
int max,
int infd,
int outfd)
293 int n = snprintf(buffer, max,
"%s memory region, stack pointer lies %s stack\n",
294 sp_name, (inValid ?
"outside of" :
"within"));
296 if (n !=
write(outfd, buffer, n)) {
302 while (winsize > 0 && ret ==
OK) {
311 for (
int i = 0; i < chunk; i++) {
312 if (wtopaddr == topaddr) {
313 strncpy(marker,
"<-- ",
sizeof(marker));
314 strncat(marker, sp_name,
sizeof(marker) - 1);
315 strncat(marker,
" top",
sizeof(marker) - 1);
317 }
else if (wtopaddr == spaddr) {
318 strncpy(marker,
"<-- ",
sizeof(marker));
319 strncat(marker, sp_name,
sizeof(marker) - 1);
321 }
else if (wtopaddr == botaddr) {
322 strncpy(marker,
"<-- ",
sizeof(marker));
323 strncat(marker, sp_name,
sizeof(marker) - 1);
324 strncat(marker,
" bottom",
sizeof(marker) - 1);
330 n = snprintf(buffer, max,
"0x%08x 0x%08x%s\n", wtopaddr, stack[i], marker);
332 if (n !=
write(outfd, buffer, n)) {
350 int n = snprintf(buffer, max,
" r0:0x%08x r1:0x%08x r2:0x%08x r3:0x%08x r4:0x%08x r5:0x%08x r6:0x%08x r7:0x%08x\n",
351 regs[REG_R0], regs[REG_R1],
352 regs[REG_R2], regs[REG_R3],
353 regs[REG_R4], regs[REG_R5],
354 regs[REG_R6], regs[REG_R7]);
356 if (n !=
write(fd, buffer, n)) {
360 n = snprintf(buffer, max,
" r8:0x%08x r9:0x%08x r10:0x%08x r11:0x%08x r12:0x%08x sp:0x%08x lr:0x%08x pc:0x%08x\n",
361 regs[REG_R8], regs[REG_R9],
362 regs[REG_R10], regs[REG_R11],
363 regs[REG_R12], regs[REG_R13],
364 regs[REG_R14], regs[REG_R15]);
366 if (n !=
write(fd, buffer, n)) {
370 #ifdef CONFIG_ARMV7M_USEBASEPRI 371 n = snprintf(buffer, max,
" xpsr:0x%08x basepri:0x%08x control:0x%08x\n",
372 regs[REG_XPSR], regs[REG_BASEPRI],
375 n = snprintf(buffer, max,
" xpsr:0x%08x primask:0x%08x control:0x%08x\n",
376 regs[REG_XPSR], regs[REG_PRIMASK],
380 if (n !=
write(fd, buffer, n)) {
384 #ifdef REG_EXC_RETURN 385 n = snprintf(buffer, max,
" exe return:0x%08x\n", regs[REG_EXC_RETURN]);
387 if (n !=
write(fd, buffer, n)) {
404 int n = snprintf(buffer, sz,
" Processor registers: from 0x%08x\n", pi->
current_regs);
406 if (n ==
write(fdout, buffer, n)) {
424 &pi->
stacks.interrupt,
"IRQ",
451 char *buffer,
unsigned int sz)
458 n = snprintf(buffer, sz,
"System fault Occurred on: %s\n", fmtbuff);
460 if (n !=
write(fdout, buffer, n)) {
465 n = snprintf(buffer, sz,
" Type:Hard Fault");
468 n = snprintf(buffer, sz,
" Type:Assertion failed");
471 if (n !=
write(fdout, buffer, n)) {
475 #ifdef CONFIG_TASK_NAME_SIZE 476 n = snprintf(buffer, sz,
" in file:%s at line: %d running task: %s\n",
479 n = snprintf(buffer, sz,
" in file:%s at line: %d \n",
483 if (n !=
write(fdout, buffer, n)) {
489 if (n !=
write(fdout, buffer, n)) {
493 n = snprintf(buffer, sz,
" Build datetime: %s %s\n", __DATE__, __TIME__);
495 if (n !=
write(fdout, buffer, n)) {
499 n = snprintf(buffer, sz,
" Build url: %s \n",
px4_build_uri());
501 if (n !=
write(fdout, buffer, n)) {
512 struct timespec *ts,
char *buffer,
unsigned int sz)
517 int n = snprintf(buffer, sz,
"[%s] -- %s %s Fault Log --\n", caller, fmtbuff, tag);
519 if (n !=
write(fdout, buffer, n)) {
529 char *buffer,
unsigned int sz)
537 char *buffer,
unsigned int sz)
557 "Interrupt sp", buffer, sz, fdin, fdout);
580 "User sp", buffer, sz, fdin, fdout);
596 int write_size_remaining = lseek(fdin, 0, SEEK_END);
598 if (write_size_remaining < 0) {
602 lseek(fdin, 0, SEEK_SET);
620 if (strlen(ulog_file_name) == 0) {
625 syslog(LOG_INFO,
"Appending to ULog %s\n", ulog_file_name);
630 if (stat(ulog_file_name, &st) == -1) {
634 const off_t ulog_file_size = st.st_size;
637 int ulog_fd = open(ulog_file_name, O_RDWR);
655 if (
read(ulog_fd, chunk, 8) != 8) {
657 syslog(LOG_INFO,
"Reading ULog header failed\n");
661 if (memcmp(magic, chunk, 7) != 0) {
666 const int flag_offset = 16 + 3 + 8;
667 lseek(ulog_fd, flag_offset, SEEK_SET);
669 if (
read(ulog_fd, chunk, 1) != 1) {
675 lseek(ulog_fd, flag_offset, SEEK_SET);
677 if (
write(ulog_fd, chunk, 1) != 1) {
683 const int append_file_offset = 16 + 3 + 8 + 8;
686 for (
int i = 0; i < 3; ++i) {
687 int current_offset = append_file_offset + i * 8;
688 lseek(ulog_fd, current_offset, SEEK_SET);
691 if (
read(ulog_fd, &offset,
sizeof(offset)) !=
sizeof(offset)) {
697 lseek(ulog_fd, current_offset, SEEK_SET);
698 offset = ulog_file_size;
700 if (
write(ulog_fd, &offset,
sizeof(offset)) !=
sizeof(offset)) {
712 syslog(LOG_ERR,
"Cannot append more data to ULog (no offsets left)\n");
719 lseek(ulog_fd, 0, SEEK_END);
721 const int max_bytes_to_write = (1 << 16) - 100;
722 uint8_t is_continued = 0;
724 while (write_size_remaining > 0) {
725 int bytes_to_write = write_size_remaining;
727 if (bytes_to_write > max_bytes_to_write) {
728 bytes_to_write = max_bytes_to_write;
732 chunk[3] = is_continued;
734 const int key_len = snprintf((
char *)chunk + 5,
sizeof(chunk) - 5,
"char[%i] hardfault_plain", bytes_to_write);
736 const uint16_t ulog_msg_len = bytes_to_write + key_len + 5 - 3;
737 memcpy(chunk, &ulog_msg_len,
sizeof(uint16_t));
739 if (
write(ulog_fd, chunk, key_len + 5) != key_len + 5) {
746 while (bytes_to_write > 0) {
748 int max_read =
sizeof(chunk);
750 if (max_read > bytes_to_write) {
751 max_read = bytes_to_write;
754 num_read =
read(fdin, chunk, max_read);
758 syslog(LOG_ERR,
"read() failed: %i, %i\n", num_read, errno);
763 ret =
write(ulog_fd, chunk, num_read);
765 if (ret != num_read) {
770 bytes_to_write -= num_read;
771 write_size_remaining -= num_read;
791 struct bbsramd_s desc;
798 state = (desc.lastwrite.tv_sec || desc.lastwrite.tv_nsec) ?
OK : 1;
803 syslog(LOG_INFO,
"Failed to Close Fault Log (%d)\n", rv);
809 syslog(LOG_INFO,
"Nothing to save\n", path);
816 int fdout = open(path, O_RDWR | O_CREAT);
820 syslog(LOG_INFO,
"Saving Fault Log file %s\n", path);
823 syslog(LOG_INFO,
"Done saving Fault Log file\n");
834 syslog(LOG_INFO,
"Successfully appended to ULog\n");
838 syslog(LOG_INFO,
"No ULog to append to\n");
843 syslog(LOG_INFO,
"Failed to append to ULog (%i)\n", ret);
863 struct bbsramd_s *desc,
int format)
877 syslog(LOG_INFO,
"Failed to read Fault Log file [%s] (%d)\n",
HARDFAULT_PATH, ret);
971 syslog(LOG_INFO,
"Failed to re arming Fault Log (%d)\n", rv);
976 syslog(LOG_INFO,
"Fault Log is Armed\n");
988 struct bbsramd_s desc;
994 if (ret == -ENOENT) {
995 syslog(LOG_INFO,
"Fault Log is Armed\n");
998 syslog(LOG_INFO,
"Failed to open Fault Log file [%s] (%d)\n",
HARDFAULT_PATH, ret);
1003 state = (desc.lastwrite.tv_sec || desc.lastwrite.tv_nsec) ?
OK : 1;
1008 syslog(LOG_INFO,
"Failed to Close Fault Log (%d)\n", rv);
1013 syslog(LOG_INFO,
"Fault Log info File No %d Length %d flags:0x%02x state:%d\n",
1014 (
unsigned int)desc.fileno, (
unsigned int) desc.len, (
unsigned int)desc.flags, state);
1020 syslog(LOG_INFO,
"Fault Logged on %s - Valid\n", buf);
1053 if (
read(fd, &count,
sizeof(count)) !=
sizeof(count)) {
1058 lseek(fd, 0, SEEK_SET);
1064 ret =
write(fd, &count,
sizeof(count));
1066 if (ret !=
sizeof(count)) {
1087 struct bbsramd_s desc;
1111 syslog(LOG_INFO,
"Failed to Close Fault Log (%d)\n", ret);
1115 if (rv ==
OK && rearm) {
1120 syslog(LOG_INFO,
"Failed to re-arm Fault Log (%d)\n", ret);
1130 syslog(LOG_INFO,
"Failed to Write Fault Log (%d)\n", ret);
1139 PRINT_MODULE_DESCRIPTION(
"Hardfault utility\n" 1141 "Used in startup scripts to handle hardfaults\n" 1145 PRINT_MODULE_USAGE_NAME(
"hardfault_log",
"command");
1146 PRINT_MODULE_USAGE_COMMAND_DESCR(
"check",
"Check if there's an uncommited hardfault");
1147 PRINT_MODULE_USAGE_COMMAND_DESCR(
"rearm",
"Drop an uncommited hardfault");
1149 PRINT_MODULE_USAGE_COMMAND_DESCR(
"fault",
"Generate a hardfault (this command crashes the system :)");
1150 PRINT_MODULE_USAGE_ARG(
"0|1",
"Hardfault type: 0=divide by 0, 1=Assertion (default=0)",
true);
1152 PRINT_MODULE_USAGE_COMMAND_DESCR(
"commit",
1153 "Write uncommited hardfault to /fs/microsd/fault_%i.txt (and rearm, but don't reset)");
1154 PRINT_MODULE_USAGE_COMMAND_DESCR(
"count",
1155 "Read the reboot counter, counts the number of reboots of an uncommited hardfault (returned as the exit code of the program)");
1156 PRINT_MODULE_USAGE_COMMAND_DESCR(
"reset",
"Reset the reboot counter");
1164 char *
self =
"hardfault_log";
1171 if (!strcmp(argv[1],
"check")) {
1175 }
else if (!strcmp(argv[1],
"rearm")) {
1179 }
else if (!strcmp(argv[1],
"fault")) {
1184 fault = atol(argv[2]);
1189 }
else if (!strcmp(argv[1],
"commit")) {
1193 }
else if (!strcmp(argv[1],
"count")) {
1197 }
else if (!strcmp(argv[1],
"reset")) {
static int write_user_stack_info(int fdout, info_s *pi, char *buffer, unsigned int sz)
CCASSERT(TIME_FMT_LEN==HEADER_TIME_FMT_LEN)
static int read_stack(int fd, stack_word_t *words, int num)
#define HARDFAULT_FILE_FORMAT
__EXPORT int hardfault_rearm(char *caller)
static int write_stack(bool inValid, int winsize, uint32_t wtopaddr, uint32_t topaddr, uint32_t spaddr, uint32_t botaddr, char *sp_name, char *buffer, int max, int infd, int outfd)
static int write_dump_info(int fdout, info_s *info, struct bbsramd_s *desc, char *buffer, unsigned int sz)
static int write_stack_detail(bool inValid, _stack_s *si, char *sp_name, char *buffer, int max, int fd)
#define HARDFAULT_ULOG_PATH
#define HARDFAULT_MAX_ULOG_FILE_LEN
int info()
Print a little info about the driver.
A set of useful macros for enhanced runtime and compile time error detection and warning suppression...
#define HEADER_TIME_FMT_LEN
int reset(enum LPS22HB_BUS busid)
Reset the driver.
#define CONFIG_ISTACK_SIZE
static int hardfault_dowrite(char *caller, int infd, int outfd, struct bbsramd_s *desc, int format)
static int write_registers_info(int fdout, info_s *pi, char *buffer, int sz)
static void read(bootloader_app_shared_t *pshared)
static int hardfault_commit(char *caller)
static int format_fault_file_name(struct timespec *ts, char *buffer, unsigned int maxsz)
static int genfault(int fault)
#define LOG_PATH_BASE_LEN
static int format_fault_time(char *format, struct timespec *ts, char *buffer, unsigned int maxsz)
static int write_dump_footer(char *caller, int fdout, struct timespec *ts, char *buffer, unsigned int sz)
static void print_usage(void)
static int hardfault_get_desc(char *caller, struct bbsramd_s *desc, bool silent)
#define HARDFAULT_DISPLAY_FORMAT
__EXPORT int hardfault_log_main(int argc, char *argv[])
#define HARDFAULT_REBOOT_PATH
const char * px4_firmware_version_string(void)
Firmware version as human readable string (git tag)
const char * px4_build_uri(void)
get the build URI (used for crash logging)
Tools for system version detection.
static void write(bootloader_app_shared_t *pshared)
__EXPORT int hardfault_check_status(char *caller)
constexpr _Tp max(_Tp a, _Tp b)
uint32_t regs[XCPTCONTEXT_REGS]
static int write_interrupt_stack_info(int fdout, info_s *pi, char *buffer, unsigned int sz)
__EXPORT int hardfault_increment_reboot(char *caller, bool reset)
static int write_user_stack(int fdin, int fdout, info_s *pi, char *buffer, unsigned int sz)
static void identify(const char *caller)
static int write_dump_header(char *caller, int fdout, struct timespec *ts, char *buffer, unsigned int sz)
static int write_intterupt_stack(int fdin, int fdout, info_s *pi, char *buffer, unsigned int sz)
static int hardfault_append_to_ulog(const char *caller, int fdin)
Append hardfault data to the stored ULog file (the log path is stored in BBSRAM). ...
char filename[MAX_FILE_PATH_LENGTH]
static int write_registers(uint32_t regs[], char *buffer, int max, int fd)
#define CONFIG_USTACK_SIZE
__EXPORT int hardfault_write(char *caller, int fd, int format, bool rearm)
static int write_dump_time(char *caller, char *tag, int fdout, struct timespec *ts, char *buffer, unsigned int sz)