Compare commits

...

36 commits

Author SHA1 Message Date
hathach
850e1aaee1
fix warnings
warning: taking address of packed member of 'directoryEntry' may result
in an unaligned pointer value [-Waddress-of-packed-member]
2021-05-26 09:49:02 +07:00
hathach
b2a36980bb
Update library.properties 2019-09-09 21:59:36 +07:00
hathach
fa76619c03
Merge pull request #6 from hathach/master
clean up warnings
2019-09-09 21:58:35 +07:00
hathach
56d6610432 clean up warnings 2019-09-09 21:57:32 +07:00
Limor "Ladyada" Fried
cf8f5d8f61
Merge pull request #5 from hathach/master
fix writing to 2nd FAT with 1-fat filesystem
2019-09-05 02:02:20 -04:00
hathach
28fd5dc4fc fix writing to 2nd FAT with 1-fat filesystem 2019-09-05 11:56:55 +07:00
Ladyada
641f23b353 more esp32 skips and fix one compiletime 2019-07-27 18:23:42 -04:00
ladyada
5d726947af skip somre moe tests 2019-07-27 17:37:33 -04:00
ladyada
94aad3094c fix name 2019-07-27 16:48:22 -04:00
Limor "Ladyada" Fried
f1f0f93432
Update library.properties 2019-07-23 00:38:17 -04:00
Limor "Ladyada" Fried
d0a2565114
Update library.properties 2019-07-23 00:37:52 -04:00
ladyada
e157117f9c skip some more tests 2019-07-16 19:06:07 -04:00
ladyada
6324f8eed2 fix skipname 2019-07-16 18:42:13 -04:00
ladyada
fca3f1475f some skips, dont test extras 2019-07-16 18:40:43 -04:00
ladyada
1b0c9bce15 path 2019-07-16 18:30:49 -04:00
ladyada
0b0f1296d3 fix git clone 2019-07-16 18:10:35 -04:00
ladyada
81d38972f6 try installing i2cdev 2019-07-16 17:51:22 -04:00
ladyada
cb28106207 rm dir 2019-07-16 16:27:59 -04:00
ladyada
5de302b19a skip attic 2019-07-16 16:05:23 -04:00
ladyada
699c9e410e travis 2019-07-16 15:47:05 -04:00
Limor "Ladyada" Fried
18f071dc69
Merge pull request #3 from hathach/master
add m_fatCount to support either 1 or 2 FAT
2019-07-16 15:14:21 -04:00
Limor "Ladyada" Fried
31783e24e8
Merge branch 'master' into master 2019-07-16 15:13:50 -04:00
ladyada
013b7ea281 dont break things :( 2019-07-16 13:20:18 -04:00
hathach
829f4925f4 add m_fatCount to support either 1 or 2 FAT 2019-07-16 12:40:21 +07:00
ladyada
88902b576e support 1 or 2 FATs! 2019-07-16 00:14:01 -04:00
ladyada
f918ed0077 allow 1 or 2 FATs 2019-07-15 23:51:48 -04:00
ladyada
10cdd7964c dont use DMA by default (Audio doesnt like it) 2019-07-07 19:11:14 -04:00
Limor "Ladyada" Fried
ec247da5da
Merge pull request #2 from hathach/master
enable ENABLE_EXTENDED_TRANSFER_CLASS and FAT12_SUPPORT
2019-06-17 14:18:53 -04:00
hathach
f24364bff2 enable ENABLE_EXTENDED_TRANSFER_CLASS and FAT12_SUPPORT to support smal size block device such as external flash 2019-06-18 01:09:35 +07:00
Limor "Ladyada" Fried
9c046af871
Merge pull request #1 from adafruit/pb-samd-dma
Add DMA to SAMD21 and SAMD51
2019-05-14 00:52:28 -04:00
ladyada
2b053a1910 spacey boi 2019-05-14 00:51:58 -04:00
ladyada
7a8686d63d get back to original sdfat state in case we do a PR 2019-05-14 00:51:33 -04:00
ladyada
4d87dfbee3 Merge branch 'pb-samd-dma' of github.com:adafruit/SdFat into pb-samd-dma 2019-05-14 00:49:29 -04:00
ladyada
391949068e sending w/DMA isnt working yet (?) but reading does so lets just enable that 2019-05-14 00:48:39 -04:00
Phillip Burgess
98a88f0389 Remove debug println 2019-05-10 22:42:42 -07:00
Phillip Burgess
e0acc32b59 SAMD DMA support (requires Adafruit_ZeroDMA lib) 2019-05-10 21:43:10 -07:00
32 changed files with 253 additions and 19 deletions

31
.travis.yml Normal file
View file

@ -0,0 +1,31 @@
language: c
sudo: false
cache:
directories:
- ~/arduino_ide
- ~/.arduino15/packages/
git:
depth: false
quiet: true
env:
global:
- PRETTYNAME="SdFat (Adafruit Fork)"
before_install:
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/install.sh)
install:
- git clone --quiet http://github.com/jrowberg/i2cdevlib.git $HOME/i2cdevlib
- mv $HOME/i2cdevlib/Arduino/* $HOME/Arduino/libraries/
- rm -rf $HOME/arduino_ide/libraries/Adafruit_Test_Library/examples/*attic
- rm -rf $HOME/arduino_ide/libraries/Adafruit_Test_Library/extras
script:
- build_main_platforms
after_success:
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/library_check.sh)
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/doxy_gen_and_deploy.sh)

View file

View file

View file

View file

@ -114,7 +114,7 @@ void loop() {
break;
case 3:
file.printField(12345678UL + i, '\n');
file.printField((uint32_t) (12345678UL + i), '\n');
break;
case 4:

View file

View file

View file

View file

View file

View file

View file

View file

View file

View file

View file

View file

@ -1,11 +1,11 @@
name=SdFat
version=1.1.0
name=SdFat - Adafruit Fork
version=1.2.3
license=MIT
author=Bill Greiman <fat16lib@sbcglobal.net>
maintainer=Bill Greiman <fat16lib@sbcglobal.net>
sentence=FAT16/FAT32 file system for SD cards.
paragraph=FAT16/FAT32 file system for SD cards.
maintainer=Adafruit <support@adafruit.com>
sentence=FAT16/FAT32 file system for SD cards and QSPI Flash.
paragraph=FAT16/FAT32 file system for SD cards and QSPI Flash.
category=Data Storage
url=https://github.com/greiman/SdFat
repository=https://github.com/greiman/SdFat.git
url=https://github.com/adafruit/SdFat
repository=https://github.com/adafruit/SdFat.git
architectures=*

View file

@ -664,7 +664,7 @@ bool FatFile::openParent(FatFile* dirFile) {
goto fail;
}
} else {
memset(&dotdot, 0, sizeof(FatFile));
memset((void*) &dotdot, 0, sizeof(FatFile));
dotdot.m_attr = FILE_ATTR_SUBDIR;
dotdot.m_flags = F_READ;
dotdot.m_vol = dirFile->m_vol;
@ -1215,7 +1215,14 @@ bool FatFile::sync() {
// set modify time if user supplied a callback date/time function
if (m_dateTime) {
m_dateTime(&dir->lastWriteDate, &dir->lastWriteTime);
// use temp date/time to fix warning -Waddress-of-packed-member
uint16_t tmp_date = dir->lastWriteDate;
uint16_t tmp_time = dir->lastWriteTime;
m_dateTime(&tmp_date, &tmp_time);
dir->lastWriteDate = tmp_date;
dir->lastWriteTime = tmp_time;
dir->lastAccessDate = dir->lastWriteDate;
}
// clear directory dirty

View file

@ -474,8 +474,15 @@ create:
// set timestamps
if (m_dateTime) {
// use temp date/time to fix warning -Waddress-of-packed-member
uint16_t tmp_date = dir->creationDate;
uint16_t tmp_time = dir->creationTime;
// call user date/time function
m_dateTime(&dir->creationDate, &dir->creationTime);
m_dateTime(&tmp_date, &tmp_time);
dir->creationDate = tmp_date;
dir->creationTime = tmp_time;
} else {
// use default date/time
dir->creationDate = FAT_DEFAULT_DATE;

View file

@ -55,7 +55,7 @@ bool FatCache::sync() {
goto fail;
}
// mirror second FAT
if (m_status & CACHE_STATUS_MIRROR_FAT) {
if ( (m_vol->m_fatCount == 2) && (m_status & CACHE_STATUS_MIRROR_FAT) ) {
uint32_t lbn = m_lbn + m_vol->blocksPerFat();
if (!m_vol->writeBlock(lbn, m_block.data)) {
DBG_FAIL_MACRO;
@ -487,12 +487,14 @@ bool FatVolume::init(uint8_t part) {
}
fbs = &(pc->fbs32);
if (fbs->bytesPerSector != 512 ||
fbs->fatCount != 2 ||
fbs->fatCount < 1 ||
fbs->fatCount > 2 ||
fbs->reservedSectorCount == 0) {
// not valid FAT volume
DBG_FAIL_MACRO;
goto fail;
}
m_fatCount = fbs->fatCount;
m_blocksPerCluster = fbs->sectorsPerCluster;
m_clusterBlockMask = m_blocksPerCluster - 1;
// determine shift that is same as multiply by m_blocksPerCluster
@ -512,7 +514,7 @@ bool FatVolume::init(uint8_t part) {
m_rootDirEntryCount = fbs->rootDirEntryCount;
// directory start for FAT16 dataStart for FAT32
m_rootDirStart = m_fatStartBlock + 2 * m_blocksPerFat;
m_rootDirStart = m_fatStartBlock + m_fatCount * m_blocksPerFat;
// data start for FAT16 and FAT32
m_dataStartBlock = m_rootDirStart + ((32 * fbs->rootDirEntryCount + 511)/512);
@ -576,7 +578,7 @@ bool FatVolume::wipe(print_t* pr) {
}
}
// Clear FATs.
count = 2*m_blocksPerFat;
count = m_fatCount * m_blocksPerFat;
lbn = m_fatStartBlock;
for (uint32_t nb = 0; nb < count; nb++) {
if (pr && (nb & 0XFF) == 0) {
@ -601,7 +603,7 @@ bool FatVolume::wipe(print_t* pr) {
goto fail;
}
if (!writeBlock(m_fatStartBlock, cache->data) ||
!writeBlock(m_fatStartBlock + m_blocksPerFat, cache->data)) {
(m_fatCount == 2 && !writeBlock(m_fatStartBlock + m_blocksPerFat, cache->data))) {
DBG_FAIL_MACRO;
goto fail;
}

View file

@ -292,6 +292,7 @@ class FatVolume {
uint8_t m_clusterBlockMask; // Mask to extract block of cluster.
uint8_t m_clusterSizeShift; // Cluster count to block count shift.
uint8_t m_fatType; // Volume type (12, 16, OR 32).
uint8_t m_fatCount; // Number of FAT (1 or 2)
uint16_t m_rootDirEntryCount; // Number of entries in FAT16 root dir.
uint32_t m_allocSearchStart; // Start cluster for alloc search.
uint32_t m_blocksPerFat; // FAT size in blocks

View file

@ -68,7 +68,7 @@
* These classes used extended multi-block SD I/O for better performance.
* the SPI bus may not be shared with other devices in this mode.
*/
#define ENABLE_EXTENDED_TRANSFER_CLASS 0
#define ENABLE_EXTENDED_TRANSFER_CLASS 1
//------------------------------------------------------------------------------
/**
* If the symbol USE_STANDARD_SPI_LIBRARY is zero, an optimized custom SPI
@ -148,7 +148,7 @@
* Set FAT12_SUPPORT nonzero to enable use if FAT12 volumes.
* FAT12 has not been well tested and requires additional flash.
*/
#define FAT12_SUPPORT 0
#define FAT12_SUPPORT 1
//------------------------------------------------------------------------------
/**
* Set DESTRUCTOR_CLOSES_FILE nonzero to close a file in its destructor.
@ -209,7 +209,7 @@
/**
* Determine the default SPI configuration.
*/
#if defined(__STM32F1__) || defined(__STM32F4__) || defined(PLATFORM_ID)
#if defined(__STM32F1__) || defined(__STM32F4__) || defined(PLATFORM_ID) || defined(ARDUINO_ARCH_SAMD)
// has multiple SPI ports
#define SD_HAS_CUSTOM_SPI 2
#elif defined(__AVR__)\

