Compare commits

...

59 commits

Author SHA1 Message Date
Limor "Ladyada" Fried
8313193820
Update library.properties
bump
2022-01-14 11:05:11 -05:00
Ha Thach
e72d81e8aa
Merge pull request #12 from adafruit/work-with-rp2040
Work with rp2040
2022-01-14 18:48:02 +07:00
hathach
b11fcfdc59
correct skip test 2022-01-14 18:23:09 +07:00
hathach
7ec6995235
skip SD example for feather rp2040 2022-01-14 18:14:36 +07:00
hathach
4537faa145
also include samd, nrf52,esp32 2022-01-14 18:01:47 +07:00
hathach
fb0d11a405
specify rp2040 in architectures to be selected instead of built-in SdFat of rp2040 2022-01-14 17:58:07 +07:00
hathach
15c39defe5
add feather_rp2040_tinyusb to ci, expect ci to fail 2022-01-14 17:37:38 +07:00
Eva Herrada
3e298145ce
Bump to 1.4.0 2022-01-03 16:39:05 -05:00
Limor "Ladyada" Fried
5d752a3901
Merge pull request #11 from Travelbacon/master
Add support for Arduinu Uno WiFi R2
2021-12-29 12:10:17 -05:00
George
cf2a10a274
Add support for Arduinu Uno WiFi R2
Added support for the Arduino Uno WiFi R2. Solution found at https://forums.adafruit.com/viewtopic.php?f=47&t=161677#p799163 found by the user thorx.
2021-12-29 15:10:13 +01:00
Eva Herrada
df91320ee6
1.3.0 2021-12-20 23:04:59 -05:00
Ha Thach
476f8d979a
Merge pull request #9 from adafruit/fix-esp32-fcntl-warning
USE_FCNTL_H for esp32/s2
2021-12-13 23:59:50 +07:00
hathach
8190df112f
more ci fix 2021-12-13 23:40:02 +07:00
hathach
3f952664eb
more ci test 2021-12-13 22:31:21 +07:00
hathach
0f512b0155
include SD as dependency for ci 2021-12-13 18:44:46 +07:00
hathach
ca1cf4e0e1
sd dependency 2021-12-13 18:37:38 +07:00
hathach
a13979b5ca
fix some ci 2021-12-13 18:16:29 +07:00
hathach
4f3f65cb31
add ci build 2021-12-13 17:44:47 +07:00
hathach
d3cbd6511c
USE_FCNTL_H for esp32/s2 2021-12-13 17:25:35 +07:00
Limor "Ladyada" Fried
659033f387
Merge pull request #8 from paulhayes/master
Allow USE_STANDARD_SPI_LIBRARY to be set by compilation definition flag
2021-12-07 12:30:44 -05:00
Paul Hayes
367cde634d
Allow USE_STANDARD_SPI_LIBRARY to be set by compilation definition flag
I had to do this to allow alternative SPI when using Platformio. Here's how this is used in platformio.ini:
```
build_flags =
  -DUSE_STANDARD_SPI_LIBRARY=2
```
2021-12-07 13:12:07 +00:00
Dylan Herrada
68dd2d4d80
Bump to 1.2.4 2021-06-28 15:28:05 -04:00
Limor "Ladyada" Fried
54ca0c7012
Merge pull request #7 from adafruit/fix-warnings
fix warnings
2021-06-16 17:53:37 -04:00
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
24 changed files with 431 additions and 28 deletions

92
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View file

