New SDCARD layer platform agnostic

This commit is contained in:
Anthony Rabine 2023-06-05 06:42:00 +02:00
parent b83baaaffa
commit 087982964a
26 changed files with 19286 additions and 1476 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 15 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -30,7 +30,7 @@
// "device": "STM32L431VC",
"runToMain": true,
"preRestartCommands": [
"cd ${workspaceRoot}/build",
"cd ${workspaceRoot}/build/RaspberryPico",
"file open-story-teller.elf",
// "target extended-remote /dev/ttyACM0",
"set mem inaccessible-by-default off",

View file

@ -1,3 +1,14 @@
{
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools"
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
"files.associations": {
"**/frontmatter.json": "jsonc",
"**/.frontmatter/config/*.json": "jsonc",
"diskio.h": "c",
"ost_hal.h": "c",
"stdint.h": "c",
"sdcard.h": "c",
"ff.h": "c",
"debug.h": "c",
"ffconf.h": "c"
}
}

View file

@ -6,7 +6,7 @@
cmake_minimum_required(VERSION 3.13)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_VERBOSE_MAKEFILE OFF)
set(CMAKE_COLOR_MAKEFILE ON)
set(PROJECT_NAME open-story-teller)
@ -31,6 +31,7 @@ endif()
set(OST_SRCS
system/main.c
system/sdcard.c
system/ff_diskio_sdcard.c
system/debug.c
system/picture.c
system/filesystem.c

View file

@ -53,10 +53,18 @@ extern "C"
// ----------------------------------------------------------------------------
// SDCARD HAL
// ----------------------------------------------------------------------------
void sdcard_set_slow_clock();
void sdcard_set_fast_clock();
void sdcard_cs_high();
void sdcard_cs_low();
/**
* @brief Deselect the SD-Card by driving the Chip Select to high level (eg: 3.3V)
*
*/
void ost_hal_sdcard_cs_high();
/**
* @brief Deselect the SD-Card by driving the Chip Select to low level (eg: 0V)
*
*/
void ost_hal_sdcard_cs_low();
/**
* @brief
@ -64,15 +72,14 @@ extern "C"
* @param dat Data to send
* @return uint8_t
*/
uint8_t sdcard_spi_transfer(uint8_t dat);
uint8_t ost_hal_sdcard_spi_transfer(uint8_t dat);
/**
* @brief Receive multiple byte
* @brief Return 1 if the SD card is physically inserted, otherwise 0
*
* @param buff Pointer to data buffer
* @param btr Number of bytes to receive (even number)
* @return uint8_t SD card is present or not
*/
void sdcard_spi_recv_multi(uint8_t *buff, uint32_t btr);
uint8_t ost_hal_sdcard_get_presence();
// ----------------------------------------------------------------------------
// DISPLAY HAL

View file

@ -307,17 +307,17 @@ void sdcard_set_fast_clock()
spi_init(800000, 0);
}
void sdcard_cs_high()
void ost_hal_sdcard_cs_high()
{
spi_ss(1);
}
void sdcard_cs_low()
void ost_hal_sdcard_cs_low()
{
spi_ss(0);
}
uint8_t sdcard_spi_transfer(uint8_t dat)
uint8_t ost_hal_sdcard_spi_transfer(uint8_t dat)
{
return spi_transfer(dat);
}

View file

@ -17,6 +17,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(PICO_SRCS
${CMAKE_CURRENT_LIST_DIR}/pico_hal_wrapper.c
${CMAKE_CURRENT_LIST_DIR}/pico_lcd_spi.c
${CMAKE_CURRENT_LIST_DIR}/pico_sdcard_spi.c
)
include_directories(../../src ../../hal ../../library)

View file

@ -3,14 +3,18 @@
#include "ost_hal.h"
#include "debug.h"
#include "st7789.h"
#include <ff.h>
#include "diskio.h"
// Raspberry Pico SDK
#include "pico/stdlib.h"
#include "hardware/uart.h"
#include "hardware/spi.h"
#include "pico.h"
// Local
#include "pico_lcd_spi.h"
#include "pico_sdcard_spi.h"
static volatile uint32_t msTicks = 0;
@ -39,18 +43,26 @@ const uint8_t LCD_CS = 9;
const uint8_t LCD_RESET = 12;
const uint8_t LCD_BL = 13;
const uint8_t ROTARY_A = 19;
const uint8_t ROTARY_B = 19;
const uint8_t ROTARY_A = 6;
const uint8_t ROTARY_B = 7;
const uint8_t SD_CARD_CS = 17;
const uint8_t SD_CARD_PRESENCE = 24;
extern void disk_timerproc();
static bool sys_timer_callback(struct repeating_timer *t)
{
msTicks++;
// disk_timerproc();
return true;
}
void ost_system_initialize()
{
stdio_init_all();
// stdio_init_all();
////------------------- Init DEBUG LED
gpio_init(LED_PIN);
@ -95,6 +107,16 @@ void ost_system_initialize()
gpio_init(ROTARY_B);
gpio_set_dir(ROTARY_B, GPIO_IN);
//------------------- Init SDCARD
gpio_init(SD_CARD_CS);
gpio_put(SD_CARD_CS, 1);
gpio_set_dir(SD_CARD_CS, GPIO_OUT);
gpio_init(SD_CARD_PRESENCE);
gpio_set_dir(SD_CARD_PRESENCE, GPIO_IN);
pico_sdcard_spi_init(10000);
//------------------- System timer (1ms)
add_repeating_timer_ms(1, sys_timer_callback, NULL, &sys_timer);
}
@ -144,35 +166,35 @@ void ost_hal_gpio_set(ost_hal_gpio_t gpio, int value)
void sdcard_set_slow_clock()
{
// spi_init(100000, 0);
spi_set_baudrate(spi0, 10000);
}
void sdcard_set_fast_clock()
{
// spi_init(800000, 0);
spi_set_baudrate(spi0, 1000 * 1000);
}
void sdcard_cs_high()
void ost_hal_sdcard_cs_high()
{
// spi_ss(1);
gpio_put(SD_CARD_CS, 1);
}
void sdcard_cs_low()
void ost_hal_sdcard_cs_low()
{
// spi_ss(0);
gpio_put(SD_CARD_CS, 0);
}
uint8_t sdcard_spi_transfer(uint8_t dat)
uint8_t ost_hal_sdcard_spi_transfer(uint8_t dat)
{
// return spi_transfer(dat);
return 0;
uint8_t out;
pico_ost_hal_sdcard_spi_transfer(&dat, &out, 1);
return out;
}
void sdcard_spi_recv_multi(uint8_t *buff, uint32_t btr)
uint8_t ost_hal_sdcard_get_presence()
{
// for (uint32_t i = 0; i < btr; i++)
// {
// buff[i] = spi_transfer(buff[i]);
// }
return 1; // not wired
}
// ----------------------------------------------------------------------------

View file

