Add SDIO support for RP2040/RP2350
This commit is contained in:
parent
052d38e2c6
commit
67e26476f1
99 changed files with 4283 additions and 1531 deletions
62
README.md
62
README.md
|
|
@ -1,3 +1,65 @@
|
|||
### Warning: This version has major internal changes.
|
||||
|
||||
SdFat version 2.3.0 has major changes to implement RP2040/RP2350 SDIO.
|
||||
|
||||
In addition there are number of bug fixes.
|
||||
|
||||
Begin by running the Rp2040SdioSetup example to try RP2040/RP2350 SDIO.
|
||||
|
||||
This example requires a SDIO Card socket with the following six lines.
|
||||
|
||||
CLK - A clock signal sent to the card by the MCU.
|
||||
CMD - A bidirectional line for for commands and responses.
|
||||
DAT[0:3] - Four bidirectional lines for data transfer.
|
||||
|
||||
CLK and CMD can be connected to any GPIO pins. DAT[0:3] can be connected
|
||||
to any four consecutive GPIO pins in the order DAT0, DAT1, DAT2, DAT3.
|
||||
|
||||
Here is an example of SDIO for Pico using an Adafruit socket, PiCowbell
|
||||
Proto and PiCowbell Proto Doubler.
|
||||
|
||||

