Skip to content

Commit 86fe73b

Browse files
committed
drivers/memory/spiflash: Move cache buffer to user-provided config.
This patch removes the global cache variables from the SPI flash driver and now requires the user to provide the cache memory themselves, via the SPI flash configuration struct. This allows to either have a shared cache for multiple SPI flash devices (by sharing a mp_spiflash_cache_t struct), or have a single cache per device (or a mix of these options). To configure the cache use: mp_spiflash_cache_t spi_bdev_cache; const mp_spiflash_config_t spiflash_config = // any bus options .cache = &spi_bdev_cache, };
1 parent cf1509c commit 86fe73b

2 files changed

Lines changed: 48 additions & 34 deletions

File tree

drivers/memory/spiflash.c

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,7 @@
4848
#define WAIT_SR_TIMEOUT (1000000)
4949

5050
#define PAGE_SIZE (256) // maximum bytes we can write in one SPI transfer
51-
#define SECTOR_SIZE (4096) // size of erase sector
52-
53-
// Note: this code is not reentrant with this shared buffer
54-
STATIC uint8_t buf[SECTOR_SIZE] __attribute__((aligned(4)));
55-
STATIC mp_spiflash_t *bufuser; // current user of buf
56-
STATIC uint32_t bufsec; // current sector stored in buf; 0xffffffff if invalid
51+
#define SECTOR_SIZE MP_SPIFLASH_ERASE_BLOCK_SIZE
5752

