This describes a concept for a new SDLogger, so we can discuss it before it is actually implemented. New logger uses the previously committed sdcard_spi peripheral.
It also uses pprzlog_transport for transporting messages.
The logger itself is a device to which paparazzi messages can be written, like this:
`DOWNLINK_SEND_IMU_ACCEL_SCALED(pprzlog_tp, sdlogger_spi, data...);`
Thereby it is possible to send messages at anytime from anywhere in the code. Although it is not really DOWNLINK, this macro is generally used to direct messages to a device. In this case, the device is an SD Logger. I would also be fine with using `pprz_msg_send_MESSAGE();`
And the logger is implemented as a module. Its periodic tasks is to run the sdcard periodic task.
By implementing it as a device like this, it is also easy to make it compatible with periodic “telemetry”.
All bytes of a block on the SDCard are used (512 bytes). Messages may be split over subsequent blocks.
To have some sort of a filesystem, a few blocks at the beginning can be reserved to contain information on present data. Thereby, it should be possible to start a new log without overwriting the previous one.
TODO: Describe how data is retrieved from the SDCard and sent over by true telemetry.
Modified/new files
|-sw/airborne/modules/loggers | |-sdlogger_spi.h | |-sdlogger_spi.c |-sw/airborne/subsystems/datalink | |-datalink.h
Below is the general idea/concept of each file
sdlogger_spi.h
#include "sdcard_spi.h" struct sdlogger_spi { uint8_t buffer[64]; ///< Number is a fraction of 512. Data copied to sdcard-buffer when full. uint16_t buf_idx; uint16_t ore; ///< Overrun error counter. struct link_device device; };
sdlogger_spi.c
/* * If SDCard is busy writing, return number of bytes left in sdlogger_spi.buffer. * Else, return total number of bytes left in both SDCard buffer and sdlogger_spi.buffer (64) */ bool_t sdlogger_spi_check_free_space(struct sdlogger_spi *p, uint8_t len); /* * Put the byte in the SDCard buffer directly. * If SDCard is currently busy (writing previous data), put it in the sdlogger_spi.buffer * When SDCard is no longer busy, copy sdlogger_spi.buffer content to SDCard buffer. */ void sdlogger_spi_put_byte(struct sdlogger_spi *p, uint8_t data); static void null_function(struct sdlogger_spi *p __attribute__((unused))) {} // Initialization function void sdlogger_spi_init(struct sdlogger_spi *p) { // Set structure initial values, including .device functions // These are called from functions in pprzlog_transport.c p->device.periph = (void *)p; p->device.check_free_space = (check_free_space_t)sdlogger_spi_check_free_space; p->device.put_byte = (put_byte_t)sdlogger_spi_put_byte; p->device.send_message = (send_message_t)null_function; p->device.char_available not used atm p->device.get_byte not used atm }
downlink.h
+ #ifdef USE_SDLOGGER_SPI + #include "sdlogger_spi.h" + #endif
Defines required
USE_PPRZLOG USE_SDLOGGER_SPI
Usage example imu.c
// Already present (in many files): #include "subsystems/datalink/telemetry.h" ///<< Includes datalink.h << Now includes sdlogger_spi.h DOWNLINK_SEND_IMU_ACCEL_SCALED(pprzlog_tp, sdlogger_spi, data...);
Got feedback from Felix to use pprz_msg_send_MESSAGE(); instead of the DOWNLINK_SEND_* macro.