Repository: HaoboGu/rmk (language: rust)

Issue:
Add an option making it possible to update keymap when re-flashing



Discussion / hints:

Fix patch:
diff --git a/docs/src/faq.md b/docs/src/faq.md
index f7423c11..d4e9bc32 100644
--- a/docs/src/faq.md
+++ b/docs/src/faq.md
@@ -38,6 +38,18 @@ By default, Rust compiler generates `elf` file in target folder. There're a litt
   
   This script requires you have `python` command available in your commandline. Some platforms have `python3` command only, you can change `python` in `Makefile.toml` to `python3` in this case.
 
+### I changed keymap in `keyboard.toml`, but the keyboard is not updated
+
+RMK assumes that users change the keymap using [vial](https://vial.rocks). So reflashing the firmware won't change the keymap by default. For testing senario, RMK provides a config `clear_storage` under `[storage]` section, you can enable it to clear the storage when the keyboard boots.
+
+```toml
+[storage]
+# Set `clear_storage` to true to clear all the stored info when the keyboard boots
+clear_storage = true
+```
+
+Note that the storage will be clear EVERYTIME you reboot the keyboard.
+
 ### I can see a `RMK Start` log, but nothing else
 
 First you need to check the RCC config of your board, make sure that the USB's clock is enabled and set to 48MHZ. For example, if you're using stm32f1, you can set the RCC as the following:
diff --git a/docs/src/storage.md b/docs/src/storage.md
index 4e0b58f1..b3704f88 100644
--- a/docs/src/storage.md
+++ b/docs/src/storage.md
@@ -21,6 +21,10 @@ enabled = true
 start_addr = 0x00000000
 # How many sectors are used for storage, the default value is 2
 num_sectors = 2
+# Clear storage at keyboard boot. 
+# Set it to true will reset the storage(including keymap, BLE bond info, etc.) at each reboot.
+# This option is useful when testing the firmware.
+clear_storage = false
 ```
 
 You can also edit `storage_config` field in `RmkConfig` if you're using Rust API:
@@ -31,6 +35,7 @@ You can also edit `storage_config` field in `RmkConfig` if you're using Rust API
 let storage_config = StorageConfig {
     start_addr: 0x70000,
     num_sectors: 2,
+    ..Default::default()
 };
 let keyboard_config = RmkConfig {
     usb_config: keyboard_usb_config,
diff --git a/examples/use_config/nrf52840_ble/keyboard.toml b/examples/use_config/nrf52840_ble/keyboard.toml
index d890ff24..510fed94 100644
--- a/examples/use_config/nrf52840_ble/keyboard.toml
+++ b/examples/use_config/nrf52840_ble/keyboard.toml
@@ -19,7 +19,7 @@ cols = 3
 layers = 2
 keymap = [
     [
-        ["A", "B", "C"],
+        ["A", "A", "A"],
         ["Kc1", "Kc2", "Kc3"],
         ["LCtrl", "MO(1)", "LShift"],
         ["OSL(1)", "LT(2, Kc9)", "LM(1, LShift | LGui)"]
@@ -45,6 +45,7 @@ capslock.low_active = false
 [storage]
 # Storage feature is enabled by default
 # enabled = false
+clear_storage = true
 
 [ble]
 enabled = true
diff --git a/examples/use_rust/nrf52832_ble/src/main.rs b/examples/use_rust/nrf52832_ble/src/main.rs
index 9e58d1ed..c0ad7c2a 100644
--- a/examples/use_rust/nrf52832_ble/src/main.rs
+++ b/examples/use_rust/nrf52832_ble/src/main.rs
@@ -47,6 +47,7 @@ async fn main(spawner: Spawner) {
     let storage_config = StorageConfig {
         start_addr: 0x70000,
         num_sectors: 2,
+        ..Default::default()
     };
     let keyboard_config = RmkConfig {
         usb_config: keyboard_usb_config,
diff --git a/examples/use_rust/nrf52840_ble/src/main.rs b/examples/use_rust/nrf52840_ble/src/main.rs
index 9b20ea00..a2692a41 100644
--- a/examples/use_rust/nrf52840_ble/src/main.rs
+++ b/examples/use_rust/nrf52840_ble/src/main.rs
@@ -96,6 +96,7 @@ async fn main(spawner: Spawner) {
     let storage_config = StorageConfig {
         start_addr: 0,
         num_sectors: 6,
+        ..Default::default()
     };
     let keyboard_config = RmkConfig {
         usb_config: keyboard_usb_config,
diff --git a/examples/use_rust/nrf52840_ble_split/src/central.rs b/examples/use_rust/nrf52840_ble_split/src/central.rs
index fc587fba..c7cf9805 100644
--- a/examples/use_rust/nrf52840_ble_split/src/central.rs
+++ b/examples/use_rust/nrf52840_ble_split/src/central.rs
@@ -98,6 +98,7 @@ async fn main(spawner: Spawner) {
     let storage_config = StorageConfig {
         start_addr: 0,
         num_sectors: 6,
+        ..Default::default()
     };
     let keyboard_config = RmkConfig {
         usb_config: keyboard_usb_config,
diff --git a/rmk-macro/CHANGELOG.md b/rmk-macro/CHANGELOG.md
index 4e5bb70e..eb4138e6 100644
--- a/rmk-macro/CHANGELOG.md
+++ b/rmk-macro/CHANGELOG.md
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## [Unreleased]
 
+### Added
+
+- Add `clear_storage` option
+
 ## [0.3.4] - 2024-11-27
 
 ### Changed
diff --git a/rmk-macro/src/config/mod.rs b/rmk-macro/src/config/mod.rs
index 42091ebd..25cff483 100644
--- a/rmk-macro/src/config/mod.rs
+++ b/rmk-macro/src/config/mod.rs
@@ -77,6 +77,8 @@ pub struct StorageConfig {
     pub num_sectors: Option<u8>,
     #[serde(default = "default_true")]
     pub enabled: bool,
+    // Clear on the storage at reboot, set this to true if you want to reset the keymap
+    pub clear_storage: Option<bool>,
 }
 
 #[derive(Clone, Default, Debug, Deserialize)]
diff --git a/rmk-macro/src/default_config/esp32.rs b/rmk-macro/src/default_config/esp32.rs
index 687402ce..1a2a48be 100644
--- a/rmk-macro/src/default_config/esp32.rs
+++ b/rmk-macro/src/default_config/esp32.rs
@@ -17,6 +17,7 @@ pub(crate) fn default_esp32(chip: ChipModel) -> KeyboardConfig {
             start_addr: Some(0),
             num_sectors: Some(32),
             enabled: true,
+            ..Default::default()
         },
         ..Default::default()
     }
diff --git a/rmk-macro/src/default_config/nrf52810.rs b/rmk-macro/src/default_config/nrf52810.rs
index c9bba451..593de49c 100644
--- a/rmk-macro/src/default_config/nrf52810.rs
+++ b/rmk-macro/src/default_config/nrf52810.rs
@@ -17,6 +17,7 @@ pub(crate) fn default_nrf52810(chip: ChipModel) -> KeyboardConfig {
             start_addr: Some(0x28000),
             num_sectors: Some(8),
             enabled: true,
+            ..Default::default()
         },
         ..Default::default()
     }
diff --git a/rmk-macro/src/default_config/nrf52832.rs b/rmk-macro/src/default_config/nrf52832.rs
index 16680e3e..9dc631c9 100644
--- a/rmk-macro/src/default_config/nrf52832.rs
+++ b/rmk-macro/src/default_config/nrf52832.rs
@@ -16,6 +16,7 @@ pub(crate) fn default_nrf52832(chip: ChipModel) -> KeyboardConfig {
             start_addr: Some(0x60000),
             num_sectors: Some(16),
             enabled: true,
+            ..Default::default()
         },
         ..Default::default()
     }
diff --git a/rmk-macro/src/default_config/nrf52840.rs b/rmk-macro/src/default_config/nrf52840.rs
index 8d2372ff..1250ed12 100644
--- a/rmk-macro/src/default_config/nrf52840.rs
+++ b/rmk-macro/src/default_config/nrf52840.rs
@@ -26,6 +26,7 @@ pub(crate) fn default_nrf52840(chip: ChipModel) -> KeyboardConfig {
             start_addr: Some(0x60000),
             num_sectors: Some(16),
             enabled: true,
+            ..Default::default()
         },
         ..Default::default()
     }
diff --git a/rmk-macro/src/default_config/rp2040.rs b/rmk-macro/src/default_config/rp2040.rs
index 39c9bd4b..a414c948 100644
--- a/rmk-macro/src/default_config/rp2040.rs
+++ b/rmk-macro/src/default_config/rp2040.rs
@@ -15,6 +15,7 @@ pub(crate) fn default_rp2040(chip: ChipModel) -> KeyboardConfig {
             start_addr: Some(0),
             num_sectors: Some(16),
             enabled: true,
+            ..Default::default()
         },
         ..Default::default()
     }
diff --git a/rmk-macro/src/default_config/stm32.rs b/rmk-macro/src/default_config/stm32.rs
index 6582987e..325d2de0 100644
--- a/rmk-macro/src/default_config/stm32.rs
+++ b/rmk-macro/src/default_config/stm32.rs
@@ -15,6 +15,7 @@ pub(crate) fn default_stm32(chip: ChipModel) -> KeyboardConfig {
             start_addr: Some(0),
             num_sectors: Some(2),
             enabled: true,
+            ..Default::default()
         },
         ..Default::default()
     }
diff --git a/rmk-macro/src/flash.rs b/rmk-macro/src/flash.rs
index 9a211311..1c70e3f2 100644
--- a/rmk-macro/src/flash.rs
+++ b/rmk-macro/src/flash.rs
@@ -47,10 +47,12 @@ pub(crate) fn expand_flash_init(keyboard_config: &KeyboardConfig) -> TokenStream
 fn get_storage_config(storage_config: &StorageConfig) -> TokenStream2 {
     let num_sectors = storage_config.num_sectors.unwrap_or(2);
     let start_addr = storage_config.start_addr.unwrap_or(0);
+    let clear_storage = storage_config.clear_storage.unwrap_or(false);
     quote! {
         let storage_config = ::rmk::config::StorageConfig {
             num_sectors: #num_sectors,
-            start_addr: #start_addr
+            start_addr: #start_addr,
+            clear_storage: #clear_storage
         };
     }
 }
diff --git a/rmk-macro/src/keyboard_config.rs b/rmk-macro/src/keyboard_config.rs
index 69f0e376..e08e8ec9 100644
--- a/rmk-macro/src/keyboard_config.rs
+++ b/rmk-macro/src/keyboard_config.rs
@@ -464,6 +464,7 @@ impl KeyboardConfig {
             // Use default setting if the corresponding field is not set
             storage.start_addr = storage.start_addr.or(default.start_addr);
             storage.num_sectors = storage.num_sectors.or(default.num_sectors);
+            storage.clear_storage = storage.clear_storage.or(default.clear_storage);
             storage
         } else {
             default
diff --git a/rmk/CHANGELOG.md b/rmk/CHANGELOG.md
index 5c091164..57a6b368 100644
--- a/rmk/CHANGELOG.md
+++ b/rmk/CHANGELOG.md
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## [Unreleased]
 
+### Added
+
+- Add `clear_storage` option
+
 ### Changed
 
 - Remove `rmk-config`
diff --git a/rmk/src/ble/esp/mod.rs b/rmk/src/ble/esp/mod.rs
index 6ab2496b..b9ea28ca 100644
--- a/rmk/src/ble/esp/mod.rs
+++ b/rmk/src/ble/esp/mod.rs
@@ -53,6 +53,7 @@ pub(crate) async fn initialize_esp_ble_keyboard_with_config_and_run<
         StorageConfig {
             start_addr: 0,
             num_sectors,
+            ..Default::default()
         },
     )
     .await;
diff --git a/rmk/src/config/mod.rs b/rmk/src/config/mod.rs
index e75ad2c4..03147bf3 100644
--- a/rmk/src/config/mod.rs
+++ b/rmk/src/config/mod.rs
@@ -68,6 +68,7 @@ pub struct StorageConfig {
     pub start_addr: usize,
     // Number of sectors used for storage, >= 2.
     pub num_sectors: u8,
+    pub clear_storage: bool,
 }
 
 impl Default for StorageConfig {
@@ -75,6 +76,7 @@ impl Default for StorageConfig {
         Self {
             start_addr: 0,
             num_sectors: 2,
+            clear_storage: false,
         }
     }
 }
diff --git a/rmk/src/storage/mod.rs b/rmk/src/storage/mod.rs
index fc67a273..fd707875 100644
--- a/rmk/src/storage/mod.rs
+++ b/rmk/src/storage/mod.rs
@@ -1,6 +1,7 @@
 mod eeconfig;
 pub mod nor_flash;
 
+use crate::config::StorageConfig;
 use byteorder::{BigEndian, ByteOrder};
 use core::fmt::Debug;
 use core::ops::Range;
@@ -9,7 +10,6 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
 use embassy_sync::channel::Channel;
 use embedded_storage::nor_flash::NorFlash;
 use embedded_storage_async::nor_flash::NorFlash as AsyncNorFlash;
-use crate::config::StorageConfig;
 use sequential_storage::{
     cache::NoCache,
     map::{fetch_item, store_item, SerializationError, Value},
@@ -388,6 +388,11 @@ impl<F: AsyncNorFlash, const ROW: usize, const COL: usize, const NUM_LAYER: usiz
             buffer: [0; get_buffer_size()],
         };
 
+        if config.clear_storage {
+            // Clear storage
+            let _ = sequential_storage::erase_all(&mut storage.flash, storage.storage_range.clone()).await;
+        }
+
         // Check whether keymap and configs have been storaged in flash
         if !storage.check_enable().await {
             // Initialize storage from keymap and config


Test patch: