From 4015b7bf4276fb9d7867f348e2bb4280ec403dcd Mon Sep 17 00:00:00 2001 From: sys64738 Date: Thu, 26 Aug 2021 03:52:06 +0200 Subject: [PATCH] PERSISTENT_STORAGE usage flag --- CMakeLists.txt | 11 ++++++++--- src/main.c | 4 ++++ src/modeset.c | 11 +++++++++++ src/storage.c | 16 ++++++++++------ src/storage.h | 7 +++++-- src/storage_save.c | 18 ++++++++++++------ src/vnd_cfg.c | 43 +++++++++++++++++++++++++++++++++++++++++++ src/vnd_cfg.h | 6 ++++++ 8 files changed, 99 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d67157a..1383f3f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,5 @@ option(USE_USBCDC_FOR_STDIO "Export an extra USB-CDC interface for stdio, instead of echoing it to a UART port (and requiring UART loopback for receiving stdio output on a host computer)." OFF) +option(PERSISTENT_STORAGE "Use persistent storage (usually on-chip/on-board flash) to save the current mode, and settings of modes" ON) set(FAMILY "rp2040" CACHE STRING "Board/MCU family, decides which drivers to use. Set to RP2040 by default.") set(BOARD "raspberry_pi_pico" CACHE STRING "Board used, determines the pinout. Defaults to the Raspberry Pi Pico.") @@ -45,10 +46,10 @@ if(FAMILY STREQUAL "rp2040") # need uart stdio, usb is busy doing other stuff if(USE_USBCDC_FOR_STDIO) # we're going to manually implement this case - #pico_enable_stdio_uart(${PROJECT} 0) - target_compile_definitions(${PROJECT} PUBLIC USE_USBCDC_FOR_STDIO=1 PICO_STDIO_USB=1) + #pico_enable_stdio_uart(${PROJECT} 0) + target_compile_definitions(${PROJECT} PUBLIC USE_USBCDC_FOR_STDIO=1) else() - #pico_enable_stdio_uart(${PROJECT} 1) + #pico_enable_stdio_uart(${PROJECT} 1) endif() pico_enable_stdio_uart(${PROJECT} 1) pico_enable_stdio_usb(${PROJECT} 0) @@ -95,10 +96,14 @@ target_sources(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/bsp/${FAMILY}/m_sump/sump_hw.c ) if(USE_USBCDC_FOR_STDIO) + target_compile_definitions(${PROJECT} PUBLIC USE_USBCDC_FOR_STDIO=1) target_sources(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/bsp/${FAMILY}/cdc_stdio.c ) endif() +if (PERSISTENT_STORAGE) + target_compile_definitions(${PROJECT} PUBLIC PERSISTENT_STORAGE=1) +endif() target_include_directories(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/ ${CMAKE_CURRENT_SOURCE_DIR}/libco/ diff --git a/src/main.c b/src/main.c index 1951908..380a863 100644 --- a/src/main.c +++ b/src/main.c @@ -32,7 +32,11 @@ int main() { vndcfg_thread = co_derive(vndcfg_stack, sizeof vndcfg_stack, vndcfg_thread_fn); thread_enter(vndcfg_thread); +#if defined(PERSISTENT_STORAGE) && defined(DBOARD_HAS_STORAGE) int startupmode = storage_init(); +#else + int startupmode = -1; +#endif modes_init(startupmode); if (mode_current) mode_current->enter(); diff --git a/src/modeset.c b/src/modeset.c index c7abdac..22eea42 100644 --- a/src/modeset.c +++ b/src/modeset.c @@ -5,6 +5,7 @@ #include "alloc.h" #include "board.h" /* bsp_reset_bootloader() */ #include "mode.h" +#include "storage.h" extern struct mode m_01_default, m_03_jscan, m_04_sump; @@ -171,3 +172,13 @@ void modes_switch(uint8_t newmode) { if (mode_current) mode_current->enter(); } +#if defined(PERSISTENT_STORAGE) && defined(DBOARD_HAS_STORAGE) +void tud_umount_cb(void) { + storage_flush_data(); +} +void tud_suspend_cb(bool remote_wakeup_en) { + (void)remote_wakeup_en; + storage_flush_data(); +} +#endif + diff --git a/src/storage.c b/src/storage.c index 931cb46..a253d39 100644 --- a/src/storage.c +++ b/src/storage.c @@ -5,13 +5,15 @@ #include "mode.h" #include "storage.h" -#ifndef DBOARD_HAS_STORAGE -int storage_init(void) { return -1; } -void storage_flush_data(void) { } +#if !defined(PERSISTENT_STORAGE) || !defined(DBOARD_HAS_STORAGE) +/*int storage_init(void) { return -1; } +bool storage_flush_data(void) { return false; } struct mode_info storage_mode_get_size(int _) { (void)_; return (struct mode_info){ .size = 0, .version = 0 }; } -void storage_mode_read(int _, void* __) { (void)_; (void)__; } +void storage_mode_read(int _, void* __, size_t ___, size_t ____) { + (void)_; (void)__; (void)___; (void)____; +}*/ #else #include "storage_internal.h" @@ -144,7 +146,7 @@ struct mode_info storage_mode_get_info(int mode) { #undef DEF_RETVAL } -void storage_mode_read(int mode, void* dst) { +void storage_mode_read(int mode, void* dst, size_t offset, size_t maxlen) { if (mode >= 16 || !header_valid || mode <= 0) return; for (size_t i = 0; i < header_tmp.nmodes; ++i) { @@ -175,8 +177,10 @@ void storage_mode_read(int mode, void* dst) { mode_bad |= 1<= mdsize) return; + // skip hash check in this case - storage_read(dst, mdoffset, mdsize); + storage_read(dst, mdoffset + offset, mdsize < maxlen ? mdsize : maxlen); return; } } diff --git a/src/storage.h b/src/storage.h index e77a06a..25c4b6a 100644 --- a/src/storage.h +++ b/src/storage.h @@ -32,7 +32,7 @@ struct mode_info { // functions mode-specific code can use to retrieve the save data struct mode_info storage_mode_get_info(int mode); // returns size=0 for none found -void storage_mode_read(int mode, void* dst); +void storage_mode_read(int mode, void* dst, size_t offset, size_t maxlen); // global functions @@ -40,7 +40,10 @@ void storage_mode_read(int mode, void* dst); int storage_init(void); // flush edits if anything has been edited -void storage_flush_data(void); +bool storage_flush_data(void); + +bool storage_priv_mode_has(int mode); +void* storage_priv_get_header_ptr(void); #endif diff --git a/src/storage_save.c b/src/storage_save.c index e8e336f..771581b 100644 --- a/src/storage_save.c +++ b/src/storage_save.c @@ -5,11 +5,11 @@ #include "mode.h" #include "storage.h" -#ifdef DBOARD_HAS_STORAGE +#if defined(PERSISTENT_STORAGE) && defined(DBOARD_HAS_STORAGE) #include "storage_internal.h" -static bool storage_mode_has(int i) { +bool storage_priv_mode_has(int i) { if (mode_list[i]->storage.stclass == mode_storage_none) return false; if (mode_list[i]->storage.get_size == NULL) return false; if (mode_list[i]->storage.get_data == NULL) return false; @@ -17,6 +17,9 @@ static bool storage_mode_has(int i) { return true; } +void* storage_priv_get_header_ptr(void) { + return &header_tmp; +} static struct mode_storage msto[16]; @@ -38,7 +41,7 @@ static size_t storage_allocate_new(void) { for (enum mode_storage_class stcls = mode_storage_32b; stcls <= mode_storage_big; ++stcls) { for (int mode = 1; mode < 16; ++mode) { - if (mode_list[mode] == NULL || !storage_mode_has(mode)) continue; + if (mode_list[mode] == NULL || !storage_priv_mode_has(mode)) continue; if (mode_list[mode]->storage.stclass != stcls) continue; // too big for the class? don't write the data, then @@ -150,17 +153,20 @@ static void STORAGE_RAM_FUNC(storage_write_data)(void) { // * try to save when unplugging??? } -void storage_flush_data(void) { +bool storage_flush_data(void) { if (mode_bad != 0 || mode_current_id != header_tmp.curmode) { storage_write_data(); + return true; } else for (int i = 1; i < 16; ++i) { - if (mode_list[i] == NULL || !storage_mode_has(i)) continue; + if (mode_list[i] == NULL || !storage_priv_mode_has(i)) continue; if (mode_list[i]->storage.is_dirty()) { storage_write_data(); - return; + return true; } } + + return false; } #endif diff --git a/src/vnd_cfg.c b/src/vnd_cfg.c index a6cd4b6..b25c9b3 100644 --- a/src/vnd_cfg.c +++ b/src/vnd_cfg.c @@ -18,6 +18,8 @@ static uint32_t rxavail, rxpos, txpos; static int VND_N_CFG = 0; +extern uint8_t data_tmp[256]; + void vnd_cfg_init(void) { rxavail = 0; rxpos = 0; @@ -191,6 +193,47 @@ void vnd_cfg_task(void) { case cfg_cmd_get_infostr: vnd_cfg_write_str(cfg_resp_ok, INFO_PRODUCT(INFO_BOARDNAME)); break; +#if defined(PERSISTENT_STORAGE) && defined(DBOARD_HAS_STORAGE) + case cfg_cmd_storage_get_header: + vnd_cfg_write_resp(cfg_resp_ok, 256, storage_priv_get_header_ptr()); + break; + case cfg_cmd_storage_get_modedata: + verbuf[0] = vnd_cfg_read_byte(); + if (verbuf[0] == 0 || verbuf[0] >= 16 || mode_list[verbuf[0]] == NULL) { + vnd_cfg_write_resp(cfg_resp_nosuchmode, 0, NULL); + } else if (!storage_priv_mode_has(verbuf[0])) { + vnd_cfg_write_resp(cfg_resp_badarg, 0, NULL); + } else { + uint32_t len = storage_mode_get_info(verbuf[0]).size; + vnd_cfg_write_byte(cfg_resp_ok); + if (len < (1<<7)) { + vnd_cfg_write_byte(len); + } else if (len < (1<<14)) { + vnd_cfg_write_byte((len & 0x7f) | 0x80); + vnd_cfg_write_byte((len >> 7) & 0x7f); + } else { + vnd_cfg_write_byte((len & 0x7f) | 0x80); + vnd_cfg_write_byte(((len >> 7) & 0x7f) | 0x80); + vnd_cfg_write_byte(((len >> 14) & 0x7f)); + } + + for (size_t i = 0; i < len; i += sizeof data_tmp) { + size_t tosend = sizeof data_tmp; + if (tosend > len - i) tosend = len - i; + storage_mode_read(verbuf[0], data_tmp, i, tosend); + + for (size_t ii = 0; ii < tosend; ++ii) + vnd_cfg_write_byte(data_tmp[ii]); + } + + vnd_cfg_write_flush(); + } + break; + case cfg_cmd_storage_flush_data: + verbuf[0] = storage_flush_data() ? 1 : 0; + vnd_cfg_write_resp(cfg_resp_ok, 1, verbuf); + break; +#endif default: vnd_cfg_write_resp(cfg_resp_illcmd, 0, NULL); break; diff --git a/src/vnd_cfg.h b/src/vnd_cfg.h index c6dd08b..f5de9c1 100644 --- a/src/vnd_cfg.h +++ b/src/vnd_cfg.h @@ -30,6 +30,12 @@ enum cfg_cmd { cfg_cmd_get_cur_mode = 0x02, cfg_cmd_set_cur_mode = 0x03, cfg_cmd_get_infostr = 0x04, + +#if defined(PERSISTENT_STORAGE) && defined(DBOARD_HAS_STORAGE) + cfg_cmd_storage_get_header = 0x0c, + cfg_cmd_storage_get_modedata = 0x0d, + cfg_cmd_storage_flush_data = 0x0e, +#endif }; // common commands for every mode