File write (-22) using External flash zephyr

Hello, 

I am trying to write data into an external flash memory using a custom board (NRF52840-QFAA). 

The external flash is the W25Q256JVEIQ. I get a fs_write (-22) error at random times when writing to the file. 

I have set the partition to 28MB and I am writing around 1-2MB of data inside the memory. 

Please see my main file, prj.conf, device tree, pm_static.yml and the error I get

Can someone help me deduce the issue? 
It would usually start letting me write if I reformat, but I dont want to reformat the memory because data will be lost. 

[00:02:30.597,656] <inf> main: Synced to flash [00:02:31.478,820] <inf> main: Synced to flash [00:02:32.270,019] <inf> main: Synced to flash [00:02:33.162,933] <inf> main: Synced to flash [00:02:33.965,911] <inf> main: Synced to flash [00:02:34.774,444] <inf> main: Synced to flash [00:02:35.588,989] <inf> main: Synced to flash [00:02:36.408,905] <inf> main: Synced to flash [00:02:37.234,497] <inf> main: Synced to flash [00:02:38.116,210] <inf> main: Synced to flash [00:02:38.908,172] <inf> main: Synced to flash [00:02:39.705,780] <inf> main: Synced to flash [00:02:39.926,788] <err> fs: file write error (-22) [00:02:39.927,093] <err> main: fs_write failed (-22) [00:02:39.927,398] <wrn> main: Write returned -EINVAL; attempting FS recovery [00:02:39.927,825] <inf> littlefs: /lfs unmounted [00:02:39.928,131] <inf> littlefs: LittleFS version 2.9, disk version 2.1 [00:02:39.928,527] <inf> littlefs: FS at SPI_FLASH:0x0 is 7168 0x1000-byte blocks with 512 cycle [00:02:39.928,985] <inf> littlefs: sizes: rd 16 ; pr 256 ; ca 256 ; la 128 [00:02:39.943,023] <wrn> main: Filesystem recovery complete [00:02:40.177,398] <err> fs: file write error (-22) [00:02:40.177,703] <err> main: fs_write failed (-22) [00:02:40.178,009] <wrn> main: Write returned -EINVAL; attempting FS recovery [00:02:40.178,436] <inf> littlefs: /lfs unmounted [00:02:40.178,741] <inf> littlefs: LittleFS version 2.9, disk version 2.1 [00:02:40.179,138] <inf> littlefs: FS at SPI_FLASH:0x0 is 7168 0x1000-byte blocks with 512 cycle [00:02:40.179,595] <inf> littlefs: sizes: rd 16 ; pr 256 ; ca 256 ; la 128 [00:02:40.193,634] <wrn> main: Filesystem recovery complete [00:02:40.428,009] <err> fs: file write error (-22) [00:02:40.428,314] <err> main: fs_write failed (-22) [00:02:40.428,619] <wrn> main: Write returned -EINVAL; attempting FS recovery

// #include <zephyr/kernel.h>
// #include <zephyr/device.h>
// #include <zephyr/drivers/gpio.h>
// #include <zephyr/drivers/pwm.h>
// #include <zephyr/fs/fs.h>
// #include <zephyr/fs/littlefs.h>
// #include <zephyr/storage/flash_map.h>
// #include <zephyr/logging/log.h>
// #include <string.h>
// #include <errno.h>
// #include <stdint.h>
// #include <stdbool.h>
// #include <zephyr/drivers/flash.h>
// #include "clock_bt_setup.h"
// #include "sensor_fusion.h"
// #include "bluetooth_conn.h"

// LOG_MODULE_REGISTER(main, LOG_LEVEL_INF);

// /* =========================
//  * Flash / FS
//  * ========================= */
// #define LFS_PARTITION_ID FLASH_AREA_ID(lfs_partition)

// static struct fs_littlefs lfs_cfg = {
// 	.cfg = {
// 		.read_size = 16,
// 		.prog_size = 16,
// 		.cache_size = 256,
// 		.lookahead_size = 128,
// 		.block_cycles = 512,
// 	}
// };

// static struct fs_mount_t littlefs_mnt = {
// 	.type = FS_LITTLEFS,
// 	.fs_data = &lfs_cfg,
// 	.storage_dev = (void *)LFS_PARTITION_ID,
// 	.mnt_point = "/lfs",
// };

// /* =========================
//  * Hardware
//  * ========================= */
// #define LED_G_NODE DT_PATH(pwmleds, led_g)
// #define LED_B_NODE DT_PATH(pwmleds, led_b)

// static const struct pwm_dt_spec pwm_g = PWM_DT_SPEC_GET(LED_G_NODE);
// static const struct pwm_dt_spec pwm_b = PWM_DT_SPEC_GET(LED_B_NODE);

// #define EXT_SWITCH_NODE DT_PATH(buttons, ext_switch)
// #define SWITCH_NODE DT_PATH(buttons, sw1)

// static const struct gpio_dt_spec ext_switch =
// 	GPIO_DT_SPEC_GET(EXT_SWITCH_NODE, gpios);
// static const struct gpio_dt_spec sw1 =
// 	GPIO_DT_SPEC_GET(SWITCH_NODE, gpios);

// /* =========================
//  * Buttons
//  * ========================= */
// #define BUTTON_POLL_MS         10
// #define BUTTON_DEBOUNCE_MS     40
// #define MULTICLICK_TIMEOUT_MS  500
// #define LONG_PRESS_MS          1500

// /* =========================
//  * Logging config
//  * ========================= */
// #define RECORDS_PER_BUFFER     1
// #define SYNC_INTERVAL_BYTES    4096
// #define SAMPLE_INTERVAL_MS     20
// #define LOG_SEGMENT_MS         (5 * 60 * 1000)
// #define LOG_RESTART_DELAY_MS   1000
// #define TOTAL_LOG_TIME_MS      (1 * 60 * 1000)
// #define LOG_FILE_PATH          "/lfs/imu.bin"

// /* =========================
//  * Logging buffer/state
//  * ========================= */
// static size_t total_records_logged = 0;
// static sensor_sample_t record_buffer[RECORDS_PER_BUFFER]__aligned(16);
// static size_t buffer_index = 0;
// static size_t bytes_since_sync = 0;

// /* =========================
//  * LED Helpers
//  * ========================= */
// static void green_on(void)
// {
// 	(void)pwm_set_dt(&pwm_g, pwm_g.period, 0);
// }

// static void green_off(void)
// {
// 	(void)pwm_set_dt(&pwm_g, pwm_g.period, pwm_g.period);
// }

// static void blue_on(void)
// {
// 	(void)pwm_set_dt(&pwm_b, pwm_b.period, 0);
// }

// static void blue_off(void)
// {
// 	(void)pwm_set_dt(&pwm_b, pwm_b.period, pwm_b.period);
// }

// /* =========================
//  * Button Helpers
//  * ========================= */
// static bool button_pressed(const struct gpio_dt_spec *btn)
// {
// 	int val = gpio_pin_get_dt(btn);
// 	return (val > 0);
// }

