Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update fatfs to R0.13c #145

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion config/attributes.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ local sf = string.format
local function _validate_choice( adesc, aname, aval, elname, sectname )
aval = tostring( aval ):lower()
for k, v in pairs( adesc.attrvals ) do
if v == aval then return v end
--TH: Fix to allow numerical values as value table
local _v = tostring( v ):lower()
if _v == aval then return _v end
end
return false, sf( "invalid value '%s' for attribute '%s' of element '%s' in section '%s'", aval, aname, elname, sectname )
end
Expand Down
83 changes: 66 additions & 17 deletions config/components.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,26 +25,63 @@ end
-- MMCFS support

local function mmcfs_auxcheck( eldesc, data, enabled )
local ports, pins, spis = data.MMCFS_CS_PORT.value, data.MMCFS_CS_PIN.value, data.MMCFS_SPI_NUM.value
if #ports ~= #pins or #pins ~= #spis then
return false, "non-equal sizes for values of 'cs_port', 'cs_pin' and 'spi' of element 'mmcfs' in secetion 'components'"
end

-- Only check when cs_port is defined
if data.MMCFS_CS_PORT then
if not data.MMCFS_CS_PIN then
return false, " section mmc : cs_port defined without cs_pin"
end
local ports, pins, spis = data.MMCFS_CS_PORT.value, data.MMCFS_CS_PIN.value, data.MMCFS_SPI_NUM.value
if #ports ~= #pins or #pins ~= #spis then
return false, "non-equal sizes for values of 'cs_port', 'cs_pin' and 'spi' of element 'mmcfs' in secetion 'components'"
end
end
return true
end

local function mmcfs_gen( eldesc, data, generated )
local ports, pins, spis = data.MMCFS_CS_PORT.value, data.MMCFS_CS_PIN.value, data.MMCFS_SPI_NUM.value
local data = ''
if #ports == 1 then -- single card
data = data .. gen.print_define( 'MMCFS_CS_PORT', ports[ 1 ] )
data = data .. gen.print_define( 'MMCFS_CS_PIN', pins[ 1 ] )
data = data .. gen.print_define( 'MMCFS_SPI_NUM', spis[ 1 ] )

local function get_boolean(v)

return v and v ~= 0
end

local ports, pins, spis
spis= data.MMCFS_SPI_NUM.value
if data.MMCFS_CS_PORT then
ports,pins = data.MMCFS_CS_PORT.value, data.MMCFS_CS_PIN.value
end
local out = ''
if #spis == 1 then -- single card
if ports then
out = out .. gen.print_define( 'MMCFS_CS_PORT', ports[ 1 ] ) ..
gen.print_define( 'MMCFS_CS_PIN', pins[ 1 ] )
end
out = out .. gen.print_define( 'MMCFS_SPI_NUM', spis[ 1 ] )
else -- multiple cards
data = data .. gen.print_define( 'MMCFS_CS_PORT_ARRAY', ports )
data = data .. gen.print_define( 'MMCFS_CS_PIN_ARRAY', pins )
data = data .. gen.print_define( 'MMCFS_SPI_NUM_ARRAY', spis )
if ports then
out = out .. gen.print_define( 'MMCFS_CS_PORT_ARRAY', ports ) ..
gen.print_define( 'MMCFS_CS_PIN_ARRAY', pins )
end
out = out .. gen.print_define( 'MMCFS_SPI_NUM_ARRAY', spis )
end
return data

local lfn_unicode= get_boolean(data.MMCFS_API_MODE.value) and '2' or '0'
local tiny = get_boolean(data.MMCFS_TINY.value) and '1' or '0'
if get_boolean(data.MMCFS_USE_LOCKING.value) then
out= out .. gen.print_define('MMCFS_USE_LOCKING')
end

out = out .. gen.print_define('MMCFS_CODEPAGE',data.MMCFS_CODEPAGE.value) ..

