Paparazzi UAS  v5.18.0_stable
Paparazzi is a free software Unmanned Aircraft System.
sdlog_chibios.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2013-2015 Gautier Hattenberger, Alexandre Bustico
3  *
4  * This file is part of paparazzi.
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, write to
18  * the Free Software Foundation, 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 
22 /*
23  * @file modules/loggers/sdlog_chibios.c
24  * @brief sdlog process with battery monitoring
25  *
26  */
27 
28 #include <ch.h>
29 #include <hal.h>
35 #include "mcu_periph/adc.h"
36 #include "mcu.h"
37 #include "led.h"
38 
39 #if HAL_USE_RTC
40 #include <hal_rtc.h>
41 #include <time.h>
42 #include "subsystems/gps.h"
43 #endif
44 
45 // Delay before starting SD log
46 #ifndef SDLOG_START_DELAY
47 #define SDLOG_START_DELAY 30
48 #endif
49 
50 // Auto-flush period (in seconds)
51 #ifndef SDLOG_AUTO_FLUSH_PERIOD
52 #define SDLOG_AUTO_FLUSH_PERIOD 10
53 #endif
54 
55 // Contiguous storage memory (in Mo)
56 #ifndef SDLOG_CONTIGUOUS_STORAGE_MEM
57 #define SDLOG_CONTIGUOUS_STORAGE_MEM 50
58 #endif
59 
60 #if (!defined USE_ADC_WATCHDOG) || (USE_ADC_WATCHDOG == 0)
61 #error sdlog_chibios need USE_ADC_WATCHDOG in order to properly close files when power is unplugged
62 #endif
63 
64 #define DefaultAdcOfVoltage(voltage) ((uint32_t) (voltage/(DefaultVoltageOfAdc(1))))
66 static const char PPRZ_LOG_NAME[] = "pprzlog_";
67 static const char PPRZ_LOG_DIR[] = "PPRZ";
68 
69 /*
70  * Start log thread
71  */
72 static THD_WORKING_AREA(wa_thd_startlog, 2048);
73 static __attribute__((noreturn)) void thd_startlog(void *arg);
74 
75 /*
76  * Bat survey thread
77  */
78 static THD_WORKING_AREA(wa_thd_bat_survey, 1024);
79 static __attribute__((noreturn)) void thd_bat_survey(void *arg);
80 static void powerOutageIsr(void);
81 event_source_t powerOutageSource;
82 event_listener_t powerOutageListener;
83 
84 bool sdOk = false;
85 
87 
89 
90 #if FLIGHTRECORDER_SDLOG
91 static const char FLIGHTRECORDER_LOG_NAME[] = "fr_";
92 static const char FR_LOG_DIR[] = "FLIGHT_RECORDER";
93 FileDes flightRecorderLogFile = -1;
94 #endif
95 
98 static enum {
103 
106 static char chibios_sdlog_filenames[68];
107 static char NO_FILE_NAME[] = "none";
108 
109 #if PERIODIC_TELEMETRY
111 static void send_sdlog_status(struct transport_tx *trans, struct link_device *dev)
112 {
114  uint8_t errno = (uint8_t) sdLogGetStorageStatus();
115  uint32_t used = (uint32_t) sdLogGetNbBytesWrittenToStorage();
116  uint8_t size = strlen(chibios_sdlog_filenames);
117  char *filenames = chibios_sdlog_filenames;
118  if (size == 0) {
119  // when no file opened
120  filenames = NO_FILE_NAME;
121  size = strlen(filenames);
122  }
123  pprz_msg_send_LOGGER_STATUS(trans, dev, AC_ID, &status, &errno, &used, size, filenames);
124 }
125 #endif
126 
127 
128 // Functions for the generic device API
129 static int sdlog_check_free_space(struct chibios_sdlog *p __attribute__((unused)), long *fd, uint16_t len)
130 {
131  SdLogBuffer *sdb;
132  SdioError status = sdLogAllocSDB(&sdb, len);
133  if (status != SDLOG_OK) {
134  return 0;
135  } else {
136  *fd = (long) sdb;
137  return 1;
138  }
139 }
140 
141 static void sdlog_transmit(struct chibios_sdlog *p __attribute__((unused)), long fd, uint8_t byte)
142 {
143  SdLogBuffer *sdb = (SdLogBuffer *) fd;
144  uint8_t *data = (uint8_t *) sdLogGetBufferFromSDB(sdb);
145  *data = byte;
146  sdLogSeekBufferFromSDB(sdb, 1);
147 }
148 
149 static void sdlog_transmit_buffer(struct chibios_sdlog *p __attribute__((unused)), long fd, uint8_t *data, uint16_t len)
150 {
151  SdLogBuffer *sdb = (SdLogBuffer *) fd;
152  memcpy(sdLogGetBufferFromSDB(sdb), data, len);
153  sdLogSeekBufferFromSDB(sdb, len);
154 }
155 
156 static void sdlog_send(struct chibios_sdlog *p, long fd)
157 {
158  SdLogBuffer *sdb = (SdLogBuffer *) fd;
159  sdLogWriteSDB(*(p->file), sdb);
160 }
161 
162 static int null_function(struct chibios_sdlog *p __attribute__((unused))) { return 0; }
163 static uint8_t null_byte_function(struct chibios_sdlog *p __attribute__((unused))) { return 0; }
164 
166 {
167  // Store file descriptor
168  sdlog->file = file;
169  // Configure generic device
170  sdlog->device.periph = (void *)(sdlog);
171  sdlog->device.check_free_space = (check_free_space_t) sdlog_check_free_space;
172  sdlog->device.put_byte = (put_byte_t) sdlog_transmit;
173  sdlog->device.put_buffer = (put_buffer_t) sdlog_transmit_buffer;
174  sdlog->device.send_message = (send_message_t) sdlog_send;
175  sdlog->device.char_available = (char_available_t) null_function; // write only
176  sdlog->device.get_byte = (get_byte_t) null_byte_function; // write only
177 
178 }
179 
181 {
183 #if PERIODIC_TELEMETRY
185 #endif
186 
187  // Start polling on USB
189 
190  // Start log thread
191  chThdCreateStatic(wa_thd_startlog, sizeof(wa_thd_startlog),
192  NORMALPRIO + 2, thd_startlog, NULL);
193 }
194 
195 
196 void sdlog_chibios_finish(const bool flush)
197 {
198  if (pprzLogFile != -1) {
199  // disable all required periph to save energy and maximize chance to flush files
200  // to mass storage and avoid infamous dirty bit on filesystem
202 
203  // if a FF_FS_REENTRANT is true, we can umount fs without closing
204  // file, fatfs lock will assure that umount is done after a write,
205  // and umount will close all open files cleanly. Thats the fatest
206  // way to umount cleanly filesystem.
207  //
208  // if FF_FS_REENTRANT is false,
209  // we have to flush and close files before unmounting filesystem
210 #if FF_FS_REENTRANT == 0
211  sdLogCloseAllLogs(flush);
212 #else
213  (void) flush;
214 #endif
215 
216  sdLogFinish();
217  pprzLogFile = 0;
218 #if FLIGHTRECORDER_SDLOG
219  flightRecorderLogFile = 0;
220 #endif
221  }
223 }
224 
225 static void thd_startlog(void *arg)
226 {
227  (void) arg;
228  chRegSetThreadName("start log");
229  char tmpFilename[32];
230 
231  // Wait before starting the log if needed
232  chThdSleepSeconds(SDLOG_START_DELAY);
233  // Check if we are already in USB Storage mode
234  if (usbStorageIsItRunning()) {
235  chThdSleepSeconds(20000); // stuck here for hours FIXME stop the thread ?
236  }
237 
238  // Init sdlog struct
240 
241  // Check for init errors
242  sdOk = true;
243 
244  if (sdLogInit(NULL) != SDLOG_OK) {
245  sdOk = false;
246  } else {
248  if (sdLogOpenLog(&pprzLogFile, PPRZ_LOG_DIR,
250  SDLOG_CONTIGUOUS_STORAGE_MEM, LOG_PREALLOCATION_DISABLED, tmpFilename, sizeof(tmpFilename)) != SDLOG_OK) {
251  sdOk = false;
252  }
253  chsnprintf(chibios_sdlog_filenames, sizeof(chibios_sdlog_filenames), "%s", tmpFilename);
254 #if FLIGHTRECORDER_SDLOG
255  removeEmptyLogs(FR_LOG_DIR, FLIGHTRECORDER_LOG_NAME, 50);
256  if (sdLogOpenLog(&flightRecorderLogFile, FR_LOG_DIR, FLIGHTRECORDER_LOG_NAME,
258  SDLOG_CONTIGUOUS_STORAGE_MEM, LOG_PREALLOCATION_DISABLED, tmpFilename, sizeof(tmpFilename)) != SDLOG_OK) {
259  sdOk = false;
260  }
262 #endif
263  }
264 
265  if (sdOk) {
266  // Create Battery Survey Thread with event
267  chEvtObjectInit(&powerOutageSource);
268  chThdCreateStatic(wa_thd_bat_survey, sizeof(wa_thd_bat_survey),
269  NORMALPRIO + 2, thd_bat_survey, NULL);
270 
272  } else {
274  }
275 
276  while (true) {
277 #ifdef SDLOG_LED
278  LED_TOGGLE(SDLOG_LED);
279 #endif
280  // Blink faster if init has errors
281  chThdSleepMilliseconds(sdOk == true ? 1000 : 200);
282  if (sdLogGetStorageStatus() != SDLOG_OK) {
284  sdOk = false;
285  } else {
287  sdOk = true;
288  }
289 
290 #if HAL_USE_RTC && USE_GPS
291  static uint32_t timestamp = 0;
292  // FIXME this could be done somewhere else, like in sys_time
293  // we sync gps time to rtc every 5 seconds
294  if (chVTGetSystemTime() - timestamp > 5000) {
295  timestamp = chVTGetSystemTime();
296  if (gps.tow != 0) {
297  // Unix timestamp of the GPS epoch 1980-01-06 00:00:00 UTC
298  const uint32_t unixToGpsEpoch = 315964800;
299  struct tm time_tm;
300  time_t univTime = ((gps.week * 7 * 24 * 3600) + (gps.tow / 1000)) + unixToGpsEpoch;
301  gmtime_r(&univTime, &time_tm);
302  // Chibios date struct
303  RTCDateTime date;
304  rtcConvertStructTmToDateTime(&time_tm, 0, &date);
305  rtcSetTime(&RTCD1, &date);
306  }
307  }
308 #endif
309 
310  }
311 }
312 
313 
314 static void thd_bat_survey(void *arg)
315 {
316  (void)arg;
317  chRegSetThreadName("battery survey");
318  chEvtRegister(&powerOutageSource, &powerOutageListener, 1);
319  chThdSleepMilliseconds(2000);
320 
321  register_adc_watchdog(&SDLOG_BAT_ADC, SDLOG_BAT_CHAN, V_ALERT, &powerOutageIsr);
322 
323  chEvtWaitOne(EVENT_MASK(1));
324  // in case of powerloss, we should go fast and avoid to flush ram buffer
325  sdlog_chibios_finish(false);
326  chThdExit(0);
327  mcu_deep_sleep();
328  chThdSleep(TIME_INFINITE);
329  while (true); // never goes here, only to avoid compiler warning: 'noreturn' function does return
330 }
331 
332 
333 /*
334  powerOutageIsr is called within a lock zone from an isr, so no lock/unlock is needed
335  */
336 static void powerOutageIsr(void)
337 {
338  chEvtBroadcastI(&powerOutageSource);
339 }
340 
uint16_t
unsigned short uint16_t
Definition: types.h:16
pprzLogFile
FileDes pprzLogFile
Definition: sdlog_chibios.c:86
sdlog_chibios_finish
void sdlog_chibios_finish(const bool flush)
Definition: sdlog_chibios.c:196
sdlog_send
static void sdlog_send(struct chibios_sdlog *p, long fd)
Definition: sdlog_chibios.c:156
sdlog_chibios_init
void sdlog_chibios_init(void)
Definition: sdlog_chibios.c:180
status
uint8_t status
Definition: nps_radio_control_spektrum.c:101
GpsState::tow
uint32_t tow
GPS time of week in ms.
Definition: gps.h:109
tlsf_malloc.h
SDLOG_OK
@ SDLOG_OK
Definition: sdLog.h:112
sdlog_transmit_buffer
static void sdlog_transmit_buffer(struct chibios_sdlog *p, long fd, uint8_t *data, uint16_t len)
Definition: sdlog_chibios.c:149
SdLogBuffer
struct _SdLogBuffer SdLogBuffer
Definition: sdLog.h:127
sdLog.h
sdLogFinish
SdioError sdLogFinish(void)
unmount filesystem
Definition: sdLog.c:262
uint32_t
unsigned long uint32_t
Definition: types.h:18
chibios_sdlog_init
void chibios_sdlog_init(struct chibios_sdlog *sdlog, FileDes *file)
init chibios_sdlog structure
Definition: sdlog_chibios.c:165
usbStorage.h
thd_startlog
static void thd_startlog(void *arg)
Definition: sdlog_chibios.c:225
adc.h
arch independent ADC (Analog to Digital Converter) API
chsnprintf
void chsnprintf(char *buffer, size_t size, const char *fmt,...)
Definition: printf.c:377
usbStorageStartPolling
void usbStorageStartPolling(void)
Definition: usbStorage.c:70
powerOutageListener
event_listener_t powerOutageListener
Definition: sdlog_chibios.c:82
LED_TOGGLE
#define LED_TOGGLE(i)
Definition: led_hw.h:53
SDLOG_BAT_CHAN
#define SDLOG_BAT_CHAN
Definition: board.h:593
chibios_sdlog_filenames
static char chibios_sdlog_filenames[68]
sdlog filenames
Definition: sdlog_chibios.c:106
sdlog_chibios.h
telemetry.h
chibios_sdlog::file
FileDes * file
Definition: sdlog_chibios.h:55
gps.h
Device independent GPS code (interface)
printf.h
Mini printf-like functionality.
removeEmptyLogs
SdioError removeEmptyLogs(const char *directoryName, const char *prefix, const size_t sizeConsideredEmpty)
remove spurious log file left on sd
Definition: sdLog.c:791
powerOutageIsr
static void powerOutageIsr(void)
Definition: sdlog_chibios.c:336
GpsState::week
uint16_t week
GPS week.
Definition: gps.h:108
mcu.h
Arch independent mcu ( Micro Controller Unit ) utilities.
dev
static const struct usb_device_descriptor dev
Definition: usb_ser_hw.c:74
DefaultAdcOfVoltage
#define DefaultAdcOfVoltage(voltage)
Definition: sdlog_chibios.c:64
SDLOG_BAT_ADC
#define SDLOG_BAT_ADC
Definition: board.h:592
chibios_sdlog
chibios_sdlog structure
Definition: sdlog_chibios.h:54
chibios_sdlog::device
struct link_device device
Generic device interface.
Definition: sdlog_chibios.h:57
null_function
static int null_function(struct chibios_sdlog *p)
Definition: sdlog_chibios.c:162
uint8_t
unsigned char uint8_t
Definition: types.h:14
register_periodic_telemetry
int8_t register_periodic_telemetry(struct periodic_telemetry *_pt, uint8_t _id, telemetry_cb _cb)
Register a telemetry callback function.
Definition: telemetry.c:46
byte
#define byte
Definition: nps_fdm_crrcsim.c:74
sdlog_transmit
static void sdlog_transmit(struct chibios_sdlog *p, long fd, uint8_t byte)
Definition: sdlog_chibios.c:141
PPRZ_LOG_DIR
static const char PPRZ_LOG_DIR[]
Definition: sdlog_chibios.c:67
led.h
arch independent LED (Light Emitting Diodes) API
LOG_APPEND_TAG_AT_CLOSE_DISABLED
#define LOG_APPEND_TAG_AT_CLOSE_DISABLED
Definition: sdLog.h:105
FileDes
int8_t FileDes
Definition: sdLog.h:128
SDLOG_AUTO_FLUSH_PERIOD
#define SDLOG_AUTO_FLUSH_PERIOD
Definition: sdlog_chibios.c:52
sdOk
bool sdOk
Definition: sdlog_chibios.c:84
f
uint16_t f
Camera baseline, in meters (i.e. horizontal distance between the two cameras of the stereo setup)
Definition: wedgebug.c:204
SDLOG_START_DELAY
#define SDLOG_START_DELAY
Definition: sdlog_chibios.c:47
V_ALERT
static const uint16_t V_ALERT
Definition: sdlog_chibios.c:65
SDLOG_CONTIGUOUS_STORAGE_MEM
#define SDLOG_CONTIGUOUS_STORAGE_MEM
Definition: sdlog_chibios.c:57
fd
int fd
Definition: serial.c:26
SDLOG_RUNNING
@ SDLOG_RUNNING
Definition: sdlog_chibios.c:100
SDLOG_ERROR
@ SDLOG_ERROR
Definition: sdlog_chibios.c:101
thd_bat_survey
static void thd_bat_survey(void *arg)
Definition: sdlog_chibios.c:314
null_byte_function
static uint8_t null_byte_function(struct chibios_sdlog *p)
Definition: sdlog_chibios.c:163
usbStorageIsItRunning
bool usbStorageIsItRunning(void)
Definition: usbStorage.c:145
SDLOG_STOPPED
@ SDLOG_STOPPED
Definition: sdlog_chibios.c:99
PPRZ_LOG_NAME
static const char PPRZ_LOG_NAME[]
Definition: sdlog_chibios.c:66
mcu_periph_energy_save
void WEAK mcu_periph_energy_save(void)
Call board specific energy saving Can be necessary for closing on power off.
Definition: mcu_arch.c:154
LOG_PREALLOCATION_DISABLED
#define LOG_PREALLOCATION_DISABLED
Definition: sdLog.h:103
chibios_sdlog_status
static enum @293 chibios_sdlog_status
sdlog status
SdioError
SdioError
Definition: sdLog.h:111
mcu_deep_sleep
static void mcu_deep_sleep(void)
Put MCU into deep sleep mode.
Definition: mcu_arch.h:55
sdlog_check_free_space
static int sdlog_check_free_space(struct chibios_sdlog *p, long *fd, uint16_t len)
Definition: sdlog_chibios.c:129
gps
struct GpsState gps
global GPS state
Definition: gps.c:69
THD_WORKING_AREA
static THD_WORKING_AREA(wa_thd_startlog, 2048)
sdLogInit
SdioError sdLogInit(uint32_t *freeSpaceInKo)
initialise sdLog
Definition: sdLog.c:202
DefaultPeriodic
#define DefaultPeriodic
Set default periodic telemetry.
Definition: telemetry.h:66
p
static float p[2][2]
Definition: ins_alt_float.c:268
NO_FILE_NAME
static char NO_FILE_NAME[]
Definition: sdlog_chibios.c:107
powerOutageSource
event_source_t powerOutageSource
Definition: sdlog_chibios.c:81
send_sdlog_status
static void send_sdlog_status(struct transport_tx *trans, struct link_device *dev)
Definition: sdlog_chibios.c:111