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

View File

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