feat(fs): file writes update the file cache (#6186)
Co-authored-by: kevinkang-Globe <139213362+kevinkang-Globe@users.noreply.github.com>
This commit is contained in:
@@ -42,7 +42,8 @@ extensions = [
|
|||||||
'sphinx_sitemap',
|
'sphinx_sitemap',
|
||||||
'lv_example',
|
'lv_example',
|
||||||
'sphinx_rtd_dark_mode',
|
'sphinx_rtd_dark_mode',
|
||||||
'link_roles'
|
'link_roles',
|
||||||
|
'sphinxcontrib.mermaid'
|
||||||
]
|
]
|
||||||
|
|
||||||
default_dark_mode = False
|
default_dark_mode = False
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ The work directory can be set with ``LV_FS_..._PATH``. E.g.
|
|||||||
``"/home/joe/projects/"`` The actual file/directory paths will be
|
``"/home/joe/projects/"`` The actual file/directory paths will be
|
||||||
appended to it.
|
appended to it.
|
||||||
|
|
||||||
Cached reading is also supported if ``LV_FS_..._CACHE_SIZE`` is set to
|
:ref:`Cached reading <overview_file_system_cache>` is also supported if ``LV_FS_..._CACHE_SIZE`` is set to
|
||||||
not ``0`` value. :cpp:func:`lv_fs_read` caches this size of data to lower the
|
not ``0`` value. :cpp:func:`lv_fs_read` caches this size of data to lower the
|
||||||
number of actual reads from the storage.
|
number of actual reads from the storage.
|
||||||
|
|
||||||
|
|||||||
@@ -155,6 +155,95 @@ To use files in image widgets the following callbacks are required:
|
|||||||
- seek
|
- seek
|
||||||
- tell
|
- tell
|
||||||
|
|
||||||
|
.. _overview_file_system_cache:
|
||||||
|
|
||||||
|
Optional file buffering/caching
|
||||||
|
*******************************
|
||||||
|
|
||||||
|
Files will buffer their reads if the corresponding ``LV_FS_*_CACHE_SIZE``
|
||||||
|
config option is set to a value greater than zero. Each open file will
|
||||||
|
buffer up to that many bytes to reduce the number of FS driver calls.
|
||||||
|
|
||||||
|
Generally speaking, file buffering can be optimized for different kinds
|
||||||
|
of access patterns. The one implemented here is optimal for reading large
|
||||||
|
files in chunks, which is what the image decoder does.
|
||||||
|
It has the potential to call the driver's ``read`` fewer
|
||||||
|
times than ``lv_fs_read`` is called. In the best case where the cache size is
|
||||||
|
\>= the size of the file, ``read`` will only be called once. This strategy is good
|
||||||
|
for linear reading of large files but less helpful for short random reads across a file bigger than the buffer
|
||||||
|
since data will be buffered that will be discarded after the next seek and read.
|
||||||
|
The cache should be sufficiently large or disabled in that case. Another case where the cache should be disabled
|
||||||
|
is if the file contents are expected to change by an external factor like with special OS files.
|
||||||
|
|
||||||
|
The implementation is documented below. Note that the FS functions make calls
|
||||||
|
to other driver FS functions when the cache is enabled. i.e., ``lv_fs_read`` may call the driver's ``seek``
|
||||||
|
so the driver needs to implement more callbacks when the cache is enabled.
|
||||||
|
|
||||||
|
``lv_fs_read`` :sub:`(behavior when the cache is enabled)`
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
.. mermaid::
|
||||||
|
:zoom:
|
||||||
|
|
||||||
|
%%{init: {'theme':'neutral'}}%%
|
||||||
|
flowchart LR
|
||||||
|
A["call lv_fs_read and
|
||||||
|
the cache is enabled"] --> B{{"is there cached data
|
||||||
|
at the file position?"}}
|
||||||
|
B -->|yes| C{{"does the cache have
|
||||||
|
all required bytes available?"}}
|
||||||
|
C -->|yes| D["copy all required bytes from
|
||||||
|
the cache to the destination
|
||||||
|
buffer"]
|
||||||
|
C -->|no| F["copy the available
|
||||||
|
required bytes
|
||||||
|
until the end of the cache
|
||||||
|
into the destination buffer"]
|
||||||
|
--> G["seek the real file to the end
|
||||||
|
of what the cache had available"]
|
||||||
|
--> H{{"is the number of remaining bytes
|
||||||
|
larger than the size of the whole cache?"}}
|
||||||
|
H -->|yes| I["read the remaining bytes
|
||||||
|
from the real file to the
|
||||||
|
destination buffer"]
|
||||||
|
H -->|no| J["eagerly read the real file
|
||||||
|
to fill the whole cache
|
||||||
|
or as many bytes as the
|
||||||
|
read call can"]
|
||||||
|
--> O["copy the required bytes
|
||||||
|
to the destination buffer"]
|
||||||
|
B -->|no| K["seek the real file to
|
||||||
|
the file position"]
|
||||||
|
--> L{{"is the number of required
|
||||||
|
bytes greater than the
|
||||||
|
size of the entire cache?"}}
|
||||||
|
L -->|yes| M["read the real file to
|
||||||
|
the destination buffer"]
|
||||||
|
L -->|no| N["eagerly read the real file
|
||||||
|
to fill the whole cache
|
||||||
|
or as many bytes as the
|
||||||
|
read call can"]
|
||||||
|
--> P["copy the required bytes
|
||||||
|
to the destination buffer"]
|
||||||
|
|
||||||
|
``lv_fs_write`` :sub:`(behavior when the cache is enabled)`
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
The part of the cache that coincides with the written content
|
||||||
|
will be updated to reflect the written content.
|
||||||
|
|
||||||
|
``lv_fs_seek`` :sub:`(behavior when the cache is enabled)`
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
The driver's ``seek`` will not actually be called unless the ``whence``
|
||||||
|
is ``LV_FS_SEEK_END``, in which case ``seek`` and ``tell`` will be called
|
||||||
|
to determine where the end of the file is.
|
||||||
|
|
||||||
|
``lv_fs_tell`` :sub:`(behavior when the cache is enabled)`
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
The driver's ``tell`` will not actually be called.
|
||||||
|
|
||||||
.. _overview_file_system_api:
|
.. _overview_file_system_api:
|
||||||
|
|
||||||
API
|
API
|
||||||
|
|||||||
@@ -10,5 +10,6 @@ sphinxcontrib-htmlhelp
|
|||||||
sphinxcontrib-jsmath
|
sphinxcontrib-jsmath
|
||||||
sphinxcontrib-qthelp
|
sphinxcontrib-qthelp
|
||||||
sphinxcontrib-serializinghtml
|
sphinxcontrib-serializinghtml
|
||||||
|
sphinxcontrib-mermaid
|
||||||
sphinx-rtd-dark-mode
|
sphinx-rtd-dark-mode
|
||||||
typing-extensions
|
typing-extensions
|
||||||
|
|||||||
337
src/misc/lv_fs.c
337
src/misc/lv_fs.c
@@ -27,6 +27,9 @@
|
|||||||
* STATIC PROTOTYPES
|
* STATIC PROTOTYPES
|
||||||
**********************/
|
**********************/
|
||||||
static const char * lv_fs_get_real_path(const char * path);
|
static const char * lv_fs_get_real_path(const char * path);
|
||||||
|
static lv_fs_res_t lv_fs_read_cached(lv_fs_file_t * file_p, void * buf, uint32_t btr, uint32_t * br);
|
||||||
|
static lv_fs_res_t lv_fs_write_cached(lv_fs_file_t * file_p, const void * buf, uint32_t btw, uint32_t * bw);
|
||||||
|
static lv_fs_res_t lv_fs_seek_cached(lv_fs_file_t * file_p, uint32_t pos, lv_fs_whence_t whence);
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
* STATIC VARIABLES
|
* STATIC VARIABLES
|
||||||
@@ -171,100 +174,17 @@ lv_fs_res_t lv_fs_close(lv_fs_file_t * file_p)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static lv_fs_res_t lv_fs_read_cached(lv_fs_file_t * file_p, char * buf, uint32_t btr, uint32_t * br)
|
|
||||||
{
|
|
||||||
LV_PROFILER_BEGIN;
|
|
||||||
|
|
||||||
lv_fs_res_t res = LV_FS_RES_OK;
|
|
||||||
uint32_t file_position = file_p->cache->file_position;
|
|
||||||
uint32_t start = file_p->cache->start;
|
|
||||||
uint32_t end = file_p->cache->end;
|
|
||||||
char * buffer = file_p->cache->buffer;
|
|
||||||
uint32_t buffer_size = file_p->drv->cache_size;
|
|
||||||
|
|
||||||
if(start <= file_position && file_position <= end) {
|
|
||||||
/* Data can be read from cache buffer */
|
|
||||||
uint32_t buffer_remaining_length = (uint32_t)end - file_position + 1;
|
|
||||||
uint32_t buffer_offset = (end - start) - buffer_remaining_length + 1;
|
|
||||||
|
|
||||||
/* Do not allow reading beyond the actual memory block for memory-mapped files */
|
|
||||||
if(file_p->drv->cache_size == LV_FS_CACHE_FROM_BUFFER) {
|
|
||||||
if(btr > buffer_remaining_length)
|
|
||||||
btr = buffer_remaining_length - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(btr <= buffer_remaining_length) {
|
|
||||||
/*Data is in cache buffer, and buffer end not reached, no need to read from FS*/
|
|
||||||
lv_memcpy(buf, buffer + buffer_offset, btr);
|
|
||||||
*br = btr;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/*First part of data is in cache buffer, but we need to read rest of data from FS*/
|
|
||||||
lv_memcpy(buf, buffer + buffer_offset, buffer_remaining_length);
|
|
||||||
|
|
||||||
file_p->drv->seek_cb(file_p->drv, file_p->file_d, file_p->cache->end + 1,
|
|
||||||
LV_FS_SEEK_SET);
|
|
||||||
|
|
||||||
uint32_t bytes_read_to_buffer = 0;
|
|
||||||
if(btr - buffer_remaining_length > buffer_size) {
|
|
||||||
/*If remaining data chuck is bigger than buffer size, then do not use cache, instead read it directly from FS*/
|
|
||||||
res = file_p->drv->read_cb(file_p->drv, file_p->file_d, (void *)(buf + buffer_remaining_length),
|
|
||||||
btr - buffer_remaining_length, &bytes_read_to_buffer);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/*If remaining data chunk is smaller than buffer size, then read into cache buffer*/
|
|
||||||
res = file_p->drv->read_cb(file_p->drv, file_p->file_d, (void *)buffer, buffer_size, &bytes_read_to_buffer);
|
|
||||||
file_p->cache->start = file_p->cache->end + 1;
|
|
||||||
file_p->cache->end = file_p->cache->start + bytes_read_to_buffer - 1;
|
|
||||||
|
|
||||||
uint16_t data_chunk_remaining = LV_MIN(btr - buffer_remaining_length, bytes_read_to_buffer);
|
|
||||||
lv_memcpy(buf + buffer_remaining_length, buffer, data_chunk_remaining);
|
|
||||||
}
|
|
||||||
*br = LV_MIN(buffer_remaining_length + bytes_read_to_buffer, btr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
file_p->drv->seek_cb(file_p->drv, file_p->file_d, file_p->cache->file_position,
|
|
||||||
LV_FS_SEEK_SET);
|
|
||||||
|
|
||||||
/*Data is not in cache buffer*/
|
|
||||||
if(btr > buffer_size) {
|
|
||||||
/*If bigger data is requested, then do not use cache, instead read it directly*/
|
|
||||||
res = file_p->drv->read_cb(file_p->drv, file_p->file_d, (void *)buf, btr, br);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/*If small data is requested, then read from FS into cache buffer*/
|
|
||||||
if(buffer == NULL) {
|
|
||||||
file_p->cache->buffer = lv_malloc(buffer_size);
|
|
||||||
LV_ASSERT_MALLOC(file_p->cache->buffer);
|
|
||||||
buffer = file_p->cache->buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t bytes_read_to_buffer = 0;
|
|
||||||
res = file_p->drv->read_cb(file_p->drv, file_p->file_d, (void *)buffer, buffer_size, &bytes_read_to_buffer);
|
|
||||||
file_p->cache->start = file_position;
|
|
||||||
file_p->cache->end = file_p->cache->start + bytes_read_to_buffer - 1;
|
|
||||||
|
|
||||||
*br = LV_MIN(btr, bytes_read_to_buffer);
|
|
||||||
lv_memcpy(buf, buffer, *br);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(res == LV_FS_RES_OK) {
|
|
||||||
file_p->cache->file_position += *br;
|
|
||||||
}
|
|
||||||
|
|
||||||
LV_PROFILER_END;
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
lv_fs_res_t lv_fs_read(lv_fs_file_t * file_p, void * buf, uint32_t btr, uint32_t * br)
|
lv_fs_res_t lv_fs_read(lv_fs_file_t * file_p, void * buf, uint32_t btr, uint32_t * br)
|
||||||
{
|
{
|
||||||
if(br != NULL) *br = 0;
|
if(br != NULL) *br = 0;
|
||||||
if(file_p->drv == NULL) return LV_FS_RES_INV_PARAM;
|
if(file_p->drv == NULL) return LV_FS_RES_INV_PARAM;
|
||||||
if(file_p->drv->read_cb == NULL) return LV_FS_RES_NOT_IMP;
|
|
||||||
|
if(file_p->drv->cache_size) {
|
||||||
|
if(file_p->drv->read_cb == NULL || file_p->drv->seek_cb == NULL) return LV_FS_RES_NOT_IMP;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(file_p->drv->read_cb == NULL) return LV_FS_RES_NOT_IMP;
|
||||||
|
}
|
||||||
|
|
||||||
LV_PROFILER_BEGIN;
|
LV_PROFILER_BEGIN;
|
||||||
|
|
||||||
@@ -272,7 +192,7 @@ lv_fs_res_t lv_fs_read(lv_fs_file_t * file_p, void * buf, uint32_t btr, uint32_t
|
|||||||
lv_fs_res_t res;
|
lv_fs_res_t res;
|
||||||
|
|
||||||
if(file_p->drv->cache_size) {
|
if(file_p->drv->cache_size) {
|
||||||
res = lv_fs_read_cached(file_p, (char *)buf, btr, &br_tmp);
|
res = lv_fs_read_cached(file_p, buf, btr, &br_tmp);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
res = file_p->drv->read_cb(file_p->drv, file_p->file_d, buf, btr, &br_tmp);
|
res = file_p->drv->read_cb(file_p->drv, file_p->file_d, buf, btr, &br_tmp);
|
||||||
@@ -293,30 +213,25 @@ lv_fs_res_t lv_fs_write(lv_fs_file_t * file_p, const void * buf, uint32_t btw, u
|
|||||||
return LV_FS_RES_INV_PARAM;
|
return LV_FS_RES_INV_PARAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(file_p->drv->write_cb == NULL) {
|
if(file_p->drv->cache_size) {
|
||||||
return LV_FS_RES_NOT_IMP;
|
if(file_p->drv->write_cb == NULL || file_p->drv->seek_cb == NULL) return LV_FS_RES_NOT_IMP;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(file_p->drv->write_cb == NULL) return LV_FS_RES_NOT_IMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
LV_PROFILER_BEGIN;
|
LV_PROFILER_BEGIN;
|
||||||
|
|
||||||
lv_fs_res_t res = LV_FS_RES_OK;
|
lv_fs_res_t res;
|
||||||
|
|
||||||
/*Need to do FS seek before writing data to FS*/
|
|
||||||
if(file_p->drv->cache_size) {
|
|
||||||
res = file_p->drv->seek_cb(file_p->drv, file_p->file_d, file_p->cache->file_position, LV_FS_SEEK_SET);
|
|
||||||
if(res != LV_FS_RES_OK) {
|
|
||||||
LV_PROFILER_END;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t bw_tmp = 0;
|
uint32_t bw_tmp = 0;
|
||||||
res = file_p->drv->write_cb(file_p->drv, file_p->file_d, buf, btw, &bw_tmp);
|
if(file_p->drv->cache_size) {
|
||||||
|
res = lv_fs_write_cached(file_p, buf, btw, &bw_tmp);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
res = file_p->drv->write_cb(file_p->drv, file_p->file_d, buf, btw, &bw_tmp);
|
||||||
|
}
|
||||||
if(bw != NULL) *bw = bw_tmp;
|
if(bw != NULL) *bw = bw_tmp;
|
||||||
|
|
||||||
if(file_p->drv->cache_size && res == LV_FS_RES_OK)
|
|
||||||
file_p->cache->file_position += bw_tmp;
|
|
||||||
|
|
||||||
LV_PROFILER_END;
|
LV_PROFILER_END;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
@@ -328,49 +243,18 @@ lv_fs_res_t lv_fs_seek(lv_fs_file_t * file_p, uint32_t pos, lv_fs_whence_t whenc
|
|||||||
return LV_FS_RES_INV_PARAM;
|
return LV_FS_RES_INV_PARAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(file_p->drv->seek_cb == NULL) {
|
if(file_p->drv->cache_size) {
|
||||||
return LV_FS_RES_NOT_IMP;
|
if(file_p->drv->seek_cb == NULL || file_p->drv->tell_cb == NULL) return LV_FS_RES_NOT_IMP;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(file_p->drv->seek_cb == NULL) return LV_FS_RES_NOT_IMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
LV_PROFILER_BEGIN;
|
LV_PROFILER_BEGIN;
|
||||||
|
|
||||||
lv_fs_res_t res = LV_FS_RES_OK;
|
lv_fs_res_t res;
|
||||||
if(file_p->drv->cache_size) {
|
if(file_p->drv->cache_size) {
|
||||||
switch(whence) {
|
res = lv_fs_seek_cached(file_p, pos, whence);
|
||||||
case LV_FS_SEEK_SET: {
|
|
||||||
file_p->cache->file_position = pos;
|
|
||||||
|
|
||||||
/*FS seek if new position is outside cache buffer*/
|
|
||||||
if(file_p->cache->file_position < file_p->cache->start || file_p->cache->file_position > file_p->cache->end) {
|
|
||||||
res = file_p->drv->seek_cb(file_p->drv, file_p->file_d, file_p->cache->file_position, LV_FS_SEEK_SET);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case LV_FS_SEEK_CUR: {
|
|
||||||
file_p->cache->file_position += pos;
|
|
||||||
|
|
||||||
/*FS seek if new position is outside cache buffer*/
|
|
||||||
if(file_p->cache->file_position < file_p->cache->start || file_p->cache->file_position > file_p->cache->end) {
|
|
||||||
res = file_p->drv->seek_cb(file_p->drv, file_p->file_d, file_p->cache->file_position, LV_FS_SEEK_SET);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case LV_FS_SEEK_END: {
|
|
||||||
/*Because we don't know the file size, we do a little trick: do a FS seek, then get the new file position from FS*/
|
|
||||||
res = file_p->drv->seek_cb(file_p->drv, file_p->file_d, pos, whence);
|
|
||||||
if(res == LV_FS_RES_OK) {
|
|
||||||
uint32_t tmp_position;
|
|
||||||
res = file_p->drv->tell_cb(file_p->drv, file_p->file_d, &tmp_position);
|
|
||||||
|
|
||||||
if(res == LV_FS_RES_OK) {
|
|
||||||
file_p->cache->file_position = tmp_position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
res = file_p->drv->seek_cb(file_p->drv, file_p->file_d, pos, whence);
|
res = file_p->drv->seek_cb(file_p->drv, file_p->file_d, pos, whence);
|
||||||
@@ -388,7 +272,7 @@ lv_fs_res_t lv_fs_tell(lv_fs_file_t * file_p, uint32_t * pos)
|
|||||||
return LV_FS_RES_INV_PARAM;
|
return LV_FS_RES_INV_PARAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(file_p->drv->tell_cb == NULL) {
|
if(file_p->drv->cache_size == 0 && file_p->drv->tell_cb == NULL) {
|
||||||
*pos = 0;
|
*pos = 0;
|
||||||
return LV_FS_RES_NOT_IMP;
|
return LV_FS_RES_NOT_IMP;
|
||||||
}
|
}
|
||||||
@@ -621,3 +505,162 @@ static const char * lv_fs_get_real_path(const char * path)
|
|||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static lv_fs_res_t lv_fs_read_cached(lv_fs_file_t * file_p, void * buf, uint32_t btr, uint32_t * br)
|
||||||
|
{
|
||||||
|
lv_fs_res_t res = LV_FS_RES_OK;
|
||||||
|
uint32_t file_position = file_p->cache->file_position;
|
||||||
|
uint32_t start = file_p->cache->start;
|
||||||
|
uint32_t end = file_p->cache->end;
|
||||||
|
char * buffer = file_p->cache->buffer;
|
||||||
|
uint32_t buffer_size = file_p->drv->cache_size;
|
||||||
|
|
||||||
|
if(start <= file_position && file_position <= end) {
|
||||||
|
/* Data can be read from cache buffer */
|
||||||
|
uint32_t buffer_remaining_length = (uint32_t)end - file_position + 1;
|
||||||
|
uint32_t buffer_offset = (end - start) - buffer_remaining_length + 1;
|
||||||
|
|
||||||
|
/* Do not allow reading beyond the actual memory block for memory-mapped files */
|
||||||
|
if(file_p->drv->cache_size == LV_FS_CACHE_FROM_BUFFER) {
|
||||||
|
if(btr > buffer_remaining_length)
|
||||||
|
btr = buffer_remaining_length - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(btr <= buffer_remaining_length) {
|
||||||
|
/*Data is in cache buffer, and buffer end not reached, no need to read from FS*/
|
||||||
|
lv_memcpy(buf, buffer + buffer_offset, btr);
|
||||||
|
*br = btr;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/*First part of data is in cache buffer, but we need to read rest of data from FS*/
|
||||||
|
lv_memcpy(buf, buffer + buffer_offset, buffer_remaining_length);
|
||||||
|
|
||||||
|
file_p->drv->seek_cb(file_p->drv, file_p->file_d, file_p->cache->end + 1,
|
||||||
|
LV_FS_SEEK_SET);
|
||||||
|
|
||||||
|
uint32_t bytes_read_to_buffer = 0;
|
||||||
|
if(btr - buffer_remaining_length > buffer_size) {
|
||||||
|
/*If remaining data chuck is bigger than buffer size, then do not use cache, instead read it directly from FS*/
|
||||||
|
res = file_p->drv->read_cb(file_p->drv, file_p->file_d, (char *)buf + buffer_remaining_length,
|
||||||
|
btr - buffer_remaining_length, &bytes_read_to_buffer);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/*If remaining data chunk is smaller than buffer size, then read into cache buffer*/
|
||||||
|
res = file_p->drv->read_cb(file_p->drv, file_p->file_d, buffer, buffer_size, &bytes_read_to_buffer);
|
||||||
|
file_p->cache->start = file_p->cache->end + 1;
|
||||||
|
file_p->cache->end = file_p->cache->start + bytes_read_to_buffer - 1;
|
||||||
|
|
||||||
|
uint16_t data_chunk_remaining = LV_MIN(btr - buffer_remaining_length, bytes_read_to_buffer);
|
||||||
|
lv_memcpy((char *)buf + buffer_remaining_length, buffer, data_chunk_remaining);
|
||||||
|
}
|
||||||
|
*br = LV_MIN(buffer_remaining_length + bytes_read_to_buffer, btr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
file_p->drv->seek_cb(file_p->drv, file_p->file_d, file_p->cache->file_position,
|
||||||
|
LV_FS_SEEK_SET);
|
||||||
|
|
||||||
|
/*Data is not in cache buffer*/
|
||||||
|
if(btr > buffer_size) {
|
||||||
|
/*If bigger data is requested, then do not use cache, instead read it directly*/
|
||||||
|
res = file_p->drv->read_cb(file_p->drv, file_p->file_d, (void *)buf, btr, br);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/*If small data is requested, then read from FS into cache buffer*/
|
||||||
|
if(buffer == NULL) {
|
||||||
|
file_p->cache->buffer = lv_malloc(buffer_size);
|
||||||
|
LV_ASSERT_MALLOC(file_p->cache->buffer);
|
||||||
|
buffer = file_p->cache->buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t bytes_read_to_buffer = 0;
|
||||||
|
res = file_p->drv->read_cb(file_p->drv, file_p->file_d, (void *)buffer, buffer_size, &bytes_read_to_buffer);
|
||||||
|
file_p->cache->start = file_position;
|
||||||
|
file_p->cache->end = file_p->cache->start + bytes_read_to_buffer - 1;
|
||||||
|
|
||||||
|
*br = LV_MIN(btr, bytes_read_to_buffer);
|
||||||
|
lv_memcpy(buf, buffer, *br);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(res == LV_FS_RES_OK) {
|
||||||
|
file_p->cache->file_position += *br;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static lv_fs_res_t lv_fs_write_cached(lv_fs_file_t * file_p, const void * buf, uint32_t btw, uint32_t * bw)
|
||||||
|
{
|
||||||
|
lv_fs_res_t res = LV_FS_RES_OK;
|
||||||
|
|
||||||
|
/*Need to do FS seek before writing data to FS*/
|
||||||
|
res = file_p->drv->seek_cb(file_p->drv, file_p->file_d, file_p->cache->file_position, LV_FS_SEEK_SET);
|
||||||
|
if(res != LV_FS_RES_OK) return res;
|
||||||
|
|
||||||
|
res = file_p->drv->write_cb(file_p->drv, file_p->file_d, buf, btw, bw);
|
||||||
|
if(res != LV_FS_RES_OK) return res;
|
||||||
|
|
||||||
|
if(file_p->cache->end >= file_p->cache->start) {
|
||||||
|
uint32_t start_position = file_p->cache->file_position;
|
||||||
|
uint32_t end_position = file_p->cache->file_position + *bw - 1;
|
||||||
|
char * cache_buffer = file_p->cache->buffer;
|
||||||
|
const char * write_buffer = buf;
|
||||||
|
|
||||||
|
if(start_position <= file_p->cache->start && end_position >= file_p->cache->end) {
|
||||||
|
lv_memcpy(cache_buffer,
|
||||||
|
write_buffer + (file_p->cache->start - start_position),
|
||||||
|
file_p->cache->end + 1 - file_p->cache->start);
|
||||||
|
}
|
||||||
|
else if(start_position >= file_p->cache->start && end_position <= file_p->cache->end) {
|
||||||
|
lv_memcpy(cache_buffer + (start_position - file_p->cache->start),
|
||||||
|
write_buffer,
|
||||||
|
end_position + 1 - start_position);
|
||||||
|
}
|
||||||
|
else if(end_position >= file_p->cache->start && end_position <= file_p->cache->end) {
|
||||||
|
lv_memcpy(cache_buffer,
|
||||||
|
write_buffer + (file_p->cache->start - start_position),
|
||||||
|
end_position + 1 - file_p->cache->start);
|
||||||
|
}
|
||||||
|
else if(start_position >= file_p->cache->start && start_position <= file_p->cache->end) {
|
||||||
|
lv_memcpy(cache_buffer + (start_position - file_p->cache->start),
|
||||||
|
write_buffer,
|
||||||
|
file_p->cache->end + 1 - start_position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file_p->cache->file_position += *bw;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static lv_fs_res_t lv_fs_seek_cached(lv_fs_file_t * file_p, uint32_t pos, lv_fs_whence_t whence)
|
||||||
|
{
|
||||||
|
lv_fs_res_t res = LV_FS_RES_OK;
|
||||||
|
switch(whence) {
|
||||||
|
case LV_FS_SEEK_SET: {
|
||||||
|
file_p->cache->file_position = pos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LV_FS_SEEK_CUR: {
|
||||||
|
file_p->cache->file_position += pos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LV_FS_SEEK_END: {
|
||||||
|
/*Because we don't know the file size, we do a little trick: do a FS seek, then get the new file position from FS*/
|
||||||
|
res = file_p->drv->seek_cb(file_p->drv, file_p->file_d, pos, whence);
|
||||||
|
if(res == LV_FS_RES_OK) {
|
||||||
|
uint32_t tmp_position;
|
||||||
|
res = file_p->drv->tell_cb(file_p->drv, file_p->file_d, &tmp_position);
|
||||||
|
|
||||||
|
if(res == LV_FS_RES_OK) {
|
||||||
|
file_p->cache->file_position = tmp_position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|||||||
@@ -178,4 +178,99 @@ static void read_random_drv(char drv_letter, uint32_t cache_size)
|
|||||||
drv->cache_size = original_cache_size;
|
drv->cache_size = original_cache_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_write_read_random(void)
|
||||||
|
{
|
||||||
|
lv_fs_drv_t * drv = lv_fs_get_drv('A');
|
||||||
|
uint32_t original_cache_size = drv->cache_size;
|
||||||
|
drv->cache_size = 7;
|
||||||
|
|
||||||
|
/* create the file and reopen for read+write. stdio "rb+" mode requires the file to exist */
|
||||||
|
lv_fs_res_t res;
|
||||||
|
lv_fs_file_t f;
|
||||||
|
res = lv_fs_open(&f, "A:fs_write_read_random.bin", LV_FS_MODE_WR);
|
||||||
|
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
|
||||||
|
res = lv_fs_close(&f);
|
||||||
|
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
|
||||||
|
res = lv_fs_open(&f, "A:fs_write_read_random.bin", LV_FS_MODE_WR | LV_FS_MODE_RD);
|
||||||
|
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
|
||||||
|
|
||||||
|
uint8_t buf1000[1000];
|
||||||
|
for(uint32_t i = 0; i < 1000; i++) buf1000[i] = i;
|
||||||
|
res = lv_fs_write(&f, buf1000, 1000, NULL);
|
||||||
|
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {{{action, amount}, ... x20 actions per combo}, ... x100 combos}
|
||||||
|
* actions are read (0), write (1), seek (2)
|
||||||
|
* read and write amount ranges from 1 to 20. seek amount ranges from -20 to 20.
|
||||||
|
* seeks occur as frequently as reads+writes combined.
|
||||||
|
*/
|
||||||
|
// *INDENT-OFF*
|
||||||
|
static const int8_t actions[100][20][2] = {
|
||||||
|
{{2, -20}, {2, 17}, {0, 20}, {2, 19}, {1, 18}, {1, 4}, {1, 13}, {2, -7}, {1, 6}, {1, 19}, {2, 3}, {1, 12}, {2, 12}, {2, -2}, {2, -20}, {2, -17}, {1, 15}, {2, -17}, {0, 18}, {2, 14}}, {{2, 19}, {2, 17}, {2, -12}, {2, -5}, {2, -1}, {2, -17}, {1, 4}, {2, 19}, {2, 3}, {2, 1}, {2, 10}, {2, 18}, {0, 10}, {2, 8}, {2, 17}, {2, 20}, {0, 5}, {0, 14}, {0, 6}, {1, 8}}, {{0, 1}, {2, -20}, {2, -12}, {1, 9}, {0, 9}, {2, 19}, {1, 8}, {0, 13}, {0, 5}, {2, -7}, {2, -14}, {0, 8}, {2, 13}, {1, 5}, {0, 3}, {0, 16}, {2, 19}, {0, 4}, {1, 6}, {2, -4}}, {{0, 1}, {2, 12}, {1, 7}, {1, 17}, {1, 19}, {0, 8}, {1, 1}, {2, 9}, {2, -14}, {2, 14}, {2, -17}, {2, 11}, {1, 4}, {2, 19}, {2, -18}, {1, 12}, {2, -14}, {0, 9}, {1, 7}, {2, 17}}, {{2, -6}, {0, 13}, {1, 15}, {1, 8}, {2, -1}, {2, 15}, {2, 3}, {2, -16}, {2, -11}, {2, 14}, {2, -19}, {2, 6}, {1, 10}, {1, 6}, {1, 12}, {2, 12}, {0, 10}, {2, 10}, {2, -4}, {2, 5}}, {{2, -6}, {1, 2}, {1, 11}, {1, 19}, {2, 2}, {2, 20}, {2, -19}, {2, -7}, {0, 13}, {2, 4}, {1, 6}, {0, 9}, {0, 6}, {2, -1}, {2, -5}, {2, 14}, {2, 15}, {0, 4}, {0, 6}, {0, 10}}, {{1, 17}, {1, 17}, {0, 15}, {0, 3}, {1, 8}, {2, -9}, {1, 13}, {0, 20}, {0, 3}, {1, 17}, {2, -8}, {2, -1}, {1, 13}, {0, 13}, {0, 8}, {1, 1}, {2, -4}, {2, 13}, {2, 17}, {2, -14}}, {{1, 17}, {1, 13}, {1, 17}, {1, 5}, {1, 3}, {0, 20}, {2, 12}, {0, 13}, {2, 5}, {2, -10}, {2, 10}, {0, 6}, {2, 18}, {0, 17}, {2, 2}, {1, 5}, {2, 16}, {2, -10}, {0, 2}, {2, -9}}, {{2, 7}, {2, -2}, {1, 14}, {0, 15}, {1, 2}, {2, 6}, {2, 11}, {1, 2}, {0, 12}, {2, 9}, {0, 17}, {0, 15}, {2, -19}, {0, 11}, {2, 3}, {2, 15}, {2, 19}, {2, -16}, {1, 6}, {1, 15}}, {{2, 12}, {1, 2}, {2, -4}, {2, -20}, {0, 18}, {2, -16}, {1, 15}, {2, -9}, {2, -7}, {1, 1}, {0, 7}, {0, 18}, {1, 18}, {0, 2}, {2, 17}, {1, 2}, {1, 8}, {1, 18}, {2, -7}, {0, 2}},
|
||||||
|
{{2, 19}, {2, 17}, {2, -7}, {0, 17}, {0, 18}, {1, 4}, {1, 1}, {0, 3}, {2, 4}, {2, -4}, {1, 20}, {0, 1}, {2, 20}, {0, 6}, {2, 10}, {0, 19}, {2, -1}, {0, 7}, {0, 16}, {1, 13}}, {{2, 10}, {2, 13}, {2, 15}, {2, 3}, {2, 12}, {0, 14}, {2, 6}, {2, 14}, {2, -13}, {2, 18}, {0, 19}, {2, -8}, {2, -9}, {0, 12}, {2, -20}, {2, -6}, {2, 15}, {2, 18}, {1, 18}, {1, 10}}, {{0, 15}, {2, -6}, {2, 17}, {1, 7}, {0, 9}, {0, 11}, {0, 12}, {0, 20}, {2, -1}, {2, -8}, {0, 13}, {2, 19}, {1, 3}, {0, 18}, {1, 13}, {2, 12}, {2, 13}, {1, 5}, {2, -14}, {2, 18}}, {{0, 6}, {1, 4}, {1, 6}, {0, 2}, {2, 8}, {1, 9}, {2, 20}, {0, 9}, {2, -1}, {2, 5}, {0, 18}, {2, 8}, {2, 12}, {2, -14}, {0, 18}, {1, 1}, {2, -15}, {2, 14}, {2, -11}, {2, -2}}, {{1, 4}, {2, 6}, {2, 18}, {1, 19}, {0, 18}, {0, 19}, {0, 14}, {0, 12}, {2, 3}, {0, 19}, {2, -20}, {0, 8}, {2, -15}, {2, -15}, {0, 8}, {1, 17}, {2, 2}, {1, 14}, {0, 11}, {0, 13}}, {{2, -10}, {2, -8}, {1, 18}, {1, 11}, {1, 5}, {0, 2}, {2, -19}, {2, -9}, {1, 5}, {2, -1}, {2, 2}, {1, 5}, {0, 9}, {0, 17}, {2, 2}, {0, 10}, {1, 12}, {1, 10}, {0, 8}, {2, -13}}, {{0, 13}, {1, 5}, {2, -1}, {2, -16}, {2, 2}, {0, 6}, {2, -11}, {0, 5}, {2, 5}, {2, -6}, {2, -6}, {1, 19}, {0, 8}, {2, -16}, {2, 14}, {0, 11}, {0, 14}, {0, 18}, {0, 14}, {2, 1}}, {{2, 3}, {2, -2}, {0, 10}, {1, 1}, {0, 10}, {2, -15}, {2, 19}, {2, 2}, {1, 15}, {1, 10}, {2, -18}, {0, 20}, {0, 10}, {2, 3}, {1, 13}, {0, 8}, {0, 16}, {0, 14}, {2, 13}, {2, -7}}, {{0, 4}, {1, 7}, {0, 2}, {0, 15}, {0, 20}, {1, 9}, {0, 14}, {2, 18}, {0, 1}, {0, 4}, {2, -17}, {1, 10}, {1, 15}, {0, 2}, {2, -6}, {2, 4}, {2, 4}, {2, 17}, {2, -13}, {1, 20}}, {{1, 8}, {0, 20}, {2, 4}, {1, 6}, {2, -19}, {1, 4}, {0, 5}, {1, 8}, {1, 17}, {2, -4}, {2, 14}, {1, 10}, {2, 7}, {1, 18}, {2, 17}, {1, 6}, {0, 20}, {2, 1}, {2, -12}, {2, 18}},
|
||||||
|
{{2, -7}, {1, 12}, {2, 4}, {2, 14}, {0, 13}, {1, 17}, {2, -2}, {2, -9}, {2, -13}, {1, 4}, {2, 4}, {1, 5}, {0, 15}, {2, -11}, {2, 3}, {2, 1}, {2, -11}, {2, 11}, {2, -11}, {0, 4}}, {{1, 7}, {2, 20}, {0, 6}, {0, 9}, {1, 2}, {0, 11}, {2, 4}, {2, -19}, {0, 17}, {2, -7}, {0, 20}, {0, 10}, {1, 11}, {1, 20}, {1, 6}, {2, 14}, {0, 11}, {0, 19}, {2, 4}, {1, 8}}, {{0, 9}, {2, -3}, {1, 17}, {2, 14}, {2, 3}, {1, 19}, {2, 17}, {0, 18}, {2, 16}, {0, 9}, {2, -15}, {1, 14}, {2, 11}, {2, -7}, {0, 17}, {2, 12}, {2, 6}, {2, 9}, {0, 7}, {1, 3}}, {{0, 1}, {2, 13}, {1, 19}, {0, 19}, {2, 6}, {2, -14}, {2, 8}, {2, -18}, {2, 4}, {2, -7}, {0, 12}, {2, 15}, {1, 3}, {2, -19}, {2, 15}, {2, -2}, {1, 19}, {1, 18}, {1, 19}, {0, 16}}, {{2, 7}, {2, 14}, {2, 14}, {2, -19}, {0, 1}, {2, -5}, {0, 17}, {2, 2}, {2, 15}, {1, 13}, {0, 20}, {0, 12}, {2, 20}, {0, 9}, {2, -8}, {0, 14}, {1, 19}, {2, -15}, {2, 17}, {2, -12}}, {{0, 16}, {2, -7}, {2, -4}, {1, 11}, {1, 17}, {2, -14}, {0, 16}, {2, 6}, {1, 19}, {2, 17}, {2, 10}, {2, -12}, {2, -17}, {1, 4}, {2, -14}, {2, -7}, {2, -17}, {2, -1}, {2, -16}, {1, 8}}, {{0, 5}, {0, 15}, {2, 4}, {2, 20}, {2, 7}, {2, 3}, {2, 17}, {0, 8}, {0, 18}, {2, -18}, {1, 1}, {0, 15}, {2, -4}, {0, 13}, {1, 11}, {0, 4}, {2, 11}, {1, 11}, {1, 10}, {2, -9}}, {{2, -5}, {2, -16}, {1, 2}, {1, 17}, {2, 9}, {2, -2}, {0, 7}, {0, 14}, {2, -10}, {0, 6}, {1, 14}, {1, 15}, {2, 12}, {2, 11}, {2, -9}, {2, -10}, {2, -14}, {2, 9}, {0, 13}, {2, 5}}, {{2, 8}, {2, -16}, {2, 20}, {1, 8}, {1, 2}, {2, -5}, {2, -20}, {1, 2}, {1, 4}, {1, 9}, {0, 19}, {2, -18}, {0, 6}, {0, 13}, {1, 5}, {2, 2}, {0, 4}, {1, 19}, {2, 15}, {1, 12}}, {{2, -8}, {0, 16}, {1, 10}, {2, 5}, {2, -16}, {0, 3}, {2, 5}, {0, 6}, {1, 17}, {2, 1}, {2, 13}, {0, 3}, {0, 6}, {0, 6}, {0, 19}, {1, 13}, {2, 19}, {2, 5}, {1, 16}, {2, 5}},
|
||||||
|
{{2, -19}, {2, -1}, {0, 19}, {2, -3}, {2, 13}, {2, -12}, {0, 2}, {2, -20}, {2, 15}, {2, -9}, {2, -2}, {2, 13}, {2, -6}, {0, 2}, {1, 6}, {2, -1}, {0, 12}, {0, 20}, {2, -14}, {1, 2}}, {{1, 9}, {2, -14}, {2, -2}, {2, -13}, {0, 3}, {1, 6}, {2, 20}, {2, 11}, {2, 17}, {2, 5}, {0, 5}, {1, 1}, {2, -9}, {1, 8}, {2, -2}, {0, 18}, {2, -8}, {1, 11}, {2, 6}, {1, 7}}, {{2, 17}, {2, 14}, {2, 16}, {1, 20}, {2, -1}, {2, -7}, {1, 3}, {1, 14}, {0, 1}, {0, 18}, {2, -14}, {0, 10}, {0, 18}, {2, 19}, {1, 13}, {2, -16}, {1, 17}, {1, 1}, {2, -13}, {0, 13}}, {{2, -2}, {0, 14}, {0, 12}, {2, -8}, {1, 16}, {0, 18}, {2, 5}, {2, 13}, {1, 14}, {2, -4}, {2, 16}, {2, -16}, {2, 16}, {1, 18}, {2, 15}, {2, 4}, {2, -5}, {1, 7}, {2, -20}, {2, -9}}, {{2, 18}, {2, 2}, {2, 5}, {0, 4}, {2, 17}, {2, -15}, {2, 8}, {2, -11}, {1, 8}, {2, -6}, {2, -13}, {0, 5}, {0, 18}, {0, 15}, {2, -8}, {2, -15}, {1, 1}, {2, 4}, {2, -9}, {2, 14}}, {{2, -1}, {2, 1}, {1, 12}, {0, 9}, {2, -11}, {1, 4}, {1, 11}, {1, 5}, {0, 12}, {2, -7}, {1, 1}, {0, 6}, {0, 15}, {2, -10}, {2, -18}, {2, -12}, {0, 3}, {2, 2}, {2, -17}, {2, 1}}, {{2, -5}, {2, 18}, {1, 2}, {2, 14}, {2, 20}, {0, 13}, {0, 11}, {0, 6}, {2, -7}, {2, 13}, {1, 13}, {2, -1}, {1, 12}, {2, -9}, {2, 3}, {1, 6}, {2, -16}, {0, 6}, {0, 9}, {2, -14}}, {{1, 6}, {2, 7}, {2, -13}, {0, 5}, {1, 4}, {0, 15}, {2, 18}, {2, -4}, {2, 16}, {1, 1}, {2, 17}, {0, 2}, {1, 12}, {0, 17}, {1, 18}, {1, 5}, {1, 8}, {1, 4}, {2, -9}, {1, 9}}, {{0, 20}, {1, 10}, {2, 20}, {2, 13}, {0, 18}, {0, 10}, {1, 3}, {0, 8}, {2, -16}, {2, -16}, {2, -2}, {0, 20}, {2, -19}, {2, -11}, {1, 17}, {1, 18}, {1, 5}, {0, 6}, {2, -9}, {1, 8}}, {{0, 18}, {0, 19}, {2, 16}, {2, -14}, {1, 7}, {1, 9}, {0, 16}, {0, 16}, {1, 17}, {0, 14}, {2, -16}, {1, 6}, {1, 11}, {2, 7}, {1, 19}, {1, 11}, {2, -14}, {0, 7}, {1, 12}, {0, 2}},
|
||||||
|
{{2, 3}, {2, -15}, {0, 13}, {2, -3}, {0, 16}, {1, 18}, {0, 11}, {0, 16}, {1, 13}, {2, -18}, {1, 14}, {2, 11}, {0, 11}, {2, -14}, {2, -19}, {0, 2}, {2, -7}, {0, 5}, {0, 20}, {2, -7}}, {{2, 9}, {2, 5}, {2, 7}, {0, 15}, {2, 4}, {0, 5}, {2, -17}, {2, 16}, {2, 8}, {0, 11}, {0, 1}, {1, 8}, {2, -5}, {1, 1}, {2, 4}, {2, -4}, {2, -17}, {0, 5}, {1, 10}, {0, 5}}, {{0, 11}, {1, 16}, {1, 18}, {0, 5}, {2, -13}, {0, 5}, {1, 13}, {1, 10}, {1, 11}, {0, 5}, {1, 9}, {1, 4}, {1, 19}, {2, 1}, {1, 19}, {1, 18}, {1, 8}, {2, 2}, {2, -5}, {1, 4}}, {{0, 12}, {1, 16}, {2, -1}, {1, 10}, {1, 10}, {2, -19}, {2, -20}, {1, 17}, {1, 19}, {1, 4}, {2, 12}, {0, 1}, {2, -15}, {2, -1}, {2, -10}, {2, -19}, {0, 18}, {0, 6}, {2, 18}, {0, 18}}, {{1, 10}, {0, 13}, {2, 3}, {0, 20}, {0, 19}, {0, 5}, {0, 9}, {0, 5}, {0, 20}, {0, 9}, {2, 16}, {1, 11}, {0, 12}, {2, -17}, {0, 20}, {0, 14}, {1, 17}, {2, 15}, {1, 7}, {2, -1}}, {{2, -10}, {2, 1}, {0, 2}, {2, -11}, {2, -17}, {2, -10}, {1, 9}, {2, -6}, {2, -19}, {1, 14}, {0, 4}, {1, 6}, {2, -9}, {2, 3}, {1, 2}, {2, 19}, {1, 15}, {0, 7}, {0, 4}, {2, 2}}, {{1, 12}, {2, -8}, {2, 13}, {2, -19}, {0, 17}, {0, 20}, {1, 3}, {1, 15}, {1, 20}, {2, 17}, {0, 12}, {2, -2}, {1, 8}, {2, -12}, {0, 11}, {2, 17}, {1, 14}, {1, 13}, {2, 2}, {2, 3}}, {{0, 13}, {1, 13}, {2, -4}, {1, 17}, {1, 1}, {1, 5}, {0, 10}, {1, 12}, {0, 9}, {2, -16}, {0, 13}, {2, 19}, {2, 9}, {1, 18}, {2, -1}, {2, -14}, {0, 5}, {1, 2}, {0, 20}, {2, -19}}, {{1, 7}, {2, 19}, {2, 11}, {2, -16}, {1, 19}, {2, -14}, {0, 7}, {1, 10}, {2, 8}, {0, 12}, {1, 12}, {2, -11}, {2, 6}, {2, -16}, {2, 15}, {1, 20}, {2, -12}, {1, 7}, {2, -16}, {2, 7}}, {{0, 8}, {2, 19}, {1, 12}, {2, -12}, {2, 4}, {1, 10}, {1, 13}, {2, 2}, {2, -14}, {2, -10}, {2, 18}, {1, 16}, {0, 10}, {2, 19}, {2, -1}, {1, 17}, {2, -1}, {0, 14}, {1, 11}, {0, 18}},
|
||||||
|
{{2, 2}, {2, -2}, {2, 12}, {0, 7}, {0, 14}, {2, -15}, {2, 13}, {2, -3}, {0, 1}, {2, -2}, {1, 2}, {2, 4}, {2, 4}, {2, 16}, {1, 4}, {2, 1}, {1, 9}, {1, 6}, {1, 12}, {1, 11}}, {{2, -10}, {1, 16}, {1, 12}, {0, 18}, {2, -13}, {0, 19}, {2, 15}, {0, 11}, {0, 2}, {0, 4}, {0, 7}, {0, 10}, {2, -10}, {2, 11}, {0, 13}, {0, 10}, {2, -14}, {2, -18}, {0, 7}, {2, 16}}, {{2, -19}, {2, -5}, {1, 9}, {0, 15}, {2, 4}, {2, -14}, {1, 13}, {2, 10}, {2, -7}, {2, 14}, {2, 8}, {2, 9}, {0, 14}, {2, -4}, {1, 2}, {1, 19}, {0, 18}, {2, 18}, {1, 6}, {2, -6}}, {{2, -15}, {2, 1}, {0, 8}, {1, 5}, {2, -11}, {2, -3}, {0, 19}, {0, 4}, {1, 19}, {1, 2}, {1, 2}, {0, 3}, {0, 16}, {2, -3}, {2, 18}, {1, 20}, {2, -16}, {2, -2}, {2, -17}, {1, 15}}, {{1, 19}, {2, -11}, {1, 13}, {0, 14}, {1, 18}, {2, 11}, {2, 13}, {2, -14}, {1, 5}, {2, -6}, {0, 4}, {2, 19}, {0, 12}, {1, 4}, {2, -6}, {2, 8}, {2, 9}, {2, -10}, {2, -3}, {2, -19}}, {{2, 7}, {2, -9}, {2, 5}, {2, 12}, {2, -20}, {2, -3}, {2, -12}, {2, 5}, {0, 6}, {2, 15}, {1, 8}, {1, 9}, {2, 18}, {2, -14}, {2, 10}, {1, 5}, {1, 2}, {0, 14}, {2, 14}, {0, 19}}, {{2, 12}, {0, 9}, {0, 14}, {1, 4}, {2, 4}, {2, -8}, {2, 4}, {0, 13}, {1, 10}, {2, 18}, {2, 13}, {2, 15}, {1, 18}, {2, 7}, {2, -18}, {2, 18}, {1, 9}, {2, -9}, {0, 16}, {2, -14}}, {{0, 16}, {2, 9}, {2, 7}, {1, 6}, {0, 14}, {2, -18}, {1, 14}, {1, 2}, {0, 10}, {1, 6}, {0, 10}, {2, 2}, {1, 1}, {0, 19}, {1, 6}, {2, -3}, {2, 3}, {2, 12}, {2, 5}, {1, 18}}, {{2, -17}, {0, 17}, {0, 5}, {2, 18}, {2, 8}, {0, 14}, {0, 10}, {1, 20}, {2, 7}, {1, 10}, {1, 14}, {1, 10}, {0, 11}, {1, 15}, {0, 16}, {1, 14}, {0, 3}, {2, 16}, {2, -5}, {2, -4}}, {{1, 15}, {2, -9}, {0, 11}, {0, 16}, {2, 1}, {0, 12}, {0, 7}, {0, 16}, {2, 14}, {0, 3}, {1, 11}, {2, 4}, {1, 6}, {2, -1}, {1, 20}, {1, 13}, {0, 2}, {2, -12}, {0, 9}, {2, 8}},
|
||||||
|
{{0, 1}, {2, -4}, {0, 19}, {2, -15}, {2, -16}, {2, -10}, {2, 7}, {0, 10}, {2, -6}, {2, -8}, {2, -3}, {2, 18}, {1, 20}, {2, 10}, {1, 18}, {2, -3}, {0, 7}, {2, 3}, {2, 14}, {2, 15}}, {{1, 17}, {0, 7}, {1, 17}, {2, -8}, {2, -12}, {2, -9}, {2, 15}, {0, 10}, {1, 10}, {2, -6}, {2, -20}, {1, 17}, {2, -9}, {1, 15}, {1, 3}, {1, 8}, {0, 1}, {1, 13}, {2, -5}, {0, 14}}, {{2, 8}, {0, 11}, {0, 12}, {2, 5}, {2, -4}, {2, -5}, {2, -2}, {0, 20}, {2, -4}, {1, 1}, {1, 2}, {0, 4}, {2, 14}, {1, 17}, {2, -13}, {1, 13}, {2, 12}, {2, 20}, {2, 14}, {2, -9}}, {{2, -20}, {2, 13}, {1, 20}, {2, 20}, {2, 9}, {0, 16}, {2, 1}, {0, 13}, {2, 17}, {2, 8}, {2, 13}, {2, -3}, {2, -1}, {2, -19}, {2, 1}, {1, 16}, {2, -16}, {0, 6}, {2, 2}, {1, 8}}, {{1, 4}, {1, 9}, {1, 8}, {2, -12}, {0, 4}, {1, 8}, {0, 9}, {2, -2}, {2, -19}, {2, 2}, {2, -1}, {0, 14}, {2, 4}, {2, -17}, {0, 1}, {2, 4}, {2, -20}, {2, 3}, {0, 7}, {1, 4}}, {{0, 6}, {2, -5}, {1, 13}, {2, 15}, {2, 11}, {0, 7}, {1, 17}, {2, 9}, {1, 14}, {2, -7}, {2, 12}, {2, -18}, {0, 19}, {2, -1}, {2, 14}, {2, 5}, {2, -16}, {1, 2}, {2, -2}, {0, 17}}, {{1, 11}, {2, 4}, {2, 7}, {1, 16}, {2, 14}, {0, 14}, {2, 16}, {1, 11}, {1, 10}, {2, -3}, {2, -10}, {1, 7}, {2, 9}, {0, 19}, {2, 1}, {0, 7}, {1, 11}, {0, 9}, {2, -16}, {1, 8}}, {{0, 10}, {0, 4}, {2, -8}, {2, 20}, {2, 16}, {2, 5}, {0, 16}, {1, 6}, {2, 2}, {2, 14}, {2, 11}, {1, 15}, {2, -10}, {2, -5}, {0, 4}, {0, 4}, {2, -13}, {2, 11}, {0, 13}, {0, 11}}, {{0, 6}, {1, 4}, {2, 15}, {2, 17}, {1, 1}, {2, -20}, {1, 18}, {0, 19}, {2, -12}, {2, 1}, {2, -15}, {2, -11}, {1, 19}, {0, 13}, {1, 2}, {0, 17}, {2, 14}, {0, 14}, {2, 12}, {0, 19}}, {{2, -16}, {1, 20}, {2, -14}, {1, 7}, {2, -13}, {2, 19}, {2, 20}, {2, -14}, {1, 17}, {2, 20}, {1, 2}, {2, -19}, {2, -17}, {2, 18}, {2, 6}, {1, 17}, {2, 7}, {0, 8}, {1, 20}, {2, 9}},
|
||||||
|
{{2, 20}, {2, 17}, {2, 15}, {1, 13}, {0, 7}, {2, -6}, {0, 8}, {2, -17}, {1, 15}, {2, -20}, {0, 17}, {2, -17}, {0, 12}, {1, 14}, {2, -8}, {2, -17}, {0, 12}, {2, -3}, {2, -13}, {0, 7}}, {{0, 3}, {2, 12}, {2, 4}, {0, 13}, {0, 15}, {1, 4}, {2, 7}, {2, -20}, {0, 4}, {0, 6}, {0, 12}, {2, 10}, {2, -13}, {0, 20}, {2, -11}, {0, 16}, {2, -13}, {2, -5}, {1, 14}, {0, 7}}, {{2, 16}, {1, 11}, {2, -1}, {0, 9}, {0, 19}, {2, 9}, {2, 6}, {1, 15}, {2, 2}, {2, 8}, {1, 3}, {2, 20}, {2, -18}, {2, -15}, {2, -20}, {0, 10}, {1, 9}, {2, 5}, {2, -17}, {2, 14}}, {{2, -15}, {2, -10}, {2, -18}, {1, 20}, {1, 4}, {0, 18}, {1, 10}, {2, 19}, {2, -9}, {2, 20}, {0, 1}, {0, 11}, {2, -18}, {2, 5}, {1, 15}, {0, 10}, {2, -14}, {2, 6}, {0, 17}, {0, 3}}, {{1, 18}, {1, 5}, {0, 11}, {2, 11}, {0, 13}, {1, 5}, {0, 19}, {2, 20}, {1, 10}, {2, 19}, {0, 13}, {0, 7}, {2, 1}, {2, 14}, {1, 19}, {0, 9}, {1, 17}, {2, 18}, {0, 11}, {1, 9}}, {{2, -17}, {2, 10}, {2, -19}, {2, -18}, {2, 6}, {0, 9}, {0, 20}, {1, 7}, {2, -14}, {2, -11}, {0, 14}, {1, 1}, {0, 13}, {0, 2}, {2, 3}, {0, 2}, {2, 11}, {2, 10}, {2, 12}, {2, -4}}, {{2, 13}, {1, 14}, {2, 7}, {1, 12}, {2, -9}, {2, -4}, {2, -8}, {2, 13}, {0, 3}, {1, 20}, {2, 2}, {2, 5}, {0, 19}, {0, 10}, {2, 14}, {2, -15}, {1, 5}, {2, 18}, {2, -8}, {2, 6}}, {{1, 5}, {1, 9}, {1, 19}, {2, 19}, {0, 13}, {2, 2}, {2, 12}, {2, 17}, {2, -16}, {0, 12}, {0, 9}, {1, 17}, {0, 13}, {2, 7}, {1, 7}, {2, 14}, {0, 12}, {0, 7}, {2, -16}, {1, 7}}, {{2, 15}, {0, 9}, {1, 3}, {0, 4}, {2, -3}, {0, 12}, {2, 9}, {0, 6}, {1, 16}, {0, 10}, {2, -6}, {1, 20}, {2, 11}, {2, -3}, {2, -6}, {0, 15}, {0, 14}, {0, 11}, {2, -19}, {2, -14}}, {{0, 12}, {2, 8}, {1, 20}, {2, 18}, {2, 3}, {2, 2}, {2, 4}, {2, 7}, {2, -19}, {2, -9}, {2, 2}, {0, 19}, {0, 11}, {2, -9}, {0, 9}, {2, -14}, {1, 13}, {0, 2}, {0, 1}, {2, -19}},
|
||||||
|
{{2, -4}, {1, 6}, {0, 18}, {2, 4}, {1, 12}, {0, 17}, {2, 10}, {2, 13}, {2, 10}, {1, 10}, {2, -1}, {2, -11}, {2, -15}, {2, -5}, {2, -16}, {2, -12}, {0, 2}, {2, -10}, {2, 15}, {1, 2}}, {{2, -9}, {2, -14}, {1, 4}, {0, 5}, {2, -9}, {0, 7}, {0, 9}, {1, 16}, {1, 10}, {2, -14}, {0, 7}, {2, -18}, {0, 19}, {1, 3}, {1, 7}, {2, -19}, {2, 14}, {0, 9}, {1, 7}, {2, -5}}, {{2, 16}, {0, 13}, {2, 20}, {2, -9}, {0, 20}, {2, 20}, {0, 5}, {0, 6}, {1, 4}, {2, -11}, {0, 14}, {0, 9}, {2, 18}, {0, 14}, {0, 12}, {2, 16}, {2, 8}, {2, -13}, {1, 9}, {1, 3}}, {{2, 1}, {2, 13}, {2, -8}, {0, 9}, {2, -16}, {0, 12}, {0, 12}, {2, 19}, {2, -10}, {2, 1}, {2, -20}, {1, 10}, {0, 18}, {2, -15}, {2, -15}, {1, 15}, {0, 15}, {0, 1}, {2, -5}, {0, 19}}, {{2, 6}, {2, 15}, {2, -20}, {1, 20}, {2, 3}, {2, 7}, {1, 1}, {0, 5}, {0, 4}, {2, 8}, {1, 19}, {2, -3}, {2, 18}, {1, 10}, {0, 11}, {2, -19}, {0, 3}, {2, 5}, {1, 4}, {0, 6}}, {{0, 5}, {2, -17}, {1, 1}, {0, 1}, {2, -9}, {0, 8}, {2, -10}, {2, -4}, {0, 13}, {2, 19}, {0, 6}, {2, 9}, {2, 14}, {2, 11}, {0, 16}, {2, 13}, {1, 1}, {2, 9}, {2, 14}, {0, 18}}, {{0, 10}, {1, 12}, {1, 4}, {2, -12}, {2, 7}, {0, 5}, {1, 15}, {2, 7}, {2, 17}, {1, 18}, {2, 3}, {0, 12}, {1, 8}, {1, 13}, {2, -17}, {1, 20}, {0, 18}, {1, 12}, {1, 16}, {0, 16}}, {{2, -10}, {2, -1}, {2, 10}, {1, 4}, {2, -12}, {1, 19}, {2, 18}, {2, -15}, {2, -5}, {1, 11}, {2, -7}, {0, 20}, {2, -12}, {2, -12}, {1, 11}, {2, 8}, {2, 2}, {2, -2}, {2, -4}, {2, 19}}, {{2, 5}, {1, 15}, {1, 18}, {2, 20}, {1, 4}, {0, 7}, {2, -8}, {2, 1}, {2, -6}, {2, 8}, {1, 1}, {2, 12}, {1, 15}, {0, 16}, {1, 13}, {0, 1}, {0, 19}, {0, 20}, {2, -3}, {0, 12}}, {{1, 18}, {2, -4}, {1, 8}, {2, 19}, {1, 11}, {0, 12}, {0, 20}, {2, 4}, {1, 12}, {0, 17}, {2, 8}, {1, 5}, {2, -13}, {1, 3}, {1, 14}, {1, 4}, {0, 20}, {1, 18}, {0, 7}, {0, 17}},
|
||||||
|
{{2, 14}, {2, 10}, {2, -12}, {2, -15}, {1, 3}, {2, -17}, {1, 12}, {2, 9}, {2, -9}, {0, 11}, {2, 12}, {0, 16}, {0, 13}, {2, -17}, {2, 13}, {2, 11}, {1, 13}, {2, 16}, {0, 14}, {2, -8}}, {{0, 16}, {2, -10}, {1, 12}, {1, 12}, {2, 19}, {1, 5}, {2, 1}, {2, 19}, {0, 17}, {2, -19}, {2, 20}, {0, 7}, {1, 11}, {2, -3}, {2, -19}, {2, -20}, {2, 15}, {2, -18}, {2, 11}, {2, -19}}, {{2, -11}, {2, 10}, {0, 10}, {1, 15}, {1, 1}, {2, 7}, {2, -9}, {2, -3}, {0, 2}, {0, 20}, {0, 1}, {2, 14}, {2, -16}, {1, 14}, {0, 19}, {0, 11}, {2, 4}, {2, -9}, {2, -4}, {2, -10}}, {{2, 2}, {2, 17}, {1, 7}, {0, 18}, {0, 12}, {2, -15}, {2, 18}, {1, 7}, {1, 3}, {2, 14}, {1, 19}, {1, 6}, {2, -19}, {2, 9}, {0, 11}, {1, 13}, {2, -13}, {0, 19}, {1, 15}, {0, 14}}, {{2, 14}, {1, 3}, {2, 4}, {0, 14}, {1, 8}, {2, 7}, {0, 16}, {1, 11}, {2, 11}, {1, 13}, {1, 6}, {2, -10}, {0, 17}, {1, 18}, {1, 1}, {2, -11}, {1, 9}, {0, 16}, {2, 5}, {2, -6}}, {{0, 11}, {2, -2}, {1, 7}, {2, 8}, {2, 20}, {0, 7}, {0, 14}, {2, -17}, {2, 14}, {2, -14}, {2, -16}, {2, -12}, {2, -19}, {2, 10}, {2, -8}, {1, 1}, {1, 14}, {0, 5}, {0, 14}, {2, 14}}, {{2, 10}, {2, 18}, {1, 15}, {1, 15}, {2, 10}, {2, 14}, {1, 15}, {2, -16}, {2, -4}, {2, -1}, {2, -20}, {2, 2}, {1, 6}, {0, 2}, {2, -17}, {0, 13}, {2, -8}, {2, 18}, {2, 9}, {2, -12}}, {{2, -7}, {1, 16}, {2, 15}, {1, 14}, {1, 15}, {0, 8}, {1, 19}, {2, -13}, {2, 17}, {2, 4}, {2, -17}, {2, -2}, {0, 8}, {1, 11}, {2, 14}, {0, 13}, {2, -12}, {2, -1}, {2, -5}, {0, 6}}, {{0, 2}, {2, -1}, {2, -15}, {1, 9}, {0, 17}, {0, 8}, {2, 19}, {0, 5}, {1, 16}, {2, 3}, {1, 17}, {2, -8}, {2, -1}, {2, -4}, {2, -16}, {0, 4}, {2, -8}, {2, 14}, {2, -20}, {2, -15}}, {{0, 5}, {0, 20}, {1, 13}, {0, 13}, {2, 18}, {1, 19}, {0, 7}, {0, 13}, {2, -7}, {2, 11}, {0, 16}, {1, 6}, {2, -19}, {2, 6}, {1, 18}, {2, 4}, {2, -7}, {2, -8}, {2, 20}, {0, 19}}
|
||||||
|
};
|
||||||
|
// *INDENT-ON*
|
||||||
|
|
||||||
|
uint8_t buf[20];
|
||||||
|
uint8_t n = 0;
|
||||||
|
uint32_t bres = 0;
|
||||||
|
for(uint32_t i = 0; i < 100; i++) {
|
||||||
|
/* bring the pos back to the middle of the file */
|
||||||
|
int32_t pos = 500;
|
||||||
|
res = lv_fs_seek(&f, pos, LV_FS_SEEK_SET);
|
||||||
|
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
|
||||||
|
for(uint32_t j = 0; j < 20; j++) {
|
||||||
|
int8_t action = actions[i][j][0];
|
||||||
|
int8_t amount = actions[i][j][1];
|
||||||
|
switch(action) {
|
||||||
|
case 0: /* read */
|
||||||
|
res = lv_fs_read(&f, buf, amount, &bres);
|
||||||
|
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
|
||||||
|
TEST_ASSERT_EQUAL(amount, bres);
|
||||||
|
TEST_ASSERT(0 == memcmp(buf, buf1000 + pos, amount));
|
||||||
|
pos += amount;
|
||||||
|
break;
|
||||||
|
case 1: /* write */
|
||||||
|
for(int32_t k = 0; k < amount; k++) {
|
||||||
|
buf[k] = n;
|
||||||
|
buf1000[pos + k] = n;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
res = lv_fs_write(&f, buf, amount, &bres);
|
||||||
|
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
|
||||||
|
TEST_ASSERT_EQUAL(amount, bres);
|
||||||
|
pos += amount;
|
||||||
|
break;
|
||||||
|
case 2: /* seek */
|
||||||
|
pos += amount; /* amount may be negative */
|
||||||
|
res = lv_fs_seek(&f, pos, LV_FS_SEEK_SET);
|
||||||
|
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* test SEEK_END */
|
||||||
|
uint32_t tell_pos;
|
||||||
|
res = lv_fs_seek(&f, 0, LV_FS_SEEK_END);
|
||||||
|
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
|
||||||
|
res = lv_fs_tell(&f, &tell_pos);
|
||||||
|
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
|
||||||
|
TEST_ASSERT_EQUAL(tell_pos, 1000);
|
||||||
|
|
||||||
|
res = lv_fs_close(&f);
|
||||||
|
TEST_ASSERT_EQUAL(LV_FS_RES_OK, res);
|
||||||
|
|
||||||
|
drv->cache_size = original_cache_size;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user