gen.simple_gen('MMCFS_USE_LFN',data,generated) ..
gen.simple_gen('MMCFS_MAX_LFN',data,generated) ..
gen.simple_gen('MMCFS_MAX_FDS',data,generated) ..
gen.print_define('MMCFS_API_MODE',lfn_unicode) ..
gen.print_define('MMCFS_TINY',tiny) ..
gen.print_define('MMCFS_NUM_CARDS',#spis)

return out
end

-------------------------------------------------------------------------------
Expand Down Expand Up @@ -176,9 +213,21 @@ function init()
auxcheck = mmcfs_auxcheck,
gen = mmcfs_gen,
attrs = {
cs_port = at.array_of( at.int_attr( 'MMCFS_CS_PORT' ), true ),
cs_pin = at.array_of( at.int_attr( 'MMCFS_CS_PIN' ), true ),
spi = at.array_of( at.int_attr( 'MMCFS_SPI_NUM' ), true )
cs_port =at.make_optional(at.array_of( at.int_attr( 'MMCFS_CS_PORT' ), true )),
cs_pin = at.make_optional(at.array_of( at.int_attr( 'MMCFS_CS_PIN' ), true )),

spi = at.array_of( at.int_attr( 'MMCFS_SPI_NUM' ), true ),

codepage = at.choice_attr('MMCFS_CODEPAGE',{
437,720,737,771,775,850,852,855,857,860,861,862,863,864,865,
866,869,932,936,949,950,0
},437),
lfn = at.choice_attr('MMCFS_USE_LFN',{0,1,2},1),
lfn_length=at.int_attr('MMCFS_MAX_LFN',30,255,30),
use_utf8_api=at.bool_attr('MMCFS_API_MODE',false),
tiny=at.bool_attr('MMCFS_TINY',true),
files=at.int_attr('MMCFS_MAX_FDS',4,32,4),
use_locking=at.bool_attr('MMCFS_USE_LOCKING',true)
}
}
-- RPC
Expand Down
5 changes: 5 additions & 0 deletions inc/newlib/devman.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@
#define DM_MAX_DEV_NAME 12

// GLOBAL maximum file length (on ALL supported filesystem)
//TH: Overwrite max filename length with config from mmcfs
#ifdef MMCFS_MAX_LFN
#define DM_MAX_FNAME_LENGTH MMCFS_MAX_LFN
#else
#define DM_MAX_FNAME_LENGTH 30
#endif

// Pack/unpack descriptions
// Even if a file descriptor is an 'int', newlib treats it as a short, so we need to stuff
Expand Down
54 changes: 31 additions & 23 deletions src/elua_mmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,28 +38,56 @@
#error "MMC not supported on this board"
#endif



#if defined( MMCFS_CS_PORT )
#if !defined( MMCFS_CS_PIN )
#error "mmcfs cs_port parameter without cs_pin parameter"
#endif

const u8 mmcfs_cs_ports[ NUM_CARDS ] = { MMCFS_CS_PORT };
static const u8 mmcfs_cs_pins[ NUM_CARDS ] = { MMCFS_CS_PIN };
static const u8 mmcfs_spi_nums[ NUM_CARDS ] = { MMCFS_SPI_NUM };

#elif defined( MMCFS_CS_PORT_ARRAY )
#if !defined( MMCFS_CS_PIN_ARRAY )
#error "mmcfs cs_port parameter without cs_pin parameter"
#endif

const u8 mmcfs_cs_ports[ NUM_CARDS ] = MMCFS_CS_PORT_ARRAY;
static const u8 mmcfs_cs_pins[ NUM_CARDS ] = MMCFS_CS_PIN_ARRAY;
static const u8 mmcfs_spi_nums[ NUM_CARDS ] = MMCFS_SPI_NUM_ARRAY;

#else
#pragma message "MMC driver using platform_spi_select for SD card CS"
#define __MMC_USE_SPI_SELECT

#endif

#if defined( MMCFS_SPI_NUM )
static const u8 mmcfs_spi_nums[ NUM_CARDS ] = { MMCFS_SPI_NUM };
#elif defined( MMCFS_SPI_NUM_ARRAY )
static const u8 mmcfs_spi_nums[ NUM_CARDS ] = MMCFS_SPI_NUM_ARRAY;
#endif

// asserts the CS pin to the card
static
void SELECT (BYTE id)
{
platform_pio_op( mmcfs_cs_ports[ id ] , ( ( u32 ) 1 << mmcfs_cs_pins[ id ] ), PLATFORM_IO_PIN_CLEAR );
#if defined ( __MMC_USE_SPI_SELECT )
platform_spi_select( mmcfs_spi_nums[ id ], 1 );
#else
platform_pio_op( mmcfs_cs_ports[ id ] , ( ( u32 ) 1 << mmcfs_cs_pins[ id ] ), PLATFORM_IO_PIN_CLEAR );
#endif
}