// static void wait_for_release(const struct gpio_dt_spec *btn)
// {
// 	while (button_pressed(btn)) {
// 		k_msleep(BUTTON_POLL_MS);
// 	}
// }

// static uint8_t wait_for_clicks(const struct gpio_dt_spec *btn,
// 			       uint8_t min, uint8_t max)
// {
// 	uint8_t count = 0;
// 	int64_t last = 0;
// 	bool prev = button_pressed(btn);

// 	wait_for_release(btn);

// 	while (1) {
// 		bool now = button_pressed(btn);

// 		if (now && !prev) {
// 			k_msleep(BUTTON_DEBOUNCE_MS);
// 			now = button_pressed(btn);

// 			if (now) {
// 				count++;
// 				last = k_uptime_get();
// 				LOG_INF("Button click count = %u", count);
// 			}
// 		}

// 		if (count >= min) {
// 			if ((k_uptime_get() - last) > MULTICLICK_TIMEOUT_MS) {
// 				return count;
// 			}
// 		}

// 		if (count >= max) {
// 			return count;
// 		}

// 		prev = now;
// 		k_msleep(BUTTON_POLL_MS);
// 	}
// }

// /* =========================
//  * Boot Mode
//  * ========================= */
// enum mode {
// 	MODE_IDLE,
// 	MODE_SYNC,
// 	MODE_LOG,
// 	MODE_TRANSFER
// };

// static enum mode wait_for_mode(void)
// {
// 	LOG_INF("Waiting for input: SW1 x2=SYNC, SW1 long press=LOG, EXT x2=TRANSFER");

// 	while (1) {
// 		if (button_pressed(&sw1)) {
// 			k_msleep(BUTTON_DEBOUNCE_MS);

// 			if (button_pressed(&sw1)) {
// 				int64_t press_start = k_uptime_get();

// 				while (button_pressed(&sw1)) {
// 					if ((k_uptime_get() - press_start) >= LONG_PRESS_MS) {
// 						LOG_INF("SW1 long press detected");
// 						wait_for_release(&sw1);
// 						return MODE_LOG;
// 					}
// 					k_msleep(BUTTON_POLL_MS);
// 				}

// 				uint8_t c = wait_for_clicks(&sw1, 2, 2);
// 				if (c == 2) {
// 					return MODE_SYNC;
// 				}
// 			}
// 		}

// 		if (button_pressed(&ext_switch)) {
// 			uint8_t c = wait_for_clicks(&ext_switch, 2, 2);
// 			if (c == 2) {
// 				return MODE_TRANSFER;
// 			}
// 		}

// 		k_msleep(10);
// 	}
// }

// /* =========================
//  * FS Helpers
//  * ========================= */
// static int mount_fs_no_format(void)
// {
// 	int rc = fs_mount(&littlefs_mnt);
// 	if (rc == 0) {
// 		LOG_INF("LittleFS mounted");
// 		return 0;
// 	}

// 	LOG_ERR("LittleFS mount failed (%d)", rc);
// 	return rc;
// }

// static void log_flash_params(void)
// {
// 	const struct flash_area *fa;
// 	int rc = flash_area_open(LFS_PARTITION_ID, &fa);
// 	if (rc < 0) {
// 		LOG_ERR("flash_area_open failed (%d)", rc);
// 		return;
// 	}

// 	const struct device *flash_dev = fa->fa_dev;
// 	if (!device_is_ready(flash_dev)) {
// 		LOG_ERR("Flash device not ready");
// 		flash_area_close(fa);
// 		return;
// 	}

// 	const struct flash_parameters *params = flash_get_parameters(flash_dev);
// 	size_t wbs = flash_get_write_block_size(flash_dev);

// 	LOG_INF("flash write_block_size=%u erase_value=0x%02x",
// 		(unsigned int)wbs,
// 		(unsigned int)params->erase_value);

// 	flash_area_close(fa);
// }

// static int format_and_mount_fs(void)
// {
// 	int rc;

// 	rc = fs_mkfs(FS_LITTLEFS, (uintptr_t)LFS_PARTITION_ID, &lfs_cfg, 0);
// 	if (rc < 0) {
// 		LOG_ERR("fs_mkfs failed (%d)", rc);
// 		return rc;
// 	}

// 	LOG_INF("LittleFS formatted");

// 	rc = fs_mount(&littlefs_mnt);
// 	if (rc < 0) {
// 		LOG_ERR("Mount after format failed (%d)", rc);
// 		return rc;
// 	}

// 	LOG_INF("LittleFS mounted after format");
// 	return 0;
// }

// static int open_log_file(struct fs_file_t *file, bool truncate_file)
// {
// 	int rc;

// 	fs_file_t_init(file);

// 	if (truncate_file) {
// 		rc = fs_open(file, LOG_FILE_PATH,
// 			     FS_O_CREATE | FS_O_TRUNC | FS_O_RDWR);
// 		if (rc < 0) {
// 			LOG_ERR("File open (truncate) failed (%d)", rc);
// 			return rc;
// 		}

// 		LOG_INF("Opened %s as new file", LOG_FILE_PATH);
// 		return 0;
// 	}

// 	rc = fs_open(file, LOG_FILE_PATH,
// 		     FS_O_CREATE | FS_O_APPEND | FS_O_RDWR);
// 	if (rc < 0) {
// 		LOG_ERR("File open (append) failed (%d)", rc);
// 		return rc;
// 	}

// 	off_t pos = fs_tell(file);
// 	LOG_INF("Opened %s for append, current pos=%lld bytes",
// 		LOG_FILE_PATH, (long long)pos);

// 	return 0;
// }

// static int flush_buffer(struct fs_file_t *file)
// {
// 	if (buffer_index == 0) {
// 		return 0;
// 	}

// 	size_t total_size = buffer_index * sizeof(sensor_sample_t);
// 	uint8_t *p = (uint8_t *)record_buffer;
// 	size_t remaining = total_size;

// 	off_t before = fs_tell(file);
// 	LOG_INF("flush_buffer: buffer_index=%u total_size=%u file_pos_before=%lld",
// 		(unsigned int)buffer_index,
// 		(unsigned int)total_size,
// 		(long long)before);

// 	while (remaining > 0) {
// 		size_t chunk = (remaining > 48) ? 48 : remaining;

// 		ssize_t written = fs_write(file, p, chunk);
// 		if (written < 0) {
// 			LOG_ERR("fs_write failed (%d) on chunk=%u file_pos_before_fail=%lld",
// 				(int)written,
// 				(unsigned int)chunk,
// 				(long long)fs_tell(file));
// 			return (int)written;
// 		}

// 		if ((size_t)written != chunk) {
// 			LOG_ERR("fs_write short (%d/%u)", (int)written,
// 				(unsigned int)chunk);
// 			return -EIO;
// 		}

