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.h"
|
||||||
#include "at25xxx_constants.h"
|
#include "at25xxx_constants.h"
|
||||||
#include "at25xxx_params.h"
|
#include "at25xxx_params.h"
|
||||||
|
#include "bitarithm.h"
|
||||||
#include "byteorder.h"
|
#include "byteorder.h"
|
||||||
|
|
||||||
#include "xtimer.h"
|
#include "xtimer.h"
|
||||||
@ -81,12 +82,14 @@ static inline int _wait_until_eeprom_ready(const at25xxx_t *dev)
|
|||||||
return tries == 0 ? -ETIMEDOUT : 0;
|
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 */
|
/* 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);
|
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 */
|
/* wait for previous write to finish - may take up to 5 ms */
|
||||||
int res = _wait_until_eeprom_ready(dev);
|
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;
|
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 at25xxx_write(const at25xxx_t *dev, uint32_t pos, const void *data, size_t len)
|
||||||
{
|
{
|
||||||
int res = 0;
|
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;
|
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);
|
getbus(dev);
|
||||||
|
|
||||||
while (len) {
|
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) {
|
if (written < 0) {
|
||||||
res = written;
|
res = written;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
len -= written;
|
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);
|
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)
|
int at25xxx_set(const at25xxx_t *dev, uint32_t pos, uint8_t val, size_t len)
|
||||||
{
|
{
|
||||||
uint8_t data[AT225XXXX_SET_BUF_SIZE];
|
uint8_t data[AT225XXXX_SET_BUF_SIZE];
|
||||||
size_t total = 0;
|
|
||||||
|
|
||||||
if (pos + len > dev->params.size) {
|
if (pos + len > dev->params.size) {
|
||||||
return -ERANGE;
|
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));
|
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);
|
getbus(dev);
|
||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
size_t written = _write_page(dev, pos, data, min(len, sizeof(data)));
|
size_t written = _at25xxx_write_page(dev, page, offset, data, min(len, sizeof(data)));
|
||||||
len -= written;
|
len -= written;
|
||||||
pos += written;
|
page += (offset + written) >> page_shift;
|
||||||
total += written;
|
offset = (offset + written) & page_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
spi_release(dev->params.spi);
|
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);
|
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)
|
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);
|
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,
|
.init = mtd_at25xxx_init,
|
||||||
.read = mtd_at25xxx_read,
|
.read = mtd_at25xxx_read,
|
||||||
.write = mtd_at25xxx_write,
|
.write = mtd_at25xxx_write,
|
||||||
|
.write_page = mtd_at25xxx_write_page,
|
||||||
.erase = mtd_at25xxx_erase,
|
.erase = mtd_at25xxx_erase,
|
||||||
.power = mtd_at25xxx_power,
|
.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);
|
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
|
* @brief Set @p len bytes from a given position @p pos to the
|
||||||
* value @p val
|
* value @p val
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user