Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
- In the **APPLICATIONS** section of the nRF Connect extension tab:
- Select the `open-earable-2` application
- Click **"+ Add build configuration"** to set up a new build
- Select the SDK version 3.0.1, toolchain version 3.0.1, and `open-earable-2/nrf5340/cpuapp` as board target
- Select the SDK version 3.0.1, toolchain version 3.0.1, and `openearable_v2/nrf5340/cpuapp` as board target
- To build **with FOTA** (firmware over-the-air update functionality):
- Leave the `Base configuration files (Kconfig fragments)` dropdown empty
- as `Extra CMAKE arguments` set `-DFILE_SUFFIX="fota"`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
Expand Down
40 changes: 35 additions & 5 deletions src/SD_Card/SDLogger/SDLogger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand Down
7 changes: 7 additions & 0 deletions src/SD_Card/SDLogger/SDLogger.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
26 changes: 25 additions & 1 deletion src/SD_Card/SD_Card_Manager/SD_Card_Manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <string.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/devicetree.h>
#include <hal/nrf_spim.h>

#include "openearable_common.h"

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}

Expand Down