Browse Source

put persistent config storage at end of flash

Thomas Buck 1 year ago
parent
commit
2dcf213eca
6 changed files with 126 additions and 2 deletions
  1. 3
    0
      CMakeLists.txt
  2. 40
    0
      include/mem.h
  3. 5
    1
      src/main.c
  4. 73
    0
      src/mem.c
  5. 4
    0
      src/menu.c
  6. 1
    1
      src/state_scan.c

+ 3
- 0
CMakeLists.txt View File

@@ -87,6 +87,7 @@ target_sources(gadget PUBLIC
87 87
     src/state_volcano_run.c
88 88
     src/crafty.c
89 89
     src/state_crafty.c
90
+    src/mem.c
90 91
 
91 92
     ${CMAKE_CURRENT_BINARY_DIR}/fatfs/ff.c
92 93
     ${CMAKE_CURRENT_BINARY_DIR}/fatfs/ffunicode.c
@@ -147,6 +148,8 @@ target_link_libraries(gadget
147 148
     pico_btstack_ble
148 149
     pico_btstack_cyw43
149 150
     pico_cyw43_arch_threadsafe_background
151
+    hardware_flash
152
+    pico_flash
150 153
 )
151 154
 
152 155
 target_compile_definitions(gadget PUBLIC

+ 40
- 0
include/mem.h View File

@@ -0,0 +1,40 @@
1
+/*
2
+ * mem.h
3
+ *
4
+ * Copyright (c) 2023 Thomas Buck (thomas@xythobuz.de)
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * See <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#ifndef __MEM_H__
20
+#define __MEM_H__
21
+
22
+#include <stdint.h>
23
+
24
+#define MEM_VERSION 0x01
25
+
26
+struct mem_data {
27
+    uint8_t version;
28
+    uint16_t backlight;
29
+} __attribute__((packed));
30
+
31
+#define MEM_DATA_INIT {         \
32
+    .version = MEM_VERSION,     \
33
+    .backlight = (0xFF00 >> 1), \
34
+}
35
+
36
+void mem_init(void);
37
+void mem_write(void);
38
+struct mem_data *mem_data(void);
39
+
40
+#endif // __MEM_H__

+ 5
- 1
src/main.c View File

@@ -33,6 +33,7 @@
33 33
 #include "lcd.h"
34 34
 #include "text.h"
35 35
 #include "image.h"
36
+#include "mem.h"
36 37
 #include "state.h"
37 38
 #include "serial.h"
38 39
 #include "workflow.h"
@@ -50,10 +51,13 @@ int main(void) {
50 51
     serial_init();
51 52
     usb_init();
52 53
 
54
+    debug("mem_init");
55
+    mem_init();
56
+
53 57
     debug("lcd_init");
54 58
     lcd_init();
55 59
     draw_splash();
56
-    lcd_set_backlight(0xFF00 >> 1);
60
+    lcd_set_backlight(mem_data()->backlight);
57 61
 
58 62
     if (watchdog_caused_reboot()) {
59 63
         debug("reset by watchdog");

+ 73
- 0
src/mem.c View File

@@ -0,0 +1,73 @@
1
+/*
2
+ * mem.c
3
+ *
4
+ * Copyright (c) 2023 Thomas Buck (thomas@xythobuz.de)
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * See <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#include <string.h>
20
+
21
+#include "hardware/flash.h"
22
+#include "pico/flash.h"
23
+
24
+#include "config.h"
25
+#include "log.h"
26
+#include "mem.h"
27
+
28
+#define FLASH_LOCK_TIMEOUT_MS 500
29
+#define FLASH_OFFSET (PICO_FLASH_SIZE_BYTES - FLASH_SECTOR_SIZE)
30
+
31
+static struct mem_data data_ram = MEM_DATA_INIT;
32
+static const uint8_t *data_flash = (const uint8_t *)(XIP_BASE + FLASH_OFFSET);
33
+
34
+static_assert(sizeof(struct mem_data) < FLASH_SECTOR_SIZE,
35
+              "Config needs to fit inside a flash sector");
36
+
37
+void mem_init(void) {
38
+    if (!flash_safe_execute_core_init()) {
39
+        debug("error calling flash_safe_execute_core_init");
40
+    }
41
+
42
+    const struct mem_data *flash_ptr = (const struct mem_data *)data_flash;
43
+
44
+    if (flash_ptr->version == MEM_VERSION) {
45
+        debug("found matching config (0x%02X)", flash_ptr->version);
46
+        data_ram = *flash_ptr;
47
+    } else {
48
+        debug("invalid config (0x%02X != 0x%02X)", flash_ptr->version, MEM_VERSION);
49
+    }
50
+}
51
+
52
+static void mem_write_flash(void *param) {
53
+    flash_range_erase(FLASH_OFFSET, FLASH_SECTOR_SIZE);
54
+
55
+    // TODO only need to write with length multiple of FLASH_PAGE_SIZE
56
+    flash_range_program(FLASH_OFFSET, param, FLASH_SECTOR_SIZE);
57
+}
58
+
59
+void mem_write(void) {
60
+    if (memcmp(&data_ram, data_flash, sizeof(struct mem_data)) == 0) {
61
+        debug("no change, skip write");
62
+        return;
63
+    }
64
+
65
+    int r = flash_safe_execute(mem_write_flash, &data_ram, FLASH_LOCK_TIMEOUT_MS);
66
+    if (r != PICO_OK) {
67
+        debug("error calling mem_write_flash: %d", r);
68
+    }
69
+}
70
+
71
+struct mem_data *mem_data(void) {
72
+    return &data_ram;
73
+}

+ 4
- 0
src/menu.c View File

@@ -22,6 +22,7 @@
22 22
 #include "buttons.h"
23 23
 #include "text.h"
24 24
 #include "lcd.h"
25
+#include "mem.h"
25 26
 #include "menu.h"
26 27
 
27 28
 static char prev_buff[MENU_MAX_LEN] = {0};
@@ -37,6 +38,7 @@ static void menu_buttons(enum buttons btn, bool state) {
37 38
             backlight_value = backlight_value >> 1;
38 39
         }
39 40
         lcd_set_backlight(backlight_value);
41
+        mem_data()->backlight = backlight_value;
40 42
         return;
41 43
     } else if (state && (btn == BTN_RIGHT)) {
42 44
         uint16_t backlight_value = lcd_get_backlight();
@@ -44,6 +46,7 @@ static void menu_buttons(enum buttons btn, bool state) {
44 46
             backlight_value = backlight_value << 1;
45 47
         }
46 48
         lcd_set_backlight(backlight_value);
49
+        mem_data()->backlight = backlight_value;
47 50
         return;
48 51
     } else if (state && ((btn == BTN_ENTER) || (btn == BTN_A))) {
49 52
         if (enter_callback) {
@@ -100,6 +103,7 @@ void menu_init(void (*enter)(int), void (*exit)(void)) {
100 103
 
101 104
 void menu_deinit(void) {
102 105
     buttons_callback(NULL);
106
+    mem_write();
103 107
 }
104 108
 
105 109
 void menu_run(void (*draw)(struct menu_state *), bool centered) {

+ 1
- 1
src/state_scan.c View File

@@ -58,8 +58,8 @@ void state_scan_enter(void) {
58 58
 }
59 59
 
60 60
 void state_scan_exit(void) {
61
-    menu_deinit();
62 61
     ble_scan(BLE_SCAN_OFF);
62
+    menu_deinit();
63 63
 }
64 64
 
65 65
 static void draw(struct menu_state *menu) {

Loading…
Cancel
Save