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)