5853
STATIC void mp_spiflash_acquire_bus(mp_spiflash_t *self) {
5954
const mp_spiflash_config_t *c = self->config;
@@ -231,15 +226,16 @@ void mp_spiflash_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *d
231226
return;
232227
}
233228
mp_spiflash_acquire_bus(self);
234-
if (bufuser == self && bufsec != 0xffffffff) {
229+
mp_spiflash_cache_t *cache = self->config->cache;
230+
if (cache->user == self && cache->block != 0xffffffff) {
235231
uint32_t bis = addr / SECTOR_SIZE;
236232
uint32_t bie = (addr + len - 1) / SECTOR_SIZE;
237-
if (bis <= bufsec && bufsec <= bie) {
233+
if (bis <= cache->block && cache->block <= bie) {
238234
// Read straddles current buffer
239235
size_t rest = 0;
240-
if (bis < bufsec) {
236+
if (bis < cache->block) {
241237
// Read direct from flash for first part
242-
rest = bufsec * SECTOR_SIZE - addr;
238+
rest = cache->block * SECTOR_SIZE - addr;
243239
mp_spiflash_read_data(self, addr, rest, dest);
244240
len -= rest;
245241
dest += rest;
@@ -250,7 +246,7 @@ void mp_spiflash_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *d
250246
if (rest > len) {
251247
rest = len;
252248
}
253-
memcpy(dest, &buf[offset], rest);
249+
memcpy(dest, &cache->buf[offset], rest);
254250
len -= rest;
255251
if (len == 0) {
256252
mp_spiflash_release_bus(self);
@@ -273,15 +269,17 @@ STATIC void mp_spiflash_flush_internal(mp_spiflash_t *self) {
273269

274270
self->flags &= ~1;
275271

272+
mp_spiflash_cache_t *cache = self->config->cache;
273+
276274
// Erase sector
277-
int ret = mp_spiflash_erase_sector(self, bufsec * SECTOR_SIZE);
275+
int ret = mp_spiflash_erase_sector(self, cache->block * SECTOR_SIZE);
278276
if (ret != 0) {
279277
return;
280278
}
281279

282280
// Write
283281
for (int i = 0; i < 16; i += 1) {
284-
int ret = mp_spiflash_write_page(self, bufsec * SECTOR_SIZE + i * PAGE_SIZE, buf + i * PAGE_SIZE);
282+
int ret = mp_spiflash_write_page(self, cache->block * SECTOR_SIZE + i * PAGE_SIZE, cache->buf + i * PAGE_SIZE);
285283
if (ret != 0) {
286284
return;
287285
}
@@ -302,44 +300,46 @@ STATIC int mp_spiflash_write_part(mp_spiflash_t *self, uint32_t addr, size_t len
302300
addr = sec << 12;
303301

304302
// Restriction for now, so we don't need to erase multiple pages
305-
if (offset + len > sizeof(buf)) {
303+
if (offset + len > SECTOR_SIZE) {
306304
printf("mp_spiflash_write_part: len is too large\n");
307305
return -MP_EIO;
308306
}
309307

308+
mp_spiflash_cache_t *cache = self->config->cache;
309+
310310
// Acquire the sector buffer
311-
if (bufuser != self) {
312-
if (bufuser != NULL) {
313-
mp_spiflash_flush(bufuser);
311+
if (cache->user != self) {
312+
if (cache->user != NULL) {
313+
mp_spiflash_flush(cache->user);
314314
}
315-
bufuser = self;
316-
bufsec = 0xffffffff;
315+
cache->user = self;
316+
cache->block = 0xffffffff;
317317
}
318318

319-
if (bufsec != sec) {
319+
if (cache->block != sec) {
320320
// Read sector
321321
#if USE_WR_DELAY
322-
if (bufsec != 0xffffffff) {
322+
if (cache->block != 0xffffffff) {
323323
mp_spiflash_flush_internal(self);
324324
}
325325
#endif
326-
mp_spiflash_read_data(self, addr, SECTOR_SIZE, buf);
326+
mp_spiflash_read_data(self, addr, SECTOR_SIZE, cache->buf);
327327
}
328328

329329
#if USE_WR_DELAY
330330

331-
bufsec = sec;
331+
cache->block = sec;
332332
// Just copy to buffer
333-
memcpy(buf + offset, src, len);
333+
memcpy(cache->buf + offset, src, len);
334334
// And mark dirty
335335
self->flags |= 1;
336336

337337
#else
338338

339339
uint32_t dirty = 0;
340340
for (size_t i = 0; i < len; ++i) {
341-
if (buf[offset + i] != src[i]) {
342-
if (buf[offset + i] != 0xff) {
341+
if (cache->buf[offset + i] != src[i]) {
342+
if (cache->buf[offset + i] != 0xff) {
343343
// Erase sector
344344
int ret = mp_spiflash_erase_sector(self, addr);
345345
if (ret != 0) {
@@ -353,14 +353,14 @@ STATIC int mp_spiflash_write_part(mp_spiflash_t *self, uint32_t addr, size_t len
353353
}
354354
}
355355

356-
bufsec = sec;
356+
cache->block = sec;
357357
// Copy new block into buffer
358-
memcpy(buf + offset, src, len);
358+
memcpy(cache->buf + offset, src, len);
359359

360360
// Write sector in pages of 256 bytes
361361
for (size_t i = 0; i < 16; ++i) {
362362
if (dirty & (1 << i)) {
363-
int ret = mp_spiflash_write_page(self, addr + i * PAGE_SIZE, buf + i * PAGE_SIZE);
363+
int ret = mp_spiflash_write_page(self, addr + i * PAGE_SIZE, cache->buf + i * PAGE_SIZE);
364364
if (ret != 0) {
365365
return ret;
366366
}
@@ -378,16 +378,17 @@ int mp_spiflash_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint
378378

379379
mp_spiflash_acquire_bus(self);
380380

381-
if (bufuser == self && bis <= bufsec && bie >= bufsec) {
381+
mp_spiflash_cache_t *cache = self->config->cache;
382+
if (cache->user == self && bis <= cache->block && bie >= cache->block) {
382383
// Write straddles current buffer
383384
uint32_t pre;
384385
uint32_t offset;
385-
if (bufsec * SECTOR_SIZE >= addr) {
386-
pre = bufsec * SECTOR_SIZE - addr;
386+
if (cache->block * SECTOR_SIZE >= addr) {
387+
pre = cache->block * SECTOR_SIZE - addr;
387388
offset = 0;
388389
} else {
389390
pre = 0;
390-
offset = addr - bufsec * SECTOR_SIZE;
391+
offset = addr - cache->block * SECTOR_SIZE;
391392
}
392393

393394
// Write buffered part first
@@ -397,7 +398,7 @@ int mp_spiflash_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint
397398
len = len_in_buf - (SECTOR_SIZE - offset);
398399
len_in_buf = SECTOR_SIZE - offset;
399400
}
400-
memcpy(&buf[offset], &src[pre], len_in_buf);
401+
memcpy(&cache->buf[offset], &src[pre], len_in_buf);
401402
self->flags |= 1; // Mark dirty
402403

403404
// Write part before buffer sector

drivers/memory/spiflash.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,23 @@
2929
#include "drivers/bus/spi.h"
3030
#include "drivers/bus/qspi.h"
3131

32+
#define MP_SPIFLASH_ERASE_BLOCK_SIZE (4096) // must be a power of 2
33+
3234
enum {
3335
MP_SPIFLASH_BUS_SPI,
3436
MP_SPIFLASH_BUS_QSPI,
3537
};
3638

39+
struct _mp_spiflash_t;
40+
41+
// A cache must be provided by the user in the config struct. The same cache
42+
// struct can be shared by multiple SPI flash instances.
43+
typedef struct _mp_spiflash_cache_t {
44+
uint8_t buf[MP_SPIFLASH_ERASE_BLOCK_SIZE] __attribute__((aligned(4)));
45+
struct _mp_spiflash_t *user; // current user of buf, for shared use
46+
uint32_t block; // current block stored in buf; 0xffffffff if invalid
47+
} mp_spiflash_cache_t;
48+
3749
typedef struct _mp_spiflash_config_t {
3850
uint32_t bus_kind;
3951
union {
@@ -47,6 +59,7 @@ typedef struct _mp_spiflash_config_t {
4759
const mp_qspi_proto_t *proto;
4860
} u_qspi;
4961
} bus;
62+
mp_spiflash_cache_t *cache;
5063
} mp_spiflash_config_t;
5164

5265
typedef struct _mp_spiflash_t {

0 commit comments

Comments
 (0)