// 		p += chunk;
// 		remaining -= chunk;
// 		bytes_since_sync += chunk;
// 	}

// 	buffer_index = 0;

// 	off_t after = fs_tell(file);
// 	LOG_INF("flush_buffer: file_pos_after=%lld", (long long)after);

// 	/* diagnostic: sync every flush */
// 	int rc = fs_sync(file);
// 	if (rc < 0) {
// 		LOG_ERR("fs_sync failed (%d)", rc);
// 		return rc;
// 	}

// 	bytes_since_sync = 0;
// 	LOG_INF("Synced to flash");

// 	return 0;
// }

// static int recover_filesystem_no_format(struct fs_file_t *file)
// {
// 	int rc;

// 	fs_close(file);
// 	fs_unmount(&littlefs_mnt);

// 	k_msleep(500);

// 	rc = fs_mount(&littlefs_mnt);
// 	if (rc < 0) {
// 		LOG_ERR("Mount failed during recovery (%d)", rc);
// 		return rc;
// 	}

// 	fs_file_t_init(file);

// 	rc = fs_open(file, LOG_FILE_PATH, FS_O_CREATE | FS_O_APPEND | FS_O_RDWR);
// 	if (rc < 0) {
// 		LOG_ERR("File open failed during recovery (%d)", rc);
// 		return rc;
// 	}

// 	buffer_index = 0;
// 	bytes_since_sync = 0;

// 	LOG_WRN("Filesystem recovery complete without formatting; append mode restored");

// 	green_on();
// 	k_msleep(500);
// 	green_off();

// 	return 0;
// }

// /* =========================
//  * Logging
//  * ========================= */
// static int start_logging_segment(struct fs_file_t *file, int64_t segment_ms)
// {
// 	int rc;
// 	bool led_state = false;
// 	uint32_t blink_count = 0;
// 	int64_t start_ms = k_uptime_get();
// 	int64_t next_sample_time = start_ms;

// 	buffer_index = 0;
// 	bytes_since_sync = 0;

// 	while ((k_uptime_get() - start_ms) < segment_ms) {
// 		sensor_sample_t r;

// 		rc = sensors_read(&r);
// 		if (rc < 0) {
// 			LOG_ERR("sensors_read failed (%d)", rc);
// 			return rc;
// 		}

// 		record_buffer[buffer_index++] = r;
// 		total_records_logged++;

// 		if (buffer_index >= RECORDS_PER_BUFFER) {
// 			rc = flush_buffer(file);
// 			if (rc < 0) {
// 				LOG_ERR("flush_buffer returned %d", rc);
// 				return rc;
// 			}
// 		}

// 		if (++blink_count >= 20) {
// 			led_state = !led_state;
// 			(void)pwm_set_dt(&pwm_b, pwm_b.period,
// 					 led_state ? 0 : pwm_b.period);
// 			blink_count = 0;
// 		}

// 		next_sample_time += SAMPLE_INTERVAL_MS;

// 		int64_t now = k_uptime_get();
// 		if (next_sample_time > now) {
// 			k_msleep((int32_t)(next_sample_time - now));
// 		} else {
// 			next_sample_time = now;
// 		}
// 	}

// 	rc = flush_buffer(file);
// 	if (rc < 0) {
// 		LOG_ERR("final flush_buffer returned %d", rc);
// 		return rc;
// 	}

// 	rc = fs_sync(file);
// 	if (rc < 0) {
// 		LOG_ERR("fs_sync failed (%d)", rc);
// 		return rc;
// 	}

// 	LOG_INF("Segment complete, total records logged=%u",
// 		(unsigned int)total_records_logged);

// 	return 0;
// }

// /* =========================
//  * Modes
//  * ========================= */
// static int run_sync(void)
// {
// 	int rc = setup_clock();
// 	if (rc < 0) {
// 		LOG_ERR("setup_clock failed (%d)", rc);
// 		return rc;
// 	}

// 	bool state = false;
// 	while (!clock_bt_is_time_synced()) {
// 		state = !state;
// 		(void)pwm_set_dt(&pwm_g, pwm_g.period, state ? 0 : pwm_g.period);
// 		k_msleep(200);
// 	}

// 	green_on();
// 	k_msleep(1000);

// 	rc = shutdown_clock_bt();
// 	if (rc < 0) {
// 		LOG_ERR("shutdown_clock_bt failed (%d)", rc);
// 		return rc;
// 	}

// 	green_off();
// 	return 0;
// }

// static int run_log(void)
// {
// 	int rc;
// 	struct fs_file_t file;
// 	bool first_segment = true;
// 	int64_t total_start_ms;
// 	uint32_t segment_num = 0;

// 	green_off();
// 	blue_off();

// 	rc = sensors_init();
// 	if (rc < 0) {
// 		LOG_ERR("sensors_init failed (%d)", rc);
// 		return rc;
// 	}

// 	log_flash_params();

// 	total_records_logged = 0;
// 	buffer_index = 0;
// 	bytes_since_sync = 0;

// 	total_start_ms = k_uptime_get();

// 	while ((k_uptime_get() - total_start_ms) < TOTAL_LOG_TIME_MS) {
// 		int64_t elapsed_ms = k_uptime_get() - total_start_ms;
// 		int64_t remaining_ms = TOTAL_LOG_TIME_MS - elapsed_ms;
// 		int64_t this_segment_ms =
// 			(remaining_ms > LOG_SEGMENT_MS) ? LOG_SEGMENT_MS : remaining_ms;

// 		segment_num++;
// 		LOG_INF("Starting segment %u, duration=%lld ms",
// 			segment_num, (long long)this_segment_ms);

// 		/* Open fresh on first segment, append on later segments */
// 		if (first_segment) {
// 			rc = format_and_mount_fs();
// 			if (rc < 0) {
// 				LOG_ERR("format_and_mount_fs failed (%d)", rc);
// 				k_msleep(LOG_RESTART_DELAY_MS);
// 				continue;
// 			}

// 			rc = open_log_file(&file, true);
// 			if (rc < 0) {
// 				LOG_ERR("open_log_file(new) failed (%d)", rc);
// 				fs_unmount(&littlefs_mnt);
// 				k_msleep(LOG_RESTART_DELAY_MS);
// 				continue;
// 			}

// 			first_segment = false;
// 		} else {
// 			rc = mount_fs_no_format();
// 			if (rc < 0) {
// 				LOG_ERR("mount_fs_no_format failed (%d)", rc);
// 				k_msleep(LOG_RESTART_DELAY_MS);
// 				continue;
// 			}

// 			rc = open_log_file(&file, false);
// 			if (rc < 0) {
// 				LOG_ERR("open_log_file(append) failed (%d)", rc);
// 				fs_unmount(&littlefs_mnt);
// 				k_msleep(LOG_RESTART_DELAY_MS);
// 				continue;
// 			}
// 		}

// 		rc = start_logging_segment(&file, this_segment_ms);

