Browse Source

pkg: add package for FatFs with support for sdcard_spi and native

master
MichelRottleuthner 6 years ago
parent
commit
e0f60ba10a
  1. 4
      Makefile.dep
  2. 58
      pkg/fatfs/Makefile
  3. 15
      pkg/fatfs/Makefile.include
  4. 1
      pkg/fatfs/Makefile.module
  5. 2
      pkg/fatfs/fatfs_diskio/Makefile
  6. 53
      pkg/fatfs/fatfs_diskio/fatfs_diskio_common.c
  7. 51
      pkg/fatfs/fatfs_diskio/include/fatfs_diskio_common.h
  8. 7
      pkg/fatfs/fatfs_diskio/native/Makefile
  9. 252
      pkg/fatfs/fatfs_diskio/native/native_diskio.c
  10. 11
      pkg/fatfs/fatfs_diskio/sdcard_spi/Makefile
  11. 207
      pkg/fatfs/fatfs_diskio/sdcard_spi/sdcard_spi_diskio.c
  12. 11
      pkg/fatfs/patches/disable_rtc.patch
  13. 11
      pkg/fatfs/patches/enable_fs_tiny.patch
  14. 11
      pkg/fatfs/patches/enable_use_lable.patch
  15. 11
      pkg/fatfs/patches/enable_use_mkfs.patch
  16. 194
      pkg/fatfs/patches/fix_for_guards.patch
  17. 5
      pkg/fatfs/patches/remove_int_type.patch
  18. 11
      pkg/fatfs/patches/set_code_page_to_ascii.patch
  19. 7
      sys/Makefile
  20. 33
      tests/pkg_fatfs/Makefile
  21. 27
      tests/pkg_fatfs/README.md
  22. 381
      tests/pkg_fatfs/main.c

4
Makefile.dep

@ -8,6 +8,10 @@ OLD_USEPKG := $(sort $(USEPKG))
# pull dependencies from drivers
include $(RIOTBASE)/drivers/Makefile.dep
ifneq (,$(filter fatfs_diskio_sdcard_spi,$(USEMODULE)))
USEMODULE += sdcard_spi
endif
ifneq (,$(filter csma_sender,$(USEMODULE)))
USEMODULE += random
USEMODULE += xtimer

58
pkg/fatfs/Makefile

@ -0,0 +1,58 @@
PKG_NAME = fatfs
PKG_URL = elm-chan.org/fsw/ff/arc
PKG_VERSION = ff12b
PKG_EXT = zip
PKG_FILE = $(PKG_NAME)-$(PKG_VERSION).$(PKG_EXT)
PKG_BUILDDIR = $(PKGDIRBASE)/$(PKG_NAME)
MODULE_MAKEFILE := $(CURDIR)/Makefile.module
ifneq ($(RIOTBASE),)
include $(RIOTBASE)/Makefile.base
endif
.PHONY: all clean patch
all: $(PKG_BUILDDIR)/.patched
ffconf_patches += $(CURDIR)/patches/enable_use_lable.patch
ffconf_patches += $(CURDIR)/patches/set_code_page_to_ascii.patch
ffconf_patches += $(CURDIR)/patches/enable_use_mkfs.patch
ffconf_patches += $(CURDIR)/patches/enable_fs_tiny.patch
#if periph_rtc is available use it. Otherwise use static timestamps
ifeq (, $(filter $(periph_rtc), $(FEATURES_PROVIDED)))
ffconf_patches += $(CURDIR)/patches/disable_rtc.patch
FEATURES_REQUIRED += periph_rtc
endif
$(PKG_BUILDDIR)/.patched: $(PKG_BUILDDIR)/.prepared
@$(foreach p, $(ffconf_patches), patch $(PKG_BUILDDIR)/ffconf.h < $(p);)
@patch $(PKG_BUILDDIR)/integer.h < $(CURDIR)/patches/remove_int_type.patch
@patch $(PKG_BUILDDIR)/ff.c < $(CURDIR)/patches/fix_for_guards.patch
@touch $@
$(PKG_BUILDDIR)/.prepared: $(PKG_BUILDDIR)/.extracted
@mv $(PKG_BUILDDIR)/src/* $(PKG_BUILDDIR)/
@rm -rf $(PKG_BUILDDIR)/src
@rm -rf $(PKG_BUILDDIR)/doc
#this file is only a dummy that should be replaced by a compatible implementation
@rm $(PKG_BUILDDIR)/diskio.c
@cp $(MODULE_MAKEFILE) $(PKG_BUILDDIR)/Makefile
@touch $@
$(PKG_BUILDDIR)/.extracted: $(PKG_BUILDDIR)/$(PKG_FILE)
@mkdir -p $(@D)
@cd $(@D) && $(UNZIP_HERE) $(<)
@touch $@
$(PKG_BUILDDIR)/$(PKG_FILE):
@mkdir -p $(@D)
@$(DOWNLOAD_TO_FILE) $@ $(PKG_URL)/$(PKG_VERSION).$(PKG_EXT)
clean::
#delete all files except the downloaded zip file
@ls -A $(PKG_BUILDDIR)/ | grep -v $(PKG_FILE) | xargs -I % rm -rf $(PKG_BUILDDIR)/%
distclean::
@rm -rf $(PKG_BUILDDIR)

15
pkg/fatfs/Makefile.include

@ -0,0 +1,15 @@
INCLUDES += -I$(PKGDIRBASE)
INCLUDES += -I$(RIOTPKG)/fatfs/fatfs_diskio/include
DIRS += $(PKGDIRBASE)/fatfs
ifneq (,$(filter fatfs_diskio_native,$(USEMODULE)))
DIRS += $(RIOTBASE)/pkg/fatfs/fatfs_diskio/native
endif
ifneq (,$(filter fatfs_diskio_sdcard_spi,$(USEMODULE)))
DIRS += $(RIOTBASE)/pkg/fatfs/fatfs_diskio/sdcard_spi
endif
ifeq ($(shell uname -s),Darwin)
CFLAGS += -Wno-empty-body
endif

1
pkg/fatfs/Makefile.module

@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base

2
pkg/fatfs/fatfs_diskio/Makefile

@ -0,0 +1,2 @@
MODULE = fatfs_diskio
include $(RIOTBASE)/Makefile.base

53
pkg/fatfs/fatfs_diskio/fatfs_diskio_common.c

@ -0,0 +1,53 @@
/*
* Copyright (C) 2016 Michel Rottleuthner <michel.rottleuthner@haw-hamburg.de>
*
* 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 sys_fatfs_diskio
* @{
*
* @file
* @brief Implementation of common FatFs interface for native and sdcard_spi
* Based on low level disk I/O module example for FatFs by ChaN, 2016
*
* @author Michel Rottleuthner <michel.rottleuthner@haw-hamburg.de>
*
* @}
*/
#include "fatfs/diskio.h" /* FatFs lower layer API */
#include "fatfs_diskio_common.h"
#ifdef FATFS_RTC_AVAILABLE
#define FATFS_DISKIO_FATTIME_YEAR_OFFS 25
#define FATFS_DISKIO_FATTIME_MON_OFFS 21
#define FATFS_DISKIO_FATTIME_DAY_OFFS 16
#define FATFS_DISKIO_FATTIME_HH_OFFS 11
#define FATFS_DISKIO_FATTIME_MM_OFFS 5
DWORD get_fattime(void)
{
struct tm time;
rtc_get_time(&time);
/* bit 31:25 Year origin from 1980 (0..127) */
uint8_t year = time.tm_year + RTC_YEAR_OFFSET - FATFS_YEAR_OFFSET;
uint8_t month = time.tm_mon + 1; /* bit 24:21 month (1..12) */
uint8_t day_of_month = time.tm_mon + 1; /* bit 20:16 day (1..31) */
uint8_t hour = time.tm_hour; /* bit 15:11 hour (0..23) */
uint8_t minute = time.tm_min; /* bit 10:5 minute (0..59) */
uint8_t second = (time.tm_sec / 2); /* bit 4:0 second/2 (0..29) */
return year << FATFS_DISKIO_FATTIME_YEAR_OFFS |
month << FATFS_DISKIO_FATTIME_MON_OFFS |
day_of_month << FATFS_DISKIO_FATTIME_DAY_OFFS |
hour << FATFS_DISKIO_FATTIME_HH_OFFS |
minute << FATFS_DISKIO_FATTIME_MM_OFFS |
second;
}
#endif

