diff --git a/Makefile.dep b/Makefile.dep index 383bb7f0893e94bfdaba233d622fb1f15ca1b12b..bdc0cac9b9ba1ee2ee4fdf35c55dee395effebd5 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -669,17 +669,8 @@ ifneq (,$(filter ccn-lite,$(USEPKG))) endif ifneq (,$(filter fatfs_vfs,$(USEMODULE))) - USEPKG += fatfs - USEMODULE += vfs - - 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 + USEMODULE += vfs endif # always select gpio (until explicit dependencies are sorted out) diff --git a/pkg/fatfs/Makefile.dep b/pkg/fatfs/Makefile.dep index 77d06329e0566c2ef72a89b0f402db82e9c29277..73eca11fe61ba081a9ceff155d002160b9b184ab 100644 --- a/pkg/fatfs/Makefile.dep +++ b/pkg/fatfs/Makefile.dep @@ -1,10 +1,6 @@ -ifneq (,$(filter fatfs_diskio_sdcard_spi,$(USEMODULE))) - USEMODULE += sdcard_spi -endif - -ifneq (,$(filter fatfs,$(USEPKG))) - USEMODULE += fatfs_diskio_common -endif +USEMODULE += fatfs_diskio_mtd +USEMODULE += auto_init_storage +USEMODULE += mtd include $(RIOTBASE)/boards/$(BOARD)/Makefile.features diff --git a/pkg/fatfs/Makefile.include b/pkg/fatfs/Makefile.include index 2db484e79978733c334c5dbe8e53c0bdbd359ec4..918fe83c886b62773f8daad7fbebe542a69194d8 100644 --- a/pkg/fatfs/Makefile.include +++ b/pkg/fatfs/Makefile.include @@ -1,19 +1,12 @@ INCLUDES += -I$(PKGDIRBASE) -INCLUDES += -I$(RIOTPKG)/fatfs/fatfs_diskio/common/include +INCLUDES += -I$(RIOTPKG)/fatfs/fatfs_diskio/mtd/include DIRS += $(PKGDIRBASE)/fatfs -DIRS += $(RIOTBASE)/pkg/fatfs/fatfs_diskio/common +DIRS += $(RIOTBASE)/pkg/fatfs/fatfs_diskio/mtd -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 ifneq (,$(filter fatfs_vfs,$(USEMODULE))) - DIRS += $(RIOTBASE)/pkg/fatfs/fatfs_vfs + DIRS += $(RIOTBASE)/pkg/fatfs/fatfs_vfs endif ifeq ($(shell uname -s),Darwin) diff --git a/pkg/fatfs/fatfs_diskio/common/fatfs_diskio_common.c b/pkg/fatfs/fatfs_diskio/common/fatfs_diskio_common.c deleted file mode 100644 index 5e82a7d3d67b3022ca466315060712460362f57a..0000000000000000000000000000000000000000 --- a/pkg/fatfs/fatfs_diskio/common/fatfs_diskio_common.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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" -#include "time.h" -#include "stdint.h" - -#if FATFS_FFCONF_OPT_FS_NORTC == 0 -#include "periph/rtc.h" - -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 diff --git a/pkg/fatfs/fatfs_diskio/common/Makefile b/pkg/fatfs/fatfs_diskio/mtd/Makefile similarity index 54% rename from pkg/fatfs/fatfs_diskio/common/Makefile rename to pkg/fatfs/fatfs_diskio/mtd/Makefile index 0eedefea551905ff295ef40b0e15075b5a664677..0ab82c0041d2213be793ef7a981829b809ead3ca 100644 --- a/pkg/fatfs/fatfs_diskio/common/Makefile +++ b/pkg/fatfs/fatfs_diskio/mtd/Makefile @@ -1,3 +1,3 @@ -MODULE = fatfs_diskio_common +MODULE = fatfs_diskio_mtd include $(RIOTBASE)/Makefile.base diff --git a/pkg/fatfs/fatfs_diskio/common/include/fatfs_diskio_common.h b/pkg/fatfs/fatfs_diskio/mtd/include/fatfs_diskio_mtd.h similarity index 90% rename from pkg/fatfs/fatfs_diskio/common/include/fatfs_diskio_common.h rename to pkg/fatfs/fatfs_diskio/mtd/include/fatfs_diskio_mtd.h index d019e0acddd18b0c37dfd3888530f45390810045..a81ccfd2adcf32782c67112898f847347f0adebf 100644 --- a/pkg/fatfs/fatfs_diskio/common/include/fatfs_diskio_common.h +++ b/pkg/fatfs/fatfs_diskio/mtd/include/fatfs_diskio_mtd.h @@ -15,8 +15,8 @@ * @author Michel Rottleuthner <michel.rottleuthner@haw-hamburg.de> */ -#ifndef FATFS_DISKIO_COMMON_H -#define FATFS_DISKIO_COMMON_H +#ifndef FATFS_DISKIO_MTD_H +#define FATFS_DISKIO_MTD_H #ifdef __cplusplus extern "C" { @@ -41,5 +41,5 @@ extern "C" { } #endif -#endif /* FATFS_DISKIO_COMMON_H */ +#endif /* FATFS_DISKIO_MTD_H */ /** @} */ diff --git a/pkg/fatfs/fatfs_diskio/mtd/mtd_diskio.c b/pkg/fatfs/fatfs_diskio/mtd/mtd_diskio.c new file mode 100644 index 0000000000000000000000000000000000000000..bf985a25213fcdfaa17ee116987f34e9bb5c668e --- /dev/null +++ b/pkg/fatfs/fatfs_diskio/mtd/mtd_diskio.c @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2017 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 diskio interface that supports mtd 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_mtd.h" +#include "fatfs/ffconf.h" +#include "mtd.h" +#include "fatfs/integer.h" +#define ENABLE_DEBUG (0) +#include "debug.h" + +#if FATFS_FFCONF_OPT_FS_NORTC == 0 +#include "periph/rtc.h" +#endif + +/* mtd devices for use by FatFs should be provided by the application */ +extern mtd_dev_t *fatfs_mtd_devs[_VOLUMES]; + +/** + * @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) +{ + DEBUG("disk_status %d\n", pdrv); + if (pdrv >= _VOLUMES) { + return STA_NODISK; + } else if (fatfs_mtd_devs[pdrv]->driver == NULL){ + return STA_NOINIT; + } + + return FATFS_DISKIO_DSTASTUS_OK; +} + +/** + * @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) +{ + DEBUG("disk_initialize %d\n", pdrv); + if (pdrv >= _VOLUMES) { + return STA_NODISK; + } else if (fatfs_mtd_devs[pdrv]->driver == NULL){ + return STA_NOINIT; + } + + return (mtd_init(fatfs_mtd_devs[pdrv]) == 0) ? FATFS_DISKIO_DSTASTUS_OK + : 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_ERROR if data wasn't read completely + * @return RES_PARERR if prdv is invalid or has no mtd-driver set + */ +DRESULT disk_read(BYTE pdrv, BYTE *buff, DWORD sector, UINT count) +{ + DEBUG("disk_read: %d, %lu, %d\n", pdrv, sector, count); + if ((pdrv >= _VOLUMES) || (fatfs_mtd_devs[pdrv]->driver == NULL)) { + return RES_PARERR; + } + + int res = mtd_read(fatfs_mtd_devs[pdrv], buff, + sector * fatfs_mtd_devs[pdrv]->page_size, + count * fatfs_mtd_devs[pdrv]->page_size); + + if (res >= 0) { + uint32_t r_sect = ((unsigned)res) / fatfs_mtd_devs[pdrv]->page_size; + return ((r_sect == count) ? RES_OK : RES_ERROR); + } + + return RES_ERROR; +} + +/** + * @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_ERROR if data wasn't written completely + * @return RES_PARERR if prdv is invalid or has no mtd-driver set + */ +DRESULT disk_write(BYTE pdrv, const BYTE *buff, DWORD sector, UINT count) +{ + DEBUG("disk_write: %d, %lu, %d\n", pdrv, sector, count); + if ((pdrv >= _VOLUMES) || (fatfs_mtd_devs[pdrv]->driver == NULL)) { + return RES_PARERR; + } + + /* erase memory before writing to it */ + int res = mtd_erase(fatfs_mtd_devs[pdrv], + sector * fatfs_mtd_devs[pdrv]->page_size, + count * fatfs_mtd_devs[pdrv]->page_size); + + if (res != 0) { + return RES_ERROR; /* erase failed! */ + } + + res = mtd_write(fatfs_mtd_devs[pdrv], buff, + sector * fatfs_mtd_devs[pdrv]->page_size, + count * fatfs_mtd_devs[pdrv]->page_size); + + if (res >= 0) { + uint32_t w_sect = ((unsigned)res) / fatfs_mtd_devs[pdrv]->page_size; + return ((w_sect == count) ? RES_OK : RES_ERROR); + } + + return RES_ERROR; +} + +/** + * @brief perform miscellaneous low-level control functions + * + * @param[in] pdrv Physical drive nmuber (0.._VOLUMES-1) + * @param[in out] cmd Control code + * @param[in] sector Buffer to send/receive control data + * + * @return RES_OK if no error occurred + * @return RES_PARERR if cmd is unknown or + * prdv is either invalid or has no mtd-driver set + */ +DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) +{ + if ((pdrv >= _VOLUMES) || (fatfs_mtd_devs[pdrv]->driver == NULL)) { + return RES_PARERR; + } + + switch (cmd) { +#if (_FS_READONLY == 0) + case CTRL_SYNC: + /* r/w is always finished within r/w-functions of mtd */ + return RES_OK; +#endif + +#if (_USE_MKFS == 1) + case GET_SECTOR_COUNT: + *(DWORD *)buff = fatfs_mtd_devs[pdrv]->sector_count; + return RES_OK; + + /*Erase block size in number of sectors (1 to 32768 in power of 2). + Return 1 if the erase block size is unknown. */ + case GET_BLOCK_SIZE: + *(DWORD *)buff = fatfs_mtd_devs[pdrv]->pages_per_sector; + return RES_OK; +#endif + +#if (_MAX_SS != _MIN_SS) + case GET_SECTOR_SIZE: + *(DWORD *)buff = fatfs_mtd_devs[pdrv]->page_size; + return RES_OK; +#endif + +#if (_USE_TRIM == 1) + case CTRL_TRIM: + return RES_OK; +#endif + } + + return RES_PARERR; +} + +#if FATFS_FFCONF_OPT_FS_NORTC == 0 +/** + * @brief store local time in a 32-bit bitfiled + * + * @return timestamp as bitfield + */ +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 diff --git a/pkg/fatfs/fatfs_diskio/native/Makefile b/pkg/fatfs/fatfs_diskio/native/Makefile deleted file mode 100644 index f56b6f5f2f75c5513ddb3727aca5e6453b194b48..0000000000000000000000000000000000000000 --- a/pkg/fatfs/fatfs_diskio/native/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -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 diff --git a/pkg/fatfs/fatfs_diskio/native/native_diskio.c b/pkg/fatfs/fatfs_diskio/native/native_diskio.c deleted file mode 100644 index 1951e84a1e1166c2e91594ab8b1e8e312b087fa4..0000000000000000000000000000000000000000 --- a/pkg/fatfs/fatfs_diskio/native/native_diskio.c +++ /dev/null @@ -1,263 +0,0 @@ -/* - * 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/ffconf.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> -#include <sys/stat.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 successfully - * @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 */ - - #if (_USE_MKFS == 1) - dummy_volume_t *volume; - struct stat s; - #endif - - DEBUG("disk_ioctl: %d\n", cmd); - - 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: - volume = get_volume_file(pdrv); - DEBUG("GET_SECTOR_COUNT: volume: %p\n", (void*)volume); - - if ((volume != NULL) && volume->opened) { - if (stat(volume->image_path, &s) == 0) { - *(DWORD *)buff = s.st_size / FIXED_BLOCK_SIZE; - DEBUG("GET_SECTOR_COUNT\n"); - return RES_OK; - } - DEBUG("GET_SECTOR_COUNT: RES_ERROR\n"); - } - return RES_ERROR; - - case GET_BLOCK_SIZE: - *(DWORD *)buff = FIXED_BLOCK_SIZE; - DEBUG("GET_BLOCK_SIZE: %d\n", FIXED_BLOCK_SIZE); - return RES_OK; - #endif - - #if (_USE_TRIM == 1) - case CTRL_TRIM: - return RES_OK; - #endif - } - - return RES_PARERR; -} diff --git a/pkg/fatfs/fatfs_diskio/sdcard_spi/Makefile b/pkg/fatfs/fatfs_diskio/sdcard_spi/Makefile deleted file mode 100644 index 24f8401efa3dcd788f4a8d061a188a498ad0b2f6..0000000000000000000000000000000000000000 --- a/pkg/fatfs/fatfs_diskio/sdcard_spi/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -MODULE = fatfs_diskio_sdcard_spi - -USEMODULE += sdcard_spi - -include $(RIOTBASE)/Makefile.base diff --git a/pkg/fatfs/fatfs_diskio/sdcard_spi/sdcard_spi_diskio.c b/pkg/fatfs/fatfs_diskio/sdcard_spi/sdcard_spi_diskio.c deleted file mode 100644 index 08a484dc2814632772693d8281f050c5dc9d81ac..0000000000000000000000000000000000000000 --- a/pkg/fatfs/fatfs_diskio/sdcard_spi/sdcard_spi_diskio.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * 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 < (int)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 successfully - * @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 ((int)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 ((int)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; -} diff --git a/pkg/fatfs/fatfs_vfs/fatfs_vfs.c b/pkg/fatfs/fatfs_vfs/fatfs_vfs.c index 12fda2f7cb121e9a782756b2aa19c93c73683efa..da304e401a3f644960fb9c800946fe43c63d630e 100644 --- a/pkg/fatfs/fatfs_vfs/fatfs_vfs.c +++ b/pkg/fatfs/fatfs_vfs/fatfs_vfs.c @@ -88,46 +88,44 @@ static int _umount(vfs_mount_t *mountp) static int _unlink(vfs_mount_t *mountp, const char *name) { - char fatfs_abs_path[FATFS_MAX_VOL_STR_LEN + VFS_NAME_MAX + 1]; fatfs_desc_t *fs_desc = (fatfs_desc_t *)mountp->private_data; - snprintf(fatfs_abs_path, sizeof(fatfs_abs_path), "%d:/%s", + snprintf(fs_desc->abs_path_str_buff, FATFS_MAX_ABS_PATH_SIZE, "%d:/%s", fs_desc->vol_idx, name); - return fatfs_err_to_errno(f_unlink(fatfs_abs_path)); + return fatfs_err_to_errno(f_unlink(fs_desc->abs_path_str_buff)); } static int _rename(vfs_mount_t *mountp, const char *from_path, const char *to_path) { - char fatfs_abs_path_f[FATFS_MAX_VOL_STR_LEN + VFS_NAME_MAX + 1]; - char fatfs_abs_path_t[FATFS_MAX_VOL_STR_LEN + VFS_NAME_MAX + 1]; + char fatfs_abs_path_to[FATFS_MAX_ABS_PATH_SIZE]; fatfs_desc_t *fs_desc = (fatfs_desc_t *)mountp->private_data; - snprintf(fatfs_abs_path_f, sizeof(fatfs_abs_path_f), "%d:/%s", + snprintf(fs_desc->abs_path_str_buff, FATFS_MAX_ABS_PATH_SIZE, "%d:/%s", fs_desc->vol_idx, from_path); - snprintf(fatfs_abs_path_t, sizeof(fatfs_abs_path_t), "%d:/%s", + snprintf(fatfs_abs_path_to, sizeof(fatfs_abs_path_to), "%d:/%s", fs_desc->vol_idx, to_path); - return fatfs_err_to_errno(f_rename(fatfs_abs_path_f, fatfs_abs_path_t)); + return fatfs_err_to_errno(f_rename(fs_desc->abs_path_str_buff, + fatfs_abs_path_to)); } static int _open(vfs_file_t *filp, const char *name, int flags, mode_t mode, const char *abs_path) { fatfs_file_desc_t *fd = (fatfs_file_desc_t *)&filp->private_data.buffer[0]; - char fatfs_abs_path[FATFS_MAX_VOL_STR_LEN + VFS_NAME_MAX + 1]; fatfs_desc_t *fs_desc = (fatfs_desc_t *)filp->mp->private_data; - snprintf(fatfs_abs_path, sizeof(fatfs_abs_path), "%d:/%s", fs_desc->vol_idx, - name); + snprintf(fs_desc->abs_path_str_buff, FATFS_MAX_ABS_PATH_SIZE, "%d:/%s", + fs_desc->vol_idx, name); (void) abs_path; (void) mode; /* fatfs can't use mode param with f_open*/ DEBUG("fatfs_vfs.c: _open: private_data = %p, name = %s; flags = 0x%x\n", filp->mp->private_data, name, flags); - strncpy(fd->fname, fatfs_abs_path, VFS_NAME_MAX); + strncpy(fd->fname, fs_desc->abs_path_str_buff, VFS_NAME_MAX); uint8_t fatfs_flags = 0; @@ -153,7 +151,9 @@ static int _open(vfs_file_t *filp, const char *name, int flags, mode_t mode, fatfs_flags |= FA_OPEN_EXISTING; } - FRESULT open_resu = f_open(&fd->file, fatfs_abs_path, fatfs_flags); + FRESULT open_resu = f_open(&fd->file, fs_desc->abs_path_str_buff, + fatfs_flags); + if (open_resu == FR_OK) { DEBUG("[OK]"); } @@ -247,17 +247,16 @@ static off_t _lseek(vfs_file_t *filp, off_t off, int whence) static int _fstat(vfs_file_t *filp, struct stat *buf) { fatfs_file_desc_t *fd = (fatfs_file_desc_t *)filp->private_data.buffer; - char fatfs_abs_path[FATFS_MAX_VOL_STR_LEN + VFS_NAME_MAX + 1]; fatfs_desc_t *fs_desc = (fatfs_desc_t *)filp->mp->private_data; FILINFO fi; FRESULT res; - snprintf(fatfs_abs_path, sizeof(fatfs_abs_path), "%d:/%s", fs_desc->vol_idx, - fd->fname); + snprintf(fs_desc->abs_path_str_buff, FATFS_MAX_ABS_PATH_SIZE, "%d:/%s", + fs_desc->vol_idx, fd->fname); memset(buf, 0, sizeof(*buf)); - res = f_stat(fatfs_abs_path, &fi); + res = f_stat(fs_desc->abs_path_str_buff, &fi); if (res != FR_OK) { return fatfs_err_to_errno(res); @@ -266,11 +265,11 @@ static int _fstat(vfs_file_t *filp, struct stat *buf) buf->st_size = fi.fsize; /* set last modification timestamp */ - #ifdef SYS_STAT_H_ +#ifdef SYS_STAT_H _fatfs_time_to_timespec(fi.fdate, fi.ftime, &(buf->st_mtim.tv_sec)); - #else +#else _fatfs_time_to_timespec(fi.fdate, fi.ftime, &(buf->st_mtime)); - #endif +#endif if (fi.fattrib & AM_DIR) { buf->st_mode = S_IFDIR; /**< it's a directory */ @@ -293,14 +292,13 @@ static int _fstat(vfs_file_t *filp, struct stat *buf) static int _opendir(vfs_DIR *dirp, const char *dirname, const char *abs_path) { DIR *dir = (DIR *)&dirp->private_data.buffer; - char fatfs_abs_path[FATFS_MAX_VOL_STR_LEN + VFS_NAME_MAX + 1]; fatfs_desc_t *fs_desc = (fatfs_desc_t *)dirp->mp->private_data; (void) abs_path; - snprintf(fatfs_abs_path, sizeof(fatfs_abs_path), "%d:/%s", fs_desc->vol_idx, - dirname); + snprintf(fs_desc->abs_path_str_buff, FATFS_MAX_ABS_PATH_SIZE, "%d:/%s", + fs_desc->vol_idx, dirname); - return fatfs_err_to_errno(f_opendir(dir, fatfs_abs_path)); + return fatfs_err_to_errno(f_opendir(dir, fs_desc->abs_path_str_buff)); } static int _readdir(vfs_DIR *dirp, vfs_dirent_t *entry) @@ -333,23 +331,23 @@ static int _closedir(vfs_DIR *dirp) static int _mkdir (vfs_mount_t *mountp, const char *name, mode_t mode) { - char fatfs_abs_path[FATFS_MAX_VOL_STR_LEN + VFS_NAME_MAX + 1]; fatfs_desc_t *fs_desc = (fatfs_desc_t *)mountp->private_data; (void) mode; - snprintf(fatfs_abs_path, sizeof(fatfs_abs_path), "%d:/%s", fs_desc->vol_idx, - name); - return fatfs_err_to_errno(f_mkdir(fatfs_abs_path)); + snprintf(fs_desc->abs_path_str_buff, FATFS_MAX_ABS_PATH_SIZE, "%d:/%s", + fs_desc->vol_idx, name); + + return fatfs_err_to_errno(f_mkdir(fs_desc->abs_path_str_buff)); } static int _rmdir (vfs_mount_t *mountp, const char *name) { - char fatfs_abs_path[FATFS_MAX_VOL_STR_LEN + VFS_NAME_MAX + 1]; fatfs_desc_t *fs_desc = (fatfs_desc_t *)mountp->private_data; - snprintf(fatfs_abs_path, sizeof(fatfs_abs_path), "%d:/%s", fs_desc->vol_idx, - name); - return fatfs_err_to_errno(f_unlink(fatfs_abs_path)); + snprintf(fs_desc->abs_path_str_buff, FATFS_MAX_ABS_PATH_SIZE, "%d:/%s", + fs_desc->vol_idx, name); + + return fatfs_err_to_errno(f_unlink(fs_desc->abs_path_str_buff)); } static void _fatfs_time_to_timespec(WORD fdate, WORD ftime, time_t *time) @@ -406,11 +404,11 @@ static int fatfs_err_to_errno(int32_t err) case FR_EXIST: return -EEXIST; case FR_INVALID_OBJECT: - #ifdef EBADFD +#ifdef EBADFD return -EBADFD; - #else +#else return -EINVAL; - #endif +#endif case FR_WRITE_PROTECTED: return -EACCES; case FR_INVALID_DRIVE: diff --git a/sys/include/fs/fatfs.h b/sys/include/fs/fatfs.h index 683959c945b688d769bfd6daea25e2cacb88f37a..f29725c25e4e1c85a45b85d14e491f488bd57f84 100644 --- a/sys/include/fs/fatfs.h +++ b/sys/include/fs/fatfs.h @@ -17,39 +17,42 @@ * @author Michel Rottleuthner <michel.rottleuthner@haw-hamburg.de> */ -#ifndef FATFS_H -#define FATFS_H +#ifndef FS_FATFS_H +#define FS_FATFS_H #ifdef __cplusplus extern "C" { #endif -#ifndef VFS_DIR_BUFFER_SIZE -#define VFS_DIR_BUFFER_SIZE (44) -#endif - -#ifndef VFS_FILE_BUFFER_SIZE -#define VFS_FILE_BUFFER_SIZE (72) -#endif - #include "fatfs/ff.h" #include "vfs.h" #ifndef FATFS_YEAR_OFFSET +/** The year in FatFs timestamps is relative to this offset */ #define FATFS_YEAR_OFFSET (1980) #endif +/** The epoch offset is used to convert between FatFs and time_t timestamps */ #define EPOCH_YEAR_OFFSET (1970) -/** Size of the buffer needed for directory -> should be: sizeof(DIR)*/ +/** Size of the buffer needed for a directory entry -> @attention this should be: sizeof(DIR). + sizeof(DIR) currently isn't used directly because it's not possible to use that within + preprocessor-if (see below) */ #define FATFS_DIR_SIZE (44) -/** the problem with the above is: it's not possible to use sizeof(DIR) as this is later usen in #if (see below) */ -/** Size of the buffer needed for directory -> should be: sizeof(fatfs_file_desc_t)*/ +/** Size of the buffer needed for directory + -> should be: sizeof(fatfs_file_desc_t) */ #define FATFS_FILE_SIZE (72) -#define FATFS_MAX_VOL_STR_LEN (4) /**< size needed for volume strings like "n:/" where n is the volume id */ -#define FATFS_MOUNT_OPT (1) /**< 0:mount on first file access, 1 mount in f_mount() call */ +/** size needed for volume strings like "n:/" where n is the volume id */ +#define FATFS_MAX_VOL_STR_LEN (4) + +/** 0:mount on first file access, 1 mount in f_mount() call */ +#define FATFS_MOUNT_OPT (1) + +/** most FatFs file operations need an absolute path. This defines the size of the + needed buffer to circumvent stack allocation within vfs-wrappers */ +#define FATFS_MAX_ABS_PATH_SIZE (FATFS_MAX_VOL_STR_LEN + VFS_NAME_MAX + 1) #if (VFS_DIR_BUFFER_SIZE < FATFS_DIR_SIZE) #error "VFS_DIR_BUFFER_SIZE too small" @@ -65,23 +68,29 @@ extern "C" { typedef struct fatfs_desc { FATFS fat_fs; /**< FatFs work area needed for each volume */ uint8_t vol_idx; /**< low level device that is used by FatFs */ + + /** most FatFs file operations need an absolute path. This buffer provides + static memory to circumvent stack allocation within vfs-wrappers */ + char abs_path_str_buff[FATFS_MAX_ABS_PATH_SIZE]; } fatfs_desc_t; /** * info of a single opened file */ typedef struct fatfs_file_desc { - FIL file; /**< FatFs work area for a single file */ - char fname[VFS_NAME_MAX + 1]; /**< name of the file (some FatFs functions e.g. f_stat use filename instead of FIL) */ + FIL file; /**< FatFs work area for a single file */ + char fname[VFS_NAME_MAX + 1]; /**< name of the file (e.g. f_stat uses + filename instead of FIL) */ } fatfs_file_desc_t; -/** The FatFs vfs driver, a pointer to a fatfs_desc_t must be provided as vfs_mountp::private_data */ +/** The FatFs vfs driver, a pointer to a fatfs_desc_t must be + provided as vfs_mountp::private_data */ extern const vfs_file_system_t fatfs_file_system; #ifdef __cplusplus } #endif -#endif /* FATFS_H */ +#endif /* FS_FATFS_H */ /** @} */ diff --git a/tests/pkg_fatfs/Makefile b/tests/pkg_fatfs/Makefile index 40d6593277326d6f91a38af9855be45c2ca8b042..3e572b325df359379719589417181dc3ef21db25 100644 --- a/tests/pkg_fatfs/Makefile +++ b/tests/pkg_fatfs/Makefile @@ -1,34 +1,51 @@ include ../Makefile.tests_common -USEMODULE += shell - BOARD ?= native FEATURES_OPTIONAL += periph_rtc -# 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-l152 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 remote-pa remote-reva remote-revb samd21-xpro \ - saml21-xpro samr21-xpro sodaq-autonomo spark-core stm32f0discovery \ +# this list is composed of boards that support spi/gpio + native +BOARD_WHITELIST := airfy-beacon arduino-due arduino-duemilanove arduino-mega2560 \ + arduino-mkr1000 arduino-mkrzero arduino-uno arduino-zero avsextrem \ + b-l072z-lrwan1 b-l475e-iot01a bluepill cc2538dk ek-lm4f120xl \ + feather-m0 fox frdm-k22f frdm-k64f ikea-tradfri iotlab-a8-m3 \ + iotlab-m3 limifrog-v1 maple-mini msb-430 msb-430h msba2 msbiot \ + mulle nrf52840dk nrf52dk nrf6310 nucleo144-f207 nucleo144-f303 \ + nucleo144-f412 nucleo144-f413 nucleo144-f429 nucleo144-f446 \ + nucleo32-f031 nucleo32-f042 nucleo32-f303 nucleo32-l031 \ + nucleo32-l432 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-l152 nucleo-l476 \ + nz32-sc151 openmote-cc2538 pba-d-01-kw2x remote-pa remote-reva \ + remote-revb samd21-xpro saml21-xpro samr21-xpro sltb001a \ + sodaq-autonomo sodaq-explorer spark-core stm32f0discovery \ stm32f3discovery stm32f4discovery telosb udoo waspmote-pro \ - wsn430-v1_3b wsn430-v1_4 yunjia-nrf51822 z1 + wsn430-v1_3b wsn430-v1_4 yunjia-nrf51822 z1 native + +USEMODULE += shell +USEMODULE += fatfs_diskio_mtd +USEMODULE += mtd +USEPKG += fatfs + +FATFS_IMAGE_FILE_SIZE_MIB ?= 128 ifeq ($(BOARD),native) - USEMODULE += fatfs_diskio_native - FATFS_DISKIO_NATIVE_DEFAULT_FILE ?= \"riot_fatfs_disk.img\" +#overwrite default mtd_native-config to use fat image as flash device +CFLAGS += -DMTD_NATIVE_FILENAME=\"./bin/riot_fatfs_disk.img\" +CFLAGS += -DMTD_NATIVE_PAGE_SIZE=512 +CFLAGS += -DMTD_NATIVE_SECTOR_SIZE=512 +CFLAGS += -DFATFS_IMAGE_FILE_SIZE_MIB=$(FATFS_IMAGE_FILE_SIZE_MIB) +CFLAGS += -DMTD_NATIVE_SECTOR_NUM=\(\(\(FATFS_IMAGE_FILE_SIZE_MIB\)*1024*1024\)/MTD_NATIVE_SECTOR_SIZE\) else - USEMODULE += fatfs_diskio_sdcard_spi - USEMODULE += auto_init_storage +# for actual hardware use mtd_sdcard as storage device +USEMODULE += mtd_sdcard endif -USEPKG += fatfs +image: + @tar -xjf riot_fatfs_disk.tar.gz -C ./bin/ + +#this generates a compressed fat image file that can be used by the fat driver on native +compressed-image: + @./create_fat_image_file.sh $(FATFS_IMAGE_FILE_SIZE_MIB) include $(RIOTBASE)/Makefile.include diff --git a/tests/pkg_fatfs/README.md b/tests/pkg_fatfs/README.md index 92e8f2ac23910b130e7d1bfa410586c304a9530e..12f4ad1e5d54ca35978dcd0b27c9f40c6ed8fbf4 100644 --- a/tests/pkg_fatfs/README.md +++ b/tests/pkg_fatfs/README.md @@ -1,27 +1,17 @@ -Using FatFs on native +Using FatFs on RIOT ======================================= -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` +# native -2. create a FAT file system within the file -`mkfs.fat riot_fatfs_disk.img` +To use this test on native you can either use a FAT-formatted image file or directly use the mkfs command from the RIOT shell. +Use `make image` to extract a prepared image file that already contains a simple test.txt file. +This is only a convinience function to allow testing against a "default linux" formatted fat volume without the need to call mount or other stuff that may require super user privileges. +Optionally `make compressed-image` can be used to generate the compressed image that is in turn used by `make image`. -3. create a mount point which you can use later to add files with your file browser -`sudo mkdir -p /media/riot_fatfs_disk` +To tell RIOT where your image file is located you can use the define `MTD_NATIVE_FILENAME`. -4. give all needed rights for that mountpoint to your user -`sudo chown <your_username> /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. -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` +# Real Hardware -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. \ No newline at end of file +Currently the test defaults to sdcard_spi on real hardware. But generally any device that supports the mtd-interface can be used with FatFs. diff --git a/tests/pkg_fatfs/main.c b/tests/pkg_fatfs/main.c index 6faaa8789897d2e6e5c84e7e5868e0e37a47f684..8637ae79433b2a8ccfca44c8a6c204df4b14ce29 100644 --- a/tests/pkg_fatfs/main.c +++ b/tests/pkg_fatfs/main.c @@ -21,7 +21,8 @@ #if FATFS_FFCONF_OPT_FS_NORTC == 0 #include "periph/rtc.h" #endif -#include "fatfs_diskio_common.h" +#include "mtd.h" +#include "fatfs_diskio_mtd.h" #include "fatfs/ff.h" #include "shell.h" #include <string.h> @@ -47,7 +48,23 @@ #define IEC_KIBI 1024 #define SI_KILO 1000 -FATFS fat_fs; /* FatFs work area needed for each volume */ +FATFS fat_fs; /* FatFs work area needed for each volume */ + +#ifdef MODULE_MTD_NATIVE +/* mtd device for native is provided in boards/native/board_init.c */ +extern mtd_dev_t *mtd0; +mtd_dev_t *fatfs_mtd_devs[1]; +#elif MODULE_MTD_SDCARD +#include "mtd_sdcard.h" +#include "sdcard_spi_params.h" +#define SDCARD_SPI_NUM (sizeof(sdcard_spi_params) / sizeof(sdcard_spi_params[0])) +/* sdcard devs are provided by sys/auto_init/storage/auto_init_sdcard_spi.c */ +extern sdcard_spi_t sdcard_spi_devs[SDCARD_SPI_NUM]; +mtd_sdcard_t mtd_sdcard_devs[SDCARD_SPI_NUM]; +mtd_dev_t *fatfs_mtd_devs[SDCARD_SPI_NUM]; +#endif + +#define MTD_NUM (sizeof(fatfs_mtd_devs) / sizeof(fatfs_mtd_devs[0])) static int _mount(int argc, char **argv) { @@ -58,7 +75,12 @@ static int _mount(int argc, char **argv) return -1; } - vol_idx = (int)atoi(argv[1]); + vol_idx = atoi(argv[1]); + + if (vol_idx > (int)(MTD_NUM-1)) { + printf("max allowed <volume_idx> is %d\n", (int)(MTD_NUM - 1)); + return -1; + } char volume_str[TEST_FATFS_MAX_VOL_STR_LEN]; sprintf(volume_str, "%d:/", vol_idx); @@ -300,7 +322,7 @@ static int _mkfs(int argc, char **argv) BYTE opt; if (argc == 3) { - vol_idx = (int)atoi(argv[1]); + vol_idx = atoi(argv[1]); if (strcmp(argv[2], "fat") == 0) { opt = FM_FAT; @@ -320,6 +342,11 @@ static int _mkfs(int argc, char **argv) return -1; } + if (vol_idx > (int)(MTD_NUM - 1)) { + printf("max allowed <volume_idx> is %d\n", (int)(MTD_NUM - 1)); + return -1; + } + char volume_str[TEST_FATFS_MAX_VOL_STR_LEN]; sprintf(volume_str, "%d:/", vol_idx); BYTE work[_MAX_SS]; @@ -373,6 +400,24 @@ int main(void) rtc_set_time(&time); #endif + + #if MODULE_MTD_NATIVE + fatfs_mtd_devs[0] = mtd0; + #elif MODULE_MTD_SDCARD + for (unsigned int i = 0; i < SDCARD_SPI_NUM; i++){ + mtd_sdcard_devs[i].base.driver = &mtd_sdcard_driver; + mtd_sdcard_devs[i].sd_card = &sdcard_spi_devs[i]; + mtd_sdcard_devs[i].params = &sdcard_spi_params[i]; + fatfs_mtd_devs[i] = &mtd_sdcard_devs[i].base; + + if(mtd_init(&mtd_sdcard_devs[i].base) == 0) { + printf("init sdcard_mtd %u [OK]\n", i); + }else{ + printf("init sdcard_mtd %u [FAILED]\n", i); + } + } + #endif + char line_buf[SHELL_DEFAULT_BUFSIZE]; shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); diff --git a/tests/pkg_fatfs_vfs/Makefile b/tests/pkg_fatfs_vfs/Makefile index 44b562dd44198afde9fe3362fb84bf238c809bc2..c7468626c718123005c4ed6a9913d907b686ef35 100644 --- a/tests/pkg_fatfs_vfs/Makefile +++ b/tests/pkg_fatfs_vfs/Makefile @@ -2,33 +2,57 @@ APPLICATION = pkg_fatfs_vfs include ../Makefile.tests_common USEMODULE += fatfs_vfs +FEATURES_OPTIONAL += periph_rtc -FATFS_DISKIO_NATIVE_DEFAULT_FILE ?= \"./bin/riot_fatfs_disk.img\" - -# 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 - -# export is needed to pass this value to the Makefile of the native_diskio module -export FATFS_DISKIO_NATIVE_DEFAULT_FILE +CFLAGS += -DVFS_FILE_BUFFER_SIZE=72 -DVFS_DIR_BUFFER_SIZE=44 + +FATFS_IMAGE_FILE_SIZE_MIB ?= 128 + +ifeq ($(BOARD),native) + USEMODULE += mtd_native + + #overwrite default mtd_native-config to use fat image as flash device + MTD_NATIVE_FILENAME ?= \"./bin/riot_fatfs_disk.img\" + MTD_NATIVE_PAGE_SIZE ?= 512 + MTD_NATIVE_SECTOR_SIZE ?= 512 + MTD_NATIVE_SECTOR_NUM ?= \(\(\(FATFS_IMAGE_FILE_SIZE_MIB\)*1024*1024\)/MTD_NATIVE_SECTOR_SIZE\) + CFLAGS += -DMTD_NATIVE_FILENAME=$(MTD_NATIVE_FILENAME) + CFLAGS += -DMTD_NATIVE_PAGE_SIZE=$(MTD_NATIVE_PAGE_SIZE) + CFLAGS += -DMTD_NATIVE_SECTOR_SIZE=$(MTD_NATIVE_SECTOR_SIZE) + CFLAGS += -DFATFS_IMAGE_FILE_SIZE_MIB=$(FATFS_IMAGE_FILE_SIZE_MIB) + CFLAGS += -DMTD_NATIVE_SECTOR_NUM=$(MTD_NATIVE_SECTOR_NUM) +else + USEMODULE += mtd_sdcard +endif + +BOARD_INSUFFICIENT_MEMORY := nucleo32-f031 + +# this list is composed of boards with sufficient memory and support spi/gpio + native +BOARD_WHITELIST := airfy-beacon arduino-due arduino-duemilanove arduino-mega2560 \ + arduino-mkr1000 arduino-mkrzero arduino-uno arduino-zero avsextrem \ + b-l072z-lrwan1 b-l475e-iot01a bluepill cc2538dk ek-lm4f120xl \ + feather-m0 fox frdm-k22f frdm-k64f ikea-tradfri iotlab-a8-m3 \ + iotlab-m3 limifrog-v1 maple-mini msb-430 msb-430h msba2 msbiot \ + mulle nrf52840dk nrf52dk nrf6310 nucleo144-f207 nucleo144-f303 \ + nucleo144-f412 nucleo144-f413 nucleo144-f429 nucleo144-f446 \ + nucleo32-f042 nucleo32-f303 nucleo32-l031 \ + nucleo32-l432 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-l152 nucleo-l476 \ + nz32-sc151 openmote-cc2538 pba-d-01-kw2x remote-pa remote-reva \ + remote-revb samd21-xpro saml21-xpro samr21-xpro sltb001a \ + sodaq-autonomo sodaq-explorer spark-core stm32f0discovery \ + stm32f3discovery stm32f4discovery telosb udoo waspmote-pro \ + wsn430-v1_3b wsn430-v1_4 yunjia-nrf51822 z1 native include $(RIOTBASE)/Makefile.include +image: + @tar -xjf riot_fatfs_disk.tar.gz -C ./bin/ + #this generates a compressed fat image file that can be used by the fat driver on native -fatimage: - @./create_fat_image_file.sh +compressed-image: + @./create_fat_image_file.sh $(FATFS_IMAGE_FILE_SIZE_MIB) -test: - @tar -xjf riot_fatfs_disk.tar.gz -C ./bin/ +test: image ./tests/01-run.py diff --git a/tests/pkg_fatfs_vfs/README.md b/tests/pkg_fatfs_vfs/README.md new file mode 100644 index 0000000000000000000000000000000000000000..b1671ae522a420ae9c2bfa0ff651c91a60c6c482 --- /dev/null +++ b/tests/pkg_fatfs_vfs/README.md @@ -0,0 +1,20 @@ +Using FatFs (with VFS) on RIOT +======================================= + +# native + +To use this test on native you can either use a FAT-formatted image file or directly use the mkfs command from the RIOT shell. +Use `make image` to extract a prepared image file that already contains a simple test.txt file. +This is only a convinience function to allow testing against a "default linux" formatted fat volume without the need to call mount or other stuff that may require super user privileges. +Optionally `make compressed-image` can be used to generate the compressed image that is in turn used by `make image`. + +To tell RIOT where your image file is located you can use the define `MTD_NATIVE_FILENAME`. + + 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. + +# Real Hardware + +Currently the test defaults to sdcard_spi on real hardware. But generally any device that supports the mtd-interface can be used with FatFs. +To use the automated test in pkg_fatfs_vfs you need to copy the generated image to your storage device (e.g. your SD-card). +To copy the image onto the card you can use something like `make image && dd if=bin/riot_fatfs_disk.img of=/dev/<your_sdcard>`. +After that you can connect the card to your RIOT device and check the test output via terminal. diff --git a/tests/pkg_fatfs_vfs/create_fat_image_file.sh b/tests/pkg_fatfs_vfs/create_fat_image_file.sh index 517c6b366717eb86d846bf4dcc0900e94b6e1680..fa72597b7b2284bf680280596bde609741849806 100755 --- a/tests/pkg_fatfs_vfs/create_fat_image_file.sh +++ b/tests/pkg_fatfs_vfs/create_fat_image_file.sh @@ -6,7 +6,7 @@ # General Public License v2.1. See the file LICENSE in the top level # directory for more details. # -dd if=/dev/zero of=riot_fatfs_disk.img bs=1M count=128 +dd if=/dev/zero of=riot_fatfs_disk.img bs=1M count=$1 mkfs.fat riot_fatfs_disk.img sudo mkdir -p /media/riot_fatfs_disk sudo mount -o loop,umask=000 riot_fatfs_disk.img /media/riot_fatfs_disk diff --git a/tests/pkg_fatfs_vfs/main.c b/tests/pkg_fatfs_vfs/main.c index 4ba369b4bd210cdae6d124e46fe5f84945d281c1..7ac9207b9a29da9f8426f493571e6a6b1cd2ff71 100644 --- a/tests/pkg_fatfs_vfs/main.c +++ b/tests/pkg_fatfs_vfs/main.c @@ -24,6 +24,13 @@ #include "fs/fatfs.h" #include "vfs.h" +#include "mtd.h" + +#ifdef MODULE_MTD_SDCARD +#include "mtd_sdcard.h" +#include "sdcard_spi.h" +#include "sdcard_spi_params.h" +#endif #if FATFS_FFCONF_OPT_FS_NORTC == 0 #include "periph/rtc.h" @@ -54,6 +61,20 @@ static vfs_mount_t _test_vfs_mount = { .private_data = (void *)&fatfs, }; +/* provide mtd devices for use within diskio layer of fatfs */ +mtd_dev_t *fatfs_mtd_devs[_VOLUMES]; + +#ifdef MODULE_MTD_NATIVE +/* mtd device for native is provided in boards/native/board_init.c */ +extern mtd_dev_t *mtd0; +#elif MODULE_MTD_SDCARD +#define SDCARD_SPI_NUM (sizeof(sdcard_spi_params) / sizeof(sdcard_spi_params[0])) +extern sdcard_spi_t sdcard_spi_devs[SDCARD_SPI_NUM]; +mtd_sdcard_t mtd_sdcard_devs[SDCARD_SPI_NUM]; +/* always default to first sdcard*/ +static mtd_dev_t *mtd1 = (mtd_dev_t*)&mtd_sdcard_devs[0]; +#endif + static void print_test_result(const char *test_name, int ok) { printf("%s:[%s]\n", test_name, ok ? "OK" : "FAILED"); @@ -116,7 +137,7 @@ static void test_rw(void) /* try to read from WO file (success if no bytes are actually read) */ nr = vfs_read(fd, buf, sizeof(test_txt)); - print_test_result("test_rw__read_wo", nw <= 0); + print_test_result("test_rw__read_wo", nr <= 0); print_test_result("test_rw__close_wo", vfs_close(fd) == 0); @@ -146,7 +167,6 @@ static void test_rw(void) test_txt2, sizeof(test_txt2)) == 0)); - print_test_result("test_rw__close_rw", vfs_close(fd) == 0); /* create new file */ @@ -273,12 +293,27 @@ static void test_create(void) print_test_result("test_create__umount", vfs_umount(&_test_vfs_mount) == 0); } - int main(void) { - #if FATFS_FFCONF_OPT_FS_NORTC == 0 +#if defined(BOARD_NATIVE) && (FATFS_FFCONF_OPT_FS_NORTC == 0) rtc_init(); - #endif +#endif + +#if MODULE_MTD_SDCARD + for(unsigned int i = 0; i < SDCARD_SPI_NUM; i++){ + mtd_sdcard_devs[i].base.driver = &mtd_sdcard_driver; + mtd_sdcard_devs[i].sd_card = &sdcard_spi_devs[i]; + mtd_sdcard_devs[i].params = &sdcard_spi_params[i]; + fatfs_mtd_devs[i] = &mtd_sdcard_devs[i].base; + mtd_init(&mtd_sdcard_devs[i].base); + } +#endif + +#ifdef MODULE_MTD_NATIVE + fatfs_mtd_devs[fatfs.vol_idx] = mtd0; +#else + fatfs_mtd_devs[fatfs.vol_idx] = mtd1; +#endif printf("Tests for FatFs over VFS - test results will be printed " "in the format test_name:result\n"); @@ -293,6 +328,5 @@ int main(void) test_create(); printf("Test end.\n"); - return 0; } diff --git a/tests/pkg_fatfs_vfs/tests/01-run.py b/tests/pkg_fatfs_vfs/tests/01-run.py index 6150bbc8c545fc877993c08d9f489dfc2d3fc559..80b811234825dde884dde90c3c80a2d6024c8072 100755 --- a/tests/pkg_fatfs_vfs/tests/01-run.py +++ b/tests/pkg_fatfs_vfs/tests/01-run.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright (C) 2017 HAW-Hamburg.de # @@ -9,28 +9,28 @@ import os import sys -sys.path.append(os.path.join(os.environ['RIOTBASE'], 'dist/tools/testrunner')) -import testrunner - -from datetime import datetime class TestFailed(Exception): pass + def testfunc(child): child.expect(u"Tests for FatFs over VFS - test results will be printed in " - "the format test_name:result\r\n") + "the format test_name:result\r\n") while True: res = child.expect([u"[^\n]*:\[OK\]\r\n", u"Test end.\r\n", - u".[^\n]*:\[FAILED\]\r\n" , + u".[^\n]*:\[FAILED\]\r\n", u".*\r\n"]) if res > 1: - raise TestFailed(child.after.split(':',1)[0] + " test failed!") + raise TestFailed(child.after.split(':', 1)[0] + " test failed!") elif res == 1: - break; + break + if __name__ == "__main__": + sys.path.append(os.path.join(os.environ['RIOTBASE'], 'dist/tools/testrunner')) + import testrunner sys.exit(testrunner.run(testfunc))