@ -0,0 +1,63 @@
#include <stdio.h>
#include <stdlib.h>
#include "pico/stdlib.h"
#include "pico/binary_info.h"
#include "hardware/spi.h"
#include "hardware/dma.h"
#define SDCARD_SCK 18
#define SDCARD_MOSI 19
#define SDCARD_MISO 16
static uint dma_tx;
void pico_sdcard_spi_init(int clock)
{
spi_init(spi0, clock);
spi_set_format(spi0, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
gpio_set_function(SDCARD_SCK, GPIO_FUNC_SPI);
gpio_set_function(SDCARD_MOSI, GPIO_FUNC_SPI);
gpio_set_function(SDCARD_MISO, GPIO_FUNC_SPI);
// Grab some unused dma channels
// dma_tx = dma_claim_unused_channel(true);
// uint dma_rx = dma_claim_unused_channel(true);
// Force loopback for testing (I don't have an SPI device handy)
// hw_set_bits(&spi_get_hw(spi_default)->cr1, SPI_SSPCR1_LBM_BITS);
/*
static uint8_t txbuf[TEST_SIZE];
static uint8_t rxbuf[TEST_SIZE];
for (uint i = 0; i < TEST_SIZE; ++i)
{
txbuf[i] = rand();
}
*/
}
void pico_ost_hal_sdcard_spi_transfer(const uint8_t *buffer, uint8_t *out, uint32_t size)
{
spi_write_read_blocking(spi0, buffer, out, size);
/* ------- DMA
// We set the outbound DMA to transfer from a memory buffer to the SPI transmit FIFO paced by the SPI TX FIFO DREQ
// The default is for the read address to increment every element (in this case 1 byte = DMA_SIZE_8)
// and for the write address to remain unchanged.
printf("Configure TX DMA\n");
dma_channel_config c = dma_channel_get_default_config(dma_tx);
channel_config_set_transfer_data_size(&c, DMA_SIZE_8);
channel_config_set_dreq(&c, spi_get_dreq(spi_default, true));
dma_channel_configure(dma_tx, &c,
&spi_get_hw(spi_default)->dr, // write address
buffer, // read address
size, // element count (each element is of size transfer_data_size)
false); // don't start yet
dma_start_channel_mask((1u << dma_tx));
dma_channel_wait_for_finish_blocking(dma_tx);
*/
}

View file

@ -0,0 +1,6 @@
#pragma once
#include <stdint.h>
void pico_sdcard_spi_init(int clock);
void pico_ost_hal_sdcard_spi_transfer(const uint8_t *buffer, uint8_t *out, uint32_t size);

View file

@ -228,17 +228,17 @@ void sdcard_set_fast_clock()
spi1_set_fclk_fast();
}
void sdcard_cs_high()
void ost_hal_sdcard_cs_high()
{
void spi1_cs_high();
}
void sdcard_cs_low()
void ost_hal_sdcard_cs_low()
{
void spi1_cs_low();
}
uint8_t sdcard_spi_transfer(uint8_t dat)
uint8_t ost_hal_sdcard_spi_transfer(uint8_t dat)
{
return xchg_spi1(dat);
}

View file

@ -344,3 +344,26 @@ R0.14a (December 5, 2020)
Fixed old floppy disks formatted with MS-DOS 2.x and 3.x cannot be mounted.
Fixed some compiler warnings.
R0.14b (April 17, 2021)
Made FatFs uses standard library <string.h> for copy, compare and search instead of built-in string functions.
Added support for long long integer and floating point to f_printf(). (FF_STRF_LLI and FF_STRF_FP)
Made path name parser ignore the terminating separator to allow "dir/".
Improved the compatibility in Unix style path name feature.
Fixed the file gets dead-locked when f_open() failed with some conditions. (appeared at R0.12a)
Fixed f_mkfs() can create wrong exFAT volume due to a timing dependent error. (appeared at R0.12)
Fixed code page 855 cannot be set by f_setcp().
Fixed some compiler warnings.
R0.15 (November 6, 2022)
Changed user provided synchronization functions in order to completely eliminate the platform dependency from FatFs code.
FF_SYNC_t is removed from the configuration options.
Fixed a potential error in f_mount when FF_FS_REENTRANT.
Fixed file lock control FF_FS_LOCK is not mutal excluded when FF_FS_REENTRANT && FF_VOLUMES > 1 is true.
Fixed f_mkfs() creates broken exFAT volume when the size of volume is >= 2^32 sectors.
Fixed string functions cannot write the unicode characters not in BMP when FF_LFN_UNICODE == 2 (UTF-8).
Fixed a compatibility issue in identification of GPT header.

View file

@ -1,4 +1,4 @@
FatFs Module Source Files R0.14a
FatFs Module Source Files R0.15
FILES

229
software/system/ff/diskio.c Normal file
View file

@ -0,0 +1,229 @@
/*-----------------------------------------------------------------------*/
/* Low level disk I/O module SKELETON for FatFs (C)ChaN, 2019 */
/*-----------------------------------------------------------------------*/
/* If a working storage control module is available, it should be */
/* attached to the FatFs via a glue function rather than modifying it. */
/* This is an example of glue functions to attach various exsisting */
/* storage control modules to the FatFs module with a defined API. */
/*-----------------------------------------------------------------------*/
#include "ff.h" /* Obtains integer types */
#include "diskio.h" /* Declarations of disk functions */
/* Definitions of physical drive number for each drive */
#define DEV_RAM 0 /* Example: Map Ramdisk to physical drive 0 */
#define DEV_MMC 1 /* Example: Map MMC/SD card to physical drive 1 */
#define DEV_USB 2 /* Example: Map USB MSD to physical drive 2 */
/*-----------------------------------------------------------------------*/
/* Get Drive Status */
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
DSTATUS stat;
int result;
switch (pdrv) {
case DEV_RAM :
result = RAM_disk_status();
// translate the reslut code here
return stat;
case DEV_MMC :
result = MMC_disk_status();
// translate the reslut code here
return stat;
case DEV_USB :
result = USB_disk_status();
// translate the reslut code here
return stat;
}
return STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Inidialize a Drive */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
DSTATUS stat;
int result;
switch (pdrv) {
case DEV_RAM :
result = RAM_disk_initialize();
// translate the reslut code here
return stat;
case DEV_MMC :
result = MMC_disk_initialize();
// translate the reslut code here
return stat;
case DEV_USB :
result = USB_disk_initialize();
// translate the reslut code here
return stat;
}
return STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
LBA_t sector, /* Start sector in LBA */
UINT count /* Number of sectors to read */
)
{
DRESULT res;
int result;
switch (pdrv) {
case DEV_RAM :
// translate the arguments here
result = RAM_disk_read(buff, sector, count);
// translate the reslut code here
return res;
case DEV_MMC :
// translate the arguments here
result = MMC_disk_read(buff, sector, count);
// translate the reslut code here
return res;
case DEV_USB :
// translate the arguments here
result = USB_disk_read(buff, sector, count);
// translate the reslut code here
return res;
}
return RES_PARERR;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
#if FF_FS_READONLY == 0
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
LBA_t sector, /* Start sector in LBA */
UINT count /* Number of sectors to write */
)
{
DRESULT res;
int result;
switch (pdrv) {
case DEV_RAM :
// translate the arguments here
result = RAM_disk_write(buff, sector, count);
// translate the reslut code here
return res;
case DEV_MMC :
// translate the arguments here
result = MMC_disk_write(buff, sector, count);
// translate the reslut code here
return res;
case DEV_USB :
// translate the arguments here
result = USB_disk_write(buff, sector, count);
// translate the reslut code here
return res;
}
return RES_PARERR;
}
#endif
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
DRESULT disk_ioctl (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
DRESULT res;
int result;
switch (pdrv) {
case DEV_RAM :
// Process of the command for the RAM drive
return res;
case DEV_MMC :
// Process of the command for the MMC/SD card
return res;
case DEV_USB :
// Process of the command the USB drive
return res;
}
return RES_PARERR;
}

View file