@ -0,0 +1,92 @@
name: Bug Report
description: Report a problem
labels: 'Bug'
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
It's okay to leave some blank if it doesn't apply to your problem.
- type: dropdown
attributes:
label: Operating System
options:
- Linux
- MacOS
- RaspberryPi OS
- Windows 7
- Windows 10
- Windows 11
- Others
validations:
required: true
- type: input
attributes:
label: IDE version
placeholder: e.g Arduino 1.8.15
validations:
required: true
- type: input
attributes:
label: Board
placeholder: e.g Feather nRF52840 Express
validations:
required: true
- type: input
attributes:
label: BSP version
description: Can be found under "Board Manager" menu
validations:
required: true
- type: input
attributes:
label: SPIFlash Library version
placeholder: "Release version or github latest"
validations:
required: true
- type: textarea
attributes:
label: Sketch
placeholder: |
e.g examples/flash_info
If it is custom sketch, please provide links to your minimal sources or as attached files.
validations:
required: true
- type: textarea
attributes:
label: What happened ?
placeholder: A clear and concise description of what the bug is.
validations:
required: true
- type: textarea
attributes:
label: How to reproduce ?
placeholder: |
1. Go to '...'
2. Click on '....'
3. See error
validations:
required: true
- type: textarea
attributes:
label: Debug Log
placeholder: |
Debug log where the issue occurred as attached txt file, best with comments to explain the actual events.
validations:
required: false
- type: textarea
attributes:
label: Screenshots
description: If applicable, add screenshots to help explain your problem.
validations:
required: false

4
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View file

@ -0,0 +1,4 @@
contact_links:
- name: Adafruit Support Forum
url: https://forums.adafruit.com
about: If you have other questions or need help, post it here.

View file

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: Feature
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

45
.github/workflows/githubci.yml vendored Normal file
View file

@ -0,0 +1,45 @@
name: Build
on: [pull_request, push, repository_dispatch]
jobs:
build:
strategy:
fail-fast: false
matrix:
arduino-platform:
- 'feather_rp2040'
- 'metro_m0'
- 'metro_m4'
- 'nrf52840'
- 'metroesp32s2'
runs-on: ubuntu-latest
steps:
- name: Setup Python
uses: actions/setup-python@v1
with:
python-version: '3.x'
- name: Checkout code
uses: actions/checkout@v2
- name: Checkout adafruit/ci-arduino
uses: actions/checkout@v2
with:
repository: adafruit/ci-arduino
path: ci
- name: pre-install
run: bash ci/actions_install.sh
- name: test platforms
run: python3 ci/build_platform.py ${{ matrix.arduino-platform }}
#- name: clang
# skip clang for fatfs (ff) to make it easier to compare and upgrade
# run: python3 ci/run-clang-format.py -e "ci/*" -e "bin/*" -e "./examples/SdFat_format/*" -r .
#- name: doxygen
# env:
# GH_REPO_TOKEN: ${{ secrets.GH_REPO_TOKEN }}
# PRETTYNAME : "Adafruit SPIFlash Library"
# run: bash ci/doxy_gen_and_deploy.sh

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

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

View file

View file

View file

View file

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

View file

