Paparazzi UAS  v5.10_stable-5-g83a0da5-dirty
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 "led.h"
36 
37 #if HAL_USE_RTC
38 #include <rtc.h>
39 #include <time.h>
40 #include "subsystems/gps.h"
41 #endif
42 
43 // Delay before starting SD log
44 #ifndef SDLOG_START_DELAY
45 #define SDLOG_START_DELAY 30
46 #endif
47 
48 
49 #if (!defined USE_ADC_WATCHDOG) || (USE_ADC_WATCHDOG == 0)
50 #error sdlog_chibios need USE_ADC_WATCHDOG in order to properly close files when power is unplugged
51 #endif
52 
53 #define DefaultAdcOfVoltage(voltage) ((uint32_t) (voltage/(DefaultVoltageOfAdc(1))))
54 static const uint16_t V_ALERT = DefaultAdcOfVoltage(5.5f);
55 static const char PPRZ_LOG_NAME[] = "pprzlog_";
56 static const char PPRZ_LOG_DIR[] = "PPRZ";
57 
58 /*
59  * Start log thread
60  */
61 static THD_WORKING_AREA(wa_thd_startlog, 2048);
62 static __attribute__((noreturn)) void thd_startlog(void *arg);
63 
64 /*
65  * Bat survey thread
66  */
67 static THD_WORKING_AREA(wa_thd_bat_survey, 1024);
68 static __attribute__((noreturn)) void thd_bat_survey(void *arg);
69 static void powerOutageIsr (void);
70 static void systemDeepSleep (void);
71 event_source_t powerOutageSource;
72 event_listener_t powerOutageListener;
73 
74 bool sdOk = false;
75 
77 
79 
80 #if FLIGHTRECORDER_SDLOG
81 static const char FLIGHTRECORDER_LOG_NAME[] = "fr_";
82 static const char FR_LOG_DIR[] = "FLIGHT_RECORDER";
83 FileDes flightRecorderLogFile = -1;
84 #endif
85 
86 
87 // Functions for the generic device API
88 static int sdlog_check_free_space(struct chibios_sdlog* p __attribute__((unused)), long *fd, uint16_t len)
89 {
90  SdLogBuffer *sdb;
91  SdioError status = sdLogAllocSDB(&sdb, len);
92  if (status != SDLOG_OK) {
93  return 0;
94  } else {
95  *fd = (long) sdb;
96  return 1;
97  }
98 }
99 
100 static void sdlog_transmit(struct chibios_sdlog* p __attribute__((unused)), long fd, uint8_t byte)
101 {
102  SdLogBuffer *sdb = (SdLogBuffer *) fd;
103  uint8_t *data = (uint8_t *) sdLogGetBufferFromSDB(sdb);
104  *data = byte;
105  sdLogSeekBufferFromSDB(sdb, 1);
106 }
107 
108 static void sdlog_transmit_buffer(struct chibios_sdlog* p __attribute__((unused)), long fd, uint8_t *data, uint16_t len)
109 {
110  SdLogBuffer *sdb = (SdLogBuffer *) fd;
111  memcpy(sdLogGetBufferFromSDB(sdb), data, len);
112  sdLogSeekBufferFromSDB(sdb, len);
113 }
114 
115 static void sdlog_send(struct chibios_sdlog* p, long fd)
116 {
117  SdLogBuffer *sdb = (SdLogBuffer *) fd;
118  sdLogWriteSDB(*(p->file), sdb);
119 }
120 
121 static int null_function(struct chibios_sdlog *p __attribute__((unused))) { return 0; }
122 
123 void chibios_sdlog_init(struct chibios_sdlog *sdlog, FileDes *file)
124 {
125  // Store file descriptor
126  sdlog->file = file;
127  // Configure generic device
128  sdlog->device.periph = (void *)(sdlog);
129  sdlog->device.check_free_space = (check_free_space_t) sdlog_check_free_space;
130  sdlog->device.put_byte = (put_byte_t) sdlog_transmit;
131  sdlog->device.put_buffer = (put_buffer_t) sdlog_transmit_buffer;
132  sdlog->device.send_message = (send_message_t) sdlog_send;
133  sdlog->device.char_available = (char_available_t) null_function; // write only
134  sdlog->device.get_byte = (get_byte_t) null_function; // write only
135 
136 }
137 
139 {
140  // Start polling on USB
142 
143  // Start log thread
144  chThdCreateStatic(wa_thd_startlog, sizeof(wa_thd_startlog),
145  NORMALPRIO+2, thd_startlog, NULL);
146 }
147 
148 
149 void sdlog_chibios_finish(bool flush)
150 {
151  if (pprzLogFile != -1) {
152  sdLogCloseAllLogs(flush);
153  sdLogFinish ();
154  pprzLogFile = 0;
155 #if FLIGHTRECORDER_SDLOG
156  flightRecorderLogFile = 0;
157 #endif
158  }
159 }
160 
161 static void thd_startlog(void *arg)
162 {
163  (void) arg;
164  chRegSetThreadName("start log");
165 
166  // Wait before starting the log if needed
167  chThdSleepSeconds (SDLOG_START_DELAY);
168  // Check if we are already in USB Storage mode
169  if (usbStorageIsItRunning ())
170  chThdSleepSeconds (20000); // stuck here for hours FIXME stop the thread ?
171 
172  // Init sdlog struct
173  chibios_sdlog_init(&chibios_sdlog, &pprzLogFile);
174 
175  // Check for init errors
176  sdOk = true;
177 
178  if (sdLogInit (NULL) != SDLOG_OK) {
179  sdOk = false;
180  }
181  else {
183  if (sdLogOpenLog (&pprzLogFile, PPRZ_LOG_DIR, PPRZ_LOG_NAME, true) != SDLOG_OK)
184  sdOk = false;
185 
186 #if FLIGHTRECORDER_SDLOG
187  removeEmptyLogs (FR_LOG_DIR, FLIGHTRECORDER_LOG_NAME, 50);
188  if (sdLogOpenLog (&flightRecorderLogFile, FR_LOG_DIR, FLIGHTRECORDER_LOG_NAME, false) != SDLOG_OK)
189  sdOk = false;
190 #endif
191  }
192 
193  if (sdOk) {
194  // Create Battery Survey Thread with event
195  chEvtObjectInit (&powerOutageSource);
196  chThdCreateStatic (wa_thd_bat_survey, sizeof(wa_thd_bat_survey),
197  NORMALPRIO+2, thd_bat_survey, NULL);
198  }
199 
200  while (true) {
201 #ifdef LED_SDLOG
202  LED_TOGGLE(LED_SDLOG);
203 #endif
204  // Blink faster if init has errors
205  chThdSleepMilliseconds (sdOk == true ? 1000 : 200);
206  static uint32_t timestamp = 0;
207 
208 #if HAL_USE_RTC
209  // FIXME this could be done somewhere else, like in sys_time
210  // we sync gps time to rtc every 5 seconds
211  if (chVTGetSystemTime() - timestamp > 5000) {
212  timestamp = chVTGetSystemTime();
213  if (gps.tow != 0) {
214  // Unix timestamp of the GPS epoch 1980-01-06 00:00:00 UTC
215  const uint32_t unixToGpsEpoch = 315964800;
216  struct tm time_tm;
217  time_t univTime = ((gps.week * 7 * 24 * 3600) + (gps.tow/1000)) + unixToGpsEpoch;
218  gmtime_r(&univTime, &time_tm);
219  // Chibios date struct
220  RTCDateTime date;
221  rtcConvertStructTmToDateTime(&time_tm, 0, &date);
222  rtcSetTime(&RTCD1, &date);
223  }
224  }
225 #endif
226 
227  }
228 }
229 
230 
231 static void thd_bat_survey(void *arg)
232 {
233  (void)arg;
234  chRegSetThreadName ("battery survey");
235  chEvtRegister(&powerOutageSource, &powerOutageListener, 1);
236  chThdSleepMilliseconds (2000);
237 
238  // FIXME: &ADCD1 and channel AD1_4 should not be hardcoded like this
239  register_adc_watchdog(&ADCD1, AD1_4_CHANNEL, V_ALERT, &powerOutageIsr);
240 
241  chEvtWaitOne(EVENT_MASK(1));
242  sdlog_chibios_finish (true);
243  chThdExit(0);
244  systemDeepSleep();
245  chThdSleepMilliseconds (TIME_INFINITE);
246  while (1); // never goes here, only to avoid compiler warning: 'noreturn' function does return
247 }
248 
249 
250 /*
251  powerOutageIsr is called within a lock zone from an isr, so no lock/unlock is needed
252  */
253 static void powerOutageIsr (void)
254 {
255  chEvtBroadcastI(&powerOutageSource);
256 }
257 
258 
259 static void systemDeepSleep (void)
260 {
261  chSysLock();
262  SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
263  PWR->CR |= (PWR_CR_PDDS | PWR_CR_LPDS | PWR_CR_CSBF | PWR_CR_CWUF);
264  __WFE();
265  chSysUnlock();
266 }
SdioError sdLogFinish(void)
unmount filesystem
Definition: sdLog.c:224
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:100
event_listener_t powerOutageListener
Definition: sdlog_chibios.c:72
static void thd_startlog(void *arg)
uint16_t week
GPS week.
Definition: gps.h:100
static void systemDeepSleep(void)
static const uint16_t V_ALERT
Definition: sdlog_chibios.c:54
struct link_device device
Generic device interface.
Definition: sdlog_chibios.h:58
static const char PPRZ_LOG_NAME[]
Definition: sdlog_chibios.c:55
static const char PPRZ_LOG_DIR[]
Definition: sdlog_chibios.c:56
static void powerOutageIsr(void)
arch independent ADC (Analog to Digital Converter) API
SdioError sdLogInit(uint32_t *freeSpaceInKo)
initialise sdLog
Definition: sdLog.c:166
chibios_sdlog structure
Definition: sdlog_chibios.h:55
Definition: sdLog.h:86
FileDes * file
Definition: sdlog_chibios.h:56
Dynamic memory allocation based on TLSF library.
static int sdlog_check_free_space(struct chibios_sdlog *p, long *fd, uint16_t len)
Definition: sdlog_chibios.c:88
event_source_t powerOutageSource
Definition: sdlog_chibios.c:71
#define SCB
Definition: LPC21xx.h:394
uint32_t tow
GPS time of week in ms.
Definition: gps.h:101
Device independent GPS code (interface)
void usbStorageStartPolling(void)
Definition: usbStorage.c:242
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:708
#define AD1_4_CHANNEL
Definition: board.h:755
FileDes pprzLogFile
Definition: sdlog_chibios.c:76
SdioError
Definition: sdLog.h:85
#define LED_TOGGLE(i)
Definition: led_hw.h:51
static int null_function(struct chibios_sdlog *p)
#define DefaultAdcOfVoltage(voltage)
Definition: sdlog_chibios.c:53
unsigned char uint8_t
Definition: types.h:14
#define byte
bool sdOk
Definition: sdlog_chibios.c:74
int fd
Definition: serial.c:26
#define SDLOG_START_DELAY
Definition: sdlog_chibios.c:45
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:339
static void sdlog_transmit(struct chibios_sdlog *p, long fd, uint8_t byte)
void sdlog_chibios_finish(bool flush)
static void sdlog_send(struct chibios_sdlog *p, long fd)
struct _SdLogBuffer SdLogBuffer
Definition: sdLog.h:99
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)