diff --git a/drivers/flash/flash_stm32_ospi.c b/drivers/flash/flash_stm32_ospi.c index 02a520dcdd164..0106ab4a54bd2 100644 --- a/drivers/flash/flash_stm32_ospi.c +++ b/drivers/flash/flash_stm32_ospi.c @@ -931,16 +931,11 @@ static int flash_stm32_ospi_erase(const struct device *dev, off_t addr, if (stm32_ospi_mem_ready(&dev_data->hospi, dev_cfg->data_mode, dev_cfg->data_rate) != 0) { + ospi_unlock_thread(dev); LOG_ERR("Erase failed : flash busy"); return -EBUSY; } - if (stm32_ospi_write_enable(&dev_data->hospi, - dev_cfg->data_mode, dev_cfg->data_rate) != 0) { - LOG_ERR("Erase failed : write enable"); - return -EIO; - } - cmd_erase.InstructionMode = (dev_cfg->data_mode == OSPI_OPI_MODE) ? HAL_OSPI_INSTRUCTION_8_LINES : HAL_OSPI_INSTRUCTION_1_LINE; @@ -952,6 +947,14 @@ static int flash_stm32_ospi_erase(const struct device *dev, off_t addr, : HAL_OSPI_INSTRUCTION_8_BITS; while ((size > 0) && (ret == 0)) { + + ret = stm32_ospi_write_enable(&dev_data->hospi, + dev_cfg->data_mode, dev_cfg->data_rate); + if (ret != 0) { + LOG_ERR("Erase failed : write enable"); + break; + } + if (size == dev_cfg->flash_size) { /* Chip erase */ LOG_DBG("Chip Erase"); @@ -966,6 +969,7 @@ static int flash_stm32_ospi_erase(const struct device *dev, off_t addr, } else { /* Sector erase */ LOG_DBG("Sector Erase"); + cmd_erase.Address = addr; const struct jesd216_erase_type *erase_types = dev_data->erase_types; @@ -1002,6 +1006,10 @@ static int flash_stm32_ospi_erase(const struct device *dev, off_t addr, ? stm32_ospi_hal_address_size(dev) : HAL_OSPI_ADDRESS_24_BITS; cmd_erase.Address = addr; + /* Avoid using wrong erase type, + * if zero entries are found in erase_types + */ + bet = NULL; } } @@ -1180,6 +1188,7 @@ static int flash_stm32_ospi_write(const struct device *dev, off_t addr, ret = stm32_ospi_mem_ready(&dev_data->hospi, dev_cfg->data_mode, dev_cfg->data_rate); if (ret != 0) { + ospi_unlock_thread(dev); LOG_ERR("OSPI: write not ready"); return -EIO; } diff --git a/samples/drivers/spi_flash/src/main.c b/samples/drivers/spi_flash/src/main.c index 381e3971a6eb2..177cd953b964a 100644 --- a/samples/drivers/spi_flash/src/main.c +++ b/samples/drivers/spi_flash/src/main.c @@ -26,25 +26,18 @@ #endif #define SPI_FLASH_SECTOR_SIZE 4096 -void main(void) +#if defined CONFIG_FLASH_STM32_OSPI +#define SPI_FLASH_MULTI_SECTOR_TEST +#endif + +void single_sector_test(const struct device *flash_dev) { const uint8_t expected[] = { 0x55, 0xaa, 0x66, 0x99 }; const size_t len = sizeof(expected); uint8_t buf[sizeof(expected)]; - const struct device *flash_dev; int rc; - flash_dev = DEVICE_DT_GET(DT_ALIAS(spi_flash0)); - - if (!device_is_ready(flash_dev)) { - printk("%s: device not ready.\n", flash_dev->name); - return; - } - - printf("\n%s SPI flash testing\n", flash_dev->name); - printf("==========================\n"); - - + printf("\nPerform test on single sector"); /* Write protection needs to be disabled before each write or * erase, since the flash component turns on write protection * automatically after completion of write and erase @@ -96,3 +89,106 @@ void main(void) } } } + +#if defined SPI_FLASH_MULTI_SECTOR_TEST +void multi_sector_test(const struct device *flash_dev) +{ + const uint8_t expected[] = { 0x55, 0xaa, 0x66, 0x99 }; + const size_t len = sizeof(expected); + uint8_t buf[sizeof(expected)]; + int rc; + + printf("\nPerform test on multiple consequtive sectors"); + + /* Write protection needs to be disabled before each write or + * erase, since the flash component turns on write protection + * automatically after completion of write and erase + * operations. + */ + printf("\nTest 1: Flash erase\n"); + + /* Full flash erase if SPI_FLASH_TEST_REGION_OFFSET = 0 and + * SPI_FLASH_SECTOR_SIZE = flash size + * Erase 2 sectors for check for erase of consequtive sectors + */ + rc = flash_erase(flash_dev, SPI_FLASH_TEST_REGION_OFFSET, SPI_FLASH_SECTOR_SIZE * 2); + if (rc != 0) { + printf("Flash erase failed! %d\n", rc); + } else { + /* Read the content and check for erased */ + memset(buf, 0, len); + size_t offs = SPI_FLASH_TEST_REGION_OFFSET; + + while (offs < SPI_FLASH_TEST_REGION_OFFSET + 2 * SPI_FLASH_SECTOR_SIZE) { + rc = flash_read(flash_dev, offs, buf, len); + if (rc != 0) { + printf("Flash read failed! %d\n", rc); + return; + } + if (buf[0] != 0xff) { + printf("Flash erase failed at offset 0x%x got 0x%x\n", + offs, buf[0]); + return; + } + offs += SPI_FLASH_SECTOR_SIZE; + } + printf("Flash erase succeeded!\n"); + } + + printf("\nTest 2: Flash write\n"); + + size_t offs = SPI_FLASH_TEST_REGION_OFFSET; + + while (offs < SPI_FLASH_TEST_REGION_OFFSET + 2 * SPI_FLASH_SECTOR_SIZE) { + printf("Attempting to write %zu bytes at offset 0x%x\n", len, offs); + rc = flash_write(flash_dev, offs, expected, len); + if (rc != 0) { + printf("Flash write failed! %d\n", rc); + return; + } + + memset(buf, 0, len); + rc = flash_read(flash_dev, offs, buf, len); + if (rc != 0) { + printf("Flash read failed! %d\n", rc); + return; + } + + if (memcmp(expected, buf, len) == 0) { + printf("Data read matches data written. Good!!\n"); + } else { + const uint8_t *wp = expected; + const uint8_t *rp = buf; + const uint8_t *rpe = rp + len; + + printf("Data read does not match data written!!\n"); + while (rp < rpe) { + printf("%08x wrote %02x read %02x %s\n", + (uint32_t)(offs + (rp - buf)), + *wp, *rp, (*rp == *wp) ? "match" : "MISMATCH"); + ++rp; + ++wp; + } + } + offs += SPI_FLASH_SECTOR_SIZE; + } +} +#endif + +void main(void) +{ + const struct device *flash_dev = DEVICE_DT_GET(DT_ALIAS(spi_flash0)); + + if (!device_is_ready(flash_dev)) { + printk("%s: device not ready.\n", flash_dev->name); + return; + } + + printf("\n%s SPI flash testing\n", flash_dev->name); + printf("==========================\n"); + + single_sector_test(flash_dev); +#if defined SPI_FLASH_MULTI_SECTOR_TEST + multi_sector_test(flash_dev); +#endif +}