Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rework to use smart SPI flash detection #2670

Merged
merged 2 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...

## [unreleased][unreleased]
- Changed SPI flash detection to calculate the size instead of table lookup, updated spi_flash_decode.py script with more ICs (@ANTodorov)
- Fixed `hf/lf tune` segfault when called from script (@doegox)
- Added option to set and get maximum read/write block number using `hf_mf_ultimatecard` script (@piotrva)
- Added JEDEC information for SPI flash W25Q64JV (@ANTodorov)
Expand Down
158 changes: 107 additions & 51 deletions client/pyscripts/spi_flash_decode.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,62 +12,118 @@ def color(s, fg=None):
return str(s)

spi = {
0x68:{
"manufacturer": "Boya",
"jedec" : {
0x40: {
0x15: {
"part": "BY25Q16BS",
"size": "16mbits",
"sizeB": "2MB",
},
},
},
},
0x85:{
"manufacturer": "Puya",
0x60: {
0x15: {
"part": "P25Q16H",
"size": "16mbits",
"sizeB": "2MB",
"jedec" : {
0x60: {
0x15: {
"part": "P25Q16H",
"size": "16mbits",
"sizeB": "2MB",
},
0x16: {
"part": "P25Q32H",
"size": "32mbits",
"sizeB": "4MB",
},
0x17: {
"part": "P25Q64H",
"size": "64mbits",
"sizeB": "8MB",
},
},
},
},
0xEF:{
"manufacturer": "Winbond",
0x30: {
0x11: {
"part": "W25X10BV",
"size": "1mbits",
"sizeB": "128KB",
},
0x12: {
"part": "W25X20BV",
"size": "2mbits",
"sizeB": "256KB",
},
0x13: {
"part": "W25X40BV",
"size": "4mbits",
"sizeB": "512KB",
},
},
0x40: {
0x13: {
"part": "W25Q40BV",
"size": "4mbits",
"sizeB": "512KB",
},
0x14: {
"part": "W25Q80BV",
"size": "8mbits",
"sizeB": "1MB",
"jedec" : {
0x30: {
0x11: {
"part": "W25X10BV",
"size": "1mbits",
"sizeB": "128KB",
},
0x12: {
"part": "W25X20BV",
"size": "2mbits",
"sizeB": "256KB",
},
0x13: {
"part": "W25X40BV",
"size": "4mbits",
"sizeB": "512KB",
},
},
0x15: {
"part": "W25Q16BV",
"size": "16mbits",
"sizeB": "2MB",
0x40: {
0x12: {
"part": "W25Q20BV",
"size": "2mbits",
"sizeB": "256KB",
},
0x13: {
"part": "W25Q40BV",
"size": "4mbits",
"sizeB": "512KB",
},
0x14: {
"part": "W25Q80BV",
"size": "8mbits",
"sizeB": "1MB",
},
0x15: {
"part": "W25Q16BV",
"size": "16mbits",
"sizeB": "2MB",
},
0x16: {
"part": "W25Q32BV",
"size": "32mbits",
"sizeB": "4MB",
},
0x17: {
"part": "W25Q64BV",
"size": "64mbits",
"sizeB": "8MB",
},
},
0x16: {
"part": "W25Q32BV",
"size": "32mbits",
"sizeB": "4MB",
},
},
0x70: {
0x22: {
"part": "W25Q02JV-IM",
"size": "2mbits",
"sizeB": "256KB",
0x70: {
0x14: {
"part": "W25Q80JV",
"size": "8mbits",
"sizeB": "1MB",
},
0x15: {
"part": "W25Q16JV",
"size": "16mbits",
"sizeB": "2MB",
},
0x16: {
"part": "W25Q32JV",
"size": "32mbits",
"sizeB": "4MB",
},
0x17: {
"part": "W25Q64JV",
"size": "64mbits",
"sizeB": "8MB",
},
0x22: {
"part": "W25Q02JV-IM",
"size": "2mbits",
"sizeB": "256KB",
},
},
},
},
Expand All @@ -90,16 +146,16 @@ def color(s, fg=None):
did_h = did >> 8
did_l = did & 0xff
t = None

print(f"\n JEDEC ID....... 0x{mid:X} / 0x{did:X}")
if mid in spi:

mfr = spi[mid]['manufacturer']

if did_h in spi[mid]:
if did_h in spi[mid]['jedec']:

if did_l in spi[mid][did_h]:
if did_l in spi[mid]['jedec'][did_h]:

t = spi[mid][did_h][did_l]
t = spi[mid]['jedec'][did_h][did_l]
print("\n Manufacturer... " + color(f"{mfr}", fg="green") +
"\n Device......... " + color(f"{t['part']}", fg="green") +
"\n Size........... " + color(f"{t['size']} ({t['sizeB']})", fg="yellow")
Expand Down
21 changes: 6 additions & 15 deletions common_arm/flashmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,6 @@ void Flashmem_print_status(void) {
);
}

Dbprintf(" Device.................. " _YELLOW_("%s"), spi_flash_data.device);
Dbprintf(" Memory size............. " _YELLOW_("%d kB (%d pages * 64k)"), spi_flash_pages64k * 64, spi_flash_pages64k);

uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0};
Expand Down Expand Up @@ -442,21 +441,13 @@ bool FlashDetect(void) {
} else {
if (g_dbglevel > 3) Dbprintf("Flash_ReadID failed reading Mfr/Dev (0x90)");
}
// default device is 'unknown'
spi_flash_data.device = SpiFlashTable[0].device;

// Check JEDEC data is valid, compare the reported device types and then calculate the number of pages
// It is covering the most (known) cases of devices but probably there are vendors with different data
// They will be handled when there is such cases
if (ret) {
for (int i = 0; i < ARRAYLEN(SpiFlashTable); i++) {
if (SpiFlashTable[i].manufacturer_id == spi_flash_data.manufacturer_id) {
if (SpiFlashTable[i].jedec_id == spi_flash_data.jedec_id) {
spi_flash_pages64k = SpiFlashTable[i].pages64k;
spi_flash_data.device = SpiFlashTable[i].device;
break;
}
if (SpiFlashTable[i].device_id == spi_flash_data.device_id) {
spi_flash_data.device = SpiFlashTable[i].device;
break;
}
if (spi_flash_data.jedec_id > 0 && spi_flash_data.jedec_id < 0xFFFF) {
if (((spi_flash_data.device_id + 1) & 0x0F) == (spi_flash_data.jedec_id & 0x000F)) {
spi_flash_pages64k = 1 << (spi_flash_data.jedec_id & 0x000F);
}
}
}
Expand Down
33 changes: 0 additions & 33 deletions common_arm/flashmem.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,41 +140,8 @@ typedef struct {
uint8_t manufacturer_id;
uint8_t device_id;
uint16_t jedec_id;
uint8_t pages64k;
char *device;
} spi_flash_t;

static const spi_flash_t SpiFlashTable[] = {
// first element is the default of 4 * 64kB pages (256kB)
{ 0x00, 0x00, 0x0000, 4, "unknown" }, // 256k
// Manufacturer: Puya
{ 0x85, 0x14, 0x6015, 32, "P25Q16H" }, // 2048k
// Manufacturer: Winbond
{ 0xEF, 0x00, 0x3012, 4, "W25X20BV" }, // 256k
{ 0xEF, 0x00, 0x3013, 8, "W25X40BV" }, // 512k

{ 0xEF, 0x00, 0x4013, 8, "W25Q40BV" }, // 512k
{ 0xEF, 0x00, 0x4014, 16, "W25Q80BV" }, // 1024k
{ 0xEF, 0x14, 0x4015, 32, "W25Q16BV" }, // 2048k
{ 0xEF, 0x15, 0x4016, 64, "W25Q32BV" }, // 4096k

{ 0xEF, 0x16, 0x7017, 128, "W25Q64JV" }, // 8192k
{ 0xEF, 0x21, 0x7022, 4, "W25Q02JV" },

// identified by Manufacturer /Device ID only
/// Manufacturer: Renesas
{ 0x1F, 0x46, 0x0000, 32, "AT25XE161D" }, // 2048k
{ 0x1F, 0x47, 0x0000, 64, "AT25XE321D" }, // 4096k
// { 0xEF, 0x05, 0x0000, 1, "Winbond!!!" }, // 64k (too small !!!)
{ 0xEF, 0x10, 0x0000, 2, "W25*10BV!" }, // 128k (small !!!)
{ 0xEF, 0x11, 0x0000, 4, "W25*20BV" }, // 256k
{ 0xEF, 0x12, 0x0000, 8, "W25*40BV" }, // 512k
{ 0xEF, 0x13, 0x0000, 16, "W25*80BV" }, // 1024k
{ 0xEF, 0x14, 0x0000, 32, "W25*16*" }, // 2048k
{ 0xEF, 0x15, 0x0000, 64, "W25*32*" }, // 4096k
{ 0xEF, 0x16, 0x0000, 128, "W25*64*" } // 8192k
};

extern uint8_t spi_flash_pages64k;

bool FlashDetect(void);
Expand Down
Loading