Skip to content

Commit 8aebfbe

Browse files
committed
msc update to use flash block API (with caching)
1 parent 86fdf16 commit 8aebfbe

File tree

2 files changed

+27
-270
lines changed

2 files changed

+27
-270
lines changed

examples/MassStorage/msc_external_flash/msc_external_flash.ino

Lines changed: 15 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -2,51 +2,31 @@
22
// Copyright (c) 2019 Ha Thach for Adafruit Industries
33

44
/* This example demo how to expose on-board external Flash as USB Mass Storage.
5-
* - For M0 express series with SPI flash device
6-
* follow library is required
5+
* Following library is required
76
* https://github.com/adafruit/Adafruit_SPIFlash
8-
*
9-
* - For M4 expres series and nRF52840 with QSPI flash, additional library is reuiqred
10-
* https://github.com/adafruit/Adafruit_QSPI
117
*/
128

139
#include "Adafruit_TinyUSB.h"
1410
#include "Adafruit_SPIFlash.h"
1511

1612
#if defined(__SAMD51__) || defined(NRF52840_XXAA)
17-
#include "Adafruit_QSPI.h"
18-
#include "Adafruit_QSPI_Flash.h"
19-
20-
Adafruit_QSPI_Flash flash;
13+
Adafruit_FlashTransport_QSPI flashTransport(PIN_QSPI_SCK, PIN_QSPI_CS, PIN_QSPI_IO0, PIN_QSPI_IO1, PIN_QSPI_IO2, PIN_QSPI_IO3);
2114
#else
22-
// Configuration of the flash chip pins and flash fatfs object.
23-
// You don't normally need to change these if using a Feather/Metro
24-
// M0 express board.
25-
26-
// Flash chip type. If you change this be sure to change the fatfs to match as well
27-
#define FLASH_TYPE SPIFLASHTYPE_W25Q16BV
28-
2915
#if (SPI_INTERFACES_COUNT == 1)
30-
#define FLASH_SS SS // Flash chip SS pin.
31-
#define FLASH_SPI_PORT SPI // What SPI port is Flash on?
16+
Adafruit_FlashTransport_SPI flashTransport(SS0, &SPI);
3217
#else
33-
#define FLASH_SS SS1 // Flash chip SS pin.
34-
#define FLASH_SPI_PORT SPI1 // What SPI port is Flash on?
18+
Adafruit_FlashTransport_SPI flashTransport(SS1, &SPI1);
3519
#endif
36-
37-
Adafruit_SPIFlash flash(FLASH_SS, &FLASH_SPI_PORT); // Use hardware SPI
3820
#endif
3921

22+
Adafruit_SPIFlash flash(&flashTransport);
23+
4024
Adafruit_USBD_MSC usb_msc;
4125

4226
// the setup function runs once when you press reset or power the board
4327
void setup()
4428
{
45-
#if defined(__SAMD51__) || defined(NRF52840_XXAA)
4629
flash.begin();
47-
#else
48-
flash.begin(FLASH_TYPE);
49-
#endif
5030

5131
pinMode(LED_BUILTIN, OUTPUT);
5232

@@ -68,9 +48,8 @@ void setup()
6848
while ( !Serial ) delay(10); // wait for native usb
6949

7050
Serial.println("Adafruit TinyUSB Mass Storage SPI Flash example");
71-
Serial.print("Page size: "); Serial.println(flash.pageSize());
72-
Serial.print("Page num : "); Serial.println(flash.numPages());
73-
Serial.print("JEDEC ID: "); Serial.println(flash.GetJEDECID(), HEX);
51+
Serial.print("JEDEC ID: "); Serial.println(flash.getJEDECID(), HEX);
52+
Serial.print("Flash size: "); Serial.println(flash.size());
7453
}
7554

7655
void loop()
@@ -83,8 +62,9 @@ void loop()
8362
// return number of copied bytes (must be multiple of block size)
8463
int32_t msc_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
8564
{
86-
const uint32_t addr = lba*512;
87-
flash_cache_read((uint8_t*) buffer, addr, bufsize);
65+
// Note: SPIFLash Bock API: readBlocks/writeBlocks/syncBlocks
66+
// already include 4K sector caching internally. We don't need to cache it, yahhhh!!
67+
flash.readBlocks(lba, (uint8_t*) buffer, bufsize/512);
8868
return bufsize;
8969
}
9070