// 		if (rc < 0) {
// 			LOG_WRN("Segment %u failed (%d). Waiting %d ms and restarting logging",
// 				segment_num, rc, LOG_RESTART_DELAY_MS);
// 			green_on();
// 			k_msleep(500);
// 			fs_close(&file);
// 			fs_unmount(&littlefs_mnt);

// 			blue_off();
// 			green_off();
// 			k_msleep(LOG_RESTART_DELAY_MS);

// 			/* Do not exit. Next loop iteration remounts and appends. */
// 			continue;
// 		}

// 		rc = fs_seek(&file, 0, FS_SEEK_END);
// 		if (rc == 0) {
// 			off_t size = fs_tell(&file);
// 			LOG_INF("File size after segment %u: %lld bytes",
// 				segment_num, (long long)size);
// 		}

// 		fs_close(&file);
// 		fs_unmount(&littlefs_mnt);

// 		if ((k_uptime_get() - total_start_ms) >= TOTAL_LOG_TIME_MS) {
// 			break;
// 		}

// 		LOG_INF("Segment %u complete. Waiting %d ms before restart",
// 			segment_num, LOG_RESTART_DELAY_MS);

// 		blue_off();
// 		k_msleep(LOG_RESTART_DELAY_MS);
// 	}

// 	blue_off();
// 	green_off();

// 	LOG_INF("Logging session complete. Total records=%u",
// 		(unsigned int)total_records_logged);

// 	return 0;
// }

// static int run_transfer(void)
// {
// 	int rc;
// 	struct fs_file_t file;
// 	sensor_sample_t sample;
// 	bool blink = false;

// 	rc = mount_fs_no_format();
// 	if (rc < 0) {
// 		return rc;
// 	}

// 	rc = bluetooth_init();
// 	if (rc < 0) {
// 		LOG_ERR("bluetooth_init failed (%d)", rc);
// 		fs_unmount(&littlefs_mnt);
// 		return rc;
// 	}

// 	while (!ble_is_connected() || !ble_is_mtu_ready()) {
// 		blink = !blink;
// 		(void)pwm_set_dt(&pwm_b, pwm_b.period, blink ? 0 : pwm_b.period);
// 		k_msleep(200);
// 	}

// 	blue_off();
// 	green_on();

// 	fs_file_t_init(&file);
// 	rc = fs_open(&file, LOG_FILE_PATH, FS_O_READ);
// 	if (rc < 0) {
// 		LOG_ERR("File open for read failed (%d)", rc);
// 		fs_unmount(&littlefs_mnt);
// 		return rc;
// 	}

// 	while (1) {
// 		ssize_t r = fs_read(&file, &sample, sizeof(sample));
// 		if (r < 0) {
// 			LOG_ERR("fs_read failed (%d)", (int)r);
// 			fs_close(&file);
// 			fs_unmount(&littlefs_mnt);
// 			return (int)r;
// 		}

// 		if (r == 0) {
// 			break;
// 		}

// 		if (r != sizeof(sample)) {
// 			LOG_WRN("Partial record read (%d), stopping transfer", (int)r);
// 			break;
// 		}

// 		ble_send_sample(&sample);
// 		k_msleep(50);
// 	}

// 	fs_close(&file);
// 	fs_unmount(&littlefs_mnt);

// 	k_msleep(500);

// 	rc = bluetooth_shutdown();
// 	if (rc < 0) {
// 		LOG_ERR("bluetooth_shutdown failed (%d)", rc);
// 		return rc;
// 	}

// 	green_off();
// 	blue_off();
// 	LOG_INF("Transfer complete");
// 	return 0;
// }



// /* =========================
//  * MAIN
//  * ========================= */
// int main(void)
// {
// 	int rc;

// 	if (!device_is_ready(pwm_g.dev) ||
// 	    !device_is_ready(pwm_b.dev) ||
// 	    !device_is_ready(ext_switch.port) ||
// 	    !device_is_ready(sw1.port)) {
// 		LOG_ERR("Required device not ready");
// 		return -ENODEV;
// 	}

// 	rc = gpio_pin_configure_dt(&sw1, GPIO_INPUT);
// 	if (rc < 0) {
// 		LOG_ERR("Failed to configure SW1 (%d)", rc);
// 		return rc;
// 	}

// 	rc = gpio_pin_configure_dt(&ext_switch, GPIO_INPUT);
// 	if (rc < 0) {
// 		LOG_ERR("Failed to configure EXT switch (%d)", rc);
// 		return rc;
// 	}

// 	green_on();
// 	blue_on();
// 	k_msleep(1000);
// 	green_off();
// 	blue_off();

// 	while (1) {
// 		LOG_INF("Press SW1 2x for SYNC, hold SW1 for LOGGING | EXT switch 2x for TRANSFER");
// 		LOG_INF("Waiting for mode selection...");
// 		enum mode m = wait_for_mode();

// 		switch (m) {
// 		case MODE_SYNC:
// 			LOG_INF("MODE: SYNC");
// 			rc = run_sync();
// 			break;

// 		case MODE_LOG:
// 			LOG_INF("MODE: LOGGING");
// 			rc = run_log();
// 			break;

// 		case MODE_TRANSFER:
// 			LOG_INF("MODE: TRANSFER");
// 			rc = run_transfer();
// 			break;

// 		default:
// 			LOG_INF("MODE: IDLE");
// 			rc = 0;
// 			break;
// 		}

// 		if (rc < 0) {
// 			LOG_ERR("Mode failed (%d)", rc);
// 		}

// 		LOG_INF("Returning to idle wait...");
// 	}
// }


#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/pwm.h>
#include <zephyr/fs/fs.h>
#include <zephyr/fs/littlefs.h>
#include <zephyr/storage/flash_map.h>
#include <zephyr/logging/log.h>
#include <string.h>
#include <errno.h>

#include "clock_bt_setup.h"
#include "sensor_fusion.h"
#include "bluetooth_conn.h"

LOG_MODULE_REGISTER(main, LOG_LEVEL_INF);

/* =========================
 * Flash / FS
 * ========================= */
#define LFS_PARTITION_ID FLASH_AREA_ID(lfs_partition)

static struct fs_littlefs lfs_cfg = {
	.cfg = {
		.read_size = 16,
		.prog_size = 16,
		.cache_size = 64,
		.lookahead_size = 64,
		.block_cycles = 32,
	}
};

static struct fs_mount_t littlefs_mnt = {
	.type = FS_LITTLEFS,
	.fs_data = &lfs_cfg,
	.storage_dev = (void *)LFS_PARTITION_ID,
	.mnt_point = "/lfs",
};

/* =========================
 * Hardware
 * ========================= */
#define LED_G_NODE DT_PATH(pwmleds, led_g)
#define LED_B_NODE DT_PATH(pwmleds, led_b)

static const struct pwm_dt_spec pwm_g = PWM_DT_SPEC_GET(LED_G_NODE);
static const struct pwm_dt_spec pwm_b = PWM_DT_SPEC_GET(LED_B_NODE);