51
pkg/fatfs/fatfs_diskio/include/fatfs_diskio_common.h

@ -0,0 +1,51 @@
/*
* Copyright (C) 2016 Michel Rottleuthner <michel.rottleuthner@haw-hamburg.de>
*
* 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 sys_fatfs_diskio
* @brief
* @{
*
* @brief Common defines for fatfs low-level diskio defines
* @author Michel Rottleuthner <michel.rottleuthner@haw-hamburg.de>
*/
#ifndef FATFS_DISKIO_COMMON_H
#define FATFS_DISKIO_COMMON_H
#ifdef __cplusplus
extern "C" {
#endif
#include "fatfs/diskio.h" /* FatFs lower layer API */
#define CTRL_SYNC 0 /* Complete pending write process
(needed when _FS_READONLY == 0) */
#define GET_SECTOR_COUNT 1 /* (needed when _USE_MKFS == 1) */
#define GET_SECTOR_SIZE 2 /* (needed when _MAX_SS > 512 ) */
#define GET_BLOCK_SIZE 3 /* erase block size (needed when _USE_MKFS == 1) */
#define CTRL_TRIM 4 /* Inform device about no longer needed data blocks
(needed when _USE_TRIM == 1) */
#define RTC_YEAR_OFFSET 1900
#define FATFS_YEAR_OFFSET 1980
#define FIXED_BLOCK_SIZE 512
#define FATFS_DISKIO_DSTASTUS_OK 0
#ifdef __cplusplus
}
#endif
#endif /* FATFS_DISKIO_COMMON_H */
/** @} */

7
pkg/fatfs/fatfs_diskio/native/Makefile

@ -0,0 +1,7 @@
MODULE = fatfs_diskio_native
FATFS_DISKIO_NATIVE_DEFAULT_FILE ?= \"riot_fatfs_disk.img\"
CFLAGS += -DFATFS_DISKIO_NATIVE_DEFAULT_FILE=$(FATFS_DISKIO_NATIVE_DEFAULT_FILE)
include $(RIOTBASE)/Makefile.base

252
pkg/fatfs/fatfs_diskio/native/native_diskio.c

