Skip to content

Commit

Permalink
WIP: Working.
Browse files Browse the repository at this point in the history
  • Loading branch information
jakkra committed Oct 7, 2023
1 parent 57f46cd commit 9e18e97
Show file tree
Hide file tree
Showing 7 changed files with 326 additions and 10 deletions.
1 change: 1 addition & 0 deletions app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ target_sources(app PRIVATE src/zsw_light_sensor.c)

target_sources_ifdef(CONFIG_SPI_FLASH_LOADER app PRIVATE src/zsw_rtt_flash_loader.c)
target_sources_ifdef(CONFIG_FILE_SYSTEM_LITTLEFS app PRIVATE src/zsw_filesystem.c)
target_sources_ifdef(CONFIG_FILE_SYSTEM_LITTLEFS app PRIVATE src/zsw_lvgl_spi_decoder.c)

if (DFU_BUILD)
target_sources(app PRIVATE src/dfu.c)
Expand Down
69 changes: 69 additions & 0 deletions app/scripts/create_lvgl_image.py
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)
6 changes: 4 additions & 2 deletions app/scripts/upload_fs_west_command.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from west.commands import WestCommand # your extension must subclass this
from west import log # use this for user output
from create_resource_fs import create_fs_image
#from create_resource_fs import create_fs_image
from rtt_flash_loader import run_loader
from create_lvgl_image import create_fs_image
import sys

class UploadFsWestCommand(WestCommand):
Expand Down Expand Up @@ -37,5 +38,6 @@ def do_run(self, args, unknown_args):
if (args.read_file):
filename = args.read_file
if args.read_file is None:
create_fs_image(img_filename, img_size, block_size, read_size, prog_size, name_max, file_max, attr_max, source_dir, disk_version)
create_fs_image(img_filename, source_dir, block_size)
#create_fs_image(img_filename, img_size, block_size, read_size, prog_size, name_max, file_max, attr_max, source_dir, disk_version)
sys.exit(run_loader("nRF5340_XXAA", filename, args.read_file))
2 changes: 1 addition & 1 deletion app/src/applications/qr_code/qr_code_ui.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ void qr_code_ui_show(lv_obj_t *root)

lv_obj_t *img = lv_img_create(root_page);
#ifdef CONFIG_LV_Z_USE_FILESYSTEM
lv_img_set_src(img, "/lvgl_fs/round_qr_full.bin");
lv_img_set_src(img, "S:x_ray.bin");
#else
LV_IMG_DECLARE(round_qr_full);
lv_img_set_src(img, &round_qr_full);
Expand Down
2 changes: 1 addition & 1 deletion app/src/zsw_filesystem.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,4 @@ int zsw_filesystem_ls(void)
return 0;
}

SYS_INIT(zsw_filesystem_ls, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
//SYS_INIT(zsw_filesystem_ls, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
250 changes: 250 additions & 0 deletions app/src/zsw_lvgl_spi_decoder.c
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);
6 changes: 0 additions & 6 deletions app/src/zsw_rtt_flash_loader.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
/*
* Copyright (c) 2023 Jakob Krantz
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
Expand Down

0 comments on commit 9e18e97

Please sign in to comment.