void shutdown_worker(void *arg) { PX4_DEBUG("shutdown worker (%i)", shutdown_counter); bool done = true; pthread_mutex_lock(&shutdown_mutex); for (int i = 0; i < max_shutdown_hooks; ++i) { if (shutdown_hooks[i]) { if (!shutdown_hooks[i]()) { done = false; } } } if ((done && shutdown_lock_counter == 0) || ++shutdown_counter > shutdown_timeout_ms / 10) { if (shutdown_args & SHUTDOWN_ARG_REBOOT) { PX4_WARN("Reboot NOW."); px4_systemreset(shutdown_args & SHUTDOWN_ARG_TO_BOOTLOADER); } else { PX4_WARN("Shutdown NOW. Good Bye."); board_shutdown(); } pthread_mutex_unlock(&shutdown_mutex); // must NEVER come here } else { pthread_mutex_unlock(&shutdown_mutex); work_queue(HPWORK, &shutdown_work, (worker_t)&shutdown_worker, nullptr, USEC2TICK(10000)); } }
bool handleRestartRequest(uavcan::NodeID request_source) override { ::syslog(LOG_INFO, "UAVCAN: Restarting by request from %i\n", int(request_source.get())); ::usleep(20 * 1000 * 1000); px4_systemreset(false); return true; // Will never be executed BTW }
int px4_shutdown_request(bool reboot, bool to_bootloader) { int ret = 0; pthread_mutex_lock(&shutdown_mutex); // FIXME: if shutdown_lock_counter > 0, we should wait, but unfortunately we don't have work queues if (reboot) { px4_systemreset(to_bootloader); } else { ret = board_shutdown(); } pthread_mutex_unlock(&shutdown_mutex); return ret; }
int reboot_main(int argc, char *argv[]) { int ch; bool to_bootloader = false; int myoptind = 1; const char *myoptarg = NULL; while ((ch = px4_getopt(argc, argv, "b", &myoptind, &myoptarg)) != -1) { switch (ch) { case 'b': to_bootloader = true; break; default: PX4_ERR("usage: reboot [-b]\n" " -b reboot into the bootloader"); } } px4_systemreset(to_bootloader); }
static void cb_reboot(const uavcan::TimerEvent &) { px4_systemreset(false); }
__EXPORT void board_crashdump(uintptr_t currentsp, FAR void *tcb, FAR const uint8_t *filename, int lineno) { /* We need a chunk of ram to save the complete context in. * Since we are going to reboot we will use &_sdata * which is the lowest memory and the amount we will save * _should be_ below any resources we need herein. * Unfortunately this is hard to test. See dead below */ fullcontext_s *pdump = (fullcontext_s *)&_sdata; (void)enter_critical_section(); struct tcb_s *rtcb = (struct tcb_s *)tcb; /* Zero out everything */ memset(pdump, 0, sizeof(fullcontext_s)); /* Save Info */ pdump->info.lineno = lineno; if (filename) { int offset = 0; unsigned int len = strlen((char *)filename) + 1; if (len > sizeof(pdump->info.filename)) { offset = len - sizeof(pdump->info.filename) ; } strncpy(pdump->info.filename, (char *)&filename[offset], sizeof(pdump->info.filename)); } /* Save the value of the pointer for current_regs as debugging info. * It should be NULL in case of an ASSERT and will aid in cross * checking the validity of system memory at the time of the * fault. */ pdump->info.current_regs = (uintptr_t) CURRENT_REGS; /* Save Context */ #if CONFIG_TASK_NAME_SIZE > 0 strncpy(pdump->info.name, rtcb->name, CONFIG_TASK_NAME_SIZE); #endif pdump->info.pid = rtcb->pid; /* If current_regs is not NULL then we are in an interrupt context * and the user context is in current_regs else we are running in * the users context */ if (CURRENT_REGS) { pdump->info.stacks.interrupt.sp = currentsp; pdump->info.flags |= (eRegsPresent | eUserStackPresent | eIntStackPresent); memcpy(pdump->info.regs, (void *)CURRENT_REGS, sizeof(pdump->info.regs)); pdump->info.stacks.user.sp = pdump->info.regs[REG_R13]; } else { /* users context */ pdump->info.flags |= eUserStackPresent; pdump->info.stacks.user.sp = currentsp; } if (pdump->info.pid == 0) { pdump->info.stacks.user.top = g_idle_topstack - 4; pdump->info.stacks.user.size = CONFIG_IDLETHREAD_STACKSIZE; } else { pdump->info.stacks.user.top = (uint32_t) rtcb->adj_stack_ptr; pdump->info.stacks.user.size = (uint32_t) rtcb->adj_stack_size;; } #if CONFIG_ARCH_INTERRUPTSTACK > 3 /* Get the limits on the interrupt stack memory */ pdump->info.stacks.interrupt.top = (uint32_t)&g_intstackbase; pdump->info.stacks.interrupt.size = (CONFIG_ARCH_INTERRUPTSTACK & ~3); /* If In interrupt Context save the interrupt stack data centered * about the interrupt stack pointer */ if ((pdump->info.flags & eIntStackPresent) != 0) { stack_word_t *ps = (stack_word_t *) pdump->info.stacks.interrupt.sp; copy_reverse(pdump->istack, &ps[arraySize(pdump->istack) / 2], arraySize(pdump->istack)); } /* Is it Invalid? */ if (!(pdump->info.stacks.interrupt.sp <= pdump->info.stacks.interrupt.top && pdump->info.stacks.interrupt.sp > pdump->info.stacks.interrupt.top - pdump->info.stacks.interrupt.size)) { pdump->info.flags |= eInvalidIntStackPrt; } #endif /* If In interrupt context or User save the user stack data centered * about the user stack pointer */ if ((pdump->info.flags & eUserStackPresent) != 0) { stack_word_t *ps = (stack_word_t *) pdump->info.stacks.user.sp; copy_reverse(pdump->ustack, &ps[arraySize(pdump->ustack) / 2], arraySize(pdump->ustack)); } /* Is it Invalid? */ if (!(pdump->info.stacks.user.sp <= pdump->info.stacks.user.top && pdump->info.stacks.user.sp > pdump->info.stacks.user.top - pdump->info.stacks.user.size)) { pdump->info.flags |= eInvalidUserStackPtr; } int rv = stm32_bbsram_savepanic(HARDFAULT_FILENO, (uint8_t *)pdump, sizeof(fullcontext_s)); /* Test if memory got wiped because of using _sdata */ if (rv == -ENXIO) { char *dead = "Memory wiped - dump not saved!"; while (*dead) { up_lowputc(*dead++); } } else if (rv == -ENOSPC) { /* hard fault again */ up_lowputc('!'); } #if defined(CONFIG_BOARD_RESET_ON_CRASH) px4_systemreset(false); #endif }
int test_mount(int argc, char *argv[]) { const unsigned iterations = 2000; const unsigned alignments = 10; const char *cmd_filename = "/fs/microsd/mount_test_cmds.txt"; /* check if microSD card is mounted */ struct stat buffer; if (stat(PX4_ROOTFSDIR "/fs/microsd/", &buffer)) { PX4_ERR("no microSD card mounted, aborting file test"); return 1; } /* list directory */ DIR *d; struct dirent *dir; d = opendir(PX4_ROOTFSDIR "/fs/microsd"); if (d) { while ((dir = readdir(d)) != NULL) { //printf("%s\n", dir->d_name); } closedir(d); PX4_INFO("directory listing ok (FS mounted and readable)"); } else { /* failed opening dir */ PX4_ERR("FAILED LISTING MICROSD ROOT DIRECTORY"); if (stat(cmd_filename, &buffer) == OK) { (void)unlink(cmd_filename); } return 1; } /* read current test status from file, write test instructions for next round */ /* initial values */ int it_left_fsync = fsync_tries; int it_left_abort = abort_tries; int cmd_fd; if (stat(cmd_filename, &buffer) == OK) { /* command file exists, read off state */ cmd_fd = open(cmd_filename, O_RDWR | O_NONBLOCK); char buf[64]; int ret = read(cmd_fd, buf, sizeof(buf)); if (ret > 0) { int count = 0; ret = sscanf(buf, "TEST: %u %u %n", &it_left_fsync, &it_left_abort, &count); } else { buf[0] = '\0'; } if (it_left_fsync > fsync_tries) { it_left_fsync = fsync_tries; } if (it_left_abort > abort_tries) { it_left_abort = abort_tries; } PX4_INFO("Iterations left: #%d / #%d of %d / %d\n(%s)", it_left_fsync, it_left_abort, fsync_tries, abort_tries, buf); int it_left_fsync_prev = it_left_fsync; /* now write again what to do next */ if (it_left_fsync > 0) { it_left_fsync--; } if (it_left_fsync == 0 && it_left_abort > 0) { it_left_abort--; /* announce mode switch */ if (it_left_fsync_prev != it_left_fsync && it_left_fsync == 0) { PX4_INFO("\n SUCCESSFULLY PASSED FSYNC'ED WRITES, CONTINUTING WITHOUT FSYNC"); fsync(fileno(stdout)); fsync(fileno(stderr)); usleep(20000); } } if (it_left_abort == 0) { (void)unlink(cmd_filename); return 0; } } else { /* this must be the first iteration, do something */ cmd_fd = open(cmd_filename, O_TRUNC | O_WRONLY | O_CREAT, PX4_O_MODE_666); PX4_INFO("First iteration of file test\n"); } char buf[64]; (void)sprintf(buf, "TEST: %d %d ", it_left_fsync, it_left_abort); lseek(cmd_fd, 0, SEEK_SET); write(cmd_fd, buf, strlen(buf) + 1); fsync(cmd_fd); /* perform tests for a range of chunk sizes */ unsigned chunk_sizes[] = {32, 64, 128, 256, 512, 600, 1200}; for (unsigned c = 0; c < (sizeof(chunk_sizes) / sizeof(chunk_sizes[0])); c++) { printf("\n\n====== FILE TEST: %u bytes chunks (%s) ======\n", chunk_sizes[c], (it_left_fsync > 0) ? "FSYNC" : "NO FSYNC"); printf("unpower the system immediately (within 0.5s) when the hash (#) sign appears\n"); fsync(fileno(stdout)); fsync(fileno(stderr)); usleep(50000); for (unsigned a = 0; a < alignments; a++) { printf("."); uint8_t write_buf[chunk_sizes[c] + alignments] __attribute__((aligned(64))); /* fill write buffer with known values */ for (unsigned i = 0; i < sizeof(write_buf); i++) { /* this will wrap, but we just need a known value with spacing */ write_buf[i] = i + 11; } uint8_t read_buf[chunk_sizes[c] + alignments] __attribute__((aligned(64))); int fd = px4_open(PX4_ROOTFSDIR "/fs/microsd/testfile", O_TRUNC | O_WRONLY | O_CREAT); for (unsigned i = 0; i < iterations; i++) { int wret = write(fd, write_buf + a, chunk_sizes[c]); if (wret != (int)chunk_sizes[c]) { PX4_ERR("WRITE ERROR!"); if ((0x3 & (uintptr_t)(write_buf + a))) { PX4_ERR("memory is unaligned, align shift: %d", a); } return 1; } if (it_left_fsync > 0) { fsync(fd); } else { printf("#"); fsync(fileno(stdout)); fsync(fileno(stderr)); } } if (it_left_fsync > 0) { printf("#"); } printf("."); fsync(fileno(stdout)); fsync(fileno(stderr)); usleep(200000); px4_close(fd); fd = px4_open(PX4_ROOTFSDIR "/fs/microsd/testfile", O_RDONLY); /* read back data for validation */ for (unsigned i = 0; i < iterations; i++) { int rret = read(fd, read_buf, chunk_sizes[c]); if (rret != (int)chunk_sizes[c]) { PX4_ERR("READ ERROR!"); return 1; } /* compare value */ bool compare_ok = true; for (unsigned j = 0; j < chunk_sizes[c]; j++) { if (read_buf[j] != write_buf[j + a]) { PX4_WARN("COMPARISON ERROR: byte %d, align shift: %d", j, a); compare_ok = false; break; } } if (!compare_ok) { PX4_ERR("ABORTING FURTHER COMPARISON DUE TO ERROR"); return 1; } } int ret = unlink(PX4_ROOTFSDIR "/fs/microsd/testfile"); px4_close(fd); if (ret) { px4_close(cmd_fd); PX4_ERR("UNLINKING FILE FAILED"); return 1; } } } fsync(fileno(stdout)); fsync(fileno(stderr)); usleep(20000); px4_close(cmd_fd); /* we always reboot for the next test if we get here */ PX4_INFO("Iteration done, rebooting.."); fsync(fileno(stdout)); fsync(fileno(stderr)); usleep(50000); px4_systemreset(false); /* never going to get here */ return 0; }