Skip to content

Commit 42433d5

Browse files
committed
add flash caching for msc spiflash example
1 parent d59f991 commit 42433d5

File tree

1 file changed

+109
-3
lines changed

1 file changed

+109
-3
lines changed

examples/MassStorage/msc_spiflash/msc_spiflash.ino

Lines changed: 109 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Adafruit_SPIFlash flash(FLASH_SS, &FLASH_SPI_PORT); // Use hardware SPI
2929

3030
Adafruit_USBD_MSC usb_msc;
3131

32+
3233
// the setup function runs once when you press reset or power the board
3334
void setup()
3435
{
@@ -67,7 +68,8 @@ void loop()
6768
int32_t msc_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
6869
{
6970
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;
7173
}
7274

7375
// Callback invoked when received WRITE10 command.
@@ -77,12 +79,116 @@ int32_t msc_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
7779
{
7880
// need to erase & caching write back
7981
const uint32_t addr = lba*512;
80-
return flash.writeBuffer(addr, buffer, bufsize);
82+
flash_cache_write(addr, buffer, bufsize);
83+
return bufsize;
8184
}
8285

8386
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
8487
// used to flush any pending cache.
8588
void msc_flush_cb (void)
8689
{
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+
}
88194
}

0 commit comments

Comments
 (0)