@@ -93,118 +73,15 @@ int32_t msc_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
9373
// return number of written bytes (must be multiple of block size)
9474
int32_t msc_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
9575
{
96-
// need to erase & caching write back
97-
const uint32_t addr = lba*512;
98-
flash_cache_write(addr, buffer, bufsize);
76+
// Note: SPIFLash Bock API: readBlocks/writeBlocks/syncBlocks
77+
// already include 4K sector caching internally. We don't need to cache it, yahhhh!!
78+
flash.writeBlocks(lba, buffer, bufsize/512);
9979
return bufsize;
10080
}
10181

10282
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
10383
// used to flush any pending cache.
10484
void msc_flush_cb (void)
10585
{
106-
flash_cache_flush();
107-
}
108-
109-
//--------------------------------------------------------------------+
110-
// Flash Caching
111-
//--------------------------------------------------------------------+
112-
#define FLASH_CACHE_SIZE 4096 // must be a erasable page size
113-
#define FLASH_CACHE_INVALID_ADDR 0xffffffff
114-
115-
uint32_t cache_addr = FLASH_CACHE_INVALID_ADDR;
116-
uint8_t cache_buf[FLASH_CACHE_SIZE];
117-
118-
static inline uint32_t page_addr_of (uint32_t addr)
119-
{
120-
return addr & ~(FLASH_CACHE_SIZE - 1);
121-
}
122-
123-
static inline uint32_t page_offset_of (uint32_t addr)
124-
{
125-
return addr & (FLASH_CACHE_SIZE - 1);
126-
}
127-
128-
void flash_cache_flush (void)
129-
{
130-
if ( cache_addr == FLASH_CACHE_INVALID_ADDR ) return;
131-
132-
// indicator
133-
digitalWrite(LED_BUILTIN, HIGH);
134-
135-
flash.eraseSector(cache_addr/FLASH_CACHE_SIZE);
136-
flash.writeBuffer(cache_addr, cache_buf, FLASH_CACHE_SIZE);
137-
138-
digitalWrite(LED_BUILTIN, LOW);
139-
140-
cache_addr = FLASH_CACHE_INVALID_ADDR;
141-
}
142-
143-
uint32_t flash_cache_write (uint32_t dst, void const * src, uint32_t len)
144-
{
145-
uint8_t const * src8 = (uint8_t const *) src;
146-
uint32_t remain = len;
147-
148-
// Program up to page boundary each loop
149-
while ( remain )
150-
{
151-
uint32_t const page_addr = page_addr_of(dst);
152-
uint32_t const offset = page_offset_of(dst);
153-
154-
uint32_t wr_bytes = FLASH_CACHE_SIZE - offset;
155-
wr_bytes = min(remain, wr_bytes);
156-
157-
// Page changes, flush old and update new cache
158-
if ( page_addr != cache_addr )
159-
{
160-
flash_cache_flush();
161-
cache_addr = page_addr;
162-
163-
// read a whole page from flash
164-
flash.readBuffer(page_addr, cache_buf, FLASH_CACHE_SIZE);
165-
}
166-
167-
memcpy(cache_buf + offset, src8, wr_bytes);
168-
169-
// adjust for next run
170-
src8 += wr_bytes;
171-
remain -= wr_bytes;
172-
dst += wr_bytes;
173-
}
174-
175-
return len - remain;
176-
}
177-
178-
void flash_cache_read (uint8_t* dst, uint32_t addr, uint32_t count)
179-
{
180-
// overwrite with cache value if available
181-
if ( (cache_addr != FLASH_CACHE_INVALID_ADDR) &&
182-
!(addr < cache_addr && addr + count <= cache_addr) &&
183-
!(addr >= cache_addr + FLASH_CACHE_SIZE) )
184-
{
185-
int dst_off = cache_addr - addr;
186-
int src_off = 0;
187-
188-
if ( dst_off < 0 )
189-
{
190-
src_off = -dst_off;
191-
dst_off = 0;
192-
}
193-
194-
int cache_bytes = min(FLASH_CACHE_SIZE-src_off, count - dst_off);
195-
196-
// start to cached
197-
if ( dst_off ) flash.readBuffer(addr, dst, dst_off);
198-
199-
// cached
200-
memcpy(dst + dst_off, cache_buf + src_off, cache_bytes);
201-
202-
// cached to end
203-
int copied = dst_off + cache_bytes;
204-
if ( copied < count ) flash.readBuffer(addr + copied, dst + copied, count - copied);
205-
}
206-
else
207-
{
208-
flash.readBuffer(addr, dst, count);
209-
}
86+
flash.syncBlocks();
21087
}

