From d25edd9a1824faeab9e4deeec2a8db56c512b0fe Mon Sep 17 00:00:00 2001 From: batt Date: Sat, 3 Jul 2010 12:31:04 +0000 Subject: [PATCH] Add unbuffered methods for accessing a KBlock. Since some modules which will use KBlock use an internal buffer, the buffered API supplied by KBlock may be redundant. Specifically, if a module (like the FatFS) has its own internal block buffer, the buffer inside the KBlock would be wasted. In order to avoid this waste of RAM, this patch adds an unbuffered and simplified version of the API. All KBlocks will implement this unbuffered API, and they will give the user the option of adding a software emulated buffer at init time. In this way we can have both APIs with no RAM wasting. In order to simplify KBlock implementors' job, a series of generic functions is supplied. If the device supports only a few functions of the KBlock low level API, the missing ones may be generated using the generic ones. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@3991 38d2e660-2303-0410-9eaa-f027e97ec537 --- bertos/io/kblock.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++ bertos/io/kblock.h | 52 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 101 insertions(+), 3 deletions(-) diff --git a/bertos/io/kblock.c b/bertos/io/kblock.c index 65f42790..fb70ef94 100644 --- a/bertos/io/kblock.c +++ b/bertos/io/kblock.c @@ -42,10 +42,12 @@ #define LOG_FORMAT LOG_FMT_VERBOSE #include +#include INLINE size_t kblock_readDirect(struct KBlock *b, block_idx_t index, void *buf, size_t offset, size_t size) { KB_ASSERT_METHOD(b, readDirect); + ASSERT(index < b->blk_cnt); return b->priv.vt->readDirect(b, b->priv.blk_start + index, buf, offset, size); } @@ -134,6 +136,7 @@ size_t kblock_write(struct KBlock *b, block_idx_t idx, const void *buf, size_t o { ASSERT(b); ASSERT(buf); + ASSERT(idx < b->blk_cnt); ASSERT(offset + size <= b->blk_size); LOG_INFO("blk_idx %d, offset %d, size %d\n", idx, offset, size); @@ -148,6 +151,8 @@ size_t kblock_write(struct KBlock *b, block_idx_t idx, const void *buf, size_t o int kblock_copy(struct KBlock *b, block_idx_t idx1, block_idx_t idx2) { ASSERT(b); + ASSERT(idx1 < b->blk_cnt); + ASSERT(idx2 < b->blk_cnt); if (!kblock_loadPage(b, idx1)) return EOF; @@ -157,3 +162,50 @@ int kblock_copy(struct KBlock *b, block_idx_t idx1, block_idx_t idx2) return 0; } +int kblock_swWriteBlock(struct KBlock *b, block_idx_t index, const void *buf) +{ + return (kblock_write(b, index, buf, 0, b->blk_size) == b->blk_size) ? 0 : EOF; +} + +int kblock_swReadBlock(struct KBlock *b, block_idx_t index, void *buf) +{ + return (kblock_read(b, index, buf, 0, b->blk_size) == b->blk_size) ? 0 : EOF; +} + +int kblock_swLoad(struct KBlock *b, block_idx_t index) +{ + return kblock_readBlock(b, index, b->priv.buf); +} + +int kblock_swStore(struct KBlock *b, block_idx_t index) +{ + return kblock_writeBlock(b, index, b->priv.buf); +} + +size_t kblock_swReadBuf(struct KBlock *b, void *buf, size_t offset, size_t size) +{ + ASSERT(buf); + ASSERT(offset + size <= b->blk_size); + + memcpy(buf, (uint8_t *)b->priv.buf + offset, size); + return size; +} + +size_t kblock_swWriteBuf(struct KBlock *b, const void *buf, size_t offset, size_t size) +{ + ASSERT(buf); + ASSERT(offset + size <= b->blk_size); + memcpy((uint8_t *)b->priv.buf + offset, buf, size); + return size; +} + +size_t kblock_swReadDirect(struct KBlock *b, block_idx_t index, void *buf, size_t offset, size_t size) +{ + ASSERT(buf); + ASSERT(index < b->blk_cnt); + + if (!kblock_loadPage(b, index)) + return 0; + + return kblock_swReadBuf(b, buf, offset, size); +} \ No newline at end of file diff --git a/bertos/io/kblock.h b/bertos/io/kblock.h index 4dffe18b..abc0fcb2 100644 --- a/bertos/io/kblock.h +++ b/bertos/io/kblock.h @@ -61,6 +61,10 @@ typedef size_t (* kblock_read_t) (struct KBlock *b, void *buf, size_t off typedef size_t (* kblock_write_t) (struct KBlock *b, const void *buf, size_t offset, size_t size); typedef int (* kblock_load_t) (struct KBlock *b, block_idx_t index); typedef int (* kblock_store_t) (struct KBlock *b, block_idx_t index); + +typedef int (* kblock_write_block_t) (struct KBlock *b, block_idx_t index, const void *buf); +typedef int (* kblock_read_block_t) (struct KBlock *b, block_idx_t index, void *buf); + typedef int (* kblock_error_t) (struct KBlock *b); typedef int (* kblock_clearerr_t) (struct KBlock *b); typedef int (* kblock_close_t) (struct KBlock *b); @@ -72,11 +76,15 @@ typedef int (* kblock_close_t) (struct KBlock *b); typedef struct KBlockVTable { kblock_read_direct_t readDirect; - kblock_read_t readBuf; + + kblock_read_t readBuf; kblock_write_t writeBuf; kblock_load_t load; kblock_store_t store; - + + kblock_read_block_t readBlock; + kblock_write_block_t writeBlock; + kblock_error_t error; ///< \sa kblock_error() kblock_clearerr_t clearerr; ///< \sa kblock_clearerr() @@ -84,6 +92,8 @@ typedef struct KBlockVTable } KBlockVTable; +#define KB_BUFFERED BV(0) + /** * KBlock private members. * These are the private members of the KBlock class, please do not @@ -93,11 +103,12 @@ typedef struct KBlockPriv { DB(id_t type); ///< Used to keep track, at runtime, of the class type. int flags; ///< Status and error flags. + void *buf; block_idx_t blk_start; ///< Start block number when the device is trimmed. \sa kblock_trim() block_idx_t curr_blk; bool cache_dirty; - struct KBlockVTable *vt; ///< Virtual table of interface functions. + const struct KBlockVTable *vt; ///< Virtual table of interface functions. } KBlockPriv; /** @@ -215,6 +226,31 @@ INLINE int kblock_close(struct KBlock *b) return b->priv.vt->close(b); } +INLINE int kblock_writeBlock(struct KBlock *b, block_idx_t index, const void *buf) +{ + KB_ASSERT_METHOD(b, writeBlock); + ASSERT(index < b->blk_cnt); + return b->priv.vt->writeBlock(b, b->priv.blk_start + index, buf); +} + +INLINE int kblock_readBlock(struct KBlock *b, block_idx_t index, void *buf) +{ + KB_ASSERT_METHOD(b, readDirect); + ASSERT(index < b->blk_cnt); + return b->priv.vt->readBlock(b, b->priv.blk_start + index, buf); +} + +INLINE block_idx_t kblock_cachedBlock(struct KBlock *b) +{ + return b->priv.curr_blk; +} + +INLINE bool kblock_buffered(struct KBlock *b) +{ + ASSERT(b); + return (b->priv.flags & KB_BUFFERED); +} + size_t kblock_read(struct KBlock *b, block_idx_t idx, void *buf, size_t offset, size_t size); int kblock_flush(struct KBlock *b); @@ -223,4 +259,14 @@ size_t kblock_write(struct KBlock *b, block_idx_t idx, const void *buf, size_t o int kblock_copy(struct KBlock *b, block_idx_t idx1, block_idx_t idx2); + +int kblock_swWriteBlock(struct KBlock *b, block_idx_t index, const void *buf); +int kblock_swReadBlock(struct KBlock *b, block_idx_t index, void *buf); + +size_t kblock_swReadDirect(struct KBlock *b, block_idx_t index, void *buf, size_t offset, size_t size); +int kblock_swLoad(struct KBlock *b, block_idx_t index); +int kblock_swStore(struct KBlock *b, block_idx_t index); +size_t kblock_swReadBuf(struct KBlock *b, void *buf, size_t offset, size_t size); +size_t kblock_swWriteBuf(struct KBlock *b, const void *buf, size_t offset, size_t size); + #endif /* IO_KBLOCK_H */ -- 2.25.1