diff --git a/firmware/src/CMakeLists.txt b/firmware/src/CMakeLists.txt index 952270f..658997c 100644 --- a/firmware/src/CMakeLists.txt +++ b/firmware/src/CMakeLists.txt @@ -4,7 +4,7 @@ set(LWIP_ROOT ${PICO_SDK_PATH}/lib/lwip) function(make_firmware board board_def) pico_sdk_init() add_executable(${board} - main.c slider.c rgb.c button.c save.c config.c commands.c + main.c slider.c rgb.c button.c savedata.c config.c commands.c cli.c mpr121.c hebtn.c lzfx.c usb_descriptors.c ps4_feat.c) target_compile_definitions(${board} PUBLIC ${board_def}) pico_enable_stdio_usb(${board} 1) diff --git a/firmware/src/cli.c b/firmware/src/cli.c index 6725bc4..f5c5d33 100644 --- a/firmware/src/cli.c +++ b/firmware/src/cli.c @@ -7,8 +7,9 @@ #include "pico/stdio.h" #include "pico/stdlib.h" #include "pico/bootrom.h" +#include "pico/unique_id.h" + #include "cli.h" -#include "save.h" #define MAX_COMMANDS 32 #define MAX_PARAMETERS 10 @@ -24,6 +25,13 @@ static int max_cmd_len = 0; static int num_commands = 0; +uint64_t board_id_64() +{ + pico_unique_board_id_t id; + pico_get_unique_board_id(&id); + return *(uint64_t *)(id.id); +} + void cli_register(const char *cmd, cmd_handler_t handler, const char *help) { if (num_commands < MAX_COMMANDS) { diff --git a/firmware/src/commands.c b/firmware/src/commands.c index a0da068..245790e 100644 --- a/firmware/src/commands.c +++ b/firmware/src/commands.c @@ -10,7 +10,7 @@ #include "config.h" #include "slider.h" #include "hebtn.h" -#include "save.h" +#include "savedata.h" #include "cli.h" #include "usb_descriptors.h" @@ -190,7 +190,7 @@ static void handle_keymap(int argc, char *argv[]) diva_cfg->hid.joy_map = match; disp_hid(); - save_request(true); + savedata_request(true); printf("Please replug the controller to apply the change.\n"); } @@ -405,7 +405,7 @@ static void handle_debug(int argc, char *argv[]) static void handle_save() { - save_request(true); + savedata_request(true); } static void handle_factory_reset() diff --git a/firmware/src/config.c b/firmware/src/config.c index bcc8c4b..99f232b 100644 --- a/firmware/src/config.c +++ b/firmware/src/config.c @@ -7,7 +7,7 @@ */ #include "config.h" -#include "save.h" +#include "savedata.h" diva_cfg_t *diva_cfg; @@ -66,16 +66,16 @@ static void config_loaded() void config_changed() { - save_request(false); + savedata_request(false); } void config_factory_reset() { *diva_cfg = default_cfg; - save_request(true); + savedata_request(true); } void config_init() { - diva_cfg = (diva_cfg_t *)save_alloc(sizeof(*diva_cfg), &default_cfg, config_loaded); + diva_cfg = (diva_cfg_t *)savedata_alloc(sizeof(*diva_cfg), &default_cfg, config_loaded); } diff --git a/firmware/src/main.c b/firmware/src/main.c index 5cb3517..e010e12 100644 --- a/firmware/src/main.c +++ b/firmware/src/main.c @@ -24,7 +24,7 @@ #include "board_defs.h" -#include "save.h" +#include "savedata.h" #include "config.h" #include "cli.h" #include "commands.h" @@ -196,15 +196,18 @@ static void run_lights() } } -static mutex_t core1_io_lock; +static void core1_init() +{ + flash_safe_execute_core_init(); +} + static void core1_loop() { + core1_init(); + while (1) { - if (mutex_try_enter(&core1_io_lock, NULL)) { - run_lights(); - rgb_update(); - mutex_exit(&core1_io_lock); - } + run_lights(); + rgb_update(); cli_fps_count(1); sleep_us(700); } @@ -219,7 +222,7 @@ static void core0_loop() cli_run(); - save_loop(); + savedata_loop(); cli_fps_count(0); button_update(); @@ -291,8 +294,7 @@ void init() update_check(); config_init(); - mutex_init(&core1_io_lock); - save_init(0xca44cafe, &core1_io_lock); + savedata_init(0xca44cafe); slider_init(); rgb_init(); diff --git a/firmware/src/save.h b/firmware/src/save.h deleted file mode 100644 index cde4229..0000000 --- a/firmware/src/save.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Controller Flash Save and Load - * WHowe - */ - -#ifndef SAVE_H -#define SAVE_H - -#include -#include -#include - -#include "pico/multicore.h" - -uint32_t board_id_32(); -uint64_t board_id_64(); - -/* It's safer to lock other I/O ops during saving, so we need a locker */ -typedef void (*io_locker_func)(bool pause); -void save_init(uint32_t magic, mutex_t *lock); - -void save_loop(); - -void *save_alloc(size_t size, void *def, void (*after_load)()); -void save_request(bool immediately); - -#endif diff --git a/firmware/src/save.c b/firmware/src/savedata.c similarity index 61% rename from firmware/src/save.c rename to firmware/src/savedata.c index 3afec3c..10444a3 100644 --- a/firmware/src/save.c +++ b/firmware/src/savedata.c @@ -5,21 +5,20 @@ * Config is stored in last sector of flash */ -#include "save.h" +#include "savedata.h" #include #include +#include #include #include -#include "bsp/board.h" #include "pico/bootrom.h" #include "pico/stdio.h" #include "hardware/flash.h" #include "pico/multicore.h" -#include "pico/unique_id.h" static struct { size_t size; @@ -33,6 +32,9 @@ static uint32_t my_magic = 0xcafecafe; #define SAVE_TIMEOUT_US 5000000 #define SAVE_SECTOR_OFFSET (PICO_FLASH_SIZE_BYTES - FLASH_SECTOR_SIZE) +#define GLOBAL_SECTOR_NUM 2 +#define GLOBAL_SECTOR_SIZE (GLOBAL_SECTOR_NUM * FLASH_SECTOR_SIZE) +#define GLOBAL_SECTOR_OFFSET (SAVE_SECTOR_OFFSET - GLOBAL_SECTOR_SIZE) typedef struct __attribute ((packed)) { uint32_t magic; @@ -47,26 +49,25 @@ static int data_page = -1; static bool requesting_save = false; static uint64_t requesting_time = 0; -static mutex_t *io_lock; -static void save_program() +static void do_write(void *param) { - old_data = new_data; - - data_page = (data_page + 1) % (FLASH_SECTOR_SIZE / FLASH_PAGE_SIZE); - printf("\nProgram Flash %d %8lx\n", data_page, old_data.magic); - if (mutex_enter_timeout_us(io_lock, 100000)) { - sleep_ms(10); /* wait for all io operations to finish */ - uint32_t ints = save_and_disable_interrupts(); if (data_page == 0) { flash_range_erase(SAVE_SECTOR_OFFSET, FLASH_SECTOR_SIZE); } flash_range_program(SAVE_SECTOR_OFFSET + data_page * FLASH_PAGE_SIZE, (uint8_t *)&old_data, FLASH_PAGE_SIZE); - restore_interrupts(ints); - mutex_exit(io_lock); +} + +static void save_program() +{ + old_data = new_data; + data_page = (data_page + 1) % (FLASH_SECTOR_SIZE / FLASH_PAGE_SIZE); + printf("\nProgram Save %d %8lx ", data_page, old_data.magic); + if (flash_safe_execute(do_write, NULL, 1000) != PICO_OK) { + printf("Failed!\n"); } else { - printf("Program Flash Failed.\n"); + printf("Done.\n"); } } @@ -94,7 +95,7 @@ static void save_load() if (data_page < 0) { load_default(); - save_request(false); + savedata_request(false); return; } @@ -110,37 +111,15 @@ static void save_loaded() } } -static union __attribute__((packed)) { - pico_unique_board_id_t id; - struct { - uint32_t id32h; - uint32_t id32l; - }; - uint64_t id64; -} board_id; - -uint32_t board_id_32() -{ - pico_get_unique_board_id(&board_id.id); - return board_id.id32h ^ board_id.id32l; -} - -uint64_t board_id_64() -{ - pico_get_unique_board_id(&board_id.id); - return board_id.id64; -} - -void save_init(uint32_t magic, mutex_t *locker) +void savedata_init(uint32_t magic) { my_magic = magic; - io_lock = locker; save_load(); - save_loop(); + savedata_loop(); save_loaded(); } -void save_loop() +void savedata_loop() { if (requesting_save && (time_us_64() - requesting_time > SAVE_TIMEOUT_US)) { requesting_save = false; @@ -152,10 +131,16 @@ void save_loop() } } -void *save_alloc(size_t size, void *def, void (*after_load)()) +void *savedata_alloc(size_t size, void *def, void (*after_load)()) { + size_t offset = 0; + if (module_num > 0) { + offset = modules[module_num - 1].offset + modules[module_num - 1].size; + } + if (offset + size > sizeof(default_data.data)) { + return NULL; + } modules[module_num].size = size; - size_t offset = module_num > 0 ? modules[module_num - 1].offset + size : 0; modules[module_num].offset = offset; modules[module_num].after_load = after_load; module_num++; @@ -163,7 +148,7 @@ void *save_alloc(size_t size, void *def, void (*after_load)()) return new_data.data + offset; } -void save_request(bool immediately) +void savedata_request(bool immediately) { if (!requesting_save) { printf("Save requested.\n"); @@ -173,6 +158,42 @@ void save_request(bool immediately) } if (immediately) { requesting_time = 0; - save_loop(); + savedata_loop(); + } +} + + +void savedata_read_global(size_t offset, void *data, size_t size) +{ + if ((data == NULL) || (size == 0) || (offset >= GLOBAL_SECTOR_SIZE)) { + return; + } + if (size > GLOBAL_SECTOR_SIZE - offset) { + size = GLOBAL_SECTOR_SIZE - offset; + } + memcpy(data, (void *)(XIP_BASE + GLOBAL_SECTOR_OFFSET + offset), size); +} + +static void do_write_global(void *param) +{ + uintptr_t *p = (uintptr_t *)param; + const uint8_t *data = (const uint8_t *)p[0]; + size_t size = (size_t)p[1]; + + flash_range_erase(GLOBAL_SECTOR_OFFSET, GLOBAL_SECTOR_NUM * FLASH_SECTOR_SIZE); + flash_range_program(GLOBAL_SECTOR_OFFSET, data, size); +} + +void savedata_write_global(const void *data, size_t size) +{ + static uintptr_t param[2]; + param[0] = (uintptr_t)data; + param[1] = size; + + printf("Program Global %8x ", GLOBAL_SECTOR_OFFSET); + if (flash_safe_execute(do_write_global, param, 1000) != PICO_OK) { + printf("Failed!\n"); + } else { + printf("Done.\n"); } } diff --git a/firmware/src/savedata.h b/firmware/src/savedata.h new file mode 100644 index 0000000..d8078fb --- /dev/null +++ b/firmware/src/savedata.h @@ -0,0 +1,26 @@ +/* + * Controller Flash Save and Load + * WHowe + */ + +#ifndef SAVEDATA_H +#define SAVEDATA_H + +#include +#include +#include + +#include "pico/multicore.h" + +/* It's safer to lock other I/O ops during saving, so we need a locker */ +void savedata_init(uint32_t magic); + +void savedata_loop(); + +void *savedata_alloc(size_t size, void *def, void (*after_load)()); +void savedata_request(bool immediately); + +void savedata_read_global(size_t offset, void *data, size_t size); +void savedata_write_global(const void *data, size_t size); + +#endif