Paparazzi UAS  v5.15_devel-110-g5cf27ee
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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 #if SDLOGGER_ON_ARM
39 #include "autopilot.h"
40 #endif
41 
42 #ifdef LOGGER_LED
43 #define LOGGER_LED_ON LED_ON(LOGGER_LED);
44 #define LOGGER_LED_OFF LED_OFF(LOGGER_LED);
45 #else
46 #define LOGGER_LED_ON {}
47 #define LOGGER_LED_OFF {}
48 #endif
49 
50 #ifndef TELEMETRY_MODE_Main_empty
51 #warning You need to define a main telemetry mode named "empty" without any \
52  messages in your config file in /conf/telemetry/<your_config.xml>. \
53  \
54  Add <mode name="empty"></mode> to your main telemetry process.
55 #endif
56 
57 #ifndef TELEMETRY_PROCESS_Logger
58 #error "You need to use a telemetry xml file with Logger process!"
59 #endif
60 
61 #ifndef DOWNLINK_DEVICE
62 #warning This module can only be used with uart downlink for now.
63 #endif
64 
66 
72 {
73  /* Initialize the SD Card */
74  sdcard_spi_init(&sdcard1, &(SDLOGGER_SPI_LINK_DEVICE),
75  SDLOGGER_SPI_LINK_SLAVE_NUMBER);
76 
77  /* Set values in the struct to their defaults */
82 
83  /* Fill internal buffer with zeros */
84  for (uint8_t i = 0; i < sizeof(sdlogger_spi.buffer); i++) {
85  sdlogger_spi.buffer[i] = 0;
86  }
87  sdlogger_spi.idx = 0;
93  sdlogger_spi.do_log = 0;
94 
95  /* Set function pointers in link_device to the logger functions */
96  sdlogger_spi.device.check_free_space = (check_free_space_t)sdlogger_spi_direct_check_free_space;
97  sdlogger_spi.device.put_byte = (put_byte_t)sdlogger_spi_direct_put_byte;
98  sdlogger_spi.device.put_buffer = (put_buffer_t)sdlogger_spi_direct_put_buffer;
99  sdlogger_spi.device.send_message = (send_message_t)sdlogger_spi_direct_send_message;
100  sdlogger_spi.device.char_available = (char_available_t)sdlogger_spi_direct_char_available;
101  sdlogger_spi.device.get_byte = (get_byte_t)sdlogger_spi_direct_get_byte;
102  sdlogger_spi.device.periph = &sdlogger_spi;
103 
104 }
105 
111 {
113 
114 #if SDLOGGER_ON_ARM
116  sdlogger_spi.do_log = 1;
117  } else {
118  sdlogger_spi.do_log = 0;
119  }
120 #endif
121 
122  switch (sdlogger_spi.status) {
124  if (sdcard1.status == SDCard_Idle) {
127  }
128  break;
129 
130  case SDLogger_Ready:
131  if ((sdlogger_spi.do_log == 1) &&
136  }
137  break;
138 
139  case SDLogger_Logging:
140  /* This line is NOT unit-tested because it is an inline function */
141  #if PERIODIC_TELEMETRY
142  periodic_telemetry_send_Logger(DefaultPeriodic,
143  &pprzlog_tp.trans_tx,
145  #endif
146  /* Check if SD Card buffer is full and SD Card is ready for new data */
147  if (sdlogger_spi.sdcard_buf_idx > 512 &&
150  }
151  /* Check if switch is flipped to stop logging */
152  if (sdlogger_spi.do_log == 0) {
154  }
155  break;
156 
159  if (sdlogger_spi.sdcard_buf_idx > 512) {
161  }
162  else if (sdlogger_spi.sdcard_buf_idx > 1) {
163  /* Fill with trailing zero's */
164  for (uint16_t i = sdlogger_spi.sdcard_buf_idx; i < (SD_BLOCK_SIZE+1); i++) {
165  sdcard1.output_buf[i] = 0x00;
166  }
168  }
169  else if (sdlogger_spi.sdcard_buf_idx == 1) {
172  }
173  }
174  break;
175 
177  if (sdcard1.status == SDCard_Idle) {
180  }
181  break;
182 
184  if (sdcard1.status == SDCard_Idle) {
187  }
188  break;
189 
191  if (sdcard1.status == SDCard_Idle) {
192  /* Put bytes to the buffer until all is written or buffer is full */
193  for (uint16_t i = sdlogger_spi.sdcard_buf_idx; i < SD_BLOCK_SIZE; i++) {
194  long fd = 0;
195  if (uart_check_free_space(&(DOWNLINK_DEVICE), &fd, 1)) {
197  }
198  else {
199  /* No free space left, abort for-loop */
200  break;
201  }
203  }
204  /* Request next block if entire buffer was written to uart */
206  if (sdlogger_spi.download_length > 0) {
210  }
211  else {
214  }
216  }
217  }
218  break;
219 
220  default:
221  break;
222  }
223 }
224 
227 
233 {
234 
235  switch (sdlogger_spi.status) {
239  // Save data for later use
241  (sdcard1.input_buf[1] << 16) |
242  (sdcard1.input_buf[2] << 8) |
243  (sdcard1.input_buf[3]);
245 
246  if(sdlogger_spi.next_available_address < 0x00004000) {
248  }
249 
250  /* Ready to start logging */
252  break;
253 
255  /* Copy input buffer to output buffer */
256  for (uint16_t i = 0; i < SD_BLOCK_SIZE; i++) {
258  }
259 
260  /* Increment last completed log */
262  /* Write log info at dedicated location */
263  {
264  uint16_t log_idx_start = 5 + 6 + (sdlogger_spi.last_completed - 1) * 12;
265 
266  /* Set start address and length at location that belongs to the log nr */
267  sdcard1.output_buf[log_idx_start+0] = sdlogger_spi.next_available_address >> 24;
268  sdcard1.output_buf[log_idx_start+1] = sdlogger_spi.next_available_address >> 16;
269  sdcard1.output_buf[log_idx_start+2] = sdlogger_spi.next_available_address >> 8;
270  sdcard1.output_buf[log_idx_start+3] = sdlogger_spi.next_available_address >> 0;
271  sdcard1.output_buf[log_idx_start+4] = sdlogger_spi.log_len >> 24;
272  sdcard1.output_buf[log_idx_start+5] = sdlogger_spi.log_len >> 16;
273  sdcard1.output_buf[log_idx_start+6] = sdlogger_spi.log_len >> 8;
274  sdcard1.output_buf[log_idx_start+7] = sdlogger_spi.log_len >> 0;
275  }
276 
277  /* Increment and update the next available address */
283 
284  sdcard_spi_write_block(&sdcard1, 0x00002000);
285  /* Reset log length */
286  sdlogger_spi.log_len = 0;
288  break;
289 
291  {
292  uint16_t info_idx = 5 + (sdlogger_spi.download_id - 1) * 12;
293  sdlogger_spi.download_address = (sdcard1.input_buf[info_idx+0] << 24) |
294  (sdcard1.input_buf[info_idx+1] << 16) |
295  (sdcard1.input_buf[info_idx+2] << 8) |
296  (sdcard1.input_buf[info_idx+3] << 0);
297  sdlogger_spi.download_length = (sdcard1.input_buf[info_idx+4] << 24) |
298  (sdcard1.input_buf[info_idx+5] << 16) |
299  (sdcard1.input_buf[info_idx+6] << 8) |
300  (sdcard1.input_buf[info_idx+7] << 0);
301  if (sdlogger_spi.download_length > 0) {
302  /* Request the first block */
304  /* After each read block, incr address, decr length */
308  }
309  else {
312  }
314  }
315  break;
316 
317  default:
318  break;
319  }
320 
321 }
322 
329 {
330  /* Increment log length */
332 
333  /* Copy data from logger buffer to SD Card buffer */
334  for (uint8_t i = 0; i < sdlogger_spi.idx; i++) {
336  }
337  /* Set sdcard buffer index to new value */
339  /* And reset the logger buffer index */
340  sdlogger_spi.idx = 0;
341 }
342 
344 {
346  sdlogger_spi.command < 43) {
348  sdcard_spi_read_block(&sdcard1, 0x00002000,
352  }
353  else if (sdcard1.status == SDCard_Idle && sdlogger_spi.command == 255) {
354  telemetry_mode_Main = TELEMETRY_MODE_Main_empty;
356  sdcard_spi_read_block(&sdcard1, 0x00002000, NULL);
360  }
361  /* Always reset command value back to zero */
362  sdlogger_spi.command = 0;
363 }
364 
365 bool sdlogger_spi_direct_check_free_space(struct sdlogger_spi_periph *p, long *fd __attribute__((unused)), uint16_t len)
366 {
367  if (p->status == SDLogger_Logging) {
368  /* Calculating free space in both buffers */
369  if ( (513 - p->sdcard_buf_idx) + (SDLOGGER_BUFFER_SIZE - p->idx) >= len) {
370  return true;
371  }
372  }
373  return false;
374 }
375 
376 void sdlogger_spi_direct_put_byte(struct sdlogger_spi_periph *p, long fd __attribute__((unused)), uint8_t data)
377 {
378  /* SD Buffer full, write in logger buffer */
379  if (p->sdcard_buf_idx > 512) {
380  if (p->idx < SDLOGGER_BUFFER_SIZE) {
381  p->buffer[p->idx++] = data;
382  }
383  /* else: data lost */
384  }
385  /* Writing directly to SD Card buffer */
386  else {
387  sdcard1.output_buf[p->sdcard_buf_idx++] = data;
388 
389  /* Flush buffer */
390  if (p->sdcard_buf_idx > 512 && sdcard1.status == SDCard_MultiWriteIdle) {
392  }
393  }
394 }
395 
397 {
398  int i;
399  for (i = 0; i < len; i++) {
400  sdlogger_spi_direct_put_byte(p, fd, data[i]);
401  }
402 }
403 
404 void sdlogger_spi_direct_send_message(void *p, long fd __attribute__((unused)))
405 {
406  (void) p;
407 }
408 
410  (void) p;
411  return 0;
412 }
413 
415 {
416  (void) p;
417  return 0;
418 }
419 
420 
421 
enum SDLoggerStatus status
unsigned short uint16_t
Definition: types.h:16
Initialization sequence succesful.
Definition: sdcard_spi.h:58
uint8_t buffer[SDLOGGER_BUFFER_SIZE]
void sdlogger_spi_direct_send_message(void *p, long fd)
struct link_device device
uint8_t input_buf[SD_BLOCK_SIZE+10]
The input buffer for the SPI transaction.
Definition: sdcard_spi.h:113
uint8_t sdlogger_spi_direct_get_byte(void *p)
#define DOWNLINK_DEVICE
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
Periodic telemetry system header (includes downlink utility and generated code).
bool autopilot_get_motors_on(void)
get motors status
Definition: autopilot.c:212
void sdlogger_spi_direct_init(void)
sdlogger_spi_direct_init Initialize the logger and SD Card.
int sdlogger_spi_direct_char_available(void *p)
enum SDCardStatus status
The status of the SD card.
Definition: sdcard_spi.h:112
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
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
uint8_t output_buf[SD_BLOCK_SIZE+10]
The output buffer for the SPI transaction.
Definition: sdcard_spi.h:114
bool sdlogger_spi_direct_check_free_space(struct sdlogger_spi_periph *p, long *fd, uint16_t len)
Initialize pprzlog transport.
bool uart_check_free_space(struct uart_periph *p, long *fd, uint16_t len)
Definition: uart_arch.c:954
#define SDLOGGER_BUFFER_SIZE
void sdcard_spi_multiwrite_stop(struct SDCard *sdcard)
Stop with multiwrite procedure.
Definition: sdcard_spi.c:666
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
void sdlogger_spi_direct_stop(void)
void sdcard_spi_periodic(struct SDCard *sdcard)
Periodic function of the SDCard.
Definition: sdcard_spi.c:99
#define LOGGER_LED_OFF
struct sdlogger_spi_periph sdlogger_spi
#define SD_BLOCK_SIZE
Definition: sdcard_spi.h:38
#define DefaultPeriodic
Set default periodic telemetry.
Definition: telemetry.h:66
void sdlogger_spi_direct_multiwrite_written(void)
sdlogger_spi_direct_multiwrite_written Called when a multiwrite is complete.
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
void sdlogger_spi_direct_periodic(void)
sdlogger_spi_direct_periodic Periodic function called at module frequency
void uart_put_byte(struct uart_periph *p, long fd, uint8_t data)
Uart transmit implementation.
Definition: uart_arch.c:972
void sdlogger_spi_direct_start(void)
Core autopilot interface common to all firmwares.
struct SDCard sdcard1
This is the definition of the SD card.
Definition: sdcard_spi.c:56
unsigned char uint8_t
Definition: types.h:14
void sdlogger_spi_direct_index_received(void)
sdlogger_spi_direct_index_received Callback from SD Card when block at index location is received...
void sdlogger_spi_direct_command(void)
int fd
Definition: serial.c:26
arch independent LED (Light Emitting Diodes) API
static float p[2][2]
struct pprzlog_transport pprzlog_tp
PPRZLOG transport structure.
Definition: pprzlog_tp.c:29
#define LOGGER_LED_ON
void sdlogger_spi_direct_put_byte(struct sdlogger_spi_periph *p, long fd, uint8_t data)
void sdlogger_spi_direct_put_buffer(struct sdlogger_spi_periph *p, long fd, uint8_t *data, uint16_t len)
CMD25 complete, ready to sent blocks.
Definition: sdcard_spi.h:84