@ -0,0 +1,252 @@
/*
* Copyright (C) 2016 Michel Rottleuthner <michel.rottleuthner@haw-hamburg.de>
*
* 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 sys_fatfs_diskio
* @{
*
* @file
* @brief Implementation of FatFs interface that makes use of a fatfs image
* file instead of hardware to allow FatFs usage/testing on native.
* Based on low level disk I/O module example for FatFs by ChaN, 2016
*
* @author Michel Rottleuthner <michel.rottleuthner@haw-hamburg.de>
*
* @}
*/
#define ENABLE_DEBUG (0)
#include "debug.h"
#include "fatfs/diskio.h"
#include "fatfs_diskio_common.h"
#include "fatfs/integer.h"
#include "periph/rtc.h"
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <errno.h>
bool rtc_init_done = false;
typedef struct {
const char *image_path;
FILE *fd;
bool opened;
} dummy_volume_t;
static dummy_volume_t volume_files[] = {
{
.image_path = FATFS_DISKIO_NATIVE_DEFAULT_FILE,
.fd = NULL,
.opened = false
},
};
static inline dummy_volume_t *get_volume_file(uint32_t idx)
{
if (idx < sizeof(volume_files) / sizeof(dummy_volume_t)) {
return &volume_files[idx];
}
else {
return NULL;
}
}
/**
* @brief returns the status of the disk
*
* @param[in] pdrv drive number to identify the drive
*
* @return STA_NODISK if no disk exists with the given id
* @return 0 if disk is initialized
* @return STA_NOINIT if disk id exists, but disk isn't initialized
*/
DSTATUS disk_status(BYTE pdrv)
{
dummy_volume_t *volume = get_volume_file(pdrv);
if (volume == NULL) {
return STA_NODISK;
}
if (volume->opened) {
return FATFS_DISKIO_DSTASTUS_OK;
}
else {
return STA_NOINIT;
}
}
/**
* @brief initializes the disk
*
* @param[in] pdrv drive number to identify the drive
*
* @return STA_NODISK if no disk exists with the given id
* @return 0 if disk was initialized sucessfully
* @return STA_NOINIT if disk id exists, but couldn't be initialized
*/
DSTATUS disk_initialize(BYTE pdrv)
{
dummy_volume_t *volume = get_volume_file(pdrv);
DEBUG("disk_initialize: %d\n", pdrv);
if (volume == NULL) {
return STA_NODISK;
}
if (volume->opened) { /* if volume is already opened close it first */
fclose(volume->fd);
volume->opened = false;
}
/* open file for r/w but don't create if it doesn't exist */
FILE *fd = fopen(volume->image_path, "r+");
DEBUG("fd: %p\n", (void *)fd);
if (fd == NULL) {
DEBUG("diskio_native.c: disk_initialize: fopen: "
"errno: 0x%08x\n", errno);
return STA_NOINIT;
}
else {
volume->fd = fd;
volume->opened = true;
return FATFS_DISKIO_DSTASTUS_OK;
}
}
/**
* @brief reads sectors from disk
*
* @param[in] pdrv drive number to identify the drive
* @param[out] buff Data buffer to store read data
* @param[in] sector Start sector in LBA
* @param[in] count Number of sectors to read
*
* @return RES_OK if no error occurred
* @return RES_NOTRDY if data wasn't read completely
*/
DRESULT disk_read(BYTE pdrv, BYTE *buff, DWORD sector, UINT count)
{
dummy_volume_t *volume = get_volume_file(pdrv);
if ((volume != NULL) && volume->opened) {
/* set read pointer to secor equivalent position */
if (fseek(volume->fd, sector * FIXED_BLOCK_SIZE, SEEK_SET) == 0) {
if (fread(buff, FIXED_BLOCK_SIZE, count, volume->fd) == count) {
return RES_OK;
}
else {
DEBUG("diskio_native.c: disk_read: fread: "
"errno: 0x%08x\n", errno);
}
}
else {
DEBUG("diskio_native.c: disk_read: fseek: errno: 0x%08x\n", errno);
}
}
return RES_NOTRDY;
}
/**
* @brief writes sectors to disk
*
* @param[in] pdrv Physical drive nmuber to identify the drive
* @param[in] buff Data to be written
* @param[in] sector Start sector in LBA
* @param[in] count Number of sectors to write
*
* @return RES_OK if no error occurred
* @return RES_NOTRDY if data wasn't written completely
*/
DRESULT disk_write(BYTE pdrv, const BYTE *buff, DWORD sector, UINT count)
{
dummy_volume_t *volume = get_volume_file(pdrv);
if ((volume != NULL) && volume->opened) {
/* set write pointer to secor equivalent position */
if (fseek(volume->fd, sector * FIXED_BLOCK_SIZE, SEEK_SET) == 0) {
if (fwrite(buff, FIXED_BLOCK_SIZE, count, volume->fd) == count) {
if (fflush(volume->fd) == 0) {
return RES_OK;
}
else {
DEBUG("diskio_native.c: disk_write: fflush: "
"errno: 0x%08x\n", errno);
}
}
else {
DEBUG("diskio_native.c: disk_write: fwrite: "
"errno: 0x%08x\n", errno);
}
}
else {
DEBUG("diskio_native.c: disk_write: fseek: errno: 0x%08x\n", errno);
}
}
return RES_NOTRDY;
}
/**
* @brief perform miscellaneous low-level control functions
*
* @param[in] pdrv Physical drive nmuber (0..)
* @param[in out] cmd Control code
* @param[in] sector Buffer to send/receive control data
*
* @return RES_OK if no error occurred
* @return RES_ERROR if an error occurred
* @return RES_PARERR if an error occurred
*/
DRESULT disk_ioctl(
BYTE pdrv, /* */
BYTE cmd, /* */
void *buff /* Buffer to send/receive control data */
)
{
(void) pdrv; /* prevent warning about unused param */
(void) buff; /* prevent warning about unused param */
switch (cmd) {
#if (_FS_READONLY == 0)
case CTRL_SYNC:
/* r/w is always finished within r/w-functions */
return RES_OK;
#endif
#if (_MAX_SS != _MIN_SS)
case GET_SECTOR_SIZE;
*buff = FIXED_BLOCK_SIZE;
return RES_OK;
#endif
#if (_USE_MKFS == 1)
case GET_SECTOR_COUNT:
dummy_volume_t *volume = get_volume_file(pdrv);
if ((volume != NULL) && volume->opened) {
struct stat s;
if (stat(volume->image_path, &s) == 0) {
*(DWORD *)buff = s.st_size / FIXED_BLOCK_SIZE;
return RES_OK;
}
}
return RES_ERROR;
case GET_BLOCK_SIZE:
*(DWORD *)buff = FIXED_BLOCK_SIZE;
return RES_OK;
#endif
#if (_USE_TRIM == 1)
case CTRL_TRIM:
return RES_OK;
#endif
}
return RES_PARERR;
}

11
pkg/fatfs/fatfs_diskio/sdcard_spi/Makefile

@ -0,0 +1,11 @@
MODULE = fatfs_diskio_sdcard_spi
USEMODULE += sdcard_spi
#if periph_rtc is available use it. Otherwise use static timestamps
ifneq (, $(filter $(periph_rtc), $(FEATURES_PROVIDED)))
CFLAGS += -DFATFS_RTC_AVAILABLE
USEMODULE += periph_rtc
endif
include $(RIOTBASE)/Makefile.base

207
pkg/fatfs/fatfs_diskio/sdcard_spi/sdcard_spi_diskio.c

