The application is a controller for a vehicle. The critical part of the software runs on the M4, and some processes on the A7 take care of user interactions and logging. The end product is not meant to be easily accessible during or after the vehicle operation, so signals logged are retrieved using the SCP protocol over the Ethernet interface.
Our system performs some computation on the M4 running FreeRTOS, then forwards the results to the A7 running Linux through shared memory (rpmsg-lite), then logs it to a binary file on the eMMC. We are talking about a relatively small data rate (around 160 kB/s). Analysing the logs, we observed that some data was missing; every 30 s there would be several seconds (up to 7) of missing data. Things we have already implemented:
- Reducing the other Linux processes to
a minimum - Pre-allocating the file size (this helped a lot)
Any idea how we could achieve lossless logging of our data? Should we modify the strategy and log on an SD card?
Here is the code portion that runs in a Linux process where the data is received from the M4 through RPMSG and the log file is written.
const char dev_filename[] = {"/dev/rpmsg_ept12.1"};
const char *log_filename = argv[1];
int32_t log_file_size_max_i32 = strtol(argv[3], NULL, 0);
// Open log file
log_fd_i32 = open(log_filename, O_WRONLY | O_CREAT | O_SYNC);
if(log_fd_i32 < 0) {
enable_log_i = 0U;
}
// Preallocate space for log file
double ratio = (double)sizeof(APSWin_bus_obj) / (double)sizeof(APSWlog_bus_obj);
posix_fallocate(log_fd_i32, 0, (uint32_t)(log_file_size_max_i32 * (1 - ratio)));
// Open logging char device node file
dev_fd_i32 = open(dev_filename, O_RDWR);
if(dev_fd_i32 > -1) {
fds[0].fd = dev_fd_i32;
fds[0].events = POLLIN;
// Initialise communication with the M4
write(dev_fd_i32, &fdi_ui32, sizeof(fdi_ui32));
// Infinite loop
while(run_i) {
// Check if data is already present in the buffer
dev_bytes_read_i32 = read(dev_fd_i32,
read_buffer_i + dev_bytes_read_tot_i32,
READ_SIZE_MAX - dev_bytes_read_tot_i32);
if(dev_bytes_read_i32 == 0) {
retval = poll(fds, 1, -1);
if(retval > 0 &&
!((fds[0].revents & POLLERR) ||
(fds[0].revents & POLLHUP) ||
(fds[0].revents & POLLNVAL))) {
dev_bytes_read_i32 = read(dev_fd_i32,
read_buffer_i + dev_bytes_read_tot_i32,
READ_SIZE_MAX - dev_bytes_read_tot_i32);
}
else {
// FDI Polling error
fdi_ui32 |= 8U;
printf("LLS_LOGa: Polling Error\r\n");
}
}
dev_bytes_read_tot_i32 += dev_bytes_read_i32;
if(dev_bytes_read_tot_i32 > READ_SIZE_MAX) {
printf("LLS_LOGa: Synchronisation lost with the m4 \r\n");
dev_bytes_read_tot_i32 = 0;
}
// Receive logging stucture
if(dev_bytes_read_tot_i32 == sizeof(APSWlog_bus_obj)) {
receive_type_i = 0U;
dev_bytes_read_tot_i32 = 0;
if(enable_log_i == 1U || enable_tlm_i == 1U) {
file_bytes_write_tot_i32 = 0;
file_bytes_write_cur_i32 = 0;
BytePackAPSWlog_bus_obj((APSWlog_bus_obj *) read_buffer_i,
write_buffer_i,
&file_write_len_ui32);
if(enable_log_i == 1U) {
// Loop to make sure all the data is written to the log file
while(file_bytes_write_tot_i32 < file_write_len_ui32) {
// Write to log file
file_bytes_write_cur_i32 = write(log_fd_i32,
write_buffer_i + file_bytes_write_tot_i32,
file_write_len_ui32 - file_bytes_write_tot_i32);
if(file_bytes_write_cur_i32 <= 0) {
// FDI Write error
fdi_ui32 |= 4U;
printf("LLS_LOGa: Write file error\r\n");
enable_log_i = 0U;
enable_inp_i = 0U;
break;
}
file_bytes_write_tot_i32 += file_bytes_write_cur_i32;
}
logfile_bytes_tot_i32 += file_bytes_write_tot_i32;
}
// Send back fdi to M4
if(write(dev_fd_i32, &fdi_ui32, sizeof(fdi_ui32)) != sizeof(fdi_ui32)) {
fdi_ui32 |= 64U;
printf("LLS_LOGa: Send fdi to M4 failed\r\n");
} /*-?|LLS_review_DB_001|beaudette|c3|?*/
else {
fdi_ui32 = 0U;
}
}
}
// Reset file if size exceeds limit
if((logfile_bytes_tot_i32 > log_file_size_max_i32) {
printf("LLS_LOGa: Reset file \r\n");
if(lseek(log_fd_i32, APSWLOG_BUS_OBJ_HEADER_LEN, SEEK_SET) != (APSWLOG_BUS_OBJ_HEADER_LEN)) {
// FDI
fdi_ui32 |= 32U;
printf("LLS_LOGa: Reset file error\r\n");
}
logfile_bytes_tot_i32 = APSWLOG_BUS_OBJ_HEADER_LEN;
}
}
}
// Close opened files
if(log_fd_i32 != -1) {
close(log_fd_i32);
}
if(dev_fd_i32 != -1) {
close(dev_fd_i32);
}
return 0;