-
Notifications
You must be signed in to change notification settings - Fork 6.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This sample has two volumes, FAT16 and FAT32, exported via new USB device MSC support. Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
- Loading branch information
1 parent
38d33bc
commit 5e5d632
Showing
7 changed files
with
254 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Copyright (c) 2023 Nordic Semiconductor ASA | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
cmake_minimum_required(VERSION 3.20.0) | ||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) | ||
project(ffat) | ||
|
||
include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake) | ||
FILE(GLOB app_sources src/*.c) | ||
target_sources(app PRIVATE ${app_sources}) |
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,9 @@ | ||
# Copyright (c) 2023 Nordic Semiconductor ASA | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
# Source common USB sample options used to initialize new experimental USB | ||
# device stack. The scope of these options is limited to USB samples in project | ||
# tree, you cannot use them in your own application. | ||
source "samples/subsys/usb/common/Kconfig.sample_usbd" | ||
|
||
source "Kconfig.zephyr" |
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,35 @@ | ||
.. zephyr:code-sample:: usb-ffat | ||
:name: USB FFAT | ||
:relevant-api: usbd_api usbd_msc_device | ||
|
||
Expose a FFAT disk over USB using the USB Mass Storage Class implementation. | ||
|
||
Overview | ||
******** | ||
|
||
This sample application demonstrates the FFAT disk implementation using the new | ||
experimental USB device stack. The sample has two FFAT disks that emulate FAT16 | ||
and FAT32 file system formatted disks. There is no real disk or file system | ||
behind them. The two disks emulate FAT formatted disks at runtime. When mounted | ||
on the host side, you will find three files on the FFAT16 disk and two files on | ||
the FFAT32 disk. You can read and write to the binary files; the text files are | ||
read-only. Writing to a file means that for each block written to the disk, a | ||
callback is invoked on the Zephyr side that can be used, for example, to update | ||
firmware or load something into the device running the Zephyr RTOS. | ||
|
||
Requirements | ||
************ | ||
|
||
This project requires an experimental USB device driver (UDC API). | ||
|
||
Building and Running | ||
******************** | ||
|
||
This sample can be built for multiple boards, in this example we will build it | ||
for the nRF52840DK board: | ||
|
||
.. zephyr-app-commands:: | ||
:zephyr-app: samples/subsys/usb/ffat | ||
:board: nrf52840dk/nrf52840 | ||
:goals: build flash | ||
:compact: |
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,23 @@ | ||
/* | ||
* Copyright (c) 2023 Nordic Semiconductor ASA | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
/ { | ||
ffatdisk0 { | ||
compatible = "zephyr,ffat-disk"; | ||
disk-name = "FFAT16"; | ||
sector-size = <512>; | ||
sector-count = <8192>; | ||
sector-per-cluster = <1>; | ||
}; | ||
|
||
ffatdisk1 { | ||
compatible = "zephyr,ffat32-disk", "zephyr,ffat-disk"; | ||
disk-name = "FFAT32"; | ||
sector-size = <512>; | ||
sector-count = <7744512>; | ||
sector-per-cluster = <8>; | ||
}; | ||
}; |
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,11 @@ | ||
CONFIG_USB_DEVICE_STACK_NEXT=y | ||
|
||
CONFIG_STDOUT_CONSOLE=y | ||
CONFIG_USBD_MSC_CLASS=y | ||
CONFIG_USBD_MSC_LUNS_PER_INSTANCE=2 | ||
|
||
CONFIG_LOG=y | ||
CONFIG_USBD_LOG_LEVEL_WRN=y | ||
CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y | ||
|
||
CONFIG_MAIN_STACK_SIZE=2048 |
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,14 @@ | ||
sample: | ||
name: USB FFAT sample | ||
common: | ||
depends_on: | ||
- usbd | ||
integration_platforms: | ||
- nrf52840dk/nrf52840 | ||
- nrf54h20dk/nrf54h20/cpuapp | ||
- frdm_k64f | ||
- nucleo_f413zh | ||
- mimxrt1060_evk | ||
tests: | ||
sample.usbd.ffat: | ||
tags: usb filesystem |
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,152 @@ | ||
/* | ||
* Copyright (c) 2023 Nordic Semiconductor ASA | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <sample_usbd.h> | ||
|
||
#include <stdint.h> | ||
#include <version.h> | ||
|
||
#include <zephyr/kernel.h> | ||
#include <zephyr/sys/byteorder.h> | ||
#include <zephyr/usb/usbd.h> | ||
#include <zephyr/usb/class/usbd_msc.h> | ||
#include <zephyr/storage/ffatdisk.h> | ||
|
||
#include <zephyr/logging/log.h> | ||
LOG_MODULE_REGISTER(main, LOG_LEVEL_INF); | ||
|
||
#ifdef BUILD_VERSION | ||
#define BANNER_VERSION STRINGIFY(BUILD_VERSION) | ||
#else | ||
#define BANNER_VERSION KERNEL_VERSION_STRING | ||
#endif | ||
|
||
const char txt_info_file[] = | ||
"Zephyr RTOS\n" | ||
"Build " BANNER_VERSION "\n" | ||
"Board " CONFIG_BOARD "\n" | ||
"Arch "CONFIG_ARCH "\n"; | ||
|
||
const char html_info_file[] = | ||
"<!DOCTYPE html>\n" | ||
"<html>\n" | ||
"<head>\n" | ||
"<style>\n" | ||
"body {\n" | ||
"background: #AF7FE4;\n" | ||
"}\n" | ||
".content {\n" | ||
"max-width: 480px;\n" | ||
"background: #F0F2F4;\n" | ||
"margin: auto;\n" | ||
"padding: 16px;\n" | ||
"}\n" | ||
"</style>\n" | ||
"</head>\n" | ||
"<body>\n" | ||
"<div class=\"content\">\n" | ||
"<h1>FFAT sample</h1>\n" | ||
"<p><a href=\"https://www.zephyrproject.org/\">zephyrproject.org</a></p>\n" | ||
"</div>\n" | ||
"</body>\n" | ||
"</html>\n"; | ||
|
||
struct binfile { | ||
uint32_t s_tag; | ||
uint32_t b_num; | ||
uint8_t reserved[500]; | ||
uint32_t e_tag; | ||
} __packed; | ||
|
||
BUILD_ASSERT(sizeof(struct binfile) == 512U); | ||
|
||
static int infofile_rd_cb(struct ffat_file *const f, const uint32_t sector, | ||
uint8_t *const buf, const uint32_t size) | ||
{ | ||
size_t f_off = size * sector; | ||
|
||
if (f->size > f_off) { | ||
size_t len = MIN(f->size - f_off, size); | ||
|
||
memcpy(buf, (uint8_t *)f->priv + f_off, len); | ||
LOG_DBG("Read %u bytes, sector %u file offset %zu, f->size %zu", | ||
len, sector, f_off, f->size); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static int binfile_rd_cb(struct ffat_file *const f, const uint32_t sector, | ||
uint8_t *const buf, const uint32_t size) | ||
{ | ||
size_t f_off = size * sector; | ||
|
||
if (f->size > f_off) { | ||
size_t len = MIN(f->size - f_off, size); | ||
struct binfile *test = (void *)buf; | ||
|
||
test->s_tag = sys_cpu_to_le32(0xDECAFBAD); | ||
test->b_num = sys_cpu_to_le32(sector); | ||
test->e_tag = sys_cpu_to_le32(0xDEADDA7A); | ||
|
||
LOG_DBG("Read %u bytes, sector %u file offset %zu, f->size %zu", | ||
len, sector, f_off, f->size); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static int binfile_wr_cb(struct ffat_file *const f, const uint32_t sector, | ||
const uint8_t *const buf, const uint32_t size) | ||
{ | ||
size_t f_off = size * sector; | ||
|
||
if (f->size > f_off) { | ||
size_t len = MIN(f->size - f_off, size); | ||
|
||
LOG_DBG("Write %u bytes, sector %u file offset %zu, f->size %zu", | ||
len, sector, f_off, f->size); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
FFAT_FILE_DEFINE(readme, "FFAT16", "README TXT", sizeof(txt_info_file), | ||
infofile_rd_cb, NULL, txt_info_file); | ||
FFAT_FILE_DEFINE(html, "FFAT16", "INDEX HTM", sizeof(html_info_file), | ||
infofile_rd_cb, NULL, html_info_file); | ||
FFAT_FILE_DEFINE(bin, "FFAT16", "FOOBAZ BIN", 32768U, | ||
binfile_rd_cb, binfile_wr_cb, NULL); | ||
|
||
FFAT_FILE_DEFINE(readme32, "FFAT32", "README TXT", sizeof(txt_info_file), | ||
infofile_rd_cb, NULL, txt_info_file); | ||
FFAT_FILE_DEFINE(big, "FFAT32", "FOOBAZ BIN", 66051072UL, | ||
binfile_rd_cb, binfile_wr_cb, NULL); | ||
|
||
USBD_DEFINE_MSC_LUN(ffat16, "FFAT16", "Zephyr", "FFAT16", "0.00"); | ||
USBD_DEFINE_MSC_LUN(ffat32, "FFAT32", "Zephyr", "FFAT32", "0.00"); | ||
|
||
int main(void) | ||
{ | ||
struct usbd_context *sample_usbd; | ||
int ret; | ||
|
||
sample_usbd = sample_usbd_init_device(NULL); | ||
if (sample_usbd == NULL) { | ||
LOG_ERR("Failed to initialize USB device"); | ||
return -ENODEV; | ||
} | ||
|
||
ret = usbd_enable(sample_usbd); | ||
if (ret) { | ||
LOG_ERR("Failed to enable device support"); | ||
return ret; | ||
} | ||
|
||
LOG_INF("FFAT sample is ready."); | ||
|
||
return 0; | ||
} |