Browse Source

fat fs no longer in RAM. mkfs as part of build process. page cache to still be able to write from usb or app.

Thomas Buck 4 months ago
parent
commit
628b40423f
18 changed files with 425 additions and 172 deletions
  1. 3
    5
      CMakeLists.txt
  2. 1
    1
      conf/ffconf.h
  3. 15
    2
      conf/memmap_custom.ld
  4. 6
    0
      data/README.md
  5. 16
    5
      include/cache.h
  6. 3
    9
      include/config.h
  7. 2
    2
      include/debug_disk.h
  8. 10
    0
      include/mem.h
  9. 30
    13
      pack_data.sh
  10. 1
    1
      picowota
  11. 308
    0
      src/cache.c
  12. 7
    0
      src/console.c
  13. 2
    73
      src/debug_disk.c
  14. 5
    19
      src/fat_disk.c
  15. 5
    6
      src/http.c
  16. 4
    6
      src/main.c
  17. 3
    14
      src/mem.c
  18. 4
    16
      src/usb_msc.c

+ 3
- 5
CMakeLists.txt View File

@@ -114,6 +114,7 @@ target_sources(gadget PUBLIC
114 114
     src/state_wifi_edit.c
115 115
     src/state_string.c
116 116
     src/http.c
117
+    src/cache.c
117 118
 
118 119
     ${CMAKE_CURRENT_BINARY_DIR}/fatfs/ff.c
119 120
     ${CMAKE_CURRENT_BINARY_DIR}/fatfs/ffunicode.c
@@ -142,9 +143,9 @@ target_include_directories(gadget PUBLIC ${CMAKE_CURRENT_LIST_DIR}/build)
142 143
 target_include_directories(gadget PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
143 144
 
144 145
 # compress source code and stuff we want to include
145
-add_custom_target(pack bash -c "./pack_data.sh"
146
+add_custom_target(pack bash -c "./pack_data.sh ${CMAKE_CURRENT_BINARY_DIR}"
146 147
     WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
147
-    BYPRODUCTS "build/pack_data.h"
148
+    BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/fat_fs.o"
148 149
 )
149 150
 add_dependencies(gadget pack)
150 151
 
@@ -163,9 +164,6 @@ set_source_files_properties(pico-sdk/lib/btstack/src/classic/avdtp_util.c PROPER
163 164
 set_source_files_properties(pico-sdk/lib/btstack/src/classic/goep_client.c PROPERTIES COMPILE_FLAGS -Wno-unused-parameter)
164 165
 set_source_files_properties(pico-sdk/lib/btstack/src/classic/goep_server.c PROPERTIES COMPILE_FLAGS -Wno-unused-parameter)
165 166
 
166
-# suppress warnings for BittyHTTP
167
-set_source_files_properties(BittyHTTP/src/WebServer.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare -Wno-unused-parameter -Wno-maybe-uninitialized")
168
-
169 167
 # pull in common dependencies
170 168
 target_link_libraries(gadget
171 169
     pico_stdlib

+ 1
- 1
conf/ffconf.h View File

@@ -30,7 +30,7 @@
30 30
 /  f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
31 31
 
32 32
 
33
-#define FF_USE_MKFS		1
33
+#define FF_USE_MKFS		0
34 34
 /* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
35 35
 
36 36
 

+ 15
- 2
conf/memmap_custom.ld View File

@@ -3,12 +3,21 @@
3 3
  * https://community.element14.com/products/raspberry-pi/b/blog/posts/raspberry-pico-c-sdk-reserve-a-flash-memory-block-for-persistent-storage
4 4
  */
5 5
 
6
-/* TODO hard-coded. Should take into account PICO_FLASH_BANK_STORAGE_OFFSET */
6
+INPUT (./fat_fs.o)
7
+
8
+/*
9
+ * TODO hard-coded.
10
+ * Should take into account PICO_FLASH_BANK_STORAGE_OFFSET
11
+ * and DISK_BLOCK_SIZE and DISK_BLOCK_COUNT from config.h
12
+ */
7 13
 __PERSISTENT_STORAGE_LEN = (3 * 4k);
14
+__FLASH_CACHE_LEN = (48 * 4k);
15
+__ADDITIONAL_LEN = (__PERSISTENT_STORAGE_LEN + __FLASH_CACHE_LEN);
8 16
 
9 17
 MEMORY
10 18
 {
11
-    FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 2048k - __PERSISTENT_STORAGE_LEN
19
+    FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 2048k - __ADDITIONAL_LEN
20
+    FLASH_CACHE(r) : ORIGIN = 0x10000000 + (2048k - __ADDITIONAL_LEN) , LENGTH = __FLASH_CACHE_LEN
12 21
     FLASH_PERSISTENT(r) : ORIGIN = 0x10000000 + (2048k - __PERSISTENT_STORAGE_LEN) , LENGTH = __PERSISTENT_STORAGE_LEN
13 22
     RAM(rwx) : ORIGIN =  0x20000000, LENGTH = 256k
14 23
     SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k
@@ -216,6 +225,10 @@ SECTIONS
216 225
         KEEP(*(.stack*))
217 226
     } > SCRATCH_Y
218 227
 
228
+    .fat_fs_bin : {
229
+        KEEP(./fat_fs.o (.fat_fs_bin))
230
+    } > FLASH_CACHE
231
+
219 232
     .flash_end : {
220 233
         PROVIDE(__flash_binary_end = .);
221 234
     } > FLASH

+ 6
- 0
data/README.md View File

@@ -0,0 +1,6 @@
1
+# Volcano Remote Control Gadget
2
+
3
+Project by Thomas Buck <thomas@xythobuz.de>
4
+Licensed under GPLv3.
5
+See included 'src.tar.xz' for sources.
6
+Repo at https://git.xythobuz.de/thomas/sb-py

include/fat_disk.h → include/cache.h View File

@@ -1,7 +1,7 @@
1
-/* 
2
- * fat_disk.h
1
+/*
2
+ * cache.h
3 3
  *
4
- * Copyright (c) 2022 - 2023 Thomas Buck (thomas@xythobuz.de)
4
+ * Copyright (c) 2023 Thomas Buck (thomas@xythobuz.de)
5 5
  *
6 6
  * This program is free software: you can redistribute it and/or modify
7 7
  * it under the terms of the GNU General Public License as published by
@@ -16,6 +16,17 @@
16 16
  * See <http://www.gnu.org/licenses/>.
17 17
  */
18 18
 
19
-void fat_disk_init(void);
19
+#ifndef __CACHE_H__
20
+#define __CACHE_H__
20 21
 
21
-uint8_t *fat_disk_get_sector(uint32_t sector);
22
+#include <sys/types.h>
23
+
24
+void cache_init(void);
25
+void cache_status(void);
26
+void cache_sync(void);
27
+void cache_run(void);
28
+
29
+ssize_t cache_read(uint8_t *buf, size_t addr, size_t len);
30
+ssize_t cache_write(const uint8_t *buf, size_t addr, size_t len);
31
+
32
+#endif // __CACHE_H__

+ 3
- 9
include/config.h View File

@@ -34,10 +34,10 @@
34 34
 // Release build
35 35
 #define AUTO_MOUNT_MASS_STORAGE
36 36
 #define AUTO_LOG_ON_MASS_STORAGE
37
-#define DEBUG_DISK_WRITE_SOURCES
38 37
 #endif // NDEBUG
39 38
 
40 39
 #define WATCHDOG_PERIOD_MS 1000
40
+#define FLASH_LOCK_TIMEOUT_MS 500
41 41
 
42 42
 // ASCII 0x18 = CAN (cancel)
43 43
 #define ENTER_BOOTLOADER_MAGIC 0x18
@@ -47,15 +47,9 @@
47 47
 
48 48
 #define SERIAL_WRITES_BLOCK_WHEN_BUFFER_FULL
49 49
 
50
+// TODO needs to be the same as in pack_data.sh
50 51
 #define DISK_BLOCK_SIZE 512
51
-
52
-#ifdef DEBUG_DISK_WRITE_SOURCES
53
-#define DISK_ADD_BLOCKS_SOURCES 90 //128
54
-#else // DEBUG_DISK_WRITE_SOURCES
55
-#define DISK_ADD_BLOCKS_SOURCES 0
56
-#endif // DEBUG_DISK_WRITE_SOURCES
57
-
58
-#define DISK_BLOCK_COUNT (256 + DISK_ADD_BLOCKS_SOURCES)
52
+#define DISK_BLOCK_COUNT (256 + 128) // 384 * 512 = 196608
59 53
 
60 54
 //#define TEST_VOLCANO_AUTO_CONNECT "xx:xx:xx:xx:xx:xx 1"
61 55
 //#define TEST_CRAFTY_AUTO_CONNECT "xx:xx:xx:xx:xx:xx 0"

+ 2
- 2
include/debug_disk.h View File

@@ -19,9 +19,9 @@
19 19
 #ifndef __DEBUG_DISK_H__
20 20
 #define __DEBUG_DISK_H__
21 21
 
22
-void debug_disk_init(void);
23
-
24 22
 int debug_disk_mount(void);
25 23
 int debug_disk_unmount(void);
26 24
 
25
+void debug_disk_init_log(void);
26
+
27 27
 #endif // __DEBUG_DISK_H__

+ 10
- 0
include/mem.h View File

@@ -19,12 +19,22 @@
19 19
 #ifndef __MEM_H__
20 20
 #define __MEM_H__
21 21
 
22
+#include "hardware/flash.h"
23
+#include "pico/btstack_flash_bank.h"
24
+
22 25
 #include <stdint.h>
23 26
 #include <stdbool.h>
24 27
 
25 28
 #include "workflow.h"
26 29
 #include "wifi.h"
27 30
 
31
+/*
32
+ * Last two flash pages are used by BTstack.
33
+ * So we use the third-last page for our persistent storage.
34
+ * This is kept clear by our custom linker script.
35
+ */
36
+#define EEPROM_FLASH_OFFSET (PICO_FLASH_BANK_STORAGE_OFFSET - FLASH_SECTOR_SIZE)
37
+
28 38
 // to migrate settings when struct changes between releases
29 39
 #define MEM_VERSION 0
30 40
 

+ 30
- 13
pack_data.sh View File

@@ -18,23 +18,40 @@
18 18
 
19 19
 set -euo pipefail
20 20
 
21
+# TODO take from config.h
22
+DISK_BLOCK_SIZE=512
23
+DISK_BLOCK_COUNT=384
24
+
21 25
 cd "$(dirname "$0")"
22 26
 echo "Packing data"
23 27
 
24
-rm -rf build/src
25
-mkdir -p build/src
26
-cp COPYING build/src
27
-cp README.md build/src
28
-cp CMakeLists.txt build/src
29
-cp .gitmodules build/src/gitmodules
30
-cp -r include build/src
31
-cp -r conf build/src
32
-cp -r src build/src
33
-
34
-cd build
28
+rm -rf $1/src
29
+mkdir -p $1/src
30
+cp COPYING $1/src
31
+cp README.md $1/src
32
+cp CMakeLists.txt $1/src
33
+cp .gitmodules $1/src/gitmodules
34
+cp -r include $1/src
35
+cp -r conf $1/src
36
+cp -r src $1/src
37
+
38
+echo "Compressing data"
39
+cd $1
35 40
 rm -rf data.tar data.tar.xz
36 41
 tar -f data.tar -c src
37 42
 xz -z -9 data.tar
38 43
 
39
-xxd -i data.tar.xz > pack_data.h
40
-sed -i 's/unsigned/static const unsigned/g' pack_data.h
44
+echo "Creating empty bin"
45
+dd if=/dev/zero of=fat_fs.bin bs=$DISK_BLOCK_SIZE count=$DISK_BLOCK_COUNT
46
+
47
+echo "Writing FAT file system"
48
+mkfs.vfat fat_fs.bin
49
+
50
+echo "Copying source code archive"
51
+mcopy -i fat_fs.bin ../data/README.md ::README.md
52
+mcopy -i fat_fs.bin data.tar.xz ::src.tar.xz
53
+
54
+echo "Converting to object file"
55
+arm-none-eabi-objcopy -I binary -O elf32-littlearm \
56
+    --rename-section .data=.fat_fs_bin,CONTENTS,ALLOC,LOAD,READONLY,DATA \
57
+    fat_fs.bin fat_fs.o

+ 1
- 1
picowota

@@ -1 +1 @@
1
-Subproject commit 682ce01a0ea6ae9d702d404e3e24894f904c277d
1
+Subproject commit 9e9371e28b635a15d702c2f117a27831c8ce683e

+ 308
- 0
src/cache.c View File

@@ -0,0 +1,308 @@
1
+/*
2
+ * cache.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 <stdbool.h>
20
+#include <string.h>
21
+
22
+#include "pico/flash.h"
23
+
24
+#include "config.h"
25
+#include "log.h"
26
+#include "mem.h"
27
+#include "cache.h"
28
+
29
+#define CACHE_MAX_AGE_MS (5 * 1000)
30
+
31
+#define PAGE_SIZE FLASH_SECTOR_SIZE // 4K
32
+#define CACHE_ENTRIES 10 // 40K in RAM
33
+
34
+// 384 * 512 = 196608 bytes = 48 Pages (Sectors) in Flash
35
+#define DISK_SIZE (DISK_BLOCK_SIZE * DISK_BLOCK_COUNT)
36
+#define DISK_PAGES (DISK_SIZE / PAGE_SIZE)
37
+
38
+static_assert((DISK_SIZE % PAGE_SIZE) == 0, "Disk blocks need to fit cleanly into flash pages.");
39
+
40
+// PICO_FLASH_SIZE_BYTES is 2MB = 512 * 4K pages
41
+// BTstack uses the last two pages, we use one more for EEPROM config.
42
+// So 509 pages remain, minus the 48 pages for the FAT disk.
43
+// --> 461 pages remain for bootloader and application.
44
+// --> 461 * 4096 = 1888256 bytes
45
+#define CACHE_FLASH_OFFSET (EEPROM_FLASH_OFFSET - (DISK_PAGES * PAGE_SIZE))
46
+static_assert(DISK_PAGES == 48, "TODO conversions are hard-coded currently");
47
+
48
+struct cache_entry {
49
+    bool set;
50
+    size_t page;
51
+    bool dirty;
52
+    uint32_t age;
53
+    uint8_t buff[PAGE_SIZE];
54
+};
55
+
56
+static struct cache_entry cache[CACHE_ENTRIES] = {0};
57
+static const uint8_t *disk = (const uint8_t *)(XIP_BASE + CACHE_FLASH_OFFSET);
58
+
59
+void cache_init(void) {
60
+    for (size_t i = 0; i < CACHE_ENTRIES; i++) {
61
+        cache[i].set = false;
62
+    }
63
+}
64
+
65
+void cache_status(void) {
66
+    size_t count = 0;
67
+
68
+    for (size_t i = 0; i < CACHE_ENTRIES; i++) {
69
+        if (!cache[i].set) {
70
+            continue;
71
+        }
72
+
73
+        println("Cache Entry %d:", count);
74
+        println("  Page: %d", cache[i].page);
75
+        println("  Dirty: %s", cache[i].dirty ? "Yes" : "No");
76
+
77
+        uint32_t now = to_ms_since_boot(get_absolute_time());
78
+        println("  Age: %.1fs", (now - cache[i].age) / 1000.0f);
79
+
80
+        count++;
81
+    }
82
+
83
+    println("Total entries: %d", count);
84
+}
85
+
86
+struct cache_write_data {
87
+    uint32_t addr;
88
+    uint8_t *buff;
89
+};
90
+
91
+static void cache_write_flash(void *param) {
92
+    struct cache_write_data *tmp = param;
93
+    flash_range_erase(tmp->addr, PAGE_SIZE);
94
+    flash_range_program(tmp->addr, tmp->buff, PAGE_SIZE);
95
+}
96
+
97
+static void cache_flush(size_t i) {
98
+    // after this the cache entry is gone
99
+    cache[i].set = false;
100
+
101
+    // if it is not actually modified, we can bail out here
102
+    if (!cache[i].dirty) {
103
+        return;
104
+    }
105
+
106
+    // now actually write contents back to flash
107
+    uint32_t addr = CACHE_FLASH_OFFSET + (cache[i].page * PAGE_SIZE);
108
+    debug("flushing entry %d page %d at 0x%08lX", i, cache[i].page, addr);
109
+
110
+    struct cache_write_data tmp = { .addr = addr, .buff = cache[i].buff };
111
+    int r = flash_safe_execute(cache_write_flash, &tmp, FLASH_LOCK_TIMEOUT_MS);
112
+    if (r != PICO_OK) {
113
+        debug("error calling cache_write_flash: %d", r);
114
+    }
115
+}
116
+
117
+void cache_sync(void) {
118
+    for (size_t i = 0; i < CACHE_ENTRIES; i++) {
119
+        if (!cache[i].set) {
120
+            continue;
121
+        }
122
+
123
+        // just flush out all available entries
124
+        cache_flush(i);
125
+    }
126
+}
127
+
128
+void cache_run(void) {
129
+    for (size_t i = 0; i < CACHE_ENTRIES; i++) {
130
+        if (!cache[i].set) {
131
+            continue;
132
+        }
133
+
134
+        // only flush out entries that are too old
135
+        uint32_t now = to_ms_since_boot(get_absolute_time());
136
+        if ((now - cache[i].age) >= CACHE_MAX_AGE_MS) {
137
+            cache_flush(i);
138
+        }
139
+    }
140
+}
141
+
142
+static ssize_t cache_read_single(uint8_t *buf, size_t page, size_t off, size_t len) {
143
+    if (page >= DISK_PAGES) {
144
+        debug("error: invalid page %d", page);
145
+        return -1;
146
+    }
147
+
148
+    if ((off + len) > PAGE_SIZE) {
149
+        debug("error: too long %d %d", off, len);
150
+        return -1;
151
+    }
152
+
153
+    // is it in the cache?
154
+    for (size_t i = 0; i < CACHE_ENTRIES; i++) {
155
+        if (!cache[i].set) {
156
+            continue;
157
+        }
158
+
159
+        if (cache[i].page != page) {
160
+            continue;
161
+        }
162
+
163
+        // it is in the cache!
164
+        memcpy(buf, cache[i].buff + off, len);
165
+        return len;
166
+    }
167
+
168
+    // not in cache, read directly from flash
169
+    memcpy(buf, disk + (page * PAGE_SIZE) + off, len);
170
+    return len;
171
+}
172
+
173
+static ssize_t write_into_cache(size_t idx, const uint8_t *buf, size_t off, size_t len) {
174
+    bool changed = false;
175
+    for (size_t i = 0; i < len; i++) {
176
+        if (cache[idx].buff[off + i] != buf[i]) {
177
+            changed = true;
178
+        }
179
+
180
+        cache[idx].buff[off + i] = buf[i];
181
+    }
182
+
183
+    if (changed) {
184
+        cache[idx].dirty = true;
185
+        cache[idx].age = to_ms_since_boot(get_absolute_time());
186
+    }
187
+
188
+    return len;
189
+}
190
+
191
+static ssize_t cache_write_single(const uint8_t *buf, size_t page, size_t off, size_t len) {
192
+    if (page >= DISK_PAGES) {
193
+        debug("error: invalid page %d", page);
194
+        return -1;
195
+    }
196
+
197
+    if ((off + len) > PAGE_SIZE) {
198
+        debug("error: too long %d %d", off, len);
199
+        return -1;
200
+    }
201
+
202
+    // is it in the cache?
203
+    for (size_t i = 0; i < CACHE_ENTRIES; i++) {
204
+        if (!cache[i].set) {
205
+            continue;
206
+        }
207
+
208
+        if (cache[i].page != page) {
209
+            continue;
210
+        }
211
+
212
+        // it is in the cache!
213
+        return write_into_cache(i, buf, off, len);
214
+    }
215
+
216
+    // not in cache yet, find free cache entry
217
+    ssize_t free = -1, oldest = -1;
218
+    uint32_t min_age = 0xFFFFFFFF;
219
+    for (size_t i = 0; i < CACHE_ENTRIES; i++) {
220
+        if (!cache[i].set) {
221
+            if (free < 0) {
222
+                free = i;
223
+            }
224
+        }
225
+
226
+        if (cache[i].age < min_age) {
227
+            min_age = cache[i].age;
228
+            oldest = i;
229
+        }
230
+    }
231
+
232
+    if (free < 0) {
233
+        // flush oldest current entry and use its place
234
+        if (oldest < 0) {
235
+            debug("error, no oldest entry?!");
236
+            return -1;
237
+        }
238
+
239
+        cache_flush(oldest);
240
+        free = oldest;
241
+    }
242
+
243
+    // populate new cache entry
244
+    cache[free].set = true;
245
+    cache[free].page = page;
246
+    cache[free].dirty = false;
247
+    cache[free].age = to_ms_since_boot(get_absolute_time());
248
+    memcpy(cache[free].buff, disk + (page * PAGE_SIZE), PAGE_SIZE);
249
+
250
+    debug("add cache %d for page %d", free, page);
251
+
252
+    // perform write operation into cache entry
253
+    return write_into_cache(free, buf, off, len);
254
+}
255
+
256
+ssize_t cache_read(uint8_t *buf, size_t addr, size_t len) {
257
+    size_t page = addr / PAGE_SIZE;
258
+    size_t off = addr % PAGE_SIZE;
259
+    size_t count = 0;
260
+
261
+    while ((off + len) > PAGE_SIZE) {
262
+        debug("split cache page read");
263
+
264
+        size_t chunk = PAGE_SIZE - off;
265
+        ssize_t r = cache_read_single(buf + count, page, off, chunk);
266
+        if (r < 0) {
267
+            return r;
268
+        }
269
+        count += r;
270
+        len -= r;
271
+        off = 0;
272
+        page++;
273
+    }
274
+
275
+    ssize_t r = cache_read_single(buf + count, page, off, len);
276
+    if (r < 0) {
277
+        return r;
278
+    }
279
+    count += r;
280
+    return count;
281
+}
282
+
283
+ssize_t cache_write(const uint8_t *buf, size_t addr, size_t len) {
284
+    size_t page = addr / PAGE_SIZE;
285
+    size_t off = addr % PAGE_SIZE;
286
+    size_t count = 0;
287
+
288
+    while ((off + len) > PAGE_SIZE) {
289
+        debug("split cache page write");
290
+
291
+        size_t chunk = PAGE_SIZE - off;
292
+        ssize_t r = cache_write_single(buf + count, page, off, chunk);
293
+        if (r < 0) {
294
+            return r;
295
+        }
296
+        count += r;
297
+        len -= r;
298
+        off = 0;
299
+        page++;
300
+    }
301
+
302
+    ssize_t r = cache_write_single(buf + count, page, off, len);
303
+    if (r < 0) {
304
+        return r;
305
+    }
306
+    count += r;
307
+    return count;
308
+}

+ 7
- 0
src/console.c View File

@@ -42,6 +42,7 @@
42 42
 #include "workflow.h"
43 43
 #include "crafty.h"
44 44
 #include "mem.h"
45
+#include "cache.h"
45 46
 #include "console.h"
46 47
 
47 48
 #define CNSL_BUFF_SIZE 64
@@ -103,6 +104,8 @@ static void cnsl_interpret(const char *line) {
103 104
         println("  power - show Lipo battery status");
104 105
         println("   memr - reset flash memory config");
105 106
         println("     bl - print backlight pwm level");
107
+        println("  cache - print flash cache status");
108
+        println("  flush - flush flash cache");
106 109
         println("");
107 110
         println("   scan - start or stop BLE scan");
108 111
         println("scanres - print list of found BLE devices");
@@ -158,6 +161,10 @@ static void cnsl_interpret(const char *line) {
158 161
         mem_write();
159 162
     } else if (strcmp(line, "bl") == 0) {
160 163
         println("bl: 0x%04X", mem_data()->backlight);
164
+    } else if (strcmp(line, "cache") == 0) {
165
+        cache_status();
166
+    } else if (strcmp(line, "flush") == 0) {
167
+        cache_sync();
161 168
     } else if (strcmp(line, "scan") == 0) {
162 169
         ble_scan(BLE_SCAN_TOGGLE);
163 170
     } else if (strcmp(line, "scanres") == 0) {

+ 2
- 73
src/debug_disk.c View File

@@ -26,87 +26,16 @@
26 26
 #include "log.h"
27 27
 #include "debug_disk.h"
28 28
 
29
-#ifdef DEBUG_DISK_WRITE_SOURCES
30
-#include "pack_data.h"
31
-#endif // DEBUG_DISK_WRITE_SOURCES
32
-
33 29
 static FATFS fs;
34 30
 static bool mounted = false;
35 31
 
36
-static void write_readme(void) {
37
-    FIL file;
38
-    FRESULT res = f_open(&file, "README.md", FA_CREATE_ALWAYS | FA_WRITE);
39
-    if (res != FR_OK) {
40
-        debug("error: f_open returned %d", res);
41
-    } else {
42
-        char readme[1024];
43
-        size_t pos = 0;
44
-        pos += snprintf(readme + pos, 1024 - pos, "# Volcano Remote Control Gadget\r\n");
45
-        pos += snprintf(readme + pos, 1024 - pos, "\r\n");
46
-        pos += snprintf(readme + pos, 1024 - pos, "Project by Thomas Buck <thomas@xythobuz.de>\r\n");
47
-        pos += snprintf(readme + pos, 1024 - pos, "Licensed under GPLv3.\r\n");
48
-        pos += snprintf(readme + pos, 1024 - pos, "See included 'src.tar.xz' for sources.\r\n");
49
-        pos += snprintf(readme + pos, 1024 - pos, "Repo at https://git.xythobuz.de/thomas/sb-py\r\n");
50
-
51
-        size_t len = strlen(readme);
52
-        UINT bw;
53
-        res = f_write(&file, readme, len, &bw);
54
-        if ((res != FR_OK) || (bw != len)) {
55
-            debug("error: f_write returned %d", res);
56
-        }
57
-
58
-        res = f_close(&file);
59
-        if (res != FR_OK) {
60
-            debug("error: f_close returned %d", res);
61
-        }
62
-    }
63
-}
64
-
65
-#ifdef DEBUG_DISK_WRITE_SOURCES
66
-static void write_sources(void) {
67
-    FIL file;
68
-    FRESULT res = f_open(&file, "src.tar.xz", FA_CREATE_ALWAYS | FA_WRITE);
69
-    if (res != FR_OK) {
70
-        debug("error: f_open returned %d", res);
71
-    } else {
72
-        UINT bw;
73
-        UINT len = 0;
74
-        while (1) {
75
-            res = f_write(&file, data_tar_xz + len, data_tar_xz_len - len, &bw);
76
-            len += bw;
77
-            if (res != FR_OK) {
78
-                debug("error: f_write returned %d", res);
79
-                break;
80
-            } else if (bw == 0) {
81
-                debug("error: f_write did not write");
82
-                break;
83
-            } else if (bw == data_tar_xz_len) {
84
-                break;
85
-            }
86
-        }
87
-
88
-        res = f_close(&file);
89
-        if (res != FR_OK) {
90
-            debug("error: f_close returned %d", res);
91
-        }
92
-    }
93
-}
94
-#endif // DEBUG_DISK_WRITE_SOURCES
95
-
96
-void debug_disk_init(void) {
32
+void debug_disk_init_log(void) {
97 33
     if (debug_disk_mount() != 0) {
98 34
         debug("error mounting disk");
99 35
         return;
100 36
     }
101 37
 
102
-    // maximum length: 11 bytes
103
-    f_setlabel("Volcano RC");
104
-
105
-    write_readme();
106
-
107
-#ifdef DEBUG_DISK_WRITE_SOURCES
108
-    write_sources();
109
-#endif // DEBUG_DISK_WRITE_SOURCES
38
+    log_dump_to_disk();
110 39
 
111 40
     if (debug_disk_unmount() != 0) {
112 41
         debug("error unmounting disk");

+ 5
- 19
src/fat_disk.c View File

@@ -24,23 +24,9 @@
24 24
 #include "diskio.h"
25 25
 
26 26
 #include "config.h"
27
+#include "cache.h"
27 28
 #include "log.h"
28 29
 #include "debug_disk.h"
29
-#include "fat_disk.h"
30
-
31
-static uint8_t disk[DISK_BLOCK_COUNT * DISK_BLOCK_SIZE];
32
-
33
-void fat_disk_init(void) {
34
-    BYTE work[FF_MAX_SS];
35
-    FRESULT res = f_mkfs("", 0, work, sizeof(work));
36
-    if (res != FR_OK) {
37
-        debug("error: f_mkfs returned %d", res);
38
-    }
39
-}
40
-
41
-uint8_t *fat_disk_get_sector(uint32_t sector) {
42
-    return disk + (sector * DISK_BLOCK_SIZE);
43
-}
44 30
 
45 31
 /*
46 32
  * FatFS ffsystem.c
@@ -87,8 +73,8 @@ DRESULT disk_read(BYTE pdrv, BYTE *buff, LBA_t sector, UINT count) {
87 73
         return RES_ERROR;
88 74
     }
89 75
 
90
-    memcpy(buff, disk + (sector * DISK_BLOCK_SIZE), count * DISK_BLOCK_SIZE);
91
-    return RES_OK;
76
+    ssize_t r = cache_read(buff, sector * DISK_BLOCK_SIZE, count * DISK_BLOCK_SIZE);
77
+    return (r == (ssize_t)(count * DISK_BLOCK_SIZE)) ? RES_OK : RES_ERROR;
92 78
 }
93 79
 
94 80
 DRESULT disk_write(BYTE pdrv, const BYTE *buff, LBA_t sector, UINT count) {
@@ -102,8 +88,8 @@ DRESULT disk_write(BYTE pdrv, const BYTE *buff, LBA_t sector, UINT count) {
102 88
         return RES_ERROR;
103 89
     }
104 90
 
105
-    memcpy(disk + (sector * DISK_BLOCK_SIZE), buff, count * DISK_BLOCK_SIZE);
106
-    return RES_OK;
91
+    ssize_t r = cache_write(buff, sector * DISK_BLOCK_SIZE, count * DISK_BLOCK_SIZE);
92
+    return (r == (ssize_t)(count * DISK_BLOCK_SIZE)) ? RES_OK : RES_ERROR;
107 93
 }
108 94
 
109 95
 DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) {

+ 5
- 6
src/http.c View File

@@ -26,25 +26,26 @@
26 26
 #include "log.h"
27 27
 #include "http.h"
28 28
 
29
-
30 29
 void http_init(void) {
31 30
     httpd_init();
32 31
 }
33 32
 
34
-#ifdef DEBUG_DISK_WRITE_SOURCES
35
-
36 33
 #include "lwip/apps/fs.h"
37 34
 #include <string.h>
38
-#include "pack_data.h"
39 35
 
40 36
 int fs_open_custom(struct fs_file *file, const char *name) {
37
+    // TODO hook up to fat fs
41 38
     if (strcmp(name, "/src.tar.xz") == 0) {
39
+        /*
42 40
         memset(file, 0, sizeof(struct fs_file));
43 41
         file->data = (const char *)data_tar_xz;
44 42
         file->len = data_tar_xz_len;
45 43
         file->index = file->len;
46 44
         file->flags = FS_FILE_FLAGS_HEADER_PERSISTENT;
47 45
         return 1;
46
+        */
47
+        (void)file;
48
+        return 0;
48 49
     }
49 50
     return 0;
50 51
 }
@@ -52,5 +53,3 @@ int fs_open_custom(struct fs_file *file, const char *name) {
52 53
 void fs_close_custom(struct fs_file *file) {
53 54
     (void)file;
54 55
 }
55
-
56
-#endif // DEBUG_DISK_WRITE_SOURCES

+ 4
- 6
src/main.c View File

@@ -27,7 +27,6 @@
27 27
 #include "log.h"
28 28
 #include "usb.h"
29 29
 #include "usb_msc.h"
30
-#include "fat_disk.h"
31 30
 #include "debug_disk.h"
32 31
 #include "buttons.h"
33 32
 #include "ble.h"
@@ -40,6 +39,7 @@
40 39
 #include "workflow.h"
41 40
 #include "wifi.h"
42 41
 #include "http.h"
42
+#include "cache.h"
43 43
 #include "main.h"
44 44
 
45 45
 void main_loop_hw(void) {
@@ -53,6 +53,7 @@ void main_loop_hw(void) {
53 53
     }
54 54
 
55 55
     networking_run();
56
+    cache_run();
56 57
 }
57 58
 
58 59
 void networking_init(void) {
@@ -121,11 +122,8 @@ int main(void) {
121 122
     debug("ble_init");
122 123
     ble_init();
123 124
 
124
-    debug("fat_disk_init");
125
-    fat_disk_init();
126
-
127
-    debug("debug_disk_init");
128
-    debug_disk_init();
125
+    debug("cache_init");
126
+    cache_init();
129 127
 
130 128
 #ifdef AUTO_MOUNT_MASS_STORAGE
131 129
     msc_set_medium_available(true);

+ 3
- 14
src/mem.c View File

@@ -18,23 +18,12 @@
18 18
 
19 19
 #include <string.h>
20 20
 
21
-#include "hardware/flash.h"
22 21
 #include "pico/flash.h"
23
-#include "pico/btstack_flash_bank.h"
24 22
 
25 23
 #include "config.h"
26 24
 #include "log.h"
27 25
 #include "mem.h"
28 26
 
29
-#define FLASH_LOCK_TIMEOUT_MS 500
30
-
31
-/*
32
- * Last two flash pages are used by BTstack.
33
- * So we use the third-last page for our persistent storage.
34
- * This is kept clear by our custom linker script.
35
- */
36
-#define FLASH_OFFSET (PICO_FLASH_BANK_STORAGE_OFFSET - FLASH_SECTOR_SIZE)
37
-
38 27
 struct mem_contents {
39 28
     uint8_t version;
40 29
     uint32_t checksum;
@@ -50,7 +39,7 @@ struct mem_contents {
50 39
 
51 40
 static const struct mem_contents data_defaults = MEM_CONTENTS_INIT;
52 41
 static struct mem_contents data_ram = data_defaults;
53
-static const uint8_t *data_flash = (const uint8_t *)(XIP_BASE + FLASH_OFFSET);
42
+static const uint8_t *data_flash = (const uint8_t *)(XIP_BASE + EEPROM_FLASH_OFFSET);
54 43
 
55 44
 static_assert(sizeof(struct mem_contents) < FLASH_SECTOR_SIZE,
56 45
               "Config needs to fit inside a flash sector");
@@ -142,10 +131,10 @@ void mem_load(void) {
142 131
 }
143 132
 
144 133
 static void mem_write_flash(void *param) {
145
-    flash_range_erase(FLASH_OFFSET, FLASH_SECTOR_SIZE);
134
+    flash_range_erase(EEPROM_FLASH_OFFSET, FLASH_SECTOR_SIZE);
146 135
 
147 136
     // TODO only need to write with length multiple of FLASH_PAGE_SIZE
148
-    flash_range_program(FLASH_OFFSET, param, FLASH_SECTOR_SIZE);
137
+    flash_range_program(EEPROM_FLASH_OFFSET, param, FLASH_SECTOR_SIZE);
149 138
 }
150 139
 
151 140
 void mem_write(void) {

+ 4
- 16
src/usb_msc.c View File

@@ -30,7 +30,7 @@
30 30
 #include "tusb.h"
31 31
 
32 32
 #include "config.h"
33
-#include "fat_disk.h"
33
+#include "cache.h"
34 34
 #include "debug_disk.h"
35 35
 #include "log.h"
36 36
 
@@ -125,12 +125,7 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba,
125 125
         return -1;
126 126
     }
127 127
 
128
-    // TODO better range checking and length calculation?
129
-
130
-    uint8_t const* addr = fat_disk_get_sector(lba) + offset;
131
-    memcpy(buffer, addr, bufsize);
132
-
133
-    return (int32_t) bufsize;
128
+    return cache_read(buffer, (lba * DISK_BLOCK_SIZE) + offset, bufsize);
134 129
 }
135 130
 
136 131
 bool tud_msc_is_writable_cb (uint8_t lun) {
@@ -150,12 +145,7 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba,
150 145
         return -1;
151 146
     }
152 147
 
153
-    // TODO better range checking and length calculation?
154
-
155
-    uint8_t* addr = fat_disk_get_sector(lba) + offset;
156
-    memcpy(addr, buffer, bufsize);
157
-
158
-    return (int32_t) bufsize;
148
+    return cache_write(buffer, (lba * DISK_BLOCK_SIZE) + offset, bufsize);
159 149
 }
160 150
 
161 151
 // Callback invoked when received an SCSI command not in built-in list below
@@ -182,9 +172,7 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16],
182 172
                 medium_locked = true;
183 173
 
184 174
 #ifdef AUTO_LOG_ON_MASS_STORAGE
185
-                debug_disk_mount();
186
-                log_dump_to_disk();
187
-                debug_disk_unmount();
175
+                debug_disk_init_log();
188 176
 #endif // AUTO_LOG_ON_MASS_STORAGE
189 177
             }
190 178
         } else {

Loading…
Cancel
Save