// de-asserts the CS pin to the card
static
void DESELECT (BYTE id)
{
#if defined ( __MMC_USE_SPI_SELECT )
platform_spi_select( mmcfs_spi_nums[ id ], 0 );
#else
platform_pio_op( mmcfs_cs_ports[ id ], ( ( u32 ) 1 << mmcfs_cs_pins[ id ] ), PLATFORM_IO_PIN_SET );
#endif
}


Expand Down Expand Up @@ -602,25 +630,5 @@ DRESULT disk_ioctl (
}



/*---------------------------------------------------------*/
/* User Provided Timer Function for FatFs module */
/*---------------------------------------------------------*/
/* This is a real time clock service to be called from */
/* FatFs module. Any valid time must be returned even if */
/* the system does not support a real time clock. */

DWORD get_fattime (void)
{

return ((2007UL-1980) << 25) // Year = 2007
| (6UL << 21) // Month = June
| (5UL << 16) // Day = 5
| (11U << 11) // Hour = 11
| (38U << 5) // Min = 38
| (0U >> 1) // Sec = 0
;

}
#endif // #if defined( BUILD_MMCFS ) && !defined( ELUA_SIMULATOR )

48 changes: 48 additions & 0 deletions src/fatfs/FATFS_README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# fastfs R0.13c Update for eLua

## General
The update of fatfs to R0.13c should be mostly compatible with the old version. The disk I/O interface in elua_mmc.c is still the same as before. There are some improvements, that have nothing to do with fatfs itself, see below

## Configuration parameters
The mmcfs section in the board configuration has some additional parmeters to allow configuration of fatfs:

Example:
```
mmcfs= { spi=0, codepage=850,
use_utf8_api=false, tiny=false, use_locking=true,
files=8, lfn_length=255
}
```

| Value | Default | Description | ffconf.h parameter | eLua define |
|-------------- |--------- |----------------------------------------------------------------------------------- |----------------------- |------------------- |
| codepage | 437 | Codepage where long file names are converted too (see ffconf.h for allowed values | FF_CODE_PAGE | MMCFS_CODEPAGE |
| use_utf8_api | false | Convert long file names to utf-8 encoding instead of codepag (true/false) | FF_LFN_UNICODE | MMMCFS_API_MODE |
| tiny | true | Use FF_FS_TINY parameter (see fatfs documentation) (true/false) | FF_FS_TINY | MMFCFS_TINY |
| use_locking | true | Enable fatfs file locking (true/false) | FF_FS_LOCK | MMCFS_USE_LOCKING |
| files | 4 | Max. number of open files (4-32) | FF_FS_LOCK | MMCFS_MAX_FDS |
| lfn | 1 | long file name mode - see ffconf.h for documentation (0,1,2) | FF_USE_LFN | MMCFS_USE_LFN |
| lfn_length | 30 | Maximum length of a long file name (30-255) | FF_MAX_LFN/FF_LFN_BUF | MMCFS_MAX_LFN |


## File locking
Enabling file locking is highly recommended, because otherwise fatfs can corrupt data on the file system, when a file is opened for writing more than once.

## Long file name support
Setting lfn to 0 will limit fatfs to 8.3 filenames in upper case like old DOS versions. It only makes sense in very memory constrained enviornments.
lfn=1 uses a static working buffer for the long file name in the bss segment, this is the mode fatfs 0.07 in elua has used
lfn=2 uses a buffer on the stack, so it only consumes memory when files are accessed. What is better may depend on your needs.
lnf=3 requires implementation of heap allocation functions for fatfs, this is the reason why the configurator currently does not allow this mode.

Setting use_utf8_api will change the encoding/decoding of non-ASCII characters in long file names to UTF-8 instead of using a codepage. This is expermental.

## ffunicode.c
The old file ccsbcs.c is replaced by ffunicode.c from fatfs 0.13c. It serves the same purpose.
The file is very big, but if a single code page is selected with the codepage parameter the compiled result will only contain the selected code page.
The usage of DBCS codepages (9XX) is not tested.

## Error code mapping
The function map_error in mmcfs.c maps fatfs error codes to newlib error codes. This will result in better error messages.

## Use of platform_spi_select on for chip select
When no gpio port/pin is set in the mmcfs section of the board configuration the platform_spi_select function is used to control the cs pin.