mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
drivers/mtd_spi_nor: prevent data corruption on 'sector erase'
There is no difference between 4k erase and sector erase. But sector erase would previously do `.block_erase` which would not erase a sector (4k) but a whole block (64k). Fortunately all boards declare `SPI_NOR_F_SECT_4K` and all file systems don't try to erase anything smaller, so this was never triggered. Add an `assert(0)` to crash instead of corrupting data.
This commit is contained in:
parent
783df5990b
commit
fde3026312
@ -30,7 +30,6 @@ static const mtd_spi_nor_params_t _ikea_tradfri_nor_params = {
|
||||
.wait_chip_erase = 2LU * US_PER_SEC,
|
||||
.wait_32k_erase = 500LU *US_PER_MS,
|
||||
.wait_sector_erase = 300LU * US_PER_MS,
|
||||
.wait_4k_erase = 300LU * US_PER_MS,
|
||||
.wait_chip_wake_up = 1LU * US_PER_MS,
|
||||
.clk = IKEA_TRADFRI_NOR_SPI_CLK,
|
||||
.flag = IKEA_TRADFRI_NOR_FLAGS,
|
||||
|
@ -51,9 +51,8 @@ static devfs_t mulle_nvram_devfs = {
|
||||
static const mtd_spi_nor_params_t mulle_nor_params = {
|
||||
.opcode = &mtd_spi_nor_opcode_default,
|
||||
.wait_chip_erase = 16LU * US_PER_SEC,
|
||||
.wait_sector_erase = 40LU * US_PER_MS,
|
||||
.wait_sector_erase = 10LU * US_PER_MS,
|
||||
.wait_32k_erase = 20LU * US_PER_MS,
|
||||
.wait_4k_erase = 10LU * US_PER_MS,
|
||||
.wait_chip_wake_up = 1LU * US_PER_MS,
|
||||
.spi = MULLE_NOR_SPI_DEV,
|
||||
.cs = MULLE_NOR_SPI_CS,
|
||||
|
@ -32,7 +32,6 @@ static const mtd_spi_nor_params_t _nrf52840dk_nor_params = {
|
||||
.wait_chip_erase = 50LU * US_PER_SEC,
|
||||
.wait_32k_erase = 240LU *US_PER_MS,
|
||||
.wait_sector_erase = 40LU * US_PER_MS,
|
||||
.wait_4k_erase = 40LU * US_PER_MS,
|
||||
.wait_chip_wake_up = 35LU * US_PER_MS,
|
||||
.clk = NRF52840DK_NOR_SPI_CLK,
|
||||
.flag = NRF52840DK_NOR_FLAGS,
|
||||
|
@ -35,7 +35,6 @@ static const mtd_spi_nor_params_t _pinetime_nor_params = {
|
||||
.wait_chip_erase = 9LU * US_PER_SEC,
|
||||
.wait_32k_erase = 160LU *US_PER_MS,
|
||||
.wait_sector_erase = 70LU * US_PER_MS,
|
||||
.wait_4k_erase = 70LU * US_PER_MS,
|
||||
.wait_chip_wake_up = 1LU * US_PER_MS,
|
||||
.clk = PINETIME_NOR_SPI_CLK,
|
||||
.flag = PINETIME_NOR_FLAGS,
|
||||
|
@ -33,7 +33,6 @@ static const mtd_spi_nor_params_t _serpente_nor_params = {
|
||||
.wait_chip_erase = 15LU * US_PER_SEC,
|
||||
.wait_32k_erase = 250LU * US_PER_MS,
|
||||
.wait_sector_erase = 50LU * US_PER_MS,
|
||||
.wait_4k_erase = 150LU * US_PER_MS,
|
||||
.wait_chip_wake_up = 1LU * US_PER_MS,
|
||||
.clk = SERPENTE_NOR_SPI_CLK,
|
||||
.flag = SERPENTE_NOR_FLAGS,
|
||||
|
@ -32,7 +32,6 @@ static const mtd_spi_nor_params_t _weact_nor_params = {
|
||||
.wait_chip_erase = 4800LU * US_PER_MS,
|
||||
.wait_32k_erase = 300LU * US_PER_MS,
|
||||
.wait_sector_erase = 70LU * US_PER_MS,
|
||||
.wait_4k_erase = 70LU * US_PER_MS,
|
||||
.wait_chip_wake_up = 1LU * US_PER_MS,
|
||||
.clk = WEACT_411CE_NOR_SPI_CLK,
|
||||
.flag = WEACT_411CE_NOR_FLAGS,
|
||||
|
@ -49,7 +49,7 @@ typedef struct {
|
||||
uint8_t page_program; /**< Page program */
|
||||
uint8_t sector_erase; /**< Block erase 4 KiB */
|
||||
uint8_t block_erase_32k; /**< 32KiB block erase */
|
||||
uint8_t block_erase; /**< Block erase (usually 64 KiB) */
|
||||
uint8_t block_erase_64k; /**< Block erase (usually 64 KiB) */
|
||||
uint8_t chip_erase; /**< Chip erase */
|
||||
uint8_t sleep; /**< Deep power down */
|
||||
uint8_t wake; /**< Release from deep power down */
|
||||
@ -85,20 +85,26 @@ typedef struct __attribute__((packed)) {
|
||||
* @brief Flag to set when the device support 4KiB sector erase (sector_erase opcode)
|
||||
*/
|
||||
#define SPI_NOR_F_SECT_4K (1)
|
||||
|
||||
/**
|
||||
* @brief Flag to set when the device support 32KiB block erase (block_erase_32k opcode)
|
||||
*/
|
||||
#define SPI_NOR_F_SECT_32K (2)
|
||||
|
||||
/**
|
||||
* @brief Flag to set when the device support 64KiB block erase (block_erase_32k opcode)
|
||||
*/
|
||||
#define SPI_NOR_F_SECT_64K (4)
|
||||
|
||||
/**
|
||||
* @brief Compile-time parameters for a serial flash device
|
||||
*/
|
||||
typedef struct {
|
||||
const mtd_spi_nor_opcode_t *opcode; /**< Opcode table for the device */
|
||||
uint32_t wait_chip_erase; /**< Full chip erase wait time in µs */
|
||||
uint32_t wait_sector_erase; /**< Sector erase wait time in µs */
|
||||
uint32_t wait_64k_erase; /**< 64KB page erase wait time in µs */
|
||||
uint32_t wait_32k_erase; /**< 32KB page erase wait time in µs */
|
||||
uint32_t wait_4k_erase; /**< 4KB page erase wait time in µs */
|
||||
uint32_t wait_sector_erase; /**< 4KB sector erase wait time in µs */
|
||||
uint32_t wait_chip_wake_up; /**< Chip wake up time in µs */
|
||||
spi_clk_t clk; /**< SPI clock */
|
||||
uint16_t flag; /**< Config flags */
|
||||
|
@ -46,6 +46,8 @@
|
||||
#define MTD_POWER_UP_WAIT_FOR_ID (0x0F)
|
||||
#endif
|
||||
|
||||
#define MTD_64K (65536ul)
|
||||
#define MTD_64K_ADDR_MASK (0xFFFF)
|
||||
#define MTD_32K (32768ul)
|
||||
#define MTD_32K_ADDR_MASK (0x7FFF)
|
||||
#define MTD_4K (4096ul)
|
||||
@ -605,6 +607,14 @@ static int mtd_spi_nor_erase(mtd_dev_t *mtd, uint32_t addr, uint32_t size)
|
||||
size -= total_size;
|
||||
us = dev->params->wait_chip_erase;
|
||||
}
|
||||
else if ((dev->params->flag & SPI_NOR_F_SECT_64K) && (size >= MTD_64K) &&
|
||||
((addr & MTD_64K_ADDR_MASK) == 0)) {
|
||||
/* 64 KiB blocks can be erased with block erase command */
|
||||
mtd_spi_cmd_addr_write(dev, dev->params->opcode->block_erase_64k, addr, NULL, 0);
|
||||
addr += MTD_64K;
|
||||
size -= MTD_64K;
|
||||
us = dev->params->wait_64k_erase;
|
||||
}
|
||||
else if ((dev->params->flag & SPI_NOR_F_SECT_32K) && (size >= MTD_32K) &&
|
||||
((addr & MTD_32K_ADDR_MASK) == 0)) {
|
||||
/* 32 KiB blocks can be erased with block erase command */
|
||||
@ -619,13 +629,14 @@ static int mtd_spi_nor_erase(mtd_dev_t *mtd, uint32_t addr, uint32_t size)
|
||||
mtd_spi_cmd_addr_write(dev, dev->params->opcode->sector_erase, addr, NULL, 0);
|
||||
addr += MTD_4K;
|
||||
size -= MTD_4K;
|
||||
us = dev->params->wait_4k_erase;
|
||||
us = dev->params->wait_sector_erase;
|
||||
}
|
||||
else {
|
||||
mtd_spi_cmd_addr_write(dev, dev->params->opcode->block_erase, addr, NULL, 0);
|
||||
addr += sector_size;
|
||||
size -= sector_size;
|
||||
us = dev->params->wait_sector_erase;
|
||||
/* no suitable erase block found */
|
||||
assert(0);
|
||||
|
||||
mtd_spi_release(dev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* waiting for the command to complete before continuing */
|
||||
|
@ -36,7 +36,7 @@ const mtd_spi_nor_opcode_t mtd_spi_nor_opcode_default = {
|
||||
.page_program = 0x02,
|
||||
.sector_erase = 0x20,
|
||||
.block_erase_32k = 0x52,
|
||||
.block_erase = 0xd8,
|
||||
.block_erase_64k = 0xd8,
|
||||
.chip_erase = 0xc7,
|
||||
.sleep = 0xb9,
|
||||
.wake = 0xab,
|
||||
@ -52,7 +52,7 @@ const mtd_spi_nor_opcode_t mtd_spi_nor_opcode_default_4bytes = {
|
||||
.page_program = 0x12,
|
||||
.sector_erase = 0x21,
|
||||
.block_erase_32k = 0x5c,
|
||||
.block_erase = 0xdc,
|
||||
.block_erase_64k = 0xdc,
|
||||
.chip_erase = 0xc7,
|
||||
.sleep = 0xb9,
|
||||
.wake = 0xab,
|
||||
|
Loading…
Reference in New Issue
Block a user