diff --git a/README.md b/README.md index 70457168..9a4036e5 100644 --- a/README.md +++ b/README.md @@ -6,15 +6,16 @@ ## Table of Contents -1. [Setup](#setup) - -2. [Battery States](#battery-states) - -3. [Connection States](#connection-states) - -4. [SD Card](#sd-card) - -5. [Citing](#citing) +- [OpenEarable 2 - Firmware](#openearable-2---firmware) + - [Table of Contents](#table-of-contents) + - [Setup](#setup) + - [Battery States](#battery-states) + - [Charging States](#charging-states) + - [Discharging States](#discharging-states) + - [Connection States](#connection-states) + - [SD Card](#sd-card) + - [File Parsing](#file-parsing) + - [Citing](#citing) ## Setup diff --git a/boards/teco/openearable_v2/openearable_v2_nrf5340_cpuapp_common.dts b/boards/teco/openearable_v2/openearable_v2_nrf5340_cpuapp_common.dts index d3796b69..ca836918 100644 --- a/boards/teco/openearable_v2/openearable_v2_nrf5340_cpuapp_common.dts +++ b/boards/teco/openearable_v2/openearable_v2_nrf5340_cpuapp_common.dts @@ -231,6 +231,7 @@ &spi4 { compatible = "nordic,nrf-spim"; status = "okay"; + max-frequency = <32000000>; cs-gpios = <&gpio0 11 GPIO_ACTIVE_LOW>,<&gpio1 1 GPIO_ACTIVE_LOW>; pinctrl-0 = <&spi4_default>; diff --git a/src/SD_Card/SDLogger/SDLogger.cpp b/src/SD_Card/SDLogger/SDLogger.cpp index 35f93c2b..eebf55b5 100644 --- a/src/SD_Card/SDLogger/SDLogger.cpp +++ b/src/SD_Card/SDLogger/SDLogger.cpp @@ -93,6 +93,9 @@ void sd_listener_callback(const struct zbus_channel *chan) state_indicator.set_sd_state(SD_FAULT); LOG_ERR("SD card removed mid recording. Stop recording."); + (void)sdlogger.flush(); + (void)sdlogger.sd_card->sync(); + (void)sdlogger.sd_card->close_file(); // sdlogger.end(); sdlogger.is_open = false; @@ -126,8 +129,27 @@ void SDLogger::sensor_sd_task() { ring_buf_get_claim(&ring_buffer, &data, SD_BLOCK_SIZE); bytes_read = sdlogger.sd_card->write((char*)data, &write_size, false); + uint64_t end_us = micros(); ring_buf_get_finish(&ring_buffer, bytes_read); + if (bytes_read > 0) { + sdlogger.unsynced_bytes += bytes_read; + uint64_t now = end_us; + bool size_gate = (sdlogger.unsynced_bytes >= SYNC_EVERY_BYTES); + bool time_gate = ((now - sdlogger.last_sync_us) >= (uint64_t)SYNC_EVERY_MS * 1000); + + // Optional: only sync when ring is not near full to reduce contention + if ((size_gate || time_gate) && ring_buf_size_get(&ring_buffer) < (BUFFER_SIZE / 4)) { + int sret = sdlogger.sd_card->sync(); + if (sret == 0) { + sdlogger.unsynced_bytes = 0; + sdlogger.last_sync_us = now; + } else { + LOG_WRN("fs_sync deferred: %d", sret); + } + } + } + //k_mutex_unlock(&write_mutex); //fill -= bytes_read; @@ -231,6 +253,9 @@ int SDLogger::begin(const std::string& filename) { k_poll_signal_raise(&logger_sig, 0); + unsynced_bytes = 0; + last_sync_us = micros(); + return 0; } @@ -284,13 +309,15 @@ int SDLogger::write_sensor_data(const sensor_data& msg) { int SDLogger::flush() { uint32_t bytes_read; uint8_t * data; - size_t write_size = SD_BLOCK_SIZE; - uint32_t fill = ring_buf_size_get(&ring_buffer); + if (fill == 0) return 0; - ring_buf_get_claim(&ring_buffer, &data, fill); + // Claim exactly what’s available + uint32_t claimed = ring_buf_get_claim(&ring_buffer, &data, fill); + if (claimed == 0) return 0; - bytes_read = sd_card->write((char*)ring_buffer.buffer, &write_size, false); + size_t write_size = claimed; + bytes_read = sd_card->write((char*)data, &write_size, false); ring_buf_get_finish(&ring_buffer, bytes_read); @@ -322,7 +349,10 @@ int SDLogger::end() { LOG_ERR("Failed to flush file buffer."); return ret; } - + int sret = sd_card->sync(); + if (sret) { + LOG_WRN("Final fs_sync failed: %d", sret); + } LOG_INF("Close File ...."); LOG_DBG("Max buffer fill: %d bytes", count_max_buffer_fill); diff --git a/src/SD_Card/SDLogger/SDLogger.h b/src/SD_Card/SDLogger/SDLogger.h index 1b52e524..97017df9 100644 --- a/src/SD_Card/SDLogger/SDLogger.h +++ b/src/SD_Card/SDLogger/SDLogger.h @@ -54,6 +54,13 @@ class SDLogger { friend void sd_listener_callback(const struct zbus_channel *chan); + // Batching controls + size_t unsynced_bytes = 0; + uint64_t last_sync_us = 0; + // Tunables + static constexpr size_t SYNC_EVERY_BYTES = 32 * 1024; // 32 KB + static constexpr uint32_t SYNC_EVERY_MS = 500; // 0.5 s + public: SDLogger(); ~SDLogger(); diff --git a/src/SD_Card/SD_Card_Manager/SD_Card_Manager.cpp b/src/SD_Card/SD_Card_Manager/SD_Card_Manager.cpp index 9620a2eb..4a45e50d 100644 --- a/src/SD_Card/SD_Card_Manager/SD_Card_Manager.cpp +++ b/src/SD_Card/SD_Card_Manager/SD_Card_Manager.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include "openearable_common.h" @@ -231,6 +232,29 @@ int SDCardManager::mount() { } } + // Set SPI bus frequency to 32MHz + nrf_spim_frequency_set(NRF_SPIM4, NRF_SPIM_FREQ_32M); + + // Log SPI bus frequency (configured max frequency from device tree) + uint32_t spi_max_freq = DT_PROP(DT_NODELABEL(spi4), max_frequency); + LOG_INF("SD card SPI bus frequency: %d Hz (max configured)", spi_max_freq); + + // Log actual SPI bus frequency + uint32_t actual_hz; + switch(nrf_spim_frequency_get(NRF_SPIM4)) { + case NRF_SPIM_FREQ_125K: actual_hz = 125000; break; + case NRF_SPIM_FREQ_250K: actual_hz = 250000; break; + case NRF_SPIM_FREQ_500K: actual_hz = 500000; break; + case NRF_SPIM_FREQ_1M: actual_hz = 1000000; break; + case NRF_SPIM_FREQ_2M: actual_hz = 2000000; break; + case NRF_SPIM_FREQ_4M: actual_hz = 4000000; break; + case NRF_SPIM_FREQ_8M: actual_hz = 8000000; break; + case NRF_SPIM_FREQ_16M: actual_hz = 16000000; break; + case NRF_SPIM_FREQ_32M: actual_hz = 32000000; break; + default: actual_hz = 0; break; + } + LOG_INF("Effective SPI frequency: %d Hz", actual_hz); + ret = k_mutex_lock(&m_sem_sd_mngr_oper_ongoing, K_FOREVER); if (ret) { k_mutex_unlock(&m_sem_sd_mngr_oper_ongoing); @@ -653,7 +677,7 @@ int SDCardManager::rm(std::string path) { } int SDCardManager::sync() { - if (!this->mounted) { + if (!this->mounted || !this->tracked_file.is_open) { return -ENODEV; }