aboutsummaryrefslogtreecommitdiff
path: root/src/modules/sdlog2/sdlog2.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/sdlog2/sdlog2.c')
-rw-r--r--src/modules/sdlog2/sdlog2.c181
1 files changed, 130 insertions, 51 deletions
diff --git a/src/modules/sdlog2/sdlog2.c b/src/modules/sdlog2/sdlog2.c
index 0a8564da6..abc69a4b5 100644
--- a/src/modules/sdlog2/sdlog2.c
+++ b/src/modules/sdlog2/sdlog2.c
@@ -1,6 +1,6 @@
/****************************************************************************
*
- * Copyright (c) 2012-2014 PX4 Development Team. All rights reserved.
+ * Copyright (c) 2012-2015 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -39,12 +39,14 @@
*
* @author Lorenz Meier <lm@inf.ethz.ch>
* @author Anton Babushkin <anton.babushkin@me.com>
+ * @author Ban Siesta <bansiesta@gmail.com>
*/
#include <nuttx/config.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/prctl.h>
+#include <sys/statfs.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
@@ -57,6 +59,7 @@
#include <unistd.h>
#include <drivers/drv_hrt.h>
#include <math.h>
+#include <time.h>
#include <drivers/drv_range_finder.h>
@@ -103,6 +106,8 @@
#include "sdlog2_format.h"
#include "sdlog2_messages.h"
+#define PX4_EPOCH_SECS 1234567890ULL
+
/**
* Logging rate.
*
@@ -158,7 +163,9 @@ static const int MIN_BYTES_TO_WRITE = 512;
static bool _extended_logging = false;
-static const char *log_root = "/fs/microsd/log";
+#define MOUNTPOINT "/fs/microsd"
+static const char *mountpoint = MOUNTPOINT;
+static const char *log_root = MOUNTPOINT "/log";
static int mavlink_fd = -1;
struct logbuffer_s lb;
@@ -171,6 +178,7 @@ static char log_dir[32];
/* statistics counters */
static uint64_t start_time = 0;
static unsigned long log_bytes_written = 0;
+static unsigned long last_checked_bytes_written = 0;
static unsigned long log_msgs_written = 0;
static unsigned long log_msgs_skipped = 0;
@@ -185,6 +193,9 @@ static bool log_name_timestamp = false;
/* helper flag to track system state changes */
static bool flag_system_armed = false;
+/* flag if warning about MicroSD card being almost full has already been sent */
+static bool space_warning_sent = false;
+
static pthread_t logwriter_pthread = 0;
static pthread_attr_t logwriter_attr;
@@ -244,6 +255,11 @@ static bool file_exist(const char *filename);
static int file_copy(const char *file_old, const char *file_new);
+/**
+ * Check if there is still free space available
+ */
+static int check_free_space(void);
+
static void handle_command(struct vehicle_command_s *cmd);
static void handle_status(struct vehicle_status_s *cmd);
@@ -338,13 +354,16 @@ int create_log_dir()
uint16_t dir_number = 1; // start with dir sess001
int mkdir_ret;
- if (log_name_timestamp && gps_time != 0) {
- /* use GPS date for log dir naming: e.g. /fs/microsd/2014-01-19 */
- time_t gps_time_sec = gps_time / 1000000;
- struct tm t;
- gmtime_r(&gps_time_sec, &t);
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ /* use RTC time for log file naming, e.g. /fs/microsd/2014-01-19/19_37_52.px4log */
+ time_t utc_time_sec = ts.tv_sec + (ts.tv_nsec / 1e9);
+ struct tm tt;
+ struct tm *ttp = gmtime_r(&utc_time_sec, &tt);
+
+ if (log_name_timestamp && ttp && (utc_time_sec > PX4_EPOCH_SECS)) {
int n = snprintf(log_dir, sizeof(log_dir), "%s/", log_root);
- strftime(log_dir + n, sizeof(log_dir) - n, "%Y-%m-%d", &t);
+ strftime(log_dir + n, sizeof(log_dir) - n, "%Y-%m-%d", &tt);
mkdir_ret = mkdir(log_dir, S_IRWXU | S_IRWXG | S_IRWXO);
if (mkdir_ret == OK) {
@@ -384,8 +403,7 @@ int create_log_dir()
}
/* print logging path, important to find log file later */
- warnx("log dir: %s", log_dir);
- mavlink_log_info(mavlink_fd, "[sdlog2] log dir: %s", log_dir);
+ mavlink_and_console_log_info(mavlink_fd, "[sdlog2] log dir: %s", log_dir);
return 0;
}
@@ -395,12 +413,16 @@ int open_log_file()
char log_file_name[32] = "";
char log_file_path[64] = "";
- if (log_name_timestamp && gps_time != 0) {
- /* use GPS time for log file naming, e.g. /fs/microsd/2014-01-19/19_37_52.bin */
- time_t gps_time_sec = gps_time / 1000000;
- struct tm t;
- gmtime_r(&gps_time_sec, &t);
- strftime(log_file_name, sizeof(log_file_name), "%H_%M_%S.bin", &t);
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ /* use RTC time for log file naming, e.g. /fs/microsd/2014-01-19/19_37_52.px4log */
+ time_t utc_time_sec = ts.tv_sec + (ts.tv_nsec / 1e9);
+ struct tm tt;
+ struct tm *ttp = gmtime_r(&utc_time_sec, &tt);
+
+ /* start logging if we have a valid time and the time is not in the past */
+ if (log_name_timestamp && ttp && (utc_time_sec > PX4_EPOCH_SECS)) {
+ strftime(log_file_name, sizeof(log_file_name), "%H_%M_%S.px4log", &tt);
snprintf(log_file_path, sizeof(log_file_path), "%s/%s", log_dir, log_file_name);
} else {
@@ -408,8 +430,8 @@ int open_log_file()
/* look for the next file that does not exist */
while (file_number <= MAX_NO_LOGFILE) {
- /* format log file path: e.g. /fs/microsd/sess001/log001.bin */
- snprintf(log_file_name, sizeof(log_file_name), "log%03u.bin", file_number);
+ /* format log file path: e.g. /fs/microsd/sess001/log001.px4log */
+ snprintf(log_file_name, sizeof(log_file_name), "log%03u.px4log", file_number);
snprintf(log_file_path, sizeof(log_file_path), "%s/%s", log_dir, log_file_name);
if (!file_exist(log_file_path)) {
@@ -421,7 +443,7 @@ int open_log_file()
if (file_number > MAX_NO_LOGFILE) {
/* we should not end up here, either we have more than MAX_NO_LOGFILE on the SD card, or another problem */
- mavlink_log_critical(mavlink_fd, "[sdlog2] ERR: max files %d", MAX_NO_LOGFILE);
+ mavlink_and_console_log_critical(mavlink_fd, "[sdlog2] ERR: max files %d", MAX_NO_LOGFILE);
return -1;
}
}
@@ -429,12 +451,10 @@ int open_log_file()
int fd = open(log_file_path, O_CREAT | O_WRONLY | O_DSYNC);
if (fd < 0) {
- warn("failed opening log: %s", log_file_name);
- mavlink_log_critical(mavlink_fd, "[sdlog2] failed opening log: %s", log_file_name);
+ mavlink_and_console_log_critical(mavlink_fd, "[sdlog2] failed opening log: %s", log_file_name);
} else {
- warnx("log file: %s", log_file_name);
- mavlink_log_info(mavlink_fd, "[sdlog2] log file: %s", log_file_name);
+ mavlink_and_console_log_info(mavlink_fd, "[sdlog2] log file: %s", log_file_name);
}
return fd;
@@ -446,12 +466,15 @@ int open_perf_file(const char* str)
char log_file_name[32] = "";
char log_file_path[64] = "";
- if (log_name_timestamp && gps_time != 0) {
- /* use GPS time for log file naming, e.g. /fs/microsd/2014-01-19/19_37_52.bin */
- time_t gps_time_sec = gps_time / 1000000;
- struct tm t;
- gmtime_r(&gps_time_sec, &t);
- strftime(log_file_name, sizeof(log_file_name), "perf%H_%M_%S.txt", &t);
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ /* use RTC time for log file naming, e.g. /fs/microsd/2014-01-19/19_37_52.txt */
+ time_t utc_time_sec = ts.tv_sec + (ts.tv_nsec / 1e9);
+ struct tm tt;
+ struct tm *ttp = gmtime_r(&utc_time_sec, &tt);
+
+ if (log_name_timestamp && ttp && (utc_time_sec > PX4_EPOCH_SECS)) {
+ strftime(log_file_name, sizeof(log_file_name), "perf%H_%M_%S.txt", &tt);
snprintf(log_file_path, sizeof(log_file_path), "%s/%s_%s", log_dir, str, log_file_name);
} else {
@@ -459,7 +482,7 @@ int open_perf_file(const char* str)
/* look for the next file that does not exist */
while (file_number <= MAX_NO_LOGFILE) {
- /* format log file path: e.g. /fs/microsd/sess001/log001.bin */
+ /* format log file path: e.g. /fs/microsd/sess001/log001.txt */
snprintf(log_file_name, sizeof(log_file_name), "perf%03u.txt", file_number);
snprintf(log_file_path, sizeof(log_file_path), "%s/%s_%s", log_dir, str, log_file_name);
@@ -472,7 +495,7 @@ int open_perf_file(const char* str)
if (file_number > MAX_NO_LOGFILE) {
/* we should not end up here, either we have more than MAX_NO_LOGFILE on the SD card, or another problem */
- mavlink_log_critical(mavlink_fd, "[sdlog2] ERR: max files %d", MAX_NO_LOGFILE);
+ mavlink_and_console_log_critical(mavlink_fd, "[sdlog2] ERR: max files %d", MAX_NO_LOGFILE);
return -1;
}
}
@@ -480,12 +503,8 @@ int open_perf_file(const char* str)
int fd = open(log_file_path, O_CREAT | O_WRONLY | O_DSYNC);
if (fd < 0) {
- warn("failed opening log: %s", log_file_name);
- mavlink_log_critical(mavlink_fd, "[sdlog2] failed opening log: %s", log_file_name);
+ mavlink_and_console_log_critical(mavlink_fd, "[sdlog2] failed opening: %s", log_file_name);
- } else {
- warnx("log file: %s", log_file_name);
- mavlink_log_info(mavlink_fd, "[sdlog2] log file: %s", log_file_name);
}
return fd;
@@ -547,6 +566,7 @@ static void *logwriter_thread(void *arg)
pthread_mutex_unlock(&logbuffer_mutex);
if (available > 0) {
+
/* do heavy IO here */
if (available > MAX_WRITE_CHUNK) {
n = MAX_WRITE_CHUNK;
@@ -584,6 +604,16 @@ static void *logwriter_thread(void *arg)
if (++poll_count == 10) {
fsync(log_fd);
poll_count = 0;
+
+ }
+
+ if (log_bytes_written - last_checked_bytes_written > 20*1024*1024) {
+ /* check if space is available, if not stop everything */
+ if (check_free_space() != OK) {
+ logwriter_should_exit = true;
+ main_thread_should_exit = true;
+ }
+ last_checked_bytes_written = log_bytes_written;
}
}
@@ -598,15 +628,15 @@ static void *logwriter_thread(void *arg)
void sdlog2_start_log()
{
- warnx("start logging");
- mavlink_log_info(mavlink_fd, "[sdlog2] start logging");
+ mavlink_and_console_log_info(mavlink_fd, "[sdlog2] start logging");
/* create log dir if needed */
if (create_log_dir() != 0) {
- mavlink_log_critical(mavlink_fd, "[sdlog2] error creating log dir");
- errx(1, "error creating log dir");
+ mavlink_and_console_log_critical(mavlink_fd, "[sdlog2] error creating log dir");
+ exit(1);
}
+
/* initialize statistics counter */
log_bytes_written = 0;
start_time = hrt_absolute_time();
@@ -644,8 +674,7 @@ void sdlog2_start_log()
void sdlog2_stop_log()
{
- warnx("stop logging");
- mavlink_log_info(mavlink_fd, "[sdlog2] stop logging");
+ mavlink_and_console_log_info(mavlink_fd, "[sdlog2] stop logging");
logging_enabled = false;
@@ -771,7 +800,7 @@ int sdlog2_thread_main(int argc, char *argv[])
mavlink_fd = open(MAVLINK_LOG_DEVICE, 0);
if (mavlink_fd < 0) {
- warnx("failed to open MAVLink log stream, start mavlink app first");
+ warnx("ERR: log stream, start mavlink app first");
}
/* delay = 1 / rate (rate defined by -r option), default log rate: 50 Hz */
@@ -899,11 +928,17 @@ int sdlog2_thread_main(int argc, char *argv[])
}
+
+ if (check_free_space() != OK) {
+ errx(1, "ERR: MicroSD almost full");
+ }
+
+
/* create log root dir */
int mkdir_ret = mkdir(log_root, S_IRWXU | S_IRWXG | S_IRWXO);
if (mkdir_ret != 0 && errno != EEXIST) {
- err(1, "failed creating log root dir: %s", log_root);
+ err(1, "ERR: failed creating log dir: %s", log_root);
}
/* copy conversion scripts */
@@ -1112,6 +1147,7 @@ int sdlog2_thread_main(int argc, char *argv[])
hrt_abstime magnetometer_timestamp = 0;
hrt_abstime barometer_timestamp = 0;
hrt_abstime differential_pressure_timestamp = 0;
+ hrt_abstime barometer1_timestamp = 0;
hrt_abstime gyro1_timestamp = 0;
hrt_abstime accelerometer1_timestamp = 0;
hrt_abstime magnetometer1_timestamp = 0;
@@ -1127,7 +1163,7 @@ int sdlog2_thread_main(int argc, char *argv[])
/* check GPS topic to get GPS time */
if (log_name_timestamp) {
if (!orb_copy(ORB_ID(vehicle_gps_position), subs.gps_pos_sub, &buf_gps_pos)) {
- gps_time = buf_gps_pos.time_gps_usec;
+ gps_time = buf_gps_pos.time_utc_usec;
}
}
@@ -1155,7 +1191,7 @@ int sdlog2_thread_main(int argc, char *argv[])
bool gps_pos_updated = copy_if_updated(ORB_ID(vehicle_gps_position), subs.gps_pos_sub, &buf_gps_pos);
if (gps_pos_updated && log_name_timestamp) {
- gps_time = buf_gps_pos.time_gps_usec;
+ gps_time = buf_gps_pos.time_utc_usec;
}
if (!logging_enabled) {
@@ -1185,7 +1221,7 @@ int sdlog2_thread_main(int argc, char *argv[])
if (gps_pos_updated) {
log_msg.msg_type = LOG_GPS_MSG;
- log_msg.body.log_GPS.gps_time = buf_gps_pos.time_gps_usec;
+ log_msg.body.log_GPS.gps_time = buf_gps_pos.time_utc_usec;
log_msg.body.log_GPS.fix_type = buf_gps_pos.fix_type;
log_msg.body.log_GPS.eph = buf_gps_pos.eph;
log_msg.body.log_GPS.epv = buf_gps_pos.epv;
@@ -1257,6 +1293,7 @@ int sdlog2_thread_main(int argc, char *argv[])
bool write_IMU1 = false;
bool write_IMU2 = false;
bool write_SENS = false;
+ bool write_SENS1 = false;
if (buf.sensor.timestamp != gyro_timestamp) {
gyro_timestamp = buf.sensor.timestamp;
@@ -1307,6 +1344,22 @@ int sdlog2_thread_main(int argc, char *argv[])
LOGBUFFER_WRITE_AND_COUNT(SENS);
}
+ if (buf.sensor.baro1_timestamp != barometer1_timestamp) {
+ barometer1_timestamp = buf.sensor.baro1_timestamp;
+ write_SENS1 = true;
+ }
+
+ if (write_SENS1) {
+ log_msg.msg_type = LOG_AIR1_MSG;
+ log_msg.body.log_SENS.baro_pres = buf.sensor.baro1_pres_mbar;
+ log_msg.body.log_SENS.baro_alt = buf.sensor.baro1_alt_meter;
+ log_msg.body.log_SENS.baro_temp = buf.sensor.baro1_temp_celcius;
+ log_msg.body.log_SENS.diff_pres = buf.sensor.differential_pressure1_pa;
+ log_msg.body.log_SENS.diff_pres_filtered = buf.sensor.differential_pressure1_filtered_pa;
+ // XXX moving to AIR0-AIR2 instead of SENS
+ LOGBUFFER_WRITE_AND_COUNT(SENS);
+ }
+
if (buf.sensor.accelerometer1_timestamp != accelerometer1_timestamp) {
accelerometer1_timestamp = buf.sensor.accelerometer1_timestamp;
write_IMU1 = true;
@@ -1737,8 +1790,6 @@ int sdlog2_thread_main(int argc, char *argv[])
free(lb.data);
- warnx("exiting");
-
thread_running = false;
return 0;
@@ -1771,7 +1822,7 @@ int file_copy(const char *file_old, const char *file_new)
int ret = 0;
if (source == NULL) {
- warnx("failed opening input file to copy");
+ warnx("ERR: open in");
return 1;
}
@@ -1779,7 +1830,7 @@ int file_copy(const char *file_old, const char *file_new)
if (target == NULL) {
fclose(source);
- warnx("failed to open output file to copy");
+ warnx("ERR: open out");
return 1;
}
@@ -1804,6 +1855,34 @@ int file_copy(const char *file_old, const char *file_new)
return OK;
}
+int check_free_space()
+{
+ /* use statfs to determine the number of blocks left */
+ FAR struct statfs statfs_buf;
+ if (statfs(mountpoint, &statfs_buf) != OK) {
+ errx(ERROR, "ERR: statfs");
+ }
+
+ /* use a threshold of 50 MiB */
+ if (statfs_buf.f_bavail < (int)(50 * 1024 * 1024 / statfs_buf.f_bsize)) {
+ mavlink_and_console_log_critical(mavlink_fd,
+ "[sdlog2] no space on MicroSD: %u MiB",
+ (unsigned int)(statfs_buf.f_bavail * statfs_buf.f_bsize) / (1024U * 1024U));
+ /* we do not need a flag to remember that we sent this warning because we will exit anyway */
+ return ERROR;
+
+ /* use a threshold of 100 MiB to send a warning */
+ } else if (!space_warning_sent && statfs_buf.f_bavail < (int)(100 * 1024 * 1024 / statfs_buf.f_bsize)) {
+ mavlink_and_console_log_critical(mavlink_fd,
+ "[sdlog2] space on MicroSD low: %u MiB",
+ (unsigned int)(statfs_buf.f_bavail * statfs_buf.f_bsize) / (1024U * 1024U));
+ /* we don't want to flood the user with warnings */
+ space_warning_sent = true;
+ }
+
+ return OK;
+}
+
void handle_command(struct vehicle_command_s *cmd)
{
int param;