Add the Labs projects provided in the V10.2.1_191129 zip file.

This commit is contained in:
Richard Barry 2019-12-02 23:39:25 +00:00
parent 46e5937529
commit e5708b38e9
801 changed files with 356576 additions and 0 deletions

View file

@ -0,0 +1,58 @@
Changes between 160112 and 160908 releases
NOTE: The 160908 release is a maintenance release for the 160112 single
interface labs release - not a release of the current development branch.
+ ff-deltree() now correctly handles deleted file entries.
+ Simplified mapping of standard library functions to their Visual Studio
equivalents.
+ ffconfigMIN_CLUSTERS_FAT32 and ffconfigMIN_CLUSTERS_FAT16 introduced to
allow the minimum disk sizes for the two FAT file system types to be
smaller than is permitted by Windows.
Changes between 150825 and 160111 releases
+ New device support: Demo applications and example drivers are provided
for Atmel SAM4E and ST STM32F4 microcontrollers.
+ Various updates to improve compliance with the FreeRTOS coding standard.
+ Modified the stdio tests so they can be executed on SD cards, where the
test files might already exists on power on - previously the tests were
only executed on RAM disks which are always known to be empty on power on.
+ Added ff_deltree() implementation, with note of caution about its use as
it uses recursion ( ff_deltree() recursively removes a directory and
everything contained by it).
+ Update the Zynq project to use version 2015.4 of the Xilinx SDK. This
driver dynamically recognises all types of memory cards.
+ The path cache is cleared when a disk is re-mounted, allowing a disk to be
hot swapped.
Bug fixes resulting from testing performed while converting the acquired
component to be FreeRTOS+ compliant:
+ Fix bug in FF_FindNext() when using 'ffconfigFINDAPI_ALLOW_WILDCARDS'.
+ Fix bug in ff_fat.c when using 'ffconfigFSINFO_TRUSTED' and when the
stored free cluster count equals ~0ul (which means: not filled in) as this
was interpreted as having 4294967295 free clusters.
+ FF_Open() now checks file permissions before truncating a file, previously
the file was truncated first.
+ Fix typo in source of FF_isEOF().
+ FF_ExtendFile() now only attempts to reserve new clusters if it is
actually necessary.
+ FF_Format() now correctly fills in the number of free clusters for FAT32.
+ FF_Partition() has been updated to use ffconfigMAX_PARTITIONS in all
cases, whereas previously some legacy code was assuming a fixed maximum
number of partitions.
+ FF_DeleteIOManager() now deletes the IO manager!
Changes for 150825 (?)
+ Issue fixed in FF_Move().
+ Improved handling of files and directories that start with a '.' character.
+ Changed the locking mechanisms from mutexes to an event group.
+ Add FF_ERR_DRIVER_NOMEDIUM to better handle media being removed and
re-inserted.
+ Fix re-entrancy issue in FF_CheckValid().
+ Remove hashes for deleted files.
+ General structural work.

View file

@ -0,0 +1,66 @@
> is there a repository I should be aware of when it comes to FreeRTOS Labs?
Unfortunately there isn't. FreeRTOS+FAT has become a bit of an orphan. All time and energy goes to the products in the [AWS/FreeRTOS release](https://github.com/aws/amazon-freertos)
But I am still actively maintaining FreeRTOS+FAT: implementing requests and fixes.
Please comment your findings with the above +FAT release.
Here is a complete list of all changes since the 160919 Labs release:
● `ff_dir.c : FF_MkDir()`
refuse to create a directory with an empty name
● `ff_fat.c : FF_GetFreeSize()`
in case of an error, return 0
● `ff_file.c : FF_FileSize()`
This function returns the size of a file, or a negative number in case of an error.
Hence, the maximum size returned was returned is 2 GB.
We've added a new function:
`FF_Error_t FF_GetFileSize( FF_FILE *pxFile, uint32_t *pulSize );`
which separates the length from the error code.
● `ff_file.c : FF_ExtendFile()`
Sometimes while building up a file, it may be more efficient not to flush the changes immediately. When defining `ffconfigFILE_EXTEND_FLUSHES_BUFFERS` as `0`, there is no immediate flushing.
● `ff_file.c : FF_Seek()`
Seeking didn't work for sizes larger than 2 GB. Although the parameter `int32_t lOffset` is signed, it will now be casted to 32-bits unsigned:
`ulPosition = ( uint32_t )lOffset;`
All options (`SET`, `CUR`, and `END` ) re-tested.
● `ff_file.c : FF_Close()`
`FF_FlushCache()` is now called at the end of the function in order to also write the last changes.
● `ff_format.c : FF_Format()`
A variable `lRemaining` should have been declared unsigned: `uint32_t`.
Also: a small optimisation for large SD-cards:
"Putting the FAT-table into the second 4MB erase block gives a higher performance and a longer life-time"
● `ff_format.c : FF_Partition()`
`ulHiddenSectors` must be at least `1`
( see [this post](https://sourceforge.net/p/freertos/discussion/382005/thread/d2b6524a/?limit=250#e1ea) )
● `ff_ioman.c : FF_CreateIOManger()`
`FF_CreateEvents` shall only be called in case an `pxIOManager` was successfully created.
● `ff_ioman.c : FF_DeleteIOManager()`
Added a call to `FF_DeleteEvents()`, which will delete the event group belonging to the I/O manager.
● `ff_ioman.c : FF_FlushCache()`
Added a user application hook per disk: `fnFlushApplicationHook()`. This is useful for e.g. NAND-drivers.
● `ff_ioman.c : FF_Mount()`
Make sure that `pcVolumeLabel` is null-terminated.
● `ff_ioman.c : FF_IncreaseFreeClusters()`
A lock is needed before `ulLastFreeCluster` can be changed. But before taking this lock, check if has already been taken to avoid a dead lock.
● `ff_locking.c : FF_DeleteEvents`
This is a new function which deletes ( frees up ) the event group belonging to an I/O manager.
● `ff_stdio.c : ff_filelength()`
This function will now call `FF_GetFileSize()` in order to get the `unsigned` length of a file, increasing the maximum reported size from 2 to 4 GB.
● `ff_sys.c : *`
This module combines several I/O managers ( = disks ) into a single file system that starts with a root `"/"`.
All code has been re-written ( re-styled ) and re-tested.

View file

@ -0,0 +1,5 @@
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,2
[InternetShortcut]
URL=http://www.freertos.org/fat
IDList=

View file

@ -0,0 +1,256 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
/**
* @file ff_crc.c
* @ingroup CRC
*
* @defgroup CRC CRC Checksums for Strings
* @brief Provides fast hashing functions.
*
**/
#include "ff_headers.h"
/*static*/ const uint32_t crc32_table[ 256 ] =
{
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
uint32_t FF_GetCRC32( uint8_t *pbyData, uint32_t stLength )
{
register uint32_t crc = 0xFFFFFFFF;
while( stLength-- != 0 )
{
crc = ( ( crc >> 8 ) & 0x00FFFFFF ) ^ crc32_table[ ( crc ^ *( pbyData++ ) ) & 0x000000FF ];
}
return crc ^ 0xFFFFFFFF;
}
static const uint8_t crc16_table_low[ 256 ] =
{
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
};
static const uint8_t crc16_table_high[256] =
{
0x000, 0x0c0, 0x0c1, 0x001, 0x0c3, 0x003, 0x002, 0x0c2,
0x0c6, 0x006, 0x007, 0x0c7, 0x005, 0x0c5, 0x0c4, 0x004,
0x0cc, 0x00c, 0x00d, 0x0cd, 0x00f, 0x0cf, 0x0ce, 0x00e,
0x00a, 0x0ca, 0x0cb, 0x00b, 0x0c9, 0x009, 0x008, 0x0c8,
0x0d8, 0x018, 0x019, 0x0d9, 0x01b, 0x0db, 0x0da, 0x01a,
0x01e, 0x0de, 0x0df, 0x01f, 0x0dd, 0x01d, 0x01c, 0x0dc,
0x014, 0x0d4, 0x0d5, 0x015, 0x0d7, 0x017, 0x016, 0x0d6,
0x0d2, 0x012, 0x013, 0x0d3, 0x011, 0x0d1, 0x0d0, 0x010,
0x0f0, 0x030, 0x031, 0x0f1, 0x033, 0x0f3, 0x0f2, 0x032,
0x036, 0x0f6, 0x0f7, 0x037, 0x0f5, 0x035, 0x034, 0x0f4,
0x03c, 0x0fc, 0x0fd, 0x03d, 0x0ff, 0x03f, 0x03e, 0x0fe,
0x0fa, 0x03a, 0x03b, 0x0fb, 0x039, 0x0f9, 0x0f8, 0x038,
0x028, 0x0e8, 0x0e9, 0x029, 0x0eb, 0x02b, 0x02a, 0x0ea,
0x0ee, 0x02e, 0x02f, 0x0ef, 0x02d, 0x0ed, 0x0ec, 0x02c,
0x0e4, 0x024, 0x025, 0x0e5, 0x027, 0x0e7, 0x0e6, 0x026,
0x022, 0x0e2, 0x0e3, 0x023, 0x0e1, 0x021, 0x020, 0x0e0,
0x0a0, 0x060, 0x061, 0x0a1, 0x063, 0x0a3, 0x0a2, 0x062,
0x066, 0x0a6, 0x0a7, 0x067, 0x0a5, 0x065, 0x064, 0x0a4,
0x06c, 0x0ac, 0x0ad, 0x06d, 0x0af, 0x06f, 0x06e, 0x0ae,
0x0aa, 0x06a, 0x06b, 0x0ab, 0x069, 0x0a9, 0x0a8, 0x068,
0x078, 0x0b8, 0x0b9, 0x079, 0x0bb, 0x07b, 0x07a, 0x0ba,
0x0be, 0x07e, 0x07f, 0x0bf, 0x07d, 0x0bd, 0x0bc, 0x07c,
0x0b4, 0x074, 0x075, 0x0b5, 0x077, 0x0b7, 0x0b6, 0x076,
0x072, 0x0b2, 0x0b3, 0x073, 0x0b1, 0x071, 0x070, 0x0b0,
0x050, 0x090, 0x091, 0x051, 0x093, 0x053, 0x052, 0x092,
0x096, 0x056, 0x057, 0x097, 0x055, 0x095, 0x094, 0x054,
0x09c, 0x05c, 0x05d, 0x09d, 0x05f, 0x09f, 0x09e, 0x05e,
0x05a, 0x09a, 0x09b, 0x05b, 0x099, 0x059, 0x058, 0x098,
0x088, 0x048, 0x049, 0x089, 0x04b, 0x08b, 0x08a, 0x04a,
0x04e, 0x08e, 0x08f, 0x04f, 0x08d, 0x04d, 0x04c, 0x08c,
0x044, 0x084, 0x085, 0x045, 0x087, 0x047, 0x046, 0x086,
0x082, 0x042, 0x043, 0x083, 0x041, 0x081, 0x080, 0x040,
};
/*****************************************************************************
* Description: Function to 16 bit CRC check a block of memory
*
* Parameters: pbyData - Pointer to the source data
* stLength - The length to CRC
*
* Return value: The 16 bit CRC value
*
*****************************************************************************/
uint16_t FF_GetCRC16( uint8_t *pbyData, uint32_t stLength )
{
uint8_t bTableValue;
uint16_t wCRC = 0;
while( stLength-- != 0 )
{
bTableValue = ( uint8_t ) ( (wCRC & 0x00FF ) ^ *pbyData++ );
wCRC = ( uint16_t ) ( ( ( crc16_table_high[ bTableValue ] ) << 8 ) +
( crc16_table_low[ bTableValue ] ^ ( ( wCRC >> 8 ) & 0x00FF ) ) );
}
return wCRC;
}
static const uint8_t crc8_table[256] =
{
0, 94, 188, 226, 97, 63, 221, 131,
194, 156, 126, 32, 163, 253, 31, 65,
157, 195, 33, 127, 252, 162, 64, 30,
95, 1, 227, 189, 62, 96, 130, 220,
35, 125, 159, 193, 66, 28, 254, 160,
225, 191, 93, 3, 128, 222, 60, 98,
190, 224, 2, 92, 223, 129, 99, 61,
124, 34, 192, 158, 29, 67, 161, 255,
70, 24, 250, 164, 39, 121, 155, 197,
132, 218, 56, 102, 229, 187, 89, 7,
219, 133, 103, 57, 186, 228, 6, 88,
25, 71, 165, 251, 120, 38, 196, 154,
101, 59, 217, 135, 4, 90, 184, 230,
167, 249, 27, 69, 198, 152, 122, 36,
248, 166, 68, 26, 153, 199, 37, 123,
58, 100, 134, 216, 91, 5, 231, 185,
140, 210, 48, 110, 237, 179, 81, 15,
78, 16, 242, 172, 47, 113, 147, 205,
17, 79, 173, 243, 112, 46, 204, 146,
211, 141, 111, 49, 178, 236, 14, 80,
175, 241, 19, 77, 206, 144, 114, 44,
109, 51, 209, 143, 12, 82, 176, 238,
50, 108, 142, 208, 83, 13, 239, 177,
240, 174, 76, 18, 145, 207, 45, 115,
202, 148, 118, 40, 171, 245, 23, 73,
8, 86, 180, 234, 105, 55, 213, 139,
87, 9, 235, 181, 54, 104, 138, 212,
149, 203, 41, 119, 244, 170, 72, 22,
233, 183, 85, 11, 136, 214, 52, 106,
43, 117, 151, 201, 74, 20, 246, 168,
116, 42, 200, 150, 21, 75, 169, 247,
182, 232, 10, 84, 215, 137, 107, 53
};
/*****************************************************************************
* Description: Function to CRC check a block of memory
*
* Parameters: pbyData - Pointer to the source data
* stLength - The length to CRC
*
* Return value: The 8 bit CRC value
*
*****************************************************************************/
uint8_t FF_GetCRC8( uint8_t *pbyData, uint32_t stLength )
{
uint8_t byCRC = 0, byData;
while( stLength-- != 0 )
{
byData = *pbyData++;
byCRC = crc8_table[ ( byCRC ^ byData ) ];
}
return byCRC;
}

View file

@ -0,0 +1,235 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
#include <stdio.h>
#include <string.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "portable.h"
#include "ff_headers.h"
#include "ff_devices.h"
#ifndef ARRAY_SIZE
# define ARRAY_SIZE( x ) ( int )( sizeof( x ) / sizeof( x )[ 0 ] )
#endif
#if( ffconfigDEV_SUPPORT == 0 )
#error No use to include this module if ffconfigDEV_SUPPORT is disabled
#endif /* ffconfigDEV_SUPPORT == 0 */
struct SFileCache
{
char pcFileName[16];
uint32_t ulFileLength;
uint32_t ulFilePointer;
};
struct SFileCache xFiles[ 16 ];
enum eCACHE_ACTION
{
eCACHE_LOOKUP,
eCACHE_ADD,
eCACHE_REMOVE,
};
const char pcDevicePath[] = ffconfigDEV_PATH;
struct SFileCache *pxFindFile( const char *pcFname, enum eCACHE_ACTION eAction )
{
BaseType_t xIndex, xFreeIndex = -1;
struct SFileCache *pxResult = NULL;
for( xIndex = 0; xIndex < ARRAY_SIZE( xFiles ); xIndex++ )
{
if( xFiles[ xIndex ].pcFileName[ 0 ] == '\0' )
{
if( xFreeIndex < 0 )
{
xFreeIndex = xIndex;
}
}
else if( strcmp( xFiles[ xIndex ].pcFileName, pcFname ) == 0 )
{
if( eAction == eCACHE_REMOVE )
{
xFiles[ xIndex ].pcFileName[ 0 ] = '\0';
}
pxResult = xFiles + xIndex;
break;
}
}
if( ( pxResult == NULL ) && ( eAction == eCACHE_ADD ) && ( xFreeIndex >= 0 ) )
{
pxResult = xFiles + xFreeIndex;
snprintf( pxResult->pcFileName, sizeof( pxResult->pcFileName ), "%s", pcFname );
pxResult->ulFileLength = 0;
pxResult->ulFilePointer = 0;
}
return pxResult;
}
BaseType_t xCheckDevicePath( const char *pcPath )
{
BaseType_t xDevLength;
BaseType_t xPathLength;
BaseType_t xIsDevice;
xDevLength = sizeof( pcDevicePath ) - 1;
xPathLength = strlen( pcPath );
/* System "/dev" should not match with "/device/etc". */
if( ( xPathLength >= xDevLength ) &&
( memcmp( pcDevicePath, pcPath, xDevLength ) == 0 ) &&
( ( pcPath[ xDevLength ] == '\0' ) || ( pcPath[ xDevLength ] == '/' ) ) )
{
xIsDevice = FF_DEV_CHAR_DEV;
}
else
{
xIsDevice = FF_DEV_NO_DEV;
}
return xIsDevice;
}
BaseType_t FF_Device_Open( const char *pcPath, FF_FILE *pxStream )
{
uint8_t ucIsDevice;
ucIsDevice = xCheckDevicePath( pcPath );
if( ucIsDevice != pdFALSE )
{
const char *pcBaseName = pcPath;
if( memcmp( pcBaseName, pcDevicePath, sizeof( pcDevicePath ) - 1 ) == 0 )
{
pcBaseName = pcBaseName + sizeof( pcDevicePath );
}
pxStream->pxDevNode = pxFindFile( pcBaseName, eCACHE_ADD );
if( pxStream->pxDevNode != NULL )
{
pxStream->pxDevNode->ulFilePointer = 0;
if( ( pxStream->ucMode & ( FF_MODE_WRITE | FF_MODE_APPEND | FF_MODE_CREATE ) ) == 0 )
{
pxStream->ulFileSize = pxStream->pxDevNode->ulFileLength;
}
}
}
return ucIsDevice;
}
void FF_Device_Close( FF_FILE * pxStream )
{
if( pxStream->pxDevNode != NULL )
{
pxStream->ulFileSize = 0ul;
pxStream->ulFilePointer = 0ul;
}
}
size_t FF_Device_Read( void *pvBuf, size_t lSize, size_t lCount, FF_FILE * pxStream )
{
lCount *= lSize;
return lCount;
}
size_t FF_Device_Write( const void *pvBuf, size_t lSize, size_t lCount, FF_FILE * pxStream )
{
lCount *= lSize;
if( pxStream->pxDevNode != NULL )
{
pxStream->pxDevNode->ulFilePointer += lCount;
if( pxStream->pxDevNode->ulFileLength < pxStream->pxDevNode->ulFilePointer )
{
pxStream->pxDevNode->ulFileLength = pxStream->pxDevNode->ulFilePointer;
}
}
return lCount;
}
int FF_Device_Seek( FF_FILE *pxStream, long lOffset, int iWhence )
{
if( pxStream->pxDevNode != NULL )
{
if( iWhence == FF_SEEK_SET )
{
pxStream->pxDevNode->ulFilePointer = lOffset;
}
else if( iWhence == FF_SEEK_END )
{
pxStream->pxDevNode->ulFilePointer = pxStream->pxDevNode->ulFileLength - lOffset;
}
}
return 0;
}
int FF_Device_GetDirEnt( const char *pcPath, FF_DirEnt_t *pxDirEnt )
{
BaseType_t xIsDotDir = 0;
if( pxDirEnt->pcFileName[ 0 ] == '.' )
{
if( ( pxDirEnt->pcFileName[ 1 ] == '.' ) &&
( pxDirEnt->pcFileName[ 2 ] == '\0' ) )
{
xIsDotDir = 2;
}
else if( pxDirEnt->pcFileName[ 1 ] == '\0' )
{
xIsDotDir = 1;
}
}
if( xIsDotDir == 0 )
{
struct SFileCache *pxDevNode;
pxDevNode = pxFindFile( pxDirEnt->pcFileName, eCACHE_LOOKUP );
pxDirEnt->ucIsDeviceDir = FF_DEV_CHAR_DEV;
if( pxDevNode != NULL )
{
pxDirEnt->ulFileSize = pxDevNode->ulFileLength;
}
else if( pxDirEnt->ulFileSize < 2048 )
{
pxDirEnt->ulFileSize = 2048;
}
}
return 1024;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,311 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
/**
* @file ff_error.c
* @ingroup ERROR
*
* @defgroup ERR Error Message
* @brief Used to return human readable strings for FreeRTOS+FAT error codes.
*
**/
#include <stdio.h>
/* _HT_ with the new GNU settings, the prototype of [v]snprintf()
is not included in stdio.h Don't know why. */
int snprintf( char *, size_t, const char *, ... );
#include "ff_headers.h"
#if !defined( ARRAY_SIZE )
#define ARRAY_SIZE( x ) ( int )( sizeof( x )/sizeof( x )[ 0 ] )
#endif
/* This if-block spans the rest of the source file.*/
#if( ffconfigDEBUG != 0 )
const struct _FFMODULETAB
{
const char * const strModuleName;
const uint8_t ucModuleID;
} xFreeRTOSFATModuleTable[] =
{
{ "Unknown Module", 1}, /* 1 here is ok, as the GetError functions start at the end of the table. */
{ "ff_ioman.c", FF_GETMODULE( FF_MODULE_IOMAN ) },
{ "ff_dir.c", FF_GETMODULE( FF_MODULE_DIR ) },
{ "ff_file.c", FF_GETMODULE( FF_MODULE_FILE ) },
{ "ff_fat.c", FF_GETMODULE( FF_MODULE_FAT ) },
{ "ff_crc.c", FF_GETMODULE( FF_MODULE_CRC ) },
{ "ff_format.c", FF_GETMODULE( FF_MODULE_FORMAT ) },
{ "ff_memory.c", FF_GETMODULE( FF_MODULE_MEMORY ) },
{ "ff_string.c", FF_GETMODULE( FF_MODULE_STRING ) },
{ "ff_locking.c", FF_GETMODULE( FF_MODULE_LOCKING ) },
{ "ff_time.c", FF_GETMODULE( FF_MODULE_TIME ) },
{ "Platform Driver", FF_GETMODULE( FF_MODULE_DRIVER ) },
};
#if( ffconfigHAS_FUNCTION_TAB != 0 )
const struct _FFFUNCTIONTAB
{
const char * const strFunctionName;
const uint16_t ucFunctionID;
} xFreeRTOSFATFunctionTable[] =
{
{ "Unknown Function", 1},
/*----- FF_IOManager_t - The FreeRTOS+FAT I/O Manager */
{ "FF_CreateIOManger", FF_GETMOD_FUNC( FF_CREATEIOMAN ) },
{ "FF_DeleteIOManager", FF_GETMOD_FUNC( FF_DESTROYIOMAN ) },
{ "FF_Mount", FF_GETMOD_FUNC( FF_MOUNT ) },
{ "FF_Unmount", FF_GETMOD_FUNC( FF_UNMOUNT ) },
{ "FF_FlushCache", FF_GETMOD_FUNC( FF_FLUSHCACHE ) },
{ "FF_GetPartitionBlockSize", FF_GETMOD_FUNC( FF_GETPARTITIONBLOCKSIZE ) },
{ "FF_BlockRead", FF_GETMOD_FUNC( FF_BLOCKREAD ) },
{ "FF_BlockWrite", FF_GETMOD_FUNC( FF_BLOCKWRITE ) },
{ "FF_DetermineFatType", FF_GETMOD_FUNC( FF_DETERMINEFATTYPE ) },
{ "FF_GetEfiPartitionEntry", FF_GETMOD_FUNC( FF_GETEFIPARTITIONENTRY ) },
{ "FF_UserDriver", FF_GETMOD_FUNC( FF_USERDRIVER ) },
{ "FF_DecreaseFreeClusters", FF_GETMOD_FUNC( FF_DECREASEFREECLUSTERS ) },
{ "FF_IncreaseFreeClusters", FF_GETMOD_FUNC( FF_INCREASEFREECLUSTERS ) },
{ "FF_PartitionSearch", FF_GETMOD_FUNC( FF_PARTITIONSEARCH ) },
{ "FF_ParseExtended", FF_GETMOD_FUNC( FF_PARSEEXTENDED ) },
/*----- FF_DIR - The FreeRTOS+FAT directory handling routines */
{ "FF_FetchEntryWithContext", FF_GETMOD_FUNC( FF_FETCHENTRYWITHCONTEXT ) },
{ "FF_PushEntryWithContext", FF_GETMOD_FUNC( FF_PUSHENTRYWITHCONTEXT ) },
{ "FF_GetEntry", FF_GETMOD_FUNC( FF_GETENTRY ) },
{ "FF_FindFirst", FF_GETMOD_FUNC( FF_FINDFIRST ) },
{ "FF_FindNext", FF_GETMOD_FUNC( FF_FINDNEXT ) },
{ "FF_RewindFind", FF_GETMOD_FUNC( FF_REWINDFIND ) },
{ "FF_FindFreeDirent", FF_GETMOD_FUNC( FF_FINDFREEDIRENT ) },
{ "FF_PutEntry", FF_GETMOD_FUNC( FF_PUTENTRY ) },
{ "FF_CreateShortName", FF_GETMOD_FUNC( FF_CREATESHORTNAME ) },
{ "FF_CreateLFNs", FF_GETMOD_FUNC( FF_CREATELFNS ) },
{ "FF_ExtendDirectory", FF_GETMOD_FUNC( FF_EXTENDDIRECTORY ) },
{ "FF_MkDir", FF_GETMOD_FUNC( FF_MKDIR ) },
{ "FF_Traverse", FF_GETMOD_FUNC( FF_TRAVERSE ) },
{ "FF_FindDir", FF_GETMOD_FUNC( FF_FINDDIR ) },
/*----- FF_FILE - The FreeRTOS+FAT file handling routines */
{ "FF_GetModeBits", FF_GETMOD_FUNC( FF_GETMODEBITS ) },
{ "FF_Open", FF_GETMOD_FUNC( FF_OPEN ) },
{ "FF_isDirEmpty", FF_GETMOD_FUNC( FF_ISDIREMPTY ) },
{ "FF_RmDir", FF_GETMOD_FUNC( FF_RMDIR ) },
{ "FF_RmFile", FF_GETMOD_FUNC( FF_RMFILE ) },
{ "FF_Move", FF_GETMOD_FUNC( FF_MOVE ) },
{ "FF_isEOF", FF_GETMOD_FUNC( FF_ISEOF ) },
{ "FF_GetSequentialClusters", FF_GETMOD_FUNC( FF_GETSEQUENTIALCLUSTERS ) },
{ "FF_ReadClusters", FF_GETMOD_FUNC( FF_READCLUSTERS ) },
{ "FF_ExtendFile", FF_GETMOD_FUNC( FF_EXTENDFILE ) },
{ "FF_WriteClusters", FF_GETMOD_FUNC( FF_WRITECLUSTERS ) },
{ "FF_Read", FF_GETMOD_FUNC( FF_READ ) },
{ "FF_GetC", FF_GETMOD_FUNC( FF_GETC ) },
{ "FF_GetLine", FF_GETMOD_FUNC( FF_GETLINE ) },
{ "FF_Tell", FF_GETMOD_FUNC( FF_TELL ) },
{ "FF_Write", FF_GETMOD_FUNC( FF_WRITE ) },
{ "FF_PutC", FF_GETMOD_FUNC( FF_PUTC ) },
{ "FF_Seek", FF_GETMOD_FUNC( FF_SEEK ) },
{ "FF_Invalidate", FF_GETMOD_FUNC( FF_INVALIDATE ) },
{ "FF_CheckValid", FF_GETMOD_FUNC( FF_CHECKVALID ) },
{ "FF_Close", FF_GETMOD_FUNC( FF_CLOSE ) },
{ "FF_SetTime", FF_GETMOD_FUNC( FF_SETTIME ) },
{ "FF_BytesLeft", FF_GETMOD_FUNC( FF_BYTESLEFT ) },
{ "FF_SetFileTime", FF_GETMOD_FUNC( FF_SETFILETIME ) },
{ "FF_InitBuf", FF_GETMOD_FUNC( FF_INITBUF ) },
/*----- FF_FAT - The FreeRTOS+FAT FAT handling routines */
{ "FF_getFATEntry", FF_GETMOD_FUNC( FF_GETFATENTRY ) },
{ "FF_ClearCluster", FF_GETMOD_FUNC( FF_CLEARCLUSTER ) },
{ "FF_putFATEntry", FF_GETMOD_FUNC( FF_PUTFATENTRY ) },
{ "FF_FindFreeCluster", FF_GETMOD_FUNC( FF_FINDFREECLUSTER ) },
{ "FF_CountFreeClusters", FF_GETMOD_FUNC( FF_COUNTFREECLUSTERS ) },
/*----- FF_UNICODE - The FreeRTOS+FAT hashing routines */
{ "FF_Utf8ctoUtf16c", FF_GETMOD_FUNC( FF_UTF8CTOUTF16C ) },
{ "FF_Utf16ctoUtf8c", FF_GETMOD_FUNC( FF_UTF16CTOUTF8C ) },
{ "FF_Utf32ctoUtf16c", FF_GETMOD_FUNC( FF_UTF32CTOUTF16C ) },
{ "FF_Utf16ctoUtf32c", FF_GETMOD_FUNC( FF_UTF16CTOUTF32C ) },
/*----- FF_FORMAT - The FreeRTOS+FAT format routine */
{ "FF_FormatPartition", FF_GETMOD_FUNC( FF_FORMATPARTITION ) },
/*----- FF_STDIO - The FreeRTOS+FAT stdio front-end */
{ "ff_chmod", FF_GETMOD_FUNC( FF_CHMOD ) },
{ "ff_stat", FF_GETMOD_FUNC( FF_STAT_FUNC ) },
};
#endif /* ffconfigHAS_FUNCTION_TAB */
#define TPASTE2( a, b ) a##b
#if( ffconfigLONG_ERR_MSG != 0 )
/* To get the full error msg: "Not enough memory (malloc( ) returned NULL )" */
#define ERR_ENTRY( M, E ) { M, TPASTE2( FF_ERR_, E ) }
#else
/* To get a shorter msg: "NOT_ENOUGH_MEMORY" */
#define ERR_ENTRY( M, E ) { #E, TPASTE2( FF_ERR_, E ) }
#endif /* ffconfigLONG_ERR_MSG */
const struct _FFERRTAB
{
const char * const strErrorString;
const uint8_t ucErrorCode; /* Currently there are less then 256 errors, so lets keep this table small. */
} xFreeRTOSFATErrorTable[] =
{
{"Unknown or Generic Error!", 1},
ERR_ENTRY( "No Error", NONE ),
ERR_ENTRY( "Null Pointer provided, (probably for IOMAN)", NULL_POINTER ),
ERR_ENTRY( "Not enough memory (malloc() returned NULL)", NOT_ENOUGH_MEMORY ),
ERR_ENTRY( "Device Driver returned a FATAL error!", DEVICE_DRIVER_FAILED ),
ERR_ENTRY( "The blocksize is not 512 multiple", IOMAN_BAD_BLKSIZE ),
ERR_ENTRY( "The memory size, is not a multiple of the blocksize. (Atleast 2 Blocks)", IOMAN_BAD_MEMSIZE ),
ERR_ENTRY( "Device is already registered, use FF_UnregisterBlkDevice() first", IOMAN_DEV_ALREADY_REGD ),
ERR_ENTRY( "No mountable partition was found on the specified device", IOMAN_NO_MOUNTABLE_PARTITION ),
ERR_ENTRY( "The format of the MBR was unrecognised", IOMAN_INVALID_FORMAT ),
ERR_ENTRY( "The provided partition number is out-of-range (0 - 3)", IOMAN_INVALID_PARTITION_NUM ),
ERR_ENTRY( "The selected partition / volume doesn't appear to be FAT formatted", IOMAN_NOT_FAT_FORMATTED ),
ERR_ENTRY( "Cannot register device. (BlkSize not a multiple of 512)", IOMAN_DEV_INVALID_BLKSIZE ),
ERR_ENTRY( "Cannot unregister device, a partition is still mounted", IOMAN_PARTITION_MOUNTED ),
ERR_ENTRY( "Cannot unmount the partition while there are active FILE handles", IOMAN_ACTIVE_HANDLES ),
ERR_ENTRY( "The GPT partition header appears to be corrupt, refusing to mount", IOMAN_GPT_HEADER_CORRUPT ),
ERR_ENTRY( "Disk full", IOMAN_NOT_ENOUGH_FREE_SPACE ),
ERR_ENTRY( "Attempted to Read a sector out of bounds", IOMAN_OUT_OF_BOUNDS_READ ),
ERR_ENTRY( "Attempted to Write a sector out of bounds", IOMAN_OUT_OF_BOUNDS_WRITE ),
ERR_ENTRY( "I/O driver is busy", IOMAN_DRIVER_BUSY ),
ERR_ENTRY( "I/O driver returned fatal error", IOMAN_DRIVER_FATAL_ERROR ),
ERR_ENTRY( "I/O driver returned \"no medium error\"", IOMAN_DRIVER_NOMEDIUM ),
ERR_ENTRY( "Cannot open the file, file already in use", FILE_ALREADY_OPEN ),
ERR_ENTRY( "The specified file could not be found", FILE_NOT_FOUND ),
ERR_ENTRY( "Cannot open a Directory", FILE_OBJECT_IS_A_DIR ),
ERR_ENTRY( "Cannot open for writing: File is marked as Read-Only", FILE_IS_READ_ONLY ),
ERR_ENTRY( "Path not found", FILE_INVALID_PATH ),
ERR_ENTRY( "File operation failed - the file was not opened for writing", FILE_NOT_OPENED_IN_WRITE_MODE ),
ERR_ENTRY( "File operation failed - the file was not opened for reading", FILE_NOT_OPENED_IN_READ_MODE ),
ERR_ENTRY( "File operation failed - could not extend file", FILE_EXTEND_FAILED ),
ERR_ENTRY( "Destination file already exists", FILE_DESTINATION_EXISTS ),
ERR_ENTRY( "Source file was not found", FILE_SOURCE_NOT_FOUND ),
ERR_ENTRY( "Destination path (dir) was not found", FILE_DIR_NOT_FOUND ),
ERR_ENTRY( "Failed to create the directory Entry", FILE_COULD_NOT_CREATE_DIRENT ),
ERR_ENTRY( "A file handle was invalid", FILE_BAD_HANDLE ),
#if( ffconfigREMOVABLE_MEDIA != 0 )
ERR_ENTRY( "File handle got invalid because media was removed", FILE_MEDIA_REMOVED ),
#endif /* ffconfigREMOVABLE_MEDIA */
ERR_ENTRY( "A file or folder of the same name already exists", DIR_OBJECT_EXISTS ),
ERR_ENTRY( "DIR_DIRECTORY_FULL", DIR_DIRECTORY_FULL ),
ERR_ENTRY( "DIR_END_OF_DIR", DIR_END_OF_DIR ),
ERR_ENTRY( "The directory is not empty", DIR_NOT_EMPTY ),
ERR_ENTRY( "Could not extend File or Folder - No Free Space!", FAT_NO_FREE_CLUSTERS ),
ERR_ENTRY( "Could not find the directory specified by the path", DIR_INVALID_PATH ),
ERR_ENTRY( "The Root Dir is full, and cannot be extended on Fat12 or 16 volumes", DIR_CANT_EXTEND_ROOT_DIR ),
ERR_ENTRY( "Not enough space to extend the directory.", DIR_EXTEND_FAILED ),
ERR_ENTRY( "Name exceeds the number of allowed characters for a filename", DIR_NAME_TOO_LONG ),
#if( ffconfigUNICODE_UTF16_SUPPORT != 0 )
ERR_ENTRY( "An invalid Unicode character was provided!", UNICODE_INVALID_CODE ),
ERR_ENTRY( "Not enough space in the UTF-16 buffer to encode the entire sequence", UNICODE_DEST_TOO_SMALL ),
ERR_ENTRY( "An invalid UTF-16 sequence was encountered", UNICODE_INVALID_SEQUENCE ),
ERR_ENTRY( "Filename exceeds MAX long-filename length when converted to UTF-16", UNICODE_CONVERSION_EXCEEDED ),
#endif /* ffconfigUNICODE_UTF16_SUPPORT */
};
/**
* @public
* @brief Returns a pointer to a string relating to a FreeRTOS+FAT error code.
*
* @param iErrorCode The error code.
*
* @return Pointer to a string describing the error.
*
**/
const char *FF_GetErrMessage( FF_Error_t iErrorCode )
{
uint32_t stCount = ARRAY_SIZE( xFreeRTOSFATErrorTable );
while( stCount-- )
{
if( ( ( UBaseType_t )xFreeRTOSFATErrorTable[ stCount ].ucErrorCode ) == FF_GETERROR( iErrorCode ) )
{
break;
}
}
return xFreeRTOSFATErrorTable[ stCount ].strErrorString;
}
const char *FF_GetErrModule( FF_Error_t iErrorCode )
{
uint32_t stCount = ARRAY_SIZE( xFreeRTOSFATModuleTable );
while( stCount-- )
{
if( xFreeRTOSFATModuleTable[ stCount ].ucModuleID == ( uint8_t )FF_GETMODULE( iErrorCode ) )
{
break;
}
}
return xFreeRTOSFATModuleTable[ stCount ].strModuleName;
}
#if( ffconfigHAS_FUNCTION_TAB != 0 )
const char *FF_GetErrFunction( FF_Error_t iErrorCode )
{
uint32_t stCount = ARRAY_SIZE( xFreeRTOSFATFunctionTable );
uint16_t ModuleFunc = FF_GETMOD_FUNC( iErrorCode );
static char funcCode[32];
while( stCount-- != 0 )
{
if( xFreeRTOSFATFunctionTable[ stCount ].ucFunctionID == ModuleFunc )
{
return xFreeRTOSFATFunctionTable[ stCount ].strFunctionName;
}
}
snprintf( funcCode, sizeof( funcCode ), "Func %X", ModuleFunc );
return ( const char * )funcCode;
}
#endif /* ffconfigHAS_FUNCTION_TAB */
const char *FF_GetErrDescription( FF_Error_t iErrorCode, char *apBuf, int aMaxlen )
{
if( FF_isERR( iErrorCode ) )
{
#if( ffconfigHAS_FUNCTION_TAB != 0 )
snprintf (apBuf, ( size_t ) aMaxlen, "%s::%s::%s",
FF_GetErrModule( iErrorCode ),
FF_GetErrFunction( iErrorCode ),
FF_GetErrMessage( iErrorCode ));
#else
snprintf (apBuf, ( size_t ) aMaxlen, "%s::%s",
FF_GetErrModule( iErrorCode ),
FF_GetErrMessage( iErrorCode ));
#endif /* ffconfigHAS_FUNCTION_TAB */
}
else
{
snprintf (apBuf, ( size_t ) aMaxlen, "No error");
}
return apBuf;
}
#endif /* ffconfigDEBUG != 0 */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,753 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
/**
* @file ff_format.c
* @ingroup FORMAT
*
* @defgroup FAT Fat File-System
* @brief Format a drive, given the number of sectors.
*
**/
#include "ff_headers.h"
#include <time.h>
#include <string.h>
#if defined( __BORLANDC__ )
#include "ff_windows.h"
#else
#include "FreeRTOS.h"
#include "task.h" /* For FreeRTOS date/time function */
#endif
/*=========================================================================================== */
#define OFS_PART_ACTIVE_8 0x000 /* 0x01BE 0x80 if active */
#define OFS_PART_START_HEAD_8 0x001 /* 0x01BF */
#define OFS_PART_START_SEC_TRACK_16 0x002 /* 0x01C0 */
#define OFS_PART_ID_NUMBER_8 0x004 /* 0x01C2 */
#define OFS_PART_ENDING_HEAD_8 0x005 /* 0x01C3 */
#define OFS_PART_ENDING_SEC_TRACK_16 0x006 /* 0x01C4 = SectorCount - 1 - ulHiddenSectors */
#define OFS_PART_STARTING_LBA_32 0x008 /* 0x01C6 = ulHiddenSectors (This is important) */
#define OFS_PART_LENGTH_32 0x00C /* 0x01CA = SectorCount - 1 - ulHiddenSectors */
#define OFS_PTABLE_MACH_CODE 0x000 /* 0x0000 */
#define OFS_PTABLE_PART_0 0x1BE /* 446 */
#define OFS_PTABLE_PART_1 0x1CE /* 462 */
#define OFS_PTABLE_PART_2 0x1DE /* 478 */
#define OFS_PTABLE_PART_3 0x1FE /* 494 */
#define OFS_PTABLE_PART_LEN 16
/*=========================================================================================== */
#define OFS_BPB_jmpBoot_24 0x000 /* uchar jmpBoot[3] "0xEB 0x00 0x90" */
#define OFS_BPB_OEMName_64 0x003 /* uchar BS_OEMName[8] "MSWIN4.1" */
#define OFS_BPB_BytsPerSec_16 0x00B /* Only 512, 1024, 2048 or 4096 */
#define OFS_BPB_SecPerClus_8 0x00D /* Only 1, 2, 4, 8, 16, 32, 64, 128 */
#define OFS_BPB_ResvdSecCnt_16 0x00E /* ulFATReservedSectors, e.g. 1 (FAT12/16) or 32 (FAT32) */
#define OFS_BPB_NumFATs_8 0x010 /* 2 recommended */
#define OFS_BPB_RootEntCnt_16 0x011 /* ((iFAT16RootSectors * 512) / 32) 512 (FAT12/16) or 0 (FAT32) */
#define OFS_BPB_TotSec16_16 0x013 /* xxx (FAT12/16) or 0 (FAT32) */
#define OFS_BPB_Media_8 0x015 /* 0xF0 (rem media) also in FAT[0] low byte */
#define OFS_BPB_FATSz16_16 0x016
#define OFS_BPB_SecPerTrk_16 0x018 /* n.a. CF has no tracks */
#define OFS_BPB_NumHeads_16 0x01A /* n.a. 1 ? */
#define OFS_BPB_HiddSec_32 0x01C /* n.a. 0 for nonparitioned volume */
#define OFS_BPB_TotSec32_32 0x020 /* >= 0x10000 */
#define OFS_BPB_16_DrvNum_8 0x024 /* n.a. */
#define OFS_BPB_16_Reserved1_8 0x025 /* n.a. */
#define OFS_BPB_16_BootSig_8 0x026 /* n.a. */
#define OFS_BPB_16_BS_VolID_32 0x027 /* "unique" number */
#define OFS_BPB_16_BS_VolLab_88 0x02B /* "NO NAME " */
#define OFS_BPB_16_FilSysType_64 0x036 /* "FAT12 " */
#define OFS_BPB_32_FATSz32_32 0x024 /* Only when BPB_FATSz16 = 0 */
#define OFS_BPB_32_ExtFlags_16 0x028 /* FAT32 only */
#define OFS_BPB_32_FSVer_16 0x02A /* 0:0 */
#define OFS_BPB_32_RootClus_32 0x02C /* See 'iFAT32RootClusters' Normally 2 */
#define OFS_BPB_32_FSInfo_16 0x030 /* Normally 1 */
#define OFS_BPB_32_BkBootSec_16 0x032 /* Normally 6 */
#define OFS_BPB_32_Reserved_96 0x034 /* Zeros */
#define OFS_BPB_32_DrvNum_8 0x040 /* n.a. */
#define OFS_BPB_32_Reserved1_8 0x041 /* n.a. */
#define OFS_BPB_32_BootSig_8 0x042 /* n.a. */
#define OFS_BPB_32_VolID_32 0x043 /* "unique" number */
#define OFS_BPB_32_VolLab_88 0x047 /* "NO NAME " */
#define OFS_BPB_32_FilSysType_64 0x052 /* "FAT12 " */
#define OFS_FSI_32_LeadSig 0x000 /* With contents 0x41615252 */
#define OFS_FSI_32_Reserved1 0x004 /* 480 times 0 */
#define OFS_FSI_32_StrucSig 0x1E4 /* With contents 0x61417272 */
#define OFS_FSI_32_Free_Count 0x1E8 /* last known free cluster count on the volume, ~0 for unknown */
#define OFS_FSI_32_Nxt_Free 0x1EC /* cluster number at which the driver should start looking for free clusters */
#define OFS_FSI_32_Reserved2 0x1F0 /* zero's */
#define OFS_FSI_32_TrailSig 0x1FC /* 0xAA550000 (little endian) */
#define RESV_COUNT 32
#ifdef ffconfigMIN_CLUSTERS_FAT32
#define MIN_CLUSTER_COUNT_FAT32 ffconfigMIN_CLUSTERS_FAT32
#else
#define MIN_CLUSTER_COUNT_FAT32 ( 65525 )
#endif
#ifdef ffconfigMIN_CLUSTERS_FAT16
#define MIN_CLUSTERS_FAT16 ffconfigMIN_CLUSTERS_FAT16
#else
#define MIN_CLUSTERS_FAT16 ( 4085 + 1 )
#endif
#ifndef ffconfigFAT16_ROOT_SECTORS
#define ffconfigFAT16_ROOT_SECTORS 32
#endif
static portINLINE uint32_t ulMin32( uint32_t a, uint32_t b )
{
uint32_t ulReturn;
if( a <= b )
{
ulReturn = a;
}
else
{
ulReturn = b;
}
return ulReturn;
}
/*_RB_ Candidate for splitting into multiple functions? */
FF_Error_t FF_Format( FF_Disk_t *pxDisk, BaseType_t xPartitionNumber, BaseType_t xPreferFAT16, BaseType_t xSmallClusters )
{
uint32_t ulHiddenSectors; /* Space from MBR and partition table */
const uint32_t ulFSInfo = 1; /* Sector number of FSINFO structure within the reserved area */
const uint32_t ulBackupBootSector = 6; /* Sector number of "copy of the boot record" within the reserved area */
const BaseType_t xFATCount = 2; /* Number of FAT's */
uint32_t ulFATReservedSectors = 0; /* Space between the partition table and FAT table. */
int32_t iFAT16RootSectors = 0; /* Number of sectors reserved for root directory (FAT16 only) */
int32_t iFAT32RootClusters = 0; /* Initial amount of clusters claimed for root directory (FAT32 only) */
uint8_t ucFATType = 0; /* Either 'FF_T_FAT16' or 'FF_T_FAT32' */
uint32_t ulVolumeID = 0; /* A pseudo Volume ID */
uint32_t ulSectorsPerFAT = 0; /* Number of sectors used by a single FAT table */
uint32_t ulClustersPerFATSector = 0; /* # of clusters which can be described within a sector (256 or 128) */
uint32_t ulSectorsPerCluster = 0; /* Size of a cluster (# of sectors) */
uint32_t ulUsableDataSectors = 0; /* Usable data sectors (= SectorCount - (ulHiddenSectors + ulFATReservedSectors)) */
uint32_t ulUsableDataClusters = 0; /* equals "ulUsableDataSectors / ulSectorsPerCluster" */
uint32_t ulNonDataSectors = 0; /* ulFATReservedSectors + ulHiddenSectors + iFAT16RootSectors */
uint32_t ulClusterBeginLBA = 0; /* Sector address of the first data cluster */
uint32_t ulSectorCount;
uint8_t *pucSectorBuffer = 0;
FF_SPartFound_t xPartitionsFound;
FF_Part_t *pxMyPartition = 0;
FF_IOManager_t *pxIOManager = pxDisk->pxIOManager;
FF_PartitionSearch( pxIOManager, &xPartitionsFound );
if( xPartitionNumber >= xPartitionsFound.iCount )
{
return FF_ERR_IOMAN_INVALID_PARTITION_NUM | FF_MODULE_FORMAT;
}
pxMyPartition = xPartitionsFound.pxPartitions + xPartitionNumber;
ulSectorCount = pxMyPartition->ulSectorCount;
ulHiddenSectors = pxMyPartition->ulStartLBA;
if( ( ( xPreferFAT16 == pdFALSE ) && ( ( ulSectorCount - RESV_COUNT ) >= 65536 ) ) ||
( ( ulSectorCount - RESV_COUNT ) >= ( 64 * MIN_CLUSTER_COUNT_FAT32 ) ) )
{
ucFATType = FF_T_FAT32;
iFAT32RootClusters = 2;
ulFATReservedSectors = RESV_COUNT;
iFAT16RootSectors = 0;
}
else
{
ucFATType = FF_T_FAT16;
iFAT32RootClusters = 0;
ulFATReservedSectors = 1u;
iFAT16RootSectors = ffconfigFAT16_ROOT_SECTORS; /* 32 sectors to get 512 dir entries */
}
/* Set start sector and length to allow FF_BlockRead/Write */
pxIOManager->xPartition.ulTotalSectors = pxMyPartition->ulSectorCount;
pxIOManager->xPartition.ulBeginLBA = pxMyPartition->ulStartLBA;
/* TODO: Find some solution here to get a unique disk ID */
ulVolumeID = ( rand() << 16 ) | rand(); /*_RB_ rand() has proven problematic in some environments. */
/* Sectors within partition which can not be used */
ulNonDataSectors = ulFATReservedSectors + iFAT16RootSectors;
/* A fs dependent constant: */
if( ucFATType == FF_T_FAT32 )
{
/* In FAT32, 4 bytes are needed to store the address (LBA) of a cluster.
Each FAT sector of 512 bytes can contain 512 / 4 = 128 entries. */
ulClustersPerFATSector = 128u;
}
else
{
/* In FAT16, 2 bytes are needed to store the address (LBA) of a cluster.
Each FAT sector of 512 bytes can contain 512 / 2 = 256 entries. */
ulClustersPerFATSector = 256u;
}
FF_PRINTF( "FF_Format: Secs %lu Rsvd %lu Hidden %lu Root %lu Data %lu\n",
ulSectorCount, ulFATReservedSectors, ulHiddenSectors, iFAT16RootSectors, ulSectorCount - ulNonDataSectors );
/* Either search from small to large or v.v. */
if( xSmallClusters != 0 )
{
/* The caller prefers to have small clusters.
Less waste but it can be slower. */
ulSectorsPerCluster = 1u;
}
else
{
if( ucFATType == FF_T_FAT32 )
{
ulSectorsPerCluster = 64u;
}
else
{
ulSectorsPerCluster = 32u;
}
}
for( ;; )
{
int32_t groupSize;
/* Usable sectors */
ulUsableDataSectors = ulSectorCount - ulNonDataSectors;
/* Each group consists of 'xFATCount' sectors + 'ulClustersPerFATSector' clusters */
groupSize = xFATCount + ulClustersPerFATSector * ulSectorsPerCluster;
/* This amount of groups will fit: */
ulSectorsPerFAT = ( ulUsableDataSectors + groupSize - ulSectorsPerCluster - xFATCount ) / groupSize;
ulUsableDataClusters = ulMin32(
( uint32_t ) ( ulUsableDataSectors - xFATCount * ulSectorsPerFAT ) / ulSectorsPerCluster,
( uint32_t ) ( ulClustersPerFATSector * ulSectorsPerFAT ) );
ulUsableDataSectors = ulUsableDataClusters * ulSectorsPerCluster;
if( ( ucFATType == FF_T_FAT16 ) && ( ulUsableDataClusters >= MIN_CLUSTERS_FAT16 ) && ( ulUsableDataClusters < 65536 ) )
{
break;
}
if( ( ucFATType == FF_T_FAT32 ) && ( ulUsableDataClusters >= 65536 ) && ( ulUsableDataClusters < 0x0FFFFFEF ) )
{
break;
}
/* Was this the last test? */
if( ( ( xSmallClusters != pdFALSE ) && ( ulSectorsPerCluster == 32 ) ) ||
( ( xSmallClusters == pdFALSE ) && ( ulSectorsPerCluster == 1) ) )
{
FF_PRINTF( "FF_Format: Can not make a FAT%d (tried %d) with %lu sectors\n",
ucFATType == FF_T_FAT32 ? 32 : 16, xPreferFAT16 ? 16 : 32, ulSectorCount );
return FF_ERR_IOMAN_BAD_MEMSIZE | FF_MODULE_FORMAT;
}
/* No it wasn't, try next clustersize */
if( xSmallClusters != pdFALSE )
{
ulSectorsPerCluster <<= 1;
}
else
{
ulSectorsPerCluster >>= 1;
}
}
if( ( ucFATType == FF_T_FAT32 ) && ( ulSectorCount >= 0x100000UL ) ) /* Larger than 0.5 GB */
{
uint32_t ulRemaining;
/*
* Putting the FAT-table into the second 4MB erase block gives
* a higher performance and a longer life-time.
* See e.g. here:
* http://3gfp.com/wp/2014/07/formatting-sd-cards-for-speed-and-lifetime/
*/
ulFATReservedSectors = 8192 - ulHiddenSectors;
ulNonDataSectors = ulFATReservedSectors + iFAT16RootSectors;
ulRemaining = (ulNonDataSectors + 2 * ulSectorsPerFAT) % 128;
if( ulRemaining != 0 )
{
/* In order to get ClusterBeginLBA well aligned (on a 128 sector boundary) */
ulFATReservedSectors += ( 128 - ulRemaining );
ulNonDataSectors = ulFATReservedSectors + iFAT16RootSectors;
}
ulUsableDataSectors = ulSectorCount - ulNonDataSectors - 2 * ulSectorsPerFAT;
ulUsableDataClusters = ulUsableDataSectors / ulSectorsPerCluster;
}
ulClusterBeginLBA = ulHiddenSectors + ulFATReservedSectors + 2 * ulSectorsPerFAT;
pucSectorBuffer = ( uint8_t * ) ffconfigMALLOC( 512 );
if( pucSectorBuffer == NULL )
{
return FF_ERR_NOT_ENOUGH_MEMORY | FF_MODULE_FORMAT;
}
/* ======================================================================================= */
memset( pucSectorBuffer, '\0', 512 );
memcpy( pucSectorBuffer + OFS_BPB_jmpBoot_24, "\xEB\x00\x90" "FreeRTOS", 11 ); /* Includes OFS_BPB_OEMName_64 */
FF_putShort( pucSectorBuffer, OFS_BPB_BytsPerSec_16, 512 ); /* 0x00B / Only 512, 1024, 2048 or 4096 */
FF_putShort( pucSectorBuffer, OFS_BPB_ResvdSecCnt_16, ( uint32_t ) ulFATReservedSectors ); /* 0x00E / 1 (FAT12/16) or 32 (FAT32) */
FF_putChar( pucSectorBuffer, OFS_BPB_NumFATs_8, 2); /* 0x010 / 2 recommended */
FF_putShort( pucSectorBuffer, OFS_BPB_RootEntCnt_16, ( uint32_t ) ( iFAT16RootSectors * 512 ) / 32 ); /* 0x011 / 512 (FAT12/16) or 0 (FAT32) */
/* For FAT12 and FAT16 volumes, this field contains the count of 32- */
/* byte directory entries in the root directory */
FF_putChar( pucSectorBuffer, OFS_BPB_Media_8, 0xF8 ); /* 0x015 / 0xF0 (rem media) also in FAT[0] low byte */
FF_putShort( pucSectorBuffer, OFS_BPB_SecPerTrk_16, 0x3F ); /* 0x18 n.a. CF has no tracks */
FF_putShort( pucSectorBuffer, OFS_BPB_NumHeads_16, 255 ); /* 0x01A / n.a. 1 ? */
FF_putLong (pucSectorBuffer, OFS_BPB_HiddSec_32, ( uint32_t ) ulHiddenSectors ); /* 0x01C / n.a. 0 for nonparitioned volume */
{
int32_t fatBeginLBA;
int32_t dirBegin;
FF_putChar( pucSectorBuffer, OFS_BPB_SecPerClus_8, ( uint32_t ) ulSectorsPerCluster ); /* 0x00D / Only 1, 2, 4, 8, 16, 32, 64, 128 */
FF_PRINTF("FF_Format: SecCluster %lu DatSec %lu DataClus %lu ulClusterBeginLBA %lu\n",
ulSectorsPerCluster, ulUsableDataSectors, ulUsableDataClusters, ulClusterBeginLBA );
/* This field is the new 32-bit total count of sectors on the volume. */
/* This count includes the count of all sectors in all four regions of the volume */
FF_putShort( pucSectorBuffer, OFS_BPB_TotSec16_16, 0 ); /* 0x013 / xxx (FAT12/16) or 0 (FAT32) */
FF_putLong (pucSectorBuffer, OFS_BPB_TotSec32_32, ulSectorCount ); /* 0x020 / >= 0x10000 */
if( ucFATType == FF_T_FAT32 )
{
FF_putLong( pucSectorBuffer, OFS_BPB_32_FATSz32_32, ulSectorsPerFAT ); /* 0x24 / Only when BPB_FATSz16 = 0 */
FF_putShort( pucSectorBuffer, OFS_BPB_32_ExtFlags_16, 0 ); /* 0x28 / FAT32 only */
FF_putShort( pucSectorBuffer, OFS_BPB_32_FSVer_16, 0 ); /* 0x2A / 0:0 */
FF_putLong( pucSectorBuffer, OFS_BPB_32_RootClus_32, ( uint32_t ) iFAT32RootClusters ); /* 0x2C / Normally 2 */
FF_putShort( pucSectorBuffer, OFS_BPB_32_FSInfo_16, ulFSInfo ); /* 0x30 / Normally 1 */
FF_putShort( pucSectorBuffer, OFS_BPB_32_BkBootSec_16, ulBackupBootSector ); /* 0x32 / Normally 6 */
FF_putChar( pucSectorBuffer, OFS_BPB_32_DrvNum_8, 0 ); /* 0x40 / n.a. */
FF_putChar( pucSectorBuffer, OFS_BPB_32_BootSig_8, 0x29 ); /* 0x42 / n.a. */
FF_putLong( pucSectorBuffer, OFS_BPB_32_VolID_32, ( uint32_t ) ulVolumeID ); /* 0x43 / "unique" number */
memcpy( pucSectorBuffer + OFS_BPB_32_VolLab_88, "MY NAME ", 11 ); /* 0x47 / "NO NAME " */
memcpy( pucSectorBuffer + OFS_BPB_32_FilSysType_64, "FAT32 ", 8 ); /* 0x52 / "FAT12 " */
}
else
{
FF_putChar( pucSectorBuffer, OFS_BPB_16_DrvNum_8, 0u ); /* 0x024 / n.a. */
FF_putChar( pucSectorBuffer, OFS_BPB_16_Reserved1_8, 0 ); /* 0x025 / n.a. */
FF_putChar( pucSectorBuffer, OFS_BPB_16_BootSig_8, 0x29 ); /* 0x026 / n.a. */
FF_putLong (pucSectorBuffer, OFS_BPB_16_BS_VolID_32, ( uint32_t ) ulVolumeID ); /* 0x027 / "unique" number */
FF_putShort( pucSectorBuffer, OFS_BPB_FATSz16_16, ulSectorsPerFAT ); /* 0x16 */
memcpy( pucSectorBuffer + OFS_BPB_16_BS_VolLab_88, "MY NAME ", 11 ); /* 0x02B / "NO NAME " */
memcpy( pucSectorBuffer + OFS_BPB_16_FilSysType_64, "FAT16 ", 8 ); /* 0x036 / "FAT12 " */
}
pucSectorBuffer[510] = 0x55;
pucSectorBuffer[511] = 0xAA;
FF_BlockWrite( pxIOManager, ulHiddenSectors, 1, pucSectorBuffer, 0u );
if (ucFATType == FF_T_FAT32)
{
FF_BlockWrite( pxIOManager, ulHiddenSectors + ulBackupBootSector, 1, pucSectorBuffer, pdFALSE );
}
if( ucFATType == FF_T_FAT32 )
{
memset( pucSectorBuffer, '\0', 512 );
FF_putLong( pucSectorBuffer, OFS_FSI_32_LeadSig, 0x41615252 ); /* to validate that this is in fact an FSInfo sector. */
/* OFS_FSI_32_Reserved1 0x004 / 480 times 0 */
FF_putLong( pucSectorBuffer, OFS_FSI_32_StrucSig, 0x61417272 ); /* Another signature that is more localized in the */
/* sector to the location of the fields that are used. */
FF_putLong( pucSectorBuffer, OFS_FSI_32_Free_Count, ulUsableDataClusters ); /* last known free cluster count on the volume, ~0 for unknown */
FF_putLong( pucSectorBuffer, OFS_FSI_32_Nxt_Free, 2 ); /* cluster number at which the driver should start looking for free clusters */
/* OFS_FSI_32_Reserved2 0x1F0 / zero's */
FF_putLong( pucSectorBuffer, OFS_FSI_32_TrailSig, 0xAA550000 ); /* Will correct for endianness */
FF_BlockWrite( pxIOManager, ulHiddenSectors + ulFSInfo, 1, pucSectorBuffer, pdFALSE );
FF_BlockWrite( pxIOManager, ulHiddenSectors + ulFSInfo + ulBackupBootSector, 1, pucSectorBuffer, pdFALSE );
}
fatBeginLBA = ulHiddenSectors + ulFATReservedSectors;
memset( pucSectorBuffer, '\0', 512 );
switch( ucFATType )
{
case FF_T_FAT16:
FF_putShort( pucSectorBuffer, 0, 0xFFF8 ); /* First FAT entry. */
FF_putShort( pucSectorBuffer, 2, 0xFFFF ); /* RESERVED alloc. */
break;
case FF_T_FAT32:
FF_putLong( pucSectorBuffer, 0, 0x0FFFFFF8 ); /* FAT32 FAT sig. */
FF_putLong( pucSectorBuffer, 4, 0xFFFFFFFF ); /* RESERVED alloc. */
FF_putLong( pucSectorBuffer, 8, 0x0FFFFFFF ); /* Root dir allocation. */
break;
default:
break;
}
FF_BlockWrite( pxIOManager, ( uint32_t ) fatBeginLBA, 1, pucSectorBuffer, pdFALSE );
FF_BlockWrite( pxIOManager, ( uint32_t ) fatBeginLBA + ulSectorsPerFAT, 1, pucSectorBuffer, pdFALSE );
FF_PRINTF( "FF_Format: Clearing entire FAT (2 x %lu sectors):\n", ulSectorsPerFAT );
{
int32_t addr;
memset( pucSectorBuffer, '\0', 512 );
for( addr = fatBeginLBA+1;
addr < ( fatBeginLBA + ( int32_t ) ulSectorsPerFAT );
addr++ )
{
FF_BlockWrite( pxIOManager, ( uint32_t ) addr, 1, pucSectorBuffer, pdFALSE );
FF_BlockWrite( pxIOManager, ( uint32_t ) addr + ulSectorsPerFAT, 1, pucSectorBuffer, pdFALSE );
}
}
FF_PRINTF( "FF_Format: Clearing done\n" );
dirBegin = fatBeginLBA + ( 2 * ulSectorsPerFAT );
#if( ffconfigTIME_SUPPORT != 0 )
{
FF_SystemTime_t str_t;
int16_t myShort;
FF_GetSystemTime( &str_t );
myShort = ( ( str_t.Hour << 11 ) & 0xF800 ) |
( ( str_t.Minute << 5 ) & 0x07E0 ) |
( ( str_t.Second / 2 ) & 0x001F );
FF_putShort( pucSectorBuffer, 22, ( uint32_t ) myShort );
myShort = ( ( ( str_t.Year- 1980 ) << 9 ) & 0xFE00 ) |
( ( str_t.Month << 5 ) & 0x01E0 ) |
( str_t.Day & 0x001F );
FF_putShort( pucSectorBuffer, 24, ( uint32_t ) myShort);
}
#endif /* ffconfigTIME_SUPPORT */
memcpy (pucSectorBuffer, "MY_DISK ", 11);
pucSectorBuffer[11] = FF_FAT_ATTR_VOLID;
{
int32_t lAddress;
int32_t lLastAddress;
if( iFAT16RootSectors != 0 )
{
lLastAddress = dirBegin + iFAT16RootSectors;
}
else
{
lLastAddress = dirBegin + ulSectorsPerCluster;
}
FF_PRINTF("FF_Format: Clearing root directory at %08lX: %lu sectors\n", dirBegin, lLastAddress - dirBegin );
for( lAddress = dirBegin; lAddress < lLastAddress; lAddress++ )
{
FF_BlockWrite( pxIOManager, ( uint32_t ) lAddress, 1, pucSectorBuffer, 0u );
if( lAddress == dirBegin )
{
memset( pucSectorBuffer, '\0', 512 );
}
}
}
}
ffconfigFREE( pucSectorBuffer );
return FF_ERR_NONE;
}
FF_Error_t FF_Partition( FF_Disk_t *pxDisk, FF_PartitionParameters_t *pParams )
{
const uint32_t ulInterSpace = pParams->ulInterSpace ? pParams->ulInterSpace : 2048; /* Hidden space between 2 extended partitions */
BaseType_t xPartitionNumber;
FF_Part_t pxPartitions[ ffconfigMAX_PARTITIONS ];
uint32_t ulPartitionOffset; /* Pointer within partition table */
FF_Buffer_t *pxSectorBuffer;
uint8_t *pucBuffer;
uint32_t ulSummedSizes = 0; /* Summed sizes as a percentage or as number of sectors. */
BaseType_t xPartitionCount = 0;
BaseType_t xNeedExtended;
uint32_t ulReservedSpace;
uint32_t ulAvailable;
FF_IOManager_t *pxIOManager = pxDisk->pxIOManager;
/* Clear caching without flushing first. */
FF_IOMAN_InitBufferDescriptors( pxIOManager );
/* Avoid sanity checks by FF_BlockRead/Write. */
pxIOManager->xPartition.ulTotalSectors = 0;
/* Get the sum of sizes and number of actual partitions. */
for( xPartitionNumber = 0; xPartitionNumber < ffconfigMAX_PARTITIONS; xPartitionNumber++ )
{
if( pParams->xSizes[ xPartitionNumber ] > 0 )
{
xPartitionCount++;
ulSummedSizes += pParams->xSizes[ xPartitionNumber ];
}
}
if( xPartitionCount == 0 )
{
xPartitionCount = 1;
if( pParams->eSizeType == eSizeIsSectors)
{
pParams->xSizes[ 0 ] = pParams->ulSectorCount;
}
else
{
pParams->xSizes[ 0 ] = 100;
}
ulSummedSizes = pParams->xSizes[ 0 ];
}
/* Correct PrimaryCount if necessary. */
if( pParams->xPrimaryCount > ( ( xPartitionCount > 4 ) ? 3 : xPartitionCount ) )
{
pParams->xPrimaryCount = ( xPartitionCount > 4 ) ? 3 : xPartitionCount;
}
/* Now see if extended is necessary. */
xNeedExtended = ( xPartitionCount > pParams->xPrimaryCount );
if( xNeedExtended != pdFALSE )
{
if( pParams->ulHiddenSectors < 4096 )
{
pParams->ulHiddenSectors = 4096;
}
ulReservedSpace = ulInterSpace * ( xPartitionCount - pParams->xPrimaryCount );
}
else
{
/* There must be at least 1 hidden sector. */
if( pParams->ulHiddenSectors < 1 )
{
pParams->ulHiddenSectors = 1;
}
ulReservedSpace = 0;
}
ulAvailable = pParams->ulSectorCount - pParams->ulHiddenSectors - ulReservedSpace;
/* Check validity of Sizes */
switch( pParams->eSizeType )
{
case eSizeIsQuota: /* Assign a quotum (sum of Sizes is free, all disk space will be allocated) */
break;
case eSizeIsPercent: /* Assign a percentage of the available space (sum of Sizes must be <= 100) */
if( ulSummedSizes > 100 )
{
return FF_FORMATPARTITION | FF_ERR_IOMAN_BAD_MEMSIZE;
}
ulSummedSizes = 100;
break;
case eSizeIsSectors: /* Assign fixed number of sectors (512 byte each) */
if( ulSummedSizes > ulAvailable )
{
return FF_FORMATPARTITION | FF_ERR_IOMAN_BAD_MEMSIZE;
}
break;
}
{
uint32_t ulRemaining = ulAvailable;
uint32_t ulLBA = pParams->ulHiddenSectors;
/* Divide the available sectors among the partitions: */
memset( pxPartitions, '\0', sizeof( pxPartitions ) );
for( xPartitionNumber = 0; xPartitionNumber < xPartitionCount; xPartitionNumber++ )
{
if( pParams->xSizes[ xPartitionNumber ] > 0 )
{
uint32_t ulSize;
switch( pParams->eSizeType )
{
case eSizeIsQuota: /* Assign a quotum (sum of Sizes is free, all disk space will be allocated) */
case eSizeIsPercent: /* Assign a percentage of the available space (sum of Sizes must be <= 100) */
ulSize = ( uint32_t ) ( ( ( uint64_t ) pParams->xSizes[ xPartitionNumber ] * ulAvailable) / ulSummedSizes );
break;
case eSizeIsSectors: /* Assign fixed number of sectors (512 byte each) */
default: /* Just for the compiler(s) */
ulSize = pParams->xSizes[ xPartitionNumber ];
break;
}
if( ulSize > ulRemaining )
{
ulSize = ulRemaining;
}
ulRemaining -= ulSize;
pxPartitions[ xPartitionNumber ].ulSectorCount = ulSize;
pxPartitions[ xPartitionNumber ].ucActive = 0x80;
pxPartitions[ xPartitionNumber ].ulStartLBA = ulLBA; /* ulStartLBA might still change for logical partitions */
pxPartitions[ xPartitionNumber ].ucPartitionID = 0x0B;
ulLBA += ulSize;
}
}
}
if( xNeedExtended != pdFALSE )
{
/* Create at least 1 extended/logical partition */
int index;
/* Start of the big extended partition */
unsigned extendedLBA = pParams->ulHiddenSectors;
/* Where to write the table */
uint32_t ulLBA = 0;
/* Contents of the table */
FF_Part_t writeParts[4];
for( index = -1; index < xPartitionCount; index++ )
{
uint32_t ulNextLBA;
memset (writeParts, '\0', sizeof( writeParts ) );
if( index < 0 )
{
/* we're at secor 0: */
/* write primary partitions, if any */
/* create big extended partition */
uint32_t ulStartLBA = pParams->ulHiddenSectors;
for( xPartitionNumber = 0; xPartitionNumber < pParams->xPrimaryCount; xPartitionNumber++ )
{
writeParts[ xPartitionNumber ].ulStartLBA = ulStartLBA;
writeParts[ xPartitionNumber ].ulSectorCount = pxPartitions[ xPartitionNumber ].ulSectorCount;
writeParts[ xPartitionNumber ].ucActive = 0x80;
writeParts[ xPartitionNumber ].ucPartitionID = 0x0B;
ulStartLBA += writeParts[ xPartitionNumber ].ulSectorCount;
index++;
}
extendedLBA = ulStartLBA;
writeParts[ xPartitionNumber ].ulStartLBA = ulStartLBA;
writeParts[ xPartitionNumber ].ulSectorCount = pParams->ulSectorCount - ulStartLBA;
writeParts[ xPartitionNumber ].ucActive = 0x80;
writeParts[ xPartitionNumber ].ucPartitionID = 0x05;
ulNextLBA = ulStartLBA;
}
else
{
/* Create a logical partition with "ulSectorCount" sectors: */
writeParts[ 0 ].ulStartLBA = ulInterSpace;
writeParts[ 0 ].ulSectorCount = pxPartitions[index].ulSectorCount;
writeParts[ 0 ].ucActive = 0x80;
writeParts[ 0 ].ucPartitionID = 0x0B;
if( index < xPartitionCount - 1 )
{
/* Next extended partition */
writeParts[ 1 ].ulStartLBA = ulInterSpace + ulLBA - extendedLBA + writeParts[ 0 ].ulSectorCount;
writeParts[ 1 ].ulSectorCount = pxPartitions[index+1].ulSectorCount + ulInterSpace;
writeParts[ 1 ].ucActive = 0x80;
writeParts[ 1 ].ucPartitionID = 0x05;
}
ulNextLBA = writeParts[ 1 ].ulStartLBA + extendedLBA;
}
pxSectorBuffer = FF_GetBuffer(pxIOManager, ( uint32_t ) ulLBA, ( uint8_t ) FF_MODE_WRITE );
{
if( pxSectorBuffer == NULL )
{
return FF_ERR_DEVICE_DRIVER_FAILED;
}
}
pucBuffer = pxSectorBuffer->pucBuffer;
memset ( pucBuffer, 0, 512 );
memcpy ( pucBuffer + OFS_BPB_jmpBoot_24, "\xEB\x00\x90" "FreeRTOS", 11 ); /* Includes OFS_BPB_OEMName_64 */
ulPartitionOffset = OFS_PTABLE_PART_0;
for( xPartitionNumber = 0; xPartitionNumber < ffconfigMAX_PARTITIONS; xPartitionNumber++, ulPartitionOffset += 16 )
{
FF_putChar( pucBuffer, ulPartitionOffset + OFS_PART_ACTIVE_8, writeParts[ xPartitionNumber ].ucActive ); /* 0x01BE 0x80 if active */
FF_putChar( pucBuffer, ulPartitionOffset + OFS_PART_START_HEAD_8, 1 ); /* 0x001 / 0x01BF */
FF_putShort(pucBuffer, ulPartitionOffset + OFS_PART_START_SEC_TRACK_16, 1 ); /* 0x002 / 0x01C0 */
FF_putChar( pucBuffer, ulPartitionOffset + OFS_PART_ID_NUMBER_8, writeParts[ xPartitionNumber ].ucPartitionID );/* 0x004 / 0x01C2 */
FF_putChar( pucBuffer, ulPartitionOffset + OFS_PART_ENDING_HEAD_8, 0xFE ); /* 0x005 / 0x01C3 */
FF_putShort(pucBuffer, ulPartitionOffset + OFS_PART_ENDING_SEC_TRACK_16, writeParts[ xPartitionNumber ].ulSectorCount );/* 0x006 / 0x01C4 */
FF_putLong (pucBuffer, ulPartitionOffset + OFS_PART_STARTING_LBA_32, writeParts[ xPartitionNumber ].ulStartLBA ); /* 0x008 / 0x01C6 This is important */
FF_putLong (pucBuffer, ulPartitionOffset + OFS_PART_LENGTH_32, writeParts[ xPartitionNumber ].ulSectorCount );/* 0x00C / 0x01CA Equal to total sectors */
}
pucBuffer[510] = 0x55;
pucBuffer[511] = 0xAA;
FF_ReleaseBuffer(pxIOManager, pxSectorBuffer );
FF_FlushCache( pxIOManager );
ulLBA = ulNextLBA;
}
}
else
{
pxSectorBuffer = FF_GetBuffer( pxIOManager, 0, ( uint8_t ) FF_MODE_WRITE );
{
if( pxSectorBuffer == NULL )
{
return FF_ERR_DEVICE_DRIVER_FAILED;
}
}
pucBuffer = pxSectorBuffer->pucBuffer;
memset (pucBuffer, 0, 512 );
memcpy (pucBuffer + OFS_BPB_jmpBoot_24, "\xEB\x00\x90" "FreeRTOS", 11 ); /* Includes OFS_BPB_OEMName_64 */
ulPartitionOffset = OFS_PTABLE_PART_0;
for( xPartitionNumber = 0; xPartitionNumber < ffconfigMAX_PARTITIONS; xPartitionNumber++ )
{
FF_putChar( pucBuffer, ulPartitionOffset + OFS_PART_ACTIVE_8, pxPartitions[ xPartitionNumber ].ucActive ); /* 0x01BE 0x80 if active */
FF_putChar( pucBuffer, ulPartitionOffset + OFS_PART_START_HEAD_8, 1 ); /* 0x001 / 0x01BF */
FF_putShort( pucBuffer, ulPartitionOffset + OFS_PART_START_SEC_TRACK_16, 1 ); /* 0x002 / 0x01C0 */
FF_putChar( pucBuffer, ulPartitionOffset + OFS_PART_ID_NUMBER_8, pxPartitions[ xPartitionNumber ].ucPartitionID ); /* 0x004 / 0x01C2 */
FF_putChar( pucBuffer, ulPartitionOffset + OFS_PART_ENDING_HEAD_8, 0xFE ); /* 0x005 / 0x01C3 */
FF_putShort( pucBuffer, ulPartitionOffset + OFS_PART_ENDING_SEC_TRACK_16, pxPartitions[ xPartitionNumber ].ulSectorCount ); /* 0x006 / 0x01C4 */
FF_putLong( pucBuffer, ulPartitionOffset + OFS_PART_STARTING_LBA_32, pxPartitions[ xPartitionNumber ].ulStartLBA ); /* 0x008 / 0x01C6 This is important */
FF_putLong( pucBuffer, ulPartitionOffset + OFS_PART_LENGTH_32, pxPartitions[ xPartitionNumber ].ulSectorCount ); /* 0x00C / 0x01CA Equal to total sectors */
ulPartitionOffset += 16;
}
pucBuffer[ 510 ] = 0x55;
pucBuffer[ 511 ] = 0xAA;
FF_ReleaseBuffer( pxIOManager, pxSectorBuffer );
FF_FlushCache( pxIOManager );
}
return FF_ERR_NONE;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,325 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Scheduler include files. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "ff_headers.h"
#include "event_groups.h"
#ifndef configUSE_RECURSIVE_MUTEXES
#error configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h
#else
#if( configUSE_RECURSIVE_MUTEXES != 1 )
#error configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h
#endif
#endif /* configUSE_RECURSIVE_MUTEXES */
#if ( INCLUDE_vTaskDelay != 1 )
#error Missing some FreeRTOS define
#endif
/* There are two areas which are protected with a semaphore:
Directories and the FAT area.
The masks below are used when calling Group Event functions. */
#define FF_FAT_LOCK_EVENT_BITS ( ( const EventBits_t ) FF_FAT_LOCK )
#define FF_DIR_LOCK_EVENT_BITS ( ( const EventBits_t ) FF_DIR_LOCK )
/* This is not a real lock: it is a bit (or semaphore) will will be given
each time when a sector buffer is released. */
#define FF_BUF_LOCK_EVENT_BITS ( ( const EventBits_t ) FF_BUF_LOCK )
/*-----------------------------------------------------------*/
BaseType_t FF_TrySemaphore( void *pxSemaphore, uint32_t ulTime_ms )
{
BaseType_t xReturn;
/* HT: Actually FF_TrySemaphore is never used. */
if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )
{
return 0;
}
configASSERT( pxSemaphore );
xReturn = xSemaphoreTakeRecursive( ( SemaphoreHandle_t ) pxSemaphore, pdMS_TO_TICKS( ulTime_ms ) );
return xReturn;
}
/*-----------------------------------------------------------*/
void FF_PendSemaphore( void *pxSemaphore )
{
if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )
{
/* No need to take the semaphore. */
return;
}
configASSERT( pxSemaphore );
xSemaphoreTakeRecursive( ( SemaphoreHandle_t ) pxSemaphore, portMAX_DELAY );
}
/*-----------------------------------------------------------*/
void FF_ReleaseSemaphore( void *pxSemaphore )
{
if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )
{
/* Scheduler not yet active. */
return;
}
configASSERT( pxSemaphore );
xSemaphoreGiveRecursive( ( SemaphoreHandle_t ) pxSemaphore );
}
/*-----------------------------------------------------------*/
void FF_Sleep( uint32_t ulTime_ms )
{
if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )
{
/* This sleep is used as a kind of yield.
Not necessary while the Scheduler does not run. */
return;
}
vTaskDelay( pdMS_TO_TICKS( ulTime_ms ) );
}
/*-----------------------------------------------------------*/
void FF_DeleteEvents( FF_IOManager_t *pxIOManager )
{
if( pxIOManager->xEventGroup != NULL )
{
vEventGroupDelete( pxIOManager->xEventGroup );
}
}
/*-----------------------------------------------------------*/
BaseType_t FF_CreateEvents( FF_IOManager_t *pxIOManager )
{
BaseType_t xResult;
pxIOManager->xEventGroup = xEventGroupCreate();
if( pxIOManager->xEventGroup != NULL )
{
xEventGroupSetBits( pxIOManager->xEventGroup,
FF_FAT_LOCK_EVENT_BITS | FF_DIR_LOCK_EVENT_BITS | FF_BUF_LOCK_EVENT_BITS );
xResult = pdTRUE;
}
else
{
xResult = pdFALSE;
}
return xResult;
}
/*-----------------------------------------------------------*/
void FF_LockDirectory( FF_IOManager_t *pxIOManager )
{
EventBits_t xBits;
if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )
{
/* Scheduler not yet active. */
return;
}
for( ;; )
{
/* Called when a task want to make changes to a directory.
First it waits for the desired bit to come high. */
xEventGroupWaitBits( pxIOManager->xEventGroup,
FF_DIR_LOCK_EVENT_BITS, /* uxBitsToWaitFor */
( EventBits_t )0, /* xClearOnExit */
pdFALSE, /* xWaitForAllBits n.a. */
pdMS_TO_TICKS( 10000UL ) );
/* The next operation will only succeed for 1 task at a time,
because it is an atomary test & set operation: */
xBits = xEventGroupClearBits( pxIOManager->xEventGroup, FF_DIR_LOCK_EVENT_BITS );
if( ( xBits & FF_DIR_LOCK_EVENT_BITS ) != 0 )
{
/* This task has cleared the desired bit.
It now 'owns' the resource. */
break;
}
}
}
/*-----------------------------------------------------------*/
void FF_UnlockDirectory( FF_IOManager_t *pxIOManager )
{
if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )
{
/* Scheduler not yet active. */
return;
}
configASSERT( ( xEventGroupGetBits( pxIOManager->xEventGroup ) & FF_DIR_LOCK_EVENT_BITS ) == 0 );
xEventGroupSetBits( pxIOManager->xEventGroup, FF_DIR_LOCK_EVENT_BITS );
}
/*-----------------------------------------------------------*/
int FF_Has_Lock( FF_IOManager_t *pxIOManager, uint32_t aBits )
{
int iReturn;
if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )
{
/* Scheduler not yet active. */
return 0;
}
void *handle = xTaskGetCurrentTaskHandle();
if( ( aBits & FF_FAT_LOCK_EVENT_BITS ) != 0 )
{
if( ( pxIOManager->pvFATLockHandle != NULL ) && ( pxIOManager->pvFATLockHandle == handle ) )
{
iReturn = pdTRUE;
}
else
{
iReturn = pdFALSE;
}
}
else
{
iReturn = pdFALSE;
}
return iReturn;
}
void FF_Assert_Lock( FF_IOManager_t *pxIOManager, uint32_t aBits )
{
void *handle;
if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )
{
/* Scheduler not yet active. */
return;
}
handle = xTaskGetCurrentTaskHandle();
if( ( aBits & FF_FAT_LOCK_EVENT_BITS ) != 0 )
{
configASSERT( ( pxIOManager->pvFATLockHandle != NULL ) && ( pxIOManager->pvFATLockHandle == handle ) );
/* In case configASSERT() is not defined. */
( void ) pxIOManager;
( void ) handle;
}
}
void FF_LockFAT( FF_IOManager_t *pxIOManager )
{
EventBits_t xBits;
if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )
{
/* Scheduler not yet active. */
return;
}
configASSERT( FF_Has_Lock( pxIOManager, FF_FAT_LOCK ) == pdFALSE );
for( ;; )
{
/* Called when a task want to make changes to the FAT area.
First it waits for the desired bit to come high. */
xEventGroupWaitBits( pxIOManager->xEventGroup,
FF_FAT_LOCK_EVENT_BITS, /* uxBitsToWaitFor */
( EventBits_t )0, /* xClearOnExit */
pdFALSE, /* xWaitForAllBits n.a. */
pdMS_TO_TICKS( 10000UL ) );
/* The next operation will only succeed for 1 task at a time,
because it is an atomary test & set operation: */
xBits = xEventGroupClearBits( pxIOManager->xEventGroup, FF_FAT_LOCK_EVENT_BITS );
if( ( xBits & FF_FAT_LOCK_EVENT_BITS ) != 0 )
{
/* This task has cleared the desired bit.
It now 'owns' the resource. */
pxIOManager->pvFATLockHandle = xTaskGetCurrentTaskHandle();
break;
}
}
}
/*-----------------------------------------------------------*/
void FF_UnlockFAT( FF_IOManager_t *pxIOManager )
{
if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )
{
/* Scheduler not yet active. */
return;
}
configASSERT( ( xEventGroupGetBits( pxIOManager->xEventGroup ) & FF_FAT_LOCK_EVENT_BITS ) == 0 );
pxIOManager->pvFATLockHandle = NULL;
xEventGroupSetBits( pxIOManager->xEventGroup, FF_FAT_LOCK_EVENT_BITS );
}
/*-----------------------------------------------------------*/
BaseType_t FF_BufferWait( FF_IOManager_t *pxIOManager, uint32_t xWaitMS )
{
EventBits_t xBits;
BaseType_t xReturn;
if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )
{
/* Scheduler not yet active. */
return pdTRUE;
}
/* This function is called when a task is waiting for a sector buffer
to become available. */
xBits = xEventGroupWaitBits( pxIOManager->xEventGroup,
FF_BUF_LOCK_EVENT_BITS, /* uxBitsToWaitFor */
FF_BUF_LOCK_EVENT_BITS, /* xClearOnExit */
pdFALSE, /* xWaitForAllBits n.a. */
pdMS_TO_TICKS( xWaitMS ) );
if( ( xBits & FF_BUF_LOCK_EVENT_BITS ) != 0 )
{
xReturn = pdTRUE;
}
else
{
xReturn = pdFALSE;
}
return xReturn;
}
/*-----------------------------------------------------------*/
void FF_BufferProceed( FF_IOManager_t *pxIOManager )
{
if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )
{
/* Scheduler not yet active. */
return;
}
/* Wake-up all tasks that are waiting for a sector buffer to become available. */
xEventGroupSetBits( pxIOManager->xEventGroup, FF_BUF_LOCK_EVENT_BITS );
}
/*-----------------------------------------------------------*/

View file

@ -0,0 +1,262 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Scheduler include files. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "ff_headers.h"
#include "event_groups.h"
#ifndef configUSE_RECURSIVE_MUTEXES
#error configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h
#else
#if( configUSE_RECURSIVE_MUTEXES != 1 )
#error configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h
#endif
#endif /* configUSE_RECURSIVE_MUTEXES */
#if ( INCLUDE_vTaskDelay != 1 )
#error Missing some FreeRTOS define
#endif
/* There are two areas which are protected with a semaphore:
Directories and the FAT area.
The masks below are used when calling Group Event functions. */
#define FF_FAT_LOCK_EVENT_BITS ( ( const EventBits_t ) FF_FAT_LOCK )
#define FF_DIR_LOCK_EVENT_BITS ( ( const EventBits_t ) FF_DIR_LOCK )
/* This is not a real lock: it is a bit (or semaphore) will will be given
each time when a sector buffer is released. */
#define FF_BUF_LOCK_EVENT_BITS ( ( const EventBits_t ) FF_BUF_LOCK )
/*-----------------------------------------------------------*/
BaseType_t FF_TrySemaphore( void *pxSemaphore, uint32_t ulTime_ms )
{
BaseType_t xReturn;
configASSERT( pxSemaphore );
xReturn = xSemaphoreTakeRecursive( ( SemaphoreHandle_t ) pxSemaphore, pdMS_TO_TICKS( ulTime_ms ) );
return xReturn;
}
/*-----------------------------------------------------------*/
void FF_PendSemaphore( void *pxSemaphore )
{
configASSERT( pxSemaphore );
xSemaphoreTakeRecursive( ( SemaphoreHandle_t ) pxSemaphore, portMAX_DELAY );
}
/*-----------------------------------------------------------*/
void FF_ReleaseSemaphore( void *pxSemaphore )
{
configASSERT( pxSemaphore );
xSemaphoreGiveRecursive( ( SemaphoreHandle_t ) pxSemaphore );
}
/*-----------------------------------------------------------*/
void FF_Sleep( uint32_t ulTime_ms )
{
vTaskDelay( pdMS_TO_TICKS( ulTime_ms ) );
}
/*-----------------------------------------------------------*/
void FF_DeleteEvents( FF_IOManager_t *pxIOManager )
{
if( pxIOManager->xEventGroup != NULL )
{
vEventGroupDelete( pxIOManager->xEventGroup );
}
}
/*-----------------------------------------------------------*/
BaseType_t FF_CreateEvents( FF_IOManager_t *pxIOManager )
{
BaseType_t xResult;
pxIOManager->xEventGroup = xEventGroupCreate();
if( pxIOManager->xEventGroup != NULL )
{
xEventGroupSetBits( pxIOManager->xEventGroup,
FF_FAT_LOCK_EVENT_BITS | FF_DIR_LOCK_EVENT_BITS | FF_BUF_LOCK_EVENT_BITS );
xResult = pdTRUE;
}
else
{
xResult = pdFALSE;
}
return xResult;
}
/*-----------------------------------------------------------*/
void FF_LockDirectory( FF_IOManager_t *pxIOManager )
{
EventBits_t xBits;
for( ;; )
{
/* Called when a task want to make changes to a directory.
First it waits for the desired bit to come high. */
xEventGroupWaitBits( pxIOManager->xEventGroup,
FF_DIR_LOCK_EVENT_BITS, /* uxBitsToWaitFor */
( EventBits_t )0, /* xClearOnExit */
pdFALSE, /* xWaitForAllBits n.a. */
pdMS_TO_TICKS( 10000UL ) );
/* The next operation will only succeed for 1 task at a time,
because it is an atomary test & set operation: */
xBits = xEventGroupClearBits( pxIOManager->xEventGroup, FF_DIR_LOCK_EVENT_BITS );
if( ( xBits & FF_DIR_LOCK_EVENT_BITS ) != 0 )
{
/* This task has cleared the desired bit.
It now 'owns' the resource. */
break;
}
}
}
/*-----------------------------------------------------------*/
void FF_UnlockDirectory( FF_IOManager_t *pxIOManager )
{
configASSERT( ( xEventGroupGetBits( pxIOManager->xEventGroup ) & FF_DIR_LOCK_EVENT_BITS ) == 0 );
xEventGroupSetBits( pxIOManager->xEventGroup, FF_DIR_LOCK_EVENT_BITS );
}
/*-----------------------------------------------------------*/
int FF_Has_Lock( FF_IOManager_t *pxIOManager, uint32_t aBits )
{
int iReturn;
void *handle = xTaskGetCurrentTaskHandle();
if( ( aBits & FF_FAT_LOCK_EVENT_BITS ) != 0 )
{
if( ( pxIOManager->pvFATLockHandle != NULL ) && ( pxIOManager->pvFATLockHandle == handle ) )
{
iReturn = pdTRUE;
}
else
{
iReturn = pdFALSE;
}
}
else
{
iReturn = pdFALSE;
}
return iReturn;
}
void FF_Assert_Lock( FF_IOManager_t *pxIOManager, uint32_t aBits )
{
void *handle = xTaskGetCurrentTaskHandle();
if( ( aBits & FF_FAT_LOCK_EVENT_BITS ) != 0 )
{
configASSERT( ( pxIOManager->pvFATLockHandle != NULL ) && ( pxIOManager->pvFATLockHandle == handle ) );
/* In case configASSERT() is not defined. */
( void ) pxIOManager;
( void ) handle;
}
}
void FF_LockFAT( FF_IOManager_t *pxIOManager )
{
EventBits_t xBits;
configASSERT( FF_Has_Lock( pxIOManager, FF_FAT_LOCK ) == pdFALSE );
for( ;; )
{
/* Called when a task want to make changes to the FAT area.
First it waits for the desired bit to come high. */
xEventGroupWaitBits( pxIOManager->xEventGroup,
FF_FAT_LOCK_EVENT_BITS, /* uxBitsToWaitFor */
( EventBits_t )0, /* xClearOnExit */
pdFALSE, /* xWaitForAllBits n.a. */
pdMS_TO_TICKS( 10000UL ) );
/* The next operation will only succeed for 1 task at a time,
because it is an atomary test & set operation: */
xBits = xEventGroupClearBits( pxIOManager->xEventGroup, FF_FAT_LOCK_EVENT_BITS );
if( ( xBits & FF_FAT_LOCK_EVENT_BITS ) != 0 )
{
/* This task has cleared the desired bit.
It now 'owns' the resource. */
pxIOManager->pvFATLockHandle = xTaskGetCurrentTaskHandle();
break;
}
}
}
/*-----------------------------------------------------------*/
void FF_UnlockFAT( FF_IOManager_t *pxIOManager )
{
configASSERT( ( xEventGroupGetBits( pxIOManager->xEventGroup ) & FF_FAT_LOCK_EVENT_BITS ) == 0 );
pxIOManager->pvFATLockHandle = NULL;
xEventGroupSetBits( pxIOManager->xEventGroup, FF_FAT_LOCK_EVENT_BITS );
}
/*-----------------------------------------------------------*/
BaseType_t FF_BufferWait( FF_IOManager_t *pxIOManager, uint32_t xWaitMS )
{
EventBits_t xBits;
BaseType_t xReturn;
/* This function is called when a task is waiting for a sector buffer
to become available. */
xBits = xEventGroupWaitBits( pxIOManager->xEventGroup,
FF_BUF_LOCK_EVENT_BITS, /* uxBitsToWaitFor */
FF_BUF_LOCK_EVENT_BITS, /* xClearOnExit */
pdFALSE, /* xWaitForAllBits n.a. */
pdMS_TO_TICKS( xWaitMS ) );
if( ( xBits & FF_BUF_LOCK_EVENT_BITS ) != 0 )
{
xReturn = pdTRUE;
}
else
{
xReturn = pdFALSE;
}
return xReturn;
}
/*-----------------------------------------------------------*/
void FF_BufferProceed( FF_IOManager_t *pxIOManager )
{
/* Wake-up all tasks that are waiting for a sector buffer to become available. */
xEventGroupSetBits( pxIOManager->xEventGroup, FF_BUF_LOCK_EVENT_BITS );
}
/*-----------------------------------------------------------*/

View file

@ -0,0 +1,108 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
/**
* @file ff_memory.c
* @ingroup MEMORY
*
* @defgroup MEMORY FreeRTOS+FAT Memory Access Routines
* @brief Handles memory access in a portable way.
*
* Provides simple, fast, and portable access to memory routines.
* These are only used to read data from buffers. That are LITTLE ENDIAN
* due to the FAT specification.
*
* These routines may need to be modified to your platform.
*
**/
#include "ff_headers.h"
/*
* Here below 3 x 2 access functions that allow the code
* not to worry about the endianness of the MCU.
*/
#if( ffconfigINLINE_MEMORY_ACCESS == 0 )
uint8_t FF_getChar( const uint8_t *pBuffer, uint32_t aOffset )
{
return ( uint8_t ) ( pBuffer[ aOffset ] );
}
uint16_t FF_getShort( const uint8_t *pBuffer, uint32_t aOffset )
{
FF_T_UN16 u16;
pBuffer += aOffset;
u16.bytes.u8_1 = pBuffer[ 1 ];
u16.bytes.u8_0 = pBuffer[ 0 ];
return u16.u16;
}
uint32_t FF_getLong( const uint8_t *pBuffer, uint32_t aOffset )
{
FF_T_UN32 u32;
pBuffer += aOffset;
u32.bytes.u8_3 = pBuffer[ 3 ];
u32.bytes.u8_2 = pBuffer[ 2 ];
u32.bytes.u8_1 = pBuffer[ 1 ];
u32.bytes.u8_0 = pBuffer[ 0 ];
return u32.u32;
}
void FF_putChar( uint8_t *pBuffer, uint32_t aOffset, uint32_t Value )
{
pBuffer[ aOffset ] = ( uint8_t ) Value;
}
void FF_putShort( uint8_t *pBuffer, uint32_t aOffset, uint32_t Value )
{
FF_T_UN16 u16;
u16.u16 = ( uint16_t ) Value;
pBuffer += aOffset;
pBuffer[ 0 ] = u16.bytes.u8_0;
pBuffer[ 1 ] = u16.bytes.u8_1;
}
void FF_putLong( uint8_t *pBuffer, uint32_t aOffset, uint32_t Value )
{
FF_T_UN32 u32;
u32.u32 = Value;
pBuffer += aOffset;
pBuffer[ 0 ] = u32.bytes.u8_0;
pBuffer[ 1 ] = u32.bytes.u8_1;
pBuffer[ 2 ] = u32.bytes.u8_2;
pBuffer[ 3 ] = u32.bytes.u8_3;
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,716 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
/**
* @file ff_string.c
* @ingroup STRING
*
* @defgroup STRING FreeRTOS+FAT String Library
* @brief Portable String Library for FreeRTOS+FAT
*
*
**/
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "ff_headers.h"
#if( ffconfigUNICODE_UTF16_SUPPORT != 0 )
#include <wchar.h>
#include <wctype.h>
#endif
/*
* These will eventually be moved into a platform independent string
* library. Which will be optional. (To allow the use of system specific versions).
*/
#if( ffconfigUNICODE_UTF16_SUPPORT != 0 )
void FF_cstrntowcs( FF_T_WCHAR *wcsDest, const int8_t *szpSource, uint32_t ulLength )
{
while( ( *szpSource != '\0' ) && ( ulLength-- != 0 ) )
{
*( wcsDest++ ) = *( szpSource++ );
}
*wcsDest = '\0';
}
#endif /* ffconfigUNICODE_UTF16_SUPPORT */
/*-----------------------------------------------------------*/
#if( ffconfigUNICODE_UTF16_SUPPORT != 0 )
void FF_cstrtowcs( FF_T_WCHAR *wcsDest, const int8_t *szpSource )
{
while( *szpSource != '\0' )
{
*wcsDest++ = ( FF_T_WCHAR ) *( szpSource++ );
}
*wcsDest = '\0';
}
#endif /* ffconfigUNICODE_UTF16_SUPPORT */
/*-----------------------------------------------------------*/
#if( ffconfigUNICODE_UTF16_SUPPORT != 0 )
void FF_wcstocstr( int8_t *szpDest, const FF_T_WCHAR *wcsSource )
{
while( *wcsSource != '\0' )
{
*szpDest++ = ( int8_t )*( wcsSource++ );
}
*szpDest = '\0';
}
#endif /* ffconfigUNICODE_UTF16_SUPPORT */
/*-----------------------------------------------------------*/
#if( ffconfigUNICODE_UTF16_SUPPORT != 0 )
void FF_wcsntocstr( int8_t *szpDest, const FF_T_WCHAR *wcsSource, uint32_t ulLength )
{
while( ( *wcsSource != '\0' ) && ( ulLength-- != 0 ) )
{
*( szpDest++ ) = ( int8_t ) *( wcsSource++ );
}
*szpDest = '\0';
}
#endif /* ffconfigUNICODE_UTF16_SUPPORT */
/*-----------------------------------------------------------*/
/*-----------------------------------------------------------*/
#if( ffconfigUNICODE_UTF16_SUPPORT != 0 )
void FF_toupper( FF_T_WCHAR *string, uint32_t ulLength )
{
uint32_t i;
for( i = 0; i < ulLength; i++ )
{
string[ i ] = towupper( string[ i ] );
}
}
/*-----------------------------------------------------------*/
void FF_tolower( FF_T_WCHAR *string, uint32_t ulLength )
{
uint32_t i;
for( i = 0; i < ulLength; i++ )
{
string[ i ] = towlower( string[ i ] );
}
}
/*-----------------------------------------------------------*/
#else /* ffconfigUNICODE_UTF16_SUPPORT */
void FF_toupper( char *string, uint32_t ulLength )
{
uint32_t i;
for( i = 0; i < ulLength; i++ )
{
if( ( string[ i ] >= 'a' ) && ( string[ i ] <= 'z' ) )
{
string[ i ] -= 32;
}
if( string[ i ] == '\0' )
{
break;
}
}
}
/*-----------------------------------------------------------*/
void FF_tolower( char *string, uint32_t ulLength )
{
uint32_t i;
for( i = 0; i < ulLength; i++ )
{
if( ( string[ i ] >= 'A' ) && ( string[ i ] <= 'Z' ) )
{
string[ i ] += 32;
}
if( string[ i ] == '\0' )
{
break;
}
}
}
/*-----------------------------------------------------------*/
#endif /* ffconfigUNICODE_UTF16_SUPPORT */
/**
* @private
* @brief Compares 2 strings for the specified length, and returns pdTRUE is they are identical
* otherwise pdFALSE is returned.
*
**/
#if( ffconfigUNICODE_UTF16_SUPPORT == 0 )
BaseType_t FF_strmatch( const char *str1, const char *str2, BaseType_t xLength )
{
register BaseType_t i;
register char char1, char2;
if( xLength == 0 )
{
xLength = strlen( str1 );
if( xLength != ( BaseType_t )strlen( str2 ) )
{
return pdFALSE;
}
}
for( i = 0; i < xLength; i++ )
{
char1 = str1[ i ];
char2 = str2[ i ];
if( ( char1 >= 'A' ) && ( char1 <= 'Z' ) )
{
char1 += 32;
}
if( ( char2 >= 'A' ) && ( char2 <= 'Z' ) )
{
char2 += 32;
}
if( char1 != char2 )
{
return pdFALSE;
}
}
return pdTRUE;
}
#else /* ffconfigUNICODE_UTF16_SUPPORT */
BaseType_t FF_strmatch( const FF_T_WCHAR *str1, const FF_T_WCHAR *str2, BaseType_t xLength )
{
register BaseType_t i;
register FF_T_WCHAR char1, char2;
if( xLength == 0 )
{
xLength = wcslen( str1 );
if( xLength != wcslen( str2 ) )
{
return pdFALSE;
}
}
for( i = 0; i < xLength; i++ )
{
char1 = towlower( str1[ i ] );
char2 = towlower( str2[ i ] );
if( char1 != char2 )
{
return pdFALSE;
}
}
return pdTRUE;
}
#endif /* ffconfigUNICODE_UTF16_SUPPORT */
/**
* @private
* @brief A re-entrant Strtok function. No documentation is provided :P
* Use at your own risk. (This is for FreeRTOS+FAT's use only).
**/
#if( ffconfigUNICODE_UTF16_SUPPORT == 0 )
char *FF_strtok( const char *string, char *token, uint16_t *tokenNumber, BaseType_t *last, BaseType_t xLength )
{
uint16_t i,y, tokenStart, tokenEnd = 0;
i = 0;
y = 0;
if( ( string[ i ] == '\\' ) || ( string[ i ] == '/' ) )
{
i++;
}
tokenStart = i;
while( i < xLength )
{
if( ( string[ i ] == '\\' ) || ( string[ i ] == '/' ) )
{
y++;
if( y == *tokenNumber )
{
tokenStart = ( uint16_t )( i + 1 );
}
if( y == ( *tokenNumber + 1 ) )
{
tokenEnd = i;
break;
}
}
i++;
}
if( tokenEnd == 0 )
{
if( *last == pdTRUE )
{
return NULL;
}
else
{
*last = pdTRUE;
}
tokenEnd = i;
}
if( ( tokenEnd - tokenStart ) < ffconfigMAX_FILENAME )
{
memcpy( token, ( string + tokenStart ), ( uint32_t )( tokenEnd - tokenStart ) );
token[ tokenEnd - tokenStart ] = '\0';
}
else
{
memcpy( token, ( string + tokenStart ), ( uint32_t )( ffconfigMAX_FILENAME ) );
token[ ffconfigMAX_FILENAME - 1 ] = '\0';
}
/*token[tokenEnd - tokenStart] = '\0'; */
*tokenNumber += 1;
return token;
}
#else /* ffconfigUNICODE_UTF16_SUPPORT */
FF_T_WCHAR *FF_strtok( const FF_T_WCHAR *string, FF_T_WCHAR *token, uint16_t *tokenNumber, BaseType_t *last, BaseType_t xLength )
{
uint16_t i,y, tokenStart, tokenEnd = 0;
i = 0;
y = 0;
if( ( string[ i ] == '\\' ) || ( string[ i ] == '/' ) )
{
i++;
}
tokenStart = i;
while( i < xLength )
{
if( ( string[ i ] == '\\' ) || ( string[ i ] == '/' ) )
{
y++;
if( y == *tokenNumber )
{
tokenStart = ( uint16_t ) ( i + 1 );
}
if( y == ( *tokenNumber + 1 ) )
{
tokenEnd = i;
break;
}
}
i++;
}
if( tokenEnd == 0 )
{
if( *last == pdTRUE )
{
return NULL;
}
else
{
*last = pdTRUE;
}
tokenEnd = i;
}
if( ( tokenEnd - tokenStart ) < ffconfigMAX_FILENAME )
{
memcpy( token, ( string + tokenStart ), ( uint32_t )( tokenEnd - tokenStart ) * sizeof( FF_T_WCHAR ) );
token[ tokenEnd - tokenStart ] = '\0';
}
else
{
memcpy( token, ( string + tokenStart ), ( uint32_t )( ffconfigMAX_FILENAME ) * sizeof( FF_T_WCHAR ) );
token[ ffconfigMAX_FILENAME - 1 ] = '\0';
}
/*token[tokenEnd - tokenStart] = '\0'; */
*tokenNumber += 1;
return token;
}
#endif /* ffconfigUNICODE_UTF16_SUPPORT */
/* UTF-8 Routines */
/*
UCS-4 range (hex.) UTF-8 octet sequence (binary)
0000 0000-0000 007F 0xxxxxxx
0000 0080-0000 07FF 110xxxxx 10xxxxxx
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx -- We don't encode these because we won't receive them. (Invalid UNICODE).
0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx -- We don't encode these because we won't receive them. (Invalid UNICODE).
*/
#if ( ( ffconfigUNICODE_UTF16_SUPPORT != 0 ) && ( WCHAR_MAX > 0xFFFF ) ) || ( ffconfigUNICODE_UTF8_SUPPORT != 0 )
UBaseType_t FF_GetUtf16SequenceLen( uint16_t usLeadChar )
{
UBaseType_t uxReturn;
if( ( usLeadChar & 0xFC00 ) == 0xD800 )
{
uxReturn = 2;
}
else
{
uxReturn = 1;
}
return uxReturn;
} /* FF_GetUtf16SequenceLen() */
#endif
/*-----------------------------------------------------------*/
/*
Returns the number of UTF-8 units read.
Will not exceed ulSize UTF-16 units. (ulSize * 2 bytes).
*/
/*
UCS-4 range (hex.) UTF-8 octet sequence (binary)
0000 0000-0000 007F 0xxxxxxx
0000 0080-0000 07FF 110xxxxx 10xxxxxx
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx -- We don't encode these because we won't receive them. (Invalid UNICODE).
0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx -- We don't encode these because we won't receive them. (Invalid UNICODE).
*/
#if ( ffconfigUNICODE_UTF8_SUPPORT != 0 )
int32_t FF_Utf8ctoUtf16c( uint16_t *utf16Dest, const uint8_t *utf8Source, uint32_t ulSize )
{
uint32_t ulUtf32char;
uint16_t utf16Source = 0;
register int32_t lSequenceNumber = 0;
/* Count number of set bits before a zero. */
while( ( ( *utf8Source != '\0' ) & ( 0x80 >> ( lSequenceNumber ) ) ) )
{
lSequenceNumber++;
}
if( lSequenceNumber == 0UL )
{
lSequenceNumber++;
}
if( ulSize == 0UL )
{
/* Returned value becomes an error, with the highest bit set. */
lSequenceNumber = FF_ERR_UNICODE_DEST_TOO_SMALL | FF_UTF8CTOUTF16C;
}
else
{
switch( lSequenceNumber )
{
case 1:
utf16Source = (uint16_t) *utf8Source;
memcpy(utf16Dest,&utf16Source,sizeof(uint16_t));
break;
case 2:
utf16Source =(uint16_t) ((*utf8Source & 0x1F) << 6) | ((*(utf8Source + 1) & 0x3F));
memcpy(utf16Dest,&utf16Source,sizeof(uint16_t));
break;
case 3:
utf16Source =(uint16_t) ((*utf8Source & 0x0F) << 12) | ((*(utf8Source + 1) & 0x3F) << 6) | ((*(utf8Source + 2) & 0x3F));
memcpy(utf16Dest,&utf16Source,sizeof(uint16_t));
break;
case 4:
if( ulSize < 2 )
{
/* Returned value becomes an error. */
lSequenceNumber = FF_ERR_UNICODE_DEST_TOO_SMALL | FF_UTF8CTOUTF16C;
}
else
{
/* Convert to UTF-32 and then into UTF-16 */
ulUtf32char = ( uint16_t )
( ( *utf8Source & 0x0F ) << 18 ) |
( ( *( utf8Source + 1 ) & 0x3F ) << 12 ) |
( ( *( utf8Source + 2 ) & 0x3F ) << 6 ) |
( ( *( utf8Source + 3 ) & 0x3F ) );
utf16Source = ( uint16_t ) ( ( ( ulUtf32char - 0x10000 ) & 0xFFC00 ) >> 10 ) | 0xD800;
memcpy( utf16Dest, &utf16Source, sizeof( uint16_t ) );
utf16Source = ( uint16_t ) ( ( ( ulUtf32char - 0x10000 ) & 0x003FF ) >> 00 ) | 0xDC00;
memcpy( utf16Dest + 1, &utf16Source, sizeof( uint16_t ) );
}
break;
default:
break;
}
}
return lSequenceNumber;
} /* FF_Utf8ctoUtf16c() */
#endif /* ffconfigUNICODE_UTF8_SUPPORT */
/*-----------------------------------------------------------*/
/*
Returns the number of UTF-8 units required to encode the UTF-16 sequence.
Will not exceed ulSize UTF-8 units. (ulSize * 1 bytes).
*/
#if ( ffconfigUNICODE_UTF8_SUPPORT != 0 )
int32_t FF_Utf16ctoUtf8c( uint8_t *utf8Dest, const uint16_t *utf16Source, uint32_t ulSize )
{
uint32_t ulUtf32char;
uint16_t ulUtf16char;
int32_t lReturn = 0L;
do
{
if( ulSize == 0UL )
{
lReturn = FF_ERR_UNICODE_DEST_TOO_SMALL | FF_UTF16CTOUTF8C;
break;
}
memcpy( &ulUtf16char, utf16Source, sizeof( uint16_t ) );
/* A surrogate sequence was encountered. Must transform to UTF32 first. */
if( ( ulUtf16char & 0xF800) == 0xD800 )
{
ulUtf32char = ( ( uint32_t ) ( ulUtf16char & 0x003FF ) << 10 ) + 0x10000;
memcpy( &ulUtf16char, utf16Source + 1, sizeof( uint16_t ) );
if( ( ulUtf16char & 0xFC00 ) != 0xDC00 )
{
/* Invalid UTF-16 sequence. */
lReturn = FF_ERR_UNICODE_INVALID_SEQUENCE | FF_UTF16CTOUTF8C;
break;
}
ulUtf32char |= ( ( uint32_t ) ( ulUtf16char & 0x003FF ) );
}
else
{
ulUtf32char = ( uint32_t ) ulUtf16char;
}
/* Now convert to the UTF-8 sequence. */
/* Single byte UTF-8 sequence. */
if( ulUtf32char < 0x00000080 )
{
*( utf8Dest + 0 ) = ( uint8_t )ulUtf32char;
lReturn = 1;
break;
}
/* Double byte UTF-8 sequence. */
if( ulUtf32char < 0x00000800 )
{
if( ulSize < 2 )
{
lReturn = FF_ERR_UNICODE_DEST_TOO_SMALL | FF_UTF16CTOUTF8C;
}
else
{
*( utf8Dest + 0 ) = ( uint8_t ) ( 0xC0 | ( ( ulUtf32char >> 6 ) & 0x1F ) );
*( utf8Dest + 1 ) = ( uint8_t ) ( 0x80 | ( ( ulUtf32char >> 0 ) & 0x3F ) );
lReturn = 2;
}
break;
}
/* Triple byte UTF-8 sequence. */
if( ulUtf32char < 0x00010000 )
{
if( ulSize < 3 )
{
lReturn = FF_ERR_UNICODE_DEST_TOO_SMALL | FF_UTF16CTOUTF8C;
}
else
{
*( utf8Dest + 0 ) = ( uint8_t ) ( 0xE0 | ( ( ulUtf32char >> 12 ) & 0x0F ) );
*( utf8Dest + 1 ) = ( uint8_t ) ( 0x80 | ( ( ulUtf32char >> 6 ) & 0x3F ) );
*( utf8Dest + 2 ) = ( uint8_t ) ( 0x80 | ( ( ulUtf32char >> 0 ) & 0x3F ) );
lReturn = 3;
}
break;
}
/* Quadruple byte UTF-8 sequence. */
if( ulUtf32char < 0x00200000 )
{
if( ulSize < 4 )
{
lReturn = FF_ERR_UNICODE_DEST_TOO_SMALL | FF_UTF16CTOUTF8C;
}
else
{
*( utf8Dest + 0 ) = ( uint8_t ) (0xF0 | ( ( ulUtf32char >> 18 ) & 0x07 ) );
*( utf8Dest + 1 ) = ( uint8_t ) (0x80 | ( ( ulUtf32char >> 12 ) & 0x3F ) );
*( utf8Dest + 2 ) = ( uint8_t ) (0x80 | ( ( ulUtf32char >> 6 ) & 0x3F ) );
*( utf8Dest + 3 ) = ( uint8_t ) (0x80 | ( ( ulUtf32char >> 0 ) & 0x3F ) );
lReturn = 4;
}
break;
}
lReturn = FF_ERR_UNICODE_INVALID_CODE | FF_UTF16CTOUTF8C; /* Invalid Character */
}
while( pdFALSE );
return lReturn;
} /* FF_Utf16ctoUtf8c() */
#endif /* ffconfigUNICODE_UTF8_SUPPORT */
/*-----------------------------------------------------------*/
/* UTF-16 Support Functions */
/* Converts a UTF-32 Character into its equivalent UTF-16 sequence. */
#if( ffconfigUNICODE_UTF16_SUPPORT != 0 ) && ( WCHAR_MAX > 0xFFFF )
int32_t FF_Utf32ctoUtf16c( uint16_t *utf16Dest, uint32_t utf32char, uint32_t ulSize )
{
int32_t lReturn;
/* Check that its a valid UTF-32 wide-char! */
/* This range is not a valid Unicode code point. */
if( ( utf32char >= 0xD800 ) && ( utf32char <= 0xDFFF ) )
{
lReturn = FF_ERR_UNICODE_INVALID_CODE | FF_UTF32CTOUTF16C; /* Invalid character. */
}
else if( utf32char < 0x10000 )
{
*utf16Dest = (uint16_t) utf32char; /* Simple conversion! Char comes within UTF-16 space (without surrogates). */
lReturn = 1;
}
else if( ulSize < 2 )
{
lReturn FF_ERR_UNICODE_DEST_TOO_SMALL | FF_UTF32CTOUTF16C; /* Not enough UTF-16 units to record this character. */
}
else if( utf32char < 0x00200000 )
{
/* Conversion to a UTF-16 Surrogate pair! */
/*valueImage = utf32char - 0x10000; */
*( utf16Dest + 0 ) = ( uint16_t ) ( ( ( utf32char - 0x10000 ) & 0xFFC00 ) >> 10 ) | 0xD800;
*( utf16Dest + 1 ) = ( uint16_t ) ( ( ( utf32char - 0x10000 ) & 0x003FF ) >> 00 ) | 0xDC00;
lReturn = 2; /* Surrogate pair encoded value. */
}
else
{
/* Invalid Character */
lReturn = FF_ERR_UNICODE_INVALID_CODE | FF_UTF32CTOUTF16C;
}
return lReturn;
} /* FF_Utf32ctoUtf16c() */
#endif /* #if( ffconfigUNICODE_UTF16_SUPPORT != 0 ) && ( WCHAR_MAX > 0xFFFF ) */
/*-----------------------------------------------------------*/
/* Converts a UTF-16 sequence into its equivalent UTF-32 code point. */
#if( ffconfigNOT_USED_FOR_NOW != 0 )
int32_t FF_Utf16ctoUtf32c( uint32_t *utf32Dest, const uint16_t *utf16Source )
{
int32_t lReturn;
/*Not a surrogate sequence. */
if( ( *utf16Source & 0xFC00 ) != 0xD800 )
{
*utf32Dest = ( uint32_t )*utf16Source;
lReturn = 1; /* A single UTF-16 item was used to represent the character. */
}
else
{
*utf32Dest = ( ( uint32_t) ( * ( utf16Source + 0 ) & 0x003FF ) << 10 ) + 0x10000;
if( ( *(utf16Source + 1) & 0xFC00 ) != 0xDC00 )
{
lReturn = FF_ERR_UNICODE_INVALID_SEQUENCE | FF_UTF16CTOUTF32C; /* Invalid UTF-16 sequence. */
}
else
{
*utf32Dest |= ( ( uint32_t ) ( *( utf16Source + 1 ) & 0x003FF ) );
lReturn = 2; /* 2 utf-16 units make up the Unicode code-point. */
}
}
return lReturn;
} /* FF_Utf16ctoUtf32c() */
#endif /* ffconfigNOT_USED_FOR_NOW */
/*-----------------------------------------------------------*/
/*
Returns the total number of UTF-16 items required to represent
the provided UTF-32 string in UTF-16 form.
*/
/*
UBaseType_t FF_Utf32GetUtf16Len( const uint32_t *utf32String )
{
UBaseType_t utf16len = 0;
while( *utf32String )
{
if( *utf32String++ <= 0xFFFF )
{
utf16len++;
}
else
{
utf16len += 2;
}
}
return utf16len;
}
*/
/*-----------------------------------------------------------*/
/* String conversions */
#if( ffconfigNOT_USED_FOR_NOW != 0 )
int32_t FF_Utf32stoUtf8s( uint8_t *Utf8String, uint32_t *Utf32String )
{
int i = 0,y = 0;
uint16_t utf16buffer[ 2 ];
while( Utf32String[ i ] != '\0' )
{
/* Convert to a UTF16 char. */
FF_Utf32ctoUtf16c( utf16buffer, Utf32String[ i ], 2 );
/* Now convert the UTF16 to UTF8 sequence. */
y += FF_Utf16ctoUtf8c( &Utf8String[ y ], utf16buffer, 4 );
i++;
}
Utf8String[ y ] = '\0';
return 0;
} /* FF_Utf32stoUtf8s() */
#endif /* ffconfigNOT_USED_FOR_NOW */
/*-----------------------------------------------------------*/

View file

@ -0,0 +1,274 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
#include <stdio.h>
#include <string.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "portable.h"
#include "ff_headers.h"
#include "ff_sys.h"
#ifndef ARRAY_SIZE
# define ARRAY_SIZE(x) ( int )( sizeof( x ) / sizeof( x )[ 0 ] )
#endif
/*
* Define a collection of 'file systems' as a simple array
*/
typedef struct xSYSTEM
{
FF_SubSystem_t xSystems[ ffconfigMAX_FILE_SYS ];
volatile BaseType_t xFileSystemCount;
} ff_sys_t;
static ff_sys_t file_systems;
static const char rootDir[] = "/";
int FF_FS_Count( void )
{
return ( int )file_systems.xFileSystemCount;
}
/*-----------------------------------------------------------*/
void FF_FS_Init( void )
{
memset( &file_systems, '\0', sizeof( file_systems ) );
/* There is always a root file system, even if it doesn't have a
IO manager. */
file_systems.xFileSystemCount = ( BaseType_t ) 1;
/* Set to "/", second byte is already zero. */
file_systems.xSystems[ 0 ].pcPath[ 0 ] = ( char ) '/';
file_systems.xSystems[ 0 ].xPathlen = 1;
}
/*-----------------------------------------------------------*/
int FF_FS_Add( const char *pcPath, FF_Disk_t *pxDisk )
{
int iReturn = pdFALSE;
configASSERT( pxDisk );
if( *pcPath != ( char ) '/' )
{
FF_PRINTF( "FF_FS_Add: Need a \"/\": '%s'\n", pcPath );
}
else
{
BaseType_t xUseIndex = -1;
size_t uxPathLength = strlen( pcPath );
vTaskSuspendAll();
{
if( file_systems.xFileSystemCount == ( BaseType_t ) 0 )
{
FF_FS_Init();
}
if( uxPathLength == ( size_t ) 1u )
{
/* This is the "/" path
* and will always be put at index 0 */
xUseIndex = ( BaseType_t ) 0;
}
else
{
BaseType_t xIndex, xFreeIndex = -1;
FF_SubSystem_t *pxSubSystem = file_systems.xSystems + 1; /* Skip the root entry */
for( xIndex = ( BaseType_t ) 1; xIndex < file_systems.xFileSystemCount; xIndex++, pxSubSystem++ )
{
if( ( pxSubSystem->xPathlen == ( BaseType_t )uxPathLength ) &&
( memcmp( pxSubSystem->pcPath, pcPath, uxPathLength ) == 0 ) )
{
/* A system is updated with a new handler. */
xUseIndex = xIndex;
break;
}
if( ( pxSubSystem->pxManager == NULL ) && ( xFreeIndex < 0 ) )
{
/* Remember the first free slot. */
xFreeIndex = xIndex;
}
}
if( xUseIndex < ( BaseType_t ) 0 )
{
if( xFreeIndex >= ( BaseType_t ) 0 )
{
/* Use the first free slot. */
xUseIndex = xFreeIndex;
}
else if( file_systems.xFileSystemCount < ARRAY_SIZE( file_systems.xSystems ) )
{
/* Fill a new entry. */
xUseIndex = file_systems.xFileSystemCount++;
}
}
} /* uxPathLength != 1 */
if( xUseIndex >= ( BaseType_t ) 0 )
{
iReturn = pdTRUE;
strncpy( file_systems.xSystems[ xUseIndex ].pcPath, pcPath, sizeof( file_systems.xSystems[ xUseIndex ].pcPath ) );
file_systems.xSystems[ xUseIndex ].xPathlen = uxPathLength;
file_systems.xSystems[ xUseIndex ].pxManager = pxDisk->pxIOManager;
}
}
xTaskResumeAll( );
if( iReturn == pdFALSE )
{
FF_PRINTF( "FF_FS_Add: Table full '%s' (max = %d)\n", pcPath, (int)ARRAY_SIZE( file_systems.xSystems ) );
}
}
return iReturn;
}
/*-----------------------------------------------------------*/
void FF_FS_Remove( const char *pcPath )
{
BaseType_t xUseIndex, xIndex;
size_t uxPathLength;
if( pcPath[ 0 ] == ( char ) '/' )
{
xUseIndex = -1;
uxPathLength = strlen( pcPath );
/* Is it the "/" path ? */
if( uxPathLength == ( size_t ) 1u )
{
xUseIndex = 0;
}
else
{
FF_SubSystem_t *pxSubSystem = file_systems.xSystems + 1;
for( xIndex = 1; xIndex < file_systems.xFileSystemCount; xIndex++, pxSubSystem++ )
{
if( ( pxSubSystem->xPathlen == ( BaseType_t ) uxPathLength ) &&
( memcmp( pxSubSystem->pcPath, pcPath, uxPathLength ) == 0 ) )
{
xUseIndex = xIndex;
break;
}
}
}
if( xUseIndex >= 0 )
{
vTaskSuspendAll();
{
file_systems.xSystems[ xUseIndex ].pxManager = NULL;
file_systems.xSystems[ xUseIndex ].xPathlen = ( BaseType_t )0;
for( xIndex = file_systems.xFileSystemCount - 1; xIndex > 0; xIndex-- )
{
if( file_systems.xSystems[ xIndex ].pxManager != NULL )
{
/* The slot at 'xIndex' is still in use. */
break;
}
}
file_systems.xFileSystemCount = xIndex + 1;
}
xTaskResumeAll( );
}
}
}
/*-----------------------------------------------------------*/
int FF_FS_Find( const char *pcPath, FF_DirHandler_t *pxHandler )
{
FF_SubSystem_t *pxSubSystem;
size_t uxPathLength;
BaseType_t xUseIndex;
int iReturn;
pxSubSystem = file_systems.xSystems + 1;
uxPathLength = strlen( pcPath );
memset( pxHandler, '\0', sizeof( *pxHandler ) );
for( xUseIndex = 1; xUseIndex < file_systems.xFileSystemCount; xUseIndex++, pxSubSystem++ )
{
if( ( uxPathLength >= ( size_t ) pxSubSystem->xPathlen ) &&
( memcmp( pxSubSystem->pcPath, pcPath, ( size_t ) pxSubSystem->xPathlen ) == 0 ) &&
( ( pcPath[ pxSubSystem->xPathlen ] == '\0' ) || ( pcPath[ pxSubSystem->xPathlen ] == '/') ) ) /* System "/ram" should not match with "/ramc/etc". */
{
if( pcPath[ pxSubSystem->xPathlen ] == '\0')
{
pxHandler->pcPath = rootDir;
}
else
{
pxHandler->pcPath = pcPath + pxSubSystem->xPathlen;
}
pxHandler->pxManager = pxSubSystem->pxManager;
break;
}
}
if( xUseIndex == file_systems.xFileSystemCount )
{
pxHandler->pcPath = pcPath;
pxHandler->pxManager = file_systems.xSystems[ 0 ].pxManager;
}
if( FF_Mounted( pxHandler->pxManager ) )
{
iReturn = pdTRUE;
}
else
{
iReturn = pdFALSE;
}
return iReturn;
}
/*-----------------------------------------------------------*/
int FF_FS_Get( int xIndex, FF_SubSystem_t *pxSystem )
{
int iReturn;
/* Get a copy of a fs info. */
if( ( xIndex < 0 ) || ( xIndex >= file_systems.xFileSystemCount ) )
{
iReturn = pdFALSE;
}
else
{
/* Note: it will copy the contents of 'FF_SubSystem_t'. */
*pxSystem = file_systems.xSystems[ xIndex ];
iReturn = pdTRUE;
}
return iReturn;
}
/*-----------------------------------------------------------*/

View file

@ -0,0 +1,291 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
#include <stdio.h>
#include <time.h>
#include <string.h>
#include "FreeRTOS.h"
#include "task.h"
#include "ff_time.h"
/**
* @file ff_time.c
* @ingroup TIME
*
* @defgroup TIME Real-Time Clock Interface
* @brief Allows FreeRTOS+FAT to time-stamp files.
*
* Provides a means for receiving the time on any platform.
**/
#if( ffconfigTIME_SUPPORT != 0 ) /* This if-block spans the rest of the source file. */
/**
* @public
* @brief Populates an FF_SystemTime_t object with the current time from the system.
*
* The developer must modify this function so that it is suitable for their platform.
* The function must return with 0, and if the time is not available all elements of the
* FF_SystemTime_t object must be zero'd, as in the examples provided.
*
* @param pxTime Pointer to an FF_TIME object.
*
* @return Always returns 0.
**/
int32_t FF_GetSystemTime( FF_SystemTime_t *pxTime )
{
FF_TimeStruct_t xTimeStruct;
/* Fetch the current time. */
time_t secs = FreeRTOS_time( NULL );
/* Fill the fields in 'xTimeStruct'. */
FreeRTOS_gmtime_r( &secs, &xTimeStruct );
pxTime->Hour = xTimeStruct.tm_hour;
pxTime->Minute = xTimeStruct.tm_min;
pxTime->Second = xTimeStruct.tm_sec;
pxTime->Day = xTimeStruct.tm_mday;
pxTime->Month = xTimeStruct.tm_mon + 1;
pxTime->Year = xTimeStruct.tm_year + 1900;
return 0;
} /* FF_GetSystemTime() */
/*-----------------------------------------------------------*/
/*
* FreeRTOS+FAT
* Time conversion functions:
*
* FF_TimeStruct_t *FreeRTOS_gmtime_r( const time_t *pxTime, FF_TimeStruct_t *pxTimeBuf )
* time_t FreeRTOS_mktime(FF_TimeStruct_t *pxTimeBuf)
*/
#define GMTIME_FIRST_YEAR ( 1970 )
#define TM_STRUCT_FIRST_YEAR ( 1900 )
#define SECONDS_PER_MINUTE ( 60 )
#define MINUTES_PER_HOUR ( 60 )
#define HOURS_PER_DAY ( 24 )
#define SECONDS_PER_HOUR ( MINUTES_PER_HOUR * SECONDS_PER_MINUTE )
#define SECONDS_PER_DAY ( HOURS_PER_DAY * SECONDS_PER_HOUR )
/* The first weekday in 'FF_TimeStruct_t' is Sunday. */
#define WEEK_DAY_SUNDAY 0
#define WEEK_DAY_MONNDAY 1
#define WEEK_DAY_TUESDAY 2
#define WEEK_DAY_WEDNESDAY 3
#define WEEK_DAY_THURSDAY 4
#define WEEK_DAY_FRIDAY 5
#define WEEK_DAY_SATURDAY 6
/* Make a bitmask with a '1' for each 31-day month. */
#define _MM(month) ( 1u << ( month - 1 ) )
#define MASK_LONG_MONTHS ( _MM(1) | _MM(3) | _MM(5) | _MM(7) | _MM(8) | _MM(10) | _MM(12) )
#define DAYS_UNTIL_1970 ( ( 1970 * 365 ) + ( 1970 / 4 ) - ( 1970 / 100 ) + ( 1970 / 400 ) )
#define DAYS_BEFORE_MARCH ( 59 )
static portINLINE int iIsLeapyear( int iYear )
{
int iReturn;
if( ( iYear % 4 ) != 0 )
{
/* Not a multiple of 4 years. */
iReturn = pdFALSE;
}
else if( ( iYear % 400 ) == 0 )
{
/* Every 4 centuries there is a leap year */
iReturn = pdTRUE;
}
else if( ( iYear % 100 ) == 0 )
{
/* Other centuries are not a leap year */
iReturn = pdFALSE;
}
else
{
/* Otherwise every fourth year. */
iReturn = pdTRUE;
}
return iReturn;
}
static portINLINE unsigned long ulDaysPerYear( int iYear )
{
int iDays;
if( iIsLeapyear( iYear ) )
{
iDays = 366;
}
else
{
iDays = 365;
}
return iDays;
}
static int iDaysPerMonth( int iYear, int iMonth )
{
int iDays;
/* Month is zero-based, 1 is February. */
if (iMonth != 1 )
{
/* 30 or 31 days? */
if( ( MASK_LONG_MONTHS & ( 1u << iMonth ) ) != 0 )
{
iDays = 31;
}
else
{
iDays = 30;
}
}
else if( iIsLeapyear( iYear ) == pdFALSE )
{
/* February, non leap year. */
iDays = 28;
}
else
{
/* February, leap year. */
iDays = 29;
}
return iDays;
}
FF_TimeStruct_t *FreeRTOS_gmtime_r( const time_t *pxTime, FF_TimeStruct_t *pxTimeBuf )
{
time_t xTime = *pxTime;
unsigned long ulDaySeconds, ulDayNumber;
int iYear = GMTIME_FIRST_YEAR;
int iMonth;
/* Clear all fields, some might not get set here. */
memset( ( void * )pxTimeBuf, '\0', sizeof( *pxTimeBuf ) );
/* Seconds since last midnight. */
ulDaySeconds = ( unsigned long ) ( xTime % SECONDS_PER_DAY ) ;
/* Days since 1 Jan 1970. */
ulDayNumber = ( unsigned long ) ( xTime / SECONDS_PER_DAY ) ;
/* Today's HH:MM:SS */
pxTimeBuf->tm_hour = ulDaySeconds / SECONDS_PER_HOUR;
pxTimeBuf->tm_min = ( ulDaySeconds % SECONDS_PER_HOUR ) / 60;
pxTimeBuf->tm_sec = ulDaySeconds % 60;
/* Today's week day, knowing that 1-1-1970 was a THursday. */
pxTimeBuf->tm_wday = ( ulDayNumber + WEEK_DAY_THURSDAY ) % 7;
for( ; ; )
{
/* Keep subtracting 365 (or 366) days while possible. */
unsigned long ulDays = ulDaysPerYear( iYear );
if( ulDayNumber < ulDays )
{
break;
}
ulDayNumber -= ulDays;
iYear++;
}
/* Subtract 1900. */
pxTimeBuf->tm_year = iYear - TM_STRUCT_FIRST_YEAR;
/* The day within this year. */
pxTimeBuf->tm_yday = ulDayNumber;
/* Month are counted as 0..11 */
iMonth = 0;
for( ; ; )
{
unsigned long ulDays = iDaysPerMonth( iYear, iMonth );
/* Keep subtracting 30 (or 28, 29, or 31) days while possible. */
if( ulDayNumber < ulDays )
{
break;
}
ulDayNumber -= ulDays;
iMonth++;
}
pxTimeBuf->tm_mon = iMonth;
/* Month days are counted as 1..31 */
pxTimeBuf->tm_mday = ulDayNumber + 1;
return pxTimeBuf;
}
time_t FreeRTOS_mktime( const FF_TimeStruct_t *pxTimeBuf )
{
/* Get year AD. */
int iYear = 1900 + pxTimeBuf->tm_year; /* 20xx */
/* Get month zero-based. */
int iMonth = pxTimeBuf->tm_mon; /* 0..11 */
uint32_t ulDays;
uint32_t ulResult;
ulDays = pxTimeBuf->tm_mday - 1; /* 1..31 */
/* Make March the first month. */
iMonth -= 2;
if( iMonth < 0 )
{
/* January or February: leap day has yet to come for this year. */
iYear--;
iMonth += 12;
}
/* Add the number of days past until this month. */
ulDays += ( ( 306 * iMonth ) + 5 ) / 10;
/* Add days past before this year: */
ulDays +=
+ ( iYear * 365 ) /* Every normal year. */
+ ( iYear / 4 ) /* Plus a day for every leap year. */
- ( iYear / 100 ) /* Minus the centuries. */
+ ( iYear / 400 ) /* Except every fourth century. */
- ( DAYS_UNTIL_1970 ) /* Minus the days before 1-1-1970 */
+ ( DAYS_BEFORE_MARCH );/* Because 2 months were subtracted. */
ulResult =
( ulDays * SECONDS_PER_DAY ) +
( pxTimeBuf->tm_hour * SECONDS_PER_HOUR ) +
( pxTimeBuf->tm_min * SECONDS_PER_MINUTE ) +
pxTimeBuf->tm_sec;
return ulResult;
}
#endif /* ffconfigTIME_SUPPORT */

View file

@ -0,0 +1,427 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
#ifndef FF_DEFAULTCONFIG_H
/* The error numbers defined in this file will be moved to the core FreeRTOS
code in future versions of FreeRTOS - at which time the following header file
will be removed. */
#include "FreeRTOS_errno_FAT.h"
#if !defined( ffconfigBYTE_ORDER )
/* Must be set to either pdFREERTOS_LITTLE_ENDIAN or pdFREERTOS_BIG_ENDIAN,
depending on the endian of the architecture on which FreeRTOS is running. */
#error Invalid FreeRTOSFATConfig.h file: ffconfigBYTE_ORDER must be set to either pdFREERTOS_LITTLE_ENDIAN or pdFREERTOS_BIG_ENDIAN
#endif
#if ( ffconfigBYTE_ORDER != pdFREERTOS_LITTLE_ENDIAN ) && ( ffconfigBYTE_ORDER != pdFREERTOS_BIG_ENDIAN )
#error Invalid FreeRTOSFATConfig.h file: ffconfigBYTE_ORDER must be set to either pdFREERTOS_LITTLE_ENDIAN or pdFREERTOS_BIG_ENDIAN
#endif
#if ( pdFREERTOS_LITTLE_ENDIAN != 0 ) || ( pdFREERTOS_BIG_ENDIAN != 1 )
#error Invalid projdefs.h or FreeRTOS_errno_FAT.h file
#endif
#if !defined( ffconfigHAS_CWD )
/* Set to 1 to maintain a current working directory (CWD) for each task that
accesses the file system, allowing relative paths to be used.
Set to 0 not to use a CWD, in which case full paths must be used for each
file access. */
#define ffconfigHAS_CWD 0
#if !defined( ffconfigCWD_THREAD_LOCAL_INDEX )
#error ffconfigCWD_THREAD_LOCAL_INDEX must be set to a free position within FreeRTOSs thread local storage pointer array for storage of a pointer to the CWD structure.
#endif
#endif
#if !defined( ffconfigLFN_SUPPORT )
/* Set to 1 to include long file name support. Set to 0 to exclude long
file name support.
If long file name support is excluded then only 8.3 file names can be used.
Long file names will be recognised but ignored.
Users should familiarise themselves with any patent issues that may
potentially exist around the use of long file names in FAT file systems
before enabling long file name support. */
#define ffconfigLFN_SUPPORT 0
#endif
#if !defined( ffconfigINCLUDE_SHORT_NAME )
/* Only used when ffconfigLFN_SUPPORT is set to 1.
Set to 1 to include a file's short name when listing a directory, i.e. when
calling findfirst()/findnext(). The short name will be stored in the
'pcShortName' field of FF_DirEnt_t.
Set to 0 to only include a file's long name. */
#define ffconfigINCLUDE_SHORT_NAME 0
#endif
#if !defined( ffconfigSHORTNAME_CASE )
/* Set to 1 to recognise and apply the case bits used by Windows XP+ when
using short file names - storing file names such as "readme.TXT" or
"SETUP.exe" in a short-name entry. This is the recommended setting for
maximum compatibility.
Set to 0 to ignore the case bits. */
#define ffconfigSHORTNAME_CASE 0
#endif
#if !defined( ipconfigQUICK_SHORT_FILENAME_CREATION )
/* This method saves a lot of time when creating directories with
many similar file names: when the short name version of a LFN already
exists, try at most 3 entries with a tilde:
README~1.TXT
README~2.TXT
README~3.TXT
After that create entries with pseudo-random 4-digit hex digits:
REA~E7BB.TXT
REA~BA32.TXT
REA~D394.TXT
*/
#define ipconfigQUICK_SHORT_FILENAME_CREATION 1
#endif
/* ASCII versus UNICODE, UTF-16 versus UTF-8 :
FAT directories, when using Long File Names, always store file and directory
names UTF-16 encoded.
The user can select how these names must be represented internally:
- ASCII (default)
- UTF-8 (ffconfigUNICODE_UTF8_SUPPORT = 1)
- UTF-16 (ffconfigUNICODE_UTF16_SUPPORT = 1)
*/
#if( ffconfigUNICODE_UTF16_SUPPORT == 0 )
/* Only used when ffconfigLFN_SUPPORT is set to 1.
Set to 1 to use UTF-16 (wide-characters) for file and directory names.
Set to 0 to use either 8-bit ASCII or UTF-8 for file and directory names
(see the ffconfigUNICODE_UTF8_SUPPORT). */
#define ffconfigUNICODE_UTF16_SUPPORT 0
#endif
#if !defined( ffconfigUNICODE_UTF8_SUPPORT )
/* Only used when ffconfigLFN_SUPPORT is set to 1.
Set to 1 to use UTF-8 encoding for file and directory names.
Set to 0 to use either 8-bit ASCII or UTF-16 for file and directory
names (see the ffconfig_UTF_16_SUPPORT setting). */
#define ffconfigUNICODE_UTF8_SUPPORT 0
#endif
#if( ffconfigUNICODE_UTF16_SUPPORT != 0 ) && ( ffconfigUNICODE_UTF8_SUPPORT != 0 )
#error Can not use both UTF-16 and UTF-8
#endif
#if !defined( ffconfigFAT12_SUPPORT )
/* Set to 1 to include FAT12 support.
Set to 0 to exclude FAT12 support.
FAT16 and FAT32 are always enabled. */
#define ffconfigFAT12_SUPPORT 0
#endif
#if !defined( ffconfigOPTIMISE_UNALIGNED_ACCESS )
/* When writing and reading data, i/o becomes less efficient if sizes other
than 512 bytes are being used. When set to 1 each file handle will
allocate a 512-byte character buffer to facilitate "unaligned access". */
#define ffconfigOPTIMISE_UNALIGNED_ACCESS 0
#endif
#if !defined( ffconfigCACHE_WRITE_THROUGH )
/* Input and output to a disk uses buffers that are only flushed at the
following times:
- When a new buffer is needed and no other buffers are available.
- When opening a buffer in READ mode for a sector that has just been changed.
- After creating, removing or closing a file or a directory.
Normally this is quick enough and it is efficient. If
ffconfigCACHE_WRITE_THROUGH is set to 1 then buffers will also be flushed each
time a buffer is released - which is less efficient but more secure. */
#define ffconfigCACHE_WRITE_THROUGH 0
#endif
#if !defined( ffconfigWRITE_BOTH_FATS )
/* In most cases, the FAT table has two identical copies on the disk,
allowing the second copy to be used in the case of a read error. If
Set to 1 to use both FATs - this is less efficient but more secure.
Set to 0 to use only one FAT - the second FAT will never be written to. */
#define ffconfigWRITE_BOTH_FATS 0
#endif
#if !defined( ffconfigWRITE_FREE_COUNT )
/* Set to 1 to have the number of free clusters and the first free cluster
to be written to the FS info sector each time one of those values changes.
Set to 0 not to store these values in the FS info sector, making booting
slower, but making changes faster. */
#define ffconfigWRITE_FREE_COUNT 0
#endif
#if !defined( ffconfigTIME_SUPPORT )
/* Set to 1 to maintain file and directory time stamps for creation, modify
and last access.
Set to 0 to exclude time stamps.
If time support is used, the following function must be supplied:
time_t FreeRTOS_time( time_t *pxTime );
FreeRTOS_time has the same semantics as the standard time() function. */
#define ffconfigTIME_SUPPORT 0
#endif
#if !defined( ffconfigREMOVABLE_MEDIA )
/* Set to 1 if the media is removable (such as a memory card).
Set to 0 if the media is not removable.
When set to 1 all file handles will be "invalidated" if the media is
extracted. If set to 0 then file handles will not be invalidated.
In that case the user will have to confirm that the media is still present
before every access. */
#define ffconfigREMOVABLE_MEDIA 0
#endif
#if !defined( ffconfigMOUNT_FIND_FREE )
/* Set to 1 to determine the disk's free space and the disk's first free
cluster when a disk is mounted.
Set to 0 to find these two values when they are first needed. Determining
the values can take some time. */
#define ffconfigMOUNT_FIND_FREE 0
#endif
#if !defined( ffconfigFSINFO_TRUSTED )
/* Set to 1 to 'trust' the contents of the 'ulLastFreeCluster' and
ulFreeClusterCount fields.
Set to 0 not to 'trust' these fields.*/
#define ffconfigFSINFO_TRUSTED 0
#endif
#if !defined( ffconfigFINDAPI_ALLOW_WILDCARDS )
/* For now must be set to 0. */
#define ffconfigFINDAPI_ALLOW_WILDCARDS 0
#endif
#if !defined( ffconfigWILDCARD_CASE_INSENSITIVE )
/* For now must be set to 0. */
#define ffconfigWILDCARD_CASE_INSENSITIVE 0
#endif
#if !defined( ffconfigPATH_CACHE )
/* Set to 1 to store recent paths in a cache, enabling much faster access
when the path is deep within a directory structure at the expense of
additional RAM usage.
Set to 0 to not use a path cache. */
#define ffconfigPATH_CACHE 0
#endif
#if !defined( ffconfigPATH_CACHE_DEPTH )
/* Only used if ffconfigPATH_CACHE is 1.
Sets the maximum number of paths that can exist in the patch cache at any
one time. */
#define ffconfigPATH_CACHE_DEPTH 5
#endif
#if !defined( ffconfigHASH_CACHE )
/* Set to 1 to calculate a HASH value for each existing short file name.
Use of HASH values can improve performance when working with large
directories, or with files that have a similar name.
Set to 0 not to calculate a HASH value. */
#define ffconfigHASH_CACHE 0
#endif
#if( ffconfigHASH_CACHE != 0 )
#if !defined( ffconfigHASH_FUNCTION )
/* Only used if ffconfigHASH_CACHE is set to 1
Set to CRC8 or CRC16 to use 8-bit or 16-bit HASH values respectively. */
#define ffconfigHASH_FUNCTION CRC16
#endif
#if ffconfigHASH_FUNCTION == CRC16
#define ffconfigHASH_TABLE_SIZE 8192
#elif ffconfigHASH_FUNCTION == CRC8
#define ffconfigHASH_TABLE_SIZE 32
#else
#error Invalid Hashing function selected. CRC16 or CRC8. See your FreeRTOSFATConfig.h.
#endif
#endif /* ffconfigHASH_CACHE != 0 */
#if !defined( ffconfigMKDIR_RECURSIVE )
/* Set to 1 to add a parameter to ff_mkdir() that allows an entire directory
tree to be created in one go, rather than having to create one directory in
the tree at a time. For example mkdir( "/etc/settings/network", pdTRUE );.
Set to 0 to use the normal mkdir() semantics (without the additional
parameter). */
#define ffconfigMKDIR_RECURSIVE 0
#endif
#if !defined( ffconfigMALLOC )
/* Set to a function that will be used for all dynamic memory allocations.
Setting to pvPortMalloc() will use the same memory allocator as FreeRTOS. */
#define ffconfigMALLOC( size ) pvPortMalloc( size )
#endif
#if !defined( ffconfigFREE )
/* Set to a function that matches the above allocator defined with
ffconfigMALLOC. Setting to vPortFree() will use the same memory free
function as FreeRTOS. */
#define ffconfigFREE( ptr ) vPortFree( ptr )
#endif
#if !defined( ffconfig64_NUM_SUPPORT )
/* Set to 1 to calculate the free size and volume size as a 64-bit number.
Set to 0 to calculate these values as a 32-bit number. */
#define ffconfig64_NUM_SUPPORT 0
#endif
#if !defined( ffconfigMAX_PARTITIONS )
/* Defines the maximum number of partitions (and also logical partitions)
that can be recognised. */
#define ffconfigMAX_PARTITIONS 4
#endif
#if !defined( ffconfigMAX_FILE_SYS )
/* Defines how many drives can be combined in total. Should be set to at
least 2. */
#define ffconfigMAX_FILE_SYS 4
#endif
#if !defined( ffconfigDRIVER_BUSY_SLEEP_MS )
/* In case the low-level driver returns an error 'FF_ERR_DRIVER_BUSY',
the library will pause for a number of ms, defined in
ffconfigDRIVER_BUSY_SLEEP_MS before re-trying. */
#define ffconfigDRIVER_BUSY_SLEEP_MS 20
#endif
#if !defined( ffconfigFPRINTF_SUPPORT )
/* Set to 1 to include the ff_fprintf() function.
Set to 0 to exclude the ff_fprintf() function.
ff_fprintf() is quite a heavy function because it allocates RAM and
brings in a lot of string and variable argument handling code. If
ff_fprintf() is not being used then the code size can be reduced by setting
ffconfigFPRINTF_SUPPORT to 0. */
#define ffconfigFPRINTF_SUPPORT 0
#endif
#if !defined( ffconfigFPRINTF_BUFFER_LENGTH )
/* ff_fprintf() will allocate a buffer of this size in which it will create
its formatted string. The buffer will be freed before the function
exits. */
#define ffconfigFPRINTF_BUFFER_LENGTH 128
#endif
#if !defined( ffconfigDEBUG )
#define ffconfigDEBUG 0
#endif
#if !defined( ffconfigLONG_ERR_MSG )
#define ffconfigLONG_ERR_MSG 0
#endif
#if( ffconfigDEBUG != 0 )
#if !defined( ffconfigHAS_FUNCTION_TAB )
#define ffconfigHAS_FUNCTION_TAB 1
#endif
#endif
#if !defined( ffconfigINLINE_MEMORY_ACCESS )
/* Set to 1 to inline some internal memory access functions.
Set to 0 to not inline the memory access functions. */
#define ffconfigINLINE_MEMORY_ACCESS 0
#endif
#if !defined( ffconfigMIRROR_FATS_UMOUNT )
/*_RB_ not sure. */
#define ffconfigMIRROR_FATS_UMOUNT 0
#endif
#if !defined( ffconfigFAT_CHECK )
/* Officially the only criteria to determine the FAT type (12, 16, or 32
bits) is the total number of clusters:
if( ulNumberOfClusters < 4085 ) : Volume is FAT12
if( ulNumberOfClusters < 65525 ) : Volume is FAT16
if( ulNumberOfClusters >= 65525 ) : Volume is FAT32
Not every formatted device follows the above rule.
Set to 1 to perform additional checks over and above inspecting the
number of clusters on a disk to determine the FAT type.
Set to 0 to only look at the number of clusters on a disk to determine the
FAT type. */
#define ffconfigFAT_CHECK 0
#endif
#if !defined( ffconfigMAX_FILENAME )
/* Sets the maximum length for file names, including the path.
Note that the value of this define is directly related to the maximum stack
use of the +FAT library. In some API's, a character buffer of size
'ffconfigMAX_FILENAME' will be declared on stack. */
#define ffconfigMAX_FILENAME 129
#endif
#if !defined( ffconfigUSE_DELTREE )
/* By default, do not include the recursive function ff_deltree() as
recursion breaches the coding standard - USE WITH CARE. */
#define ffconfigUSE_DELTREE 0
#endif
#if !defined(ffconfigFILE_EXTEND_FLUSHES_BUFFERS)
/* When writing large files, the contents of the FAT entries will be flushed
after every call to FF_Write(). This flushing can be inhibited, by defining
ffconfigFILE_EXTEND_FLUSHES_BUFFERS as 0. */
#define ffconfigFILE_EXTEND_FLUSHES_BUFFERS 1
#endif
#if !defined( FF_PRINTF )
#define FF_PRINTF FF_PRINTF
static portINLINE void FF_PRINTF( const char *pcFormat, ... )
{
( void ) pcFormat;
}
#endif
#endif

View file

@ -0,0 +1,90 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
#ifndef FREERTOS_ERRNO_FAT
#define FREERTOS_ERRNO_FAT
/* The following definitions will be included in the core FreeRTOS code in
future versions of FreeRTOS - hence the 'pd' (ProjDefs) prefix - at which time
this file will be removed. */
/* The following errno values are used by FreeRTOS+ components, not FreeRTOS
itself. */
/* For future compatibility (see comment above), check the definitions have not
already been made. */
#ifndef pdFREERTOS_ERRNO_NONE
#define pdFREERTOS_ERRNO_NONE 0 /* No errors */
#define pdFREERTOS_ERRNO_ENOENT 2 /* No such file or directory */
#define pdFREERTOS_ERRNO_EIO 5 /* I/O error */
#define pdFREERTOS_ERRNO_ENXIO 6 /* No such device or address */
#define pdFREERTOS_ERRNO_EBADF 9 /* Bad file number */
#define pdFREERTOS_ERRNO_EAGAIN 11 /* No more processes */
#define pdFREERTOS_ERRNO_EWOULDBLOCK 11 /* Operation would block */
#define pdFREERTOS_ERRNO_ENOMEM 12 /* Not enough memory */
#define pdFREERTOS_ERRNO_EACCES 13 /* Permission denied */
#define pdFREERTOS_ERRNO_EFAULT 14 /* Bad address */
#define pdFREERTOS_ERRNO_EBUSY 16 /* Mount device busy */
#define pdFREERTOS_ERRNO_EEXIST 17 /* File exists */
#define pdFREERTOS_ERRNO_EXDEV 18 /* Cross-device link */
#define pdFREERTOS_ERRNO_ENODEV 19 /* No such device */
#define pdFREERTOS_ERRNO_ENOTDIR 20 /* Not a directory */
#define pdFREERTOS_ERRNO_EISDIR 21 /* Is a directory */
#define pdFREERTOS_ERRNO_EINVAL 22 /* Invalid argument */
#define pdFREERTOS_ERRNO_ENOSPC 28 /* No space left on device */
#define pdFREERTOS_ERRNO_ESPIPE 29 /* Illegal seek */
#define pdFREERTOS_ERRNO_EROFS 30 /* Read only file system */
#define pdFREERTOS_ERRNO_EUNATCH 42 /* Protocol driver not attached */
#define pdFREERTOS_ERRNO_EBADE 50 /* Invalid exchange */
#define pdFREERTOS_ERRNO_EFTYPE 79 /* Inappropriate file type or format */
#define pdFREERTOS_ERRNO_ENMFILE 89 /* No more files */
#define pdFREERTOS_ERRNO_ENOTEMPTY 90 /* Directory not empty */
#define pdFREERTOS_ERRNO_ENAMETOOLONG 91 /* File or path name too long */
#define pdFREERTOS_ERRNO_EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
#define pdFREERTOS_ERRNO_ENOBUFS 105 /* No buffer space available */
#define pdFREERTOS_ERRNO_ENOPROTOOPT 109 /* Protocol not available */
#define pdFREERTOS_ERRNO_EADDRINUSE 112 /* Address already in use */
#define pdFREERTOS_ERRNO_ETIMEDOUT 116 /* Connection timed out */
#define pdFREERTOS_ERRNO_EINPROGRESS 119 /* Connection already in progress */
#define pdFREERTOS_ERRNO_EALREADY 120 /* Socket already connected */
#define pdFREERTOS_ERRNO_EADDRNOTAVAIL 125 /* Address not available */
#define pdFREERTOS_ERRNO_EISCONN 127 /* Socket is already connected */
#define pdFREERTOS_ERRNO_ENOTCONN 128 /* Socket is not connected */
#define pdFREERTOS_ERRNO_ENOMEDIUM 135 /* No medium inserted */
#define pdFREERTOS_ERRNO_EILSEQ 138 /* An invalid UTF-16 sequence was encountered. */
#define pdFREERTOS_ERRNO_ECANCELED 140 /* Operation canceled. */
/* The following endian values are used by FreeRTOS+ components, not FreeRTOS
itself. */
#define pdFREERTOS_LITTLE_ENDIAN 0
#define pdFREERTOS_BIG_ENDIAN 1
#endif /* pdFREERTOS_ERRNO_NONE */
#endif /* FREERTOS_ERRNO_FAT */

View file

@ -0,0 +1,42 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
/**
* @file ff_crc.h
* @ingroup CRC
*
**/
#ifndef _FF_CRC_H_
#define _FF_CRC_H_
uint8_t FF_GetCRC8( uint8_t *pbyData, uint32_t stLength );
uint16_t FF_GetCRC16( uint8_t *pbyData, uint32_t stLength );
uint32_t FF_GetCRC32( uint8_t *pbyData, uint32_t stLength );
extern const uint32_t crc32_table[256];
#endif

View file

@ -0,0 +1,64 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
/**
* @file ff_devices.h
**/
#ifndef FF_DEVICES_H
#define FF_DEVICES_H
#ifndef PLUS_FAT_H
#error this header will be included from "plusfat.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define FF_DEV_NO_DEV 0
#define FF_DEV_CHAR_DEV 1
#define FF_DEV_BLOCK_DEV 2
BaseType_t xCheckDevicePath( const char *pcPath );
int FF_Device_Seek( FF_FILE *pxStream, long lOffset, int iWhence );
BaseType_t FF_Device_Open( const char *pcPath, FF_FILE * pxStream );
void FF_Device_Close( FF_FILE * pxStream );
size_t FF_Device_Read( void *pvBuf, size_t lSize, size_t lCount, FF_FILE * pxStream );
size_t FF_Device_Write( const void *pvBuf, size_t lSize, size_t lCount, FF_FILE * pxStream );
int FF_Device_GetDirEnt( const char *pcPath, FF_DirEnt_t *pxDirEnt );
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* FF_DEVICES_H */

View file

@ -0,0 +1,205 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
/**
* @file ff_dir.h
* @ingroup DIR
**/
#ifndef _FF_DIR_H_
#define _FF_DIR_H_
#ifndef PLUS_FAT_H
#error this header will be included from "plusfat.h"
#endif
#define FIND_FLAG_SHORTNAME_SET 0x01u
#define FIND_FLAG_SHORTNAME_CHECKED 0x02u
#define FIND_FLAG_SHORTNAME_FOUND 0x04u
#define FIND_FLAG_FITS_SHORT 0x08u
#define FIND_FLAG_SIZE_OK 0x10u
#define FIND_FLAG_CREATE_FLAG 0x20u
#define FIND_FLAG_FITS_SHORT_OK ( FIND_FLAG_FITS_SHORT | FIND_FLAG_SIZE_OK )
typedef struct
{
uint32_t ulChainLength;
uint32_t ulDirCluster;
uint32_t ulCurrentClusterLCN;
uint32_t ulCurrentClusterNum;
FF_Buffer_t *pxBuffer;
} FF_FetchContext_t;
typedef struct
{
uint32_t ulFileSize;
uint32_t ulObjectCluster;
/* Book Keeping. */
uint32_t ulCurrentCluster;
uint32_t ulAddrCurrentCluster;
uint32_t ulDirCluster;
uint16_t usCurrentItem;
/* End Book Keeping. */
#if( ffconfigTIME_SUPPORT != 0 )
FF_SystemTime_t xCreateTime; /* Date and Time Created. */
FF_SystemTime_t xModifiedTime; /* Date and Time Modified. */
FF_SystemTime_t xAccessedTime; /* Date of Last Access. */
#endif
#if( ffconfigFINDAPI_ALLOW_WILDCARDS != 0 )
#if( ffconfigUNICODE_UTF16_SUPPORT != 0 )
FF_T_WCHAR pcWildCard[ ffconfigMAX_FILENAME ];
#else
char pcWildCard[ ffconfigMAX_FILENAME ];
#endif
BaseType_t xInvertWildCard;
#endif
#if( ffconfigUNICODE_UTF16_SUPPORT != 0 )
FF_T_WCHAR pcFileName[ ffconfigMAX_FILENAME ];
#else
char pcFileName[ ffconfigMAX_FILENAME ];
#endif
#if( ffconfigLFN_SUPPORT != 0 ) && ( ffconfigINCLUDE_SHORT_NAME != 0 )
char pcShortName[ 13 ];
#endif
uint8_t ucAttrib;
#if( ffconfigDEV_SUPPORT != 0 )
uint8_t ucIsDeviceDir;
#endif
FF_FetchContext_t xFetchContext;
} FF_DirEnt_t;
/*
* Some public API's, i.e. they're used but ff_stdio.c
*/
#if( ffconfigUNICODE_UTF16_SUPPORT != 0 )
FF_Error_t FF_FindFirst( FF_IOManager_t *pxIOManager, FF_DirEnt_t *pxDirent, const FF_T_WCHAR *pcPath );
FF_Error_t FF_MkDir( FF_IOManager_t *pxIOManager, const FF_T_WCHAR *pcPath );
#else
FF_Error_t FF_FindFirst( FF_IOManager_t *pxIOManager, FF_DirEnt_t *pxDirent, const char *pcPath );
FF_Error_t FF_MkDir( FF_IOManager_t *pxIOManager, const char *pcPath );
#endif
FF_Error_t FF_FindNext( FF_IOManager_t *pxIOManager, FF_DirEnt_t *pxDirent );
static portINLINE void FF_RewindFind( FF_DirEnt_t *pxDirent )
{
pxDirent->usCurrentItem = 0;
}
/*
* Some API's internal to the +FAT library.
*/
FF_Error_t FF_GetEntry( FF_IOManager_t *pxIOManager, uint16_t usEntry, uint32_t ulDirCluster, FF_DirEnt_t *pxDirent );
FF_Error_t FF_PutEntry( FF_IOManager_t *pxIOManager, uint16_t usEntry, uint32_t ulDirCluster, FF_DirEnt_t *pxDirent, uint8_t *pucContents );
int8_t FF_FindEntry( FF_IOManager_t *pxIOManager, uint32_t ulDirCluster, int8_t *Name, FF_DirEnt_t *pxDirent, BaseType_t LFNs );
void FF_PopulateShortDirent( FF_IOManager_t *pxIOManager, FF_DirEnt_t *pxDirent, const uint8_t *pucEntryBuffer );
FF_Error_t FF_PopulateLongDirent( FF_IOManager_t *pxIOManager, FF_DirEnt_t *pxDirent, uint16_t usEntry, FF_FetchContext_t *pFetchContext );
FF_Error_t FF_InitEntryFetch( FF_IOManager_t *pxIOManager, uint32_t ulDirCluster, FF_FetchContext_t *pContext );
FF_Error_t FF_FetchEntryWithContext( FF_IOManager_t *pxIOManager, uint32_t ulEntry, FF_FetchContext_t *pContext, uint8_t *pEntryBuffer );
FF_Error_t FF_PushEntryWithContext( FF_IOManager_t *pxIOManager, uint32_t ulEntry, FF_FetchContext_t *pContext, uint8_t *pEntryBuffer );
FF_Error_t FF_CleanupEntryFetch( FF_IOManager_t *pxIOManager, FF_FetchContext_t *pContext );
int8_t FF_PushEntry( FF_IOManager_t *pxIOManager, uint32_t ulDirCluster, uint16_t usEntry, uint8_t *buffer, void *pParam );
static portINLINE BaseType_t FF_isEndOfDir( const uint8_t *pucEntryBuffer )
{
return pucEntryBuffer[ 0 ] == ( uint8_t ) 0;
}
static portINLINE BaseType_t FF_isDeleted( const uint8_t *pucEntryBuffer )
{
return pucEntryBuffer[ 0 ] == ( uint8_t ) FF_FAT_DELETED;
}
struct _FF_FIND_PARAMS
{
uint32_t ulDirCluster; /* The beginning cluster of this directory. */
int32_t lFreeEntry; /* The first free entry big enough to add the file. */
uint32_t ulFlags; /* See FIND_FLAG_xxx defines above. */
char pcEntryBuffer[ 32 ]; /* LFN converted to short name. */
uint8_t ucCaseAttrib;
uint8_t ucFirstTilde;
};
typedef struct _FF_FIND_PARAMS FF_FindParams_t;
#if( ffconfigUNICODE_UTF16_SUPPORT != 0 )
uint32_t FF_CreateFile( FF_IOManager_t *pxIOManager, FF_FindParams_t *findParams, FF_T_WCHAR *FileName,
FF_DirEnt_t *pxDirent, FF_Error_t *pError );
uint32_t FF_FindEntryInDir( FF_IOManager_t *pxIOManager, FF_FindParams_t *findParams, const FF_T_WCHAR *name,
uint8_t pa_Attrib, FF_DirEnt_t *pxDirent, FF_Error_t *pError );
uint32_t FF_FindDir( FF_IOManager_t *pxIOManager, const FF_T_WCHAR *pcPath, uint16_t pathLen, FF_Error_t *pError );
void FF_CreateShortName( FF_FindParams_t *pxFindParams, const FF_T_WCHAR *pcLongName );
#else
uint32_t FF_CreateFile( FF_IOManager_t *pxIOManager, FF_FindParams_t *findParams, char *FileName,
FF_DirEnt_t *pxDirent, FF_Error_t *pError );
uint32_t FF_FindEntryInDir( FF_IOManager_t *pxIOManager, FF_FindParams_t *findParams, const char *name,
uint8_t pa_Attrib, FF_DirEnt_t *pxDirent, FF_Error_t *pError );
uint32_t FF_FindDir( FF_IOManager_t *pxIOManager, const char *pcPath, uint16_t pathLen, FF_Error_t *pError );
void FF_CreateShortName( FF_FindParams_t *pxFindParams, const char *pcLongName );
#endif
int32_t FF_FindShortName( FF_IOManager_t *pxIOManager, FF_FindParams_t *findParams );
FF_Error_t FF_CreateDirent( FF_IOManager_t *pxIOManager, FF_FindParams_t *findParams, FF_DirEnt_t *pxDirent );
FF_Error_t FF_ExtendDirectory( FF_IOManager_t *pxIOManager, uint32_t ulDirCluster );
FF_Error_t FF_RmLFNs( FF_IOManager_t *pxIOManager, uint16_t usDirEntry, FF_FetchContext_t *pContext );
#if( ffconfigHASH_CACHE != 0 )
BaseType_t FF_CheckDirentHash( FF_IOManager_t *pxIOManager, uint32_t ulDirCluster, uint32_t ulHash );
BaseType_t FF_DirHashed( FF_IOManager_t *pxIOManager, uint32_t ulDirCluster );
void FF_AddDirentHash( FF_IOManager_t *pxIOManager, uint32_t ulDirCluster, uint32_t ulHash );
FF_Error_t FF_HashDir( FF_IOManager_t *pxIOManager, uint32_t ulDirCluster );
void FF_UnHashDir( FF_IOManager_t *pxIOManager, uint32_t ulDirCluster );
#endif
struct SBuffStats {
unsigned sectorMatch;
unsigned sectorMiss;
unsigned bufCounts;
unsigned bufCalls;
};
extern struct SBuffStats buffStats;
#endif

View file

@ -0,0 +1,260 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
#ifndef _FF_ERROR_H_
#define _FF_ERROR_H_
/**
* @file ff_error.h
* @ingroup ERROR
**/
/**
* Error codes are 32-bit numbers, and consist of three items:
* 1Bit 7Bits 8Bits 16Bits
* . ........ ........ ........ ........
* [ErrFlag][ModuleID][FunctionID][-- ERROR CODE --]
*
* Error Codes should always have the ErrFlag set, this is the reason why all module
* codes include it.
*
* When returning an error simply return the defined Error Code, OR'd with the function
* name (capitalised) in which the error has occurred.
*
* When receiving an Error code from another layer, do not modify the code, as this will
* prevent the error code from containing the origin of the error, simply pass it to the
* next layer.
*
* Some API's have been defined to provide, useful and meaningful Error messages to the
* the 'userspace' application layer.
*
**/
#define FF_MODULE_SHIFT 24
#define FF_FUNCTION_SHIFT 16
#define FF_GETERROR( x ) ( ( ( unsigned ) x ) & 0xFFFF )
#define FF_GETMODULE( x ) ( ( ( ( unsigned ) x ) >> FF_MODULE_SHIFT ) & 0x7F )
#define FF_GETFUNCTION( x ) ( ( ( ( unsigned ) x ) >> FF_FUNCTION_SHIFT ) & 0xFF )
#define FF_GETMOD_FUNC( x ) ( ( ( ( unsigned ) x ) >> FF_FUNCTION_SHIFT ) & 0xFFFF )
#define FF_ERRFLAG 0x80000000
#define FF_isERR( x ) ( ( ( x ) & FF_ERRFLAG ) != 0 )
/*----- FreeRTOS+FAT Module Identifiers */
#define FF_MODULE_IOMAN ( ( 1 << FF_MODULE_SHIFT ) | FF_ERRFLAG )
#define FF_MODULE_DIR ( ( 2 << FF_MODULE_SHIFT ) | FF_ERRFLAG )
#define FF_MODULE_FILE ( ( 3 << FF_MODULE_SHIFT ) | FF_ERRFLAG )
#define FF_MODULE_FAT ( ( 4 << FF_MODULE_SHIFT ) | FF_ERRFLAG )
#define FF_MODULE_CRC ( ( 5 << FF_MODULE_SHIFT ) | FF_ERRFLAG )
#define FF_MODULE_FORMAT ( ( 6 << FF_MODULE_SHIFT ) | FF_ERRFLAG )
#define FF_MODULE_MEMORY ( ( 7 << FF_MODULE_SHIFT ) | FF_ERRFLAG )
#define FF_MODULE_STRING ( ( 8 << FF_MODULE_SHIFT ) | FF_ERRFLAG )
#define FF_MODULE_LOCKING ( ( 9 << FF_MODULE_SHIFT ) | FF_ERRFLAG )
#define FF_MODULE_TIME ( ( 10 << FF_MODULE_SHIFT ) | FF_ERRFLAG )
#define FF_MODULE_DRIVER ( ( 11 << FF_MODULE_SHIFT ) | FF_ERRFLAG )
#define FF_MODULE_STDIO ( ( 12 << FF_MODULE_SHIFT ) | FF_ERRFLAG )
/*----- FreeRTOS+FAT Function Identifiers (In Modular Order) */
/*----- FF_IOManager_t - The FreeRTOS+FAT I/O Manager. */
#define FF_CREATEIOMAN ( ( 1 << FF_FUNCTION_SHIFT ) | FF_MODULE_IOMAN )
#define FF_DESTROYIOMAN ( ( 2 << FF_FUNCTION_SHIFT ) | FF_MODULE_IOMAN )
#define FF_MOUNT ( ( 3 << FF_FUNCTION_SHIFT ) | FF_MODULE_IOMAN )
#define FF_UNMOUNT ( ( 4 << FF_FUNCTION_SHIFT ) | FF_MODULE_IOMAN )
#define FF_FLUSHCACHE ( ( 5 << FF_FUNCTION_SHIFT ) | FF_MODULE_IOMAN )
#define FF_GETPARTITIONBLOCKSIZE ( ( 6 << FF_FUNCTION_SHIFT ) | FF_MODULE_IOMAN )
#define FF_BLOCKREAD ( ( 7 << FF_FUNCTION_SHIFT ) | FF_MODULE_IOMAN )
#define FF_BLOCKWRITE ( ( 8 << FF_FUNCTION_SHIFT ) | FF_MODULE_IOMAN )
#define FF_DETERMINEFATTYPE ( ( 9 << FF_FUNCTION_SHIFT ) | FF_MODULE_IOMAN )
#define FF_GETEFIPARTITIONENTRY ( ( 10 << FF_FUNCTION_SHIFT ) | FF_MODULE_IOMAN )
#define FF_USERDRIVER ( ( 11 << FF_FUNCTION_SHIFT ) | FF_MODULE_IOMAN )
#define FF_DECREASEFREECLUSTERS ( ( 12 << FF_FUNCTION_SHIFT ) | FF_MODULE_IOMAN )
#define FF_INCREASEFREECLUSTERS ( ( 13 << FF_FUNCTION_SHIFT ) | FF_MODULE_IOMAN )
#define FF_PARTITIONSEARCH ( ( 14 << FF_FUNCTION_SHIFT ) | FF_MODULE_IOMAN )
#define FF_PARSEEXTENDED ( ( 15 << FF_FUNCTION_SHIFT ) | FF_MODULE_IOMAN )
/*----- FreeRTOS+FAT Return codes for user Rd/Wr routines */
#define FF_ERR_DRIVER_NOMEDIUM ( FF_ERR_IOMAN_DRIVER_NOMEDIUM | FF_USERDRIVER | FF_MODULE_DRIVER )
#define FF_ERR_DRIVER_BUSY ( FF_ERR_IOMAN_DRIVER_BUSY | FF_USERDRIVER | FF_MODULE_DRIVER )
#define FF_ERR_DRIVER_FATAL_ERROR ( FF_ERR_IOMAN_DRIVER_FATAL_ERROR | FF_USERDRIVER | FF_MODULE_DRIVER )
/*----- FF_DIR - The FreeRTOS+FAT directory handling routines. */
#define FF_FETCHENTRYWITHCONTEXT ( ( 1 << FF_FUNCTION_SHIFT ) | FF_MODULE_DIR )
#define FF_PUSHENTRYWITHCONTEXT ( ( 2 << FF_FUNCTION_SHIFT ) | FF_MODULE_DIR )
#define FF_GETENTRY ( ( 3 << FF_FUNCTION_SHIFT ) | FF_MODULE_DIR )
#define FF_FINDFIRST ( ( 4 << FF_FUNCTION_SHIFT ) | FF_MODULE_DIR )
#define FF_FINDNEXT ( ( 5 << FF_FUNCTION_SHIFT ) | FF_MODULE_DIR )
#define FF_REWINDFIND ( ( 6 << FF_FUNCTION_SHIFT ) | FF_MODULE_DIR )
#define FF_FINDFREEDIRENT ( ( 7 << FF_FUNCTION_SHIFT ) | FF_MODULE_DIR )
#define FF_PUTENTRY ( ( 8 << FF_FUNCTION_SHIFT ) | FF_MODULE_DIR )
#define FF_CREATESHORTNAME ( ( 9 << FF_FUNCTION_SHIFT ) | FF_MODULE_DIR )
#define FF_CREATELFNS ( ( 10 << FF_FUNCTION_SHIFT ) | FF_MODULE_DIR )
#define FF_EXTENDDIRECTORY ( ( 11 << FF_FUNCTION_SHIFT ) | FF_MODULE_DIR )
#define FF_MKDIR ( ( 12 << FF_FUNCTION_SHIFT ) | FF_MODULE_DIR )
#define FF_TRAVERSE ( ( 13 << FF_FUNCTION_SHIFT ) | FF_MODULE_DIR )
#define FF_FINDDIR ( ( 14 << FF_FUNCTION_SHIFT ) | FF_MODULE_DIR )
/*----- FF_FILE - The FreeRTOS+FAT file handling routines. */
#define FF_GETMODEBITS ( ( 1 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
#define FF_OPEN ( ( 2 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
#define FF_ISDIREMPTY ( ( 3 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
#define FF_RMDIR ( ( 4 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
#define FF_RMFILE ( ( 5 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
#define FF_MOVE ( ( 6 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
#define FF_ISEOF ( ( 7 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
#define FF_GETSEQUENTIALCLUSTERS ( ( 8 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
#define FF_READCLUSTERS ( ( 9 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
#define FF_EXTENDFILE ( ( 10 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
#define FF_WRITECLUSTERS ( ( 11 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
#define FF_READ ( ( 12 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
#define FF_GETC ( ( 13 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
#define FF_GETLINE ( ( 14 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
#define FF_TELL ( ( 15 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
#define FF_WRITE ( ( 16 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
#define FF_PUTC ( ( 17 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
#define FF_SEEK ( ( 18 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
#define FF_INVALIDATE ( ( 19 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
#define FF_CHECKVALID ( ( 20 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
#define FF_CLOSE ( ( 21 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
#define FF_SETTIME ( ( 22 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
#define FF_BYTESLEFT ( ( 23 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
#define FF_SETFILETIME ( ( 24 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
#define FF_INITBUF ( ( 25 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
#define FF_SETEOF ( ( 26 << FF_FUNCTION_SHIFT ) | FF_MODULE_FILE )
/*----- FF_FAT - The FreeRTOS+FAT FAT handling routines. */
#define FF_GETFATENTRY ( ( 1 << FF_FUNCTION_SHIFT ) | FF_MODULE_FAT )
#define FF_CLEARCLUSTER ( ( 2 << FF_FUNCTION_SHIFT ) | FF_MODULE_FAT )
#define FF_PUTFATENTRY ( ( 3 << FF_FUNCTION_SHIFT ) | FF_MODULE_FAT )
#define FF_FINDFREECLUSTER ( ( 4 << FF_FUNCTION_SHIFT ) | FF_MODULE_FAT )
#define FF_COUNTFREECLUSTERS ( ( 5 << FF_FUNCTION_SHIFT ) | FF_MODULE_FAT )
/*----- FF_FORMAT - The FreeRTOS+FAT format routine */
#define FF_FORMATPARTITION ( ( 1 << FF_FUNCTION_SHIFT ) | FF_MODULE_FORMAT )
/*----- FF_UNICODE - The FreeRTOS+FAT unicode routines. */
#define FF_UTF8CTOUTF16C ( ( 1 << FF_FUNCTION_SHIFT ) | FF_MODULE_STRING )
#define FF_UTF16CTOUTF8C ( ( 2 << FF_FUNCTION_SHIFT ) | FF_MODULE_STRING )
#define FF_UTF32CTOUTF16C ( ( 3 << FF_FUNCTION_SHIFT ) | FF_MODULE_STRING )
#define FF_UTF16CTOUTF32C ( ( 4 << FF_FUNCTION_SHIFT ) | FF_MODULE_STRING )
/*----- FF_STDIO - The stdio-interface to FreeRTOS+FAT. */
#define FF_CHMOD ( ( 1 << FF_FUNCTION_SHIFT ) | FF_MODULE_STDIO )
#define FF_STAT_FUNC ( ( 2 << FF_FUNCTION_SHIFT ) | FF_MODULE_STDIO )
/* FreeRTOS+FAT defines different Error-Code spaces for each module. This ensures
that all error codes remain unique, and their meaning can be quickly identified.
*/
/* Global Error Codes */
#define FF_ERR_NONE 0 /* No Error */
/*#define FF_ERR_GENERIC 1*/ /* BAD NEVER USE THIS! -- Therefore commented out. */
#define FF_ERR_NULL_POINTER 2 /* Parameter was NULL. */
#define FF_ERR_NOT_ENOUGH_MEMORY 3 /* malloc() failed! - Could not allocate handle memory. */
#define FF_ERR_DEVICE_DRIVER_FAILED 4 /* The Block Device driver reported a FATAL error, cannot continue. */
/* User return codes for Rd/Wr functions: */
#define FF_ERR_IOMAN_DRIVER_NOMEDIUM 8
#define FF_ERR_IOMAN_DRIVER_BUSY 9
#define FF_ERR_IOMAN_DRIVER_FATAL_ERROR 10
/* IOMAN Error Codes */
#define FF_ERR_IOMAN_BAD_BLKSIZE 11 /* The provided blocksize was not a multiple of 512. */
#define FF_ERR_IOMAN_BAD_MEMSIZE 12 /* The memory size was not a multiple of the blocksize. */
#define FF_ERR_IOMAN_DEV_ALREADY_REGD 13 /* Device was already registered. Use FF_UnRegister() to re-use this IOMAN with another device. */
#define FF_ERR_IOMAN_NO_MOUNTABLE_PARTITION 14 /* A mountable partition could not be found on the device. */
#define FF_ERR_IOMAN_INVALID_FORMAT 15
#define FF_ERR_IOMAN_INVALID_PARTITION_NUM 16 /* The partition number provided was out of range. */
#define FF_ERR_IOMAN_NOT_FAT_FORMATTED 17 /* The partition did not look like a FAT partition. */
#define FF_ERR_IOMAN_DEV_INVALID_BLKSIZE 18 /* IOMAN object BlkSize is not compatible with the blocksize of this device driver. */
#define FF_ERR_IOMAN_PARTITION_MOUNTED 19 /* Device is in use by an actively mounted partition. Unmount the partition first. */
#define FF_ERR_IOMAN_ACTIVE_HANDLES 20 /* The partition cannot be unmounted until all active file handles are closed. (There may also be active handles on the cache). */
#define FF_ERR_IOMAN_GPT_HEADER_CORRUPT 21 /* The GPT partition table appears to be corrupt, refusing to mount. */
#define FF_ERR_IOMAN_NOT_ENOUGH_FREE_SPACE 22
#define FF_ERR_IOMAN_OUT_OF_BOUNDS_READ 23
#define FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE 24
/* File Error Codes 30 + */
#define FF_ERR_FILE_ALREADY_OPEN 30 /* File is in use. */
#define FF_ERR_FILE_NOT_FOUND 31 /* File was not found. */
#define FF_ERR_FILE_OBJECT_IS_A_DIR 32 /* Tried to FF_Open() a Directory. */
#define FF_ERR_FILE_IS_READ_ONLY 33 /* Tried to FF_Open() a file marked read only. */
#define FF_ERR_FILE_INVALID_PATH 34 /* The path of the file was not found. */
#define FF_ERR_FILE_NOT_OPENED_IN_WRITE_MODE 35
#define FF_ERR_FILE_NOT_OPENED_IN_READ_MODE 36
#define FF_ERR_FILE_EXTEND_FAILED 37 /* Could not extend the file. */
#define FF_ERR_FILE_DESTINATION_EXISTS 38
#define FF_ERR_FILE_SOURCE_NOT_FOUND 39
#define FF_ERR_FILE_DIR_NOT_FOUND 40
#define FF_ERR_FILE_COULD_NOT_CREATE_DIRENT 41
#define FF_ERR_FILE_BAD_HANDLE 42 /* A file handle was invalid */
#define FF_ERR_FILE_MEDIA_REMOVED 43 /* File handle got invalid because media was removed */
#define FF_ERR_FILE_READ_ZERO 44 /* Used internally. */
#define FF_ERR_FILE_SEEK_INVALID_ORIGIN 45 /* Seeking beyond end of file. */
#define FF_ERR_FILE_SEEK_INVALID_POSITION 46 /* Bad value for the 'whence' parameter. */
/* Directory Error Codes 50 + */
#define FF_ERR_DIR_OBJECT_EXISTS 50 /* A file or folder of the same name already exists in the current directory. */
#define FF_ERR_DIR_DIRECTORY_FULL 51 /* No more items could be added to the directory. */
#define FF_ERR_DIR_END_OF_DIR 52 /*/ */
#define FF_ERR_DIR_NOT_EMPTY 53 /* Cannot delete a directory that contains files or folders. */
#define FF_ERR_DIR_INVALID_PATH 54 /* Could not find the directory specified by the path. */
#define FF_ERR_DIR_INVALID_PARAMETER 55 /* Could not find the directory specified by the path. */
#define FF_ERR_DIR_CANT_EXTEND_ROOT_DIR 56 /* Can't extend the root dir. */
#define FF_ERR_DIR_EXTEND_FAILED 57 /* Not enough space to extend the directory. */
#define FF_ERR_DIR_NAME_TOO_LONG 58 /* Name exceeds the number of allowed characters for a filename. */
/* Fat Error Codes 70 + */
#define FF_ERR_FAT_NO_FREE_CLUSTERS 70 /* No more free space is available on the disk. */
/* UNICODE Error Codes 100 + */
#define FF_ERR_UNICODE_INVALID_CODE 100 /* An invalid Unicode character was provided! */
#define FF_ERR_UNICODE_DEST_TOO_SMALL 101 /* Not enough space in the UTF-16 buffer to encode the entire sequence as UTF-16. */
#define FF_ERR_UNICODE_INVALID_SEQUENCE 102 /* An invalid UTF-16 sequence was encountered. */
#define FF_ERR_UNICODE_CONVERSION_EXCEEDED 103 /* Filename exceeds MAX long-filename length when converted to UTF-16. */
typedef int32_t FF_Error_t;
#if( ffconfigDEBUG != 0 )
const char *FF_GetErrMessage( FF_Error_t iErrorCode );
const char *FF_GetErrModule( FF_Error_t iErrorCode );
const char *FF_GetErrFunction( FF_Error_t iErrorCode );
const char *FF_GetErrDescription( FF_Error_t iErrorCode, char *pcBuffer, int iMaxLength ); /* Get the complete description */
#else /* ffconfigDEBUG */
#define FF_GetErrMessage( X ) "" /* A special MACRO in case FF_GetErrMessage() isn't gated with ffconfigDEBUG */
#define FF_GetErrModule( X ) ""
#define FF_GetErrFunction( X ) ""
static portINLINE const char *FF_GetErrDescription( FF_Error_t iErrorCode, char *pcBuffer, int iMaxLength )
{
( void ) iErrorCode;
( void ) iMaxLength;
strcpy( pcBuffer, "unknown" );
return pcBuffer;
}
#endif /* Function call is safely replaced with a NULL string. */
#endif /* INCLUDE GUARD END */

View file

@ -0,0 +1,128 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
/**
* @file ff_fat.h
* @ingroup FAT
**/
#ifndef _FF_FAT_H_
#define _FF_FAT_H_
#ifndef PLUS_FAT_H
#error this header will be included from "plusfat.h"
#endif
/*---------- ERROR CODES */
/*---------- PROTOTYPES */
/* HT statistics Will be taken away after testing: */
#if( ffconfigFAT_USES_STAT != 0 )
struct SFatStat
{
unsigned initCount;
unsigned clearCount;
unsigned getCount[2]; /* Index 0 for READ counts, index 1 for WRITE counts. */
unsigned reuseCount[2];
unsigned missCount[2];
};
extern struct SFatStat fatStat;
#endif
#if( ffconfigWRITE_BOTH_FATS != 0 )
#define ffconfigBUF_STORE_COUNT 2
#else
#define ffconfigBUF_STORE_COUNT 1
#endif
typedef struct _FatBuffers
{
FF_Buffer_t *pxBuffers[ffconfigBUF_STORE_COUNT];
uint8_t ucMode; /* FF_MODE_READ or WRITE. */
} FF_FATBuffers_t;
uint32_t FF_getClusterPosition( FF_IOManager_t *pxIOManager, uint32_t ulEntry, uint32_t ulEntrySize );
uint32_t FF_getClusterChainNumber( FF_IOManager_t *pxIOManager, uint32_t ulEntry, uint32_t ulEntrySize );
uint32_t FF_getMajorBlockNumber( FF_IOManager_t *pxIOManager, uint32_t ulEntry, uint32_t ulEntrySize );
uint32_t FF_getMinorBlockNumber( FF_IOManager_t *pxIOManager, uint32_t ulEntry, uint32_t ulEntrySize );
uint32_t FF_getMinorBlockEntry( FF_IOManager_t *pxIOManager, uint32_t ulEntry, uint32_t ulEntrySize );
/* A partition may define a block size larger than 512 bytes (at offset 0x0B of the PBR).
This function translates a block address to an address based on 'pxIOManager->usBlkSize',
which is usually 512 bytes.
*/
static portINLINE uint32_t FF_getRealLBA( FF_IOManager_t *pxIOManager, uint32_t LBA )
{
return LBA * pxIOManager->xPartition.ucBlkFactor;
}
uint32_t FF_Cluster2LBA( FF_IOManager_t *pxIOManager, uint32_t ulCluster );
uint32_t FF_LBA2Cluster( FF_IOManager_t *pxIOManager, uint32_t ulAddress );
uint32_t FF_getFATEntry( FF_IOManager_t *pxIOManager, uint32_t ulCluster, FF_Error_t *pxError, FF_FATBuffers_t *pxFATBuffers );
FF_Error_t FF_putFATEntry( FF_IOManager_t *pxIOManager, uint32_t ulCluster, uint32_t ulValue, FF_FATBuffers_t *pxFATBuffers );
BaseType_t FF_isEndOfChain( FF_IOManager_t *pxIOManager, uint32_t ulFatEntry );
uint32_t FF_FindFreeCluster( FF_IOManager_t *pxIOManager, FF_Error_t *pxError, BaseType_t aDoClaim );
uint32_t FF_ExtendClusterChain( FF_IOManager_t *pxIOManager, uint32_t ulStartCluster, uint32_t ulCount );
FF_Error_t FF_UnlinkClusterChain( FF_IOManager_t *pxIOManager, uint32_t ulStartCluster, BaseType_t xDoTruncate );
uint32_t FF_TraverseFAT( FF_IOManager_t *pxIOManager, uint32_t ulStart, uint32_t ulCount, FF_Error_t *pxError );
uint32_t FF_CreateClusterChain( FF_IOManager_t *pxIOManager, FF_Error_t *pxError );
uint32_t FF_GetChainLength( FF_IOManager_t *pxIOManager, uint32_t pa_nStartCluster, uint32_t *piEndOfChain, FF_Error_t *pxError );
uint32_t FF_FindEndOfChain( FF_IOManager_t *pxIOManager, uint32_t Start, FF_Error_t *pxError );
FF_Error_t FF_ClearCluster( FF_IOManager_t *pxIOManager, uint32_t ulCluster );
#if( ffconfig64_NUM_SUPPORT != 0 )
uint64_t FF_GetFreeSize( FF_IOManager_t *pxIOManager, FF_Error_t *pxError );
#else
uint32_t FF_GetFreeSize( FF_IOManager_t *pxIOManager, FF_Error_t *pxError );
#endif
/* WARNING: If this prototype changes, it must be updated in ff_ioman.c also! */
uint32_t FF_CountFreeClusters( FF_IOManager_t *pxIOManager, FF_Error_t *pxError );
FF_Error_t FF_ReleaseFATBuffers( FF_IOManager_t *pxIOManager, FF_FATBuffers_t *pxFATBuffers );
static portINLINE void FF_InitFATBuffers( FF_FATBuffers_t *pxFATBuffers, uint8_t ucMode )
{
pxFATBuffers->pxBuffers[ 0 ] = NULL;
#if ffconfigBUF_STORE_COUNT > 1
pxFATBuffers->pxBuffers[ 1 ] = NULL;
#endif
#if ffconfigBUF_STORE_COUNT > 2
#error Please check this code, maybe it is time to use memset
#endif
pxFATBuffers->ucMode = ucMode; /* FF_MODE_READ/WRITE */
#if ffconfigFAT_USES_STAT
{
fatStat.initCount++;
}
#endif
}
#endif

View file

@ -0,0 +1,109 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
#ifndef _FF_FATDEF_H_
#define _FF_FATDEF_H_
/*
This file defines offsets to various data for the FAT specification.
*/
/* MBR / PBR Offsets. */
#define FF_FAT_BYTES_PER_SECTOR 0x00B
#define FF_FAT_SECTORS_PER_CLUS 0x00D
#define FF_FAT_RESERVED_SECTORS 0x00E
#define FF_FAT_NUMBER_OF_FATS 0x010
#define FF_FAT_ROOT_ENTRY_COUNT 0x011
#define FF_FAT_16_TOTAL_SECTORS 0x013
#define FF_FAT_MEDIA_TYPE 0x015
#define FF_FAT_32_TOTAL_SECTORS 0x020
#define FF_FAT_16_SECTORS_PER_FAT 0x016
#define FF_FAT_32_SECTORS_PER_FAT 0x024
#define FF_FAT_ROOT_DIR_CLUSTER 0x02C
#define FF_FAT_EXT_BOOT_SIGNATURE 0x042
#define FF_FAT_16_VOL_LABEL 0x02B
#define FF_FAT_32_VOL_LABEL 0x047
#define FF_FAT_PTBL 0x1BE
#define FF_FAT_PTBL_LBA 0x008
#define FF_FAT_PTBL_SECT_COUNT 0x00C
#define FF_FAT_PTBL_ACTIVE 0x000
#define FF_FAT_PTBL_ID 0x004
#define FF_DOS_EXT_PART 0x05
#define FF_LINUX_EXT_PART 0x85
#define FF_WIN98_EXT_PART 0x0f
#define FF_FAT_MBR_SIGNATURE 0x1FE
#define FF_FAT_DELETED 0xE5
/* Directory Entry Offsets. */
#define FF_FAT_DIRENT_SHORTNAME 0x000
#define FF_FAT_DIRENT_ATTRIB 0x00B
#define FF_FAT_DIRENT_CREATE_TIME 0x00E /* Creation Time. */
#define FF_FAT_DIRENT_CREATE_DATE 0x010 /* Creation Date. */
#define FF_FAT_DIRENT_LASTACC_DATE 0x012 /* Date of Last Access. */
#define FF_FAT_DIRENT_CLUS_HIGH 0x014
#define FF_FAT_DIRENT_LASTMOD_TIME 0x016 /* Time of Last modification. */
#define FF_FAT_DIRENT_LASTMOD_DATE 0x018 /* Date of Last modification. */
#define FF_FAT_DIRENT_CLUS_LOW 0x01A
#define FF_FAT_DIRENT_FILESIZE 0x01C
#define FF_FAT_LFN_ORD 0x000
#define FF_FAT_LFN_NAME_1 0x001
#define FF_FAT_LFN_CHECKSUM 0x00D
#define FF_FAT_LFN_NAME_2 0x00E
#define FF_FAT_LFN_NAME_3 0x01C
/* Dirent Attributes. */
#define FF_FAT_ATTR_READONLY 0x01
#define FF_FAT_ATTR_HIDDEN 0x02
#define FF_FAT_ATTR_SYSTEM 0x04
#define FF_FAT_ATTR_VOLID 0x08
#define FF_FAT_ATTR_DIR 0x10
#define FF_FAT_ATTR_ARCHIVE 0x20
#define FF_FAT_ATTR_LFN 0x0F
/**
* -- Hein_Tibosch additions for mixed case in shortnames --
*
* Specifically, bit 4 means lowercase extension and bit 3 lowercase basename,
* which allows for combinations such as "example.TXT" or "HELLO.txt" but not "Mixed.txt"
*/
#define FF_FAT_CASE_OFFS 0x0C /* After NT/XP : 2 case bits. */
#define FF_FAT_CASE_ATTR_BASE 0x08
#define FF_FAT_CASE_ATTR_EXT 0x10
#if( ffconfigLFN_SUPPORT != 0 ) && ( ffconfigINCLUDE_SHORT_NAME != 0 )
#define FF_FAT_ATTR_IS_LFN 0x40 /* artificial attribute, for debugging only. */
#endif
#endif

View file

@ -0,0 +1,163 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
/**
* @file ff_file.h
* @ingroup FILEIO
**/
#ifndef _FF_FILE_H_
#define _FF_FILE_H_
#ifndef PLUS_FAT_H
#error this header will be included from "plusfat.h"
#endif
#define FF_SEEK_SET 0
#define FF_SEEK_CUR 1
#define FF_SEEK_END 2
#if( ffconfigOPTIMISE_UNALIGNED_ACCESS != 0 )
#define FF_BUFSTATE_INVALID 0x00 /* Data in file handle buffer is invalid. */
#define FF_BUFSTATE_VALID 0x01 /* Valid data in pBuf (Something has been read into it). */
#define FF_BUFSTATE_WRITTEN 0x02 /* Data was written into pBuf, this must be saved when leaving sector. */
#endif
#if( ffconfigDEV_SUPPORT != 0 )
struct xDEV_NODE
{
uint8_t
ucIsDevice;
};
#endif
typedef struct _FF_FILE
{
FF_IOManager_t *pxIOManager; /* Ioman Pointer! */
uint32_t ulFileSize; /* File's Size. */
uint32_t ulObjectCluster; /* File's Start Cluster. */
uint32_t ulChainLength; /* Total Length of the File's cluster chain. */
uint32_t ulCurrentCluster; /* Prevents FAT Thrashing. */
uint32_t ulAddrCurrentCluster; /* Address of the current cluster. */
uint32_t ulEndOfChain; /* Address of the last cluster in the chain. */
uint32_t ulFilePointer; /* Current Position Pointer. */
uint32_t ulDirCluster; /* Cluster Number that the Dirent is in. */
uint32_t ulValidFlags; /* Handle validation flags. */
#if( ffconfigOPTIMISE_UNALIGNED_ACCESS != 0 )
uint8_t *pucBuffer; /* A buffer for providing fast unaligned access. */
uint8_t ucState; /* State information about the buffer. */
#endif
uint8_t ucMode; /* Mode that File Was opened in. */
uint16_t usDirEntry; /* Dirent Entry Number describing this file. */
#if( ffconfigDEV_SUPPORT != 0 )
struct SFileCache *pxDevNode;
#endif
struct _FF_FILE *pxNext; /* Pointer to the next file object in the linked list. */
} FF_FILE;
#define FF_VALID_FLAG_INVALID 0x00000001
#define FF_VALID_FLAG_DELETED 0x00000002
/*---------- PROTOTYPES */
/* PUBLIC (Interfaces): */
#if( ffconfigUNICODE_UTF16_SUPPORT != 0 )
FF_FILE *FF_Open( FF_IOManager_t *pxIOManager, const FF_T_WCHAR *path, uint8_t Mode, FF_Error_t *pError );
BaseType_t FF_isDirEmpty( FF_IOManager_t *pxIOManager, const FF_T_WCHAR *Path );
FF_Error_t FF_RmFile( FF_IOManager_t *pxIOManager, const FF_T_WCHAR *path );
FF_Error_t FF_RmDir( FF_IOManager_t *pxIOManager, const FF_T_WCHAR *path );
FF_Error_t FF_Move( FF_IOManager_t *pxIOManager, const FF_T_WCHAR *szSourceFile, const FF_T_WCHAR *szDestinationFile,
BaseType_t bDeleteIfExists );
#else /* ffconfigUNICODE_UTF16_SUPPORT */
FF_FILE *FF_Open( FF_IOManager_t *pxIOManager, const char *path, uint8_t Mode, FF_Error_t *pError );
BaseType_t FF_isDirEmpty( FF_IOManager_t *pxIOManager, const char *Path );
FF_Error_t FF_RmFile( FF_IOManager_t *pxIOManager, const char *path );
FF_Error_t FF_RmDir( FF_IOManager_t *pxIOManager, const char *path );
FF_Error_t FF_Move( FF_IOManager_t *pxIOManager, const char *szSourceFile, const char *szDestinationFile,
BaseType_t bDeleteIfExists );
#endif /* ffconfigUNICODE_UTF16_SUPPORT */
#if( ffconfigTIME_SUPPORT != 0 )
enum {
ETimeCreate = 1,
ETimeMod = 2,
ETimeAccess = 4,
ETimeAll = 7
};
FF_Error_t FF_SetFileTime( FF_FILE *pFile, FF_SystemTime_t *pxTime, UBaseType_t uxWhat );
#if( ffconfigUNICODE_UTF16_SUPPORT != 0 )
FF_Error_t FF_SetTime( FF_IOManager_t *pxIOManager, const FF_T_WCHAR *path, FF_SystemTime_t *pxTime, UBaseType_t uxWhat );
#else
FF_Error_t FF_SetTime( FF_IOManager_t *pxIOManager, const char *path, FF_SystemTime_t *pxTime, UBaseType_t uxWhat );
#endif /* ffconfigUNICODE_UTF16_SUPPORT */
#endif /* ffconfigTIME_SUPPORT */
#if( ffconfigUNICODE_UTF16_SUPPORT != 0 )
FF_Error_t FF_SetPerm( FF_IOManager_t *pxIOManager, const FF_T_WCHAR *path, UBaseType_t aPerm );
#else
FF_Error_t FF_SetPerm( FF_IOManager_t *pxIOManager, const char *path, UBaseType_t aPerm );
#endif
FF_Error_t FF_SetEof( FF_FILE *pFile );
FF_Error_t FF_Close( FF_FILE *pFile );
int32_t FF_GetC( FF_FILE *pFile );
int32_t FF_GetLine( FF_FILE *pFile, char *szLine, uint32_t ulLimit );
int32_t FF_Read( FF_FILE *pFile, uint32_t ElementSize, uint32_t Count, uint8_t *buffer );
int32_t FF_Write( FF_FILE *pFile, uint32_t ElementSize, uint32_t Count, uint8_t *buffer );
BaseType_t FF_isEOF( FF_FILE *pFile );
int32_t FF_BytesLeft( FF_FILE *pFile ); /* Returns # of bytes left to read. */
/* FF_FileSize is an earlier version of FF_GetFileSize(). For files
equal to or larger than 2GB, the return value is negative.
Function is deprecated. Please use FF_GetFileSize(). */
int32_t FF_FileSize( FF_FILE *pFile ); /* Returns # of bytes in a file. */
/* Use the following function in case files may get larger than 2 GB.
Writes the size of a file to the parameter.
Returns 0 or error code. */
FF_Error_t FF_GetFileSize( FF_FILE *pFile, uint32_t *pulSize );
FF_Error_t FF_Seek( FF_FILE *pFile, int32_t Offset, BaseType_t xOrigin );
int32_t FF_PutC( FF_FILE *pFile, uint8_t Value );
static portINLINE uint32_t FF_Tell( FF_FILE *pFile )
{
return pFile ? pFile->ulFilePointer : 0;
}
uint8_t FF_GetModeBits( const char *Mode );
FF_Error_t FF_CheckValid( FF_FILE *pFile ); /* Check if pFile is a valid FF_FILE pointer. */
#if( ffconfigREMOVABLE_MEDIA != 0 )
int32_t FF_Invalidate( FF_IOManager_t *pxIOManager ); /* Invalidate all handles belonging to pxIOManager. */
#endif
/* Private : */
#endif

View file

@ -0,0 +1,75 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
/**
* @file ff_format.c
* @ingroup FORMAT
*
**/
#ifndef _FF_FORMAT_H_
#define _FF_FORMAT_H_
#ifdef __cplusplus
extern "C" {
#endif
#ifndef PLUS_FAT_H
#error this header will be included from "plusfat.h"
#endif
/*---------- PROTOTYPES */
/* PUBLIC (Interfaces): */
typedef enum _FF_SizeType {
eSizeIsQuota, /* Assign a quotum (sum of xSizes is free, all disk space will be allocated) */
eSizeIsPercent, /* Assign a percentage of the available space (sum of xSizes must be <= 100) */
eSizeIsSectors, /* Assign fixed number of sectors (sum of xSizes must be < ulSectorCount) */
} eSizeType_t;
typedef struct _FF_PartitionParameters {
uint32_t ulSectorCount; /* Total number of sectors on the disk, including hidden/reserved */
/* Must be obtained from the block driver */
uint32_t ulHiddenSectors; /* Keep at least these initial sectors free */
uint32_t ulInterSpace; /* Number of sectors to keep free between partitions (when 0 -> 2048) */
BaseType_t xSizes[ ffconfigMAX_PARTITIONS ]; /* E.g. 80, 20, 0, 0 (see eSizeType) */
BaseType_t xPrimaryCount; /* The number of partitions that must be "primary" */
eSizeType_t eSizeType;
} FF_PartitionParameters_t;
FF_Error_t FF_Partition( FF_Disk_t *pxDisk, FF_PartitionParameters_t *pParams );
FF_Error_t FF_Format( FF_Disk_t *pxDisk, BaseType_t xPartitionNumber, BaseType_t xPreferFAT16, BaseType_t xSmallClusters );
/* Private : */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

View file

@ -0,0 +1,62 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
#ifndef PLUS_FAT_H
#define PLUS_FAT_H
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "FreeRTOSFATConfig.h"
#include "FreeRTOSFATConfigDefaults.h"
#include "ff_error.h"
#include "ff_ioman.h"
#include "ff_fat.h"
#include "ff_fatdef.h"
#include "ff_memory.h"
#include "ff_time.h"
#include "ff_crc.h"
#include "ff_file.h"
#include "ff_dir.h"
#include "ff_string.h"
#include "ff_format.h"
#include "ff_locking.h"
/* See if any older defines with a prefix "FF_" are still defined: */
#include "ff_old_config_defines.h"
#ifdef __cplusplus
} // extern "C"
#endif
#endif

View file

@ -0,0 +1,383 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
/**
* @file ff_ioman.h
* @ingroup IOMAN
**/
#ifndef _FF_IOMAN_H_
#define _FF_IOMAN_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdlib.h> /* Use of malloc() */
#ifndef PLUS_FAT_H
#error this header will be included from "plusfat.h"
#endif
#define FF_T_FAT12 0x0A
#define FF_T_FAT16 0x0B
#define FF_T_FAT32 0x0C
#define FF_MODE_READ 0x01 /* Buffer / FILE Mode for Read Access. */
#define FF_MODE_WRITE 0x02 /* Buffer / FILE Mode for Write Access. */
#define FF_MODE_APPEND 0x04 /* FILE Mode Append Access. */
#define FF_MODE_CREATE 0x08 /* FILE Mode Create file if not existing. */
#define FF_MODE_TRUNCATE 0x10 /* FILE Mode Truncate an Existing file. */
#define FF_MODE_VIRGIN 0x40 /* Buffer mode: do not fetch content from disk. Used for write-only buffers. */
#define FF_MODE_DIR 0x80 /* Special Mode to open a Dir. (Internal use ONLY!) */
#define FF_MODE_RD_WR ( FF_MODE_READ | FF_MODE_WRITE ) /* Just for bit filtering. */
/* The buffer write-only mode saves a fetch from disk.
The write-only mode is used when a buffer is needed just
for clearing sectors. */
#define FF_MODE_WR_ONLY ( FF_MODE_VIRGIN | FF_MODE_WRITE ) /* Buffer for Write-only Access (Internal use ONLY!) */
#define FF_BUF_MAX_HANDLES 0xFFFF /* Maximum number handles sharing a buffer. (16 bit integer, we don't want to overflow it!) */
#define FF_MAX_ENTRIES_PER_DIRECTORY 0xFFFF
#define FF_SIZEOF_SECTOR 512
#define FF_SIZEOF_DIRECTORY_ENTRY 32
#ifndef pdTRUE_SIGNED
/* Temporary solution: eventually the defines below will appear
in 'Source\include\projdefs.h' */
#define pdTRUE_SIGNED pdTRUE
#define pdFALSE_SIGNED pdFALSE
#define pdTRUE_UNSIGNED ( ( UBaseType_t ) 1u )
#define pdFALSE_UNSIGNED ( ( UBaseType_t ) 0u )
#endif
/**
* I/O Driver Definitions
* Provide access to any Block Device via the following interfaces.
* Returns the number of blocks actually read or written.
**/
/**
* A special information structure for the FreeRTOS+FAT mass storage device
* driver model.
**/
typedef struct
{
uint16_t BlkSize;
uint32_t TotalBlocks;
} FF_DeviceInfo_t;
#if( ffconfigHASH_CACHE != 0 )
#define FF_HASH_TABLE_ENTRY_COUNT ( ( ffconfigHASH_TABLE_SIZE + 3 ) / 4 )
struct xHASH_TABLE
{
uint32_t ulDirCluster; /* The Starting Cluster of the dir that the hash represents. */
uint32_t ulNumHandles; /* Number of active Handles using this hash table. */
uint32_t ulMisses; /* Number of times this Hash Table was missed, (i.e. how redundant it is). */
uint32_t ulBitTable[ FF_HASH_TABLE_ENTRY_COUNT ];
};
typedef struct xHASH_TABLE FF_HashTable_t;
void FF_ClearHash( FF_HashTable_t *pxHash, uint32_t ulHash );
void FF_SetHash( FF_HashTable_t *pxHash, uint32_t ulHash );
BaseType_t FF_isHashSet( FF_HashTable_t *pxHash, uint32_t ulHash );
#endif /* ffconfigHASH_CACHE */
/* A forward declaration for the I/O manager, to be used in 'struct xFFDisk'. */
struct _FF_IOMAN;
struct xFFDisk;
typedef void ( *FF_FlushApplicationHook )( struct xFFDisk *pxDisk );
/*
* Some low-level drivers also need to flush data to a device.
* Use an Application hook that will be called every time when
* FF_FlushCache() is called. The semaphore will still be taken
* to avoid unwanted reentrancy.
* For example:
*
* void FTL_FlushData( struct xFFDisk *pxDisk )
* {
* // You may or may not inspect 'pxDisk'
* FTL_FlushTableCache();
* }
*
* Make sure you bind the function to the disc object, right after creation:
*
* pxDisk->fnFlushApplicationHook = FTL_FlushData;
*/
/* Structure that contains fields common to all media drivers, and can be
extended to contain additional fields to tailor it for use with a specific media
type. */
struct xFFDisk
{
struct
{
/* Flags that can optionally be used by the media driver to ensure the
disk has been initialised, registered and mounted before it is accessed. */
uint32_t bIsInitialised : 1;
uint32_t bIsMounted : 1;
uint32_t spare0 : 5;
/* The partition number on the media described by this structure. */
uint32_t bPartitionNumber : 8;
uint32_t spare1 : 16;
} xStatus;
/* Provided to allow this structure to be extended to include additional
attributes that are specific to a media type. */
void * pvTag;
/* Points to input and output manager used by the disk described by this
structure. */
struct _FF_IOMAN *pxIOManager;
/* The number of sectors on the disk. */
uint32_t ulNumberOfSectors;
/* See comments here above. */
FF_FlushApplicationHook fnFlushApplicationHook;
/* Field that can optionally be set to a signature that is unique to the
media. Read and write functions can check the ulSignature field to validate
the media type before they attempt to access the pvTag field, or perform any
read and write operations. */
uint32_t ulSignature;
};
typedef struct xFFDisk FF_Disk_t;
typedef int32_t ( *FF_WriteBlocks_t ) ( uint8_t *pucBuffer, uint32_t ulSectorAddress, uint32_t ulCount, FF_Disk_t *pxDisk );
typedef int32_t ( *FF_ReadBlocks_t ) ( uint8_t *pucBuffer, uint32_t ulSectorAddress, uint32_t ulCount, FF_Disk_t *pxDisk );
/**
* @public
* @brief Describes the block device driver interface to FreeRTOS+FAT.
**/
typedef struct
{
FF_WriteBlocks_t fnpWriteBlocks; /* Function Pointer, to write a block(s) from a block device. */
FF_ReadBlocks_t fnpReadBlocks; /* Function Pointer, to read a block(s) from a block device. */
FF_Disk_t *pxDisk; /* Earlier called 'pParam': pointer to some parameters e.g. for a Low-Level Driver Handle. */
} FF_BlockDevice_t;
/**
* @private
* @brief FreeRTOS+FAT handles memory with buffers, described as below.
* @note This may change throughout development.
**/
typedef struct
{
uint32_t ulSector; /* The LBA of the Cached sector. */
uint32_t ulLRU; /* For the Least Recently Used algorithm. */
uint8_t *pucBuffer; /* Pointer to the cache block. */
uint32_t ucMode : 8, /* Read or Write mode. */
bModified : 1, /* If the sector was modified since read. */
bValid : 1; /* Initially FALSE. */
uint16_t usNumHandles; /* Number of objects using this buffer. */
uint16_t usPersistance; /* For the persistance algorithm. */
} FF_Buffer_t;
typedef struct
{
#if( ffconfigUNICODE_UTF16_SUPPORT != 0 )
FF_T_WCHAR pcPath[ ffconfigMAX_FILENAME ];
#else
char pcPath[ ffconfigMAX_FILENAME ];
#endif
uint32_t ulDirCluster;
} FF_PathCache_t;
/**
* @private
* @brief FreeRTOS+FAT identifies a partition with the following data.
* @note This may shrink as development and optimisation goes on.
**/
typedef struct
{
uint32_t ulBeginLBA; /* LBA start address of the partition. */
uint32_t ulFATBeginLBA; /* LBA of the FAT tables. */
uint32_t ulSectorsPerFAT; /* Number of sectors per Fat. */
uint32_t ulTotalSectors;
uint32_t ulDataSectors;
#if( ffconfigWRITE_FREE_COUNT != 0 )
uint32_t ulFSInfoLBA; /* LBA of the FSINFO sector. */
#endif
uint32_t ulRootDirSectors;
uint32_t ulFirstDataSector;
uint32_t ulClusterBeginLBA; /* LBA of first cluster. */
uint32_t ulNumClusters; /* Number of clusters. */
uint32_t ulRootDirCluster; /* Cluster number of the root directory entry. */
uint32_t ulLastFreeCluster;
uint32_t ulFreeClusterCount; /* Records free space on mount. */
uint32_t ulSectorsPerCluster;/* Number of sectors per Cluster. */
char pcVolumeLabel[ 12 ];/* Volume Label of the partition. */
uint16_t usBlkSize; /* Size of a Sector Block in bytes. */
uint16_t usReservedSectors;
uint8_t ucType; /* Partition Type Identifier. */
uint8_t ucBlkFactor; /* Scale Factor for block sizes above 512! */
uint8_t ucNumFATS; /* Number of FAT tables. */
uint8_t ucPartitionMounted; /* pdTRUE if the partition is mounted, otherwise pdFALSE. */
#if( ffconfigPATH_CACHE != 0 )
FF_PathCache_t pxPathCache[ffconfigPATH_CACHE_DEPTH];
uint32_t ulPCIndex;
#endif
} FF_Partition_t;
/**
* @public
* @brief FF_IOManager_t Object description.
*
* FreeRTOS+FAT functions around an object like this.
**/
#define FF_FAT_LOCK 0x01 /* Lock bit mask for FAT table locking. */
#define FF_DIR_LOCK 0x02 /* Lock bit mask for DIR modification locking. */
#define FF_BUF_LOCK 0x04 /* Lock bit mask for buffers. */
/**
* @public
* @brief FF_IOManager_t Object. A developer should not touch these values.
*
**/
typedef struct _FF_IOMAN
{
FF_BlockDevice_t xBlkDevice; /* Pointer to a Block device description. */
FF_Partition_t xPartition; /* A partition description. */
FF_Buffer_t *pxBuffers; /* Pointer to an array of buffer descriptors. */
void *pvSemaphore; /* Pointer to a Semaphore object. (For buffer description modifications only!). */
void *FirstFile; /* Pointer to the first File object. */
void *xEventGroup; /* An event group, used for locking FAT, DIR and Buffers. Replaces ucLocks. */
uint8_t *pucCacheMem; /* Pointer to a block of memory for the cache. */
uint16_t usSectorSize; /* The sector size that IOMAN is configured to. */
uint16_t usCacheSize; /* Size of the cache in number of Sectors. */
uint8_t ucPreventFlush; /* Flushing to disk only allowed when 0. */
uint8_t ucFlags; /* Bit-Mask: identifying allocated pointers and other flags */
#if( ffconfigHASH_CACHE != 0 )
FF_HashTable_t xHashCache[ ffconfigHASH_CACHE_DEPTH ];
#endif
void *pvFATLockHandle;
} FF_IOManager_t;
/* Bit values for 'FF_IOManager_t::ucFlags': */
/* Memory Allocation testing and other flags. */
#define FF_IOMAN_ALLOC_BUFDESCR 0x01 /* Flags the pxBuffers pointer is allocated. */
#define FF_IOMAN_ALLOC_BUFFERS 0x02 /* Flags the pucCacheMem pointer is allocated. */
#define FF_IOMAN_BLOCK_DEVICE_IS_REENTRANT 0x10 /* When true, ffRead/ffWrite are not protected by a semaphore. */
#if( ffconfigREMOVABLE_MEDIA != 0 )
#define FF_IOMAN_DEVICE_IS_EXTRACTED 0x20
#endif /* ffconfigREMOVABLE_MEDIA */
typedef struct xFF_CREATION_PARAMETERS
{
uint8_t *pucCacheMemory; /* User provided memory, or use NULL to malloc the cache memory. */
uint32_t ulMemorySize; /* Size of the cache memory, must be a multiple of 'ulSectorSize'. */
BaseType_t ulSectorSize; /* Sector size, unit for reading/writing to the disk, normally 512 bytes. */
FF_WriteBlocks_t fnWriteBlocks; /* A function to write sectors to the device. */
FF_ReadBlocks_t fnReadBlocks; /* A function to read sectors from the device. */
FF_Disk_t *pxDisk; /* Some properties of the disk driver. */
void *pvSemaphore; /* Pointer to a Semaphore object. */
BaseType_t xBlockDeviceIsReentrant; /* Make non-zero if ffRead/ffWrite are re-entrant. */
} FF_CreationParameters_t;
/*---------- PROTOTYPES (in order of appearance). */
/* PUBLIC (Interfaces): */
FF_IOManager_t *FF_CreateIOManger( FF_CreationParameters_t *pxParameters, FF_Error_t *pError );
FF_Error_t FF_DeleteIOManager( FF_IOManager_t *pxIOManager);
FF_Error_t FF_Mount( FF_Disk_t *pxDisk, BaseType_t xPartitionNumber );
FF_Error_t FF_Unmount( FF_Disk_t *pxDisk );
FF_Error_t FF_FlushCache( FF_IOManager_t *pxIOManager );
static portINLINE BaseType_t FF_Mounted( FF_IOManager_t *pxIOManager )
{
return pxIOManager && pxIOManager->xPartition.ucPartitionMounted;
}
int32_t FF_GetPartitionBlockSize(FF_IOManager_t *pxIOManager);
#if( ffconfig64_NUM_SUPPORT != 0 )
uint64_t FF_GetVolumeSize( FF_IOManager_t *pxIOManager );
#else
uint32_t FF_GetVolumeSize( FF_IOManager_t *pxIOManager );
#endif
/* PUBLIC (To FreeRTOS+FAT Only): */
int32_t FF_BlockRead( FF_IOManager_t *pxIOManager, uint32_t ulSectorLBA, uint32_t ulNumSectors, void *pBuffer, BaseType_t aSemLocked );
int32_t FF_BlockWrite( FF_IOManager_t *pxIOManager, uint32_t ulSectorLBA, uint32_t ulNumSectors, void *pBuffer, BaseType_t aSemLocked );
FF_Error_t FF_IncreaseFreeClusters( FF_IOManager_t *pxIOManager, uint32_t Count );
FF_Error_t FF_DecreaseFreeClusters( FF_IOManager_t *pxIOManager, uint32_t Count );
FF_Buffer_t *FF_GetBuffer( FF_IOManager_t *pxIOManager, uint32_t ulSector, uint8_t Mode );
FF_Error_t FF_ReleaseBuffer( FF_IOManager_t *pxIOManager, FF_Buffer_t *pBuffer );
/* 'Internal' to FreeRTOS+FAT. */
typedef struct _SPart
{
uint32_t ulStartLBA; /* FF_FAT_PTBL_LBA */
uint32_t ulSectorCount; /* FF_FAT_PTBL_SECT_COUNT */
uint32_t
ucActive : 8, /* FF_FAT_PTBL_ACTIVE */
ucPartitionID : 8, /* FF_FAT_PTBL_ID */
bIsExtended : 1;
} FF_Part_t;
typedef struct _SPartFound
{
int iCount;
FF_Part_t pxPartitions[ffconfigMAX_PARTITIONS];
} FF_SPartFound_t;
/* This function will parse the 4 entries in a partition table: */
void FF_ReadParts( uint8_t *pucBuffer, FF_Part_t *pxParts );
/* FF_PartitionCount() has now been replaced by FF_PartitionSearch()
* It will enumerate all valid partitions found
* If sector-0 happens to be a valid MBR, 1 partition will be returned
*/
FF_Error_t FF_PartitionSearch( FF_IOManager_t *pxIOManager, FF_SPartFound_t *pPartsFound );
/* HT : for debugging only. */
BaseType_t xIsFatSector( FF_IOManager_t *pxIOManager, uint32_t ulSectorNr );
BaseType_t xNeedLogging( FF_IOManager_t *pxIOManager );
BaseType_t xIsRootDirSector( FF_IOManager_t *pxIOManager, uint32_t ulSectorNr );
const char *pcSectorType( FF_IOManager_t *pxIOManager, uint32_t ulSectorNr );
/* Needed to make this public/private to be used in FF_Partition/FF_Format. */
void FF_IOMAN_InitBufferDescriptors( FF_IOManager_t *pxIOManager );
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

View file

@ -0,0 +1,91 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
/**
* @file ff_locking.h
* @ingroup LOCKING
**/
#ifndef _FF_LOCKING_H_
#define _FF_LOCKING_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdlib.h>
/*---------- PROTOTYPES (in order of appearance). */
/* PUBLIC: */
/* PRIVATE: */
void FF_PendSemaphore ( void *pSemaphore );
BaseType_t FF_TrySemaphore ( void *pSemaphore, uint32_t TimeMs );
void FF_ReleaseSemaphore ( void *pSemaphore );
void FF_Sleep ( uint32_t TimeMs );
/* Create an event group and bind it to an I/O manager. */
BaseType_t FF_CreateEvents( FF_IOManager_t *pxIOManager );
/* Delete an event group. */
void FF_DeleteEvents( FF_IOManager_t *pxIOManager );
/* Get a lock on all DIR operations for a given I/O manager. */
void FF_LockDirectory( FF_IOManager_t *pxIOManager );
/* Release the lock on all DIR operations. */
void FF_UnlockDirectory( FF_IOManager_t *pxIOManager );
/* Get a lock on all FAT operations for a given I/O manager. */
void FF_LockFAT( FF_IOManager_t *pxIOManager );
/* Release the lock on all FAT operations. */
void FF_UnlockFAT( FF_IOManager_t *pxIOManager );
/* Called from FF_GetBuffer() as long as no buffer is available. */
BaseType_t FF_BufferWait( FF_IOManager_t *pxIOManager, uint32_t xWaitMS );
/* Called from FF_ReleaseBuffer(). */
void FF_BufferProceed( FF_IOManager_t *pxIOManager );
/* Check if the current task already has locked the FAT. */
int FF_Has_Lock( FF_IOManager_t *pxIOManager, uint32_t aBits );
/*
* Throw a configASSERT() in case the FAT has not been locked
* by this task.
*/
/* _HT_ This function is only necessary while testing. */
void FF_Assert_Lock( FF_IOManager_t *pxIOManager, uint32_t aBits );
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* _FF_LOCKING_H_ */

View file

@ -0,0 +1,168 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
/**
* @file ff_memory.h
* @ingroup MEMORY
**/
#ifndef _FF_MEMORY_H_
#define _FF_MEMORY_H_
/*
* When sector data is written or analysed, some values might be stored unaligned.
* The routines below treat all values as little arrays of either 2 or 4 bytes.
* Also on big endian platforms, the order of bytes will be swapped.
*/
/*---------- PROTOTYPES */
#if( ffconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )
/*
* FAT is little endian.
* On a little endian CPU, bytes will be copied to the structures below 1-to-1 :
*/
typedef struct
{
uint8_t u8_0; /* the first byte */
uint8_t u8_1; /* the second byte */
} FF_TShort_t;
typedef struct
{
uint8_t u8_0;
uint8_t u8_1;
uint8_t u8_2;
uint8_t u8_3;
} FF_TLong_t;
#elif( ffconfigBYTE_ORDER == pdFREERTOS_BIG_ENDIAN )
/*
* On a big endian CPU, all bytes will be swapped, either 2 or 4 bytes:
*/
typedef struct
{
uint8_t u8_1; /* the second byte */
uint8_t u8_0; /* the first byte */
} FF_TShort_t;
typedef struct
{
uint8_t u8_3;
uint8_t u8_2;
uint8_t u8_1;
uint8_t u8_0;
} FF_TLong_t;
#else
#error Little or Big Endian? - Please set ffconfigBYTE_ORDER to either pdFREERTOS_LITTLE_ENDIAN or pdFREERTOS_BIG_ENDIAN 1 in FreeRTOSFATConfig.h
#endif
/*! 16-bit union. */
typedef union
{
uint16_t u16;
FF_TShort_t bytes;
} FF_T_UN16;
/*! 32-bit union. */
typedef union
{
uint32_t u32;
FF_TLong_t bytes;
} FF_T_UN32;
/* HT inlined these functions:
*/
#if( ffconfigINLINE_MEMORY_ACCESS != 0 )
static portINLINE uint8_t FF_getChar( const uint8_t *pBuffer, uint32_t aOffset )
{
return ( uint8_t ) ( pBuffer[ aOffset ] );
}
static portINLINE uint16_t FF_getShort( const uint8_t *pBuffer, uint32_t aOffset )
{
FF_T_UN16 u16;
pBuffer += aOffset;
u16.bytes.u8_1 = pBuffer[ 1 ];
u16.bytes.u8_0 = pBuffer[ 0 ];
return u16.u16;
}
static portINLINE uint32_t FF_getLong( const uint8_t *pBuffer, uint32_t aOffset )
{
FF_T_UN32 u32;
pBuffer += aOffset;
u32.bytes.u8_3 = pBuffer[ 3 ];
u32.bytes.u8_2 = pBuffer[ 2 ];
u32.bytes.u8_1 = pBuffer[ 1 ];
u32.bytes.u8_0 = pBuffer[ 0 ];
return u32.u32;
}
static portINLINE void FF_putChar( uint8_t *pBuffer, uint32_t aOffset, uint32_t Value )
{
pBuffer[ aOffset ] = ( uint8_t ) Value;
}
static portINLINE void FF_putShort( uint8_t *pBuffer, uint32_t aOffset, uint32_t Value )
{
FF_T_UN16 u16;
u16.u16 = ( uint16_t ) Value;
pBuffer += aOffset;
pBuffer[ 0 ] = u16.bytes.u8_0;
pBuffer[ 1 ] = u16.bytes.u8_1;
}
static portINLINE void FF_putLong( uint8_t *pBuffer, uint32_t aOffset, uint32_t Value )
{
FF_T_UN32 u32;
u32.u32 = Value;
pBuffer += aOffset;
pBuffer[ 0 ] = u32.bytes.u8_0;
pBuffer[ 1 ] = u32.bytes.u8_1;
pBuffer[ 2 ] = u32.bytes.u8_2;
pBuffer[ 3 ] = u32.bytes.u8_3;
}
#else /* ffconfigINLINE_MEMORY_ACCESS */
uint8_t FF_getChar( const uint8_t *pBuffer, uint32_t aOffset );
uint16_t FF_getShort( const uint8_t *pBuffer, uint32_t aOffset );
uint32_t FF_getLong( const uint8_t *pBuffer, uint32_t aOffset );
void FF_putChar( uint8_t *pBuffer, uint32_t aOffset, uint32_t Value );
void FF_putShort( uint8_t *pBuffer, uint32_t aOffset, uint32_t Value );
void FF_putLong( uint8_t *pBuffer, uint32_t aOffset, uint32_t Value );
#endif /* ffconfigINLINE_MEMORY_ACCESS */
#endif /* _FF_MEMORY_H_ */

View file

@ -0,0 +1,256 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
/*
As of 15/3/2015 all +FAT configuration items changed their prefix,
e.g. FF_LITTLE_ENDIAN has become ffconfigLITTLE_ENDIAN
This tempoary header file checks for the presence old configuration items
and issue a compiler error if any is defined.
*/
#ifdef FF_LITTLE_ENDIAN
#error FF_LITTLE_ENDIAN was dropped and replaced with 'ffconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN'
#endif
#ifdef FF_BIG_ENDIAN
#error FF_BIG_ENDIAN was dropped and replaced with 'ffconfigBYTE_ORDER == pdFREERTOS_BIG_ENDIAN'
#endif
#ifdef ffconfigLITTLE_ENDIAN
#error ffconfigLITTLE_ENDIAN was dropped.
#endif
#ifdef ffconfigBIG_ENDIAN
#error ffconfigBIG_ENDIAN was dropped.
#endif
#ifdef FF_HAS_CWD
#error FF_HAS_CWD still defined. Please use ffconfig prefix.
#endif
#if !defined( pdFREERTOS_LITTLE_ENDIAN ) || !defined( pdFREERTOS_BIG_ENDIAN )
#error Missing defines from FreeRTOS
#endif
#ifdef FF_LFN_SUPPORT
#error FF_LFN_SUPPORT still defined. Please use ffconfig prefix.
#endif
#ifdef FF_INCLUDE_SHORT_NAME
#error FF_INCLUDE_SHORT_NAME still defined. Please use ffconfig prefix.
#endif
#ifdef FF_SHORTNAME_CASE
#error FF_SHORTNAME_CASE still defined. Please use ffconfig prefix.
#endif
#ifdef FF_UNICODE_UTF16_SUPPORT
#error FF_UNICODE_UTF16_SUPPORT still defined. Please use ffconfig prefix.
#endif
#ifdef FF_UNICODE_UTF8_SUPPORT
#error FF_UNICODE_UTF8_SUPPORT still defined. Please use ffconfig prefix.
#endif
#ifdef FF_FAT12_SUPPORT
#error FF_FAT12_SUPPORT still defined. Please use ffconfig prefix.
#endif
#ifdef FF_OPTIMISE_UNALIGNED_ACCESS
#error FF_OPTIMISE_UNALIGNED_ACCESS still defined. Please use ffconfig prefix.
#endif
#ifdef FF_CACHE_WRITE_THROUGH
#error FF_CACHE_WRITE_THROUGH still defined. Please use ffconfig prefix.
#endif
#ifdef FF_WRITE_BOTH_FATS
#error FF_WRITE_BOTH_FATS still defined. Please use ffconfig prefix.
#endif
#ifdef FF_WRITE_FREE_COUNT
#error FF_WRITE_FREE_COUNT still defined. Please use ffconfig prefix.
#endif
#ifdef FF_TIME_SUPPORT
#error FF_TIME_SUPPORT still defined. Please use ffconfig prefix.
#endif
#ifdef FF_REMOVABLE_MEDIA
#error FF_REMOVABLE_MEDIA still defined. Please use ffconfig prefix.
#endif
#ifdef FF_MOUNT_FIND_FREE
#error FF_MOUNT_FIND_FREE still defined. Please use ffconfig prefix.
#endif
#ifdef FF_FINDAPI_ALLOW_WILDCARDS
#error FF_FINDAPI_ALLOW_WILDCARDS still defined. Please use ffconfig prefix.
#endif
#ifdef FF_WILDCARD_CASE_INSENSITIVE
#error FF_WILDCARD_CASE_INSENSITIVE still defined. Please use ffconfig prefix.
#endif
#ifdef FF_PATH_CACHE
#error FF_PATH_CACHE still defined. Please use ffconfig prefix.
#endif
#ifdef FF_PATH_CACHE_DEPTH
#error FF_PATH_CACHE_DEPTH still defined. Please use ffconfig prefix.
#endif
#ifdef FF_HASH_CACHE
#error FF_HASH_CACHE still defined. Please use ffconfig prefix.
#endif
#ifdef FF_HASH_FUNCTION
#error FF_HASH_FUNCTION still defined. Please use ffconfig prefix.
#endif
#ifdef FF_HASH_TABLE_SIZE
#error FF_HASH_TABLE_SIZE still defined. Please use ffconfig prefix.
#endif
#ifdef FF_HASH_TABLE_SIZE
#error FF_HASH_TABLE_SIZE still defined. Please use ffconfig prefix.
#endif
#ifdef FF_MKDIR_RECURSIVE
#error FF_MKDIR_RECURSIVE still defined. Please use ffconfig prefix.
#endif
#ifdef FF_BLKDEV_USES_SEM
#error FF_BLKDEV_USES_SEM is not used any more
#endif
#ifdef ffconfigBLKDEV_USES_SEM
#error ffconfigBLKDEV_USES_SEM is not used any more
#endif
#ifdef FF_MALLOC
#error FF_MALLOC still defined. Please use ffconfig prefix.
#endif
#ifdef FF_FREE
#error FF_FREE still defined. Please use ffconfig prefix.
#endif
#ifdef FF_64_NUM_SUPPORT
#error FF_64_NUM_SUPPORT still defined. Please use ffconfig prefix.
#endif
#ifdef FF_MAX_PARTITIONS
#error FF_MAX_PARTITIONS still defined. Please use ffconfig prefix.
#endif
#ifdef FF_MAX_FILE_SYS
#error FF_MAX_FILE_SYS still defined. Please use ffconfig prefix.
#endif
#ifdef FF_DRIVER_BUSY_SLEEP_MS
#error FF_DRIVER_BUSY_SLEEP_MS still defined. Please use ffconfig prefix.
#endif
#ifdef FF_FPRINTF_SUPPORT
#error FF_FPRINTF_SUPPORT still defined. Please use ffconfig prefix.
#endif
#ifdef FF_FPRINTF_BUFFER_LENGTH
#error FF_FPRINTF_BUFFER_LENGTH still defined. Please use ffconfig prefix.
#endif
#ifdef FF_DEBUG
#error FF_DEBUG still defined. Please use ffconfig prefix.
#endif
#ifdef FF_HAS_FUNCTION_TAB
#error FF_HAS_FUNCTION_TAB still defined. Please use ffconfig prefix.
#endif
#ifdef FF_FAT_CHECK
#error FF_FAT_CHECK still defined. Please use ffconfig prefix.
#endif
#ifdef FF_MAX_FILENAME
#error FF_MAX_FILENAME still defined. Please use ffconfig prefix.
#endif
#ifdef FF_PRINTFFF_PRINTF
#error FF_PRINTFFF_PRINTF still defined. Please use ffconfig prefix.
#endif
#ifdef FF_FAT_USES_STAT
#error FF_FAT_USES_STAT still defined. Please use ffconfig prefix.
#endif
#ifdef BUF_STORE_COUNT
#error BUF_STORE_COUNT still defined. Please use ffconfig prefix.
#endif
#ifdef FF_USE_NOTIFY
#error FF_USE_NOTIFY still defined. Please use ffconfig prefix.
#endif
#ifdef FF_DEV_SUPPORT
#error FF_DEV_SUPPORT still defined. Please use ffconfig prefix.
#endif
#ifdef FF_FSINFO_TRUSTED
#error FF_FSINFO_TRUSTED still defined. Please use ffconfig prefix.
#endif
#ifdef FF_LONG_ERR_MSG
#error FF_LONG_ERR_MSG still defined. Please use ffconfig prefix.
#endif
#ifdef FF_INLINE_MEMORY_ACCESS
#error FF_INLINE_MEMORY_ACCESS still defined. Please use ffconfig prefix.
#endif
#ifdef FF_MIRROR_FATS_UMOUNT
#error FF_MIRROR_FATS_UMOUNT still defined. Please use ffconfig prefix.
#endif
#ifdef FF_HASH_CACHE_DEPTH
#error FF_HASH_CACHE_DEPTH still defined. Please use ffconfig prefix.
#endif
#ifdef FF_HASH_TABLE_SUPPORT
#error FF_HASH_TABLE_SUPPORT was dropped
#endif
#ifdef FF_INLINE_BLOCK_CALCULATIONS
#error FF_INLINE_BLOCK_CALCULATIONS was dropped
#endif
#ifdef FF_CWD_THREAD_LOCAL_INDEX
#error FF_CWD_THREAD_LOCAL_INDEX is now called ffconfigCWD_THREAD_LOCAL_INDEX
#endif
#ifdef FF_DEV_PATH
#error FF_DEV_PATH was dropped
#endif

View file

@ -0,0 +1,353 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
/*
ff_stdio.h
An front-end which make +FAT look like the well-known stdio-functions
*/
#ifndef FF_STDIO_H
#define FF_STDIO_H
#if defined(__WIN32__)
#include <dir.h>
#endif
/* Standard includes. */
#include <stdio.h>
#include <stdarg.h>
/* FreeRTOS+FAT includes. */
#include "ff_headers.h"
#include "ff_sys.h"
#if( ffconfigDEV_SUPPORT != 0 )
#include "ff_devices.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* Error return from some functions. */
#define FF_EOF (-1)
/* Bits used in the FF_Stat_t structure. */
#define FF_IFDIR 0040000u /* directory */
#define FF_IFCHR 0020000u /* character special */
#define FF_IFBLK 0060000u /* block special */
#define FF_IFREG 0100000u /* regular */
/* Bits used in the FF_FindData_t structure. */
#define FF_FA_NORMAL 0x00
#define FF_FA_RDONLY 0x01
#define FF_FA_HIDDEN 0x02
#define FF_FA_SYSTEM 0x04
#define FF_FA_LABEL 0x08
#define FF_FA_DIREC 0x10
#define FF_FA_ARCH 0x20
/* FreeRTOS+FAT uses three thread local buffers. The first stores errno, the
second a pointer to the CWD structure (if one is used), and the third the more
descriptive error code. */
#define stdioERRNO_THREAD_LOCAL_OFFSET ( ffconfigCWD_THREAD_LOCAL_INDEX + 0 )
#define stdioCWD_THREAD_LOCAL_OFFSET ( ffconfigCWD_THREAD_LOCAL_INDEX + 1 )
#define stdioFF_ERROR_THREAD_LOCAL_OFFSET ( ffconfigCWD_THREAD_LOCAL_INDEX + 2 )
/* Structure used with ff_stat(). */
typedef struct FF_STAT
{
uint32_t st_ino; /* First data cluster number. */
uint32_t st_size; /* Size of the object in number of bytes. */
uint16_t st_dev; /* The device on which the file can be found (see ff_sys.c) */
uint16_t st_mode; /* The mode (attribute bits) of this file or directory. */
#if( ffconfigTIME_SUPPORT == 1 )
uint32_t st_atime;
uint32_t st_mtime;
uint32_t st_ctime;
#endif /* ffconfigTIME_SUPPORT */
} FF_Stat_t;
/* Structure used with ff_findfirst(), ff_findnext(), etc. */
typedef struct
{
/* private */
UBaseType_t
#if( ffconfigDEV_SUPPORT != 0 )
bIsDeviceDir : 1,
#endif
bEntryPOwner : 1;
struct FF_DIR_HANDLER xDirectoryHandler;
FF_DirEnt_t xDirectoryEntry;
/* Public fields included so FF_DirEnt_t does not need to be public. */
const char * pcFileName;
uint32_t ulFileSize;
uint8_t ucAttributes;
} FF_FindData_t;
/*-----------------------------------------------------------
* Get and set the task's file system errno
* The most up to date API documentation is currently provided on the following URL:
* http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_FAT/Standard_File_System_API.html
*-----------------------------------------------------------*/
/*
int FF_GetErrno( void );
void FF_SetErrno( int ff_errno );
_RB_ comments are incorrect and index should use the stdioERRNO_THREAD_LOCAL_OFFSET offset.
*/
/* The errno is stored in a thread local buffer. */
static portINLINE void stdioSET_ERRNO( int iErrno )
{
vTaskSetThreadLocalStoragePointer( NULL, ffconfigCWD_THREAD_LOCAL_INDEX, ( void * ) ( iErrno ) );
}
static portINLINE int stdioGET_ERRNO( void )
{
void *pvResult;
pvResult = pvTaskGetThreadLocalStoragePointer( ( TaskHandle_t )NULL, ffconfigCWD_THREAD_LOCAL_INDEX );
return ( int ) pvResult;
}
#if( ( configNUM_THREAD_LOCAL_STORAGE_POINTERS - ffconfigCWD_THREAD_LOCAL_INDEX ) < 3 )
#error Please define space for 3 entries
#endif
/*
* Store the FreeRTOS+FAT error code, which provides more detail than errno.
*/
static portINLINE void stdioSET_FF_ERROR( FF_Error_t iFF_ERROR )
{
vTaskSetThreadLocalStoragePointer( NULL, stdioFF_ERROR_THREAD_LOCAL_OFFSET, ( void * ) ( iFF_ERROR ) );
}
/*
* Read back the FreeRTOS+FAT error code, which provides more detail than
* errno.
*/
static portINLINE FF_Error_t stdioGET_FF_ERROR( void )
{
void *pvResult;
pvResult = pvTaskGetThreadLocalStoragePointer( NULL, stdioFF_ERROR_THREAD_LOCAL_OFFSET );
return ( FF_Error_t ) pvResult;
}
/*-----------------------------------------------------------
* Open and close a file
* The most up to date API documentation is currently provided on the following URL:
* http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_FAT/Standard_File_System_API.html
*-----------------------------------------------------------*/
FF_FILE *ff_fopen( const char *pcFile, const char *pcMode );
int ff_fclose( FF_FILE *pxStream );
/*-----------------------------------------------------------
* Seek and tell
* The most up to date API documentation is currently provided on the following URL:
* http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_FAT/Standard_File_System_API.html
*-----------------------------------------------------------*/
int ff_fseek( FF_FILE *pxStream, long lOffset, int iWhence );
void ff_rewind( FF_FILE *pxStream );
long ff_ftell( FF_FILE *pxStream );
int ff_feof( FF_FILE *pxStream );
/*-----------------------------------------------------------
* Read and write
* The most up to date API documentation is currently provided on the following URL:
* http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_FAT/Standard_File_System_API.html
*-----------------------------------------------------------*/
size_t ff_fread( void *pvBuffer, size_t xSize, size_t xItems, FF_FILE * pxStream );
size_t ff_fwrite( const void *pvBuffer, size_t xSize, size_t xItems, FF_FILE * pxStream );
/* Whenever possible, use ellipsis parameter type checking.
_RB_ Compiler specifics need to be moved to the compiler specific header files. */
#if defined(__GNUC__)
/* The GNU-C compiler will check if the parameters are correct. */
int ff_fprintf( FF_FILE * pxStream, const char *pcFormat, ... )
__attribute__ ( ( format ( __printf__, 2, 3 ) ) );
#else
int ff_fprintf( FF_FILE * pxStream, const char *pcFormat, ... );
#endif
int ff_fgetc( FF_FILE * pxStream);
int ff_fputc( int iChar, FF_FILE *pxStream );
char *ff_fgets( char *pcBuffer, size_t xCount, FF_FILE *pxStream );
/*-----------------------------------------------------------
* Change length of file (truncate)
* File should have been opened in "w" or "a" mode
* The actual length of the file will be made equal to the current writing
* position
* The most up to date API documentation is currently provided on the following URL:
* http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_FAT/Standard_File_System_API.html
*-----------------------------------------------------------*/
int ff_seteof( FF_FILE *pxStream );
/*-----------------------------------------------------------
* Open a file in append/update mode, truncate its length to a given value,
* or write zero's up until the required length, and return a handle to the open
* file. If NULL is returned, ff_errno contains an error code.
* The most up to date API documentation is currently provided on the following URL:
* http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_FAT/Standard_File_System_API.html
*-----------------------------------------------------------*/
FF_FILE *ff_truncate( const char * pcFileName, long lTruncateSize );
/*-----------------------------------------------------------
* Flush to disk
* The most up to date API documentation is currently provided on the following URL:
* http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_FAT/Standard_File_System_API.html
*-----------------------------------------------------------*/
int ff_fflush( FF_FILE *pxStream );
/*-----------------------------------------------------------
* Create directory, remove and rename files
* The most up to date API documentation is currently provided on the following URL:
* http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_FAT/Standard_File_System_API.html
*-----------------------------------------------------------*/
#if( ffconfigMKDIR_RECURSIVE == 0 )
int ff_mkdir( const char *pcPath );
#else
/* If the parameter bRecursive is non-zero, the entire path will be checked
and if necessary, created. */
int ff_mkdir( const char *pcPath, int bRecursive );
#endif
/*-----------------------------------------------------------
* Create path specified by the pcPath parameter.
* The most up to date API documentation is currently provided on the following URL:
* http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_FAT/Standard_File_System_API.html
*-----------------------------------------------------------*/
int ff_mkpath( const char *pcPath );
/*-----------------------------------------------------------
* Remove the directory specified by the pcDirectory parameter.
* The most up to date API documentation is currently provided on the following URL:
* http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_FAT/Standard_File_System_API.html
*-----------------------------------------------------------*/
int ff_rmdir( const char *pcDirectory );
/*-----------------------------------------------------------
* Delete a directory and, recursively, all of its contents.
* The most up to date API documentation is currently provided on the following URL:
* http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_FAT/Standard_File_System_API.html
*-----------------------------------------------------------*/
#if( ffconfigUSE_DELTREE != 0 )
/* By default, this function will not be compiled. The function will
recursively call itself, which is against the FreeRTOS coding standards, so
IT MUST BE USED WITH CARE.
The cost of each recursion will be roughly:
Stack : 48 (12 stack words)
Heap : 112 + ffconfigMAX_FILENAME
These numbers may change depending on CPU and compiler. */
int ff_deltree( const char *pcPath );
#endif
/*-----------------------------------------------------------
* Remove/delete a file.
* The most up to date API documentation is currently provided on the following URL:
* http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_FAT/Standard_File_System_API.html
*-----------------------------------------------------------*/
int ff_remove( const char *pcPath );
/*-----------------------------------------------------------
* Move a file, also cross-directory but not across a file system.
* The most up to date API documentation is currently provided on the following URL:
* http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_FAT/Standard_File_System_API.html
*-----------------------------------------------------------*/
int ff_rename( const char *pcOldName, const char *pcNewName, int bDeleteIfExists );
/*-----------------------------------------------------------
* Get the status of a file.
* The most up to date API documentation is currently provided on the following URL:
* http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_FAT/Standard_File_System_API.html
*-----------------------------------------------------------*/
int ff_stat( const char *pcFileName, FF_Stat_t *pxStatBuffer );
/* _HT_ Keep this for a while, until the new ff_stat() is wel tested */
int ff_old_stat( const char *pcName, FF_Stat_t *pxStatBuffer );
/*-----------------------------------------------------------
* Get the length of a file in bytes.
* The most up to date API documentation is currently provided on the following URL:
* http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_FAT/Standard_File_System_API.html
*-----------------------------------------------------------*/
size_t ff_filelength( FF_FILE *pxFile );
/*-----------------------------------------------------------
* Working directory and iterating through directories.
* The most up to date API documentation is currently provided on the following URL:
* http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_FAT/Standard_File_System_API.html
*-----------------------------------------------------------*/
#if ffconfigHAS_CWD
int ff_chdir( const char *pcDirectoryName );
char *ff_getcwd( char *pcBuffer, size_t xBufferLength );
#endif
int ff_findfirst( const char *pcDirectory, FF_FindData_t *pxFindData );
int ff_findnext( FF_FindData_t *pxFindData );
int ff_isdirempty(const char *pcPath );
/* _RB_ What to do regarding documentation for the definitions below here. */
#if( ffconfig64_NUM_SUPPORT != 0 )
int64_t ff_diskfree(const char *pcPath, uint32_t *pxSectorCount );
#else
int32_t ff_diskfree(const char *pcPath, uint32_t *pxSectorCount );
#endif
int ff_finddir( const char *pcPath );
#if( ffconfigHAS_CWD == 1 )
/* Obtain the CWD used by the current task. */
void ff_free_CWD_space( void );
#endif
typedef enum _EFileAction {
eFileCreate,
eFileRemove,
eFileChange,
eFileIsDir = 0x80,
} eFileAction_t;
void callFileEvents( const char *apPath, eFileAction_t aAction );
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* FF_STDIO_H */

View file

@ -0,0 +1,108 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
/**
* @file ff_string.c
* @ingroup STRING
*
* @defgroup STRING FreeRTOS+FAT String Library
* @brief Portable String Library for FreeRTOS+FAT
*
*
**/
#ifndef _FF_STRING_H_
#define _FF_STRING_H_
#include "FreeRTOSFATConfig.h"
#include <string.h>
#if( ffconfigUNICODE_UTF16_SUPPORT != 0 )
#include <wchar.h>
typedef wchar_t FF_T_WCHAR; /*/< Unicode UTF-16 Character type, for FreeRTOS+FAT when UNICODE is enabled. */
#endif
#if defined( _MSC_VER ) && ( _MSC_VER <= 1600 )
#define FF_stricmp _stricmp
#else
#define FF_stricmp strcasecmp
#endif
#if( ffconfigUNICODE_UTF16_SUPPORT != 0 )
void FF_tolower ( FF_T_WCHAR *string, uint32_t strLen );
void FF_toupper ( FF_T_WCHAR *string, uint32_t strLen );
BaseType_t FF_strmatch ( const FF_T_WCHAR *str1, const FF_T_WCHAR *str2, BaseType_t len );
FF_T_WCHAR *FF_strtok ( const FF_T_WCHAR *string, FF_T_WCHAR *token, uint16_t *tokenNumber, BaseType_t *last, BaseType_t xLength );
BaseType_t FF_wildcompare ( const FF_T_WCHAR *pcWildCard, const FF_T_WCHAR *pszString );
/* ASCII to UTF16 and UTF16 to ASCII routines. -- These are lossy routines, and are only for converting ASCII to UTF-16 */
/* and the equivalent back to ASCII. Do not use them for international text. */
void FF_cstrtowcs(FF_T_WCHAR *wcsDest, const char *szpSource);
void FF_wcstocstr(char *szpDest, const FF_T_WCHAR *wcsSource);
void FF_cstrntowcs(FF_T_WCHAR *wcsDest, const char *szpSource, uint32_t len);
void FF_wcsntocstr(char *szpDest, const FF_T_WCHAR *wcsSource, uint32_t len);
#else
void FF_tolower ( char *string, uint32_t strLen );
void FF_toupper ( char *string, uint32_t strLen );
BaseType_t FF_strmatch ( const char *str1, const char *str2, BaseType_t len );
char *FF_strtok ( const char *string, char *token, uint16_t *tokenNumber, BaseType_t *last, BaseType_t xLength );
BaseType_t FF_wildcompare ( const char *pcWildCard, const char *pszString );
#endif /* ffconfigUNICODE_UTF16_SUPPORT */
/* UTF8 / UTF16 Transformation Functions. */
#if ( ( ffconfigUNICODE_UTF16_SUPPORT != 0 ) && ( WCHAR_MAX > 0xFFFF ) ) || ( ffconfigUNICODE_UTF8_SUPPORT != 0 )
UBaseType_t FF_GetUtf16SequenceLen (uint16_t usLeadChar);
#endif
#if( ffconfigUNICODE_UTF8_SUPPORT != 0 )
int32_t FF_Utf8ctoUtf16c (uint16_t *utf16Dest, const uint8_t *utf8Source, uint32_t ulSize);
int32_t FF_Utf16ctoUtf8c (uint8_t *utf8Dest, const uint16_t *utf16Source, uint32_t ulSize);
#endif /* ffconfigUNICODE_UTF8_SUPPORT */
/* UTF16 / UTF32 Transformation Functions. */
#if( ffconfigNOT_USED_FOR_NOW != 0 )
int32_t FF_Utf16ctoUtf32c(uint32_t *utf32Dest, const uint16_t *utf16Source);
#endif
#if( ffconfigUNICODE_UTF16_SUPPORT != 0 ) && ( WCHAR_MAX > 0xFFFF )
int32_t FF_Utf32ctoUtf16c(uint16_t *utf16Dest, uint32_t utf32char, uint32_t ulSize);
#endif
/* String transformations. */
int32_t FF_Utf32stoUtf8s(uint8_t *Utf8String, uint32_t *Utf32String);
#if( ffconfigUNICODE_UTF16_SUPPORT != 0 )
#define STRNCPY( target, src, maxlen ) wcsncpy( ( target ), ( src ), ( maxlen ) )
#define STRLEN( string ) wcslen( ( string ) )
#else
#define STRNCPY( target, src, maxlen ) strncpy( ( target ), ( src ), ( maxlen ) );
#define STRLEN( string ) strlen( ( string ) )
#endif
#endif

View file

@ -0,0 +1,129 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
/*
ff_sys.h
This module allow to map several separate file-sub-systems into a root directory
For instance, a system with 3 sub sytems:
/flash : NAND flash driver
/ram : RAM-disk driver
/ : SD-card driver
In this example, the SD-card driver handles ALL files and directories which
do not match /flash/ * or /ram/ *
Now for instance a file call "/flash/etc/network.ini"
will be stored as "/etc/network.ini" on the NAND drive
This module along with ff_stdio.c make translations between absolute
and relative paths
*/
#ifndef FF_SYS_H
#define FF_SYS_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct FILE_SUB_SYSTEM
{
char pcPath[16];
BaseType_t xPathlen;
FF_IOManager_t *pxManager;
} FF_SubSystem_t;
typedef struct FF_DIR_HANDLER
{
union
{
struct
{
unsigned
bEndOfDir : 1,
bFirstCalled : 1,
bIsValid : 1,
bAddDotEntries : 2;
} bits;
unsigned uFlags;
} u;
/*
* path will contain the relative path. It will be used when calling +FAT functions
* like FF_FindFirst() / FF_FindNext()
* For instance, for "/flash/etc" path will become "/etc"
*/
const char *pcPath;
FF_IOManager_t *pxManager; /* Will point to handler of this partition. */
BaseType_t xFSIndex; /* The index of this entry, where 0 always means: the root system. */
} FF_DirHandler_t;
/*
* Initialise (clear) the file system table
* This will also called by FF_FS_Add()
*/
void FF_FS_Init( void );
/*
* Add a file system
* The path must be absolute, e.g. start with a slash
* The second argument is the FF_Disk_t structure that is handling the driver
*/
int FF_FS_Add( const char *pcPath, FF_Disk_t *pxDisk );
/*
* Remove a file system
* which ws earlier added by ff_fs_ad()
*/
void FF_FS_Remove( const char *pcPath );
/*
* Internally used by ff_stdio:
* The ff_dir_handler helps to iterate through a mounte directory
*
* FF_FS_Find() will find a ff_dir_handler for a given path
*/
int FF_FS_Find( const char *pcPath, FF_DirHandler_t *pxHandler );
/*
* For internal use:
* Get the file system information, based on an index
*/
int FF_FS_Get( int iIndex, FF_SubSystem_t *pxSystem );
/*
* Returns the number of registered
* file systems
*/
int FF_FS_Count( void );
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* FF_SYS_H */

View file

@ -0,0 +1,86 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
/**
* @file ff_time.h
* @ingroup TIME
*
* Provides a means for receiving the time on any platform.
**/
#ifndef _FF_TIME_H_
#define _FF_TIME_H_
#include <time.h>
#include "FreeRTOSFATConfig.h"
/* _HT_
The following declarations and functions may be moved to a common directory?
*/
typedef struct xTIME_STRUCT
{
int tm_sec; /* Seconds */
int tm_min; /* Minutes */
int tm_hour; /* Hour (0--23) */
int tm_mday; /* Day of month (1--31) */
int tm_mon; /* Month (0--11) */
int tm_year; /* Year (calendar year minus 1900) */
int tm_wday; /* Weekday (0--6; Sunday = 0) */
int tm_yday; /* Day of year (0--365) */
int tm_isdst; /* 0 if daylight savings time is not in effect) */
} FF_TimeStruct_t;
/* Equivalent of time() : returns the number of seconds after 1-1-1970. */
time_t FreeRTOS_time( time_t *pxTime );
/* Equivalent of mktime() : calculates the number of seconds after 1-1-1970. */
time_t FreeRTOS_mktime( const FF_TimeStruct_t *pxTimeBuf );
/* Equivalent of gmtime_r() : Fills a 'struct tm'. */
FF_TimeStruct_t *FreeRTOS_gmtime_r( const time_t *pxTime, FF_TimeStruct_t *pxTimeBuf );
/**
* @public
* @brief A TIME and DATE object for FreeRTOS+FAT. A FreeRTOS+FAT time driver must populate these values.
*
**/
typedef struct
{
uint16_t Year; /* Year (e.g. 2009). */
uint16_t Month; /* Month (e.g. 1 = Jan, 12 = Dec). */
uint16_t Day; /* Day (1 - 31). */
uint16_t Hour; /* Hour (0 - 23). */
uint16_t Minute; /* Min (0 - 59). */
uint16_t Second; /* Second (0 - 59). */
} FF_SystemTime_t;
/*---------- PROTOTYPES */
int32_t FF_GetSystemTime(FF_SystemTime_t *pxTime);
#endif

View file

@ -0,0 +1,815 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
/* Standard includes. */
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "portmacro.h"
/* FreeRTOS+FAT includes. */
#include "ff_sddisk.h"
#include "ff_sys.h"
/* Atmel includes. */
#include <board.h>
#include <sd_mmc.h>
#include "hr_gettime.h"
/* Misc definitions. */
#define sdSIGNATURE 0x41404342UL
#define sdHUNDRED_64_BIT ( 100ull )
#define sdBYTES_PER_MB ( 1024ull * 1024ull )
#define sdSECTORS_PER_MB ( sdBYTES_PER_MB / 512ull )
#define sdIOMAN_MEM_SIZE 4096
#define xSDCardInfo ( sd_mmc_cards[ 0 ] )
#define sdAligned( pvAddress ) ( ( ( ( size_t ) ( pvAddress ) ) & ( sizeof( size_t ) - 1 ) ) == 0 )
#if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )
/* Define a time-out for all DMA transactions in msec. */
#ifndef sdMAX_TRANSFER_TIME
#define sdMAX_TRANSFER_TIME 4000
#endif
/* Define all possible interrupts of interest. */
#define sdHSMCI_INTERRUPT_FLAGS \
HSMCI_IER_NOTBUSY | \
HSMCI_IER_UNRE | \
HSMCI_IER_OVRE | \
HSMCI_IER_DTOE | \
HSMCI_IER_DCRCE | \
HSMCI_IER_TXBUFE | \
HSMCI_IER_RXBUFF | \
HSMCI_IER_XFRDONE
#define sdMSMCI_USE_SEMAPHORE 1
#endif /* ffconfigSDIO_DRIVER_USES_INTERRUPT */
/*-----------------------------------------------------------*/
#if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )
static TickType_t xDMARemainingTime;
static TimeOut_t xDMATimeOut;
static volatile uint32_t ulSDInterruptStatus;
static volatile int iWaitForWriting;
#if( sdMSMCI_USE_SEMAPHORE != 0 )
static SemaphoreHandle_t xSDSemaphore = NULL;
#else
static TaskHandle_t xSDTaskHandle = NULL;
#endif
#endif /* ffconfigSDIO_DRIVER_USES_INTERRUPT */
/*
* Return pdFALSE if the SD card is not inserted.
*/
static BaseType_t prvSDDetect( void );
/*
* Check if the card is present, and if so, print out some info on the card.
*/
static BaseType_t prvSDMMCInit( BaseType_t xDriveNumber );
/*-----------------------------------------------------------*/
/*
* Mutex for partition.
*/
static SemaphoreHandle_t xPlusFATMutex = NULL;
/*
* Remembers if the card is currently considered to be present.
*/
static BaseType_t xSDCardStatus = pdFALSE;
/*-----------------------------------------------------------*/
typedef struct {
uint32_t ulStart;
uint32_t ulSize;
} MemoryGroup_t;
#define ARRAY_SIZE(x) (int)(sizeof(x)/sizeof(x)[0])
static const MemoryGroup_t xMemories[] = {
{ IRAM_ADDR, IRAM_SIZE },
{ EBI_CS1_ADDR, 512ul * 1024ul },
{ EBI_CS3_ADDR, 512ul * 1024ul },
};
static BaseType_t prvIsInternalRAM( uint8_t *pucBuffer )
{
BaseType_t xResult = pdFALSE, xIndex;
uint32_t ulAddress = ( uint32_t ) pucBuffer;
for( xIndex = 0; xIndex < ARRAY_SIZE( xMemories ); xIndex++ )
{
if( ( ulAddress >= xMemories[ xIndex].ulStart ) && ( ulAddress < xMemories[ xIndex].ulStart + xMemories[ xIndex].ulSize ) )
{
xResult = pdTRUE;
break;
}
}
return xResult;
}
/*-----------------------------------------------------------*/
static int32_t prvFFRead( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk )
{
int32_t lReturnCode = FF_ERR_IOMAN_OUT_OF_BOUNDS_READ | FF_ERRFLAG, lResult = pdFALSE;
if( ( pxDisk != NULL ) &&
( xSDCardStatus == pdPASS ) &&
( pxDisk->ulSignature == sdSIGNATURE ) &&
( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&
( ulSectorNumber < pxDisk->ulNumberOfSectors ) &&
( ( pxDisk->ulNumberOfSectors - ulSectorNumber ) >= ulSectorCount ) )
{
/* As the MCI driver is configured to use DMA, it must be tested that
the buffer is located in internal SRAM ("IRAM") and if it is 4-byte aligned. */
if( sdAligned( pucBuffer ) && prvIsInternalRAM( pucBuffer ) )
{
lResult = sd_physical_read( ulSectorNumber, pucBuffer, ulSectorCount );
}
else
{
uint32_t ulSector;
uint8_t *pucDMABuffer = ffconfigMALLOC( 512ul );
/* The buffer is NOT word-aligned, read to an aligned buffer and then
copy the data to the user provided buffer. */
if( pucDMABuffer != NULL )
{
for( ulSector = 0; ulSector < ulSectorCount; ulSector++ )
{
lResult = sd_physical_read( ulSectorNumber + ulSector, pucDMABuffer, 1 );
if( lResult == pdFALSE )
{
break;
}
/* Copy to the user-provided buffer. */
memcpy( pucBuffer + 512ul * ulSector, pucDMABuffer, 512ul );
}
ffconfigFREE( pucDMABuffer );
}
else
{
FF_PRINTF( "prvFFRead: malloc failed\n" );
lResult = pdFALSE;
}
}
if( lResult != pdFALSE )
{
lReturnCode = 0L;
}
else
{
/* Some error occurred. */
FF_PRINTF( "prvFFRead: %lu: %ld\n", ulSectorNumber, lResult );
}
}
else
{
/* Make sure no random data is in the returned buffer. */
memset( ( void * ) pucBuffer, '\0', ulSectorCount * 512UL );
if( pxDisk->xStatus.bIsInitialised != pdFALSE )
{
FF_PRINTF( "prvFFRead: warning: %lu + %lu > %lu\n", ulSectorNumber, ulSectorCount, pxDisk->ulNumberOfSectors );
}
}
return lReturnCode;
}
/*-----------------------------------------------------------*/
static int32_t prvFFWrite( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk )
{
int32_t lReturnCode = FF_ERR_IOMAN_OUT_OF_BOUNDS_READ | FF_ERRFLAG, lResult = pdFALSE;
if( ( pxDisk != NULL ) &&
( xSDCardStatus == pdPASS ) &&
( pxDisk->ulSignature == sdSIGNATURE ) &&
( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&
( ulSectorNumber < pxDisk->ulNumberOfSectors ) &&
( ( pxDisk->ulNumberOfSectors - ulSectorNumber ) >= ulSectorCount ) )
{
/* As the MCI driver is configured to use DMA, it must be tested that
the buffer is located in internal SRAM ("IRAM") and if it is 4-byte aligned. */
if( sdAligned( pucBuffer ) && prvIsInternalRAM( pucBuffer ) )
{
lResult = sd_physical_write( ulSectorNumber, pucBuffer, ulSectorCount );
}
else
{
uint32_t ulSector;
uint8_t *pucDMABuffer = ffconfigMALLOC( 512ul );
/* The buffer is NOT word-aligned, read to an aligned buffer and then
copy the data to the user provided buffer. */
if( pucDMABuffer != NULL )
{
for( ulSector = 0; ulSector < ulSectorCount; ulSector++ )
{
/* Copy from the user provided buffer to the temporary buffer. */
memcpy( pucDMABuffer, pucBuffer + 512ul * ulSector, 512ul );
lResult = sd_physical_write( ulSectorNumber + ulSector, pucDMABuffer, 1 );
if( lResult == pdFALSE )
{
break;
}
}
ffconfigFREE( pucDMABuffer );
}
else
{
FF_PRINTF( "prvFFWrite: malloc failed\n" );
lResult = pdFALSE;
}
}
if( lResult != pdFALSE )
{
/* No errors. */
lReturnCode = 0L;
}
else
{
FF_PRINTF( "prvFFWrite: %lu: %ld\n", ulSectorNumber, lResult );
}
}
else
{
if( pxDisk->xStatus.bIsInitialised != pdFALSE )
{
FF_PRINTF( "prvFFWrite: warning: %lu + %lu > %lu\n", ulSectorNumber, ulSectorCount, pxDisk->ulNumberOfSectors );
}
}
return lReturnCode;
}
/*-----------------------------------------------------------*/
void FF_SDDiskFlush( FF_Disk_t *pxDisk )
{
if( ( pxDisk != NULL ) &&
( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&
( pxDisk->pxIOManager != NULL ) )
{
FF_FlushCache( pxDisk->pxIOManager );
}
}
/*-----------------------------------------------------------*/
/* Initialise the SDIO driver and mount an SD card */
FF_Disk_t *FF_SDDiskInit( const char *pcName )
{
FF_Error_t xFFError;
BaseType_t xPartitionNumber = 0;
FF_CreationParameters_t xParameters;
FF_Disk_t *pxDisk;
#if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )
{
NVIC_SetPriority( HSMCI_IRQn, configHSMCI_INTERRUPT_PRIORITY );
NVIC_EnableIRQ( HSMCI_IRQn );
#if( sdMSMCI_USE_SEMAPHORE != 0 )
{
if( xSDSemaphore == NULL )
{
xSDSemaphore = xSemaphoreCreateBinary();
}
}
#endif /* sdMSMCI_USE_SEMAPHORE */
}
#endif /* ffconfigSDIO_DRIVER_USES_INTERRUPT */
xSDCardStatus = prvSDMMCInit( 0 );
if( xSDCardStatus == pdPASS )
{
pxDisk = (FF_Disk_t *)ffconfigMALLOC( sizeof( *pxDisk ) );
if( pxDisk != NULL )
{
/* Initialise the created disk structure. */
memset( pxDisk, '\0', sizeof( *pxDisk ) );
/* The Atmel MMC driver sets capacity as a number of KB.
Divide by two to get the number of 512-byte sectors. */
pxDisk->ulNumberOfSectors = xSDCardInfo.capacity << 1;
if( xPlusFATMutex == NULL )
{
xPlusFATMutex = xSemaphoreCreateRecursiveMutex();
}
pxDisk->ulSignature = sdSIGNATURE;
if( xPlusFATMutex != NULL)
{
memset( &xParameters, '\0', sizeof( xParameters ) );
xParameters.ulMemorySize = sdIOMAN_MEM_SIZE;
xParameters.ulSectorSize = 512;
xParameters.fnWriteBlocks = prvFFWrite;
xParameters.fnReadBlocks = prvFFRead;
xParameters.pxDisk = pxDisk;
/* prvFFRead()/prvFFWrite() are not re-entrant and must be
protected with the use of a semaphore. */
xParameters.xBlockDeviceIsReentrant = pdFALSE;
/* The semaphore will be used to protect critical sections in
the +FAT driver, and also to avoid concurrent calls to
prvFFRead()/prvFFWrite() from different tasks. */
xParameters.pvSemaphore = ( void * ) xPlusFATMutex;
pxDisk->pxIOManager = FF_CreateIOManger( &xParameters, &xFFError );
if( pxDisk->pxIOManager == NULL )
{
FF_PRINTF( "FF_SDDiskInit: FF_CreateIOManger: %s\n", (const char*)FF_GetErrMessage( xFFError ) );
FF_SDDiskDelete( pxDisk );
pxDisk = NULL;
}
else
{
pxDisk->xStatus.bIsInitialised = pdTRUE;
pxDisk->xStatus.bPartitionNumber = xPartitionNumber;
if( FF_SDDiskMount( pxDisk ) == 0 )
{
FF_SDDiskDelete( pxDisk );
pxDisk = NULL;
}
else
{
if( pcName == NULL )
{
pcName = "/";
}
FF_FS_Add( pcName, pxDisk );
FF_PRINTF( "FF_SDDiskInit: Mounted SD-card as root \"%s\"\n", pcName );
}
} /* if( pxDisk->pxIOManager != NULL ) */
} /* if( xPlusFATMutex != NULL) */
} /* if( pxDisk != NULL ) */
else
{
FF_PRINTF( "FF_SDDiskInit: Malloc failed\n" );
}
} /* if( xSDCardStatus == pdPASS ) */
else
{
FF_PRINTF( "FF_SDDiskInit: prvSDMMC_Init failed\n" );
pxDisk = NULL;
}
return pxDisk;
}
/*-----------------------------------------------------------*/
BaseType_t FF_SDDiskFormat( FF_Disk_t *pxDisk, BaseType_t xPartitionNumber )
{
FF_Error_t xError;
BaseType_t xReturn = pdFAIL;
xError = FF_Unmount( pxDisk );
if( FF_isERR( xError ) != pdFALSE )
{
FF_PRINTF( "FF_SDDiskFormat: unmount fails: %08x\n", ( unsigned ) xError );
}
else
{
/* Format the drive - try FAT32 with large clusters. */
xError = FF_Format( pxDisk, xPartitionNumber, pdFALSE, pdFALSE);
if( FF_isERR( xError ) )
{
FF_PRINTF( "FF_SDDiskFormat: %s\n", (const char*)FF_GetErrMessage( xError ) );
}
else
{
FF_PRINTF( "FF_SDDiskFormat: OK, now remounting\n" );
pxDisk->xStatus.bPartitionNumber = xPartitionNumber;
xError = FF_SDDiskMount( pxDisk );
FF_PRINTF( "FF_SDDiskFormat: rc %08x\n", ( unsigned )xError );
if( FF_isERR( xError ) == pdFALSE )
{
xReturn = pdPASS;
}
}
}
return xReturn;
}
/*-----------------------------------------------------------*/
BaseType_t FF_SDDiskUnmount( FF_Disk_t *pxDisk )
{
FF_Error_t xFFError;
BaseType_t xReturn = pdPASS;
if( ( pxDisk != NULL ) && ( pxDisk->xStatus.bIsMounted != pdFALSE ) )
{
pxDisk->xStatus.bIsMounted = pdFALSE;
xFFError = FF_Unmount( pxDisk );
if( FF_isERR( xFFError ) )
{
FF_PRINTF( "FF_SDDiskUnmount: rc %08x\n", ( unsigned )xFFError );
xReturn = pdFAIL;
}
else
{
FF_PRINTF( "Drive unmounted\n" );
}
}
return xReturn;
}
/*-----------------------------------------------------------*/
BaseType_t FF_SDDiskReinit( FF_Disk_t *pxDisk )
{
BaseType_t xStatus = prvSDMMCInit( 0 ); /* Hard coded index. */
/*_RB_ parameter not used. */
( void ) pxDisk;
FF_PRINTF( "FF_SDDiskReinit: rc %08x\n", ( unsigned ) xStatus );
return xStatus;
}
/*-----------------------------------------------------------*/
BaseType_t FF_SDDiskMount( FF_Disk_t *pxDisk )
{
FF_Error_t xFFError;
BaseType_t xReturn;
/* Mount the partition */
xFFError = FF_Mount( pxDisk, pxDisk->xStatus.bPartitionNumber );
if( FF_isERR( xFFError ) )
{
FF_PRINTF( "FF_SDDiskMount: %08lX\n", xFFError );
xReturn = pdFAIL;
}
else
{
pxDisk->xStatus.bIsMounted = pdTRUE;
FF_PRINTF( "****** FreeRTOS+FAT initialized %lu sectors\n", pxDisk->pxIOManager->xPartition.ulTotalSectors );
FF_SDDiskShowPartition( pxDisk );
xReturn = pdPASS;
}
return xReturn;
}
/*-----------------------------------------------------------*/
FF_IOManager_t *sddisk_ioman( FF_Disk_t *pxDisk )
{
FF_IOManager_t *pxReturn;
if( ( pxDisk != NULL ) && ( pxDisk->xStatus.bIsInitialised != pdFALSE ) )
{
pxReturn = pxDisk->pxIOManager;
}
else
{
pxReturn = NULL;
}
return pxReturn;
}
/*-----------------------------------------------------------*/
/* Release all resources */
BaseType_t FF_SDDiskDelete( FF_Disk_t *pxDisk )
{
if( pxDisk != NULL )
{
pxDisk->ulSignature = 0;
pxDisk->xStatus.bIsInitialised = 0;
if( pxDisk->pxIOManager != NULL )
{
if( FF_Mounted( pxDisk->pxIOManager ) != pdFALSE )
{
FF_Unmount( pxDisk );
}
FF_DeleteIOManager( pxDisk->pxIOManager );
}
vPortFree( pxDisk );
}
return 1;
}
/*-----------------------------------------------------------*/
BaseType_t FF_SDDiskShowPartition( FF_Disk_t *pxDisk )
{
FF_Error_t xError;
uint64_t ullFreeSectors;
uint32_t ulTotalSizeMB, ulFreeSizeMB;
int iPercentageFree;
FF_IOManager_t *pxIOManager;
const char *pcTypeName = "unknown type";
BaseType_t xReturn = pdPASS;
if( pxDisk == NULL )
{
xReturn = pdFAIL;
}
else
{
pxIOManager = pxDisk->pxIOManager;
FF_PRINTF( "Reading FAT and calculating Free Space\n" );
switch( pxIOManager->xPartition.ucType )
{
case FF_T_FAT12:
pcTypeName = "FAT12";
break;
case FF_T_FAT16:
pcTypeName = "FAT16";
break;
case FF_T_FAT32:
pcTypeName = "FAT32";
break;
default:
pcTypeName = "UNKOWN";
break;
}
FF_GetFreeSize( pxIOManager, &xError );
ullFreeSectors = pxIOManager->xPartition.ulFreeClusterCount * pxIOManager->xPartition.ulSectorsPerCluster;
iPercentageFree = ( int ) ( ( sdHUNDRED_64_BIT * ullFreeSectors + pxIOManager->xPartition.ulDataSectors / 2 ) /
( ( uint64_t )pxIOManager->xPartition.ulDataSectors ) );
ulTotalSizeMB = pxIOManager->xPartition.ulDataSectors / sdSECTORS_PER_MB;
ulFreeSizeMB = ( uint32_t ) ( ullFreeSectors / sdSECTORS_PER_MB );
/* It is better not to use the 64-bit format such as %Lu because it
might not be implemented. */
FF_PRINTF( "Partition Nr %8u\n", pxDisk->xStatus.bPartitionNumber );
FF_PRINTF( "Type %8u (%s)\n", pxIOManager->xPartition.ucType, pcTypeName );
FF_PRINTF( "VolLabel '%8s' \n", pxIOManager->xPartition.pcVolumeLabel );
FF_PRINTF( "TotalSectors %8lu\n", pxIOManager->xPartition.ulTotalSectors );
FF_PRINTF( "SecsPerCluster %8lu\n", pxIOManager->xPartition.ulSectorsPerCluster );
FF_PRINTF( "Size %8lu MB\n", ulTotalSizeMB );
FF_PRINTF( "FreeSize %8lu MB ( %d perc free )\n", ulFreeSizeMB, iPercentageFree );
}
return xReturn;
}
/*-----------------------------------------------------------*/
BaseType_t FF_SDDiskDetect( FF_Disk_t *pxDisk )
{
BaseType_t xIsPresent;
void *pvSemaphore;
if( ( pxDisk != NULL ) && ( pxDisk->pxIOManager ) )
{
pvSemaphore = pxDisk->pxIOManager->pvSemaphore;
}
else
{
pvSemaphore = NULL;
}
/*_RB_ Can these NULL checks be moved inside the FF_nnnSemaphore() functions? */
/*_HT_ I'm afraid not, both functions start with configASSERT( pxSemaphore ); */
if( pvSemaphore != NULL )
{
FF_PendSemaphore( pvSemaphore );
}
xIsPresent = prvSDDetect();
if( pvSemaphore != NULL )
{
FF_ReleaseSemaphore( pvSemaphore );
}
return xIsPresent;
}
/*-----------------------------------------------------------*/
static BaseType_t prvSDDetect( void )
{
static BaseType_t xWasPresent;
BaseType_t xIsPresent;
sd_mmc_err_t xSDPresence;
if( xWasPresent == pdFALSE )
{
/* Try to initialize SD MMC stack */
sd_mmc_init();
xSDPresence = sd_mmc_check( 0 );
if( ( xSDPresence == SD_MMC_OK ) || ( xSDPresence == SD_MMC_INIT_ONGOING ) )
{
xIsPresent = pdTRUE;
}
else
{
xIsPresent = pdFALSE;
}
}
else
{
/* See if the card is still present. */
xSDPresence = sd_mmc_check_status(0);
if( xSDPresence == SD_MMC_OK )
{
xIsPresent = pdTRUE;
}
else
{
xIsPresent = pdFALSE;
}
}
xWasPresent = xIsPresent;
return xIsPresent;
}
/*-----------------------------------------------------------*/
static BaseType_t prvSDMMCInit( BaseType_t xDriveNumber )
{
BaseType_t xReturn;
/* 'xDriveNumber' not yet in use. */
( void ) xDriveNumber;
/* Check if the SD card is plugged in the slot */
if( prvSDDetect() == pdFALSE )
{
FF_PRINTF( "No SD card detected\n" );
xReturn = pdFAIL;
}
else
{
FF_PRINTF( "HAL_SD_Init: type: %s Capacity: %lu MB\n",
xSDCardInfo.type & CARD_TYPE_HC ? "SDHC" : "SD",
( xSDCardInfo.capacity << 1 ) / 2048 );
xReturn = pdPASS;
}
return xReturn;
}
/*-----------------------------------------------------------*/
#if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )
void HSMCI_Handler( void )
{
uint32_t ulSR;
BaseType_t xSwitchRequired = pdFALSE;
ulSR = HSMCI->HSMCI_SR & HSMCI->HSMCI_IMR;
HSMCI->HSMCI_IDR = ulSR;
ulSDInterruptStatus |= ulSR;
#if( sdMSMCI_USE_SEMAPHORE != 0 )
{
if( xSDSemaphore != NULL )
{
xSemaphoreGiveFromISR( xSDSemaphore, &xSwitchRequired );
}
}
#else
{
if( xSDTaskHandle != NULL )
{
vTaskNotifyGiveFromISR( xSDTaskHandle, ( BaseType_t * ) &xSwitchRequired );
}
}
#endif
if( xSwitchRequired != pdFALSE )
{
portEND_SWITCHING_ISR( xSwitchRequired );
}
}
#endif /* ffconfigSDIO_DRIVER_USES_INTERRUPT */
/*-----------------------------------------------------------*/
#if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )
void vMCIEventSetupFunction( int iForWriting )
{
iWaitForWriting = iForWriting != 0;
#if( sdMSMCI_USE_SEMAPHORE == 0 )
{
xSDTaskHandle = xTaskGetCurrentTaskHandle();
}
#endif
ulSDInterruptStatus = 0;
HSMCI->HSMCI_IER = sdHSMCI_INTERRUPT_FLAGS;
/* A DMA transfer to or from the SD-card is about to start.
Reset the timers that will be used in prvEventWaitFunction() */
xDMARemainingTime = pdMS_TO_TICKS( sdMAX_TRANSFER_TIME );
vTaskSetTimeOutState( &xDMATimeOut );
}
#endif /* ffconfigSDIO_DRIVER_USES_INTERRUPT */
/*-----------------------------------------------------------*/
#if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )
void vMCIEventReadyFunction()
{
#if( sdMSMCI_USE_SEMAPHORE == 0 )
{
xSDTaskHandle = NULL;
}
#endif
ulSDInterruptStatus = 0;
HSMCI->HSMCI_IDR = sdHSMCI_INTERRUPT_FLAGS;
}
#endif /* ffconfigSDIO_DRIVER_USES_INTERRUPT */
/*-----------------------------------------------------------*/
#if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )
uint32_t ulMCIEventWaitFunction( uint32_t ulMask )
{
/*
* It was measured how quickly a DMA interrupt was received. It varied
* between 0 and 4 ms.
* <= 1 ms : 8047
* <= 2 ms : 1850
* <= 3 ms : 99
* <= 4 ms : 79
* >= 5 ms : 0 times
*/
if( xTaskCheckForTimeOut( &xDMATimeOut, &xDMARemainingTime ) != pdFALSE )
{
/* The timeout has been reached, no need to block. */
FF_PRINTF( "ulMCIEventWaitFunction: %s timed out. SR = %08x\n",
iWaitForWriting ? "Write" : "Read", ulSDInterruptStatus );
}
else
{
/* The timeout has not been reached yet, block on the semaphore. */
#if( sdMSMCI_USE_SEMAPHORE != 0 )
{
if( ( ulSDInterruptStatus & ulMask ) == 0ul )
{
xSemaphoreTake( xSDSemaphore, xDMARemainingTime );
}
}
#else
{
if( ( ulSDInterruptStatus & ulMask ) == 0ul )
{
ulTaskNotifyTake( pdFALSE, xDMARemainingTime );
}
}
#endif
if( xTaskCheckForTimeOut( &xDMATimeOut, &xDMARemainingTime ) != pdFALSE )
{
FF_PRINTF( "ulMCIEventWaitFunction: %s timed out. SR = %08x\n",
iWaitForWriting ? "Write" : "Read", ulSDInterruptStatus );
}
}
return ulSDInterruptStatus;
}
#endif /* ffconfigSDIO_DRIVER_USES_INTERRUPT */
/*-----------------------------------------------------------*/

View file

@ -0,0 +1,552 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
/* Standard includes. */
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "portmacro.h"
/* FreeRTOS+FAT includes. */
#include "ff_sddisk.h"
#include "ff_sys.h"
/* Atmel includes. */
#include <sd_mmc.h>
/* Misc definitions. */
#define sdSIGNATURE 0x41404342UL
#define sdHUNDRED_64_BIT ( 100ull )
#define sdBYTES_PER_MB ( 1024ull * 1024ull )
#define sdSECTORS_PER_MB ( sdBYTES_PER_MB / 512ull )
#define sdIOMAN_MEM_SIZE 4096
#define xSDCardInfo ( sd_mmc_cards[ 0 ] )
/*-----------------------------------------------------------*/
/*
* Return pdFALSE if the SD card is not inserted.
*/
static BaseType_t prvSDDetect( void );
/*
* Check if the card is present, and if so, print out some info on the card.
*/
static BaseType_t prvSDMMCInit( BaseType_t xDriveNumber );
/*-----------------------------------------------------------*/
/*
* Mutex for partition.
*/
static SemaphoreHandle_t xPlusFATMutex = NULL;
/*
* Remembers if the card is currently considered to be present.
*/
static BaseType_t xSDCardStatus = pdFALSE;
/*-----------------------------------------------------------*/
static int32_t prvFFRead( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk )
{
int32_t lReturnCode = FF_ERR_IOMAN_OUT_OF_BOUNDS_READ | FF_ERRFLAG, lResult;
if( ( pxDisk != NULL ) &&
( xSDCardStatus == pdPASS ) &&
( pxDisk->ulSignature == sdSIGNATURE ) &&
( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&
( ulSectorNumber < pxDisk->ulNumberOfSectors ) &&
( ( pxDisk->ulNumberOfSectors - ulSectorNumber ) >= ulSectorCount ) )
{
lResult = sd_physical_read( ulSectorNumber, pucBuffer, ulSectorCount);
if( lResult != pdFALSE )
{
lReturnCode = 0L;
}
else
{
/* Some error occurred. */
FF_PRINTF( "prvFFRead: %lu: %lu\n", ulSectorNumber, lResult );
}
}
else
{
/* Make sure no random data is in the returned buffer. */
memset( ( void * ) pucBuffer, '\0', ulSectorCount * 512UL );
if( pxDisk->xStatus.bIsInitialised != pdFALSE )
{
FF_PRINTF( "prvFFRead: warning: %lu + %lu > %lu\n", ulSectorNumber, ulSectorCount, pxDisk->ulNumberOfSectors );
}
}
return lReturnCode;
}
/*-----------------------------------------------------------*/
static int32_t prvFFWrite( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk )
{
int32_t lReturnCode = FF_ERR_IOMAN_OUT_OF_BOUNDS_READ | FF_ERRFLAG;
BaseType_t xResult;
if( ( pxDisk != NULL ) &&
( xSDCardStatus == pdPASS ) &&
( pxDisk->ulSignature == sdSIGNATURE ) &&
( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&
( ulSectorNumber < pxDisk->ulNumberOfSectors ) &&
( ( pxDisk->ulNumberOfSectors - ulSectorNumber ) >= ulSectorCount ) )
{
xResult = sd_physical_write( ulSectorNumber, pucBuffer, ulSectorCount );
if( xResult != pdFALSE )
{
/* No errors. */
lReturnCode = 0L;
}
else
{
FF_PRINTF( "prvFFWrite: %lu: %lu\n", ulSectorNumber, xResult );
}
}
else
{
if( pxDisk->xStatus.bIsInitialised != pdFALSE )
{
FF_PRINTF( "prvFFWrite: warning: %lu + %lu > %lu\n", ulSectorNumber, ulSectorCount, pxDisk->ulNumberOfSectors );
}
}
return lReturnCode;
}
/*-----------------------------------------------------------*/
void FF_SDDiskFlush( FF_Disk_t *pxDisk )
{
if( ( pxDisk != NULL ) &&
( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&
( pxDisk->pxIOManager != NULL ) )
{
FF_FlushCache( pxDisk->pxIOManager );
}
}
/*-----------------------------------------------------------*/
/* Initialise the SDIO driver and mount an SD card */
FF_Disk_t *FF_SDDiskInit( const char *pcName )
{
FF_Error_t xFFError;
BaseType_t xPartitionNumber = 0;
FF_CreationParameters_t xParameters;
FF_Disk_t *pxDisk;
xSDCardStatus = prvSDMMCInit( 0 );
if( xSDCardStatus != pdPASS )
{
FF_PRINTF( "FF_SDDiskInit: prvSDMMCInit failed\n" );
pxDisk = NULL;
}
else
{
pxDisk = ( FF_Disk_t * )pvPortMalloc( sizeof( *pxDisk ) );
if( pxDisk == NULL )
{
FF_PRINTF( "FF_SDDiskInit: Malloc failed\n" );
}
else
{
/* Initialise the created disk structure. */
memset( pxDisk, '\0', sizeof( *pxDisk ) );
/* The Atmel MMC driver sets capacity as a number of KB.
Divide by two to get the number of 512-byte sectors. */
pxDisk->ulNumberOfSectors = xSDCardInfo.capacity << 1;
if( xPlusFATMutex == NULL )
{
xPlusFATMutex = xSemaphoreCreateRecursiveMutex();
}
pxDisk->ulSignature = sdSIGNATURE;
if( xPlusFATMutex != NULL)
{
memset( &xParameters, '\0', sizeof( xParameters ) );
xParameters.ulMemorySize = sdIOMAN_MEM_SIZE;
xParameters.ulSectorSize = 512;
xParameters.fnWriteBlocks = prvFFWrite;
xParameters.fnReadBlocks = prvFFRead;
xParameters.pxDisk = pxDisk;
/* prvFFRead()/prvFFWrite() are not re-entrant and must be
protected with the use of a semaphore. */
xParameters.xBlockDeviceIsReentrant = pdFALSE;
/* The semaphore will be used to protect critical sections in
the +FAT driver, and also to avoid concurrent calls to
prvFFRead()/prvFFWrite() from different tasks. */
xParameters.pvSemaphore = ( void * ) xPlusFATMutex;
pxDisk->pxIOManager = FF_CreateIOManger( &xParameters, &xFFError );
if( pxDisk->pxIOManager == NULL )
{
FF_PRINTF( "FF_SDDiskInit: FF_CreateIOManger: %s\n", (const char*)FF_GetErrMessage( xFFError ) );
FF_SDDiskDelete( pxDisk );
pxDisk = NULL;
}
else
{
pxDisk->xStatus.bIsInitialised = pdTRUE;
pxDisk->xStatus.bPartitionNumber = xPartitionNumber;
if( FF_SDDiskMount( pxDisk ) == 0 )
{
FF_SDDiskDelete( pxDisk );
pxDisk = NULL;
}
else
{
if( pcName == NULL )
{
pcName = "/";
}
FF_FS_Add( pcName, pxDisk );
FF_PRINTF( "FF_SDDiskInit: Mounted SD-card as root \"%s\"\n", pcName );
FF_SDDiskShowPartition( pxDisk );
}
} /* if( pxDisk->pxIOManager != NULL ) */
} /* if( xPlusFATMutex != NULL) */
} /* if( pxDisk != NULL ) */
} /* if( xSDCardStatus == pdPASS ) */
return pxDisk;
}
/*-----------------------------------------------------------*/
BaseType_t FF_SDDiskFormat( FF_Disk_t *pxDisk, BaseType_t aPart )
{
FF_Error_t xError;
BaseType_t xReturn = pdFAIL;
xError = FF_Unmount( pxDisk );
if( FF_isERR( xError ) != pdFALSE )
{
FF_PRINTF( "FF_SDDiskFormat: unmount fails: %08x\n", ( unsigned ) xError );
}
else
{
/* Format the drive - try FAT32 with large clusters. */
xError = FF_Format( pxDisk, aPart, pdFALSE, pdFALSE);
if( FF_isERR( xError ) )
{
FF_PRINTF( "FF_SDDiskFormat: %s\n", (const char*)FF_GetErrMessage( xError ) );
}
else
{
FF_PRINTF( "FF_SDDiskFormat: OK, now remounting\n" );
pxDisk->xStatus.bPartitionNumber = aPart;
xError = FF_SDDiskMount( pxDisk );
FF_PRINTF( "FF_SDDiskFormat: rc %08x\n", ( unsigned )xError );
if( FF_isERR( xError ) == pdFALSE )
{
xReturn = pdPASS;
FF_SDDiskShowPartition( pxDisk );
}
}
}
return xReturn;
}
/*-----------------------------------------------------------*/
BaseType_t FF_SDDiskUnmount( FF_Disk_t *pxDisk )
{
FF_Error_t xFFError;
BaseType_t xReturn = pdPASS;
if( ( pxDisk != NULL ) && ( pxDisk->xStatus.bIsMounted != pdFALSE ) )
{
pxDisk->xStatus.bIsMounted = pdFALSE;
xFFError = FF_Unmount( pxDisk );
if( FF_isERR( xFFError ) )
{
FF_PRINTF( "FF_SDDiskUnmount: rc %08x\n", ( unsigned )xFFError );
xReturn = pdFAIL;
}
else
{
FF_PRINTF( "Drive unmounted\n" );
}
}
return xReturn;
}
/*-----------------------------------------------------------*/
BaseType_t FF_SDDiskReinit( FF_Disk_t *pxDisk )
{
BaseType_t xStatus = prvSDMMCInit( 0 ); /* Hard coded index. */
/*_RB_ parameter not used. */
( void ) pxDisk;
FF_PRINTF( "FF_SDDiskReinit: rc %08x\n", ( unsigned ) xStatus );
return xStatus;
}
/*-----------------------------------------------------------*/
BaseType_t FF_SDDiskMount( FF_Disk_t *pxDisk )
{
FF_Error_t xFFError;
BaseType_t xReturn;
/* Mount the partition */
xFFError = FF_Mount( pxDisk, pxDisk->xStatus.bPartitionNumber );
if( FF_isERR( xFFError ) )
{
FF_PRINTF( "FF_SDDiskMount: %08lX\n", xFFError );
xReturn = pdFAIL;
}
else
{
pxDisk->xStatus.bIsMounted = pdTRUE;
FF_PRINTF( "****** FreeRTOS+FAT initialized %lu sectors\n", pxDisk->pxIOManager->xPartition.ulTotalSectors );
xReturn = pdPASS;
}
return xReturn;
}
/*-----------------------------------------------------------*/
FF_IOManager_t *sddisk_ioman( FF_Disk_t *pxDisk )
{
FF_IOManager_t *pxReturn;
if( ( pxDisk != NULL ) && ( pxDisk->xStatus.bIsInitialised != pdFALSE ) )
{
pxReturn = pxDisk->pxIOManager;
}
else
{
pxReturn = NULL;
}
return pxReturn;
}
/*-----------------------------------------------------------*/
/* Release all resources */
BaseType_t FF_SDDiskDelete( FF_Disk_t *pxDisk )
{
if( pxDisk != NULL )
{
pxDisk->ulSignature = 0;
pxDisk->xStatus.bIsInitialised = 0;
if( pxDisk->pxIOManager != NULL )
{
if( FF_Mounted( pxDisk->pxIOManager ) != pdFALSE )
{
FF_Unmount( pxDisk );
}
FF_DeleteIOManager( pxDisk->pxIOManager );
}
vPortFree( pxDisk );
}
return 1;
}
/*-----------------------------------------------------------*/
BaseType_t FF_SDDiskShowPartition( FF_Disk_t *pxDisk )
{
FF_Error_t xError;
uint64_t ullFreeSectors;
uint32_t ulTotalSizeMB, ulFreeSizeMB;
int iPercentageFree;
FF_IOManager_t *pxIOManager;
const char *pcTypeName = "unknown type";
BaseType_t xReturn = pdPASS;
if( pxDisk == NULL )
{
xReturn = pdFAIL;
}
else
{
pxIOManager = pxDisk->pxIOManager;
FF_PRINTF( "Reading FAT and calculating Free Space\n" );
switch( pxIOManager->xPartition.ucType )
{
case FF_T_FAT12:
pcTypeName = "FAT12";
break;
case FF_T_FAT16:
pcTypeName = "FAT16";
break;
case FF_T_FAT32:
pcTypeName = "FAT32";
break;
default:
pcTypeName = "UNKOWN";
break;
}
FF_GetFreeSize( pxIOManager, &xError );
ullFreeSectors = pxIOManager->xPartition.ulFreeClusterCount * pxIOManager->xPartition.ulSectorsPerCluster;
iPercentageFree = ( int ) ( ( sdHUNDRED_64_BIT * ullFreeSectors + pxIOManager->xPartition.ulDataSectors / 2 ) /
( ( uint64_t )pxIOManager->xPartition.ulDataSectors ) );
ulTotalSizeMB = pxIOManager->xPartition.ulDataSectors / sdSECTORS_PER_MB;
ulFreeSizeMB = ( uint32_t ) ( ullFreeSectors / sdSECTORS_PER_MB );
/* It is better not to use the 64-bit format such as %Lu because it
might not be implemented. */
FF_PRINTF( "Partition Nr %8u\n", pxDisk->xStatus.bPartitionNumber );
FF_PRINTF( "Type %8u (%s)\n", pxIOManager->xPartition.ucType, pcTypeName );
FF_PRINTF( "VolLabel '%8s' \n", pxIOManager->xPartition.pcVolumeLabel );
FF_PRINTF( "TotalSectors %8lu\n", pxIOManager->xPartition.ulTotalSectors );
FF_PRINTF( "SecsPerCluster %8lu\n", pxIOManager->xPartition.ulSectorsPerCluster );
FF_PRINTF( "Size %8lu MB\n", ulTotalSizeMB );
FF_PRINTF( "FreeSize %8lu MB ( %d perc free )\n", ulFreeSizeMB, iPercentageFree );
}
return xReturn;
}
/*-----------------------------------------------------------*/
BaseType_t FF_SDDiskDetect( FF_Disk_t *pxDisk )
{
BaseType_t xIsPresent;
void *pvSemaphore;
if( ( pxDisk != NULL ) &&
( pxDisk->pxIOManager ) )
{
pvSemaphore = pxDisk->pxIOManager->pvSemaphore;
}
else
{
pvSemaphore = NULL;
}
/*_RB_ Can these NULL checks be moved inside the FF_nnnSemaphore() functions? */
/*_HT_ I'm afraid not, both functions start with configASSERT( pxSemaphore ); */
if( pvSemaphore != NULL )
{
FF_PendSemaphore( pvSemaphore );
}
xIsPresent = prvSDDetect();
if( pvSemaphore != NULL )
{
FF_ReleaseSemaphore( pvSemaphore );
}
return xIsPresent;
}
/*-----------------------------------------------------------*/
static BaseType_t prvSDDetect( void )
{
static BaseType_t xWasPresent;
BaseType_t xIsPresent;
sd_mmc_err_t xSDPresence;
if( xWasPresent == pdFALSE )
{
/* Try to initialize SD MMC stack */
sd_mmc_init();
xSDPresence = sd_mmc_check( 0 );
if( ( xSDPresence == SD_MMC_OK ) || ( xSDPresence == SD_MMC_INIT_ONGOING ) )
{
xIsPresent = pdTRUE;
}
else
{
xIsPresent = pdFALSE;
}
}
else
{
/* See if the card is still present. */
xSDPresence = sd_mmc_check_status(0);
if( xSDPresence == SD_MMC_OK )
{
xIsPresent = pdTRUE;
}
else
{
xIsPresent = pdFALSE;
}
}
xWasPresent = xIsPresent;
return xIsPresent;
}
/*-----------------------------------------------------------*/
static BaseType_t prvSDMMCInit( BaseType_t xDriveNumber )
{
BaseType_t xReturn;
/* 'xDriveNumber' not yet in use. */
( void ) xDriveNumber;
/* Check if the SD card is plugged in the slot */
if( prvSDDetect() == pdFALSE )
{
FF_PRINTF( "No SD card detected\n" );
xReturn = pdFAIL;
}
else
{
FF_PRINTF( "HAL_SD_Init: type: %s Capacity: %lu MB\n",
xSDCardInfo.type & CARD_TYPE_HC ? "SDHC" : "SD",
( xSDCardInfo.capacity << 1 ) / 2048 );
xReturn = pdPASS;
}
return xReturn;
}
/*-----------------------------------------------------------*/

View file

@ -0,0 +1,11 @@
Disk drivers are provided as examples only, and do not form part of the
FreeRTOS+FAT itself. They:
+ May be based on driver code provided by the chip vendors,
+ May not have been tested in all possible configurations,
+ Will not necessarily be optimised.
+ May not necessarily comply with any particular coding standard.
+ May have dependencies on chip company libraries.
+ May include other hardware board dependencies.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,802 @@
/**
******************************************************************************
* @file stm32f4xx_hal_sd.h
* @author MCD Application Team
* @version V1.3.2
* @date 26-June-2015
* @brief Header file of SD HAL module.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F4xx_HAL_SD_H
#define __STM32F4xx_HAL_SD_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_ll_sdmmc.h"
/** @addtogroup STM32F4xx_HAL_Driver
* @{
*/
/** @defgroup SD SD
* @brief SD HAL module driver
* @{
*/
/* Exported types ------------------------------------------------------------*/
/** @defgroup SD_Exported_Types SD Exported Types
* @{
*/
/** @defgroup SD_Exported_Types_Group1 SD Handle Structure definition
* @{
*/
#define SD_InitTypeDef SDIO_InitTypeDef
#define SD_TypeDef SDIO_TypeDef
struct xSD_Handle;
/* A function will be called at the start of a DMA action. */
typedef void ( * SD_EventSetupFunctionTypeDef )( struct xSD_Handle * /* pxhandle */ );
/* This function is supposed to wait for an event: SDIO or DMA.
* Return non-zero if a timeout has been reached. */
typedef uint32_t ( * SD_EventWaitFunctionTypeDef )( struct xSD_Handle * /* pxhandle */ );
typedef struct xSD_Handle
{
SD_TypeDef *Instance; /*!< SDIO register base address */
SD_InitTypeDef Init; /*!< SD required parameters */
HAL_LockTypeDef Lock; /*!< SD locking object */
uint32_t CardType; /*!< SD card type */
uint32_t RCA; /*!< SD relative card address */
uint32_t CSD[4]; /*!< SD card specific data table */
uint32_t CID[4]; /*!< SD card identification number table */
__IO uint32_t SdTransferCplt; /*!< SD transfer complete flag in non blocking mode */
__IO uint32_t SdTransferErr; /*!< SD transfer error flag in non blocking mode */
__IO uint32_t DmaTransferCplt; /*!< SD DMA transfer complete flag */
__IO uint32_t SdOperation; /*!< SD transfer operation (read/write) */
DMA_HandleTypeDef *hdmarx; /*!< SD Rx DMA handle parameters */
DMA_HandleTypeDef *hdmatx; /*!< SD Tx DMA handle parameters */
SD_EventSetupFunctionTypeDef EventSetupFunction;
SD_EventWaitFunctionTypeDef EventWaitFunction;
}SD_HandleTypeDef;
/**
* @}
*/
/** @defgroup SD_Exported_Types_Group2 Card Specific Data: CSD Register
* @{
*/
typedef struct
{
__IO uint8_t CSDStruct; /*!< CSD structure */
__IO uint8_t SysSpecVersion; /*!< System specification version */
__IO uint8_t Reserved1; /*!< Reserved */
__IO uint8_t TAAC; /*!< Data read access time 1 */
__IO uint8_t NSAC; /*!< Data read access time 2 in CLK cycles */
__IO uint8_t MaxBusClkFrec; /*!< Max. bus clock frequency */
__IO uint16_t CardComdClasses; /*!< Card command classes */
__IO uint8_t RdBlockLen; /*!< Max. read data block length */
__IO uint8_t PartBlockRead; /*!< Partial blocks for read allowed */
__IO uint8_t WrBlockMisalign; /*!< Write block misalignment */
__IO uint8_t RdBlockMisalign; /*!< Read block misalignment */
__IO uint8_t DSRImpl; /*!< DSR implemented */
__IO uint8_t Reserved2; /*!< Reserved */
__IO uint32_t DeviceSize; /*!< Device Size */
__IO uint8_t MaxRdCurrentVDDMin; /*!< Max. read current @ VDD min */
__IO uint8_t MaxRdCurrentVDDMax; /*!< Max. read current @ VDD max */
__IO uint8_t MaxWrCurrentVDDMin; /*!< Max. write current @ VDD min */
__IO uint8_t MaxWrCurrentVDDMax; /*!< Max. write current @ VDD max */
__IO uint8_t DeviceSizeMul; /*!< Device size multiplier */
__IO uint8_t EraseGrSize; /*!< Erase group size */
__IO uint8_t EraseGrMul; /*!< Erase group size multiplier */
__IO uint8_t WrProtectGrSize; /*!< Write protect group size */
__IO uint8_t WrProtectGrEnable; /*!< Write protect group enable */
__IO uint8_t ManDeflECC; /*!< Manufacturer default ECC */
__IO uint8_t WrSpeedFact; /*!< Write speed factor */
__IO uint8_t MaxWrBlockLen; /*!< Max. write data block length */
__IO uint8_t WriteBlockPaPartial; /*!< Partial blocks for write allowed */
__IO uint8_t Reserved3; /*!< Reserved */
__IO uint8_t ContentProtectAppli; /*!< Content protection application */
__IO uint8_t FileFormatGrouop; /*!< File format group */
__IO uint8_t CopyFlag; /*!< Copy flag (OTP) */
__IO uint8_t PermWrProtect; /*!< Permanent write protection */
__IO uint8_t TempWrProtect; /*!< Temporary write protection */
__IO uint8_t FileFormat; /*!< File format */
__IO uint8_t ECC; /*!< ECC code */
__IO uint8_t CSD_CRC; /*!< CSD CRC */
__IO uint8_t Reserved4; /*!< Always 1 */
}HAL_SD_CSDTypedef;
/**
* @}
*/
/** @defgroup SD_Exported_Types_Group3 Card Identification Data: CID Register
* @{
*/
typedef struct
{
__IO uint8_t ManufacturerID; /*!< Manufacturer ID */
__IO uint16_t OEM_AppliID; /*!< OEM/Application ID */
__IO uint32_t ProdName1; /*!< Product Name part1 */
__IO uint8_t ProdName2; /*!< Product Name part2 */
__IO uint8_t ProdRev; /*!< Product Revision */
__IO uint32_t ProdSN; /*!< Product Serial Number */
__IO uint8_t Reserved1; /*!< Reserved1 */
__IO uint16_t ManufactDate; /*!< Manufacturing Date */
__IO uint8_t CID_CRC; /*!< CID CRC */
__IO uint8_t Reserved2; /*!< Always 1 */
}HAL_SD_CIDTypedef;
/**
* @}
*/
/** @defgroup SD_Exported_Types_Group4 SD Card Status returned by ACMD13
* @{
*/
typedef struct
{
__IO uint8_t DAT_BUS_WIDTH; /*!< Shows the currently defined data bus width */
__IO uint8_t SECURED_MODE; /*!< Card is in secured mode of operation */
__IO uint16_t SD_CARD_TYPE; /*!< Carries information about card type */
__IO uint32_t SIZE_OF_PROTECTED_AREA; /*!< Carries information about the capacity of protected area */
__IO uint8_t SPEED_CLASS; /*!< Carries information about the speed class of the card */
__IO uint8_t PERFORMANCE_MOVE; /*!< Carries information about the card's performance move */
__IO uint8_t AU_SIZE; /*!< Carries information about the card's allocation unit size */
__IO uint16_t ERASE_SIZE; /*!< Determines the number of AUs to be erased in one operation */
__IO uint8_t ERASE_TIMEOUT; /*!< Determines the timeout for any number of AU erase */
__IO uint8_t ERASE_OFFSET; /*!< Carries information about the erase offset */
}HAL_SD_CardStatusTypedef;
/**
* @}
*/
/** @defgroup SD_Exported_Types_Group5 SD Card information structure
* @{
*/
typedef struct
{
HAL_SD_CSDTypedef SD_csd; /*!< SD card specific data register */
HAL_SD_CIDTypedef SD_cid; /*!< SD card identification number register */
uint64_t CardCapacity; /*!< Card capacity */
uint32_t CardBlockSize; /*!< Card block size */
uint16_t RCA; /*!< SD relative card address */
uint8_t CardType; /*!< SD card type */
}HAL_SD_CardInfoTypedef;
/**
* @}
*/
/** @defgroup SD_Exported_Types_Group6 SD Error status enumeration Structure definition
* @{
*/
typedef enum
{
/**
* @brief SD specific error defines
*/
SD_CMD_CRC_FAIL = (1), /*!< Command response received (but CRC check failed) */
SD_DATA_CRC_FAIL = (2), /*!< Data block sent/received (CRC check failed) */
SD_CMD_RSP_TIMEOUT = (3), /*!< Command response timeout */
SD_DATA_TIMEOUT = (4), /*!< Data timeout */
SD_TX_UNDERRUN = (5), /*!< Transmit FIFO underrun */
SD_RX_OVERRUN = (6), /*!< Receive FIFO overrun */
SD_START_BIT_ERR = (7), /*!< Start bit not detected on all data signals in wide bus mode */
SD_CMD_OUT_OF_RANGE = (8), /*!< Command's argument was out of range. */
SD_ADDR_MISALIGNED = (9), /*!< Misaligned address */
SD_BLOCK_LEN_ERR = (10), /*!< Transferred block length is not allowed for the card or the number of transferred bytes does not match the block length */
SD_ERASE_SEQ_ERR = (11), /*!< An error in the sequence of erase command occurs. */
SD_BAD_ERASE_PARAM = (12), /*!< An invalid selection for erase groups */
SD_WRITE_PROT_VIOLATION = (13), /*!< Attempt to program a write protect block */
SD_LOCK_UNLOCK_FAILED = (14), /*!< Sequence or password error has been detected in unlock command or if there was an attempt to access a locked card */
SD_COM_CRC_FAILED = (15), /*!< CRC check of the previous command failed */
SD_ILLEGAL_CMD = (16), /*!< Command is not legal for the card state */
SD_CARD_ECC_FAILED = (17), /*!< Card internal ECC was applied but failed to correct the data */
SD_CC_ERROR = (18), /*!< Internal card controller error */
SD_GENERAL_UNKNOWN_ERROR = (19), /*!< General or unknown error */
SD_STREAM_READ_UNDERRUN = (20), /*!< The card could not sustain data transfer in stream read operation. */
SD_STREAM_WRITE_OVERRUN = (21), /*!< The card could not sustain data programming in stream mode */
SD_CID_CSD_OVERWRITE = (22), /*!< CID/CSD overwrite error */
SD_WP_ERASE_SKIP = (23), /*!< Only partial address space was erased */
SD_CARD_ECC_DISABLED = (24), /*!< Command has been executed without using internal ECC */
SD_ERASE_RESET = (25), /*!< Erase sequence was cleared before executing because an out of erase sequence command was received */
SD_AKE_SEQ_ERROR = (26), /*!< Error in sequence of authentication. */
SD_INVALID_VOLTRANGE = (27),
SD_ADDR_OUT_OF_RANGE = (28),
SD_SWITCH_ERROR = (29),
SD_SDIO_DISABLED = (30),
SD_SDIO_FUNCTION_BUSY = (31),
SD_SDIO_FUNCTION_FAILED = (32),
SD_SDIO_UNKNOWN_FUNCTION = (33),
/**
* @brief Standard error defines
*/
SD_INTERNAL_ERROR = (34),
SD_NOT_CONFIGURED = (35),
SD_REQUEST_PENDING = (36),
SD_REQUEST_NOT_APPLICABLE = (37),
SD_INVALID_PARAMETER = (38),
SD_UNSUPPORTED_FEATURE = (39),
SD_UNSUPPORTED_HW = (40),
SD_ERROR = (41),
SD_OK = (0)
}HAL_SD_ErrorTypedef;
/**
* @}
*/
/** @defgroup SD_Exported_Types_Group7 SD Transfer state enumeration structure
* @{
*/
typedef enum
{
SD_TRANSFER_OK = 0, /*!< Transfer success */
SD_TRANSFER_BUSY = 1, /*!< Transfer is occurring */
SD_TRANSFER_ERROR = 2 /*!< Transfer failed */
}HAL_SD_TransferStateTypedef;
/**
* @}
*/
/** @defgroup SD_Exported_Types_Group8 SD Card State enumeration structure
* @{
*/
typedef enum
{
SD_CARD_READY = ((uint32_t)0x00000001), /*!< Card state is ready */
SD_CARD_IDENTIFICATION = ((uint32_t)0x00000002), /*!< Card is in identification state */
SD_CARD_STANDBY = ((uint32_t)0x00000003), /*!< Card is in standby state */
SD_CARD_TRANSFER = ((uint32_t)0x00000004), /*!< Card is in transfer state */
SD_CARD_SENDING = ((uint32_t)0x00000005), /*!< Card is sending an operation */
SD_CARD_RECEIVING = ((uint32_t)0x00000006), /*!< Card is receiving operation information */
SD_CARD_PROGRAMMING = ((uint32_t)0x00000007), /*!< Card is in programming state */
SD_CARD_DISCONNECTED = ((uint32_t)0x00000008), /*!< Card is disconnected */
SD_CARD_ERROR = ((uint32_t)0x000000FF) /*!< Card is in error state */
}HAL_SD_CardStateTypedef;
/**
* @}
*/
/** @defgroup SD_Exported_Types_Group9 SD Operation enumeration structure
* @{
*/
typedef enum
{
SD_READ_SINGLE_BLOCK = 0, /*!< Read single block operation */
SD_READ_MULTIPLE_BLOCK = 1, /*!< Read multiple blocks operation */
SD_WRITE_SINGLE_BLOCK = 2, /*!< Write single block operation */
SD_WRITE_MULTIPLE_BLOCK = 3 /*!< Write multiple blocks operation */
}HAL_SD_OperationTypedef;
/**
* @}
*/
/**
* @}
*/
/* Exported constants --------------------------------------------------------*/
/** @defgroup SD_Exported_Constants SD Exported Constants
* @{
*/
/**
* @brief SD Commands Index
*/
#define SD_CMD_GO_IDLE_STATE ((uint8_t)0) /*!< Resets the SD memory card. */
#define SD_CMD_SEND_OP_COND ((uint8_t)1) /*!< Sends host capacity support information and activates the card's initialization process. */
#define SD_CMD_ALL_SEND_CID ((uint8_t)2) /*!< Asks any card connected to the host to send the CID numbers on the CMD line. */
#define SD_CMD_SET_REL_ADDR ((uint8_t)3) /*!< Asks the card to publish a new relative address (RCA). */
#define SD_CMD_SET_DSR ((uint8_t)4) /*!< Programs the DSR of all cards. */
#define SD_CMD_SDIO_SEN_OP_COND ((uint8_t)5) /*!< Sends host capacity support information (HCS) and asks the accessed card to send its
operating condition register (OCR) content in the response on the CMD line. */
#define SD_CMD_HS_SWITCH ((uint8_t)6) /*!< Checks switchable function (mode 0) and switch card function (mode 1). */
#define SD_CMD_SEL_DESEL_CARD ((uint8_t)7) /*!< Selects the card by its own relative address and gets deselected by any other address */
#define SD_CMD_HS_SEND_EXT_CSD ((uint8_t)8) /*!< Sends SD Memory Card interface condition, which includes host supply voltage information
and asks the card whether card supports voltage. */
#define SD_CMD_SEND_CSD ((uint8_t)9) /*!< Addressed card sends its card specific data (CSD) on the CMD line. */
#define SD_CMD_SEND_CID ((uint8_t)10) /*!< Addressed card sends its card identification (CID) on the CMD line. */
#define SD_CMD_READ_DAT_UNTIL_STOP ((uint8_t)11) /*!< SD card doesn't support it. */
#define SD_CMD_STOP_TRANSMISSION ((uint8_t)12) /*!< Forces the card to stop transmission. */
#define SD_CMD_SEND_STATUS ((uint8_t)13) /*!< Addressed card sends its status register. */
#define SD_CMD_HS_BUSTEST_READ ((uint8_t)14)
#define SD_CMD_GO_INACTIVE_STATE ((uint8_t)15) /*!< Sends an addressed card into the inactive state. */
#define SD_CMD_SET_BLOCKLEN ((uint8_t)16) /*!< Sets the block length (in bytes for SDSC) for all following block commands
(read, write, lock). Default block length is fixed to 512 Bytes. Not effective
for SDHS and SDXC. */
#define SD_CMD_READ_SINGLE_BLOCK ((uint8_t)17) /*!< Reads single block of size selected by SET_BLOCKLEN in case of SDSC, and a block of
fixed 512 bytes in case of SDHC and SDXC. */
#define SD_CMD_READ_MULT_BLOCK ((uint8_t)18) /*!< Continuously transfers data blocks from card to host until interrupted by
STOP_TRANSMISSION command. */
#define SD_CMD_HS_BUSTEST_WRITE ((uint8_t)19) /*!< 64 bytes tuning pattern is sent for SDR50 and SDR104. */
#define SD_CMD_WRITE_DAT_UNTIL_STOP ((uint8_t)20) /*!< Speed class control command. */
#define SD_CMD_SET_BLOCK_COUNT ((uint8_t)23) /*!< Specify block count for CMD18 and CMD25. */
#define SD_CMD_WRITE_SINGLE_BLOCK ((uint8_t)24) /*!< Writes single block of size selected by SET_BLOCKLEN in case of SDSC, and a block of
fixed 512 bytes in case of SDHC and SDXC. */
#define SD_CMD_WRITE_MULT_BLOCK ((uint8_t)25) /*!< Continuously writes blocks of data until a STOP_TRANSMISSION follows. */
#define SD_CMD_PROG_CID ((uint8_t)26) /*!< Reserved for manufacturers. */
#define SD_CMD_PROG_CSD ((uint8_t)27) /*!< Programming of the programmable bits of the CSD. */
#define SD_CMD_SET_WRITE_PROT ((uint8_t)28) /*!< Sets the write protection bit of the addressed group. */
#define SD_CMD_CLR_WRITE_PROT ((uint8_t)29) /*!< Clears the write protection bit of the addressed group. */
#define SD_CMD_SEND_WRITE_PROT ((uint8_t)30) /*!< Asks the card to send the status of the write protection bits. */
#define SD_CMD_SD_ERASE_GRP_START ((uint8_t)32) /*!< Sets the address of the first write block to be erased. (For SD card only). */
#define SD_CMD_SD_ERASE_GRP_END ((uint8_t)33) /*!< Sets the address of the last write block of the continuous range to be erased. */
#define SD_CMD_ERASE_GRP_START ((uint8_t)35) /*!< Sets the address of the first write block to be erased. Reserved for each command
system set by switch function command (CMD6). */
#define SD_CMD_ERASE_GRP_END ((uint8_t)36) /*!< Sets the address of the last write block of the continuous range to be erased.
Reserved for each command system set by switch function command (CMD6). */
#define SD_CMD_ERASE ((uint8_t)38) /*!< Reserved for SD security applications. */
#define SD_CMD_FAST_IO ((uint8_t)39) /*!< SD card doesn't support it (Reserved). */
#define SD_CMD_GO_IRQ_STATE ((uint8_t)40) /*!< SD card doesn't support it (Reserved). */
#define SD_CMD_LOCK_UNLOCK ((uint8_t)42) /*!< Sets/resets the password or lock/unlock the card. The size of the data block is set by
the SET_BLOCK_LEN command. */
#define SD_CMD_APP_CMD ((uint8_t)55) /*!< Indicates to the card that the next command is an application specific command rather
than a standard command. */
#define SD_CMD_GEN_CMD ((uint8_t)56) /*!< Used either to transfer a data block to the card or to get a data block from the card
for general purpose/application specific commands. */
#define SD_CMD_NO_CMD ((uint8_t)64)
/**
* @brief Following commands are SD Card Specific commands.
* SDIO_APP_CMD should be sent before sending these commands.
*/
#define SD_CMD_APP_SD_SET_BUSWIDTH ((uint8_t)6) /*!< (ACMD6) Defines the data bus width to be used for data transfer. The allowed data bus
widths are given in SCR register. */
#define SD_CMD_SD_APP_STATUS ((uint8_t)13) /*!< (ACMD13) Sends the SD status. */
#define SD_CMD_SD_APP_SEND_NUM_WRITE_BLOCKS ((uint8_t)22) /*!< (ACMD22) Sends the number of the written (without errors) write blocks. Responds with
32bit+CRC data block. */
#define SD_CMD_SD_APP_OP_COND ((uint8_t)41) /*!< (ACMD41) Sends host capacity support information (HCS) and asks the accessed card to
send its operating condition register (OCR) content in the response on the CMD line. */
#define SD_CMD_SD_APP_SET_CLR_CARD_DETECT ((uint8_t)42) /*!< (ACMD42) Connects/Disconnects the 50 KOhm pull-up resistor on CD/DAT3 (pin 1) of the card. */
#define SD_CMD_SD_APP_SEND_SCR ((uint8_t)51) /*!< Reads the SD Configuration Register (SCR). */
#define SD_CMD_SDIO_RW_DIRECT ((uint8_t)52) /*!< For SD I/O card only, reserved for security specification. */
#define SD_CMD_SDIO_RW_EXTENDED ((uint8_t)53) /*!< For SD I/O card only, reserved for security specification. */
/**
* @brief Following commands are SD Card Specific security commands.
* SD_CMD_APP_CMD should be sent before sending these commands.
*/
#define SD_CMD_SD_APP_GET_MKB ((uint8_t)43) /*!< For SD card only */
#define SD_CMD_SD_APP_GET_MID ((uint8_t)44) /*!< For SD card only */
#define SD_CMD_SD_APP_SET_CER_RN1 ((uint8_t)45) /*!< For SD card only */
#define SD_CMD_SD_APP_GET_CER_RN2 ((uint8_t)46) /*!< For SD card only */
#define SD_CMD_SD_APP_SET_CER_RES2 ((uint8_t)47) /*!< For SD card only */
#define SD_CMD_SD_APP_GET_CER_RES1 ((uint8_t)48) /*!< For SD card only */
#define SD_CMD_SD_APP_SECURE_READ_MULTIPLE_BLOCK ((uint8_t)18) /*!< For SD card only */
#define SD_CMD_SD_APP_SECURE_WRITE_MULTIPLE_BLOCK ((uint8_t)25) /*!< For SD card only */
#define SD_CMD_SD_APP_SECURE_ERASE ((uint8_t)38) /*!< For SD card only */
#define SD_CMD_SD_APP_CHANGE_SECURE_AREA ((uint8_t)49) /*!< For SD card only */
#define SD_CMD_SD_APP_SECURE_WRITE_MKB ((uint8_t)48) /*!< For SD card only */
/**
* @brief Supported SD Memory Cards
*/
#define STD_CAPACITY_SD_CARD_V1_1 ((uint32_t)0x00000000)
#define STD_CAPACITY_SD_CARD_V2_0 ((uint32_t)0x00000001)
#define HIGH_CAPACITY_SD_CARD ((uint32_t)0x00000002)
#define MULTIMEDIA_CARD ((uint32_t)0x00000003)
#define SECURE_DIGITAL_IO_CARD ((uint32_t)0x00000004)
#define HIGH_SPEED_MULTIMEDIA_CARD ((uint32_t)0x00000005)
#define SECURE_DIGITAL_IO_COMBO_CARD ((uint32_t)0x00000006)
#define HIGH_CAPACITY_MMC_CARD ((uint32_t)0x00000007)
/**
* @}
*/
/* Exported macro ------------------------------------------------------------*/
/** @defgroup SD_Exported_macros SD Exported Macros
* @brief macros to handle interrupts and specific clock configurations
* @{
*/
/**
* @brief Enable the SD device.
* @retval None
*/
#define __HAL_SD_SDIO_ENABLE() __SDIO_ENABLE()
/**
* @brief Disable the SD device.
* @retval None
*/
#define __HAL_SD_SDIO_DISABLE() __SDIO_DISABLE()
/**
* @brief Enable the SDIO DMA transfer.
* @retval None
*/
#define __HAL_SD_SDIO_DMA_ENABLE() __SDIO_DMA_ENABLE()
/**
* @brief Disable the SDIO DMA transfer.
* @retval None
*/
#define __HAL_SD_SDIO_DMA_DISABLE() __SDIO_DMA_DISABLE()
/**
* @brief Enable the SD device interrupt.
* @param __HANDLE__: SD Handle
* @param __INTERRUPT__: specifies the SDIO interrupt sources to be enabled.
* This parameter can be one or a combination of the following values:
* @arg SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt
* @arg SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt
* @arg SDIO_IT_CTIMEOUT: Command response timeout interrupt
* @arg SDIO_IT_DTIMEOUT: Data timeout interrupt
* @arg SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt
* @arg SDIO_IT_RXOVERR: Received FIFO overrun error interrupt
* @arg SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt
* @arg SDIO_IT_CMDSENT: Command sent (no response required) interrupt
* @arg SDIO_IT_DATAEND: Data end (data counter, SDIDCOUNT, is zero) interrupt
* @arg SDIO_IT_STBITERR: Start bit not detected on all data signals in wide
* bus mode interrupt
* @arg SDIO_IT_DBCKEND: Data block sent/received (CRC check passed) interrupt
* @arg SDIO_IT_CMDACT: Command transfer in progress interrupt
* @arg SDIO_IT_TXACT: Data transmit in progress interrupt
* @arg SDIO_IT_RXACT: Data receive in progress interrupt
* @arg SDIO_IT_TXFIFOHE: Transmit FIFO Half Empty interrupt
* @arg SDIO_IT_RXFIFOHF: Receive FIFO Half Full interrupt
* @arg SDIO_IT_TXFIFOF: Transmit FIFO full interrupt
* @arg SDIO_IT_RXFIFOF: Receive FIFO full interrupt
* @arg SDIO_IT_TXFIFOE: Transmit FIFO empty interrupt
* @arg SDIO_IT_RXFIFOE: Receive FIFO empty interrupt
* @arg SDIO_IT_TXDAVL: Data available in transmit FIFO interrupt
* @arg SDIO_IT_RXDAVL: Data available in receive FIFO interrupt
* @arg SDIO_IT_SDIOIT: SD I/O interrupt received interrupt
* @arg SDIO_IT_CEATAEND: CE-ATA command completion signal received for CMD61 interrupt
* @retval None
*/
#define __HAL_SD_SDIO_ENABLE_IT(__HANDLE__, __INTERRUPT__) __SDIO_ENABLE_IT((__HANDLE__)->Instance, (__INTERRUPT__))
/**
* @brief Disable the SD device interrupt.
* @param __HANDLE__: SD Handle
* @param __INTERRUPT__: specifies the SDIO interrupt sources to be disabled.
* This parameter can be one or a combination of the following values:
* @arg SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt
* @arg SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt
* @arg SDIO_IT_CTIMEOUT: Command response timeout interrupt
* @arg SDIO_IT_DTIMEOUT: Data timeout interrupt
* @arg SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt
* @arg SDIO_IT_RXOVERR: Received FIFO overrun error interrupt
* @arg SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt
* @arg SDIO_IT_CMDSENT: Command sent (no response required) interrupt
* @arg SDIO_IT_DATAEND: Data end (data counter, SDIDCOUNT, is zero) interrupt
* @arg SDIO_IT_STBITERR: Start bit not detected on all data signals in wide
* bus mode interrupt
* @arg SDIO_IT_DBCKEND: Data block sent/received (CRC check passed) interrupt
* @arg SDIO_IT_CMDACT: Command transfer in progress interrupt
* @arg SDIO_IT_TXACT: Data transmit in progress interrupt
* @arg SDIO_IT_RXACT: Data receive in progress interrupt
* @arg SDIO_IT_TXFIFOHE: Transmit FIFO Half Empty interrupt
* @arg SDIO_IT_RXFIFOHF: Receive FIFO Half Full interrupt
* @arg SDIO_IT_TXFIFOF: Transmit FIFO full interrupt
* @arg SDIO_IT_RXFIFOF: Receive FIFO full interrupt
* @arg SDIO_IT_TXFIFOE: Transmit FIFO empty interrupt
* @arg SDIO_IT_RXFIFOE: Receive FIFO empty interrupt
* @arg SDIO_IT_TXDAVL: Data available in transmit FIFO interrupt
* @arg SDIO_IT_RXDAVL: Data available in receive FIFO interrupt
* @arg SDIO_IT_SDIOIT: SD I/O interrupt received interrupt
* @arg SDIO_IT_CEATAEND: CE-ATA command completion signal received for CMD61 interrupt
* @retval None
*/
#define __HAL_SD_SDIO_DISABLE_IT(__HANDLE__, __INTERRUPT__) __SDIO_DISABLE_IT((__HANDLE__)->Instance, (__INTERRUPT__))
/**
* @brief Check whether the specified SD flag is set or not.
* @param __HANDLE__: SD Handle
* @param __FLAG__: specifies the flag to check.
* This parameter can be one of the following values:
* @arg SDIO_FLAG_CCRCFAIL: Command response received (CRC check failed)
* @arg SDIO_FLAG_DCRCFAIL: Data block sent/received (CRC check failed)
* @arg SDIO_FLAG_CTIMEOUT: Command response timeout
* @arg SDIO_FLAG_DTIMEOUT: Data timeout
* @arg SDIO_FLAG_TXUNDERR: Transmit FIFO underrun error
* @arg SDIO_FLAG_RXOVERR: Received FIFO overrun error
* @arg SDIO_FLAG_CMDREND: Command response received (CRC check passed)
* @arg SDIO_FLAG_CMDSENT: Command sent (no response required)
* @arg SDIO_FLAG_DATAEND: Data end (data counter, SDIDCOUNT, is zero)
* @arg SDIO_FLAG_STBITERR: Start bit not detected on all data signals in wide bus mode.
* @arg SDIO_FLAG_DBCKEND: Data block sent/received (CRC check passed)
* @arg SDIO_FLAG_CMDACT: Command transfer in progress
* @arg SDIO_FLAG_TXACT: Data transmit in progress
* @arg SDIO_FLAG_RXACT: Data receive in progress
* @arg SDIO_FLAG_TXFIFOHE: Transmit FIFO Half Empty
* @arg SDIO_FLAG_RXFIFOHF: Receive FIFO Half Full
* @arg SDIO_FLAG_TXFIFOF: Transmit FIFO full
* @arg SDIO_FLAG_RXFIFOF: Receive FIFO full
* @arg SDIO_FLAG_TXFIFOE: Transmit FIFO empty
* @arg SDIO_FLAG_RXFIFOE: Receive FIFO empty
* @arg SDIO_FLAG_TXDAVL: Data available in transmit FIFO
* @arg SDIO_FLAG_RXDAVL: Data available in receive FIFO
* @arg SDIO_FLAG_SDIOIT: SD I/O interrupt received
* @arg SDIO_FLAG_CEATAEND: CE-ATA command completion signal received for CMD61
* @retval The new state of SD FLAG (SET or RESET).
*/
#define __HAL_SD_SDIO_GET_FLAG(__HANDLE__, __FLAG__) __SDIO_GET_FLAG((__HANDLE__)->Instance, (__FLAG__))
/**
* @brief Clear the SD's pending flags.
* @param __HANDLE__: SD Handle
* @param __FLAG__: specifies the flag to clear.
* This parameter can be one or a combination of the following values:
* @arg SDIO_FLAG_CCRCFAIL: Command response received (CRC check failed)
* @arg SDIO_FLAG_DCRCFAIL: Data block sent/received (CRC check failed)
* @arg SDIO_FLAG_CTIMEOUT: Command response timeout
* @arg SDIO_FLAG_DTIMEOUT: Data timeout
* @arg SDIO_FLAG_TXUNDERR: Transmit FIFO underrun error
* @arg SDIO_FLAG_RXOVERR: Received FIFO overrun error
* @arg SDIO_FLAG_CMDREND: Command response received (CRC check passed)
* @arg SDIO_FLAG_CMDSENT: Command sent (no response required)
* @arg SDIO_FLAG_DATAEND: Data end (data counter, SDIDCOUNT, is zero)
* @arg SDIO_FLAG_STBITERR: Start bit not detected on all data signals in wide bus mode
* @arg SDIO_FLAG_DBCKEND: Data block sent/received (CRC check passed)
* @arg SDIO_FLAG_SDIOIT: SD I/O interrupt received
* @arg SDIO_FLAG_CEATAEND: CE-ATA command completion signal received for CMD61
* @retval None
*/
#define __HAL_SD_SDIO_CLEAR_FLAG(__HANDLE__, __FLAG__) __SDIO_CLEAR_FLAG((__HANDLE__)->Instance, (__FLAG__))
/**
* @brief Check whether the specified SD interrupt has occurred or not.
* @param __HANDLE__: SD Handle
* @param __INTERRUPT__: specifies the SDIO interrupt source to check.
* This parameter can be one of the following values:
* @arg SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt
* @arg SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt
* @arg SDIO_IT_CTIMEOUT: Command response timeout interrupt
* @arg SDIO_IT_DTIMEOUT: Data timeout interrupt
* @arg SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt
* @arg SDIO_IT_RXOVERR: Received FIFO overrun error interrupt
* @arg SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt
* @arg SDIO_IT_CMDSENT: Command sent (no response required) interrupt
* @arg SDIO_IT_DATAEND: Data end (data counter, SDIDCOUNT, is zero) interrupt
* @arg SDIO_IT_STBITERR: Start bit not detected on all data signals in wide
* bus mode interrupt
* @arg SDIO_IT_DBCKEND: Data block sent/received (CRC check passed) interrupt
* @arg SDIO_IT_CMDACT: Command transfer in progress interrupt
* @arg SDIO_IT_TXACT: Data transmit in progress interrupt
* @arg SDIO_IT_RXACT: Data receive in progress interrupt
* @arg SDIO_IT_TXFIFOHE: Transmit FIFO Half Empty interrupt
* @arg SDIO_IT_RXFIFOHF: Receive FIFO Half Full interrupt
* @arg SDIO_IT_TXFIFOF: Transmit FIFO full interrupt
* @arg SDIO_IT_RXFIFOF: Receive FIFO full interrupt
* @arg SDIO_IT_TXFIFOE: Transmit FIFO empty interrupt
* @arg SDIO_IT_RXFIFOE: Receive FIFO empty interrupt
* @arg SDIO_IT_TXDAVL: Data available in transmit FIFO interrupt
* @arg SDIO_IT_RXDAVL: Data available in receive FIFO interrupt
* @arg SDIO_IT_SDIOIT: SD I/O interrupt received interrupt
* @arg SDIO_IT_CEATAEND: CE-ATA command completion signal received for CMD61 interrupt
* @retval The new state of SD IT (SET or RESET).
*/
#define __HAL_SD_SDIO_GET_IT (__HANDLE__, __INTERRUPT__) __SDIO_GET_IT ((__HANDLE__)->Instance, __INTERRUPT__)
/**
* @brief Clear the SD's interrupt pending bits.
* @param __HANDLE__ : SD Handle
* @param __INTERRUPT__: specifies the interrupt pending bit to clear.
* This parameter can be one or a combination of the following values:
* @arg SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt
* @arg SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt
* @arg SDIO_IT_CTIMEOUT: Command response timeout interrupt
* @arg SDIO_IT_DTIMEOUT: Data timeout interrupt
* @arg SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt
* @arg SDIO_IT_RXOVERR: Received FIFO overrun error interrupt
* @arg SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt
* @arg SDIO_IT_CMDSENT: Command sent (no response required) interrupt
* @arg SDIO_IT_DATAEND: Data end (data counter, SDIO_DCOUNT, is zero) interrupt
* @arg SDIO_IT_STBITERR: Start bit not detected on all data signals in wide
* bus mode interrupt
* @arg SDIO_IT_SDIOIT: SD I/O interrupt received interrupt
* @arg SDIO_IT_CEATAEND: CE-ATA command completion signal received for CMD61
* @retval None
*/
#define __HAL_SD_SDIO_CLEAR_IT(__HANDLE__, __INTERRUPT__) __SDIO_CLEAR_IT((__HANDLE__)->Instance, (__INTERRUPT__))
/**
* @}
*/
/* Exported functions --------------------------------------------------------*/
/** @defgroup SD_Exported_Functions SD Exported Functions
* @{
*/
/** @defgroup SD_Exported_Functions_Group1 Initialization and de-initialization functions
* @{
*/
HAL_SD_ErrorTypedef HAL_SD_Init(SD_HandleTypeDef *hsd, HAL_SD_CardInfoTypedef *SDCardInfo);
HAL_StatusTypeDef HAL_SD_DeInit (SD_HandleTypeDef *hsd);
void HAL_SD_MspInit(SD_HandleTypeDef *hsd);
void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd);
/**
* @}
*/
/** @defgroup SD_Exported_Functions_Group2 I/O operation functions
* @{
*/
/* Blocking mode: Polling */
HAL_SD_ErrorTypedef HAL_SD_ReadBlocks(SD_HandleTypeDef *hsd, uint32_t *pReadBuffer, uint64_t ReadAddr, uint32_t BlockSize, uint32_t NumberOfBlocks);
HAL_SD_ErrorTypedef HAL_SD_WriteBlocks(SD_HandleTypeDef *hsd, uint32_t *pWriteBuffer, uint64_t WriteAddr, uint32_t BlockSize, uint32_t NumberOfBlocks);
HAL_SD_ErrorTypedef HAL_SD_Erase(SD_HandleTypeDef *hsd, uint64_t startaddr, uint64_t endaddr);
/* Non-Blocking mode: Interrupt */
void HAL_SD_IRQHandler(SD_HandleTypeDef *hsd);
/* Callback in non blocking modes (DMA) */
void HAL_SD_DMA_RxCpltCallback(DMA_HandleTypeDef *hdma);
void HAL_SD_DMA_RxErrorCallback(DMA_HandleTypeDef *hdma);
void HAL_SD_DMA_TxCpltCallback(DMA_HandleTypeDef *hdma);
void HAL_SD_DMA_TxErrorCallback(DMA_HandleTypeDef *hdma);
void HAL_SD_XferCpltCallback(SD_HandleTypeDef *hsd);
void HAL_SD_XferErrorCallback(SD_HandleTypeDef *hsd);
/* Non-Blocking mode: DMA */
HAL_SD_ErrorTypedef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint32_t *pReadBuffer, uint64_t ReadAddr, uint32_t BlockSize, uint32_t NumberOfBlocks);
HAL_SD_ErrorTypedef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint32_t *pWriteBuffer, uint64_t WriteAddr, uint32_t BlockSize, uint32_t NumberOfBlocks);
HAL_SD_ErrorTypedef HAL_SD_CheckWriteOperation(SD_HandleTypeDef *hsd, uint32_t Timeout);
HAL_SD_ErrorTypedef HAL_SD_CheckReadOperation(SD_HandleTypeDef *hsd, uint32_t Timeout);
/**
* @}
*/
/** @defgroup SD_Exported_Functions_Group3 Peripheral Control functions
* @{
*/
HAL_SD_ErrorTypedef HAL_SD_Get_CardInfo(SD_HandleTypeDef *hsd, HAL_SD_CardInfoTypedef *pCardInfo);
HAL_SD_ErrorTypedef HAL_SD_WideBusOperation_Config(SD_HandleTypeDef *hsd, uint32_t WideMode);
HAL_SD_ErrorTypedef HAL_SD_StopTransfer(SD_HandleTypeDef *hsd);
HAL_SD_ErrorTypedef HAL_SD_HighSpeed (SD_HandleTypeDef *hsd);
/**
* @}
*/
/* Peripheral State functions ************************************************/
/** @defgroup SD_Exported_Functions_Group4 Peripheral State functions
* @{
*/
HAL_SD_ErrorTypedef HAL_SD_SendSDStatus(SD_HandleTypeDef *hsd, uint32_t *pSDstatus);
HAL_SD_ErrorTypedef HAL_SD_GetCardStatus(SD_HandleTypeDef *hsd, HAL_SD_CardStatusTypedef *pCardStatus);
HAL_SD_TransferStateTypedef HAL_SD_GetStatus(SD_HandleTypeDef *hsd);
/**
* @}
*/
/**
* @}
*/
/* Private types -------------------------------------------------------------*/
/** @defgroup SD_Private_Types SD Private Types
* @{
*/
/**
* @}
*/
/* Private defines -----------------------------------------------------------*/
/** @defgroup SD_Private_Defines SD Private Defines
* @{
*/
/**
* @}
*/
/* Private variables ---------------------------------------------------------*/
/** @defgroup SD_Private_Variables SD Private Variables
* @{
*/
/**
* @}
*/
/* Private constants ---------------------------------------------------------*/
/** @defgroup SD_Private_Constants SD Private Constants
* @{
*/
/**
* @}
*/
/* Private macros ------------------------------------------------------------*/
/** @defgroup SD_Private_Macros SD Private Macros
* @{
*/
/**
* @}
*/
/* Private functions prototypes ----------------------------------------------*/
/** @defgroup SD_Private_Functions_Prototypes SD Private Functions Prototypes
* @{
*/
/**
* @}
*/
/* Private functions ---------------------------------------------------------*/
/** @defgroup SD_Private_Functions SD Private Functions
* @{
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __STM32F4xx_HAL_SD_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,788 @@
/**
******************************************************************************
* @file stm32f7xx_hal_sd.h
* @author MCD Application Team
* @version V1.0.0
* @date 12-May-2015
* @brief Header file of SD HAL module.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F7xx_HAL_SD_H
#define __STM32F7xx_HAL_SD_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f7xx_ll_sdmmc.h"
/** @addtogroup STM32F7xx_HAL_Driver
* @{
*/
/** @defgroup SD SD
* @brief SD HAL module driver
* @{
*/
/* Exported types ------------------------------------------------------------*/
/** @defgroup SD_Exported_Types SD Exported Types
* @{
*/
/** @defgroup SD_Exported_Types_Group1 SD Handle Structure definition
* @{
*/
#define SD_InitTypeDef SDMMC_InitTypeDef
#define SD_TypeDef SDMMC_TypeDef
struct xSD_Handle;
/* A function will be called at the start of a DMA action. */
typedef void ( * SD_EventSetupFunctionTypeDef )( struct xSD_Handle * /* pxhandle */ );
/* This function is supposed to wait for an event: SDIO or DMA.
* Return non-zero if a timeout has been reached. */
typedef uint32_t ( * SD_EventWaitFunctionTypeDef )( struct xSD_Handle * /* pxhandle */ );
typedef struct xSD_Handle
{
SD_TypeDef *Instance; /*!< SDMMC register base address */
SD_InitTypeDef Init; /*!< SD required parameters */
HAL_LockTypeDef Lock; /*!< SD locking object */
uint32_t CardType; /*!< SD card type */
uint32_t RCA; /*!< SD relative card address */
uint32_t CSD[4]; /*!< SD card specific data table */
uint32_t CID[4]; /*!< SD card identification number table */
__IO uint32_t SdTransferCplt; /*!< SD transfer complete flag in non blocking mode */
__IO uint32_t SdTransferErr; /*!< SD transfer error flag in non blocking mode */
__IO uint32_t DmaTransferCplt; /*!< SD DMA transfer complete flag */
__IO uint32_t SdOperation; /*!< SD transfer operation (read/write) */
DMA_HandleTypeDef *hdmarx; /*!< SD Rx DMA handle parameters */
DMA_HandleTypeDef *hdmatx; /*!< SD Tx DMA handle parameters */
SD_EventSetupFunctionTypeDef EventSetupFunction;
SD_EventWaitFunctionTypeDef EventWaitFunction;
}SD_HandleTypeDef;
/**
* @}
*/
/** @defgroup SD_Exported_Types_Group2 Card Specific Data: CSD Register
* @{
*/
typedef struct
{
__IO uint8_t CSDStruct; /*!< CSD structure */
__IO uint8_t SysSpecVersion; /*!< System specification version */
__IO uint8_t Reserved1; /*!< Reserved */
__IO uint8_t TAAC; /*!< Data read access time 1 */
__IO uint8_t NSAC; /*!< Data read access time 2 in CLK cycles */
__IO uint8_t MaxBusClkFrec; /*!< Max. bus clock frequency */
__IO uint16_t CardComdClasses; /*!< Card command classes */
__IO uint8_t RdBlockLen; /*!< Max. read data block length */
__IO uint8_t PartBlockRead; /*!< Partial blocks for read allowed */
__IO uint8_t WrBlockMisalign; /*!< Write block misalignment */
__IO uint8_t RdBlockMisalign; /*!< Read block misalignment */
__IO uint8_t DSRImpl; /*!< DSR implemented */
__IO uint8_t Reserved2; /*!< Reserved */
__IO uint32_t DeviceSize; /*!< Device Size */
__IO uint8_t MaxRdCurrentVDDMin; /*!< Max. read current @ VDD min */
__IO uint8_t MaxRdCurrentVDDMax; /*!< Max. read current @ VDD max */
__IO uint8_t MaxWrCurrentVDDMin; /*!< Max. write current @ VDD min */
__IO uint8_t MaxWrCurrentVDDMax; /*!< Max. write current @ VDD max */
__IO uint8_t DeviceSizeMul; /*!< Device size multiplier */
__IO uint8_t EraseGrSize; /*!< Erase group size */
__IO uint8_t EraseGrMul; /*!< Erase group size multiplier */
__IO uint8_t WrProtectGrSize; /*!< Write protect group size */
__IO uint8_t WrProtectGrEnable; /*!< Write protect group enable */
__IO uint8_t ManDeflECC; /*!< Manufacturer default ECC */
__IO uint8_t WrSpeedFact; /*!< Write speed factor */
__IO uint8_t MaxWrBlockLen; /*!< Max. write data block length */
__IO uint8_t WriteBlockPaPartial; /*!< Partial blocks for write allowed */
__IO uint8_t Reserved3; /*!< Reserved */
__IO uint8_t ContentProtectAppli; /*!< Content protection application */
__IO uint8_t FileFormatGrouop; /*!< File format group */
__IO uint8_t CopyFlag; /*!< Copy flag (OTP) */
__IO uint8_t PermWrProtect; /*!< Permanent write protection */
__IO uint8_t TempWrProtect; /*!< Temporary write protection */
__IO uint8_t FileFormat; /*!< File format */
__IO uint8_t ECC; /*!< ECC code */
__IO uint8_t CSD_CRC; /*!< CSD CRC */
__IO uint8_t Reserved4; /*!< Always 1 */
}HAL_SD_CSDTypedef;
/**
* @}
*/
/** @defgroup SD_Exported_Types_Group3 Card Identification Data: CID Register
* @{
*/
typedef struct
{
__IO uint8_t ManufacturerID; /*!< Manufacturer ID */
__IO uint16_t OEM_AppliID; /*!< OEM/Application ID */
__IO uint32_t ProdName1; /*!< Product Name part1 */
__IO uint8_t ProdName2; /*!< Product Name part2 */
__IO uint8_t ProdRev; /*!< Product Revision */
__IO uint32_t ProdSN; /*!< Product Serial Number */
__IO uint8_t Reserved1; /*!< Reserved1 */
__IO uint16_t ManufactDate; /*!< Manufacturing Date */
__IO uint8_t CID_CRC; /*!< CID CRC */
__IO uint8_t Reserved2; /*!< Always 1 */
}HAL_SD_CIDTypedef;
/**
* @}
*/
/** @defgroup SD_Exported_Types_Group4 SD Card Status returned by ACMD13
* @{
*/
typedef struct
{
__IO uint8_t DAT_BUS_WIDTH; /*!< Shows the currently defined data bus width */
__IO uint8_t SECURED_MODE; /*!< Card is in secured mode of operation */
__IO uint16_t SD_CARD_TYPE; /*!< Carries information about card type */
__IO uint32_t SIZE_OF_PROTECTED_AREA; /*!< Carries information about the capacity of protected area */
__IO uint8_t SPEED_CLASS; /*!< Carries information about the speed class of the card */
__IO uint8_t PERFORMANCE_MOVE; /*!< Carries information about the card's performance move */
__IO uint8_t AU_SIZE; /*!< Carries information about the card's allocation unit size */
__IO uint16_t ERASE_SIZE; /*!< Determines the number of AUs to be erased in one operation */
__IO uint8_t ERASE_TIMEOUT; /*!< Determines the timeout for any number of AU erase */
__IO uint8_t ERASE_OFFSET; /*!< Carries information about the erase offset */
}HAL_SD_CardStatusTypedef;
/**
* @}
*/
/** @defgroup SD_Exported_Types_Group5 SD Card information structure
* @{
*/
typedef struct
{
HAL_SD_CSDTypedef SD_csd; /*!< SD card specific data register */
HAL_SD_CIDTypedef SD_cid; /*!< SD card identification number register */
uint64_t CardCapacity; /*!< Card capacity */
uint32_t CardBlockSize; /*!< Card block size */
uint16_t RCA; /*!< SD relative card address */
uint8_t CardType; /*!< SD card type */
}HAL_SD_CardInfoTypedef;
/**
* @}
*/
/** @defgroup SD_Exported_Types_Group6 SD Error status enumeration Structure definition
* @{
*/
typedef enum
{
/**
* @brief SD specific error defines
*/
SD_CMD_CRC_FAIL = (1), /*!< Command response received (but CRC check failed) */
SD_DATA_CRC_FAIL = (2), /*!< Data block sent/received (CRC check failed) */
SD_CMD_RSP_TIMEOUT = (3), /*!< Command response timeout */
SD_DATA_TIMEOUT = (4), /*!< Data timeout */
SD_TX_UNDERRUN = (5), /*!< Transmit FIFO underrun */
SD_RX_OVERRUN = (6), /*!< Receive FIFO overrun */
SD_START_BIT_ERR = (7), /*!< Start bit not detected on all data signals in wide bus mode */
SD_CMD_OUT_OF_RANGE = (8), /*!< Command's argument was out of range. */
SD_ADDR_MISALIGNED = (9), /*!< Misaligned address */
SD_BLOCK_LEN_ERR = (10), /*!< Transferred block length is not allowed for the card or the number of transferred bytes does not match the block length */
SD_ERASE_SEQ_ERR = (11), /*!< An error in the sequence of erase command occurs. */
SD_BAD_ERASE_PARAM = (12), /*!< An invalid selection for erase groups */
SD_WRITE_PROT_VIOLATION = (13), /*!< Attempt to program a write protect block */
SD_LOCK_UNLOCK_FAILED = (14), /*!< Sequence or password error has been detected in unlock command or if there was an attempt to access a locked card */
SD_COM_CRC_FAILED = (15), /*!< CRC check of the previous command failed */
SD_ILLEGAL_CMD = (16), /*!< Command is not legal for the card state */
SD_CARD_ECC_FAILED = (17), /*!< Card internal ECC was applied but failed to correct the data */
SD_CC_ERROR = (18), /*!< Internal card controller error */
SD_GENERAL_UNKNOWN_ERROR = (19), /*!< General or unknown error */
SD_STREAM_READ_UNDERRUN = (20), /*!< The card could not sustain data transfer in stream read operation. */
SD_STREAM_WRITE_OVERRUN = (21), /*!< The card could not sustain data programming in stream mode */
SD_CID_CSD_OVERWRITE = (22), /*!< CID/CSD overwrite error */
SD_WP_ERASE_SKIP = (23), /*!< Only partial address space was erased */
SD_CARD_ECC_DISABLED = (24), /*!< Command has been executed without using internal ECC */
SD_ERASE_RESET = (25), /*!< Erase sequence was cleared before executing because an out of erase sequence command was received */
SD_AKE_SEQ_ERROR = (26), /*!< Error in sequence of authentication. */
SD_INVALID_VOLTRANGE = (27),
SD_ADDR_OUT_OF_RANGE = (28),
SD_SWITCH_ERROR = (29),
SD_SDMMC_DISABLED = (30),
SD_SDMMC_FUNCTION_BUSY = (31),
SD_SDMMC_FUNCTION_FAILED = (32),
SD_SDMMC_UNKNOWN_FUNCTION = (33),
/**
* @brief Standard error defines
*/
SD_INTERNAL_ERROR = (34),
SD_NOT_CONFIGURED = (35),
SD_REQUEST_PENDING = (36),
SD_REQUEST_NOT_APPLICABLE = (37),
SD_INVALID_PARAMETER = (38),
SD_UNSUPPORTED_FEATURE = (39),
SD_UNSUPPORTED_HW = (40),
SD_ERROR = (41),
SD_OK = (0)
}HAL_SD_ErrorTypedef;
/**
* @}
*/
/** @defgroup SD_Exported_Types_Group7 SD Transfer state enumeration structure
* @{
*/
typedef enum
{
SD_TRANSFER_OK = 0, /*!< Transfer success */
SD_TRANSFER_BUSY = 1, /*!< Transfer is occurring */
SD_TRANSFER_ERROR = 2 /*!< Transfer failed */
}HAL_SD_TransferStateTypedef;
/**
* @}
*/
/** @defgroup SD_Exported_Types_Group8 SD Card State enumeration structure
* @{
*/
typedef enum
{
SD_CARD_READY = ((uint32_t)0x00000001), /*!< Card state is ready */
SD_CARD_IDENTIFICATION = ((uint32_t)0x00000002), /*!< Card is in identification state */
SD_CARD_STANDBY = ((uint32_t)0x00000003), /*!< Card is in standby state */
SD_CARD_TRANSFER = ((uint32_t)0x00000004), /*!< Card is in transfer state */
SD_CARD_SENDING = ((uint32_t)0x00000005), /*!< Card is sending an operation */
SD_CARD_RECEIVING = ((uint32_t)0x00000006), /*!< Card is receiving operation information */
SD_CARD_PROGRAMMING = ((uint32_t)0x00000007), /*!< Card is in programming state */
SD_CARD_DISCONNECTED = ((uint32_t)0x00000008), /*!< Card is disconnected */
SD_CARD_ERROR = ((uint32_t)0x000000FF) /*!< Card is in error state */
}HAL_SD_CardStateTypedef;
/**
* @}
*/
/** @defgroup SD_Exported_Types_Group9 SD Operation enumeration structure
* @{
*/
typedef enum
{
SD_READ_SINGLE_BLOCK = 0, /*!< Read single block operation */
SD_READ_MULTIPLE_BLOCK = 1, /*!< Read multiple blocks operation */
SD_WRITE_SINGLE_BLOCK = 2, /*!< Write single block operation */
SD_WRITE_MULTIPLE_BLOCK = 3 /*!< Write multiple blocks operation */
}HAL_SD_OperationTypedef;
/**
* @}
*/
/**
* @}
*/
/* Exported constants --------------------------------------------------------*/
/** @defgroup SD_Exported_Constants SD Exported Constants
* @{
*/
/**
* @brief SD Commands Index
*/
#define SD_CMD_GO_IDLE_STATE ((uint8_t)0) /*!< Resets the SD memory card. */
#define SD_CMD_SEND_OP_COND ((uint8_t)1) /*!< Sends host capacity support information and activates the card's initialization process. */
#define SD_CMD_ALL_SEND_CID ((uint8_t)2) /*!< Asks any card connected to the host to send the CID numbers on the CMD line. */
#define SD_CMD_SET_REL_ADDR ((uint8_t)3) /*!< Asks the card to publish a new relative address (RCA). */
#define SD_CMD_SET_DSR ((uint8_t)4) /*!< Programs the DSR of all cards. */
#define SD_CMD_SDMMC_SEN_OP_COND ((uint8_t)5) /*!< Sends host capacity support information (HCS) and asks the accessed card to send its
operating condition register (OCR) content in the response on the CMD line. */
#define SD_CMD_HS_SWITCH ((uint8_t)6) /*!< Checks switchable function (mode 0) and switch card function (mode 1). */
#define SD_CMD_SEL_DESEL_CARD ((uint8_t)7) /*!< Selects the card by its own relative address and gets deselected by any other address */
#define SD_CMD_HS_SEND_EXT_CSD ((uint8_t)8) /*!< Sends SD Memory Card interface condition, which includes host supply voltage information
and asks the card whether card supports voltage. */
#define SD_CMD_SEND_CSD ((uint8_t)9) /*!< Addressed card sends its card specific data (CSD) on the CMD line. */
#define SD_CMD_SEND_CID ((uint8_t)10) /*!< Addressed card sends its card identification (CID) on the CMD line. */
#define SD_CMD_READ_DAT_UNTIL_STOP ((uint8_t)11) /*!< SD card doesn't support it. */
#define SD_CMD_STOP_TRANSMISSION ((uint8_t)12) /*!< Forces the card to stop transmission. */
#define SD_CMD_SEND_STATUS ((uint8_t)13) /*!< Addressed card sends its status register. */
#define SD_CMD_HS_BUSTEST_READ ((uint8_t)14)
#define SD_CMD_GO_INACTIVE_STATE ((uint8_t)15) /*!< Sends an addressed card into the inactive state. */
#define SD_CMD_SET_BLOCKLEN ((uint8_t)16) /*!< Sets the block length (in bytes for SDSC) for all following block commands
(read, write, lock). Default block length is fixed to 512 Bytes. Not effective
for SDHS and SDXC. */
#define SD_CMD_READ_SINGLE_BLOCK ((uint8_t)17) /*!< Reads single block of size selected by SET_BLOCKLEN in case of SDSC, and a block of
fixed 512 bytes in case of SDHC and SDXC. */
#define SD_CMD_READ_MULT_BLOCK ((uint8_t)18) /*!< Continuously transfers data blocks from card to host until interrupted by
STOP_TRANSMISSION command. */
#define SD_CMD_HS_BUSTEST_WRITE ((uint8_t)19) /*!< 64 bytes tuning pattern is sent for SDR50 and SDR104. */
#define SD_CMD_WRITE_DAT_UNTIL_STOP ((uint8_t)20) /*!< Speed class control command. */
#define SD_CMD_SET_BLOCK_COUNT ((uint8_t)23) /*!< Specify block count for CMD18 and CMD25. */
#define SD_CMD_WRITE_SINGLE_BLOCK ((uint8_t)24) /*!< Writes single block of size selected by SET_BLOCKLEN in case of SDSC, and a block of
fixed 512 bytes in case of SDHC and SDXC. */
#define SD_CMD_WRITE_MULT_BLOCK ((uint8_t)25) /*!< Continuously writes blocks of data until a STOP_TRANSMISSION follows. */
#define SD_CMD_PROG_CID ((uint8_t)26) /*!< Reserved for manufacturers. */
#define SD_CMD_PROG_CSD ((uint8_t)27) /*!< Programming of the programmable bits of the CSD. */
#define SD_CMD_SET_WRITE_PROT ((uint8_t)28) /*!< Sets the write protection bit of the addressed group. */
#define SD_CMD_CLR_WRITE_PROT ((uint8_t)29) /*!< Clears the write protection bit of the addressed group. */
#define SD_CMD_SEND_WRITE_PROT ((uint8_t)30) /*!< Asks the card to send the status of the write protection bits. */
#define SD_CMD_SD_ERASE_GRP_START ((uint8_t)32) /*!< Sets the address of the first write block to be erased. (For SD card only). */
#define SD_CMD_SD_ERASE_GRP_END ((uint8_t)33) /*!< Sets the address of the last write block of the continuous range to be erased. */
#define SD_CMD_ERASE_GRP_START ((uint8_t)35) /*!< Sets the address of the first write block to be erased. Reserved for each command
system set by switch function command (CMD6). */
#define SD_CMD_ERASE_GRP_END ((uint8_t)36) /*!< Sets the address of the last write block of the continuous range to be erased.
Reserved for each command system set by switch function command (CMD6). */
#define SD_CMD_ERASE ((uint8_t)38) /*!< Reserved for SD security applications. */
#define SD_CMD_FAST_IO ((uint8_t)39) /*!< SD card doesn't support it (Reserved). */
#define SD_CMD_GO_IRQ_STATE ((uint8_t)40) /*!< SD card doesn't support it (Reserved). */
#define SD_CMD_LOCK_UNLOCK ((uint8_t)42) /*!< Sets/resets the password or lock/unlock the card. The size of the data block is set by
the SET_BLOCK_LEN command. */
#define SD_CMD_APP_CMD ((uint8_t)55) /*!< Indicates to the card that the next command is an application specific command rather
than a standard command. */
#define SD_CMD_GEN_CMD ((uint8_t)56) /*!< Used either to transfer a data block to the card or to get a data block from the card
for general purpose/application specific commands. */
#define SD_CMD_NO_CMD ((uint8_t)64)
/**
* @brief Following commands are SD Card Specific commands.
* SDMMC_APP_CMD should be sent before sending these commands.
*/
#define SD_CMD_APP_SD_SET_BUSWIDTH ((uint8_t)6) /*!< (ACMD6) Defines the data bus width to be used for data transfer. The allowed data bus
widths are given in SCR register. */
#define SD_CMD_SD_APP_STATUS ((uint8_t)13) /*!< (ACMD13) Sends the SD status. */
#define SD_CMD_SD_APP_SEND_NUM_WRITE_BLOCKS ((uint8_t)22) /*!< (ACMD22) Sends the number of the written (without errors) write blocks. Responds with
32bit+CRC data block. */
#define SD_CMD_SD_APP_OP_COND ((uint8_t)41) /*!< (ACMD41) Sends host capacity support information (HCS) and asks the accessed card to
send its operating condition register (OCR) content in the response on the CMD line. */
#define SD_CMD_SD_APP_SET_CLR_CARD_DETECT ((uint8_t)42) /*!< (ACMD42) Connects/Disconnects the 50 KOhm pull-up resistor on CD/DAT3 (pin 1) of the card. */
#define SD_CMD_SD_APP_SEND_SCR ((uint8_t)51) /*!< Reads the SD Configuration Register (SCR). */
#define SD_CMD_SDMMC_RW_DIRECT ((uint8_t)52) /*!< For SD I/O card only, reserved for security specification. */
#define SD_CMD_SDMMC_RW_EXTENDED ((uint8_t)53) /*!< For SD I/O card only, reserved for security specification. */
/**
* @brief Following commands are SD Card Specific security commands.
* SD_CMD_APP_CMD should be sent before sending these commands.
*/
#define SD_CMD_SD_APP_GET_MKB ((uint8_t)43) /*!< For SD card only */
#define SD_CMD_SD_APP_GET_MID ((uint8_t)44) /*!< For SD card only */
#define SD_CMD_SD_APP_SET_CER_RN1 ((uint8_t)45) /*!< For SD card only */
#define SD_CMD_SD_APP_GET_CER_RN2 ((uint8_t)46) /*!< For SD card only */
#define SD_CMD_SD_APP_SET_CER_RES2 ((uint8_t)47) /*!< For SD card only */
#define SD_CMD_SD_APP_GET_CER_RES1 ((uint8_t)48) /*!< For SD card only */
#define SD_CMD_SD_APP_SECURE_READ_MULTIPLE_BLOCK ((uint8_t)18) /*!< For SD card only */
#define SD_CMD_SD_APP_SECURE_WRITE_MULTIPLE_BLOCK ((uint8_t)25) /*!< For SD card only */
#define SD_CMD_SD_APP_SECURE_ERASE ((uint8_t)38) /*!< For SD card only */
#define SD_CMD_SD_APP_CHANGE_SECURE_AREA ((uint8_t)49) /*!< For SD card only */
#define SD_CMD_SD_APP_SECURE_WRITE_MKB ((uint8_t)48) /*!< For SD card only */
/**
* @brief Supported SD Memory Cards
*/
#define STD_CAPACITY_SD_CARD_V1_1 ((uint32_t)0x00000000)
#define STD_CAPACITY_SD_CARD_V2_0 ((uint32_t)0x00000001)
#define HIGH_CAPACITY_SD_CARD ((uint32_t)0x00000002)
#define MULTIMEDIA_CARD ((uint32_t)0x00000003)
#define SECURE_DIGITAL_IO_CARD ((uint32_t)0x00000004)
#define HIGH_SPEED_MULTIMEDIA_CARD ((uint32_t)0x00000005)
#define SECURE_DIGITAL_IO_COMBO_CARD ((uint32_t)0x00000006)
#define HIGH_CAPACITY_MMC_CARD ((uint32_t)0x00000007)
/**
* @}
*/
/* Exported macro ------------------------------------------------------------*/
/** @defgroup SD_Exported_macros SD Exported Macros
* @brief macros to handle interrupts and specific clock configurations
* @{
*/
/**
* @brief Enable the SD device.
* @retval None
*/
#define __HAL_SD_SDMMC_ENABLE(__HANDLE__) __SDMMC_ENABLE((__HANDLE__)->Instance)
/**
* @brief Disable the SD device.
* @retval None
*/
#define __HAL_SD_SDMMC_DISABLE(__HANDLE__) __SDMMC_DISABLE((__HANDLE__)->Instance)
/**
* @brief Enable the SDMMC DMA transfer.
* @retval None
*/
#define __HAL_SD_SDMMC_DMA_ENABLE(__HANDLE__) __SDMMC_DMA_ENABLE((__HANDLE__)->Instance)
/**
* @brief Disable the SDMMC DMA transfer.
* @retval None
*/
#define __HAL_SD_SDMMC_DMA_DISABLE(__HANDLE__) __SDMMC_DMA_DISABLE((__HANDLE__)->Instance)
/**
* @brief Enable the SD device interrupt.
* @param __HANDLE__: SD Handle
* @param __INTERRUPT__: specifies the SDMMC interrupt sources to be enabled.
* This parameter can be one or a combination of the following values:
* @arg SDMMC_IT_CCRCFAIL: Command response received (CRC check failed) interrupt
* @arg SDMMC_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt
* @arg SDMMC_IT_CTIMEOUT: Command response timeout interrupt
* @arg SDMMC_IT_DTIMEOUT: Data timeout interrupt
* @arg SDMMC_IT_TXUNDERR: Transmit FIFO underrun error interrupt
* @arg SDMMC_IT_RXOVERR: Received FIFO overrun error interrupt
* @arg SDMMC_IT_CMDREND: Command response received (CRC check passed) interrupt
* @arg SDMMC_IT_CMDSENT: Command sent (no response required) interrupt
* @arg SDMMC_IT_DATAEND: Data end (data counter, SDIDCOUNT, is zero) interrupt
* @arg SDMMC_IT_DBCKEND: Data block sent/received (CRC check passed) interrupt
* @arg SDMMC_IT_CMDACT: Command transfer in progress interrupt
* @arg SDMMC_IT_TXACT: Data transmit in progress interrupt
* @arg SDMMC_IT_RXACT: Data receive in progress interrupt
* @arg SDMMC_IT_TXFIFOHE: Transmit FIFO Half Empty interrupt
* @arg SDMMC_IT_RXFIFOHF: Receive FIFO Half Full interrupt
* @arg SDMMC_IT_TXFIFOF: Transmit FIFO full interrupt
* @arg SDMMC_IT_RXFIFOF: Receive FIFO full interrupt
* @arg SDMMC_IT_TXFIFOE: Transmit FIFO empty interrupt
* @arg SDMMC_IT_RXFIFOE: Receive FIFO empty interrupt
* @arg SDMMC_IT_TXDAVL: Data available in transmit FIFO interrupt
* @arg SDMMC_IT_RXDAVL: Data available in receive FIFO interrupt
* @arg SDMMC_IT_SDIOIT: SD I/O interrupt received interrupt
* @retval None
*/
#define __HAL_SD_SDMMC_ENABLE_IT(__HANDLE__, __INTERRUPT__) __SDMMC_ENABLE_IT((__HANDLE__)->Instance, (__INTERRUPT__))
/**
* @brief Disable the SD device interrupt.
* @param __HANDLE__: SD Handle
* @param __INTERRUPT__: specifies the SDMMC interrupt sources to be disabled.
* This parameter can be one or a combination of the following values:
* @arg SDMMC_IT_CCRCFAIL: Command response received (CRC check failed) interrupt
* @arg SDMMC_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt
* @arg SDMMC_IT_CTIMEOUT: Command response timeout interrupt
* @arg SDMMC_IT_DTIMEOUT: Data timeout interrupt
* @arg SDMMC_IT_TXUNDERR: Transmit FIFO underrun error interrupt
* @arg SDMMC_IT_RXOVERR: Received FIFO overrun error interrupt
* @arg SDMMC_IT_CMDREND: Command response received (CRC check passed) interrupt
* @arg SDMMC_IT_CMDSENT: Command sent (no response required) interrupt
* @arg SDMMC_IT_DATAEND: Data end (data counter, SDIDCOUNT, is zero) interrupt
* @arg SDMMC_IT_DBCKEND: Data block sent/received (CRC check passed) interrupt
* @arg SDMMC_IT_CMDACT: Command transfer in progress interrupt
* @arg SDMMC_IT_TXACT: Data transmit in progress interrupt
* @arg SDMMC_IT_RXACT: Data receive in progress interrupt
* @arg SDMMC_IT_TXFIFOHE: Transmit FIFO Half Empty interrupt
* @arg SDMMC_IT_RXFIFOHF: Receive FIFO Half Full interrupt
* @arg SDMMC_IT_TXFIFOF: Transmit FIFO full interrupt
* @arg SDMMC_IT_RXFIFOF: Receive FIFO full interrupt
* @arg SDMMC_IT_TXFIFOE: Transmit FIFO empty interrupt
* @arg SDMMC_IT_RXFIFOE: Receive FIFO empty interrupt
* @arg SDMMC_IT_TXDAVL: Data available in transmit FIFO interrupt
* @arg SDMMC_IT_RXDAVL: Data available in receive FIFO interrupt
* @arg SDMMC_IT_SDIOIT: SD I/O interrupt received interrupt
* @retval None
*/
#define __HAL_SD_SDMMC_DISABLE_IT(__HANDLE__, __INTERRUPT__) __SDMMC_DISABLE_IT((__HANDLE__)->Instance, (__INTERRUPT__))
/**
* @brief Check whether the specified SD flag is set or not.
* @param __HANDLE__: SD Handle
* @param __FLAG__: specifies the flag to check.
* This parameter can be one of the following values:
* @arg SDMMC_FLAG_CCRCFAIL: Command response received (CRC check failed)
* @arg SDMMC_FLAG_DCRCFAIL: Data block sent/received (CRC check failed)
* @arg SDMMC_FLAG_CTIMEOUT: Command response timeout
* @arg SDMMC_FLAG_DTIMEOUT: Data timeout
* @arg SDMMC_FLAG_TXUNDERR: Transmit FIFO underrun error
* @arg SDMMC_FLAG_RXOVERR: Received FIFO overrun error
* @arg SDMMC_FLAG_CMDREND: Command response received (CRC check passed)
* @arg SDMMC_FLAG_CMDSENT: Command sent (no response required)
* @arg SDMMC_FLAG_DATAEND: Data end (data counter, SDIDCOUNT, is zero)
* @arg SDMMC_FLAG_DBCKEND: Data block sent/received (CRC check passed)
* @arg SDMMC_FLAG_CMDACT: Command transfer in progress
* @arg SDMMC_FLAG_TXACT: Data transmit in progress
* @arg SDMMC_FLAG_RXACT: Data receive in progress
* @arg SDMMC_FLAG_TXFIFOHE: Transmit FIFO Half Empty
* @arg SDMMC_FLAG_RXFIFOHF: Receive FIFO Half Full
* @arg SDMMC_FLAG_TXFIFOF: Transmit FIFO full
* @arg SDMMC_FLAG_RXFIFOF: Receive FIFO full
* @arg SDMMC_FLAG_TXFIFOE: Transmit FIFO empty
* @arg SDMMC_FLAG_RXFIFOE: Receive FIFO empty
* @arg SDMMC_FLAG_TXDAVL: Data available in transmit FIFO
* @arg SDMMC_FLAG_RXDAVL: Data available in receive FIFO
* @arg SDMMC_FLAG_SDIOIT: SD I/O interrupt received
* @retval The new state of SD FLAG (SET or RESET).
*/
#define __HAL_SD_SDMMC_GET_FLAG(__HANDLE__, __FLAG__) __SDMMC_GET_FLAG((__HANDLE__)->Instance, (__FLAG__))
/**
* @brief Clear the SD's pending flags.
* @param __HANDLE__: SD Handle
* @param __FLAG__: specifies the flag to clear.
* This parameter can be one or a combination of the following values:
* @arg SDMMC_FLAG_CCRCFAIL: Command response received (CRC check failed)
* @arg SDMMC_FLAG_DCRCFAIL: Data block sent/received (CRC check failed)
* @arg SDMMC_FLAG_CTIMEOUT: Command response timeout
* @arg SDMMC_FLAG_DTIMEOUT: Data timeout
* @arg SDMMC_FLAG_TXUNDERR: Transmit FIFO underrun error
* @arg SDMMC_FLAG_RXOVERR: Received FIFO overrun error
* @arg SDMMC_FLAG_CMDREND: Command response received (CRC check passed)
* @arg SDMMC_FLAG_CMDSENT: Command sent (no response required)
* @arg SDMMC_FLAG_DATAEND: Data end (data counter, SDIDCOUNT, is zero)
* @arg SDMMC_FLAG_DBCKEND: Data block sent/received (CRC check passed)
* @arg SDMMC_FLAG_SDIOIT: SD I/O interrupt received
* @retval None
*/
#define __HAL_SD_SDMMC_CLEAR_FLAG(__HANDLE__, __FLAG__) __SDMMC_CLEAR_FLAG((__HANDLE__)->Instance, (__FLAG__))
/**
* @brief Check whether the specified SD interrupt has occurred or not.
* @param __HANDLE__: SD Handle
* @param __INTERRUPT__: specifies the SDMMC interrupt source to check.
* This parameter can be one of the following values:
* @arg SDMMC_IT_CCRCFAIL: Command response received (CRC check failed) interrupt
* @arg SDMMC_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt
* @arg SDMMC_IT_CTIMEOUT: Command response timeout interrupt
* @arg SDMMC_IT_DTIMEOUT: Data timeout interrupt
* @arg SDMMC_IT_TXUNDERR: Transmit FIFO underrun error interrupt
* @arg SDMMC_IT_RXOVERR: Received FIFO overrun error interrupt
* @arg SDMMC_IT_CMDREND: Command response received (CRC check passed) interrupt
* @arg SDMMC_IT_CMDSENT: Command sent (no response required) interrupt
* @arg SDMMC_IT_DATAEND: Data end (data counter, SDIDCOUNT, is zero) interrupt
* @arg SDMMC_IT_DBCKEND: Data block sent/received (CRC check passed) interrupt
* @arg SDMMC_IT_CMDACT: Command transfer in progress interrupt
* @arg SDMMC_IT_TXACT: Data transmit in progress interrupt
* @arg SDMMC_IT_RXACT: Data receive in progress interrupt
* @arg SDMMC_IT_TXFIFOHE: Transmit FIFO Half Empty interrupt
* @arg SDMMC_IT_RXFIFOHF: Receive FIFO Half Full interrupt
* @arg SDMMC_IT_TXFIFOF: Transmit FIFO full interrupt
* @arg SDMMC_IT_RXFIFOF: Receive FIFO full interrupt
* @arg SDMMC_IT_TXFIFOE: Transmit FIFO empty interrupt
* @arg SDMMC_IT_RXFIFOE: Receive FIFO empty interrupt
* @arg SDMMC_IT_TXDAVL: Data available in transmit FIFO interrupt
* @arg SDMMC_IT_RXDAVL: Data available in receive FIFO interrupt
* @arg SDMMC_IT_SDIOIT: SD I/O interrupt received interrupt
* @retval The new state of SD IT (SET or RESET).
*/
#define __HAL_SD_SDMMC_GET_IT(__HANDLE__, __INTERRUPT__) __SDMMC_GET_IT((__HANDLE__)->Instance, (__INTERRUPT__))
/**
* @brief Clear the SD's interrupt pending bits.
* @param __HANDLE__ : SD Handle
* @param __INTERRUPT__: specifies the interrupt pending bit to clear.
* This parameter can be one or a combination of the following values:
* @arg SDMMC_IT_CCRCFAIL: Command response received (CRC check failed) interrupt
* @arg SDMMC_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt
* @arg SDMMC_IT_CTIMEOUT: Command response timeout interrupt
* @arg SDMMC_IT_DTIMEOUT: Data timeout interrupt
* @arg SDMMC_IT_TXUNDERR: Transmit FIFO underrun error interrupt
* @arg SDMMC_IT_RXOVERR: Received FIFO overrun error interrupt
* @arg SDMMC_IT_CMDREND: Command response received (CRC check passed) interrupt
* @arg SDMMC_IT_CMDSENT: Command sent (no response required) interrupt
* @arg SDMMC_IT_DATAEND: Data end (data counter, SDMMC_DCOUNT, is zero) interrupt
* @arg SDMMC_IT_SDIOIT: SD I/O interrupt received interrupt
* @retval None
*/
#define __HAL_SD_SDMMC_CLEAR_IT(__HANDLE__, __INTERRUPT__) __SDMMC_CLEAR_IT((__HANDLE__)->Instance, (__INTERRUPT__))
/**
* @}
*/
/* Exported functions --------------------------------------------------------*/
/** @defgroup SD_Exported_Functions SD Exported Functions
* @{
*/
/** @defgroup SD_Exported_Functions_Group1 Initialization and de-initialization functions
* @{
*/
HAL_SD_ErrorTypedef HAL_SD_Init(SD_HandleTypeDef *hsd, HAL_SD_CardInfoTypedef *SDCardInfo);
HAL_StatusTypeDef HAL_SD_DeInit (SD_HandleTypeDef *hsd);
void HAL_SD_MspInit(SD_HandleTypeDef *hsd);
void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd);
/**
* @}
*/
/** @defgroup SD_Exported_Functions_Group2 Input and Output operation functions
* @{
*/
/* Blocking mode: Polling */
HAL_SD_ErrorTypedef HAL_SD_ReadBlocks(SD_HandleTypeDef *hsd, uint32_t *pReadBuffer, uint64_t ReadAddr, uint32_t BlockSize, uint32_t NumberOfBlocks);
HAL_SD_ErrorTypedef HAL_SD_WriteBlocks(SD_HandleTypeDef *hsd, uint32_t *pWriteBuffer, uint64_t WriteAddr, uint32_t BlockSize, uint32_t NumberOfBlocks);
HAL_SD_ErrorTypedef HAL_SD_Erase(SD_HandleTypeDef *hsd, uint64_t startaddr, uint64_t endaddr);
/* Non-Blocking mode: Interrupt */
void HAL_SD_IRQHandler(SD_HandleTypeDef *hsd);
/* Callback in non blocking modes (DMA) */
void HAL_SD_DMA_RxCpltCallback(DMA_HandleTypeDef *hdma);
void HAL_SD_DMA_RxErrorCallback(DMA_HandleTypeDef *hdma);
void HAL_SD_DMA_TxCpltCallback(DMA_HandleTypeDef *hdma);
void HAL_SD_DMA_TxErrorCallback(DMA_HandleTypeDef *hdma);
void HAL_SD_XferCpltCallback(SD_HandleTypeDef *hsd);
void HAL_SD_XferErrorCallback(SD_HandleTypeDef *hsd);
/* Non-Blocking mode: DMA */
HAL_SD_ErrorTypedef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint32_t *pReadBuffer, uint64_t ReadAddr, uint32_t BlockSize, uint32_t NumberOfBlocks);
HAL_SD_ErrorTypedef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint32_t *pWriteBuffer, uint64_t WriteAddr, uint32_t BlockSize, uint32_t NumberOfBlocks);
HAL_SD_ErrorTypedef HAL_SD_CheckWriteOperation(SD_HandleTypeDef *hsd, uint32_t Timeout);
HAL_SD_ErrorTypedef HAL_SD_CheckReadOperation(SD_HandleTypeDef *hsd, uint32_t Timeout);
/**
* @}
*/
/** @defgroup SD_Exported_Functions_Group3 Peripheral Control functions
* @{
*/
HAL_SD_ErrorTypedef HAL_SD_Get_CardInfo(SD_HandleTypeDef *hsd, HAL_SD_CardInfoTypedef *pCardInfo);
HAL_SD_ErrorTypedef HAL_SD_WideBusOperation_Config(SD_HandleTypeDef *hsd, uint32_t WideMode);
HAL_SD_ErrorTypedef HAL_SD_StopTransfer(SD_HandleTypeDef *hsd);
HAL_SD_ErrorTypedef HAL_SD_HighSpeed (SD_HandleTypeDef *hsd);
/**
* @}
*/
/* Peripheral State functions ************************************************/
/** @defgroup SD_Exported_Functions_Group4 Peripheral State functions
* @{
*/
HAL_SD_ErrorTypedef HAL_SD_SendSDStatus(SD_HandleTypeDef *hsd, uint32_t *pSDstatus);
HAL_SD_ErrorTypedef HAL_SD_GetCardStatus(SD_HandleTypeDef *hsd, HAL_SD_CardStatusTypedef *pCardStatus);
HAL_SD_TransferStateTypedef HAL_SD_GetStatus(SD_HandleTypeDef *hsd);
/**
* @}
*/
/**
* @}
*/
/* Private types -------------------------------------------------------------*/
/** @defgroup SD_Private_Types SD Private Types
* @{
*/
/**
* @}
*/
/* Private defines -----------------------------------------------------------*/
/** @defgroup SD_Private_Defines SD Private Defines
* @{
*/
/**
* @}
*/
/* Private variables ---------------------------------------------------------*/
/** @defgroup SD_Private_Variables SD Private Variables
* @{
*/
/**
* @}
*/
/* Private constants ---------------------------------------------------------*/
/** @defgroup SD_Private_Constants SD Private Constants
* @{
*/
/**
* @}
*/
/* Private macros ------------------------------------------------------------*/
/** @defgroup SD_Private_Macros SD Private Macros
* @{
*/
/**
* @}
*/
/* Private functions prototypes ----------------------------------------------*/
/** @defgroup SD_Private_Functions_Prototypes SD Private Functions Prototypes
* @{
*/
/**
* @}
*/
/* Private functions ---------------------------------------------------------*/
/** @defgroup SD_Private_Functions SD Private Functions
* @{
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __STM32F7xx_HAL_SD_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View file

@ -0,0 +1,894 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
/* Standard includes. */
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
/* Xilinx library includes. */
#include "xparameters.h"
#include "xil_types.h"
#include "xsdps.h" /* SD device driver */
#include "xsdps_info.h" /* SD info */
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "portmacro.h"
/* FreeRTOS+FAT includes. */
#include "ff_headers.h"
#include "ff_sddisk.h"
#include "ff_sys.h"
#if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )
#include "xil_exception.h"
#include "xscugic_hw.h"
#endif /* ffconfigSDIO_DRIVER_USES_INTERRUPT */
#include "uncached_memory.h"
#define sdSIGNATURE 0x41404342
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) (int) (sizeof(x)/sizeof(x)[0])
#endif
#define STA_NOINIT 0x01 /* Drive not initialized */
#define STA_NODISK 0x02 /* No medium in the drive */
#define STA_PROTECT 0x04 /* Write protected */
#define SD_DEVICE_ID XPAR_XSDPS_0_DEVICE_ID
#define HIGH_SPEED_SUPPORT 0x01
#define WIDTH_4_BIT_SUPPORT 0x4
#define SD_CLK_12_MHZ 12000000
#define SD_CLK_25_MHZ 25000000
#define SD_CLK_26_MHZ 26000000
#define SD_CLK_52_MHZ 52000000
#define EXT_CSD_DEVICE_TYPE_BYTE 196
#define EXT_CSD_4_BIT_WIDTH_BYTE 183
#define EXT_CSD_HIGH_SPEED_BYTE 185
#define EXT_CSD_DEVICE_TYPE_HIGH_SPEED 0x3
#define HUNDRED_64_BIT 100ULL
#define BYTES_PER_MB ( 1024ull * 1024ull )
#define SECTORS_PER_MB ( BYTES_PER_MB / 512ull )
#define XSDPS_INTR_NORMAL_ENABLE ( XSDPS_INTR_CC_MASK | XSDPS_INTR_TC_MASK | \
XSDPS_INTR_DMA_MASK | XSDPS_INTR_CARD_INSRT_MASK | XSDPS_INTR_CARD_REM_MASK | \
XSDPS_INTR_ERR_MASK )
/* Two defines used to set or clear the interrupt */
#define INTC_BASE_ADDR XPAR_SCUGIC_CPU_BASEADDR
#define INTC_DIST_BASE_ADDR XPAR_SCUGIC_DIST_BASEADDR
/* Interupt numbers for SDIO units 0 and 1: */
#define SCUGIC_SDIO_0_INTR 0x38
#define SCUGIC_SDIO_1_INTR 0x4F
/* Define a timeout on data transfers for SDIO: */
#define sdWAIT_INT_TIME_OUT_MS 5000UL
/* Define a short timeout, used during card-detection only (CMD1): */
#define sdQUICK_WAIT_INT_TIME_OUT_MS 1000UL
/* XSdPs xSDCardInstance; */
static XSdPs *pxSDCardInstance;
static int sd_disk_status = STA_NOINIT; /* Disk status */
const int drive_nr = 0;
static SemaphoreHandle_t xPlusFATMutex;
#if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )
/* Create a semaphore for each of the two memory-card slots. */
static SemaphoreHandle_t xSDSemaphores[ 2 ];
#endif
static int vSDMMC_Init( int iDriveNumber );
static int vSDMMC_Status( int iDriveNumber );
#if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )
static void vInstallInterrupt( void );
#endif
struct xCACHE_MEMORY_INFO
{
/* Reserve 'uncached' memory for caching sectors, will be passed to the +FAT library. */
uint8_t pucCacheMemory[ 0x10000 ];
/* Reserve 'uncached' memory for i/o to the SD-card. */
uint8_t pucHelpMemory[ 0x40000 ];
XSdPs xSDCardInstance;
};
struct xCACHE_STATS
{
uint32_t xMemcpyReadCount;
uint32_t xMemcpyWriteCount;
uint32_t xPassReadCount;
uint32_t xPassWriteCount;
uint32_t xFailReadCount;
uint32_t xFailWriteCount;
};
struct xCACHE_STATS xCacheStats;
struct xCACHE_MEMORY_INFO *pxCacheMem = NULL;
static const uint8_t *prvStoreSDCardData( const uint8_t *pucBuffer, uint32_t ulByteCount );
static uint8_t *prvReadSDCardData( uint8_t *pucBuffer, uint32_t ulByteCount );
#if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )
void XSdPs_IntrHandler(void *XSdPsPtr);
#endif /* ffconfigSDIO_DRIVER_USES_INTERRUPT */
static int32_t prvFFRead( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk )
{
int32_t lReturnCode;
int iResult;
uint8_t *pucReadBuffer;
if( ( pxDisk != NULL ) && /*_RB_ Could this be changed to an assert? */
( pxDisk->ulSignature == sdSIGNATURE ) &&
( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&
( ulSectorNumber < pxDisk->ulNumberOfSectors ) &&
( pxDisk->ulNumberOfSectors - ulSectorNumber ) >= ulSectorCount )
{
iResult = vSDMMC_Status( drive_nr );
if( ( iResult & STA_NODISK ) != 0 )
{
lReturnCode = FF_ERR_DRIVER_NOMEDIUM | FF_ERRFLAG;
FF_PRINTF( "prvFFRead: NOMEDIUM\n" );
}
else if( ( iResult & STA_NOINIT ) != 0 )
{
lReturnCode = FF_ERR_IOMAN_OUT_OF_BOUNDS_READ | FF_ERRFLAG;
FF_PRINTF( "prvFFRead: NOINIT\n" );
}
else if( ulSectorCount == 0ul )
{
lReturnCode = 0;
}
else
{
/* Convert LBA to byte address if needed */
if( pxSDCardInstance->HCS == 0 )
{
ulSectorNumber *= XSDPS_BLK_SIZE_512_MASK;
}
pucReadBuffer = prvReadSDCardData( pucBuffer, 512UL * ulSectorCount );
if( ucIsCachedMemory( pucReadBuffer ) != pdFALSE )
{
xCacheStats.xFailReadCount++;
}
iResult = XSdPs_ReadPolled( pxSDCardInstance, ulSectorNumber, ulSectorCount, pucReadBuffer );
if( pucBuffer != pucReadBuffer )
{
xCacheStats.xMemcpyReadCount++;
memcpy( pucBuffer, pucReadBuffer, 512 * ulSectorCount );
}
else
{
xCacheStats.xPassReadCount++;
}
if( iResult == XST_SUCCESS )
{
lReturnCode = 0l;
}
else
{
lReturnCode = FF_ERR_IOMAN_OUT_OF_BOUNDS_READ | FF_ERRFLAG;
}
}
}
else
{
memset( ( void *) pucBuffer, '\0', ulSectorCount * 512 );
if( pxDisk->xStatus.bIsInitialised != pdFALSE )
{
FF_PRINTF( "prvFFRead: warning: %lu + %lu > %lu\n", ulSectorNumber, ulSectorCount, pxDisk->ulNumberOfSectors );
}
lReturnCode = FF_ERR_IOMAN_OUT_OF_BOUNDS_READ | FF_ERRFLAG;
}
return lReturnCode;
}
/*-----------------------------------------------------------*/
static int32_t prvFFWrite( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk )
{
int32_t lReturnCode;
if( ( pxDisk != NULL ) &&
( pxDisk->ulSignature == sdSIGNATURE ) &&
( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&
( ulSectorNumber < pxDisk->ulNumberOfSectors ) &&
( ( pxDisk->ulNumberOfSectors - ulSectorNumber ) >= ulSectorCount ) )
{
int iResult;
iResult = vSDMMC_Status(drive_nr);
if( ( iResult & STA_NODISK ) != 0 )
{
lReturnCode = FF_ERR_DRIVER_NOMEDIUM | FF_ERRFLAG;
FF_PRINTF( "prvFFWrite: NOMEDIUM\n" );
}
else if( ( iResult & STA_NOINIT ) != 0 )
{
lReturnCode = FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE | FF_ERRFLAG;
FF_PRINTF( "prvFFWrite: NOINIT\n" );
}
else
{
if( ulSectorCount == 0ul )
{
lReturnCode = 0l;
}
else
{
/* Convert LBA to byte address if needed */
if (!(pxSDCardInstance->HCS)) ulSectorNumber *= XSDPS_BLK_SIZE_512_MASK;
pucBuffer = ( uint8_t * )prvStoreSDCardData( pucBuffer, 512UL * ulSectorCount );
if( ucIsCachedMemory( pucBuffer ) != pdFALSE )
{
xCacheStats.xFailWriteCount++;
}
iResult = XSdPs_WritePolled( pxSDCardInstance, ulSectorNumber, ulSectorCount, pucBuffer );
if( iResult == XST_SUCCESS )
{
lReturnCode = 0;
}
else
{
FF_PRINTF( "prvFFWrite[%d]: at 0x%X count %ld : %d\n",
(int)drive_nr, (unsigned)ulSectorNumber, ulSectorCount, iResult );
lReturnCode = FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE | FF_ERRFLAG;
}
}
}
}
else
{
lReturnCode = FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE | FF_ERRFLAG;
if( pxDisk->xStatus.bIsInitialised )
{
FF_PRINTF( "prvFFWrite::read: warning: %lu + %lu > %lu\n",
ulSectorNumber, ulSectorCount, pxDisk->ulNumberOfSectors );
}
}
return lReturnCode;
}
/*-----------------------------------------------------------*/
void FF_SDDiskFlush( FF_Disk_t *pxDisk )
{
if( ( pxDisk != NULL ) &&
( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&
( pxDisk->pxIOManager != NULL ) )
{
FF_FlushCache( pxDisk->pxIOManager );
}
}
/*-----------------------------------------------------------*/
static const uint8_t *prvStoreSDCardData( const uint8_t *pucBuffer, uint32_t ulByteCount )
{
const uint8_t *pucReturn;
if( ( ucIsCachedMemory( pucBuffer ) != pdFALSE ) && ( ulByteCount <= sizeof( pxCacheMem->pucHelpMemory ) ) )
{
memcpy( pxCacheMem->pucHelpMemory, pucBuffer, ulByteCount );
pucReturn = pxCacheMem->pucHelpMemory;
xCacheStats.xMemcpyWriteCount++;
}
else
{
pucReturn = pucBuffer;
xCacheStats.xPassWriteCount++;
}
return pucReturn;
}
/*-----------------------------------------------------------*/
static uint8_t *prvReadSDCardData( uint8_t *pucBuffer, uint32_t ulByteCount )
{
uint8_t *pucReturn;
if( ( ucIsCachedMemory( pucBuffer ) != pdFALSE ) && ( ulByteCount <= sizeof( pxCacheMem->pucHelpMemory ) ) )
{
pucReturn = pxCacheMem->pucHelpMemory;
}
else
{
pucReturn = pucBuffer;
}
return pucReturn;
}
/*-----------------------------------------------------------*/
static struct xCACHE_MEMORY_INFO *pucGetSDIOCacheMemory( )
{
if( pxCacheMem == NULL )
{
pxCacheMem = ( struct xCACHE_MEMORY_INFO * ) pucGetUncachedMemory( sizeof( *pxCacheMem ) );
memset( pxCacheMem, '\0', sizeof( *pxCacheMem ) );
}
return pxCacheMem;
}
/*-----------------------------------------------------------*/
/* Initialise the SDIO driver and mount an SD card */
FF_Disk_t *FF_SDDiskInit( const char *pcName )
{
FF_Error_t xFFError;
BaseType_t xPartitionNumber = 0;
FF_CreationParameters_t xParameters;
FF_Disk_t * pxDisk;
#if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )
int iIndex;
#endif
pucGetSDIOCacheMemory();
pxDisk = (FF_Disk_t *)pvPortMalloc( sizeof( *pxDisk ) );
if( pxDisk == NULL )
{
FF_PRINTF( "FF_SDDiskInit: Malloc failed\n" );
}
else if( pxCacheMem == NULL )
{
FF_PRINTF( "FF_SDDiskInit: Cached memory failed\n" );
}
else
{
pxSDCardInstance = &( pxCacheMem->xSDCardInstance );
#if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )
{
for( iIndex = 0; iIndex < ARRAY_SIZE( xSDSemaphores ); iIndex++ )
{
if( xSDSemaphores[ iIndex ] == NULL )
{
xSDSemaphores[ iIndex ] = xSemaphoreCreateBinary();
configASSERT( xSDSemaphores[ iIndex ] != NULL );
}
}
}
#endif
vSDMMC_Init( 0 );
/* Initialise the created disk structure. */
memset( pxDisk, '\0', sizeof( *pxDisk ) );
pxDisk->ulNumberOfSectors = myCSD.sd_last_block_address + 1;
if( xPlusFATMutex == NULL )
{
xPlusFATMutex = xSemaphoreCreateRecursiveMutex();
}
pxDisk->ulSignature = sdSIGNATURE;
if( xPlusFATMutex != NULL)
{
memset( &xParameters, '\0', sizeof( xParameters ) );
xParameters.pucCacheMemory = pxCacheMem->pucCacheMemory;
xParameters.ulMemorySize = sizeof( pxCacheMem->pucCacheMemory );
xParameters.ulSectorSize = 512;
xParameters.fnWriteBlocks = prvFFWrite;
xParameters.fnReadBlocks = prvFFRead;
xParameters.pxDisk = pxDisk;
/* prvFFRead()/prvFFWrite() are not re-entrant and must be protected with
the use of a semaphore. */
xParameters.xBlockDeviceIsReentrant = pdFALSE;
/* The semaphore will be used to protect critical sections in the +FAT driver,
and also to avoid concurrent calls to prvFFRead()/prvFFWrite() from different tasks. */
xParameters.pvSemaphore = ( void * ) xPlusFATMutex;
pxDisk->pxIOManager = FF_CreateIOManger( &xParameters, &xFFError );
if( pxDisk->pxIOManager == NULL )
{
FF_PRINTF( "FF_SDDiskInit: FF_CreateIOManger: %s\n", (const char*)FF_GetErrMessage( xFFError ) );
FF_SDDiskDelete( pxDisk );
pxDisk = NULL;
}
else
{
pxDisk->xStatus.bIsInitialised = pdTRUE;
pxDisk->xStatus.bPartitionNumber = xPartitionNumber;
if( FF_SDDiskMount( pxDisk ) == 0 )
{
FF_SDDiskDelete( pxDisk );
pxDisk = NULL;
}
else
{
if( pcName == NULL )
{
pcName = "/";
}
FF_FS_Add( pcName, pxDisk );
FF_PRINTF( "FF_SDDiskInit: Mounted SD-card as root \"%s\"\n", pcName );
FF_SDDiskShowPartition( pxDisk );
}
}
}
}
return pxDisk;
}
/*-----------------------------------------------------------*/
BaseType_t FF_SDDiskFormat( FF_Disk_t *pxDisk, BaseType_t aPart )
{
FF_Error_t xError;
BaseType_t xReturn = 0;
FF_SDDiskUnmount( pxDisk );
{
/* Format the drive */
xError = FF_Format( pxDisk, aPart, pdFALSE, pdFALSE); // Try FAT32 with large clusters
if( FF_isERR( xError ) )
{
FF_PRINTF( "FF_SDDiskFormat: %s\n", (const char*)FF_GetErrMessage( xError ) );
return 0;
}
else
{
FF_PRINTF( "FF_SDDiskFormat: OK, now remounting\n" );
pxDisk->xStatus.bPartitionNumber = aPart;
xError = FF_SDDiskMount( pxDisk );
FF_PRINTF( "FF_SDDiskFormat: rc %08x\n", ( unsigned )xError );
if( FF_isERR( xError ) == pdFALSE )
{
xReturn = 1;
FF_SDDiskShowPartition( pxDisk );
}
}
}
return xReturn;
}
/*-----------------------------------------------------------*/
/* Unmount the volume */
BaseType_t FF_SDDiskUnmount( FF_Disk_t *pxDisk )
{
FF_Error_t xFFError;
BaseType_t xReturn = 1;
if( ( pxDisk != NULL ) && ( pxDisk->xStatus.bIsMounted != pdFALSE ) )
{
pxDisk->xStatus.bIsMounted = pdFALSE;
xFFError = FF_Unmount( pxDisk );
FF_PRINTF( "FF_SDDiskUnmount: rc %08x\n", ( unsigned )xFFError );
if( FF_isERR( xFFError ) )
{
xReturn = 0;
}
else
{
FF_PRINTF( "Drive unmounted\n" );
}
}
return xReturn;
}
/*-----------------------------------------------------------*/
BaseType_t FF_SDDiskReinit( FF_Disk_t *pxDisk )
{
int iStatus = vSDMMC_Init( 0 ); /* Hard coded index. */
/*_RB_ parameter not used. */
( void ) pxDisk;
FF_PRINTF( "FF_SDDiskReinit: rc %08x\n", ( unsigned )iStatus );
return iStatus;
}
/*-----------------------------------------------------------*/
BaseType_t FF_SDDiskMount( FF_Disk_t *pxDisk )
{
FF_Error_t xFFError;
BaseType_t xReturn = 1;
/* Mount the partition */
xFFError = FF_Mount( pxDisk, pxDisk->xStatus.bPartitionNumber );
if( FF_isERR( xFFError ) )
{
FF_PRINTF( "FF_SDDiskMount: %08lX\n", xFFError );
xReturn = 0;
}
else
{
pxDisk->xStatus.bIsMounted = pdTRUE;
FF_PRINTF( "****** FreeRTOS+FAT initialized %lu sectors\n", pxDisk->pxIOManager->xPartition.ulTotalSectors );
}
return xReturn;
}
/*-----------------------------------------------------------*/
/* Get a pointer to IOMAN, which can be used for all FreeRTOS+FAT functions */
FF_IOManager_t *sddisk_ioman( FF_Disk_t *pxDisk )
{
FF_IOManager_t *pxReturn;
if( ( pxDisk != NULL ) && ( pxDisk->xStatus.bIsInitialised != pdFALSE ) )
{
pxReturn = pxDisk->pxIOManager;
}
else
{
pxReturn = NULL;
}
return pxReturn;
}
/*-----------------------------------------------------------*/
/* Release all resources */
BaseType_t FF_SDDiskDelete( FF_Disk_t *pxDisk )
{
if( pxDisk != NULL )
{
pxDisk->ulSignature = 0;
pxDisk->xStatus.bIsInitialised = 0;
if( pxDisk->pxIOManager != NULL )
{
if( FF_Mounted( pxDisk->pxIOManager ) != pdFALSE )
{
FF_Unmount( pxDisk );
}
FF_DeleteIOManager( pxDisk->pxIOManager );
}
vPortFree( pxDisk );
}
return 1;
}
/*-----------------------------------------------------------*/
BaseType_t FF_SDDiskShowPartition( FF_Disk_t *pxDisk )
{
FF_Error_t xError;
uint64_t ullFreeSectors;
uint32_t ulTotalSizeMB, ulFreeSizeMB;
int iPercentageFree;
FF_IOManager_t *pxIOManager;
const char *pcTypeName = "unknown type";
BaseType_t xReturn = pdPASS;
if( pxDisk == NULL )
{
xReturn = pdFAIL;
}
else
{
pxIOManager = pxDisk->pxIOManager;
FF_PRINTF( "Reading FAT and calculating Free Space\n" );
switch( pxIOManager->xPartition.ucType )
{
case FF_T_FAT12:
pcTypeName = "FAT12";
break;
case FF_T_FAT16:
pcTypeName = "FAT16";
break;
case FF_T_FAT32:
pcTypeName = "FAT32";
break;
default:
pcTypeName = "UNKOWN";
break;
}
FF_GetFreeSize( pxIOManager, &xError );
ullFreeSectors = pxIOManager->xPartition.ulFreeClusterCount * pxIOManager->xPartition.ulSectorsPerCluster;
iPercentageFree = ( int ) ( ( HUNDRED_64_BIT * ullFreeSectors + pxIOManager->xPartition.ulDataSectors / 2 ) /
( ( uint64_t )pxIOManager->xPartition.ulDataSectors ) );
ulTotalSizeMB = pxIOManager->xPartition.ulDataSectors / SECTORS_PER_MB;
ulFreeSizeMB = ( uint32_t ) ( ullFreeSectors / SECTORS_PER_MB );
/* It is better not to use the 64-bit format such as %Lu because it
might not be implemented. */
FF_PRINTF( "Partition Nr %8u\n", pxDisk->xStatus.bPartitionNumber );
FF_PRINTF( "Type %8u (%s)\n", pxIOManager->xPartition.ucType, pcTypeName );
FF_PRINTF( "VolLabel '%8s' \n", pxIOManager->xPartition.pcVolumeLabel );
FF_PRINTF( "TotalSectors %8lu\n", pxIOManager->xPartition.ulTotalSectors );
FF_PRINTF( "DataSectors %8lu\n", pxIOManager->xPartition.ulDataSectors );
FF_PRINTF( "SecsPerCluster %8lu\n", pxIOManager->xPartition.ulSectorsPerCluster );
FF_PRINTF( "Size %8lu MB\n", ulTotalSizeMB );
FF_PRINTF( "FreeSize %8lu MB ( %d perc free )\n", ulFreeSizeMB, iPercentageFree );
FF_PRINTF( "BeginLBA %8lu\n", pxIOManager->xPartition.ulBeginLBA );
FF_PRINTF( "FATBeginLBA %8lu\n", pxIOManager->xPartition.ulFATBeginLBA );
}
return xReturn;
}
/*-----------------------------------------------------------*/
#if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )
static void vInstallInterrupt( void )
{
/* Install an interrupt handler for SDIO_0 */
XScuGic_RegisterHandler( INTC_BASE_ADDR, SCUGIC_SDIO_0_INTR,
( Xil_ExceptionHandler )XSdPs_IntrHandler,
( void * )pxSDCardInstance );
/* Enable this interrupt. */
XScuGic_EnableIntr( INTC_DIST_BASE_ADDR, SCUGIC_SDIO_0_INTR );
/* Choose the signals. */
XSdPs_WriteReg16(pxSDCardInstance->Config.BaseAddress,
XSDPS_NORM_INTR_SIG_EN_OFFSET,
XSDPS_INTR_NORMAL_ENABLE );
XSdPs_WriteReg16(pxSDCardInstance->Config.BaseAddress,
XSDPS_ERR_INTR_SIG_EN_OFFSET,
0x0 );
}
#endif /* ffconfigSDIO_DRIVER_USES_INTERRUPT */
/*-----------------------------------------------------------*/
static int vSDMMC_Init( int iDriveNumber )
{
int iReturnCode, iStatus;
XSdPs_Config *SdConfig;
/*_RB_ Function name not following convention, parameter not used, parameter
using plain int type. */
/* Open a do {} while(0) loop to allow the use of break. */
do
{
/* Check if card is in the socket */
iStatus = vSDMMC_Status( iDriveNumber );
if( ( iStatus & STA_NODISK ) != 0 )
{
break;
}
/* Assume that the initialisation will fail: set the 'STA_NOINIT' bit. */
iStatus |= STA_NOINIT;
/* Initialize the host controller */
SdConfig = XSdPs_LookupConfig(SD_DEVICE_ID);
if( SdConfig == NULL )
{
break;
}
iReturnCode = XSdPs_CfgInitialize(pxSDCardInstance, SdConfig, SdConfig->BaseAddress);
if( iReturnCode != XST_SUCCESS )
{
break;
}
#if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )
{
vInstallInterrupt();
}
#endif /* ffconfigSDIO_DRIVER_USES_INTERRUPT */
iReturnCode = XSdPs_CardInitialize( pxSDCardInstance );
if( iReturnCode != XST_SUCCESS )
{
break;
}
/* Disk is initialized OK: clear the 'STA_NOINIT' bit. */
iStatus &= ~( STA_NOINIT );
} while( 0 );
sd_disk_status = iStatus;
return iStatus;
}
/*-----------------------------------------------------------*/
static int vSDMMC_Status( int iDriveNumber )
{
int iStatus = sd_disk_status;
u32 ulStatusReg;
/*_RB_ Function name not following convention, parameter not used, parameter
using plain int type. */
( void ) iDriveNumber;
ulStatusReg = XSdPs_GetPresentStatusReg( XPAR_XSDPS_0_BASEADDR );
if( ( ulStatusReg & XSDPS_PSR_CARD_INSRT_MASK ) == 0 )
{
iStatus = STA_NODISK | STA_NOINIT;
}
else
{
iStatus &= ~STA_NODISK;
if( ( ulStatusReg & XSDPS_PSR_WPS_PL_MASK ) != 0 )
{
iStatus &= ~STA_PROTECT;
}
else
{
iStatus |= STA_PROTECT;
}
}
sd_disk_status = iStatus;
return iStatus;
}
/*-----------------------------------------------------------*/
BaseType_t FF_SDDiskInserted( BaseType_t xDriveNr )
{
BaseType_t xReturn;
int iStatus;
/* Check if card is in the socket */
iStatus = vSDMMC_Status( xDriveNr );
if( ( iStatus & STA_NODISK ) != 0 )
{
xReturn = pdFALSE;
}
else
{
xReturn = pdTRUE;
}
return xReturn;
}
volatile unsigned sd_int_count = 0;
#if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )
volatile u32 ulSDInterruptStatus[2];
void XSdPs_IntrHandler(void *XSdPsPtr)
{
XSdPs *InstancePtr = (XSdPs *)XSdPsPtr;
int iIndex = InstancePtr->Config.DeviceId;
uint32_t ulStatusReg;
configASSERT( iIndex <= 1 );
sd_int_count++;
/* Read the current status. */
ulStatusReg = XSdPs_ReadReg( InstancePtr->Config.BaseAddress, XSDPS_NORM_INTR_STS_OFFSET );
/* Write to clear error bits. */
XSdPs_WriteReg( InstancePtr->Config.BaseAddress, XSDPS_NORM_INTR_STS_OFFSET, ulStatusReg );
/* The new value must be OR-ed, if not the
Command Complete (CC) event might get overwritten
by the Transfer Complete (TC) event. */
ulSDInterruptStatus[ iIndex ] |= ulStatusReg;
if( ( ulStatusReg & ( XSDPS_INTR_CARD_INSRT_MASK | XSDPS_INTR_CARD_REM_MASK ) ) != 0 )
{
/* Could wake-up another task. */
}
if( xSDSemaphores[ iIndex ] != NULL )
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR( xSDSemaphores[ iIndex ], &xHigherPriorityTaskWoken );
if( xHigherPriorityTaskWoken != 0 )
{
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
}
}
#endif /* ffconfigSDIO_DRIVER_USES_INTERRUPT */
/*-----------------------------------------------------------*/
#if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )
void XSdPs_ClearInterrupt( XSdPs *InstancePtr )
{
int iIndex = InstancePtr->Config.DeviceId;
configASSERT( iIndex <= 1 );
ulSDInterruptStatus[ iIndex ] = 0;
}
#endif /* ffconfigSDIO_DRIVER_USES_INTERRUPT */
/*-----------------------------------------------------------*/
#if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )
/* Wait for an interrupt and return the 32 bits of the status register.
A return value of 0 means: time-out. */
u32 XSdPs_WaitInterrupt( XSdPs *InstancePtr, u32 ulMask, u32 ulWait )
{
u32 ulStatusReg;
int iIndex = InstancePtr->Config.DeviceId;
TickType_t xRemainingTime = pdMS_TO_TICKS( sdWAIT_INT_TIME_OUT_MS );
TimeOut_t xTimeOut;
if( ulWait == 0UL )
{
xRemainingTime = pdMS_TO_TICKS( sdQUICK_WAIT_INT_TIME_OUT_MS );
}
configASSERT( iIndex <= 1 );
configASSERT( xSDSemaphores[ iIndex ] != 0 );
vTaskSetTimeOutState( &xTimeOut );
/* Loop until:
1. Expected bit (ulMask) becomes high
2. Time-out reached (normally 2 seconds)
*/
do
{
if( xRemainingTime != 0 )
{
xSemaphoreTake( xSDSemaphores[ iIndex ], xRemainingTime );
}
ulStatusReg = ulSDInterruptStatus[ iIndex ];
if( ( ulStatusReg & XSDPS_INTR_ERR_MASK ) != 0 )
{
break;
}
}
while( ( xTaskCheckForTimeOut( &xTimeOut, &xRemainingTime ) == pdFALSE ) &&
( ( ulStatusReg & ulMask ) == 0 ) );
if( ( ulStatusReg & ulMask ) == 0 )
{
ulStatusReg = XSdPs_ReadReg( InstancePtr->Config.BaseAddress, XSDPS_NORM_INTR_STS_OFFSET );
if( ulWait != 0UL )
{
FF_PRINTF( "XSdPs_WaitInterrupt[ %d ]: Got %08lx, expect %08lx ints: %d\n",
iIndex,
ulStatusReg,
ulMask,
sd_int_count );
}
}
return ulStatusReg;
}
#endif /* ffconfigSDIO_DRIVER_USES_INTERRUPT */
/*-----------------------------------------------------------*/

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,221 @@
/******************************************************************************
*
* Copyright (C) 2013 - 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xsdps.h
* @addtogroup sdps_v2_5
* @{
* @details
*
* This file contains the implementation of XSdPs driver.
* This driver is used initialize read from and write to the SD card.
* Features such as switching bus width to 4-bit and switching to high speed,
* changing clock frequency, block size etc. are supported.
* SD 2.0 uses 1/4 bus width and speeds of 25/50KHz. Initialization, however
* is done using 1-bit bus width and 400KHz clock frequency.
* SD commands are classified as broadcast and addressed. Commands can be
* those with response only (using only command line) or
* response + data (using command and data lines).
* Only one command can be sent at a time. During a data transfer however,
* when dsta lines are in use, certain commands (which use only the command
* line) can be sent, most often to obtain status.
* This driver does not support multi card slots at present.
*
* Intialization:
* This includes initialization on the host controller side to select
* clock frequency, bus power and default transfer related parameters.
* The default voltage is 3.3V.
* On the SD card side, the initialization and identification state diagram is
* implemented. This resets the card, gives it a unique address/ID and
* identifies key card related specifications.
*
* Data transfer:
* The SD card is put in tranfer state to read from or write to it.
* The default block size is 512 bytes and if supported,
* default bus width is 4-bit and bus speed is High speed.
* The read and write functions are implemented in polled mode using ADMA2.
*
* At any point, when key parameters such as block size or
* clock/speed or bus width are modified, this driver takes care of
* maintaining the same selection on host and card.
* All error bits in host controller are monitored by the driver and in the
* event one of them is set, driver will clear the interrupt status and
* communicate failure to the upper layer.
*
* File system use:
* This driver can be used with xilffs library to read and write files to SD.
* (Please refer to procedure in diskio.c). The file system read/write example
* in polled mode can used for reference.
*
* There is no example for using SD driver without file system at present.
* However, the driver can be used without the file system. The glue layer
* in filesytem can be used as reference for the same. The block count
* passed to the read/write function in one call is limited by the ADMA2
* descriptor table and hence care will have to be taken to call read/write
* API's in a loop for large file sizes.
*
* Interrupt mode is not supported because it offers no improvement when used
* with file system.
*
* eMMC support:
* SD driver supports SD and eMMC based on the "enable MMC" parameter in SDK.
* The features of eMMC supported by the driver will depend on those supported
* by the host controller. The current driver supports read/write on eMMC card
* using 4-bit and high speed mode currently.
*
* Features not supported include - card write protect, password setting,
* lock/unlock, interrupts, SDMA mode, programmed I/O mode and
* 64-bit addressed ADMA2, erase/pre-erase commands.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00a hk/sg 10/17/13 Initial release
* 2.0 hk 03/07/14 Version number revised.
* 2.1 hk 04/18/14 Increase sleep for eMMC switch command.
* Add sleep for microblaze designs. CR# 781117.
* 2.2 hk 07/28/14 Make changes to enable use of data cache.
* 2.3 sk 09/23/14 Send command for relative card address
* when re-initialization is done.CR# 819614.
* Use XSdPs_Change_ClkFreq API whenever changing
* clock.CR# 816586.
* 2.4 sk 12/04/14 Added support for micro SD without
* WP/CD. CR# 810655.
* Checked for DAT Inhibit mask instead of CMD
* Inhibit mask in Cmd Transfer API.
* Added Support for SD Card v1.0
* 2.5 sg 07/09/15 Added SD 3.0 features
* kvn 07/15/15 Modified the code according to MISRAC-2012.
* 2.6 sk 10/12/15 Added support for SD card v1.0 CR# 840601.
*
* </pre>
*
******************************************************************************/
#ifndef SDPS_H_
#define SDPS_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "xstatus.h"
#include "xsdps_hw.h"
#include <string.h>
/************************** Constant Definitions *****************************/
#define XSDPS_CT_ERROR 0x2U /**< Command timeout flag */
/**************************** Type Definitions *******************************/
/**
* This typedef contains configuration information for the device.
*/
typedef struct {
u16 DeviceId; /**< Unique ID of device */
u32 BaseAddress; /**< Base address of the device */
u32 InputClockHz; /**< Input clock frequency */
u32 CardDetect; /**< Card Detect */
u32 WriteProtect; /**< Write Protect */
} XSdPs_Config;
/* ADMA2 descriptor table */
typedef struct {
u16 Attribute; /**< Attributes of descriptor */
u16 Length; /**< Length of current dma transfer */
u32 Address; /**< Address of current dma transfer */
} XSdPs_Adma2Descriptor;
/**
* The XSdPs driver instance data. The user is required to allocate a
* variable of this type for every SD device in the system. A pointer
* to a variable of this type is then passed to the driver API functions.
*/
typedef struct {
XSdPs_Config Config; /**< Configuration structure */
u32 IsReady; /**< Device is initialized and ready */
u32 Host_Caps; /**< Capabilities of host controller */
u32 Host_CapsExt; /**< Extended Capabilities */
u32 HCS; /**< High capacity support in card */
u8 CardType; /**< Type of card - SD/MMC/eMMC */
u8 Card_Version; /**< Card version */
u8 HC_Version; /**< Host controller version */
u8 BusWidth; /**< Current operating bus width */
u32 BusSpeed; /**< Current operating bus speed */
u8 Switch1v8; /**< 1.8V Switch support */
u32 CardID[4]; /**< Card ID Register */
u32 RelCardAddr; /**< Relative Card Address */
u32 CardSpecData[4]; /**< Card Specific Data Register */
u32 SdCardConfig; /**< Sd Card Configuration Register */
/**< ADMA Descriptors */
#ifdef __ICCARM__
#pragma data_alignment = 32
XSdPs_Adma2Descriptor Adma2_DescrTbl[32];
#pragma data_alignment = 4
#else
XSdPs_Adma2Descriptor Adma2_DescrTbl[32] __attribute__ ((aligned(32)));
#endif
} XSdPs;
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
XSdPs_Config *XSdPs_LookupConfig(u16 DeviceId);
s32 XSdPs_CfgInitialize(XSdPs *InstancePtr, XSdPs_Config *ConfigPtr,
u32 EffectiveAddr);
s32 XSdPs_SdCardInitialize(XSdPs *InstancePtr);
s32 XSdPs_ReadPolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff);
s32 XSdPs_WritePolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff);
s32 XSdPs_SetBlkSize(XSdPs *InstancePtr, u16 BlkSize);
s32 XSdPs_Select_Card (XSdPs *InstancePtr);
s32 XSdPs_Change_ClkFreq(XSdPs *InstancePtr, u32 SelFreq);
s32 XSdPs_Change_BusWidth(XSdPs *InstancePtr);
s32 XSdPs_Change_BusSpeed(XSdPs *InstancePtr);
s32 XSdPs_Get_BusWidth(XSdPs *InstancePtr, u8 *SCR);
s32 XSdPs_Get_BusSpeed(XSdPs *InstancePtr, u8 *ReadBuff);
s32 XSdPs_Pullup(XSdPs *InstancePtr);
s32 XSdPs_MmcCardInitialize(XSdPs *InstancePtr);
s32 XSdPs_CardInitialize(XSdPs *InstancePtr);
s32 XSdPs_Get_Mmc_ExtCsd(XSdPs *InstancePtr, u8 *ReadBuff);
/* Wait for Command/Transfer Complete. */
s32 XSdPs_Wait_For(XSdPs *InstancePtr, u32 Mask, u32 Wait);
#ifdef __cplusplus
}
#endif
#endif /* SD_H_ */
/** @} */

View file

@ -0,0 +1,69 @@
/******************************************************************************
*
* Copyright (C) 2013 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xsdps_g.c
*
* This file contains a configuration table that specifies the configuration of
* SD devices in the system.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00a hk/sg 10/17/13 Initial release
*
* </pre>
*
******************************************************************************/
#include "xparameters.h"
#include "xsdps.h"
/*
* The configuration table for devices
*/
XSdPs_Config XSdPs_ConfigTable[] =
{
{
XPAR_XSDPS_0_DEVICE_ID,
XPAR_XSDPS_0_BASEADDR,
XPAR_XSDPS_0_SDIO_CLK_FREQ_HZ,
0,
0
}
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,300 @@
/******************************************************************************
*
* mmc_decode_cid() and sd_decode_csd()
*
* analyse the meta data of an SD-card to read its capacity and some other properties.
*
* CID and CSD Analysis borrowed from the Linux kernel.
*
******************************************************************************/
#include "xsdps.h"
#include "xparameters.h"
#include "xil_cache.h"
#include "ff_headers.h"
#include "xsdps_info.h"
struct mmc_cid myCID;
struct mmc_csd myCSD;
u32 UNSTUFF_BITS( u32 *ulResponse, int iFirst, int iSize )
{
const u32 ulMask = ( iSize < 32 ? ( 1 << iSize ) : 0 ) - 1;
const int iOffset = 3 - ( iFirst / 32);
const int iShiftCount = iFirst & 31;
u32 ulResult;
ulResult = ulResponse[ iOffset ] >> iShiftCount;
if( iSize + iShiftCount > 32 )
{
ulResult |= ulResponse[ iOffset - 1 ] << ( ( 32 - iShiftCount ) % 32 );
}
return ulResult & ulMask; \
}
int mmc_decode_cid( const struct mmc_csd *pxCSD, struct mmc_cid *pxCID, u32 *ulResponse )
{
int iResult = 0;
/*
* The selection of the format here is based upon published
* specs from sandisk and from what people have reported.
*/
switch( pxCSD->mmca_vsn )
{
case 0: /* MMC v1.0 - v1.2 */
case 1: /* MMC v1.4 */
pxCID->manfid = UNSTUFF_BITS( ulResponse, 104, 24 );
pxCID->prod_name[ 0 ] = UNSTUFF_BITS( ulResponse, 96, 8 );
pxCID->prod_name[ 1 ] = UNSTUFF_BITS( ulResponse, 88, 8 );
pxCID->prod_name[ 2 ] = UNSTUFF_BITS( ulResponse, 80, 8 );
pxCID->prod_name[ 3 ] = UNSTUFF_BITS( ulResponse, 72, 8 );
pxCID->prod_name[ 4 ] = UNSTUFF_BITS( ulResponse, 64, 8 );
pxCID->prod_name[ 5 ] = UNSTUFF_BITS( ulResponse, 56, 8 );
pxCID->prod_name[ 6 ] = UNSTUFF_BITS( ulResponse, 48, 8 );
pxCID->hwrev = UNSTUFF_BITS( ulResponse, 44, 4 );
pxCID->fwrev = UNSTUFF_BITS( ulResponse, 40, 4 );
pxCID->serial = UNSTUFF_BITS( ulResponse, 16, 24 );
pxCID->month = UNSTUFF_BITS( ulResponse, 12, 4 );
pxCID->year = UNSTUFF_BITS( ulResponse, 8, 4 ) + 1997;
break;
case 2: /* MMC v2.0 - v2.2 */
case 3: /* MMC v3.1 - v3.3 */
case 4: /* MMC v4 */
pxCID->manfid = UNSTUFF_BITS( ulResponse, 120, 8 );
pxCID->oemid = UNSTUFF_BITS( ulResponse, 104, 16 );
pxCID->prod_name[ 0 ] = UNSTUFF_BITS( ulResponse, 96, 8 );
pxCID->prod_name[ 1 ] = UNSTUFF_BITS( ulResponse, 88, 8 );
pxCID->prod_name[ 2 ] = UNSTUFF_BITS( ulResponse, 80, 8 );
pxCID->prod_name[ 3 ] = UNSTUFF_BITS( ulResponse, 72, 8 );
pxCID->prod_name[ 4 ] = UNSTUFF_BITS( ulResponse, 64, 8 );
pxCID->prod_name[ 5 ] = UNSTUFF_BITS( ulResponse, 56, 8 );
pxCID->serial = UNSTUFF_BITS( ulResponse, 16, 32 );
pxCID->month = UNSTUFF_BITS( ulResponse, 12, 4 );
pxCID->year = UNSTUFF_BITS( ulResponse, 8, 4 ) + 1997;
break;
default:
FF_PRINTF ("mmc_decode_cid: card has unknown MMCA version %d\n",
pxCSD->mmca_vsn);
iResult = -1;
break;
}
if( iResult >= 0 )
{
FF_PRINTF ("CID: Manfid %lu (%-8.8s) serial %lu oem %u mon/year %u/%u rev %u fw %u\n",
pxCID->manfid,
pxCID->prod_name,
pxCID->serial,
pxCID->oemid,
pxCID->month,
pxCID->year,
pxCID->hwrev,
pxCID->fwrev);
}
return iResult;
}
static const unsigned int tran_exp[] =
{
10000, 100000, 1000000, 10000000,
0, 0, 0, 0
};
static const unsigned char tran_mant[] =
{
0, 10, 12, 13, 15, 20, 25, 30,
35, 40, 45, 50, 55, 60, 70, 80,
};
static const unsigned int tacc_exp[] =
{
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
};
static const unsigned int tacc_mant[] =
{
0, 10, 12, 13, 15, 20, 25, 30,
35, 40, 45, 50, 55, 60, 70, 80,
};
char mmc_is_block_addressed;
/* Given a 128-bit response, decode to our card CSD structure. */
static __inline unsigned tobe32( unsigned value )
{
return
( value >> 24 ) |
( ( value >> 8 ) & 0x0000ff00 ) |
( ( value << 8 ) & 0x00ff0000 ) |
( value << 24 );
}
int sd_decode_csd( struct mmc_csd *pxCSD, u32 *ulResponse )
{
unsigned int e, m, csd_struct;
int iResult = 0;
csd_struct = UNSTUFF_BITS( ulResponse, 126, 2 );
pxCSD->mmca_vsn = UNSTUFF_BITS( ulResponse, 122, 4 );
FF_PRINTF("CSD data: %08x %08x %08x %08x mmca_vsn = %u\n",
( unsigned )ulResponse[0],
( unsigned )ulResponse[1],
( unsigned )ulResponse[2],
( unsigned )ulResponse[3],
pxCSD->mmca_vsn);
// pxCSD->mmca_vsn = 2;
// CSD data: 005e0032 5f5a83cb 2db7ffbf 9680000f
// sd_decode_csd: capacity 1989120 (byte addressed)
switch (csd_struct) {
case 0:
m = UNSTUFF_BITS( ulResponse, 115, 4 );
e = UNSTUFF_BITS( ulResponse, 112, 3 );
pxCSD->tacc_ns = ( tacc_exp[ e ] * tacc_mant[ m ] + 9 ) / 10;
pxCSD->tacc_clks = UNSTUFF_BITS( ulResponse, 104, 8 ) * 100;
m = UNSTUFF_BITS( ulResponse, 99, 4 );
e = UNSTUFF_BITS( ulResponse, 96, 3 );
pxCSD->max_dtr = tran_exp[ e ] * tran_mant[ m ];
pxCSD->cmdclass = UNSTUFF_BITS( ulResponse, 84, 12 );
e = UNSTUFF_BITS( ulResponse, 47, 3 );
m = UNSTUFF_BITS( ulResponse, 62, 12 );
pxCSD->capacity = ( 1 + m ) << ( e + 2 );
/*
* The CSD capacity field is in units of read_blkbits.
* set_capacity takes units of 512 bytes.
*/
pxCSD->read_blkbits = UNSTUFF_BITS( ulResponse, 80, 4 );
pxCSD->read_partial = UNSTUFF_BITS( ulResponse, 79, 1 );
pxCSD->write_misalign = UNSTUFF_BITS( ulResponse, 78, 1 );
pxCSD->read_misalign = UNSTUFF_BITS( ulResponse, 77, 1 );
pxCSD->r2w_factor = UNSTUFF_BITS( ulResponse, 26, 3 );
pxCSD->write_blkbits = UNSTUFF_BITS( ulResponse, 22, 4 );
pxCSD->write_partial = UNSTUFF_BITS( ulResponse, 21, 1 );
pxCSD->capacity <<= ( pxCSD->read_blkbits - 9 );
FF_PRINTF ("Capacity: (%u + 1) << (%u + 2) = %u Rd/Wr bits %u/%u\n",
m, e,
( unsigned )pxCSD->capacity,
( unsigned )pxCSD->read_blkbits,
( unsigned )pxCSD->write_blkbits);
if( UNSTUFF_BITS( ulResponse, 46, 1 ) )
{
pxCSD->erase_size = 1;
}
else if( pxCSD->write_blkbits >= 9 )
{
pxCSD->erase_size = UNSTUFF_BITS( ulResponse, 39, 7 ) + 1;
pxCSD->erase_size <<= pxCSD->write_blkbits - 9;
}
else
{
pxCSD->erase_size = 0; // Card is not eraseble
}
break;
case 1:
/*
* This is a block-addressed SDHC card. Most
* interesting fields are unused and have fixed
* values. To avoid getting tripped by buggy cards,
* we assume those fixed values ourselves.
*/
mmc_is_block_addressed = 1;
pxCSD->tacc_ns = 0; /* Unused */
pxCSD->tacc_clks = 0; /* Unused */
m = UNSTUFF_BITS( ulResponse, 99, 4 );
e = UNSTUFF_BITS( ulResponse, 96, 3 );
// max_dtr gives 25,000,000
pxCSD->max_dtr = tran_exp[ e ] * tran_mant[ m ];
// cmdClass gives: 10110110101 (0x5B5)
pxCSD->cmdclass = UNSTUFF_BITS( ulResponse, 84, 12 );
m = UNSTUFF_BITS( ulResponse, 48, 22 );
pxCSD->capacity = ( 1 + m ) << 10;
FF_PRINTF( "capacity: (1 + %u) << 10 DTR %u Mhz\n", m, pxCSD->max_dtr / 1000000);
pxCSD->read_blkbits = 9;
pxCSD->read_partial = 0;
pxCSD->write_misalign = 0;
pxCSD->read_misalign = 0;
pxCSD->r2w_factor = 4; /* Unused */
pxCSD->write_blkbits = 9;
pxCSD->write_partial = 0;
pxCSD->erase_size = 1;
break;
default:
FF_PRINTF ("sd_decode_csd: unrecognised CSD structure version %d\n", csd_struct);
iResult = -1;
break;
}
if( iResult >= 0 )
{
unsigned int sz;
FF_PRINTF ("sd_decode_csd: capacity %lu (%s addressed)\n",
pxCSD->capacity, mmc_is_block_addressed ? "block" : "byte");
sz = (pxCSD->capacity << (pxCSD->read_blkbits - 9)) >> 11;
if (sz < 128)
{
pxCSD->pref_erase = 512 * 1024 / 512;
}
else if (sz < 512)
{
pxCSD->pref_erase = 1024 * 1024 / 512;
}
else if (sz < 1024)
{
pxCSD->pref_erase = 2 * 1024 * 1024 / 512;
}
else
{
pxCSD->pref_erase = 4 * 1024 * 1024 / 512;
}
if (pxCSD->pref_erase < pxCSD->erase_size)
{
pxCSD->pref_erase = pxCSD->erase_size;
}
else
{
sz = ( pxCSD->pref_erase % pxCSD->erase_size );
if( sz != 0 )
{
pxCSD->pref_erase += ( pxCSD->erase_size - sz );
}
}
// compute last block addr
pxCSD->sd_last_block_address = pxCSD->capacity - 1;
// compute card capacity in bytes
pxCSD->capacity_bytes = ( ( uint64_t )XSDPS_BLK_SIZE_512_MASK ) * pxCSD->capacity;
FF_PRINTF( "sd_mmc_spi_get_capacity: Capacity %lu MB Erase %u Pref %lu\n",
( uint32_t ) ( pxCSD->capacity_bytes / ( 1024LLU * 1024LLU ) ),
pxCSD->erase_size,
pxCSD->pref_erase );
}
return iResult;
}

View file

@ -0,0 +1,56 @@
/******************************************************************************
*
* mmc_decode_cid() and sd_decode_csd()
*
* analyse the meta data of an SD-card to read its capacity and some other properties.
*
* CID and CSD Analysis borrowed from the Linux kernel.
*
******************************************************************************/
#ifndef SDPS_INFO_H_
#define SDPS_INFO_H_ 1
#include <stdint.h>
struct mmc_cid {
uint32_t manfid;
char prod_name[8];
uint32_t serial;
uint16_t oemid;
uint16_t year;
uint8_t hwrev;
uint8_t fwrev;
uint8_t month;
};
struct mmc_csd {
volatile uint64_t capacity_bytes;
uint32_t sd_last_block_address;
uint8_t mmca_vsn;
uint16_t erase_size;
uint8_t spare;
uint16_t cmdclass;
uint16_t tacc_clks;
int32_t erase_shift;
uint32_t tacc_ns;
uint32_t r2w_factor;
uint32_t max_dtr;
uint32_t read_blkbits;
uint32_t write_blkbits;
uint32_t capacity;
uint32_t pref_erase;
uint32_t read_partial : 1,
read_misalign : 1,
write_partial : 1,
write_misalign : 1;
};
extern struct mmc_cid myCID;
extern struct mmc_csd myCSD;
int mmc_decode_cid( const struct mmc_csd *pxCSD, struct mmc_cid *pxCID, uint32_t *raw_data );
int sd_decode_csd( struct mmc_csd *pxCSD, uint32_t *ulResponse );
#endif /* SDPS_INFO_H_ */

View file

@ -0,0 +1,978 @@
/******************************************************************************
*
* Copyright (C) 2013 - 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xsdps_options.c
* @addtogroup sdps_v2_5
* @{
*
* Contains API's for changing the various options in host and card.
* See xsdps.h for a detailed description of the device and driver.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00a hk/sg 10/17/13 Initial release
* 2.1 hk 04/18/14 Increase sleep for eMMC switch command.
* Add sleep for microblaze designs. CR# 781117.
* 2.3 sk 09/23/14 Use XSdPs_Change_ClkFreq API whenever changing
* clock.CR# 816586.
* 2.5 sg 07/09/15 Added SD 3.0 features
* kvn 07/15/15 Modified the code according to MISRAC-2012.
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xsdps.h"
#include "xil_cache.h"
/*
* The header sleep.h and API usleep() can only be used with an arm design.
* MB_Sleep() is used for microblaze design.
*/
#if defined (__arm__) || defined (__aarch64__)
#include "sleep.h"
#endif
#ifdef __MICROBLAZE__
#include "microblaze_sleep.h"
#endif
#include <FreeRTOS.h>
#include "task.h"
#include "FreeRTOSFATConfig.h"
#include "uncached_memory.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
s32 XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt);
void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff);
s32 XSdPs_Uhs_ModeInit(XSdPs *InstancePtr, u8 Mode);
static s32 XSdPs_Execute_Tuning(XSdPs *InstancePtr);
s32 XSdPs_Uhs_ModeInit(XSdPs *InstancePtr, u8 Mode);
#if( ffconfigSDIO_DRIVER_USES_INTERRUPT != 0 )
/* Declared in ff_sddisk.c :
Function will sleep and get interrupted on a change of
the status register. It will loop until:
1. Expected bit (ulMask) becomes high
2. Time-out reached (normally 2 seconds)
*/
extern u32 XSdPs_WaitInterrupt( XSdPs *InstancePtr, u32 ulMask );
/* Clear the interrupt before using it. */
extern void XSdPs_ClearInterrupt( XSdPs *InstancePtr );
#else
#error Please define ffconfigSDIO_DRIVER_USES_INTERRUPT
#endif
/*****************************************************************************/
/**
* Update Block size for read/write operations.
*
* @param InstancePtr is a pointer to the instance to be worked on.
* @param BlkSize - Block size passed by the user.
*
* @return None
*
******************************************************************************/
s32 XSdPs_SetBlkSize(XSdPs *InstancePtr, u16 BlkSize)
{
s32 Status;
u32 PresentStateReg;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
XSDPS_PRES_STATE_OFFSET);
if ((PresentStateReg & ((u32)XSDPS_PSR_INHIBIT_CMD_MASK |
(u32)XSDPS_PSR_INHIBIT_DAT_MASK |
(u32)XSDPS_PSR_WR_ACTIVE_MASK | (u32)XSDPS_PSR_RD_ACTIVE_MASK)) != 0U) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
/* Send block write command */
Status = XSdPs_CmdTransfer(InstancePtr, CMD16, BlkSize, 0U);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
Status = (s32)XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
XSDPS_RESP0_OFFSET);
/* Set block size to the value passed */
XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET,
BlkSize & XSDPS_BLK_SIZE_MASK);
Status = XST_SUCCESS;
RETURN_PATH:
return Status;
}
/*****************************************************************************/
/**
*
* API to get bus width support by card.
*
*
* @param InstancePtr is a pointer to the XSdPs instance.
* @param SCR - buffer to store SCR register returned by card.
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
*
* @note None.
*
******************************************************************************/
s32 XSdPs_Get_BusWidth(XSdPs *InstancePtr, u8 *SCR)
{
s32 Status;
u16 BlkCnt;
u16 BlkSize;
s32 LoopCnt;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
for (LoopCnt = 0; LoopCnt < 8; LoopCnt++) {
SCR[LoopCnt] = 0U;
}
/* Send block write command */
Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
InstancePtr->RelCardAddr, 0U);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
BlkCnt = XSDPS_SCR_BLKCNT;
BlkSize = XSDPS_SCR_BLKSIZE;
/* Set block size to the value passed */
BlkSize &= XSDPS_BLK_SIZE_MASK;
XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
XSDPS_BLK_SIZE_OFFSET, BlkSize);
XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, SCR);
XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
XSDPS_XFER_MODE_OFFSET,
XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK);
Xil_DCacheInvalidateRange((u32)SCR, 8);
Status = XSdPs_CmdTransfer(InstancePtr, ACMD51, 0U, BlkCnt);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
/*
* Check for transfer complete
*/
Status = XSdPs_Wait_For(InstancePtr, XSDPS_INTR_TC_MASK, pdTRUE);
if (Status != XST_SUCCESS) {
goto RETURN_PATH;
}
Status = (s32)XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
XSDPS_RESP0_OFFSET);
Status = XST_SUCCESS;
RETURN_PATH:
return Status;
}
/*****************************************************************************/
/**
*
* API to set bus width to 4-bit in card and host
*
*
* @param InstancePtr is a pointer to the XSdPs instance.
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
*
* @note None.
*
******************************************************************************/
s32 XSdPs_Change_BusWidth(XSdPs *InstancePtr)
{
s32 Status;
u32 StatusReg;
u32 Arg;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
if (InstancePtr->CardType == XSDPS_CARD_SD) {
Status = XSdPs_CmdTransfer(InstancePtr, CMD55, InstancePtr->RelCardAddr,
0U);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
InstancePtr->BusWidth = XSDPS_4_BIT_WIDTH;
Arg = ((u32)InstancePtr->BusWidth);
Status = XSdPs_CmdTransfer(InstancePtr, ACMD6, Arg, 0U);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
} else {
if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3)
&& (InstancePtr->CardType == XSDPS_CHIP_EMMC)) {
/* in case of eMMC data width 8-bit */
InstancePtr->BusWidth = XSDPS_8_BIT_WIDTH;
} else {
InstancePtr->BusWidth = XSDPS_4_BIT_WIDTH;
}
if (InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH) {
Arg = XSDPS_MMC_8_BIT_BUS_ARG;
} else {
Arg = XSDPS_MMC_4_BIT_BUS_ARG;
}
Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 0U);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
/* Check for transfer complete */
Status = XSdPs_Wait_For(InstancePtr, XSDPS_INTR_TC_MASK, pdTRUE);
if (Status != XST_SUCCESS) {
goto RETURN_PATH;
}
}
#if defined (__arm__) || defined (__aarch64__)
usleep(XSDPS_MMC_DELAY_FOR_SWITCH);
#endif
#ifdef __MICROBLAZE__
/* 2 msec delay */
MB_Sleep(2);
#endif
StatusReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
XSDPS_HOST_CTRL1_OFFSET);
/* Width setting in controller */
if (InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH) {
StatusReg |= XSDPS_HC_EXT_BUS_WIDTH;
} else {
StatusReg |= XSDPS_HC_WIDTH_MASK;
}
XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
XSDPS_HOST_CTRL1_OFFSET,
(u8)StatusReg);
Status = (s32)XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
XSDPS_RESP0_OFFSET);
Status = XST_SUCCESS;
RETURN_PATH:
return Status;
}
/*****************************************************************************/
/**
*
* API to get bus speed supported by card.
*
*
* @param InstancePtr is a pointer to the XSdPs instance.
* @param ReadBuff - buffer to store function group support data
* returned by card.
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
*
* @note None.
*
******************************************************************************/
s32 XSdPs_Get_BusSpeed(XSdPs *InstancePtr, u8 *ReadBuff)
{
s32 Status;
u32 Arg;
u16 BlkCnt;
u16 BlkSize;
s32 LoopCnt;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
for (LoopCnt = 0; LoopCnt < 64; LoopCnt++) {
ReadBuff[LoopCnt] = 0U;
}
BlkCnt = XSDPS_SWITCH_CMD_BLKCNT;
BlkSize = XSDPS_SWITCH_CMD_BLKSIZE;
BlkSize &= XSDPS_BLK_SIZE_MASK;
XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
XSDPS_BLK_SIZE_OFFSET, BlkSize);
XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, ReadBuff);
XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
XSDPS_XFER_MODE_OFFSET,
XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK);
Arg = XSDPS_SWITCH_CMD_HS_GET;
Xil_DCacheInvalidateRange((u32)ReadBuff, 64);
Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 1U);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
/*
* Check for transfer complete
*/
Status = XSdPs_Wait_For(InstancePtr, XSDPS_INTR_TC_MASK, pdTRUE);
if (Status != XST_SUCCESS) {
goto RETURN_PATH;
}
Status = (s32)XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
XSDPS_RESP0_OFFSET);
Status = XST_SUCCESS;
RETURN_PATH:
return Status;
}
/*****************************************************************************/
/**
*
* API to set high speed in card and host. Changes clock in host accordingly.
*
*
* @param InstancePtr is a pointer to the XSdPs instance.
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
*
* @note None.
*
******************************************************************************/
s32 XSdPs_Change_BusSpeed(XSdPs *InstancePtr)
{
s32 Status;
u32 StatusReg;
u32 Arg;
u16 BlkCnt;
u16 BlkSize;
u8 ReadBuff[64];
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
if (InstancePtr->CardType == XSDPS_CARD_SD) {
BlkCnt = XSDPS_SWITCH_CMD_BLKCNT;
BlkSize = XSDPS_SWITCH_CMD_BLKSIZE;
BlkSize &= XSDPS_BLK_SIZE_MASK;
XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
XSDPS_BLK_SIZE_OFFSET, BlkSize);
XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, ReadBuff);
Xil_DCacheFlushRange((u32)ReadBuff, 64);
XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
XSDPS_XFER_MODE_OFFSET,
XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK);
Arg = XSDPS_SWITCH_CMD_HS_SET;
Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 1U);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
/*
* Check for transfer complete
*/
Status = XSdPs_Wait_For(InstancePtr, XSDPS_INTR_TC_MASK, pdTRUE);
if (Status != XST_SUCCESS) {
goto RETURN_PATH;
}
/* Change the clock frequency to 50 MHz */
InstancePtr->BusSpeed = XSDPS_CLK_50_MHZ;
Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
} else if (InstancePtr->CardType == XSDPS_CARD_MMC) {
Arg = XSDPS_MMC_HIGH_SPEED_ARG;
Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 0U);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
/*
* Check for transfer complete
*/
Status = XSdPs_Wait_For(InstancePtr, XSDPS_INTR_TC_MASK, pdTRUE);
if (Status != XST_SUCCESS) {
goto RETURN_PATH;
}
/* Change the clock frequency to 52 MHz */
InstancePtr->BusSpeed = XSDPS_CLK_52_MHZ;
Status = XSdPs_Change_ClkFreq(InstancePtr, XSDPS_CLK_52_MHZ);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
} else {
Arg = XSDPS_MMC_HS200_ARG;
Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 0U);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
/*
* Check for transfer complete
*/
Status = XSdPs_Wait_For(InstancePtr, XSDPS_INTR_TC_MASK, pdTRUE);
if (Status != XST_SUCCESS) {
goto RETURN_PATH;
}
/* Change the clock frequency to 200 MHz */
InstancePtr->BusSpeed = XSDPS_MMC_HS200_MAX_CLK;
Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
Status = XSdPs_Execute_Tuning(InstancePtr);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
}
#if defined (__arm__) || defined (__aarch64__)
usleep(XSDPS_MMC_DELAY_FOR_SWITCH);
#endif
#ifdef __MICROBLAZE__
/* 2 msec delay */
MB_Sleep(2);
#endif
StatusReg = (s32)XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
XSDPS_HOST_CTRL1_OFFSET);
StatusReg |= XSDPS_HC_SPEED_MASK;
XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
XSDPS_HOST_CTRL1_OFFSET, (u8)StatusReg);
Status = (s32)XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
XSDPS_RESP0_OFFSET);
Status = XST_SUCCESS;
RETURN_PATH:
return Status;
}
/*****************************************************************************/
/**
*
* API to change clock freq to given value.
*
*
* @param InstancePtr is a pointer to the XSdPs instance.
* @param SelFreq - Clock frequency in Hz.
*
* @return None
*
* @note This API will change clock frequency to the value less than
* or equal to the given value using the permissible dividors.
*
******************************************************************************/
s32 XSdPs_Change_ClkFreq(XSdPs *InstancePtr, u32 SelFreq)
{
u16 ClockReg;
u16 DivCnt;
u16 Divisor = 0U;
u16 ExtDivisor;
s32 Status;
u16 ReadReg;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/* Disable clock */
ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
XSDPS_CLK_CTRL_OFFSET);
ClockReg &= ~(XSDPS_CC_SD_CLK_EN_MASK | XSDPS_CC_INT_CLK_EN_MASK);
XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
XSDPS_CLK_CTRL_OFFSET, ClockReg);
if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
/* Calculate divisor */
for (DivCnt = 0x1U; DivCnt <= XSDPS_CC_EXT_MAX_DIV_CNT;DivCnt++) {
if (((InstancePtr->Config.InputClockHz) / DivCnt) <= SelFreq) {
Divisor = DivCnt >> 1;
break;
}
}
if (DivCnt > XSDPS_CC_EXT_MAX_DIV_CNT) {
/* No valid divisor found for given frequency */
Status = XST_FAILURE;
goto RETURN_PATH;
}
} else {
/* Calculate divisor */
DivCnt = 0x1U;
while (DivCnt <= XSDPS_CC_MAX_DIV_CNT) {
if (((InstancePtr->Config.InputClockHz) / DivCnt) <= SelFreq) {
Divisor = DivCnt / 2U;
break;
}
DivCnt = DivCnt << 1U;
}
if (DivCnt > XSDPS_CC_MAX_DIV_CNT) {
/* No valid divisor found for given frequency */
Status = XST_FAILURE;
goto RETURN_PATH;
}
}
/* Set clock divisor */
if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
XSDPS_CLK_CTRL_OFFSET);
ClockReg &= ~(XSDPS_CC_SDCLK_FREQ_SEL_MASK |
XSDPS_CC_SDCLK_FREQ_SEL_EXT_MASK);
ExtDivisor = Divisor >> 8;
ExtDivisor <<= XSDPS_CC_EXT_DIV_SHIFT;
ExtDivisor &= XSDPS_CC_SDCLK_FREQ_SEL_EXT_MASK;
Divisor <<= XSDPS_CC_DIV_SHIFT;
Divisor &= XSDPS_CC_SDCLK_FREQ_SEL_MASK;
ClockReg |= Divisor | ExtDivisor | (u16)XSDPS_CC_INT_CLK_EN_MASK;
XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_CLK_CTRL_OFFSET,
ClockReg);
} else {
ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
XSDPS_CLK_CTRL_OFFSET);
ClockReg &= (~XSDPS_CC_SDCLK_FREQ_SEL_MASK);
Divisor <<= XSDPS_CC_DIV_SHIFT;
Divisor &= XSDPS_CC_SDCLK_FREQ_SEL_MASK;
ClockReg |= Divisor | (u16)XSDPS_CC_INT_CLK_EN_MASK;
XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_CLK_CTRL_OFFSET,
ClockReg);
}
/* Wait for internal clock to stabilize */
ReadReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
XSDPS_CLK_CTRL_OFFSET);
while((ReadReg & XSDPS_CC_INT_CLK_STABLE_MASK) == 0U) {
ReadReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
XSDPS_CLK_CTRL_OFFSET);;
}
/* Enable SD clock */
ClockReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
XSDPS_CLK_CTRL_OFFSET);
XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
XSDPS_CLK_CTRL_OFFSET,
ClockReg | XSDPS_CC_SD_CLK_EN_MASK);
Status = XST_SUCCESS;
RETURN_PATH:
return Status;
}
/*****************************************************************************/
/**
*
* API to send pullup command to card before using DAT line 3(using 4-bit bus)
*
*
* @param InstancePtr is a pointer to the XSdPs instance.
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
*
* @note None.
*
******************************************************************************/
s32 XSdPs_Pullup(XSdPs *InstancePtr)
{
s32 Status;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
InstancePtr->RelCardAddr, 0U);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
Status = XSdPs_CmdTransfer(InstancePtr, ACMD42, 0U, 0U);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
Status = XST_SUCCESS;
RETURN_PATH:
return Status;
}
/*****************************************************************************/
/**
*
* API to get EXT_CSD register of eMMC.
*
*
* @param InstancePtr is a pointer to the XSdPs instance.
* @param ReadBuff - buffer to store EXT_CSD
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
*
* @note None.
*
******************************************************************************/
s32 XSdPs_Get_Mmc_ExtCsd(XSdPs *InstancePtr, u8 *ReadBuff)
{
s32 Status;
u32 Arg = 0U;
u16 BlkCnt;
u16 BlkSize;
s32 LoopCnt;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
for (LoopCnt = 0; LoopCnt < 512; LoopCnt++) {
ReadBuff[LoopCnt] = 0U;
}
BlkCnt = XSDPS_EXT_CSD_CMD_BLKCNT;
BlkSize = XSDPS_EXT_CSD_CMD_BLKSIZE;
BlkSize &= XSDPS_BLK_SIZE_MASK;
XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
XSDPS_BLK_SIZE_OFFSET, BlkSize);
XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, ReadBuff);
Xil_DCacheInvalidateRange((u32)ReadBuff, 512U);
XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
XSDPS_XFER_MODE_OFFSET,
XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK);
/* Send SEND_EXT_CSD command */
Status = XSdPs_CmdTransfer(InstancePtr, CMD8, Arg, 1U);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
/*
* Check for transfer complete
*/
Status = XSdPs_Wait_For(InstancePtr, XSDPS_INTR_TC_MASK, pdTRUE);
if (Status != XST_SUCCESS) {
goto RETURN_PATH;
}
Status = (s32)XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
XSDPS_RESP0_OFFSET);
Status = XST_SUCCESS;
RETURN_PATH:
return Status;
}
/*****************************************************************************/
/**
*
* API to UHS-I mode initialization
*
*
* @param InstancePtr is a pointer to the XSdPs instance.
* @param Mode UHS-I mode
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
*
* @note None.
*
******************************************************************************/
s32 XSdPs_Uhs_ModeInit(XSdPs *InstancePtr, u8 Mode)
{
s32 Status;
u16 CtrlReg;
u32 Arg;
u16 BlkCnt;
u16 BlkSize;
u8 ReadBuff[64];
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/* Drive strength */
/* Bus speed mode selection */
BlkCnt = XSDPS_SWITCH_CMD_BLKCNT;
BlkSize = XSDPS_SWITCH_CMD_BLKSIZE;
BlkSize &= XSDPS_BLK_SIZE_MASK;
XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET,
BlkSize);
XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, ReadBuff);
Xil_DCacheFlushRange((u32)ReadBuff, 64);
XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_XFER_MODE_OFFSET,
XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK);
switch (Mode) {
case 0U:
Arg = XSDPS_SWITCH_CMD_SDR12_SET;
InstancePtr->BusSpeed = XSDPS_SD_SDR12_MAX_CLK;
break;
case 1U:
Arg = XSDPS_SWITCH_CMD_SDR25_SET;
InstancePtr->BusSpeed = XSDPS_SD_SDR25_MAX_CLK;
break;
case 2U:
Arg = XSDPS_SWITCH_CMD_SDR50_SET;
InstancePtr->BusSpeed = XSDPS_SD_SDR50_MAX_CLK;
break;
case 3U:
Arg = XSDPS_SWITCH_CMD_SDR104_SET;
InstancePtr->BusSpeed = XSDPS_SD_SDR104_MAX_CLK;
break;
case 4U:
Arg = XSDPS_SWITCH_CMD_DDR50_SET;
InstancePtr->BusSpeed = XSDPS_SD_DDR50_MAX_CLK;
break;
default:
Status = XST_FAILURE;
goto RETURN_PATH;
break;
}
Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 1U);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
/*
* Check for transfer complete
*/
Status = XSdPs_Wait_For(InstancePtr, XSDPS_INTR_TC_MASK, pdTRUE);
if (Status != XST_SUCCESS) {
goto RETURN_PATH;
}
/* Current limit */
/* Set UHS mode in controller */
CtrlReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
XSDPS_HOST_CTRL2_OFFSET);
CtrlReg &= (u16)(~XSDPS_HC2_UHS_MODE_MASK);
CtrlReg |= Mode;
XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
XSDPS_HOST_CTRL2_OFFSET, CtrlReg);
/* Change the clock frequency */
Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
if((Mode == XSDPS_UHS_SPEED_MODE_SDR104) ||
(Mode == XSDPS_UHS_SPEED_MODE_DDR50)) {
/* Send tuning pattern */
Status = XSdPs_Execute_Tuning(InstancePtr);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
}
Status = XST_SUCCESS;
RETURN_PATH:
return Status;
}
static s32 XSdPs_Execute_Tuning(XSdPs *InstancePtr)
{
s32 Status;
u16 BlkCnt;
u16 BlkSize;
s32 LoopCnt;
u8 ReadBuff[128];
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
BlkCnt = XSDPS_TUNING_CMD_BLKCNT;
BlkSize = XSDPS_TUNING_CMD_BLKSIZE;
if(InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH)
{
BlkSize = BlkSize*2U;
}
BlkSize &= XSDPS_BLK_SIZE_MASK;
XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET,
BlkSize);
for (LoopCnt = 0; LoopCnt < (s32)BlkSize; LoopCnt++) {
ReadBuff[LoopCnt] = 0U;
}
XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, ReadBuff);
XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_XFER_MODE_OFFSET,
XSDPS_TM_DAT_DIR_SEL_MASK | XSDPS_TM_DMA_EN_MASK);
Xil_DCacheInvalidateRange((u32)ReadBuff, BlkSize);
if(InstancePtr->CardType == XSDPS_CARD_SD) {
Status = XSdPs_CmdTransfer(InstancePtr, CMD19, 0U, 1U);
} else {
Status = XSdPs_CmdTransfer(InstancePtr, CMD21, 0U, 1U);
}
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
/*
* Check for transfer complete
* Polling for response for now
*/
Status = XSdPs_Wait_For(InstancePtr, XSDPS_INTR_TC_MASK, pdTRUE);
if (Status != XST_SUCCESS) {
goto RETURN_PATH;
}
Status = XST_SUCCESS;
RETURN_PATH: return Status;
}
/** @} */

View file

@ -0,0 +1,95 @@
/******************************************************************************
*
* Copyright (C) 2013 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xsdps_sinit.c
*
* The implementation of the XSdPs component's static initialization
* functionality.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00a hk/sg 10/17/13 Initial release
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xstatus.h"
#include "xsdps.h"
#include "xparameters.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/************************** Variable Definitions *****************************/
extern XSdPs_Config XSdPs_ConfigTable[];
/*****************************************************************************/
/**
*
* Looks up the device configuration based on the unique device ID. A table
* contains the configuration info for each device in the system.
*
* @param DeviceId contains the ID of the device to look up the
* configuration for.
*
* @return
*
* A pointer to the configuration found or NULL if the specified device ID was
* not found. See xsdps.h for the definition of XSdPs_Config.
*
* @note None.
*
******************************************************************************/
XSdPs_Config *XSdPs_LookupConfig(u16 DeviceId)
{
XSdPs_Config *CfgPtr = NULL;
int Index;
for (Index = 0; Index < XPAR_XSDPS_NUM_INSTANCES; Index++) {
if (XSdPs_ConfigTable[Index].DeviceId == DeviceId) {
CfgPtr = &XSdPs_ConfigTable[Index];
break;
}
}
return CfgPtr;
}

View file

@ -0,0 +1,75 @@
//
//
//
#define SD_MMC_SPI_MEM 1
#include "ff_headers.h"
#include "logbuf.h"
#include "secCache.h"
#include "ff_flush.h"
extern BaseType_t FF_SemaphoreTaken( void *pxSemaphore );
FF_Error_t FF_FlushWrites( FF_IOManager_t *pxIOManager, BaseType_t xForced )
{
FF_Error_t xRetValue;
if( ( pxIOManager == NULL ) || ( cache_dirt_count() == 0 ) )
{
xRetValue = FF_ERR_NONE;
}
else if( ( pxIOManager->ucPreventFlush != pdFALSE ) && ( xForced == pdFALSE ) )
{
xRetValue = FF_ERR_IOMAN_PARTITION_MOUNTED | FF_ERRFLAG;
}
else
{
BaseType_t rc = 0;
if( xForced != pdFALSE )
{
FF_FlushCache( pxIOManager );
}
// if( FF_TrySemaphore( pxIOManager->pvSemaphore, xForced ? 5000 : 0 ) != pdFALSE )
if( ( xForced != pdFALSE ) || ( FF_SemaphoreTaken( pxIOManager->pvSemaphore ) == pdFALSE ) )
{
rc = cache_flush( xForced );
// FF_ReleaseSemaphore( pxIOManager->pvSemaphore );
}
xRetValue = rc;
}
return xRetValue;
}
FF_Error_t FF_StopFlush( FF_IOManager_t *pxIOManager, BaseType_t xFlag )
{
FF_Error_t xRetValue;
if( pxIOManager == NULL )
{
xRetValue = 0;
}
else
{
vTaskSuspendAll();
{
xRetValue = pxIOManager->ucPreventFlush;
if( xFlag != FLUSH_ENABLE )
{
xRetValue++;
}
else if ( xRetValue > 0 )
{
xRetValue--;
}
pxIOManager->ucPreventFlush = xRetValue;
}
xTaskResumeAll();
}
return xRetValue;
}

View file

@ -0,0 +1,48 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
#if !defined(__FF_FLUSH_H__)
#define __FF_FLUSH_H__
#ifdef __cplusplus
extern "C" {
#endif
// HT addition: call FF_FlushCache and in addition call cache_write_flush (see secCache.cpp)
FF_Error_t FF_FlushWrites( FF_IOManager_t *pxIOManager, BaseType_t xForced );
#define FLUSH_DISABLE 1
#define FLUSH_ENABLE 0
// HT addition: prevent flushing temporarily FF_StopFlush(pIoMan, true)
FF_Error_t FF_StopFlush( FF_IOManager_t *pxIOManager, BaseType_t xFlag );
#ifdef __cplusplus
} // extern "C"
#endif
#endif // !defined(__FF_FLUSH_H__)

View file

@ -0,0 +1,343 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Scheduler include files. */
#include "FreeRTOS.h"
#include "ff_headers.h"
#include "event_groups.h"
/* Scheduler include files. */
#ifdef __WIN32__
#include "MyMalloc.h"
#else
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "tcpLogging.h"
#endif
#include "logbuf.h"
#include <string.h>
#include "bitops.h"
#if USE_SOFT_WDT
#include "softWdt.h"
#endif
#include "thread_mutex.h"
#include "event_groups.h"
#if( FF_DO_TRACE_SEMAPHORE != 0 )
#include "eventLogging.h"
#endif
/* There are two areas which are protected with a semaphore:
Directories and the FAT area.
The masks below are used when calling Group Event functions. */
#define FF_FAT_LOCK_EVENT_BITS ( ( const EventBits_t ) FF_FAT_LOCK )
#define FF_DIR_LOCK_EVENT_BITS ( ( const EventBits_t ) FF_DIR_LOCK )
/* This is not a real lock: it is a bit (or semaphore) will will be given
each time when a sector buffer is released. */
#define FF_BUF_LOCK_EVENT_BITS ( ( const EventBits_t ) FF_BUF_LOCK )
extern void myTaskDelay (unsigned aTime);
static char cMutexWasCreated = 0;
static pthread_mutex_t xFATMutex;
static void vCreateFATMutex ()
{
cMutexWasCreated = 1;
pthread_mutex_init ("FreeRTOS+FAT", &xFATMutex, 0);
}
BaseType_t FF_HasSemaphore (void *pxSemaphore)
{
// Return pdTRUE if the calling task owns the semaphore
if (!cMutexWasCreated) vCreateFATMutex ();
return pthread_has_mutex (&xFATMutex);
}
BaseType_t FF_SemaphoreTaken (void *pxSemaphore)
{
// Return pdTRUE if the calling task owns the semaphore
if (!cMutexWasCreated) vCreateFATMutex ();
return pthread_mutex_islocked (&xFATMutex);
}
#if( FF_DO_TRACE_SEMAPHORE != 0 )
static char mutex_owner[32];
#endif
BaseType_t FF_TrySemaphore( void *pxSemaphore, uint32_t ulTime_ms)
{
BaseType_t rc;
#if( FF_DO_TRACE_SEMAPHORE != 0 )
{
eventLogAdd("Pend_%s\n", pcName);
}
#endif /* FF_DO_TRACE_SEMAPHORE */
if (!cMutexWasCreated) vCreateFATMutex ();
rc = pthread_mutex_lock (&xFATMutex, ulTime_ms);
#if( FF_DO_TRACE_SEMAPHORE != 0 )
if (rc > 0) {
if(mutex_owner[0] != 0) {
logPrintf("Pend Try: %s overruled\n", mutex_owner);
}
snprintf(mutex_owner, sizeof mutex_owner, pcName);
}
#endif /* FF_DO_TRACE_SEMAPHORE */
return rc;
}
/*-----------------------------------------------------------*/
void FF_PendSemaphore( void *pxSemaphore )
{
#if( FF_DO_TRACE_SEMAPHORE != 0 )
{
eventLogAdd("Pend_%s\n", pcName);
}
#endif /* FF_DO_TRACE_SEMAPHORE */
if (!cMutexWasCreated) vCreateFATMutex ();
pthread_mutex_lock (&xFATMutex, 120000);
#if( FF_DO_TRACE_SEMAPHORE != 0 )
{
if(mutex_owner[0] != 0) {
logPrintf("Pend Enter: %s overruled by %s\n", mutex_owner, pcName);
}
snprintf(mutex_owner, sizeof mutex_owner, pcName);
}
#endif /* FF_DO_TRACE_SEMAPHORE */
}
/*-----------------------------------------------------------*/
void FF_ReleaseSemaphore( void *pxSemaphore )
{
#if( FF_DO_TRACE_SEMAPHORE != 0 )
{
if(strcmp (pcName, mutex_owner) != 0) {
// FF_GetBuffer2 != FF_GetBuffer
logPrintf("Pend Exit: %s owned by %s\n", pcName, mutex_owner);
}
eventLogAdd("Exit_%s\n", pcName);
mutex_owner[0] = '\0';
}
#endif /* FF_DO_TRACE_SEMAPHORE */
if (cMutexWasCreated) {
pthread_mutex_unlock (&xFATMutex);
}
}
/*-----------------------------------------------------------*/
void FF_Sleep( uint32_t ulTime_ms )
{
myTaskDelay (ulTime_ms);
}
/*-----------------------------------------------------------*/
BaseType_t FF_CreateEvents( FF_IOManager_t *pxIOManager )
{
BaseType_t xResult;
pxIOManager->xEventGroup = xEventGroupCreate();
if( pxIOManager->xEventGroup != NULL )
{
xEventGroupSetBits( pxIOManager->xEventGroup,
FF_FAT_LOCK_EVENT_BITS | FF_DIR_LOCK_EVENT_BITS | FF_BUF_LOCK_EVENT_BITS );
xResult = pdTRUE;
}
else
{
xResult = pdFALSE;
}
return xResult;
}
/*-----------------------------------------------------------*/
void FF_LockDirectory( FF_IOManager_t *pxIOManager )
{
EventBits_t xBits;
for( ;; )
{
/* Called when a task want to make changes to a directory.
First it waits for the desired bit to come high. */
xEventGroupWaitBits( pxIOManager->xEventGroup,
FF_DIR_LOCK_EVENT_BITS, /* uxBitsToWaitFor */
( EventBits_t )0, /* xClearOnExit */
pdFALSE, /* xWaitForAllBits n.a. */
pdMS_TO_TICKS( 10000UL ) );
/* The next operation will only succeed for 1 task at a time,
because it is an atomary test & set operation: */
xBits = xEventGroupClearBits( pxIOManager->xEventGroup, FF_DIR_LOCK_EVENT_BITS );
if( ( xBits & FF_DIR_LOCK_EVENT_BITS ) != 0 )
{
/* This task has cleared the desired bit.
It now 'owns' the resource. */
break;
}
}
}
/*-----------------------------------------------------------*/
void FF_UnlockDirectory( FF_IOManager_t *pxIOManager )
{
configASSERT( ( xEventGroupGetBits( pxIOManager->xEventGroup ) & FF_DIR_LOCK_EVENT_BITS ) == 0 );
xEventGroupSetBits( pxIOManager->xEventGroup, FF_DIR_LOCK_EVENT_BITS );
}
/*-----------------------------------------------------------*/
int FF_Has_Lock( FF_IOManager_t *pxIOManager, uint32_t aBits )
{
int iReturn;
void *handle = xTaskGetCurrentTaskHandle();
if( ( aBits & FF_FAT_LOCK_EVENT_BITS ) != 0 )
{
if( ( pxIOManager->pvFATLockHandle != NULL ) && ( pxIOManager->pvFATLockHandle == handle ) )
{
iReturn = pdTRUE;
}
else
{
iReturn = pdFALSE;
}
}
else
{
iReturn = pdFALSE;
}
return iReturn;
}
void FF_Assert_Lock( FF_IOManager_t *pxIOManager, uint32_t aBits )
{
void *handle = xTaskGetCurrentTaskHandle();
if( ( aBits & FF_FAT_LOCK_EVENT_BITS ) != 0 )
{
configASSERT( pxIOManager->pvFATLockHandle != NULL && pxIOManager->pvFATLockHandle == handle );
/* In case configASSERT() is not defined. */
( void ) pxIOManager;
( void ) handle;
}
}
void FF_LockFAT( FF_IOManager_t *pxIOManager )
{
EventBits_t xBits;
configASSERT( FF_Has_Lock( pxIOManager, FF_FAT_LOCK ) == pdFALSE );
if (FF_Has_Lock( pxIOManager, FF_FAT_LOCK ) != pdFALSE )
{
return;
}
for( ;; )
{
/* Called when a task want to make changes to the FAT area.
First it waits for the desired bit to come high. */
xEventGroupWaitBits( pxIOManager->xEventGroup,
FF_FAT_LOCK_EVENT_BITS, /* uxBitsToWaitFor */
( EventBits_t )0, /* xClearOnExit */
pdFALSE, /* xWaitForAllBits n.a. */
pdMS_TO_TICKS( 10000UL ) );
/* The next operation will only succeed for 1 task at a time,
because it is an atomary test & set operation: */
xBits = xEventGroupClearBits( pxIOManager->xEventGroup, FF_FAT_LOCK_EVENT_BITS );
if( ( xBits & FF_FAT_LOCK_EVENT_BITS ) != 0 )
{
/* This task has cleared the desired bit.
It now 'owns' the resource. */
pxIOManager->pvFATLockHandle = xTaskGetCurrentTaskHandle();
break;
}
}
}
/*-----------------------------------------------------------*/
void FF_UnlockFAT( FF_IOManager_t *pxIOManager )
{
configASSERT( ( xEventGroupGetBits( pxIOManager->xEventGroup ) & FF_FAT_LOCK_EVENT_BITS ) == 0 );
if (FF_Has_Lock( pxIOManager, FF_FAT_LOCK ) != pdFALSE )
{
pxIOManager->pvFATLockHandle = NULL;
xEventGroupSetBits( pxIOManager->xEventGroup, FF_FAT_LOCK_EVENT_BITS );
}
else
{
FF_PRINTF("FF_UnlockFAT: wasn't locked by me\n");
}
}
/*-----------------------------------------------------------*/
BaseType_t FF_BufferWait( FF_IOManager_t *pxIOManager, uint32_t xWaitMS )
{
EventBits_t xBits;
BaseType_t xReturn;
/* This function is called when a task is waiting for a sector buffer
to become available. */
xBits = xEventGroupWaitBits( pxIOManager->xEventGroup,
FF_BUF_LOCK_EVENT_BITS, /* uxBitsToWaitFor */
FF_BUF_LOCK_EVENT_BITS, /* xClearOnExit */
pdFALSE, /* xWaitForAllBits n.a. */
pdMS_TO_TICKS( xWaitMS ) );
if( ( xBits & FF_BUF_LOCK_EVENT_BITS ) != 0 )
{
xReturn = pdTRUE;
}
else
{
xReturn = pdFALSE;
}
return xReturn;
}
/*-----------------------------------------------------------*/
void FF_BufferProceed( FF_IOManager_t *pxIOManager )
{
/* Wake-up all tasks that are waiting for a sector buffer to become available. */
xEventGroupSetBits( pxIOManager->xEventGroup, FF_BUF_LOCK_EVENT_BITS );
}
/*-----------------------------------------------------------*/

View file

@ -0,0 +1,423 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
/* Standard includes. */
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
/* Scheduler include files. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "portmacro.h"
/* FreeRTOS+FAT includes. */
#include "ff_headers.h"
#include "ff_ramdisk.h"
#include "ff_sys.h"
#define ramHIDDEN_SECTOR_COUNT 8
#define ramPRIMARY_PARTITIONS 1
#define ramHUNDRED_64_BIT 100ULL
#define ramSECTOR_SIZE 512UL
#define ramPARTITION_NUMBER 0 /* Only a single partition is used. */
#define ramBYTES_PER_KB ( 1024ull )
#define ramSECTORS_PER_KB ( ramBYTES_PER_KB / 512ull )
/* Used as a magic number to indicate that an FF_Disk_t structure is a RAM
disk. */
#define ramSIGNATURE 0x41404342
/*-----------------------------------------------------------*/
/*
* The function that writes to the media - as this is implementing a RAM disk
* the media is just a RAM buffer.
*/
static int32_t prvWriteRAM( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk );
/*
* The function that reads from the media - as this is implementing a RAM disk
* the media is just a RAM buffer.
*/
static int32_t prvReadRAM( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk );
/*
* This is the driver for a RAM disk. Unlike most media types, RAM disks are
* volatile so are created anew each time the system is booted. As the disk is
* new and just created, it must also be partitioned and formatted.
*/
static FF_Error_t prvPartitionAndFormatDisk( FF_Disk_t *pxDisk );
/*-----------------------------------------------------------*/
/* This is the prototype of the function used to initialise the RAM disk driver.
Other media drivers do not have to have the same prototype.
In this example:
+ pcName is the name to give the disk within FreeRTOS+FAT's virtual file system.
+ pucDataBuffer is the start of the RAM to use as the disk.
+ ulSectorCount is effectively the size of the disk, each sector is 512 bytes.
+ xIOManagerCacheSize is the size of the IO manager's cache, which must be a
multiple of the sector size, and at least twice as big as the sector size.
*/
FF_Disk_t *FF_RAMDiskInit( char *pcName, uint8_t *pucDataBuffer, uint32_t ulSectorCount, size_t xIOManagerCacheSize )
{
FF_Error_t xError;
FF_Disk_t *pxDisk = NULL;
FF_CreationParameters_t xParameters;
/* Check the validity of the xIOManagerCacheSize parameter. */
configASSERT( ( xIOManagerCacheSize % ramSECTOR_SIZE ) == 0 );
configASSERT( ( xIOManagerCacheSize >= ( 2 * ramSECTOR_SIZE ) ) );
/* Attempt to allocated the FF_Disk_t structure. */
pxDisk = ( FF_Disk_t * ) pvPortMalloc( sizeof( FF_Disk_t ) );
if( pxDisk != NULL )
{
/* Start with every member of the structure set to zero. */
memset( pxDisk, '\0', sizeof( FF_Disk_t ) );
/* Clear the entire space. */
memset( pucDataBuffer, '\0', ulSectorCount * ramSECTOR_SIZE );
/* The pvTag member of the FF_Disk_t structure allows the structure to be
extended to also include media specific parameters. The only media
specific data that needs to be stored in the FF_Disk_t structure for a
RAM disk is the location of the RAM buffer itself - so this is stored
directly in the FF_Disk_t's pvTag member. */
pxDisk->pvTag = ( void * ) pucDataBuffer;
/* The signature is used by the disk read and disk write functions to
ensure the disk being accessed is a RAM disk. */
pxDisk->ulSignature = ramSIGNATURE;
/* The number of sectors is recorded for bounds checking in the read and
write functions. */
pxDisk->ulNumberOfSectors = ulSectorCount;
/* Create the IO manager that will be used to control the RAM disk. */
memset( &xParameters, '\0', sizeof( xParameters ) );
xParameters.pucCacheMemory = NULL;
xParameters.ulMemorySize = xIOManagerCacheSize;
xParameters.ulSectorSize = ramSECTOR_SIZE;
xParameters.fnWriteBlocks = prvWriteRAM;
xParameters.fnReadBlocks = prvReadRAM;
xParameters.pxDisk = pxDisk;
/* Driver is reentrant so xBlockDeviceIsReentrant can be set to pdTRUE.
In this case the semaphore is only used to protect FAT data
structures. */
xParameters.pvSemaphore = ( void * ) xSemaphoreCreateRecursiveMutex();
xParameters.xBlockDeviceIsReentrant = pdFALSE;
pxDisk->pxIOManager = FF_CreateIOManger( &xParameters, &xError );
if( ( pxDisk->pxIOManager != NULL ) && ( FF_isERR( xError ) == pdFALSE ) )
{
/* Record that the RAM disk has been initialised. */
pxDisk->xStatus.bIsInitialised = pdTRUE;
/* Create a partition on the RAM disk. NOTE! The disk is only
being partitioned here because it is a new RAM disk. It is
known that the disk has not been used before, and cannot already
contain any partitions. Most media drivers will not perform
this step because the media will have already been partitioned. */
xError = prvPartitionAndFormatDisk( pxDisk );
if( FF_isERR( xError ) == pdFALSE )
{
/* Record the partition number the FF_Disk_t structure is, then
mount the partition. */
pxDisk->xStatus.bPartitionNumber = ramPARTITION_NUMBER;
/* Mount the partition. */
xError = FF_Mount( pxDisk, ramPARTITION_NUMBER );
FF_PRINTF( "FF_RAMDiskInit: FF_Mount: %s\n", ( const char * ) FF_GetErrMessage( xError ) );
}
if( FF_isERR( xError ) == pdFALSE )
{
/* The partition mounted successfully, add it to the virtual
file system - where it will appear as a directory off the file
system's root directory. */
FF_FS_Add( pcName, pxDisk );
}
}
else
{
FF_PRINTF( "FF_RAMDiskInit: FF_CreateIOManger: %s\n", ( const char * ) FF_GetErrMessage( xError ) );
/* The disk structure was allocated, but the disk's IO manager could
not be allocated, so free the disk again. */
FF_RAMDiskDelete( pxDisk );
pxDisk = NULL;
}
}
else
{
FF_PRINTF( "FF_RAMDiskInit: Malloc failed\n" );
}
return pxDisk;
}
/*-----------------------------------------------------------*/
BaseType_t FF_RAMDiskDelete( FF_Disk_t *pxDisk )
{
if( pxDisk != NULL )
{
pxDisk->ulSignature = 0;
pxDisk->xStatus.bIsInitialised = 0;
if( pxDisk->pxIOManager != NULL )
{
FF_DeleteIOManager( pxDisk->pxIOManager );
}
vPortFree( pxDisk );
}
return pdPASS;
}
/*-----------------------------------------------------------*/
static int32_t prvReadRAM( uint8_t *pucDestination, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk )
{
int32_t lReturn;
uint8_t *pucSource;
if( pxDisk != NULL )
{
if( pxDisk->ulSignature != ramSIGNATURE )
{
/* The disk structure is not valid because it doesn't contain a
magic number written to the disk when it was created. */
lReturn = FF_ERR_IOMAN_DRIVER_FATAL_ERROR | FF_ERRFLAG;
}
else if( pxDisk->xStatus.bIsInitialised == pdFALSE )
{
/* The disk has not been initialised. */
lReturn = FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE | FF_ERRFLAG;
}
else if( ulSectorNumber >= pxDisk->ulNumberOfSectors )
{
/* The start sector is not within the bounds of the disk. */
lReturn = ( FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE | FF_ERRFLAG );
}
else if( ( pxDisk->ulNumberOfSectors - ulSectorNumber ) < ulSectorCount )
{
/* The end sector is not within the bounds of the disk. */
lReturn = ( FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE | FF_ERRFLAG );
}
else
{
/* Obtain the pointer to the RAM buffer being used as the disk. */
pucSource = ( uint8_t * ) pxDisk->pvTag;
/* Move to the start of the sector being read. */
pucSource += ( ramSECTOR_SIZE * ulSectorNumber );
/* Copy the data from the disk. As this is a RAM disk this can be
done using memcpy(). */
memcpy( ( void * ) pucDestination,
( void * ) pucSource,
( size_t ) ( ulSectorCount * ramSECTOR_SIZE ) );
lReturn = FF_ERR_NONE;
}
}
else
{
lReturn = FF_ERR_NULL_POINTER | FF_ERRFLAG;
}
return lReturn;
}
/*-----------------------------------------------------------*/
static int32_t prvWriteRAM( uint8_t *pucSource, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk )
{
int32_t lReturn = FF_ERR_NONE;
uint8_t *pucDestination;
if( pxDisk != NULL )
{
if( pxDisk->ulSignature != ramSIGNATURE )
{
/* The disk structure is not valid because it doesn't contain a
magic number written to the disk when it was created. */
lReturn = FF_ERR_IOMAN_DRIVER_FATAL_ERROR | FF_ERRFLAG;
}
else if( pxDisk->xStatus.bIsInitialised == pdFALSE )
{
/* The disk has not been initialised. */
lReturn = FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE | FF_ERRFLAG;
}
else if( ulSectorNumber >= pxDisk->ulNumberOfSectors )
{
/* The start sector is not within the bounds of the disk. */
lReturn = ( FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE | FF_ERRFLAG );
}
else if( ( pxDisk->ulNumberOfSectors - ulSectorNumber ) < ulSectorCount )
{
/* The end sector is not within the bounds of the disk. */
lReturn = ( FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE | FF_ERRFLAG );
}
else
{
/* Obtain the location of the RAM being used as the disk. */
pucDestination = ( uint8_t * ) pxDisk->pvTag;
/* Move to the sector being written to. */
pucDestination += ( ramSECTOR_SIZE * ulSectorNumber );
/* Write to the disk. As this is a RAM disk the write can use a
memcpy(). */
memcpy( ( void * ) pucDestination,
( void * ) pucSource,
( size_t ) ulSectorCount * ( size_t ) ramSECTOR_SIZE );
lReturn = FF_ERR_NONE;
}
}
else
{
lReturn = FF_ERR_NULL_POINTER | FF_ERRFLAG;
}
return lReturn;
}
/*-----------------------------------------------------------*/
static FF_Error_t prvPartitionAndFormatDisk( FF_Disk_t *pxDisk )
{
FF_PartitionParameters_t xPartition;
FF_Error_t xError;
/* Create a single partition that fills all available space on the disk. */
memset( &xPartition, '\0', sizeof( xPartition ) );
xPartition.ulSectorCount = pxDisk->ulNumberOfSectors;
xPartition.ulHiddenSectors = ramHIDDEN_SECTOR_COUNT;
xPartition.xPrimaryCount = ramPRIMARY_PARTITIONS;
xPartition.eSizeType = eSizeIsQuota;
/* Partition the disk */
xError = FF_Partition( pxDisk, &xPartition );
FF_PRINTF( "FF_Partition: %s\n", ( const char * ) FF_GetErrMessage( xError ) );
if( FF_isERR( xError ) == pdFALSE )
{
/* Format the partition. */
xError = FF_Format( pxDisk, ramPARTITION_NUMBER, pdTRUE, pdTRUE );
FF_PRINTF( "FF_RAMDiskInit: FF_Format: %s\n", ( const char * ) FF_GetErrMessage( xError ) );
}
return xError;
}
/*-----------------------------------------------------------*/
BaseType_t FF_RAMDiskShowPartition( FF_Disk_t *pxDisk )
{
FF_Error_t xError;
uint64_t ullFreeSectors;
uint32_t ulTotalSizeKB, ulFreeSizeKB;
int iPercentageFree;
FF_IOManager_t *pxIOManager;
const char *pcTypeName = "unknown type";
BaseType_t xReturn = pdPASS;
if( pxDisk == NULL )
{
xReturn = pdFAIL;
}
else
{
pxIOManager = pxDisk->pxIOManager;
FF_PRINTF( "Reading FAT and calculating Free Space\n" );
switch( pxIOManager->xPartition.ucType )
{
case FF_T_FAT12:
pcTypeName = "FAT12";
break;
case FF_T_FAT16:
pcTypeName = "FAT16";
break;
case FF_T_FAT32:
pcTypeName = "FAT32";
break;
default:
pcTypeName = "UNKOWN";
break;
}
FF_GetFreeSize( pxIOManager, &xError );
ullFreeSectors = pxIOManager->xPartition.ulFreeClusterCount * pxIOManager->xPartition.ulSectorsPerCluster;
if( pxIOManager->xPartition.ulDataSectors == ( uint32_t )0 )
{
iPercentageFree = 0;
}
else
{
iPercentageFree = ( int ) ( ( ramHUNDRED_64_BIT * ullFreeSectors + pxIOManager->xPartition.ulDataSectors / 2 ) /
( ( uint64_t )pxIOManager->xPartition.ulDataSectors ) );
}
ulTotalSizeKB = pxIOManager->xPartition.ulDataSectors / ramSECTORS_PER_KB;
ulFreeSizeKB = ( uint32_t ) ( ullFreeSectors / ramSECTORS_PER_KB );
/* It is better not to use the 64-bit format such as %Lu because it
might not be implemented. */
FF_PRINTF( "Partition Nr %8u\n", pxDisk->xStatus.bPartitionNumber );
FF_PRINTF( "Type %8u (%s)\n", pxIOManager->xPartition.ucType, pcTypeName );
FF_PRINTF( "VolLabel '%8s' \n", pxIOManager->xPartition.pcVolumeLabel );
FF_PRINTF( "TotalSectors %8lu\n", pxIOManager->xPartition.ulTotalSectors );
FF_PRINTF( "SecsPerCluster %8lu\n", pxIOManager->xPartition.ulSectorsPerCluster );
FF_PRINTF( "Size %8lu KB\n", ulTotalSizeKB );
FF_PRINTF( "FreeSize %8lu KB ( %d perc free )\n", ulFreeSizeKB, iPercentageFree );
}
return xReturn;
}
/*-----------------------------------------------------------*/
void FF_RAMDiskFlush( FF_Disk_t *pxDisk )
{
if( ( pxDisk != NULL ) && ( pxDisk->xStatus.bIsInitialised != 0 ) && ( pxDisk->pxIOManager != NULL ) )
{
FF_FlushCache( pxDisk->pxIOManager );
}
}
/*-----------------------------------------------------------*/

View file

@ -0,0 +1,50 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
#ifndef __RAMDISK_H__
#define __RAMDISK_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "ff_headers.h"
/* Create a RAM disk, supplying enough memory to hold N sectors of 512 bytes each */
FF_Disk_t *FF_RAMDiskInit( char *pcName, uint8_t *pucDataBuffer, uint32_t ulSectorCount, size_t xIOManagerCacheSize );
/* Release all resources */
BaseType_t FF_RAMDiskDelete( FF_Disk_t *pxDisk );
/* Show some partition information */
BaseType_t FF_RAMDiskShowPartition( FF_Disk_t *pxDisk );
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* __RAMDISK_H__ */

View file

@ -0,0 +1,76 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
#ifndef __SDDISK_H__
#define __SDDISK_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "ff_headers.h"
/* Return non-zero if the SD-card is present.
The parameter 'pxDisk' may be null, unless device locking is necessary. */
BaseType_t FF_SDDiskDetect( FF_Disk_t *pxDisk );
/* Create a RAM disk, supplying enough memory to hold N sectors of 512 bytes each */
FF_Disk_t *FF_SDDiskInit( const char *pcName );
BaseType_t FF_SDDiskReinit( FF_Disk_t *pxDisk );
/* Unmount the volume */
BaseType_t FF_SDDiskUnmount( FF_Disk_t *pDisk );
/* Mount the volume */
BaseType_t FF_SDDiskMount( FF_Disk_t *pDisk );
/* Release all resources */
BaseType_t FF_SDDiskDelete( FF_Disk_t *pDisk );
/* Show some partition information */
BaseType_t FF_SDDiskShowPartition( FF_Disk_t *pDisk );
/* Flush changes from the driver's buf to disk */
void FF_SDDiskFlush( FF_Disk_t *pDisk );
/* Format a given partition on an SD-card. */
BaseType_t FF_SDDiskFormat( FF_Disk_t *pxDisk, BaseType_t aPart );
/* Return non-zero if an SD-card is detected in a given slot. */
BaseType_t FF_SDDiskInserted( BaseType_t xDriveNr );
/* _RB_ Temporary function - ideally the application would not need the IO
manageer structure, just a handle to a disk. */
FF_IOManager_t *sddisk_ioman( FF_Disk_t *pxDisk );
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* __SDDISK_H__ */

View file

@ -0,0 +1,532 @@
/*
* FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Authors include James Walmsley, Hein Tibosch and Richard Barry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
*
*/
/* Standard includes. */
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
/* LPC18xx includes. */
#include "chip.h"
#include "board.h"
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "portmacro.h"
/* FreeRTOS+FAT includes. */
#include "ff_sddisk.h"
#include "ff_sys.h"
#include "hr_gettime.h"
/* Misc definitions. */
#define sdSIGNATURE 0x41404342UL
#define sdHUNDRED_64_BIT ( 100ull )
#define sdBYTES_PER_MB ( 1024ull * 1024ull )
#define sdSECTORS_PER_MB ( sdBYTES_PER_MB / 512ull )
#define sdIOMAN_MEM_SIZE 4096
#define xSDCardInfo ( sd_mmc_cards[ 0 ] )
#define sdAligned( pvAddress ) ( ( ( ( size_t ) ( pvAddress ) ) & ( sizeof( size_t ) - 1 ) ) == 0 )
/*-----------------------------------------------------------*/
/*_RB_ Functions require comment blocks. */
static void prvSDMMCSetupWakeup( void *pvInfo );
static uint32_t prvSDMMCWait( void );
static void prvSDMMCDelay_ms( uint32_t time );
static void prvInitialiseCardInfo( void );
static int32_t prvSDMMC_Init( void );
static int32_t prvFFRead( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk );
static int32_t prvFFWrite( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk );
/*-----------------------------------------------------------*/
/*_RB_ Variables require a comment block where appropriate. */
static int32_t lSDDetected = 0;
static mci_card_struct xCardInfo;
static volatile int32_t lSDIOWaitExit;
static BaseType_t xSDCardStatus;
static SemaphoreHandle_t xSDCardSemaphore;
static SemaphoreHandle_t xPlusFATMutex;
/*-----------------------------------------------------------*/
#warning Update to make read and write functions static and make use of the FF_Disk_t type.
static int32_t prvFFRead( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk )
{
int32_t iReturn;
/*_RB_ Many of the comments in this file apply to other functions in the file. */
if( ( pxDisk != NULL ) &&
( xSDCardStatus == pdPASS ) &&
( pxDisk->ulSignature == sdSIGNATURE ) &&
( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&
( ulSectorNumber < pxDisk->ulNumberOfSectors ) &&
( ( pxDisk->ulNumberOfSectors - ulSectorNumber ) >= ulSectorCount ) )
{
iReturn = Chip_SDMMC_ReadBlocks( LPC_SDMMC, pucBuffer, ulSectorNumber, ulSectorCount );
/*_RB_ I'm guessing 512 is a sector size, but that needs to be clear.
Is it defined in a header somewhere? If so we can do a search and
replace in files on it as it seems to be used everywhere. */
if( iReturn == ( ulSectorCount * 512 ) ) /*_RB_ Signed/unsigned mismatch (twice!) */
{
iReturn = FF_ERR_NONE;
}
else
{
/*_RB_ Signed number used to return bitmap (again below). */
iReturn = ( FF_ERR_IOMAN_OUT_OF_BOUNDS_READ | FF_ERRFLAG );
}
}
else
{
memset( ( void * ) pucBuffer, '\0', ulSectorCount * 512 );
if( pxDisk->xStatus.bIsInitialised != 0 )
{
FF_PRINTF( "prvFFRead: warning: %lu + %lu > %lu\n", ulSectorNumber, ulSectorCount, pxDisk->ulNumberOfSectors );
}
iReturn = ( FF_ERR_IOMAN_OUT_OF_BOUNDS_READ | FF_ERRFLAG );
}
return iReturn;
}
/*-----------------------------------------------------------*/
static int32_t prvFFWrite( uint8_t *pucBuffer, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk )
{
int32_t iReturn;
if( ( pxDisk != NULL ) &&
( xSDCardStatus == pdPASS ) &&
( pxDisk->ulSignature == sdSIGNATURE ) &&
( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&
( ulSectorNumber < pxDisk->ulNumberOfSectors ) &&
( ( pxDisk->ulNumberOfSectors - ulSectorNumber ) >= ulSectorCount ) )
{
iReturn = Chip_SDMMC_WriteBlocks( LPC_SDMMC, pucBuffer, ulSectorNumber, ulSectorCount );
if( iReturn == ( ulSectorCount * 512 ) ) /*_RB_ Signed/unsigned mismatch (twice!) */
{
iReturn = 0;
}
else
{
iReturn = ( FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE | FF_ERRFLAG );
}
}
else
{
memset( ( void * ) pucBuffer, '\0', ulSectorCount * 512 );
if( pxDisk->xStatus.bIsInitialised )
{
FF_PRINTF( "prvFFWrite: warning: %lu + %lu > %lu\n", ulSectorNumber, ulSectorCount, pxDisk->ulNumberOfSectors );
}
iReturn = ( FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE | FF_ERRFLAG );
}
return iReturn;
}
/*-----------------------------------------------------------*/
void FF_SDDiskFlush( FF_Disk_t *pxDisk )
{
if( ( pxDisk != NULL ) &&
( pxDisk->xStatus.bIsInitialised != pdFALSE ) &&
( pxDisk->pxIOManager != NULL ) )
{
FF_FlushCache( pxDisk->pxIOManager );
}
}
/*-----------------------------------------------------------*/
/* Initialise the SDIO driver and mount an SD card */
FF_Disk_t *FF_SDDiskInit( const char *pcName )
{
FF_Error_t xFFError;
BaseType_t xPartitionNumber = 0;
FF_CreationParameters_t xParameters;
FF_Disk_t * pxDisk;
xSDCardStatus = prvSDMMC_Init();
if( xSDCardStatus == pdPASS )
{
pxDisk = ( FF_Disk_t * ) pvPortMalloc( sizeof( *pxDisk ) );
if( pxDisk != NULL )
{
/* Initialise the created disk structure. */
memset( pxDisk, '\0', sizeof( *pxDisk ) );
if( xPlusFATMutex == NULL)
{
xPlusFATMutex = xSemaphoreCreateRecursiveMutex();
}
pxDisk->ulNumberOfSectors = xCardInfo.card_info.blocknr;
pxDisk->ulSignature = sdSIGNATURE;
if( xPlusFATMutex != NULL)
{
memset( &xParameters, '\0', sizeof( xParameters ) );
xParameters.ulMemorySize = sdIOMAN_MEM_SIZE;
xParameters.ulSectorSize = 512;
xParameters.fnWriteBlocks = prvFFWrite;
xParameters.fnReadBlocks = prvFFRead;
xParameters.pxDisk = pxDisk;
/* prvFFRead()/prvFFWrite() are not re-entrant and must be
protected with the use of a semaphore. */
xParameters.xBlockDeviceIsReentrant = pdFALSE;
/* The semaphore will be used to protect critical sections in
the +FAT driver, and also to avoid concurrent calls to
prvFFRead()/prvFFWrite() from different tasks. */
xParameters.pvSemaphore = ( void * ) xPlusFATMutex;
pxDisk->pxIOManager = FF_CreateIOManger( &xParameters, &xFFError );
if( pxDisk->pxIOManager == NULL )
{
FF_PRINTF( "FF_SDDiskInit: FF_CreateIOManger: %s\n", ( const char * ) FF_GetErrMessage( xFFError ) );
FF_SDDiskDelete( pxDisk );
pxDisk = NULL;
}
else
{
pxDisk->xStatus.bIsInitialised = pdTRUE;
pxDisk->xStatus.bPartitionNumber = xPartitionNumber;
if( FF_SDDiskMount( pxDisk ) == 0 )
{
FF_SDDiskDelete( pxDisk );
pxDisk = NULL;
}
else
{
if( pcName == NULL )
{
pcName = "/";
}
FF_FS_Add( pcName, pxDisk );
FF_PRINTF( "FF_SDDiskInit: Mounted SD-card as root \"%s\"\n", pcName );
FF_SDDiskShowPartition( pxDisk );
}
} /* if( pxDisk->pxIOManager != NULL ) */
} /* if( xPlusFATMutex != NULL) */
} /* if( pxDisk != NULL ) */
else
{
FF_PRINTF( "FF_SDDiskInit: Malloc failed\n" );
}
} /* if( xSDCardStatus == pdPASS ) */
else
{
FF_PRINTF( "FF_SDDiskInit: prvSDMMC_Init failed\n" );
pxDisk = NULL;
}
return pxDisk;
}
/*-----------------------------------------------------------*/
BaseType_t FF_SDDiskFormat( FF_Disk_t *pxDisk, BaseType_t xPartitionNumber )
{
FF_Error_t xError;
BaseType_t xReturn = pdFAIL;
xError = FF_Unmount( pxDisk );
if( FF_isERR( xError ) != pdFALSE )
{
FF_PRINTF( "FF_SDDiskFormat: unmount fails: %08x\n", ( unsigned ) xError );
}
else
{
/* Format the drive - try FAT32 with large clusters. */
xError = FF_Format( pxDisk, xPartitionNumber, pdFALSE, pdFALSE);
if( FF_isERR( xError ) )
{
FF_PRINTF( "FF_SDDiskFormat: %s\n", (const char*)FF_GetErrMessage( xError ) );
}
else
{
FF_PRINTF( "FF_SDDiskFormat: OK, now remounting\n" );
pxDisk->xStatus.bPartitionNumber = xPartitionNumber;
xError = FF_SDDiskMount( pxDisk );
FF_PRINTF( "FF_SDDiskFormat: rc %08x\n", ( unsigned )xError );
if( FF_isERR( xError ) == pdFALSE )
{
xReturn = pdPASS;
}
}
}
return xReturn;
}
/*-----------------------------------------------------------*/
/* Get a pointer to IOMAN, which can be used for all FreeRTOS+FAT functions */
BaseType_t FF_SDDiskMount( FF_Disk_t *pxDisk )
{
FF_Error_t xFFError;
BaseType_t xReturn;
/* Mount the partition */
xFFError = FF_Mount( pxDisk, pxDisk->xStatus.bPartitionNumber );
if( FF_isERR( xFFError ) )
{
FF_PRINTF( "FF_SDDiskMount: %08lX\n", xFFError );
xReturn = pdFAIL;
}
else
{
pxDisk->xStatus.bIsMounted = pdTRUE;
FF_PRINTF( "****** FreeRTOS+FAT initialized %lu sectors\n", pxDisk->pxIOManager->xPartition.ulTotalSectors );
FF_SDDiskShowPartition( pxDisk );
xReturn = pdPASS;
}
return xReturn;
}
/*-----------------------------------------------------------*/
FF_IOManager_t *sddisk_ioman( FF_Disk_t *pxDisk )
{
FF_IOManager_t *pxReturn;
if( ( pxDisk != NULL ) && ( pxDisk->xStatus.bIsInitialised != pdFALSE ) )
{
pxReturn = pxDisk->pxIOManager;
}
else
{
pxReturn = NULL;
}
return pxReturn;
}
/*-----------------------------------------------------------*/
/* Release all resources */
BaseType_t FF_SDDiskDelete( FF_Disk_t *pxDisk )
{
if( pxDisk != NULL )
{
pxDisk->ulSignature = 0;
pxDisk->xStatus.bIsInitialised = 0;
if( pxDisk->pxIOManager != NULL )
{
if( FF_Mounted( pxDisk->pxIOManager ) != pdFALSE )
{
FF_Unmount( pxDisk );
}
FF_DeleteIOManager( pxDisk->pxIOManager );
}
vPortFree( pxDisk );
}
return 1;
}
/*-----------------------------------------------------------*/
BaseType_t FF_SDDiskShowPartition( FF_Disk_t *pxDisk )
{
FF_Error_t xError;
uint64_t ullFreeSectors;
uint32_t ulTotalSizeMB, ulFreeSizeMB;
int iPercentageFree;
FF_IOManager_t *pxIOManager;
const char *pcTypeName = "unknown type";
BaseType_t xReturn = pdPASS;
if( pxDisk == NULL )
{
xReturn = pdFAIL;
}
else
{
pxIOManager = pxDisk->pxIOManager;
FF_PRINTF( "Reading FAT and calculating Free Space\n" );
switch( pxIOManager->xPartition.ucType )
{
case FF_T_FAT12:
pcTypeName = "FAT12";
break;
case FF_T_FAT16:
pcTypeName = "FAT16";
break;
case FF_T_FAT32:
pcTypeName = "FAT32";
break;
default:
pcTypeName = "UNKOWN";
break;
}
FF_GetFreeSize( pxIOManager, &xError );
ullFreeSectors = pxIOManager->xPartition.ulFreeClusterCount * pxIOManager->xPartition.ulSectorsPerCluster;
iPercentageFree = ( int ) ( ( sdHUNDRED_64_BIT * ullFreeSectors + pxIOManager->xPartition.ulDataSectors / 2 ) /
( ( uint64_t )pxIOManager->xPartition.ulDataSectors ) );
ulTotalSizeMB = pxIOManager->xPartition.ulDataSectors / sdSECTORS_PER_MB;
ulFreeSizeMB = ( uint32_t ) ( ullFreeSectors / sdSECTORS_PER_MB );
/* It is better not to use the 64-bit format such as %Lu because it
might not be implemented. */
FF_PRINTF( "Partition Nr %8u\n", pxDisk->xStatus.bPartitionNumber );
FF_PRINTF( "Type %8u (%s)\n", pxIOManager->xPartition.ucType, pcTypeName );
FF_PRINTF( "VolLabel '%8s' \n", pxIOManager->xPartition.pcVolumeLabel );
FF_PRINTF( "TotalSectors %8lu\n", pxIOManager->xPartition.ulTotalSectors );
FF_PRINTF( "SecsPerCluster %8lu\n", pxIOManager->xPartition.ulSectorsPerCluster );
FF_PRINTF( "Size %8lu MB\n", ulTotalSizeMB );
FF_PRINTF( "FreeSize %8lu MB ( %d perc free )\n", ulFreeSizeMB, iPercentageFree );
}
return xReturn;
}
/*-----------------------------------------------------------*/
void SDIO_IRQHandler( void )
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
/* All SD based register handling is done in the callback function. The SDIO
interrupt is not enabled as part of this driver and needs to be
enabled/disabled in the callbacks or application as needed. This is to allow
flexibility with IRQ handling for applications and RTOSes. */
/* Set wait exit flag to tell wait function we are ready. In an RTOS, this
would trigger wakeup of a thread waiting for the IRQ. */
NVIC_DisableIRQ( SDIO_IRQn );
xSemaphoreGiveFromISR( xSDCardSemaphore, &xHigherPriorityTaskWoken );
lSDIOWaitExit = 1;
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
/*-----------------------------------------------------------*/
/* Sets up the SD event driven wakeup */
static void prvSDMMCSetupWakeup( void *pvInfo )
{
uint32_t *ulWaitStatus = ( uint32_t * ) pvInfo;
/* Wait for IRQ - for an RTOS, you would pend on an event here with a IRQ
based wakeup. */
/*_RB_ Don't understand why this is spinning on a block time of 0. Is it
really meant to be != pdFALSE? */
while( xSemaphoreTake( xSDCardSemaphore, 0 ) != pdFALSE )
{
}
NVIC_ClearPendingIRQ( SDIO_IRQn );
lSDIOWaitExit = 0;
Chip_SDIF_SetIntMask( LPC_SDMMC, *ulWaitStatus );
NVIC_EnableIRQ( SDIO_IRQn );
}
/*-----------------------------------------------------------*/
static uint32_t prvSDMMCWait( void )
{
uint32_t ulStatus;
/*_RB_ 2000 needs to be defined and use pdMS_TO_TICKS so the delay period
remains constant no matter how the end user sets configTICK_RATE_MS. */
xSemaphoreTake( xSDCardSemaphore, 2000 );
ulStatus = Chip_SDIF_GetIntStatus( LPC_SDMMC );
if( ( ( ulStatus & MCI_INT_CMD_DONE ) == 0 ) || ( lSDIOWaitExit == 0 ) )
{
FF_PRINTF( "Wait SD: int32_t %ld ulStatus 0x%02lX\n", lSDIOWaitExit, ulStatus );
}
return ulStatus;
}
/*-----------------------------------------------------------*/
static void prvSDMMCDelay_ms( uint32_t ulTime )
{
/* In an RTOS, the thread would sleep allowing other threads to run.
For standalone operation, just spin on a timer */
vTaskDelay( pdMS_TO_TICKS( ulTime ) );
}
/*-----------------------------------------------------------*/
static int32_t prvSDMMC_Init( void )
{
int32_t lSDCardStatus;
if( xSDCardSemaphore == NULL )
{
xSDCardSemaphore = xSemaphoreCreateBinary();
configASSERT( xSDCardSemaphore );
xSemaphoreGive( xSDCardSemaphore );
}
prvInitialiseCardInfo();
NVIC_SetPriority( SDIO_IRQn, configSD_INTERRUPT_PRIORITY );
/*_RB_ Board_SDMMC_Init() is library specific code that is also specific to
the target development board.The SDMMC peripheral should be initialised from
the application code before this code is called. */
Board_SDMMC_Init();
Chip_SDIF_Init( LPC_SDMMC );
lSDDetected = !Chip_SDIF_CardNDetect( LPC_SDMMC );
Chip_SDIF_PowerOn( LPC_SDMMC );
lSDCardStatus = Chip_SDMMC_Acquire( LPC_SDMMC, &xCardInfo );
FF_PRINTF( "Acquire: %ld\n", lSDCardStatus );
return lSDCardStatus;
}
/*-----------------------------------------------------------*/
static void prvInitialiseCardInfo( void )
{
memset( &xCardInfo, 0, sizeof( xCardInfo ) );
xCardInfo.card_info.evsetup_cb = prvSDMMCSetupWakeup;
xCardInfo.card_info.waitfunc_cb = prvSDMMCWait;
xCardInfo.card_info.msdelay_func = prvSDMMCDelay_ms;
}