#define EXT_SWITCH_NODE DT_PATH(buttons, ext_switch)
#define SWITCH_NODE DT_PATH(buttons, sw1)

static const struct gpio_dt_spec ext_switch =
	GPIO_DT_SPEC_GET(EXT_SWITCH_NODE, gpios);
static const struct gpio_dt_spec sw1 =
	GPIO_DT_SPEC_GET(SWITCH_NODE, gpios);

/* =========================
 * Buttons
 * ========================= */
#define BUTTON_POLL_MS         10
#define BUTTON_DEBOUNCE_MS     40
#define MULTICLICK_TIMEOUT_MS  500
#define LONG_PRESS_MS          1500

/* =========================
 * Logging buffer
 * ========================= */
#define RECORDS_PER_BUFFER   4 // 4 x 48 bytes = 192 bytes < 2048 heap pool size
#define SYNC_INTERVAL_BYTES  4096
#define MAX_RECORDS          750   /* testing only */

static int counter = 0;
static size_t total_records_logged = 0;

static sensor_sample_t record_buffer[RECORDS_PER_BUFFER];
static size_t buffer_index = 0;
static size_t bytes_since_sync = 0;

/* =========================
 * LED Helpers
 * ========================= */
static void green_on(void)
{
	(void)pwm_set_dt(&pwm_g, pwm_g.period, 0);
}

static void green_off(void)
{
	(void)pwm_set_dt(&pwm_g, pwm_g.period, pwm_g.period);
}

static void blue_on(void)
{
	(void)pwm_set_dt(&pwm_b, pwm_b.period, 0);
}

static void blue_off(void)
{
	(void)pwm_set_dt(&pwm_b, pwm_b.period, pwm_b.period);
}

/* =========================
 * Button Helpers
 * ========================= */
static bool button_pressed(const struct gpio_dt_spec *btn)
{
	int val = gpio_pin_get_dt(btn);
	return (val > 0);
}

static void wait_for_release(const struct gpio_dt_spec *btn)
{
    while (button_pressed(btn)) {
        k_msleep(BUTTON_POLL_MS);
    }
}

static uint8_t wait_for_clicks(const struct gpio_dt_spec *btn,
			       uint8_t min, uint8_t max)
{
	uint8_t count = 0;
	int64_t last = 0;
	bool prev = button_pressed(btn);

    /* Start from a known released state */
    wait_for_release(btn);

	while (1) {
		bool now = button_pressed(btn);

		if (now && !prev) {
			k_msleep(BUTTON_DEBOUNCE_MS);
			now = button_pressed(btn);

			if (now) {
				count++;
				last = k_uptime_get();
				LOG_INF("Button click count = %u", count);
			}
		}

		if (count >= min) {
			if ((k_uptime_get() - last) > MULTICLICK_TIMEOUT_MS) {
				return count;
			}
		}

		if (count >= max) {
			return count;
		}

		prev = now;
		k_msleep(BUTTON_POLL_MS);
	}
}

/* =========================
 * Boot Mode
 * ========================= */
enum mode {
	MODE_IDLE,
	MODE_SYNC,
	MODE_LOG,
	MODE_TRANSFER
};

static enum mode wait_for_mode(void)
{
    LOG_INF("Waiting for input: SW1 x2=SYNC, SW1 long press=LOG, EXT x2=TRANSFER");

    while (1) {

        /* ---------- SW1 handling ---------- */
        if (button_pressed(&sw1)) {
            k_msleep(BUTTON_DEBOUNCE_MS);

            if (button_pressed(&sw1)) {
                int64_t press_start = k_uptime_get();

                /* Stay here while button is held to determine long press */
                while (button_pressed(&sw1)) {
                    if ((k_uptime_get() - press_start) >= LONG_PRESS_MS) {
                        LOG_INF("SW1 long press detected");
                        wait_for_release(&sw1);
                        return MODE_LOG;
                    }
                    k_msleep(BUTTON_POLL_MS);
                }

                /*
                 * If we get here, SW1 was a short press.
                 * Count it as part of a double-click sequence.
                 */
                uint8_t c = wait_for_clicks(&sw1, 2, 2);
                if (c == 2) {
                    return MODE_SYNC;
                }
            }
        }

        /* ---------- EXT switch handling ---------- */
        if (button_pressed(&ext_switch)) {
            uint8_t c = wait_for_clicks(&ext_switch, 2, 2);
            if (c == 2) {
                return MODE_TRANSFER;
            }
        }

        k_msleep(10);
    }
}

/* =========================
 * FS Helpers
 * ========================= */
static int mount_fs(void)
{
	int rc = fs_mount(&littlefs_mnt);
	if (rc == 0) {
		LOG_INF("LittleFS mounted");
		return 0;
	}

	LOG_WRN("Mount failed (%d), formatting", rc);

	rc = fs_mkfs(FS_LITTLEFS, (uintptr_t)LFS_PARTITION_ID, &lfs_cfg, 0);
	if (rc < 0) {
		LOG_ERR("fs_mkfs failed (%d)", rc);
		return rc;
	}

	rc = fs_mount(&littlefs_mnt);
	if (rc < 0) {
		LOG_ERR("Mount after format failed (%d)", rc);
		return rc;
	}

	LOG_INF("LittleFS formatted and mounted");
	return 0;
}

static int flush_buffer(struct fs_file_t *file)
{
	if (buffer_index == 0) {
		return 0;
	}

	size_t write_size = buffer_index * sizeof(sensor_sample_t);

	ssize_t written = fs_write(file, record_buffer, write_size);
	if (written < 0) {
		LOG_ERR("fs_write failed (%d)", (int)written);
		return (int)written;
	}

	if ((size_t)written != write_size) {
		LOG_ERR("fs_write short (%d/%u)", (int)written,
			(unsigned int)write_size);
		return -EIO;
	}

	bytes_since_sync += write_size;
	buffer_index = 0;

	if (bytes_since_sync >= SYNC_INTERVAL_BYTES) {
		int rc = fs_sync(file);
		if (rc < 0) {
			LOG_ERR("fs_sync failed (%d)", rc);
			return rc;
		}

		bytes_since_sync = 0;
		counter++;
		LOG_INF("Synced to flash");
	}

	return 0;
}

static int recover_filesystem_no_format(struct fs_file_t *file)
{
	int rc;

	fs_close(file);
	fs_unmount(&littlefs_mnt);

	k_msleep(500); // Let things settle before remounting

	// rc = fs_mkfs(FS_LITTLEFS, (uintptr_t)LFS_PARTITION_ID, &lfs_cfg, 0);
	// if (rc < 0) {
	// 	LOG_ERR("fs_mkfs failed during recovery (%d)", rc);
	// 	return rc;
	// }

	rc = fs_mount(&littlefs_mnt);
	if (rc < 0) {
		LOG_ERR("Mount failed during recovery (%d)", rc);
		return rc;
	}

	fs_file_t_init(file);

	rc = fs_open(file, "/lfs/imu.bin",
		     FS_O_CREATE | FS_O_TRUNC | FS_O_RDWR);
	if (rc < 0) {
		LOG_ERR("File open failed during recovery (%d)", rc);
		return rc;
	}

	buffer_index = 0;
	bytes_since_sync = 0;

	LOG_WRN("Filesystem recovery complete without formatting");
	green_on();	
	k_msleep(500);
	green_off();
	return 0;
}

