Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
high_speed_logger_direct_memory.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2014 Clement Roblot
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 */
20
29
30#include <string.h>
31
32#include "modules/imu/imu.h"
33#include "mcu_periph/spi.h"
34#include "mcu_periph/uart.h"
35
38
39
40/******************************************************************/
41/* */
42/* Config values, go crazy */
43/* */
44/******************************************************************/
46#define READING_BLOCK_SIZE 200
48#define ERASE_MEMORY_AT_START 0
50#define SIZE_OF_LOGGED_VALUES 4
52#define SIZE_OF_VALUES_NAMES 10
53
58#define SKIP_X_CALLS_BETWEEN_VALUES 0
59
61#define NBR_VALUES_TO_LOG 9
62
65
67 //That list must be pointers to the variables
68 //you want to log
69
70 (uint32_t) &imu.accel_unscaled.x,
71 (uint32_t) &imu.accel_unscaled.y,
72 (uint32_t) &imu.accel_unscaled.z,
73
74 (uint32_t) &imu.gyro_unscaled.p,
75 (uint32_t) &imu.gyro_unscaled.q,
76 (uint32_t) &imu.gyro_unscaled.r,
77
78 (uint32_t) &imu.mag_unscaled.x,
79 (uint32_t) &imu.mag_unscaled.y,
80 (uint32_t) &imu.mag_unscaled.z
81};
82
83
84
87{
88 "acc x",
89 "acc y",
90 "acc z",
91 "gyro p",
92 "gyro q",
93 "gyro r",
94 "mag x",
95 "mag y",
96 "mag z"
97};
98
99
100
101/******************************************************************/
102/* */
103/* Fixed values, do not touch */
104/* */
105/******************************************************************/
107#define MEMORY_READ_LATTENCY 5
109#define TOTAL_MEMORY_SIZE 32
111#define END_OF_MEMORY_THRESHOLD 10
112
113
114//log start-start_of_values-end flags
116uint8_t start_log_sequence[6] = {0xAA, 0x55, 0xFF, 0x00, 0x55, 0xAA};
118uint8_t start_values_sequence[3] = {0xF0, 0xF0, 0xA5};
120uint8_t start_lost_values_sequence[6] = {0x42, 0x0F, 0X42, 0X00, 0XFF, 0xAA};
122uint8_t stop_lost_values_sequence[6] = {0xAA, 0xFF, 0x00, 0x42, 0x0F, 0x42};
123
124
126uint8_t stop_log_sequence[6] = {0xFF, 0x00, 0x55, 0xAA, 0x00, 0xFF};
127
128//low level buffers used to communicate over SPI
130uint8_t buff[25]; //25 is enough even for the reading of the ID (24 values)
137
138//local buffer used to log values
149
150//local status flags
161
162
163//memory management variables
171static volatile bool memory_ready = true;
178
179
182
183
184
185static void memory_transaction_done_cb(struct spi_transaction *trans);
186static void memory_read_status_cb(struct spi_transaction *trans);
187static void memory_read_values_cb(struct spi_transaction *trans);
188
189
190/******************************************************************/
191/* */
192/* Low level function, directly acting with the SPI */
193/* */
194/******************************************************************/
195
216
235
254
273
279static void memory_read_status_cb(struct spi_transaction *trans __attribute__((unused)))
280{
281
282 memory_ready = true;
283
286}
287
294{
295
296 uint8_t *addr = (uint8_t *) &mem_addr;
297
298 memory_ready = false;
299 msg[0] = 0x21;
300 msg[1] = addr[3];
301 msg[2] = addr[2];
302 msg[3] = addr[1];
303 msg[4] = addr[0];
304
307
310
312
314}
315
335
370
378{
379
380 uint8_t *addr = (uint8_t *) &mem_addr;
381
382 memory_ready = false;
383 msg[0] = 0x13;
384 msg[1] = addr[3];
385 msg[2] = addr[2];
386 msg[3] = addr[1];
387 msg[4] = addr[0];
388
391
394 MEMORY_READ_LATTENCY; //the first MEMORY_READ_LATTENCY Bytes are lost because of reading to soon
395
397
399}
400
406static void memory_read_values_cb(struct spi_transaction *trans __attribute__((unused)))
407{
408
410
411 memory_ready = true;
412
413 if (msg_size) {
414
415 if (is_sequence_in_array(uart_read_buff, msg_size, stop_log_sequence, 6)) { //this is the end of the log
416
419
420 } else { //this is not the end of the log
421
423 }
424
427 }
428}
429
435static void memory_transaction_done_cb(struct spi_transaction *trans __attribute__((unused)))
436{
437 memory_ready = true;
438}
439
440
441
442
443/******************************************************************/
444/* */
445/* Mid low level functions, abstracting the low SPI layer */
446/* */
447/******************************************************************/
448
463{
465 static uint32_t previus_mem_addr = 0;
466 static uint8_t *previus_values = NULL;
467 static uint8_t previus_size = 0;
468
469
470 //test if we are stating a new writting cicle
472 ((previus_mem_addr != mem_addr) || (previus_values != values) || (previus_size != size))) {
473
476 previus_values = values;
477 previus_size = size;
478 }
479
481
482 case 0 :
483 //waiting for something to do
484 break;
485
486 case 1 :
489 //break;
490 //we imediatly send the values after this message.
491 //The low level functions are not using the same buffers
492 //so we can do it
493
494 case 2 :
495 memory_write_values(mem_addr, values, size);
498 break;
499
500 case 3 :
501 memory_read_status_1(); //we wait for the writting to be done
504 } else { //the writting has been completed
506 }
507 break;
508
509 default :
510 break;
511 }
512
514}
515
516
529{
530
532
534
535 case 0 :
538 break;
539
540 case 1 :
544 break;
545
546 case 2 :
547 memory_read_status_1(); //we wait for the writting to be done
550 } else { //the erasing have been completed
552 }
553 break;
554
555 default :
556 break;
557 }
558
560}
561
562
574{
575
577
578 switch (ml_erase_memory_status) {
579
580 case 0 :
583 break;
584
585 case 1 :
589 break;
590
591 case 2 :
592 memory_read_status_1(); //we wait for the writting to be done
595 } else { //the erasing have been completed
597 }
598 break;
599
600 default : break;
601 }
602
604}
605
606
618
619
620
621
622
623/******************************************************************/
624/* */
625/* Mid high level function : memory management */
626/* */
627/******************************************************************/
628
644{
645
651
653
654 while (!wait_for_SPI) {
655
656 switch (append_to_memory_status) {
657
658 case 0 :
660 if ((current_unerased_addr - current_writting_addr) > size) { //we got enough cleared space to write the value
661
663 } else {
664
666
667 current_unerased_addr += 4096; //65536
668 } else {
669
670 wait_for_SPI = 1;
671 }
672 }
673 } else {
674
676 }
677 break;
678
679
680 case 1 :
681 //we start writting the values
682 //need to fit the values in pages of 4K
683
684 //256 bytes per pages
687
691
692 if (size_to_write > 250) { size_to_write = 250; } //protection against overflows in the lower levels
693
694 if (size_to_write > 0) {
695
697
700
701 if (index_value_unwritten == size) {
702
705 return_code = 0;
706 }
707
708 //test is we are close to the end of the memory
710 //if we got less than END_OF_MEMORY_THRESHOLD kilo Bytes of mem left
711
712 logging_status_gui = 3; //we stop the logging
713 }
714
715
716 }
717
718 wait_for_SPI = 1;
719 }
720 break;
721
722 default:
723 break;
724 }
725 }
726
727 return return_code;
728}
729
730
731
739{
740
742 static uint8_t i = MEMORY_READ_LATTENCY;
743 long fd = 0;
744
746
747 while (uart_check_free_space(&HS_LOG_UART, &fd, 1)) {
748
749 if (i >= msg_size) {
750
754
757 }
758 break;
759 }
761 i++;
762 }
763
764 } else {
765
770 }
771 }
772}
773
774
775
787{
788
790
791 if (*size > 0) {
792 if (!append_values_to_memory(buffer, *size)) {
793 *size = 0;
794 return_code = 0;
795 }
796 } else {
797 return_code = 0;
798 }
799
800 return return_code;
801}
802
803
804
805
806/******************************************************************/
807/* */
808/* High level function : local buffer management */
809/* */
810/******************************************************************/
811
823{
824 if (buffer_used) {
825
826 if (nbr_values_in_buffer_sending < 0xFF) {
829 } else {
831 }
832
833 } else {
834
835 if (nbr_values_in_buffer < 0xFF) {
838 } else {
840 }
841 }
842}
843
855{
856 uint8_t i;
857
858 for (i = 0; i < size; i++) {
860 }
861}
862
922
923
924
929{
931
933 return_value = 1;
934 }
935
936 return return_value;
937}
938
939
940
941
942/******************************************************************/
943/* */
944/* High level function : log management */
945/* */
946/******************************************************************/
947
962{
963
964 static uint8_t start_log_status = 0;
966
968 uint8_t i;
969
970 for (i = 0; i < NBR_VALUES_TO_LOG; i++) {
971
973 if (i != (NBR_VALUES_TO_LOG - 1)) { strcat(msg_names, ";"); } //we don't put a ';' at the end of the list
974 }
975
976 switch (start_log_status) {
977
978 case 0 :
979 current_writting_addr = 0x00000000; //restart the writting at the begining of the memory
980 current_unerased_addr = 0x00000000;
981
983
985
987 }
988 } else {
989
991 }
992 break;
993
994
995 case 1 :
999 break;
1000
1001 case 2 :
1003 start_log_status = 3;
1004 break;
1005
1006 case 3 :
1008 start_log_status = 0;
1009 return_code = 0;
1010 break;
1011
1012 default :
1013 break;
1014 }
1015
1016 return return_code;
1017}
1018
1019
1027{
1029 uint8_t i, j;
1030
1031 for (i = 0; i < NBR_VALUES_TO_LOG; i++) {
1032
1034
1035 for (j = 0; j < SIZE_OF_LOGGED_VALUES; j++) {
1036
1038 }
1039 }
1040}
1041
1042
1046void run_logger(void)
1047{
1048 static uint8_t i = 0;
1049 //useless variable. It simply remove a warning when SKIP_X_CALLS_BETWEEN_VALUES=0 and the test is always true
1051
1052 if (i >= limit) { //3 with erase memory, 0 WITHOUT SKIP_X_CALLS_BETWEEN_VALUES
1054 i = 0;
1055 }
1056 i++;
1057}
1058
1059
1071{
1073
1074 if (are_buffers_empty()) { //if the buffers are empty to prevent from writting during a buffer overflow
1076 return_value = 0;
1077 }
1078
1079 return return_value;
1080}
1081
1082
1083
1084
1085/******************************************************************/
1086/* */
1087/* Module function */
1088/* */
1089/******************************************************************/
1090
1091
1096{
1097 //init the SPI to communicat with the memory
1111
1113
1114
1128
1129
1130
1131 //init the UART to send the values back to the computer
1134}
1135
1136
1137
1142{
1144
1145 //UART part (communication with the computer to dump the memory)
1147
1149
1150 if (uart_received == 'A') {
1153
1154 } else if (uart_received == 'B') {
1156 }
1157 }
1158
1159
1160 //SPI part (to log the values on the memory when in flight)
1161 if (memory_ready) {
1162
1163 switch (logging_status_gui) {
1164
1165 case 0 :
1166 //idle state, nothing to do
1167 break;
1168
1169 case 1 :
1170 //start a new log
1171 if (!start_new_log()) { logging_status_gui = 0; }
1172 break;
1173
1174 case 2 :
1175 //logging values
1176 run_logger();
1177 break;
1178
1179 case 3 :
1180 //finishing the log
1181 if (!end_log()) { logging_status_gui = 0; }
1182 break;
1183
1184 default :
1185 break;
1186 }
1187
1189 }
1190
1191 //this function regulats itself, we have to call it at every iteration of the module
1193}
1194
1195
1196
1197/******************************************************************/
1198/* */
1199/* Other functions */
1200/* */
1201/******************************************************************/
1202
1218{
1220 static uint8_t current_sequence_id = 0;
1221
1222 for (i = MEMORY_READ_LATTENCY; i < array_size; i++) {
1223
1224 if (array[i] == sequence[current_sequence_id]) {
1228 return 1;
1229 }
1230 } else {
1232 }
1233 }
1234
1235 return 0;
1236}
1237
1238
enum SPIClockPolarity cpol
clock polarity control
Definition spi.h:155
enum SPIClockPhase cpha
clock phase control
Definition spi.h:156
enum SPISlaveSelect select
slave selection behavior
Definition spi.h:154
SPICallback after_cb
NULL or function called after the transaction.
Definition spi.h:161
enum SPIDataSizeSelect dss
data transfer word size
Definition spi.h:157
volatile uint8_t * output_buf
pointer to transmit buffer for DMA
Definition spi.h:150
uint16_t input_length
number of data words to read
Definition spi.h:151
enum SPIClockDiv cdiv
prescaler of main clock to use as SPI clock
Definition spi.h:159
volatile uint8_t * input_buf
pointer to receive buffer for DMA
Definition spi.h:149
uint8_t slave_idx
slave id: SPI_SLAVE0 to SPI_SLAVE4
Definition spi.h:153
enum SPIBitOrder bitorder
MSB/LSB order.
Definition spi.h:158
uint16_t output_length
number of data words to write
Definition spi.h:152
bool spi_submit(struct spi_periph *p, struct spi_transaction *t)
Submit SPI transaction.
Definition spi_arch.c:533
@ SPICphaEdge2
CPHA = 1.
Definition spi.h:75
@ SPICpolIdleHigh
CPOL = 1.
Definition spi.h:84
@ SPISelectUnselect
slave is selected before transaction and unselected after
Definition spi.h:63
@ SPIMSBFirst
Definition spi.h:112
@ SPIDiv64
Definition spi.h:125
@ SPIDss8bit
Definition spi.h:90
SPI transaction structure.
Definition spi.h:148
void memory_write_values(uint32_t mem_addr, uint8_t *values, uint8_t size)
Function sending a request to write a buffer of values to the memory.
static void memory_read_values_cb(struct spi_transaction *trans)
Callback function decrypting the read values from the memory.
char ** name_of_the_values
list of the names of the messages you are logging
uint8_t start_new_log(void)
Function starting a new log.
#define READING_BLOCK_SIZE
size of the block that we read in the memory and send over UART. MAX = 250.
void ml_read_log_in_memory(void)
Function continuing the reading of the current log in memory.
uint8_t run_memory_management(void)
Function sending the buffer to the memory when possible.
static void memory_read_status_cb(struct spi_transaction *trans)
Callback function decrypting the status Byte of the memory.
void high_speed_logger_direct_memory_init(void)
Function initialisating the module.
uint8_t end_log(void)
Function ending the current log.
void memory_erase_4k(uint32_t mem_addr)
Function sending a request to erase 4KB of the memory.
uint32_t current_writting_addr
The address at wich we will write next time.
uint8_t sending_buffer_to_uart
Flag defining if we are sending values through the UART.
void add_array_to_buffer(uint8_t *array, uint8_t size)
Function adding an array to the local buffer.
#define TOTAL_MEMORY_SIZE
nbr of MB in the memory
void memory_read_values(uint32_t mem_addr, uint8_t size)
Function sending a request to read some values in memory.
uint8_t uart_read_buff[READING_BLOCK_SIZE+MEMORY_READ_LATTENCY]
Buffer used to fetch the values from the memory.
struct spi_transaction memory_send_value_transaction
Structure used for sending values to the memory.
uint8_t are_buffers_empty(void)
Function returning true if the two local buffers are empty.
#define SIZE_OF_VALUES_NAMES
size (in characters) of the nameof the logged values.
uint8_t msg[10]
Buffer used for general comunication over SPI (out buffer)
struct spi_transaction memory_transaction
Structure used for general comunication with the memory.
uint32_t nbr_lost_values
Number of Bytes we have lost due to overflows (reseted each time we can write agin in the buffer)
uint8_t start_lost_values_sequence[6]
Start sequence indicating we have lost some Bytes due to overflows.
#define SKIP_X_CALLS_BETWEEN_VALUES
Skip X values between write.
static volatile bool memory_ready
Flag stating if the memory is being used.
void memory_read_status_1(void)
Function sending a request to fetch the status Byte of the memory.
uint8_t nbr_values_in_buffer
Number of Bytes in the first buffer (buffer_values_logged)
void memory_completly_erase(void)
Function sending a request to erase the entire memory.
#define MEMORY_READ_LATTENCY
nbr of Bytes 0x00 received before the real values when reading the memory
uint8_t ml_erase_completely_memory(void)
Function erasing the entire memory.
void add_values_to_buffer(void)
Function adding the configured messages to the buffers of the values to be written in memory.
void memory_read_id(void)
Function sending a request for the ID of the memory chip.
#define NBR_VALUES_TO_LOG
nbr of messages you want to log
uint8_t start_values_sequence[3]
Start sequence written at the begining of the values of a log (after the header)
uint8_t ml_write_values_to_memory(uint32_t mem_addr, uint8_t *values, uint8_t size)
Function writting a buffer of values to the memory.
#define SIZE_OF_LOGGED_VALUES
size (in bytes) of the values we log.
static void memory_transaction_done_cb(struct spi_transaction *trans)
generic allback function for SPI transactions
uint8_t values_send_buffer[256]
Buffer used for sending value to the memory.
uint8_t buff[25]
Buffer used for general comunication over SPI (in buffer)
uint8_t stop_log_sequence[6]
Stop sequence written at the end of the log.
void high_speed_logger_direct_memory_periodic(void)
Main function of the module.
void memory_send_wren(void)
Function sending a request to set the writte enable flag in the memory.
uint8_t buffer_values_sending[256]
Second local buffer for the log.
uint32_t values_to_log[NBR_VALUES_TO_LOG]
list of the messages you want to log
void send_buffer_to_uart(void)
Function sending the read values from the memory to te UART.
uint8_t ml_erase_4k_on_memory(uint32_t mem_addr)
Function erasing 4KB of the memory.
uint8_t start_log_sequence[6]
Start sequence written at the begining of a log.
uint8_t send_buffer_to_memory(uint8_t *buffer, uint8_t *size)
Function sending a buffer ot the memory.
#define ERASE_MEMORY_AT_START
if we completly erase the memory at the start of the log.
uint8_t relaunch_reading_memory
Flag defining if we need to keep reading the memory (if the stop sequence is found we stop)
#define END_OF_MEMORY_THRESHOLD
the nbr of kilo Bytes left at the end of the memory before stoping the log automaticaly
void memory_send_wrdi(void)
Function sending a request to clear the writte enable flag in the memory.
uint8_t is_sequence_in_array(uint8_t *array, uint8_t array_size, uint8_t *sequence, uint8_t sequence_size)
Function testing if a sequence is in a buffer of values.
uint32_t current_unerased_addr
The address of the next block to erase.
uint8_t logging_status_gui
Status of the module.
uint8_t nbr_values_in_buffer_sending
Number of Bytes in the second buffer (nbr_values_in_buffer_sending)
uint8_t wait_answear_from_reading_memory
Flag defining if we are waiting for an answear from the memory when reading values from it.
uint8_t buffer_values_logged[256]
First local buffer for the log.
uint8_t buffer_used
Flag defining wich buffer is used.
uint8_t stop_lost_values_sequence[6]
Stop sequence indicating we have lost some Bytes due to overflows.
uint8_t memory_status_byte
Last status Byte read from the memory.
void run_logger(void)
Funcion called to add the values to log to the buffer with a frequency divider in order to not overfl...
void high_speed_logger_direct_memory_handler(uint8_t val)
Function managing the interface with the user.
void add_byte_to_buffer(uint8_t value)
Function adding a Byte to the local buffer.
uint32_t current_reading_addr
The address at wich we will read next time.
uint8_t append_values_to_memory(uint8_t *values, uint8_t size)
Function adding a buffer of values to the memory.
uint8_t continue_reading_memory
Flag defining if we need to keep reading the memory (if the PC asked for new values)
struct Imu imu
global IMU state
Definition imu.c:422
Inertial Measurement Unit interface.
void uart_put_byte(struct uart_periph *periph, long fd, uint8_t data)
Definition uart_arch.c:306
int uart_char_available(struct uart_periph *p)
Check UART for available chars in receive buffer.
Definition uart_arch.c:357
void uart_periph_set_bits_stop_parity(struct uart_periph *periph, uint8_t bits, uint8_t stop, uint8_t parity)
Definition uart_arch.c:296
uint8_t uart_getch(struct uart_periph *p)
Definition uart_arch.c:348
uint16_t foo
Definition main_demo5.c:58
int fd
Definition serial.c:26
int * array
Architecture independent SPI (Serial Peripheral Interface) API.
Periodic telemetry system header (includes downlink utility and generated code).
uint16_t val[TCOUPLE_NB]
void uart_periph_init(struct uart_periph *p)
Definition uart.c:126
int WEAK uart_check_free_space(struct uart_periph *p, long *fd, uint16_t len)
Definition uart.c:151
arch independent UART (Universal Asynchronous Receiver/Transmitter) API
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.