mirror of
https://github.com/micropython/micropython.git
synced 2025-12-13 08:20:13 +01:00
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>
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user