@ -0,0 +1,207 @@
/*
* Copyright (C) 2016 Michel Rottleuthner <michel.rottleuthner@haw-hamburg.de>
*
* 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 sys_fatfs_diskio
* @{
*
* @file
* @brief Implementation of fatfs interface that supports sdcard_spi driver
* based on low level disk I/O module example for FatFs by ChaN, 2016
*
* @author Michel Rottleuthner <michel.rottleuthner@haw-hamburg.de>
*
* @}
*/
#include "fatfs/diskio.h" /* FatFs lower layer API */
#include "fatfs_diskio_common.h"
#include "fatfs/ffconf.h"
#include "fatfs/integer.h"
#include "sdcard_spi.h"
#include "sdcard_spi_internal.h"
#include "sdcard_spi_params.h"
#include <stdio.h>
#include <time.h>
#include "periph_conf.h"
#include "periph/rtc.h"
#include "xtimer.h"
#include "debug.h"
#define NUM_OF_SD_CARDS (sizeof(sdcard_spi_params) / sizeof(sdcard_spi_params[0]))
extern sdcard_spi_t sdcard_spi_devs[NUM_OF_SD_CARDS];
static inline sdcard_spi_t *get_sd_card(int idx)
{
if (idx < NUM_OF_SD_CARDS) {
return &(sdcard_spi_devs[idx]);
}
return NULL;
}
/**
* @brief returns the status of the disk
*
* @param[in] pdrv drive number to identify the drive
*
* @return STA_NODISK if no disk exists with the given id
* @return 0 if disk is initialized
* @return STA_NOINIT if disk id exists, but disk isn't initialized
*/
DSTATUS disk_status(BYTE pdrv)
{
sdcard_spi_t *card = get_sd_card(pdrv);
if (card == NULL) {
return STA_NODISK;
}
else if (card->init_done) {
return FATFS_DISKIO_DSTASTUS_OK;
}
return STA_NOINIT;
}
/**
* @brief initializes the disk
*
* @param[in] pdrv drive number to identify the drive
*
* @return STA_NODISK if no disk exists with the given id
* @return 0 if disk was initialized sucessfully
* @return STA_NOINIT if disk id exists, but couldn't be initialized
*/
DSTATUS disk_initialize(BYTE pdrv)
{
sdcard_spi_t *card = get_sd_card(pdrv);
if (card == NULL) {
return STA_NODISK;
}
else if (sdcard_spi_init(card, &sdcard_spi_params[pdrv]) == 0) {
return FATFS_DISKIO_DSTASTUS_OK;
}
return STA_NOINIT;
}
/**
* @brief reads sectors from disk
*
* @param[in] pdrv drive number to identify the drive
* @param[out] buff Data buffer to store read data
* @param[in] sector Start sector in LBA
* @param[in] count Number of sectors to read
*
* @return RES_OK if no error occurred
* @return RES_NOTRDY if data wasn't read completely
*/
DRESULT disk_read(BYTE pdrv, BYTE *buff, DWORD sector, UINT count)
{
sdcard_spi_t *card = get_sd_card(pdrv);
if ((card != NULL) && card->init_done) {
sd_rw_response_t state;
if (count != sdcard_spi_read_blocks(card, sector, (char *)buff,
SD_HC_BLOCK_SIZE, count, &state)) {
printf("[ERROR] disk_read: sdcard_spi_read_blocks: %d\n", state);
return RES_NOTRDY;
}
return RES_OK;
}
return RES_NOTRDY;
}
/**
* @brief writes sectors to disk
*
* @param[in] pdrv Physical drive nmuber to identify the drive
* @param[in] buff Data to be written
* @param[in] sector Start sector in LBA
* @param[in] count Number of sectors to write
*
* @return RES_OK if no error occurred
* @return RES_NOTRDY if data wasn't written completely
*/
DRESULT disk_write(BYTE pdrv, const BYTE *buff, DWORD sector, UINT count)
{
sdcard_spi_t *card = get_sd_card(pdrv);
if ((card != NULL) && card->init_done) {
sd_rw_response_t state;
if (count != sdcard_spi_write_blocks(card, sector, (char *)buff,
SD_HC_BLOCK_SIZE, count, &state)) {
printf("[ERROR] disk_write: sdcard_spi_write_blocks: %d\n", state);
return RES_NOTRDY;
}
return RES_OK;
}
return RES_NOTRDY;
}
/**
* @brief perform miscellaneous low-level control functions
*
* @param[in] pdrv Physical drive nmuber (0..)
* @param[in out] cmd Control code
* @param[in] sector Buffer to send/receive control data
*
* @return RES_OK if no error occurred
* @return RES_ERROR if an error occurred
* @return RES_PARERR if an error occurred
*/
DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff)
{
#if (_USE_MKFS == 1)
sdcard_spi_t *card = get_sd_card(pdrv);
#endif
switch (cmd) {
#if (_FS_READONLY == 0)
case CTRL_SYNC:
/* r/w is always finished within r/w-functions of sdcard_spi */
return RES_OK;
#endif
#if (_USE_MKFS == 1)
case GET_SECTOR_COUNT:
if ((card != NULL) && card->init_done) {
*(DWORD *)buff = sdcard_spi_get_sector_count(card);
return RES_OK;
}
else {
return RES_ERROR;
}
case GET_BLOCK_SIZE:
if ((card != NULL) && card->init_done) {
/* erase block size in unit of sector */
*(DWORD *)buff = sdcard_spi_get_au_size(card) / SD_HC_BLOCK_SIZE;
return RES_OK;
}
*(DWORD *)buff = 0;
return RES_ERROR;
#endif
#if (_MAX_SS != _MIN_SS)
case GET_SECTOR_SIZE:
*buff = SD_HC_BLOCK_SIZE;
return RES_OK;
#endif
#if (_USE_TRIM == 1)
case CTRL_TRIM:
return RES_OK;
#endif
}
return RES_PARERR;
}

11
pkg/fatfs/patches/disable_rtc.patch

@ -0,0 +1,11 @@
--- ffconf.h 2016-09-04 21:41:04.000000000 +0200
+++ ffconf_patched.h 2016-11-29 22:04:09.000000000 +0100
@@ -215,7 +215,7 @@
/ Note that enabling exFAT discards C89 compatibility. */
-#define _FS_NORTC 0
+#define _FS_NORTC 1
#define _NORTC_MON 1
#define _NORTC_MDAY 1
#define _NORTC_YEAR 2016

11
pkg/fatfs/patches/enable_fs_tiny.patch

@ -0,0 +1,11 @@
--- ./bin/pkg/native/fatfs/ffconf.h 2017-05-08 12:19:04.813286471 +0200
+++ ./bin/pkg/native/fatfs/ffconf_patched.h 2017-05-08 12:19:28.785574968 +0200
@@ -202,7 +202,7 @@
/ System Configurations
/---------------------------------------------------------------------------*/
-#define _FS_TINY 0
+#define _FS_TINY 1
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
/ At the tiny configuration, size of file object (FIL) is reduced _MAX_SS bytes.
/ Instead of private sector buffer eliminated from the file object, common sector

11
pkg/fatfs/patches/enable_use_lable.patch

@ -0,0 +1,11 @@
--- ffconf.h 2016-10-14 16:11:35.060659327 +0200
+++ ffconf_patched.h 2016-10-17 12:17:56.767995083 +0200
@@ -56,7 +56,7 @@
/ (0:Disable or 1:Enable) Also _FS_READONLY needs to be 0 to enable this option. */
-#define _USE_LABEL 0
+#define _USE_LABEL 1
/* This option switches volume label functions, f_getlabel() and f_setlabel().
/ (0:Disable or 1:Enable) */

11
pkg/fatfs/patches/enable_use_mkfs.patch

@ -0,0 +1,11 @@
--- ffconf.h 2016-12-20 19:46:33.302977112 +0100
+++ ffconf_patched.h 2016-12-20 19:57:08.246791926 +0100
@@ -39,7 +39,7 @@
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
-#define _USE_MKFS 0
+#define _USE_MKFS 1
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */

194
pkg/fatfs/patches/fix_for_guards.patch