static int recover_filesystem(struct fs_file_t *file)
{
	int rc;

	fs_close(file);
	fs_unmount(&littlefs_mnt);

	rc = fs_mkfs(FS_LITTLEFS, (uintptr_t)LFS_PARTITION_ID, &lfs_cfg, 0);
	if (rc < 0) {
		LOG_ERR("fs_mkfs failed during recovery (%d)", rc);
		return rc;
	}

	rc = fs_mount(&littlefs_mnt);
	if (rc < 0) {
		LOG_ERR("Mount failed during recovery (%d)", rc);
		return rc;
	}

	fs_file_t_init(file);

	rc = fs_open(file, "/lfs/imu.bin",
		     FS_O_CREATE | FS_O_TRUNC | FS_O_RDWR);
	if (rc < 0) {
		LOG_ERR("File open failed during recovery (%d)", rc);
		return rc;
	}

	buffer_index = 0;
	bytes_since_sync = 0;

	LOG_WRN("Filesystem recovery complete");
	return 0;
}

/* =========================
 * Logging
 * ========================= */
static int start_logging(struct fs_file_t *file)
{
	int rc;
	bool led_state = false;
	uint32_t blink_count = 0;

	total_records_logged = 0;
	buffer_index = 0;
	bytes_since_sync = 0;
	counter = 0;

	while (counter <= MAX_RECORDS) {
		sensor_sample_t r;

		rc = sensors_read(&r);
		if (rc < 0) {
			LOG_ERR("sensors_read failed (%d)", rc);
			return rc;
		}

		record_buffer[buffer_index++] = r;
		total_records_logged++;

		if (buffer_index >= RECORDS_PER_BUFFER) {
			rc = flush_buffer(file);

			if (rc == -EINVAL) {
				LOG_WRN("Write returned -EINVAL; attempting FS recovery");
				if (counter == 0) {
					rc = recover_filesystem(file);
				}
				LOG_INF("Logging failed, total records=%u",
				(unsigned int)total_records_logged);

				rc = recover_filesystem_no_format(file);
				if (rc < 0) {
					return rc;
				}
				continue;
			}

			if (rc < 0) {
				return rc;
			}
		}

		if (++blink_count >= 20) {
			led_state = !led_state;
			(void)pwm_set_dt(&pwm_b, pwm_b.period,
					 led_state ? 0 : pwm_b.period);
			blink_count = 0;
		}

		k_msleep(20);
	}

	rc = flush_buffer(file);
	if (rc == -EINVAL) {
		LOG_WRN("Final flush -EINVAL; attempting FS recovery");
		rc = recover_filesystem_no_format(file);
		if (rc < 0) {
			return rc;
		}
	} else if (rc < 0) {
		return rc;
	}

	rc = fs_sync(file);
	if (rc < 0) {
		LOG_ERR("fs_sync failed (%d)", rc);
		return rc;
	}

	LOG_INF("Logging complete, total records=%u",
		(unsigned int)total_records_logged);

	return 0;
}

/* =========================
 * Modes
 * ========================= */
static int run_sync(void)
{
	int rc = setup_clock();
	if (rc < 0) {
		LOG_ERR("setup_clock failed (%d)", rc);
		return rc;
	}

	bool state = false;
	while (!clock_bt_is_time_synced()) {
		state = !state;
		(void)pwm_set_dt(&pwm_g, pwm_g.period, state ? 0 : pwm_g.period);
		k_msleep(200);
	}

	green_on();
	k_msleep(1000);

	rc = shutdown_clock_bt();
	if (rc < 0) {
		LOG_ERR("shutdown_clock_bt failed (%d)", rc);
		return rc;
	}
	
	green_off();

	return 0;
}

static int run_log(void)
{
	int rc;
	struct fs_file_t file;

	/* Ensure LED state is clean before logging */
	green_off();
	blue_off();

	rc = sensors_init();
	if (rc < 0) {
		LOG_ERR("sensors_init failed (%d)", rc);
		return rc;
	}	
	//format the system before writing to it, to ensure a clean state. This will delete any existing data, but ensures we can log without fs errors.
	rc = fs_mkfs(FS_LITTLEFS, (uintptr_t)LFS_PARTITION_ID, &lfs_cfg, 0);
	if (rc < 0) {
		LOG_ERR("fs_mkfs failed during recovery (%d)", rc);
		return rc;
	}
	LOG_INF("Filesystem formatted for logging");

	rc = mount_fs();
	if (rc < 0) {
		return rc;
	}

	fs_file_t_init(&file);

	// rc = fs_open(&file, "/lfs/imu.bin",
	// 	     FS_O_CREATE | FS_O_TRUNC | FS_O_RDWR);
	rc = fs_open(&file, "/lfs/imu.bin",
		     FS_O_CREATE | FS_O_TRUNC | FS_O_RDWR);
	if (rc < 0) {
		LOG_ERR("File open failed (%d)", rc);
		fs_unmount(&littlefs_mnt);
		return rc;
	}

	rc = start_logging(&file);

    rc = fs_seek(&file, 0, FS_SEEK_END);
    if (rc == 0) {
        off_t size = fs_tell(&file);
        LOG_INF("Logged file size: %lld bytes", (long long)size);
    }

	fs_close(&file);
	fs_unmount(&littlefs_mnt);

	if (rc < 0) {
		return rc;
	}

	blue_off();
	green_off();
	return 0;
}

static int run_transfer(void)
{
	int rc;
	struct fs_file_t file;
	sensor_sample_t sample;
	bool blink = false;

	rc = mount_fs();
	if (rc < 0) {
		return rc;
	}

	rc = bluetooth_init();
	if (rc < 0) {
		LOG_ERR("bluetooth_init failed (%d)", rc);
		fs_unmount(&littlefs_mnt);
		return rc;
	}

	while (!ble_is_connected() || !ble_is_mtu_ready()) {
		blink = !blink;
		(void)pwm_set_dt(&pwm_b, pwm_b.period, blink ? 0 : pwm_b.period);
		k_msleep(200);
	}

	blue_off();
	green_on();

	fs_file_t_init(&file);
	rc = fs_open(&file, "/lfs/imu.bin", FS_O_READ);
	if (rc < 0) {
		LOG_ERR("File open for read failed (%d)", rc);
		fs_unmount(&littlefs_mnt);
		return rc;
	}

	while (1) {
		ssize_t r = fs_read(&file, &sample, sizeof(sample));
		if (r < 0) {
			LOG_ERR("fs_read failed (%d)", (int)r);
			fs_close(&file);
			fs_unmount(&littlefs_mnt);
			return (int)r;
		}

		if (r == 0) {
			break;
		}

		if (r != sizeof(sample)) {
			LOG_WRN("Partial record read (%d), stopping transfer", (int)r);
			break;
		}

		ble_send_sample(&sample);
		k_msleep(50);
	}

	fs_close(&file);
	fs_unmount(&littlefs_mnt);

	/* Let final BLE packets drain */
	k_msleep(500);	

	rc = bluetooth_shutdown();
	if (rc < 0) {
		LOG_ERR("bluetooth_shutdown failed (%d)", rc);
		return rc;
	}

	green_off();
	blue_off();
	LOG_INF("Transfer complete");
	return 0;
}

