mtd: re-add mtd_write_page()
Add a write_page() command that performs a read-modify-write cycle if necessary.
This commit is contained in:
parent
60eb75da3c
commit
e8bbe1d1c7
@ -60,8 +60,16 @@ typedef struct {
|
|||||||
uint32_t sector_count; /**< Number of sector in the MTD */
|
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 pages_per_sector; /**< Number of pages by sector in the MTD */
|
||||||
uint32_t page_size; /**< Size of the pages in the MTD */
|
uint32_t page_size; /**< Size of the pages in the MTD */
|
||||||
|
#if defined(MODULE_MTD_WRITE_PAGE) || DOXYGEN
|
||||||
|
void *work_area; /**< sector-sized buffer */
|
||||||
|
#endif
|
||||||
} mtd_dev_t;
|
} mtd_dev_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief MTD driver can write any data to the storage without erasing it first.
|
||||||
|
*/
|
||||||
|
#define MTD_DRIVER_FLAG_DIRECT_WRITE (1 << 0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief MTD driver interface
|
* @brief MTD driver interface
|
||||||
*
|
*
|
||||||
@ -203,6 +211,11 @@ struct mtd_desc {
|
|||||||
* @return < 0 value on error
|
* @return < 0 value on error
|
||||||
*/
|
*/
|
||||||
int (*power)(mtd_dev_t *dev, enum mtd_power_state power);
|
int (*power)(mtd_dev_t *dev, enum mtd_power_state power);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Properties of the MTD driver
|
||||||
|
*/
|
||||||
|
uint8_t flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -306,6 +319,36 @@ int mtd_write(mtd_dev_t *mtd, const void *src, uint32_t addr, uint32_t count);
|
|||||||
int mtd_write_page_raw(mtd_dev_t *mtd, const void *src, uint32_t page,
|
int mtd_write_page_raw(mtd_dev_t *mtd, const void *src, uint32_t page,
|
||||||
uint32_t offset, uint32_t size);
|
uint32_t offset, uint32_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write data to a MTD device with pagewise addressing
|
||||||
|
*
|
||||||
|
* The MTD layer will take care of splitting up the transaction into multiple
|
||||||
|
* writes if it is required by the underlying storage media.
|
||||||
|
*
|
||||||
|
* If the underlying sector needs to be erased before it can be written, the MTD
|
||||||
|
* layer will take care of the read-modify-write operation.
|
||||||
|
*
|
||||||
|
* @p offset must be smaller than the page size
|
||||||
|
*
|
||||||
|
* @note this requires the `mtd_write_page` module
|
||||||
|
*
|
||||||
|
* @param mtd the device to write to
|
||||||
|
* @param[in] src the buffer to write
|
||||||
|
* @param[in] page Page number to start writing to
|
||||||
|
* @param[in] offset byte offset from the start of the page
|
||||||
|
* @param[in] size the number of bytes to write
|
||||||
|
*
|
||||||
|
* @return 0 on success
|
||||||
|
* @return < 0 if an error occurred
|
||||||
|
* @return -ENODEV if @p mtd is not a valid device
|
||||||
|
* @return -ENOTSUP if operation is not supported on @p mtd
|
||||||
|
* @return -EOVERFLOW if @p addr or @p count are not valid, i.e. outside memory,
|
||||||
|
* @return -EIO if I/O error occurred
|
||||||
|
* @return -EINVAL if parameters are invalid
|
||||||
|
*/
|
||||||
|
int mtd_write_page(mtd_dev_t *mtd, const void *src, uint32_t page,
|
||||||
|
uint32_t offset, uint32_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Erase sectors of a MTD device
|
* @brief Erase sectors of a MTD device
|
||||||
*
|
*
|
||||||
|
|||||||
@ -22,6 +22,8 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "bitarithm.h"
|
#include "bitarithm.h"
|
||||||
#include "mtd.h"
|
#include "mtd.h"
|
||||||
@ -32,12 +34,22 @@ int mtd_init(mtd_dev_t *mtd)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int res = -ENOTSUP;
|
||||||
|
|
||||||
if (mtd->driver->init) {
|
if (mtd->driver->init) {
|
||||||
return mtd->driver->init(mtd);
|
res = mtd->driver->init(mtd);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return -ENOTSUP;
|
#ifdef MODULE_MTD_WRITE_PAGE
|
||||||
|
if ((mtd->driver->flags & MTD_DRIVER_FLAG_DIRECT_WRITE) == 0) {
|
||||||
|
mtd->work_area = malloc(mtd->pages_per_sector * mtd->page_size);
|
||||||
|
if (mtd->work_area == NULL) {
|
||||||
|
res = -ENOMEM;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mtd_read(mtd_dev_t *mtd, void *dest, uint32_t addr, uint32_t count)
|
int mtd_read(mtd_dev_t *mtd, void *dest, uint32_t addr, uint32_t count)
|
||||||
@ -125,6 +137,44 @@ int mtd_write(mtd_dev_t *mtd, const void *src, uint32_t addr, uint32_t count)
|
|||||||
return mtd_write_page_raw(mtd, src, addr >> page_shift, addr & page_mask, count);
|
return mtd_write_page_raw(mtd, src, addr >> page_shift, addr & page_mask, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MODULE_MTD_WRITE_PAGE
|
||||||
|
int mtd_write_page(mtd_dev_t *mtd, const void *data, uint32_t page,
|
||||||
|
uint32_t offset, uint32_t len)
|
||||||
|
{
|
||||||
|
if (!mtd || !mtd->driver) {
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mtd->work_area == NULL) {
|
||||||
|
return mtd_write_page_raw(mtd, data, page, offset, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int res;
|
||||||
|
uint8_t *work = mtd->work_area;
|
||||||
|
const uint32_t sector = page / mtd->pages_per_sector;
|
||||||
|
const uint32_t sector_page = sector * mtd->pages_per_sector;
|
||||||
|
const uint32_t sector_size = mtd->pages_per_sector * mtd->page_size;
|
||||||
|
|
||||||
|
/* copy sector to RAM */
|
||||||
|
res = mtd_read_page(mtd, work, sector_page, 0, sector_size);
|
||||||
|
if (res < 0) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* erase sector */
|
||||||
|
res = mtd_erase_sector(mtd, sector, 1);
|
||||||
|
if (res < 0) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* modify sector in RAM */
|
||||||
|
memcpy(work + (page - sector_page) * mtd->page_size + offset, data, len);
|
||||||
|
|
||||||
|
/* write back modified sector copy */
|
||||||
|
return mtd_write_page_raw(mtd, work, sector_page, 0, sector_size);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int mtd_write_page_raw(mtd_dev_t *mtd, const void *src, uint32_t page, uint32_t offset,
|
int mtd_write_page_raw(mtd_dev_t *mtd, const void *src, uint32_t page, uint32_t offset,
|
||||||
uint32_t count)
|
uint32_t count)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -81,6 +81,7 @@ PSEUDOMODULES += log_color
|
|||||||
PSEUDOMODULES += lora
|
PSEUDOMODULES += lora
|
||||||
PSEUDOMODULES += mpu_stack_guard
|
PSEUDOMODULES += mpu_stack_guard
|
||||||
PSEUDOMODULES += mpu_noexec_ram
|
PSEUDOMODULES += mpu_noexec_ram
|
||||||
|
PSEUDOMODULES += mtd_write_page
|
||||||
PSEUDOMODULES += nanocoap_%
|
PSEUDOMODULES += nanocoap_%
|
||||||
PSEUDOMODULES += netdev_default
|
PSEUDOMODULES += netdev_default
|
||||||
PSEUDOMODULES += netdev_ieee802154_%
|
PSEUDOMODULES += netdev_ieee802154_%
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user