mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
238 lines
6.9 KiB
C
238 lines
6.9 KiB
C
/*
|
|
* 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 pkg_fatfs
|
|
* @{
|
|
*
|
|
* @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_mtd.h"
|
|
#include "ffconf.h"
|
|
#include "mtd.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[FF_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 >= FF_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 successfully
|
|
* @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 >= FF_VOLUMES) {
|
|
return STA_NODISK;
|
|
} else if (fatfs_mtd_devs[pdrv]->driver == NULL){
|
|
return STA_NOINIT;
|
|
}
|
|
|
|
if (mtd_init(fatfs_mtd_devs[pdrv])) {
|
|
return STA_NOINIT;
|
|
}
|
|
|
|
uint32_t sector_size = fatfs_mtd_devs[pdrv]->page_size
|
|
* fatfs_mtd_devs[pdrv]->pages_per_sector;
|
|
if (sector_size > FF_MAX_SS) {
|
|
assert(0);
|
|
return STA_NOINIT;
|
|
}
|
|
|
|
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_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, (long unsigned)sector, count);
|
|
if ((pdrv >= FF_VOLUMES) || (fatfs_mtd_devs[pdrv]->driver == NULL)) {
|
|
return RES_PARERR;
|
|
}
|
|
|
|
uint32_t sector_size = fatfs_mtd_devs[pdrv]->page_size
|
|
* fatfs_mtd_devs[pdrv]->pages_per_sector;
|
|
|
|
int res = mtd_read_page(fatfs_mtd_devs[pdrv], buff,
|
|
sector, 0, count * sector_size);
|
|
|
|
if (res != 0) {
|
|
return RES_ERROR;
|
|
}
|
|
return RES_OK;
|
|
}
|
|
|
|
/**
|
|
* @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, (long unsigned)sector, count);
|
|
if ((pdrv >= FF_VOLUMES) || (fatfs_mtd_devs[pdrv]->driver == NULL)) {
|
|
return RES_PARERR;
|
|
}
|
|
|
|
/* erase memory before writing to it */
|
|
int res = mtd_erase_sector(fatfs_mtd_devs[pdrv], sector, count);
|
|
|
|
if (res != 0) {
|
|
return RES_ERROR; /* erase failed! */
|
|
}
|
|
|
|
uint32_t sector_size = fatfs_mtd_devs[pdrv]->page_size
|
|
* fatfs_mtd_devs[pdrv]->pages_per_sector;
|
|
|
|
res = mtd_write_page_raw(fatfs_mtd_devs[pdrv], buff,
|
|
sector, 0, count * sector_size);
|
|
|
|
if (res != 0) {
|
|
return RES_ERROR;
|
|
}
|
|
return RES_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief perform miscellaneous low-level control functions
|
|
*
|
|
* @param[in] pdrv Physical drive nmuber (0..FF_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)
|
|
{
|
|
(void)buff;
|
|
|
|
if ((pdrv >= FF_VOLUMES) || (fatfs_mtd_devs[pdrv]->driver == NULL)) {
|
|
return RES_PARERR;
|
|
}
|
|
|
|
switch (cmd) {
|
|
#if (FF_FS_READONLY == 0)
|
|
case CTRL_SYNC:
|
|
/* r/w is always finished within r/w-functions of mtd */
|
|
return RES_OK;
|
|
#endif
|
|
|
|
#if (FF_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 (FF_MAX_SS != FF_MIN_SS)
|
|
case GET_SECTOR_SIZE:
|
|
*(DWORD *)buff = fatfs_mtd_devs[pdrv]->page_size;
|
|
return RES_OK;
|
|
#endif
|
|
|
|
#if (FF_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_mday; /* 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 (DWORD)year << FATFS_DISKIO_FATTIME_YEAR_OFFS |
|
|
(DWORD)month << FATFS_DISKIO_FATTIME_MON_OFFS |
|
|
(DWORD)day_of_month << FATFS_DISKIO_FATTIME_DAY_OFFS |
|
|
hour << FATFS_DISKIO_FATTIME_HH_OFFS |
|
|
minute << FATFS_DISKIO_FATTIME_MM_OFFS |
|
|
second;
|
|
}
|
|
#endif
|