-
-
Notifications
You must be signed in to change notification settings - Fork 216
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
326 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import os | ||
import argparse | ||
from struct import * | ||
|
||
MAX_FILE_NAME = 16 | ||
FILE_TABLE_MAX_LEN = 1024 # TODO USE and match with c code | ||
''' | ||
magic_number:uint32 | ||
header_len:uint32 | ||
total_length:uint32 | ||
num_files:uint32 | ||
filename[MAX_FILE_NAME + 1] | ||
offset:uint32 | ||
len:uint32 | ||
filename[MAX_FILE_NAME + 1] | ||
offset:uint32 | ||
len:uint32 | ||
... | ||
''' | ||
# TODO add total length ijn the beginning? | ||
|
||
def create_fs_image(img_filename, source_dir, block_size=4096): | ||
table = {} | ||
offset = 0 | ||
files_image = bytearray() | ||
header_image = bytearray() | ||
for root, dirs, files in os.walk(source_dir): | ||
print(f"root {root} dirs {dirs} files {files}") | ||
for filename in files: | ||
path = os.path.join(root, filename) | ||
relpath = os.path.relpath(path, start=source_dir) | ||
print(f"Adding {path}") | ||
with open(path, "rb") as infile: | ||
files_image.extend(infile.read()) | ||
header_image = bytearray() | ||
table[filename] = { | ||
'offset': offset, | ||
'len': infile.tell() | ||
} | ||
offset = offset + infile.tell() | ||
print(table) | ||
header_image = pack("<II", 0x0A0A0A0A, len(table)) | ||
for name, data in table.items(): | ||
if (len(name) <= MAX_FILE_NAME): | ||
print("asdf", name.ljust(MAX_FILE_NAME)) | ||
header_image = header_image + pack(f"<{MAX_FILE_NAME}sII", bytes(name, 'utf-8'), data['offset'], data['len']) | ||
else: | ||
print('Filename to long, skipping', name, len(name)) | ||
|
||
with open(img_filename, "wb") as f: | ||
print('total len', 4 + len(header_image) + len(files_image)) | ||
f.write(pack("<I", 4 + len(header_image))) | ||
f.write(pack("<I", 4 + len(header_image) + len(files_image))) | ||
f.write(header_image) | ||
f.write(files_image) | ||
|
||
|
||
if __name__ == "__main__": | ||
parser = argparse.ArgumentParser() | ||
parser.add_argument("--img-filename", default="littlefs.img") | ||
parser.add_argument("--block-size", type=int, default=4096) | ||
parser.add_argument("source") | ||
args = parser.parse_args() | ||
|
||
img_filename = args.img_filename | ||
block_size = args.block_size | ||
source_dir = args.source | ||
|
||
create_fs_image(img_filename, source_dir, block_size) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,250 @@ | ||
#include <zephyr/kernel.h> | ||
#include <zephyr/init.h> | ||
#include <zephyr/logging/log.h> | ||
#include <zephyr/drivers/flash.h> | ||
#include <zephyr/storage/flash_map.h> | ||
#include <lvgl.h> | ||
#include "lv_conf.h" | ||
#include LV_MEM_CUSTOM_INCLUDE | ||
|
||
|
||
#define SPI_FLASH_SECTOR_SIZE 4096 | ||
|
||
#define FLASH_PARTITION_NAME lvgl_fs_partition | ||
|
||
#define FLASH_PARTITION_ID FIXED_PARTITION_ID(FLASH_PARTITION_NAME) | ||
#define FLASH_PARTITION_DEVICE FIXED_PARTITION_DEVICE(FLASH_PARTITION_NAME) | ||
#define FLASH_PARTITION_OFFSET FIXED_PARTITION_OFFSET(FLASH_PARTITION_NAME) | ||
|
||
#define FILE_TABLE_MAX_LEN 1024 | ||
#define MAX_FILE_NAME_LEN 16 | ||
#define MAX_OPENED_FILES 8 | ||
|
||
typedef struct file_header_t { | ||
uint8_t filename[MAX_FILE_NAME_LEN]; | ||
uint32_t offset; | ||
uint32_t len; | ||
} file_header_t; | ||
|
||
typedef struct file_table_t { | ||
uint32_t header_length; // Image offset counted from after this. | ||
uint32_t total_length; | ||
uint32_t magic; | ||
uint32_t num_files; | ||
file_header_t file_headers[FILE_TABLE_MAX_LEN / sizeof(file_header_t)]; | ||
} file_table_t; | ||
|
||
typedef struct opened_file_t { | ||
file_header_t* header; | ||
uint32_t index; | ||
} opened_file_t; | ||
|
||
static file_table_t file_table; | ||
static opened_file_t opened_files[MAX_OPENED_FILES]; | ||
|
||
static const struct flash_area *flash_area; | ||
|
||
static file_header_t* find_file(const char* name) | ||
{ | ||
for (int i = 0; i < file_table.num_files; i++) { | ||
if (strncmp(name, file_table.file_headers[i].filename, MAX_FILE_NAME_LEN) == 0) { | ||
return &file_table.file_headers[i]; | ||
} | ||
} | ||
return NULL; | ||
} | ||
|
||
static opened_file_t* find_free_opened_file(void) | ||
{ | ||
for (int i = 0; i < MAX_OPENED_FILES; i++) { | ||
if (opened_files[i].header == NULL) { | ||
return &opened_files[i]; | ||
} | ||
} | ||
return NULL; | ||
} | ||
|
||
static bool lvgl_fs_ready(struct _lv_fs_drv_t *drv) | ||
{ | ||
return true; | ||
} | ||
|
||
static lv_fs_res_t errno_to_lv_fs_res(int err) | ||
{ | ||
switch (err) { | ||
case 0: | ||
return LV_FS_RES_OK; | ||
case -EIO: | ||
/*Low level hardware error*/ | ||
return LV_FS_RES_HW_ERR; | ||
case -EBADF: | ||
/*Error in the file system structure */ | ||
return LV_FS_RES_FS_ERR; | ||
case -ENOENT: | ||
/*Driver, file or directory is not exists*/ | ||
return LV_FS_RES_NOT_EX; | ||
case -EFBIG: | ||
/*Disk full*/ | ||
return LV_FS_RES_FULL; | ||
case -EACCES: | ||
/*Access denied. Check 'fs_open' modes and write protect*/ | ||
return LV_FS_RES_DENIED; | ||
case -EBUSY: | ||
/*The file system now can't handle it, try later*/ | ||
return LV_FS_RES_BUSY; | ||
case -ENOMEM: | ||
/*Not enough memory for an internal operation*/ | ||
return LV_FS_RES_OUT_OF_MEM; | ||
case -EINVAL: | ||
/*Invalid parameter among arguments*/ | ||
return LV_FS_RES_INV_PARAM; | ||
case -ENOTSUP: | ||
/*Not supported by the filesystem*/ | ||
return LV_FS_RES_NOT_IMP; | ||
default: | ||
return LV_FS_RES_UNKNOWN; | ||
} | ||
} | ||
|
||
static void *lvgl_fs_open(struct _lv_fs_drv_t *drv, const char *path, lv_fs_mode_t mode) | ||
{ | ||
file_header_t* file = find_file(path); | ||
opened_file_t* open_file; | ||
|
||
if (!file) { | ||
return NULL; | ||
} | ||
|
||
open_file = find_free_opened_file(); | ||
if (!file) { | ||
return NULL; | ||
} | ||
|
||
open_file->header = file; | ||
open_file->index = 0; | ||
|
||
return open_file; | ||
} | ||
|
||
static lv_fs_res_t lvgl_fs_close(struct _lv_fs_drv_t *drv, void *file) | ||
{ | ||
opened_file_t* open_file = (opened_file_t*)file; | ||
open_file->header = NULL; | ||
open_file->index = 0; | ||
return errno_to_lv_fs_res(0); | ||
} | ||
|
||
static lv_fs_res_t lvgl_fs_read(struct _lv_fs_drv_t *drv, void *file, void *buf, uint32_t btr, | ||
uint32_t *br) | ||
{ | ||
int rc; | ||
opened_file_t* open_file = (opened_file_t*)file; | ||
|
||
rc = flash_area_read(flash_area, 40 + open_file->index/*open_file->header->offset + open_file->index + file_table.header_length - 2*/, buf, btr); | ||
if (rc != 0) { | ||
printk("Flash read failed! %d\n", rc); | ||
*br = 0; | ||
return errno_to_lv_fs_res(rc); | ||
} | ||
*br = btr; | ||
return errno_to_lv_fs_res(0); | ||
} | ||
|
||
static lv_fs_res_t lvgl_fs_write(struct _lv_fs_drv_t *drv, void *file, const void *buf, | ||
uint32_t btw, uint32_t *bw) | ||
{ | ||
return LV_FS_RES_NOT_IMP; | ||
} | ||
|
||
static lv_fs_res_t lvgl_fs_seek(struct _lv_fs_drv_t *drv, void *file, uint32_t pos, | ||
lv_fs_whence_t whence) | ||
{ | ||
opened_file_t* open_file = (opened_file_t*)file; | ||
|
||
switch (whence) { | ||
case LV_FS_SEEK_END: | ||
open_file->index = open_file->header->len; | ||
break; | ||
case LV_FS_SEEK_CUR: | ||
// We are already there? | ||
break; | ||
case LV_FS_SEEK_SET: | ||
default: | ||
open_file->index = pos; | ||
break; | ||
} | ||
|
||
return errno_to_lv_fs_res(0); | ||
} | ||
|
||
static lv_fs_res_t lvgl_fs_tell(struct _lv_fs_drv_t *drv, void *file, uint32_t *pos_p) | ||
{ | ||
opened_file_t* open_file = (opened_file_t*)file; | ||
*pos_p = open_file->index; | ||
return LV_FS_RES_OK; | ||
} | ||
|
||
static void *lvgl_fs_dir_open(struct _lv_fs_drv_t *drv, const char *path) | ||
{ | ||
return NULL; | ||
} | ||
|
||
static lv_fs_res_t lvgl_fs_dir_read(struct _lv_fs_drv_t *drv, void *dir, char *fn) | ||
{ | ||
return LV_FS_RES_NOT_IMP; | ||
} | ||
|
||
static lv_fs_res_t lvgl_fs_dir_close(struct _lv_fs_drv_t *drv, void *dir) | ||
{ | ||
int err; | ||
err = 0; | ||
return errno_to_lv_fs_res(err); | ||
} | ||
|
||
static lv_fs_drv_t fs_drv; | ||
|
||
int zsw_decoder_init(void) | ||
{ | ||
int rc; | ||
lv_fs_drv_init(&fs_drv); | ||
|
||
/* LVGL uses letter based mount points, just pass the root slash as a | ||
* letter. Note that LVGL will remove the drive letter, or in this case | ||
* the root slash, from the path passed via the FS callbacks. | ||
* Zephyr FS API assumes this slash is present so we will need to add | ||
* it back. | ||
*/ | ||
fs_drv.letter = 'S'; | ||
fs_drv.ready_cb = lvgl_fs_ready; | ||
|
||
fs_drv.open_cb = lvgl_fs_open; | ||
fs_drv.close_cb = lvgl_fs_close; | ||
fs_drv.read_cb = lvgl_fs_read; | ||
fs_drv.write_cb = lvgl_fs_write; | ||
fs_drv.seek_cb = lvgl_fs_seek; | ||
fs_drv.tell_cb = lvgl_fs_tell; | ||
|
||
fs_drv.dir_open_cb = lvgl_fs_dir_open; | ||
fs_drv.dir_read_cb = lvgl_fs_dir_read; | ||
fs_drv.dir_close_cb = lvgl_fs_dir_close; | ||
|
||
lv_fs_drv_register(&fs_drv); | ||
|
||
memset(opened_files, 0, sizeof(opened_files)); | ||
|
||
rc = flash_area_open(FLASH_PARTITION_ID, &flash_area); | ||
|
||
if (rc != 0) { | ||
printk("FAIL: unable to find flash area %u: %d\n", FLASH_PARTITION_ID, rc); | ||
return 0; | ||
} | ||
|
||
rc = flash_area_read(flash_area, 0, &file_table, FILE_TABLE_MAX_LEN); | ||
if (rc != 0) { | ||
printk("Flash read failed! %d\n", rc); | ||
return rc; | ||
} | ||
return 0; | ||
} | ||
|
||
SYS_INIT(zsw_decoder_init, APPLICATION, 99); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters