flash_internal: replace probe size with more accurate probe_read and probe_write
This commit is contained in:
parent
e85af656d3
commit
8142854522
|
@ -10,6 +10,7 @@
|
||||||
#include <stdlib.h> // general utilities
|
#include <stdlib.h> // general utilities
|
||||||
|
|
||||||
/* STM32 (including CM3) libraries */
|
/* STM32 (including CM3) libraries */
|
||||||
|
#include <libopencmsis/core_cm3.h> // Cortex M3 utilities
|
||||||
#include <libopencm3/stm32/flash.h> // flash utilities
|
#include <libopencm3/stm32/flash.h> // flash utilities
|
||||||
#include <libopencm3/stm32/desig.h> // device signature definitions
|
#include <libopencm3/stm32/desig.h> // device signature definitions
|
||||||
#include <libopencm3/stm32/dbgmcu.h> // debug definitions
|
#include <libopencm3/stm32/dbgmcu.h> // debug definitions
|
||||||
|
@ -307,69 +308,49 @@ int32_t flash_internal_eeprom_write(const uint8_t *eeprom, uint16_t size)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t flash_internal_probe_size(void)
|
uint32_t flash_internal_probe_read_size(void)
|
||||||
|
{
|
||||||
|
// we will check is a flash address is readable until a bus fault occurs
|
||||||
|
cm_disable_faults(); // disable all faults, particularly BusFault
|
||||||
|
SCB_CFSR |= SCB_CFSR_BFARVALID; // clear bus fault flag
|
||||||
|
SCB_CCR |= SCB_CCR_BFHFNMIGN; // ignore bus faults (but still flag them)
|
||||||
|
uint32_t address = FLASH_BASE; // start with the start of flash
|
||||||
|
while (0 == (SCB_CFSR & SCB_CFSR_BFARVALID)) { // until a bus fault occurs
|
||||||
|
(void)*(volatile uint8_t*)address; // access address
|
||||||
|
address++; // got to next address
|
||||||
|
}
|
||||||
|
SCB_CFSR |= SCB_CFSR_BFARVALID; // clear bus fault flag
|
||||||
|
SCB_CCR &= ~SCB_CCR_BFHFNMIGN; // re-enable bus fault
|
||||||
|
cm_enable_faults(); // re-enable faults
|
||||||
|
|
||||||
|
return address - 1 - FLASH_BASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t flash_internal_probe_write_size(void)
|
||||||
{
|
{
|
||||||
if (0 == DESIG_FLASH_SIZE) { // no flash size advertised
|
if (0 == DESIG_FLASH_SIZE) { // no flash size advertised
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get max flash size based on device identifier (DEV_ID)
|
// prepare for reading the flash
|
||||||
uint32_t flash_size_max = 0; // max flash size (in bytes)
|
cm_disable_faults(); // disable all faults, particularly BusFault
|
||||||
switch (DBGMCU_IDCODE & DBGMCU_IDCODE_DEV_ID_MASK) { // get page size based on family code
|
SCB_CFSR |= SCB_CFSR_BFARVALID; // clear bus fault flag
|
||||||
case 0x412: // low-density, 16-32 kB flash
|
SCB_CCR |= SCB_CCR_BFHFNMIGN; // ignore bus faults (but still flag them)
|
||||||
flash_size_max = 32;
|
// prepare for writing the flash
|
||||||
break;
|
|
||||||
case 0x410: // medium-density, 64-128 kB flash
|
|
||||||
flash_size_max = 128;
|
|
||||||
break;
|
|
||||||
case 0x414: // high-density, 256-512 kB flash
|
|
||||||
flash_size_max = 512;
|
|
||||||
break;
|
|
||||||
case 0x430: // XL-density, 768-1024 kB flash
|
|
||||||
flash_size_max = 1024;
|
|
||||||
break;
|
|
||||||
case 0x418: // connectivity, 64-256 kB flash
|
|
||||||
flash_size_max = 256;
|
|
||||||
break;
|
|
||||||
case 0: // DBGMCU_IDCODE is only accessible in debug mode (this is a known issue documented in STM32F10xxC/D/E Errata sheet, without workaround)
|
|
||||||
default: // unknown
|
|
||||||
if ((*(uint32_t*)0x1FFFF000 & 0xFFFE0000) == 0x20000000) { // non-connectivity system memory start detected (MSP address pointing to SRAM
|
|
||||||
switch (DESIG_FLASH_SIZE) {
|
|
||||||
case 16:
|
|
||||||
case 32:
|
|
||||||
flash_size_max = 32; // low-density, 16-32 kB flash
|
|
||||||
break;
|
|
||||||
case 64:
|
|
||||||
case 128:
|
|
||||||
flash_size_max = 128; // medium-density, 64-128 kB flash
|
|
||||||
break;
|
|
||||||
case 256:
|
|
||||||
case 512:
|
|
||||||
flash_size_max = 512; // high-density, 256-512 kB flash
|
|
||||||
break;
|
|
||||||
case 768:
|
|
||||||
case 1024:
|
|
||||||
flash_size_max = 1024; // XL-density, 768-1024 kB flash
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else { // connectivity system memory start is at 0x1FFFB000
|
|
||||||
flash_size_max = 256; // connectivity, 64-256 kB flash
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (0 == flash_size_max) { // could not determine max flash size
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
flash_size_max *= 1024; // get in bytes
|
|
||||||
|
|
||||||
// test if page is writable, starting with last one
|
|
||||||
uint32_t flash_size; // tested flash size (in bytes)
|
|
||||||
const uint16_t test_data = 0x2342; // the data we will write and read to test page
|
|
||||||
flash_unlock(); // unlock flash to be able to write it
|
flash_unlock(); // unlock flash to be able to write it
|
||||||
for (flash_size = DESIG_FLASH_SIZE * 1024 - flash_internal_page_size(); flash_size < flash_size_max; flash_size += flash_internal_page_size()) { // don't exceed max size else it will erase the first page (weird behaviour)
|
// try reading and writing the flash, page per page
|
||||||
uint32_t address = FLASH_BASE + flash_size;
|
uint32_t address = FLASH_BASE + DESIG_FLASH_SIZE * 1024; // start with the end of the advertised flash
|
||||||
|
if ((uint32_t)&__flash_end >= FLASH_BASE) {
|
||||||
|
address = (uint32_t)&__flash_end;
|
||||||
|
}
|
||||||
|
const uint16_t test_data = 0x2342; // the data we will write and read to test page
|
||||||
|
while (address < 0x1FFFEFFF) { // this is where the system memory starts
|
||||||
|
// try reading the flash
|
||||||
|
(void)*(volatile uint32_t*)address; // access address
|
||||||
|
if (0 != (SCB_CFSR & SCB_CFSR_BFARVALID)) { // until a bus fault occurs
|
||||||
|
break; // page not readable
|
||||||
|
}
|
||||||
|
// try writing the flash
|
||||||
flash_erase_page(address); // erase current page
|
flash_erase_page(address); // erase current page
|
||||||
if (flash_get_status_flags() != FLASH_SR_EOP) { // operation went wrong
|
if (flash_get_status_flags() != FLASH_SR_EOP) { // operation went wrong
|
||||||
break;
|
break;
|
||||||
|
@ -385,12 +366,13 @@ uint16_t flash_internal_probe_size(void)
|
||||||
if (flash_get_status_flags() != FLASH_SR_EOP) { // operation went wrong
|
if (flash_get_status_flags() != FLASH_SR_EOP) { // operation went wrong
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
address += flash_internal_page_size(); // go to next page
|
||||||
}
|
}
|
||||||
flash_lock();
|
flash_clear_status_flags(); // clear all flag
|
||||||
|
flash_lock(); // protect again from writing
|
||||||
|
SCB_CFSR |= SCB_CFSR_BFARVALID; // clear bus fault flag
|
||||||
|
SCB_CCR &= ~SCB_CCR_BFHFNMIGN; // re-enable bus fault
|
||||||
|
cm_enable_faults(); // re-enable faults
|
||||||
|
|
||||||
if (flash_size < DESIG_FLASH_SIZE * 1024) { // less than advertised size
|
return address - FLASH_BASE;
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return flash_size / 1024;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,12 @@ bool flash_internal_eeprom_read(uint8_t *eeprom, uint16_t size);
|
||||||
*/
|
*/
|
||||||
int32_t flash_internal_eeprom_write(const uint8_t *eeprom, uint16_t size);
|
int32_t flash_internal_eeprom_write(const uint8_t *eeprom, uint16_t size);
|
||||||
/** probe the real size of the internal flash
|
/** probe the real size of the internal flash
|
||||||
* @return tested size (in KiB), or 0 if less than advertised
|
* @return tested size (in bytes)
|
||||||
* @warning it will write the last page of the advertised size
|
* @note it only test if the flash is readable (not writable)
|
||||||
*/
|
*/
|
||||||
uint16_t flash_internal_probe_size(void);
|
uint32_t flash_internal_probe_read_size(void);
|
||||||
|
/** probe the real size of the internal flash
|
||||||
|
* @return tested size (in bytes)
|
||||||
|
* @warning it will write to the pages over the advertised size (it will not test the MCU advertised or linker provided size and assumes this is writable)
|
||||||
|
*/
|
||||||
|
uint32_t flash_internal_probe_write_size(void);
|
||||||
|
|
Loading…
Reference in New Issue