Add buffering support for flash drivers.

Some devices can get a significant boost in performance by writing to
flash memories one page at a time.  Generic function to do this are
provided at the target layer and may be used by flash drivers.
This commit is contained in:
Gareth McMullin 2015-03-26 22:20:47 -07:00
parent 36f749fed9
commit 45328ea124
2 changed files with 59 additions and 0 deletions

View File

@ -133,6 +133,12 @@ struct target_flash {
struct target_flash *next;
int align;
uint8_t erased;
/* For buffered flash */
size_t buf_size;
flash_write_func write_buf;
uint32_t buf_addr;
void *buf;
};
struct target_s {
@ -215,6 +221,9 @@ void target_add_commands(target *t, const struct command_s *cmds, const char *na
void target_add_ram(target *t, uint32_t start, uint32_t len);
void target_add_flash(target *t, struct target_flash *f);
const char *target_mem_map(target *t);
int target_flash_write_buffered(struct target_flash *f,
uint32_t dest, const void *src, size_t len);
int target_flash_done_buffered(struct target_flash *f);
static inline uint32_t target_mem_read32(target *t, uint32_t addr)
{

View File

@ -57,6 +57,8 @@ void target_list_free(void)
}
while (target_list->flash) {
void * next = target_list->flash->next;
if (target_list->flash->buf)
free(target_list->flash->buf);
free(target_list->flash);
target_list->flash = next;
}
@ -216,3 +218,51 @@ int target_flash_done(target *t)
return 0;
}
int target_flash_write_buffered(struct target_flash *f,
uint32_t dest, const void *src, size_t len)
{
int ret = 0;
if (f->buf == NULL) {
/* Allocate flash sector buffer */
f->buf = malloc(f->buf_size);
f->buf_addr = -1;
}
while (len) {
uint32_t offset = dest % f->buf_size;
uint32_t base = dest - offset;
if (base != f->buf_addr) {
if (f->buf_addr != (uint32_t)-1) {
/* Write sector to flash if valid */
ret |= f->write_buf(f, f->buf_addr,
f->buf, f->buf_size);
}
/* Setup buffer for a new sector */
f->buf_addr = base;
memset(f->buf, f->erased, f->buf_size);
}
/* Copy chunk into sector buffer */
size_t sectlen = MIN(f->buf_size - offset, len);
memcpy(f->buf + offset, src, sectlen);
dest += sectlen;
src += sectlen;
len -= sectlen;
}
return ret;
}
int target_flash_done_buffered(struct target_flash *f)
{
int ret = 0;
if ((f->buf != NULL) &&(f->buf_addr != (uint32_t)-1)) {
/* Write sector to flash if valid */
ret = f->write_buf(f, f->buf_addr, f->buf, f->buf_size);
f->buf_addr = -1;
free(f->buf);
f->buf = NULL;
}
return ret;
}