VFS FileSystem
Requirements
No specific requirement. This example should run without issue on GAP9 EVK.
Description
This example shows you how to use VFS on GAP9 with mram or external flash.
# Boot from JTAG
cmake -B build
cmake --build buil -j -t run
Code
/*
* Copyright (C) 2017 ETH Zurich, University of Bologna and GreenWaves Technologies
* All rights reserved.
*
* This software may be modified and distributed under the terms
* of the BSD license. See the LICENSE file for details.
*
*/
#include "pmsis.h"
#include "bsp/bsp.h"
#include "bsp/flash_partition_v2.h"
#include "bsp/vfs.h"
#define QUOTE(name) #name
#define STR(macro) QUOTE(macro)
#define TOTAL_SIZE ( 16384 )
#define BUFF_SIZE ( 1024 )
static PI_L2 char buff[2][BUFF_SIZE];
static pi_fs_file_t *file[2];
static pi_fs_file_t *tx_file[2];
static PI_L2 char check_buff[BUFF_SIZE];
static int32_t exec_reads()
{
printf("exec read test\n");
int32_t size0 = file[0]->size;
int32_t size1 = file[1]->size;
int32_t rd_size0, rd_size1;
uint32_t index0 = 0;
uint32_t index1 = 0;
do{
if (size0 > BUFF_SIZE)
rd_size0 = BUFF_SIZE;
else
rd_size0 = size0;
if (size1 > BUFF_SIZE)
rd_size1 = BUFF_SIZE;
else
rd_size1 = size1;
pi_fs_read(file[0], buff[0], rd_size0);
pi_fs_read(file[1], buff[1], rd_size1);
size0 -= rd_size0;
size1 -= rd_size1;
for (int32_t i=0; i<rd_size0; i++)
{
unsigned char expected;
expected = (index0%128) & 0x7f;
if (expected != buff[0][i])
{
printf("Error, buffer: %d, index: %d, expected: 0x%x, read: 0x%x\n", 0, i, expected, buff[0][i]);
return -6;
}
index0 ++;
}
for (int32_t i=0; i<rd_size1; i++)
{
unsigned char expected;
expected = (index1 %128) | 0x80;
if (expected != buff[1][i])
{
printf("Error, buffer: %d, index: %d, expected: 0x%x, read: 0x%x\n", 1, i, expected, buff[1][i]);
return -6;
}
index1 ++;
}
} while(size0 && size1);
index0 = 0;
index1 = 0;
return 0;
}
static int exec_tests_lfs()
{
for(int i=0; i<(TOTAL_SIZE/BUFF_SIZE); i++)
{
pi_vfs_read(file[0], buff[0], BUFF_SIZE);
pi_vfs_write(tx_file[0], buff[0], BUFF_SIZE);
pi_vfs_read(file[1], buff[1], BUFF_SIZE);
pi_vfs_write(tx_file[1], buff[1], BUFF_SIZE);
}
return 0;
}
int test_vfs_ls(pi_vfs_t *vfs,char* url)
{
pi_vfs_file_t* dir;
dir = pi_vfs_dir_open(vfs,url);
if(dir==NULL)
return -1;
printf("fs dir opened\n");
pi_vfs_info_t info;
while (true) {
int res = pi_vfs_dir_read(dir, &info);
if (res < 0) {
printf("dir read failed\n");
return res;
}
if (res == 0) {
break;
}
switch (info.file_type) {
case PI_FS_TYPE_REG: printf("reg "); break;
case PI_FS_TYPE_DIR: printf("dir "); break;
default: printf("? "); break;
}
static const char *prefixes[] = {"", "K", "M", "G"};
for (int i = sizeof(prefixes)/sizeof(prefixes[0])-1; i >= 0; i--) {
if ((int)info.size >= (1 << 10*i)-1) {
printf("%*u%sB ", 4-(i != 0), info.size >> 10*i, prefixes[i]);
break;
}
}
printf("%s\n", info.name);
}
pi_vfs_dir_close(dir);
return 0;
}
int test_lfs(pi_vfs_t *vfs)
{
int err = 0;
pi_vfs_file_t *vfile[2];
pi_vfs_file_t *tx_vfile[2];
err += test_vfs_ls(vfs, "/");
//This is a debug function to print the content of a folder.
printf("List Dir: /\n");
pi_vfs_ls(vfs, "/");
printf("\n\n\n");
printf("List Dir: /files\n");
pi_vfs_ls(vfs, "/files/");
printf("\n\n\n");
//Create a new directory
printf("Creating Directory: \"/new_dir\"\n");
pi_vfs_mkdir(vfs,"/new_dir");
// Print to see that has been properly created
printf("List Dir: /\n");
pi_vfs_ls(vfs, "/");
printf("\n\n\n");
//Copy files in the new folder
vfile[0] = pi_vfs_open(vfs, STR(FILE0), PI_FS_FLAGS_READ);
if (vfile[0] == NULL)
{
printf("File0 not found\n");
return -3;
}
vfile[1] = pi_vfs_open(vfs, STR(FILE1), PI_FS_FLAGS_READ);
if (vfile[1] == NULL)
{
printf("File1 not found\n");
return -4;
}
tx_vfile[0] = pi_vfs_open(vfs, STR(TX_FILE0), PI_FS_FLAGS_WRITE);
if (tx_vfile[0] == NULL)
{
printf("error when opening tx_file0\n");
return -3;
}
tx_vfile[1] = pi_vfs_open(vfs, STR(TX_FILE1), PI_FS_FLAGS_WRITE);
if (tx_vfile[1] == NULL)
{
printf("error when opening tx_file1\n");
return -4;
}
for(int i=0; i<(TOTAL_SIZE/BUFF_SIZE); i++)
{
pi_vfs_read(vfile[0], buff[0], BUFF_SIZE);
pi_vfs_write(tx_vfile[0], buff[0], BUFF_SIZE);
pi_vfs_read(vfile[1], buff[1], BUFF_SIZE);
pi_vfs_write(tx_vfile[1], buff[1], BUFF_SIZE);
}
// Close file to wrote data on flash.
pi_vfs_close(vfile[0]);
pi_vfs_close(vfile[1]);
pi_vfs_close(tx_vfile[0]);
pi_vfs_close(tx_vfile[1]);
printf("Copying %s to %s\n",STR(FILE0),STR(TX_FILE0));
printf("Copying %s to %s\n",STR(FILE1),STR(TX_FILE1));
for (int j=0; j<2; j++)
{
pi_vfs_file_t *file;
if (j == 0)
file = pi_vfs_open(vfs, STR(TX_FILE0), PI_FS_FLAGS_READ);
else
file = pi_vfs_open(vfs, STR(TX_FILE1), PI_FS_FLAGS_READ);
pi_vfs_read(file, check_buff, BUFF_SIZE);
for (int i=0; i<BUFF_SIZE; i++)
{
unsigned char expected;
if (j == 0)
expected = i & 0x7f;
else
expected = i | 0x80;
if (expected != check_buff[i])
{
printf("Error, buffer: %d, index: %d, expected: 0x%x, read: 0x%x\n", j, i, expected, check_buff[i]);
return -6;
}
}
pi_vfs_close(file);
}
printf("Hooray! copied Files checked correctly!!!\n");
//Remove copyied files:
printf("Removing %s\n",STR(TX_FILE0));
pi_vfs_remove(vfs,STR(TX_FILE0));
printf("Removing %s\n",STR(TX_FILE1));
pi_vfs_remove(vfs,STR(TX_FILE1));
printf("Removing /new_dir\n");
//Remove Created Directory;
pi_vfs_remove(vfs,"/new_dir");
//List all files in the filesystem
printf("List Dir all FS content:\n");
printf("\n/\n");
test_vfs_ls(vfs,"/");
printf("\n/files/\n");
test_vfs_ls(vfs,"/files/");
printf("\n\n\n");
return err;
}
int main(void)
{
pi_device_t my_vfs[2];
pi_vfs_conf_t my_vfs_conf[2];
pi_vfs_conf_init(&my_vfs_conf[0]);
pi_vfs_conf_init(&my_vfs_conf[1]);
pi_open_from_conf(&my_vfs[0], &my_vfs_conf[0]);
pi_open_from_conf(&my_vfs[1], &my_vfs_conf[1]);
/*
* Test Volume mount
*/
printf("============================\n");
printf(" Test Volume mount via VFS\n");
printf("============================\n");
/* Open volume */
pi_fpv2_volume_desc_t* test_volume = (pi_fpv2_volume_desc_t *) pi_vfs_mount(&my_vfs[0], "/app");
if(test_volume == NULL)
{
printf("mount app failed\n");
return -1;
}
else
printf("Volume volume /app has been mounted\n");
pi_fpv2_volume_dump(test_volume);
pi_vfs_unmount(&my_vfs[0]);
printf("Mount volume test done\n");
/*
* Test ReadFS mount
*/
printf("============================\n");
printf(" Test readFS via VFS\n");
printf("============================\n");
pi_vfs_t *my_readfs_mram = (pi_vfs_t *) pi_vfs_mount(&my_vfs[0], "/app/readfs_mram");
pi_vfs_t *my_readfs_flash = (pi_vfs_t *) pi_vfs_mount(&my_vfs[1], "/app/readfs_flash");
if( my_readfs_mram == NULL || my_readfs_flash == NULL )
{
printf("mount /app/readfs failed\n");
return -1;
}
file[0] = pi_fs_open(my_readfs_mram->fs, "flash_file_0.bin", 0);
file[1] = pi_fs_open(my_readfs_flash->fs, "flash_file_1.bin", 0);
if (file[0] == NULL || file[1] == NULL)
{
printf("file open failed\n");
return -1;
}
else
{
printf("files opened\n");
}
if (exec_reads())
{
printf("read test failed\n");
return -1;
}
pi_fs_close(file[0]);
pi_fs_close(file[1]);
pi_vfs_unmount(&my_vfs[0]);
pi_vfs_unmount(&my_vfs[1]);
printf("readFS test succeed\n");
/*
* Test LFS mount
*/
printf("============================\n");
printf(" Test LFS via VFS\n");
printf("============================\n");
pi_vfs_t *my_lfs_flash = (pi_vfs_t *) pi_vfs_mount(&my_vfs[0], "/app/lfs_flash");
pi_vfs_t *my_lfs_mram = (pi_vfs_t *) pi_vfs_mount(&my_vfs[1], "/app/lfs_mram");
if(my_lfs_flash == NULL || my_lfs_mram == NULL)
{
printf("mount /app/lfs_flash failed\n");
return -1;
}
printf("lfs mounted via VFS\n");
test_lfs(my_lfs_flash);
test_lfs(my_lfs_mram);
pi_vfs_unmount(&my_vfs[0]);
pi_vfs_unmount(&my_vfs[1]);
/*
* Test dir access and dir read
*/
printf("============================\n");
printf(" Test dir load via VFS\n");
printf("============================\n");
pi_vfs_file_t *root_dir_flash = (pi_vfs_file_t *) pi_vfs_mount(&my_vfs[0], "/app/lfs_flash/lfs_file_folder/");
pi_vfs_file_t *root_dir_mram = (pi_vfs_file_t *) pi_vfs_mount(&my_vfs[1], "/app/lfs_flash/");
if(root_dir_flash == NULL || root_dir_mram == NULL)
{
printf("mount /app/lfs_flash/files failed\n");
return -1;
}
printf("lfs dir mounted via VFS\n");
pi_vfs_info_t info;
// Dump the info for lfs_file_folder in ext-flash
printf("dump the content in the lfs_file_folder in ext-flash\n");
while (true) {
int res = pi_vfs_dir_read(root_dir_flash, &info);
if (res < 0) {
printf("dir read failed\n");
return res;
}
if (res == 0) {
break;
}
switch (info.file_type) {
case PI_FS_TYPE_REG: printf("reg "); break;
case PI_FS_TYPE_DIR: printf("dir "); break;
default: printf("? "); break;
}
static const char *prefixes[] = {"", "K", "M", "G"};
for (int i = sizeof(prefixes)/sizeof(prefixes[0])-1; i >= 0; i--) {
if ((int)info.size >= (1 << 10*i)-1) {
printf("%*u%sB ", 4-(i != 0), info.size >> 10*i, prefixes[i]);
break;
}
}
printf("%s\n", info.name);
}
// Dump the info for / folder in mram
printf("dump the content in the / in mram\n");
while (true) {
int res = pi_vfs_dir_read(root_dir_mram, &info);
if (res < 0) {
printf("dir read failed\n");
return res;
}
if (res == 0) {
break;
}
switch (info.file_type) {
case PI_FS_TYPE_REG: printf("reg "); break;
case PI_FS_TYPE_DIR: printf("dir "); break;
default: printf("? "); break;
}
static const char *prefixes[] = {"", "K", "M", "G"};
for (int i = sizeof(prefixes)/sizeof(prefixes[0])-1; i >= 0; i--) {
if ((int)info.size >= (1 << 10*i)-1) {
printf("%*u%sB ", 4-(i != 0), info.size >> 10*i, prefixes[i]);
break;
}
}
printf("%s\n", info.name);
}
pi_vfs_dir_close(root_dir_flash);
pi_vfs_dir_close(root_dir_mram);
pi_vfs_unmount(&my_vfs[0]);
pi_vfs_unmount(&my_vfs[1]);
printf("Leaving example\n");
return 0;
}
# Copyright (c) 2022 GreenWaves Technologies SAS
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of GreenWaves Technologies SAS nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
cmake_minimum_required(VERSION 3.19)
###############################################################################
# Panel Control
###############################################################################
set(TARGET_NAME "vfs_example")
set(TARGET_SRCS test.c)
set(FILE0_NAME flash_file_0.bin)
set(FILE1_NAME flash_file_1.bin)
set(TX_FILE0 tx_flash_file_0.bin)
set(TX_FILE1 tx_flash_file_1.bin)
set(TX_FILE0_PATH /new_dir/${TX_FILE0})
set(TX_FILE1_PATH /new_dir/${TX_FILE1})
set(LITTLEFS_ROOT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/files")
###############################################################################
# CMake pre initialization
###############################################################################
include($ENV{GAP_SDK_HOME}/utils/cmake/setup.cmake)
list(APPEND TARGET_PREPROCESSOR -DFILE0=${FILE0_NAME} -DFILE1=${FILE1_NAME})
list(APPEND TARGET_PREPROCESSOR -DTX_FILE0=${TX_FILE0_PATH} -DTX_FILE1=${TX_FILE1_PATH})
readfs_add_files(FILES ${CMAKE_CURRENT_SOURCE_DIR}/files/${FILE0_NAME} FLASH mram)
readfs_add_files(FILES ${CMAKE_CURRENT_SOURCE_DIR}/files/${FILE1_NAME} FLASH flash)
littlefs_set_root_directory(ROOT_DIRECTORY ${LITTLEFS_ROOT_DIRECTORY} FLASH mram)
littlefs_set_root_directory(ROOT_DIRECTORY ${LITTLEFS_ROOT_DIRECTORY} FLASH flash)
#add_compile_definitions("TRACE_READFS=1" "PI_LOG_LOCAL_LEVEL=5" "TRACE_PARTITION=1")
list(APPEND GAPY_RUNNER_ARGS
--flash-property=${CMAKE_BINARY_DIR}/${TARGET_NAME}@mram:app:binary
--flash-property=${CONFIG_GAP_SDK_HOME}/install/target/bin/fsbl@mram:fsbl:binary
--flash-property=${CONFIG_GAP_SDK_HOME}/install/target/bin/ssbl@mram:ssbl:binary)
message(STATUS "status: ${TARGET_PREPROCESSOR}")
project(${TARGET_NAME} C ASM)
add_executable(${TARGET_NAME} ${TARGET_SRCS})
target_compile_options(${TARGET_NAME} PUBLIC ${TARGET_CFLAGS}
${TARGET_INCS}
${TARGET_PREPROCESSOR})
###############################################################################
# CMake post initialization
###############################################################################
setupos(${TARGET_NAME})