diff options
| author | robert-hh <robert@hammelrath.com> | 2025-04-09 18:07:24 +0200 |
|---|---|---|
| committer | Damien George <damien@micropython.org> | 2025-05-07 16:19:48 +1000 |
| commit | 2e6df08e05f4832806f062c56f78c5412fd37ceb (patch) | |
| tree | 163c7fe9eca64b397dba5fb4701f185d6fa04d38 | |
| parent | c22c2c806694dbce55cfe484b1b9e55af33bb950 (diff) | |
samd/samd_spiflash: Improve the flash type detection.
Changes in this commit:
- Check for the proper SFDP header.
- Use the flash size information from SFDP, if present.
- Add two more special flash chips <= 1 MByte without SFDP. JEDEC-ID table
for special flash types instead of a series of conditional statements.
- Add a compile flag `MICROPY_HW_SPIFLASH_SIZE` to set the size in
`mpconfigboard.h`, which replaces getting the size from the JEDEC ID or
the SFDP record.
Signed-off-by: robert-hh <robert@hammelrath.com>
| -rw-r--r-- | ports/samd/samd_spiflash.c | 65 |
1 files changed, 47 insertions, 18 deletions
diff --git a/ports/samd/samd_spiflash.c b/ports/samd/samd_spiflash.c index 8ada7e960..63dc0a830 100644 --- a/ports/samd/samd_spiflash.c +++ b/ports/samd/samd_spiflash.c @@ -67,6 +67,19 @@ typedef struct _spiflash_obj_t { extern const mp_obj_type_t samd_spiflash_type; +typedef struct _spiflash_jedec_id_t { + uint32_t jedec_id; + uint32_t mask; + uint32_t size; +} spiflash_jedec_id_t; + +spiflash_jedec_id_t jedec_id_table[] = { + { 0x1f8401, 0xffff00, 512 * 1024 }, // Adesto/Renesas 4 MBit + { 0x1f2400, 0xffff00, 512 * 1024 }, // Adesto 4 MBit + { 0x1f4501, 0xffff00, 1024 * 1024 }, // Adesto/Renesas/Atmel 8 MBit + { 0xc84013, 0xffffff, 512 * 1024 }, // Gigadevices 4 MBit +}; + // The SPIflash object is a singleton static spiflash_obj_t spiflash_obj = { { &samd_spiflash_type }, NULL, 0, false, PAGE_SIZE, SECTOR_SIZE, NULL, 0 @@ -124,6 +137,7 @@ static void write_enable(spiflash_obj_t *self) { mp_hal_pin_write(self->cs, 1); } +#if !defined(MICROPY_HW_SPIFLASH_SIZE) // Write status register 1 static void write_sr1(spiflash_obj_t *self, uint8_t value) { uint8_t msg[2]; @@ -134,6 +148,7 @@ static void write_sr1(spiflash_obj_t *self, uint8_t value) { spi_transfer(self->spi, 2, msg, NULL); mp_hal_pin_write(self->cs, 1); } +#endif static void get_sfdp(spiflash_obj_t *self, uint32_t addr, uint8_t *buffer, int size) { uint8_t dummy[1]; @@ -170,32 +185,46 @@ static mp_obj_t spiflash_make_new(const mp_obj_type_t *type, size_t n_args, size // Get the flash size from the device ID (default) uint8_t id[3]; get_id(self, id); - bool read_sfdp = true; - - if (id[1] == 0x84 && id[2] == 1) { // Adesto - self->size = 512 * 1024; - } else if (id[0] == 0x1f && id[1] == 0x45 && id[2] == 1) { // Adesto/Renesas 8 MBit - self->size = 1024 * 1024; - read_sfdp = false; - self->sectorsize = 4096; - self->addr_is_32bit = false; - // Globally unlock the sectors, which are locked after power on. - write_enable(self); - write_sr1(self, 0); - } else { - self->size = 1 << id[2]; + + #if defined(MICROPY_HW_SPIFLASH_SIZE) + self->size = MICROPY_HW_SPIFLASH_SIZE; + #else + // Assume as default that the size is coded into the last JEDEC ID byte. + self->size = 1 << id[2]; + // Look for specific flash devices with different encoding. + uint32_t jedec_id = (id[0] << 16) | (id[1] << 8) | id[2]; + for (int i = 0; i < MP_ARRAY_SIZE(jedec_id_table); i++) { + if (jedec_id_table[i].jedec_id == (jedec_id & jedec_id_table[i].mask)) { + self->size = jedec_id_table[i].size; + // Globally unlock the sectors, which may be locked after power on. + write_enable(self); + write_sr1(self, 0); + break; + } } + #endif - // Get the addr_is_32bit flag and the sector size - if (read_sfdp) { - uint8_t buffer[128]; - get_sfdp(self, 0, buffer, 16); // get the header + // Get the flash size, addr_is_32bit flag and sector size from SFDP, if present. + uint8_t buffer[128]; + get_sfdp(self, 0, buffer, 16); // get the header + if (*(uint32_t *)buffer == 0x50444653) { // Header signature "SFDP" int len = MIN(buffer[11] * 4, sizeof(buffer)); if (len >= 29) { int addr = buffer[12] + (buffer[13] << 8) + (buffer[14] << 16); get_sfdp(self, addr, buffer, len); // Get the JEDEC mandatory table self->sectorsize = 1 << buffer[28]; self->addr_is_32bit = ((buffer[2] >> 1) & 0x03) != 0; + #if !defined(MICROPY_HW_SPIFLASH_SIZE) + // Get the bit size from the SFDP data + uint32_t size = *(uint32_t *)(buffer + 4); + if (size & 0x8000000) { + // Byte size is 2 ** lower_31_bits / 8 + self->size = 1 << ((size & 0x7fffffff) >> 3); + } else { + // Byte size is lower_31_bits / 8 + 1 + self->size = ((size & 0x7fffffff) >> 3) + 1; + } + #endif } } self->commands = self->addr_is_32bit ? _COMMANDS_32BIT : _COMMANDS_24BIT; |
