mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
examples: add filesystem example
This commit is contained in:
parent
3d97fd4771
commit
01ac354929
46
examples/filesystem/Makefile
Normal file
46
examples/filesystem/Makefile
Normal file
@ -0,0 +1,46 @@
|
||||
# name of your application
|
||||
APPLICATION = filesystem
|
||||
|
||||
# If no BOARD is found in the environment, use this default:
|
||||
BOARD ?= native
|
||||
|
||||
BOARD_INSUFFICIENT_MEMORY := nucleo32-f031
|
||||
|
||||
# This has to be the absolute path to the RIOT base directory:
|
||||
RIOTBASE ?= $(CURDIR)/../..
|
||||
|
||||
# Comment this out to disable code in RIOT that does safety checking
|
||||
# which is not needed in a production environment but helps in the
|
||||
# development process:
|
||||
DEVELHELP ?= 1
|
||||
|
||||
# Change this to 0 show compiler invocation lines by default:
|
||||
QUIET ?= 1
|
||||
|
||||
# Modules to include:
|
||||
USEMODULE += shell
|
||||
USEMODULE += shell_commands
|
||||
USEMODULE += ps
|
||||
|
||||
# Use MTD (flash layer)
|
||||
USEMODULE += mtd
|
||||
|
||||
# Use VFS
|
||||
USEMODULE += vfs
|
||||
|
||||
# Use a file system
|
||||
USEMODULE += littlefs
|
||||
# USEMODULE += spiffs
|
||||
# USEMODULE += fatfs
|
||||
USEMODULE += constfs
|
||||
# USEMODULE += devfs
|
||||
|
||||
# Set file systems specific variables
|
||||
ifneq (,$(filter littlefs, $(USEMODULE)))
|
||||
CFLAGS += -DVFS_FILE_BUFFER_SIZE=52 -DVFS_DIR_BUFFER_SIZE=44
|
||||
else ifneq (,$(filter spiffs, $(USEMODULE)))
|
||||
SPIFFS_NB_FD ?= 8
|
||||
CFLAGS += '-DSPIFFS_FS_FD_SPACE_SIZE=(32 * $(SPIFFS_NB_FD))'
|
||||
endif
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
31
examples/filesystem/README.md
Normal file
31
examples/filesystem/README.md
Normal file
@ -0,0 +1,31 @@
|
||||
# File system usage example
|
||||
|
||||
This is a basic example how to use a file system with RIOT in your embedded application.
|
||||
|
||||
This example shows:
|
||||
- how to mount/format/unmount a filesystem, with spiffs, littlefs and constfs examples
|
||||
- how to open/read/write/close a file with and without newlib
|
||||
|
||||
In RIOT, most filesystems use `mtd` as flash interface. So to use this example
|
||||
you must define `MTD_0`. `MTD_0` is a pointer to a `mtd_dev_t` instance.
|
||||
This example use `littlefs` as default filesystem on the whole `mtd` device.
|
||||
A `constfs` filesystem is also demonstrated with two files.
|
||||
|
||||
All the RIOT filesystems are used through the `vfs` interface, and on most platform
|
||||
they can be accessed transparently with `open/close/read/write/...` functions.
|
||||
With newlib, `fopen/fclose/fread/fwrite/...` can also be used transparently.
|
||||
|
||||
The following commands are available:
|
||||
- `format`: should be called the first time only, it will format the `mtd` device
|
||||
with the comfigured filesystem
|
||||
- `mount`: mount the filesystem on the configured mount point (default is `/sda`
|
||||
but it can be configured with `FLASH_MOUNT_POINT` define). The `constfs` filesystem
|
||||
is mounted automatically when the application starts
|
||||
- `umount`: unmount `/sda`
|
||||
- `cat <file>`: similarly to unix `cat` unix command, it prints the given `<file>` on
|
||||
stdout
|
||||
- `tee <file> <str>`: similarly to `tee` unix command, it writes `<str>` in `<file>`
|
||||
|
||||
Apart from these commands, the default `vfs` commands can be used, for instance:
|
||||
- `vfs df`: shows all mountpoints and used/available memory
|
||||
- `vfs ls <path>`: list files
|
264
examples/filesystem/main.c
Normal file
264
examples/filesystem/main.c
Normal file
@ -0,0 +1,264 @@
|
||||
/*
|
||||
* Copyright (C) 2018 OTA keys S.A.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup examples
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief File system usage example application
|
||||
*
|
||||
* @author Vincent Dupont <vincent@otakeys.com>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "board.h" /* MTD_0 is defined in board.h */
|
||||
|
||||
/* Flash mount point */
|
||||
#define FLASH_MOUNT_POINT "/sda"
|
||||
|
||||
/* In this example, MTD_0 is used as mtd interface for littlefs or spiffs */
|
||||
/* littlefs and spiffs basic usage are shown */
|
||||
#ifdef MTD_0
|
||||
/* File system descriptor initialization */
|
||||
#if defined(MODULE_LITTLEFS)
|
||||
/* include file system header for driver */
|
||||
#include "fs/littlefs_fs.h"
|
||||
|
||||
/* file system specific descriptor
|
||||
* for littlefs, some fields can be tweaked to define the size
|
||||
* of the partition, see header documentation.
|
||||
* In this example, default behavior will be used, i.e. the entire
|
||||
* memory will be used (parameters come from mtd) */
|
||||
static littlefs_desc_t fs_desc = {
|
||||
.lock = MUTEX_INIT,
|
||||
};
|
||||
|
||||
/* littlefs file system driver will be used */
|
||||
#define FS_DRIVER littlefs_file_system
|
||||
|
||||
#elif defined(MODULE_SPIFFS)
|
||||
/* include file system header */
|
||||
#include "fs/spiffs_fs.h"
|
||||
|
||||
/* file system specific descriptor
|
||||
* as for littlefs, some fields can be changed if needed,
|
||||
* this example focus on basic usage, i.e. entire memory used */
|
||||
static spiffs_desc_t fs_desc = {
|
||||
.lock = MUTEX_INIT,
|
||||
};
|
||||
|
||||
/* spiffs driver will be used */
|
||||
#define FS_DRIVER spiffs_file_system
|
||||
#endif
|
||||
|
||||
/* this structure defines the vfs mount point:
|
||||
* - fs field is set to the file system driver
|
||||
* - mount_point field is the mount point name
|
||||
* - private_data depends on the underlying file system. For both spiffs and
|
||||
* littlefs, it needs to be a pointer to the file system descriptor */
|
||||
static vfs_mount_t flash_mount = {
|
||||
.fs = &FS_DRIVER,
|
||||
.mount_point = FLASH_MOUNT_POINT,
|
||||
.private_data = &fs_desc,
|
||||
};
|
||||
#endif /* MTD_0 */
|
||||
|
||||
/* constfs example */
|
||||
#include "fs/constfs.h"
|
||||
|
||||
#define HELLO_WORLD_CONTENT "Hello World!\n"
|
||||
#define HELLO_RIOT_CONTENT "Hello RIOT!\n"
|
||||
|
||||
/* this defines two const files in the constfs */
|
||||
static constfs_file_t constfs_files[] = {
|
||||
{
|
||||
.path = "/hello-world",
|
||||
.size = sizeof(HELLO_WORLD_CONTENT),
|
||||
.data = (const uint8_t *)HELLO_WORLD_CONTENT,
|
||||
},
|
||||
{
|
||||
.path = "/hello-riot",
|
||||
.size = sizeof(HELLO_RIOT_CONTENT),
|
||||
.data = (const uint8_t *)HELLO_RIOT_CONTENT,
|
||||
}
|
||||
};
|
||||
|
||||
/* this is the constfs specific descriptor */
|
||||
static constfs_t constfs_desc = {
|
||||
.nfiles = sizeof(constfs_files) / sizeof(constfs_files[0]),
|
||||
.files = constfs_files,
|
||||
};
|
||||
|
||||
/* constfs mount point, as for previous example, it needs a file system driver,
|
||||
* a mount poinr and private_data is a pointer to the constfs descriptor */
|
||||
static vfs_mount_t const_mount = {
|
||||
.fs = &constfs_file_system,
|
||||
.mount_point = "/const",
|
||||
.private_data = &constfs_desc,
|
||||
};
|
||||
|
||||
/* Command handlers */
|
||||
static int _mount(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
#if defined(MTD_0) && (defined(MODULE_SPIFFS) || defined(MODULE_LITTLEFS))
|
||||
int res = vfs_mount(&flash_mount);
|
||||
if (res < 0) {
|
||||
printf("Error while mounting %s...try format\n", FLASH_MOUNT_POINT);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("%s successfully mounted\n", FLASH_MOUNT_POINT);
|
||||
return 0;
|
||||
#else
|
||||
puts("No external flash file system selected");
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int _format(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
#if defined(MTD_0) && (defined(MODULE_SPIFFS) || defined(MODULE_LITTLEFS))
|
||||
int res = vfs_format(&flash_mount);
|
||||
if (res < 0) {
|
||||
printf("Error while formatting %s\n", FLASH_MOUNT_POINT);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("%s successfully formatted\n", FLASH_MOUNT_POINT);
|
||||
return 0;
|
||||
#else
|
||||
puts("No external flash file system selected");
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int _umount(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
#if defined(MTD_0) && (defined(MODULE_SPIFFS) || defined(MODULE_LITTLEFS))
|
||||
int res = vfs_umount(&flash_mount);
|
||||
if (res < 0) {
|
||||
printf("Error while unmounting %s\n", FLASH_MOUNT_POINT);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("%s successfully unmounted\n", FLASH_MOUNT_POINT);
|
||||
return 0;
|
||||
#else
|
||||
puts("No external flash file system selected");
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int _cat(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
printf("Usage: %s <file>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
/* With newlib, low-level syscalls are plugged to RIOT vfs
|
||||
* on native, open/read/write/close/... are plugged to RIOT vfs */
|
||||
#ifdef MODULE_NEWLIB
|
||||
FILE *f = fopen(argv[1], "r");
|
||||
if (f == NULL) {
|
||||
printf("file %s does not exist\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
char c;
|
||||
while (fread(&c, 1, 1, f) != 0) {
|
||||
putchar(c);
|
||||
}
|
||||
fclose(f);
|
||||
#else
|
||||
int fd = open(argv[1], O_RDONLY);
|
||||
if (fd < 0) {
|
||||
printf("file %s does not exist\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
char c;
|
||||
while (read(fd, &c, 1) != 0) {
|
||||
putchar(c);
|
||||
}
|
||||
close(fd);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _tee(int argc, char **argv)
|
||||
{
|
||||
if (argc != 3) {
|
||||
printf("Usage: %s <file> <str>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef MODULE_NEWLIB
|
||||
FILE *f = fopen(argv[1], "w+");
|
||||
if (f == NULL) {
|
||||
printf("error while trying to create %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
if (fwrite(argv[2], 1, strlen(argv[2]), f) != strlen(argv[2])) {
|
||||
puts("Error while writing");
|
||||
}
|
||||
fclose(f);
|
||||
#else
|
||||
int fd = open(argv[1], O_RDWR | O_CREAT);
|
||||
if (fd < 0) {
|
||||
printf("error while trying to create %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
if (write(fd, argv[2], strlen(argv[2])) != (ssize_t)strlen(argv[2])) {
|
||||
puts("Error while writing");
|
||||
}
|
||||
close(fd);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const shell_command_t shell_commands[] = {
|
||||
{ "mount", "mount flash filesystem", _mount },
|
||||
{ "format", "format flash file system", _format },
|
||||
{ "umount", "unmount flash filesystem", _umount },
|
||||
{ "cat", "print the content of a file", _cat },
|
||||
{ "tee", "write a string in a file", _tee },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
#if defined(MTD_0) && (defined(MODULE_SPIFFS) || defined(MODULE_LITTLEFS))
|
||||
/* spiffs and littlefs need a mtd pointer
|
||||
* by default the whole memory is used */
|
||||
fs_desc.dev = MTD_0;
|
||||
#endif
|
||||
int res = vfs_mount(&const_mount);
|
||||
if (res < 0) {
|
||||
puts("Error while mounting constfs");
|
||||
}
|
||||
else {
|
||||
puts("constfs mounted successfully");
|
||||
}
|
||||
|
||||
char line_buf[SHELL_DEFAULT_BUFSIZE];
|
||||
shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user