@ -664,7 +664,7 @@ bool FatFile::openParent(FatFile* dirFile) {
goto fail; goto fail;
} }
} else { } else {
memset(&dotdot, 0, sizeof(FatFile)); memset((void*) &dotdot, 0, sizeof(FatFile));
dotdot.m_attr = FILE_ATTR_SUBDIR; dotdot.m_attr = FILE_ATTR_SUBDIR;
dotdot.m_flags = F_READ; dotdot.m_flags = F_READ;
dotdot.m_vol = dirFile->m_vol; dotdot.m_vol = dirFile->m_vol;
@ -1215,7 +1215,14 @@ bool FatFile::sync() {
// set modify time if user supplied a callback date/time function // set modify time if user supplied a callback date/time function
if (m_dateTime) { 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; dir->lastAccessDate = dir->lastWriteDate;
} }
// clear directory dirty // clear directory dirty

View file

@ -474,8 +474,15 @@ create:
// set timestamps // set timestamps
if (m_dateTime) { 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 // 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 { } else {
// use default date/time // use default date/time
dir->creationDate = FAT_DEFAULT_DATE; dir->creationDate = FAT_DEFAULT_DATE;

View file

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

View file

@ -292,6 +292,7 @@ class FatVolume {
uint8_t m_clusterBlockMask; // Mask to extract block of cluster. uint8_t m_clusterBlockMask; // Mask to extract block of cluster.
uint8_t m_clusterSizeShift; // Cluster count to block count shift. uint8_t m_clusterSizeShift; // Cluster count to block count shift.
uint8_t m_fatType; // Volume type (12, 16, OR 32). 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. uint16_t m_rootDirEntryCount; // Number of entries in FAT16 root dir.
uint32_t m_allocSearchStart; // Start cluster for alloc search. uint32_t m_allocSearchStart; // Start cluster for alloc search.
uint32_t m_blocksPerFat; // FAT size in blocks 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. * 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. * 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 * If the symbol USE_STANDARD_SPI_LIBRARY is zero, an optimized custom SPI
@ -77,7 +77,9 @@
* USE_STANDARD_SPI_LIBRARY is two, the SPI port can be selected with the * USE_STANDARD_SPI_LIBRARY is two, the SPI port can be selected with the
* constructors SdFat(SPIClass* spiPort) and SdFatEX(SPIClass* spiPort). * constructors SdFat(SPIClass* spiPort) and SdFatEX(SPIClass* spiPort).
*/ */
#ifndef USE_STANDARD_SPI_LIBRARY
#define USE_STANDARD_SPI_LIBRARY 0 #define USE_STANDARD_SPI_LIBRARY 0
#endif
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** /**
* If the symbol ENABLE_SOFTWARE_SPI_CLASS is nonzero, the class SdFatSoftSpi * If the symbol ENABLE_SOFTWARE_SPI_CLASS is nonzero, the class SdFatSoftSpi
@ -91,16 +93,16 @@
* will be defined by including the system file fcntl.h. * will be defined by including the system file fcntl.h.
*/ */
#if defined(__AVR__) #if defined(__AVR__)
// AVR fcntl.h does not define open flags. // AVR fcntl.h does not define open flags.
#define USE_FCNTL_H 0 #define USE_FCNTL_H 0
#elif defined(PLATFORM_ID) #elif defined(PLATFORM_ID)
// Particle boards - use fcntl.h. // Particle boards - use fcntl.h.
#define USE_FCNTL_H 1 #define USE_FCNTL_H 1
#elif defined(__arm__) #elif defined(__arm__) || defined(ARDUINO_ARCH_ESP32)
// ARM gcc defines open flags. // ARM and ESP32 gcc defines open flags.
#define USE_FCNTL_H 1 #define USE_FCNTL_H 1
#else // defined(__AVR__) #else // defined(__AVR__)
#define USE_FCNTL_H 0 #define USE_FCNTL_H 0
#endif // defined(__AVR__) #endif // defined(__AVR__)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** /**
@ -148,7 +150,7 @@
* Set FAT12_SUPPORT nonzero to enable use if FAT12 volumes. * Set FAT12_SUPPORT nonzero to enable use if FAT12 volumes.
* FAT12 has not been well tested and requires additional flash. * 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. * Set DESTRUCTOR_CLOSES_FILE nonzero to close a file in its destructor.
@ -209,7 +211,7 @@
/** /**
* Determine the default SPI configuration. * 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 // has multiple SPI ports
#define SD_HAS_CUSTOM_SPI 2 #define SD_HAS_CUSTOM_SPI 2
#elif defined(__AVR__)\ #elif defined(__AVR__)\

View file

@ -372,6 +372,11 @@ typedef SdFatSpiDriver SdSpiDriver;
//============================================================================== //==============================================================================
// Use of in-line for AVR to save flash. // Use of in-line for AVR to save flash.
#ifdef __AVR__ #ifdef __AVR__
#if defined (__AVR_ATmega4809__)
#define SPDR SPI0_DATA
#define SPSR SPI0_INTFLAGS
#define SPIF 7
#endif // __AVR_ATmega4809__
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
inline void SdSpiAltDriver::begin(uint8_t csPin) { inline void SdSpiAltDriver::begin(uint8_t csPin) {
m_csPin = csPin; m_csPin = csPin;

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)