@ -1,17 +1,14 @@
/*-----------------------------------------------------------------------
/ Low level disk interface module include file (C)ChaN, 2014
/*-----------------------------------------------------------------------/
/ Low level disk interface modlue include file (C)ChaN, 2019 /
/-----------------------------------------------------------------------*/
#ifndef SDCARD_DEFINED
#define SDCARD_DEFINED
#ifndef _DISKIO_DEFINED
#define _DISKIO_DEFINED
#ifdef __cplusplus
extern "C" {
#endif
#include "ff.h"
/* Status of Disk Functions */
typedef BYTE DSTATUS;
@ -27,7 +24,6 @@ typedef enum {
/*---------------------------------------*/
/* Prototypes for disk control functions */
/*---------------------------------------*/
DSTATUS disk_initialize (BYTE pdrv);
@ -38,6 +34,7 @@ DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
/* Disk Status Bits (DSTATUS) */
#define STA_NOINIT 0x01 /* Drive not initialized */
#define STA_NODISK 0x02 /* No medium in the drive */
#define STA_PROTECT 0x04 /* Write protected */
@ -53,40 +50,25 @@ DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */
/* Generic command (Not used by FatFs) */
#define CTRL_FORMAT 5 /* Create physical format on the media */
#define CTRL_POWER_IDLE 6 /* Put the device idle state */
#define CTRL_POWER_OFF 7 /* Put the device off state */
#define CTRL_LOCK 8 /* Lock media removal */
#define CTRL_UNLOCK 9 /* Unlock media removal */
#define CTRL_EJECT 10 /* Eject media */
#define CTRL_GET_SMART 11 /* Read SMART information */
#define CTRL_POWER 5 /* Get/Set power status */
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
#define CTRL_EJECT 7 /* Eject media */
#define CTRL_FORMAT 8 /* Create physical format on the media */
/* MMC/SDC specific command (Not used by FatFs) */
#define MMC_GET_TYPE 50 /* Get card type */
#define MMC_GET_CSD 51 /* Read CSD */
#define MMC_GET_CID 52 /* Read CID */
#define MMC_GET_OCR 53 /* Read OCR */
#define MMC_GET_SDSTAT 54 /* Read SD status */
/* MMC/SDC specific ioctl command */
#define MMC_GET_TYPE 10 /* Get card type */
#define MMC_GET_CSD 11 /* Get CSD */
#define MMC_GET_CID 12 /* Get CID */
#define MMC_GET_OCR 13 /* Get OCR */
#define MMC_GET_SDSTAT 14 /* Get SD status */
#define ISDIO_READ 55 /* Read data form SD iSDIO register */
#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */
#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */
/* ATA/CF specific command (Not used by FatFs) */
#define ATA_GET_REV 60 /* Get F/W revision */
#define ATA_GET_MODEL 61 /* Get model name */
#define ATA_GET_SN 62 /* Get serial number */
/* MMC card type flags (MMC_GET_TYPE) */
#define CT_MMC3 0x01 /* MMC ver 3 */
#define CT_MMC4 0x02 /* MMC ver 4+ */
#define CT_MMC 0x03 /* MMC */
#define CT_SDC1 0x02 /* SDC ver 1 */
#define CT_SDC2 0x04 /* SDC ver 2+ */
#define CT_SDC 0x0C /* SDC */
#define CT_BLOCK 0x10 /* Block addressing */
void disk_timerproc (void);
/* ATA/CF specific ioctl command */
#define ATA_GET_REV 20 /* Get F/W revision */
#define ATA_GET_MODEL 21 /* Get model name */
#define ATA_GET_SN 22 /* Get serial number */
#ifdef __cplusplus
}

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,8 @@
/*----------------------------------------------------------------------------/
/ FatFs - Generic FAT Filesystem module R0.14a /
/ FatFs - Generic FAT Filesystem module R0.15 /
/-----------------------------------------------------------------------------/
/
/ Copyright (C) 2020, ChaN, all right reserved.
/ Copyright (C) 2022, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
@ -20,7 +20,7 @@
#ifndef FF_DEFINED
#define FF_DEFINED 80196 /* Revision ID */
#define FF_DEFINED 80286 /* Revision ID */
#ifdef __cplusplus
extern "C" {
@ -35,10 +35,14 @@ extern "C" {
/* Integer types used for FatFs API */
#if defined(_WIN32) /* Main development platform */
#if defined(_WIN32) /* Windows VC++ (for development only) */
#define FF_INTDEF 2
#include <windows.h>
typedef unsigned __int64 QWORD;
#include <float.h>
#define isnan(v) _isnan(v)
#define isinf(v) (!_finite(v))
#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus) /* C99 or later */
#define FF_INTDEF 2
#include <stdint.h>
@ -48,6 +52,7 @@ typedef uint16_t WORD; /* 16-bit unsigned integer */
typedef uint32_t DWORD; /* 32-bit unsigned integer */
typedef uint64_t QWORD; /* 64-bit unsigned integer */
typedef WORD WCHAR; /* UTF-16 character type */
#else /* Earlier than C99 */
#define FF_INTDEF 1
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
@ -58,53 +63,6 @@ typedef WORD WCHAR; /* UTF-16 character type */
#endif
/* Definitions of volume management */
#if FF_MULTI_PARTITION /* Multiple partition configuration */
typedef struct {
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
extern PARTITION VolToPart[]; /* Volume - Partition mapping table */
#endif
#if FF_STR_VOLUME_ID
#ifndef FF_VOLUME_STRS
extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */
#endif
#endif
/* Type of path name strings on FatFs API */
#ifndef _INC_TCHAR
#define _INC_TCHAR
#if FF_USE_LFN && FF_LFN_UNICODE == 1 /* Unicode in UTF-16 encoding */
typedef WCHAR TCHAR;
#define _T(x) L ## x
#define _TEXT(x) L ## x
#elif FF_USE_LFN && FF_LFN_UNICODE == 2 /* Unicode in UTF-8 encoding */
typedef char TCHAR;
#define _T(x) u8 ## x
#define _TEXT(x) u8 ## x
#elif FF_USE_LFN && FF_LFN_UNICODE == 3 /* Unicode in UTF-32 encoding */
typedef DWORD TCHAR;
#define _T(x) U ## x
#define _TEXT(x) U ## x
#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3)
#error Wrong FF_LFN_UNICODE setting
#else /* ANSI/OEM code in SBCS/DBCS */
typedef char TCHAR;
#define _T(x) x
#define _TEXT(x) x
#endif
#endif
/* Type of file size and LBA variables */
#if FF_FS_EXFAT
@ -127,14 +85,57 @@ typedef DWORD LBA_t;
/* Type of path name strings on FatFs API (TCHAR) */
#if FF_USE_LFN && FF_LFN_UNICODE == 1 /* Unicode in UTF-16 encoding */
typedef WCHAR TCHAR;
#define _T(x) L ## x
#define _TEXT(x) L ## x
#elif FF_USE_LFN && FF_LFN_UNICODE == 2 /* Unicode in UTF-8 encoding */
typedef char TCHAR;
#define _T(x) u8 ## x
#define _TEXT(x) u8 ## x
#elif FF_USE_LFN && FF_LFN_UNICODE == 3 /* Unicode in UTF-32 encoding */
typedef DWORD TCHAR;
#define _T(x) U ## x
#define _TEXT(x) U ## x
#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3)
#error Wrong FF_LFN_UNICODE setting
#else /* ANSI/OEM code in SBCS/DBCS */
typedef char TCHAR;
#define _T(x) x
#define _TEXT(x) x
#endif
/* Definitions of volume management */
#if FF_MULTI_PARTITION /* Multiple partition configuration */
typedef struct {
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
extern PARTITION VolToPart[]; /* Volume - Partition mapping table */
#endif
#if FF_STR_VOLUME_ID
#ifndef FF_VOLUME_STRS
extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */
#endif
#endif
/* Filesystem object structure (FATFS) */
typedef struct {
BYTE fs_type; /* Filesystem type (0:not mounted) */
BYTE pdrv; /* Associated physical drive */
BYTE pdrv; /* Volume hosting physical drive */
BYTE ldrv; /* Logical drive number (used only when FF_FS_REENTRANT) */
BYTE n_fats; /* Number of FATs (1 or 2) */
BYTE wflag; /* win[] flag (b0:dirty) */
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
BYTE wflag; /* win[] status (b0:dirty) */
BYTE fsi_flag; /* FSINFO status (b7:disabled, b0:dirty) */
WORD id; /* Volume mount ID */
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
WORD csize; /* Cluster size [sectors] */
@ -147,9 +148,6 @@ typedef struct {
#if FF_FS_EXFAT
BYTE* dirbuf; /* Directory entry block scratchpad buffer for exFAT */
#endif
#if FF_FS_REENTRANT
FF_SYNC_t sobj; /* Identifier of sync object */
#endif
#if !FF_FS_READONLY
DWORD last_clst; /* Last allocated cluster */
DWORD free_clst; /* Number of free clusters */
@ -163,10 +161,10 @@ typedef struct {
#endif
#endif
DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */
DWORD fsize; /* Size of an FAT [sectors] */
DWORD fsize; /* Number of sectors per FAT */
LBA_t volbase; /* Volume base sector */
LBA_t fatbase; /* FAT base sector */
LBA_t dirbase; /* Root directory base sector/cluster */
LBA_t dirbase; /* Root directory base sector (FAT12/16) or cluster (FAT32/exFAT) */
LBA_t database; /* Data base sector */
#if FF_FS_EXFAT
LBA_t bitbase; /* Allocation bitmap base sector */
@ -181,7 +179,7 @@ typedef struct {
typedef struct {
FATFS* fs; /* Pointer to the hosting volume of this object */
WORD id; /* Hosting volume mount ID */
WORD id; /* Hosting volume's mount ID */
BYTE attr; /* Object attribute */
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */
DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */
@ -250,7 +248,7 @@ typedef struct {
WORD ftime; /* Modified time */
BYTE fattrib; /* File attribute */
#if FF_USE_LFN
TCHAR altname[FF_SFN_BUF + 1];/* Altenative file name */
TCHAR altname[FF_SFN_BUF + 1];/* Alternative file name */
TCHAR fname[FF_LFN_BUF + 1]; /* Primary file name */
#else
TCHAR fname[12 + 1]; /* File name */
@ -298,8 +296,10 @@ typedef enum {
/*--------------------------------------------------------------*/
/* FatFs Module Application Interface */
/*--------------------------------------------------------------*/
/* FatFs module application interface */
FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */
FRESULT f_close (FIL* fp); /* Close an open file object */
@ -336,6 +336,8 @@ int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */
int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */
/* Some API fucntions are implemented as macro */
#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize))
#define f_error(fp) ((fp)->err)
#define f_tell(fp) ((fp)->fptr)
@ -349,38 +351,43 @@ TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the fil
/*--------------------------------------------------------------*/
/* Additional user defined functions */
/* Additional Functions */
/*--------------------------------------------------------------*/
/* RTC function */
/* RTC function (provided by user) */
#if !FF_FS_READONLY && !FF_FS_NORTC
DWORD get_fattime (void);
DWORD get_fattime (void); /* Get current time */
#endif
/* LFN support functions */
#if FF_USE_LFN >= 1 /* Code conversion (defined in unicode.c) */
/* LFN support functions (defined in ffunicode.c) */
#if FF_USE_LFN >= 1
WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */
WCHAR ff_uni2oem (DWORD uni, WORD cp); /* Unicode to OEM code conversion */
DWORD ff_wtoupper (DWORD uni); /* Unicode upper-case conversion */
#endif
/* O/S dependent functions (samples available in ffsystem.c) */
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
void* ff_memalloc (UINT msize); /* Allocate memory block */
void ff_memfree (void* mblock); /* Free memory block */
#endif
/* Sync functions */
#if FF_FS_REENTRANT
int ff_cre_syncobj (BYTE vol, FF_SYNC_t* sobj); /* Create a sync object */
int ff_req_grant (FF_SYNC_t sobj); /* Lock sync object */
void ff_rel_grant (FF_SYNC_t sobj); /* Unlock sync object */
int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */
#if FF_FS_REENTRANT /* Sync functions */
int ff_mutex_create (int vol); /* Create a sync object */
void ff_mutex_delete (int vol); /* Delete a sync object */
int ff_mutex_take (int vol); /* Lock sync object */
void ff_mutex_give (int vol); /* Unlock sync object */
#endif
/*--------------------------------------------------------------*/
/* Flags and offset address */
/* Flags and Offset Address */
/*--------------------------------------------------------------*/
/* File access mode and open method flags (3rd argument of f_open) */
#define FA_READ 0x01

View file

@ -1,8 +1,8 @@
/*---------------------------------------------------------------------------/
/ FatFs Functional Configurations
/ Configurations of FatFs Module
/---------------------------------------------------------------------------*/
#define FFCONF_DEF 80196 /* Revision ID */
#define FFCONF_DEF 80286 /* Revision ID */
/*---------------------------------------------------------------------------/
/ Function Configurations
@ -14,7 +14,6 @@
/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
/ and optional writing functions as well. */
#define FF_FS_MINIMIZE 0
/* This option defines minimization level to remove some basic API functions.
/
@ -24,51 +23,58 @@
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
/ 3: f_lseek() function is removed in addition to 2. */
#define FF_USE_STRFUNC 0
/* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf().
/
/ 0: Disable string functions.
/ 1: Enable without LF-CRLF conversion.
/ 2: Enable with LF-CRLF conversion. */
#define FF_USE_FIND 0
/* This option switches filtered directory read functions, f_findfirst() and
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
#define FF_USE_MKFS 0
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
#define FF_USE_FASTSEEK 0
/* This option switches fast seek function. (0:Disable or 1:Enable) */
#define FF_USE_EXPAND 0
/* This option switches f_expand function. (0:Disable or 1:Enable) */
#define FF_USE_CHMOD 0
/* This option switches attribute manipulation functions, f_chmod() and f_utime().
/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */
#define FF_USE_LABEL 0
/* This option switches volume label functions, f_getlabel() and f_setlabel().
/ (0:Disable or 1:Enable) */
#define FF_USE_FORWARD 0
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
#define FF_USE_STRFUNC 0
#define FF_PRINT_LLI 1
#define FF_PRINT_FLOAT 1
#define FF_STRF_ENCODE 3
/* FF_USE_STRFUNC switches string functions, f_gets(), f_putc(), f_puts() and
/ f_printf().
/
/ 0: Disable. FF_PRINT_LLI, FF_PRINT_FLOAT and FF_STRF_ENCODE have no effect.
/ 1: Enable without LF-CRLF conversion.
/ 2: Enable with LF-CRLF conversion.
/
/ FF_PRINT_LLI = 1 makes f_printf() support long long argument and FF_PRINT_FLOAT = 1/2
/ makes f_printf() support floating point argument. These features want C99 or later.
/ When FF_LFN_UNICODE >= 1 with LFN enabled, string functions convert the character
/ encoding in it. FF_STRF_ENCODE selects assumption of character encoding ON THE FILE
/ to be read/written via those functions.
/
/ 0: ANSI/OEM in current CP
/ 1: Unicode in UTF-16LE
/ 2: Unicode in UTF-16BE
/ 3: Unicode in UTF-8
*/
/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/
#define FF_CODE_PAGE 932
#define FF_CODE_PAGE 437
/* This option specifies the OEM code page to be used on the target system.
/ Incorrect code page setting can cause a file open failure.
/
@ -96,7 +102,6 @@
/ 0 - Include all code pages above and configured by f_setcp()
*/
#define FF_USE_LFN 1
#define FF_MAX_LFN 255
/* The FF_USE_LFN switches the support for LFN (long file name).
@ -116,7 +121,6 @@
/ memory for the working buffer, memory management functions, ff_memalloc() and
/ ff_memfree() exemplified in ffsystem.c, need to be added to the project. */
#define FF_LFN_UNICODE 0
/* This option switches the character encoding on the API when LFN is enabled.
/
@ -128,7 +132,6 @@
/ Also behavior of string I/O functions will be affected by this option.
/ When LFN is not enabled, this option has no effect. */
#define FF_LFN_BUF 255
#define FF_SFN_BUF 12
/* This set of options defines size of file name members in the FILINFO structure
@ -136,20 +139,6 @@
/ the file names to read. The maximum possible length of the read file name depends
/ on character encoding. When LFN is not enabled, these options have no effect. */
#define FF_STRF_ENCODE 3
/* When FF_LFN_UNICODE >= 1 with LFN enabled, string I/O functions, f_gets(),
/ f_putc(), f_puts and f_printf() convert the character encoding in it.
/ This option selects assumption of character encoding ON THE FILE to be
/ read/written via those functions.
/
/ 0: ANSI/OEM in current CP
/ 1: Unicode in UTF-16LE
/ 2: Unicode in UTF-16BE
/ 3: Unicode in UTF-8
*/
#define FF_FS_RPATH 0
/* This option configures support for relative path.
/
@ -158,7 +147,6 @@
/ 2: f_getcwd() function is available in addition to 1.
*/
/*---------------------------------------------------------------------------/
/ Drive/Volume Configurations
/---------------------------------------------------------------------------*/
@ -166,57 +154,49 @@
#define FF_VOLUMES 1
/* Number of volumes (logical drives) to be used. (1-10) */
#define FF_STR_VOLUME_ID 0
#define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
#define FF_VOLUME_STRS "RAM", "NAND", "CF", "SD", "SD2", "USB", "USB2", "USB3"
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
/ logical drives. Number of items must not be less than FF_VOLUMES. Valid
/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are
/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is
/ not defined, a user defined volume string table needs to be defined as:
/ not defined, a user defined volume string table is needed as:
/
/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",...
*/
#define FF_MULTI_PARTITION 0
/* This option switches support for multiple volumes on the physical drive.
/ By default (0), each logical drive number is bound to the same physical drive
/ number and only an FAT volume found on the physical drive will be mounted.
/ When this function is enabled (1), each logical drive number can be bound to
/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
/ funciton will be available. */
/ function will be available. */
#define FF_MIN_SS 512
#define FF_MAX_SS 512
/* This set of options configures the range of sector size to be supported. (512,
/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
/ harddisk. But a larger value may be required for on-board flash memory and some
/ harddisk, but a larger value may be required for on-board flash memory and some
/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured
/ for variable sector size mode and disk_ioctl() function needs to implement
/ GET_SECTOR_SIZE command. */
#define FF_LBA64 0
/* This option switches support for 64-bit LBA. (0:Disable or 1:Enable)
/ To enable the 64-bit LBA, also exFAT needs to be enabled. (FF_FS_EXFAT == 1) */
#define FF_MIN_GPT 0x10000000
/* Minimum number of sectors to switch GPT as partitioning format in f_mkfs and
/ f_fdisk function. 0x100000000 max. This option has no effect when FF_LBA64 == 0. */
#define FF_USE_TRIM 0
/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable)
/ To enable Trim function, also CTRL_TRIM command should be implemented to the
/ disk_ioctl() function. */
/*---------------------------------------------------------------------------/
/ System Configurations
/---------------------------------------------------------------------------*/
@ -227,30 +207,27 @@
/ Instead of private sector buffer eliminated from the file object, common sector
/ buffer in the filesystem object (FATFS) is used for the file data transfer. */
#define FF_FS_EXFAT 0
#define FF_FS_EXFAT 1
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
/ To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1)
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
#define FF_FS_NORTC 0
#define FF_NORTC_MON 1
#define FF_NORTC_MDAY 1
#define FF_NORTC_YEAR 2020
/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
/ the timestamp function. Every object modified by FatFs will have a fixed timestamp
#define FF_NORTC_YEAR 2022
/* The option FF_FS_NORTC switches timestamp feature. If the system does not have
/ an RTC or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable the
/ timestamp feature. Every object modified by FatFs will have a fixed timestamp
/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time.
/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be
/ added to the project to read current time form real-time clock. FF_NORTC_MON,
/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect.
/ These options have no effect in read-only configuration (FF_FS_READONLY = 1). */
#define FF_FS_NOFSINFO 0
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
/ option, and f_getfree() function at first time after volume mount will force
/ option, and f_getfree() function at the first time after volume mount will force
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
/
/ bit0=0: Use free cluster count in the FSINFO if available.
@ -259,7 +236,6 @@
/ bit1=1: Do not trust last allocated cluster number in the FSINFO.
*/
#define FF_FS_LOCK 0
/* The option FF_FS_LOCK switches file lock function to control duplicated file open
/ and illegal operation to open objects. This option must be 0 when FF_FS_READONLY
@ -271,28 +247,20 @@
/ can be opened simultaneously under file lock control. Note that the file
/ lock control is independent of re-entrancy. */
/* #include <somertos.h> // O/S definitions */
#define FF_FS_REENTRANT 0
#define FF_FS_TIMEOUT 1000
#define FF_SYNC_t HANDLE
/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
/ module itself. Note that regardless of this option, file access to different
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
/ and f_fdisk() function, are always not re-entrant. Only file/directory access
/ to the same volume is under control of this function.
/ to the same volume is under control of this featuer.
/
/ 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect.
/ 0: Disable re-entrancy. FF_FS_TIMEOUT have no effect.
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
/ function, must be added to the project. Samples are available in
/ option/syscall.c.
/ ff_mutex_create(), ff_mutex_delete(), ff_mutex_take() and ff_mutex_give()
/ function, must be added to the project. Samples are available in ffsystem.c.
/
/ The FF_FS_TIMEOUT defines timeout period in unit of time tick.
/ The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
/ included somewhere in the scope of ff.h. */
/ The FF_FS_TIMEOUT defines timeout period in unit of O/S time tick.
*/
/*--- End of configuration options ---*/

View file

@ -1,170 +1,208 @@
/*------------------------------------------------------------------------*/
/* Sample Code of OS Dependent Functions for FatFs */
/* (C)ChaN, 2018 */
/* A Sample Code of User Provided OS Dependent Functions for FatFs */
/*------------------------------------------------------------------------*/
#include "ff.h"
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
#if FF_USE_LFN == 3 /* Use dynamic memory allocation */
/*------------------------------------------------------------------------*/
/* Allocate a memory block */
/* Allocate/Free a Memory Block */
/*------------------------------------------------------------------------*/
#include <stdlib.h> /* with POSIX API */
void* ff_memalloc ( /* Returns pointer to the allocated memory block (null if not enough core) */
UINT msize /* Number of bytes to allocate */
)
{
return malloc(msize); /* Allocate a new memory block with POSIX API */
return malloc((size_t)msize); /* Allocate a new memory block */
}
/*------------------------------------------------------------------------*/
/* Free a memory block */
/*------------------------------------------------------------------------*/
void ff_memfree (
void* mblock /* Pointer to the memory block to free (nothing to do if null) */
void* mblock /* Pointer to the memory block to free (no effect if null) */
)
{
free(mblock); /* Free the memory block with POSIX API */
free(mblock); /* Free the memory block */
}
#endif
#if FF_FS_REENTRANT /* Mutal exclusion */
/*------------------------------------------------------------------------*/
/* Create a Synchronization Object */
/* Definitions of Mutex */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to create a new
/ synchronization object for the volume, such as semaphore and mutex.
/ When a 0 is returned, the f_mount() function fails with FR_INT_ERR.
*/
//const osMutexDef_t Mutex[FF_VOLUMES]; /* Table of CMSIS-RTOS mutex */
#define OS_TYPE 0 /* 0:Win32, 1:uITRON4.0, 2:uC/OS-II, 3:FreeRTOS, 4:CMSIS-RTOS */
int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */
BYTE vol, /* Corresponding volume (logical drive number) */
FF_SYNC_t* sobj /* Pointer to return the created sync object */
)
{
/* Win32 */
*sobj = CreateMutex(NULL, FALSE, NULL);
return (int)(*sobj != INVALID_HANDLE_VALUE);
#if OS_TYPE == 0 /* Win32 */
#include <windows.h>
static HANDLE Mutex[FF_VOLUMES + 1]; /* Table of mutex handle */
/* uITRON */
// T_CSEM csem = {TA_TPRI,1,1};
// *sobj = acre_sem(&csem);
// return (int)(*sobj > 0);
#elif OS_TYPE == 1 /* uITRON */
#include "itron.h"
#include "kernel.h"
static mtxid Mutex[FF_VOLUMES + 1]; /* Table of mutex ID */
/* uC/OS-II */
// OS_ERR err;
// *sobj = OSMutexCreate(0, &err);
// return (int)(err == OS_NO_ERR);
#elif OS_TYPE == 2 /* uc/OS-II */
#include "includes.h"
static OS_EVENT *Mutex[FF_VOLUMES + 1]; /* Table of mutex pinter */
/* FreeRTOS */
// *sobj = xSemaphoreCreateMutex();
// return (int)(*sobj != NULL);
#elif OS_TYPE == 3 /* FreeRTOS */
#include "FreeRTOS.h"
#include "semphr.h"
static SemaphoreHandle_t Mutex[FF_VOLUMES + 1]; /* Table of mutex handle */
/* CMSIS-RTOS */
// *sobj = osMutexCreate(&Mutex[vol]);
// return (int)(*sobj != NULL);
}
/*------------------------------------------------------------------------*/
/* Delete a Synchronization Object */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to delete a synchronization
/ object that created with ff_cre_syncobj() function. When a 0 is returned,
/ the f_mount() function fails with FR_INT_ERR.
*/
int ff_del_syncobj ( /* 1:Function succeeded, 0:Could not delete due to an error */
FF_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */
)
{
/* Win32 */
return (int)CloseHandle(sobj);
/* uITRON */
// return (int)(del_sem(sobj) == E_OK);
/* uC/OS-II */
// OS_ERR err;
// OSMutexDel(sobj, OS_DEL_ALWAYS, &err);
// return (int)(err == OS_NO_ERR);
/* FreeRTOS */
// vSemaphoreDelete(sobj);
// return 1;
/* CMSIS-RTOS */
// return (int)(osMutexDelete(sobj) == osOK);
}
/*------------------------------------------------------------------------*/
/* Request Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on entering file functions to lock the volume.
/ When a 0 is returned, the file function fails with FR_TIMEOUT.
*/
int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */
FF_SYNC_t sobj /* Sync object to wait */
)
{
/* Win32 */
return (int)(WaitForSingleObject(sobj, FF_FS_TIMEOUT) == WAIT_OBJECT_0);
/* uITRON */
// return (int)(wai_sem(sobj) == E_OK);
/* uC/OS-II */
// OS_ERR err;
// OSMutexPend(sobj, FF_FS_TIMEOUT, &err));
// return (int)(err == OS_NO_ERR);
/* FreeRTOS */
// return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE);
/* CMSIS-RTOS */
// return (int)(osMutexWait(sobj, FF_FS_TIMEOUT) == osOK);
}
/*------------------------------------------------------------------------*/
/* Release Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on leaving file functions to unlock the volume.
*/
void ff_rel_grant (
FF_SYNC_t sobj /* Sync object to be signaled */
)
{
/* Win32 */
ReleaseMutex(sobj);
/* uITRON */
// sig_sem(sobj);
/* uC/OS-II */
// OSMutexPost(sobj);
/* FreeRTOS */
// xSemaphoreGive(sobj);
/* CMSIS-RTOS */
// osMutexRelease(sobj);
}
#elif OS_TYPE == 4 /* CMSIS-RTOS */
#include "cmsis_os.h"
static osMutexId Mutex[FF_VOLUMES + 1]; /* Table of mutex ID */
#endif
/*------------------------------------------------------------------------*/
/* Create a Mutex */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount function to create a new mutex
/ or semaphore for the volume. When a 0 is returned, the f_mount function
/ fails with FR_INT_ERR.
*/
int ff_mutex_create ( /* Returns 1:Function succeeded or 0:Could not create the mutex */
int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */
)
{
#if OS_TYPE == 0 /* Win32 */
Mutex[vol] = CreateMutex(NULL, FALSE, NULL);
return (int)(Mutex[vol] != INVALID_HANDLE_VALUE);
#elif OS_TYPE == 1 /* uITRON */
T_CMTX cmtx = {TA_TPRI,1};
Mutex[vol] = acre_mtx(&cmtx);
return (int)(Mutex[vol] > 0);
#elif OS_TYPE == 2 /* uC/OS-II */
OS_ERR err;
Mutex[vol] = OSMutexCreate(0, &err);
return (int)(err == OS_NO_ERR);
#elif OS_TYPE == 3 /* FreeRTOS */
Mutex[vol] = xSemaphoreCreateMutex();
return (int)(Mutex[vol] != NULL);
#elif OS_TYPE == 4 /* CMSIS-RTOS */
osMutexDef(cmsis_os_mutex);
Mutex[vol] = osMutexCreate(osMutex(cmsis_os_mutex));
return (int)(Mutex[vol] != NULL);
#endif
}
/*------------------------------------------------------------------------*/
/* Delete a Mutex */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount function to delete a mutex or
/ semaphore of the volume created with ff_mutex_create function.
*/
void ff_mutex_delete ( /* Returns 1:Function succeeded or 0:Could not delete due to an error */
int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */
)
{
#if OS_TYPE == 0 /* Win32 */
CloseHandle(Mutex[vol]);
#elif OS_TYPE == 1 /* uITRON */
del_mtx(Mutex[vol]);
#elif OS_TYPE == 2 /* uC/OS-II */
OS_ERR err;
OSMutexDel(Mutex[vol], OS_DEL_ALWAYS, &err);
#elif OS_TYPE == 3 /* FreeRTOS */
vSemaphoreDelete(Mutex[vol]);
#elif OS_TYPE == 4 /* CMSIS-RTOS */
osMutexDelete(Mutex[vol]);
#endif
}
/*------------------------------------------------------------------------*/
/* Request a Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on enter file functions to lock the volume.
/ When a 0 is returned, the file function fails with FR_TIMEOUT.
*/
int ff_mutex_take ( /* Returns 1:Succeeded or 0:Timeout */
int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */
)
{
#if OS_TYPE == 0 /* Win32 */
return (int)(WaitForSingleObject(Mutex[vol], FF_FS_TIMEOUT) == WAIT_OBJECT_0);
#elif OS_TYPE == 1 /* uITRON */
return (int)(tloc_mtx(Mutex[vol], FF_FS_TIMEOUT) == E_OK);
#elif OS_TYPE == 2 /* uC/OS-II */
OS_ERR err;
OSMutexPend(Mutex[vol], FF_FS_TIMEOUT, &err));
return (int)(err == OS_NO_ERR);
#elif OS_TYPE == 3 /* FreeRTOS */
return (int)(xSemaphoreTake(Mutex[vol], FF_FS_TIMEOUT) == pdTRUE);
#elif OS_TYPE == 4 /* CMSIS-RTOS */
return (int)(osMutexWait(Mutex[vol], FF_FS_TIMEOUT) == osOK);
#endif
}
/*------------------------------------------------------------------------*/
/* Release a Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on leave file functions to unlock the volume.
*/
void ff_mutex_give (
int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */
)
{
#if OS_TYPE == 0 /* Win32 */
ReleaseMutex(Mutex[vol]);
#elif OS_TYPE == 1 /* uITRON */
unl_mtx(Mutex[vol]);
#elif OS_TYPE == 2 /* uC/OS-II */
OSMutexPost(Mutex[vol]);
#elif OS_TYPE == 3 /* FreeRTOS */
xSemaphoreGive(Mutex[vol]);
#elif OS_TYPE == 4 /* CMSIS-RTOS */
osMutexRelease(Mutex[vol]);
#endif
}
#endif /* FF_FS_REENTRANT */

15593
software/system/ff/ffunicode.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,149 @@
/*------------------------------------------------------------------------*/
/* STM32F100: MMCv3/SDv1/SDv2 (SPI mode) control module */
/*------------------------------------------------------------------------*/
/*
/ Copyright (C) 2018, ChaN, all right reserved.
/
/ * This software is a free software and there is NO WARRANTY.
/ * No restriction on use. You can use, modify and redistribute it for
/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
/ * Redistributions of source code must retain the above copyright notice.
/
/-------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------
Module Private Functions
---------------------------------------------------------------------------*/
#include "ost_hal.h"
#include "debug.h"
#include "ff.h"
#include "diskio.h"
#include "sdcard.h"
#include "ffconf.h"
/*-----------------------------------------------------------------------*/
/* Initialize a Drive */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize(
BYTE drv /* Physical drive number (0..) */
)
{
if (drv)
return STA_NOINIT;
if (sdcard_init() != SD_RESPONSE_NO_ERROR)
return STA_NOINIT;
return 0;
}
/*-----------------------------------------------------------------------*/
/* Return Drive Status */
/*-----------------------------------------------------------------------*/
DSTATUS disk_status(
BYTE drv /* Physical drive number (0..) */
)
{
if (drv)
return STA_NOINIT;
return 0;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_read(
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
LBA_t sector, /* Start sector in LBA */
UINT count /* Number of sectors to read */
)
{
DRESULT res;
if (pdrv || !count)
return RES_PARERR;
if (count == 1)
res = (DRESULT)sdcard_sector_read(sector, buff);
else
res = (DRESULT)sdcard_sectors_read(sector, buff, count);
if (res == 0x00)
return RES_OK;
return RES_ERROR;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
#if _READONLY == 0
DRESULT disk_write(
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
LBA_t sector, /* Start sector in LBA */
UINT count /* Number of sectors to write */
)
{
DRESULT res;
if (pdrv || !count)
return RES_PARERR;
if (count == 1)
res = (DRESULT)sdcard_sector_write(sector, buff);
else
res = (DRESULT)sdcard_sectors_write(sector, buff, count);
if (res == 0)
return RES_OK;
return RES_ERROR;
}
#endif /* _READONLY */
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
DRESULT disk_ioctl(
BYTE drv, /* Physical drive number (0..) */
BYTE ctrl, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
SD_CardInfo cardinfo;
DRESULT res;
if (drv)
return RES_PARERR;
switch (ctrl)
{
case CTRL_SYNC:
// res = ( SD_WaitReady() == SD_RESPONSE_NO_ERROR ) ? RES_OK : RES_ERROR
res = RES_OK;
break;
case GET_BLOCK_SIZE:
*(WORD *)buff = FF_MAX_SS;
res = RES_OK;
break;
case GET_SECTOR_COUNT:
if (sdcard_get_card_info(&cardinfo) != SD_RESPONSE_NO_ERROR)
res = RES_ERROR;
else
{
*(DWORD *)buff = cardinfo.CardCapacity;
res = (*(DWORD *)buff > 0) ? RES_OK : RES_PARERR;
}
break;
case CTRL_TRIM:
res = (sdcard_sectors_erase(((DWORD *)buff)[0], ((DWORD *)buff)[1]) == SD_RESPONSE_NO_ERROR)
? RES_OK
: RES_PARERR;
break;
default:
res = RES_PARERR;
break;
}
return res;
}

View file

@ -35,12 +35,20 @@ int main(void)
return 0;
}
#else
#include "sdcard.h"
int main()
{
ost_system_initialize();
// 1. Test the printf output
debug_printf("\r\n>>>>> Starting OpenStoryTeller tests: V%d.%d <<<<<\n", 1, 0);
debug_printf("\r\n [OST] Starting OpenStoryTeller tests: V%d.%d\r\n", 1, 0);
filesystem_mount();
// 2. Unit test the SD Card
// sdcard_init();
for (;;)
{

File diff suppressed because it is too large Load diff

316
software/system/sdcard.h Normal file
View file

@ -0,0 +1,316 @@
#pragma once
#include <stdint.h>
/**
* @brief Card Specific Data: CSD Register
*/
typedef struct _SD_CSD
{ /* v1 v2 bits */
uint8_t CSDStruct; /*!< 2 x (=0) CSD structure */
uint8_t SysSpecVersion; /*!< 4 x (reserved=0) System specification version */
uint8_t Reserved1; /*!< 2 x Reserved */
uint8_t TAAC; /*!< 8 x Data read access-time 1 */
uint8_t NSAC; /*!< 8 x Data read access-time 2 in CLK cycles */
uint8_t MaxBusClkFrec; /*!< 8 x (={32,5A}) Max. bus clock frequency */
uint16_t CardComdClasses; /*!< 12 x (=01x110110101) Card command classes */
uint8_t RdBlockLen; /*!< 4 x Max. read data block length */
uint8_t PartBlockRead; /*!< 1 x (=1) Partial blocks for read allowed */
uint8_t WrBlockMisalign; /*!< 1 x Write block misalignment */
uint8_t RdBlockMisalign; /*!< 1 x Read block misalignment */
uint8_t DSRImpl; /*!< 1 x DSR implemented */
uint8_t Reserved2; /*!< 2 (=0) Reserved */
// {{ these 27 bits are for v1:
uint32_t DeviceSize; /*!< 12 Device Size */
uint8_t MaxRdCurrentVDDMin; /*!< 3 Max. read current @ VDD min */
uint8_t MaxRdCurrentVDDMax; /*!< 3 Max. read current @ VDD max */
uint8_t MaxWrCurrentVDDMin; /*!< 3 Max. write current @ VDD min */
uint8_t MaxWrCurrentVDDMax; /*!< 3 Max. write current @ VDD max */
uint8_t DeviceSizeMul; /*!< 3 Device size multiplier */
// }}
// {{ these 27 bits are for v2:
uint8_t Reserved5; /*!< 4 (=0) Reserved */
// uint32_t DeviceSize; /*!< 22 Device Size */
uint8_t Reserved6; /*!< 1 (=0) Reserved */
// }}
uint8_t EraseBlockEnable; /*!< 1 x (=1 for v2) Erase single block enable */
uint8_t EraseSectorSize; /*!< 7 x (=7F for v2) Erase sector size */
uint8_t WrProtectGrSize; /*!< 7 x Write protect group size */
uint8_t WrProtectGrEnable; /*!< 1 x Write protect group enable */
uint8_t ManDeflECC; /*!< 2 x (reserved=0) Manufacturer default ECC */
uint8_t WrSpeedFact; /*!< 3 x Write speed factor */
uint8_t MaxWrBlockLen; /*!< 4 x Max. write data block length */
uint8_t WriteBlockPaPartial; /*!< 1 x Partial blocks for write allowed */
uint8_t Reserved3; /*!< 4 x (=0) Reserved */
uint8_t ContentProtectAppli; /*!< 1 x (reserved=0) Content protection application */
uint8_t FileFormatGroup; /*!< 1 x File format group */
uint8_t CopyFlag; /*!< 1 x Copy flag (OTP) */
uint8_t PermWrProtect; /*!< 1 x Permanent write protection */
uint8_t TempWrProtect; /*!< 1 x Temporary write protection */
uint8_t FileFormat; /*!< 2 x File Format */
uint8_t ECC; /*!< 2 x (reserved=0) ECC code */
uint8_t CSD_CRC; /*!< 7 x CSD CRC */
uint8_t Reserved4; /*!< 1 x (=1) not used */
} SD_CSD;
/**
* @brief SD Card Configuration Register
*/
typedef struct _SD_SCR
{ /* bits */
uint8_t SCR_Version; /*!< :4 (=0, else reserved) SCR structure version */
uint8_t SpecVersion; /*!< :4 Physical layer specification version number
0 - Version 1.0 and 1.01
1 - Version 1.10
2 - Version 2.00 or 3.0x
3-15 - reserved */
uint8_t StateAfterErase; /*!< :1 State of bits after sector erase */
uint8_t Security; /*!< :3 CPRM security version
0 - no security
1 - not used
2 - SDSC security ver 1.01
3 - SDHC security ver 2.00
4 - SDXC security ver 3.xx
5-7 - reserved */
uint8_t BusWidth; /*!< :4 Supported data bus width
bit 0 - 1 bit
bit 1 - reserved
bit 2 - 4 bit
bit 3 - reserved */
uint8_t SpecVersion3; /*!< :1 Distinguish between SpecVersion 2.00 or 3.0x */
uint8_t ExSecurity; /*!< :4 Extended security (0 if not supported) */
uint16_t Reserved1; /*!< :9 Reserved */
uint8_t CmdSupport1; /*!< :1 Support of CMD23 (set block count) */
uint8_t CmdSupport2; /*!< :1 Support of CMD20 (speed class control) */
uint32_t Reserved2; /*!< :32 Reserved */
} SD_SCR;
/**
* @brief Card Identification Data: CID Register
*/
typedef struct _SD_CID
{ /* bits */
uint8_t ManufacturerID; /*!< : 8 ManufacturerID */
uint16_t OEM_AppliID; /*!< :16 OEM/Application ID (2-char string) */
uint32_t ProdName1; /*!< :32 Product Name part1 (4-char string) */
uint8_t ProdName2; /*!< : 8 Product Name part2 (1-char string) */
uint8_t ProdRev; /*!< : 8 Product Revision (x.y, where x and y take 4 bits each) */
uint32_t ProdSN; /*!< :32 Product Serial Number */
uint8_t Reserved1; /*!< : 4 Reserved */
uint16_t ManufactDate; /*!< :12 Manufacturing Date (bits 0-3: month, bits 4-11: year-2000) */
uint8_t CID_CRC; /*!< : 7 CID CRC */
uint8_t Reserved2; /*!< : 1 Not used, always 1 */
} SD_CID;
/**
* @brief SD Card information
*/
typedef struct _SD_CardInfo
{
SD_CSD SD_csd;
SD_CID SD_cid;
SD_SCR SD_scr;
uint32_t CardCapacity; /*!< Card Capacity */
uint32_t CardBlockSize; /*!< Card Block Size */
} SD_CardInfo;
/**
* @brief SD Card Status structure
*/
typedef struct _SD_Status
{ /* bits */
uint8_t BusWidth; /*!< : 2 Bus width */
uint8_t InSecuredMode; /*!< : 1 Set if SD card is in secured mode */
uint16_t Reserved1; /*!< : 13 Reserved */
uint16_t CardType; /*!< : 16 Card Type
0000h - Regular SD card
0001h - SD ROM card
0002h - OTP card */
uint32_t SizeProtectedArea; /*!< : 32 Size of protected area */
uint8_t SpeedClass; /*!< : 8 Speed class
00h - Class 0
01h - Class 2
02h - Class 4
03h - Class 6
04h - Class 10
05h-FFh - reserved */
uint8_t PerformanceMove; /*!< : 8 Performance move
00h - Sequential write
0xh - x Mb/sec
FFh - Infinity */
uint8_t AU_Size; /*!< : 4 Allocation Unit size
0h - not defined
1h - 16 Kb
2h - 32 Kb
3h - 64 Kb
4h - 128 Kb
5h - 256 Kb
6h - 512 Kb
7h - 1 Mb
8h - 2 Mb
9h - 4 Mb
Ah - 8 Mb
Bh - 12 Mb
Ch - 16 Mb
Dh - 24 Mb
Eh - 32 Mb
Fh - 64 Mb */
uint8_t Reserved2; /*!< : 4 Reserved */
uint16_t EraseSize; /*!< : 16 Erase Size in AU blocks */
uint8_t EraseTimeout; /*!< : 6 Erase Timeout in seconds */
uint8_t EraseOffset; /*!< : 2 Erase Offset in seconds */
uint8_t UHS_SpeedGrade; /*!< : 4 Speed Grade for UHS mode (0 - <10 Mb/sec, 1 - > 10 Mb/sec) */
uint8_t UHS_AU_Size; /*!< : 4 Allocation Unit size for UHS mode
0h - not defined
1h-6h - not used
7h - 1 Mb
8h - 2 Mb
9h - 4 Mb
Ah - 8 Mb
Bh - 12 Mb
Ch - 16 Mb
Dh - 24 Mb
Eh - 32 Mb
Fh - 64 Mb */
} SD_Status;
/**
* @brief SD R1 responses
*/
typedef enum _SD_Error
{
SD_RESPONSE_NO_ERROR = 0x00,
SD_IN_IDLE_STATE = 0x01,
SD_ERASE_RESET = 0x02,
SD_ILLEGAL_COMMAND = 0x04,
SD_COMMAND_CRC_ERROR = 0x08,
SD_ERASE_SEQUENCE_ERROR = 0x10,
SD_ADDRESS_ERROR = 0x20,
SD_PARAMETER_ERROR = 0x40,
SD_CHECK_BIT = 0x80, /*!< this bit must be set to 0 */
SD_RESPONSE_FAILURE = 0xFF
} SD_Error;
/**
* @}
*/
/* STM32_Exported_Types */
/** @defgroup STM32_Exported_Constants
* @{
*/
/**
* @brief Block (1 NAND sector) size
*/
#define SD_BLOCK_SIZE 0x200
/**
* @brief SD detection on its memory slot
*/
#define SD_PRESENT ((uint8_t)0x01)
#define SD_NOT_PRESENT ((uint8_t)0x00)
/**
* @brief Type of SD card
*/
typedef enum _SDCardType
{
SD_Card_MMC, /*!< Multimedia card (no CMD8, no ACMD41, but CMD1, uses byte-addressing) */
SD_Card_SDSC_v1, /*!< Standard Capacity card v1 (no CMD8, but ACMD41, uses byte-addressing) */
SD_Card_SDSC_v2, /*!< Standard Capacity card v2 (has CMD8+ACMD41, uses byte-addressing) */
SD_Card_SDHC /*!< High Capacity card (has CMD8+ACMD41, uses sector-addressing) */
} SDCardType;
/**
* @brief Data response sent for CMD24
*/
typedef enum _SD_DataResponse
{
SD_RESPONSE_MASK = 0x0E, /*!< any response value bits have to be masked by this */
SD_RESPONSE_ACCEPTED = 0x04, /*!< data accepted */
SD_RESPONSE_REJECTED_CRC = 0x0A, /*!< data rejected due to CRC error */
SD_RESPONSE_REJECTED_ERR = 0x0C /*!< data rejected due to write error */
} SD_DataResponse;
/**
* @brief Data response error
*/
typedef enum _SD_DataError
{
SD_DATA_TOKEN_OK = 0x00,
SD_DATA_TOKEN_ERROR = 0x01,
SD_DATA_TOKEN_CC_ERROR = 0x02,
SD_DATA_TOKEN_ECC_FAILURE = 0x04,
SD_DATA_TOKEN_OUT_OF_RANGE = 0x08,
SD_DATA_TOKEN_CARD_LOCKED = 0x10,
} SD_DataError;
/**
* @brief Commands: CMDxx = CMD-number | 0x40
*/
/*
class 0 (basic):
CMD0 CMD2 CMD3 CMD4
CMD7 CMD8 CMD9 CMD10
CMD11 CMD12 CMD13 CMD15
class 2 (block read):
CMD16 CMD17 CMD18 CMD19 CMD20 CMD23
class 4 (block write):
CMD16 CMD20 CMD23 CMD24 CMD25 CMD27
class 5 (erase):
CMD32 CMD33 CMD38
class 6 (write protection):
CMD28 CMD29 CMD30
class 7 (lock card):
CMD16 CMD40 CMD42
class 8 (application-specific):
CMD55 CMD56
ACMD6 ACMD13 ACMD22 ACMD23 ACMD41 ACMD42 ACMD51
class 9 (I/O mode):
CMD5 CMD52 CMD53
class 10 (switch):
CMD6 CMD34 CMD35 CMD36 CMD37 CMD50 CMD57
all other classes are reserved
*/
typedef enum _SD_CMD
{
SD_CMD_GO_IDLE_STATE = 0, /*!< CMD0 = 0x40, ARG=0x00000000, CRC=0x95 */
SD_CMD_SEND_OP_COND = 1, /*!< CMD1 = 0x41 */
SD_CMD_SEND_IF_COND = 8, /*!< CMD8 = 0x48, ARG=0x000001AA, CRC=0x87 */
SD_CMD_SEND_APP = 55, /*!< CMD55 = 0x77, ARG=0x00000000, CRC=0x65 */
SD_CMD_ACTIVATE_INIT = 41, /*!< ACMD41= 0x69, ARG=0x40000000, CRC=0x77 */
SD_CMD_READ_OCR = 58, /*!< CMD58 = 0x7A, ARG=0x00000000, CRC=0xFF */
SD_CMD_SEND_CSD = 9, /*!< CMD9 = 0x49 */
SD_CMD_SEND_CID = 10, /*!< CMD10 = 0x4A */
SD_CMD_SEND_SCR = 51, /*!< ACMD51= 0x73 */
SD_CMD_STATUS = 13, /*!< ACMD13= 0x4D */
SD_CMD_STOP_TRANSMISSION = 12, /*!< CMD12 = 0x4C */
SD_CMD_SET_BLOCKLEN = 16, /*!< CMD16 = 0x50 */
SD_CMD_READ_SINGLE_BLOCK = 17, /*!< CMD17 = 0x51 */
SD_CMD_READ_MULT_BLOCK = 18, /*!< CMD18 = 0x52 */
SD_CMD_SET_BLOCK_COUNT = 23, /*!< CMD23 = 0x57 */
SD_CMD_WRITE_SINGLE_BLOCK = 24, /*!< CMD24 = 0x58 */
SD_CMD_WRITE_MULT_BLOCK = 25, /*!< CMD25 = 0x59 */
SD_CMD_ERASE_BLOCK_START = 32, /*!< CMD32 = 0x60 */
SD_CMD_ERASE_BLOCK_END = 33, /*!< CMD33 = 0x61 */
SD_CMD_ERASE = 38 /*!< CMD38 = 0x66 */
} SD_CMD;
// ===============================================================================================================
// PUBLIC FUNCTIONS INTERFACE
// ===============================================================================================================
SD_Error sdcard_init();
SD_Error sdcard_get_card_info(SD_CardInfo *cardinfo);
void sdcard_dump_status(const SD_Status *SD_status);
void sdcard_dump_card_info(const SD_CardInfo *cardinfo);
SD_Error sdcard_sector_read(uint32_t readAddr, uint8_t *pBuffer);
SD_Error sdcard_sectors_read(uint32_t readAddr, uint8_t *pBuffer, uint32_t nbSectors);
SD_Error sdcard_sector_write(uint32_t writeAddr, const uint8_t *pBuffer);
SD_Error sdcard_sectors_write(uint32_t writeAddr, const uint8_t *pBuffer, uint32_t nbSectors);
SD_Error sdcard_sectors_erase(uint32_t eraseAddrFrom, uint32_t eraseAddrTo);