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:
parent
c2492209d8
commit
7c8fe862ce
@ -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);
|
||||
|
||||
@ -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,
|
||||
};
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user