spiFlash: moved BP status, unlock step into a dedicatedmethod

This commit is contained in:
Gwenhael Goavec-Merou 2025-12-17 19:54:06 +01:00
parent a7e4303563
commit 4a593c258c
2 changed files with 39 additions and 23 deletions

View File

@ -86,7 +86,8 @@
SPIFlash::SPIFlash(SPIInterface *spi, bool unprotect, int8_t verbose):
_spi(spi), _verbose(verbose), _jedec_id(0),
_flash_model(NULL), _unprotect(unprotect)
_flash_model(NULL), _unprotect(unprotect), _must_relock(false),
_status(0)
{
reset();
power_up();
@ -365,23 +366,23 @@ bool SPIFlash::dump(const std::string &filename, const int &base_addr,
return true;
}
int SPIFlash::erase_and_prog(int base_addr, const uint8_t *data, int len)
bool SPIFlash::prepare_flash(const int base_addr, const int len)
{
/* If flash not already detected: do that here */
if (_jedec_id == 0) {
try {
read_id();
} catch(std::exception &e) {
printError(e.what());
return -1;
return false;
}
}
bool must_relock = false; // used to relock after write;
/* check Block Protect Bits (hide WIP/WEN bits) */
uint8_t status = read_status_reg() & ~0x03;
_status = read_status_reg() & ~0x03;
if (_verbose > 0)
display_status_reg(status);
display_status_reg(_status);
/* if known chip */
if (_flash_model) {
/* microchip SST26VF032B/64B have global lock set
@ -390,23 +391,23 @@ int SPIFlash::erase_and_prog(int base_addr, const uint8_t *data, int len)
*/
if (_flash_model->global_lock) {
if (!global_unlock())
return -1;
return false;
}
/* check if offset + len fit in flash */
if ((unsigned int)(base_addr + len) > (_flash_model->nr_sector * 0x10000)) {
printError("flash overflow");
return -1;
return false;
}
// if device has block protect
if (_flash_model->bp_len != 0) {
/* compute protected area */
int8_t tb = get_tb();
if (tb == -1)
return -1;
std::map<std::string, uint32_t> lock_len = bp_to_len(status, tb);
return false;
std::map<std::string, uint32_t> lock_len = bp_to_len(_status, tb);
printf("%08x %08x %08x %02x\n", base_addr,
lock_len["start"], lock_len["end"], status);
lock_len["start"], lock_len["end"], _status);
/* if some blocks are locked */
if (lock_len["start"] != 0 || lock_len["end"] != 0) {
@ -414,10 +415,10 @@ int SPIFlash::erase_and_prog(int base_addr, const uint8_t *data, int len)
if (tb == 1) { // bottom blocks are protected
// check if start is in protected blocks
if ((uint32_t)base_addr <= lock_len["end"])
must_relock = true;
_must_relock = true;
} else { // top blocks
if ((uint32_t)(base_addr + len) >= lock_len["start"])
must_relock = true;
_must_relock = true;
}
}
/* ISSI IS25LP032 seems have a bug:
@ -426,7 +427,7 @@ int SPIFlash::erase_and_prog(int base_addr, const uint8_t *data, int len)
*/
if ((_jedec_id >> 8) == 0x9d6016 && tb == 1 && base_addr != 0) {
_unprotect = true;
must_relock = true;
_must_relock = true;
}
/* ST M25P16 has not TB bit:
* block protection is always in top mode:
@ -434,28 +435,38 @@ int SPIFlash::erase_and_prog(int base_addr, const uint8_t *data, int len)
*/
if ((_jedec_id >> 8) == 0x202015 && tb == 1 && base_addr != 0) {
_unprotect = true;
must_relock = true;
_must_relock = true;
}
}
} else { // unknown chip: basic test
printWarn("flash chip unknown: use basic protection detection");
if (get_bp() != 0)
must_relock = true;
_must_relock = true;
}
/* if it's needs to unlock */
if (must_relock) {
/* if it's needs to unlock... */
/* Checks if unlock is asked/allowed by the user */
if (_must_relock) {
printf("unlock blocks\n");
if (!_unprotect) {
printError("Error: block protection is set");
printError(" can't unlock without --unprotect-flash");
return -1;
return false;
} else {
if (disable_protection() != 0)
return -1;
return false;
}
}
return true;
}
int SPIFlash::erase_and_prog(int base_addr, const uint8_t *data, int len)
{
if (!prepare_flash(base_addr, len))
return -1;
/* Now we can erase sector and write new data */
ProgressBar progress("Writing", len, 50, _verbose < 0);
if (sectors_erase(base_addr, len) == -1)
@ -475,8 +486,8 @@ int SPIFlash::erase_and_prog(int base_addr, const uint8_t *data, int len)
progress.done();
/* and if required: relock blocks */
if (must_relock) {
enable_protection(status);
if (_must_relock) {
enable_protection(_status);
if (_verbose > 0)
display_status_reg(read_status_reg());
}

View File

@ -153,6 +153,9 @@ class SPIFlash {
*/
uint8_t get_bp_mask();
private:
bool prepare_flash(const int base_addr, const int len);
public:
/*!
* \brief convert block protect to len in byte
@ -174,6 +177,8 @@ class SPIFlash {
uint32_t _jedec_id; /**< CHIP ID */
flash_t *_flash_model; /**< detect flash model */
bool _unprotect; /**< allows to unprotect memory before write */
bool _must_relock;
uint8_t _status;
};
#endif // SRC_SPIFLASH_HPP_