drivers/at25xxx: export page-wise write function

Export the _write_page() function so it can be used by the MTD subsystem.
This commit is contained in:
Benjamin Valentin 2020-05-07 17:52:08 +02:00
parent c2492209d8
commit 7c8fe862ce
3 changed files with 71 additions and 11 deletions

View File

@ -26,6 +26,7 @@
#include "at25xxx.h"
#include "at25xxx_constants.h"
#include "at25xxx_params.h"
#include "bitarithm.h"
#include "byteorder.h"
#include "xtimer.h"
@ -81,12 +82,14 @@ static inline int _wait_until_eeprom_ready(const at25xxx_t *dev)
return tries == 0 ? -ETIMEDOUT : 0;
}
static ssize_t _write_page(const at25xxx_t *dev, uint32_t pos, const void *data, size_t len)
static int _at25xxx_write_page(const at25xxx_t *dev, uint32_t page, uint32_t offset, const void *data, size_t len)
{
assert(offset < PAGE_SIZE);
/* write no more than to the end of the current page to prevent wrap-around */
size_t remaining = PAGE_SIZE - (pos & (PAGE_SIZE - 1));
size_t remaining = PAGE_SIZE - offset;
len = min(len, remaining);
pos = _pos(CMD_WRITE, pos);
uint32_t pos = _pos(CMD_WRITE, page * PAGE_SIZE + offset);
/* wait for previous write to finish - may take up to 5 ms */
int res = _wait_until_eeprom_ready(dev);
@ -111,6 +114,17 @@ static ssize_t _write_page(const at25xxx_t *dev, uint32_t pos, const void *data,
return len;
}
int at25xxx_write_page(const at25xxx_t *dev, uint32_t page, uint32_t offset, const void *data, size_t len)
{
int res;
getbus(dev);
res = _at25xxx_write_page(dev, page, offset, data, len);
spi_release(dev->params.spi);
return res;
}
int at25xxx_write(const at25xxx_t *dev, uint32_t pos, const void *data, size_t len)
{
int res = 0;
@ -120,18 +134,32 @@ int at25xxx_write(const at25xxx_t *dev, uint32_t pos, const void *data, size_t l
return -ERANGE;
}
/* page size is always a power of two */
const uint32_t page_shift = bitarithm_msb(PAGE_SIZE);
const uint32_t page_mask = PAGE_SIZE - 1;
uint32_t page = pos >> page_shift;
uint32_t offset = pos & page_mask;
getbus(dev);
while (len) {
ssize_t written = _write_page(dev, pos, d, len);
ssize_t written = _at25xxx_write_page(dev, page, offset, d, len);
if (written < 0) {
res = written;
break;
}
len -= written;
pos += written;
d += written;
if (len == 0) {
break;
}
d += written;
page += (offset + written) >> page_shift;
offset = (offset + written) & page_mask;
}
spi_release(dev->params.spi);
@ -177,7 +205,6 @@ uint8_t at25xxx_read_byte(const at25xxx_t *dev, uint32_t pos)
int at25xxx_set(const at25xxx_t *dev, uint32_t pos, uint8_t val, size_t len)
{
uint8_t data[AT225XXXX_SET_BUF_SIZE];
size_t total = 0;
if (pos + len > dev->params.size) {
return -ERANGE;
@ -185,13 +212,20 @@ int at25xxx_set(const at25xxx_t *dev, uint32_t pos, uint8_t val, size_t len)
memset(data, val, sizeof(data));
/* page size is always a power of two */
const uint32_t page_shift = bitarithm_msb(PAGE_SIZE);
const uint32_t page_mask = PAGE_SIZE - 1;
uint32_t page = pos >> page_shift;
uint32_t offset = pos & page_mask;
getbus(dev);
while (len) {
size_t written = _write_page(dev, pos, data, min(len, sizeof(data)));
len -= written;
pos += written;
total += written;
size_t written = _at25xxx_write_page(dev, page, offset, data, min(len, sizeof(data)));
len -= written;
page += (offset + written) >> page_shift;
offset = (offset + written) & page_mask;
}
spi_release(dev->params.spi);

View File

@ -57,6 +57,15 @@ static int mtd_at25xxx_write(mtd_dev_t *dev, const void *buff, uint32_t addr, ui
return at25xxx_write(mtd_at25xxx_->at25xxx_eeprom, addr, buff, size);
}
static int mtd_at25xxx_write_page(mtd_dev_t *dev, const void *src, uint32_t page, uint32_t offset,
uint32_t size)
{
DEBUG("[mtd_at25xxx] write_page: page:%" PRIu32 " offset:%" PRIu32 " size:%" PRIu32 "\n",
page, offset, size);
mtd_at25xxx_t *mtd_at25xxx_ = (mtd_at25xxx_t*)dev;
return at25xxx_write_page(mtd_at25xxx_->at25xxx_eeprom, page, offset, src, size);
}
static int mtd_at25xxx_erase(mtd_dev_t *dev, uint32_t addr, uint32_t size)
{
DEBUG("[mtd_at25xxx] mtd_at25xxx_erase: addr:%" PRIu32 " size:%" PRIu32 "\n", addr, size);
@ -78,6 +87,7 @@ const mtd_desc_t mtd_at25xxx_driver = {
.init = mtd_at25xxx_init,
.read = mtd_at25xxx_read,
.write = mtd_at25xxx_write,
.write_page = mtd_at25xxx_write_page,
.erase = mtd_at25xxx_erase,
.power = mtd_at25xxx_power,
};

View File

@ -109,6 +109,22 @@ void at25xxx_write_byte(const at25xxx_t *dev, uint32_t pos, uint8_t data);
*/
int at25xxx_write(const at25xxx_t *dev, uint32_t pos, const void *data, size_t len);
/**
* @brief Sequentially write @p len bytes to a given @p page.
* The function will write up to the page boundary and then return.
*
* @param[in] dev AT25XXX device handle
* @param[in] page page of EEPROM memory
* @param[in] offset offset from the start of the page, must be < page size
* @param[in] data write buffer
* @param[in] len requested length to be written
*
* @return number of bytes written on success
* @return error on failure
*/
int at25xxx_write_page(const at25xxx_t *dev, uint32_t page, uint32_t offset,
const void *data, size_t len);
/**
* @brief Set @p len bytes from a given position @p pos to the
* value @p val