浏览代码

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 1年前
父节点
当前提交
628b40423f
共有 18 个文件被更改,包括 425 次插入172 次删除
  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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 查看文件

@@ -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 {

正在加载...
取消
保存