Paparazzi UAS  v5.12_stable-4-g9b43e9b
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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>
34 #include "mcu_periph/adc.h"
35 #include "mcu.h"
36 #include "led.h"
37 
38 #if HAL_USE_RTC
39 #include <hal_rtc.h>
40 #include <time.h>
41 #include "subsystems/gps.h"
42 #endif
43 
44 // Delay before starting SD log
45 #ifndef SDLOG_START_DELAY
46 #define SDLOG_START_DELAY 30
47 #endif
48 
49 // Auto-flush period (in seconds)
50 #ifndef SDLOG_AUTO_FLUSH_PERIOD
51 #define SDLOG_AUTO_FLUSH_PERIOD 10
52 #endif
53 
54 // Contiguous storage memory (in Mo)
55 #ifndef SDLOG_CONTIGUOUS_STORAGE_MEM
56 #define SDLOG_CONTIGUOUS_STORAGE_MEM 50
57 #endif
58 
59 #if (!defined USE_ADC_WATCHDOG) || (USE_ADC_WATCHDOG == 0)
60 #error sdlog_chibios need USE_ADC_WATCHDOG in order to properly close files when power is unplugged
61 #endif
62 
63 #define DefaultAdcOfVoltage(voltage) ((uint32_t) (voltage/(DefaultVoltageOfAdc(1))))
64 static const uint16_t V_ALERT = DefaultAdcOfVoltage(5.5f);
65 static const char PPRZ_LOG_NAME[] = "pprzlog_";
66 static const char PPRZ_LOG_DIR[] = "PPRZ";
67 
68 /*
69  * Start log thread
70  */
71 static THD_WORKING_AREA(wa_thd_startlog, 2048);
72 static __attribute__((noreturn)) void thd_startlog(void *arg);
73 
74 /*
75  * Bat survey thread
76  */
77 static THD_WORKING_AREA(wa_thd_bat_survey, 1024);
78 static __attribute__((noreturn)) void thd_bat_survey(void *arg);
79 static void powerOutageIsr(void);
80 event_source_t powerOutageSource;
81 event_listener_t powerOutageListener;
82 
83 bool sdOk = false;
84 
86 
88 
89 #if FLIGHTRECORDER_SDLOG
90 static const char FLIGHTRECORDER_LOG_NAME[] = "fr_";
91 static const char FR_LOG_DIR[] = "FLIGHT_RECORDER";
92 FileDes flightRecorderLogFile = -1;
93 #endif
94 
97 static enum {
102 
103 #if PERIODIC_TELEMETRY
105 static void send_sdlog_status(struct transport_tx *trans, struct link_device *dev)
106 {
108  uint8_t errno = (uint8_t) sdLogGetStorageStatus();
109  uint32_t used = (uint32_t) sdLogGetNbBytesWrittenToStorage();
110  pprz_msg_send_LOGGER_STATUS(trans, dev, AC_ID, &status, &errno, &used);
111 }
112 #endif
113 
114 
115 // Functions for the generic device API
116 static int sdlog_check_free_space(struct chibios_sdlog *p __attribute__((unused)), long *fd, uint16_t len)
117 {
118  SdLogBuffer *sdb;
119  SdioError status = sdLogAllocSDB(&sdb, len);
120  if (status != SDLOG_OK) {
121  return 0;
122  } else {
123  *fd = (long) sdb;
124  return 1;
125  }
126 }
127 
128 static void sdlog_transmit(struct chibios_sdlog *p __attribute__((unused)), long fd, uint8_t byte)
129 {
130  SdLogBuffer *sdb = (SdLogBuffer *) fd;
131  uint8_t *data = (uint8_t *) sdLogGetBufferFromSDB(sdb);
132  *data = byte;
133  sdLogSeekBufferFromSDB(sdb, 1);
134 }
135 
136 static void sdlog_transmit_buffer(struct chibios_sdlog *p __attribute__((unused)), long fd, uint8_t *data, uint16_t len)
137 {
138  SdLogBuffer *sdb = (SdLogBuffer *) fd;
139  memcpy(sdLogGetBufferFromSDB(sdb), data, len);
140  sdLogSeekBufferFromSDB(sdb, len);
141 }
142 
143 static void sdlog_send(struct chibios_sdlog *p, long fd)
144 {
145  SdLogBuffer *sdb = (SdLogBuffer *) fd;
146  sdLogWriteSDB(*(p->file), sdb);
147 }
148 
149 static int null_function(struct chibios_sdlog *p __attribute__((unused))) { return 0; }
150 
151 void chibios_sdlog_init(struct chibios_sdlog *sdlog, FileDes *file)
152 {
153  // Store file descriptor
154  sdlog->file = file;
155  // Configure generic device
156  sdlog->device.periph = (void *)(sdlog);
157  sdlog->device.check_free_space = (check_free_space_t) sdlog_check_free_space;
158  sdlog->device.put_byte = (put_byte_t) sdlog_transmit;
159  sdlog->device.put_buffer = (put_buffer_t) sdlog_transmit_buffer;
160  sdlog->device.send_message = (send_message_t) sdlog_send;
161  sdlog->device.char_available = (char_available_t) null_function; // write only
162  sdlog->device.get_byte = (get_byte_t) null_function; // write only
163 
164 }
165 
167 {
169 #if PERIODIC_TELEMETRY
171 #endif
172 
173  // Start polling on USB
175 
176  // Start log thread
177  chThdCreateStatic(wa_thd_startlog, sizeof(wa_thd_startlog),
178  NORMALPRIO + 2, thd_startlog, NULL);
179 }
180 
181 
182 void sdlog_chibios_finish(const bool flush)
183 {
184  if (pprzLogFile != -1) {
185  // disable all the LEDs to save energy and maximize chance to flush files
186  // to mass storage and avoid infamous dirty bit on filesystem
187  led_disable();
188  sdLogCloseAllLogs(flush);
189  sdLogFinish();
190  pprzLogFile = 0;
191 #if FLIGHTRECORDER_SDLOG
192  flightRecorderLogFile = 0;
193 #endif
194  }
196 }
197 
198 static void thd_startlog(void *arg)
199 {
200  (void) arg;
201  chRegSetThreadName("start log");
202 
203  // Wait before starting the log if needed
204  chThdSleepSeconds(SDLOG_START_DELAY);
205  // Check if we are already in USB Storage mode
206  if (usbStorageIsItRunning()) {
207  chThdSleepSeconds(20000); // stuck here for hours FIXME stop the thread ?
208  }
209 
210  // Init sdlog struct
211  chibios_sdlog_init(&chibios_sdlog, &pprzLogFile);
212 
213  // Check for init errors
214  sdOk = true;
215 
216  if (sdLogInit(NULL) != SDLOG_OK) {
217  sdOk = false;
218  } else {
220  if (sdLogOpenLog(&pprzLogFile, PPRZ_LOG_DIR,
223  sdOk = false;
224  }
225 #if FLIGHTRECORDER_SDLOG
226  removeEmptyLogs(FR_LOG_DIR, FLIGHTRECORDER_LOG_NAME, 50);
227  if (sdLogOpenLog(&flightRecorderLogFile, FR_LOG_DIR, FLIGHTRECORDER_LOG_NAME,
230  sdOk = false;
231  }
232 #endif
233  }
234 
235  if (sdOk) {
236  // Create Battery Survey Thread with event
237  chEvtObjectInit(&powerOutageSource);
238  chThdCreateStatic(wa_thd_bat_survey, sizeof(wa_thd_bat_survey),
239  NORMALPRIO + 2, thd_bat_survey, NULL);
240 
242  } else {
244  }
245 
246  while (true) {
247 #ifdef SDLOG_LED
248  LED_TOGGLE(SDLOG_LED);
249 #endif
250  // Blink faster if init has errors
251  chThdSleepMilliseconds(sdOk == true ? 1000 : 200);
252  if (sdLogGetStorageStatus() != SDLOG_OK) {
254  sdOk = false;
255  } else {
257  sdOk = true;
258  }
259 
260 #if HAL_USE_RTC && USE_GPS
261  static uint32_t timestamp = 0;
262  // FIXME this could be done somewhere else, like in sys_time
263  // we sync gps time to rtc every 5 seconds
264  if (chVTGetSystemTime() - timestamp > 5000) {
265  timestamp = chVTGetSystemTime();
266  if (gps.tow != 0) {
267  // Unix timestamp of the GPS epoch 1980-01-06 00:00:00 UTC
268  const uint32_t unixToGpsEpoch = 315964800;
269  struct tm time_tm;
270  time_t univTime = ((gps.week * 7 * 24 * 3600) + (gps.tow / 1000)) + unixToGpsEpoch;
271  gmtime_r(&univTime, &time_tm);
272  // Chibios date struct
273  RTCDateTime date;
274  rtcConvertStructTmToDateTime(&time_tm, 0, &date);
275  rtcSetTime(&RTCD1, &date);
276  }
277  }
278 #endif
279 
280  }
281 }
282 
283 
284 static void thd_bat_survey(void *arg)
285 {
286  (void)arg;
287  chRegSetThreadName("battery survey");
288  chEvtRegister(&powerOutageSource, &powerOutageListener, 1);
289  chThdSleepMilliseconds(2000);
290 
291  register_adc_watchdog(&SDLOG_BAT_ADC, SDLOG_BAT_CHAN, V_ALERT, &powerOutageIsr);
292 
293  chEvtWaitOne(EVENT_MASK(1));
294  // in case of powerloss, we should go fast and avoid to flush ram buffer
295  sdlog_chibios_finish(false);
296  chThdExit(0);
297  mcu_deep_sleep();
298  chThdSleep(TIME_INFINITE);
299  while (true); // never goes here, only to avoid compiler warning: 'noreturn' function does return
300 }
301 
302 
303 /*
304  powerOutageIsr is called within a lock zone from an isr, so no lock/unlock is needed
305  */
306 static void powerOutageIsr(void)
307 {
308  chEvtBroadcastI(&powerOutageSource);
309 }
310 
SdioError sdLogFinish(void)
unmount filesystem
Definition: sdLog.c:253
unsigned short uint16_t
Definition: types.h:16
status
Definition: anemotaxis.c:10
static void thd_bat_survey(void *arg)
static THD_WORKING_AREA(wa_thd_startlog, 2048)
int8_t FileDes
Definition: sdLog.h:124
event_listener_t powerOutageListener
Definition: sdlog_chibios.c:81
static void thd_startlog(void *arg)
void sdlog_chibios_finish(const bool flush)
Periodic telemetry system header (includes downlink utility and generated code).
uint16_t week
GPS week.
Definition: gps.h:100
static const uint16_t V_ALERT
Definition: sdlog_chibios.c:64
#define SDLOG_BAT_ADC
Definition: board.h:1040
struct link_device device
Generic device interface.
Definition: sdlog_chibios.h:57
bool led_disable
Definition: led_hw.c:4
static const char PPRZ_LOG_NAME[]
Definition: sdlog_chibios.c:65
static const char PPRZ_LOG_DIR[]
Definition: sdlog_chibios.c:66
static void powerOutageIsr(void)
arch independent ADC (Analog to Digital Converter) API
SdioError sdLogInit(uint32_t *freeSpaceInKo)
initialise sdLog
Definition: sdLog.c:193
chibios_sdlog structure
Definition: sdlog_chibios.h:54
#define SDLOG_AUTO_FLUSH_PERIOD
Definition: sdlog_chibios.c:51
FileDes * file
Definition: sdlog_chibios.h:55
Dynamic memory allocation based on TLSF library.
static int sdlog_check_free_space(struct chibios_sdlog *p, long *fd, uint16_t len)
event_source_t powerOutageSource
Definition: sdlog_chibios.c:80
uint32_t tow
GPS time of week in ms.
Definition: gps.h:101
Device independent GPS code (interface)
void usbStorageStartPolling(void)
Definition: usbStorage.c:70
unsigned long uint32_t
Definition: types.h:18
SdioError removeEmptyLogs(const char *directoryName, const char *prefix, const size_t sizeConsideredEmpty)
remove spurious log file left on sd
Definition: sdLog.c:783
#define DefaultPeriodic
Set default periodic telemetry.
Definition: telemetry.h:66
FileDes pprzLogFile
Definition: sdlog_chibios.c:85
static void mcu_deep_sleep(void)
Put MCU into deep sleep mode.
Definition: mcu_arch.h:55
SdioError
Definition: sdLog.h:107
#define SDLOG_BAT_CHAN
Definition: board.h:1041
#define LED_TOGGLE(i)
Definition: led_hw.h:52
static int null_function(struct chibios_sdlog *p)
#define DefaultAdcOfVoltage(voltage)
Definition: sdlog_chibios.c:63
static const struct usb_device_descriptor dev
Definition: usb_ser_hw.c:73
Arch independent mcu ( Micro Controller Unit ) utilities.
unsigned char uint8_t
Definition: types.h:14
static enum @283 chibios_sdlog_status
sdlog status
#define byte
bool sdOk
Definition: sdlog_chibios.c:83
#define SDLOG_CONTIGUOUS_STORAGE_MEM
Definition: sdlog_chibios.c:56
int fd
Definition: serial.c:26
#define SDLOG_START_DELAY
Definition: sdlog_chibios.c:46
void chibios_sdlog_init(struct chibios_sdlog *sdlog, FileDes *file)
init chibios_sdlog structure
arch independent LED (Light Emitting Diodes) API
static float p[2][2]
bool usbStorageIsItRunning(void)
Definition: usbStorage.c:149
static void send_sdlog_status(struct transport_tx *trans, struct link_device *dev)
static void sdlog_transmit(struct chibios_sdlog *p, long fd, uint8_t byte)
#define false
Definition: rtwtypes.h:24
static void sdlog_send(struct chibios_sdlog *p, long fd)
struct _SdLogBuffer SdLogBuffer
Definition: sdLog.h:123
struct GpsState gps
global GPS state
Definition: gps.c:75
static void sdlog_transmit_buffer(struct chibios_sdlog *p, long fd, uint8_t *data, uint16_t len)
void sdlog_chibios_init(void)
int8_t register_periodic_telemetry(struct periodic_telemetry *_pt, uint8_t _id, telemetry_cb _cb)
Register a telemetry callback function.
Definition: telemetry.c:46