dear all,
We are fighting with a problem that defied every effort to solve it so far, so we are asking for help. Our custom board is based on the nrf5340 SoC connected via QSPI to an external flash, specifically the mt25qu256 from Micron. Everything works perfectly if we stay in the lower 24 MBytes, but any write operation on address 0x1800000 or higher will silently fail. The driver reports no errors (return code is 0) but the data is not written and a subsequent read gives a series of 0xFFs.
The code runs on sdk 2.7.0 but I also tried v3.0.2 with the same results. This is the devicetree entry:
&qspi {
status = "okay";
pinctrl-0 = <&qspi_default>;
pinctrl-1 = <&qspi_sleep>;
pinctrl-names = "default", "sleep";
mt25qu256: mt25qu256@0 {
compatible = "nordic,qspi-nor";
reg = <0>;
writeoc = "pp4io";
readoc = "read4o";
// requires-ulbpr; // Is this needed?
sck-frequency = <DT_SIZE_M(48)>;
jedec-id = [20 bb 19];
size = <DT_SIZE_M(256)>; // bits, = 32 MiB
has-dpd;
t-enter-dpd = <10000>; // Chek value, this was taken from a different device
t-exit-dpd = <35000>; // Chek value, this was taken from a different device
enter-4byte-addr = <0xB7>; // Enter 4 byte command
address-size-32; // Force address size to 32 bit
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
littlefs_partition: littlefs_partition@0 {
label = "external_flash";
reg = <0x00000000 0x01800000>;
// reg = <0x00000000 0x02000000>;
};
};
};
};
And this is the relevant snippet of pm_static.yml
external_flash:
device: MT25QU256
address: 0x00000000
size: 0x02000000 # 32 MiB
region: external_flash
I tried measuring the erase operation and noted that it seems to be much faster (half of the time more or less) after 24 megabytes, this is of course quit suspect.
The code used to test the flash is here:
The code used to test the flash is here:
const int START_BLOCK_TEST = 0;
void test_flash_32m()
{
int rc = 0;
uint8_t buffer[SPI_FLASH_SECTOR_SIZE / 4];
uint8_t check[SPI_FLASH_SECTOR_SIZE / 4];
const int FLASH_ERASE_LARGE_BLOCK_SIZE = 64 * 1024;
memset(check, 0xFF, sizeof(check));
printk("Testing flash, please be patient it will take a while...\n");
unsigned int num_sectors = 0x2000000 / FLASH_ERASE_LARGE_BLOCK_SIZE;
unsigned long time = k_uptime_get();
for(size_t i = 384; i < 0x2000000 / (64 * 1024); i++) {
size_t block_address = i * FLASH_ERASE_LARGE_BLOCK_SIZE;
rc += flash_erase(qspi_flash, block_address, FLASH_ERASE_LARGE_BLOCK_SIZE);
// Check pattern
for(int j=0; j < 4 * FLASH_ERASE_LARGE_BLOCK_SIZE / SPI_FLASH_SECTOR_SIZE; j++) {
size_t address = block_address + j * SPI_FLASH_SECTOR_SIZE / 4;
rc = flash_read(qspi_flash, address, buffer, sizeof(buffer));
if (memcmp(check, buffer, sizeof(check)) != 0) {
printk("Flash erase failed at address 0x%X, error %d", address, rc);
return;
}
}
if(i % 8 == 0) {
printk("Erased block %X, time %u", block_address, k_uptime_get() - time);
time = k_uptime_get();
// printk(".\n");
}
}
printk("\n");
printk("Flash erase succeeded, writing test data\n");
// prepare test data
for(size_t i=0; i < sizeof(check); i++) {
check[i] = sys_rand8_get();
}
num_sectors = 0x2000000 / SPI_FLASH_SECTOR_SIZE; // 8192 blocks
for(size_t i = START_BLOCK_TEST; i < num_sectors; i++) {
size_t block_address = i * SPI_FLASH_SECTOR_SIZE;
// Write and check pattern
for(int j=0; j<4; j++) {
size_t address = block_address + j * SPI_FLASH_SECTOR_SIZE / 4;
int rcw = flash_write(qspi_flash, address, check, sizeof(check));
rc = flash_read(qspi_flash, address, buffer, sizeof(buffer));
if (memcmp(check, buffer, sizeof(check)) != 0) {
printk("Flash write failed at address 0x%X, error %d", address, rcw);
return;
}
else {
printk("Flash write successful at address 0x%X", address);
}
}
if(i % 128 == 0) {
cm_print(".\n");
}
}
printk("\n");
printk("Flash test succeeded on all 32 MB range\n");
}
Following the driver operation with debugger did not give any clue, to me at least, everything seems to be operating correctly but obviously it does not.
Thank you in advance to anybody that will be able to help.
Best regards
Davide