186
src/SpiDriver/SdSpiSAMD.cpp Normal file
View file

@ -0,0 +1,186 @@
/**
* Copyright (c) 2011-2018 Bill Greiman
* This file is part of the SdFat library for SD memory cards.
*
* MIT License
*
* 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.
*/
#if defined(ARDUINO_ARCH_SAMD)
#include "SdSpiDriver.h"
/** Use Adafruit_ZeroDMA library if nonzero */
#define USE_SAMD_DMA_RECV 0
#define USE_SAMD_DMA_SEND 0
#if USE_SAMD_DMA_RECV || USE_SAMD_DMA_SEND
#include <Adafruit_ZeroDMA.h>
#include "utility/dma.h"
// Three DMA channels are used. SPI DMA read requires two channels,
// one for the "dummy writes" to initiate SPI transfers, the other
// to read each incoming byte. Write requires only one channel, and
// there's probably ways to "recycle" the first of the read channels,
// but that'll take some work and is not done here, have plenty of
// channels to go around. Each channel uses one descriptor.
#define CHANNEL_READ_TX 0
#define CHANNEL_READ_RX 1
#define CHANNEL_WRITE 2
static Adafruit_ZeroDMA DMAchannel[3];
static DmacDescriptor *channelDescriptor[3];
static volatile bool dma_busy = false;
static uint8_t dum = 0xFF; // Nonsense for SPI transfer init
//------------------------------------------------------------------------------
/** Transfer-complete callback for Adafruit_ZeroDMA library.
*
*/
static void dma_callback(Adafruit_ZeroDMA *dma) {
dma_busy = false;
}
#endif // end USE_SAMD_DMA
//------------------------------------------------------------------------------
/** Set SPI options for access to SD/SDHC cards.
*
* \param[in] divisor SCK clock divider relative to the APB1 or APB2 clock.
*/
void SdSpiAltDriver::activate() {
m_spi->beginTransaction(m_spiSettings);
}
//------------------------------------------------------------------------------
/** Initialize the SPI bus.
*
* \param[in] chipSelectPin SD card chip select pin.
*/
void SdSpiAltDriver::begin(uint8_t csPin) {
m_csPin = csPin;
pinMode(m_csPin, OUTPUT);
digitalWrite(m_csPin, HIGH);
m_spi->begin();
#if USE_SAMD_DMA_RECV || USE_SAMD_DMA_SEND
// First channel and descriptor are for SPI read "dummy writes" (TX)
DMAchannel[CHANNEL_READ_TX].allocate(); // Allocate DMA channel
channelDescriptor[CHANNEL_READ_TX] =
DMAchannel[CHANNEL_READ_TX].addDescriptor(
(void *)&dum, // Source address (nonsense)
(void *)m_spi->getDataRegister(), // Dest
0, // Count (0 for now, set later)
DMA_BEAT_SIZE_BYTE, // Bytes/hwords/words
false, // Don't increment source address
false); // Don't increment dest address
DMAchannel[CHANNEL_READ_TX].setTrigger(m_spi->getDMAC_ID_TX());
DMAchannel[CHANNEL_READ_TX].setAction(DMA_TRIGGER_ACTON_BEAT);
DMAchannel[CHANNEL_READ_TX].setCallback(dma_callback);
// Second channel and descriptor are for actual SPI read (RX)
DMAchannel[CHANNEL_READ_RX].allocate(); // Allocate DMA channel
channelDescriptor[CHANNEL_READ_RX] =
DMAchannel[CHANNEL_READ_RX].addDescriptor(
(void *)m_spi->getDataRegister(), // Source address
NULL, // Dest address (NULL for now, set later)
0, // Count (0 for now, set later)
DMA_BEAT_SIZE_BYTE, // Bytes/hwords/words
false, // Don't increment source address
true); // Increment dest address
DMAchannel[CHANNEL_READ_RX].setTrigger(m_spi->getDMAC_ID_RX());
DMAchannel[CHANNEL_READ_RX].setAction(DMA_TRIGGER_ACTON_BEAT);
DMAchannel[CHANNEL_READ_RX].setCallback(dma_callback);
// SPI write is its own channel and descriptor
DMAchannel[CHANNEL_WRITE].allocate(); // Allocate DMA channel
channelDescriptor[CHANNEL_WRITE] =
DMAchannel[CHANNEL_WRITE].addDescriptor(
NULL, // Src address (NULL for now, set later)
(void *)m_spi->getDataRegister(), // Dest address
0, // Count (0 for now, set later)
DMA_BEAT_SIZE_BYTE, // Bytes/hwords/words
true, // Increment source address
false); // Don't increment dest address
DMAchannel[CHANNEL_WRITE].setTrigger(m_spi->getDMAC_ID_TX());
DMAchannel[CHANNEL_WRITE].setAction(DMA_TRIGGER_ACTON_BEAT);
DMAchannel[CHANNEL_WRITE].setCallback(dma_callback);
#endif // USE_SAMD_DMA
}
//------------------------------------------------------------------------------
/**
* End SPI transaction.
*/
void SdSpiAltDriver::deactivate() {
m_spi->endTransaction();
}
//------------------------------------------------------------------------------
/** Receive a byte.
*
* \return The byte.
*/
uint8_t SdSpiAltDriver::receive() {
return m_spi->transfer(0XFF);
}
//------------------------------------------------------------------------------
/** Receive multiple bytes.
*
* \param[out] buf Buffer to receive the data.
* \param[in] n Number of bytes to receive.
*
* \return Zero for no error or nonzero error code.
*/
uint8_t SdSpiAltDriver::receive(uint8_t* buf, size_t n) {
#if USE_SAMD_DMA_RECV
// Configure the SPI read "dummy write" (TX) length (n)
DMAchannel[CHANNEL_READ_TX].changeDescriptor(
channelDescriptor[CHANNEL_READ_TX], NULL, NULL, n);
// Configure the SPI read (RX) length (n) into buf
DMAchannel[CHANNEL_READ_RX].changeDescriptor(
channelDescriptor[CHANNEL_READ_RX], NULL, (void *)buf, n);
dma_busy = true;
DMAchannel[CHANNEL_READ_RX].startJob(); // Start the RX job BEFORE the
DMAchannel[CHANNEL_READ_TX].startJob(); // TX job! That's the secret sauce.
while(dma_busy);
#else // USE_SAMD_DMA_RECV
while(n--) *buf++ = m_spi->transfer(0xFF);
#endif // USE_SAMD_DMA_RECV
return 0;
}
//------------------------------------------------------------------------------
/** Send a byte.
*
* \param[in] b Byte to send
*/
void SdSpiAltDriver::send(uint8_t b) {
m_spi->transfer(b);
}
//------------------------------------------------------------------------------
/** Send multiple bytes.
*
* \param[in] buf Buffer for data to be sent.
* \param[in] n Number of bytes to send.
*/
void SdSpiAltDriver::send(const uint8_t* buf , size_t n) {
#if USE_SAMD_DMA_SEND
DMAchannel[CHANNEL_WRITE].changeDescriptor(
channelDescriptor[CHANNEL_WRITE], (void *)buf, NULL, n);
dma_busy = true;
DMAchannel[CHANNEL_WRITE].startJob();
while(dma_busy);
#else // USE_SAMD_DMA_SEND
while(n--) m_spi->transfer(*buf++);
#endif // USE_SAMD_DMA_SEND
}
#endif // defined(ARDUINO_ARCH_SAMD)