/* =========================
 * MAIN
 * ========================= */
int main(void)
{
	int rc;

	if (!device_is_ready(pwm_g.dev) ||
	    !device_is_ready(pwm_b.dev) ||
	    !device_is_ready(ext_switch.port) ||
	    !device_is_ready(sw1.port)) {
		LOG_ERR("Required device not ready");
		return -ENODEV;
	}

	rc = gpio_pin_configure_dt(&sw1, GPIO_INPUT);
	if (rc < 0) {
		LOG_ERR("Failed to configure SW1 (%d)", rc);
		return rc;
	}

	rc = gpio_pin_configure_dt(&ext_switch, GPIO_INPUT);
	if (rc < 0) {
		LOG_ERR("Failed to configure EXT switch (%d)", rc);
		return rc;
	}
	// POWER ON STATE OF Device 
	green_on();
	blue_on();
	k_msleep(1000);
	green_off();
	blue_off();

    while (1) {

		LOG_INF("Press SW1 2x for SYNC, hold SW1 for LOGGING | EXT switch 2x for TRANSFER");
        LOG_INF("Waiting for mode selection...");
        enum mode m = wait_for_mode();

        switch (m) {
        case MODE_SYNC:
            LOG_INF("MODE: SYNC");
            rc = run_sync();
            break;

        case MODE_LOG:
            LOG_INF("MODE: LOGGING");
            rc = run_log();
            break;

        case MODE_TRANSFER:
            LOG_INF("MODE: TRANSFER");
            rc = run_transfer();
            break;

        default:
            LOG_INF("MODE: IDLE");
            rc = 0;
            break;
        }

	if (rc < 0) {
        LOG_ERR("Mode failed (%d)", rc);
    }

    LOG_INF("Returning to idle wait...");
    }
}

# LOGGING CONFIGURATION
CONFIG_USE_SEGGER_RTT=y
CONFIG_RTT_CONSOLE=y

CONFIG_SEGGER_RTT_BUFFER_SIZE_UP=8192
CONFIG_SEGGER_RTT_BUFFER_SIZE_DOWN=16

CONFIG_HEAP_MEM_POOL_SIZE=2048

# SENSOR CONFIGURATION
CONFIG_SPI=y
CONFIG_I2C=y
CONFIG_SENSOR=y
CONFIG_IIS2MDC=y
CONFIG_ISM330DHCX=y
# SWITCH CONFIGURATION
CONFIG_GPIO=y
#PWM CONFIGURATION
CONFIG_PWM=y
# FLASH CONFIGURATION
CONFIG_FLASH=y
CONFIG_FLASH_MAP=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_SPI_NOR=y
# FILE SYSTEM CONFIGURATION
CONFIG_FILE_SYSTEM=y
CONFIG_FILE_SYSTEM_LITTLEFS=y
CONFIG_FILE_SYSTEM_MKFS=y
# BLUETOOTH CONFIGURATION
CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="GAIT_BOARD_0006"
# CONFIG_BT_MAX_CONN=1
CONFIG_BT_GATT_CLIENT=y

CONFIG_BT_SMP=y              # optional (only if you want pairing)
CONFIG_BT_GATT_DM=y
CONFIG_BT_CTS_CLIENT=y

# CONFIG_BT_GATT_NOTIFY=y
CONFIG_BT_L2CAP_TX_BUF_COUNT=10
CONFIG_BT_BUF_ACL_TX_COUNT=10
CONFIG_BT_USER_DATA_LEN_UPDATE=y
CONFIG_BT_BUF_ACL_TX_SIZE=251
CONFIG_BT_BUF_ACL_RX_SIZE=251
CONFIG_BT_L2CAP_TX_MTU=247

CONFIG_BT_PHY_UPDATE=y
CONFIG_BT_DATA_LEN_UPDATE=y
# STACK CONFIGURATION
CONFIG_MAIN_STACK_SIZE=16384
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096
CONFIG_ISR_STACK_SIZE=2048
# LOGGING CONFIGURATION
CONFIG_LOG=y
CONFIG_LOG_MODE_DEFERRED=n
CONFIG_LOG_MODE_IMMEDIATE=y

CONFIG_SPI_LOG_LEVEL_INF=y
CONFIG_FLASH_LOG_LEVEL_INF=y
#   POWER CONFIGURATION
# used for partition manager and littlefs (to set up a partition inside the external flash)
CONFIG_PARTITION_MANAGER_ENABLED=y
CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK=y

CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096

external_flash:
  address: 0x0
  size: 0x02000000   # 32MB
  region: external_flash
  device: spi_flash2  # <-- must match DT node label

lfs_partition:
  address: 0x00000000
  size:  0x01C00000   # 28MB
  region: external_flash
  device: spi_flash2

/dts-v1/;
#include <nordic/nrf52840_qfaa.dtsi>
// #include "gait_board_NRF52840-pinctrl.dtsi"

/ {
	model = "ProFormIQ, NRF52840-QFAA";
	compatible = "NordicSemiConductor,gait-board-NRF52840";

	chosen {
		zephyr,sram = &sram0;
		zephyr,flash = &flash0;
		zephyr,code-partition = &slot0_partition;
		nordic,pm-ext-flash = &spi_flash2;
	};

	// leds {
	// 	compatible = "gpio-leds";
	// 	led_g {
	// 		label = "led_g";
	// 		gpios = <&gpio0 30 GPIO_ACTIVE_HIGH>;
	// 	};

	// 	led_b {
	// 		label = "led_b";
	// 		gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>;
	// 	};

	// 	led_r {
	// 		label = "led_r";
	// 		gpios = <&gpio0 31 GPIO_ACTIVE_HIGH>;
	// 	};
	// };
	
	pwmleds {
		compatible = "pwm-leds";

		// led_r: led_r {
		// 	pwms = <&pwm0 0 PWM_HZ(1000) PWM_POLARITY_INVERTED>;
		// };

		led_b: led_b {
			pwms = <&pwm0 1 PWM_HZ(1000) PWM_POLARITY_INVERTED>;
		};

		led_g: led_g {
			pwms = <&pwm0 2 PWM_HZ(1000) PWM_POLARITY_INVERTED>;
		};
	};


	buttons {
		compatible = "gpio-keys";
		
		sw1: sw1 {
		label = "sw1";
		gpios = <&gpio0 8 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
	};
		ext_switch:ext_switch {
		label = "ext_switch";
		gpios = <&gpio0 7 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
	};

	};
};