examples/MassStorage/msc_external_flash_sdfat/msc_external_flash_sdfat.ino

Lines changed: 12 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,17 @@ const int chipSelect = 10;
1515
const int spi_freq_mhz = 50;
1616

1717
#if defined(__SAMD51__) || defined(NRF52840_XXAA)
18-
#include "Adafruit_QSPI.h"
19-
#include "Adafruit_QSPI_Flash.h"
20-
21-
Adafruit_QSPI_Flash flash;
18+
Adafruit_FlashTransport_QSPI flashTransport(PIN_QSPI_SCK, PIN_QSPI_CS, PIN_QSPI_IO0, PIN_QSPI_IO1, PIN_QSPI_IO2, PIN_QSPI_IO3);
2219
#else
23-
// Configuration of the flash chip pins and flash fatfs object.
24-
// You don't normally need to change these if using a Feather/Metro
25-
// M0 express board.
26-
27-
// Flash chip type. If you change this be sure to change the fatfs to match as well
28-
#define FLASH_TYPE SPIFLASHTYPE_W25Q16BV
29-
3020
#if (SPI_INTERFACES_COUNT == 1)
31-
#define FLASH_SS SS // Flash chip SS pin.
32-
#define FLASH_SPI_PORT SPI // What SPI port is Flash on?
21+
Adafruit_FlashTransport_SPI flashTransport(SS0, &SPI);
3322
#else
34-
#define FLASH_SS SS1 // Flash chip SS pin.
35-
#define FLASH_SPI_PORT SPI1 // What SPI port is Flash on?
23+
Adafruit_FlashTransport_SPI flashTransport(SS1, &SPI1);
3624
#endif
37-
38-
Adafruit_SPIFlash flash(FLASH_SS, &FLASH_SPI_PORT); // Use hardware SPI
3925
#endif
4026

27+
Adafruit_SPIFlash flash(&flashTransport);
28+
4129
Adafruit_USBD_MSC usb_msc;
4230
SdFat sd;
4331

@@ -48,11 +36,7 @@ void setup()
4836
usb_msc.setMaxLun(2);
4937

5038
//------------- Lun 0 for external flash -------------//
51-
#if defined(__SAMD51__) || defined(NRF52840_XXAA)
5239
flash.begin();
53-
#else
54-
flash.begin(FLASH_TYPE);
55-
#endif
5640
usb_msc.setID(0, "Adafruit", "External Flash", "1.0");
5741
usb_msc.setCapacity(0, flash.pageSize()*flash.numPages()/512, 512);
5842
usb_msc.setReadWriteCallback(0, external_flash_read_cb, external_flash_write_cb, external_flash_flush_cb);
@@ -108,7 +92,6 @@ void sdcard_flush_cb (void)
10892
sd.card()->syncBlocks();
10993
}
11094

111-
11295
//--------------------------------------------------------------------+
11396
// External Flash callbacks
11497
//--------------------------------------------------------------------+
@@ -118,8 +101,9 @@ void sdcard_flush_cb (void)
118101
// return number of copied bytes (must be multiple of block size)
119102
int32_t external_flash_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
120103
{
121-
const uint32_t addr = lba*512;
122-
flash_cache_read((uint8_t*) buffer, addr, bufsize);
104+
// Note: SPIFLash Bock API: readBlocks/writeBlocks/syncBlocks
105+
// already include 4K sector caching internally. We don't need to cache it, yahhhh!!
106+
flash.readBlocks(lba, (uint8_t*) buffer, bufsize/512);
123107
return bufsize;
124108
}
125109

@@ -128,119 +112,15 @@ int32_t external_flash_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
128112
// return number of written bytes (must be multiple of block size)
129113
int32_t external_flash_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
130114
{
131-
// need to erase & caching write back
132-
const uint32_t addr = lba*512;
133-
flash_cache_write(addr, buffer, bufsize);
115+
// Note: SPIFLash Bock API: readBlocks/writeBlocks/syncBlocks
116+
// already include 4K sector caching internally. We don't need to cache it, yahhhh!!
117+
flash.writeBlocks(lba, buffer, bufsize/512);
134118
return bufsize;
135119
}
136120