|
||||
|
||||
This Socket supports SDIO with:
|
||||
```
|
||||
#define RP_CLK_GPIO 10
|
||||
#define RP_CMD_GPIO 11
|
||||
#define RP_DAT0_GPIO 12 // DAT1: GPIO13 DAT2: GPIO14, DAT3: GPIO15.
|
||||
```
|
||||
It also can be used on SPI1 with:
|
||||
```
|
||||
const uint8_t SD_CS_PIN = 15;
|
||||
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK, &SPI1)
|
||||
|
||||
// In setup
|
||||
SPI1.setSCK(10);
|
||||
SPI1.setTX(11);
|
||||
SPI1.setRX(12);
|
||||
```
|
||||
|
||||
This setup gets the following result in the bench example using SDIO.
|
||||
|
||||
<pre>
|
||||
FILE_SIZE_MB = 5
|
||||
BUF_SIZE = 512 bytes
|
||||
Starting write test, please wait.
|
||||
|
||||
write speed and latency
|
||||
speed,max,min,avg
|
||||
KB/Sec,usec,usec,usec
|
||||
15014.05,1165,32,32
|
||||
15289.54,1249,32,32
|
||||
|
||||
Starting read test, please wait.
|
||||
|
||||
read speed and latency
|
||||
speed,max,min,avg
|
||||
KB/Sec,usec,usec,usec
|
||||
15624.00,58,32,32
|
||||
15624.00,51,32,32
|
||||
</pre>
|
||||
|
||||
|
||||
File copy constructors and file assignment operators have been made private by
|
||||
default in 2.2.3 to prevent call by value and multiple copies of file instances.
|
||||
|
||||
|
|
|
|||
249
doc/Doxyfile
249
doc/Doxyfile
|
|
@ -1,4 +1,4 @@
|
|||
# Doxyfile 1.9.6
|
||||
# Doxyfile 1.10.0
|
||||
|
||||
# This file describes the settings to be used by the documentation system
|
||||
# doxygen (www.doxygen.org) for a project.
|
||||
|
|
@ -63,6 +63,12 @@ PROJECT_BRIEF =
|
|||
|
||||
PROJECT_LOGO =
|
||||
|
||||
# With the PROJECT_ICON tag one can specify an icon that is included in the tabs
|
||||
# when the HTML document is shown. Doxygen will copy the logo to the output
|
||||
# directory.
|
||||
|
||||
PROJECT_ICON =
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
|
||||
# into which the generated documentation will be written. If a relative path is
|
||||
# entered, it will be relative to the location where doxygen was started. If
|
||||
|
|
@ -363,6 +369,17 @@ MARKDOWN_SUPPORT = YES
|
|||
|
||||
TOC_INCLUDE_HEADINGS = 0
|
||||
|
||||
# The MARKDOWN_ID_STYLE tag can be used to specify the algorithm used to
|
||||
# generate identifiers for the Markdown headings. Note: Every identifier is
|
||||
# unique.
|
||||
# Possible values are: DOXYGEN use a fixed 'autotoc_md' string followed by a
|
||||
# sequence number starting at 0 and GITHUB use the lower case version of title
|
||||
# with any whitespace replaced by '-' and punctuation characters removed.
|
||||
# The default value is: DOXYGEN.
|
||||
# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
|
||||
|
||||
MARKDOWN_ID_STYLE = DOXYGEN
|
||||
|
||||
# When enabled doxygen tries to link words that correspond to documented
|
||||
# classes, or namespaces to their corresponding documentation. Such a link can
|
||||
# be prevented in individual cases by putting a % sign in front of the word or
|
||||
|
|
@ -487,6 +504,14 @@ LOOKUP_CACHE_SIZE = 0
|
|||
|
||||
NUM_PROC_THREADS = 1
|
||||
|
||||
# If the TIMESTAMP tag is set different from NO then each generated page will
|
||||
# contain the date or date and time when the page was generated. Setting this to
|
||||
# NO can help when comparing the output of multiple runs.
|
||||
# Possible values are: YES, NO, DATETIME and DATE.
|
||||
# The default value is: NO.
|
||||
|
||||
TIMESTAMP = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
|
|
@ -872,7 +897,14 @@ WARN_IF_UNDOC_ENUM_VAL = NO
|
|||
# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
|
||||
# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
|
||||
# at the end of the doxygen process doxygen will return with a non-zero status.
|
||||
# Possible values are: NO, YES and FAIL_ON_WARNINGS.
|
||||
# If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS_PRINT then doxygen behaves
|
||||
# like FAIL_ON_WARNINGS but in case no WARN_LOGFILE is defined doxygen will not
|
||||
# write the warning messages in between other messages but write them at the end
|
||||
# of a run, in case a WARN_LOGFILE is defined the warning messages will be
|
||||
# besides being in the defined file also be shown at the end of a run, unless
|
||||
# the WARN_LOGFILE is defined as - i.e. standard output (stdout) in that case
|
||||
# the behavior will remain as with the setting FAIL_ON_WARNINGS.
|
||||
# Possible values are: NO, YES, FAIL_ON_WARNINGS and FAIL_ON_WARNINGS_PRINT.
|
||||
# The default value is: NO.
|
||||
|
||||
WARN_AS_ERROR = NO
|
||||
|
|
@ -926,7 +958,9 @@ INPUT = ../src \
|
|||
../src/SpiDriver \
|
||||
mainpage.h \
|
||||
../src/FsLib \
|
||||
../src/FsLib
|
||||
../src/FsLib \
|
||||
../src/SdCard/TeensySdio \
|
||||
../src/SdCard/Rp2040Sdio
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||
|
|
@ -959,12 +993,12 @@ INPUT_FILE_ENCODING =
|
|||
# Note the list of default checked file patterns might differ from the list of
|
||||
# default file extension mappings.
|
||||
#
|
||||
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
|
||||
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
|
||||
# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml,
|
||||
# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C
|
||||
# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
|
||||
# *.vhdl, *.ucf, *.qsf and *.ice.
|
||||
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cxxm,
|
||||
# *.cpp, *.cppm, *.ccm, *.c++, *.c++m, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl,
|
||||
# *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, *.h++, *.ixx, *.l, *.cs, *.d,
|
||||
# *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to
|
||||
# be provided as doxygen C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
|
||||
# *.f18, *.f, *.for, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.
|
||||
|
||||
FILE_PATTERNS = *.c \
|
||||
*.cc \
|
||||
|
|
@ -1016,7 +1050,9 @@ EXCLUDE = ../src/common/FsStructs.h \
|
|||
../src/common/PrintBasic.h \
|
||||
../src/common/PrintBasic.cpp \
|
||||
../src/SpiDriver/SdSpiBareUnoDriver.h \
|
||||
../src/iostream/StreamBaseClass.cpp
|
||||
../src/iostream/StreamBaseClass.cpp \
|
||||
../src/SdCard/Rp2040Sdio/DbgLog.h \
|
||||
../src/common/FsStructs.h
|
||||
|
||||
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
|
||||
# directories that are symbolic links (a Unix file system feature) are excluded
|
||||
|
|
@ -1039,9 +1075,6 @@ EXCLUDE_PATTERNS =
|
|||
# output. The symbol name can be a fully qualified name, a word, or if the
|
||||
# wildcard * is used, a substring. Examples: ANamespace, AClass,
|
||||
# ANamespace::AClass, ANamespace::*Test
|
||||
#
|
||||
# Note that the wildcards are matched against the file with absolute path, so to
|
||||
# exclude all test directories use the pattern */test/*
|
||||
|
||||
EXCLUDE_SYMBOLS =
|
||||
|
||||
|
|
@ -1155,7 +1188,8 @@ FORTRAN_COMMENT_AFTER = 72
|
|||
SOURCE_BROWSER = NO
|
||||
|
||||
# Setting the INLINE_SOURCES tag to YES will include the body of functions,
|
||||
# classes and enums directly into the documentation.
|
||||
# multi-line macros, enums or list initialized variables directly into the
|
||||
# documentation.
|
||||
# The default value is: NO.
|
||||
|
||||
INLINE_SOURCES = NO
|
||||
|
|
@ -1424,15 +1458,6 @@ HTML_COLORSTYLE_SAT = 100
|
|||
|
||||
HTML_COLORSTYLE_GAMMA = 80
|
||||
|
||||
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
|
||||
# page will contain the date and time when the page was generated. Setting this
|
||||
# to YES can help to show when doxygen was last run and thus if the
|
||||
# documentation is up to date.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_TIMESTAMP = YES
|
||||
|
||||
# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
|
||||
# documentation will contain a main index with vertical navigation menus that
|
||||
# are dynamically created via JavaScript. If disabled, the navigation index will
|
||||
|
|
@ -1452,6 +1477,33 @@ HTML_DYNAMIC_MENUS = YES
|
|||
|
||||
HTML_DYNAMIC_SECTIONS = NO
|
||||
|
||||
# If the HTML_CODE_FOLDING tag is set to YES then classes and functions can be
|
||||
# dynamically folded and expanded in the generated HTML source code.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_CODE_FOLDING = YES
|
||||
|
||||
# If the HTML_COPY_CLIPBOARD tag is set to YES then doxygen will show an icon in
|
||||
# the top right corner of code and text fragments that allows the user to copy
|
||||
# its content to the clipboard. Note this only works if supported by the browser
|
||||
# and the web page is served via a secure context (see:
|
||||
# https://www.w3.org/TR/secure-contexts/), i.e. using the https: or file:
|
||||
# protocol.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_COPY_CLIPBOARD = YES
|
||||
|
||||
# Doxygen stores a couple of settings persistently in the browser (via e.g.
|
||||
# cookies). By default these settings apply to all HTML pages generated by
|
||||
# doxygen across all projects. The HTML_PROJECT_COOKIE tag can be used to store
|
||||
# the settings under a project specific key, such that the user preferences will
|
||||
# be stored separately.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_PROJECT_COOKIE =
|
||||
|
||||
# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
|
||||
# shown in the various tree structured indices initially; the user can expand
|
||||
# and collapse entries dynamically later on. Doxygen will expand the tree to
|
||||
|
|
@ -1582,6 +1634,16 @@ BINARY_TOC = NO
|
|||
|
||||
TOC_EXPAND = NO
|
||||
|
||||
# The SITEMAP_URL tag is used to specify the full URL of the place where the
|
||||
# generated documentation will be placed on the server by the user during the
|
||||
# deployment of the documentation. The generated sitemap is called sitemap.xml
|
||||
# and placed on the directory specified by HTML_OUTPUT. In case no SITEMAP_URL
|
||||
# is specified no sitemap is generated. For information about the sitemap
|
||||
# protocol see https://www.sitemaps.org
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
SITEMAP_URL =
|
||||
|
||||
# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
|
||||
# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
|
||||
# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
|
||||
|
|
@ -2070,9 +2132,16 @@ PDF_HYPERLINKS = YES
|
|||
|
||||
USE_PDFLATEX = YES
|
||||
|
||||
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
|
||||
# command to the generated LaTeX files. This will instruct LaTeX to keep running
|
||||
# if errors occur, instead of asking the user for help.
|
||||
# The LATEX_BATCHMODE tag signals the behavior of LaTeX in case of an error.
|
||||
# Possible values are: NO same as ERROR_STOP, YES same as BATCH, BATCH In batch
|
||||
# mode nothing is printed on the terminal, errors are scrolled as if <return> is
|
||||
# hit at every error; missing files that TeX tries to input or request from
|
||||
# keyboard input (\read on a not open input stream) cause the job to abort,
|
||||
# NON_STOP In nonstop mode the diagnostic message will appear on the terminal,
|
||||
# but there is no possibility of user interaction just like in batch mode,
|
||||
# SCROLL In scroll mode, TeX will stop only for missing files to input or if
|
||||
# keyboard input is necessary and ERROR_STOP In errorstop mode, TeX will stop at
|
||||
# each error, asking for user intervention.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
|
|
@ -2093,14 +2162,6 @@ LATEX_HIDE_INDICES = NO
|
|||
|
||||
LATEX_BIB_STYLE = plain
|
||||
|
||||
# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
|
||||
# page will contain the date and time when the page was generated. Setting this
|
||||
# to NO can help when comparing the output of multiple runs.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
LATEX_TIMESTAMP = NO
|
||||
|
||||
# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
|
||||
# path from which the emoji images will be read. If a relative path is entered,
|
||||
# it will be relative to the LATEX_OUTPUT directory. If left blank the
|
||||
|
|
@ -2266,7 +2327,7 @@ DOCBOOK_OUTPUT = docbook
|
|||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
|
||||
# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
|
||||
# AutoGen Definitions (see https://autogen.sourceforge.net/) file that captures
|
||||
# the structure of the code including all documentation. Note that this feature
|
||||
# is still experimental and incomplete at the moment.
|
||||
# The default value is: NO.
|
||||
|
|
@ -2277,6 +2338,28 @@ GENERATE_AUTOGEN_DEF = NO
|
|||
# Configuration options related to Sqlite3 output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_SQLITE3 tag is set to YES doxygen will generate a Sqlite3
|
||||
# database with symbols found by doxygen stored in tables.
|
||||
# The default value is: NO.
|
||||
|
||||
GENERATE_SQLITE3 = NO
|
||||
|
||||
# The SQLITE3_OUTPUT tag is used to specify where the Sqlite3 database will be
|
||||
# put. If a relative path is entered the value of OUTPUT_DIRECTORY will be put
|
||||
# in front of it.
|
||||
# The default directory is: sqlite3.
|
||||
# This tag requires that the tag GENERATE_SQLITE3 is set to YES.
|
||||
|
||||
SQLITE3_OUTPUT = sqlite3
|
||||
|
||||
# The SQLITE3_RECREATE_DB tag is set to YES, the existing doxygen_sqlite3.db
|
||||
# database file will be recreated with each doxygen run. If set to NO, doxygen
|
||||
# will warn if a database file is already found and not modify it.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag GENERATE_SQLITE3 is set to YES.
|
||||
|
||||
SQLITE3_RECREATE_DB = YES
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the Perl module output
|
||||
#---------------------------------------------------------------------------
|
||||
|
|
@ -2423,15 +2506,15 @@ TAGFILES =
|
|||
|
||||
GENERATE_TAGFILE =
|
||||
|
||||
# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
|
||||
# the class index. If set to NO, only the inherited external classes will be
|
||||
# listed.
|
||||
# If the ALLEXTERNALS tag is set to YES, all external classes and namespaces
|
||||
# will be listed in the class and namespace index. If set to NO, only the
|
||||
# inherited external classes will be listed.
|
||||
# The default value is: NO.
|
||||
|
||||
ALLEXTERNALS = NO
|
||||
|
||||
# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
|
||||
# in the modules index. If set to NO, only the current project's groups will be
|
||||
# in the topic index. If set to NO, only the current project's groups will be
|
||||
# listed.
|
||||
# The default value is: YES.
|
||||
|
||||
|
|
@ -2445,16 +2528,9 @@ EXTERNAL_GROUPS = YES
|
|||
EXTERNAL_PAGES = YES
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
# Configuration options related to diagram generator tools
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# You can include diagrams made with dia in doxygen documentation. Doxygen will
|
||||
# then run dia to produce the diagram and insert it in the documentation. The
|
||||
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
|
||||
# If left empty dia is assumed to be found in the default search path.
|
||||
|
||||
DIA_PATH =
|
||||
|
||||
# If set to YES the inheritance and collaboration graphs will hide inheritance
|
||||
# and usage relations if the target is undocumented or is not a class.
|
||||
# The default value is: YES.
|
||||
|
|
@ -2463,7 +2539,7 @@ HIDE_UNDOC_RELATIONS = YES
|
|||
|
||||
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
|
||||
# available from the path. This tool is part of Graphviz (see:
|
||||
# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
|
||||
# https://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
|
||||
# Bell Labs. The other options in this section have no effect if this option is
|
||||
# set to NO
|
||||
# The default value is: NO.
|
||||
|
|
@ -2516,13 +2592,19 @@ DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4"
|
|||
|
||||
DOT_FONTPATH =
|
||||
|
||||
# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a
|
||||
# graph for each documented class showing the direct and indirect inheritance
|
||||
# relations. In case HAVE_DOT is set as well dot will be used to draw the graph,
|
||||
# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set
|
||||
# to TEXT the direct and indirect inheritance relations will be shown as texts /
|
||||
# links.
|
||||
# Possible values are: NO, YES, TEXT and GRAPH.
|
||||
# If the CLASS_GRAPH tag is set to YES or GRAPH or BUILTIN then doxygen will
|
||||
# generate a graph for each documented class showing the direct and indirect
|
||||
# inheritance relations. In case the CLASS_GRAPH tag is set to YES or GRAPH and
|
||||
# HAVE_DOT is enabled as well, then dot will be used to draw the graph. In case
|
||||
# the CLASS_GRAPH tag is set to YES and HAVE_DOT is disabled or if the
|
||||
# CLASS_GRAPH tag is set to BUILTIN, then the built-in generator will be used.
|
||||
# If the CLASS_GRAPH tag is set to TEXT the direct and indirect inheritance
|
||||
# relations will be shown as texts / links. Explicit enabling an inheritance
|
||||
# graph or choosing a different representation for an inheritance graph of a
|
||||
# specific class, can be accomplished by means of the command \inheritancegraph.
|
||||
# Disabling an inheritance graph can be accomplished by means of the command
|
||||
# \hideinheritancegraph.
|
||||
# Possible values are: NO, YES, TEXT, GRAPH and BUILTIN.
|
||||
# The default value is: YES.
|
||||
|
||||
CLASS_GRAPH = YES
|
||||
|
|
@ -2530,15 +2612,21 @@ CLASS_GRAPH = YES
|
|||
# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
|
||||
# graph for each documented class showing the direct and indirect implementation
|
||||
# dependencies (inheritance, containment, and class references variables) of the
|
||||
# class with other documented classes.
|
||||
# class with other documented classes. Explicit enabling a collaboration graph,
|
||||
# when COLLABORATION_GRAPH is set to NO, can be accomplished by means of the
|
||||
# command \collaborationgraph. Disabling a collaboration graph can be
|
||||
# accomplished by means of the command \hidecollaborationgraph.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
COLLABORATION_GRAPH = YES
|
||||
|
||||
# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
|
||||
# groups, showing the direct groups dependencies. See also the chapter Grouping
|
||||
# in the manual.
|
||||
# groups, showing the direct groups dependencies. Explicit enabling a group
|
||||
# dependency graph, when GROUP_GRAPHS is set to NO, can be accomplished by means
|
||||
# of the command \groupgraph. Disabling a directory graph can be accomplished by
|
||||
# means of the command \hidegroupgraph. See also the chapter Grouping in the
|
||||
# manual.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
|
|
@ -2580,8 +2668,8 @@ DOT_UML_DETAILS = NO
|
|||
|
||||
# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
|
||||
# to display on a single line. If the actual line length exceeds this threshold
|
||||
# significantly it will wrapped across multiple lines. Some heuristics are apply
|
||||
# to avoid ugly line breaks.
|
||||
# significantly it will be wrapped across multiple lines. Some heuristics are
|
||||
# applied to avoid ugly line breaks.
|
||||
# Minimum value: 0, maximum value: 1000, default value: 17.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
|
|
@ -2598,7 +2686,9 @@ TEMPLATE_RELATIONS = NO
|
|||
# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
|
||||
# YES then doxygen will generate a graph for each documented file showing the
|
||||
# direct and indirect include dependencies of the file with other documented
|
||||
# files.
|
||||
# files. Explicit enabling an include graph, when INCLUDE_GRAPH is is set to NO,
|
||||
# can be accomplished by means of the command \includegraph. Disabling an
|
||||
# include graph can be accomplished by means of the command \hideincludegraph.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
|
|
@ -2607,7 +2697,10 @@ INCLUDE_GRAPH = YES
|
|||
# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
|
||||
# set to YES then doxygen will generate a graph for each documented file showing
|
||||
# the direct and indirect include dependencies of the file with other documented
|
||||
# files.
|
||||
# files. Explicit enabling an included by graph, when INCLUDED_BY_GRAPH is set
|
||||
# to NO, can be accomplished by means of the command \includedbygraph. Disabling
|
||||
# an included by graph can be accomplished by means of the command
|
||||
# \hideincludedbygraph.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
|
|
@ -2647,7 +2740,10 @@ GRAPHICAL_HIERARCHY = YES
|
|||
# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
|
||||
# dependencies a directory has on other directories in a graphical way. The
|
||||
# dependency relations are determined by the #include relations between the
|
||||
# files in the directories.
|
||||
# files in the directories. Explicit enabling a directory graph, when
|
||||
# DIRECTORY_GRAPH is set to NO, can be accomplished by means of the command
|
||||
# \directorygraph. Disabling a directory graph can be accomplished by means of
|
||||
# the command \hidedirectorygraph.
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag HAVE_DOT is set to YES.
|
||||
|
||||
|
|
@ -2663,7 +2759,7 @@ DIR_GRAPH_MAX_DEPTH = 1
|
|||
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
|
||||
# generated by dot. For an explanation of the image formats see the section
|
||||
# output formats in the documentation of the dot tool (Graphviz (see:
|
||||
# http://www.graphviz.org/)).
|
||||
# https://www.graphviz.org/)).
|
||||
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
|
||||
# to make the SVG files visible in IE 9+ (other browsers do not have this
|
||||
# requirement).
|
||||
|
|
@ -2700,11 +2796,12 @@ DOT_PATH =
|
|||
|
||||
DOTFILE_DIRS =
|
||||
|
||||
# The MSCFILE_DIRS tag can be used to specify one or more directories that
|
||||
# contain msc files that are included in the documentation (see the \mscfile
|
||||
# command).
|
||||
# You can include diagrams made with dia in doxygen documentation. Doxygen will
|
||||
# then run dia to produce the diagram and insert it in the documentation. The
|
||||
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
|
||||
# If left empty dia is assumed to be found in the default search path.
|
||||
|
||||
MSCFILE_DIRS =
|
||||
DIA_PATH =
|
||||
|
||||
# The DIAFILE_DIRS tag can be used to specify one or more directories that
|
||||
# contain dia files that are included in the documentation (see the \diafile
|
||||
|
|
@ -2781,3 +2878,19 @@ GENERATE_LEGEND = YES
|
|||
# The default value is: YES.
|
||||
|
||||
DOT_CLEANUP = YES
|
||||
|
||||
# You can define message sequence charts within doxygen comments using the \msc
|
||||
# command. If the MSCGEN_TOOL tag is left empty (the default), then doxygen will
|
||||
# use a built-in version of mscgen tool to produce the charts. Alternatively,
|
||||
# the MSCGEN_TOOL tag can also specify the name an external tool. For instance,
|
||||
# specifying prog as the value, doxygen will call the tool as prog -T
|
||||
# <outfile_format> -o <outputfile> <inputfile>. The external tool should support
|
||||
# output file formats "png", "eps", "svg", and "ismap".
|
||||
|
||||
MSCGEN_TOOL =
|
||||
|
||||
# The MSCFILE_DIRS tag can be used to specify one or more directories that
|
||||
# contain msc files that are included in the documentation (see the \mscfile
|
||||
# command).
|
||||
|
||||
MSCFILE_DIRS =
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
2022-07-01
|
||||
2025-01-01
|
||||
|
||||
Run the SdErrorCode example to produce an updated list.
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ Code,Symbol - failed operation
|
|||
0X06,SD_CARD_ERROR_CMD8 - Send and check interface settings
|
||||
0X07,SD_CARD_ERROR_CMD9 - Read CSD data
|
||||
0X08,SD_CARD_ERROR_CMD10 - Read CID data
|
||||
0X09,SD_CARD_ERROR_CMD12 - Stop multiple block read
|
||||
0X09,SD_CARD_ERROR_CMD12 - Stop multiple block transmission
|
||||
0X0A,SD_CARD_ERROR_CMD13 - Read card status
|
||||
0X0B,SD_CARD_ERROR_CMD17 - Read single block
|
||||
0X0C,SD_CARD_ERROR_CMD18 - Read multiple blocks
|
||||
|
|
|
|||
BIN
doc/html.zip
BIN
doc/html.zip
Binary file not shown.
|
|
@ -20,11 +20,10 @@
|
|||
*/
|
||||
#ifdef __AVR__
|
||||
#include <SPI.h>
|
||||
|
||||
#include "SdFat.h"
|
||||
#include "AvrAdcLogger.h"
|
||||
#include "BufferedPrint.h"
|
||||
#include "FreeStack.h"
|
||||
#include "SdFat.h"
|
||||
|
||||
// Save SRAM if 328.
|
||||
#ifdef __AVR_ATmega328P__
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
// Test and benchmark of the fast bufferedPrint class.
|
||||
//
|
||||
// Mainly for AVR but may improve print performance with other CPUs.
|
||||
#include "BufferedPrint.h"
|
||||
#define DISABLE_FS_H_WARNING // Disable warning for type File not defined.
|
||||
#include "SdFat.h"
|
||||
|
||||
#include "BufferedPrint.h"
|
||||
// SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h,
|
||||
// 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT.
|
||||
#define SD_FAT_TYPE 3
|
||||
|
|
@ -28,13 +28,16 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
|
|||
#define SPI_CLOCK SD_SCK_MHZ(50)
|
||||
|
||||
// Try to select the best SD card configuration.
|
||||
#if HAS_SDIO_CLASS
|
||||
#if defined(HAS_TEENSY_SDIO)
|
||||
#define SD_CONFIG SdioConfig(FIFO_SDIO)
|
||||
#elif defined(RP_CLK_GPIO) && defined(RP_CMD_GPIO) && defined(RP_DAT0_GPIO)
|
||||
// See the Rp2040SdioSetup example for RP2040/RP2350 boards.
|
||||
#define SD_CONFIG SdioConfig(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO)
|
||||
#elif ENABLE_DEDICATED_SPI
|
||||
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
|
||||
#else // HAS_SDIO_CLASS
|
||||
#else // HAS_TEENSY_SDIO
|
||||
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
|
||||
#endif // HAS_SDIO_CLASS
|
||||
#endif // HAS_TEENSY_SDIO
|
||||
|
||||
#if SD_FAT_TYPE == 0
|
||||
SdFat sd;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* Example use of chdir(), ls(), mkdir(), and rmdir().
|
||||
*/
|
||||
#define DISABLE_FS_H_WARNING // Disable warning for type File not defined.
|
||||
#include "SdFat.h"
|
||||
#include "sdios.h"
|
||||
|
||||
|
|
@ -28,13 +29,16 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
|
|||
#define SPI_CLOCK SD_SCK_MHZ(50)
|
||||
|
||||
// Try to select the best SD card configuration.
|
||||
#if HAS_SDIO_CLASS
|
||||
#if defined(HAS_TEENSY_SDIO)
|
||||
#define SD_CONFIG SdioConfig(FIFO_SDIO)
|
||||
#elif defined(RP_CLK_GPIO) && defined(RP_CMD_GPIO) && defined(RP_DAT0_GPIO)
|
||||
// See the Rp2040SdioSetup example for RP2040/RP2350 boards.
|
||||
#define SD_CONFIG SdioConfig(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO)
|
||||
#elif ENABLE_DEDICATED_SPI
|
||||
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
|
||||
#else // HAS_SDIO_CLASS
|
||||
#else // HAS_TEENSY_SDIO
|
||||
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
|
||||
#endif // HAS_SDIO_CLASS
|
||||
#endif // HAS_TEENSY_SDIO
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#if SD_FAT_TYPE == 0
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@
|
|||
//
|
||||
// The maximum data rate will depend on the quality of your SD,
|
||||
// the size of the FIFO, and using dedicated SPI.
|
||||
#define DISABLE_FS_H_WARNING // Disable warning for type File not defined.
|
||||
#include "SdFat.h"
|
||||
#include "ExFatLogger.h"
|
||||
#include "FreeStack.h"
|
||||
#include "SdFat.h"
|
||||
//------------------------------------------------------------------------------
|
||||
// This example was designed for exFAT but will support FAT16/FAT32.
|
||||
// Note: Uno will not support SD_FAT_TYPE = 3.
|
||||
|
|
@ -69,13 +70,16 @@ const uint32_t PREALLOCATE_SIZE_MiB = 1024UL;
|
|||
#define SPI_CLOCK SD_SCK_MHZ(50)
|
||||
|
||||
// Try to select the best SD card configuration.
|
||||
#if HAS_SDIO_CLASS
|
||||
#if defined(HAS_TEENSY_SDIO)
|
||||
#define SD_CONFIG SdioConfig(FIFO_SDIO)
|
||||
#elif defined(RP_CLK_GPIO) && defined(RP_CMD_GPIO) && defined(RP_DAT0_GPIO)
|
||||
// See the Rp2040SdioSetup example for RP2040/RP2350 boards.
|
||||
#define SD_CONFIG SdioConfig(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO)
|
||||
#elif ENABLE_DEDICATED_SPI
|
||||
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
|
||||
#else // HAS_SDIO_CLASS
|
||||
#else // HAS_TEENSY_SDIO
|
||||
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
|
||||
#endif // HAS_SDIO_CLASS
|
||||
#endif // HAS_TEENSY_SDIO
|
||||
|
||||
// Save SRAM if 328.
|
||||
#ifdef __AVR_ATmega328P__
|
||||
|
|
@ -92,7 +96,7 @@ void logRecord(data_t* data, uint16_t overrun) {
|
|||
data->adc[0] = 0X8000 | overrun;
|
||||
} else {
|
||||
for (size_t i = 0; i < ADC_COUNT; i++) {
|
||||
data->adc[i] = analogRead(i);
|
||||
data->adc[i] = analogRead(A0 + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* Print size, modify date/time, and name for all files in root.
|
||||
*/
|
||||
#define DISABLE_FS_H_WARNING // Disable warning for type File not defined.
|
||||
#include "SdFat.h"
|
||||
|
||||
// SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h,
|
||||
|
|
@ -27,13 +28,16 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
|
|||
#define SPI_CLOCK SD_SCK_MHZ(50)
|
||||
|
||||
// Try to select the best SD card configuration.
|
||||
#if HAS_SDIO_CLASS
|
||||
#if defined(HAS_TEENSY_SDIO)
|
||||
#define SD_CONFIG SdioConfig(FIFO_SDIO)
|
||||
#elif defined(RP_CLK_GPIO) && defined(RP_CMD_GPIO) && defined(RP_DAT0_GPIO)
|
||||
// See the Rp2040SdioSetup example for RP2040/RP2350 boards.
|
||||
#define SD_CONFIG SdioConfig(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO)
|
||||
#elif ENABLE_DEDICATED_SPI
|
||||
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
|
||||
#else // HAS_SDIO_CLASS
|
||||
#else // HAS_TEENSY_SDIO
|
||||
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
|
||||
#endif // HAS_SDIO_CLASS
|
||||
#endif // HAS_TEENSY_SDIO
|
||||
|
||||
#if SD_FAT_TYPE == 0
|
||||
SdFat sd;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#define DISABLE_FS_H_WARNING // Disable warning for type File not defined.
|
||||
#include "SdFat.h"
|
||||
|
||||
// SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h,
|
||||
|
|
@ -24,13 +25,16 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
|
|||
#define SPI_CLOCK SD_SCK_MHZ(50)
|
||||
|
||||
// Try to select the best SD card configuration.
|
||||
#if HAS_SDIO_CLASS
|
||||
#if defined(HAS_TEENSY_SDIO)
|
||||
#define SD_CONFIG SdioConfig(FIFO_SDIO)
|
||||
#elif defined(RP_CLK_GPIO) && defined(RP_CMD_GPIO) && defined(RP_DAT0_GPIO)
|
||||
// See the Rp2040SdioSetup example for RP2040/RP2350 boards.
|
||||
#define SD_CONFIG SdioConfig(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO)
|
||||
#elif ENABLE_DEDICATED_SPI
|
||||
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
|
||||
#else // HAS_SDIO_CLASS
|
||||
#else // HAS_TEENSY_SDIO
|
||||
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
|
||||
#endif // HAS_SDIO_CLASS
|
||||
#endif // HAS_TEENSY_SDIO
|
||||
|
||||
#if SD_FAT_TYPE == 0
|
||||
SdFat sd;
|
||||
|
|
@ -126,7 +130,7 @@ void setup() {
|
|||
if (!file.open("ReadCsvDemo.csv", FILE_WRITE)) {
|
||||
error("open failed");
|
||||
}
|
||||
// Write test data.
|
||||
// Write test data. Test missing CRLF on last line.
|
||||
file.print(
|
||||
F("abc,123,456,7.89\r\n"
|
||||
"def,-321,654,-9.87\r\n"
|
||||
|
|
@ -143,6 +147,10 @@ void setup() {
|
|||
if (line[n - 1] != '\n' && n == (sizeof(line) - 1)) {
|
||||
error("line too long");
|
||||
}
|
||||
if (line[n - 1] == '\n') {
|
||||
// Remove new line.
|
||||
line[n -1] = 0;
|
||||
}
|
||||
if (!parseLine(line)) {
|
||||
error("parseLine failed");
|
||||
}
|
||||
|
|
|
|||
93
examples/Rp2040SdioSetup/Rp2040SdioSetup.ino
Normal file
93
examples/Rp2040SdioSetup/Rp2040SdioSetup.ino
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
// RP2040 PIO SDIO setup and test.
|
||||
/*
|
||||
This example requires a SDIO Card socket with the following six lines.
|
||||
|
||||
CLK - A clock signal sent to the card by the MCU.
|
||||
CMD - A bidirectional line for for commands and responses.
|
||||
DAT[0:3] - Four bidirectional lines for data transfer.
|
||||
|
||||
CLK and CMD can be connected to any GPIO pins. DAT[0:3] can be connected
|
||||
to any four consecutive GPIO pins in the order DAT0, DAT1, DAT2, DAT3.
|
||||
|
||||
For testing, I use several RP2040/RP3350 boards.
|
||||
The Adafruit Metro RP2040 which has a builtin SDIO socket.
|
||||
|
||||
https://learn.adafruit.com/adafruit-metro-rp2040
|
||||
|
||||
I use this SD socket breakout board for other boards.
|
||||
|
||||
https://learn.adafruit.com/adafruit-microsd-spi-sdio
|
||||
|
||||
Wires should be short since signals can be as faster than 50 MHz.
|
||||
*/
|
||||
#define DISABLE_FS_H_WARNING // Disable warning for type File not defined.
|
||||
#include "SdFat.h"
|
||||
//------------------------------------------------------------------------------
|
||||
// Example GPIO definitions I use for debug. Edit for your setup.
|
||||
// Run this example as is to print the symbol for your variant.
|
||||
//
|
||||
#if defined(ARDUINO_ADAFRUIT_METRO_RP2040)
|
||||
#define RP_CLK_GPIO 18
|
||||
#define RP_CMD_GPIO 19
|
||||
#define RP_DAT0_GPIO 20 // DAT1: GPIO21, DAT2: GPIO22, DAT3: GPIO23.
|
||||
#elif defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_RASPBERRY_PI_PICO_2)
|
||||
#define RP_CLK_GPIO 16
|
||||
#define RP_CMD_GPIO 17
|
||||
#define RP_DAT0_GPIO 18 // DAT1: GPIO19, DAT2: GPIO20, DAT3: GPIO21.
|
||||
#elif defined(ARDUINO_ADAFRUIT_FEATHER_RP2350_HSTX)
|
||||
#define RP_CLK_GPIO 11
|
||||
#define RP_CMD_GPIO 10
|
||||
#define RP_DAT0_GPIO 22 // DAT1: GPIO23, DAT2: GPIO24, DAT3: GPIO25.
|
||||
#endif // defined(ARDUINO_ADAFRUIT_METRO_RP2040))
|
||||
|
||||
#if defined(RP_CLK_GPIO) && defined(RP_CMD_GPIO) && defined(RP_DAT0_GPIO)
|
||||
#define SD_CONFIG SdioConfig(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO)
|
||||
#else // defined(RP_CLK_GPIO) && defined(RP_CMD_GPIO) && defined(RP_DAT0_GPIO)
|
||||
#warning "Undefined SD_CONFIG. Run this program for the Variant Symbol."
|
||||
#endif // defined(RP_CLK_GPIO) && defined(RP_CMD_GPIO) && defined(RP_DAT0_GPIO)
|
||||
//------------------------------------------------------------------------------
|
||||
// Class File is not defined by SdFat since the RP2040 system defines it.
|
||||
// 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT.
|
||||
#define SD_FAT_TYPE 3
|
||||
|
||||
#if SD_FAT_TYPE == 1
|
||||
SdFat32 sd;
|
||||
File32 file;
|
||||
#elif SD_FAT_TYPE == 2
|
||||
SdExFat sd;
|
||||
ExFile file;
|
||||
#elif SD_FAT_TYPE == 3
|
||||
SdFs sd;
|
||||
FsFile file;
|
||||
#else // SD_FAT_TYPE
|
||||
#error Invalid SD_FAT_TYPE
|
||||
#endif // SD_FAT_TYPE
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
yield();
|
||||
}
|
||||
Serial.println("Type any character to start\n");
|
||||
while (!Serial.available()) {
|
||||
yield();
|
||||
}
|
||||
Serial.print("Variant Symbol: ");
|
||||
Serial.print("ARDUINO_");
|
||||
Serial.println(BOARD_NAME);
|
||||
Serial.println();
|
||||
#if defined(SD_CONFIG)
|
||||
if (!sd.begin(SD_CONFIG)) {
|
||||
sd.initErrorHalt(&Serial);
|
||||
}
|
||||
Serial.println("Card successfully initialized.");
|
||||
Serial.println("\nls:");
|
||||
sd.ls(LS_A | LS_DATE | LS_SIZE); // Add LS_R for recursive list.
|
||||
Serial.println("\nDone! Try the bench example next.");
|
||||
#else // #if defined(SD_CONFIG)
|
||||
Serial.println("Error: SD_CONFIG undefined for your board.");
|
||||
Serial.println("Define RP_CLK_GPIO, RP_CMD_GPIO, and RP_DAT0_GPIO above.");
|
||||
#endif
|
||||
}
|
||||
|
||||
void loop() {}
|
||||
|
|
@ -35,13 +35,16 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
|
|||
#define SPI_CLOCK SD_SCK_MHZ(50)
|
||||
|
||||
// Try to select the best SD card configuration.
|
||||
#if HAS_SDIO_CLASS
|
||||
#if defined(HAS_TEENSY_SDIO)
|
||||
#define SD_CONFIG SdioConfig(FIFO_SDIO)
|
||||
#elif defined(RP_CLK_GPIO) && defined(RP_CMD_GPIO) && defined(RP_DAT0_GPIO)
|
||||
// See the Rp2040SdioSetup example for RP2040/RP2350 boards.
|
||||
#define SD_CONFIG SdioConfig(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO)
|
||||
#elif ENABLE_DEDICATED_SPI
|
||||
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
|
||||
#else // HAS_SDIO_CLASS
|
||||
#else // HAS_TEENSY_SDIO
|
||||
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
|
||||
#endif // HAS_SDIO_CLASS
|
||||
#endif // HAS_TEENSY_SDIO
|
||||
|
||||
#if SD_FAT_TYPE == 0
|
||||
SdFat sd;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
* For very small cards this program uses FAT16
|
||||
* and the above SDFormatter uses FAT12.
|
||||
*/
|
||||
#define DISABLE_FS_H_WARNING // Disable warning for type File not defined.
|
||||
#include "SdFat.h"
|
||||
#include "sdios.h"
|
||||
|
||||
|
|
@ -40,13 +41,16 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
|
|||
#define SPI_CLOCK SD_SCK_MHZ(50)
|
||||
|
||||
// Try to select the best SD card configuration.
|
||||
#if HAS_SDIO_CLASS
|
||||
#if defined(HAS_TEENSY_SDIO)
|
||||
#define SD_CONFIG SdioConfig(FIFO_SDIO)
|
||||
#elif defined(RP_CLK_GPIO) && defined(RP_CMD_GPIO) && defined(RP_DAT0_GPIO)
|
||||
// See the Rp2040SdioSetup example for RP2040/RP2350 boards.
|
||||
#define SD_CONFIG SdioConfig(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO)
|
||||
#elif ENABLE_DEDICATED_SPI
|
||||
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
|
||||
#else // HAS_SDIO_CLASS
|
||||
#else // HAS_TEENSY_SDIO
|
||||
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
|
||||
#endif // HAS_SDIO_CLASS
|
||||
#endif // HAS_TEENSY_SDIO
|
||||
//==============================================================================
|
||||
// Serial output stream
|
||||
ArduinoOutStream cout(Serial);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
* https://gurumeditation.org/1342/sd-memory-card-register-decoder/
|
||||
* https://archive.goughlui.com/static/multicid.htm
|
||||
*/
|
||||
#define DISABLE_FS_H_WARNING // Disable warning for type File not defined.
|
||||
#include "SdFat.h"
|
||||
#include "sdios.h"
|
||||
/*
|
||||
|
|
@ -30,13 +31,16 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
|
|||
#endif // SDCARD_SS_PIN
|
||||
|
||||
// Try to select the best SD card configuration.
|
||||
#if HAS_SDIO_CLASS
|
||||
#if defined(HAS_TEENSY_SDIO)
|
||||
#define SD_CONFIG SdioConfig(FIFO_SDIO)
|
||||
#elif defined(RP_CLK_GPIO) && defined(RP_CMD_GPIO) && defined(RP_DAT0_GPIO)
|
||||
// See the Rp2040SdioSetup example for RP2040/RP2350 boards.
|
||||
#define SD_CONFIG SdioConfig(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO)
|
||||
#elif ENABLE_DEDICATED_SPI
|
||||
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SD_SCK_MHZ(16))
|
||||
#else // HAS_SDIO_CLASS
|
||||
#else // HAS_TEENSY_SDIO
|
||||
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SD_SCK_MHZ(16))
|
||||
#endif // HAS_SDIO_CLASS
|
||||
#endif // HAS_TEENSY_SDIO
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SdFs sd;
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@
|
|||
//
|
||||
#include "ADC.h"
|
||||
#include "DMAChannel.h"
|
||||
#include "SdFat.h"
|
||||
#include "FreeStack.h"
|
||||
#include "RingBuf.h"
|
||||
#include "SdFat.h"
|
||||
|
||||
// Pin must be on first ADC.
|
||||
#define ADC_PIN A0
|
||||
|
|
|
|||
|
|
@ -29,13 +29,13 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
|
|||
#define SPI_CLOCK SD_SCK_MHZ(50)
|
||||
|
||||
// Try to select the best SD card configuration.
|
||||
#if HAS_SDIO_CLASS
|
||||
#if defined(HAS_TEENSY_SDIO)
|
||||
#define SD_CONFIG SdioConfig(FIFO_SDIO)
|
||||
#elif ENABLE_DEDICATED_SPI
|
||||
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
|
||||
#else // HAS_SDIO_CLASS
|
||||
#else // HAS_TEENSY_SDIO
|
||||
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
|
||||
#endif // HAS_SDIO_CLASS
|
||||
#endif // HAS_TEENSY_SDIO
|
||||
|
||||
#if SD_FAT_TYPE == 0
|
||||
SdFat sd;
|
||||
|
|
|
|||
|
|
@ -5,9 +5,8 @@
|
|||
// puts the controller in write mode and takes about 11 usec on a
|
||||
// Teensy 4.1. About 5 usec is required to write a sector when the
|
||||
// controller is in write mode.
|
||||
|
||||
#include "RingBuf.h"
|
||||
#include "SdFat.h"
|
||||
#include "RingBuf.h"
|
||||
|
||||
// Use Teensy SDIO
|
||||
#define SD_CONFIG SdioConfig(FIFO_SDIO)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,16 @@
|
|||
// Simple test of Unicode filename.
|
||||
// Unicode is supported as UTF-8 encoded strings.
|
||||
#define DISABLE_FS_H_WARNING // Disable warning for type File not defined.
|
||||
#include "SdFat.h"
|
||||
|
||||
// SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h,
|
||||
// 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT.
|
||||
#if defined __has_include
|
||||
#if __has_include(<FS.h>)
|
||||
#define SD_FAT_TYPE 3 // Can't use SdFat/File
|
||||
#endif // __has_include(<FS.h>)
|
||||
#endif // defined __has_include
|
||||
|
||||
// USE_UTF8_LONG_NAMES must be non-zero in SdFat/src/SdFatCongfig.h
|
||||
#if USE_UTF8_LONG_NAMES
|
||||
|
||||
|
|
@ -11,10 +20,6 @@ const char* names[] = {u8"россиянин", u8"très élégant", u8"狗.txt",
|
|||
// Remove files if non-zero.
|
||||
#define REMOVE_UTF8_FILES 1
|
||||
|
||||
// SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h,
|
||||
// 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT.
|
||||
#define SD_FAT_TYPE 0
|
||||
|
||||
// SDCARD_SS_PIN is defined for the built-in SD on some boards.
|
||||
#ifndef SDCARD_SS_PIN
|
||||
const uint8_t SD_CS_PIN = SS;
|
||||
|
|
@ -24,13 +29,16 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
|
|||
#endif // SDCARD_SS_PIN
|
||||
|
||||
// Try to select the best SD card configuration.
|
||||
#if HAS_SDIO_CLASS
|
||||
#if defined(HAS_TEENSY_SDIO)
|
||||
#define SD_CONFIG SdioConfig(FIFO_SDIO)
|
||||
#elif defined(RP_CLK_GPIO) && defined(RP_CMD_GPIO) && defined(RP_DAT0_GPIO)
|
||||
// See the Rp2040SdioSetup example for RP2040/RP2350 boards.
|
||||
#define SD_CONFIG SdioConfig(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO)
|
||||
#elif ENABLE_DEDICATED_SPI
|
||||
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SD_SCK_MHZ(16))
|
||||
#else // HAS_SDIO_CLASS
|
||||
#else // HAS_TEENSY_SDIO
|
||||
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SD_SCK_MHZ(16))
|
||||
#endif // HAS_SDIO_CLASS
|
||||
#endif // HAS_TEENSY_SDIO
|
||||
|
||||
#if SD_FAT_TYPE == 0
|
||||
SdFat sd;
|
||||
|
|
|
|||
|
|
@ -1,13 +1,22 @@
|
|||
/*
|
||||
* This program is a simple binary write/read benchmark.
|
||||
*/
|
||||
#define DISABLE_FS_H_WARNING // Disable warning for type File not defined.
|
||||
#include "SdFat.h"
|
||||
#include "FreeStack.h"
|
||||
#include "sdios.h"
|
||||
|
||||
// SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h,
|
||||
// 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT.
|
||||
#define SD_FAT_TYPE 3
|
||||
#if defined __has_include
|
||||
#if __has_include(<FS.h>)
|
||||
#define SD_FAT_TYPE 3 // Can't use SdFat/File
|
||||
#endif // __has_include(<FS.h>)
|
||||
#endif // defined __has_include
|
||||
|
||||
#ifndef SD_FAT_TYPE
|
||||
#define SD_FAT_TYPE 0 // Use SdFat/File
|
||||
#endif // SD_FAT_TYPE
|
||||
/*
|
||||
Change the value of SD_CS_PIN if you are using SPI and
|
||||
your hardware does not use the default value, SS.
|
||||
|
|
@ -27,14 +36,24 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
|
|||
// Try max SPI clock for an SD. Reduce SPI_CLOCK if errors occur.
|
||||
#define SPI_CLOCK SD_SCK_MHZ(50)
|
||||
|
||||
// Example SDIO definition for RP2040/RP2350. See the Rp2040SdioSetup example.
|
||||
#if defined(ARDUINO_ADAFRUIT_METRO_RP2040) && !defined(RP_CLK_GPIO)
|
||||
#define RP_CLK_GPIO 18
|
||||
#define RP_CMD_GPIO 19
|
||||
#define RP_DAT0_GPIO 20 // DAT1: GPIO21, DAT2: GPIO22, DAT3: GPIO23.
|
||||
#endif // defined(ARDUINO_ADAFRUIT_METRO_RP2040)
|
||||
|
||||
// Try to select the best SD card configuration.
|
||||
#if HAS_SDIO_CLASS
|
||||
#if defined(HAS_TEENSY_SDIO)
|
||||
#define SD_CONFIG SdioConfig(FIFO_SDIO)
|
||||
#elif defined(RP_CLK_GPIO) && defined(RP_CMD_GPIO) && defined(RP_DAT0_GPIO)
|
||||
// See the Rp2040SdioSetup example for RP2040/RP2350 boards.
|
||||
#define SD_CONFIG SdioConfig(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO)
|
||||
#elif ENABLE_DEDICATED_SPI
|
||||
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
|
||||
#else // HAS_SDIO_CLASS
|
||||
#else // HAS_TEENSY_SDIO
|
||||
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
|
||||
#endif // HAS_SDIO_CLASS
|
||||
#endif // HAS_TEENSY_SDIO
|
||||
|
||||
// Set PRE_ALLOCATE true to pre-allocate file clusters.
|
||||
const bool PRE_ALLOCATE = true;
|
||||
|
|
@ -128,6 +147,11 @@ void setup() {
|
|||
"\nSet ENABLE_DEDICATED_SPI nonzero in\n"
|
||||
"SdFatConfig.h for best SPI performance.\n");
|
||||
}
|
||||
if (!SD_HAS_CUSTOM_SPI && !USE_SPI_ARRAY_TRANSFER && isSpi(SD_CONFIG)) {
|
||||
cout << F(
|
||||
"\nSetting USE_SPI_ARRAY_TRANSFER nonzero in\n"
|
||||
"SdFatConfig.h may improve SPI performance.\n");
|
||||
}
|
||||
// use uppercase in hex and use 0X base prefix
|
||||
cout << uppercase << showbase << endl;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* This program demonstrates use of rename().
|
||||
*/
|
||||
#define DISABLE_FS_H_WARNING // Disable warning for type File not defined.
|
||||
#include "SdFat.h"
|
||||
#include "sdios.h"
|
||||
|
||||
|
|
@ -29,13 +30,16 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
|
|||
#define SPI_CLOCK SD_SCK_MHZ(50)
|
||||
|
||||
// Try to select the best SD card configuration.
|
||||
#if HAS_SDIO_CLASS
|
||||
#if defined(HAS_TEENSY_SDIO)
|
||||
#define SD_CONFIG SdioConfig(FIFO_SDIO)
|
||||
#elif defined(RP_CLK_GPIO) && defined(RP_CMD_GPIO) && defined(RP_DAT0_GPIO)
|
||||
// See the Rp2040SdioSetup example for RP2040/RP2350 boards.
|
||||
#define SD_CONFIG SdioConfig(RP_CLK_GPIO, RP_CMD_GPIO, RP_DAT0_GPIO)
|
||||
#elif ENABLE_DEDICATED_SPI
|
||||
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
|
||||
#else // HAS_SDIO_CLASS
|
||||
#else // HAS_TEENSY_SDIO
|
||||
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
|
||||
#endif // HAS_SDIO_CLASS
|
||||
#endif // HAS_TEENSY_SDIO
|
||||
|
||||
#if SD_FAT_TYPE == 0
|
||||
SdFat sd;
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
sh cpplint.sh
|
||||
bash cpplint.sh
|
||||
pause
|
||||
2236
extras/cpplint.py
vendored
2236
extras/cpplint.py
vendored
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,2 @@
|
|||
#!/bin/sh
|
||||
export PATH=/cygdrive/c/Python27:/cygdrive/c/Python27/DLLs:/cygdrive/c/Python27/Scripts:$PATH
|
||||
echo $PATH
|
||||
python cpplint.py --filter=-build/include,-runtime/references,-build/header_guard ../src/*.* ../src/*/*.* 2>cpplint.txt
|
||||
#! /usr/bin/bash
|
||||
./cpplint.py ../src/*.cpp ../src/*.h ../src/*/*.cpp ../src/*/*.h ../src/SdCard/*/*.cpp ../src/SdCard/*/*.h 2>cpplint.txt
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
pause
|
||||
clang-format --style=Google -i *.cpp *.h
|
||||
rem clang-format --style=Google -i DigitalIO/*.h
|
||||
rem clang-format --style=Google -i DigitalIO/boards/*.h
|
||||
|
|
@ -7,5 +8,6 @@ clang-format --style=Google -i FatLib/*.cpp FatLib/*.h
|
|||
clang-format --style=Google -i FsLib/*.cpp FsLib/*.h
|
||||
clang-format --style=Google -i iostream/*.cpp iostream/*.h
|
||||
clang-format --style=Google -i SdCard/*.cpp SdCard/*.h
|
||||
clang-format --style=Google -i SdCard/*/*.cpp SdCard/*/*.h
|
||||
clang-format --style=Google -i SpiDriver/*.cpp SpiDriver/*.h
|
||||
pause
|
||||
|
|
|
|||
BIN
images/SdioSpi.jpg
Normal file
BIN
images/SdioSpi.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 331 KiB |
BIN
images/picowbell.jpg
Normal file
BIN
images/picowbell.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 235 KiB |
|
|
@ -1,5 +1,5 @@
|
|||
name=SdFat
|
||||
version=2.2.3
|
||||
version=2.3.0
|
||||
license=MIT
|
||||
author=Bill Greiman <fat16lib@sbcglobal.net>
|
||||
maintainer=Bill Greiman <fat16lib@sbcglobal.net>
|
||||
|
|
|
|||
1
src/.clang-format-ignore
Normal file
1
src/.clang-format-ignore
Normal file
|
|
@ -0,0 +1 @@
|
|||
SdCard/Rp2040Sdio/PioSdioCard.pio.h
|
||||
3
src/CPPLINT.cfg
Normal file
3
src/CPPLINT.cfg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
filter=-build/include,-runtime/references,-build/header_guard
|
||||
filter=-whitespace/indent_namespace
|
||||
exclude_files=SdFatDebugConfig.h
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -33,7 +33,7 @@ static void printHex(print_t* pr, uint32_t val);
|
|||
static void printHex64(print_t* pr, uint64_t n);
|
||||
static void println64(print_t* pr, uint64_t n);
|
||||
//------------------------------------------------------------------------------
|
||||
static void dmpDirData(print_t* pr, DirGeneric_t* dir) {
|
||||
static void dmpDirData(print_t* pr, const DirGeneric_t* dir) {
|
||||
for (uint8_t k = 0; k < 31; k++) {
|
||||
if (k) {
|
||||
pr->write(' ');
|
||||
|
|
@ -53,7 +53,7 @@ static uint16_t exFatDirChecksum(const void* dir, uint16_t checksum) {
|
|||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static uint16_t hashDir(DirName_t* dir, uint16_t hash) {
|
||||
static uint16_t hashDir(const DirName_t* dir, uint16_t hash) {
|
||||
for (uint8_t i = 0; i < 30; i += 2) {
|
||||
uint16_t u = getLe16(dir->unicode + i);
|
||||
if (!u) {
|
||||
|
|
@ -266,7 +266,7 @@ static void println64(print_t* pr, uint64_t n) {
|
|||
pr->println(str);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static void printMbr(print_t* pr, MbrSector_t* mbr) {
|
||||
static void printMbr(print_t* pr, const MbrSector_t* mbr) {
|
||||
pr->print(F("mbrSig: 0x"));
|
||||
pr->println(getLe16(mbr->signature), HEX);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
|
|
@ -299,7 +299,7 @@ void ExFatPartition::checkUpcase(print_t* pr) {
|
|||
pr->println(F("read root failed"));
|
||||
return;
|
||||
}
|
||||
DirUpcase_t* dir = reinterpret_cast<DirUpcase_t*>(cache);
|
||||
const DirUpcase_t* dir = reinterpret_cast<DirUpcase_t*>(cache);
|
||||
|
||||
pr->println(F("\nChecking upcase table"));
|
||||
for (size_t i = 0; i < 16; i++) {
|
||||
|
|
@ -383,7 +383,7 @@ void ExFatPartition::dmpFat(print_t* pr, uint32_t start, uint32_t count) {
|
|||
pr->println(F("cache read failed"));
|
||||
return;
|
||||
}
|
||||
uint32_t* fat = reinterpret_cast<uint32_t*>(cache);
|
||||
const uint32_t* fat = reinterpret_cast<uint32_t*>(cache);
|
||||
for (size_t k = 0; k < 128; k++) {
|
||||
if (0 == cluster % 8) {
|
||||
if (k) {
|
||||
|
|
@ -400,7 +400,7 @@ void ExFatPartition::dmpFat(print_t* pr, uint32_t start, uint32_t count) {
|
|||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void ExFatPartition::dmpSector(print_t* pr, uint32_t sector) {
|
||||
uint8_t* cache = dataCachePrepare(sector, FsCache::CACHE_FOR_READ);
|
||||
const uint8_t* cache = dataCachePrepare(sector, FsCache::CACHE_FOR_READ);
|
||||
if (!cache) {
|
||||
pr->println(F("dmpSector failed"));
|
||||
return;
|
||||
|
|
@ -553,7 +553,7 @@ void ExFatPartition::printUpcase(print_t* pr) {
|
|||
uint32_t sector;
|
||||
uint32_t size = 0;
|
||||
uint32_t checksum = 0;
|
||||
DirUpcase_t* dir;
|
||||
const DirUpcase_t* dir;
|
||||
sector = clusterStartSector(m_rootDirectoryCluster);
|
||||
upcase = dataCachePrepare(sector, FsCache::CACHE_FOR_READ);
|
||||
dir = reinterpret_cast<DirUpcase_t*>(upcase);
|
||||
|
|
@ -601,7 +601,7 @@ bool ExFatPartition::printVolInfo(print_t* pr) {
|
|||
pr->println(F("read mbr failed"));
|
||||
return false;
|
||||
}
|
||||
MbrSector_t* mbr = reinterpret_cast<MbrSector_t*>(cache);
|
||||
const MbrSector_t* mbr = reinterpret_cast<MbrSector_t*>(cache);
|
||||
printMbr(pr, mbr);
|
||||
uint32_t volStart = getLe32(mbr->part->relativeSectors);
|
||||
uint32_t volSize = getLe32(mbr->part->totalSectors);
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ void ExFatFile::fgetpos(fspos_t* pos) const {
|
|||
pos->cluster = m_curCluster;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int ExFatFile::fgets(char* str, int num, char* delim) {
|
||||
int ExFatFile::fgets(char* str, int num, const char* delim) {
|
||||
char ch;
|
||||
int n = 0;
|
||||
int r = -1;
|
||||
|
|
@ -136,7 +136,7 @@ void ExFatFile::fsetpos(const fspos_t* pos) {
|
|||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool ExFatFile::getAccessDateTime(uint16_t* pdate, uint16_t* ptime) {
|
||||
DirFile_t* df = reinterpret_cast<DirFile_t*>(
|
||||
const DirFile_t* df = reinterpret_cast<DirFile_t*>(
|
||||
m_vol->dirCache(&m_dirPos, FsCache::CACHE_FOR_READ));
|
||||
if (!df) {
|
||||
DBG_FAIL_MACRO;
|
||||
|
|
@ -151,7 +151,7 @@ fail:
|
|||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool ExFatFile::getCreateDateTime(uint16_t* pdate, uint16_t* ptime) {
|
||||
DirFile_t* df = reinterpret_cast<DirFile_t*>(
|
||||
const DirFile_t* df = reinterpret_cast<DirFile_t*>(
|
||||
m_vol->dirCache(&m_dirPos, FsCache::CACHE_FOR_READ));
|
||||
if (!df) {
|
||||
DBG_FAIL_MACRO;
|
||||
|
|
@ -166,7 +166,7 @@ fail:
|
|||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool ExFatFile::getModifyDateTime(uint16_t* pdate, uint16_t* ptime) {
|
||||
DirFile_t* df = reinterpret_cast<DirFile_t*>(
|
||||
const DirFile_t* df = reinterpret_cast<DirFile_t*>(
|
||||
m_vol->dirCache(&m_dirPos, FsCache::CACHE_FOR_READ));
|
||||
if (!df) {
|
||||
DBG_FAIL_MACRO;
|
||||
|
|
@ -223,7 +223,6 @@ bool ExFatFile::open(ExFatFile* dirFile, const char* path, oflag_t oflag) {
|
|||
DBG_WARN_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// tmpDir = *this;
|
||||
tmpDir.copy(this);
|
||||
dirFile = &tmpDir;
|
||||
close();
|
||||
|
|
@ -255,7 +254,6 @@ bool ExFatFile::openCwd() {
|
|||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// *this = *ExFatVolume::cwv()->vwd();
|
||||
this->copy(ExFatVolume::cwv()->vwd());
|
||||
rewind();
|
||||
return true;
|
||||
|
|
@ -633,7 +631,7 @@ int ExFatFile::read(void* buf, size_t count) {
|
|||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
uint8_t* src = cache + sectorOffset;
|
||||
const uint8_t* src = cache + sectorOffset;
|
||||
memcpy(dst, src, n);
|
||||
#if USE_MULTI_SECTOR_IO
|
||||
} else if (toRead >= 2 * m_vol->bytesPerSector()) {
|
||||
|
|
|
|||
|
|
@ -22,8 +22,7 @@
|
|||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef ExFatFile_h
|
||||
#define ExFatFile_h
|
||||
#pragma once
|
||||
/**
|
||||
* \file
|
||||
* \brief ExFatFile class
|
||||
|
|
@ -247,7 +246,7 @@ class ExFatFile {
|
|||
* If no data is read, fgets() returns zero for EOF or -1 if an error
|
||||
* occurred.
|
||||
*/
|
||||
int fgets(char* str, int num, char* delim = nullptr);
|
||||
int fgets(char* str, int num, const char* delim = nullptr);
|
||||
/** \return The total number of bytes in a file. */
|
||||
uint64_t fileSize() const { return m_validLength; }
|
||||
/** \return Address of first sector or zero for empty file. */
|
||||
|
|
@ -898,4 +897,3 @@ class ExFile : public StreamFile<ExFatFile, uint64_t> {
|
|||
return tmpFile;
|
||||
}
|
||||
};
|
||||
#endif // ExFatFile_h
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -143,7 +143,7 @@ size_t ExFatFile::printModifyDateTime(print_t* pr) {
|
|||
}
|
||||
//------------------------------------------------------------------------------
|
||||
size_t ExFatFile::printName7(print_t* pr) {
|
||||
DirName_t* dn;
|
||||
const DirName_t* dn;
|
||||
size_t n = 0;
|
||||
uint8_t in;
|
||||
uint8_t buf[15];
|
||||
|
|
@ -174,7 +174,7 @@ fail:
|
|||
}
|
||||
//------------------------------------------------------------------------------
|
||||
size_t ExFatFile::printName8(print_t* pr) {
|
||||
DirName_t* dn;
|
||||
const DirName_t* dn;
|
||||
uint16_t hs = 0;
|
||||
uint32_t cp;
|
||||
size_t n = 0;
|
||||
|
|
@ -211,7 +211,7 @@ size_t ExFatFile::printName8(print_t* pr) {
|
|||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
char* str = FsUtf::cpToMb(cp, buf, buf + sizeof(buf));
|
||||
const char* str = FsUtf::cpToMb(cp, buf, buf + sizeof(buf));
|
||||
if (!str) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
|
|
|
|||
|
|
@ -179,7 +179,6 @@ bool ExFatFile::mkdir(ExFatFile* parent, const char* path, bool pFlag) {
|
|||
goto fail;
|
||||
}
|
||||
}
|
||||
// tmpDir = *this;
|
||||
tmpDir.copy(this);
|
||||
parent = &tmpDir;
|
||||
close();
|
||||
|
|
@ -313,7 +312,6 @@ bool ExFatFile::rename(ExFatFile* dirFile, const char* newPath) {
|
|||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// oldFile = *this;
|
||||
oldFile.copy(this);
|
||||
m_dirPos = file.m_dirPos;
|
||||
m_setCount = file.m_setCount;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -22,8 +22,7 @@
|
|||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef ExFatFormatter_h
|
||||
#define ExFatFormatter_h
|
||||
#pragma once
|
||||
#include "../common/FsBlockDevice.h"
|
||||
/**
|
||||
* \class ExFatFormatter
|
||||
|
|
@ -32,7 +31,7 @@
|
|||
class ExFatFormatter {
|
||||
public:
|
||||
/** Constructor. */
|
||||
ExFatFormatter() = default;
|
||||
ExFatFormatter() = default; // cppcheck-suppress uninitMemberVar
|
||||
/**
|
||||
* Format an exFAT volume.
|
||||
*
|
||||
|
|
@ -55,4 +54,3 @@ class ExFatFormatter {
|
|||
FsBlockDevice* m_dev;
|
||||
uint8_t* m_secBuf;
|
||||
};
|
||||
#endif // ExFatFormatter_h
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -66,7 +66,7 @@ bool ExFatFile::cmpName(const DirName_t* dirName, ExName_t* fname) {
|
|||
}
|
||||
//------------------------------------------------------------------------------
|
||||
size_t ExFatFile::getName7(char* name, size_t count) {
|
||||
DirName_t* dn;
|
||||
const DirName_t* dn;
|
||||
size_t n = 0;
|
||||
if (!isOpen()) {
|
||||
DBG_FAIL_MACRO;
|
||||
|
|
@ -100,10 +100,10 @@ fail:
|
|||
}
|
||||
//------------------------------------------------------------------------------
|
||||
size_t ExFatFile::getName8(char* name, size_t count) {
|
||||
char* end = name + count;
|
||||
const char* end = name + count;
|
||||
char* str = name;
|
||||
char* ptr;
|
||||
DirName_t* dn;
|
||||
const DirName_t* dn;
|
||||
uint16_t hs = 0;
|
||||
uint32_t cp;
|
||||
if (!isOpen()) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -36,7 +36,7 @@ uint32_t ExFatPartition::bitmapFind(uint32_t cluster, uint32_t count) {
|
|||
uint32_t bgnAlloc = start;
|
||||
uint16_t sectorSize = 1 << m_bytesPerSectorShift;
|
||||
size_t i = (start >> 3) & (sectorSize - 1);
|
||||
uint8_t* cache;
|
||||
const uint8_t* cache;
|
||||
uint8_t mask = 1 << (start & 7);
|
||||
while (true) {
|
||||
uint32_t sector =
|
||||
|
|
@ -136,7 +136,7 @@ uint32_t ExFatPartition::chainSize(uint32_t cluster) {
|
|||
return n;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
uint8_t* ExFatPartition::dirCache(DirPos_t* pos, uint8_t options) {
|
||||
uint8_t* ExFatPartition::dirCache(const DirPos_t* pos, uint8_t options) {
|
||||
uint32_t sector = clusterStartSector(pos->cluster);
|
||||
sector += (m_clusterMask & pos->position) >> m_bytesPerSectorShift;
|
||||
uint8_t* cache = dataCachePrepare(sector, options);
|
||||
|
|
@ -164,7 +164,7 @@ int8_t ExFatPartition::dirSeek(DirPos_t* pos, uint32_t offset) {
|
|||
//------------------------------------------------------------------------------
|
||||
// return -1 error, 0 EOC, 1 OK
|
||||
int8_t ExFatPartition::fatGet(uint32_t cluster, uint32_t* value) {
|
||||
uint8_t* cache;
|
||||
const uint8_t* cache;
|
||||
uint32_t next;
|
||||
uint32_t sector;
|
||||
|
||||
|
|
@ -240,7 +240,7 @@ int32_t ExFatPartition::freeClusterCount() {
|
|||
uint32_t nc = 0;
|
||||
uint32_t sector = m_clusterHeapStartSector;
|
||||
uint32_t usedCount = 0;
|
||||
uint8_t* cache;
|
||||
const uint8_t* cache;
|
||||
|
||||
while (true) {
|
||||
cache = dataCachePrepare(sector++, FsCache::CACHE_FOR_READ);
|
||||
|
|
@ -267,8 +267,8 @@ int32_t ExFatPartition::freeClusterCount() {
|
|||
//------------------------------------------------------------------------------
|
||||
bool ExFatPartition::init(FsBlockDevice* dev, uint8_t part, uint32_t volStart) {
|
||||
pbs_t* pbs;
|
||||
BpbExFat_t* bpb;
|
||||
MbrSector_t* mbr;
|
||||
const BpbExFat_t* bpb;
|
||||
const MbrSector_t* mbr;
|
||||
m_fatType = 0;
|
||||
m_blockDev = dev;
|
||||
cacheInit(m_blockDev);
|
||||
|
|
@ -285,7 +285,7 @@ bool ExFatPartition::init(FsBlockDevice* dev, uint8_t part, uint32_t volStart) {
|
|||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
MbrPart_t* mp = mbr->part + part - 1;
|
||||
const MbrPart_t* mp = mbr->part + part - 1;
|
||||
if (mp->type == 0 || (mp->boot != 0 && mp->boot != 0X80)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -22,8 +22,7 @@
|
|||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef ExFatPartition_h
|
||||
#define ExFatPartition_h
|
||||
#pragma once
|
||||
/**
|
||||
* \file
|
||||
* \brief ExFatPartition include file.
|
||||
|
|
@ -60,7 +59,7 @@ struct DirPos_t {
|
|||
*/
|
||||
class ExFatPartition {
|
||||
public:
|
||||
ExFatPartition() = default;
|
||||
ExFatPartition() = default; // cppcheck-suppress uninitMemberVar
|
||||
/** \return the number of bytes in a cluster. */
|
||||
uint32_t bytesPerCluster() const { return m_bytesPerCluster; }
|
||||
/** \return the power of two for bytesPerCluster. */
|
||||
|
|
@ -177,7 +176,7 @@ class ExFatPartition {
|
|||
return m_clusterHeapStartSector +
|
||||
((cluster - 2) << m_sectorsPerClusterShift);
|
||||
}
|
||||
uint8_t* dirCache(DirPos_t* pos, uint8_t options);
|
||||
uint8_t* dirCache(const DirPos_t* pos, uint8_t options);
|
||||
int8_t dirSeek(DirPos_t* pos, uint32_t offset);
|
||||
int8_t fatGet(uint32_t cluster, uint32_t* value);
|
||||
bool fatPut(uint32_t cluster, uint32_t value);
|
||||
|
|
@ -224,4 +223,3 @@ class ExFatPartition {
|
|||
uint8_t m_fatType = 0;
|
||||
uint8_t m_sectorsPerClusterShift;
|
||||
};
|
||||
#endif // ExFatPartition_h
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ bool ExFatVolume::chdir(const char* path) {
|
|||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// m_vwd = dir;
|
||||
m_vwd.copy(&dir);
|
||||
return true;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
#include "FatLib.h"
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
//------------------------------------------------------------------------------
|
||||
static uint16_t getLfnChar(DirLfn_t* ldir, uint8_t i) {
|
||||
static uint16_t getLfnChar(const DirLfn_t* ldir, uint8_t i) {
|
||||
if (i < 5) {
|
||||
return getLe16(ldir->unicode1 + 2 * i);
|
||||
} else if (i < 11) {
|
||||
|
|
@ -245,7 +245,7 @@ void FatPartition::dmpFat(print_t* pr, uint32_t start, uint32_t count) {
|
|||
uint32_t sector = m_fatStartSector + start;
|
||||
uint32_t cluster = nf * start;
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
uint8_t* pc = fatCachePrepare(sector + i, FsCache::CACHE_FOR_READ);
|
||||
const uint8_t* pc = fatCachePrepare(sector + i, FsCache::CACHE_FOR_READ);
|
||||
if (!pc) {
|
||||
pr->println(F("cache read failed"));
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ fail:
|
|||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool FatFile::dirEntry(DirFat_t* dst) {
|
||||
DirFat_t* dir;
|
||||
const DirFat_t* dir;
|
||||
// Make sure fields on device are correct.
|
||||
if (!sync()) {
|
||||
DBG_FAIL_MACRO;
|
||||
|
|
@ -237,7 +237,7 @@ uint32_t FatFile::dirSize() {
|
|||
return 512UL * n;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int FatFile::fgets(char* str, int num, char* delim) {
|
||||
int FatFile::fgets(char* str, int num, const char* delim) {
|
||||
char ch;
|
||||
int n = 0;
|
||||
int r = -1;
|
||||
|
|
@ -354,7 +354,6 @@ bool FatFile::mkdir(FatFile* parent, const char* path, bool pFlag) {
|
|||
goto fail;
|
||||
}
|
||||
}
|
||||
// tmpDir = *this;
|
||||
tmpDir.copy(this);
|
||||
parent = &tmpDir;
|
||||
close();
|
||||
|
|
@ -478,7 +477,6 @@ bool FatFile::open(FatFile* dirFile, const char* path, oflag_t oflag) {
|
|||
DBG_WARN_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// tmpDir = *this;
|
||||
tmpDir.copy(this);
|
||||
dirFile = &tmpDir;
|
||||
close();
|
||||
|
|
@ -497,7 +495,7 @@ bool FatFile::open(uint16_t index, oflag_t oflag) {
|
|||
bool FatFile::open(FatFile* dirFile, uint16_t index, oflag_t oflag) {
|
||||
if (index) {
|
||||
// Find start of LFN.
|
||||
DirLfn_t* ldir;
|
||||
const DirLfn_t* ldir;
|
||||
uint8_t n = index < 20 ? index : 20;
|
||||
for (uint8_t i = 1; i <= n; i++) {
|
||||
ldir = reinterpret_cast<DirLfn_t*>(dirFile->cacheDir(index - i));
|
||||
|
|
@ -634,7 +632,6 @@ bool FatFile::openCwd() {
|
|||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// *this = *FatVolume::cwv()->vwd();
|
||||
this->copy(FatVolume::cwv()->vwd());
|
||||
rewind();
|
||||
return true;
|
||||
|
|
@ -645,7 +642,7 @@ fail:
|
|||
//------------------------------------------------------------------------------
|
||||
bool FatFile::openNext(FatFile* dirFile, oflag_t oflag) {
|
||||
uint8_t checksum = 0;
|
||||
DirLfn_t* ldir;
|
||||
const DirLfn_t* ldir;
|
||||
uint8_t lfnOrd = 0;
|
||||
uint16_t index;
|
||||
|
||||
|
|
@ -840,7 +837,7 @@ int FatFile::read(void* buf, size_t nbyte) {
|
|||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
uint8_t* src = pc + offset;
|
||||
const uint8_t* src = pc + offset;
|
||||
memcpy(dst, src, n);
|
||||
#if USE_MULTI_SECTOR_IO
|
||||
} else if (toRead >= 2 * m_vol->bytesPerSector()) {
|
||||
|
|
@ -968,7 +965,6 @@ bool FatFile::rename(FatFile* dirFile, const char* newPath) {
|
|||
}
|
||||
// sync() and cache directory entry
|
||||
sync();
|
||||
// oldFile = *this;
|
||||
oldFile.copy(this);
|
||||
dir = cacheDirEntry(FsCache::CACHE_FOR_READ);
|
||||
if (!dir) {
|
||||
|
|
@ -1064,7 +1060,7 @@ bool FatFile::rmdir() {
|
|||
|
||||
// make sure directory is empty
|
||||
while (1) {
|
||||
DirFat_t* dir = readDirCache(true);
|
||||
const DirFat_t* dir = readDirCache(true);
|
||||
if (!dir) {
|
||||
// EOF if no error.
|
||||
if (!getError()) {
|
||||
|
|
@ -1108,7 +1104,7 @@ bool FatFile::rmRfStar() {
|
|||
// remember position
|
||||
index = m_curPosition / FS_DIR_SIZE;
|
||||
|
||||
DirFat_t* dir = readDirCache();
|
||||
const DirFat_t* dir = readDirCache();
|
||||
if (!dir) {
|
||||
// At EOF if no error.
|
||||
if (!getError()) {
|
||||
|
|
|
|||
|
|
@ -22,8 +22,7 @@
|
|||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef FatFile_h
|
||||
#define FatFile_h
|
||||
#pragma once
|
||||
/**
|
||||
* \file
|
||||
* \brief FatFile class
|
||||
|
|
@ -330,7 +329,7 @@ class FatFile {
|
|||
* If no data is read, fgets() returns zero for EOF or -1 if an error
|
||||
* occurred.
|
||||
*/
|
||||
int fgets(char* str, int num, char* delim = nullptr);
|
||||
int fgets(char* str, int num, const char* delim = nullptr);
|
||||
/** \return The total number of bytes in a file. */
|
||||
uint32_t fileSize() const { return m_fileSize; }
|
||||
/** \return first sector of file or zero for empty file. */
|
||||
|
|
@ -1030,7 +1029,7 @@ class FatFile {
|
|||
DirFat_t* cacheDirEntry(uint8_t action);
|
||||
bool cmpName(uint16_t index, FatLfn_t* fname, uint8_t lfnOrd);
|
||||
bool createLFN(uint16_t index, FatLfn_t* fname, uint8_t lfnOrd);
|
||||
uint16_t getLfnChar(DirLfn_t* ldir, uint8_t i);
|
||||
uint16_t getLfnChar(const DirLfn_t* ldir, uint8_t i);
|
||||
uint8_t lfnChecksum(const uint8_t* name) {
|
||||
uint8_t sum = 0;
|
||||
for (uint8_t i = 0; i < 11; i++) {
|
||||
|
|
@ -1045,8 +1044,8 @@ class FatFile {
|
|||
bool parsePathName(const char* str, FatSfn_t* fname, const char** ptr);
|
||||
bool mkdir(FatFile* parent, FatName_t* fname);
|
||||
bool open(FatFile* dirFile, FatLfn_t* fname, oflag_t oflag);
|
||||
bool open(FatFile* dirFile, FatSfn_t* fname, oflag_t oflag);
|
||||
bool openSFN(FatSfn_t* fname);
|
||||
bool open(FatFile* dirFile, const FatSfn_t* fname, oflag_t oflag);
|
||||
bool openSFN(const FatSfn_t* fname);
|
||||
bool openCachedEntry(FatFile* dirFile, uint16_t cacheIndex, oflag_t oflag,
|
||||
uint8_t lfnOrd);
|
||||
DirFat_t* readDirCache(bool skipReadOk = false);
|
||||
|
|
@ -1098,4 +1097,3 @@ class File32 : public StreamFile<FatFile, uint32_t> {
|
|||
return tmpFile;
|
||||
}
|
||||
};
|
||||
#endif // FatFile_h
|
||||
|
|
|
|||
|
|
@ -54,10 +54,9 @@ static void putLfnChar(DirLfn_t* ldir, uint8_t i, uint16_t c) {
|
|||
}
|
||||
//==============================================================================
|
||||
bool FatFile::cmpName(uint16_t index, FatLfn_t* fname, uint8_t lfnOrd) {
|
||||
// FatFile dir = *this;
|
||||
FatFile dir;
|
||||
dir.copy(this);
|
||||
DirLfn_t* ldir;
|
||||
const DirLfn_t* ldir;
|
||||
fname->reset();
|
||||
for (uint8_t order = 1; order <= lfnOrd; order++) {
|
||||
ldir = reinterpret_cast<DirLfn_t*>(dir.cacheDir(index - order));
|
||||
|
|
@ -94,7 +93,6 @@ fail:
|
|||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool FatFile::createLFN(uint16_t index, FatLfn_t* fname, uint8_t lfnOrd) {
|
||||
// FatFile dir = *this;
|
||||
FatFile dir;
|
||||
dir.copy(this);
|
||||
DirLfn_t* ldir;
|
||||
|
|
@ -220,7 +218,7 @@ fail:
|
|||
bool FatFile::makeUniqueSfn(FatLfn_t* fname) {
|
||||
const uint8_t FIRST_HASH_SEQ = 2; // min value is 2
|
||||
uint8_t pos = fname->seqPos;
|
||||
DirFat_t* dir;
|
||||
const DirFat_t* dir;
|
||||
uint16_t hex = 0;
|
||||
|
||||
DBG_HALT_IF(!(fname->flags & FNAME_FLAG_LOST_CHARS));
|
||||
|
|
@ -284,7 +282,7 @@ bool FatFile::open(FatFile* dirFile, FatLfn_t* fname, oflag_t oflag) {
|
|||
uint16_t freeTotal;
|
||||
uint16_t time;
|
||||
DirFat_t* dir;
|
||||
DirLfn_t* ldir;
|
||||
const DirLfn_t* ldir;
|
||||
auto vol = dirFile->m_vol;
|
||||
|
||||
if (!dirFile->isDir() || isOpen()) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// open with filename in fname
|
||||
#define SFN_OPEN_USES_CHKSUM 0
|
||||
bool FatFile::open(FatFile* dirFile, FatSfn_t* fname, oflag_t oflag) {
|
||||
bool FatFile::open(FatFile* dirFile, const FatSfn_t* fname, oflag_t oflag) {
|
||||
uint16_t date;
|
||||
uint16_t time;
|
||||
uint8_t ms10;
|
||||
|
|
@ -40,7 +40,7 @@ bool FatFile::open(FatFile* dirFile, FatSfn_t* fname, oflag_t oflag) {
|
|||
uint16_t emptyIndex = 0;
|
||||
uint16_t index = 0;
|
||||
DirFat_t* dir;
|
||||
DirLfn_t* ldir;
|
||||
const DirLfn_t* ldir;
|
||||
|
||||
dirFile->rewind();
|
||||
while (true) {
|
||||
|
|
@ -156,7 +156,6 @@ bool FatFile::openExistingSFN(const char* path) {
|
|||
if (*path == 0) {
|
||||
return openRoot(vol);
|
||||
}
|
||||
// *this = *vol->vwd();
|
||||
this->copy(vol->vwd());
|
||||
do {
|
||||
if (!parsePathName(path, &fname, &path)) {
|
||||
|
|
@ -174,9 +173,9 @@ fail:
|
|||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool FatFile::openSFN(FatSfn_t* fname) {
|
||||
bool FatFile::openSFN(const FatSfn_t* fname) {
|
||||
DirFat_t dir;
|
||||
DirLfn_t* ldir;
|
||||
const DirLfn_t* ldir;
|
||||
auto vol = m_vol;
|
||||
uint8_t lfnOrd = 0;
|
||||
if (!isDir()) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -22,8 +22,7 @@
|
|||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef FatFormatter_h
|
||||
#define FatFormatter_h
|
||||
#pragma once
|
||||
#include "../common/FsBlockDevice.h"
|
||||
#include "../common/SysCall.h"
|
||||
/**
|
||||
|
|
@ -33,7 +32,7 @@
|
|||
class FatFormatter {
|
||||
public:
|
||||
/** Constructor. */
|
||||
FatFormatter() = default;
|
||||
FatFormatter() = default; // cppcheck-suppress uninitMemberVar
|
||||
/**
|
||||
* Format a FAT volume.
|
||||
*
|
||||
|
|
@ -65,4 +64,3 @@ class FatFormatter {
|
|||
uint8_t m_partType;
|
||||
uint8_t m_sectorsPerCluster;
|
||||
};
|
||||
#endif // FatFormatter_h
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -22,8 +22,6 @@
|
|||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef FatLib_h
|
||||
#define FatLib_h
|
||||
#pragma once
|
||||
#include "FatFormatter.h"
|
||||
#include "FatVolume.h"
|
||||
#endif // FatLib_h
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
#include "../common/FsUtf.h"
|
||||
#include "FatLib.h"
|
||||
//------------------------------------------------------------------------------
|
||||
uint16_t FatFile::getLfnChar(DirLfn_t* ldir, uint8_t i) {
|
||||
uint16_t FatFile::getLfnChar(const DirLfn_t* ldir, uint8_t i) {
|
||||
if (i < 5) {
|
||||
return getLe16(ldir->unicode1 + 2 * i);
|
||||
} else if (i < 11) {
|
||||
|
|
@ -51,7 +51,7 @@ size_t FatFile::getName(char* name, size_t size) {
|
|||
//------------------------------------------------------------------------------
|
||||
size_t FatFile::getName7(char* name, size_t size) {
|
||||
FatFile dir;
|
||||
DirLfn_t* ldir;
|
||||
const DirLfn_t* ldir;
|
||||
size_t n = 0;
|
||||
if (!isOpen()) {
|
||||
DBG_FAIL_MACRO;
|
||||
|
|
@ -97,11 +97,11 @@ fail:
|
|||
}
|
||||
//------------------------------------------------------------------------------
|
||||
size_t FatFile::getName8(char* name, size_t size) {
|
||||
char* end = name + size;
|
||||
const char* end = name + size;
|
||||
char* str = name;
|
||||
char* ptr;
|
||||
FatFile dir;
|
||||
DirLfn_t* ldir;
|
||||
const DirLfn_t* ldir;
|
||||
uint16_t hs = 0;
|
||||
uint32_t cp;
|
||||
if (!isOpen()) {
|
||||
|
|
@ -169,8 +169,8 @@ size_t FatFile::getSFN(char* name, size_t size) {
|
|||
char c;
|
||||
uint8_t j = 0;
|
||||
uint8_t lcBit = FAT_CASE_LC_BASE;
|
||||
uint8_t* ptr;
|
||||
DirFat_t* dir;
|
||||
const uint8_t* ptr;
|
||||
const DirFat_t* dir;
|
||||
if (!isOpen()) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
|
|
@ -234,7 +234,7 @@ size_t FatFile::printName(print_t* pr) {
|
|||
//------------------------------------------------------------------------------
|
||||
size_t FatFile::printName7(print_t* pr) {
|
||||
FatFile dir;
|
||||
DirLfn_t* ldir;
|
||||
const DirLfn_t* ldir;
|
||||
size_t n = 0;
|
||||
uint8_t buf[13];
|
||||
uint8_t i;
|
||||
|
|
@ -280,12 +280,12 @@ fail:
|
|||
//------------------------------------------------------------------------------
|
||||
size_t FatFile::printName8(print_t* pr) {
|
||||
FatFile dir;
|
||||
DirLfn_t* ldir;
|
||||
const DirLfn_t* ldir;
|
||||
uint16_t hs = 0;
|
||||
uint32_t cp;
|
||||
size_t n = 0;
|
||||
char buf[5];
|
||||
char* end = buf + sizeof(buf);
|
||||
const char* end = buf + sizeof(buf);
|
||||
if (!isOpen()) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
|
|
@ -329,7 +329,7 @@ size_t FatFile::printName8(print_t* pr) {
|
|||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
char* str = FsUtf::cpToMb(cp, buf, end);
|
||||
const char* str = FsUtf::cpToMb(cp, buf, end);
|
||||
if (!str) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -157,7 +157,7 @@ fail:
|
|||
int8_t FatPartition::fatGet(uint32_t cluster, uint32_t* value) {
|
||||
uint32_t sector;
|
||||
uint32_t next;
|
||||
uint8_t* pc;
|
||||
const uint8_t* pc;
|
||||
|
||||
// error if reserved cluster of beyond FAT
|
||||
if (cluster < 2 || cluster > m_lastCluster) {
|
||||
|
|
@ -362,14 +362,14 @@ int32_t FatPartition::freeClusterCount() {
|
|||
n = todo;
|
||||
}
|
||||
if (fatType() == 16) {
|
||||
uint16_t* p16 = reinterpret_cast<uint16_t*>(pc);
|
||||
const uint16_t* p16 = reinterpret_cast<uint16_t*>(pc);
|
||||
for (uint16_t i = 0; i < n; i++) {
|
||||
if (p16[i] == 0) {
|
||||
free++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uint32_t* p32 = reinterpret_cast<uint32_t*>(pc);
|
||||
const uint32_t* p32 = reinterpret_cast<uint32_t*>(pc);
|
||||
for (uint16_t i = 0; i < n; i++) {
|
||||
if (p32[i] == 0) {
|
||||
free++;
|
||||
|
|
@ -395,8 +395,8 @@ bool FatPartition::init(FsBlockDevice* dev, uint8_t part, uint32_t volStart) {
|
|||
uint32_t totalSectors;
|
||||
m_blockDev = dev;
|
||||
pbs_t* pbs;
|
||||
BpbFat32_t* bpb;
|
||||
MbrSector_t* mbr;
|
||||
const BpbFat32_t* bpb;
|
||||
const MbrSector_t* mbr;
|
||||
uint8_t tmp;
|
||||
m_fatType = 0;
|
||||
m_allocSearchStart = 1;
|
||||
|
|
@ -417,7 +417,7 @@ bool FatPartition::init(FsBlockDevice* dev, uint8_t part, uint32_t volStart) {
|
|||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
MbrPart_t* mp = mbr->part + part - 1;
|
||||
const MbrPart_t* mp = mbr->part + part - 1;
|
||||
if (mp->type == 0 || (mp->boot != 0 && mp->boot != 0X80)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -22,8 +22,7 @@
|
|||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef FatPartition_h
|
||||
#define FatPartition_h
|
||||
#pragma once
|
||||
/**
|
||||
* \file
|
||||
* \brief FatPartition class
|
||||
|
|
@ -53,7 +52,7 @@ class FatPartition {
|
|||
public:
|
||||
/** Create an instance of FatPartition
|
||||
*/
|
||||
FatPartition() = default;
|
||||
FatPartition() = default; // cppcheck-suppress uninitMemberVar
|
||||
|
||||
/** \return The shift count required to multiply by bytesPerCluster. */
|
||||
uint8_t bytesPerClusterShift() const {
|
||||
|
|
@ -235,4 +234,3 @@ class FatPartition {
|
|||
bool freeChain(uint32_t cluster);
|
||||
bool isEOC(uint32_t cluster) const { return cluster > m_lastCluster; }
|
||||
};
|
||||
#endif // FatPartition
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ bool FatVolume::chdir(const char* path) {
|
|||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// m_vwd = dir;
|
||||
m_vwd.copy(&dir);
|
||||
return true;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -22,8 +22,7 @@
|
|||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef FatVolume_h
|
||||
#define FatVolume_h
|
||||
#pragma once
|
||||
#include "FatFile.h"
|
||||
/**
|
||||
* \file
|
||||
|
|
@ -344,4 +343,3 @@ class FatVolume : public FatPartition {
|
|||
static FatVolume* m_cwv;
|
||||
FatFile m_vwd;
|
||||
};
|
||||
#endif // FatVolume_h
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -53,7 +53,7 @@ inline char* stackPointer() {
|
|||
const char FILL = 0x55;
|
||||
void FillStack() {
|
||||
char* p = stackBegin();
|
||||
char* top = stackPointer();
|
||||
const char* top = stackPointer();
|
||||
while (p < top) {
|
||||
*p++ = FILL;
|
||||
}
|
||||
|
|
@ -62,7 +62,7 @@ void FillStack() {
|
|||
// May fail if malloc or new is used.
|
||||
int UnusedStack() {
|
||||
char* h = stackBegin();
|
||||
char* top = stackPointer();
|
||||
const char* top = stackPointer();
|
||||
int n;
|
||||
|
||||
for (n = 0; (h + n) < top; n++) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -22,8 +22,7 @@
|
|||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef FreeStack_h
|
||||
#define FreeStack_h
|
||||
#pragma once
|
||||
/**
|
||||
* \file
|
||||
* \brief FreeStack() function.
|
||||
|
|
@ -41,7 +40,7 @@ extern char __bss_end;
|
|||
* \return The number of free bytes.
|
||||
*/
|
||||
inline int FreeStack() {
|
||||
char* sp = reinterpret_cast<char*>(SP);
|
||||
const char* sp = reinterpret_cast<char*>(SP);
|
||||
return __brkval ? sp - __brkval : sp - &__bss_end;
|
||||
}
|
||||
#elif defined(ARDUINO_ARCH_APOLLO3)
|
||||
|
|
@ -87,4 +86,3 @@ int UnusedStack();
|
|||
inline void FillStack() {}
|
||||
inline int UnusedStack() { return 0; }
|
||||
#endif // defined(HAS_UNUSED_STACK)
|
||||
#endif // FreeStack_h
|
||||
|
|
|
|||
|
|
@ -22,8 +22,7 @@
|
|||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef FsFile_h
|
||||
#define FsFile_h
|
||||
#pragma once
|
||||
/**
|
||||
* \file
|
||||
* \brief FsBaseFile include file.
|
||||
|
|
@ -39,7 +38,7 @@
|
|||
class FsBaseFile {
|
||||
public:
|
||||
/** Create an instance. */
|
||||
FsBaseFile() = default;
|
||||
FsBaseFile() = default; // cppcheck-suppress uninitMemberVar
|
||||
/** Create a file object and open it in the current working directory.
|
||||
*
|
||||
* \param[in] path A path for a file to be opened.
|
||||
|
|
@ -47,6 +46,7 @@ class FsBaseFile {
|
|||
* \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
|
||||
* OR of open flags. see FatFile::open(FatFile*, const char*, uint8_t).
|
||||
*/
|
||||
// cppcheck-suppress uninitMemberVar
|
||||
FsBaseFile(const char* path, oflag_t oflag) { open(path, oflag); }
|
||||
|
||||
/** Copy from to this.
|
||||
|
|
@ -105,7 +105,7 @@ class FsBaseFile {
|
|||
close();
|
||||
}
|
||||
}
|
||||
#else // DESTRUCTOR_CLOSES_FILE
|
||||
#else // DESTRUCTOR_CLOSES_FILE
|
||||
~FsBaseFile() = default;
|
||||
#endif // DESTRUCTOR_CLOSES_FILE
|
||||
|
||||
|
|
@ -345,10 +345,6 @@ class FsBaseFile {
|
|||
bool isDir() const {
|
||||
return m_fFile ? m_fFile->isDir() : m_xFile ? m_xFile->isDir() : false;
|
||||
}
|
||||
/** This function reports if the current file is a directory or not.
|
||||
* \return true if the file is a directory.
|
||||
*/
|
||||
bool isDirectory() const { return isDir(); }
|
||||
/** \return True if this is a normal file. */
|
||||
bool isFile() const {
|
||||
return m_fFile ? m_fFile->isFile() : m_xFile ? m_xFile->isFile() : false;
|
||||
|
|
@ -385,6 +381,12 @@ class FsBaseFile {
|
|||
: m_xFile ? m_xFile->isSubDir()
|
||||
: false;
|
||||
}
|
||||
/** \return True if this is a System file else false. */
|
||||
bool isSystem() const {
|
||||
return m_fFile ? m_fFile->isSystem()
|
||||
: m_xFile ? m_xFile->isSystem()
|
||||
: false;
|
||||
}
|
||||
/** \return True file is writable. */
|
||||
bool isWritable() const {
|
||||
return m_fFile ? m_fFile->isWritable()
|
||||
|
|
@ -562,8 +564,6 @@ class FsBaseFile {
|
|||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool openRoot(FsVolume* vol);
|
||||
/** \return the current file position. */
|
||||
uint64_t position() const { return curPosition(); }
|
||||
/** Return the next available byte without consuming it.
|
||||
*
|
||||
* \return The byte if no error and not at eof else -1;
|
||||
|
|
@ -759,10 +759,6 @@ class FsBaseFile {
|
|||
if (m_fFile) m_fFile->rewind();
|
||||
if (m_xFile) m_xFile->rewind();
|
||||
}
|
||||
/** Rewind a file if it is a directory */
|
||||
void rewindDirectory() {
|
||||
if (isDir()) rewind();
|
||||
}
|
||||
/** Remove a directory file.
|
||||
*
|
||||
* The directory file will be removed only if it is empty and is not the
|
||||
|
|
@ -776,13 +772,6 @@ class FsBaseFile {
|
|||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool rmdir();
|
||||
/** Seek to a new position in the file, which must be between
|
||||
* 0 and the size of the file (inclusive).
|
||||
*
|
||||
* \param[in] pos the new file position.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool seek(uint64_t pos) { return seekSet(pos); }
|
||||
/** Set the files position to current position + \a pos. See seekSet().
|
||||
* \param[in] offset The new position in bytes from the current position.
|
||||
* \return true for success or false for failure.
|
||||
|
|
@ -805,8 +794,6 @@ class FsBaseFile {
|
|||
: m_xFile ? m_xFile->seekSet(pos)
|
||||
: false;
|
||||
}
|
||||
/** \return the file's size. */
|
||||
uint64_t size() const { return fileSize(); }
|
||||
/** The sync() call causes all modified data and directory fields
|
||||
* to be written to the storage device.
|
||||
*
|
||||
|
|
@ -928,4 +915,3 @@ class FsFile : public StreamFile<FsBaseFile, uint64_t> {
|
|||
return tmpFile;
|
||||
}
|
||||
};
|
||||
#endif // FsFile_h
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -22,8 +22,7 @@
|
|||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef FsNew_h
|
||||
#define FsNew_h
|
||||
#pragma once
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
|
@ -36,11 +35,10 @@ typedef uint32_t newalign_t;
|
|||
|
||||
/** Dimension of aligned area. */
|
||||
#define NEW_ALIGN_DIM(n) \
|
||||
(((size_t)(n) + sizeof(newalign_t) - 1U) / sizeof(newalign_t))
|
||||
((static_cast<size_t>(n) + sizeof(newalign_t) - 1U) / sizeof(newalign_t))
|
||||
|
||||
/** Dimension of aligned area for etype or ftype class. */
|
||||
#define FS_ALIGN_DIM(etype, ftype) NEW_ALIGN_DIM(FS_SIZE(etype, ftype))
|
||||
|
||||
/** Custom new placement operator */
|
||||
void* operator new(size_t size, newalign_t* ptr);
|
||||
#endif // FsNew_h
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -22,8 +22,7 @@
|
|||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef FsVolume_h
|
||||
#define FsVolume_h
|
||||
#pragma once
|
||||
/**
|
||||
* \file
|
||||
* \brief FsVolume include file.
|
||||
|
|
@ -39,7 +38,7 @@ class FsFile;
|
|||
*/
|
||||
class FsVolume {
|
||||
public:
|
||||
FsVolume() = default;
|
||||
FsVolume() = default; // cppcheck-suppress uninitMemberVar
|
||||
|
||||
~FsVolume() { end(); }
|
||||
/** Get file's user settable attributes.
|
||||
|
|
@ -399,4 +398,3 @@ class FsVolume {
|
|||
FatVolume* m_fVol = nullptr;
|
||||
ExFatVolume* m_xVol = nullptr;
|
||||
};
|
||||
#endif // FsVolume_h
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
exclude_files=SdioTeensy.h
|
||||
1
src/SdCard/Rp2040Sdio/CPPLINT.cfg
Normal file
1
src/SdCard/Rp2040Sdio/CPPLINT.cfg
Normal file
|
|
@ -0,0 +1 @@
|
|||
exclude_files=PioSdioCard.pio.h
|
||||
162
src/SdCard/Rp2040Sdio/DbgLog.h
Normal file
162
src/SdCard/Rp2040Sdio/DbgLog.h
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2024 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.
|
||||
*/
|
||||
#pragma once
|
||||
#include "Printable.h"
|
||||
|
||||
#define NUM64_HEX_A 'a'
|
||||
#define ENABLE_DBG_MSG 1
|
||||
#define DBG_LOG_PORT Serial
|
||||
|
||||
#if defined(DBG_FILE)
|
||||
#elif defined(__FILE_NAME__)
|
||||
#define DBG_FILE __FILE_NAME__
|
||||
#else
|
||||
#define DBG_FILE __FILE__
|
||||
#endif
|
||||
|
||||
#if ENABLE_DBG_MSG
|
||||
#define DBG_MSG(...) \
|
||||
do { \
|
||||
logmsgln(F(DBG_FILE), ":", __LINE__, " ", ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#else // ENABLE_DBG_MSG
|
||||
#define DBG_MSG(...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif // ENABLE_DBG_MSG
|
||||
|
||||
// Print binary with byte and nibble separators.
|
||||
class Bin : public Printable {
|
||||
// Bin not supported for 64-bits.
|
||||
explicit Bin(int64_t, uint8_t = 0) {}
|
||||
explicit Bin(uint64_t, uint8_t = 0) {}
|
||||
|
||||
public:
|
||||
template <typename T>
|
||||
explicit Bin(T n, uint8_t p = 0) : n_(n), p_(p) {}
|
||||
size_t printTo(Print& pr) const {
|
||||
auto n = n_;
|
||||
uint8_t p = p_ > 8 * sizeof(n) ? 8 * sizeof(n) : p_;
|
||||
char buf[10 * sizeof(n) + 1];
|
||||
char* end = buf + sizeof(buf);
|
||||
char* str = end;
|
||||
uint8_t i = 0;
|
||||
do {
|
||||
if (i && (i % 4) == 0) {
|
||||
*--str = i % 8 ? '\'' : '|';
|
||||
}
|
||||
*--str = n & 1 ? '1' : '0';
|
||||
n /= 2;
|
||||
i++;
|
||||
} while (n || i < p);
|
||||
return pr.write(str, end - str);
|
||||
}
|
||||
uint32_t n_;
|
||||
uint8_t p_;
|
||||
};
|
||||
|
||||
// Print floating point with precision.
|
||||
struct Dbl : public Printable {
|
||||
Dbl(double n_, int p_) : n(n_), p(p_) {}
|
||||
size_t printTo(Print& pr) const { return pr.print(n, p); }
|
||||
double n;
|
||||
int p;
|
||||
};
|
||||
|
||||
// Print in hex format.
|
||||
#if __cplusplus > 201700L
|
||||
template <typename T>
|
||||
struct Hex : public Printable {
|
||||
explicit Hex(T n_) : n(n_) {}
|
||||
size_t printTo(Print& pr) const { return pr.print(n, HEX); }
|
||||
T n;
|
||||
};
|
||||
#else // __cplusplus > 201700L
|
||||
class Hex : public Printable {
|
||||
// No 64-bit support unless C++17 or better.
|
||||
explicit Hex(int64_t) {}
|
||||
explicit Hex(uint64_t) {}
|
||||
|
||||
public:
|
||||
template <typename T>
|
||||
explicit Hex(T n_) : n(n_) {}
|
||||
size_t printTo(Print& pr) const { return pr.print(n, HEX); }
|
||||
uint32_t n;
|
||||
};
|
||||
#endif // __cplusplus > 201700L
|
||||
|
||||
// For boards with no 64-bit print, lower case hex, alt binary or precision.
|
||||
class Num : public Printable {
|
||||
uint64_t n_;
|
||||
uint8_t b_;
|
||||
uint8_t p_;
|
||||
char s_;
|
||||
|
||||
public:
|
||||
template <typename T>
|
||||
explicit Num(T n, uint8_t b = 0, uint8_t p = 0, char s = 0) : b_(b), p_(p) {
|
||||
n_ = b == 10 && n < 0 ? -n : n;
|
||||
s_ = b == 10 && n < 0 ? '-' : s;
|
||||
}
|
||||
size_t printTo(Print& pr) const {
|
||||
char buf[8 * sizeof(uint64_t) + 1];
|
||||
char* end = buf + sizeof(buf);
|
||||
char* str = end;
|
||||
uint64_t n = n_;
|
||||
uint8_t p = p_ > 8 * sizeof(n) ? 8 * sizeof(n) : p_;
|
||||
uint8_t base = b_ < 2 || b_ > 16 ? 10 : b_;
|
||||
uint8_t i = 0;
|
||||
do {
|
||||
uint8_t d = n % base;
|
||||
*--str = d < 10 ? d + '0' : d + NUM64_HEX_A - 10;
|
||||
n /= base;
|
||||
i++;
|
||||
} while (n || i < p);
|
||||
if (s_) {
|
||||
*--str = s_;
|
||||
}
|
||||
return pr.write(str, end - str);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
size_t logmsg(T arg) {
|
||||
return DBG_LOG_PORT.print(arg);
|
||||
}
|
||||
size_t logmsg(bool b) { return logmsg(b ? F("true") : F("false")); }
|
||||
|
||||
inline size_t logmsg() { return 0; }
|
||||
|
||||
template <typename T, typename... Types>
|
||||
size_t logmsg(T var1, Types... var2) {
|
||||
size_t n = logmsg(var1);
|
||||
return n += logmsg(var2...);
|
||||
}
|
||||
|
||||
template <typename... Types>
|
||||
size_t logmsgln(Types... params) {
|
||||
size_t n = logmsg(params...);
|
||||
return n + logmsg("\r\n");
|
||||
}
|
||||
56
src/SdCard/Rp2040Sdio/PioDbgInfo.h
Normal file
56
src/SdCard/Rp2040Sdio/PioDbgInfo.h
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2024 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.
|
||||
*/
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "DbgLog.h"
|
||||
//------------------------------------------------------------------------------
|
||||
static inline void gpioStatus(uint gpio) {
|
||||
logmsgln("gpio", gpio, " drive: ", gpio_get_drive_strength(gpio));
|
||||
// logmsgln("gpio", gpio,
|
||||
// " drive: ", static_cast<int>(gpio_get_drive_strength(gpio)));
|
||||
logmsgln("gpio", gpio, " slew: ", gpio_get_slew_rate(gpio));
|
||||
logmsgln("gpio", gpio, " hyst: ", gpio_is_input_hysteresis_enabled(gpio));
|
||||
logmsgln("gpio", gpio, " pull: ", gpio_is_pulled_up(gpio));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static inline void pioRegs(PIO pio) {
|
||||
logmsgln("ctrl: 0b", Bin(pio->ctrl));
|
||||
logmsgln("fstat: 0b", Bin(pio->fstat));
|
||||
logmsgln("fdebug: 0b", Bin(pio->fdebug));
|
||||
logmsgln("flevel: 0b", Bin(pio->flevel));
|
||||
logmsgln("padout: 0b", Bin(pio->dbg_padout));
|
||||
logmsgln("padoe: 0b", Bin(pio->dbg_padoe));
|
||||
logmsgln("cfginfo: 0x", Hex(pio->dbg_cfginfo));
|
||||
logmsgln("sync_bypass: 0b", Bin(pio->input_sync_bypass));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static inline void pioSmRegs(PIO pio, uint sm) {
|
||||
logmsgln("sm", sm, " clkdiv: 0x", Hex(pio->sm[sm].clkdiv));
|
||||
logmsgln("sm", sm, " execctrl: 0x", Hex(pio->sm[sm].execctrl));
|
||||
logmsgln("sm", sm, " shiftctrl: 0x", Hex(pio->sm[sm].shiftctrl));
|
||||
logmsgln("sm", sm, " addr: 0x", Hex(pio->sm[sm].addr));
|
||||
logmsgln("sm", sm, " pinctrl: 0x", Hex(pio->sm[sm].pinctrl));
|
||||
}
|
||||
954
src/SdCard/Rp2040Sdio/PioSdioCard.cpp
Normal file
954
src/SdCard/Rp2040Sdio/PioSdioCard.cpp
Normal file
|
|
@ -0,0 +1,954 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2024 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.
|
||||
*/
|
||||
#ifdef ARDUINO_ARCH_RP2040
|
||||
#define DEBUG_FILE "PioSdioCard.cpp"
|
||||
#include "../SdCardInfo.h"
|
||||
#include "../SdioCard.h"
|
||||
#include "PioDbgInfo.h"
|
||||
#include "PioSdioCard.pio.h"
|
||||
//------------------------------------------------------------------------------
|
||||
// Do not enable - not implemented
|
||||
#define HIGH_SPEED_MODE 0 // non-zero to debug High Speed Mode
|
||||
// USE_DEBUG_MODE 0 - no debug, 1 - print message, 2 - Use scope/analyzer.
|
||||
#define USE_DEBUG_MODE 0
|
||||
|
||||
const uint PIO_CLK_DIV_INIT = 2;
|
||||
|
||||
const uint PIO_CLK_DIV_RUN = 1;
|
||||
|
||||
const uint PIN_SDIO_UNDEFINED = 31u;
|
||||
|
||||
const uint DAT_FIFO_DEPTH = 8;
|
||||
const uint CMD0_RETRIES = 10;
|
||||
const uint CMD8_RETRIES = 3;
|
||||
|
||||
//==============================================================================
|
||||
// Command definitions.
|
||||
enum { RSP_R0 = 0, RSP_R1 = 1, RSP_R2 = 2, RSP_R3 = 3, RSP_R6 = 6, RSP_R7 = 7 };
|
||||
|
||||
class CmdRsp_t {
|
||||
public:
|
||||
CmdRsp_t(uint8_t idx_, uint8_t rsp_) : idx(idx_), rsp(rsp_) {}
|
||||
uint8_t idx;
|
||||
uint8_t rsp;
|
||||
};
|
||||
|
||||
static const CmdRsp_t CMD0_R0(CMD0, RSP_R0);
|
||||
static const CmdRsp_t CMD2_R2(CMD2, RSP_R2);
|
||||
static const CmdRsp_t CMD3_R6(CMD3, RSP_R6);
|
||||
static const CmdRsp_t CMD6_R1(CMD6, RSP_R1);
|
||||
static const CmdRsp_t CMD7_R1(CMD7, RSP_R1);
|
||||
static const CmdRsp_t CMD8_R7(CMD8, RSP_R7);
|
||||
static const CmdRsp_t CMD9_R2(CMD9, RSP_R2);
|
||||
static const CmdRsp_t CMD10_R2(CMD10, RSP_R2);
|
||||
static const CmdRsp_t CMD12_R1(CMD12, RSP_R1);
|
||||
static const CmdRsp_t CMD13_R1(CMD13, RSP_R1);
|
||||
static const CmdRsp_t CMD18_R1(CMD18, RSP_R1);
|
||||
static const CmdRsp_t CMD25_R1(CMD25, RSP_R1);
|
||||
static const CmdRsp_t CMD32_R1(CMD32, RSP_R1);
|
||||
static const CmdRsp_t CMD33_R1(CMD33, RSP_R1);
|
||||
static const CmdRsp_t CMD38_R1(CMD38, RSP_R1);
|
||||
static const CmdRsp_t CMD55_R1(CMD55, RSP_R1);
|
||||
static const CmdRsp_t ACMD6_R1(ACMD6, RSP_R1);
|
||||
static const CmdRsp_t ACMD13_R1(ACMD13, RSP_R1);
|
||||
static const CmdRsp_t ACMD41_R3(ACMD41, RSP_R3);
|
||||
static const CmdRsp_t ACMD51_R1(ACMD51, RSP_R1);
|
||||
//==============================================================================
|
||||
// Global variables.
|
||||
static float g_clkDiv = 0;
|
||||
static uint g_clkPin = PIN_SDIO_UNDEFINED;
|
||||
static uint g_cmdPin = PIN_SDIO_UNDEFINED;
|
||||
static uint g_dat0Pin = PIN_SDIO_UNDEFINED;
|
||||
static uint g_cardRsp;
|
||||
static uint g_errorCode;
|
||||
static uint g_errorLine;
|
||||
static bool g_highCapacity;
|
||||
static bool g_initDone = false;
|
||||
static uint g_ocr;
|
||||
static bool g_version2;
|
||||
static PIO g_pio = nullptr;
|
||||
static int g_sm0 = -1;
|
||||
static int g_sm1 = -1;
|
||||
static int g_cmdRspOffset = -1;
|
||||
static pio_sm_config g_cmdConfig;
|
||||
static int g_rdDataOffset = -1;
|
||||
static pio_sm_config g_rdDataConfig;
|
||||
static int g_rdClkOffset = -1;
|
||||
static pio_sm_config g_rdClkConfig;
|
||||
static int g_wrDataOffset = -1;
|
||||
static pio_sm_config g_wrDataConfig;
|
||||
static int g_wrRespOffset = -1;
|
||||
static pio_sm_config g_wrRespConfig;
|
||||
static uint g_rca;
|
||||
static cid_t g_cid;
|
||||
static csd_t g_csd;
|
||||
static scr_t g_scr;
|
||||
static sds_t g_sds;
|
||||
//==============================================================================
|
||||
class Timeout {
|
||||
public:
|
||||
explicit Timeout(uint ms) : _usStart(0), _usTimeout(1000 * ms) {}
|
||||
bool timedOut() {
|
||||
if (_usStart) {
|
||||
return (usSinceBoot() - _usStart) > _usTimeout;
|
||||
}
|
||||
_usStart = usSinceBoot();
|
||||
return false;
|
||||
}
|
||||
uint32_t usSinceBoot() { return to_us_since_boot(get_absolute_time()); }
|
||||
uint32_t _usStart;
|
||||
uint32_t _usTimeout;
|
||||
};
|
||||
//==============================================================================
|
||||
// Error function and macro.
|
||||
#define PIO_ERROR_ADD_PROGRAM 99
|
||||
#if USE_DEBUG_MODE
|
||||
#define SDIO_FAIL() logmsgln(DEBUG_FILE, '.', __LINE__, F("SDIO_FAIL"))
|
||||
#define sdError(code) setSdErrorCode(code, __LINE__, #code)
|
||||
static void setSdErrorCode(uint8_t code, uint32_t line, const char* txt) {
|
||||
g_errorCode = code;
|
||||
g_errorLine = line;
|
||||
logmsgln(F(DEBUG_FILE), '.', line, ' ', txt);
|
||||
}
|
||||
#else // USE_DEBUG_MODE
|
||||
#define SDIO_FAIL()
|
||||
#define sdError(code) setSdErrorCode(code, __LINE__)
|
||||
static inline void setSdErrorCode(uint8_t code, uint32_t line) {
|
||||
g_errorCode = code;
|
||||
g_errorLine = line;
|
||||
}
|
||||
#endif // USE_DEBUG_MODE
|
||||
//==============================================================================
|
||||
// CRC functions.
|
||||
//------------------------------------------------------------------------------
|
||||
// See this library's extras folder.
|
||||
static const uint8_t crc7_table[256] = {
|
||||
0x00, 0x12, 0x24, 0x36, 0x48, 0x5a, 0x6c, 0x7e, // 00 - 07
|
||||
0x90, 0x82, 0xb4, 0xa6, 0xd8, 0xca, 0xfc, 0xee, // 08 - 0f
|
||||
0x32, 0x20, 0x16, 0x04, 0x7a, 0x68, 0x5e, 0x4c, // 10 - 17
|
||||
0xa2, 0xb0, 0x86, 0x94, 0xea, 0xf8, 0xce, 0xdc, // 18 - 1f
|
||||
0x64, 0x76, 0x40, 0x52, 0x2c, 0x3e, 0x08, 0x1a, // 20 - 27
|
||||
0xf4, 0xe6, 0xd0, 0xc2, 0xbc, 0xae, 0x98, 0x8a, // 28 - 2f
|
||||
0x56, 0x44, 0x72, 0x60, 0x1e, 0x0c, 0x3a, 0x28, // 30 - 37
|
||||
0xc6, 0xd4, 0xe2, 0xf0, 0x8e, 0x9c, 0xaa, 0xb8, // 38 - 3f
|
||||
0xc8, 0xda, 0xec, 0xfe, 0x80, 0x92, 0xa4, 0xb6, // 40 - 47
|
||||
0x58, 0x4a, 0x7c, 0x6e, 0x10, 0x02, 0x34, 0x26, // 48 - 4f
|
||||
0xfa, 0xe8, 0xde, 0xcc, 0xb2, 0xa0, 0x96, 0x84, // 50 - 57
|
||||
0x6a, 0x78, 0x4e, 0x5c, 0x22, 0x30, 0x06, 0x14, // 58 - 5f
|
||||
0xac, 0xbe, 0x88, 0x9a, 0xe4, 0xf6, 0xc0, 0xd2, // 60 - 67
|
||||
0x3c, 0x2e, 0x18, 0x0a, 0x74, 0x66, 0x50, 0x42, // 68 - 6f
|
||||
0x9e, 0x8c, 0xba, 0xa8, 0xd6, 0xc4, 0xf2, 0xe0, // 70 - 77
|
||||
0x0e, 0x1c, 0x2a, 0x38, 0x46, 0x54, 0x62, 0x70, // 78 - 7f
|
||||
0x82, 0x90, 0xa6, 0xb4, 0xca, 0xd8, 0xee, 0xfc, // 80 - 87
|
||||
0x12, 0x00, 0x36, 0x24, 0x5a, 0x48, 0x7e, 0x6c, // 88 - 8f
|
||||
0xb0, 0xa2, 0x94, 0x86, 0xf8, 0xea, 0xdc, 0xce, // 90 - 97
|
||||
0x20, 0x32, 0x04, 0x16, 0x68, 0x7a, 0x4c, 0x5e, // 98 - 9f
|
||||
0xe6, 0xf4, 0xc2, 0xd0, 0xae, 0xbc, 0x8a, 0x98, // a0 - a7
|
||||
0x76, 0x64, 0x52, 0x40, 0x3e, 0x2c, 0x1a, 0x08, // a8 - af
|
||||
0xd4, 0xc6, 0xf0, 0xe2, 0x9c, 0x8e, 0xb8, 0xaa, // b0 - b7
|
||||
0x44, 0x56, 0x60, 0x72, 0x0c, 0x1e, 0x28, 0x3a, // b8 - bf
|
||||
0x4a, 0x58, 0x6e, 0x7c, 0x02, 0x10, 0x26, 0x34, // c0 - c7
|
||||
0xda, 0xc8, 0xfe, 0xec, 0x92, 0x80, 0xb6, 0xa4, // c8 - cf
|
||||
0x78, 0x6a, 0x5c, 0x4e, 0x30, 0x22, 0x14, 0x06, // d0 - d7
|
||||
0xe8, 0xfa, 0xcc, 0xde, 0xa0, 0xb2, 0x84, 0x96, // d8 - df
|
||||
0x2e, 0x3c, 0x0a, 0x18, 0x66, 0x74, 0x42, 0x50, // e0 - e7
|
||||
0xbe, 0xac, 0x9a, 0x88, 0xf6, 0xe4, 0xd2, 0xc0, // e8 - ef
|
||||
0x1c, 0x0e, 0x38, 0x2a, 0x54, 0x46, 0x70, 0x62, // f0 - f7
|
||||
0x8c, 0x9e, 0xa8, 0xba, 0xc4, 0xd6, 0xe0, 0xf2 // f8 - ff
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
inline static uint8_t CRC7(const uint8_t* data, uint8_t n) {
|
||||
uint8_t crc = 0;
|
||||
for (uint8_t i = 0; i < n; i++) {
|
||||
crc = crc7_table[crc ^ data[i]];
|
||||
}
|
||||
return crc | 1;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// Modified from sdio_crc16_4bit_checksum() in
|
||||
// https://github.com/ZuluSCSI/ZuluSCSI-firmware
|
||||
//
|
||||
static inline __attribute__((always_inline)) uint64_t crc16(uint64_t crc,
|
||||
uint32_t data_in) {
|
||||
// Shift out 8 bits for each line
|
||||
uint32_t data_out = crc >> 32;
|
||||
crc <<= 32;
|
||||
|
||||
// XOR outgoing data to itself with 4 bit delay
|
||||
data_out ^= (data_out >> 16);
|
||||
|
||||
// XOR incoming data to outgoing data with 4 bit delay
|
||||
data_out ^= (data_in >> 16);
|
||||
|
||||
// XOR outgoing and incoming data to accumulator at each tap
|
||||
uint64_t xorred = data_out ^ data_in;
|
||||
crc ^= xorred;
|
||||
crc ^= xorred << (5 * 4);
|
||||
crc ^= xorred << (12 * 4);
|
||||
return crc;
|
||||
}
|
||||
//==============================================================================
|
||||
static void pioConfig(float clkDiv) {
|
||||
g_cmdConfig =
|
||||
pio_cmd_rsp_program_config(g_cmdRspOffset, g_cmdPin, g_clkPin, clkDiv);
|
||||
g_rdClkConfig =
|
||||
pio_rd_clk_program_config(g_rdClkOffset, g_dat0Pin, g_clkPin, clkDiv);
|
||||
g_rdDataConfig =
|
||||
pio_rd_data_program_config(g_rdDataOffset, g_dat0Pin, clkDiv);
|
||||
g_wrDataConfig =
|
||||
pio_wr_data_program_config(g_wrDataOffset, g_dat0Pin, g_clkPin, clkDiv);
|
||||
g_wrRespConfig =
|
||||
pio_wr_resp_program_config(g_wrRespOffset, g_dat0Pin, g_clkPin, clkDiv);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static void pioEnd() {
|
||||
if (!g_pio) {
|
||||
return;
|
||||
}
|
||||
if (g_sm0 >= 0) {
|
||||
pio_sm_unclaim(g_pio, g_sm0);
|
||||
g_sm0 = -1;
|
||||
}
|
||||
if (g_sm1 >= 0) {
|
||||
pio_sm_unclaim(g_pio, g_sm1);
|
||||
g_sm1 = -1;
|
||||
}
|
||||
if (g_cmdRspOffset >= 0) {
|
||||
pio_remove_program(g_pio, &cmd_rsp_program, g_cmdRspOffset);
|
||||
g_cmdRspOffset = -1;
|
||||
}
|
||||
if (g_rdClkOffset >= 0) {
|
||||
pio_remove_program(g_pio, &rd_clk_program, g_rdClkOffset);
|
||||
g_rdClkOffset = -1;
|
||||
}
|
||||
if (g_rdDataOffset >= 0) {
|
||||
pio_remove_program(g_pio, &rd_data_program, g_rdDataOffset);
|
||||
g_rdDataOffset = -1;
|
||||
}
|
||||
if (g_wrDataOffset >= 0) {
|
||||
pio_remove_program(g_pio, &wr_data_program, g_wrDataOffset);
|
||||
g_wrDataOffset = -1;
|
||||
}
|
||||
if (g_wrRespOffset >= 0) {
|
||||
pio_remove_program(g_pio, &wr_resp_program, g_wrRespOffset);
|
||||
g_wrRespOffset = -1;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static bool pioInit() {
|
||||
uint pin[] = {g_clkPin, g_cmdPin, g_dat0Pin,
|
||||
g_dat0Pin + 1, g_dat0Pin + 2, g_dat0Pin + 3};
|
||||
if (g_wrRespOffset < 0) {
|
||||
uint16_t patched_inst[rd_data_program.length]; // NOLINT
|
||||
struct pio_program tmp_program;
|
||||
tmp_program.instructions = nullptr;
|
||||
tmp_program.length = cmd_rsp_program.length + rd_data_program.length +
|
||||
rd_clk_program.length + wr_data_program.length +
|
||||
wr_resp_program.length;
|
||||
tmp_program.origin = -1;
|
||||
if (pio_can_add_program(pio0, &tmp_program)) {
|
||||
g_pio = pio0;
|
||||
} else if (pio_can_add_program(pio1, &tmp_program)) {
|
||||
g_pio = pio1;
|
||||
#if NUM_PIOS > 2
|
||||
} else if (pio_can_add_program(pio2, &tmp_program)) {
|
||||
g_pio = pio2;
|
||||
#endif
|
||||
} else {
|
||||
sdError(PIO_ERROR_ADD_PROGRAM);
|
||||
goto fail;
|
||||
}
|
||||
g_sm0 = pio_claim_unused_sm(g_pio, false);
|
||||
if (g_sm0 < 0) {
|
||||
sdError(PIO_ERROR_ADD_PROGRAM);
|
||||
goto fail;
|
||||
}
|
||||
g_sm1 = pio_claim_unused_sm(g_pio, false);
|
||||
if (g_sm0 < 0) {
|
||||
sdError(PIO_ERROR_ADD_PROGRAM);
|
||||
goto fail;
|
||||
}
|
||||
g_cmdRspOffset = pio_add_program(g_pio, &cmd_rsp_program);
|
||||
if (g_cmdRspOffset < 0) {
|
||||
sdError(PIO_ERROR_ADD_PROGRAM);
|
||||
goto fail;
|
||||
}
|
||||
rd_data_patch_program(&tmp_program, patched_inst, g_clkPin);
|
||||
g_rdDataOffset = pio_add_program(g_pio, &tmp_program);
|
||||
if (g_rdDataOffset < 0) {
|
||||
sdError(PIO_ERROR_ADD_PROGRAM);
|
||||
goto fail;
|
||||
}
|
||||
g_rdClkOffset = pio_add_program(g_pio, &rd_clk_program);
|
||||
if (g_rdClkOffset < 0) {
|
||||
sdError(PIO_ERROR_ADD_PROGRAM);
|
||||
goto fail;
|
||||
}
|
||||
g_wrDataOffset = pio_add_program(g_pio, &wr_data_program);
|
||||
if (g_wrDataOffset < 0) {
|
||||
sdError(PIO_ERROR_ADD_PROGRAM);
|
||||
goto fail;
|
||||
}
|
||||
g_wrRespOffset = pio_add_program(g_pio, &wr_resp_program);
|
||||
if (g_wrRespOffset < 0) {
|
||||
sdError(PIO_ERROR_ADD_PROGRAM);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
for (uint i = 0; i < 6U; i++) {
|
||||
gpio_pull_up(pin[i]);
|
||||
}
|
||||
gpio_set_drive_strength(g_clkPin, GPIO_DRIVE_STRENGTH_8MA);
|
||||
gpio_set_slew_rate(g_clkPin, GPIO_SLEW_RATE_FAST);
|
||||
for (uint i = 0; i < 6U; i++) {
|
||||
pio_gpio_init(g_pio, pin[i]);
|
||||
}
|
||||
|
||||
g_pio->input_sync_bypass |=
|
||||
(1 << g_clkPin) | (1 << g_cmdPin) | (0XF << g_dat0Pin);
|
||||
pio_sm_set_consecutive_pindirs(g_pio, g_sm0, g_clkPin, 1, true);
|
||||
pio_sm_set_consecutive_pindirs(g_pio, g_sm0, g_cmdPin, 1, true);
|
||||
pio_sm_set_consecutive_pindirs(g_pio, g_sm0, g_dat0Pin, 4, false);
|
||||
return true;
|
||||
|
||||
fail:
|
||||
pioEnd();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static bool cardCmd(CmdRsp_t cmd, uint32_t arg, void* rsp = nullptr) {
|
||||
uint8_t buf[6];
|
||||
uint nRsp = cmd.rsp == RSP_R0 ? 0 : cmd.rsp == RSP_R2 ? 17 : 6;
|
||||
io_ro_8* rxFifo = reinterpret_cast<io_ro_8*>(&g_pio->rxf[g_sm0]);
|
||||
io_wo_8* txFifo = reinterpret_cast<io_wo_8*>(&g_pio->txf[g_sm0]);
|
||||
pio_sm_set_enabled(g_pio, g_sm1, false);
|
||||
pio_sm_init(g_pio, g_sm0, g_cmdRspOffset, &g_cmdConfig);
|
||||
pio_sm_exec(g_pio, g_sm0, pio_encode_set(pio_pindirs, 1));
|
||||
*txFifo = 55;
|
||||
pio_sm_exec(g_pio, g_sm0, pio_encode_out(pio_x, 8));
|
||||
*txFifo = nRsp ? 8 * nRsp - 1 : 0;
|
||||
pio_sm_exec(g_pio, g_sm0, pio_encode_out(pio_y, 8));
|
||||
pio_sm_set_enabled(g_pio, g_sm0, true);
|
||||
uint n = 0;
|
||||
buf[n++] = (uint8_t)(cmd.idx | 0x40);
|
||||
buf[n++] = (uint8_t)(arg >> 24U);
|
||||
buf[n++] = (uint8_t)(arg >> 16U);
|
||||
buf[n++] = (uint8_t)(arg >> 8U);
|
||||
buf[n++] = (uint8_t)arg;
|
||||
buf[n++] = CRC7(buf, 5);
|
||||
*txFifo = 0XFF;
|
||||
for (uint i = 0; i < n; i++) {
|
||||
while (pio_sm_is_tx_fifo_full(g_pio, g_sm0)) {
|
||||
}
|
||||
*txFifo = buf[i];
|
||||
}
|
||||
|
||||
Timeout timeout(SD_CMD_TIMEOUT);
|
||||
if (!nRsp) {
|
||||
uint32_t fdebug_tx_stall = 1u << (PIO_FDEBUG_TXSTALL_LSB + g_sm0);
|
||||
g_pio->fdebug = fdebug_tx_stall;
|
||||
while (!(g_pio->fdebug & fdebug_tx_stall)) {
|
||||
if (timeout.timedOut()) {
|
||||
sdError(SD_CARD_ERROR_CMD0);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
uint8_t rtn[20];
|
||||
|
||||
for (uint i = 0; i < nRsp; i++) {
|
||||
while (pio_sm_is_rx_fifo_empty(g_pio, g_sm0)) {
|
||||
if (timeout.timedOut()) {
|
||||
sdError(SD_CARD_ERROR_READ_TIMEOUT);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
rtn[i] = *rxFifo;
|
||||
}
|
||||
if (cmd.rsp == RSP_R3) {
|
||||
if (rtn[0] != 0X3F || rtn[5] != 0XFF) {
|
||||
sdError(SD_CARD_ERROR_ACMD41);
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
uint8_t crc;
|
||||
if (cmd.rsp == RSP_R2) {
|
||||
crc = CRC7(rtn + 1, nRsp - 2);
|
||||
} else {
|
||||
crc = CRC7(rtn, nRsp - 1);
|
||||
}
|
||||
if (rtn[nRsp - 1] != crc) {
|
||||
#if USE_DEBUG_MODE
|
||||
Serial.printf("CHK: %02X, CRC: %02X\n", rtn[nRsp - 1], crc);
|
||||
for (uint i = 0; i < nRsp; i++) {
|
||||
Serial.printf(" %02X", rtn[i]);
|
||||
}
|
||||
Serial.println();
|
||||
#endif // USE_DEBUG_MODE
|
||||
sdError(SD_CARD_ERROR_READ_CRC);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (nRsp == 6) {
|
||||
g_cardRsp = (rtn[1] << 24) | (rtn[2] << 16) | (rtn[3] << 8) | rtn[4];
|
||||
if (rsp) {
|
||||
*reinterpret_cast<uint32_t*>(rsp) = g_cardRsp;
|
||||
}
|
||||
} else if (rsp && nRsp == 17) {
|
||||
memcpy(rsp, rtn + 1, 16);
|
||||
}
|
||||
|
||||
done:
|
||||
pio_sm_set_enabled(g_pio, g_sm0, false);
|
||||
return true;
|
||||
|
||||
fail:
|
||||
#if USE_DEBUG_MODE
|
||||
Serial.printf("CMD%d failed\n", cmd.idx);
|
||||
#endif // USE_DEBUG_MODE
|
||||
pio_sm_set_enabled(g_pio, g_sm0, false);
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static bool cardAcmd(uint32_t rca, CmdRsp_t cmdRsp, uint32_t arg) {
|
||||
return cardCmd(CMD55_R1, rca) && cardCmd(cmdRsp, arg);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static bool __time_critical_func(readDat)(void* dst, uint n8) {
|
||||
uint32_t buf[128];
|
||||
uint n32 = n8 / 4;
|
||||
uint nr = n32 + 2;
|
||||
const uint mask = (1ul << g_sm0) | (1ul << g_sm1);
|
||||
io_wo_8* txFifo = reinterpret_cast<io_wo_8*>(&g_pio->txf[g_sm1]);
|
||||
pio_sm_init(g_pio, g_sm0, g_rdDataOffset, &g_rdDataConfig);
|
||||
pio_sm_init(g_pio, g_sm1, g_rdClkOffset, &g_rdClkConfig);
|
||||
pio_set_sm_mask_enabled(g_pio, mask, true);
|
||||
|
||||
uint nf = nr < DAT_FIFO_DEPTH ? nr : DAT_FIFO_DEPTH;
|
||||
for (uint it = 0; it < nf; it++) {
|
||||
*txFifo = 0XFF;
|
||||
}
|
||||
io_ro_32* rxFifo = reinterpret_cast<io_ro_32*>(&g_pio->rxf[g_sm0]);
|
||||
uint32_t* dst32 = (uint)dst & 3 ? buf : reinterpret_cast<uint32_t*>(dst);
|
||||
uint64_t crc = 0;
|
||||
uint64_t chk = 0;
|
||||
Timeout timeout(SD_READ_TIMEOUT);
|
||||
uint ir = 0;
|
||||
if (nf < nr) {
|
||||
uint nb = nr - nf;
|
||||
while (true) {
|
||||
while (pio_sm_get_rx_fifo_level(g_pio, g_sm0) < 4) {
|
||||
if (timeout.timedOut()) {
|
||||
sdError(SD_CARD_ERROR_READ_TIMEOUT);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
uint32_t tmp = *rxFifo;
|
||||
*txFifo = 0XFF;
|
||||
dst32[ir++] = __builtin_bswap32(tmp);
|
||||
crc = crc16(crc, tmp);
|
||||
tmp = *rxFifo;
|
||||
*txFifo = 0XFF;
|
||||
dst32[ir++] = __builtin_bswap32(tmp);
|
||||
crc = crc16(crc, tmp);
|
||||
if (ir == nb) {
|
||||
break;
|
||||
}
|
||||
tmp = *rxFifo;
|
||||
*txFifo = 0XFF;
|
||||
dst32[ir++] = __builtin_bswap32(tmp);
|
||||
crc = crc16(crc, tmp);
|
||||
tmp = *rxFifo;
|
||||
*txFifo = 0XFF;
|
||||
dst32[ir++] = __builtin_bswap32(tmp);
|
||||
crc = crc16(crc, tmp);
|
||||
}
|
||||
}
|
||||
for (; ir < nr; ir++) {
|
||||
while (pio_sm_is_rx_fifo_empty(g_pio, g_sm0)) {
|
||||
if (timeout.timedOut()) {
|
||||
sdError(SD_CARD_ERROR_READ_TIMEOUT);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
uint32_t tmp = *rxFifo;
|
||||
if (ir < n32) {
|
||||
dst32[ir] = __builtin_bswap32(tmp);
|
||||
crc = crc16(crc, tmp);
|
||||
} else {
|
||||
chk <<= 32;
|
||||
chk |= tmp;
|
||||
}
|
||||
}
|
||||
if (crc != chk) {
|
||||
#if USE_DEBUG_MODE
|
||||
Serial.printf("crc: %llX\r\nchk: %llX\r\n", crc, chk);
|
||||
#endif // USE_DEBUG_MODE
|
||||
sdError(SD_CARD_ERROR_READ_CRC);
|
||||
goto fail;
|
||||
}
|
||||
pio_set_sm_mask_enabled(g_pio, mask, false);
|
||||
if (dst32 == buf) {
|
||||
memcpy(dst, buf, n8);
|
||||
}
|
||||
return true;
|
||||
|
||||
fail:
|
||||
pio_set_sm_mask_enabled(g_pio, mask, false);
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static bool __time_critical_func(writeDat)(const uint8_t* src) {
|
||||
const uint32_t* src32;
|
||||
uint32_t buf[128];
|
||||
if ((uint)src & 3) {
|
||||
memcpy(buf, src, 512);
|
||||
src32 = (const uint32_t*)buf;
|
||||
} else {
|
||||
src32 = (const uint32_t*)src;
|
||||
}
|
||||
uint32_t tmp;
|
||||
io_wo_32* txFifo = reinterpret_cast<io_wo_32*>(&g_pio->txf[g_sm0]);
|
||||
io_ro_32* rxFifo = reinterpret_cast<io_ro_32*>(&g_pio->rxf[g_sm1]);
|
||||
uint8_t rsp;
|
||||
uint mask = (1ul << g_sm0) | (1ul << g_sm1);
|
||||
uint64_t crc = 0;
|
||||
|
||||
Timeout timeout(SD_WRITE_TIMEOUT);
|
||||
while (!gpio_get(g_dat0Pin)) {
|
||||
if (timeout.timedOut()) {
|
||||
sdError(SD_CARD_ERROR_WRITE_TIMEOUT);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
pio_sm_init(g_pio, g_sm0, g_wrDataOffset, &g_wrDataConfig);
|
||||
pio_sm_init(g_pio, g_sm1, g_wrRespOffset, &g_wrRespConfig);
|
||||
*txFifo = 1048; // 8 + 1024 + 16 + 1 - 1;
|
||||
pio_sm_exec(g_pio, g_sm0, pio_encode_out(pio_x, 32));
|
||||
pio_sm_exec(g_pio, g_sm0, pio_encode_set(pio_pindirs, 0XF));
|
||||
*txFifo = 0xFFFFFFF0;
|
||||
pio_set_sm_mask_enabled(g_pio, mask, true);
|
||||
for (int i = 0; i < 128;) {
|
||||
while (pio_sm_get_tx_fifo_level(g_pio, g_sm0) > 4) {
|
||||
if (timeout.timedOut()) {
|
||||
sdError(SD_CARD_ERROR_WRITE_FIFO);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
tmp = __builtin_bswap32(src32[i++]);
|
||||
crc = crc16(crc, tmp);
|
||||
*txFifo = tmp;
|
||||
tmp = __builtin_bswap32(src32[i++]);
|
||||
crc = crc16(crc, tmp);
|
||||
*txFifo = tmp;
|
||||
tmp = __builtin_bswap32(src32[i++]);
|
||||
crc = crc16(crc, tmp);
|
||||
*txFifo = tmp;
|
||||
tmp = __builtin_bswap32(src32[i++]);
|
||||
crc = crc16(crc, tmp);
|
||||
*txFifo = tmp;
|
||||
}
|
||||
while (pio_sm_get_tx_fifo_level(g_pio, g_sm0) > 5) {
|
||||
if (timeout.timedOut()) {
|
||||
sdError(SD_CARD_ERROR_WRITE_FIFO);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
*txFifo = (uint32_t)(crc >> 32);
|
||||
*txFifo = (uint32_t)crc;
|
||||
*txFifo = 0xFFFFFFFF;
|
||||
|
||||
while (pio_sm_is_rx_fifo_empty(g_pio, g_sm1)) {
|
||||
if (timeout.timedOut()) {
|
||||
sdError(SD_CARD_ERROR_READ_FIFO);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
rsp = *rxFifo;
|
||||
if ((rsp & 0X1F) != 0b101) {
|
||||
#if USE_DEBUG_MODE
|
||||
Serial.printf("wr rsp: %02X\n", rsp);
|
||||
#endif // USE_DEBUG_MODE
|
||||
sdError(SD_CARD_ERROR_WRITE_DATA);
|
||||
goto fail;
|
||||
}
|
||||
return true;
|
||||
fail:
|
||||
pio_set_sm_mask_enabled(g_pio, mask, false);
|
||||
return false;
|
||||
}
|
||||
//==============================================================================
|
||||
// add to SdioCard class int the future.
|
||||
// SdioCard::SdioCard()
|
||||
// SdioCard::~SdioCard()
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::begin(SdioConfig sdioConfig) {
|
||||
uint32_t arg;
|
||||
m_curState = IDLE_STATE;
|
||||
g_errorCode = SD_CARD_ERROR_NONE;
|
||||
g_highCapacity = false;
|
||||
g_initDone = false;
|
||||
g_version2 = false;
|
||||
g_clkDiv = PIO_CLK_DIV_INIT;
|
||||
g_clkPin = sdioConfig.clkPin();
|
||||
g_cmdPin = sdioConfig.cmdPin();
|
||||
g_dat0Pin = sdioConfig.dat0Pin();
|
||||
pioInit();
|
||||
pioConfig(g_clkDiv);
|
||||
#if USE_DEBUG_MODE == 2
|
||||
Serial.println();
|
||||
pioRegs(g_pio);
|
||||
pioSmRegs(g_pio, g_sm0);
|
||||
pioSmRegs(g_pio, g_sm1);
|
||||
gpioStatus(g_clkPin);
|
||||
gpioStatus(g_cmdPin);
|
||||
while (Serial.read() >= 0) {
|
||||
}
|
||||
Serial.println("Logic Analyzer on");
|
||||
while (!Serial.available()) {
|
||||
}
|
||||
#endif // USE_DEBUG_MODE
|
||||
Timeout timeout(SD_INIT_TIMEOUT);
|
||||
for (uint i = 0; i < CMD0_RETRIES; i++) {
|
||||
if (!cardCmd(CMD0_R0, 0)) {
|
||||
sdError(SD_CARD_ERROR_CMD0);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
// Try several times for case of reset delay.
|
||||
for (uint32_t i = 0; i < CMD8_RETRIES; i++) {
|
||||
if (cardCmd(CMD8_R7, 0X1AA)) {
|
||||
if (g_cardRsp != 0X1AA) {
|
||||
sdError(SD_CARD_ERROR_CMD8);
|
||||
goto fail;
|
||||
}
|
||||
g_version2 = true;
|
||||
break;
|
||||
}
|
||||
g_errorCode = SD_CARD_ERROR_NONE;
|
||||
}
|
||||
arg = g_version2 ? 0X40300000 : 0x00300000;
|
||||
while (true) {
|
||||
if (!cardAcmd(0, ACMD41_R3, arg)) {
|
||||
sdError(SD_CARD_ERROR_ACMD41);
|
||||
goto fail;
|
||||
}
|
||||
if (g_cardRsp & 0x80000000) {
|
||||
break;
|
||||
}
|
||||
if (timeout.timedOut()) {
|
||||
sdError(SD_CARD_ERROR_ACMD41);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
g_ocr = g_cardRsp;
|
||||
if (g_cardRsp & 0x40000000) {
|
||||
// Is high capacity.
|
||||
g_highCapacity = true;
|
||||
}
|
||||
if (!cardCmd(CMD2_R2, 0)) {
|
||||
sdError(SD_CARD_ERROR_CMD2);
|
||||
goto fail;
|
||||
}
|
||||
if (!cardCmd(CMD3_R6, 0)) {
|
||||
sdError(SD_CARD_ERROR_CMD3);
|
||||
goto fail;
|
||||
}
|
||||
g_rca = g_cardRsp & 0xFFFF0000;
|
||||
if (!cardCmd(CMD9_R2, g_rca, &g_csd)) {
|
||||
sdError(SD_CARD_ERROR_CMD9);
|
||||
goto fail;
|
||||
}
|
||||
if (!cardCmd(CMD10_R2, g_rca, &g_cid)) {
|
||||
sdError(SD_CARD_ERROR_CMD10);
|
||||
goto fail;
|
||||
}
|
||||
if (!cardCmd(CMD7_R1, g_rca)) {
|
||||
sdError(SD_CARD_ERROR_CMD7);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!cardAcmd(g_rca, ACMD6_R1, 2)) {
|
||||
sdError(SD_CARD_ERROR_ACMD6);
|
||||
goto fail;
|
||||
}
|
||||
if (!cardAcmd(g_rca, ACMD51_R1, 0) || !readDat(&g_scr, sizeof(g_scr))) {
|
||||
sdError(SD_CARD_ERROR_ACMD51);
|
||||
goto fail;
|
||||
}
|
||||
if (!cardAcmd(g_rca, ACMD13_R1, 0) || !readDat(&g_sds, sizeof(g_sds))) {
|
||||
sdError(SD_CARD_ERROR_ACMD13);
|
||||
goto fail;
|
||||
}
|
||||
#if HIGH_SPEED_MODE
|
||||
// Determine if High Speed mode is supported and set frequency.
|
||||
// Check status[16] for error 0XF or status[16] for new mode 0X1.
|
||||
uint8_t status[64];
|
||||
if (g_scr.sdSpec() > 0 && cardCMD6(0X00FFFFFF, status) && (2 & status[13]) &&
|
||||
cardCMD6(0X80FFFFF1, status) && (status[16] & 0XF) == 1) {
|
||||
// kHzSdClk = 50000;
|
||||
Serial.println("High Speed Mode");
|
||||
goto fail;
|
||||
} else {
|
||||
// kHzSdClk = 25000;
|
||||
Serial.println("Default Speed Mode");
|
||||
}
|
||||
#endif // HIGH_SPEED_MODE
|
||||
g_clkDiv = PIO_CLK_DIV_RUN;
|
||||
pioConfig(g_clkDiv);
|
||||
g_initDone = true;
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::cardCMD6(uint32_t arg, uint8_t* status) {
|
||||
if (!cardCmd(CMD6_R1, arg) || !readDat(status, 64)) {
|
||||
sdError(SD_CARD_ERROR_CMD6);
|
||||
goto fail;
|
||||
}
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SdioCard::end() { pioEnd(); }
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::erase(uint32_t firstSector, uint32_t lastSector) {
|
||||
Timeout timeout(SD_ERASE_TIMEOUT);
|
||||
if (!syncDevice()) {
|
||||
SDIO_FAIL();
|
||||
goto fail;
|
||||
}
|
||||
// check for single sector erase
|
||||
if (!g_csd.eraseSingleBlock()) {
|
||||
// erase size mask
|
||||
uint8_t m = g_csd.eraseSize() - 1;
|
||||
if ((firstSector & m) != 0 || ((lastSector + 1) & m) != 0) {
|
||||
// error card can't erase specified area
|
||||
sdError(SD_CARD_ERROR_ERASE_SINGLE_SECTOR);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (!g_highCapacity) {
|
||||
firstSector <<= 9;
|
||||
lastSector <<= 9;
|
||||
}
|
||||
if (!cardCmd(CMD32_R1, firstSector)) {
|
||||
sdError(SD_CARD_ERROR_CMD32);
|
||||
goto fail;
|
||||
}
|
||||
if (!cardCmd(CMD33_R1, lastSector)) {
|
||||
sdError(SD_CARD_ERROR_CMD33);
|
||||
goto fail;
|
||||
}
|
||||
if (!cardCmd(CMD38_R1, 0)) {
|
||||
sdError(SD_CARD_ERROR_CMD38);
|
||||
goto fail;
|
||||
}
|
||||
while (isBusy()) {
|
||||
if (timeout.timedOut()) {
|
||||
sdError(SD_CARD_ERROR_ERASE_TIMEOUT);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
uint8_t SdioCard::errorCode() const { return g_errorCode; }
|
||||
//------------------------------------------------------------------------------
|
||||
uint32_t SdioCard::errorData() const { return g_cardRsp; }
|
||||
//------------------------------------------------------------------------------
|
||||
uint32_t SdioCard::errorLine() const { return g_errorLine; }
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::isBusy() {
|
||||
return gpio_get(g_dat0Pin) ? false : !(status() & CARD_STATUS_READY_FOR_DATA);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::readSector(uint32_t sector, uint8_t* dst) {
|
||||
if (m_curState != READ_STATE || sector != m_curSector) {
|
||||
if (!syncDevice()) {
|
||||
SDIO_FAIL();
|
||||
goto fail;
|
||||
}
|
||||
if (!readStart(sector)) {
|
||||
sdError(SD_CARD_ERROR_READ_START);
|
||||
goto fail;
|
||||
}
|
||||
m_curSector = sector;
|
||||
m_curState = READ_STATE;
|
||||
}
|
||||
if (!readData(dst)) {
|
||||
SDIO_FAIL();
|
||||
goto fail;
|
||||
}
|
||||
m_curSector++;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::readSectors(uint32_t sector, uint8_t* dst, size_t ns) {
|
||||
for (size_t i = 0; i < ns; i++) {
|
||||
if (!readSector(sector + i, dst + i * 512UL)) {
|
||||
SDIO_FAIL();
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::readCID(cid_t* cid) {
|
||||
memcpy(cid, &g_cid, sizeof(cid_t));
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::readCSD(csd_t* csd) {
|
||||
memcpy(csd, &g_csd, sizeof(csd_t));
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool __time_critical_func(SdioCard::readData)(uint8_t* dst) {
|
||||
return readDat(dst, 512);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::readOCR(uint32_t* ocr) {
|
||||
*ocr = g_ocr;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::readSCR(scr_t* scr) {
|
||||
memcpy(scr, &g_scr, sizeof(scr_t));
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::readSDS(sds_t* sds) {
|
||||
memcpy(sds, &g_sds, sizeof(sds_t));
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::readStart(uint32_t sector) {
|
||||
uint arg = g_highCapacity ? sector : 512 * sector;
|
||||
if (!cardCmd(CMD18_R1, arg)) {
|
||||
sdError(SD_CARD_ERROR_CMD18);
|
||||
goto fail;
|
||||
}
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::readStop() { return syncDevice(); }
|
||||
//------------------------------------------------------------------------------
|
||||
uint32_t SdioCard::status() {
|
||||
return cardCmd(CMD13_R1, g_rca) ? g_cardRsp : CARD_STATUS_ERROR;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
uint32_t SdioCard::sectorCount() {
|
||||
csd_t csd;
|
||||
return readCSD(&csd) ? csd.capacity() : 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::syncDevice() {
|
||||
if (m_curState != IDLE_STATE) {
|
||||
Timeout timeout(SD_INIT_TIMEOUT);
|
||||
if (!cardCmd(CMD12_R1, 0)) {
|
||||
sdError(SD_CARD_ERROR_CMD12);
|
||||
goto fail;
|
||||
}
|
||||
while (isBusy()) {
|
||||
if (timeout.timedOut()) {
|
||||
sdError(SD_CARD_ERROR_CMD12);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
m_curState = IDLE_STATE;
|
||||
}
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
uint8_t SdioCard::type() const {
|
||||
return !g_initDone ? 0
|
||||
: !g_version2 ? SD_CARD_TYPE_SD1
|
||||
: !g_highCapacity ? SD_CARD_TYPE_SD2
|
||||
: SD_CARD_TYPE_SDHC;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::writeSector(uint32_t sector, const uint8_t* src) {
|
||||
return writeSectors(sector, src, 1);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::writeSectors(uint32_t sector, const uint8_t* src, size_t ns) {
|
||||
if (m_curState != WRITE_STATE || m_curSector != sector) {
|
||||
if (!syncDevice()) {
|
||||
sdError(SD_CARD_ERROR_CMD12);
|
||||
goto fail;
|
||||
}
|
||||
if (!writeStart(sector)) {
|
||||
sdError(SD_CARD_ERROR_WRITE_START);
|
||||
goto fail;
|
||||
}
|
||||
m_curSector = sector;
|
||||
m_curState = WRITE_STATE;
|
||||
}
|
||||
for (size_t i = 0; i < ns; i++, src += 512) {
|
||||
if (!writeData(src)) {
|
||||
sdError(SD_CARD_ERROR_WRITE_DATA);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
m_curSector += ns;
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::writeData(const uint8_t* src) { return writeDat(src); }
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::writeStart(uint32_t sector) {
|
||||
uint arg = g_highCapacity ? sector : 512 * sector;
|
||||
if (!cardCmd(CMD25_R1, arg)) {
|
||||
sdError(SD_CARD_ERROR_CMD25);
|
||||
goto fail;
|
||||
}
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::writeStop() { return syncDevice(); }
|
||||
#endif // ARDUINO_ARCH_RP2040
|
||||
175
src/SdCard/Rp2040Sdio/PioSdioCard.pio
Normal file
175
src/SdCard/Rp2040Sdio/PioSdioCard.pio
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
; Copyright (c) 2011-2024 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.
|
||||
;
|
||||
; Online assembler used to produce PioSdioCard.pio.h
|
||||
; https://wokwi.com/tools/pioasm
|
||||
|
||||
.define public SDIO_IRQ 7
|
||||
|
||||
.program cmd_rsp
|
||||
.side_set 1 opt
|
||||
.wrap_target
|
||||
cmd_begin:
|
||||
send_cmd:
|
||||
out pins, 1 side 0 [1]
|
||||
jmp X-- send_cmd side 1 [1]
|
||||
|
||||
jmp !Y cmd_begin side 0 [1]
|
||||
set pindirs, 0 side 1 [3]
|
||||
wait_resp:
|
||||
nop side 0 [3]
|
||||
nop side 1 [2]
|
||||
jmp PIN wait_resp
|
||||
|
||||
read_resp:
|
||||
in pins, 1
|
||||
push iffull block side 0 [2]
|
||||
jmp Y-- read_resp side 1 [1]
|
||||
.wrap
|
||||
|
||||
% c-sdk {
|
||||
static inline pio_sm_config pio_cmd_rsp_program_config(uint offset, uint cmd_pin, uint clk_pin, float clk_div) {
|
||||
pio_sm_config c = cmd_rsp_program_get_default_config(offset);
|
||||
sm_config_set_sideset_pins(&c, clk_pin);
|
||||
sm_config_set_out_pins(&c, cmd_pin, 1);
|
||||
sm_config_set_in_pins(&c, cmd_pin);
|
||||
sm_config_set_set_pins(&c, cmd_pin, 1);
|
||||
sm_config_set_jmp_pin(&c, cmd_pin);
|
||||
sm_config_set_in_shift(&c, false, false, 8);
|
||||
sm_config_set_out_shift(&c, false, true, 8);
|
||||
sm_config_set_clkdiv(&c, clk_div);
|
||||
return c;
|
||||
}
|
||||
%}
|
||||
.program rd_clk
|
||||
.side_set 1 opt
|
||||
wait_d0:
|
||||
nop side 0 [3]
|
||||
jmp PIN wait_d0 side 1 [3]
|
||||
|
||||
irq SDIO_IRQ
|
||||
.wrap_target
|
||||
out null, 1 side 0 [1] ; Clock stops when txFifo is empty
|
||||
nop side 1 [1]
|
||||
.wrap
|
||||
|
||||
% c-sdk {
|
||||
static inline pio_sm_config pio_rd_clk_program_config(uint offset, uint d0_pin, uint clk_pin, float clk_div) {
|
||||
pio_sm_config c = rd_clk_program_get_default_config(offset);
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||
sm_config_set_sideset_pins(&c, clk_pin);
|
||||
sm_config_set_in_pins(&c, d0_pin);
|
||||
sm_config_set_jmp_pin(&c, d0_pin);
|
||||
sm_config_set_out_shift(&c, false, true, 8);
|
||||
sm_config_set_clkdiv(&c, clk_div);
|
||||
return c;
|
||||
}
|
||||
%}
|
||||
|
||||
.program rd_data
|
||||
wait 1 irq SDIO_IRQ
|
||||
.wrap_target
|
||||
public wait0:
|
||||
wait 0 gpio 0 ; See rd_data_patch_program for CLK pin
|
||||
public wait1:
|
||||
wait 1 gpio 0 ; See rd_data_patch_program for CLK pin
|
||||
in pins, 4
|
||||
.wrap
|
||||
|
||||
% c-sdk {
|
||||
|
||||
static inline void rd_data_patch_program(pio_program *prog, uint16_t* inst, uint clk_pin) {
|
||||
*prog = rd_data_program;
|
||||
prog->instructions = inst;
|
||||
memcpy(inst, rd_data_program_instructions, sizeof(rd_data_program_instructions));
|
||||
inst[rd_data_offset_wait0] = pio_encode_wait_gpio(0, clk_pin);
|
||||
inst[rd_data_offset_wait1] = pio_encode_wait_gpio(1, clk_pin);
|
||||
}
|
||||
|
||||
static inline pio_sm_config pio_rd_data_program_config(uint offset, uint data_pin, float clk_div) {
|
||||
pio_sm_config c = rd_data_program_get_default_config(offset);
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX);
|
||||
sm_config_set_in_pins(&c, data_pin);
|
||||
sm_config_set_in_shift(&c, false, true, 32);
|
||||
sm_config_set_clkdiv(&c, clk_div);
|
||||
return c;
|
||||
}
|
||||
%}
|
||||
|
||||
|
||||
; Data transmission program
|
||||
;
|
||||
; Before running this program, pindirs should be set as output
|
||||
; and register X should be initialized with the number of nibbles
|
||||
; to send minus 1 (typically 8 + 1024 + 16 + 1 - 1 = 1048)
|
||||
;
|
||||
; Words written to TX FIFO must be:
|
||||
; - Word 0: start token 0xFFFFFFF0
|
||||
; - Word 1-128: transmitted data (512 bytes)
|
||||
; - Word 129-130: CRC checksum
|
||||
; - Word 131: end token 0xFFFFFFFF
|
||||
.program wr_data
|
||||
.side_set 1 opt
|
||||
; out X, 32
|
||||
; set pindirs, 0XF
|
||||
tx_loop:
|
||||
out pins, 4 side 0 [1]
|
||||
jmp X-- tx_loop side 1 [1]
|
||||
irq SDIO_IRQ
|
||||
.wrap_target
|
||||
nop
|
||||
.wrap
|
||||
% c-sdk {
|
||||
|
||||
|
||||
static inline pio_sm_config pio_wr_data_program_config(uint offset, uint data_pin, uint clk_pin, float clk_div) {
|
||||
pio_sm_config c = wr_data_program_get_default_config(offset);
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||
sm_config_set_sideset_pins(&c, clk_pin);
|
||||
sm_config_set_out_pins(&c, data_pin, 4);
|
||||
sm_config_set_set_pins(&c, data_pin, 4);
|
||||
sm_config_set_out_shift(&c, false, true, 32);
|
||||
sm_config_set_clkdiv(&c, clk_div);
|
||||
return c;
|
||||
}
|
||||
%}
|
||||
.program wr_resp
|
||||
.side_set 1 opt
|
||||
wait 1 irq SDIO_IRQ
|
||||
set pindirs, 0 [1]
|
||||
.wrap_target
|
||||
in pins, 1 side 1 [4]
|
||||
push iffull noblock side 0 [4]
|
||||
.wrap
|
||||
|
||||
% c-sdk {
|
||||
static inline pio_sm_config pio_wr_resp_program_config(uint offset, uint data_pin, uint clk_pin, float clk_div) {
|
||||
pio_sm_config c = wr_resp_program_get_default_config(offset);
|
||||
sm_config_set_sideset_pins(&c, clk_pin);
|
||||
sm_config_set_in_pins(&c, data_pin);
|
||||
sm_config_set_set_pins(&c, data_pin, 4);
|
||||
sm_config_set_in_shift(&c, false, false, 8);
|
||||
sm_config_set_clkdiv(&c, clk_div);
|
||||
return c;
|
||||
}
|
||||
%}
|
||||
241
src/SdCard/Rp2040Sdio/PioSdioCard.pio.h
Normal file
241
src/SdCard/Rp2040Sdio/PioSdioCard.pio.h
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
// -------------------------------------------------- //
|
||||
// This file is autogenerated by pioasm; do not edit! //
|
||||
// -------------------------------------------------- //
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
#include "hardware/pio.h"
|
||||
#endif
|
||||
|
||||
#define SDIO_IRQ 7
|
||||
|
||||
// ------- //
|
||||
// cmd_rsp //
|
||||
// ------- //
|
||||
|
||||
#define cmd_rsp_wrap_target 0
|
||||
#define cmd_rsp_wrap 9
|
||||
|
||||
static const uint16_t cmd_rsp_program_instructions[] = {
|
||||
// .wrap_target
|
||||
0x7101, // 0: out pins, 1 side 0 [1]
|
||||
0x1940, // 1: jmp x--, 0 side 1 [1]
|
||||
0x1160, // 2: jmp !y, 0 side 0 [1]
|
||||
0xfb80, // 3: set pindirs, 0 side 1 [3]
|
||||
0xb342, // 4: nop side 0 [3]
|
||||
0xba42, // 5: nop side 1 [2]
|
||||
0x00c4, // 6: jmp pin, 4
|
||||
0x4001, // 7: in pins, 1
|
||||
0x9260, // 8: push iffull block side 0 [2]
|
||||
0x1987, // 9: jmp y--, 7 side 1 [1]
|
||||
// .wrap
|
||||
};
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
static const struct pio_program cmd_rsp_program = {
|
||||
.instructions = cmd_rsp_program_instructions,
|
||||
.length = 10,
|
||||
.origin = -1,
|
||||
};
|
||||
|
||||
static inline pio_sm_config cmd_rsp_program_get_default_config(uint offset) {
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_wrap(&c, offset + cmd_rsp_wrap_target, offset + cmd_rsp_wrap);
|
||||
sm_config_set_sideset(&c, 2, true, false);
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline pio_sm_config pio_cmd_rsp_program_config(uint offset, uint cmd_pin, uint clk_pin, float clk_div) {
|
||||
pio_sm_config c = cmd_rsp_program_get_default_config(offset);
|
||||
sm_config_set_sideset_pins(&c, clk_pin);
|
||||
sm_config_set_out_pins(&c, cmd_pin, 1);
|
||||
sm_config_set_in_pins(&c, cmd_pin);
|
||||
sm_config_set_set_pins(&c, cmd_pin, 1);
|
||||
sm_config_set_jmp_pin(&c, cmd_pin);
|
||||
sm_config_set_in_shift(&c, false, false, 8);
|
||||
sm_config_set_out_shift(&c, false, true, 8);
|
||||
sm_config_set_clkdiv(&c, clk_div);
|
||||
return c;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// ------ //
|
||||
// rd_clk //
|
||||
// ------ //
|
||||
|
||||
#define rd_clk_wrap_target 3
|
||||
#define rd_clk_wrap 4
|
||||
|
||||
static const uint16_t rd_clk_program_instructions[] = {
|
||||
0xb342, // 0: nop side 0 [3]
|
||||
0x1bc0, // 1: jmp pin, 0 side 1 [3]
|
||||
0xc007, // 2: irq nowait 7
|
||||
// .wrap_target
|
||||
0x7161, // 3: out null, 1 side 0 [1]
|
||||
0xb942, // 4: nop side 1 [1]
|
||||
// .wrap
|
||||
};
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
static const struct pio_program rd_clk_program = {
|
||||
.instructions = rd_clk_program_instructions,
|
||||
.length = 5,
|
||||
.origin = -1,
|
||||
};
|
||||
|
||||
static inline pio_sm_config rd_clk_program_get_default_config(uint offset) {
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_wrap(&c, offset + rd_clk_wrap_target, offset + rd_clk_wrap);
|
||||
sm_config_set_sideset(&c, 2, true, false);
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline pio_sm_config pio_rd_clk_program_config(uint offset, uint d0_pin, uint clk_pin, float clk_div) {
|
||||
pio_sm_config c = rd_clk_program_get_default_config(offset);
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||
sm_config_set_sideset_pins(&c, clk_pin);
|
||||
sm_config_set_in_pins(&c, d0_pin);
|
||||
sm_config_set_jmp_pin(&c, d0_pin);
|
||||
sm_config_set_out_shift(&c, false, true, 8);
|
||||
sm_config_set_clkdiv(&c, clk_div);
|
||||
return c;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// ------- //
|
||||
// rd_data //
|
||||
// ------- //
|
||||
|
||||
#define rd_data_wrap_target 1
|
||||
#define rd_data_wrap 3
|
||||
|
||||
#define rd_data_offset_wait0 1u
|
||||
#define rd_data_offset_wait1 2u
|
||||
|
||||
static const uint16_t rd_data_program_instructions[] = {
|
||||
0x20c7, // 0: wait 1 irq, 7
|
||||
// .wrap_target
|
||||
0x2000, // 1: wait 0 gpio, 0
|
||||
0x2080, // 2: wait 1 gpio, 0
|
||||
0x4004, // 3: in pins, 4
|
||||
// .wrap
|
||||
};
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
static const struct pio_program rd_data_program = {
|
||||
.instructions = rd_data_program_instructions,
|
||||
.length = 4,
|
||||
.origin = -1,
|
||||
};
|
||||
|
||||
static inline pio_sm_config rd_data_program_get_default_config(uint offset) {
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_wrap(&c, offset + rd_data_wrap_target, offset + rd_data_wrap);
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline void rd_data_patch_program(pio_program *prog, uint16_t* inst, uint clk_pin) {
|
||||
*prog = rd_data_program;
|
||||
prog->instructions = inst;
|
||||
memcpy(inst, rd_data_program_instructions, sizeof(rd_data_program_instructions));
|
||||
inst[rd_data_offset_wait0] = pio_encode_wait_gpio(0, clk_pin);
|
||||
inst[rd_data_offset_wait1] = pio_encode_wait_gpio(1, clk_pin);
|
||||
}
|
||||
static inline pio_sm_config pio_rd_data_program_config(uint offset, uint data_pin, float clk_div) {
|
||||
pio_sm_config c = rd_data_program_get_default_config(offset);
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX);
|
||||
sm_config_set_in_pins(&c, data_pin);
|
||||
sm_config_set_in_shift(&c, false, true, 32);
|
||||
sm_config_set_clkdiv(&c, clk_div);
|
||||
return c;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// ------- //
|
||||
// wr_data //
|
||||
// ------- //
|
||||
|
||||
#define wr_data_wrap_target 3
|
||||
#define wr_data_wrap 3
|
||||
|
||||
static const uint16_t wr_data_program_instructions[] = {
|
||||
0x7104, // 0: out pins, 4 side 0 [1]
|
||||
0x1940, // 1: jmp x--, 0 side 1 [1]
|
||||
0xc007, // 2: irq nowait 7
|
||||
// .wrap_target
|
||||
0xa042, // 3: nop
|
||||
// .wrap
|
||||
};
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
static const struct pio_program wr_data_program = {
|
||||
.instructions = wr_data_program_instructions,
|
||||
.length = 4,
|
||||
.origin = -1,
|
||||
};
|
||||
|
||||
static inline pio_sm_config wr_data_program_get_default_config(uint offset) {
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_wrap(&c, offset + wr_data_wrap_target, offset + wr_data_wrap);
|
||||
sm_config_set_sideset(&c, 2, true, false);
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline pio_sm_config pio_wr_data_program_config(uint offset, uint data_pin, uint clk_pin, float clk_div) {
|
||||
pio_sm_config c = wr_data_program_get_default_config(offset);
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||
sm_config_set_sideset_pins(&c, clk_pin);
|
||||
sm_config_set_out_pins(&c, data_pin, 4);
|
||||
sm_config_set_set_pins(&c, data_pin, 4);
|
||||
sm_config_set_out_shift(&c, false, true, 32);
|
||||
sm_config_set_clkdiv(&c, clk_div);
|
||||
return c;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// ------- //
|
||||
// wr_resp //
|
||||
// ------- //
|
||||
|
||||
#define wr_resp_wrap_target 2
|
||||
#define wr_resp_wrap 3
|
||||
|
||||
static const uint16_t wr_resp_program_instructions[] = {
|
||||
0x20c7, // 0: wait 1 irq, 7
|
||||
0xe180, // 1: set pindirs, 0 [1]
|
||||
// .wrap_target
|
||||
0x5c01, // 2: in pins, 1 side 1 [4]
|
||||
0x9440, // 3: push iffull noblock side 0 [4]
|
||||
// .wrap
|
||||
};
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
static const struct pio_program wr_resp_program = {
|
||||
.instructions = wr_resp_program_instructions,
|
||||
.length = 4,
|
||||
.origin = -1,
|
||||
};
|
||||
|
||||
static inline pio_sm_config wr_resp_program_get_default_config(uint offset) {
|
||||
pio_sm_config c = pio_get_default_sm_config();
|
||||
sm_config_set_wrap(&c, offset + wr_resp_wrap_target, offset + wr_resp_wrap);
|
||||
sm_config_set_sideset(&c, 2, true, false);
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline pio_sm_config pio_wr_resp_program_config(uint offset, uint data_pin, uint clk_pin, float clk_div) {
|
||||
pio_sm_config c = wr_resp_program_get_default_config(offset);
|
||||
sm_config_set_sideset_pins(&c, clk_pin);
|
||||
sm_config_set_in_pins(&c, data_pin);
|
||||
sm_config_set_set_pins(&c, data_pin, 4);
|
||||
sm_config_set_in_shift(&c, false, false, 8);
|
||||
sm_config_set_clkdiv(&c, clk_div);
|
||||
return c;
|
||||
}
|
||||
|
||||
#endif
|
||||
52
src/SdCard/Rp2040Sdio/Rp2040SdioConfig.h
Normal file
52
src/SdCard/Rp2040Sdio/Rp2040SdioConfig.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2024 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.
|
||||
*/
|
||||
#pragma once
|
||||
/**
|
||||
* \class SdioConfig
|
||||
* \brief SDIO card configuration.
|
||||
*/
|
||||
class SdioConfig {
|
||||
public:
|
||||
/**
|
||||
* SdioConfig constructor.
|
||||
* \param[in] clkPin gpio pin for SDIO CLK.
|
||||
* \param[in] cmdPin gpio pin for SDIO CMD.
|
||||
* \param[in] dat0Pin gpio start pin for SDIO DAT[4].
|
||||
*/
|
||||
SdioConfig(uint clkPin, uint cmdPin, uint dat0Pin)
|
||||
: m_clkPin(clkPin), m_cmdPin(cmdPin), m_dat0Pin(dat0Pin) {}
|
||||
/** \return gpio for SDIO CLK */
|
||||
uint clkPin() { return m_clkPin; }
|
||||
/** \return gpio for SDIO CMD */
|
||||
uint cmdPin() { return m_cmdPin; }
|
||||
/** \return gpio for SDIO DAT0 */
|
||||
uint dat0Pin() { return m_dat0Pin; }
|
||||
|
||||
private:
|
||||
SdioConfig() : m_clkPin(31u), m_cmdPin(31u), m_dat0Pin(31u) {}
|
||||
const uint8_t m_clkPin;
|
||||
const uint8_t m_cmdPin;
|
||||
const uint8_t m_dat0Pin;
|
||||
};
|
||||
|
|
@ -26,8 +26,7 @@
|
|||
* \file
|
||||
* \brief Top level include for SPI and SDIO cards.
|
||||
*/
|
||||
#ifndef SdCard_h
|
||||
#define SdCard_h
|
||||
#pragma once
|
||||
#include "SdSpiCard.h"
|
||||
#include "SdioCard.h"
|
||||
#if HAS_SDIO_CLASS
|
||||
|
|
@ -91,4 +90,3 @@ class SdCardFactory {
|
|||
#endif // HAS_SDIO_CLASS
|
||||
SdSpiCard m_spiCard;
|
||||
};
|
||||
#endif // SdCard_h
|
||||
|
|
|
|||
|
|
@ -120,9 +120,9 @@ static uint16_t CRC_CCITT(const uint8_t* data, size_t n) {
|
|||
#endif // CRC_CCITT
|
||||
#endif // USE_SD_CRC
|
||||
//==============================================================================
|
||||
// SharedSpiCard member functions
|
||||
// SdSpiCard member functions
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::begin(SdSpiConfig spiConfig) {
|
||||
bool SdSpiCard::begin(SdSpiConfig spiConfig) {
|
||||
uint8_t cardType;
|
||||
uint32_t arg;
|
||||
Timeout timeout;
|
||||
|
|
@ -213,6 +213,9 @@ bool SharedSpiCard::begin(SdSpiConfig spiConfig) {
|
|||
spiStop();
|
||||
spiSetSckSpeed(spiConfig.maxSck);
|
||||
m_type = cardType;
|
||||
#if ENABLE_DEDICATED_SPI
|
||||
m_dedicatedSpi = spiOptionDedicated(spiConfig.options);
|
||||
#endif
|
||||
return true;
|
||||
|
||||
fail:
|
||||
|
|
@ -220,7 +223,7 @@ fail:
|
|||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::cardCMD6(uint32_t arg, uint8_t* status) {
|
||||
bool SdSpiCard::cardCMD6(uint32_t arg, uint8_t* status) {
|
||||
if (cardCommand(CMD6, arg)) {
|
||||
error(SD_CARD_ERROR_CMD6);
|
||||
goto fail;
|
||||
|
|
@ -237,7 +240,7 @@ fail:
|
|||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// send command and return error code. Return zero for OK
|
||||
uint8_t SharedSpiCard::cardCommand(uint8_t cmd, uint32_t arg) {
|
||||
uint8_t SdSpiCard::cardCommand(uint8_t cmd, uint32_t arg) {
|
||||
if (!syncDevice()) {
|
||||
return 0XFF;
|
||||
}
|
||||
|
|
@ -267,7 +270,7 @@ uint8_t SharedSpiCard::cardCommand(uint8_t cmd, uint32_t arg) {
|
|||
spiSend(cmd | 0x40);
|
||||
|
||||
// send argument
|
||||
uint8_t* pa = reinterpret_cast<uint8_t*>(&arg);
|
||||
const uint8_t* pa = reinterpret_cast<uint8_t*>(&arg);
|
||||
for (int8_t i = 3; i >= 0; i--) {
|
||||
spiSend(pa[i]);
|
||||
}
|
||||
|
|
@ -287,7 +290,7 @@ uint8_t SharedSpiCard::cardCommand(uint8_t cmd, uint32_t arg) {
|
|||
return m_status;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SharedSpiCard::end() {
|
||||
void SdSpiCard::end() {
|
||||
if (m_beginCalled) {
|
||||
syncDevice();
|
||||
spiEnd();
|
||||
|
|
@ -295,7 +298,7 @@ void SharedSpiCard::end() {
|
|||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::erase(uint32_t firstSector, uint32_t lastSector) {
|
||||
bool SdSpiCard::erase(uint32_t firstSector, uint32_t lastSector) {
|
||||
csd_t csd;
|
||||
if (!readCSD(&csd)) {
|
||||
goto fail;
|
||||
|
|
@ -331,12 +334,12 @@ fail:
|
|||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::eraseSingleSectorEnable() {
|
||||
bool SdSpiCard::eraseSingleSectorEnable() {
|
||||
csd_t csd;
|
||||
return readCSD(&csd) ? csd.eraseSingleBlock() : false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::isBusy() {
|
||||
bool SdSpiCard::isBusy() {
|
||||
if (m_state == READ_STATE) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -351,9 +354,9 @@ bool SharedSpiCard::isBusy() {
|
|||
return rtn;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::readData(uint8_t* dst) { return readData(dst, 512); }
|
||||
bool SdSpiCard::readData(uint8_t* dst) { return readData(dst, 512); }
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::readData(uint8_t* dst, size_t count) {
|
||||
bool SdSpiCard::readData(uint8_t* dst, size_t count) {
|
||||
#if USE_SD_CRC
|
||||
uint16_t crc;
|
||||
#endif // USE_SD_CRC
|
||||
|
|
@ -371,6 +374,8 @@ bool SharedSpiCard::readData(uint8_t* dst, size_t count) {
|
|||
goto fail;
|
||||
}
|
||||
// transfer data
|
||||
// cppcheck wrong - Due can return non-zero.
|
||||
// cppcheck-suppress knownConditionTrueFalse
|
||||
if ((m_status = spiReceive(dst, count))) {
|
||||
error(SD_CARD_ERROR_DMA);
|
||||
goto fail;
|
||||
|
|
@ -395,7 +400,7 @@ fail:
|
|||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::readOCR(uint32_t* ocr) {
|
||||
bool SdSpiCard::readOCR(uint32_t* ocr) {
|
||||
uint8_t* p = reinterpret_cast<uint8_t*>(ocr);
|
||||
if (cardCommand(CMD58, 0)) {
|
||||
error(SD_CARD_ERROR_CMD58);
|
||||
|
|
@ -417,7 +422,7 @@ fail:
|
|||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** read CID or CSR register */
|
||||
bool SharedSpiCard::readRegister(uint8_t cmd, void* buf) {
|
||||
bool SdSpiCard::readRegister(uint8_t cmd, void* buf) {
|
||||
uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
|
||||
if (cardCommand(cmd, 0)) {
|
||||
error(SD_CARD_ERROR_READ_REG);
|
||||
|
|
@ -434,7 +439,7 @@ fail:
|
|||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::readSCR(scr_t* scr) {
|
||||
bool SdSpiCard::readSCR(scr_t* scr) {
|
||||
uint8_t* dst = reinterpret_cast<uint8_t*>(scr);
|
||||
if (cardAcmd(ACMD51, 0)) {
|
||||
error(SD_CARD_ERROR_ACMD51);
|
||||
|
|
@ -451,7 +456,10 @@ fail:
|
|||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::readSector(uint32_t sector, uint8_t* dst) {
|
||||
bool SdSpiCard::readSector(uint32_t sector, uint8_t* dst) {
|
||||
#if ENABLE_DEDICATED_SPI
|
||||
return readSectors(sector, dst, 1);
|
||||
#else
|
||||
// use address if not SDHC card
|
||||
if (type() != SD_CARD_TYPE_SDHC) {
|
||||
sector <<= 9;
|
||||
|
|
@ -469,9 +477,25 @@ bool SharedSpiCard::readSector(uint32_t sector, uint8_t* dst) {
|
|||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::readSectors(uint32_t sector, uint8_t* dst, size_t ns) {
|
||||
bool SdSpiCard::readSectors(uint32_t sector, uint8_t* dst, size_t ns) {
|
||||
#if ENABLE_DEDICATED_SPI
|
||||
if (sdState() != READ_STATE || sector != m_curSector) {
|
||||
if (!readStart(sector)) {
|
||||
goto fail;
|
||||
}
|
||||
m_curSector = sector;
|
||||
}
|
||||
for (size_t i = 0; i < ns; i++, dst += 512) {
|
||||
if (!readData(dst)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
m_curSector += ns;
|
||||
return m_dedicatedSpi ? true : readStop();
|
||||
#else
|
||||
if (!readStart(sector)) {
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -481,11 +505,12 @@ bool SharedSpiCard::readSectors(uint32_t sector, uint8_t* dst, size_t ns) {
|
|||
}
|
||||
}
|
||||
return readStop();
|
||||
#endif
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::readStart(uint32_t sector) {
|
||||
bool SdSpiCard::readStart(uint32_t sector) {
|
||||
if (type() != SD_CARD_TYPE_SDHC) {
|
||||
sector <<= 9;
|
||||
}
|
||||
|
|
@ -501,7 +526,7 @@ fail:
|
|||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::readSDS(sds_t* sds) {
|
||||
bool SdSpiCard::readSDS(sds_t* sds) {
|
||||
uint8_t* dst = reinterpret_cast<uint8_t*>(sds);
|
||||
// retrun is R2 so read extra status byte.
|
||||
if (cardAcmd(ACMD13, 0) || spiReceive()) {
|
||||
|
|
@ -519,7 +544,7 @@ fail:
|
|||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::readStop() {
|
||||
bool SdSpiCard::readStop() {
|
||||
m_state = IDLE_STATE;
|
||||
if (cardCommand(CMD12, 0)) {
|
||||
error(SD_CARD_ERROR_CMD12);
|
||||
|
|
@ -533,12 +558,25 @@ fail:
|
|||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
uint32_t SharedSpiCard::sectorCount() {
|
||||
uint32_t SdSpiCard::sectorCount() {
|
||||
csd_t csd;
|
||||
return readCSD(&csd) ? csd.capacity() : 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SharedSpiCard::spiStart() {
|
||||
bool SdSpiCard::setDedicatedSpi(bool value) {
|
||||
#if ENABLE_DEDICATED_SPI
|
||||
if (!syncDevice()) {
|
||||
return false;
|
||||
}
|
||||
m_dedicatedSpi = value;
|
||||
return true;
|
||||
#else // ENABLE_DEDICATED_SPI
|
||||
(void)value;
|
||||
return false;
|
||||
#endif // ENABLE_DEDICATED_SPI
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiCard::spiStart() {
|
||||
SPI_ASSERT_NOT_ACTIVE;
|
||||
if (!m_spiActive) {
|
||||
spiActivate();
|
||||
|
|
@ -549,7 +587,7 @@ void SharedSpiCard::spiStart() {
|
|||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SharedSpiCard::spiStop() {
|
||||
void SdSpiCard::spiStop() {
|
||||
SPI_ASSERT_ACTIVE;
|
||||
if (m_spiActive) {
|
||||
spiUnselect();
|
||||
|
|
@ -560,7 +598,7 @@ void SharedSpiCard::spiStop() {
|
|||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::syncDevice() {
|
||||
bool SdSpiCard::syncDevice() {
|
||||
if (m_state == WRITE_STATE) {
|
||||
return writeStop();
|
||||
}
|
||||
|
|
@ -570,7 +608,7 @@ bool SharedSpiCard::syncDevice() {
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::waitReady(uint16_t ms) {
|
||||
bool SdSpiCard::waitReady(uint16_t ms) {
|
||||
Timeout timeout(ms);
|
||||
while (spiReceive() != 0XFF) {
|
||||
if (timeout.timedOut()) {
|
||||
|
|
@ -580,7 +618,7 @@ bool SharedSpiCard::waitReady(uint16_t ms) {
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::writeData(const uint8_t* src) {
|
||||
bool SdSpiCard::writeData(const uint8_t* src) {
|
||||
// wait for previous write to finish
|
||||
if (!waitReady(SD_WRITE_TIMEOUT)) {
|
||||
error(SD_CARD_ERROR_WRITE_TIMEOUT);
|
||||
|
|
@ -597,7 +635,7 @@ fail:
|
|||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// send one sector of data for write sector or write multiple sectors
|
||||
bool SharedSpiCard::writeData(uint8_t token, const uint8_t* src) {
|
||||
bool SdSpiCard::writeData(uint8_t token, const uint8_t* src) {
|
||||
#if USE_SD_CRC
|
||||
uint16_t crc = CRC_CCITT(src, 512);
|
||||
#else // USE_SD_CRC
|
||||
|
|
@ -620,7 +658,14 @@ fail:
|
|||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::writeSector(uint32_t sector, const uint8_t* src) {
|
||||
bool SdSpiCard::writeSector(uint32_t sector, const uint8_t* src) {
|
||||
#ifndef OLD_WAY_WRITE_SECTOR
|
||||
#if ENABLE_DEDICATED_SPI
|
||||
if (m_dedicatedSpi) {
|
||||
return writeSectors(sector, src, 1);
|
||||
}
|
||||
#endif
|
||||
#endif // OLD_WAY_WRITE_SECTOR
|
||||
// use address if not SDHC card
|
||||
if (type() != SD_CARD_TYPE_SDHC) {
|
||||
sector <<= 9;
|
||||
|
|
@ -654,8 +699,22 @@ fail:
|
|||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::writeSectors(uint32_t sector, const uint8_t* src,
|
||||
size_t ns) {
|
||||
bool SdSpiCard::writeSectors(uint32_t sector, const uint8_t* src, size_t ns) {
|
||||
#if ENABLE_DEDICATED_SPI
|
||||
if (sdState() != WRITE_STATE || m_curSector != sector) {
|
||||
if (!writeStart(sector)) {
|
||||
goto fail;
|
||||
}
|
||||
m_curSector = sector;
|
||||
}
|
||||
for (size_t i = 0; i < ns; i++, src += 512) {
|
||||
if (!writeData(src)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
m_curSector += ns;
|
||||
return m_dedicatedSpi ? true : writeStop();
|
||||
#else
|
||||
if (!writeStart(sector)) {
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -665,13 +724,13 @@ bool SharedSpiCard::writeSectors(uint32_t sector, const uint8_t* src,
|
|||
}
|
||||
}
|
||||
return writeStop();
|
||||
|
||||
#endif
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::writeStart(uint32_t sector) {
|
||||
bool SdSpiCard::writeStart(uint32_t sector) {
|
||||
// use address if not SDHC card
|
||||
if (type() != SD_CARD_TYPE_SDHC) {
|
||||
sector <<= 9;
|
||||
|
|
@ -688,7 +747,7 @@ fail:
|
|||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SharedSpiCard::writeStop() {
|
||||
bool SdSpiCard::writeStop() {
|
||||
if (!waitReady(SD_WRITE_TIMEOUT)) {
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -702,69 +761,3 @@ fail:
|
|||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//==============================================================================
|
||||
bool DedicatedSpiCard::begin(SdSpiConfig spiConfig) {
|
||||
if (!SharedSpiCard::begin(spiConfig)) {
|
||||
return false;
|
||||
}
|
||||
m_dedicatedSpi = spiOptionDedicated(spiConfig.options);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool DedicatedSpiCard::readSector(uint32_t sector, uint8_t* dst) {
|
||||
return readSectors(sector, dst, 1);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool DedicatedSpiCard::readSectors(uint32_t sector, uint8_t* dst, size_t ns) {
|
||||
if (sdState() != READ_STATE || sector != m_curSector) {
|
||||
if (!readStart(sector)) {
|
||||
goto fail;
|
||||
}
|
||||
m_curSector = sector;
|
||||
}
|
||||
for (size_t i = 0; i < ns; i++, dst += 512) {
|
||||
if (!readData(dst)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
m_curSector += ns;
|
||||
return m_dedicatedSpi ? true : readStop();
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool DedicatedSpiCard::setDedicatedSpi(bool value) {
|
||||
if (!syncDevice()) {
|
||||
return false;
|
||||
}
|
||||
m_dedicatedSpi = value;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool DedicatedSpiCard::writeSector(uint32_t sector, const uint8_t* src) {
|
||||
if (m_dedicatedSpi) {
|
||||
return writeSectors(sector, src, 1);
|
||||
}
|
||||
return SharedSpiCard::writeSector(sector, src);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool DedicatedSpiCard::writeSectors(uint32_t sector, const uint8_t* src,
|
||||
size_t ns) {
|
||||
if (sdState() != WRITE_STATE || m_curSector != sector) {
|
||||
if (!writeStart(sector)) {
|
||||
goto fail;
|
||||
}
|
||||
m_curSector = sector;
|
||||
}
|
||||
for (size_t i = 0; i < ns; i++, src += 512) {
|
||||
if (!writeData(src)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
m_curSector += ns;
|
||||
return m_dedicatedSpi ? true : writeStop();
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -26,8 +26,7 @@
|
|||
* \file
|
||||
* \brief Classes for SPI access to SD/SDHC cards.
|
||||
*/
|
||||
#ifndef SdSpiCard_h
|
||||
#define SdSpiCard_h
|
||||
#pragma once
|
||||
#include <stddef.h>
|
||||
|
||||
#include "../SpiDriver/SdSpiDriver.h"
|
||||
|
|
@ -43,8 +42,8 @@
|
|||
if (!m_spiActive) { \
|
||||
Serial.print(F("SPI_ASSERT_ACTIVE")); \
|
||||
Serial.println(__LINE__); \
|
||||
while (true) \
|
||||
; \
|
||||
while (true) { \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
#define SPI_ASSERT_NOT_ACTIVE \
|
||||
|
|
@ -52,8 +51,8 @@
|
|||
if (m_spiActive) { \
|
||||
Serial.print(F("SPI_ASSERT_NOT_ACTIVE")); \
|
||||
Serial.println(__LINE__); \
|
||||
while (true) \
|
||||
; \
|
||||
while (true) { \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
#else // CHECK_SPI_ACTIVE
|
||||
|
|
@ -64,15 +63,15 @@
|
|||
#endif // CHECK_SPI_ACTIVE
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class SharedSpiCard
|
||||
* \class SdSpiCard
|
||||
* \brief Raw access to SD and SDHC flash memory cards via shared SPI port.
|
||||
*/
|
||||
#if HAS_SDIO_CLASS
|
||||
class SharedSpiCard : public SdCardInterface {
|
||||
class SdSpiCard : public SdCardInterface {
|
||||
#elif USE_BLOCK_DEVICE_INTERFACE
|
||||
class SharedSpiCard : public FsBlockDeviceInterface {
|
||||
class SdSpiCard : public FsBlockDeviceInterface {
|
||||
#else // HAS_SDIO_CLASS
|
||||
class SharedSpiCard {
|
||||
class SdSpiCard {
|
||||
#endif // HAS_SDIO_CLASS
|
||||
public:
|
||||
/** SD is in idle state */
|
||||
|
|
@ -81,8 +80,8 @@ class SharedSpiCard {
|
|||
static const uint8_t READ_STATE = 1;
|
||||
/** SD is in multi-sector write state. */
|
||||
static const uint8_t WRITE_STATE = 2;
|
||||
/** Construct an instance of SharedSpiCard. */
|
||||
SharedSpiCard() { initSharedSpiCard(); }
|
||||
/** Construct an instance of SdSpiCard. */
|
||||
SdSpiCard() { initSharedSpiCard(); }
|
||||
/** Initialize the SD card.
|
||||
* \param[in] spiConfig SPI card configuration.
|
||||
* \return true for success or false for failure.
|
||||
|
|
@ -131,16 +130,24 @@ class SharedSpiCard {
|
|||
uint8_t errorCode() const { return m_errorCode; }
|
||||
/** \return error data for last error. */
|
||||
uint32_t errorData() const { return m_status; }
|
||||
/** \return false for shared class. */
|
||||
/** \return false for shared class. */
|
||||
#if ENABLE_DEDICATED_SPI
|
||||
bool hasDedicatedSpi() { return true; }
|
||||
#else
|
||||
bool hasDedicatedSpi() { return false; }
|
||||
#endif
|
||||
/**
|
||||
* Check for busy. MISO low indicates the card is busy.
|
||||
*
|
||||
* \return true if busy else false.
|
||||
*/
|
||||
bool isBusy();
|
||||
/** \return false, can't be in dedicated state. */
|
||||
/** \return true if in dedicated SPI state. */
|
||||
#if ENABLE_DEDICATED_SPI
|
||||
bool isDedicatedSpi() { return m_dedicatedSpi; }
|
||||
#else // ENABLE_DEDICATED_SPI
|
||||
bool isDedicatedSpi() { return false; }
|
||||
#endif // ENABLE_DEDICATED_SPI
|
||||
/** \return true if card is on SPI bus. */
|
||||
bool isSpi() { return true; }
|
||||
/**
|
||||
|
|
@ -198,7 +205,6 @@ class SharedSpiCard {
|
|||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readSectors(uint32_t sector, uint8_t* dst, size_t ns);
|
||||
|
||||
/** Start a read multiple sector sequence.
|
||||
*
|
||||
* \param[in] sector Address of first sector in sequence.
|
||||
|
|
@ -228,19 +234,12 @@ class SharedSpiCard {
|
|||
* or zero if an error occurs.
|
||||
*/
|
||||
uint32_t sectorCount();
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
// Use sectorCount(). cardSize() will be removed in the future.
|
||||
uint32_t __attribute__((error("use sectorCount()"))) cardSize();
|
||||
#endif // DOXYGEN_SHOULD_SKIP_THIS
|
||||
/** Set SPI sharing state
|
||||
* \param[in] value desired state.
|
||||
* \return false for shared card
|
||||
* \return true for success.
|
||||
*/
|
||||
bool setDedicatedSpi(bool value) {
|
||||
(void)value;
|
||||
return false;
|
||||
}
|
||||
/** end a mult-sector transfer.
|
||||
bool setDedicatedSpi(bool value);
|
||||
/** end a multi-sector transfer.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
|
|
@ -362,6 +361,10 @@ class SharedSpiCard {
|
|||
m_status = 0;
|
||||
m_type = 0;
|
||||
}
|
||||
#if ENABLE_DEDICATED_SPI
|
||||
uint32_t m_curSector = 0;
|
||||
bool m_dedicatedSpi = false;
|
||||
#endif // ENABLE_DEDICATED_SPI
|
||||
bool m_beginCalled;
|
||||
SdCsPin_t m_csPin;
|
||||
uint8_t m_errorCode;
|
||||
|
|
@ -370,74 +373,3 @@ class SharedSpiCard {
|
|||
uint8_t m_status;
|
||||
uint8_t m_type;
|
||||
};
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class DedicatedSpiCard
|
||||
* \brief Raw access to SD and SDHC flash memory cards via dedicate SPI port.
|
||||
*/
|
||||
class DedicatedSpiCard : public SharedSpiCard {
|
||||
public:
|
||||
/** Construct an instance of DedicatedSpiCard. */
|
||||
DedicatedSpiCard() = default;
|
||||
/** Initialize the SD card.
|
||||
* \param[in] spiConfig SPI card configuration.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool begin(SdSpiConfig spiConfig);
|
||||
/** \return true, can be in dedicaded state. */
|
||||
bool hasDedicatedSpi() { return true; }
|
||||
/** \return true if in dedicated SPI state. */
|
||||
bool isDedicatedSpi() { return m_dedicatedSpi; }
|
||||
/**
|
||||
* Read a 512 byte sector from an SD card.
|
||||
*
|
||||
* \param[in] sector Logical sector to be read.
|
||||
* \param[out] dst Pointer to the location that will receive the data.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readSector(uint32_t sector, uint8_t* dst);
|
||||
/**
|
||||
* Read multiple 512 byte sectors from an SD card.
|
||||
*
|
||||
* \param[in] sector Logical sector to be read.
|
||||
* \param[in] ns Number of sectors to be read.
|
||||
* \param[out] dst Pointer to the location that will receive the data.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readSectors(uint32_t sector, uint8_t* dst, size_t ns);
|
||||
/** Set SPI sharing state
|
||||
* \param[in] value desired state.
|
||||
* \return true for success else false;
|
||||
*/
|
||||
bool setDedicatedSpi(bool value);
|
||||
/**
|
||||
* Write a 512 byte sector to an SD card.
|
||||
*
|
||||
* \param[in] sector Logical sector to be written.
|
||||
* \param[in] src Pointer to the location of the data to be written.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool writeSector(uint32_t sector, const uint8_t* src);
|
||||
/**
|
||||
* Write multiple 512 byte sectors to an SD card.
|
||||
*
|
||||
* \param[in] sector Logical sector to be written.
|
||||
* \param[in] ns Number of sectors to be written.
|
||||
* \param[in] src Pointer to the location of the data to be written.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool writeSectors(uint32_t sector, const uint8_t* src, size_t ns);
|
||||
|
||||
private:
|
||||
uint32_t m_curSector = 0;
|
||||
bool m_dedicatedSpi = false;
|
||||
};
|
||||
//==============================================================================
|
||||
#if ENABLE_DEDICATED_SPI
|
||||
/** typedef for dedicated SPI. */
|
||||
typedef DedicatedSpiCard SdSpiCard;
|
||||
#else
|
||||
/** typedef for shared SPI. */
|
||||
typedef SharedSpiCard SdSpiCard;
|
||||
#endif
|
||||
#endif // SdSpiCard_h
|
||||
|
|
|
|||
|
|
@ -26,34 +26,18 @@
|
|||
* \file
|
||||
* \brief Classes for SDIO cards.
|
||||
*/
|
||||
#ifndef SdioCard_h
|
||||
#define SdioCard_h
|
||||
#pragma once
|
||||
#include "../common/SysCall.h"
|
||||
#include "SdCardInterface.h"
|
||||
/** Use programmed I/O with FIFO. */
|
||||
#define FIFO_SDIO 0
|
||||
/** Use programmed I/O with DMA. */
|
||||
#define DMA_SDIO 1
|
||||
#ifdef SDIO_CONFIG_INCLUDE
|
||||
#include SDIO_CONFIG_INCLUDE
|
||||
#else // SDIO_CONFIG_INCLUDE
|
||||
/**
|
||||
* \class SdioConfig
|
||||
* \brief SDIO card configuration.
|
||||
* \brief Empty SDIO card configuration.
|
||||
*/
|
||||
class SdioConfig {
|
||||
public:
|
||||
SdioConfig() {}
|
||||
/**
|
||||
* SdioConfig constructor.
|
||||
* \param[in] opt SDIO options.
|
||||
*/
|
||||
explicit SdioConfig(uint8_t opt) : m_options(opt) {}
|
||||
/** \return SDIO card options. */
|
||||
uint8_t options() { return m_options; }
|
||||
/** \return true if DMA_SDIO. */
|
||||
bool useDma() { return m_options & DMA_SDIO; }
|
||||
|
||||
private:
|
||||
uint8_t m_options = FIFO_SDIO;
|
||||
};
|
||||
class SdioConfig {};
|
||||
#endif // SDIO_CONFIG_INCLUDE
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* \class SdioCard
|
||||
|
|
@ -62,10 +46,10 @@ class SdioConfig {
|
|||
class SdioCard : public SdCardInterface {
|
||||
public:
|
||||
/** Initialize the SD card.
|
||||
* \param[in] sdioConfig SDIO card configuration.
|
||||
* \param[in] config SDIO card configuration.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool begin(SdioConfig sdioConfig);
|
||||
bool begin(SdioConfig config);
|
||||
/** CMD6 Switch mode: Check Function Set Function.
|
||||
* \param[in] arg CMD6 argument.
|
||||
* \param[out] status return status data.
|
||||
|
|
@ -76,7 +60,7 @@ class SdioCard : public SdCardInterface {
|
|||
/** Disable an SDIO card.
|
||||
* not implemented.
|
||||
*/
|
||||
void end() {}
|
||||
void end();
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
uint32_t __attribute__((error("use sectorCount()"))) cardSize();
|
||||
|
|
@ -253,7 +237,5 @@ class SdioCard : public SdCardInterface {
|
|||
static const uint8_t READ_STATE = 1;
|
||||
static const uint8_t WRITE_STATE = 2;
|
||||
uint32_t m_curSector;
|
||||
SdioConfig m_sdioConfig;
|
||||
uint8_t m_curState = IDLE_STATE;
|
||||
};
|
||||
#endif // SdioCard_h
|
||||
|
|
|
|||
1
src/SdCard/TeensySdio/CPPLINT.cfg
Normal file
1
src/SdCard/TeensySdio/CPPLINT.cfg
Normal file
|
|
@ -0,0 +1 @@
|
|||
exclude_files=TeensySdioDefs.h
|
||||
|
|
@ -23,10 +23,9 @@
|
|||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#if defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__)
|
||||
#include "SdioTeensy.h"
|
||||
|
||||
#include "SdCardInfo.h"
|
||||
#include "SdioCard.h"
|
||||
#include "../SdCardInfo.h"
|
||||
#include "../SdioCard.h"
|
||||
#include "TeensySdioDefs.h"
|
||||
//==============================================================================
|
||||
// limit of K66 due to errata KINETIS_K_0N65N.
|
||||
const uint32_t MAX_BLKCNT = 0XFFFF;
|
||||
|
|
@ -194,9 +193,10 @@ static bool waitTimeout(bool (*fcn)());
|
|||
//------------------------------------------------------------------------------
|
||||
static bool (*m_busyFcn)() = 0;
|
||||
static bool m_initDone = false;
|
||||
static bool m_version2;
|
||||
static bool m_highCapacity;
|
||||
static bool m_version2 = false;
|
||||
static bool m_highCapacity = false;
|
||||
static bool m_transferActive = false;
|
||||
static bool m_useDma = false;
|
||||
static uint8_t m_errorCode = SD_CARD_ERROR_INIT_NOT_CALLED;
|
||||
static uint32_t m_errorLine = 0;
|
||||
static uint32_t m_rca;
|
||||
|
|
@ -689,7 +689,7 @@ static bool waitTransferComplete() {
|
|||
bool SdioCard::begin(SdioConfig sdioConfig) {
|
||||
uint32_t kHzSdClk;
|
||||
uint32_t arg;
|
||||
m_sdioConfig = sdioConfig;
|
||||
m_useDma = sdioConfig.useDma();
|
||||
m_curState = IDLE_STATE;
|
||||
m_initDone = false;
|
||||
m_errorCode = SD_CARD_ERROR_NONE;
|
||||
|
|
@ -777,7 +777,7 @@ bool SdioCard::begin(SdioConfig sdioConfig) {
|
|||
}
|
||||
if ((status[16] & 0XF) == 1) {
|
||||
kHzSdClk = 50000;
|
||||
} else {
|
||||
} else {
|
||||
return sdError(SD_CARD_ERROR_CMD6);
|
||||
}
|
||||
}
|
||||
|
|
@ -812,6 +812,10 @@ bool SdioCard::cardCMD6(uint32_t arg, uint8_t* status) {
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SdioCard::end() {
|
||||
// to do
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::erase(uint32_t firstSector, uint32_t lastSector) {
|
||||
if (m_curState != IDLE_STATE && !syncDevice()) {
|
||||
return false;
|
||||
|
|
@ -851,7 +855,7 @@ uint32_t SdioCard::errorData() const { return m_irqstat; }
|
|||
uint32_t SdioCard::errorLine() const { return m_errorLine; }
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::isBusy() {
|
||||
if (m_sdioConfig.useDma()) {
|
||||
if (m_useDma) {
|
||||
return m_busyFcn ? m_busyFcn() : m_initDone && isBusyCMD13();
|
||||
} else {
|
||||
if (m_transferActive) {
|
||||
|
|
@ -932,7 +936,7 @@ bool SdioCard::readSDS(sds_t* sds) {
|
|||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::readSector(uint32_t sector, uint8_t* dst) {
|
||||
if (m_sdioConfig.useDma()) {
|
||||
if (m_useDma) {
|
||||
uint8_t aligned[512];
|
||||
|
||||
uint8_t* ptr = (uint32_t)dst & 3 ? aligned : dst;
|
||||
|
|
@ -973,7 +977,7 @@ bool SdioCard::readSector(uint32_t sector, uint8_t* dst) {
|
|||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::readSectors(uint32_t sector, uint8_t* dst, size_t n) {
|
||||
if (m_sdioConfig.useDma()) {
|
||||
if (m_useDma) {
|
||||
if ((uint32_t)dst & 3) {
|
||||
for (size_t i = 0; i < n; i++, sector++, dst += 512) {
|
||||
if (!readSector(sector, dst)) {
|
||||
|
|
@ -1081,7 +1085,7 @@ bool SdioCard::writeData(const uint8_t* src) {
|
|||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::writeSector(uint32_t sector, const uint8_t* src) {
|
||||
if (m_sdioConfig.useDma()) {
|
||||
if (m_useDma) {
|
||||
uint8_t* ptr;
|
||||
uint8_t aligned[512];
|
||||
if (3 & (uint32_t)src) {
|
||||
|
|
@ -1124,7 +1128,7 @@ bool SdioCard::writeSector(uint32_t sector, const uint8_t* src) {
|
|||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdioCard::writeSectors(uint32_t sector, const uint8_t* src, size_t n) {
|
||||
if (m_sdioConfig.useDma()) {
|
||||
if (m_useDma) {
|
||||
uint8_t* ptr = const_cast<uint8_t*>(src);
|
||||
if (3 & (uint32_t)ptr) {
|
||||
for (size_t i = 0; i < n; i++, sector++, ptr += 512) {
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -22,12 +22,28 @@
|
|||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef ExFatConfig_h
|
||||
#define ExFatConfig_h
|
||||
#include "SdFatConfig.h"
|
||||
#pragma once
|
||||
/** Use programmed I/O with FIFO. */
|
||||
#define FIFO_SDIO 0
|
||||
/** Use programmed I/O with DMA. */
|
||||
#define DMA_SDIO 1
|
||||
/**
|
||||
* \class SdioConfig
|
||||
* \brief SDIO card configuration.
|
||||
*/
|
||||
class SdioConfig {
|
||||
public:
|
||||
SdioConfig() {}
|
||||
/**
|
||||
* SdioConfig constructor.
|
||||
* \param[in] opt SDIO options.
|
||||
*/
|
||||
explicit SdioConfig(uint8_t opt) : m_options(opt) {}
|
||||
/** \return SDIO card options. */
|
||||
uint8_t options() { return m_options; }
|
||||
/** \return true if DMA_SDIO. */
|
||||
bool useDma() { return m_options & DMA_SDIO; }
|
||||
|
||||
#ifndef EXFAT_READ_ONLY
|
||||
#define EXFAT_READ_ONLY 0
|
||||
#endif // EXFAT_READ_ONLY
|
||||
|
||||
#endif // ExFatConfig_h
|
||||
private:
|
||||
uint8_t m_options = FIFO_SDIO;
|
||||
};
|
||||
|
|
@ -2,16 +2,14 @@
|
|||
* \file
|
||||
* \brief Definitions for Teensy HDHC.
|
||||
*/
|
||||
|
||||
#ifndef SdioTeensy_h
|
||||
#define SdioTeensy_h
|
||||
#pragma once
|
||||
|
||||
// From Paul's SD.h driver.
|
||||
|
||||
#if defined(__IMXRT1062__)
|
||||
#define MAKE_REG_MASK(m, s) (((uint32_t)(((uint32_t)(m) << s))))
|
||||
#define MAKE_REG_GET(x, m, s) (((uint32_t)(((uint32_t)(x) >> s) & m)))
|
||||
#define MAKE_REG_SET(x, m, s) (((uint32_t)(((uint32_t)(x)&m) << s)))
|
||||
#define MAKE_REG_SET(x, m, s) (((uint32_t)(((uint32_t)(x) & m) << s)))
|
||||
|
||||
#define SDHC_BLKATTR_BLKSIZE_MASK \
|
||||
MAKE_REG_MASK( \
|
||||
|
|
@ -467,7 +465,8 @@
|
|||
// Version
|
||||
|
||||
#define CCM_ANALOG_PFD_528_PFD0_FRAC_MASK 0x3f
|
||||
#define CCM_ANALOG_PFD_528_PFD0_FRAC(n) ((n)&CCM_ANALOG_PFD_528_PFD0_FRAC_MASK)
|
||||
#define CCM_ANALOG_PFD_528_PFD0_FRAC(n) \
|
||||
((n) & CCM_ANALOG_PFD_528_PFD0_FRAC_MASK)
|
||||
#define CCM_ANALOG_PFD_528_PFD1_FRAC_MASK (0x3f << 8)
|
||||
#define CCM_ANALOG_PFD_528_PFD1_FRAC(n) \
|
||||
(((n) << 8) & CCM_ANALOG_PFD_528_PFD1_FRAC_MASK)
|
||||
|
|
@ -515,16 +514,15 @@
|
|||
#define SDHC_PREV_CLKFS(x, y) ((x) >>= (y))
|
||||
|
||||
#define CCM_CSCDR1_USDHC1_CLK_PODF_MASK (0x7 << 11)
|
||||
#define CCM_CSCDR1_USDHC1_CLK_PODF(n) (((n)&0x7) << 11)
|
||||
#define CCM_CSCDR1_USDHC1_CLK_PODF(n) (((n) & 0x7) << 11)
|
||||
|
||||
#define IOMUXC_SW_PAD_CTL_PAD_SRE ((0x1 <) < 0)
|
||||
#define IOMUXC_SW_PAD_CTL_PAD_PKE ((0x1) << 12)
|
||||
#define IOMUXC_SW_PAD_CTL_PAD_PUE ((0x1) << 13)
|
||||
#define IOMUXC_SW_PAD_CTL_PAD_HYS ((0x1) << 16)
|
||||
#define IOMUXC_SW_PAD_CTL_PAD_SPEED(n) (((n)&0x3) << 6)
|
||||
#define IOMUXC_SW_PAD_CTL_PAD_PUS(n) (((n)&0x3) << 14)
|
||||
#define IOMUXC_SW_PAD_CTL_PAD_SPEED(n) (((n) & 0x3) << 6)
|
||||
#define IOMUXC_SW_PAD_CTL_PAD_PUS(n) (((n) & 0x3) << 14)
|
||||
#define IOMUXC_SW_PAD_CTL_PAD_PUS_MASK ((0x3) << 14)
|
||||
#define IOMUXC_SW_PAD_CTL_PAD_DSE(n) (((n)&0x7) << 3)
|
||||
#define IOMUXC_SW_PAD_CTL_PAD_DSE(n) (((n) & 0x7) << 3)
|
||||
#define IOMUXC_SW_PAD_CTL_PAD_DSE_MASK ((0x7) << 3)
|
||||
#endif // defined(__IMXRT1062__)
|
||||
#endif // SdioTeensy_h
|
||||
10
src/SdFat.h
10
src/SdFat.h
|
|
@ -22,8 +22,7 @@
|
|||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef SdFat_h
|
||||
#define SdFat_h
|
||||
#pragma once
|
||||
/**
|
||||
* \file
|
||||
* \brief main SdFs include file.
|
||||
|
|
@ -38,9 +37,9 @@
|
|||
#endif // INCLUDE_SDIOS
|
||||
//------------------------------------------------------------------------------
|
||||
/** SdFat version for cpp use. */
|
||||
#define SD_FAT_VERSION 20203
|
||||
#define SD_FAT_VERSION 20300
|
||||
/** SdFat version as string. */
|
||||
#define SD_FAT_VERSION_STR "2.2.3"
|
||||
#define SD_FAT_VERSION_STR "2.3.0"
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class SdBase
|
||||
|
|
@ -463,7 +462,7 @@ typedef FsFile File;
|
|||
#endif // HAS_INCLUDE_FS_H
|
||||
/**
|
||||
* \class SdFile
|
||||
* \brief FAT16/FAT32 file with Print.
|
||||
* \brief File with Print.
|
||||
*/
|
||||
class SdFile : public PrintFile<SdBaseFile> {
|
||||
public:
|
||||
|
|
@ -506,4 +505,3 @@ class SdFile : public PrintFile<SdBaseFile> {
|
|||
/** Cancel the date/time callback function. */
|
||||
static void dateTimeCallbackCancel() { FsDateTime::clearCallback(); }
|
||||
};
|
||||
#endif // SdFat_h
|
||||
|
|
|
|||
|
|
@ -26,13 +26,13 @@
|
|||
* \file
|
||||
* \brief configuration definitions
|
||||
*/
|
||||
#ifndef SdFatConfig_h
|
||||
#define SdFatConfig_h
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#ifdef __AVR__
|
||||
#include <avr/io.h>
|
||||
#endif // __AVR__
|
||||
//
|
||||
|
||||
// #include "SdFatDebugConfig.h"
|
||||
// To try UTF-8 encoded filenames.
|
||||
// #define USE_UTF8_LONG_NAMES 1
|
||||
//
|
||||
|
|
@ -87,13 +87,18 @@
|
|||
#define DESTRUCTOR_CLOSES_FILE 0
|
||||
#endif // DESTRUCTOR_CLOSES_FILE
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** For Debug - must be one */
|
||||
/** For Debug - must be one on Arduino */
|
||||
#ifndef ENABLE_ARDUINO_FEATURES
|
||||
#define ENABLE_ARDUINO_FEATURES 1
|
||||
/** For Debug - must be one */
|
||||
#endif //ENABLE_ARDUINO_FEATURES
|
||||
/** For Debug - must be one on Arduino */
|
||||
#ifndef ENABLE_ARDUINO_SERIAL
|
||||
#define ENABLE_ARDUINO_SERIAL 1
|
||||
/** For Debug - must be one */
|
||||
#endif //ENABLE_ARDUINO_SERIAL
|
||||
/** For Debug - must be one on Arduino */
|
||||
#ifndef ENABLE_ARDUINO_STRING
|
||||
#define ENABLE_ARDUINO_STRING 1
|
||||
#endif //ENABLE_ARDUINO_STRING
|
||||
//------------------------------------------------------------------------------
|
||||
#if ENABLE_ARDUINO_FEATURES
|
||||
#include "Arduino.h"
|
||||
|
|
@ -183,7 +188,11 @@
|
|||
* receive and transfer(buf, rxTmp, count) for send. Try this with STM32.
|
||||
*/
|
||||
#ifndef USE_SPI_ARRAY_TRANSFER
|
||||
#if defined(ARDUINO_ARCH_RP2040)
|
||||
#define USE_SPI_ARRAY_TRANSFER 2
|
||||
#else // defined(ARDUINO_ARCH_RP2040)
|
||||
#define USE_SPI_ARRAY_TRANSFER 0
|
||||
#endif // defined(ARDUINO_ARCH_RP2040)
|
||||
#endif // USE_SPI_ARRAY_TRANSFER
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
|
|
@ -435,6 +444,12 @@ typedef uint8_t SdCsPin_t;
|
|||
#endif // RAMEND
|
||||
//------------------------------------------------------------------------------
|
||||
/** Enable SDIO driver if available. */
|
||||
#if defined(ARDUINO_ARCH_RP2040)
|
||||
#define HAS_RP2040_SDIO 1
|
||||
#define HAS_SDIO_CLASS 1
|
||||
#define SDIO_CONFIG_INCLUDE "Rp2040Sdio/Rp2040SdioConfig.h"
|
||||
#endif // defined(ARDUINO_ARCH_RP2040)
|
||||
|
||||
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||
// Pseudo pin select for SDIO.
|
||||
#ifndef BUILTIN_SDCARD
|
||||
|
|
@ -448,10 +463,11 @@ typedef uint8_t SdCsPin_t;
|
|||
#define SDCARD_SCK_PIN 60
|
||||
#define SDCARD_SS_PIN 62
|
||||
#endif // SDCARD_SPI
|
||||
#define HAS_SDIO_CLASS 1
|
||||
#endif // defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||
#if defined(__IMXRT1062__)
|
||||
#if defined(__IMXRT1062__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||
#define HAS_SDIO_CLASS 1
|
||||
#define HAS_TEENSY_SDIO 1
|
||||
#define SDIO_CONFIG_INCLUDE "TeensySdio/TeensySdioConfig.h"
|
||||
#endif // defined(__IMXRT1062__)
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
|
|
@ -460,9 +476,8 @@ typedef uint8_t SdCsPin_t;
|
|||
#if defined(ARDUINO_ARCH_APOLLO3) || \
|
||||
(defined(__AVR__) && defined(SPDR) && defined(SPSR) && defined(SPIF)) || \
|
||||
(defined(__AVR__) && defined(SPI0) && defined(SPI_RXCIF_bm)) || \
|
||||
defined(ESP8266) || defined(ESP32) || defined(PLATFORM_ID) || \
|
||||
defined(ARDUINO_SAM_DUE) || defined(STM32_CORE_VERSION) || \
|
||||
defined(__STM32F1__) || defined(__STM32F4__) || \
|
||||
defined(__STM32F1__) || defined(__STM32F4__) || defined(PLATFORM_ID) || \
|
||||
(defined(CORE_TEENSY) && defined(__arm__))
|
||||
#define SD_HAS_CUSTOM_SPI 1
|
||||
#else // SD_HAS_CUSTOM_SPI
|
||||
|
|
@ -474,5 +489,3 @@ typedef uint8_t SdCsPin_t;
|
|||
/** Default is no SDIO. */
|
||||
#define HAS_SDIO_CLASS 0
|
||||
#endif // HAS_SDIO_CLASS
|
||||
|
||||
#endif // SdFatConfig_h
|
||||
|
|
|
|||
15
src/SdFatDebugConfig.h
Normal file
15
src/SdFatDebugConfig.h
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
// File to be included in SdFatConfig.h for debug definitions.
|
||||
#if defined(ARDUINO_ADAFRUIT_METRO_RP2040)
|
||||
#define RP_CLK_GPIO 18
|
||||
#define RP_CMD_GPIO 19
|
||||
#define RP_DAT0_GPIO 20 // DAT1: GPIO21, DAT2: GPIO22, DAT3: GPIO23.
|
||||
#elif defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_RASPBERRY_PI_PICO_2)
|
||||
#define RP_CLK_GPIO 16
|
||||
#define RP_CMD_GPIO 17
|
||||
#define RP_DAT0_GPIO 18 // DAT1: GPIO19, DAT2: GPIO20, DAT3: GPIO21.
|
||||
#elif defined(ARDUINO_ADAFRUIT_FEATHER_RP2350_HSTX)
|
||||
#define RP_CLK_GPIO 11
|
||||
#define RP_CMD_GPIO 10
|
||||
#define RP_DAT0_GPIO 22 // DAT1: GPIO23, DAT2: GPIO24, DAT3: GPIO25.
|
||||
#endif // defined(ARDUINO_ADAFRUIT_METRO_RP2040))
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -28,13 +28,15 @@
|
|||
//------------------------------------------------------------------------------
|
||||
void sdCsInit(SdCsPin_t pin) { pinMode(pin, OUTPUT); }
|
||||
//------------------------------------------------------------------------------
|
||||
void sdCsWrite(SdCsPin_t pin, bool level) { digitalWrite(pin, level); }
|
||||
void sdCsWrite(SdCsPin_t pin, bool level) {
|
||||
digitalWrite(pin, level ? HIGH : LOW);
|
||||
}
|
||||
#elif SD_CHIP_SELECT_MODE == 1
|
||||
//------------------------------------------------------------------------------
|
||||
__attribute__((weak)) void sdCsInit(SdCsPin_t pin) { pinMode(pin, OUTPUT); }
|
||||
//------------------------------------------------------------------------------
|
||||
__attribute__((weak)) void sdCsWrite(SdCsPin_t pin, bool level) {
|
||||
digitalWrite(pin, level);
|
||||
digitalWrite(pin, level ? HIGH : LOW);
|
||||
}
|
||||
#endif // SD_CHIP_SELECT_MODE == 0
|
||||
#endif // ENABLE_ARDUINO_FEATURES
|
||||
|
|
|
|||
|
|
@ -1,86 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 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.
|
||||
*/
|
||||
|
||||
#include "SdSpiDriver.h"
|
||||
#if defined(SD_USE_CUSTOM_SPI) && (defined(ESP8266) || defined(ESP32))
|
||||
#define ESP_UNALIGN_OK 1
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiArduinoDriver::activate() { m_spi->beginTransaction(m_spiSettings); }
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiArduinoDriver::begin(SdSpiConfig spiConfig) {
|
||||
if (spiConfig.spiPort) {
|
||||
m_spi = spiConfig.spiPort;
|
||||
#if defined(SDCARD_SPI) && defined(SDCARD_SS_PIN)
|
||||
} else if (spiConfig.csPin == SDCARD_SS_PIN) {
|
||||
m_spi = &SDCARD_SPI;
|
||||
#endif // defined(SDCARD_SPI) && defined(SDCARD_SS_PIN)
|
||||
} else {
|
||||
m_spi = &SPI;
|
||||
}
|
||||
m_spi->begin();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiArduinoDriver::deactivate() { m_spi->endTransaction(); }
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiArduinoDriver::end() { m_spi->end(); }
|
||||
//------------------------------------------------------------------------------
|
||||
uint8_t SdSpiArduinoDriver::receive() { return m_spi->transfer(0XFF); }
|
||||
//------------------------------------------------------------------------------
|
||||
uint8_t SdSpiArduinoDriver::receive(uint8_t* buf, size_t count) {
|
||||
#if ESP_UNALIGN_OK
|
||||
m_spi->transferBytes(nullptr, buf, count);
|
||||
#else // ESP_UNALIGN_OK
|
||||
// Adjust to 32-bit alignment.
|
||||
while ((reinterpret_cast<uintptr_t>(buf) & 0X3) && count) {
|
||||
*buf++ = m_spi->transfer(0xff);
|
||||
count--;
|
||||
}
|
||||
// Do multiple of four byte transfers.
|
||||
size_t n4 = 4 * (count / 4);
|
||||
if (n4) {
|
||||
m_spi->transferBytes(nullptr, buf, n4);
|
||||
}
|
||||
// Transfer up to three remaining bytes.
|
||||
for (buf += n4, count -= n4; count; count--) {
|
||||
*buf++ = m_spi->transfer(0xff);
|
||||
}
|
||||
#endif // ESP_UNALIGN_OK
|
||||
return 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiArduinoDriver::send(uint8_t data) { m_spi->transfer(data); }
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiArduinoDriver::send(const uint8_t* buf, size_t count) {
|
||||
#if !ESP_UNALIGN_OK
|
||||
// Adjust to 32-bit alignment.
|
||||
while ((reinterpret_cast<uintptr_t>(buf) & 0X3) && count) {
|
||||
SPI.transfer(*buf++);
|
||||
count--;
|
||||
}
|
||||
#endif // #if ESP_UNALIGN_OK
|
||||
|
||||
m_spi->transferBytes(const_cast<uint8_t*>(buf), nullptr, count);
|
||||
}
|
||||
#endif // defined(SD_USE_CUSTOM_SPI) && (defined(ESP8266) || defined(ESP32))
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -22,8 +22,7 @@
|
|||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef ArduinoFiles_h
|
||||
#define ArduinoFiles_h
|
||||
#pragma once
|
||||
#include "SysCall.h"
|
||||
//------------------------------------------------------------------------------
|
||||
/** Arduino SD.h style flag for open for read. */
|
||||
|
|
@ -44,13 +43,29 @@ class PrintFile : public print_t, public BaseFile {
|
|||
public:
|
||||
using BaseFile::clearWriteError;
|
||||
using BaseFile::getWriteError;
|
||||
using BaseFile::read;
|
||||
using BaseFile::write;
|
||||
|
||||
/** Ensure that any bytes written to the file are saved to the SD card. */
|
||||
#if defined(ARDUINO_SAM_DUE) && !defined(ARDUINO_API_VERSION)
|
||||
void flush() { BaseFile::sync(); }
|
||||
#else
|
||||
void flush() override { BaseFile::sync(); }
|
||||
#endif
|
||||
|
||||
/** Write a single byte.
|
||||
* \param[in] b byte to write.
|
||||
* \return one for success.
|
||||
*/
|
||||
size_t write(uint8_t b) { return BaseFile::write(&b, 1); }
|
||||
size_t write(uint8_t b) override { return BaseFile::write(&b, 1); }
|
||||
|
||||
/** Write data to an open file.
|
||||
* \param[in] buffer pointer
|
||||
* \param[in] size of the buffer
|
||||
* \return number of bytes actually written
|
||||
*/
|
||||
size_t write(const uint8_t* buffer, size_t size) override {
|
||||
return BaseFile::write(buffer, size);
|
||||
}
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
|
|
@ -64,35 +79,39 @@ class StreamFile : public stream_t, public BaseFile {
|
|||
using BaseFile::getWriteError;
|
||||
using BaseFile::read;
|
||||
using BaseFile::write;
|
||||
|
||||
StreamFile() {}
|
||||
|
||||
/** \return number of bytes available from the current position to EOF
|
||||
* or INT_MAX if more than INT_MAX bytes are available.
|
||||
*/
|
||||
int available() { return BaseFile::available(); }
|
||||
int available() override { return BaseFile::available(); }
|
||||
/** Ensure that any bytes written to the file are saved to the SD card. */
|
||||
void flush() { BaseFile::sync(); }
|
||||
void flush() override { BaseFile::sync(); }
|
||||
|
||||
/** This function reports if the current file is a directory or not.
|
||||
* \return true if the file is a directory.
|
||||
*/
|
||||
bool isDirectory() { return BaseFile::isDir(); }
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
char* __attribute__((error("use getName(name, size)"))) name();
|
||||
#endif // DOXYGEN_SHOULD_SKIP_THIS
|
||||
|
||||
/** Return the next available byte without consuming it.
|
||||
*
|
||||
* \return The byte if no error and not at eof else -1;
|
||||
*/
|
||||
int peek() { return BaseFile::peek(); }
|
||||
int peek() override { return BaseFile::peek(); }
|
||||
/** \return the current file position. */
|
||||
PosType position() { return BaseFile::curPosition(); }
|
||||
|
||||
/** Read the next byte from a file.
|
||||
*
|
||||
* \return For success return the next byte in the file as an int.
|
||||
* If an error occurs or end of file is reached return -1.
|
||||
*/
|
||||
int read() { return BaseFile::read(); }
|
||||
int read() override { return BaseFile::read(); }
|
||||
|
||||
/** Rewind a file if it is a directory */
|
||||
void rewindDirectory() {
|
||||
if (BaseFile::isDir()) {
|
||||
|
|
@ -114,7 +133,7 @@ class StreamFile : public stream_t, public BaseFile {
|
|||
* Use getWriteError to check for errors.
|
||||
* \return 1 for success and 0 for failure.
|
||||
*/
|
||||
size_t write(uint8_t b) { return BaseFile::write(b); }
|
||||
size_t write(uint8_t b) override { return BaseFile::write(b); }
|
||||
/** Write data to an open file.
|
||||
*
|
||||
* \note Data is moved to the cache but may not be written to the
|
||||
|
|
@ -127,8 +146,7 @@ class StreamFile : public stream_t, public BaseFile {
|
|||
* \return For success write() returns the number of bytes written, always
|
||||
* \a size.
|
||||
*/
|
||||
size_t write(const uint8_t* buffer, size_t size) {
|
||||
size_t write(const uint8_t* buffer, size_t size) override {
|
||||
return BaseFile::write(buffer, size);
|
||||
}
|
||||
};
|
||||
#endif // ArduinoFiles_h
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -22,8 +22,7 @@
|
|||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef DebugMacros_h
|
||||
#define DebugMacros_h
|
||||
#pragma once
|
||||
#include "SysCall.h"
|
||||
|
||||
// 0 - disable, 1 - fail, halt 2 - fail, halt, warn
|
||||
|
|
@ -78,4 +77,3 @@ __attribute__((unused)) static void dbgWarn(uint16_t line) {
|
|||
#define DBG_WARN_MACRO
|
||||
#define DBG_WARN_IF(b)
|
||||
#endif // USE_DBG_MACROS > 1
|
||||
#endif // DebugMacros_h
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -174,7 +174,8 @@ char* fmtBase10(char* str, uint16_t n) {
|
|||
// n = n + (n >> 16); // no code for 16-bit n
|
||||
n = n >> 3;
|
||||
uint8_t r = t - (((n << 2) + n) << 1);
|
||||
if (r > 9) {
|
||||
// cppcheck wrong.
|
||||
if (r > 9) { // cppcheck-suppress knownConditionTrueFalse
|
||||
n++;
|
||||
r -= 10;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -22,8 +22,7 @@
|
|||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef FsCache_h
|
||||
#define FsCache_h
|
||||
#pragma once
|
||||
/**
|
||||
* \file
|
||||
* \brief Common cache code for exFAT and FAT.
|
||||
|
|
@ -54,7 +53,7 @@ class FsCache {
|
|||
CACHE_STATUS_DIRTY | CACHE_OPTION_NO_READ;
|
||||
//----------------------------------------------------------------------------
|
||||
/** Cobstructor. */
|
||||
FsCache() { init(nullptr); }
|
||||
FsCache() { init(nullptr); } // cppcheck-suppress uninitMemberVar
|
||||
/** \return Cache buffer address. */
|
||||
uint8_t* cacheBuffer() { return m_buffer; }
|
||||
/**
|
||||
|
|
@ -173,4 +172,3 @@ class FsCache {
|
|||
uint32_t m_mirrorOffset;
|
||||
uint8_t m_buffer[512];
|
||||
};
|
||||
#endif // FsCache_h
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -22,8 +22,7 @@
|
|||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef FsDateTime_h
|
||||
#define FsDateTime_h
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
#include "CompileDateTime.h"
|
||||
|
|
@ -188,4 +187,3 @@ size_t fsPrintDateTime(print_t* pr, uint32_t dateTime, uint8_t s100, int8_t tz);
|
|||
size_t fsPrintTime(print_t* pr, uint16_t time);
|
||||
size_t fsPrintTime(print_t* pr, uint16_t time, uint8_t sec100);
|
||||
size_t fsPrintTimeZone(print_t* pr, int8_t tz);
|
||||
#endif // FsDateTime_h
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -22,8 +22,7 @@
|
|||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef FsUtf_h
|
||||
#define FsUtf_h
|
||||
#pragma once
|
||||
/**
|
||||
* \file
|
||||
* \brief Unicode Transformation Format functions.
|
||||
|
|
@ -98,4 +97,3 @@ const char* mbToCp(const char* str, const char* end, uint32_t* rtn);
|
|||
const char* mbToU16(const char* str, const char* end, uint16_t* hs,
|
||||
uint16_t* ls);
|
||||
} // namespace FsUtf
|
||||
#endif // FsUtf_h
|
||||
|
|
|
|||
91
src/common/PrintBasic.cpp
Normal file
91
src/common/PrintBasic.cpp
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2020 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.
|
||||
*/
|
||||
#include "PrintBasic.h"
|
||||
#if ENABLE_ARDUINO_FEATURES == 0
|
||||
#include <math.h>
|
||||
|
||||
size_t PrintBasic::print(long n, uint8_t base) {
|
||||
if (n < 0 && base == 10) {
|
||||
return print('-') + printNum(-n, base);
|
||||
}
|
||||
return printNum(n, base);
|
||||
}
|
||||
size_t PrintBasic::printNum(unsigned long n, uint8_t base) {
|
||||
const uint8_t DIM = 8 * sizeof(long);
|
||||
char buf[DIM];
|
||||
char *str = &buf[DIM];
|
||||
|
||||
if (base < 2) return 0;
|
||||
|
||||
do {
|
||||
char c = n % base;
|
||||
n /= base;
|
||||
*--str = c + (c < 10 ? '0' : 'A' - 10);
|
||||
} while (n);
|
||||
return write(str, &buf[DIM] - str);
|
||||
}
|
||||
|
||||
size_t PrintBasic::printDouble(double n, uint8_t prec) {
|
||||
// Max printable 32-bit floating point number. AVR uses 32-bit double.
|
||||
const double maxfp = static_cast<double>(0XFFFFFF00UL);
|
||||
size_t rtn = 0;
|
||||
|
||||
if (isnan(n)) {
|
||||
return write("NaN");
|
||||
}
|
||||
if (n < 0) {
|
||||
n = -n;
|
||||
rtn += print('-');
|
||||
}
|
||||
if (isinf(n)) {
|
||||
return rtn + write("Inf");
|
||||
}
|
||||
if (n > maxfp) {
|
||||
return rtn + write("Ovf");
|
||||
}
|
||||
|
||||
double round = 0.5;
|
||||
for (uint8_t i = 0; i < prec; ++i) {
|
||||
round *= 0.1;
|
||||
}
|
||||
|
||||
n += round;
|
||||
|
||||
uint32_t whole = (uint32_t)n;
|
||||
rtn += print(whole);
|
||||
|
||||
if (prec) {
|
||||
rtn += print('.');
|
||||
double fraction = n - static_cast<double>(whole);
|
||||
for (uint8_t i = 0; i < prec; i++) {
|
||||
fraction *= 10.0;
|
||||
uint8_t digit = fraction;
|
||||
rtn += print(digit);
|
||||
fraction -= digit;
|
||||
}
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
#endif // ENABLE_ARDUINO_FEATURES == 0
|
||||
148
src/common/PrintBasic.h
Normal file
148
src/common/PrintBasic.h
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2020 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.
|
||||
*/
|
||||
#ifndef PrintBasic_h
|
||||
#define PrintBasic_h
|
||||
/**
|
||||
* \file
|
||||
* \brief Stream/Print like replacement for non-Arduino systems.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../SdFatConfig.h"
|
||||
|
||||
#ifndef F
|
||||
#if defined(__AVR__)
|
||||
#include <avr/pgmspace.h>
|
||||
class __FlashStringHelper;
|
||||
#define F(string_literal) \
|
||||
(reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
|
||||
#else // defined(__AVR__)
|
||||
#define F(str) (str)
|
||||
#endif // defined(__AVR__)
|
||||
#endif // F
|
||||
|
||||
#ifdef BIN
|
||||
#undef BIN
|
||||
#endif // BIN
|
||||
#define BIN 2
|
||||
#define OCT 8
|
||||
#define DEC 10
|
||||
#define HEX 16
|
||||
|
||||
class PrintBasic {
|
||||
public:
|
||||
PrintBasic() : m_error(0) {}
|
||||
|
||||
void clearWriteError() { setWriteError(0); }
|
||||
int getWriteError() { return m_error; }
|
||||
size_t print(char c) { return write(c); }
|
||||
size_t print(const char *str) { return write(str); }
|
||||
size_t print(const __FlashStringHelper *str) {
|
||||
#ifdef __AVR__
|
||||
PGM_P p = reinterpret_cast<PGM_P>(str);
|
||||
size_t n = 0;
|
||||
for (uint8_t c; (c = pgm_read_byte(p + n)) && write(c); n++) {
|
||||
}
|
||||
return n;
|
||||
#else // __AVR__
|
||||
return print(reinterpret_cast<const char *>(str));
|
||||
#endif // __AVR__
|
||||
}
|
||||
size_t println(const __FlashStringHelper *str) {
|
||||
#ifdef __AVR__
|
||||
return print(str) + println();
|
||||
#else // __AVR__
|
||||
return println(reinterpret_cast<const char *>(str));
|
||||
#endif // __AVR__
|
||||
}
|
||||
size_t print(double n, uint8_t prec = 2) { return printDouble(n, prec); }
|
||||
size_t print(signed char n, uint8_t base = 10) {
|
||||
return print((long)n, base);
|
||||
}
|
||||
size_t print(unsigned char n, uint8_t base = 10) {
|
||||
return print((unsigned long)n, base);
|
||||
}
|
||||
size_t print(int n, uint8_t base = 10) { return print((long)n, base); }
|
||||
size_t print(unsigned int n, uint8_t base = 10) {
|
||||
return print((unsigned long)n, base);
|
||||
}
|
||||
size_t print(long n, uint8_t base = 10);
|
||||
size_t print(unsigned long n, uint8_t base = 10) { return printNum(n, base); }
|
||||
size_t println() { return write("\r\n"); }
|
||||
size_t println(char c) { return write(c) + println(); }
|
||||
size_t println(const char *str) { return print(str) + println(); }
|
||||
size_t println(double n, uint8_t prec = 2) {
|
||||
return print(n, prec) + println();
|
||||
}
|
||||
size_t println(signed char n, uint8_t base = 10) {
|
||||
return print(n, base) + println();
|
||||
}
|
||||
size_t println(unsigned char n, uint8_t base = 10) {
|
||||
return print(n, base) + println();
|
||||
}
|
||||
size_t println(int n, uint8_t base = 10) {
|
||||
return print(n, base) + println();
|
||||
}
|
||||
size_t println(unsigned int n, uint8_t base = 10) {
|
||||
return print(n, base) + println();
|
||||
}
|
||||
size_t println(long n, uint8_t base = 10) {
|
||||
return print(n, base) + println();
|
||||
}
|
||||
size_t println(unsigned long n, uint8_t base = 10) {
|
||||
return print(n, base) + println();
|
||||
}
|
||||
size_t write(const char *str) { return write(str, strlen(str)); }
|
||||
virtual size_t write(uint8_t b) = 0;
|
||||
|
||||
virtual size_t write(const uint8_t *buffer, size_t size) {
|
||||
size_t i;
|
||||
for (i = 0; i < size; i++) {
|
||||
if (!write(buffer[i])) break;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
size_t write(const char *buffer, size_t size) {
|
||||
return write(reinterpret_cast<const uint8_t *>(buffer), size);
|
||||
}
|
||||
|
||||
protected:
|
||||
void setWriteError(int err = 1) { m_error = err; }
|
||||
|
||||
private:
|
||||
size_t printDouble(double n, uint8_t prec);
|
||||
size_t printNum(unsigned long n, uint8_t base);
|
||||
int m_error;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
class StreamBasic : public PrintBasic {
|
||||
public:
|
||||
virtual int available() = 0;
|
||||
virtual int peek() = 0;
|
||||
virtual int read() = 0;
|
||||
};
|
||||
#endif // PrintBasic_h
|
||||
15
src/fmt_src.bat
Normal file
15
src/fmt_src.bat
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
clang-format --style=Google -i *.cpp *.h
|
||||
rem clang-format --style=Google -i DigitalIO/*.h
|
||||
rem clang-format --style=Google -i DigitalIO/boards/*.h
|
||||
clang-format --style=Google -i common/*.cpp common/*.h
|
||||
clang-format --style=Google -i ExFatLib/*.cpp ExFatLib/*.h
|
||||
clang-format --style=Google -i FatLib/*.cpp FatLib/*.h
|
||||
clang-format --style=Google -i FsLib/*.cpp FsLib/*.h
|
||||
clang-format --style=Google -i iostream/*.cpp iostream/*.h
|
||||
clang-format --style=Google -i SdCard/*.cpp SdCard/*.h
|
||||
rem clang-format --style=Google -i SdCard/Rp2040Sdio/DbgLogMsg.h SdCard/Rp2040Sdio/PioDbgInfo.h
|
||||
rem clang-format --style=Google -i SdCard/Rp2040Sdio/PioSdioCard.h SdCard/Rp2040Sdio/Rp2040SdioConfig.h
|
||||
clang-format --style=Google -i SdCard/Rp2040Sdio/*.cpp SdCard/Rp2040Sdio/*.h
|
||||
clang-format --style=Google -i SdCard/TeensySdio/*.cpp SdCard/TeensySdio/*.h
|
||||
clang-format --style=Google -i SpiDriver/*.cpp SpiDriver/*.h
|
||||
pause
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -243,6 +243,8 @@ size_t StdioStream::fwrite(const void* ptr, size_t size, size_t count) {
|
|||
return write(ptr, count * size) < 0 ? EOF : count;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// allow shadow of rewind() in StreamBaseFile,
|
||||
// cppcheck-suppress duplInheritedMember
|
||||
int StdioStream::write(const void* buf, size_t count) {
|
||||
const uint8_t* src = static_cast<const uint8_t*>(buf);
|
||||
size_t todo = count;
|
||||
|
|
@ -282,7 +284,7 @@ size_t StdioStream::print(const __FlashStringHelper* str) {
|
|||
//------------------------------------------------------------------------------
|
||||
int StdioStream::printDec(float value, uint8_t prec) {
|
||||
char buf[24];
|
||||
char* ptr = fmtDouble(buf + sizeof(buf), value, prec, false);
|
||||
const char* ptr = fmtDouble(buf + sizeof(buf), value, prec, false);
|
||||
return write(ptr, buf + sizeof(buf) - ptr);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -314,7 +316,7 @@ int StdioStream::printDec(int16_t n) {
|
|||
//------------------------------------------------------------------------------
|
||||
int StdioStream::printDec(uint16_t n) {
|
||||
char buf[5];
|
||||
char* ptr = fmtBase10(buf + sizeof(buf), n);
|
||||
const char* ptr = fmtBase10(buf + sizeof(buf), n);
|
||||
uint8_t len = buf + sizeof(buf) - ptr;
|
||||
return write(ptr, len);
|
||||
}
|
||||
|
|
@ -334,18 +336,20 @@ int StdioStream::printDec(int32_t n) {
|
|||
//------------------------------------------------------------------------------
|
||||
int StdioStream::printDec(uint32_t n) {
|
||||
char buf[10];
|
||||
char* ptr = fmtBase10(buf + sizeof(buf), n);
|
||||
const char* ptr = fmtBase10(buf + sizeof(buf), n);
|
||||
uint8_t len = buf + sizeof(buf) - ptr;
|
||||
return write(ptr, len);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int StdioStream::printHex(uint32_t n) {
|
||||
char buf[8];
|
||||
char* ptr = fmtHex(buf + sizeof(buf), n);
|
||||
const char* ptr = fmtHex(buf + sizeof(buf), n);
|
||||
uint8_t len = buf + sizeof(buf) - ptr;
|
||||
return write(ptr, len);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// allow shadow of rewind() in StreamBaseFile,
|
||||
// cppcheck-suppress duplInheritedMember
|
||||
bool StdioStream::rewind() {
|
||||
if (m_status & S_SWR) {
|
||||
if (!flushBuf()) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -22,8 +22,7 @@
|
|||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef StdioStream_h
|
||||
#define StdioStream_h
|
||||
#pragma once
|
||||
/**
|
||||
* \file
|
||||
* \brief StdioStream class
|
||||
|
|
@ -112,6 +111,7 @@ const uint8_t UNGETC_BUF_SIZE = 2;
|
|||
*/
|
||||
class StdioStream : private StreamBaseFile {
|
||||
public:
|
||||
using StreamBaseFile::printField;
|
||||
/** Constructor
|
||||
*
|
||||
*/
|
||||
|
|
@ -545,38 +545,6 @@ class StdioStream : private StreamBaseFile {
|
|||
*/
|
||||
int printDec(float value, uint8_t prec);
|
||||
//----------------------------------------------------------------------------
|
||||
/** Print a number followed by a field terminator.
|
||||
* \param[in] value The number to be printed.
|
||||
* \param[in] term The field terminator.
|
||||
* \param[in] prec Number of digits after decimal point.
|
||||
* \return The number of bytes written or -1 if an error occurs.
|
||||
*/
|
||||
int printField(double value, char term, uint8_t prec = 2) {
|
||||
return printField(static_cast<float>(value), term, prec) > 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Print a number followed by a field terminator.
|
||||
* \param[in] value The number to be printed.
|
||||
* \param[in] term The field terminator.
|
||||
* \param[in] prec Number of digits after decimal point.
|
||||
* \return The number of bytes written or -1 if an error occurs.
|
||||
*/
|
||||
int printField(float value, char term, uint8_t prec = 2) {
|
||||
int rtn = printDec(value, prec);
|
||||
return rtn < 0 || putc(term) < 0 ? -1 : rtn + 1;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Print a number followed by a field terminator.
|
||||
* \param[in] value The number to be printed.
|
||||
* \param[in] term The field terminator.
|
||||
* \return The number of bytes written or -1 if an error occurs.
|
||||
*/
|
||||
template <typename T>
|
||||
int printField(T value, char term) {
|
||||
int rtn = printDec(value);
|
||||
return rtn < 0 || putc(term) < 0 ? -1 : rtn + 1;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Print HEX
|
||||
* \param[in] n number to be printed as HEX.
|
||||
*
|
||||
|
|
@ -640,5 +608,3 @@ class StdioStream : private StreamBaseFile {
|
|||
uint8_t m_r = 0;
|
||||
uint8_t m_w = 0;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
#endif // StdioStream_h
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -150,9 +150,3 @@ bool StreamBaseClass::seekoff(off_type off, seekdir way) {
|
|||
}
|
||||
return seekpos(pos);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int StreamBaseClass::write(const void* buf, size_t n) {
|
||||
return StreamBaseFile::write(buf, n);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void StreamBaseClass::write(char c) { StreamBaseFile::write(&c, 1); }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -26,8 +26,7 @@
|
|||
* \file
|
||||
* \brief iostreams for files.
|
||||
*/
|
||||
#ifndef fstream_h
|
||||
#define fstream_h
|
||||
#pragma once
|
||||
#include "iostream.h"
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
|
|
@ -36,12 +35,15 @@
|
|||
*/
|
||||
class StreamBaseClass : protected StreamBaseFile, virtual public ios {
|
||||
protected:
|
||||
void clearWriteError() { StreamBaseFile::clearWriteError(); }
|
||||
using StreamBaseFile::clearWriteError;
|
||||
using StreamBaseFile::getWriteError;
|
||||
using StreamBaseFile::write;
|
||||
|
||||
/* Internal do not use
|
||||
* \return mode
|
||||
*/
|
||||
int16_t getch();
|
||||
bool getWriteError() { return StreamBaseFile::getWriteError(); }
|
||||
|
||||
void open(const char* path, ios::openmode mode);
|
||||
/** Internal do not use
|
||||
* \return mode
|
||||
|
|
@ -58,8 +60,6 @@ class StreamBaseClass : protected StreamBaseFile, virtual public ios {
|
|||
* \param[in] mode
|
||||
*/
|
||||
void setmode(ios::openmode mode) { m_mode = mode; }
|
||||
int write(const void* buf, size_t n);
|
||||
void write(char c);
|
||||
|
||||
private:
|
||||
ios::openmode m_mode;
|
||||
|
|
@ -72,6 +72,7 @@ class StreamBaseClass : protected StreamBaseFile, virtual public ios {
|
|||
class fstream : public iostream, StreamBaseClass {
|
||||
public:
|
||||
using iostream::peek;
|
||||
using StreamBaseClass::close;
|
||||
fstream() {}
|
||||
/** Constructor with open
|
||||
* \param[in] path file to open
|
||||
|
|
@ -86,14 +87,10 @@ class fstream : public iostream, StreamBaseClass {
|
|||
/** Clear state and writeError
|
||||
* \param[in] state new state for stream
|
||||
*/
|
||||
void clear(iostate state = goodbit) {
|
||||
void clear(iostate state = goodbit) override {
|
||||
ios::clear(state);
|
||||
StreamBaseClass::clearWriteError();
|
||||
}
|
||||
/** Close a file and force cached data and directory information
|
||||
* to be written to the storage device.
|
||||
*/
|
||||
void close() { StreamBaseClass::close(); }
|
||||
/** Open a fstream
|
||||
* \param[in] path path to open
|
||||
* \param[in] mode open mode
|
||||
|
|
@ -127,29 +124,29 @@ class fstream : public iostream, StreamBaseClass {
|
|||
/** Internal - do not use
|
||||
* \return
|
||||
*/
|
||||
int16_t getch() { return StreamBaseClass::getch(); }
|
||||
int16_t getch() override { return StreamBaseClass::getch(); }
|
||||
/** Internal - do not use
|
||||
* \param[out] pos
|
||||
*/
|
||||
void getpos(pos_t* pos) { StreamBaseFile::fgetpos(pos); }
|
||||
void getpos(pos_t* pos) override { StreamBaseFile::fgetpos(pos); }
|
||||
/** Internal - do not use
|
||||
* \param[in] c
|
||||
*/
|
||||
void putch(char c) { StreamBaseClass::putch(c); }
|
||||
void putch(char c) override { StreamBaseClass::putch(c); }
|
||||
/** Internal - do not use
|
||||
* \param[in] str
|
||||
*/
|
||||
void putstr(const char* str) { StreamBaseClass::putstr(str); }
|
||||
void putstr(const char* str) override { StreamBaseClass::putstr(str); }
|
||||
/** Internal - do not use
|
||||
* \param[in] pos
|
||||
*/
|
||||
bool seekoff(off_type off, seekdir way) {
|
||||
bool seekoff(off_type off, seekdir way) override {
|
||||
return StreamBaseClass::seekoff(off, way);
|
||||
}
|
||||
bool seekpos(pos_type pos) { return StreamBaseClass::seekpos(pos); }
|
||||
void setpos(pos_t* pos) { StreamBaseFile::fsetpos(pos); }
|
||||
bool sync() { return StreamBaseClass::sync(); }
|
||||
pos_type tellpos() { return StreamBaseFile::curPosition(); }
|
||||
bool seekpos(pos_type pos) override { return StreamBaseClass::seekpos(pos); }
|
||||
void setpos(const pos_t* pos) { StreamBaseFile::fsetpos(pos); }
|
||||
bool sync() override { return StreamBaseClass::sync(); }
|
||||
pos_type tellpos() override { return StreamBaseFile::curPosition(); }
|
||||
/// @endcond
|
||||
};
|
||||
//==============================================================================
|
||||
|
|
@ -160,6 +157,7 @@ class fstream : public iostream, StreamBaseClass {
|
|||
class ifstream : public istream, StreamBaseClass {
|
||||
public:
|
||||
using istream::peek;
|
||||
using StreamBaseClass::close;
|
||||
ifstream() {}
|
||||
/** Constructor with open
|
||||
* \param[in] path file to open
|
||||
|
|
@ -169,10 +167,6 @@ class ifstream : public istream, StreamBaseClass {
|
|||
#if DESTRUCTOR_CLOSES_FILE
|
||||
~ifstream() {}
|
||||
#endif // DESTRUCTOR_CLOSES_FILE
|
||||
/** Close a file and force cached data and directory information
|
||||
* to be written to the storage device.
|
||||
*/
|
||||
void close() { StreamBaseClass::close(); }
|
||||
/** \return True if stream is open else false. */
|
||||
bool is_open() { return StreamBaseFile::isOpen(); }
|
||||
/** Open an ifstream
|
||||
|
|
@ -213,6 +207,7 @@ class ifstream : public istream, StreamBaseClass {
|
|||
*/
|
||||
class ofstream : public ostream, StreamBaseClass {
|
||||
public:
|
||||
using StreamBaseClass::close;
|
||||
ofstream() {}
|
||||
/** Constructor with open
|
||||
* \param[in] path file to open
|
||||
|
|
@ -225,14 +220,10 @@ class ofstream : public ostream, StreamBaseClass {
|
|||
/** Clear state and writeError
|
||||
* \param[in] state new state for stream
|
||||
*/
|
||||
void clear(iostate state = goodbit) {
|
||||
void clear(iostate state = goodbit) override {
|
||||
ios::clear(state);
|
||||
StreamBaseClass::clearWriteError();
|
||||
}
|
||||
/** Close a file and force cached data and directory information
|
||||
* to be written to the storage device.
|
||||
*/
|
||||
void close() { StreamBaseClass::close(); }
|
||||
/** Open an ofstream
|
||||
* \param[in] path file to open
|
||||
* \param[in] mode open mode
|
||||
|
|
@ -265,4 +256,3 @@ class ofstream : public ostream, StreamBaseClass {
|
|||
pos_type tellpos() override { return StreamBaseFile::curPosition(); }
|
||||
/// @endcond
|
||||
};
|
||||
#endif // fstream_h
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2022 Bill Greiman
|
||||
* Copyright (c) 2011-2024 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
|
|
@ -22,8 +22,7 @@
|
|||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef ios_h
|
||||
#define ios_h
|
||||
#pragma once
|
||||
#include "../FsLib/FsLib.h"
|
||||
/**
|
||||
* \file
|
||||
|
|
@ -412,7 +411,7 @@ class ios : public ios_base {
|
|||
*
|
||||
* \param[in] state The flags you want to set after clearing all flags.
|
||||
**/
|
||||
void clear(iostate state = goodbit) { m_iostate = state; }
|
||||
virtual void clear(iostate state = goodbit) { m_iostate = state; }
|
||||
/** Set iostate bits.
|
||||
*
|
||||
* \param[in] state Bitts to set.
|
||||
|
|
@ -422,4 +421,3 @@ class ios : public ios_base {
|
|||
private:
|
||||
iostate m_iostate = 0;
|
||||
};
|
||||
#endif // ios_h
|
||||
|
|
|
|||
Loading…
Reference in a new issue