@@ -29,6 +29,7 @@ Adafruit_SPIFlash flash(FLASH_SS, &FLASH_SPI_PORT); // Use hardware SPI
29
29
30
30
Adafruit_USBD_MSC usb_msc;
31
31
32
+
32
33
// the setup function runs once when you press reset or power the board
33
34
void setup ()
34
35
{
@@ -67,7 +68,8 @@ void loop()
67
68
int32_t msc_read_cb (uint32_t lba, void * buffer, uint32_t bufsize)
68
69
{
69
70
const uint32_t addr = lba*512 ;
70
- return flash.readBuffer (addr, (uint8_t *) buffer, bufsize);
71
+ flash_cache_read ((uint8_t *) buffer, addr, bufsize);
72
+ return bufsize;
71
73
}
72
74
73
75
// Callback invoked when received WRITE10 command.
@@ -77,12 +79,116 @@ int32_t msc_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
77
79
{
78
80
// need to erase & caching write back
79
81
const uint32_t addr = lba*512 ;
80
- return flash.writeBuffer (addr, buffer, bufsize);
82
+ flash_cache_write (addr, buffer, bufsize);
83
+ return bufsize;
81
84
}
82
85
83
86
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
84
87
// used to flush any pending cache.
85
88
void msc_flush_cb (void )
86
89
{
87
- // nothing to do
90
+ flash_cache_flush ();
91
+ }
92
+
93
+ // --------------------------------------------------------------------+
94
+ // Flash Caching
95
+ // --------------------------------------------------------------------+
96
+ #define FLASH_CACHE_SIZE 4096 // must be a erasable page size
97
+ #define FLASH_CACHE_INVALID_ADDR 0xffffffff
98
+
99
+ uint32_t cache_addr = FLASH_CACHE_INVALID_ADDR;
100
+ uint8_t cache_buf[FLASH_CACHE_SIZE];
101
+
102
+ static inline uint32_t page_addr_of (uint32_t addr)
103
+ {
104
+ return addr & ~(FLASH_CACHE_SIZE - 1 );
105
+ }
106
+
107
+ static inline uint32_t page_offset_of (uint32_t addr)
108
+ {
109
+ return addr & (FLASH_CACHE_SIZE - 1 );
110
+ }
111
+
112
+ void flash_cache_flush (void )
113
+ {
114
+ if ( cache_addr == FLASH_CACHE_INVALID_ADDR ) return ;
115
+
116
+ // indicator
117
+ // ledOn(LED_BUILTIN);
118
+
119
+ flash.eraseSector (cache_addr/FLASH_CACHE_SIZE);
120
+ flash.writeBuffer (cache_addr, cache_buf, FLASH_CACHE_SIZE);
121
+
122
+ // ledOff(LED_BUILTIN);
123
+
124
+ cache_addr = FLASH_CACHE_INVALID_ADDR;
125
+ }
126
+
127
+ uint32_t flash_cache_write (uint32_t dst, void const * src, uint32_t len)
128
+ {
129
+ uint8_t const * src8 = (uint8_t const *) src;
130
+ uint32_t remain = len;
131
+
132
+ // Program up to page boundary each loop
133
+ while ( remain )
134
+ {
135
+ uint32_t const page_addr = page_addr_of (dst);
136
+ uint32_t const offset = page_offset_of (dst);
137
+
138
+ uint32_t wr_bytes = FLASH_CACHE_SIZE - offset;
139
+ wr_bytes = min (remain, wr_bytes);
140
+
141
+ // Page changes, flush old and update new cache
142
+ if ( page_addr != cache_addr )
143
+ {
144
+ flash_cache_flush ();
145
+ cache_addr = page_addr;
146
+
147
+ // read a whole page from flash
148
+ flash.readBuffer (page_addr, cache_buf, FLASH_CACHE_SIZE);
149
+ }
150
+
151
+ memcpy (cache_buf + offset, src8, wr_bytes);
152
+
153
+ // adjust for next run
154
+ src8 += wr_bytes;
155
+ remain -= wr_bytes;
156
+ dst += wr_bytes;
157
+ }
158
+
159
+ return len - remain;
160
+ }
161
+
162
+ void flash_cache_read (uint8_t * dst, uint32_t addr, uint32_t count)
163
+ {
164
+ // overwrite with cache value if available
165
+ if ( (cache_addr != FLASH_CACHE_INVALID_ADDR) &&
166
+ !(addr < cache_addr && addr + count <= cache_addr) &&
167
+ !(addr >= cache_addr + FLASH_CACHE_SIZE) )
168
+ {
169
+ int dst_off = cache_addr - addr;
170
+ int src_off = 0 ;
171
+
172
+ if ( dst_off < 0 )
173
+ {
174
+ src_off = -dst_off;
175
+ dst_off = 0 ;
176
+ }
177
+
178
+ int cache_bytes = min (FLASH_CACHE_SIZE-src_off, count - dst_off);
179
+
180
+ // start to cached
181
+ if ( dst_off ) flash.readBuffer (addr, dst, dst_off);
182
+
183
+ // cached
184
+ memcpy (dst + dst_off, cache_buf + src_off, cache_bytes);
185
+
186
+ // cached to end
187
+ int copied = dst_off + cache_bytes;
188
+ if ( copied < count ) flash.readBuffer (addr + copied, dst + copied, count - copied);
189
+ }
190
+ else
191
+ {
192
+ flash.readBuffer (addr, dst, count);
193
+ }
88
194
}
0 commit comments