137121
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
138122
// used to flush any pending cache.
139123
void external_flash_flush_cb (void)
140124
{
141-
flash_cache_flush();
142-
}
143-
144-
145-
//--------------------------------------------------------------------+
146-
// Flash Caching for External Flash
147-
//--------------------------------------------------------------------+
148-
#define FLASH_CACHE_SIZE 4096 // must be a erasable page size
149-
#define FLASH_CACHE_INVALID_ADDR 0xffffffff
150-
151-
uint32_t cache_addr = FLASH_CACHE_INVALID_ADDR;
152-
uint8_t cache_buf[FLASH_CACHE_SIZE];
153-
154-
static inline uint32_t page_addr_of (uint32_t addr)
155-
{
156-
return addr & ~(FLASH_CACHE_SIZE - 1);
157-
}
158-
159-
static inline uint32_t page_offset_of (uint32_t addr)
160-
{
161-
return addr & (FLASH_CACHE_SIZE - 1);
162-
}
163-
164-
void flash_cache_flush (void)
165-
{
166-
if ( cache_addr == FLASH_CACHE_INVALID_ADDR ) return;
167-
168-
// indicator
169-
digitalWrite(LED_BUILTIN, HIGH);
170-
171-
flash.eraseSector(cache_addr/FLASH_CACHE_SIZE);
172-
flash.writeBuffer(cache_addr, cache_buf, FLASH_CACHE_SIZE);
173-
174-
digitalWrite(LED_BUILTIN, LOW);
175-
176-
cache_addr = FLASH_CACHE_INVALID_ADDR;
177-
}
178-
179-
uint32_t flash_cache_write (uint32_t dst, void const * src, uint32_t len)
180-
{
181-
uint8_t const * src8 = (uint8_t const *) src;
182-
uint32_t remain = len;
183-
184-
// Program up to page boundary each loop
185-
while ( remain )
186-
{
187-
uint32_t const page_addr = page_addr_of(dst);
188-
uint32_t const offset = page_offset_of(dst);
189-
190-
uint32_t wr_bytes = FLASH_CACHE_SIZE - offset;
191-
wr_bytes = min(remain, wr_bytes);
192-
193-
// Page changes, flush old and update new cache
194-
if ( page_addr != cache_addr )
195-
{
196-
flash_cache_flush();
197-
cache_addr = page_addr;
198-
199-
// read a whole page from flash
200-
flash.readBuffer(page_addr, cache_buf, FLASH_CACHE_SIZE);
201-
}
202-
203-
memcpy(cache_buf + offset, src8, wr_bytes);
204-
205-
// adjust for next run
206-
src8 += wr_bytes;
207-
remain -= wr_bytes;
208-
dst += wr_bytes;
209-
}
210-
211-
return len - remain;
212-
}
213-
214-
void flash_cache_read (uint8_t* dst, uint32_t addr, uint32_t count)
215-
{
216-
// overwrite with cache value if available
217-
if ( (cache_addr != FLASH_CACHE_INVALID_ADDR) &&
218-
!(addr < cache_addr && addr + count <= cache_addr) &&
219-
!(addr >= cache_addr + FLASH_CACHE_SIZE) )
220-
{
221-
int dst_off = cache_addr - addr;
222-
int src_off = 0;
223-
224-
if ( dst_off < 0 )
225-
{
226-
src_off = -dst_off;
227-
dst_off = 0;
228-
}
229-
230-
int cache_bytes = min(FLASH_CACHE_SIZE-src_off, count - dst_off);
231-
232-
// start to cached
233-
if ( dst_off ) flash.readBuffer(addr, dst, dst_off);
234-
235-
// cached
236-
memcpy(dst + dst_off, cache_buf + src_off, cache_bytes);
237-
238-
// cached to end
239-
int copied = dst_off + cache_bytes;
240-
if ( copied < count ) flash.readBuffer(addr + copied, dst + copied, count - copied);
241-
}
242-
else
243-
{
244-
flash.readBuffer(addr, dst, count);
245-
}
125+
flash.syncBlocks();
246126
}

0 commit comments

Comments
 (0)