/* =========================
 * Internal Flash Partitions
 * ========================= */

&flash0 {
	partitions {
		compatible = "fixed-partitions";
		#address-cells = <1>;
		#size-cells = <1>;

		boot_partition: partition@0 {
			label = "mcuboot";
			reg = <0x00000000 DT_SIZE_K(48)>;
		};

		slot0_partition: partition@c000 {
			label = "image-0";
			reg = <0x0000c000 DT_SIZE_K(472)>;
		};

		slot1_partition: partition@82000 {
			label = "image-1";
			reg = <0x00082000 DT_SIZE_K(472)>;
		};

		storage_partition: partition@f8000 {
			label = "storage";
			reg = <0x000f8000 DT_SIZE_K(32)>;
		};
	};
};


&gpiote {
	status = "okay";
};

&gpio0 {
	status = "okay";
};

&gpio1 {
	status = "okay";
};

&spi0 {
	status = "okay";

	// CS index 0 = ISM330
	cs-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>;   

	pinctrl-0 = <&spi0_default>;
	pinctrl-1 = <&spi0_sleep>;
	pinctrl-names = "default", "sleep";

	/* =========================
	 * IMU (existing, unchanged)
	 * ========================= */
	ism330: ism330dhcx@0 {
		compatible = "st,ism330dhcx";
		reg = <0>; /* CS index 0 */
		spi-max-frequency = <10000000>;

		drdy-gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
		int-pin = <1>;

		accel-odr = <4>;
		accel-range = <4>;
		gyro-odr = <4>;
		gyro-range = <500>;
	};
};

&pinctrl {

	spi0_default: spi0_default {
		group1 {
			psels = <NRF_PSEL(SPIM_SCK, 1, 9)>,
					<NRF_PSEL(SPIM_MOSI, 0, 11)>,
					<NRF_PSEL(SPIM_MISO, 0, 12)>;
		};
	};

	spi0_sleep: spi0_sleep {
		group1 {
			psels = <NRF_PSEL(SPIM_SCK, 1, 9)>;
		};
	};

	i2c1_default: i2c1_default {
		group1 {
			psels = <NRF_PSEL(TWIM_SDA, 0, 13)>, <NRF_PSEL(TWIM_SCL, 0, 14)>;
		};
	};

	i2c1_sleep: i2c1_sleep {
		group1 {
			psels = <NRF_PSEL(TWIM_SDA, 0, 13)>;
		};
	};


	// pwm0_default: pwm0_default {
	// 		group1 {
	// 			psels = <NRF_PSEL(PWM_OUT0, 0, 31)>,
	// 					<NRF_PSEL(PWM_OUT1, 0, 30)>,
	// 					<NRF_PSEL(PWM_OUT2, 0, 29)>;
	// 		};
	// 	};

	
	pwm0_default: pwm0_default {
    group1 {
        psels = <NRF_PSEL(PWM_OUT1, 0, 30)>,
                <NRF_PSEL(PWM_OUT2, 0, 29)>;
    };
};

	pwm0_sleep: pwm0_sleep {
		group1 {
			psels = <NRF_PSEL(PWM_OUT1, 0, 30)>,
					<NRF_PSEL(PWM_OUT2, 0, 29)>;
			low-power-enable;
		};
	};


	spi2_default: spi2_default {
		group1 {
			psels = <NRF_PSEL(SPIM_SCK, 0, 19)>,
					<NRF_PSEL(SPIM_MOSI, 0, 21)>,
					<NRF_PSEL(SPIM_MISO, 0, 22)>;
		};
	};

	spi2_sleep: spi2_sleep {
		group1 {
			psels = <
				NRF_PSEL(SPIM_SCK,  0, 19)
				NRF_PSEL(SPIM_MOSI, 0, 21)
				NRF_PSEL(SPIM_MISO, 0, 22)
			>;
			low-power-enable;
		};
	};
};

&adc {
	status = "okay";
	battery_voltage: battery_voltage {
		compatible = "voltage-divider";
		io-channels = <&adc 0>;   /* AIN0 */
		label = "BATTERY_VOLTAGE";

		/* Replace with your actual resistor values */
		output-ohms = <100>;    /* Rbottom */
		full-ohms = <570>;     /* Rtop + Rbottom */
	};

};

&i2c1 {
	status = "okay";
	pinctrl-0 = <&i2c1_default>;
	pinctrl-1 = <&i2c1_sleep>;
	pinctrl-names = "default", "sleep";

		/* ISS2MDCTR – Magnetometer (open-drain INT) */
	iis2mdc: iis2mdc@1e {
		compatible = "st,iis2mdc";
		reg = <0x1e>;
		/* DRDY is open-drain, active-low */
		drdy-gpios = <&gpio0 17 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
	};

	/*DS3231 RTC Real time clock  */
	ds3231: ds3231@68 {
        compatible = "maxim,ds3231";
        reg = <0x68>;
        // status = "okay";
    };
};

&pwm0 {
    status = "okay";
    pinctrl-0 = <&pwm0_default>;
    pinctrl-1 = <&pwm0_sleep>;
    pinctrl-names = "default", "sleep";
};

&qspi {
	status = "disabled";
};

&spi2 {
	status = "okay";

	pinctrl-0 = <&spi2_default>;
	pinctrl-1 = <&spi2_sleep>;
	pinctrl-names = "default", "sleep";

	cs-gpios = <
		&gpio0 20 GPIO_ACTIVE_LOW
	>;

	spi_flash2: flash@0 {
		compatible = "jedec,spi-nor";
		reg = <0>;                    /* MUST be 0 */

		label = "SPI_FLASH";
		spi-max-frequency = <2000000>;

		jedec-id = [ EF 40 19 ];
		size = <0x02000000>;
		

		// has-dpd;
		// t-enter-dpd = <3000>;
		// t-exit-dpd = <3000>;
		// partitions {
        //     compatible = "fixed-partitions";
        //     #address-cells = <1>;
        //     #size-cells = <1>;

        //     lfs_partition: partition@0 {
        //         label = "lfs";
        //         reg = <0x00000000 0x01C00000>; /* 28 MB */
        //     };
        // };
	};
};

Parents Reply
  • Hi, 

    I was able to fix this by adjusting my device tree definition. 

    Specifically, the size definition in the spi2 section was set using bytes instead of bits. 

    Once I changed the bytes to bits, the write error went away.

    The size of the memory is around 32 MB and when I was setting the size inside the device tree, it was reading as 4 MB, so there was a mismatch. 

    The new size I set was 0x10000000 in bits, which reads as 32MB

Children
Related