@ -0,0 +1,194 @@
--- ./bin/pkg/airfy-beacon/fatfs/ff.c 2016-09-04 21:41:04.000000000 +0200
+++ ./bin/pkg/airfy-beacon/fatfs/ff_patched.c 2017-05-08 21:38:41.707271829 +0200
@@ -784,7 +784,7 @@
{
UINT i;
- for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ;
+ for (i = 0; i < _FS_LOCK && Files[i].fs; i++) {} ;
return (i == _FS_LOCK) ? 0 : 1;
}
@@ -805,7 +805,7 @@
}
if (i == _FS_LOCK) { /* Not opened. Register it as new. */
- for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ;
+ for (i = 0; i < _FS_LOCK && Files[i].fs; i++) {} ;
if (i == _FS_LOCK) return 0; /* No free entry to register (int err) */
Files[i].fs = dp->obj.fs;
Files[i].clu = dp->obj.sclust;
@@ -1270,7 +1270,7 @@
#if _FS_EXFAT || _USE_TRIM
if (ecl + 1 == nxt) { /* Is next cluster contiguous? */
ecl = nxt;
- } else { /* End of contiguous cluster block */
+ } else { /* End of contiguous cluster block */
#if _FS_EXFAT
if (fs->fs_type == FS_EXFAT) {
res = change_bitmap(fs, scl, ecl - scl + 1, 0); /* Mark the cluster block 'free' on the bitmap */
@@ -1978,12 +1978,12 @@
}
-#if !_FS_READONLY || _FS_RPATH != 0
+#if !_FS_READONLY || _FS_RPATH != 0
/*------------------------------------------------*/
/* exFAT: Load the object's directory entry block */
/*------------------------------------------------*/
static
-FRESULT load_obj_dir (
+FRESULT load_obj_dir (
DIR* dp, /* Blank directory object to be used to access containing direcotry */
const _FDID* obj /* Object with containing directory information */
)
@@ -2254,7 +2254,7 @@
if (dp->fn[NSFLAG] & (NS_DOT | NS_NONAME)) return FR_INVALID_NAME; /* Check name validity */
- for (nlen = 0; fs->lfnbuf[nlen]; nlen++) ; /* Get lfn length */
+ for (nlen = 0; fs->lfnbuf[nlen]; nlen++) {} ; /* Get lfn length */
#if _FS_EXFAT
if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
@@ -2623,7 +2623,7 @@
/* Create SFN in directory form */
mem_set(dp->fn, ' ', 11);
- for (si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++) ; /* Strip leading spaces and dots */
+ for (si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++) {} ; /* Strip leading spaces and dots */
if (si) cf |= NS_LOSS | NS_LFN;
while (di && lfn[di - 1] != '.') di--; /* Find extension (di<=si: no extension) */
@@ -2866,10 +2866,10 @@
if (*path) { /* If the pointer is not a null */
- for (tt = *path; (UINT)*tt >= (_USE_LFN ? ' ' : '!') && *tt != ':'; tt++) ; /* Find ':' in the path */
+ for (tt = *path; (UINT)*tt >= (_USE_LFN ? ' ' : '!') && *tt != ':'; tt++) {} ; /* Find ':' in the path */
if (*tt == ':') { /* If a ':' is exist in the path name */
tp = *path;
- i = *tp++ - '0';
+ i = *tp++ - '0';
if (i < 10 && tp == tt) { /* Is there a numeric drive id? */
if (i < _VOLUMES) { /* If a drive id is found, get the value and strip it */
vol = (int)i;
@@ -3017,7 +3017,7 @@
if (fmt == 1) {
QWORD maxlba;
- for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ; /* Check zero filler */
+ for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) {} ; /* Check zero filler */
if (i < BPB_ZeroedEx + 53) return FR_NO_FILESYSTEM;
if (ld_word(fs->win + BPB_FSVerEx) != 0x100) return FR_NO_FILESYSTEM; /* Check exFAT revision (Must be 1.0) */
@@ -3891,7 +3891,7 @@
if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */
if (res != FR_OK) break;
get_fileinfo(&dj, &fno); /* Get the directory name and push it to the buffer */
- for (n = 0; fno.fname[n]; n++) ;
+ for (n = 0; fno.fname[n]; n++) {} ;
if (i < n + 3) {
res = FR_NOT_ENOUGH_CORE; break;
}
@@ -4939,7 +4939,7 @@
dj.obj.fs = fs;
/* Get length of given volume label */
- for (slen = 0; (UINT)label[slen] >= ' '; slen++) ; /* Get name length */
+ for (slen = 0; (UINT)label[slen] >= ' '; slen++) {} ; /* Get name length */
#if _FS_EXFAT
if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
@@ -4960,7 +4960,7 @@
} else
#endif
{ /* On the FAT12/16/32 volume */
- for ( ; slen && label[slen - 1] == ' '; slen--) ; /* Remove trailing spaces */
+ for ( ; slen && label[slen - 1] == ' '; slen--) {} ; /* Remove trailing spaces */
if (slen) { /* Is there a volume label to be set? */
dirvn[0] = 0; i = j = 0; /* Create volume label in directory form */
do {
@@ -5335,7 +5335,7 @@
if (ch != si) {
si++; break; /* Store the up-case char if exist */
}
- for (j = 1; (WCHAR)(si + j) && (WCHAR)(si + j) == ff_wtoupper((WCHAR)(si + j)); j++) ; /* Get run length of no-case block */
+ for (j = 1; (WCHAR)(si + j) && (WCHAR)(si + j) == ff_wtoupper((WCHAR)(si + j)); j++) {} ; /* Get run length of no-case block */
if (j >= 128) {
ch = 0xFFFF; st = 2; break; /* Compress the no-case block if run is >= 128 */
}
@@ -5366,8 +5366,8 @@
nb = tbl[0] + tbl[1] + tbl[2]; /* Number of clusters in-use by system */
do {
mem_set(buf, 0, szb_buf);
- for (i = 0; nb >= 8 && i < szb_buf; buf[i++] = 0xFF, nb -= 8) ;
- for (b = 1; nb && i < szb_buf; buf[i] |= b, b <<= 1, nb--) ;
+ for (i = 0; nb >= 8 && i < szb_buf; buf[i++] = 0xFF, nb -= 8) {} ;
+ for (b = 1; nb && i < szb_buf; buf[i] |= b, b <<= 1, nb--) {} ;
n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */
if (disk_write(pdrv, buf, sect, n) != RES_OK) return FR_DISK_ERR;
sect += n; nsect -= n;
@@ -5427,8 +5427,8 @@
st_dword(buf + BPB_RootClusEx, 2 + tbl[0] + tbl[1]); /* Root dir cluster # */
st_dword(buf + BPB_VolIDEx, GET_FATTIME()); /* VSN */
st_word(buf + BPB_FSVerEx, 0x100); /* File system version (1.00) */
- for (buf[BPB_BytsPerSecEx] = 0, i = ss; i >>= 1; buf[BPB_BytsPerSecEx]++) ; /* Log2 of sector size [byte] */
- for (buf[BPB_SecPerClusEx] = 0, i = au; i >>= 1; buf[BPB_SecPerClusEx]++) ; /* Log2 of cluster size [sector] */
+ for (buf[BPB_BytsPerSecEx] = 0, i = ss; i >>= 1; buf[BPB_BytsPerSecEx]++) {} ; /* Log2 of sector size [byte] */
+ for (buf[BPB_SecPerClusEx] = 0, i = au; i >>= 1; buf[BPB_SecPerClusEx]++) {} ; /* Log2 of cluster size [sector] */
buf[BPB_NumFATsEx] = 1; /* Number of FATs */
buf[BPB_DrvNumEx] = 0x80; /* Drive number (for int13) */
st_word(buf + BS_BootCodeEx, 0xFEEB); /* Boot code (x86) */
@@ -5441,13 +5441,13 @@
mem_set(buf, 0, ss);
st_word(buf + ss - 2, 0xAA55); /* Signature (placed at end of sector) */
for (j = 1; j < 9; j++) {
- for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ; /* VBR checksum */
+ for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) {} ; /* VBR checksum */
if (disk_write(pdrv, buf, sect++, 1) != RES_OK) return FR_DISK_ERR;
}
/* OEM/Reserved record (+9..+10) */
mem_set(buf, 0, ss);
for ( ; j < 11; j++) {
- for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ; /* VBR checksum */
+ for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) {} ; /* VBR checksum */
if (disk_write(pdrv, buf, sect++, 1) != RES_OK) return FR_DISK_ERR;
}
/* Sum record (+11) */
@@ -5464,7 +5464,7 @@
if (fmt == FS_FAT32) { /* FAT32 volume */
if (!pau) { /* au auto-selection */
n = sz_vol / 0x20000; /* Volume size in unit of 128KS */
- for (i = 0, pau = 1; cst32[i] && cst32[i] <= n; i++, pau <<= 1) ; /* Get from table */
+ for (i = 0, pau = 1; cst32[i] && cst32[i] <= n; i++, pau <<= 1) {} ; /* Get from table */
}
n_clst = sz_vol / pau; /* Number of clusters */
sz_fat = (n_clst * 4 + 8 + ss - 1) / ss; /* FAT size [sector] */
@@ -5474,7 +5474,7 @@
} else { /* FAT12/16 volume */
if (!pau) { /* au auto-selection */
n = sz_vol / 0x1000; /* Volume size in unit of 4KS */
- for (i = 0, pau = 1; cst[i] && cst[i] <= n; i++, pau <<= 1) ; /* Get from table */
+ for (i = 0, pau = 1; cst[i] && cst[i] <= n; i++, pau <<= 1) {} ; /* Get from table */
}
n_clst = sz_vol / pau;
if (n_clst > MAX_FAT12) {
@@ -5682,7 +5682,7 @@
if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR;
/* Determine the CHS without any care of the drive geometry */
- for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ;
+ for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) {} ;
if (n == 256) n--;
e_hd = n - 1;
sz_cyl = 63 * n;
@@ -5991,7 +5991,7 @@
switch (d) { /* Type is... */
case 'S' : /* String */
p = va_arg(arp, TCHAR*);
- for (j = 0; p[j]; j++) ;
+ for (j = 0; p[j]; j++) {} ;
if (!(f & 2)) {
while (j++ < w) putc_bfd(&pb, ' ');
}

5
pkg/fatfs/patches/remove_int_type.patch

@ -0,0 +1,5 @@
17a18,19
> /* removed because it creates a naming clash with cc2538_rfcore.h
> * and it isn't used anyway
18a21
> */

11
pkg/fatfs/patches/set_code_page_to_ascii.patch

@ -0,0 +1,11 @@
--- ffconf.h 2016-10-14 16:11:35.060659327 +0200
+++ ffconf_patched.h 2016-10-17 12:16:11.967672504 +0200
@@ -69,7 +69,7 @@
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/
-#define _CODE_PAGE 932
+#define _CODE_PAGE 1
/* This option specifies the OEM code page to be used on the target system.
/ Incorrect setting of the code page can cause a file open failure.
/

7
sys/Makefile

@ -82,23 +82,18 @@ endif
ifneq (,$(filter tcp,$(USEMODULE)))
DIRS += net/transport_layer/tcp
endif
ifneq (,$(filter hamming256,$(USEMODULE)))
DIRS += ecc/hamming256
endif
ifneq (,$(filter uhcpc,$(USEMODULE)))
DIRS += net/application_layer/uhcp
endif
ifneq (,$(filter gnrc_uhcpc,$(USEMODULE)))
DIRS += net/gnrc/application_layer/uhcpc
endif
ifneq (,$(filter sntp,$(USEMODULE)))
DIRS += net/application_layer/sntp
endif
ifneq (,$(filter netopt,$(USEMODULE)))
DIRS += net/crosslayer/netopt
endif
@ -117,11 +112,9 @@ endif
ifneq (,$(filter sock_dns,$(USEMODULE)))
DIRS += net/application_layer/dns
endif
ifneq (,$(filter constfs,$(USEMODULE)))
DIRS += fs/constfs
endif
ifneq (,$(filter devfs,$(USEMODULE)))
DIRS += fs/devfs
endif

33
tests/pkg_fatfs/Makefile

@ -0,0 +1,33 @@
APPLICATION = pkg_fatfs
include ../Makefile.tests_common
USEMODULE += shell
BOARD ?= native
# whitelist can be removed when the problem described in #6063 was resolved
# this list is composed of boards that support spi + native
BOARD_WHITELIST := native airfy-beacon arduino-due arduino-duemilanove arduino-mega2560 \
arduino-uno arduino-zero avsextrem cc2538dk fox frdm-k64f iotlab-a8-m3 \
iotlab-m3 limifrog-v1 maple-mini msb-430 msb-430h msba2 msbiot mulle \
nrf52840dk nrf52dk nrf6310 nucleo-f072 nucleo-f091 nucleo-f103 \
nucleo-f302 nucleo-f303 nucleo-f334 nucleo-f401 nucleo-f410 nucleo-f411 \
nucleo-f446 nucleo-l053 nucleo-l073 nucleo-l1 nucleo-l476 nucleo144-f207 \
nucleo144-f303 nucleo144-f413 nucleo144-f429 nucleo144-f446 nucleo32-f031 \
nucleo32-f042 nucleo32-f303 nucleo32-l031 nucleo32-l432 openmote-cc2538 \
pba-d-01-kw2x pca10005 remote-pa remote-reva remote-revb samd21-xpro \
saml21-xpro samr21-xpro sodaq-autonomo spark-core stm32f0discovery \
stm32f3discovery stm32f4discovery telosb udoo waspmote-pro weio \
wsn430-v1_3b wsn430-v1_4 yunjia-nrf51822 z1
ifeq ($(BOARD),native)
USEMODULE += fatfs_diskio_native
FATFS_DISKIO_NATIVE_DEFAULT_FILE ?= \"riot_fatfs_disk.img\"
else
USEMODULE += fatfs_diskio_sdcard_spi
USEMODULE += auto_init_storage
endif
USEPKG += fatfs
include $(RIOTBASE)/Makefile.include

27
tests/pkg_fatfs/README.md

@ -0,0 +1,27 @@
Using FatFs on native
=======================================
To use this test on native you need a FAT image file. The following commands can be used to create such an image and mount it afterwards so you can add files to your virtual disk that can later be accessed from RIOT.
1. create an enpty file with a size of 128MB
`dd if=/dev/zero of=riot_fatfs_disk.img bs=1M count=128`
2. create a FAT file system within the file
`mkfs.fat riot_fatfs_disk.img`
3. create a mount point which you can use later to add files with your file browser
`sudo mkdir -p /media/riot_fatfs_disk`
4. give all needed rights for that mountpoint to your user
`sudo chown <your_username> /media/riot_fatfs_disk/`
5. mount the image -> the disk should now be accessible from any program
`sudo mount -o loop,umask=000 riot_fatfs_disk.img /media/riot_fatfs_disk`
6. When you are done -> unmount the disk before you use it under RIOT
`sudo umount /media/riot_fatfs_disk`
#####NOTE:
You shouldn't leave the image mounted while you use it in RIOT, the abstraction layer between FatFs and the image file mimics a dumb block device
(i.e. behaves much like the devices that are actually meant to be used with FAT) That implies it doesn't show any modifications in RIOT that you perform on your OS and the other way round. So always remember to mount/unmount correctly or your FS will probably get damaged.
To tell RIOT where your image file is located you can use the image_path entry in the volume_files array in fatfs_diskio_native/diskio.c.

381
tests/pkg_fatfs/main.c

@ -0,0 +1,381 @@
/*
* Copyright (C) 2016 Michel Rottleuthner <michel.rottleuthner@haw-hamburg.de>
*
* 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 tests
* @{
*
* @file
* @brief Test application for the fatfs package.
*
* @author Michel Rottleuthner <michel.rottleuthner@haw-hamburg.de>
*
* @}
*/
#ifdef FATFS_RTC_AVAILABLE
#include "periph/rtc.h"
#endif
#include "fatfs/ff.h"
#include "shell.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include <stdbool.h>
#define TEST_FATFS_RTC_YEAR_OFFSET 1900
#define TEST_FATFS_READ_BUFFER_SIZE 64
#define TEST_FATFS_MAX_LBL_SIZE 64
#define TEST_FATFS_MAX_VOL_STR_LEN 8
#define TEST_FATFS_FIXED_SECTOR_SIZE 512
#define TEST_FATFS_FATENT_OFFSET 2
#define TEST_FATFS_SHIFT_B_TO_GIB 30
#define TEST_FATFS_SHIFT_B_TO_MIB 20
#define TEST_FATFS_RTC_MON_OFFSET 1
#define TEST_FATFS_RTC_YEAR 2000
#define TEST_FATFS_RTC_MON 1
#define TEST_FATFS_RTC_DAY 1
#define TEST_FATFS_RTC_H 0
#define TEST_FATFS_RTC_M 0
#define TEST_FATFS_RTC_S 0
#define IEC_KIBI 1024
#define SI_KILO 1000
FATFS fat_fs; /* FatFs work area needed for each volume */
static int _mount(int argc, char **argv)
{
int vol_idx;
if (argc != 2) {
printf("usage: %s <volume_idx>\n", argv[0]);
return -1;
}
vol_idx = (int)atoi(argv[1]);
char volume_str[TEST_FATFS_MAX_VOL_STR_LEN];
sprintf(volume_str, "%d:/", vol_idx);
puts("mounting file system image...");
/* "0:/" points to the root dir of drive 0 */
FRESULT mountresu = f_mount(&fat_fs, volume_str, 1);
TCHAR label[TEST_FATFS_MAX_LBL_SIZE];
if (mountresu == FR_OK) {
puts("[OK]");
if (f_getlabel("", label, NULL) == FR_OK) {
printf("Volume name: %s\n", label);
}
FATFS *fs;
DWORD fre_clust;
/* Get volume information and free clusters of selected drive */
if (f_getfree(volume_str, &fre_clust, &fs) != FR_OK) {
puts("wasn't able to get volume size info!");
}
else {
#if _MAX_SS == _MIN_SS
uint16_t sector_size = TEST_FATFS_FIXED_SECTOR_SIZE;
#else
uint16_t sector_size = fs->ssize;
#endif
uint64_t total_bytes = (fs->n_fatent - TEST_FATFS_FATENT_OFFSET) * fs->csize;
total_bytes *= sector_size;
uint64_t free_bytes = fre_clust * fs->csize;
free_bytes *= sector_size;
uint32_t to_gib_i = total_bytes >> TEST_FATFS_SHIFT_B_TO_GIB;
uint32_t to_gib_f = ((((total_bytes >> TEST_FATFS_SHIFT_B_TO_MIB) - to_gib_i * IEC_KIBI)
* SI_KILO) / IEC_KIBI);
uint32_t fr_gib_i = free_bytes >> TEST_FATFS_SHIFT_B_TO_GIB;
uint32_t fr_gib_f = ((((free_bytes >> TEST_FATFS_SHIFT_B_TO_MIB) - fr_gib_i * IEC_KIBI)
* SI_KILO) / IEC_KIBI);
printf("%" PRIu32 ",%03" PRIu32 " GiB of %" PRIu32 ",%03" PRIu32
" GiB available\n", fr_gib_i, fr_gib_f, to_gib_i, to_gib_f);
}
}
else {
puts("[FAILED]");
switch (mountresu) {
case FR_NO_FILESYSTEM:
puts("no filesystem -> you need to format the card to FAT");
break;
case FR_DISK_ERR:
puts("error in the low-level disk driver!");
break;
default:
printf("error %d -> see ff.h of fatfs package for "
"further details\n", mountresu);
}
return -1;
}
return 0;
}
static int _touch(int argc, char **argv)
{
FIL fd;
if (argc != 2) {
printf("usage: %s <filename>\n", argv[0]);
return -1;
}
FRESULT open_resu = f_open(&fd, argv[1], FA_WRITE | FA_CREATE_ALWAYS);
if (open_resu == FR_OK) {
FRESULT close_resu = f_close(&fd);
if (close_resu == FR_OK) {
puts("[OK]");
return 0;
}
printf("[FAILED] (f_close error %d)\n", close_resu);
return -2;
}
printf("[FAILED] (f_open error %d)\n", open_resu);
return -3;
}
static int _read(int argc, char **argv)
{
FIL fd;
int resu = 0;
if ((argc < 2) || (argc > 3)) {
printf("usage: %s <filename> [<len>]\n", argv[0]);
return -1;
}
FRESULT open_resu = f_open(&fd, argv[1], FA_READ | FA_OPEN_EXISTING);
if (open_resu == FR_OK) {
UINT read_chunk;
uint32_t len = ((argc == 3) ? (uint32_t)atoi(argv[2]) : f_size(&fd));
char buffer[TEST_FATFS_READ_BUFFER_SIZE];
for (uint32_t read = 0; read < len; read += read_chunk) {
uint32_t to_read = len - read;
if (to_read > sizeof(buffer)) {
to_read = sizeof(buffer);
}
FRESULT lseek_resu = f_lseek(&fd, read);
if (lseek_resu != FR_OK) {
printf("[FAILED] f_lseek error %d\n", lseek_resu);
resu = -3;
break;
}
FRESULT read_resu = f_read(&fd, buffer, to_read, &read_chunk);
if (read_resu != FR_OK) {
printf("[FAILED] (f_read error %d)\n", read_resu);
resu = -4;
break;
}
for (uint32_t i = 0; i < read_chunk; i++) {
printf("%c", buffer[i]);
}
}
puts("");
FRESULT close_resu = f_close(&fd);
if (close_resu == FR_OK) {
puts("[OK]");
resu = 0;
}
else {
printf("[FAILED] (f_close error %d)\n", open_resu);
resu = -5;
}
}
else {
printf("[FAILED] (f_open error %d)\n", open_resu);
resu = -2;
}
return resu;
}
static int _write(int argc, char **argv)
{
FIL fd;
UINT bw;
if (argc != 3) {
printf("usage: %s <filename> <string>\n", argv[0]);
return -1;
}
uint32_t len = strlen(argv[2]);
FRESULT open_resu = f_open(&fd, argv[1], FA_WRITE | FA_OPEN_APPEND);
if (open_resu == FR_OK) {
printf("writing %" PRId32 " bytes to %s ...", len, argv[1]);
FRESULT write_resu = f_write(&fd, argv[2], len, &bw);
if ((write_resu != FR_OK) || (bw < len)) {
printf("[FAILED] (f_write error %d)\n", write_resu);
return -2;
}
else {
FRESULT close_resu = f_close(&fd);
if (close_resu == FR_OK) {
puts("[OK]");
return 0;
}
printf("[FAILED] (f_close error %d)\n", open_resu);
return -3;
}
}
printf("[FAILED] (f_open error %d)\n", open_resu);
return -1;
}
static int _ls(int argc, char **argv)
{
char *path;
FRESULT res;
DIR dir;
static FILINFO fno;
if (argc == 2) {
path = argv[1];
}
else {
path = "/";
}
res = f_opendir(&dir, path);/* Open the directory */
if (res == FR_OK) {
while (true) {
res = f_readdir(&dir, &fno); /* Read a directory item */
if ((res != FR_OK) || fno.fname[0] == 0) {
break; /* Break on error or end of dir */
}
if (fno.fattrib & AM_DIR) { /* if this element is a directory */
printf("%s%s/\n", path, fno.fname);
}
else {
printf("%s/%s\n", path, fno.fname);
}
}
f_closedir(&dir);
return 0;
}
printf("[FAILED] error %d\n", res);
return -1;
}
static int _mkfs(int argc, char **argv)
{
int vol_idx;
BYTE opt;
if (argc == 3) {
vol_idx = (int)atoi(argv[1]);
if (strcmp(argv[2], "fat") == 0) {
opt = FM_FAT;
}
else if (strcmp(argv[2], "fat32") == 0) {
opt = FM_FAT32;
}
else if (strcmp(argv[2], "exfat") == 0) {
opt = FM_EXFAT;
}
else {
opt = FM_ANY;
}
}
else {
printf("usage: %s <volume_idx> <fat|fat32|exfat|any>\n", argv[0]);
return -1;
}
char volume_str[TEST_FATFS_MAX_VOL_STR_LEN];
sprintf(volume_str, "%d:/", vol_idx);
BYTE work[_MAX_SS];
puts("formatting media...");
/* au = 0: use default allocation unit size depending on volume size */
FRESULT mkfs_resu = f_mkfs(volume_str, opt, 0, work, sizeof(work));
if (mkfs_resu == FR_OK) {
puts("[OK]");
return 0;
}
printf("[FAILED] error %d\n", mkfs_resu);
return -1;
}
static const shell_command_t shell_commands[] = {
{ "mount", "mount file system", _mount },
{ "mkfs", "format volume", _mkfs },
{ "touch", "create file", _touch },
{ "read", "print file content to console", _read },
{ "write", "append string to file", _write },
{ "ls", "list files", _ls },
{ NULL, NULL, NULL }
};
int main(void)
{
#ifdef FATFS_RTC_AVAILABLE
/* the rtc is used in diskio.c for timestamps of files */
puts("Initializing the RTC driver");
rtc_poweron();
rtc_init();
struct tm time;
time.tm_year = TEST_FATFS_RTC_YEAR - RTC_YEAR_OFFSET; /* years are counted from 1900 */
time.tm_mon = TEST_FATFS_RTC_MON; /* 0 = January, 11 = December */
time.tm_mday = TEST_FATFS_RTC_DAY;
time.tm_hour = TEST_FATFS_RTC_H;
time.tm_min = TEST_FATFS_RTC_M;
time.tm_sec = TEST_FATFS_RTC_S;
printf("Setting RTC to %04d-%02d-%02d %02d:%02d:%02d\n",
time.tm_year + RTC_YEAR_OFFSET,
time.tm_mon + RTC_MON_OFFSET,
time.tm_mday,
time.tm_hour,
time.tm_min,
time.tm_sec);
rtc_set_time(&time);
#endif
char line_buf[SHELL_DEFAULT_BUFSIZE];
shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);
return 0;
}
Loading…
Cancel
Save