Paparazzi UAS  v5.18.0_stable
Paparazzi is a free software Unmanned Aircraft System.
sdlogger_spi_direct.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) Bart Slinger
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, see
18  * <http://www.gnu.org/licenses/>.
19  */
30 #define PERIODIC_C_LOGGER
31 
36 #include "led.h"
37 
38 #include <stdbool.h>
39 
40 #if SDLOGGER_ON_ARM
41 #include "autopilot.h"
42 #endif
43 
44 #ifdef LOGGER_LED
45 #define LOGGER_LED_ON LED_ON(LOGGER_LED);
46 #define LOGGER_LED_OFF LED_OFF(LOGGER_LED);
47 #else
48 #define LOGGER_LED_ON {}
49 #define LOGGER_LED_OFF {}
50 #endif
51 
52 #ifndef TELEMETRY_MODE_Main_empty
53 #warning You need to define a main telemetry mode named "empty" without any \
54  messages in your config file in /conf/telemetry/<your_config.xml>. \
55  \
56  Add <mode name="empty"></mode> to your main telemetry process.
57 #endif
58 
59 #ifndef TELEMETRY_PROCESS_Logger
60 #error "You need to use a telemetry xml file with Logger process!"
61 #endif
62 
63 #ifndef SDLOGGER_DOWNLOAD_DEVICE
64 #error No downlink device defined for SD Logger
65 #endif
66 
67 #ifdef SDLOGGER_DOWNLOAD_DEVICE_LISTEN
68 // Listen for setting commands on download port
69 #include "pprzlink/dl_protocol.h"
70 #include "generated/settings.h"
71 
72 #include <string.h>
73 
74 PRINT_CONFIG_MSG("Listening to SETTING on SD logger download port.");
75 
76 static struct download_port_t {
77  struct link_device *device;
78  struct pprz_transport transport;
79  bool msg_available;
80  uint8_t msg_buf[256];
81 } download_port;
82 
83 static void sdlogger_spi_direct_download_port_init(void) {
84  download_port.device = &((SDLOGGER_DOWNLOAD_DEVICE).device);
85  pprz_transport_init(&download_port.transport);
86 }
87 
88 static void sdlogger_spi_direct_download_port_parse_msg(void) {
89  switch (IdOfPprzMsg(download_port.msg_buf)) {
90  case DL_SETTING: {
91  uint8_t index = DL_SETTING_index(download_port.msg_buf);
92  uint8_t ac_id = DL_SETTING_ac_id(download_port.msg_buf);
93  float value = DL_SETTING_value(download_port.msg_buf);
94  if (ac_id == AC_ID) {
95  DlSetting(index, value);
96  pprz_msg_send_DL_VALUE(&download_port.transport.trans_tx, download_port.device, AC_ID, &index, &value);
98  }
99  break; }
100  default:
101  break;
102  }
103 }
104 
105 static void sdlogger_spi_direct_download_port_periodic(void) {
106  pprz_check_and_parse(download_port.device, &download_port.transport, download_port.msg_buf, &download_port.msg_available);
107  if (download_port.msg_available) {
108  sdlogger_spi_direct_download_port_parse_msg();
109  download_port.msg_available = false;
110  }
111 }
112 #endif // SDLOGGER_DOWNLOAD_DEVICE_LISTEN
113 
115 
121 {
122  /* Initialize the SD Card */
123  sdcard_spi_init(&sdcard1, &(SDLOGGER_SPI_LINK_DEVICE),
124  SDLOGGER_SPI_LINK_SLAVE_NUMBER);
125 
126  /* Set values in the struct to their defaults */
131 
132  /* Fill internal buffer with zeros */
133  for (uint8_t i = 0; i < sizeof(sdlogger_spi.buffer); i++) {
134  sdlogger_spi.buffer[i] = 0;
135  }
136  sdlogger_spi.idx = 0;
137  sdlogger_spi.log_len = 0;
138  sdlogger_spi.command = 0;
142  sdlogger_spi.do_log = 0;
143 
144  /* Set function pointers in link_device to the logger functions */
145  sdlogger_spi.device.check_free_space = (check_free_space_t)sdlogger_spi_direct_check_free_space;
146  sdlogger_spi.device.put_byte = (put_byte_t)sdlogger_spi_direct_put_byte;
147  sdlogger_spi.device.put_buffer = (put_buffer_t)sdlogger_spi_direct_put_buffer;
148  sdlogger_spi.device.send_message = (send_message_t)sdlogger_spi_direct_send_message;
149  sdlogger_spi.device.char_available = (char_available_t)sdlogger_spi_direct_char_available;
150  sdlogger_spi.device.get_byte = (get_byte_t)sdlogger_spi_direct_get_byte;
151  sdlogger_spi.device.periph = &sdlogger_spi;
152 
153 #ifdef SDLOGGER_DOWNLOAD_DEVICE_LISTEN
154  sdlogger_spi_direct_download_port_init();
155 #endif
156 }
157 
163 {
164 #ifdef SDLOGGER_DOWNLOAD_DEVICE_LISTEN
165  sdlogger_spi_direct_download_port_periodic();
166 #endif
167 
169 
170 #if SDLOGGER_ON_ARM
172  sdlogger_spi.do_log = 1;
173  } else {
174  sdlogger_spi.do_log = 0;
175  }
176 #endif
177 
178  switch (sdlogger_spi.status) {
180  if (sdcard1.status == SDCard_Idle) {
183  }
184  break;
185 
186  case SDLogger_Ready:
187  if ((sdlogger_spi.do_log == 1) &&
192  }
193  break;
194 
195  case SDLogger_Logging:
196  /* This line is NOT unit-tested because it is an inline function */
197  #if PERIODIC_TELEMETRY
198  periodic_telemetry_send_Logger(DefaultPeriodic,
199  &pprzlog_tp.trans_tx,
201  #endif
202  /* Check if SD Card buffer is full and SD Card is ready for new data */
203  if (sdlogger_spi.sdcard_buf_idx > 512 &&
206  }
207  /* Check if switch is flipped to stop logging */
208  if (sdlogger_spi.do_log == 0) {
210  }
211  break;
212 
215  if (sdlogger_spi.sdcard_buf_idx > 512) {
217  }
218  else if (sdlogger_spi.sdcard_buf_idx > 1) {
219  /* Fill with trailing zero's */
220  for (uint16_t i = sdlogger_spi.sdcard_buf_idx; i < (SD_BLOCK_SIZE+1); i++) {
221  sdcard1.output_buf[i] = 0x00;
222  }
224  }
225  else if (sdlogger_spi.sdcard_buf_idx == 1) {
228  }
229  }
230  break;
231 
233  if (sdcard1.status == SDCard_Idle) {
236  }
237  break;
238 
240  if (sdcard1.status == SDCard_Idle) {
243  }
244  break;
245 
247  if (sdcard1.status == SDCard_Idle) {
248  /* Put bytes to the buffer until all is written or buffer is full */
249  long fd = 0;
250  uint16_t chunk_size = 64;
251  for (uint16_t i = sdlogger_spi.sdcard_buf_idx; i < SD_BLOCK_SIZE && chunk_size > 0; i++, chunk_size--) {
252  if ((SDLOGGER_DOWNLOAD_DEVICE).device.check_free_space(&(SDLOGGER_DOWNLOAD_DEVICE), &fd, 1)) {
253  (SDLOGGER_DOWNLOAD_DEVICE).device.put_byte(&(SDLOGGER_DOWNLOAD_DEVICE), fd, sdcard1.input_buf[i]);
254  } else {
255  /* No free space left, abort for-loop */
256  break;
257  }
259  }
260  /* Request next block if entire buffer was written to uart */
262  (SDLOGGER_DOWNLOAD_DEVICE).device.send_message(&(SDLOGGER_DOWNLOAD_DEVICE), fd); // Flush buffers
263  if (sdlogger_spi.download_length > 0) {
267  }
268  else {
271  }
273  }
274  }
275  break;
276 
277  default:
278  break;
279  }
280 }
281 
284 
290 {
291 
292  switch (sdlogger_spi.status) {
296  // Save data for later use
298  (sdcard1.input_buf[1] << 16) |
299  (sdcard1.input_buf[2] << 8) |
300  (sdcard1.input_buf[3]);
302 
303  if(sdlogger_spi.next_available_address < 0x00004000) {
305  }
306 
307  /* Ready to start logging */
309  break;
310 
312  /* Copy input buffer to output buffer */
313  for (uint16_t i = 0; i < SD_BLOCK_SIZE; i++) {
315  }
316 
317  /* Increment last completed log */
319  /* Write log info at dedicated location */
320  {
321  uint16_t log_idx_start = 5 + 6 + (sdlogger_spi.last_completed - 1) * 12;
322 
323  /* Set start address and length at location that belongs to the log nr */
324  sdcard1.output_buf[log_idx_start+0] = sdlogger_spi.next_available_address >> 24;
325  sdcard1.output_buf[log_idx_start+1] = sdlogger_spi.next_available_address >> 16;
326  sdcard1.output_buf[log_idx_start+2] = sdlogger_spi.next_available_address >> 8;
327  sdcard1.output_buf[log_idx_start+3] = sdlogger_spi.next_available_address >> 0;
328  sdcard1.output_buf[log_idx_start+4] = sdlogger_spi.log_len >> 24;
329  sdcard1.output_buf[log_idx_start+5] = sdlogger_spi.log_len >> 16;
330  sdcard1.output_buf[log_idx_start+6] = sdlogger_spi.log_len >> 8;
331  sdcard1.output_buf[log_idx_start+7] = sdlogger_spi.log_len >> 0;
332  }
333 
334  /* Increment and update the next available address */
340 
341  sdcard_spi_write_block(&sdcard1, 0x00002000);
342  /* Reset log length */
343  sdlogger_spi.log_len = 0;
345  break;
346 
348  {
349  uint16_t info_idx = 5 + (sdlogger_spi.download_id - 1) * 12;
350  sdlogger_spi.download_address = (sdcard1.input_buf[info_idx+0] << 24) |
351  (sdcard1.input_buf[info_idx+1] << 16) |
352  (sdcard1.input_buf[info_idx+2] << 8) |
353  (sdcard1.input_buf[info_idx+3] << 0);
354  sdlogger_spi.download_length = (sdcard1.input_buf[info_idx+4] << 24) |
355  (sdcard1.input_buf[info_idx+5] << 16) |
356  (sdcard1.input_buf[info_idx+6] << 8) |
357  (sdcard1.input_buf[info_idx+7] << 0);
358  if (sdlogger_spi.download_length > 0) {
359  /* Request the first block */
361  /* After each read block, incr address, decr length */
365  }
366  else {
369  }
371  }
372  break;
373 
374  default:
375  break;
376  }
377 
378 }
379 
386 {
387  /* Increment log length */
389 
390  /* Copy data from logger buffer to SD Card buffer */
391  for (uint8_t i = 0; i < sdlogger_spi.idx; i++) {
393  }
394  /* Set sdcard buffer index to new value */
396  /* And reset the logger buffer index */
397  sdlogger_spi.idx = 0;
398 }
399 
401 {
403  sdlogger_spi.command < 43) {
405  sdcard_spi_read_block(&sdcard1, 0x00002000,
409  }
410  else if (sdcard1.status == SDCard_Idle && sdlogger_spi.command == 255) {
411  telemetry_mode_Main = TELEMETRY_MODE_Main_empty;
413  sdcard_spi_read_block(&sdcard1, 0x00002000, NULL);
417  }
418  /* Always reset command value back to zero */
419  sdlogger_spi.command = 0;
420 }
421 
422 int sdlogger_spi_direct_check_free_space(struct sdlogger_spi_periph *p, long *fd __attribute__((unused)), uint16_t len)
423 {
424  if (p->status == SDLogger_Logging) {
425  /* Calculating free space in both buffers */
426  int available = (513 - p->sdcard_buf_idx) + (SDLOGGER_BUFFER_SIZE - p->idx);
427  if (available >= len) {
428  return available;
429  }
430  }
431  return 0;
432 }
433 
434 void sdlogger_spi_direct_put_byte(struct sdlogger_spi_periph *p, long fd __attribute__((unused)), uint8_t data)
435 {
436  /* SD Buffer full, write in logger buffer */
437  if (p->sdcard_buf_idx > 512) {
438  if (p->idx < SDLOGGER_BUFFER_SIZE) {
439  p->buffer[p->idx++] = data;
440  }
441  /* else: data lost */
442  }
443  /* Writing directly to SD Card buffer */
444  else {
445  sdcard1.output_buf[p->sdcard_buf_idx++] = data;
446 
447  /* Flush buffer */
448  if (p->sdcard_buf_idx > 512 && sdcard1.status == SDCard_MultiWriteIdle) {
450  }
451  }
452 }
453 
455 {
456  int i;
457  for (i = 0; i < len; i++) {
458  sdlogger_spi_direct_put_byte(p, fd, data[i]);
459  }
460 }
461 
462 void sdlogger_spi_direct_send_message(void *p, long fd __attribute__((unused)))
463 {
464  (void) p;
465 }
466 
468  (void) p;
469  return 0;
470 }
471 
473 {
474  (void) p;
475  return 0;
476 }
477 
sdlogger_spi_direct_multiwrite_written
void sdlogger_spi_direct_multiwrite_written(void)
sdlogger_spi_direct_multiwrite_written Called when a multiwrite is complete.
Definition: sdlogger_spi_direct.c:385
autopilot_get_motors_on
bool autopilot_get_motors_on(void)
get motors status
Definition: autopilot.c:212
sdcard_spi_multiwrite_start
void sdcard_spi_multiwrite_start(struct SDCard *sdcard, uint32_t addr)
Start writing multiple blocks of 512 bytes to the SDCard.
Definition: sdcard_spi.c:616
uint16_t
unsigned short uint16_t
Definition: types.h:16
SDCard_Idle
@ SDCard_Idle
Initialization sequence succesful.
Definition: sdcard_spi.h:58
sdcard1
struct SDCard sdcard1
This is the definition of the SD card.
Definition: sdcard_spi.c:56
sdlogger_spi_periph::status
enum SDLoggerStatus status
Definition: sdlogger_spi_direct.h:50
sdlogger_spi_periph::command
uint8_t command
Definition: sdlogger_spi_direct.h:57
sdlogger_spi_direct_periodic
void sdlogger_spi_direct_periodic(void)
sdlogger_spi_direct_periodic Periodic function called at module frequency
Definition: sdlogger_spi_direct.c:162
sdlogger_spi_periph::last_completed
uint8_t last_completed
Definition: sdlogger_spi_direct.h:52
LOGGER_LED_ON
#define LOGGER_LED_ON
Definition: sdlogger_spi_direct.c:48
sdlogger_spi_direct_start
void sdlogger_spi_direct_start(void)
Definition: sdlogger_spi_direct.c:282
pprzlog_tp.h
Initialize pprzlog transport.
sdlogger_spi_direct_send_message
void sdlogger_spi_direct_send_message(void *p, long fd)
Definition: sdlogger_spi_direct.c:462
sdlogger_spi_direct_init
void sdlogger_spi_direct_init(void)
sdlogger_spi_direct_init Initialize the logger and SD Card.
Definition: sdlogger_spi_direct.c:120
sdlogger_spi_periph::download_address
uint32_t download_address
Definition: sdlogger_spi_direct.h:59
sdlogger_spi_periph::next_available_address
uint32_t next_available_address
Definition: sdlogger_spi_direct.h:51
sdlogger_spi_direct_command
void sdlogger_spi_direct_command(void)
Definition: sdlogger_spi_direct.c:400
SDLogger_StoppedLogging
@ SDLogger_StoppedLogging
Definition: sdlogger_spi_direct.h:42
sdcard_spi_multiwrite_stop
void sdcard_spi_multiwrite_stop(struct SDCard *sdcard)
Stop with multiwrite procedure.
Definition: sdcard_spi.c:666
SDLogger_RetreivingIndex
@ SDLogger_RetreivingIndex
Definition: sdlogger_spi_direct.h:38
sdlogger_spi_direct.h
sdlogger_spi_periph::download_length
uint32_t download_length
Definition: sdlogger_spi_direct.h:60
sdcard_spi_periodic
void sdcard_spi_periodic(struct SDCard *sdcard)
Periodic function of the SDCard.
Definition: sdcard_spi.c:99
telemetry.h
sdcard_spi_init
void sdcard_spi_init(struct SDCard *sdcard, struct spi_periph *spi_p, const uint8_t slave_idx)
Configure initial values for SDCard.
Definition: sdcard_spi.c:74
sdlogger_spi_periph::log_len
uint32_t log_len
Definition: sdlogger_spi_direct.h:56
sdlogger_spi_direct_char_available
int sdlogger_spi_direct_char_available(void *p)
Definition: sdlogger_spi_direct.c:467
sdlogger_spi_periph::do_log
uint8_t do_log
Definition: sdlogger_spi_direct.h:62
sdlogger_spi
struct sdlogger_spi_periph sdlogger_spi
Definition: sdlogger_spi_direct.c:114
SDLOGGER_BUFFER_SIZE
#define SDLOGGER_BUFFER_SIZE
Definition: sdlogger_spi_direct.h:29
SDCard::status
enum SDCardStatus status
The status of the SD card.
Definition: sdcard_spi.h:112
SDCard_MultiWriteIdle
@ SDCard_MultiWriteIdle
CMD25 complete, ready to sent blocks.
Definition: sdcard_spi.h:84
sdlogger_spi_periph::device
struct link_device device
Definition: sdlogger_spi_direct.h:61
SDLogger_UpdatingIndex
@ SDLogger_UpdatingIndex
Definition: sdlogger_spi_direct.h:44
uint8_t
unsigned char uint8_t
Definition: types.h:14
sdlogger_spi_periph::buffer
uint8_t buffer[SDLOGGER_BUFFER_SIZE]
Definition: sdlogger_spi_direct.h:54
sdlogger_spi_direct_index_received
void sdlogger_spi_direct_index_received(void)
sdlogger_spi_direct_index_received Callback from SD Card when block at index location is received.
Definition: sdlogger_spi_direct.c:289
sdlogger_spi_periph::download_id
uint8_t download_id
Definition: sdlogger_spi_direct.h:58
SDLogger_Initializing
@ SDLogger_Initializing
Definition: sdlogger_spi_direct.h:37
SDLogger_GettingIndexForDownload
@ SDLogger_GettingIndexForDownload
Definition: sdlogger_spi_direct.h:45
autopilot.h
led.h
arch independent LED (Light Emitting Diodes) API
LOGGER_LED_OFF
#define LOGGER_LED_OFF
Definition: sdlogger_spi_direct.c:49
sdlogger_spi_direct_check_free_space
int sdlogger_spi_direct_check_free_space(struct sdlogger_spi_periph *p, long *fd, uint16_t len)
Definition: sdlogger_spi_direct.c:422
SDCard::output_buf
uint8_t output_buf[SD_BLOCK_SIZE+10]
The output buffer for the SPI transaction.
Definition: sdcard_spi.h:114
sdcard_spi_write_block
void sdcard_spi_write_block(struct SDCard *sdcard, uint32_t addr)
Write a single block (512 bytes) to the SDCard at a given address.
Definition: sdcard_spi.c:560
sdlogger_spi_periph
Definition: sdlogger_spi_direct.h:49
PRINT_CONFIG_MSG
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
fd
int fd
Definition: serial.c:26
SDLogger_GettingIndexForUpdate
@ SDLogger_GettingIndexForUpdate
Definition: sdlogger_spi_direct.h:43
sdlogger_spi_periph::sdcard_buf_idx
uint16_t sdcard_buf_idx
Definition: sdlogger_spi_direct.h:53
SDLogger_Logging
@ SDLogger_Logging
Definition: sdlogger_spi_direct.h:40
sdlogger_spi_direct_stop
void sdlogger_spi_direct_stop(void)
Definition: sdlogger_spi_direct.c:283
pprzlog_tp
struct pprzlog_transport pprzlog_tp
PPRZLOG transport structure.
Definition: pprzlog_tp.c:29
sdcard_spi_read_block
void sdcard_spi_read_block(struct SDCard *sdcard, uint32_t addr, SDCardCallback callback)
Read a single block (512 bytes) from the SDCard at a given address.
Definition: sdcard_spi.c:587
sdlogger_spi_direct_put_byte
void sdlogger_spi_direct_put_byte(struct sdlogger_spi_periph *p, long fd, uint8_t data)
Definition: sdlogger_spi_direct.c:434
SDLogger_Downloading
@ SDLogger_Downloading
Definition: sdlogger_spi_direct.h:46
sdlogger_spi_direct_put_buffer
void sdlogger_spi_direct_put_buffer(struct sdlogger_spi_periph *p, long fd, uint8_t *data, uint16_t len)
Definition: sdlogger_spi_direct.c:454
sdcard_spi_multiwrite_next
void sdcard_spi_multiwrite_next(struct SDCard *sdcard, SDCardCallback callback)
Write a(nother) data block (512 bytes) to the SDCard.
Definition: sdcard_spi.c:638
SDLogger_LoggingFinalBlock
@ SDLogger_LoggingFinalBlock
Definition: sdlogger_spi_direct.h:41
SD_BLOCK_SIZE
#define SD_BLOCK_SIZE
Definition: sdcard_spi.h:38
sdlogger_spi_direct_get_byte
uint8_t sdlogger_spi_direct_get_byte(void *p)
Definition: sdlogger_spi_direct.c:472
SDLogger_Ready
@ SDLogger_Ready
Definition: sdlogger_spi_direct.h:39
ac_id
uint8_t ac_id
Definition: sim_ap.c:48
SDCard::input_buf
uint8_t input_buf[SD_BLOCK_SIZE+10]
The input buffer for the SPI transaction.
Definition: sdcard_spi.h:113
DefaultPeriodic
#define DefaultPeriodic
Set default periodic telemetry.
Definition: telemetry.h:66
p
static float p[2][2]
Definition: ins_alt_float.c:268
sdlogger_spi_periph::idx
uint8_t idx
Definition: sdlogger_spi_direct.h:55