Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion boards/mulle/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ static mtd_spi_nor_t mulle_nor_dev = {
.base = {
.driver = &mtd_spi_nor_driver,
.page_size = 256,
.pages_per_sector = 256,
.sector_size = 65536,
.sector_count = 32,
.min_erase_size = 65536,
},
.opcode = &mtd_spi_nor_opcode_default,
.spi = MULLE_NOR_SPI_DEV,
Expand Down
3 changes: 2 additions & 1 deletion boards/native/board_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ static mtd_native_dev_t mtd0_dev = {
.dev = {
.driver = &native_flash_driver,
.sector_count = MTD_SECTOR_NUM,
.pages_per_sector = MTD_SECTOR_SIZE / MTD_PAGE_SIZE,
.sector_size = MTD_SECTOR_SIZE,
.min_erase_size = MTD_SECTOR_SIZE,
.page_size = MTD_PAGE_SIZE,
},
.fname = MTD_NATIVE_FILENAME,
Expand Down
13 changes: 6 additions & 7 deletions cpu/native/mtd/mtd_native.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ static int _init(mtd_dev_t *dev)
if (!f) {
return -EIO;
}
size_t size = dev->sector_count * dev->pages_per_sector * dev->page_size;
for (size_t i = 0; i < size; i++) {
size_t mtd_size = dev->sector_count * dev->sector_size;
for (size_t i = 0; i < mtd_size; i++) {
real_fputc(0xff, f);
}
}
Expand All @@ -56,7 +56,7 @@ static int _init(mtd_dev_t *dev)
static int _read(mtd_dev_t *dev, void *buff, uint32_t addr, uint32_t size)
{
mtd_native_dev_t *_dev = (mtd_native_dev_t*) dev;
size_t mtd_size = dev->sector_count * dev->pages_per_sector * dev->page_size;
size_t mtd_size = dev->sector_count * dev->sector_size;

DEBUG("mtd_native: read from page %" PRIu32 " count %" PRIu32 "\n", addr, size);

Expand All @@ -78,7 +78,7 @@ static int _read(mtd_dev_t *dev, void *buff, uint32_t addr, uint32_t size)
static int _write(mtd_dev_t *dev, const void *buff, uint32_t addr, uint32_t size)
{
mtd_native_dev_t *_dev = (mtd_native_dev_t*) dev;
size_t mtd_size = dev->sector_count * dev->pages_per_sector * dev->page_size;
size_t mtd_size = dev->sector_count * dev->sector_size;

DEBUG("mtd_native: write from 0x%" PRIx32 " count %" PRIu32 "\n", addr, size);

Expand Down Expand Up @@ -107,15 +107,14 @@ static int _write(mtd_dev_t *dev, const void *buff, uint32_t addr, uint32_t size
static int _erase(mtd_dev_t *dev, uint32_t addr, uint32_t size)
{
mtd_native_dev_t *_dev = (mtd_native_dev_t*) dev;
size_t mtd_size = dev->sector_count * dev->pages_per_sector * dev->page_size;
size_t sector_size = dev->pages_per_sector * dev->page_size;
size_t mtd_size = dev->sector_count * dev->sector_size;

DEBUG("mtd_native: erase from sector %" PRIu32 " count %" PRIu32 "\n", addr, size);

if (addr + size > mtd_size) {
return -EOVERFLOW;
}
if (((addr % sector_size) != 0) || ((size % sector_size) != 0)) {
if (((addr % dev->min_erase_size) != 0) || ((size % dev->min_erase_size) != 0)) {
return -EOVERFLOW;
}

Expand Down
3 changes: 2 additions & 1 deletion drivers/include/mtd.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ typedef struct mtd_desc mtd_desc_t;
typedef struct {
const mtd_desc_t *driver; /**< MTD driver */
uint32_t sector_count; /**< Number of sector in the MTD */
uint32_t pages_per_sector; /**< Number of pages by sector in the MTD */
uint32_t sector_size; /**< Size of the sectors in the MTD */
uint32_t min_erase_size; /**< Minimum size which can be erased */
uint32_t page_size; /**< Size of the pages in the MTD */
} mtd_dev_t;

Expand Down
13 changes: 13 additions & 0 deletions drivers/include/mtd_spi_nor.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ extern "C"
typedef struct {
uint8_t rdid; /**< Read identification (JEDEC ID) */
uint8_t wren; /**< Write enable */
uint8_t wrdi; /**< Write disable */
uint8_t rdsr; /**< Read status register */
uint8_t wrsr; /**< Write status register */
uint8_t read; /**< Read data bytes, 3 byte address */
Expand Down Expand Up @@ -109,6 +110,12 @@ typedef struct {
* Computed by mtd_spi_nor_init, no need to touch outside the driver.
*/
uint32_t sec_addr_mask;
/**
* @brief bitmask corresponding to the minimum erasable sector address
*
* Computed by mtd_spi_nor_init, no need to touch outside the driver.
*/
uint32_t min_erase_addr_mask;
uint8_t addr_width; /**< Number of bytes in addresses, usually 3 for small devices */
/**
* @brief number of right shifts to get the address to the start of the page
Expand All @@ -122,6 +129,12 @@ typedef struct {
* Computed by mtd_spi_nor_init, no need to touch outside the driver.
*/
uint8_t sec_addr_shift;
/**
* @brief number of right shifts to get the address to the start of the erasable sector
*
* Computed by mtd_spi_nor_init, no need to touch outside the driver.
*/
uint8_t min_erase_addr_shift;
} mtd_spi_nor_t;

/**
Expand Down
8 changes: 4 additions & 4 deletions drivers/mtd/mtd-vfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ static int mtd_vfs_fstat(vfs_file_t *filp, struct stat *buf)
return -EFAULT;
}
buf->st_nlink = 1;
buf->st_size = mtd->page_size * mtd->sector_count * mtd->pages_per_sector;
buf->st_size = mtd->sector_count * mtd->sector_size;
return 0;
}

Expand All @@ -71,7 +71,7 @@ static off_t mtd_vfs_lseek(vfs_file_t *filp, off_t off, int whence)
off += filp->pos;
break;
case SEEK_END:
off += mtd->page_size * mtd->sector_count * mtd->pages_per_sector;
off += mtd->sector_count * mtd->sector_size;
break;
default:
return -EINVAL;
Expand All @@ -91,7 +91,7 @@ static ssize_t mtd_vfs_read(vfs_file_t *filp, void *dest, size_t nbytes)
if (mtd == NULL) {
return -EFAULT;
}
uint32_t size = mtd->page_size * mtd->sector_count * mtd->pages_per_sector;
uint32_t size = mtd->sector_count * mtd->sector_size;
uint32_t src = filp->pos;
if (src >= size) {
return 0;
Expand All @@ -114,7 +114,7 @@ static ssize_t mtd_vfs_write(vfs_file_t *filp, const void *src, size_t nbytes)
if (mtd == NULL) {
return -EFAULT;
}
uint32_t size = mtd->page_size * mtd->sector_count * mtd->pages_per_sector;
uint32_t size = mtd->sector_count * mtd->sector_size;
uint32_t dest = filp->pos;
if (dest >= size) {
/* attempt to write outside the device memory */
Expand Down
3 changes: 2 additions & 1 deletion drivers/mtd_sdcard/mtd_sdcard.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,12 @@ static int mtd_sdcard_init(mtd_dev_t *dev)
(sdcard_spi_init(mtd_sd->sd_card, mtd_sd->params) == 0)) {
/* erasing whole sectors is handled internally by the card so you can
delete single blocks (i.e. pages) */
dev->pages_per_sector = 1;
dev->sector_count = sdcard_spi_get_sector_count(mtd_sd->sd_card);

/* sdcard_spi always uses the fixed block size of SD-HC cards */
dev->page_size = SD_HC_BLOCK_SIZE;
dev->min_erase_size = SD_HC_BLOCK_SIZE;
dev->sector_size = SD_HC_BLOCK_SIZE;
return 0;
}
return -EIO;
Expand Down
67 changes: 47 additions & 20 deletions drivers/mtd_spi_nor/mtd_spi_nor.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,12 +284,13 @@ static int mtd_spi_nor_init(mtd_dev_t *mtd)

DEBUG("mtd_spi_nor_init: %" PRIu32 " bytes "
"(%" PRIu32 " sectors, %" PRIu32 " bytes/sector, "
"%" PRIu32 " pages, "
"%" PRIu32 " pages/sector, %" PRIu32 " bytes/page)\n",
mtd->pages_per_sector * mtd->sector_count * mtd->page_size,
mtd->sector_count, mtd->pages_per_sector * mtd->page_size,
mtd->pages_per_sector * mtd->sector_count,
mtd->pages_per_sector, mtd->page_size);
"%" PRIu32 " pages, %" PRIu32 " bytes/page,"
"Min erase size %" PRIu32 ")\n",
mtd->sector_count * mtd->sector_size,
mtd->sector_count, mtd->sector_size,
(mtd->sector_count * mtd->sector_size) / mtd->page_size,
mtd->page_size,
mtd->min_erase_size);
DEBUG("mtd_spi_nor_init: Using %u byte addresses\n", dev->addr_width);

if (dev->addr_width == 0) {
Expand Down Expand Up @@ -334,7 +335,7 @@ static int mtd_spi_nor_init(mtd_dev_t *mtd)

mask = 0;
shift = 0;
uint32_t sector_size = mtd->page_size * mtd->pages_per_sector;
uint32_t sector_size = mtd->sector_size;
if ((sector_size & (sector_size - 1)) == 0) {
while ((sector_size >> shift) > 1) {
++shift;
Expand All @@ -344,6 +345,19 @@ static int mtd_spi_nor_init(mtd_dev_t *mtd)
dev->sec_addr_mask = mask;
dev->sec_addr_shift = shift;

if (dev->flag & SPI_NOR_F_SECT_4K) {
dev->min_erase_addr_mask = UINT32_MAX << 12;
dev->min_erase_addr_shift = 12;
}
else if (dev->flag & SPI_NOR_F_SECT_32K) {
dev->min_erase_addr_mask = UINT32_MAX << 15;
dev->min_erase_addr_shift = 15;
}
else {
dev->min_erase_addr_mask = dev->sec_addr_mask;
dev->min_erase_addr_shift = dev->sec_addr_shift;
}

DEBUG("mtd_spi_nor_init: sec_addr_mask = 0x%08" PRIx32 ", sec_addr_shift = %u\n",
mask, (unsigned int)shift);

Expand All @@ -355,8 +369,9 @@ static int mtd_spi_nor_read(mtd_dev_t *mtd, void *dest, uint32_t addr, uint32_t
DEBUG("mtd_spi_nor_read: %p, %p, 0x%" PRIx32 ", 0x%" PRIx32 "\n",
(void *)mtd, dest, addr, size);
const mtd_spi_nor_t *dev = (mtd_spi_nor_t *)mtd;
size_t chipsize = mtd->page_size * mtd->pages_per_sector * mtd->sector_count;
size_t chipsize = mtd->sector_size * mtd->sector_count;
if (addr > chipsize) {
DEBUG("mtd_spi_nor_read: ERR: reading outside memory!\n");
return -EOVERFLOW;
}
if (size > mtd->page_size) {
Expand Down Expand Up @@ -384,7 +399,7 @@ static int mtd_spi_nor_read(mtd_dev_t *mtd, void *dest, uint32_t addr, uint32_t

static int mtd_spi_nor_write(mtd_dev_t *mtd, const void *src, uint32_t addr, uint32_t size)
{
uint32_t total_size = mtd->page_size * mtd->pages_per_sector * mtd->sector_count;
uint32_t total_size = mtd->sector_size * mtd->sector_count;

DEBUG("mtd_spi_nor_write: %p, %p, 0x%" PRIx32 ", 0x%" PRIx32 "\n",
(void *)mtd, src, addr, size);
Expand All @@ -402,6 +417,7 @@ static int mtd_spi_nor_write(mtd_dev_t *mtd, const void *src, uint32_t addr, uin
return -EOVERFLOW;
}
if (addr + size > total_size) {
DEBUG("mtd_spi_nor_write: ERR: writing outside memory!\n");
return -EOVERFLOW;
}
be_uint32_t addr_be = byteorder_htonl(addr);
Expand All @@ -422,25 +438,29 @@ static int mtd_spi_nor_write(mtd_dev_t *mtd, const void *src, uint32_t addr, uin

static int mtd_spi_nor_erase(mtd_dev_t *mtd, uint32_t addr, uint32_t size)
{
int res = 0;
DEBUG("mtd_spi_nor_erase: %p, 0x%" PRIx32 ", 0x%" PRIx32 "\n",
(void *)mtd, addr, size);
mtd_spi_nor_t *dev = (mtd_spi_nor_t *)mtd;
uint32_t sector_size = mtd->page_size * mtd->pages_per_sector;
uint32_t total_size = sector_size * mtd->sector_count;
uint32_t total_size = mtd->sector_size * mtd->sector_count;

if (dev->sec_addr_mask &&
((addr & ~dev->sec_addr_mask) != 0)) {
if (dev->min_erase_addr_mask &&
((addr & ~dev->min_erase_addr_mask) != 0)) {
/* This is not a requirement in hardware, but it helps in catching
* software bugs (the erase-all-your-files kind) */
DEBUG("addr = %" PRIx32 " ~dev->erase_addr_mask = %" PRIx32 "", addr, ~dev->sec_addr_mask);
DEBUG("addr = %" PRIx32 " ~dev->min_erase_addr_mask = %" PRIx32 "",
addr, ~dev->min_erase_addr_mask);
DEBUG("mtd_spi_nor_erase: ERR: erase addr not aligned on %" PRIu32 " byte boundary.\n",
sector_size);
mtd->min_erase_size);
return -EOVERFLOW;
}
if (addr + size > total_size) {
DEBUG("mtd_spi_nor_erase: ERR: erasing outside memory!\n");
return -EOVERFLOW;
}
if (size % sector_size != 0) {
if (size % mtd->min_erase_size != 0) {
DEBUG("mtd_spi_nor_erase: ERR: size is not aligned on %" PRIu32 " byte boundary\n",
mtd->min_erase_size);
return -EOVERFLOW;
}

Expand All @@ -454,6 +474,11 @@ static int mtd_spi_nor_erase(mtd_dev_t *mtd, uint32_t addr, uint32_t size)
mtd_spi_cmd(dev, dev->opcode->chip_erase);
size -= total_size;
}
else if ((size >= mtd->sector_size) && ((addr & ~dev->sec_addr_mask) == 0)){
mtd_spi_cmd_addr_write(dev, dev->opcode->block_erase, addr_be, NULL, 0);
addr += mtd->sector_size;
size -= mtd->sector_size;
}
else if ((dev->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 */
Expand All @@ -469,17 +494,19 @@ static int mtd_spi_nor_erase(mtd_dev_t *mtd, uint32_t addr, uint32_t size)
size -= MTD_4K;
}
else {
mtd_spi_cmd_addr_write(dev, dev->opcode->block_erase, addr_be, NULL, 0);
addr += sector_size;
size -= sector_size;
DEBUG("mtd_spi_nor_erase: ERR: remaining size is not aligned on %" PRIu32 " byte boundary\n",
mtd->min_erase_size);
mtd_spi_cmd(dev, dev->opcode->wrdi);
res = -EOVERFLOW;
break;
}

/* waiting for the command to complete before continuing */
wait_for_write_complete(dev);
}
spi_release(dev->spi);

return 0;
return res;
}

static int mtd_spi_nor_power(mtd_dev_t *mtd, enum mtd_power_state power)
Expand Down
1 change: 1 addition & 0 deletions drivers/mtd_spi_nor/mtd_spi_nor_configs.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
const mtd_spi_nor_opcode_t mtd_spi_nor_opcode_default = {
.rdid = 0x9f,
.wren = 0x06,
.wrdi = 0x04,
.rdsr = 0x05,
.wrsr = 0x01,
.read = 0x03,
Expand Down
2 changes: 1 addition & 1 deletion pkg/fatfs/fatfs_diskio/mtd/mtd_diskio.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff)
/*Erase block size in number of sectors (1 to 32768 in power of 2).
Return 1 if the erase block size is unknown. */
case GET_BLOCK_SIZE:
*(DWORD *)buff = fatfs_mtd_devs[pdrv]->pages_per_sector;
*(DWORD *)buff = fatfs_mtd_devs[pdrv]->min_erase_size / fatfs_mtd_devs[pdrv]->page_size;
return RES_OK;
#endif

Expand Down
5 changes: 3 additions & 2 deletions pkg/littlefs/fs/littlefs_fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,11 @@ static int prepare(littlefs_desc_t *fs)
memset(&fs->fs, 0, sizeof(fs->fs));

if (!fs->config.block_count) {
fs->config.block_count = fs->dev->sector_count - fs->base_addr;
fs->config.block_count = ((fs->dev->sector_count * fs->dev->sector_size) /
fs->dev->min_erase_size) - fs->base_addr;
}
if (!fs->config.block_size) {
fs->config.block_size = fs->dev->page_size * fs->dev->pages_per_sector;
fs->config.block_size = fs->dev->min_erase_size;
}
if (!fs->config.prog_size) {
fs->config.prog_size = fs->dev->page_size;
Expand Down
14 changes: 7 additions & 7 deletions pkg/spiffs/fs/spiffs_fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,19 +134,19 @@ static int prepare(spiffs_desc_t *fs_desc)
fs_desc->config.hal_erase_f = _dev_erase;

#if SPIFFS_SINGLETON == 0
DEBUG("spiffs: mount: mtd page_size=%" PRIu32 ", pages_per_sector=%" PRIu32
", sector_count=%" PRIu32 "\n", dev->page_size, dev->pages_per_sector, dev->sector_count);
DEBUG("spiffs: mount: mtd page_size=%" PRIu32 ", sector_size=%" PRIu32
", sector_count=%" PRIu32 "\n", dev->page_size, dev->sector_size, dev->sector_count);
uint32_t sector_count = (fs_desc->block_count == 0) ? dev->sector_count : fs_desc->block_count;
/* inside memory area */
assert(((fs_desc->base_addr / (dev->page_size * dev->pages_per_sector)) + sector_count)
assert(((fs_desc->base_addr / dev->min_erase_size) + sector_count)
<= dev->sector_count);
/* base addr is aligned on a sector */
assert(fs_desc->base_addr % (dev->pages_per_sector * dev->page_size) == 0);
fs_desc->config.phys_size = dev->page_size * dev->pages_per_sector * sector_count;
fs_desc->config.log_block_size = dev->page_size * dev->pages_per_sector;
assert(fs_desc->base_addr % dev->min_erase_size == 0);
fs_desc->config.phys_size = dev->min_erase_size * sector_count;
fs_desc->config.log_block_size = dev->min_erase_size;
fs_desc->config.log_page_size = dev->page_size;
fs_desc->config.phys_addr = fs_desc->base_addr;
fs_desc->config.phys_erase_block = dev->page_size * dev->pages_per_sector;
fs_desc->config.phys_erase_block = dev->min_erase_size;
#endif

return mtd_init(dev);
Expand Down
Loading