Reformat, user SPI begin, SPI array functions, bug fixes

This commit is contained in:
Bill Greiman 2023-04-05 05:34:17 -07:00
parent 628effa1c2
commit 57900b21d2
140 changed files with 5404 additions and 4712 deletions

243
.gitignore vendored
View file

@ -1,215 +1,36 @@
#################
## Eclipse
#################
*.pydevproject
.project
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# PDT-specific
.buildpath
#################
## Visual Studio
#################
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Rr]elease/
x64/
build/
[Bb]in/
[Oo]bj/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.log
*.scc
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
*.ncrunch*
.*crunch*.local.xml
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.Publish.xml
*.pubxml
# NuGet Packages Directory
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
#packages/
# Windows Azure Build Output
csx
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.[Pp]ublish.xml
*.pfx
*.publishsettings
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
App_Data/*.mdf
App_Data/*.ldf
#############
## Windows detritus
#############
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Mac crap
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# =========================
# Operating System Files
# =========================
# OSX
# =========================
.DS_Store
.AppleDouble
.LSOverride
# Icon must ends with two \r.
Icon
#############
## Python
#############
# Thumbnails
._*
*.py[co]
# Packages
*.egg
*.egg-info
dist/
build/
eggs/
parts/
var/
sdist/
develop-eggs/
.installed.cfg
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage
.tox
#Translations
*.mo
#Mr Developer
.mr.developer.cfg
# Files that might appear on external disk
.Spotlight-V100
.Trashes

View file

@ -1,8 +1,13 @@
### Warning: This is SdFat Version 2.
### Warning: Major Reformat of Source in 2.2.2
Earlier releases of Version 1 are here:
There are a huge number of changes in 2.2.2 since I decided to use clang-format
to force Google style formatting.
https://github.com/greiman/SdFat/releases
I did this to avoid warnings from the static analysis programs Cppcheck and
cpplint.
clang-format is aggressive so it may actually cause code to fail. For example
clang-format rearranges the order of includes according to the selected style.
UTF-8 encoded filenames are supported in v2.1.0 or later.

View file

@ -1,4 +1,4 @@
# Doxyfile 1.9.2
# Doxyfile 1.9.6
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
@ -12,6 +12,16 @@
# For lists, items can also be appended using:
# TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (\" \").
#
# Note:
#
# Use doxygen to compare the used configuration file with the template
# configuration file:
# doxygen -x [configFile]
# Use doxygen to compare the used configuration file with the template
# configuration file without replacing the environment variables or CMake type
# replacement variables:
# doxygen -x_noenv [configFile]
#---------------------------------------------------------------------------
# Project related configuration options
@ -60,16 +70,28 @@ PROJECT_LOGO =
OUTPUT_DIRECTORY = .
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and
# will distribute the generated files over these directories. Enabling this
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096
# sub-directories (in 2 levels) under the output directory of each output format
# and will distribute the generated files over these directories. Enabling this
# option can be useful when feeding doxygen a huge amount of source files, where
# putting all generated files in the same directory would otherwise causes
# performance problems for the file system.
# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to
# control the number of sub-directories.
# The default value is: NO.
CREATE_SUBDIRS = NO
# Controls the number of sub-directories that will be created when
# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every
# level increment doubles the number of directories, resulting in 4096
# directories at level 8 which is the default and also the maximum value. The
# sub-directories are organized in 2 levels, the first level always has a fixed
# number of 16 directories.
# Minimum value: 0, maximum value: 8, default value: 8.
# This tag requires that the tag CREATE_SUBDIRS is set to YES.
CREATE_SUBDIRS_LEVEL = 8
# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
# characters to appear in the names of generated files. If set to NO, non-ASCII
# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
@ -81,14 +103,14 @@ ALLOW_UNICODE_NAMES = NO
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
# Ukrainian and Vietnamese.
# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian,
# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English
# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek,
# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with
# English messages), Korean, Korean-en (Korean with English messages), Latvian,
# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese,
# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish,
# Swedish, Turkish, Ukrainian and Vietnamese.
# The default value is: English.
OUTPUT_LANGUAGE = English
@ -452,7 +474,7 @@ TYPEDEF_HIDES_STRUCT = NO
LOOKUP_CACHE_SIZE = 0
# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use
# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use
# during processing. When set to 0 doxygen will based this on the number of
# cores available in the system. You can set it explicitly to a value larger
# than 0 to get more control over the balance between CPU load and processing
@ -546,7 +568,8 @@ HIDE_UNDOC_MEMBERS = NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy. If set
# to NO, these classes will be included in the various overviews. This option
# has no effect if EXTRACT_ALL is enabled.
# will also hide undocumented C++ concepts if enabled. This option has no effect
# if EXTRACT_ALL is enabled.
# The default value is: NO.
HIDE_UNDOC_CLASSES = NO
@ -577,14 +600,15 @@ INTERNAL_DOCS = NO
# filesystem is case sensitive (i.e. it supports files in the same directory
# whose names only differ in casing), the option must be set to YES to properly
# deal with such files in case they appear in the input. For filesystems that
# are not case sensitive the option should be be set to NO to properly deal with
# are not case sensitive the option should be set to NO to properly deal with
# output files written for symbols that only differ in casing, such as for two
# classes, one named CLASS and the other named Class, and to also support
# references to files without having to specify the exact matching casing. On
# Windows (including Cygwin) and MacOS, users should typically set this option
# to NO, whereas on Linux or other Unix flavors it should typically be set to
# YES.
# The default value is: system dependent.
# Possible values are: SYSTEM, NO and YES.
# The default value is: SYSTEM.
CASE_SENSE_NAMES = NO
@ -836,6 +860,14 @@ WARN_IF_INCOMPLETE_DOC = YES
WARN_NO_PARAMDOC = YES
# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, doxygen will warn about
# undocumented enumeration values. If set to NO, doxygen will accept
# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag
# will automatically be disabled.
# The default value is: NO.
WARN_IF_UNDOC_ENUM_VAL = NO
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
# 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
@ -851,13 +883,27 @@ WARN_AS_ERROR = NO
# and the warning text. Optionally the format may contain $version, which will
# be replaced by the version of the file (if it could be obtained via
# FILE_VERSION_FILTER)
# See also: WARN_LINE_FORMAT
# The default value is: $file:$line: $text.
WARN_FORMAT = "$file:$line: $text"
# In the $text part of the WARN_FORMAT command it is possible that a reference
# to a more specific place is given. To make it easier to jump to this place
# (outside of doxygen) the user can define a custom "cut" / "paste" string.
# Example:
# WARN_LINE_FORMAT = "'vi $file +$line'"
# See also: WARN_FORMAT
# The default value is: at line $line of file $file.
WARN_LINE_FORMAT = "at line $line of file $file"
# The WARN_LOGFILE tag can be used to specify a file to which warning and error
# messages should be written. If left blank the output is written to standard
# error (stderr).
# error (stderr). In case the file specified cannot be opened for writing the
# warning and error messages are written to standard error. When as file - is
# specified the warning and error messages are written to standard output
# (stdout).
WARN_LOGFILE =
@ -887,10 +933,21 @@ INPUT = ../src \
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
# documentation (see:
# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
# See also: INPUT_FILE_ENCODING
# The default value is: UTF-8.
INPUT_ENCODING = UTF-8
# This tag can be used to specify the character encoding of the source files
# that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify
# character encoding on a per file pattern basis. Doxygen will compare the file
# name with each pattern and apply the encoding instead of the default
# INPUT_ENCODING) if there is a match. The character encodings are a list of the
# form: pattern=encoding (like *.php=ISO-8859-1). See cfg_input_encoding
# "INPUT_ENCODING" for further information on supported encodings.
INPUT_FILE_ENCODING =
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
# *.h) to filter out the source-files in the directories.
@ -981,7 +1038,7 @@ EXCLUDE_PATTERNS =
# (namespaces, classes, functions, etc.) that should be excluded from the
# output. The symbol name can be a fully qualified name, a word, or if the
# wildcard * is used, a substring. Examples: ANamespace, AClass,
# AClass::ANamespace, ANamespace::*Test
# 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/*
@ -1029,6 +1086,11 @@ IMAGE_PATH =
# code is scanned, but not when the output code is generated. If lines are added
# or removed, the anchors will not be placed correctly.
#
# Note that doxygen will use the data processed and written to standard output
# for further processing, therefore nothing else, like debug statements or used
# commands (so in case of a Windows batch file always use @echo OFF), should be
# written to standard output.
#
# Note that for custom extensions or not directly supported extensions you also
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# properly processed by doxygen.
@ -1070,6 +1132,15 @@ FILTER_SOURCE_PATTERNS =
USE_MDFILE_AS_MAINPAGE =
# The Fortran standard specifies that for fixed formatted Fortran code all
# characters from position 72 are to be considered as comment. A common
# extension is to allow longer lines before the automatic comment starts. The
# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can
# be processed before the automatic comment starts.
# Minimum value: 7, maximum value: 10000, default value: 72.
FORTRAN_COMMENT_AFTER = 72
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
@ -1207,10 +1278,11 @@ CLANG_DATABASE_PATH =
ALPHABETICAL_INDEX = NO
# In case all classes in a project start with a common prefix, all classes will
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
# can be used to specify a prefix (or a list of prefixes) that should be ignored
# while generating the index headers.
# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes)
# that should be ignored while generating the index headers. The IGNORE_PREFIX
# tag works for classes, function and member names. The entity will be placed in
# the alphabetical list under the first letter of the entity name that remains
# after removing the prefix.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
IGNORE_PREFIX =
@ -1289,7 +1361,12 @@ HTML_STYLESHEET =
# Doxygen will copy the style sheet files to the output directory.
# Note: The order of the extra style sheet files is of importance (e.g. the last
# style sheet in the list overrules the setting of the previous ones in the
# list). For an example see the documentation.
# list).
# Note: Since the styling of scrollbars can currently not be overruled in
# Webkit/Chromium, the styling will be left out of the default doxygen.css if
# one or more extra stylesheets have been specified. So if scrollbar
# customization is desired it has to be added explicitly. For an example see the
# documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_STYLESHEET =
@ -1304,6 +1381,19 @@ HTML_EXTRA_STYLESHEET =
HTML_EXTRA_FILES =
# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output
# should be rendered with a dark or light theme.
# Possible values are: LIGHT always generate light mode output, DARK always
# generate dark mode output, AUTO_LIGHT automatically set the mode according to
# the user preference, use light mode if no preference is set (the default),
# AUTO_DARK automatically set the mode according to the user preference, use
# dark mode if no preference is set and TOGGLE allow to user to switch between
# light and dark mode via a button.
# The default value is: AUTO_LIGHT.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE = AUTO_LIGHT
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the style sheet and background images according to
# this color. Hue is specified as an angle on a color-wheel, see
@ -1398,6 +1488,13 @@ GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
# This tag determines the URL of the docset feed. A documentation feed provides
# an umbrella under which multiple documentation sets from a single provider
# (such as a company or product suite) can be grouped.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_FEEDURL =
# This tag specifies a string that should uniquely identify the documentation
# set bundle. This should be a reverse domain-name style string, e.g.
# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
@ -1602,7 +1699,7 @@ GENERATE_TREEVIEW = NO
# area (value NO) or if it should extend to the full height of the window (value
# YES). Setting this to YES gives a layout similar to
# https://docs.readthedocs.io with more room for contents, but less room for the
# project logo, title, and description. If either GENERATOR_TREEVIEW or
# project logo, title, and description. If either GENERATE_TREEVIEW or
# DISABLE_INDEX is set to NO, this option has no effect.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
@ -1633,6 +1730,13 @@ TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email
# addresses.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
OBFUSCATE_EMAILS = YES
# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
@ -1653,17 +1757,6 @@ HTML_FORMULA_FORMAT = png
FORMULA_FONTSIZE = 10
# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
# generated for formulas are transparent PNGs. Transparent PNGs are not
# supported properly for IE 6.0, but are supported on all modern browsers.
#
# Note that when changing this option you need to delete any form_*.png files in
# the HTML output directory before the changes have effect.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
FORMULA_TRANSPARENT = YES
# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
# to create new LaTeX commands to be used in formulas as building blocks. See
# the section "Including formulas" for details.
@ -2258,7 +2351,8 @@ SEARCH_INCLUDES = YES
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by the
# preprocessor.
# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of
# RECURSIVE has no effect here.
# This tag requires that the tag SEARCH_INCLUDES is set to YES.
INCLUDE_PATH =
@ -2354,15 +2448,6 @@ EXTERNAL_PAGES = YES
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
# NO turns the diagrams off. Note that this option also works with HAVE_DOT
# disabled, but it is recommended to install and use dot, since it yields more
# powerful graphs.
# The default value is: YES.
CLASS_DIAGRAMS = YES
# 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.
@ -2395,35 +2480,50 @@ HAVE_DOT = YES
DOT_NUM_THREADS = 0
# When you want a differently looking font in the dot files that doxygen
# generates you can specify the font name using DOT_FONTNAME. You need to make
# sure dot is able to find the font, which can be done by putting it in a
# standard location or by setting the DOTFONTPATH environment variable or by
# setting DOT_FONTPATH to the directory containing the font.
# The default value is: Helvetica.
# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of
# subgraphs. When you want a differently looking font in the dot files that
# doxygen generates you can specify fontname, fontcolor and fontsize attributes.
# For details please see <a href=https://graphviz.org/doc/info/attrs.html>Node,
# Edge and Graph Attributes specification</a> You need to make sure dot is able
# to find the font, which can be done by putting it in a standard location or by
# setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
# directory containing the font. Default graphviz fontsize is 14.
# The default value is: fontname=Helvetica,fontsize=10.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTNAME = Helvetica
DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10"
# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
# dot graphs.
# Minimum value: 4, maximum value: 24, default value: 10.
# DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can
# add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. <a
# href=https://graphviz.org/doc/info/arrows.html>Complete documentation about
# arrows shapes.</a>
# The default value is: labelfontname=Helvetica,labelfontsize=10.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTSIZE = 10
DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10"
# By default doxygen will tell dot to use the default font as specified with
# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
# the path where dot can find it using this tag.
# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes
# around nodes set 'shape=plain' or 'shape=plaintext' <a
# href=https://www.graphviz.org/doc/info/shapes.html>Shapes specification</a>
# The default value is: shape=box,height=0.2,width=0.4.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4"
# You can set the path where dot can find font specified with fontname in
# DOT_COMMON_ATTR and others dot attributes.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTPATH =
# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
# each documented class showing the direct and indirect inheritance relations.
# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
# 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.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
CLASS_GRAPH = YES
@ -2437,7 +2537,8 @@ CLASS_GRAPH = 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.
# groups, showing the direct groups dependencies. 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.
@ -2552,6 +2653,13 @@ GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels
# of child directories generated in directory dependency graphs by dot.
# Minimum value: 1, maximum value: 25, default value: 1.
# This tag requires that the tag DIRECTORY_GRAPH is set to YES.
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:
@ -2605,10 +2713,10 @@ MSCFILE_DIRS =
DIAFILE_DIRS =
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
# path where java can find the plantuml.jar file. If left blank, it is assumed
# PlantUML is not used or called during a preprocessing step. Doxygen will
# generate a warning when it encounters a \startuml command in this case and
# will not generate output for the diagram.
# path where java can find the plantuml.jar file or to the filename of jar file
# to be used. If left blank, it is assumed PlantUML is not used or called during
# a preprocessing step. Doxygen will generate a warning when it encounters a
# \startuml command in this case and will not generate output for the diagram.
PLANTUML_JAR_PATH =
@ -2646,18 +2754,6 @@ DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 1000
# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
# background. This is disabled by default, because dot on Windows does not seem
# to support this out of the box.
#
# Warning: Depending on the platform used, enabling this option may lead to
# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
# read).
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_TRANSPARENT = YES
# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
# makes dot run faster, but since only newer versions of dot (>1.8.10) support
@ -2670,6 +2766,8 @@ DOT_MULTI_TARGETS = NO
# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
# explaining the meaning of the various boxes and arrows in the dot generated
# graphs.
# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal
# graphical representation for inheritance and collaboration diagrams is used.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.

Binary file not shown.

View file

@ -3,7 +3,8 @@
const size_t BLOCK_SIZE = 64;
//------------------------------------------------------------------------------
// First block of file.
const size_t PIN_NUM_DIM = BLOCK_SIZE - 3*sizeof(uint32_t) - 2*sizeof(uint8_t);
const size_t PIN_NUM_DIM =
BLOCK_SIZE - 3 * sizeof(uint32_t) - 2 * sizeof(uint8_t);
struct metadata_t {
uint32_t adcFrequency; // ADC clock frequency
uint32_t cpuFrequency; // CPU clock frequency
@ -14,15 +15,16 @@ struct metadata_t {
};
//------------------------------------------------------------------------------
// Data block for 8-bit ADC mode.
const size_t DATA_DIM8 = (BLOCK_SIZE - 2*sizeof(uint16_t))/sizeof(uint8_t);
const size_t DATA_DIM8 = (BLOCK_SIZE - 2 * sizeof(uint16_t)) / sizeof(uint8_t);
struct block8_t {
uint16_t count; // count of data values
uint16_t overrun; // count of overruns since last block
uint8_t data[DATA_DIM8];
uint8_t data[DATA_DIM8];
};
//------------------------------------------------------------------------------
// Data block for 10-bit ADC mode.
const size_t DATA_DIM16 = (BLOCK_SIZE - 2*sizeof(uint16_t))/sizeof(uint16_t);
const size_t DATA_DIM16 =
(BLOCK_SIZE - 2 * sizeof(uint16_t)) / sizeof(uint16_t);
struct block16_t {
unsigned short count; // count of data values
unsigned short overrun; // count of overruns since last block

View file

@ -20,10 +20,11 @@
*/
#ifdef __AVR__
#include <SPI.h>
#include "SdFat.h"
#include "AvrAdcLogger.h"
#include "BufferedPrint.h"
#include "FreeStack.h"
#include "AvrAdcLogger.h"
#include "SdFat.h"
// Save SRAM if 328.
#ifdef __AVR_ATmega328P__
@ -73,7 +74,7 @@ const float SAMPLE_RATE = 5000; // Must be 0.25 or greater.
// constant instead of being calculated from SAMPLE_RATE. SAMPLE_RATE is not
// used in the code below. For example, setting SAMPLE_INTERVAL = 2.0e-4
// will result in a 200 microsecond sample interval.
const float SAMPLE_INTERVAL = 1.0/SAMPLE_RATE;
const float SAMPLE_INTERVAL = 1.0 / SAMPLE_RATE;
// Setting ROUND_SAMPLE_INTERVAL non-zero will cause the sample interval to
// be rounded to a a multiple of the ADC clock period and will reduce sample
@ -109,11 +110,11 @@ const size_t NAME_DIM = 40;
#elif RAMEND < 0X10FF
const size_t FIFO_SIZE_BYTES = 512;
#elif RAMEND < 0X20FF
const size_t FIFO_SIZE_BYTES = 4*512;
const size_t FIFO_SIZE_BYTES = 4 * 512;
#elif RAMEND < 0X40FF
const size_t FIFO_SIZE_BYTES = 12*512;
#else // RAMEND
const size_t FIFO_SIZE_BYTES = 16*512;
const size_t FIFO_SIZE_BYTES = 12 * 512;
#else // RAMEND
const size_t FIFO_SIZE_BYTES = 16 * 512;
#endif // RAMEND
//------------------------------------------------------------------------------
// ADC clock rate.
@ -136,7 +137,7 @@ const size_t FIFO_SIZE_BYTES = 16*512;
#define TMP_FILE_NAME "tmp_adc.bin"
// Number of analog pins to log.
const uint8_t PIN_COUNT = sizeof(PIN_LIST)/sizeof(PIN_LIST[0]);
const uint8_t PIN_COUNT = sizeof(PIN_LIST) / sizeof(PIN_LIST[0]);
// Minimum ADC clock cycles per sample interval
const uint16_t MIN_ADC_CYCLES = 15;
@ -181,19 +182,19 @@ file_t csvFile;
char binName[] = LOG_FILE_NAME;
#if RECORD_EIGHT_BITS
const size_t BLOCK_MAX_COUNT = PIN_COUNT*(DATA_DIM8/PIN_COUNT);
const size_t BLOCK_MAX_COUNT = PIN_COUNT * (DATA_DIM8 / PIN_COUNT);
typedef block8_t block_t;
#else // RECORD_EIGHT_BITS
const size_t BLOCK_MAX_COUNT = PIN_COUNT*(DATA_DIM16/PIN_COUNT);
#else // RECORD_EIGHT_BITS
const size_t BLOCK_MAX_COUNT = PIN_COUNT * (DATA_DIM16 / PIN_COUNT);
typedef block16_t block_t;
#endif // RECORD_EIGHT_BITS
#endif // RECORD_EIGHT_BITS
// Size of FIFO in blocks.
size_t const FIFO_DIM = FIFO_SIZE_BYTES/sizeof(block_t);
size_t const FIFO_DIM = FIFO_SIZE_BYTES / sizeof(block_t);
block_t* fifoData;
volatile size_t fifoCount = 0; // volatile - shared, ISR and background.
size_t fifoHead = 0; // Only accessed by ISR during logging.
size_t fifoTail = 0; // Only accessed by writer during logging.
volatile size_t fifoCount = 0; // volatile - shared, ISR and background.
size_t fifoHead = 0; // Only accessed by ISR during logging.
size_t fifoTail = 0; // Only accessed by writer during logging.
//==============================================================================
// Interrupt Service Routines
@ -220,7 +221,7 @@ ISR(ADC_vect) {
// Read ADC data.
#if RECORD_EIGHT_BITS
uint8_t d = ADCH;
#else // RECORD_EIGHT_BITS
#else // RECORD_EIGHT_BITS
// This will access ADCL first.
uint16_t d = ADC;
#endif // RECORD_EIGHT_BITS
@ -246,7 +247,7 @@ ISR(ADC_vect) {
if (adcindex == 0) {
timerFlag = false;
}
adcindex = adcindex < (PIN_COUNT - 1) ? adcindex + 1 : 0;
adcindex = adcindex < (PIN_COUNT - 1) ? adcindex + 1 : 0;
} else {
timerFlag = false;
}
@ -278,7 +279,7 @@ ISR(TIMER1_COMPB_vect) {
}
//==============================================================================
// Error messages stored in flash.
#define error(msg) (Serial.println(F(msg)),errorHalt())
#define error(msg) (Serial.println(F(msg)), errorHalt())
#define assert(e) ((e) ? (void)0 : error("assert: " #e))
//------------------------------------------------------------------------------
//
@ -337,12 +338,13 @@ void dateTime(uint16_t* date, uint16_t* time, uint8_t* ms10) {
#error unexpected ADC prescaler bits
#endif
//------------------------------------------------------------------------------
inline bool adcActive() {return (1 << ADIE) & ADCSRA;}
inline bool adcActive() { return (1 << ADIE) & ADCSRA; }
//------------------------------------------------------------------------------
// initialize ADC and timer1
void adcInit(metadata_t* meta) {
uint8_t adps; // prescaler bits for ADCSRA
uint32_t ticks = F_CPU*SAMPLE_INTERVAL + 0.5; // Sample interval cpu cycles.
uint32_t ticks =
F_CPU * SAMPLE_INTERVAL + 0.5; // Sample interval cpu cycles.
if (ADC_REF & ~((1 << REFS0) | (1 << REFS1))) {
error("Invalid ADC reference");
@ -352,9 +354,9 @@ void adcInit(metadata_t* meta) {
error("Invalid ADC prescaler");
}
adps = ADC_PRESCALER;
#else // ADC_PRESCALER
#else // ADC_PRESCALER
// Allow extra cpu cycles to change ADC settings if more than one pin.
int32_t adcCycles = (ticks - ISR_TIMER0)/PIN_COUNT - ISR_SETUP_ADC;
int32_t adcCycles = (ticks - ISR_TIMER0) / PIN_COUNT - ISR_SETUP_ADC;
for (adps = 7; adps > 0; adps--) {
if (adcCycles >= (MIN_ADC_CYCLES << adps)) {
@ -411,19 +413,19 @@ void adcInit(metadata_t* meta) {
// no prescale, CTC mode
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS10);
tshift = 0;
} else if (ticks < 0X10000*8) {
} else if (ticks < 0X10000 * 8) {
// prescale 8, CTC mode
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11);
tshift = 3;
} else if (ticks < 0X10000*64) {
} else if (ticks < 0X10000 * 64) {
// prescale 64, CTC mode
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11) | (1 << CS10);
tshift = 6;
} else if (ticks < 0X10000*256) {
} else if (ticks < 0X10000 * 256) {
// prescale 256, CTC mode
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS12);
tshift = 8;
} else if (ticks < 0X10000*1024) {
} else if (ticks < 0X10000 * 1024) {
// prescale 1024, CTC mode
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS12) | (1 << CS10);
tshift = 10;
@ -443,7 +445,7 @@ void adcInit(metadata_t* meta) {
// Sample interval in CPU clock ticks.
meta->sampleInterval = ticks;
meta->cpuFrequency = F_CPU;
float sampleRate = (float)meta->cpuFrequency/meta->sampleInterval;
float sampleRate = (float)meta->cpuFrequency / meta->sampleInterval;
Serial.print(F("Sample pins:"));
for (uint8_t i = 0; i < meta->pinCount; i++) {
Serial.print(' ');
@ -453,11 +455,11 @@ void adcInit(metadata_t* meta) {
Serial.print(F("ADC bits: "));
Serial.println(meta->recordEightBits ? 8 : 10);
Serial.print(F("ADC clock kHz: "));
Serial.println(meta->adcFrequency/1000);
Serial.println(meta->adcFrequency / 1000);
Serial.print(F("Sample Rate: "));
Serial.println(sampleRate);
Serial.print(F("Sample interval usec: "));
Serial.println(1000000.0/sampleRate);
Serial.println(1000000.0 / sampleRate);
}
//------------------------------------------------------------------------------
// enable ADC and timer1 interrupts
@ -509,7 +511,7 @@ void binaryToCsv() {
if (nb < 0) {
error("read binFile failed");
}
size_t nd = nb/sizeof(block_t);
size_t nd = nb / sizeof(block_t);
if (nd < 1) {
break;
}
@ -520,7 +522,8 @@ void binaryToCsv() {
error("Invalid pinCount");
}
bp.print(F("Interval,"));
float intervalMicros = 1.0e6*pm->sampleInterval/(float)pm->cpuFrequency;
float intervalMicros =
1.0e6 * pm->sampleInterval / (float)pm->cpuFrequency;
bp.print(intervalMicros, 4);
bp.println(F(",usec"));
for (uint8_t i = 0; i < PIN_COUNT; i++) {
@ -542,14 +545,15 @@ void binaryToCsv() {
}
for (size_t j = 0; j < pd->count; j += PIN_COUNT) {
for (size_t i = 0; i < PIN_COUNT; i++) {
if (!bp.printField(pd->data[i + j], i == (PIN_COUNT-1) ? '\n' : ',')) {
if (!bp.printField(pd->data[i + j],
i == (PIN_COUNT - 1) ? '\n' : ',')) {
error("printField failed");
}
}
}
}
if ((millis() - tPct) > 1000) {
uint8_t pct = binFile.curPosition()/(binFile.fileSize()/100);
uint8_t pct = binFile.curPosition() / (binFile.fileSize() / 100);
if (pct != lastPct) {
tPct = millis();
lastPct = pct;
@ -562,7 +566,7 @@ void binaryToCsv() {
error("close csvFile failed");
}
Serial.print(F("Done: "));
Serial.print(0.001*(millis() - t0));
Serial.print(0.001 * (millis() - t0));
Serial.println(F(" Seconds"));
}
//------------------------------------------------------------------------------
@ -620,7 +624,7 @@ bool createCsvFile() {
error("no dot in binName");
}
strcpy(dot + 1, "csv");
if (!csvFile.open(csvName, O_WRONLY|O_CREAT|O_TRUNC)) {
if (!csvFile.open(csvName, O_WRONLY | O_CREAT | O_TRUNC)) {
error("open csvFile failed");
}
Serial.print(F("Writing: "));
@ -633,7 +637,7 @@ bool createCsvFile() {
void logData() {
uint32_t t0;
uint32_t t1;
uint32_t overruns =0;
uint32_t overruns = 0;
uint32_t count = 0;
uint32_t maxLatencyUsec = 0;
size_t maxFifoUse = 0;
@ -677,7 +681,7 @@ void logData() {
if (m > maxLatencyUsec) {
maxLatencyUsec = m;
}
if (tmpFifoCount >maxFifoUse) {
if (tmpFifoCount > maxFifoUse) {
maxFifoUse = tmpFifoCount;
}
count += pBlock->count;
@ -712,7 +716,7 @@ void logData() {
isrStop = true;
}
if (fifoCount == 0 && !adcActive()) {
break;
break;
}
}
Serial.println();
@ -727,9 +731,9 @@ void logData() {
Serial.print(F("Max write latency usec: "));
Serial.println(maxLatencyUsec);
Serial.print(F("Record time sec: "));
Serial.println(0.001*(t1 - t0), 3);
Serial.println(0.001 * (t1 - t0), 3);
Serial.print(F("Sample count: "));
Serial.println(count/PIN_COUNT);
Serial.println(count / PIN_COUNT);
Serial.print(F("Overruns: "));
Serial.println(overruns);
Serial.print(F("FIFO_DIM: "));
@ -768,13 +772,13 @@ void printData() {
return;
}
binFile.rewind();
if (binFile.read(&buf , sizeof(buf)) != sizeof(buf)) {
if (binFile.read(&buf, sizeof(buf)) != sizeof(buf)) {
error("Read metadata failed");
}
Serial.println(F("Type any character to stop"));
delay(1000);
while (!Serial.available() &&
binFile.read(&buf , sizeof(buf)) == sizeof(buf)) {
binFile.read(&buf, sizeof(buf)) == sizeof(buf)) {
if (buf.count == 0) {
break;
}
@ -784,7 +788,7 @@ void printData() {
}
for (size_t i = 0; i < buf.count; i++) {
Serial.print(buf.data[i], DEC);
if ((i+1)%PIN_COUNT) {
if ((i + 1) % PIN_COUNT) {
Serial.print(',');
} else {
Serial.println();
@ -796,7 +800,7 @@ void printData() {
//------------------------------------------------------------------------------
bool serialReadLine(char* str, size_t size) {
size_t n = 0;
while(!Serial.available()) {
while (!Serial.available()) {
}
while (true) {
int c = Serial.read();
@ -807,7 +811,8 @@ bool serialReadLine(char* str, size_t size) {
return false;
}
uint32_t m = millis();
while (!Serial.available() && (millis() - m) < 100){}
while (!Serial.available() && (millis() - m) < 100) {
}
if (!Serial.available()) break;
}
str[n] = 0;
@ -819,9 +824,11 @@ void setup(void) {
pinMode(ERROR_LED_PIN, OUTPUT);
}
Serial.begin(9600);
while(!Serial) {}
while (!Serial) {
}
Serial.println(F("Type any character to begin."));
while(!Serial.available()) {}
while (!Serial.available()) {
}
FillStack();
@ -829,9 +836,9 @@ void setup(void) {
analogRead(PIN_LIST[0]);
#if !ENABLE_DEDICATED_SPI
Serial.println(F(
"\nFor best performance edit SdFatConfig.h\n"
"and set ENABLE_DEDICATED_SPI nonzero"));
Serial.println(
F("\nFor best performance edit SdFatConfig.h\n"
"and set ENABLE_DEDICATED_SPI nonzero"));
#endif // !ENABLE_DEDICATED_SPI
// Initialize SD.
if (!sd.begin(SD_CONFIG)) {
@ -865,7 +872,7 @@ void loop(void) {
Serial.println(F("p - print data to Serial"));
Serial.println(F("r - record ADC data"));
while(!Serial.available()) {
while (!Serial.available()) {
yield();
}
char c = tolower(Serial.read());

View file

@ -28,11 +28,12 @@ File myFile;
void setup() {
Serial.begin(9600);
while (!Serial) {}
while (!Serial) {
}
#if USE_SD_H
Serial.println(F("Using SD.h. Set USE_SD_H zero to use SdFat.h."));
#else // USE_SD_H
#else // USE_SD_H
Serial.println(F("Using SdFat.h. Set USE_SD_H nonzero to use SD.h."));
#endif // USE_SD_H
Serial.println(F("\nType any character to begin."));

View file

@ -1,8 +1,8 @@
// Test and benchmark of the fast bufferedPrint class.
//
// Mainly for AVR but may improve print performance with other CPUs.
#include "SdFat.h"
#include "BufferedPrint.h"
#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.
@ -19,7 +19,7 @@
// SDCARD_SS_PIN is defined for the built-in SD on some boards.
#ifndef SDCARD_SS_PIN
const uint8_t SD_CS_PIN = SS;
#else // SDCARD_SS_PIN
#else // SDCARD_SS_PIN
// Assume built-in SD is used.
const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
#endif // SDCARD_SS_PIN
@ -30,7 +30,7 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
// Try to select the best SD card configuration.
#if HAS_SDIO_CLASS
#define SD_CONFIG SdioConfig(FIFO_SDIO)
#elif ENABLE_DEDICATED_SPI
#elif ENABLE_DEDICATED_SPI
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
#else // HAS_SDIO_CLASS
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
@ -71,49 +71,48 @@ void benchmark() {
bp.begin(&file);
}
uint32_t t = millis();
switch(test) {
case 0:
Serial.println(F("Test of println(uint16_t)"));
for (uint16_t i = 0; i < N_PRINT; i++) {
file.println(i);
}
break;
switch (test) {
case 0:
Serial.println(F("Test of println(uint16_t)"));
for (uint16_t i = 0; i < N_PRINT; i++) {
file.println(i);
}
break;
case 1:
Serial.println(F("Test of printField(uint16_t, char)"));
for (uint16_t i = 0; i < N_PRINT; i++) {
bp.printField(i, '\n');
}
break;
case 1:
Serial.println(F("Test of printField(uint16_t, char)"));
for (uint16_t i = 0; i < N_PRINT; i++) {
bp.printField(i, '\n');
}
break;
case 2:
Serial.println(F("Test of println(uint32_t)"));
for (uint16_t i = 0; i < N_PRINT; i++) {
file.println(12345678UL + i);
}
break;
case 2:
Serial.println(F("Test of println(uint32_t)"));
for (uint16_t i = 0; i < N_PRINT; i++) {
file.println(12345678UL + i);
}
break;
case 3:
Serial.println(F("Test of printField(uint32_t, char)"));
for (uint16_t i = 0; i < N_PRINT; i++) {
bp.printField(12345678UL + i, '\n');
}
break;
case 3:
Serial.println(F("Test of printField(uint32_t, char)"));
for (uint16_t i = 0; i < N_PRINT; i++) {
bp.printField(12345678UL + i, '\n');
}
break;
case 4:
Serial.println(F("Test of println(double)"));
for (uint16_t i = 0; i < N_PRINT; i++) {
file.println((double)0.01*i);
}
break;
case 5:
Serial.println(F("Test of printField(double, char)"));
for (uint16_t i = 0; i < N_PRINT; i++) {
bp.printField((double)0.01*i, '\n');
}
break;
case 4:
Serial.println(F("Test of println(double)"));
for (uint16_t i = 0; i < N_PRINT; i++) {
file.println((double)0.01 * i);
}
break;
case 5:
Serial.println(F("Test of printField(double, char)"));
for (uint16_t i = 0; i < N_PRINT; i++) {
bp.printField((double)0.01 * i, '\n');
}
break;
}
if (test & 1) {
bp.sync();
@ -125,13 +124,13 @@ void benchmark() {
file.close();
t = millis() - t;
Serial.print(F("Time "));
Serial.print(0.001*t, 3);
Serial.print(0.001 * t, 3);
Serial.println(F(" sec"));
Serial.print(F("File size "));
Serial.print(0.001*s);
Serial.print(0.001 * s);
Serial.println(F(" KB"));
Serial.print(F("Write "));
Serial.print(s/t);
Serial.print(s / t);
Serial.println(F(" KB/sec"));
Serial.println();
}
@ -139,23 +138,23 @@ void benchmark() {
//------------------------------------------------------------------------------
void testMemberFunctions() {
BufferedPrint<Print, 32> bp(&Serial);
char c = 'c'; // char
char c = 'c'; // char
//#define BASIC_TYPES
#ifdef BASIC_TYPES
signed char sc = -1; // signed 8-bit
unsigned char uc = 1; // unsiged 8-bit
signed short ss = -2; // signed 16-bit
unsigned short us = 2; // unsigned 16-bit
signed long sl = -4; // signed 32-bit
unsigned long ul = 4; // unsigned 32-bit
#else // BASIC_TYPES
int8_t sc = -1; // signed 8-bit
uint8_t uc = 1; // unsiged 8-bit
int16_t ss = -2; // signed 16-bit
uint16_t us = 2; // unsigned 16-bit
int32_t sl = -4; // signed 32-bit
uint32_t ul = 4; // unsigned 32-bit
#endif // BASIC_TYPES
signed char sc = -1; // signed 8-bit
unsigned char uc = 1; // unsiged 8-bit
signed short ss = -2; // signed 16-bit
unsigned short us = 2; // unsigned 16-bit
signed long sl = -4; // signed 32-bit
unsigned long ul = 4; // unsigned 32-bit
#else // BASIC_TYPES
int8_t sc = -1; // signed 8-bit
uint8_t uc = 1; // unsiged 8-bit
int16_t ss = -2; // signed 16-bit
uint16_t us = 2; // unsigned 16-bit
int32_t sl = -4; // signed 32-bit
uint32_t ul = 4; // unsigned 32-bit
#endif // BASIC_TYPES
float f = -1.234;
double d = -5.678;
bp.println();
@ -216,9 +215,11 @@ void testMemberFunctions() {
//------------------------------------------------------------------------------
void setup() {
Serial.begin(9600);
while (!Serial) {}
while (!Serial) {
}
Serial.println("Type any character to begin.");
while(!Serial.available()) {}
while (!Serial.available()) {
}
if (!sd.begin(SD_CONFIG)) {
sd.initErrorHalt(&Serial);
}
@ -226,10 +227,10 @@ void setup() {
Serial.println(F("Test member funcions:"));
testMemberFunctions();
Serial.println();
Serial.println(F("Benchmark performance for uint16_t, uint32_t, and double:"));
Serial.println(
F("Benchmark performance for uint16_t, uint32_t, and double:"));
benchmark();
Serial.println("Done");
}
//------------------------------------------------------------------------------
void loop() {
}
void loop() {}

View file

@ -19,7 +19,7 @@
// SDCARD_SS_PIN is defined for the built-in SD on some boards.
#ifndef SDCARD_SS_PIN
const uint8_t SD_CS_PIN = SS;
#else // SDCARD_SS_PIN
#else // SDCARD_SS_PIN
// Assume built-in SD is used.
const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
#endif // SDCARD_SS_PIN
@ -30,7 +30,7 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
// Try to select the best SD card configuration.
#if HAS_SDIO_CLASS
#define SD_CONFIG SdioConfig(FIFO_SDIO)
#elif ENABLE_DEDICATED_SPI
#elif ENABLE_DEDICATED_SPI
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
#else // HAS_SDIO_CLASS
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
@ -78,9 +78,8 @@ void setup() {
if (!sd.begin(SD_CONFIG)) {
sd.initErrorHalt(&Serial);
}
if (sd.exists("Folder1")
|| sd.exists("Folder1/file1.txt")
|| sd.exists("Folder1/File2.txt")) {
if (sd.exists("Folder1") || sd.exists("Folder1/file1.txt") ||
sd.exists("Folder1/File2.txt")) {
error("Please remove existing Folder1, file1.txt, and File2.txt");
}

View file

@ -3,9 +3,9 @@
//
// The maximum data rate will depend on the quality of your SD,
// the size of the FIFO, and using dedicated SPI.
#include "SdFat.h"
#include "FreeStack.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.
@ -45,7 +45,7 @@ const uint32_t LOG_INTERVAL_USEC = 2000;
// SDCARD_SS_PIN is defined for the built-in SD on some boards.
#ifndef SDCARD_SS_PIN
const uint8_t SD_CS_PIN = SS;
#else // SDCARD_SS_PIN
#else // SDCARD_SS_PIN
// Assume built-in SD is used.
const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
#endif // SDCARD_SS_PIN
@ -71,7 +71,7 @@ const uint32_t PREALLOCATE_SIZE_MiB = 1024UL;
// Try to select the best SD card configuration.
#if HAS_SDIO_CLASS
#define SD_CONFIG SdioConfig(FIFO_SDIO)
#elif ENABLE_DEDICATED_SPI
#elif ENABLE_DEDICATED_SPI
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
#else // HAS_SDIO_CLASS
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
@ -127,11 +127,11 @@ void printRecord(Print* pr, data_t* data) {
}
}
//==============================================================================
const uint64_t PREALLOCATE_SIZE = (uint64_t)PREALLOCATE_SIZE_MiB << 20;
const uint64_t PREALLOCATE_SIZE = (uint64_t)PREALLOCATE_SIZE_MiB << 20;
// Max length of file name including zero byte.
#define FILE_NAME_DIM 40
// Max number of records to buffer while SD is busy.
const size_t FIFO_DIM = 512*FIFO_SIZE_SECTORS/sizeof(data_t);
const size_t FIFO_DIM = 512 * FIFO_SIZE_SECTORS / sizeof(data_t);
#if SD_FAT_TYPE == 0
typedef SdFat sd_t;
@ -191,22 +191,22 @@ void binaryToCsv() {
data_t binData[FIFO_DIM];
if (!binFile.seekSet(512)) {
error("binFile.seek failed");
error("binFile.seek failed");
}
uint32_t tPct = millis();
printRecord(&csvFile, nullptr);
while (!Serial.available() && binFile.available()) {
int nb = binFile.read(binData, sizeof(binData));
if (nb <= 0 ) {
if (nb <= 0) {
error("read binFile failed");
}
size_t nr = nb/sizeof(data_t);
size_t nr = nb / sizeof(data_t);
for (size_t i = 0; i < nr; i++) {
printRecord(&csvFile, &binData[i]);
}
if ((millis() - tPct) > 1000) {
uint8_t pct = binFile.curPosition()/(binFile.fileSize()/100);
uint8_t pct = binFile.curPosition() / (binFile.fileSize() / 100);
if (pct != lastPct) {
tPct = millis();
lastPct = pct;
@ -221,7 +221,7 @@ void binaryToCsv() {
}
csvFile.close();
Serial.print(F("Done: "));
Serial.print(0.001*(millis() - t0));
Serial.print(0.001 * (millis() - t0));
Serial.println(F(" Seconds"));
}
//------------------------------------------------------------------------------
@ -302,7 +302,7 @@ void logData() {
uint16_t overrun = 0;
uint16_t maxOverrun = 0;
uint32_t totalOverrun = 0;
uint32_t fifoBuf[128*FIFO_SIZE_SECTORS];
uint32_t fifoBuf[128 * FIFO_SIZE_SECTORS];
data_t* fifoData = (data_t*)fifoBuf;
// Write dummy sector to start multi-block write.
@ -315,7 +315,8 @@ void logData() {
Serial.println(F("Type any character to stop"));
// Wait until SD is not busy.
while (sd.card()->isBusy()) {}
while (sd.card()->isBusy()) {
}
// Start time for log file.
uint32_t m = millis();
@ -370,9 +371,9 @@ void logData() {
if (!sd.card()->isBusy()) {
size_t nw = fifoHead > fifoTail ? fifoCount : FIFO_DIM - fifoTail;
// Limit write time by not writing more than 512 bytes.
const size_t MAX_WRITE = 512/sizeof(data_t);
const size_t MAX_WRITE = 512 / sizeof(data_t);
if (nw > MAX_WRITE) nw = MAX_WRITE;
size_t nb = nw*sizeof(data_t);
size_t nb = nw * sizeof(data_t);
uint32_t usec = micros();
if (nb != binFile.write(fifoData + fifoTail, nb)) {
error("write binFile failed");
@ -392,7 +393,7 @@ void logData() {
}
}
Serial.print(F("\nLog time: "));
Serial.print(0.001*(millis() - m));
Serial.print(0.001 * (millis() - m));
Serial.println(F(" Seconds"));
binFile.truncate();
binFile.sync();
@ -469,7 +470,7 @@ void printUnusedStack() {
//------------------------------------------------------------------------------
bool serialReadLine(char* str, size_t size) {
size_t n = 0;
while(!Serial.available()) {
while (!Serial.available()) {
yield();
}
while (true) {
@ -481,7 +482,8 @@ bool serialReadLine(char* str, size_t size) {
return false;
}
uint32_t m = millis();
while (!Serial.available() && (millis() - m) < 100){}
while (!Serial.available() && (millis() - m) < 100) {
}
if (!Serial.available()) break;
}
str[n] = 0;
@ -525,9 +527,9 @@ void setup() {
}
FillStack();
#if !ENABLE_DEDICATED_SPI
Serial.println(F(
"\nFor best performance edit SdFatConfig.h\n"
"and set ENABLE_DEDICATED_SPI nonzero"));
Serial.println(
F("\nFor best performance edit SdFatConfig.h\n"
"and set ENABLE_DEDICATED_SPI nonzero"));
#endif // !ENABLE_DEDICATED_SPI
Serial.print(FIFO_DIM);
@ -567,7 +569,7 @@ void loop() {
Serial.println(F("p - print data to Serial"));
Serial.println(F("r - record data"));
Serial.println(F("t - test without logging"));
while(!Serial.available()) {
while (!Serial.available()) {
yield();
}
char c = tolower(Serial.read());

View file

@ -14,7 +14,8 @@ File file;
#include "SdFat.h"
// Setting ENABLE_DEDICATED_SPI to zero saves over 200 more bytes.
#if ENABLE_DEDICATED_SPI
#warning "Set ENABLE_DEDICATED_SPI zero in SdFat/src/SdFatConfig.h for minimum size"
#warning \
"Set ENABLE_DEDICATED_SPI zero in SdFat/src/SdFatConfig.h for minimum size"
#endif // ENABLE_DEDICATED_SPI
// Insure FAT16/FAT32 only.
SdFat32 SD;
@ -24,17 +25,19 @@ FatFile file;
void error(const char* msg) {
Serial.println(msg);
while(true);
while (true) {
}
}
void setup() {
int n;
char buf[4];
Serial.begin(9600);
while (!Serial) {}
while (!Serial) {
}
Serial.println("Type any character to begin");
while (!Serial.available()) {}
while (!Serial.available()) {
}
if (!SD.begin(CS_PIN)) error("SD.begin");
@ -47,12 +50,11 @@ void setup() {
if (!file.openExistingSFN(SFN_PATH)) error("open");
#endif
while ((n = file.read(buf, sizeof(buf)))) {
Serial.write(buf, n);
Serial.write(buf, n);
}
// close() is only needed if you write to the file. For example, read
// config data, modify the data, rewind the file and write the data.
// file.close();
// close() is only needed if you write to the file. For example, read
// config data, modify the data, rewind the file and write the data.
// file.close();
}
void loop() {
}
void loop() {}

View file

@ -18,7 +18,7 @@
// SDCARD_SS_PIN is defined for the built-in SD on some boards.
#ifndef SDCARD_SS_PIN
const uint8_t SD_CS_PIN = SS;
#else // SDCARD_SS_PIN
#else // SDCARD_SS_PIN
// Assume built-in SD is used.
const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
#endif // SDCARD_SS_PIN
@ -29,7 +29,7 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
// Try to select the best SD card configuration.
#if HAS_SDIO_CLASS
#define SD_CONFIG SdioConfig(FIFO_SDIO)
#elif ENABLE_DEDICATED_SPI
#elif ENABLE_DEDICATED_SPI
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
#else // HAS_SDIO_CLASS
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
@ -76,7 +76,7 @@ void setup() {
sd.initErrorHalt(&Serial);
}
// Open root directory
if (!dir.open("/")){
if (!dir.open("/")) {
error("dir.open failed");
}
// Open next file in root.

View file

@ -1,6 +1,7 @@
// Quick hardware test for SPI card access.
//
#include <SPI.h>
#include "SdFat.h"
#include "sdios.h"
@ -81,17 +82,17 @@ void setup() {
if (DISABLE_CHIP_SELECT < 0) {
cout << F(
"\nBe sure to edit DISABLE_CHIP_SELECT if you have\n"
"a second SPI device. For example, with the Ethernet\n"
"shield, DISABLE_CHIP_SELECT should be set to 10\n"
"to disable the Ethernet controller.\n");
"\nBe sure to edit DISABLE_CHIP_SELECT if you have\n"
"a second SPI device. For example, with the Ethernet\n"
"shield, DISABLE_CHIP_SELECT should be set to 10\n"
"to disable the Ethernet controller.\n");
}
cout << F(
"\nSD chip select is the key hardware option.\n"
"Common values are:\n"
"Arduino Ethernet shield, pin 4\n"
"Sparkfun SD shield, pin 8\n"
"Adafruit SD shields and modules, pin 10\n");
"\nSD chip select is the key hardware option.\n"
"Common values are:\n"
"Arduino Ethernet shield, pin 4\n"
"Sparkfun SD shield, pin 8\n"
"Adafruit SD shields and modules, pin 10\n");
}
bool firstTry = true;
@ -117,8 +118,8 @@ void loop() {
}
if (DISABLE_CHIP_SELECT < 0) {
cout << F(
"\nAssuming the SD is the only SPI device.\n"
"Edit DISABLE_CHIP_SELECT to disable another device.\n");
"\nAssuming the SD is the only SPI device.\n"
"Edit DISABLE_CHIP_SELECT to disable another device.\n");
} else {
cout << F("\nDisabling SPI device on pin ");
cout << int(DISABLE_CHIP_SELECT) << endl;
@ -128,12 +129,12 @@ void loop() {
if (!sd.begin(chipSelect, SPI_SPEED)) {
if (sd.card()->errorCode()) {
cout << F(
"\nSD initialization failed.\n"
"Do not reformat the card!\n"
"Is the card correctly inserted?\n"
"Is chipSelect set to the correct value?\n"
"Does another SPI device need to be disabled?\n"
"Is there a wiring/soldering problem?\n");
"\nSD initialization failed.\n"
"Do not reformat the card!\n"
"Is the card correctly inserted?\n"
"Is chipSelect set to the correct value?\n"
"Does another SPI device need to be disabled?\n"
"Is there a wiring/soldering problem?\n");
cout << F("\nerrorCode: ") << hex << showbase;
cout << int(sd.card()->errorCode());
cout << F(", errorData: ") << int(sd.card()->errorData());
@ -169,8 +170,8 @@ void loop() {
cout << F("Files found (date time size name):\n");
sd.ls(LS_R | LS_DATE | LS_SIZE);
if ((sizeMB > 1100 && sd.vol()->sectorsPerCluster() < 64)
|| (sizeMB < 2200 && sd.vol()->fatType() == 32)) {
if ((sizeMB > 1100 && sd.vol()->sectorsPerCluster() < 64) ||
(sizeMB < 2200 && sd.vol()->fatType() == 32)) {
cout << F("\nThis card should be reformatted for best performance.\n");
cout << F("Use a cluster size of 32 KB for cards larger than 1 GB.\n");
cout << F("Only cards larger than 2 GB should be formatted FAT32.\n");

View file

@ -15,7 +15,7 @@
// SDCARD_SS_PIN is defined for the built-in SD on some boards.
#ifndef SDCARD_SS_PIN
const uint8_t SD_CS_PIN = SS;
#else // SDCARD_SS_PIN
#else // SDCARD_SS_PIN
// Assume built-in SD is used.
const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
#endif // SDCARD_SS_PIN
@ -26,7 +26,7 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
// Try to select the best SD card configuration.
#if HAS_SDIO_CLASS
#define SD_CONFIG SdioConfig(FIFO_SDIO)
#elif ENABLE_DEDICATED_SPI
#elif ENABLE_DEDICATED_SPI
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
#else // HAS_SDIO_CLASS
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
@ -127,10 +127,10 @@ void setup() {
error("open failed");
}
// Write test data.
file.print(F(
"abc,123,456,7.89\r\n"
"def,-321,654,-9.87\r\n"
"ghi,333,0xff,5.55"));
file.print(
F("abc,123,456,7.89\r\n"
"def,-321,654,-9.87\r\n"
"ghi,333,0xff,5.55"));
// Rewind file for read.
file.rewind();
@ -140,7 +140,7 @@ void setup() {
if (n <= 0) {
error("fgets failed");
}
if (line[n-1] != '\n' && n == (sizeof(line) - 1)) {
if (line[n - 1] != '\n' && n == (sizeof(line) - 1)) {
error("line too long");
}
if (!parseLine(line)) {
@ -152,5 +152,4 @@ void setup() {
Serial.println(F("Done"));
}
void loop() {
}
void loop() {}

View file

@ -26,7 +26,7 @@
// SDCARD_SS_PIN is defined for the built-in SD on some boards.
#ifndef SDCARD_SS_PIN
const uint8_t SD_CS_PIN = SS;
#else // SDCARD_SS_PIN
#else // SDCARD_SS_PIN
// Assume built-in SD is used.
const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
#endif // SDCARD_SS_PIN
@ -37,7 +37,7 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
// Try to select the best SD card configuration.
#if HAS_SDIO_CLASS
#define SD_CONFIG SdioConfig(FIFO_SDIO)
#elif ENABLE_DEDICATED_SPI
#elif ENABLE_DEDICATED_SPI
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
#else // HAS_SDIO_CLASS
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
@ -59,7 +59,6 @@ FsFile file;
#error Invalid SD_FAT_TYPE
#endif // SD_FAT_TYPE
#if RTC_TYPE == 0
RTC_Millis rtc;
#elif RTC_TYPE == 1
@ -108,12 +107,12 @@ void getLine(char* line, size_t size) {
while (true) {
t = millis() + 10;
while (!Serial.available()) {
if (millis() > t){
if (millis() > t) {
return;
}
}
int c = Serial.read();
if (i >= (size - 1) || c == '\r' || c == '\n' ) {
if (i >= (size - 1) || c == '\r' || c == '\n') {
return;
}
line[i++] = c;
@ -134,11 +133,11 @@ void printField(Print* pr, char sep, uint8_t v) {
void printNow(Print* pr) {
DateTime now = rtc.now();
pr->print(now.year());
printField(pr, '-',now.month());
printField(pr, '-',now.day());
printField(pr, ' ',now.hour());
printField(pr, ':',now.minute());
printField(pr, ':',now.second());
printField(pr, '-', now.month());
printField(pr, '-', now.day());
printField(pr, ' ', now.hour());
printField(pr, ':', now.minute());
printField(pr, ':', now.second());
}
//------------------------------------------------------------------------------
bool setRtc() {
@ -180,7 +179,7 @@ void setup() {
}
#if RTC_TYPE == 0
rtc.begin(DateTime(F(__DATE__), F(__TIME__)));
#else // RTC_TYPE
#else // RTC_TYPE
if (!rtc.begin()) {
Serial.println(F("rtc.begin failed"));
return;
@ -201,7 +200,8 @@ void setup() {
Serial.println();
clearSerialInput();
Serial.println(F("Type Y to set RTC, any other character to continue"));
while (!Serial.available()) {}
while (!Serial.available()) {
}
if (Serial.read() != 'Y') break;
if (setRtc()) break;
}
@ -232,5 +232,4 @@ void setup() {
Serial.println(F("Done"));
}
//------------------------------------------------------------------------------
void loop() {
}
void loop() {}

View file

@ -2,7 +2,8 @@
#include "SdFat.h"
void setup() {
Serial.begin(9600);
while (!Serial) {}
while (!Serial) {
}
delay(1000);
Serial.println();
Serial.println(F("Code,Symbol - failed operation"));

View file

@ -31,7 +31,7 @@ const int8_t DISABLE_CS_PIN = -1;
// SDCARD_SS_PIN is defined for the built-in SD on some boards.
#ifndef SDCARD_SS_PIN
const uint8_t SD_CS_PIN = SS;
#else // SDCARD_SS_PIN
#else // SDCARD_SS_PIN
// Assume built-in SD is used.
const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
#endif // SDCARD_SS_PIN
@ -42,7 +42,7 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
// Try to select the best SD card configuration.
#if HAS_SDIO_CLASS
#define SD_CONFIG SdioConfig(FIFO_SDIO)
#elif ENABLE_DEDICATED_SPI
#elif ENABLE_DEDICATED_SPI
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
#else // HAS_SDIO_CLASS
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
@ -52,14 +52,18 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
ArduinoOutStream cout(Serial);
//------------------------------------------------------------------------------
uint32_t cardSectorCount = 0;
uint8_t sectorBuffer[512];
uint8_t sectorBuffer[512];
//------------------------------------------------------------------------------
// SdCardFactory constructs and initializes the appropriate card.
SdCardFactory cardFactory;
// Pointer to generic SD card.
SdCard* m_card = nullptr;
//------------------------------------------------------------------------------
#define sdError(msg) {cout << F("error: ") << F(msg) << endl; sdErrorHalt();}
#define sdError(msg) \
{ \
cout << F("error: ") << F(msg) << endl; \
sdErrorHalt(); \
}
//------------------------------------------------------------------------------
void sdErrorHalt() {
if (!m_card) {
@ -73,7 +77,8 @@ void sdErrorHalt() {
cout << F(" = ") << int(m_card->errorCode()) << endl;
cout << F("SD errorData = ") << int(m_card->errorData()) << endl;
}
while (true) {}
while (true) {
}
}
//------------------------------------------------------------------------------
void clearSerialInput() {
@ -102,7 +107,7 @@ void eraseCard() {
sdError("erase failed");
}
cout << '.';
if ((n++)%64 == 63) {
if ((n++) % 64 == 63) {
cout << endl;
}
firstBlock += ERASE_SIZE;
@ -123,9 +128,9 @@ void formatCard() {
FatFormatter fatFormatter;
// Format exFAT if larger than 32GB.
bool rtn = cardSectorCount > 67108864 ?
exFatFormatter.format(m_card, sectorBuffer, &Serial) :
fatFormatter.format(m_card, sectorBuffer, &Serial);
bool rtn = cardSectorCount > 67108864
? exFatFormatter.format(m_card, sectorBuffer, &Serial)
: fatFormatter.format(m_card, sectorBuffer, &Serial);
if (!rtn) {
sdErrorHalt();
@ -136,8 +141,8 @@ void formatCard() {
void printConfig(SdSpiConfig config) {
if (DISABLE_CS_PIN < 0) {
cout << F(
"\nAssuming the SD is the only SPI device.\n"
"Edit DISABLE_CS_PIN to disable an SPI device.\n");
"\nAssuming the SD is the only SPI device.\n"
"Edit DISABLE_CS_PIN to disable an SPI device.\n");
} else {
cout << F("\nDisabling SPI device on pin ");
cout << int(DISABLE_CS_PIN) << endl;
@ -169,19 +174,19 @@ void setup() {
clearSerialInput();
cout << F(
"\n"
"This program can erase and/or format SD/SDHC/SDXC cards.\n"
"\n"
"Erase uses the card's fast flash erase command.\n"
"Flash erase sets all data to 0X00 for most cards\n"
"and 0XFF for a few vendor's cards.\n"
"\n"
"Cards up to 2 GiB (GiB = 2^30 bytes) will be formated FAT16.\n"
"Cards larger than 2 GiB and up to 32 GiB will be formatted\n"
"FAT32. Cards larger than 32 GiB will be formatted exFAT.\n"
"\n"
"Warning, all data on the card will be erased.\n"
"Enter 'Y' to continue: ");
"\n"
"This program can erase and/or format SD/SDHC/SDXC cards.\n"
"\n"
"Erase uses the card's fast flash erase command.\n"
"Flash erase sets all data to 0X00 for most cards\n"
"and 0XFF for a few vendor's cards.\n"
"\n"
"Cards up to 2 GiB (GiB = 2^30 bytes) will be formated FAT16.\n"
"Cards larger than 2 GiB and up to 32 GiB will be formatted\n"
"FAT32. Cards larger than 32 GiB will be formatted exFAT.\n"
"\n"
"Warning, all data on the card will be erased.\n"
"Enter 'Y' to continue: ");
while (!Serial.available()) {
yield();
}
@ -207,9 +212,9 @@ void setup() {
return;
}
cout << F("\nCard size: ") << cardSectorCount*5.12e-7;
cout << F("\nCard size: ") << cardSectorCount * 5.12e-7;
cout << F(" GB (GB = 1E9 bytes)\n");
cout << F("Card size: ") << cardSectorCount/2097152.0;
cout << F("Card size: ") << cardSectorCount / 2097152.0;
cout << F(" GiB (GiB = 2^30 bytes)\n");
cout << F("Card will be formated ");
@ -221,13 +226,13 @@ void setup() {
cout << F("FAT16\n");
}
cout << F(
"\n"
"Options are:\n"
"E - erase the card and skip formatting.\n"
"F - erase and then format the card. (recommended)\n"
"Q - quick format the card without erase.\n"
"\n"
"Enter option: ");
"\n"
"Options are:\n"
"E - erase the card and skip formatting.\n"
"F - erase and then format the card. (recommended)\n"
"Q - quick format the card without erase.\n"
"\n"
"Enter option: ");
while (!Serial.available()) {
yield();
@ -245,5 +250,4 @@ void setup() {
formatCard();
}
}
void loop() {
}
void loop() {}

View file

@ -20,7 +20,7 @@ const int8_t DISABLE_CS_PIN = -1;
// SDCARD_SS_PIN is defined for the built-in SD on some boards.
#ifndef SDCARD_SS_PIN
const uint8_t SD_CS_PIN = SS;
#else // SDCARD_SS_PIN
#else // SDCARD_SS_PIN
const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
#endif // SDCARD_SS_PIN
@ -99,7 +99,7 @@ void errorPrint() {
bool mbrDmp() {
MbrSector_t mbr;
bool valid = true;
if (!sd.card()->readSector(0, (uint8_t*)&mbr)) {
if (!sd.card()->readSector(0, (uint8_t *)&mbr)) {
cout << F("\nread MBR failed.\n");
errorPrint();
return false;
@ -114,11 +114,11 @@ bool mbrDmp() {
}
cout << int(ip) << ',' << uppercase << showbase << hex;
cout << int(pt->boot) << ',';
for (int i = 0; i < 3; i++ ) {
for (int i = 0; i < 3; i++) {
cout << int(pt->beginCHS[i]) << ',';
}
cout << int(pt->type) << ',';
for (int i = 0; i < 3; i++ ) {
for (int i = 0; i < 3; i++) {
cout << int(pt->endCHS[i]) << ',';
}
cout << dec << getLe32(pt->relativeSectors) << ',';
@ -141,18 +141,17 @@ void dmpVol() {
cout << F("sectorsPerCluster: ") << sd.sectorsPerCluster() << endl;
cout << F("fatStartSector: ") << sd.fatStartSector() << endl;
cout << F("dataStartSector: ") << sd.dataStartSector() << endl;
cout << F("clusterCount: ") << sd.clusterCount() << endl;
cout << F("clusterCount: ") << sd.clusterCount() << endl;
cout << F("freeClusterCount: ");
if (freeClusterCount >= 0) {
cout << freeClusterCount << endl;
} else {
cout << F("failed\n");
errorPrint();
errorPrint();
}
}
//------------------------------------------------------------------------------
void printCardType() {
cout << F("\nCard type: ");
switch (sd.card()->type()) {
@ -180,8 +179,8 @@ void printCardType() {
void printConfig(SdSpiConfig config) {
if (DISABLE_CS_PIN < 0) {
cout << F(
"\nAssuming the SD is the only SPI device.\n"
"Edit DISABLE_CS_PIN to disable an SPI device.\n");
"\nAssuming the SD is the only SPI device.\n"
"Edit DISABLE_CS_PIN to disable an SPI device.\n");
} else {
cout << F("\nDisabling SPI device on pin ");
cout << int(DISABLE_CS_PIN) << endl;
@ -205,7 +204,6 @@ void setup() {
}
cout << F("SdFat version: ") << SD_FAT_VERSION_STR << endl;
printConfig(SD_CONFIG);
}
//------------------------------------------------------------------------------
void loop() {
@ -220,15 +218,14 @@ void loop() {
uint32_t t = millis();
if (!sd.cardBegin(SD_CONFIG)) {
cout << F(
"\nSD initialization failed.\n"
"Do not reformat the card!\n"
"Is the card correctly inserted?\n"
"Is there a wiring/soldering problem?\n");
"\nSD initialization failed.\n"
"Do not reformat the card!\n"
"Is the card correctly inserted?\n"
"Is there a wiring/soldering problem?\n");
if (isSpi(SD_CONFIG)) {
cout << F(
"Is SD_CS_PIN set to the correct value?\n"
"Does another SPI device need to be disabled?\n"
);
"Is SD_CS_PIN set to the correct value?\n"
"Does another SPI device need to be disabled?\n");
}
errorPrint();
return;
@ -236,23 +233,21 @@ void loop() {
t = millis() - t;
cout << F("init time: ") << dec << t << " ms" << endl;
if (!sd.card()->readCID(&cid) ||
!sd.card()->readCSD(&csd) ||
!sd.card()->readOCR(&ocr) ||
!sd.card()->readSCR(&scr)) {
if (!sd.card()->readCID(&cid) || !sd.card()->readCSD(&csd) ||
!sd.card()->readOCR(&ocr) || !sd.card()->readSCR(&scr)) {
cout << F("readInfo failed\n");
errorPrint();
return;
}
printCardType();
cout << F("sdSpecVer: ") << 0.01*scr.sdSpecVer() << endl;
cout << F("sdSpecVer: ") << 0.01 * scr.sdSpecVer() << endl;
cout << F("HighSpeedMode: ");
if (scr.sdSpecVer() &&
sd.card()->cardCMD6(0X00FFFFFF, cmd6Data) && (2 & cmd6Data[13])) {
if (scr.sdSpecVer() && sd.card()->cardCMD6(0X00FFFFFF, cmd6Data) &&
(2 & cmd6Data[13])) {
cout << F("true\n");
} else {
cout << F("false\n");
}
}
cidDmp();
csdDmp();
cout << F("\nOCR: ") << uppercase << showbase;

View file

@ -16,7 +16,7 @@ const uint8_t SD_CS_PIN = 10;
// Pin numbers in templates must be constants.
const uint8_t SOFT_MISO_PIN = 12;
const uint8_t SOFT_MOSI_PIN = 11;
const uint8_t SOFT_SCK_PIN = 13;
const uint8_t SOFT_SCK_PIN = 13;
// SdFat software SPI template
SoftSpiDriver<SOFT_MISO_PIN, SOFT_MOSI_PIN, SOFT_SCK_PIN> softSpi;
@ -77,4 +77,4 @@ void setup() {
void loop() {}
#else // SPI_DRIVER_SELECT
#error SPI_DRIVER_SELECT must be two in SdFat/SdFatConfig.h
#endif //SPI_DRIVER_SELECT
#endif // SPI_DRIVER_SELECT

View file

@ -1,14 +1,20 @@
// Test of Teensy exFAT DMA ADC logger.
// This is mainly to test use of RingBuf in an ISR.
// This example only supports pins on the first ADC.
// it has only been tested on Teensy 3.6 and 4.1.
// You should modify it for serious use as a data logger.
//
#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
// 400 sector RingBuf - could be larger on Teensy 4.1.
const size_t RING_BUF_SIZE = 400*512;
const size_t RING_BUF_SIZE = 400 * 512;
// Preallocate 8GiB file.
const uint64_t PRE_ALLOCATE_SIZE = 8ULL << 30;
@ -16,15 +22,19 @@ const uint64_t PRE_ALLOCATE_SIZE = 8ULL << 30;
// Use FIFO SDIO.
#define SD_CONFIG SdioConfig(FIFO_SDIO)
ADC adc;
DMAChannel dma(true);
SdFs sd;
FsFile file;
//------------------------------------------------------------------------------
// Ping-pong DMA buffer.
DMAMEM static uint16_t __attribute__((aligned(32))) dmaBuf[2][256];
size_t dmaCount;
// Count of DMA interrupts.
volatile size_t dmaCount;
// RingBuf for 512 byte sectors.
RingBuf<FsFile, RING_BUF_SIZE> rb;
@ -32,18 +42,26 @@ RingBuf<FsFile, RING_BUF_SIZE> rb;
// Shared between ISR and background.
volatile size_t maxBytesUsed;
// Overrun error for write to RingBuf.
volatile bool overrun;
//------------------------------------------------------------------------------
//ISR.
// ISR for DMA.
static void isr() {
if (rb.bytesFreeIsr() >= 512 && !overrun) {
rb.memcpyIn(dmaBuf[dmaCount & 1], 512);
dmaCount++;
if (rb.bytesUsed() > maxBytesUsed) {
maxBytesUsed = rb.bytesUsed();
if (!overrun) {
// Clear cache for buffer filled by DMA to insure read from DMA memory.
arm_dcache_delete((void*)dmaBuf[dmaCount & 1], 512);
// Enable RingBuf functions to be called in ISR.
rb.beginISR();
if (rb.write(dmaBuf[dmaCount & 1], 512) == 512) {
dmaCount++;
if (rb.bytesUsed() > maxBytesUsed) {
maxBytesUsed = rb.bytesUsed();
}
} else {
overrun = true;
}
} else {
overrun = true;
// End use of RingBuf functions in ISR.
rb.endISR();
}
dma.clearComplete();
dma.clearInterrupt();
@ -53,39 +71,7 @@ static void isr() {
#endif // defined(__IMXRT1062__)
}
//------------------------------------------------------------------------------
// Over-clocking will degrade quality - use only for stress testing.
void overclock() {
#if defined(__IMXRT1062__) // Teensy 4.0
ADC1_CFG =
// High Speed Configuration
ADC_CFG_ADHSC |
// Sample period 3 clocks
ADC_CFG_ADSTS(0) |
// Input clock
ADC_CFG_ADIV(0) |
// Not selected - Long Sample Time Configuration
// ADC_CFG_ADLSMP |
// 12-bit
ADC_CFG_MODE(2) |
// Asynchronous clock
ADC_CFG_ADICLK(3);
#else // defined(__IMXRT1062__)
// Set 12 bit mode and max over-clock
ADC0_CFG1 =
// Clock divide select, 0=direct, 1=div2, 2=div4, 3=div8
ADC_CFG1_ADIV(0) |
// Sample time configuration, 0=Short, 1=Long
// ADC_CFG1_ADLSMP |
// Conversion mode, 0=8 bit, 1=12 bit, 2=10 bit, 3=16 bit
ADC_CFG1_MODE(1) |
// Input clock, 0=bus, 1=bus/2, 2=OSCERCLK, 3=async
ADC_CFG1_ADICLK(0);
ADC0_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(3);
#endif // defined(__IMXRT1062__)
}
//------------------------------------------------------------------------------
#if defined(__IMXRT1062__) // Teensy 4.0
#if defined(__IMXRT1062__) // Teensy 4.x
#define SOURCE_SADDR ADC1_R0
#define SOURCE_EVENT DMAMUX_SOURCE_ADC1
#else
@ -93,54 +79,26 @@ void overclock() {
#define SOURCE_EVENT DMAMUX_SOURCE_ADC0
#endif
//------------------------------------------------------------------------------
// Should replace ADC stuff with calls to Teensy ADC library.
// https://github.com/pedvide/ADC
static void init(uint8_t pin) {
uint32_t adch;
uint32_t i, sum = 0;
// Actually, do many normal reads, to start with a nice DC level
for (i=0; i < 1024; i++) {
sum += analogRead(pin);
}
#if defined(__IMXRT1062__) // Teensy 4.0
// save channel
adch = ADC1_HC0 & 0x1F;
// Continuous conversion , DMA enable
ADC1_GC = ADC_GC_ADCO | ADC_GC_DMAEN;
// start conversion
ADC1_HC0 = adch;
#else // defined(__IMXRT1062__) // Teensy 4.0
// save channel
adch = ADC0_SC1A & 0x1F;
// DMA enable
ADC0_SC2 |= ADC_SC2_DMAEN;
// Continuous conversion enable
ADC0_SC3 = ADC_SC3_ADCO;
// Start ADC
ADC0_SC1A = adch;
#endif // defined(__IMXRT1062__) // Teensy 4.0
// set up a DMA channel to store the ADC data
dma.attachInterrupt(isr);
dma.begin();
dma.source((volatile const signed short &)SOURCE_SADDR);
dma.begin();
dma.attachInterrupt(isr);
dma.source((volatile const signed short&)SOURCE_SADDR);
dma.destinationBuffer((volatile uint16_t*)dmaBuf, sizeof(dmaBuf));
dma.interruptAtHalf();
dma.interruptAtCompletion();
dma.triggerAtHardwareEvent(SOURCE_EVENT);
dma.enable();
dma.triggerAtHardwareEvent(SOURCE_EVENT);
dma.enable();
adc.adc0->enableDMA();
adc.adc0->startContinuous(pin);
}
//------------------------------------------------------------------------------
void stopDma() {
#if defined(__IMXRT1062__) // Teensy 4.0
ADC1_GC = 0;
#else // defined(__IMXRT1062__)
ADC0_SC3 = 0;
#endif // defined(__IMXRT1062__)
adc.adc0->disableDMA();
dma.disable();
}
//------------------------------------------------------------------------------
void printTest(Print* pr) {
if (file.fileSize() < 1024*2) {
if (file.fileSize() < 1024 * 2) {
return;
}
file.rewind();
@ -153,7 +111,8 @@ void printTest(Print* pr) {
for (size_t i = 0; i < 1024; i++) {
pr->print(i);
pr->print(',');
rb.memcpyOut(&data, 2);
// Test read with: template <typename Type>bool read(Type* data).
rb.read(&data);
pr->println(data);
}
}
@ -192,36 +151,42 @@ void runTest(uint8_t pin) {
}
}
stopDma();
samplingTime = (micros() - samplingTime);
samplingTime = micros() - samplingTime;
if (!rb.sync()) {
Serial.println("sync() failed");
file.close();
return;
}
if (!file.truncate()) {
sd.errorHalt("truncate failed");
}
if (overrun) {
Serial.println("Overrun ERROR!!");
}
Serial.print("dmsCount ");
Serial.println(dmaCount);
Serial.print("RingBufSize ");
Serial.println(RING_BUF_SIZE);
Serial.print("maxBytesUsed ");
Serial.println(maxBytesUsed);
Serial.print("fileSize ");
Serial.println((uint32_t)file.fileSize());
Serial.print(0.000001*samplingTime);
file.printFileSize(&Serial);
Serial.println();
Serial.print(0.000001 * samplingTime);
Serial.println(" seconds");
Serial.print(1.0*file.fileSize()/samplingTime, 3);
Serial.print(1.0 * file.fileSize() / samplingTime, 3);
Serial.println(" MB/sec\n");
printTest(&Serial);
file.close();
}
//------------------------------------------------------------------------------
void waitSerial(const char* msg) {
uint32_t m = micros();
do {
if (Serial.read() >= 0) {
m = micros();
}
} while (micros() - m < 10000);
delay(10);
} while (Serial.read() >= 0);
Serial.println(msg);
while (!Serial.available()) {}
while (!Serial.available()) {
}
Serial.println();
}
//------------------------------------------------------------------------------
@ -239,9 +204,11 @@ void loop() {
if (!sd.begin(SD_CONFIG)) {
sd.initErrorHalt(&Serial);
}
//analogReadAveraging(1);
//analogReadResolution(12);
//overclock(); // 3 Msps on Teensy 3.6 - requires high quality card.
runTest(A0);
// Try for max speed.
adc.adc0->setAveraging(1);
adc.adc0->setResolution(10);
adc.adc0->setConversionSpeed(ADC_CONVERSION_SPEED::VERY_HIGH_SPEED);
adc.adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED);
runTest(ADC_PIN);
waitSerial("Type any character to run test again");
}

View file

@ -1,9 +1,10 @@
// Test of time-stamp callback with Teensy 3/4.
// The upload time will be used to set the RTC.
// You must arrange for syncing the RTC.
#include "SdFat.h"
#include <TimeLib.h>
#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.
#define SD_FAT_TYPE 3
@ -19,7 +20,7 @@
// SDCARD_SS_PIN is defined for the built-in SD on some boards.
#ifndef SDCARD_SS_PIN
const uint8_t SD_CS_PIN = SS;
#else // SDCARD_SS_PIN
#else // SDCARD_SS_PIN
// Assume built-in SD is used.
const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
#endif // SDCARD_SS_PIN
@ -30,7 +31,7 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
// Try to select the best SD card configuration.
#if HAS_SDIO_CLASS
#define SD_CONFIG SdioConfig(FIFO_SDIO)
#elif ENABLE_DEDICATED_SPI
#elif ENABLE_DEDICATED_SPI
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
#else // HAS_SDIO_CLASS
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
@ -55,7 +56,6 @@ FsFile file;
//------------------------------------------------------------------------------
// Call back for file timestamps. Only called for file create and sync().
void dateTime(uint16_t* date, uint16_t* time, uint8_t* ms10) {
// Return date using FS_DATE macro to format fields.
*date = FS_DATE(year(), month(), day());
@ -66,10 +66,7 @@ void dateTime(uint16_t* date, uint16_t* time, uint8_t* ms10) {
*ms10 = second() & 1 ? 100 : 0;
}
//------------------------------------------------------------------------------
time_t getTeensy3Time()
{
return Teensy3Clock.get();
}
time_t getTeensy3Time() { return Teensy3Clock.get(); }
//------------------------------------------------------------------------------
void printField(Print* pr, char sep, uint8_t v) {
if (sep) {
@ -102,7 +99,7 @@ void setup() {
while (!Serial.available()) {
yield();
}
if (timeStatus()!= timeSet) {
if (timeStatus() != timeSet) {
Serial.println("Unable to sync with the RTC");
return;
}
@ -135,5 +132,4 @@ void setup() {
Serial.println(F("Done"));
}
//------------------------------------------------------------------------------
void loop() {
}
void loop() {}

View file

@ -7,7 +7,7 @@
// SDCARD_SS_PIN is defined for the built-in SD on some boards.
#ifndef SDCARD_SS_PIN
const uint8_t SD_CS_PIN = SS;
#else // SDCARD_SS_PIN
#else // SDCARD_SS_PIN
// Assume built-in SD is used.
const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
#endif // SDCARD_SS_PIN
@ -20,7 +20,7 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
const size_t BUF_DIM = 32768;
// 8 MiB file.
const uint32_t FILE_SIZE = 256UL*BUF_DIM;
const uint32_t FILE_SIZE = 256UL * BUF_DIM;
#if SD_FAT_TYPE == 0
SdFat sd;
@ -72,13 +72,12 @@ void errorHalt(const char* msg) {
Serial.print(", ErrorData: 0X");
Serial.println(sd.sdErrorData(), HEX);
}
while (true) {}
while (true) {
}
}
bool ready = false;
//------------------------------------------------------------------------------
bool sdBusy() {
return ready ? sd.card()->isBusy() : false;
}
bool sdBusy() { return ready ? sd.card()->isBusy() : false; }
//------------------------------------------------------------------------------
// Replace "weak" system yield() function.
void yield() {
@ -110,7 +109,7 @@ void runTest() {
Serial.println("\nsize,write,read");
Serial.println("bytes,KB/sec,KB/sec");
for (size_t nb = 512; nb <= BUF_DIM; nb *= 2) {
uint32_t nRdWr = FILE_SIZE/nb;
uint32_t nRdWr = FILE_SIZE / nb;
if (!file.truncate(0)) {
errorHalt("truncate failed");
}
@ -121,14 +120,14 @@ void runTest() {
for (uint32_t n = 0; n < nRdWr; n++) {
// Set start and end of buffer.
buf32[0] = n;
buf32[nb/4 - 1] = n;
buf32[nb / 4 - 1] = n;
if (nb != file.write(buf, nb)) {
errorHalt("write failed");
}
}
t = micros() - t;
totalMicros += t;
Serial.print(1000.0*FILE_SIZE/t);
Serial.print(1000.0 * FILE_SIZE / t);
Serial.print(',');
file.rewind();
t = micros();
@ -138,13 +137,13 @@ void runTest() {
errorHalt("read failed");
}
// crude check of data.
if (buf32[0] != n || buf32[nb/4 - 1] != n) {
if (buf32[0] != n || buf32[nb / 4 - 1] != n) {
errorHalt("data check");
}
}
t = micros() - t;
totalMicros += t;
Serial.println(1000.0*FILE_SIZE/t);
Serial.println(1000.0 * FILE_SIZE / t);
}
file.close();
Serial.print("\ntotalMicros ");
@ -155,8 +154,8 @@ void runTest() {
Serial.println(yieldCalls);
Serial.print("yieldMaxUsec ");
Serial.println(yieldMaxUsec);
// Serial.print("kHzSdClk ");
// Serial.println(kHzSdClk());
// Serial.print("kHzSdClk ");
// Serial.println(kHzSdClk());
Serial.println("Done");
}
//------------------------------------------------------------------------------
@ -171,22 +170,22 @@ void loop() {
if (warn) {
warn = false;
Serial.println(
"SD cards must be power cycled to leave\n"
"SPI mode so do SDIO tests first.\n"
"\nCycle power on the card if an error occurs.");
"SD cards must be power cycled to leave\n"
"SPI mode so do SDIO tests first.\n"
"\nCycle power on the card if an error occurs.");
}
clearSerialInput();
Serial.println(
"\nType '1' for FIFO SDIO"
"\n '2' for DMA SDIO"
"\n '3' for Dedicated SPI"
"\n '4' for Shared SPI");
"\nType '1' for FIFO SDIO"
"\n '2' for DMA SDIO"
"\n '3' for Dedicated SPI"
"\n '4' for Shared SPI");
while (!Serial.available()) {
}
char c = Serial.read();
if (c =='1') {
if (c == '1') {
if (!sd.begin(SdioConfig(FIFO_SDIO))) {
errorHalt("begin failed");
}
@ -202,7 +201,7 @@ void loop() {
errorHalt("begin failed");
}
Serial.println("\nDedicated SPI mode.");
#else // ENABLE_DEDICATED_SPI
#else // ENABLE_DEDICATED_SPI
Serial.println("ENABLE_DEDICATED_SPI must be non-zero.");
return;
#endif // ENABLE_DEDICATED_SPI

View file

@ -6,20 +6,20 @@
// Teensy 4.1. About 5 usec is required to write a sector when the
// controller is in write mode.
#include "SdFat.h"
#include "RingBuf.h"
#include "SdFat.h"
// Use Teensy SDIO
#define SD_CONFIG SdioConfig(FIFO_SDIO)
#define SD_CONFIG SdioConfig(FIFO_SDIO)
// Interval between points for 25 ksps.
#define LOG_INTERVAL_USEC 40
// Size to log 10 byte lines at 25 kHz for more than ten minutes.
#define LOG_FILE_SIZE 10*25000*600 // 150,000,000 bytes.
#define LOG_FILE_SIZE 10 * 25000 * 600 // 150,000,000 bytes.
// Space to hold more than 800 ms of data for 10 byte lines at 25 ksps.
#define RING_BUF_CAPACITY 400*512
#define RING_BUF_CAPACITY 400 * 512
#define LOG_FILENAME "SdioLogger.csv"
SdFs sd;
@ -41,9 +41,9 @@ void logData() {
// File must be pre-allocated to avoid huge
// delays searching for free clusters.
if (!file.preAllocate(LOG_FILE_SIZE)) {
Serial.println("preAllocate failed\n");
file.close();
return;
Serial.println("preAllocate failed\n");
file.close();
return;
}
// initialize the RingBuf.
rb.begin(&file);
@ -88,7 +88,8 @@ void logData() {
break;
}
// Wait until time to log data.
while (micros() < logTime) {}
while (micros() < logTime) {
}
// Read ADC0 - about 17 usec on Teensy 4, Teensy 3.6 is faster.
uint16_t adc = analogRead(0);
@ -134,7 +135,8 @@ void clearSerialInput() {
}
void setup() {
Serial.begin(9600);
while (!Serial) {}
while (!Serial) {
}
// Go faster or log more channels. ADC quality will suffer.
// analogReadAveraging(1);
}
@ -142,7 +144,8 @@ void setup() {
void loop() {
clearSerialInput();
Serial.println("Type any character to start");
while (!Serial.available()) {};
while (!Serial.available()) {
}
clearSerialInput();
logData();
}

View file

@ -18,7 +18,7 @@ const char* names[] = {u8"россиянин", u8"très élégant", u8"狗.txt",
// SDCARD_SS_PIN is defined for the built-in SD on some boards.
#ifndef SDCARD_SS_PIN
const uint8_t SD_CS_PIN = SS;
#else // SDCARD_SS_PIN
#else // SDCARD_SS_PIN
// Assume built-in SD is used.
const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
#endif // SDCARD_SS_PIN
@ -91,8 +91,7 @@ void setup() {
#endif // REMOVE_UTF8_FILES
Serial.println("Done!");
}
void loop() {
}
void loop() {}
#else // USE_UTF8_LONG_NAMES
#error USE_UTF8_LONG_NAMES must be non-zero in SdFat/src/SdFatCongfig.h
#endif // USE_UTF8_LONG_NAMES

View file

@ -1,7 +1,7 @@
// An example of an external SPI driver.
//
#include "SdFat.h"
#include "SPI.h" // Only required if you use features in the SPI library.
#include "SdFat.h"
#if SPI_DRIVER_SELECT == 3 // Must be set in SdFat/SdFatConfig.h
@ -16,22 +16,16 @@
class MySpiClass : public SdSpiBaseClass {
public:
// Activate SPI hardware with correct speed and mode.
void activate() {
SPI.beginTransaction(m_spiSettings);
}
void activate() { SPI.beginTransaction(m_spiSettings); }
// Initialize the SPI bus.
void begin(SdSpiConfig config) {
(void)config;
SPI.begin();
}
// Deactivate SPI hardware.
void deactivate() {
SPI.endTransaction();
}
void deactivate() { SPI.endTransaction(); }
// Receive a byte.
uint8_t receive() {
return SPI.transfer(0XFF);
}
uint8_t receive() { return SPI.transfer(0XFF); }
// Receive multiple bytes.
// Replace this function if your board has multiple byte receive.
uint8_t receive(uint8_t* buf, size_t count) {
@ -41,9 +35,7 @@ class MySpiClass : public SdSpiBaseClass {
return 0;
}
// Send a byte.
void send(uint8_t data) {
SPI.transfer(data);
}
void send(uint8_t data) { SPI.transfer(data); }
// Send multiple bytes.
// Replace this function if your board has multiple byte send.
void send(const uint8_t* buf, size_t count) {
@ -73,9 +65,11 @@ void setup() {
sd.initErrorHalt(&Serial);
}
sd.ls(&Serial, LS_SIZE);
Serial.println("Done");
}
//------------------------------------------------------------------------------
void loop() {}
#else // SPI_DRIVER_SELECT
#error SPI_DRIVER_SELECT must be three in SdFat/SdFatConfig.h
#endif // SPI_DRIVER_SELECT

View file

@ -1,9 +1,9 @@
/*
* This program is a simple binary write/read benchmark.
*/
#include "FreeStack.h"
#include "SdFat.h"
#include "sdios.h"
#include "FreeStack.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.
@ -19,7 +19,7 @@
// SDCARD_SS_PIN is defined for the built-in SD on some boards.
#ifndef SDCARD_SS_PIN
const uint8_t SD_CS_PIN = SS;
#else // SDCARD_SS_PIN
#else // SDCARD_SS_PIN
// Assume built-in SD is used.
const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
#endif // SDCARD_SS_PIN
@ -30,7 +30,7 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
// Try to select the best SD card configuration.
#if HAS_SDIO_CLASS
#define SD_CONFIG SdioConfig(FIFO_SDIO)
#elif ENABLE_DEDICATED_SPI
#elif ENABLE_DEDICATED_SPI
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
#else // HAS_SDIO_CLASS
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
@ -58,10 +58,10 @@ const uint8_t READ_COUNT = 2;
// End of configuration constants.
//------------------------------------------------------------------------------
// File size in bytes.
const uint32_t FILE_SIZE = 1000000UL*FILE_SIZE_MB;
const uint32_t FILE_SIZE = 1000000UL * FILE_SIZE_MB;
// Insure 4-byte alignment.
uint32_t buf32[(BUF_SIZE + 3)/4];
uint32_t buf32[(BUF_SIZE + 3) / 4];
uint8_t* buf = (uint8_t*)buf32;
#if SD_FAT_TYPE == 0
@ -125,8 +125,8 @@ void setup() {
cout << F("\nUse a freshly formatted SD for best performance.\n");
if (!ENABLE_DEDICATED_SPI) {
cout << F(
"\nSet ENABLE_DEDICATED_SPI nonzero in\n"
"SdFatConfig.h for best SPI performance.\n");
"\nSet ENABLE_DEDICATED_SPI nonzero in\n"
"SdFatConfig.h for best SPI performance.\n");
}
// use uppercase in hex and use 0X base prefix
cout << uppercase << showbase << endl;
@ -161,7 +161,7 @@ void loop() {
cout << F("Type is FAT") << int(sd.fatType()) << endl;
}
cout << F("Card size: ") << sd.card()->sectorCount()*512E-9;
cout << F("Card size: ") << sd.card()->sectorCount() * 512E-9;
cout << F(" GB (GB = 1E9 bytes)") << endl;
cidDmp();
@ -176,17 +176,17 @@ void loop() {
for (size_t i = 0; i < (BUF_SIZE - 2); i++) {
buf[i] = 'A' + (i % 26);
}
buf[BUF_SIZE-2] = '\r';
buf[BUF_SIZE - 2] = '\r';
}
buf[BUF_SIZE-1] = '\n';
buf[BUF_SIZE - 1] = '\n';
cout << F("FILE_SIZE_MB = ") << FILE_SIZE_MB << endl;
cout << F("BUF_SIZE = ") << BUF_SIZE << F(" bytes\n");
cout << F("Starting write test, please wait.") << endl << endl;
// do write test
uint32_t n = FILE_SIZE/BUF_SIZE;
cout <<F("write speed and latency") << endl;
uint32_t n = FILE_SIZE / BUF_SIZE;
cout << F("write speed and latency") << endl;
cout << F("speed,max,min,avg") << endl;
cout << F("KB/Sec,usec,usec,usec") << endl;
for (uint8_t nTest = 0; nTest < WRITE_COUNT; nTest++) {
@ -223,11 +223,11 @@ void loop() {
file.sync();
t = millis() - t;
s = file.fileSize();
cout << s/t <<',' << maxLatency << ',' << minLatency;
cout << ',' << totalLatency/n << endl;
cout << s / t << ',' << maxLatency << ',' << minLatency;
cout << ',' << totalLatency / n << endl;
}
cout << endl << F("Starting read test, please wait.") << endl;
cout << endl <<F("read speed and latency") << endl;
cout << endl << F("read speed and latency") << endl;
cout << F("speed,max,min,avg") << endl;
cout << F("KB/Sec,usec,usec,usec") << endl;
@ -240,7 +240,7 @@ void loop() {
skipLatency = SKIP_FIRST_LATENCY;
t = millis();
for (uint32_t i = 0; i < n; i++) {
buf[BUF_SIZE-1] = 0;
buf[BUF_SIZE - 1] = 0;
uint32_t m = micros();
int32_t nr = file.read(buf, BUF_SIZE);
if (nr != BUF_SIZE) {
@ -248,8 +248,7 @@ void loop() {
}
m = micros() - m;
totalLatency += m;
if (buf[BUF_SIZE-1] != '\n') {
if (buf[BUF_SIZE - 1] != '\n') {
error("data check error");
}
if (skipLatency) {
@ -265,8 +264,8 @@ void loop() {
}
s = file.fileSize();
t = millis() - t;
cout << s/t <<',' << maxLatency << ',' << minLatency;
cout << ',' << totalLatency/n << endl;
cout << s / t << ',' << maxLatency << ',' << minLatency;
cout << ',' << totalLatency / n << endl;
}
cout << endl << F("Done") << endl;
file.close();

View file

@ -0,0 +1,119 @@
#include "SdFat.h"
#ifdef __AVR__
const uint32_t FILE_SIZE_MiB = 10UL;
#else // __AVR__
const uint32_t FILE_SIZE_MiB = 100UL;
#endif
bool waitBusy = true;
#define SD_CONFIG SdSpiConfig(SS, DEDICATED_SPI)
//#define SD_CONFIG SdSpiConfig(SS, SHARED_SPI)
// Config for Teensy 3.5/3.6 buit-in SD.
//#define SD_CONFIG SdSpiConfig(SDCARD_SS_PIN, DEDICATED_SPI)
//#define SD_CONFIG SdioConfig(FIFO_SDIO)
//------------------------------------------------------------------------------
const uint64_t FILE_SIZE = (uint64_t)FILE_SIZE_MiB << 20;
SdFs sd;
FsFile file;
uint8_t buf[512];
#define error(s) sd.errorHalt(&Serial, F(s))
//------------------------------------------------------------------------------
void clearSerialInput() {
uint32_t m = micros();
do {
if (Serial.read() >= 0) {
m = micros();
}
} while (micros() - m < 10000);
}
//------------------------------------------------------------------------------
void setup() {
Serial.begin(9600);
// Wait for USB Serial
while (!Serial) {
yield();
}
delay(1000);
//------------------------------------------------------------------------------
}
void loop() {
clearSerialInput();
Serial.println(F("\nType any character to start\n"));
while (!Serial.available()) {
yield();
}
// Initialize the SD card.
if (!sd.begin(SD_CONFIG)) {
sd.initErrorHalt();
}
if (!file.open("SdBusyTest.bin", O_RDWR | O_CREAT |O_TRUNC)) {
error("file open failed");
}
if (!file.preAllocate(FILE_SIZE)) {
error("preallocate failed");
}
Serial.print(F("Starting write of "));
Serial.print(FILE_SIZE_MiB);
Serial.println(F(" MiB."));
uint32_t maxWrite = 0;
uint32_t minWrite = 99999999;
uint32_t ms = millis();
uint32_t maxBusy = 0;
uint32_t minBusy = UINT32_MAX;
// Write a dummy sector to start a multi-sector write.
if(file.write(buf, sizeof(buf)) != sizeof(buf)) {
error("write failed for first sector");
}
while (file.position() < FILE_SIZE) {
uint32_t m = micros();
if (waitBusy) {
m = micros();
while (sd.card()->isBusy()) {}
m = micros() - m;
if (m < minBusy) {
minBusy = m;
}
if (m > maxBusy) {
maxBusy = m;
}
}
m = micros();
if (file.write(buf, sizeof(buf)) != sizeof(buf)) {
error("write failed");
}
m = micros() - m;
if (m < minWrite) {
minWrite = m;
}
if (m > maxWrite) {
maxWrite = m;
}
}
file.close();
ms = millis() - ms;
Serial.println(F("\nTimes in micros"));
if (waitBusy) {
Serial.print(F("minBusy: "));
Serial.println(minBusy);
Serial.print(F("maxBusy: "));
Serial.println(maxBusy);
}
Serial.print(F("minWrite: "));
Serial.println(minWrite);
Serial.print(F("maxWrite: "));
Serial.println(maxWrite);
Serial.print(1e-3*ms);
Serial.println(F(" Seconds"));
Serial.print(1.0*FILE_SIZE/ms);
Serial.println(F(" KB/sec"));
}

View file

@ -0,0 +1,51 @@
#include "SdFat.h"
#define DUMP_RAW 0
#define DUMP_UPCASE 0
const uint8_t CS_PIN = SS;
//#define SD_CONFIG SdioConfig(FIFO_SDIO)
#define SD_CONFIG SdSpiConfig(CS_PIN)
SdExFat sd;
#define error(s) sd.errorHalt(&Serial, F(s))
void setup() {
Serial.begin(9600);
while (!Serial) {
yield();
}
Serial.println(F("Type any character to begin"));
while (!Serial.available()) {
yield();
}
if (!sd.begin(SD_CONFIG)){
error("begin failed");
}
#if DUMP_RAW
sd.dmpSector(&Serial, 0);
for (uint8_t i = 0; i < 24; i++) {
sd.dmpSector(&Serial, 0X8000 + i);
Serial.println();
}
return;
#endif // DUMP_RAW
ExFatFile root;
if (!root.openRoot(&sd)) {
error("openRoot failed");
}
sd.printDir(&Serial, &root);
// startSector = 0, sectorCount = 1.
sd.dmpFat(&Serial, 0, 1);
sd.dmpBitmap(&Serial);
sd.printVolInfo(&Serial);
sd.checkUpcase(&Serial);
#if DUMP_UPCASE
sd.printUpcase(&Serial);
#endif // DUMP_UPCASE
// sd.dmpCluster(&Serial, 8, 0, 4);
Serial.println("Done");
}
void loop() {
// put your main code here, to run repeatedly:
}

View file

@ -0,0 +1,43 @@
#include "SdFat.h"
SdFs sd;
FsFile file;
const char* name[] = {
"SFN.TXT",
"LongFilename.txt",
#if USE_UTF8_LONG_NAMES
u8"très élégant.txt",
#endif // USE_UTF8_LONG_NAMES
nullptr};
char buf[32];
void setup() {
Serial.begin(9600);
while (!Serial) {}
Serial.println("Type any character to begin");
while (!Serial.available()) {}
if (!sd.begin(SS)) {
sd.initErrorHalt();
}
for (uint8_t i = 0; name[i]; i++) {
if (!file.open(name[i], O_CREAT |O_RDWR)) {
sd.errorHalt("open");
}
size_t len = strlen(name[i]);
size_t rtn = file.getName(buf, len);
if (rtn != 0) {
Serial.println("fail len");
}
rtn = file.getName(buf, len + 1);
if (rtn != len) {
Serial.println("fail len + 1");
}
Serial.print(rtn);
Serial.print(' ');
Serial.println(buf);
if (!file.remove()) {
sd.errorHalt("remove");
}
}
Serial.println("Done");
}
void loop() {}

View file

@ -0,0 +1,140 @@
/*
* This sketch is a test of subdirectory and file creation.
* It also tests allocation of clusters to directories.
*
* It will create two subdirectories and create enough files
* to force the allocation of a cluster to each directory.
*
* More than 3000 files may be created on a FAT32 volume.
*
* Note: Some cards may 'stutter' others just get slow due
* to the number of flash erases this program causes.
*/
#include <SdFat.h>
const uint8_t SD_CHIP_SELECT = SS;
SdFat sd;
typedef File file_t;
// store error strings in flash to save RAM
#define error(s) sd.errorHalt(&Serial, F(s))
/*
* create enough files to force a cluster to be allocated to dir.
*/
void dirAllocTest(file_t* dir) {
char buf[32], name[32];
file_t file;
uint16_t n;
uint32_t size = dir->dirSize();
// create files and write name to file
for (n = 0; ; n++){
// make file name
sprintf(name, "%u.TXT", n);
// open start time
uint32_t t0 = millis();
if (!file.open(dir, name, O_WRONLY | O_CREAT | O_EXCL)) {
error("open for write failed");
}
// open end time and write start time
uint32_t t1 = millis();
// write file name to file
file.print(name);
if (!file.close()) error("close write");
// write end time
uint32_t t2 = millis();
Serial.print(F("WR "));
Serial.print(n);
Serial.write(' ');
// print time to create file
Serial.print(t1 - t0);
Serial.write(' ');
// print time to write file
Serial.println(t2 - t1);
// directory size will change when a cluster is added
if (dir->curPosition() > size) break;
}
// read files and check content
for (uint16_t i = 0; i <= n; i++) {
sprintf(name, "%u.TXT", i);
// open start time
uint32_t t0 = millis();
if (!file.open(dir, name, O_RDONLY)) {
error("open for read failed");
}
// open end time and read start time
uint32_t t1 = millis();
int16_t nr = file.read(buf, sizeof(buf));
if (nr < 5) error("file.read failed");
// read end time
uint32_t t2 = millis();
// check file content
if (strlen(name) != (size_t)nr || strncmp(name, buf, nr)) {
error("content compare failed");
}
if (!file.close()) error("close read failed");
Serial.print(F("RD "));
Serial.print(i);
Serial.write(' ');
// print open time
Serial.print(t1 - t0);
Serial.write(' ');
// print read time
Serial.println(t2 - t1);
}
}
void setup() {
file_t root;
Serial.begin(9600);
while (!Serial) {} // wait for Leonardo
Serial.println(F("Type any character to start"));
while (Serial.read() <= 0) {}
delay(200); // Catch Due reset problem
// initialize the SD card at SPI_FULL_SPEED for best performance.
// try lower speed if bus errors occur.
if (!sd.begin(SD_CHIP_SELECT, SPI_FULL_SPEED)) {
sd.initErrorHalt(&Serial);
}
root.openRoot(&sd);
uint32_t m = millis();
// write files to root if not FAT16
if (sd.fatType() != 16) {
Serial.println(F("Writing files to root"));
dirAllocTest(&root);
}
// create sub1 and write files
file_t sub1;
if (!sub1.mkdir(&root, "SUB1")) error("makdeDir SUB1 failed");
Serial.println(F("Writing files to SUB1"));
dirAllocTest(&sub1);
// create sub2 and write files
file_t sub2;
if (!sub2.mkdir(&sub1, "SUB2")) error("mkdir SUB2 failed");
Serial.println(F("Writing files to SUB2"));
dirAllocTest(&sub2);
m = millis() - m;
Serial.print(F("Done millis: "));
Serial.println(m);
}
void loop() { }

View file

@ -0,0 +1,99 @@
/*
* This sketch will remove the files and directories
* created by the SdFatMakeDir.pde sketch.
*
* Performance is erratic due to the large number
* of flash erase operations caused by many random
* writes to file structures.
*/
#include <SdFat.h>
const uint8_t SD_CHIP_SELECT = SS;
SdFat sd;
typedef File file_t;
// store error strings in flash to save RAM
#define error(s) sd.errorHalt(&Serial, F(s))
/*
* remove all files in dir.
*/
void deleteFiles(FatFile* dir) {
char name[32];
file_t file;
// open and delete files
for (uint16_t n = 0; ; n++){
sprintf(name, "%u.TXT", n);
// open start time
uint32_t t0 = millis();
// assume done if open fails
if (!file.open(dir, name, O_WRONLY)) return;
// open end time and remove start time
uint32_t t1 = millis();
if (!file.remove()) error("file.remove failed");
// remove end time
uint32_t t2 = millis();
Serial.print(F("RM "));
Serial.print(n);
Serial.write(' ');
// open time
Serial.print(t1 - t0);
Serial.write(' ');
// remove time
Serial.println(t2 - t1);
}
}
void setup() {
file_t root;
Serial.begin(9600);
while (!Serial) {} // wait for Leonardo
Serial.println(F("Type any character to start"));
while (Serial.read() <= 0) {}
delay(200); // Catch Due reset problem
// initialize the SD card at SPI_FULL_SPEED for best performance.
// try lower speed if bus errors occur.
if (!sd.begin(SD_CHIP_SELECT, SPI_FULL_SPEED)) {
sd.initErrorHalt(&Serial);
}
root.openRoot(&sd);
// delete files in root if not FAT16.
if (sd.fatType() != 16) {
Serial.println(F("Remove files in root"));
deleteFiles(&root);
}
// open SUB1 and delete files
file_t sub1;
if (!sub1.open("SUB1", O_RDONLY)) error("open SUB1 failed");
Serial.println(F("Remove files in SUB1"));
deleteFiles(&sub1);
// open SUB2 and delete files
file_t sub2;
if (!sub2.open(&sub1, "SUB2", O_RDONLY)) error("open SUB2 failed");
Serial.println(F("Remove files in SUB2"));
deleteFiles(&sub2);
// remove SUB2
if (!sub2.rmdir()) error("sub2.rmdir failed");
Serial.println(F("SUB2 removed"));
// remove SUB1
if (!sub1.rmdir()) error("sub1.rmdir failed");
Serial.println(F("SUB1 removed"));
Serial.println(F("Done"));
}
void loop() { }

View file

@ -0,0 +1,162 @@
/*
* This program tests the dateTimeCallback() function
* and the timestamp() function.
*/
#include <SPI.h>
#include "SdFat.h"
#include "sdios.h"
SdFs sd;
FsFile file;
// Default SD chip select is SS pin
const uint8_t chipSelect = SS;
// create Serial stream
ArduinoOutStream cout(Serial);
//------------------------------------------------------------------------------
// store error strings in flash to save RAM
#define error(s) sd.errorHalt(F(s))
//------------------------------------------------------------------------------
/*
* date/time values for debug
* normally supplied by a real-time clock or GPS
*/
// date 1-Oct-21
uint16_t year = 2021;
uint8_t month = 10;
uint8_t day = 1;
// time 20:30:40
uint8_t hour = 20;
uint8_t minute = 30;
uint8_t second = 40;
//------------------------------------------------------------------------------
/*
* User provided date time callback function.
* See SdFile::dateTimeCallback() for usage.
*/
void dateTime(uint16_t* date, uint16_t* time) {
// User gets date and time from GPS or real-time
// clock in real callback function
// return date using FAT_DATE macro to format fields
*date = FAT_DATE(year, month, day);
// return time using FAT_TIME macro to format fields
*time = FAT_TIME(hour, minute, second);
}
//------------------------------------------------------------------------------
/*
* Function to print all timestamps.
*/
void printTimestamps(FsFile& f) {
cout << F("Creation: ");
f.printCreateDateTime(&Serial);
cout << endl << F("Modify: ");
f.printModifyDateTime(&Serial);
cout << endl << F("Access: ");
f.printAccessDateTime(&Serial);
cout << endl;
}
//------------------------------------------------------------------------------
void setup(void) {
Serial.begin(9600);
// Wait for USB Serial
while (!Serial) {
yield();
}
cout << F("Type any character to start\n");
while (!Serial.available()) {
yield();
}
// Initialize at the highest speed supported by the board that is
// not over 50 MHz. Try a lower speed if SPI errors occur.
if (!sd.begin(chipSelect, SD_SCK_MHZ(50))) {
sd.initErrorHalt();
}
// remove files if they exist
sd.remove("callback.txt");
sd.remove("default.txt");
sd.remove("stamp.txt");
// create a new file with default timestamps
if (!file.open("default.txt", O_WRONLY | O_CREAT)) {
error("open default.txt failed");
}
cout << F("\nOpen with default times\n");
printTimestamps(file);
// close file
file.close();
/*
* Test the date time callback function.
*
* dateTimeCallback() sets the function
* that is called when a file is created
* or when a file's directory entry is
* modified by sync().
*
* The callback can be disabled by the call
* SdFile::dateTimeCallbackCancel()
*/
// set date time callback function
SdFile::dateTimeCallback(dateTime);
// create a new file with callback timestamps
if (!file.open("callback.txt", O_WRONLY | O_CREAT)) {
error("open callback.txt failed");
}
cout << ("\nOpen with callback times\n");
printTimestamps(file);
// change call back date
day += 1;
// must add two to see change since FAT second field is 5-bits
second += 2;
// modify file by writing a byte
file.write('t');
// force dir update
file.sync();
cout << F("\nTimes after write\n");
printTimestamps(file);
// close file
file.close();
/*
* Test timestamp() function
*
* Cancel callback so sync will not
* change access/modify timestamp
*/
SdFile::dateTimeCallbackCancel();
// create a new file with default timestamps
if (!file.open("stamp.txt", O_WRONLY | O_CREAT)) {
error("open stamp.txt failed");
}
// set creation date time
if (!file.timestamp(T_CREATE, 2021, 11, 10, 1, 2, 3)) {
error("set create time failed");
}
// set write/modification date time
if (!file.timestamp(T_WRITE, 2021, 11, 11, 4, 5, 6)) {
error("set write time failed");
}
// set access date
if (!file.timestamp(T_ACCESS, 2021, 11, 12, 7, 8, 9)) {
error("set access time failed");
}
cout << F("\nTimes after timestamp() calls\n");
printTimestamps(file);
file.close();
cout << F("\nDone\n");
}
void loop() {}

View file

@ -22,6 +22,7 @@
#ifdef __AVR__
#include <SPI.h>
#include "SdFat.h"
#include "sdios.h"
#include "FreeStack.h"
#include "AnalogBinLogger.h"
//------------------------------------------------------------------------------
@ -648,7 +649,7 @@ void logData() {
bgnErase = endErase + 1;
}
// Start a multiple block write.
if (!sd.card()->writeStart(bgnBlock, FILE_BLOCK_COUNT)) {
if (!sd.card()->writeStart(bgnBlock)) {
error("writeBegin failed");
}
// Write metadata.

View file

@ -20,7 +20,7 @@
// SDCARD_SS_PIN is defined for the built-in SD on some boards.
#ifndef SDCARD_SS_PIN
const uint8_t SD_CS_PIN = SS;
#else // SDCARD_SS_PIN
#else // SDCARD_SS_PIN
// Assume built-in SD is used.
const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
#endif // SDCARD_SS_PIN
@ -31,7 +31,7 @@ const uint8_t SD_CS_PIN = SDCARD_SS_PIN;
// Try to select the best SD card configuration.
#if HAS_SDIO_CLASS
#define SD_CONFIG SdioConfig(FIFO_SDIO)
#elif ENABLE_DEDICATED_SPI
#elif ENABLE_DEDICATED_SPI
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SPI_CLOCK)
#else // HAS_SDIO_CLASS
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, SHARED_SPI, SPI_CLOCK)
@ -80,8 +80,7 @@ void setup() {
// Remove file/dirs from previous run.
if (sd.exists("dir2/DIR3/NAME3.txt")) {
cout << F("Removing /dir2/DIR3/NAME3.txt") << endl;
if (!sd.remove("dir2/DIR3/NAME3.txt") ||
!sd.rmdir("dir2/DIR3/") ||
if (!sd.remove("dir2/DIR3/NAME3.txt") || !sd.rmdir("dir2/DIR3/") ||
!sd.rmdir("dir2/")) {
error("remove/rmdir failed");
}

567
extras/AvrPrintStimmer.cpp Normal file
View file

@ -0,0 +1,567 @@
/*
Print.cpp - Base class that provides print() and println()
Copyright (c) 2008 David A. Mellis. All right reserved.
many modifications, by Paul Stoffregen <paul@pjrc.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Modified 23 November 2006 by David A. Mellis
*/
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <math.h>
#include <avr/pgmspace.h>
#include "Arduino.h" // (was wiring.h)
#include "Print.h"
#if ARDUINO >= 100
#else
void Print::write(const char *str)
{
write((const uint8_t *)str, strlen(str));
}
#endif
#if ARDUINO >= 100
size_t Print::write(const uint8_t *buffer, size_t size)
{
size_t count = 0;
while (size--) count += write(*buffer++);
return count;
}
#else
void Print::write(const uint8_t *buffer, size_t size)
{
while (size--) write(*buffer++);
}
#endif
#if ARDUINO >= 100
size_t Print::print(const String &s)
{
uint8_t buffer[33];
size_t count = 0;
unsigned int index = 0;
unsigned int len = s.length();
while (len > 0) {
s.getBytes(buffer, sizeof(buffer), index);
unsigned int nbytes = len;
if (nbytes > sizeof(buffer)-1) nbytes = sizeof(buffer)-1;
index += nbytes;
len -= nbytes;
count += write(buffer, nbytes);
}
return count;
}
#else
void Print::print(const String &s)
{
unsigned int len = s.length();
for (unsigned int i=0; i < len; i++) {
write(s[i]);
}
}
#endif
#if ARDUINO >= 100
size_t Print::print(const __FlashStringHelper *ifsh)
{
uint8_t buffer[32];
size_t count = 0;
const char PROGMEM *p = (const char PROGMEM *)ifsh;
unsigned int len = strlen_P(p);
while (len > 0) {
unsigned int nbytes = len;
if (nbytes > sizeof(buffer)) nbytes = sizeof(buffer);
memcpy_P(buffer, p, nbytes);
p += nbytes;
len -= nbytes;
count += write(buffer, nbytes);
}
return count;
}
#else
void Print::print(const __FlashStringHelper *ifsh)
{
const char PROGMEM *p = (const char PROGMEM *)ifsh;
while (1) {
unsigned char c = pgm_read_byte(p++);
if (c == 0) return;
write(c);
}
}
#endif
#if ARDUINO >= 100
size_t Print::print(long n)
{
uint8_t sign=0;
if (n < 0) {
sign = 1;
n = -n;
}
return printNumber(n, sign, 10);
}
#else
void Print::print(long n)
{
uint8_t sign=0;
if (n < 0) {
sign = 1;
n = -n;
}
printNumber(n, sign, 10);
}
#endif
#if ARDUINO >= 100
size_t Print::println(void)
{
uint8_t buf[2]={'\r', '\n'};
return write(buf, 2);
}
#else
void Print::println(void)
{
uint8_t buf[2]={'\r', '\n'};
write(buf, 2);
}
#endif
//#define USE_HACKER_DELIGHT_OPTIMIZATION
#define USE_STIMMER_OPTIMIZATION
#define USE_BENCHMARK_CODE
#ifdef USE_HACKER_DELIGHT_OPTIMIZATION
// Adapted from Hacker's Delight (Henry Warren, ISBN 0321842685) www.hackersdelight.org
// by Rob Tillaart, Tom Carpenter, "genom2" with input from others...
// http://forum.arduino.cc/index.php?topic=167414.0
//
#define divmod10_asm(in32, tmp32, mod8) \
asm volatile ( \
"mov %2, %A0 \n\t" /* mod = in */ \
"ori %A0, 1 \n\t" /* q = in | 1 */ \
"movw %A1, %A0 \n\t" /* x = q */ \
"movw %C1, %C0 \n\t" \
"lsr %D1 \n\t" /* x = x >> 2 */ \
"ror %C1 \n\t" \
"ror %B1 \n\t" \
"ror %A1 \n\t" \
"lsr %D1 \n\t" \
"ror %C1 \n\t" \
"ror %B1 \n\t" \
"ror %A1 \n\t" \
"sub %A0, %A1 \n\t" /* q = q - x */ \
"sbc %B0, %B1 \n\t" \
"sbc %C0, %C1 \n\t" \
"sbc %D0, %D1 \n\t" \
"movw %A1, %A0 \n\t" /* x = q */ \
"movw %C1, %C0 \n\t" \
"lsr %D1 \n\t" /* x = x >> 4 */ \
"ror %C1 \n\t" \
"ror %B1 \n\t" \
"ror %A1 \n\t" \
"lsr %D1 \n\t" \
"ror %C1 \n\t" \
"ror %B1 \n\t" \
"ror %A1 \n\t" \
"lsr %D1 \n\t" \
"ror %C1 \n\t" \
"ror %B1 \n\t" \
"ror %A1 \n\t" \
"lsr %D1 \n\t" \
"ror %C1 \n\t" \
"ror %B1 \n\t" \
"ror %A1 \n\t" \
"add %A1, %A0 \n\t" /* x = x + q */ \
"adc %B1, %B0 \n\t" \
"adc %C1, %C0 \n\t" \
"adc %D1, %D0 \n\t" \
"movw %A0, %A1 \n\t" /* q = x */ \
"movw %C0, %C1 \n\t" \
"add %A0, %B1 \n\t" /* q = q + (x >> 8) */ \
"adc %B0, %C1 \n\t" \
"adc %C0, %D1 \n\t" \
"adc %D0, r1 \n\t" \
"mov %A0, %B0 \n\t" /* q = q >> 8 */ \
"mov %B0, %C0 \n\t" \
"mov %C0, %D0 \n\t" \
"eor %D0, %D0 \n\t" \
"add %A0, %A1 \n\t" /* q = q + x */ \
"adc %B0, %B1 \n\t" \
"adc %C0, %C1 \n\t" \
"adc %D0, %D1 \n\t" \
"mov %A0, %B0 \n\t" /* q = q >> 8 */ \
"mov %B0, %C0 \n\t" \
"mov %C0, %D0 \n\t" \
"eor %D0, %D0 \n\t" \
"add %A0, %A1 \n\t" /* q = q + x */ \
"adc %B0, %B1 \n\t" \
"adc %C0, %C1 \n\t" \
"adc %D0, %D1 \n\t" \
"mov %A0, %B0 \n\t" /* q = q >> 8 */ \
"mov %B0, %C0 \n\t" \
"mov %C0, %D0 \n\t" \
"eor %D0, %D0 \n\t" \
"add %A0, %A1 \n\t" /* q = q + x */ \
"adc %B0, %B1 \n\t" \
"adc %C0, %C1 \n\t" \
"adc %D0, %D1 \n\t" \
"andi %A0, 0xF8 \n\t" /* q = q & ~0x7 */ \
"sub %2, %A0 \n\t" /* mod = mod - q */ \
"lsr %D0 \n\t" /* q = q >> 2 */ \
"ror %C0 \n\t" \
"ror %B0 \n\t" \
"ror %A0 \n\t" \
"lsr %D0 \n\t" \
"ror %C0 \n\t" \
"ror %B0 \n\t" \
"ror %A0 \n\t" \
"sub %2, %A0 \n\t" /* mod = mod - q */ \
"lsr %D0 \n\t" /* q = q >> 1 */ \
"ror %C0 \n\t" \
"ror %B0 \n\t" \
"ror %A0 \n\t" \
: "+d" (in32), "=r" (tmp32), "=r" (mod8) : : "r0" \
)
#endif // USE_HACKER_DELIGHT_OPTIMIZATION
#ifdef USE_STIMMER_OPTIMIZATION
// http://forum.arduino.cc/index.php?topic=167414.msg1293679#msg1293679
#define divmod10_asm32(in32, mod8, tmp8) \
asm volatile ( \
" ldi %2,51 \n\t" \
" mul %A0,%2 \n\t" \
" clr %A0 \n\t" \
" add r0,%2 \n\t" \
" adc %A0,r1 \n\t" \
" mov %1,r0 \n\t" \
" mul %B0,%2 \n\t" \
" clr %B0 \n\t" \
" add %A0,r0 \n\t" \
" adc %B0,r1 \n\t" \
" mul %C0,%2 \n\t" \
" clr %C0 \n\t" \
" add %B0,r0 \n\t" \
" adc %C0,r1 \n\t" \
" mul %D0,%2 \n\t" \
" clr %D0 \n\t" \
" add %C0,r0 \n\t" \
" adc %D0,r1 \n\t" \
" clr r1 \n\t" \
" add %1,%A0 \n\t" \
" adc %A0,%B0 \n\t" \
" adc %B0,%C0 \n\t" \
" adc %C0,%D0 \n\t" \
" adc %D0,r1 \n\t" \
" add %1,%B0 \n\t" \
" adc %A0,%C0 \n\t" \
" adc %B0,%D0 \n\t" \
" adc %C0,r1 \n\t" \
" adc %D0,r1 \n\t" \
" add %1,%D0 \n\t" \
" adc %A0,r1 \n\t" \
" adc %B0,r1 \n\t" \
" adc %C0,r1 \n\t" \
" adc %D0,r1 \n\t" \
" lsr %D0 \n\t" \
" ror %C0 \n\t" \
" ror %B0 \n\t" \
" ror %A0 \n\t" \
" ror %1 \n\t" \
" ldi %2,10 \n\t" \
" mul %1,%2 \n\t" \
" mov %1,r1 \n\t" \
" clr r1 \n\t" \
:"+r"(in32),"=d"(mod8),"=d"(tmp8) : : "r0")
#define divmod10_asm24(in32, mod8, tmp8) \
asm volatile ( \
" ldi %2,51 \n\t" \
" mul %A0,%2 \n\t" \
" clr %A0 \n\t" \
" add r0,%2 \n\t" \
" adc %A0,r1 \n\t" \
" mov %1,r0 \n\t" \
" mul %B0,%2 \n\t" \
" clr %B0 \n\t" \
" add %A0,r0 \n\t" \
" adc %B0,r1 \n\t" \
" mul %C0,%2 \n\t" \
" clr %C0 \n\t" \
" add %B0,r0 \n\t" \
" adc %C0,r1 \n\t" \
" clr r1 \n\t" \
" add %1,%A0 \n\t" \
" adc %A0,%B0 \n\t" \
" adc %B0,%C0 \n\t" \
" adc %C0,r1 \n\t" \
" add %1,%B0 \n\t" \
" adc %A0,%C0 \n\t" \
" adc %B0,r1 \n\t" \
" adc %C0,r1 \n\t" \
" lsr %C0 \n\t" \
" ror %B0 \n\t" \
" ror %A0 \n\t" \
" ror %1 \n\t" \
" ldi %2,10 \n\t" \
" mul %1,%2 \n\t" \
" mov %1,r1 \n\t" \
" clr r1 \n\t" \
:"+r"(in32),"=d"(mod8),"=d"(tmp8) : : "r0")
#define divmod10_asm16(in32, mod8, tmp8) \
asm volatile ( \
" ldi %2,51 \n\t" \
" mul %A0,%2 \n\t" \
" clr %A0 \n\t" \
" add r0,%2 \n\t" \
" adc %A0,r1 \n\t" \
" mov %1,r0 \n\t" \
" mul %B0,%2 \n\t" \
" clr %B0 \n\t" \
" add %A0,r0 \n\t" \
" adc %B0,r1 \n\t" \
" clr r1 \n\t" \
" add %1,%A0 \n\t" \
" adc %A0,%B0 \n\t" \
" adc %B0,r1 \n\t" \
" add %1,%B0 \n\t" \
" adc %A0,r1 \n\t" \
" adc %B0,r1 \n\t" \
" lsr %B0 \n\t" \
" ror %A0 \n\t" \
" ror %1 \n\t" \
" ldi %2,10 \n\t" \
" mul %1,%2 \n\t" \
" mov %1,r1 \n\t" \
" clr r1 \n\t" \
:"+r"(in32),"=d"(mod8),"=d"(tmp8) : : "r0")
#define divmod10_asm8(in32, mod8, tmp8) \
asm volatile ( \
" ldi %2,51 \n\t" \
" mul %A0,%2 \n\t" \
" clr %A0 \n\t" \
" add r0,%2 \n\t" \
" adc %A0,r1 \n\t" \
" mov %1,r0 \n\t" \
" clr r1 \n\t" \
" add %1,%A0 \n\t" \
" adc %A0,r1 \n\t" \
" lsr %A0 \n\t" \
" ror %1 \n\t" \
" ldi %2,10 \n\t" \
" mul %1,%2 \n\t" \
" mov %1,r1 \n\t" \
" clr r1 \n\t" \
:"+r"(in32),"=d"(mod8),"=d"(tmp8) : : "r0")
#endif // USE_STIMMER_OPTIMIZATION
#ifdef USE_BENCHMARK_CODE
uint32_t usec_print = 0;
#endif
#if ARDUINO >= 100
size_t Print::printNumberDec(unsigned long n, uint8_t sign)
#else
void Print::printNumberDec(unsigned long n, uint8_t sign)
#endif
{
uint8_t digit, buf[11], *p;
uint32_t tmp32;
uint8_t tmp8;
#ifdef USE_BENCHMARK_CODE
uint32_t usec = micros();
#endif
p = buf + (sizeof(buf)-1);
#if defined(USE_STIMMER_OPTIMIZATION)
while(n & 0xff000000){divmod10_asm32(n, digit, tmp8);*--p = digit + '0';}
while(n & 0xff0000){divmod10_asm24(n, digit, tmp8);*--p = digit + '0';}
while(n & 0xff00){divmod10_asm16(n, digit, tmp8);*--p = digit + '0';}
while((n & 0xff)>9){divmod10_asm8(n, digit, tmp8);*--p = digit + '0';}
*--p = n + '0';
#else
do {
#if defined(USE_HACKER_DELIGHT_OPTIMIZATION)
divmod10_asm(n, tmp32, digit);
#else
tmp32 = n;
n = n / 10;
digit = tmp32 - n * 10;
#endif
*--p = digit + '0';
} while (n);
#endif
if (sign) *--p = '-';
#ifdef USE_BENCHMARK_CODE
usec_print += micros() - usec;
#endif
#if ARDUINO >= 100
return write(p, sizeof(buf)-1 - (p - buf));
#else
write(p, sizeof(buf)-1 - (p - buf));
#endif
}
#if ARDUINO >= 100
size_t Print::printNumberHex(unsigned long n)
#else
void Print::printNumberHex(unsigned long n)
#endif
{
uint8_t digit, buf[8], *p;
p = buf + (sizeof(buf)-1);
do {
digit = n & 15;
*--p = (digit < 10) ? '0' + digit : 'A' + digit - 10;
n >>= 4;
} while (n);
#if ARDUINO >= 100
return write(p, sizeof(buf)-1 - (p - buf));
#else
write(p, sizeof(buf)-1 - (p - buf));
#endif
}
#if ARDUINO >= 100
size_t Print::printNumberBin(unsigned long n)
#else
void Print::printNumberBin(unsigned long n)
#endif
{
uint8_t buf[32], *p;
p = buf + (sizeof(buf)-1);
do {
*--p = '0' + ((uint8_t)n & 1);
n >>= 1;
} while (n);
#if ARDUINO >= 100
return write(p, sizeof(buf)-1 - (p - buf));
#else
write(p, sizeof(buf)-1 - (p - buf));
#endif
}
#if ARDUINO >= 100
size_t Print::printNumberAny(unsigned long n, uint8_t base)
#else
void Print::printNumberAny(unsigned long n, uint8_t base)
#endif
{
uint8_t digit, buf[21], *p;
uint32_t tmp;
//uint32_t usec;
//usec = micros();
p = buf + (sizeof(buf)-1);
do {
tmp = n;
n = n / base;
digit = tmp - n * base;
*--p = (digit < 10) ? '0' + digit : 'A' + digit - 10;
} while (n);
//usec_print += micros() - usec;
#if ARDUINO >= 100
return write(p, sizeof(buf)-1 - (p - buf));
#else
write(p, sizeof(buf)-1 - (p - buf));
#endif
}
#if ARDUINO >= 100
size_t Print::printFloat(double number, uint8_t digits)
#else
void Print::printFloat(double number, uint8_t digits)
#endif
{
uint8_t sign=0;
#if ARDUINO >= 100
size_t count=0;
#endif
// Handle negative numbers
if (number < 0.0) {
sign = 1;
number = -number;
}
// Round correctly so that print(1.999, 2) prints as "2.00"
double rounding = 0.5;
for (uint8_t i=0; i<digits; ++i) {
rounding *= 0.1;
}
number += rounding;
// Extract the integer part of the number and print it
unsigned long int_part = (unsigned long)number;
double remainder = number - (double)int_part;
#if ARDUINO >= 100
count += printNumber(int_part, sign, 10);
#else
printNumber(int_part, sign, 10);
#endif
// Print the decimal point, but only if there are digits beyond
if (digits > 0) {
uint8_t n, buf[8], count=1;
buf[0] = '.';
// Extract digits from the remainder one at a time
if (digits > sizeof(buf) - 1) digits = sizeof(buf) - 1;
while (digits-- > 0) {
remainder *= 10.0;
n = (uint8_t)(remainder);
buf[count++] = '0' + n;
remainder -= n;
}
#if ARDUINO >= 100
count += write(buf, count);
#else
write(buf, count);
#endif
}
#if ARDUINO >= 100
return count;
#endif
}

View file

@ -1,6 +1,4 @@
+++ "C:\\Users\\bill\\Documents\\ArduinoSdFat\\libraries\\USB_Host_Shield_2.0/masstorage.cpp" 2020-02-20 06:02:48.567008200 -0800
master/masstorage.cpp" 2022-10-18 08:48:03.639503200 -0700
@@ -796,6 +796,7 @@
buf[i] = 0x00;
}
@ -9,3 +7,4 @@
uint8_t rc = ModeSense6(lun, 0, 0x3f, 0, 192, buf);
if(!rc) {
WriteOk[lun] = ((buf[2] & 0x80) == 0);

View file

@ -1,4 +1,4 @@
This zip file was downloaded on 2/20/2020 from
This zip file was downloaded on 10/18/2022 from
https://github.com/felis/USB_Host_Shield_2.0

View file

@ -23,6 +23,7 @@
* DEALINGS IN THE SOFTWARE.
*/
#include "PrintBasic.h"
#if ENABLE_ARDUINO_FEATURES == 0
#include <math.h>
size_t PrintBasic::print(long n, uint8_t base) {
@ -32,14 +33,14 @@ size_t PrintBasic::print(long n, uint8_t base) {
return printNum(n, base);
}
size_t PrintBasic::printNum(unsigned long n, uint8_t base) {
const uint8_t DIM = 8*sizeof(long);
const uint8_t DIM = 8 * sizeof(long);
char buf[DIM];
char *str = &buf[DIM];
if (base < 2) return 0;
do {
char c = n%base;
char c = n % base;
n /= base;
*--str = c + (c < 10 ? '0' : 'A' - 10);
} while (n);
@ -66,7 +67,7 @@ size_t PrintBasic::printDouble(double n, uint8_t prec) {
}
double round = 0.5;
for (uint8_t i = 0; i < prec; ++i) {
for (uint8_t i = 0; i < prec; ++i) {
round *= 0.1;
}
@ -87,3 +88,4 @@ size_t PrintBasic::printDouble(double n, uint8_t prec) {
}
return rtn;
}
#endif // ENABLE_ARDUINO_FEATURES == 0

View file

@ -28,18 +28,21 @@
* \file
* \brief Stream/Print like replacement for non-Arduino systems.
*/
#include <stdint.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#ifdef F
#warning F() macro defined for non Arduino System
#elif defined(__AVR__)
#include "../SdFatConfig.h"
#ifndef F
#if defined(__AVR__)
#include <avr/pgmspace.h>
class __FlashStringHelper;
#define F(str) (reinterpret_cast<const __FlashStringHelper *>(PSTR(str)))
#else // F
#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
@ -54,63 +57,44 @@ 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);
}
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));
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__
#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(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(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 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();
}
@ -132,12 +116,10 @@ class PrintBasic {
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));
}
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) {
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;
@ -145,13 +127,11 @@ class PrintBasic {
return i;
}
size_t write(const char *buffer, size_t size) {
return write((const uint8_t*)buffer, size);
return write(reinterpret_cast<const uint8_t *>(buffer), size);
}
protected:
void setWriteError(int err = 1) {
m_error = err;
}
void setWriteError(int err = 1) { m_error = err; }
private:
size_t printDouble(double n, uint8_t prec);

2
extras/cpplint.py vendored
View file

@ -67,7 +67,7 @@ Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...]
<file> [file] ...
The style guidelines this tries to follow are those in
https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
https://google.github.io/styleguide/cppguide.html
Every problem is given a confidence score from 1-5, with 5 meaning we are
certain of the problem, and 1 meaning it could be a legitimate construct.

View file

@ -1,5 +1,5 @@
name=SdFat
version=2.2.0
version=2.2.2
license=MIT
author=Bill Greiman <fat16lib@sbcglobal.net>
maintainer=Bill Greiman <fat16lib@sbcglobal.net>

View file

@ -28,12 +28,15 @@
* \file
* \brief Fast buffered print.
*/
#ifdef __AVR__
#include <avr/pgmspace.h>
#endif // __AVR__
#include "common/FmtNumber.h"
/**
* \class BufferedPrint
* \brief Fast buffered print template.
*/
template<typename WriteClass, uint8_t BUF_DIM>
template <typename WriteClass, uint8_t BUF_DIM>
class BufferedPrint {
public:
BufferedPrint() : m_wr(nullptr), m_in(0) {}
@ -49,7 +52,7 @@ class BufferedPrint {
m_in = 0;
}
/** Flush the buffer - same as sync() with no status return. */
void flush() {sync();}
void flush() { sync(); }
/** Print a character followed by a field terminator.
* \param[in] c character to print.
* \param[in] term The field terminator. Use '\\n' for CR LF.
@ -72,7 +75,7 @@ class BufferedPrint {
* \param[in] term The field terminator. Use '\\n' for CR LF.
* \return true for success or false if an error occurs.
*/
size_t printField(const __FlashStringHelper *fsh, char term) {
size_t printField(const __FlashStringHelper* fsh, char term) {
#ifdef __AVR__
size_t rtn = 0;
PGM_P p = reinterpret_cast<PGM_P>(fsh);
@ -93,8 +96,8 @@ class BufferedPrint {
rtn += write(str, buf + sizeof(buf) - str);
}
return rtn;
#else // __AVR__
return printField(reinterpret_cast<const char *>(fsh), term);
#else // __AVR__
return printField(reinterpret_cast<const char*>(fsh), term);
#endif // __AVR__
}
/** Print a string followed by a field terminator.
@ -139,7 +142,7 @@ class BufferedPrint {
* \param[in] prec Number of digits after decimal point.
* \return true for success or false if an error occurs.
*/
size_t printField(float f, char term, uint8_t prec = 2) {
size_t printField(float f, char term, uint8_t prec = 2) {
return printField(static_cast<double>(f), term, prec);
}
/** Print an integer value for 8, 16, and 32 bit signed and unsigned types.
@ -147,7 +150,7 @@ class BufferedPrint {
* \param[in] term The field terminator. Use '\\n' for CR LF.
* \return true for success or false if an error occurs.
*/
template<typename Type>
template <typename Type>
size_t printField(Type n, char term) {
const uint8_t DIM = sizeof(Type) <= 2 ? 8 : 13;
char buf[DIM];
@ -184,9 +187,7 @@ class BufferedPrint {
* \param[in] prec Number of digits after decimal point.
* \return true for success or false if an error occurs.
*/
size_t print(double d, uint8_t prec = 2) {
return printField(d, 0, prec);
}
size_t print(double d, uint8_t prec = 2) { return printField(d, 0, prec); }
/** Print a double followed by CR LF.
* \param[in] d The number to be printed.
* \param[in] prec Number of digits after decimal point.
@ -215,7 +216,7 @@ class BufferedPrint {
* \param[in] v item to print.
* \return true for success or false if an error occurs.
*/
template<typename Type>
template <typename Type>
size_t print(Type v) {
return printField(v, 0);
}
@ -223,7 +224,7 @@ class BufferedPrint {
* \param[in] v item to print.
* \return true for success or false if an error occurs.
*/
template<typename Type>
template <typename Type>
size_t println(Type v) {
return printField(v, '\n');
}
@ -238,7 +239,7 @@ class BufferedPrint {
m_in = 0;
return true;
}
/** Write data to an open file.
/** Write data to an open file.
* \param[in] src Pointer to the location of the data to be written.
*
* \param[in] n Number of bytes to write.

View file

@ -22,9 +22,9 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "ExFatVolume.h"
#include "../common/upcase.h"
#include "ExFatLib.h"
#include "ExFatVolume.h"
#ifndef DOXYGEN_SHOULD_SKIP_THIS
//------------------------------------------------------------------------------
static void printHex(print_t* pr, uint8_t h);
@ -59,15 +59,15 @@ static uint16_t hashDir(DirName_t* dir, uint16_t hash) {
if (!u) {
break;
}
uint16_t c = toUpcase(u);
hash = ((hash << 15) | (hash >> 1)) + (c & 0XFF);
hash = ((hash << 15) | (hash >> 1)) + (c >> 8);
uint16_t c = toUpcase(u);
hash = ((hash << 15) | (hash >> 1)) + (c & 0XFF);
hash = ((hash << 15) | (hash >> 1)) + (c >> 8);
}
return hash;
}
//------------------------------------------------------------------------------
static void printDateTime(print_t* pr,
uint32_t timeDate, uint8_t ms, int8_t tz) {
static void printDateTime(print_t* pr, uint32_t timeDate, uint8_t ms,
int8_t tz) {
fsPrintDateTime(pr, timeDate, ms, tz);
pr->println();
}
@ -93,11 +93,11 @@ static void printDirFile(print_t* pr, DirFile_t* dir) {
pr->print(F("attributes: 0x"));
pr->println(getLe16(dir->attributes), HEX);
pr->print(F("createTime: "));
printDateTime(pr, getLe32(dir->createTime),
dir->createTimeMs, dir->createTimezone);
printDateTime(pr, getLe32(dir->createTime), dir->createTimeMs,
dir->createTimezone);
pr->print(F("modifyTime: "));
printDateTime(pr, getLe32(dir->modifyTime),
dir->modifyTimeMs, dir->modifyTimezone);
printDateTime(pr, getLe32(dir->modifyTime), dir->modifyTimeMs,
dir->modifyTimezone);
pr->print(F("accessTime: "));
printDateTime(pr, getLe32(dir->accessTime), 0, dir->accessTimezone);
}
@ -109,7 +109,7 @@ static void printDirLabel(print_t* pr, DirLabel_t* dir) {
pr->println(dir->labelLength);
pr->print(F("unicode: "));
for (size_t i = 0; i < dir->labelLength; i++) {
pr->write(dir->unicode[2*i]);
pr->write(dir->unicode[2 * i]);
}
pr->println();
}
@ -152,7 +152,7 @@ static void printDirStream(print_t* pr, DirStream_t* dir) {
static void printDirUpcase(print_t* pr, DirUpcase_t* dir) {
pr->print(F("dirUpcase: 0x"));
pr->println(dir->type, HEX);
pr->print(F("checksum: 0x"));
pr->print(F("checksum: 0x"));
pr->println(getLe32(dir->checksum), HEX);
pr->print(F("firstCluster: "));
pr->println(getLe32(dir->firstCluster));
@ -192,7 +192,7 @@ static void printExFatBoot(print_t* pr, pbs_t* pbs) {
pr->print(F("FileSystemRevision: 0x"));
pr->println(getLe32(ebs->fileSystemRevision), HEX);
pr->print(F("VolumeFlags: 0x"));
pr->println(getLe16(ebs->volumeFlags) , HEX);
pr->println(getLe16(ebs->volumeFlags), HEX);
pr->print(F("BytesPerSectorShift: "));
pr->println(ebs->bytesPerSectorShift);
pr->print(F("SectorsPerClusterShift: "));
@ -215,7 +215,7 @@ static void printHex(print_t* pr, uint8_t h) {
static void printHex(print_t* pr, uint16_t val) {
bool space = true;
for (uint8_t i = 0; i < 4; i++) {
uint8_t h = (val >> (12 - 4*i)) & 15;
uint8_t h = (val >> (12 - 4 * i)) & 15;
if (h || i == 3) {
space = false;
}
@ -230,7 +230,7 @@ static void printHex(print_t* pr, uint16_t val) {
static void printHex(print_t* pr, uint32_t val) {
bool space = true;
for (uint8_t i = 0; i < 8; i++) {
uint8_t h = (val >> (28 - 4*i)) & 15;
uint8_t h = (val >> (28 - 4 * i)) & 15;
if (h || i == 7) {
space = false;
}
@ -244,7 +244,7 @@ static void printHex(print_t* pr, uint32_t val) {
//------------------------------------------------------------------------------
static void printHex64(print_t* pr, uint64_t n) {
char buf[17];
char *str = &buf[sizeof(buf) - 1];
char* str = &buf[sizeof(buf) - 1];
*str = '\0';
do {
uint8_t h = n & 15;
@ -256,12 +256,12 @@ static void printHex64(print_t* pr, uint64_t n) {
//------------------------------------------------------------------------------
static void println64(print_t* pr, uint64_t n) {
char buf[21];
char *str = &buf[sizeof(buf) - 1];
char* str = &buf[sizeof(buf) - 1];
*str = '\0';
do {
uint64_t m = n;
n /= 10;
*--str = m - 10*n + '0';
*--str = m - 10 * n + '0';
} while (n);
pr->println(str);
}
@ -313,15 +313,15 @@ void ExFatPartition::checkUpcase(print_t* pr) {
pr->println(F("upcase not found"));
return;
}
for (size_t i = 0; i < size/2; i++) {
if ((i%256) == 0) {
for (size_t i = 0; i < size / 2; i++) {
if ((i % 256) == 0) {
upcase = dataCachePrepare(sector++, FsCache::CACHE_FOR_READ);
if (!upcase) {
pr->println(F("read upcase failed"));
return;
}
}
uint16_t v = getLe16(&upcase[2*(i & 0XFF)]);
uint16_t v = getLe16(&upcase[2 * (i & 0XFF)]);
if (skip) {
pr->print("skip ");
pr->print(u);
@ -334,7 +334,7 @@ void ExFatPartition::checkUpcase(print_t* pr) {
for (uint16_t k = 0; k < v; k++) {
uint16_t x = toUpcase(u + k);
if (x != (u + k)) {
printHex(pr, (uint16_t)(u+k));
printHex(pr, (uint16_t)(u + k));
pr->write(',');
printHex(pr, x);
pr->println("<<<<<<<<<<<<<<<<<<<<");
@ -363,8 +363,8 @@ void ExFatPartition::dmpBitmap(print_t* pr) {
dmpSector(pr, m_clusterHeapStartSector);
}
//------------------------------------------------------------------------------
void ExFatPartition::dmpCluster(print_t* pr, uint32_t cluster,
uint32_t offset, uint32_t count) {
void ExFatPartition::dmpCluster(print_t* pr, uint32_t cluster, uint32_t offset,
uint32_t count) {
uint32_t sector = clusterStartSector(cluster) + offset;
for (uint32_t i = 0; i < count; i++) {
pr->print(F("\nSector: "));
@ -375,7 +375,7 @@ void ExFatPartition::dmpCluster(print_t* pr, uint32_t cluster,
//------------------------------------------------------------------------------
void ExFatPartition::dmpFat(print_t* pr, uint32_t start, uint32_t count) {
uint32_t sector = m_fatStartSector + start;
uint32_t cluster = 128*start;
uint32_t cluster = 128 * start;
pr->println(F("FAT:"));
for (uint32_t i = 0; i < count; i++) {
uint8_t* cache = dataCachePrepare(sector + i, FsCache::CACHE_FOR_READ);
@ -385,7 +385,7 @@ void ExFatPartition::dmpFat(print_t* pr, uint32_t start, uint32_t count) {
}
uint32_t* fat = reinterpret_cast<uint32_t*>(cache);
for (size_t k = 0; k < 128; k++) {
if (0 == cluster%8) {
if (0 == cluster % 8) {
if (k) {
pr->println();
}
@ -406,7 +406,7 @@ void ExFatPartition::dmpSector(print_t* pr, uint32_t sector) {
return;
}
for (uint16_t i = 0; i < m_bytesPerSector; i++) {
if (i%32 == 0) {
if (i % 32 == 0) {
if (i) {
pr->println();
}
@ -427,9 +427,9 @@ bool ExFatPartition::printDir(print_t* pr, ExFatFile* file) {
uint16_t nameHash = 0;
uint16_t setChecksum = 0;
uint16_t calcChecksum = 0;
uint8_t nameLength = 0;
uint8_t setCount = 0;
uint8_t nUnicode;
uint8_t nameLength = 0;
uint8_t setCount = 0;
uint8_t nUnicode;
#define RAW_ROOT
#ifndef RAW_ROOT
@ -439,12 +439,12 @@ bool ExFatPartition::printDir(print_t* pr, ExFatFile* file) {
break;
}
dir = reinterpret_cast<DirGeneric_t*>(buf);
#else // RAW_ROOT
#else // RAW_ROOT
(void)file;
uint32_t nDir = 1UL << (m_sectorsPerClusterShift + 4);
uint32_t sector = clusterStartSector(m_rootDirectoryCluster);
for (uint32_t iDir = 0; iDir < nDir; iDir++) {
size_t i = iDir%16;
size_t i = iDir % 16;
if (i == 0) {
uint8_t* cache = dataCachePrepare(sector++, FsCache::CACHE_FOR_READ);
if (!cache) {
@ -491,7 +491,7 @@ bool ExFatPartition::printDir(print_t* pr, ExFatFile* file) {
calcHash = 0;
break;
case EXFAT_TYPE_NAME:
case EXFAT_TYPE_NAME:
dirName = reinterpret_cast<DirName_t*>(dir);
printDirName(pr, dirName);
calcChecksum = exFatDirChecksum(dir, calcChecksum);
@ -499,7 +499,7 @@ bool ExFatPartition::printDir(print_t* pr, ExFatFile* file) {
calcHash = hashDir(dirName, calcHash);
nameLength -= nUnicode;
setCount--;
if (nameLength == 0 || setCount == 0) {
if (nameLength == 0 || setCount == 0) {
pr->print(F("setChecksum: 0x"));
pr->print(setChecksum, HEX);
if (setChecksum != calcChecksum) {
@ -536,10 +536,9 @@ bool ExFatPartition::printDir(print_t* pr, ExFatFile* file) {
//------------------------------------------------------------------------------
void ExFatPartition::printFat(print_t* pr) {
uint32_t next;
int8_t status;
pr->println(F("FAT:"));
for (uint32_t cluster = 0; cluster < 16; cluster++) {
status = fatGet(cluster, &next);
int8_t status = fatGet(cluster, &next);
pr->print(cluster, HEX);
pr->write(' ');
if (status == 0) {
@ -573,20 +572,20 @@ void ExFatPartition::printUpcase(print_t* pr) {
pr->println(F("upcase not found"));
return;
}
for (uint16_t i = 0; i < size/2; i++) {
if ((i%256) == 0) {
for (uint16_t i = 0; i < size / 2; i++) {
if ((i % 256) == 0) {
upcase = dataCachePrepare(sector++, FsCache::CACHE_FOR_READ);
if (!upcase) {
pr->println(F("read upcase failed"));
return;
}
}
if (i%16 == 0) {
if (i % 16 == 0) {
pr->println();
printHex(pr, i);
}
pr->write(' ');
uint16_t uc = getLe16(&upcase[2*(i & 0XFF)]);
uint16_t uc = getLe16(&upcase[2 * (i & 0XFF)]);
printHex(pr, uc);
checksum = upcaseChecksum(uc, checksum);
}

View file

@ -36,7 +36,7 @@
inline bool lfnLegalChar(uint8_t c) {
#if USE_UTF8_LONG_NAMES
return !lfnReservedChar(c);
#else // USE_UTF8_LONG_NAMES
#else // USE_UTF8_LONG_NAMES
return !(lfnReservedChar(c) || c & 0X80);
#endif // USE_UTF8_LONG_NAMES
}
@ -60,13 +60,13 @@ bool ExFatFile::attrib(uint8_t bits) {
}
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
uint8_t* ExFatFile::dirCache(uint8_t set, uint8_t options) {
DirPos_t pos = m_dirPos;
if (m_vol->dirSeek(&pos, FS_DIR_SIZE*set) != 1) {
if (m_vol->dirSeek(&pos, FS_DIR_SIZE * set) != 1) {
return nullptr;
}
return m_vol->dirCache(&pos, options);
@ -87,8 +87,8 @@ bool ExFatFile::contiguousRange(uint32_t* bgnSector, uint32_t* endSector) {
*bgnSector = firstSector();
}
if (endSector) {
*endSector = firstSector() +
((m_validLength - 1) >> m_vol->bytesPerSectorShift());
*endSector =
firstSector() + ((m_validLength - 1) >> m_vol->bytesPerSectorShift());
}
return true;
}
@ -136,8 +136,8 @@ void ExFatFile::fsetpos(const fspos_t* pos) {
}
//------------------------------------------------------------------------------
bool ExFatFile::getAccessDateTime(uint16_t* pdate, uint16_t* ptime) {
DirFile_t* df = reinterpret_cast<DirFile_t*>
(m_vol->dirCache(&m_dirPos, FsCache::CACHE_FOR_READ));
DirFile_t* df = reinterpret_cast<DirFile_t*>(
m_vol->dirCache(&m_dirPos, FsCache::CACHE_FOR_READ));
if (!df) {
DBG_FAIL_MACRO;
goto fail;
@ -146,13 +146,13 @@ bool ExFatFile::getAccessDateTime(uint16_t* pdate, uint16_t* ptime) {
*ptime = getLe16(df->accessTime);
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
bool ExFatFile::getCreateDateTime(uint16_t* pdate, uint16_t* ptime) {
DirFile_t* df = reinterpret_cast<DirFile_t*>
(m_vol->dirCache(&m_dirPos, FsCache::CACHE_FOR_READ));
DirFile_t* df = reinterpret_cast<DirFile_t*>(
m_vol->dirCache(&m_dirPos, FsCache::CACHE_FOR_READ));
if (!df) {
DBG_FAIL_MACRO;
goto fail;
@ -161,13 +161,13 @@ bool ExFatFile::getCreateDateTime(uint16_t* pdate, uint16_t* ptime) {
*ptime = getLe16(df->createTime);
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
bool ExFatFile::getModifyDateTime(uint16_t* pdate, uint16_t* ptime) {
DirFile_t* df = reinterpret_cast<DirFile_t*>
(m_vol->dirCache(&m_dirPos, FsCache::CACHE_FOR_READ));
DirFile_t* df = reinterpret_cast<DirFile_t*>(
m_vol->dirCache(&m_dirPos, FsCache::CACHE_FOR_READ));
if (!df) {
DBG_FAIL_MACRO;
goto fail;
@ -176,13 +176,11 @@ bool ExFatFile::getModifyDateTime(uint16_t* pdate, uint16_t* ptime) {
*ptime = getLe16(df->modifyTime);
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
bool ExFatFile::isBusy() {
return m_vol->isBusy();
}
bool ExFatFile::isBusy() { return m_vol->isBusy(); }
//------------------------------------------------------------------------------
bool ExFatFile::open(const char* path, oflag_t oflag) {
return open(ExFatVolume::cwv(), path, oflag);
@ -231,7 +229,7 @@ bool ExFatFile::open(ExFatFile* dirFile, const char* path, oflag_t oflag) {
}
return openPrivate(dirFile, &fname, oflag);
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -241,7 +239,7 @@ bool ExFatFile::open(uint32_t index, oflag_t oflag) {
}
//------------------------------------------------------------------------------
bool ExFatFile::open(ExFatFile* dirFile, uint32_t index, oflag_t oflag) {
if (dirFile->seekSet(FS_DIR_SIZE*index) && openNext(dirFile, oflag)) {
if (dirFile->seekSet(FS_DIR_SIZE * index) && openNext(dirFile, oflag)) {
if (dirIndex() == index) {
return true;
}
@ -260,7 +258,7 @@ bool ExFatFile::openCwd() {
rewind();
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -271,20 +269,18 @@ bool ExFatFile::openNext(ExFatFile* dir, oflag_t oflag) {
}
return openPrivate(dir, nullptr, oflag);
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
bool ExFatFile::openPrivate(ExFatFile* dir, ExName_t* fname, oflag_t oflag) {
int n;
uint8_t modeFlags;
uint32_t curCluster __attribute__((unused));
uint8_t* cache __attribute__((unused));
DirPos_t freePos __attribute__((unused));
DirFile_t* dirFile;
DirFile_t* dirFile;
DirStream_t* dirStream;
DirName_t* dirName;
DirName_t* dirName;
uint8_t buf[FS_DIR_SIZE];
uint8_t freeCount = 0;
uint8_t freeNeed = 3;
@ -313,7 +309,7 @@ bool ExFatFile::openPrivate(ExFatFile* dir, ExName_t* fname, oflag_t oflag) {
modeFlags |= oflag & O_APPEND ? FILE_FLAG_APPEND : 0;
if (fname) {
freeNeed = 2 + (fname->nameLength + 14)/15;
freeNeed = 2 + (fname->nameLength + 14) / 15;
dir->rewind();
}
@ -394,7 +390,7 @@ bool ExFatFile::openPrivate(ExFatFile* dir, ExName_t* fname, oflag_t oflag) {
}
}
found:
found:
// Don't open if create only.
if (oflag & O_EXCL) {
DBG_FAIL_MACRO;
@ -428,11 +424,11 @@ bool ExFatFile::openPrivate(ExFatFile* dir, ExName_t* fname, oflag_t oflag) {
#endif // !EXFAT_READ_ONLY
return true;
create:
create:
#if EXFAT_READ_ONLY
DBG_FAIL_MACRO;
goto fail;
#else // EXFAT_READ_ONLY
#else // EXFAT_READ_ONLY
// don't create unless O_CREAT and write
if (!(oflag & O_CREAT) || !(modeFlags & FILE_FLAG_WRITE) || !fname) {
DBG_WARN_MACRO;
@ -441,12 +437,12 @@ bool ExFatFile::openPrivate(ExFatFile* dir, ExName_t* fname, oflag_t oflag) {
while (freeCount < freeNeed) {
n = dir->read(buf, FS_DIR_SIZE);
if (n == 0) {
curCluster = dir->m_curCluster;
uint32_t saveCurCluster = dir->m_curCluster;
if (!dir->addDirCluster()) {
DBG_FAIL_MACRO;
goto fail;
}
dir->m_curCluster = curCluster;
dir->m_curCluster = saveCurCluster;
continue;
}
if (n != FS_DIR_SIZE) {
@ -471,7 +467,7 @@ bool ExFatFile::openPrivate(ExFatFile* dir, ExName_t* fname, oflag_t oflag) {
DBG_FAIL_MACRO;
goto fail;
}
memset(cache, 0 , FS_DIR_SIZE);
memset(cache, 0, FS_DIR_SIZE);
if (i == 0) {
dirFile = reinterpret_cast<DirFile_t*>(cache);
dirFile->type = EXFAT_TYPE_FILE;
@ -489,11 +485,11 @@ bool ExFatFile::openPrivate(ExFatFile* dir, ExName_t* fname, oflag_t oflag) {
setLe16(dirFile->createDate, FS_DEFAULT_DATE);
setLe16(dirFile->modifyDate, FS_DEFAULT_DATE);
setLe16(dirFile->accessDate, FS_DEFAULT_DATE);
if (FS_DEFAULT_TIME) {
setLe16(dirFile->createTime, FS_DEFAULT_TIME);
setLe16(dirFile->modifyTime, FS_DEFAULT_TIME);
setLe16(dirFile->accessTime, FS_DEFAULT_TIME);
}
if (FS_DEFAULT_TIME) {
setLe16(dirFile->createTime, FS_DEFAULT_TIME);
setLe16(dirFile->modifyTime, FS_DEFAULT_TIME);
setLe16(dirFile->accessTime, FS_DEFAULT_TIME);
}
}
} else if (i == 1) {
dirStream = reinterpret_cast<DirStream_t*>(cache);
@ -510,14 +506,14 @@ bool ExFatFile::openPrivate(ExFatFile* dir, ExName_t* fname, oflag_t oflag) {
break;
}
uint16_t u = fname->get16();
setLe16(dirName->unicode + 2*k, u);
setLe16(dirName->unicode + 2 * k, u);
}
}
}
return sync();
#endif // EXFAT_READ_ONLY
fail:
fail:
// close file
m_attributes = FILE_ATTR_CLOSED;
m_flags = 0;
@ -535,12 +531,12 @@ bool ExFatFile::openRoot(ExFatVolume* vol) {
m_flags = FILE_FLAG_READ;
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
bool ExFatFile::parsePathName(const char* path,
ExName_t* fname, const char** ptr) {
bool ExFatFile::parsePathName(const char* path, ExName_t* fname,
const char** ptr) {
// Skip leading spaces.
while (*path == ' ') {
path++;
@ -559,20 +555,21 @@ bool ExFatFile::parsePathName(const char* path,
}
}
// Advance to next path component.
for (; *path == ' ' || isDirSeparator(*path); path++) {}
for (; *path == ' ' || isDirSeparator(*path); path++) {
}
*ptr = path;
return hashName(fname);
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
int ExFatFile::peek() {
uint64_t curPosition = m_curPosition;
uint32_t curCluster = m_curCluster;
uint64_t saveCurPosition = m_curPosition;
uint32_t saveCurCluster = m_curCluster;
int c = read();
m_curPosition = curPosition;
m_curCluster = curCluster;
m_curPosition = saveCurPosition;
m_curCluster = saveCurCluster;
return c;
}
//------------------------------------------------------------------------------
@ -600,8 +597,8 @@ int ExFatFile::read(void* buf, size_t count) {
sectorOffset = clusterOffset & m_vol->sectorMask();
if (clusterOffset == 0) {
if (m_curPosition == 0) {
m_curCluster = isRoot()
? m_vol->rootDirectoryCluster() : m_firstCluster;
m_curCluster =
isRoot() ? m_vol->rootDirectoryCluster() : m_firstCluster;
} else if (isContiguous()) {
m_curCluster++;
} else {
@ -622,8 +619,8 @@ int ExFatFile::read(void* buf, size_t count) {
}
sector = m_vol->clusterStartSector(m_curCluster) +
(clusterOffset >> m_vol->bytesPerSectorShift());
if (sectorOffset != 0 || toRead < m_vol->bytesPerSector()
|| sector == m_vol->dataCacheSector()) {
if (sectorOffset != 0 || toRead < m_vol->bytesPerSector() ||
sector == m_vol->dataCacheSector()) {
n = m_vol->bytesPerSector() - sectorOffset;
if (n > toRead) {
n = toRead;
@ -637,16 +634,16 @@ int ExFatFile::read(void* buf, size_t count) {
uint8_t* src = cache + sectorOffset;
memcpy(dst, src, n);
#if USE_MULTI_SECTOR_IO
} else if (toRead >= 2*m_vol->bytesPerSector()) {
} else if (toRead >= 2 * m_vol->bytesPerSector()) {
uint32_t ns = toRead >> m_vol->bytesPerSectorShift();
// Limit reads to current cluster.
uint32_t maxNs = m_vol->sectorsPerCluster()
- (clusterOffset >> m_vol->bytesPerSectorShift());
uint32_t maxNs = m_vol->sectorsPerCluster() -
(clusterOffset >> m_vol->bytesPerSectorShift());
if (ns > maxNs) {
ns = maxNs;
}
n = ns << m_vol->bytesPerSectorShift();
if (!m_vol->cacheSafeRead(sector, dst, ns)) {
if (!m_vol->cacheSafeRead(sector, dst, ns)) {
DBG_FAIL_MACRO;
goto fail;
}
@ -665,7 +662,7 @@ int ExFatFile::read(void* buf, size_t count) {
}
return count - toRead;
fail:
fail:
m_error |= READ_ERROR;
return -1;
}
@ -678,7 +675,7 @@ bool ExFatFile::remove(const char* path) {
}
return file.remove();
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -728,11 +725,11 @@ bool ExFatFile::seekSet(uint64_t pos) {
}
}
done:
done:
m_curPosition = pos;
return true;
fail:
fail:
m_curCluster = tmp;
return false;
}

View file

@ -30,9 +30,10 @@
*/
#include <limits.h>
#include <string.h>
#include "../common/FsDateTime.h"
#include "../common/FsApiConstants.h"
#include "../common/FmtNumber.h"
#include "../common/FsApiConstants.h"
#include "../common/FsDateTime.h"
#include "../common/FsName.h"
#include "ExFatPartition.h"
@ -68,9 +69,7 @@ class ExFatFile {
* \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).
*/
ExFatFile(const char* path, oflag_t oflag) {
open(path, oflag);
}
ExFatFile(const char* path, oflag_t oflag) { open(path, oflag); }
#if DESTRUCTOR_CLOSES_FILE
~ExFatFile() {
@ -81,18 +80,14 @@ class ExFatFile {
#endif // DESTRUCTOR_CLOSES_FILE
/** The parenthesis operator.
*
* \return true if a file is open.
*/
operator bool() {
return isOpen();
}
*
* \return true if a file is open.
*/
operator bool() { return isOpen(); }
/**
* \return user settable file attributes for success else -1.
*/
int attrib() {
return isFileOrSubDir() ? m_attributes & FS_ATTRIB_COPY : -1;
}
int attrib() { return isFileOrSubDir() ? m_attributes & FS_ATTRIB_COPY : -1; }
/** Set file attributes
*
* \param[in] bits bit-wise or of selected attributes: FS_ATTRIB_READ_ONLY,
@ -117,17 +112,11 @@ class ExFatFile {
/** \return The number of bytes available from the current position
* to EOF for normal files. Zero is returned for directory files.
*/
uint64_t available64() {
return isFile() ? fileSize() - curPosition() : 0;
}
uint64_t available64() { return isFile() ? fileSize() - curPosition() : 0; }
/** Clear all error bits. */
void clearError() {
m_error = 0;
}
void clearError() { m_error = 0; }
/** Clear writeError. */
void clearWriteError() {
m_error &= ~WRITE_ERROR;
}
void clearWriteError() { m_error &= ~WRITE_ERROR; }
/** Close a file and force cached data and directory information
* to be written to the storage device.
*
@ -145,13 +134,13 @@ class ExFatFile {
*/
bool contiguousRange(uint32_t* bgnSector, uint32_t* endSector);
/** \return The current cluster number for a file or directory. */
uint32_t curCluster() const {return m_curCluster;}
uint32_t curCluster() const { return m_curCluster; }
/** \return The current position for a file or directory. */
uint64_t curPosition() const {return m_curPosition;}
uint64_t curPosition() const { return m_curPosition; }
/** \return Total data length for file. */
uint64_t dataLength() const {return m_dataLength;}
uint64_t dataLength() const { return m_dataLength; }
/** \return Directory entry index. */
uint32_t dirIndex() const {return m_dirPos.position/FS_DIR_SIZE;}
uint32_t dirIndex() const { return m_dirPos.position / FS_DIR_SIZE; }
/** Test for the existence of a file in a directory
*
* \param[in] path Path of the file to be tested for.
@ -163,15 +152,15 @@ class ExFatFile {
*
* \return true if the file exists else false.
*/
bool exists(const char* path) {
ExFatFile file;
return file.open(this, path, O_RDONLY);
}
bool exists(const char* path) {
ExFatFile file;
return file.open(this, path, O_RDONLY);
}
/** get position for streams
* \param[out] pos struct to receive position
*/
void fgetpos(fspos_t* pos) const;
/**
/**
* Get a string from a file.
*
* fgets() reads bytes from a file into the array pointed to by \a str, until
@ -194,7 +183,7 @@ class ExFatFile {
*/
int fgets(char* str, int num, char* delim = nullptr);
/** \return The total number of bytes in a file. */
uint64_t fileSize() const {return m_validLength;}
uint64_t fileSize() const { return m_validLength; }
/** \return Address of first sector or zero for empty file. */
uint32_t firstSector() const;
/** Set position for streams
@ -202,7 +191,7 @@ class ExFatFile {
*/
void fsetpos(const fspos_t* pos);
/** Arduino name for sync() */
void flush() {sync();}
void flush() { sync(); }
/** Get a file's access date and time.
*
* \param[out] pdate Packed date for directory entry.
@ -220,9 +209,7 @@ class ExFatFile {
*/
bool getCreateDateTime(uint16_t* pdate, uint16_t* ptime);
/** \return All error bits. */
uint8_t getError() const {
return isOpen() ? m_error : 0XFF;
}
uint8_t getError() const { return isOpen() ? m_error : 0XFF; }
/** Get a file's modify date and time.
*
* \param[out] pdate Packed date for directory entry.
@ -241,7 +228,7 @@ class ExFatFile {
size_t getName(char* name, size_t size) {
#if USE_UTF8_LONG_NAMES
return getName8(name, size);
#else // USE_UTF8_LONG_NAMES
#else // USE_UTF8_LONG_NAMES
return getName7(name, size);
#endif // USE_UTF8_LONG_NAMES
}
@ -262,9 +249,7 @@ class ExFatFile {
*/
size_t getName8(char* name, size_t size);
/** \return value of writeError */
bool getWriteError() const {
return isOpen() ? m_error & WRITE_ERROR : true;
}
bool getWriteError() const { return isOpen() ? m_error & WRITE_ERROR : true; }
/**
* Check for FsBlockDevice busy.
*
@ -272,29 +257,29 @@ class ExFatFile {
*/
bool isBusy();
/** \return True if the file is contiguous. */
bool isContiguous() const {return m_flags & FILE_FLAG_CONTIGUOUS;}
bool isContiguous() const { return m_flags & FILE_FLAG_CONTIGUOUS; }
/** \return True if this is a directory. */
bool isDir() const {return m_attributes & FILE_ATTR_DIR;}
bool isDir() const { return m_attributes & FILE_ATTR_DIR; }
/** \return True if this is a normal file. */
bool isFile() const {return m_attributes & FILE_ATTR_FILE;}
bool isFile() const { return m_attributes & FILE_ATTR_FILE; }
/** \return True if this is a normal file or sub-directory. */
bool isFileOrSubDir() const {return isFile() || isSubDir();}
bool isFileOrSubDir() const { return isFile() || isSubDir(); }
/** \return True if this is a hidden. */
bool isHidden() const {return m_attributes & FS_ATTRIB_HIDDEN;}
bool isHidden() const { return m_attributes & FS_ATTRIB_HIDDEN; }
/** \return true if the file is open. */
bool isOpen() const {return m_attributes;}
bool isOpen() const { return m_attributes; }
/** \return True if file is read-only */
bool isReadOnly() const {return m_attributes & FS_ATTRIB_READ_ONLY;}
bool isReadOnly() const { return m_attributes & FS_ATTRIB_READ_ONLY; }
/** \return True if this is the root directory. */
bool isRoot() const {return m_attributes & FILE_ATTR_ROOT;}
bool isRoot() const { return m_attributes & FILE_ATTR_ROOT; }
/** \return True file is readable. */
bool isReadable() const {return m_flags & FILE_FLAG_READ;}
bool isReadable() const { return m_flags & FILE_FLAG_READ; }
/** \return True if this is a sub-directory. */
bool isSubDir() const {return m_attributes & FILE_ATTR_SUBDIR;}
bool isSubDir() const { return m_attributes & FILE_ATTR_SUBDIR; }
/** \return True if this is a system file. */
bool isSystem() const {return m_attributes & FS_ATTRIB_SYSTEM;}
bool isSystem() const { return m_attributes & FS_ATTRIB_SYSTEM; }
/** \return True file is writable. */
bool isWritable() const {return m_flags & FILE_FLAG_WRITE;}
bool isWritable() const { return m_flags & FILE_FLAG_WRITE; }
/** List directory contents.
*
* \param[in] pr Print stream for list.
@ -424,7 +409,7 @@ class ExFatFile {
* \return true for success or false for failure.
*/
bool open(const char* path, oflag_t oflag = O_RDONLY);
/** Open the current working directory.
/** Open the current working directory.
*
* \return true for success or false for failure.
*/
@ -463,14 +448,14 @@ class ExFatFile {
* \return true for success or false for failure.
*/
bool preAllocate(uint64_t length);
/** Print a file's access date and time
/** Print a file's access date and time
*
* \param[in] pr Print stream for output.
*
* \return true for success or false for failure.
*/
size_t printAccessDateTime(print_t* pr);
/** Print a file's creation date and time
/** Print a file's creation date and time
*
* \param[in] pr Print stream for output.
*
@ -512,7 +497,7 @@ class ExFatFile {
template <typename Type>
size_t printField(Type value, char term) {
char sign = 0;
char buf[3*sizeof(Type) + 3];
char buf[3 * sizeof(Type) + 3];
char* str = buf + sizeof(buf);
if (term) {
@ -556,7 +541,7 @@ class ExFatFile {
size_t printName(print_t* pr) {
#if USE_UTF8_LONG_NAMES
return printName8(pr);
#else // USE_UTF8_LONG_NAMES
#else // USE_UTF8_LONG_NAMES
return printName7(pr);
#endif // USE_UTF8_LONG_NAMES
}
@ -621,14 +606,14 @@ class ExFatFile {
* \return true for success or false for failure.
*/
bool remove(const char* path);
/** Rename a file or subdirectory.
/** Rename a file or subdirectory.
*
* \param[in] newPath New path name for the file/directory.
*
* \return true for success or false for failure.
*/
bool rename(const char* newPath);
/** Rename a file or subdirectory.
/** Rename a file or subdirectory.
*
* \param[in] dirFile Directory for the new path.
* \param[in] newPath New path name for the file/directory.
@ -637,9 +622,7 @@ class ExFatFile {
*/
bool rename(ExFatFile* dirFile, const char* newPath);
/** Set the file's current position to zero. */
void rewind() {
seekSet(0);
}
void rewind() { seekSet(0); }
/** Remove a directory file.
*
* The directory file will be removed only if it is empty and is not the
@ -657,9 +640,7 @@ class ExFatFile {
* \param[in] offset The new position in bytes from the current position.
* \return true for success or false for failure.
*/
bool seekCur(int64_t offset) {
return seekSet(m_curPosition + offset);
}
bool seekCur(int64_t offset) { return seekSet(m_curPosition + offset); }
/** Set the files position to end-of-file + \a offset. See seekSet().
* Can't be used for directory files since file size is not defined.
* \param[in] offset The new position in bytes from end-of-file.
@ -676,7 +657,7 @@ class ExFatFile {
*/
bool seekSet(uint64_t pos);
/** \return directory set count */
uint8_t setCount() const {return m_setCount;}
uint8_t setCount() const { return m_setCount; }
/** The sync() call causes all modified data and directory fields
* to be written to the storage device.
*
@ -728,32 +709,28 @@ class ExFatFile {
* \return true for success or false for failure.
*/
bool truncate();
/** Truncate a file to a specified length. The current file position
/** Truncate a file to a specified length. The current file position
* will be set to end of file.
*
* \param[in] length The desired length for the file.
*
* \return true for success or false for failure.
*/
bool truncate(uint64_t length) {
return seekSet(length) && truncate();
}
bool truncate(uint64_t length) { return seekSet(length) && truncate(); }
/** \return The valid number of bytes in a file. */
uint64_t validLength() const {return m_validLength;}
uint64_t validLength() const { return m_validLength; }
/** Write a string to a file. Used by the Arduino Print class.
* \param[in] str Pointer to the string.
* Use getWriteError to check for errors.
* \return count of characters written for success or -1 for failure.
*/
size_t write(const char* str) {
return write(str, strlen(str));
}
size_t write(const char* str) { return write(str, strlen(str)); }
/** Write a single byte.
* \param[in] b The byte to be written.
* \return +1 for success or zero for failure.
*/
size_t write(uint8_t b) {return write(&b, 1);}
size_t write(uint8_t b) { return write(&b, 1); }
/** Write data to an open file.
*
* \note Data is moved to the cache but may not be written to the
@ -781,16 +758,12 @@ class ExFatFile {
*
* \return true for success or false for failure.
*/
bool ls(uint8_t flags = 0) {
return ls(&Serial, flags);
}
bool ls(uint8_t flags = 0) { return ls(&Serial, flags); }
/** Print a file's name.
*
* \return length for success or zero for failure.
*/
size_t printName() {
return ExFatFile::printName(&Serial);
}
size_t printName() { return ExFatFile::printName(&Serial); }
#endif // ENABLE_ARDUINO_SERIAL
private:
@ -804,13 +777,12 @@ class ExFatFile {
bool mkdir(ExFatFile* parent, ExName_t* fname);
bool openPrivate(ExFatFile* dir, ExName_t* fname, oflag_t oflag);
bool parsePathName(const char* path,
ExName_t* fname, const char** ptr);
ExFatVolume* volume() const {return m_vol;}
bool parsePathName(const char* path, ExName_t* fname, const char** ptr);
ExFatVolume* volume() const { return m_vol; }
bool syncDir();
//----------------------------------------------------------------------------
static const uint8_t WRITE_ERROR = 0X1;
static const uint8_t READ_ERROR = 0X2;
static const uint8_t READ_ERROR = 0X2;
/** This file has not been opened. */
static const uint8_t FILE_ATTR_CLOSED = 0;
@ -826,21 +798,20 @@ class ExFatFile {
static const uint8_t FILE_FLAG_READ = 0X01;
static const uint8_t FILE_FLAG_WRITE = 0X02;
static const uint8_t FILE_FLAG_APPEND = 0X08;
static const uint8_t FILE_FLAG_CONTIGUOUS = 0X40;
static const uint8_t FILE_FLAG_CONTIGUOUS = 0X40;
static const uint8_t FILE_FLAG_DIR_DIRTY = 0X80;
uint64_t m_curPosition;
uint64_t m_dataLength;
uint64_t m_validLength;
uint32_t m_curCluster;
uint32_t m_firstCluster;
ExFatVolume* m_vol;
DirPos_t m_dirPos;
uint8_t m_setCount;
uint8_t m_attributes = FILE_ATTR_CLOSED;
uint8_t m_error = 0;
uint8_t m_flags = 0;
uint64_t m_curPosition;
uint64_t m_dataLength;
uint64_t m_validLength;
uint32_t m_curCluster;
uint32_t m_firstCluster;
ExFatVolume* m_vol;
DirPos_t m_dirPos;
uint8_t m_setCount;
uint8_t m_attributes = FILE_ATTR_CLOSED;
uint8_t m_error = 0;
uint8_t m_flags = 0;
};
#include "../common/ArduinoFiles.h"
@ -850,7 +821,7 @@ class ExFatFile {
*/
class ExFile : public StreamFile<ExFatFile, uint64_t> {
public:
/** Opens the next file or folder in a directory.
/** Opens the next file or folder in a directory.
*
* \param[in] oflag open flags.
* \return a FatStream object.

View file

@ -24,8 +24,8 @@
*/
#define DBG_FILE "ExFatFilePrint.cpp"
#include "../common/DebugMacros.h"
#include "ExFatLib.h"
#include "../common/FsUtf.h"
#include "ExFatLib.h"
//------------------------------------------------------------------------------
bool ExFatFile::ls(print_t* pr) {
ExFatFile file;
@ -51,7 +51,7 @@ bool ExFatFile::ls(print_t* pr) {
}
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -94,7 +94,7 @@ bool ExFatFile::ls(print_t* pr, uint8_t flags, uint8_t indent) {
}
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -119,13 +119,13 @@ size_t ExFatFile::printCreateDateTime(print_t* pr) {
size_t ExFatFile::printFileSize(print_t* pr) {
uint64_t n = m_validLength;
char buf[21];
char *str = &buf[sizeof(buf) - 1];
char *bgn = str - 12;
char* str = &buf[sizeof(buf) - 1];
char* bgn = str - 12;
*str = '\0';
do {
uint64_t m = n;
n /= 10;
*--str = m - 10*n + '0';
*--str = m - 10 * n + '0';
} while (n);
while (str > bgn) {
*--str = ' ';
@ -148,18 +148,17 @@ size_t ExFatFile::printName7(print_t* pr) {
uint8_t in;
uint8_t buf[15];
if (!isOpen()) {
DBG_FAIL_MACRO;
goto fail;
DBG_FAIL_MACRO;
goto fail;
}
for (uint8_t is = 2; is <= m_setCount; is++) {
dn = reinterpret_cast<DirName_t*>
(dirCache(is, FsCache::CACHE_FOR_READ));
dn = reinterpret_cast<DirName_t*>(dirCache(is, FsCache::CACHE_FOR_READ));
if (!dn || dn->type != EXFAT_TYPE_NAME) {
DBG_FAIL_MACRO;
goto fail;
}
for (in = 0; in < 15; in++) {
uint16_t c = getLe16(dn->unicode + 2*in);
uint16_t c = getLe16(dn->unicode + 2 * in);
if (!c) {
break;
}
@ -170,11 +169,11 @@ size_t ExFatFile::printName7(print_t* pr) {
}
return n;
fail:
fail:
return 0;
}
//------------------------------------------------------------------------------
size_t ExFatFile::printName8(print_t *pr) {
size_t ExFatFile::printName8(print_t* pr) {
DirName_t* dn;
uint16_t hs = 0;
uint32_t cp;
@ -182,18 +181,17 @@ size_t ExFatFile::printName8(print_t *pr) {
uint8_t in;
char buf[5];
if (!isOpen()) {
DBG_FAIL_MACRO;
goto fail;
DBG_FAIL_MACRO;
goto fail;
}
for (uint8_t is = 2; is <= m_setCount; is++) {
dn = reinterpret_cast<DirName_t*>
(dirCache(is, FsCache::CACHE_FOR_READ));
dn = reinterpret_cast<DirName_t*>(dirCache(is, FsCache::CACHE_FOR_READ));
if (!dn || dn->type != EXFAT_TYPE_NAME) {
DBG_FAIL_MACRO;
goto fail;
}
for (in = 0; in < 15; in++) {
uint16_t c = getLe16(dn->unicode + 2*in);
uint16_t c = getLe16(dn->unicode + 2 * in);
if (hs) {
if (!FsUtf::isLowSurrogate(c)) {
DBG_FAIL_MACRO;
@ -218,11 +216,11 @@ size_t ExFatFile::printName8(print_t *pr) {
DBG_FAIL_MACRO;
goto fail;
}
n += pr->write(buf, str - buf);
n += pr->write(reinterpret_cast<uint8_t*>(buf), str - buf);
}
}
return n;
fail:
fail:
return 0;
}

View file

@ -28,7 +28,7 @@
//==============================================================================
#if EXFAT_READ_ONLY
bool ExFatFile::mkdir(ExFatFile* parent, const char* path, bool pFlag) {
(void) parent;
(void)parent;
(void)path;
(void)pFlag;
return false;
@ -46,12 +46,8 @@ bool ExFatFile::rename(ExFatFile* dirFile, const char* newPath) {
(void)newPath;
return false;
}
bool ExFatFile::sync() {
return false;
}
bool ExFatFile::truncate() {
return false;
}
bool ExFatFile::sync() { return false; }
bool ExFatFile::truncate() { return false; }
size_t ExFatFile::write(const void* buf, size_t nbyte) {
(void)buf;
(void)nbyte;
@ -69,7 +65,7 @@ static uint16_t exFatDirChecksum(const uint8_t* data, uint16_t checksum) {
}
//------------------------------------------------------------------------------
bool ExFatFile::addCluster() {
uint32_t find = m_vol->bitmapFind(m_curCluster ? m_curCluster + 1 : 0, 1);
uint32_t find = m_vol->bitmapFind(m_curCluster ? m_curCluster + 1 : 0, 1);
if (find < 2) {
DBG_FAIL_MACRO;
goto fail;
@ -109,11 +105,11 @@ bool ExFatFile::addCluster() {
}
}
done:
done:
m_curCluster = find;
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -131,9 +127,9 @@ bool ExFatFile::addDirCluster() {
goto fail;
}
sector = m_vol->clusterStartSector(m_curCluster);
for (uint32_t i = 0; i < m_vol->sectorsPerCluster(); i++) {
cache = m_vol->dataCachePrepare(sector + i,
FsCache::CACHE_RESERVE_FOR_WRITE);
for (uint32_t i = 0; i < m_vol->sectorsPerCluster(); i++) {
cache =
m_vol->dataCachePrepare(sector + i, FsCache::CACHE_RESERVE_FOR_WRITE);
if (!cache) {
DBG_FAIL_MACRO;
goto fail;
@ -142,12 +138,12 @@ bool ExFatFile::addDirCluster() {
}
if (!isRoot()) {
m_flags |= FILE_FLAG_DIR_DIRTY;
m_dataLength += m_vol->bytesPerCluster();
m_dataLength += m_vol->bytesPerCluster();
m_validLength += m_vol->bytesPerCluster();
}
return sync();
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -189,7 +185,7 @@ bool ExFatFile::mkdir(ExFatFile* parent, const char* path, bool pFlag) {
}
return mkdir(parent, &fname);
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -218,7 +214,7 @@ bool ExFatFile::mkdir(ExFatFile* parent, ExName_t* fname) {
m_flags = FILE_FLAG_READ | FILE_FLAG_CONTIGUOUS | FILE_FLAG_DIR_DIRTY;
return sync();
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -248,7 +244,7 @@ bool ExFatFile::preAllocate(uint64_t length) {
}
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -290,7 +286,7 @@ bool ExFatFile::remove() {
// Write entry to device.
return m_vol->cacheSync();
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -330,7 +326,7 @@ bool ExFatFile::rename(ExFatFile* dirFile, const char* newPath) {
oldFile.m_attributes = FILE_ATTR_FILE;
return oldFile.remove();
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -363,7 +359,7 @@ bool ExFatFile::rmdir() {
m_flags |= FILE_FLAG_WRITE;
return remove();
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -382,7 +378,7 @@ bool ExFatFile::sync() {
}
return true;
fail:
fail:
m_error |= WRITE_ERROR;
return false;
}
@ -393,7 +389,7 @@ bool ExFatFile::syncDir() {
uint8_t* cache;
uint16_t checksum = 0;
for (uint8_t is = 0; is <= m_setCount ; is++) {
for (uint8_t is = 0; is <= m_setCount; is++) {
cache = dirCache(is, FsCache::CACHE_FOR_READ);
if (!cache) {
DBG_FAIL_MACRO;
@ -439,8 +435,8 @@ bool ExFatFile::syncDir() {
}
checksum = exFatDirChecksum(cache, checksum);
}
df = reinterpret_cast<DirFile_t*>
(m_vol->dirCache(&m_dirPos, FsCache::CACHE_FOR_WRITE));
df = reinterpret_cast<DirFile_t*>(
m_vol->dirCache(&m_dirPos, FsCache::CACHE_FOR_WRITE));
if (!df) {
DBG_FAIL_MACRO;
goto fail;
@ -452,13 +448,14 @@ bool ExFatFile::syncDir() {
}
return true;
fail:
fail:
m_error |= WRITE_ERROR;
return false;
}
//------------------------------------------------------------------------------
bool ExFatFile::timestamp(uint8_t flags, uint16_t year, uint8_t month,
uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) {
uint8_t day, uint8_t hour, uint8_t minute,
uint8_t second) {
DirFile_t* df;
uint8_t* cache;
uint16_t checksum = 0;
@ -466,16 +463,8 @@ bool ExFatFile::timestamp(uint8_t flags, uint16_t year, uint8_t month,
uint16_t time;
uint8_t ms10;
if (!isFile()
|| year < 1980
|| year > 2107
|| month < 1
|| month > 12
|| day < 1
|| day > 31
|| hour > 23
|| minute > 59
|| second > 59) {
if (!isFile() || year < 1980 || year > 2107 || month < 1 || month > 12 ||
day < 1 || day > 31 || hour > 23 || minute > 59 || second > 59) {
DBG_FAIL_MACRO;
goto fail;
}
@ -529,8 +518,8 @@ bool ExFatFile::timestamp(uint8_t flags, uint16_t year, uint8_t month,
}
checksum = exFatDirChecksum(cache, checksum);
}
df = reinterpret_cast<DirFile_t*>
(m_vol->dirCache(&m_dirPos, FsCache::CACHE_FOR_WRITE));
df = reinterpret_cast<DirFile_t*>(
m_vol->dirCache(&m_dirPos, FsCache::CACHE_FOR_WRITE));
if (!df) {
DBG_FAIL_MACRO;
goto fail;
@ -542,7 +531,7 @@ bool ExFatFile::timestamp(uint8_t flags, uint16_t year, uint8_t month,
}
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -554,7 +543,7 @@ bool ExFatFile::truncate() {
goto fail;
}
if (m_firstCluster == 0) {
return true;
return true;
}
if (isContiguous()) {
uint32_t nc = 1 + ((m_dataLength - 1) >> m_vol->bytesPerClusterShift());
@ -601,7 +590,7 @@ bool ExFatFile::truncate() {
m_flags |= FILE_FLAG_DIR_DIRTY;
return sync();
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -708,18 +697,18 @@ size_t ExFatFile::write(const void* buf, size_t nbyte) {
}
}
#if USE_MULTI_SECTOR_IO
} else if (toWrite >= 2*m_vol->bytesPerSector()) {
} else if (toWrite >= 2 * m_vol->bytesPerSector()) {
// use multiple sector write command
uint32_t ns = toWrite >> m_vol->bytesPerSectorShift();
// Limit writes to current cluster.
uint32_t maxNs = m_vol->sectorsPerCluster()
- (clusterOffset >> m_vol->bytesPerSectorShift());
uint32_t maxNs = m_vol->sectorsPerCluster() -
(clusterOffset >> m_vol->bytesPerSectorShift());
if (ns > maxNs) {
ns = maxNs;
}
n = ns << m_vol->bytesPerSectorShift();
if (!m_vol->cacheSafeWrite(sector, src, ns)) {
DBG_FAIL_MACRO;
DBG_FAIL_MACRO;
goto fail;
}
#endif // USE_MULTI_SECTOR_IO
@ -748,7 +737,7 @@ size_t ExFatFile::write(const void* buf, size_t nbyte) {
}
return nbyte;
fail:
fail:
// return for write error
m_error |= WRITE_ERROR;
return 0;

View file

@ -31,7 +31,7 @@
const uint32_t BOOT_BACKUP_OFFSET = 12;
const uint16_t BYTES_PER_SECTOR = 512;
const uint16_t SECTOR_MASK = BYTES_PER_SECTOR - 1;
const uint8_t BYTES_PER_SECTOR_SHIFT = 9;
const uint8_t BYTES_PER_SECTOR_SHIFT = 9;
const uint16_t MINIMUM_UPCASE_SKIP = 512;
const uint32_t BITMAP_CLUSTER = 2;
const uint32_t UPCASE_CLUSTER = 3;
@ -41,14 +41,16 @@ const uint32_t ROOT_CLUSTER = 4;
#if !PRINT_FORMAT_PROGRESS
#define writeMsg(pr, str)
#elif defined(__AVR__)
#define writeMsg(pr, str) if (pr) pr->print(F(str))
#define writeMsg(pr, str) \
if (pr) pr->print(F(str))
#else // PRINT_FORMAT_PROGRESS
#define writeMsg(pr, str) if (pr) pr->write(str)
#define writeMsg(pr, str) \
if (pr) pr->write(str)
#endif // PRINT_FORMAT_PROGRESS
//------------------------------------------------------------------------------
bool ExFatFormatter::format(FsBlockDevice* dev, uint8_t* secBuf, print_t* pr) {
#if !PRINT_FORMAT_PROGRESS
(void)pr;
(void)pr;
#endif // !PRINT_FORMAT_PROGRESS
MbrSector_t* mbr;
ExFatPbs_t* pbs;
@ -81,14 +83,15 @@ bool ExFatFormatter::format(FsBlockDevice* dev, uint8_t* secBuf, print_t* pr) {
goto fail;
}
// Determine partition layout.
for (m = 1, vs = 0; m && sectorCount > m; m <<= 1, vs++) {}
sectorsPerClusterShift = vs < 29 ? 8 : (vs - 11)/2;
for (m = 1, vs = 0; m && sectorCount > m; m <<= 1, vs++) {
}
sectorsPerClusterShift = vs < 29 ? 8 : (vs - 11) / 2;
sectorsPerCluster = 1UL << sectorsPerClusterShift;
fatLength = 1UL << (vs < 27 ? 13 : (vs + 1)/2);
fatLength = 1UL << (vs < 27 ? 13 : (vs + 1) / 2);
fatOffset = fatLength;
partitionOffset = 2*fatLength;
clusterHeapOffset = 2*fatLength;
clusterCount = (sectorCount - 4*fatLength) >> sectorsPerClusterShift;
partitionOffset = 2 * fatLength;
clusterHeapOffset = 2 * fatLength;
clusterCount = (sectorCount - 4 * fatLength) >> sectorsPerClusterShift;
volumeLength = clusterHeapOffset + (clusterCount << sectorsPerClusterShift);
// make Master Boot Record. Use fake CHS.
@ -152,8 +155,8 @@ bool ExFatFormatter::format(FsBlockDevice* dev, uint8_t* secBuf, print_t* pr) {
checksum = exFatChecksum(checksum, secBuf[i]);
}
sector = partitionOffset;
if (!dev->writeSector(sector, secBuf) ||
!dev->writeSector(sector + BOOT_BACKUP_OFFSET , secBuf)) {
if (!dev->writeSector(sector, secBuf) ||
!dev->writeSector(sector + BOOT_BACKUP_OFFSET, secBuf)) {
DBG_FAIL_MACRO;
goto fail;
}
@ -165,8 +168,8 @@ bool ExFatFormatter::format(FsBlockDevice* dev, uint8_t* secBuf, print_t* pr) {
for (size_t i = 0; i < BYTES_PER_SECTOR; i++) {
checksum = exFatChecksum(checksum, secBuf[i]);
}
if (!dev->writeSector(sector, secBuf) ||
!dev->writeSector(sector + BOOT_BACKUP_OFFSET , secBuf)) {
if (!dev->writeSector(sector, secBuf) ||
!dev->writeSector(sector + BOOT_BACKUP_OFFSET, secBuf)) {
DBG_FAIL_MACRO;
goto fail;
}
@ -178,8 +181,8 @@ bool ExFatFormatter::format(FsBlockDevice* dev, uint8_t* secBuf, print_t* pr) {
for (size_t i = 0; i < BYTES_PER_SECTOR; i++) {
checksum = exFatChecksum(checksum, secBuf[i]);
}
if (!dev->writeSector(sector, secBuf) ||
!dev->writeSector(sector + BOOT_BACKUP_OFFSET , secBuf)) {
if (!dev->writeSector(sector, secBuf) ||
!dev->writeSector(sector + BOOT_BACKUP_OFFSET, secBuf)) {
DBG_FAIL_MACRO;
goto fail;
}
@ -189,15 +192,15 @@ bool ExFatFormatter::format(FsBlockDevice* dev, uint8_t* secBuf, print_t* pr) {
for (size_t i = 0; i < BYTES_PER_SECTOR; i += 4) {
setLe32(secBuf + i, checksum);
}
if (!dev->writeSector(sector, secBuf) ||
!dev->writeSector(sector + BOOT_BACKUP_OFFSET , secBuf)) {
if (!dev->writeSector(sector, secBuf) ||
!dev->writeSector(sector + BOOT_BACKUP_OFFSET, secBuf)) {
DBG_FAIL_MACRO;
goto fail;
}
// Initialize FAT.
writeMsg(pr, "Writing FAT ");
sector = partitionOffset + fatOffset;
ns = ((clusterCount + 2)*4 + BYTES_PER_SECTOR - 1)/BYTES_PER_SECTOR;
ns = ((clusterCount + 2) * 4 + BYTES_PER_SECTOR - 1) / BYTES_PER_SECTOR;
memset(secBuf, 0, BYTES_PER_SECTOR);
// Allocate two reserved clusters, bitmap, upcase, and root clusters.
@ -206,7 +209,7 @@ bool ExFatFormatter::format(FsBlockDevice* dev, uint8_t* secBuf, print_t* pr) {
secBuf[i] = 0XFF;
}
for (uint32_t i = 0; i < ns; i++) {
if (i%(ns/32) == 0) {
if (i % (ns / 32) == 0) {
writeMsg(pr, ".");
}
if (!dev->writeSector(sector + i, secBuf)) {
@ -220,8 +223,8 @@ bool ExFatFormatter::format(FsBlockDevice* dev, uint8_t* secBuf, print_t* pr) {
writeMsg(pr, "\r\n");
// Write cluster two, bitmap.
sector = partitionOffset + clusterHeapOffset;
bitmapSize = (clusterCount + 7)/8;
ns = (bitmapSize + BYTES_PER_SECTOR - 1)/BYTES_PER_SECTOR;
bitmapSize = (clusterCount + 7) / 8;
ns = (bitmapSize + BYTES_PER_SECTOR - 1) / BYTES_PER_SECTOR;
if (ns > sectorsPerCluster) {
DBG_FAIL_MACRO;
goto fail;
@ -244,14 +247,14 @@ bool ExFatFormatter::format(FsBlockDevice* dev, uint8_t* secBuf, print_t* pr) {
DBG_FAIL_MACRO;
goto fail;
}
if (m_upcaseSize > BYTES_PER_SECTOR*sectorsPerCluster) {
if (m_upcaseSize > BYTES_PER_SECTOR * sectorsPerCluster) {
DBG_FAIL_MACRO;
goto fail;
}
// Initialize first sector of root.
writeMsg(pr, "Writing root\r\n");
ns = sectorsPerCluster;
sector = partitionOffset + clusterHeapOffset + 2*sectorsPerCluster;
sector = partitionOffset + clusterHeapOffset + 2 * sectorsPerCluster;
memset(secBuf, 0, BYTES_PER_SECTOR);
// Unused Label entry.
@ -284,7 +287,7 @@ bool ExFatFormatter::format(FsBlockDevice* dev, uint8_t* secBuf, print_t* pr) {
writeMsg(pr, "Format done\r\n");
return true;
fail:
fail:
writeMsg(pr, "Format failed\r\n");
return false;
}
@ -334,7 +337,8 @@ bool ExFatFormatter::writeUpcase(uint32_t sector) {
}
ch++;
} else {
for (n = ch + 1; n < 0X10000 && n == toUpcase(n); n++) {}
for (n = ch + 1; n < 0X10000 && n == toUpcase(n); n++) {
}
ns = n - ch;
if (ns >= MINIMUM_UPCASE_SKIP) {
if (!writeUpcaseUnicode(0XFFFF) || !writeUpcaseUnicode(ns)) {
@ -358,6 +362,6 @@ bool ExFatFormatter::writeUpcase(uint32_t sector) {
}
return true;
fail:
fail:
return false;
}

View file

@ -31,6 +31,8 @@
*/
class ExFatFormatter {
public:
/** Constructor. */
ExFatFormatter() = default;
/**
* Format an exFAT volume.
*
@ -41,6 +43,7 @@ class ExFatFormatter {
* \return true for success or false for failure.
*/
bool format(FsBlockDevice* dev, uint8_t* secBuf, print_t* pr = nullptr);
private:
bool syncUpcase();
bool writeUpcase(uint32_t sector);

View file

@ -24,6 +24,6 @@
*/
#ifndef ExFatLib_h
#define ExFatLib_h
#include "ExFatVolume.h"
#include "ExFatFormatter.h"
#include "ExFatVolume.h"
#endif // ExFatLib_h

View file

@ -24,13 +24,11 @@
*/
#define DBG_FILE "ExFatName.cpp"
#include "../common/DebugMacros.h"
#include "../common/upcase.h"
#include "../common/FsUtf.h"
#include "../common/upcase.h"
#include "ExFatLib.h"
//------------------------------------------------------------------------------
static char toUpper(char c) {
return 'a' <= c && c <= 'z' ? c - 'a' + 'A' : c;
}
static char toUpper(char c) { return 'a' <= c && c <= 'z' ? c - 'a' + 'A' : c; }
//------------------------------------------------------------------------------
inline uint16_t exFatHash(char c, uint16_t hash) {
uint8_t u = toUpper(c);
@ -48,16 +46,16 @@ inline uint16_t exFatHash(uint16_t u, uint16_t hash) {
//------------------------------------------------------------------------------
bool ExFatFile::cmpName(const DirName_t* dirName, ExName_t* fname) {
for (uint8_t i = 0; i < 15; i++) {
uint16_t u = getLe16(dirName->unicode + 2*i);
uint16_t u = getLe16(dirName->unicode + 2 * i);
if (fname->atEnd()) {
return u == 0;
}
#if USE_UTF8_LONG_NAMES
uint16_t cp = fname->get16();
if (toUpcase(cp) != toUpcase(u)) {
return false;
return false;
}
#else // USE_UTF8_LONG_NAMES
#else // USE_UTF8_LONG_NAMES
char c = fname->getch();
if (u >= 0x7F || toUpper(c) != toUpper(u)) {
return false;
@ -71,18 +69,17 @@ size_t ExFatFile::getName7(char* name, size_t count) {
DirName_t* dn;
size_t n = 0;
if (!isOpen()) {
DBG_FAIL_MACRO;
goto fail;
DBG_FAIL_MACRO;
goto fail;
}
for (uint8_t is = 2; is <= m_setCount; is++) {
dn = reinterpret_cast<DirName_t*>
(dirCache(is, FsCache::CACHE_FOR_READ));
dn = reinterpret_cast<DirName_t*>(dirCache(is, FsCache::CACHE_FOR_READ));
if (!dn || dn->type != EXFAT_TYPE_NAME) {
DBG_FAIL_MACRO;
goto fail;
}
for (uint8_t in = 0; in < 15; in++) {
uint16_t c = getLe16(dn->unicode + 2*in);
uint16_t c = getLe16(dn->unicode + 2 * in);
if (c == 0) {
goto done;
}
@ -93,11 +90,11 @@ size_t ExFatFile::getName7(char* name, size_t count) {
name[n++] = c < 0X7F ? c : '?';
}
}
done:
done:
name[n] = 0;
return n;
fail:
fail:
*name = 0;
return 0;
}
@ -110,18 +107,17 @@ size_t ExFatFile::getName8(char* name, size_t count) {
uint16_t hs = 0;
uint32_t cp;
if (!isOpen()) {
DBG_FAIL_MACRO;
goto fail;
DBG_FAIL_MACRO;
goto fail;
}
for (uint8_t is = 2; is <= m_setCount; is++) {
dn = reinterpret_cast<DirName_t*>
(dirCache(is, FsCache::CACHE_FOR_READ));
dn = reinterpret_cast<DirName_t*>(dirCache(is, FsCache::CACHE_FOR_READ));
if (!dn || dn->type != EXFAT_TYPE_NAME) {
DBG_FAIL_MACRO;
goto fail;
}
for (uint8_t in = 0; in < 15; in++) {
uint16_t c = getLe16(dn->unicode + 2*in);
uint16_t c = getLe16(dn->unicode + 2 * in);
if (hs) {
if (!FsUtf::isLowSurrogate(c)) {
DBG_FAIL_MACRO;
@ -150,11 +146,11 @@ size_t ExFatFile::getName8(char* name, size_t count) {
str = ptr;
}
}
done:
done:
*str = '\0';
return str - name;
fail:
fail:
*name = 0;
return 0;
}
@ -167,13 +163,13 @@ bool ExFatFile::hashName(ExName_t* fname) {
while (!fname->atEnd()) {
uint16_t u = fname->get16();
if (u == 0XFFFF) {
DBG_FAIL_MACRO;
DBG_FAIL_MACRO;
goto fail;
}
hash = exFatHash(u, hash);
fname->nameLength++;
}
#else // USE_UTF8_LONG_NAMES
#else // USE_UTF8_LONG_NAMES
while (!fname->atEnd()) {
// Convert to byte for smaller exFatHash.
char c = fname->getch();
@ -188,7 +184,6 @@ bool ExFatFile::hashName(ExName_t* fname) {
}
return true;
fail:
fail:
return false;
}

View file

@ -39,8 +39,8 @@ uint32_t ExFatPartition::bitmapFind(uint32_t cluster, uint32_t count) {
uint8_t* cache;
uint8_t mask = 1 << (start & 7);
while (true) {
uint32_t sector = m_clusterHeapStartSector +
(endAlloc >> (m_bytesPerSectorShift + 3));
uint32_t sector =
m_clusterHeapStartSector + (endAlloc >> (m_bytesPerSectorShift + 3));
cache = bitmapCachePrepare(sector, FsCache::CACHE_FOR_READ);
if (!cache) {
return 0;
@ -75,8 +75,8 @@ uint32_t ExFatPartition::bitmapFind(uint32_t cluster, uint32_t count) {
return 0;
}
//------------------------------------------------------------------------------
bool ExFatPartition::bitmapModify(uint32_t cluster,
uint32_t count, bool value) {
bool ExFatPartition::bitmapModify(uint32_t cluster, uint32_t count,
bool value) {
uint32_t sector;
uint32_t start = cluster - 2;
size_t i;
@ -88,7 +88,7 @@ bool ExFatPartition::bitmapModify(uint32_t cluster,
goto fail;
}
if (value) {
if (start <= m_bitmapStart && m_bitmapStart < (start + count)) {
if (start <= m_bitmapStart && m_bitmapStart < (start + count)) {
m_bitmapStart = (start + count) < m_clusterCount ? start + count : 0;
}
} else {
@ -97,8 +97,7 @@ bool ExFatPartition::bitmapModify(uint32_t cluster,
}
}
mask = 1 << (start & 7);
sector = m_clusterHeapStartSector +
(start >> (m_bytesPerSectorShift + 3));
sector = m_clusterHeapStartSector + (start >> (m_bytesPerSectorShift + 3));
i = (start >> 3) & m_sectorMask;
while (true) {
cache = bitmapCachePrepare(sector++, FsCache::CACHE_FOR_WRITE);
@ -122,7 +121,7 @@ bool ExFatPartition::bitmapModify(uint32_t cluster,
i = 0;
}
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -130,7 +129,7 @@ uint32_t ExFatPartition::chainSize(uint32_t cluster) {
uint32_t n = 0;
int8_t status;
do {
status = fatGet(cluster, & cluster);
status = fatGet(cluster, &cluster);
if (status < 0) return 0;
n++;
} while (status);
@ -203,7 +202,7 @@ bool ExFatPartition::fatPut(uint32_t cluster, uint32_t value) {
setLe32(cache + ((cluster << 2) & m_sectorMask), value);
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -233,7 +232,7 @@ bool ExFatPartition::freeChain(uint32_t cluster) {
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -250,9 +249,9 @@ int32_t ExFatPartition::freeClusterCount() {
}
for (size_t i = 0; i < m_bytesPerSector; i++) {
if (cache[i] == 0XFF) {
usedCount+= 8;
usedCount += 8;
} else if (cache[i]) {
for (uint8_t mask = 1; mask ; mask <<=1) {
for (uint8_t mask = 1; mask; mask <<= 1) {
if ((mask & cache[i])) {
usedCount++;
}
@ -280,8 +279,8 @@ bool ExFatPartition::init(FsBlockDevice* dev, uint8_t part, uint32_t volStart) {
DBG_FAIL_MACRO;
goto fail;
}
mbr = reinterpret_cast<MbrSector_t*>
(dataCachePrepare(0, FsCache::CACHE_FOR_READ));
mbr = reinterpret_cast<MbrSector_t*>(
dataCachePrepare(0, FsCache::CACHE_FOR_READ));
if (!mbr) {
DBG_FAIL_MACRO;
goto fail;
@ -293,8 +292,8 @@ bool ExFatPartition::init(FsBlockDevice* dev, uint8_t part, uint32_t volStart) {
}
volStart = getLe32(mp->relativeSectors);
}
pbs = reinterpret_cast<pbs_t*>
(dataCachePrepare(volStart, FsCache::CACHE_FOR_READ));
pbs = reinterpret_cast<pbs_t*>(
dataCachePrepare(volStart, FsCache::CACHE_FOR_READ));
if (!pbs) {
DBG_FAIL_MACRO;
goto fail;
@ -322,7 +321,7 @@ bool ExFatPartition::init(FsBlockDevice* dev, uint8_t part, uint32_t volStart) {
m_fatType = FAT_TYPE_EXFAT;
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------

View file

@ -28,10 +28,10 @@
* \file
* \brief ExFatPartition include file.
*/
#include "../common/SysCall.h"
#include "../common/FsBlockDevice.h"
#include "../common/FsCache.h"
#include "../common/FsStructs.h"
#include "../common/SysCall.h"
/** Set EXFAT_READ_ONLY non-zero for read only */
#ifndef EXFAT_READ_ONLY
#define EXFAT_READ_ONLY 0
@ -51,7 +51,7 @@ struct DirPos_t {
/** offset */
uint32_t position;
/** directory is contiguous */
bool isContiguous;
bool isContiguous;
};
//==============================================================================
/**
@ -60,28 +60,26 @@ struct DirPos_t {
*/
class ExFatPartition {
public:
ExFatPartition() {}
ExFatPartition() = default;
/** \return the number of bytes in a cluster. */
uint32_t bytesPerCluster() const {return m_bytesPerCluster;}
uint32_t bytesPerCluster() const { return m_bytesPerCluster; }
/** \return the power of two for bytesPerCluster. */
uint8_t bytesPerClusterShift() const {
return m_bytesPerSectorShift + m_sectorsPerClusterShift;
}
/** \return the number of bytes in a sector. */
uint16_t bytesPerSector() const {return m_bytesPerSector;}
uint16_t bytesPerSector() const { return m_bytesPerSector; }
/** \return the power of two for bytesPerSector. */
uint8_t bytesPerSectorShift() const {return m_bytesPerSectorShift;}
uint8_t bytesPerSectorShift() const { return m_bytesPerSectorShift; }
/** Clear the cache and returns a pointer to the cache. Not for normal apps.
* \return A pointer to the cache buffer or zero if an error occurs.
*/
uint8_t* cacheClear() {
return m_dataCache.clear();
}
uint8_t* cacheClear() { return m_dataCache.clear(); }
/** \return the cluster count for the partition. */
uint32_t clusterCount() const {return m_clusterCount;}
uint32_t clusterCount() const { return m_clusterCount; }
/** \return the cluster heap start sector. */
uint32_t clusterHeapStartSector() const {return m_clusterHeapStartSector;}
uint32_t clusterHeapStartSector() const { return m_clusterHeapStartSector; }
/** End access to volume
* \return pointer to sector size buffer for format.
*/
@ -90,11 +88,11 @@ class ExFatPartition {
return cacheClear();
}
/** \return the FAT length in sectors */
uint32_t fatLength() const {return m_fatLength;}
uint32_t fatLength() const { return m_fatLength; }
/** \return the FAT start sector number. */
uint32_t fatStartSector() const {return m_fatStartSector;}
uint32_t fatStartSector() const { return m_fatStartSector; }
/** \return Type FAT_TYPE_EXFAT for exFAT partition or zero for error. */
uint8_t fatType() const {return m_fatType;}
uint8_t fatType() const { return m_fatType; }
/** \return free cluster count or -1 if an error occurs. */
int32_t freeClusterCount();
/** Initialize a exFAT partition.
@ -113,25 +111,25 @@ class ExFatPartition {
*
* \return true if busy else false.
*/
bool isBusy() {return m_blockDev->isBusy();}
bool isBusy() { return m_blockDev->isBusy(); }
/** \return the root directory start cluster number. */
uint32_t rootDirectoryCluster() const {return m_rootDirectoryCluster;}
uint32_t rootDirectoryCluster() const { return m_rootDirectoryCluster; }
/** \return the root directory length. */
uint32_t rootLength();
/** \return the number of sectors in a cluster. */
uint32_t sectorsPerCluster() const {return 1UL << m_sectorsPerClusterShift;}
uint32_t sectorsPerCluster() const { return 1UL << m_sectorsPerClusterShift; }
#ifndef DOXYGEN_SHOULD_SKIP_THIS
uint32_t __attribute__((error("use sectorsPerCluster()"))) blocksPerCluster();
#endif // DOXYGEN_SHOULD_SKIP_THIS
/** \return the power of two for sectors per cluster. */
uint8_t sectorsPerClusterShift() const {return m_sectorsPerClusterShift;}
uint8_t sectorsPerClusterShift() const { return m_sectorsPerClusterShift; }
//----------------------------------------------------------------------------
#ifndef DOXYGEN_SHOULD_SKIP_THIS
void checkUpcase(print_t* pr);
bool printDir(print_t* pr, ExFatFile* file);
void dmpBitmap(print_t* pr);
void dmpCluster(print_t* pr, uint32_t cluster,
uint32_t offset, uint32_t count);
void dmpCluster(print_t* pr, uint32_t cluster, uint32_t offset,
uint32_t count);
void dmpFat(print_t* pr, uint32_t start, uint32_t count);
void dmpSector(print_t* pr, uint32_t sector);
bool printVolInfo(print_t* pr);
@ -149,7 +147,7 @@ class ExFatPartition {
uint8_t* bitmapCachePrepare(uint32_t sector, uint8_t option) {
#if USE_EXFAT_BITMAP_CACHE
return m_bitmapCache.prepare(sector, option);
#else // USE_EXFAT_BITMAP_CACHE
#else // USE_EXFAT_BITMAP_CACHE
return m_dataCache.prepare(sector, option);
#endif // USE_EXFAT_BITMAP_CACHE
}
@ -162,19 +160,19 @@ class ExFatPartition {
bool cacheSync() {
#if USE_EXFAT_BITMAP_CACHE
return m_bitmapCache.sync() && m_dataCache.sync() && syncDevice();
#else // USE_EXFAT_BITMAP_CACHE
#else // USE_EXFAT_BITMAP_CACHE
return m_dataCache.sync() && syncDevice();
#endif // USE_EXFAT_BITMAP_CACHE
}
void dataCacheDirty() {m_dataCache.dirty();}
void dataCacheInvalidate() {m_dataCache.invalidate();}
void dataCacheDirty() { m_dataCache.dirty(); }
void dataCacheInvalidate() { m_dataCache.invalidate(); }
uint8_t* dataCachePrepare(uint32_t sector, uint8_t option) {
return m_dataCache.prepare(sector, option);
}
uint32_t dataCacheSector() {return m_dataCache.sector();}
bool dataCacheSync() {return m_dataCache.sync();}
uint32_t dataCacheSector() { return m_dataCache.sector(); }
bool dataCacheSync() { return m_dataCache.sync(); }
//----------------------------------------------------------------------------
uint32_t clusterMask() const {return m_clusterMask;}
uint32_t clusterMask() const { return m_clusterMask; }
uint32_t clusterStartSector(uint32_t cluster) {
return m_clusterHeapStartSector +
((cluster - 2) << m_sectorsPerClusterShift);
@ -185,10 +183,8 @@ class ExFatPartition {
bool fatPut(uint32_t cluster, uint32_t value);
uint32_t chainSize(uint32_t cluster);
bool freeChain(uint32_t cluster);
uint16_t sectorMask() const {return m_sectorMask;}
bool syncDevice() {
return m_blockDev->syncDevice();
}
uint16_t sectorMask() const { return m_sectorMask; }
bool syncDevice() { return m_blockDev->syncDevice(); }
bool cacheSafeRead(uint32_t sector, uint8_t* dst) {
return m_dataCache.cacheSafeRead(sector, dst);
}
@ -199,7 +195,7 @@ class ExFatPartition {
return m_dataCache.cacheSafeRead(sector, dst, count);
}
bool cacheSafeWrite(uint32_t sector, const uint8_t* src, size_t count) {
return m_dataCache.cacheSafeWrite(sector, src, count);
return m_dataCache.cacheSafeWrite(sector, src, count);
}
bool readSector(uint32_t sector, uint8_t* dst) {
return m_blockDev->readSector(sector, dst);
@ -208,14 +204,14 @@ class ExFatPartition {
return m_blockDev->writeSector(sector, src);
}
//----------------------------------------------------------------------------
static const uint8_t m_bytesPerSectorShift = 9;
static const uint8_t m_bytesPerSectorShift = 9;
static const uint16_t m_bytesPerSector = 1 << m_bytesPerSectorShift;
static const uint16_t m_sectorMask = m_bytesPerSector - 1;
//----------------------------------------------------------------------------
#if USE_EXFAT_BITMAP_CACHE
FsCache m_bitmapCache;
FsCache m_bitmapCache;
#endif // USE_EXFAT_BITMAP_CACHE
FsCache m_dataCache;
FsCache m_dataCache;
uint32_t m_bitmapStart;
uint32_t m_fatStartSector;
uint32_t m_fatLength;
@ -225,7 +221,7 @@ class ExFatPartition {
uint32_t m_clusterMask;
uint32_t m_bytesPerCluster;
FsBlockDevice* m_blockDev;
uint8_t m_fatType = 0;
uint8_t m_sectorsPerClusterShift;
uint8_t m_fatType = 0;
uint8_t m_sectorsPerClusterShift;
};
#endif // ExFatPartition_h

View file

@ -40,6 +40,6 @@ bool ExFatVolume::chdir(const char* path) {
m_vwd = dir;
return true;
fail:
fail:
return false;
}

View file

@ -60,8 +60,8 @@ class ExFatVolume : public ExFatPartition {
* \param[in] volStart Start sector of volume if part is zero.
* \return true for success or false for failure.
*/
bool begin(FsBlockDevice* dev, bool setCwv = true,
uint8_t part = 1, uint32_t volStart = 0) {
bool begin(FsBlockDevice* dev, bool setCwv = true, uint8_t part = 1,
uint32_t volStart = 0) {
if (!init(dev, part, volStart)) {
return false;
}
@ -89,7 +89,7 @@ class ExFatVolume : public ExFatPartition {
bool chdir(const char* path);
/** Change global working volume to this volume. */
void chvol() {m_cwv = this;}
void chvol() { m_cwv = this; }
/**
* Test for the existence of a file.
@ -117,9 +117,7 @@ class ExFatVolume : public ExFatPartition {
*
* \return true for success or false for failure.
*/
bool ls(print_t* pr, uint8_t flags = 0) {
return m_vwd.ls(pr, flags);
}
bool ls(print_t* pr, uint8_t flags = 0) { return m_vwd.ls(pr, flags); }
/** List the contents of a directory.
*
* \param[in] pr Print stream for list.
@ -223,10 +221,8 @@ class ExFatVolume : public ExFatPartition {
*
* \return true for success or false for failure.
*/
bool ls() {
return ls(&Serial);
}
/** List the directory contents of the volume root to Serial.
bool ls() { return ls(&Serial); }
/** List the directory contents of the volume root to Serial.
*
* \param[in] flags The inclusive OR of
*
@ -238,9 +234,7 @@ class ExFatVolume : public ExFatPartition {
*
* \return true for success or false for failure.
*/
bool ls(uint8_t flags) {
return ls(&Serial, flags);
}
bool ls(uint8_t flags) { return ls(&Serial, flags); }
/** List the directory contents of a directory to Serial.
*
* \param[in] path directory to list.
@ -265,18 +259,14 @@ class ExFatVolume : public ExFatPartition {
* \param[in] path Path for volume working directory.
* \return true for success or false for failure.
*/
bool chdir(const String& path) {
return chdir(path.c_str());
}
bool chdir(const String& path) { return chdir(path.c_str()); }
/** Test for the existence of a file in a directory
*
* \param[in] path Path of the file to be tested for.
*
* \return true if the file exists else false.
*/
bool exists(const String &path) {
return exists(path.c_str());
}
bool exists(const String& path) { return exists(path.c_str()); }
/** Make a subdirectory in the volume root directory.
*
* \param[in] path A path with a valid 8.3 DOS name for the subdirectory.
@ -285,7 +275,7 @@ class ExFatVolume : public ExFatPartition {
*
* \return true for success or false for failure.
*/
bool mkdir(const String &path, bool pFlag = true) {
bool mkdir(const String& path, bool pFlag = true) {
return mkdir(path.c_str(), pFlag);
}
/** open a file
@ -294,7 +284,7 @@ class ExFatVolume : public ExFatPartition {
* \param[in] oflag open oflag flags.
* \return a ExFile object.
*/
ExFile open(const String &path, oflag_t oflag = O_RDONLY) {
ExFile open(const String& path, oflag_t oflag = O_RDONLY) {
return open(path.c_str(), oflag);
}
/** Remove a file from the volume root directory.
@ -303,9 +293,7 @@ class ExFatVolume : public ExFatPartition {
*
* \return true for success or false for failure.
*/
bool remove(const String& path) {
return remove(path.c_str());
}
bool remove(const String& path) { return remove(path.c_str()); }
/** Rename a file or subdirectory.
*
* \param[in] oldPath Path name to the file or subdirectory to be renamed.
@ -331,9 +319,7 @@ class ExFatVolume : public ExFatPartition {
*
* \return true for success or false for failure.
*/
bool rmdir(const String& path) {
return rmdir(path.c_str());
}
bool rmdir(const String& path) { return rmdir(path.c_str()); }
/** Truncate a file to a specified length. The current file position
* will be at the new EOF.
*
@ -349,8 +335,8 @@ class ExFatVolume : public ExFatPartition {
private:
friend ExFatFile;
static ExFatVolume* cwv() {return m_cwv;}
ExFatFile* vwd() {return &m_vwd;}
static ExFatVolume* cwv() { return m_cwv; }
ExFatFile* vwd() { return &m_vwd; }
static ExFatVolume* m_cwv;
ExFatFile m_vwd;
};

View file

@ -27,11 +27,11 @@
//------------------------------------------------------------------------------
static uint16_t getLfnChar(DirLfn_t* ldir, uint8_t i) {
if (i < 5) {
return getLe16(ldir->unicode1 + 2*i);
return getLe16(ldir->unicode1 + 2 * i);
} else if (i < 11) {
return getLe16(ldir->unicode2 + 2*i - 10);
return getLe16(ldir->unicode2 + 2 * (i - 5));
} else if (i < 13) {
return getLe16(ldir->unicode3 + 2*i - 22);
return getLe16(ldir->unicode3 + 2 * (i - 11));
}
return 0;
}
@ -58,7 +58,7 @@ static void printHex(print_t* pr, uint8_t w, uint16_t h) {
static void printHex(print_t* pr, uint16_t val) {
bool space = true;
for (uint8_t i = 0; i < 4; i++) {
uint8_t h = (val >> (12 - 4*i)) & 15;
uint8_t h = (val >> (12 - 4 * i)) & 15;
if (h || i == 3) {
space = false;
}
@ -73,7 +73,7 @@ static void printHex(print_t* pr, uint16_t val) {
static void printHex(print_t* pr, uint32_t val) {
bool space = true;
for (uint8_t i = 0; i < 8; i++) {
uint8_t h = (val >> (28 - 4*i)) & 15;
uint8_t h = (val >> (28 - 4 * i)) & 15;
if (h || i == 7) {
space = false;
}
@ -85,7 +85,7 @@ static void printHex(print_t* pr, uint32_t val) {
}
}
//------------------------------------------------------------------------------
template<typename Uint>
template <typename Uint>
static void printHexLn(print_t* pr, Uint val) {
printHex(pr, val);
pr->println();
@ -111,8 +111,8 @@ static bool printFatDir(print_t* pr, DirFat_t* dir) {
printHexLn(pr, dir->attributes);
pr->print(F("caseFlags: 0X"));
printHexLn(pr, dir->caseFlags);
uint32_t fc = ((uint32_t)getLe16(dir->firstClusterHigh) << 16)
| getLe16(dir->firstClusterLow);
uint32_t fc = ((uint32_t)getLe16(dir->firstClusterHigh) << 16) |
getLe16(dir->firstClusterLow);
pr->print(F("firstCluster: "));
pr->println(fc, HEX);
pr->print(F("fileSize: "));
@ -175,7 +175,7 @@ void FatFile::dmpFile(print_t* pr, uint32_t pos, size_t n) {
}
pr->write(' ');
printHex(pr, 2, h);
text[i&15] = ' ' <= h && h < 0X7F ? h : '.';
text[i & 15] = ' ' <= h && h < 0X7F ? h : '.';
}
pr->write('\r');
pr->write('\n');
@ -215,7 +215,7 @@ void FatPartition::dmpSector(print_t* pr, uint32_t sector, uint8_t bits) {
return;
}
for (uint16_t i = 0; i < m_bytesPerSector;) {
if (i%32 == 0) {
if (i % 32 == 0) {
if (i) {
pr->println();
}
@ -243,7 +243,7 @@ void FatPartition::dmpFat(print_t* pr, uint32_t start, uint32_t count) {
}
pr->println(F("FAT:"));
uint32_t sector = m_fatStartSector + start;
uint32_t cluster = nf*start;
uint32_t cluster = nf * start;
for (uint32_t i = 0; i < count; i++) {
uint8_t* pc = fatCachePrepare(sector + i, FsCache::CACHE_FOR_READ);
if (!pc) {
@ -251,7 +251,7 @@ void FatPartition::dmpFat(print_t* pr, uint32_t start, uint32_t count) {
return;
}
for (size_t k = 0; k < nf; k++) {
if (0 == cluster%8) {
if (0 == cluster % 8) {
if (k) {
pr->println();
}
@ -259,7 +259,7 @@ void FatPartition::dmpFat(print_t* pr, uint32_t start, uint32_t count) {
}
cluster++;
pr->write(' ');
uint32_t v = fatType() == 32 ? getLe32(pc + 4*k) : getLe16(pc + 2*k);
uint32_t v = fatType() == 32 ? getLe32(pc + 4 * k) : getLe16(pc + 2 * k);
printHex(pr, v);
}
pr->println();

View file

@ -42,9 +42,9 @@ bool FatFile::addCluster() {
m_flags |= FILE_FLAG_DIR_DIRTY;
return true;
fail:
fail:
return false;
#else // USE_FAT_FILE_FLAG_CONTIGUOUS
#else // USE_FAT_FILE_FLAG_CONTIGUOUS
m_flags |= FILE_FLAG_DIR_DIRTY;
return m_vol->allocateCluster(m_curCluster, &m_curCluster);
#endif // USE_FAT_FILE_FLAG_CONTIGUOUS
@ -61,7 +61,7 @@ bool FatFile::addDirCluster() {
goto fail;
}
// max folder size
if (m_curPosition >= 512UL*4095) {
if (m_curPosition >= 512UL * 4095) {
DBG_FAIL_MACRO;
goto fail;
}
@ -82,7 +82,7 @@ bool FatFile::addDirCluster() {
m_curPosition += m_vol->bytesPerCluster();
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -105,7 +105,7 @@ bool FatFile::attrib(uint8_t bits) {
}
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -120,7 +120,7 @@ DirFat_t* FatFile::cacheDirEntry(uint8_t action) {
}
return dir + (m_dirIndex & 0XF);
fail:
fail:
return nullptr;
}
//------------------------------------------------------------------------------
@ -137,7 +137,7 @@ bool FatFile::contiguousRange(uint32_t* bgnSector, uint32_t* endSector) {
DBG_FAIL_MACRO;
goto fail;
}
for (uint32_t c = m_firstCluster; ; c++) {
for (uint32_t c = m_firstCluster;; c++) {
uint32_t next;
int8_t fg = m_vol->fatGet(c, &next);
if (fg < 0) {
@ -158,14 +158,14 @@ bool FatFile::contiguousRange(uint32_t* bgnSector, uint32_t* endSector) {
*bgnSector = m_vol->clusterStartSector(m_firstCluster);
}
if (endSector) {
*endSector = m_vol->clusterStartSector(c)
+ m_vol->sectorsPerCluster() - 1;
*endSector =
m_vol->clusterStartSector(c) + m_vol->sectorsPerCluster() - 1;
}
return true;
}
}
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -178,12 +178,12 @@ bool FatFile::createContiguous(const char* path, uint32_t size) {
return true;
}
close();
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
bool FatFile::createContiguous(FatFile* dirFile,
const char* path, uint32_t size) {
bool FatFile::createContiguous(FatFile* dirFile, const char* path,
uint32_t size) {
if (!open(dirFile, path, O_CREAT | O_EXCL | O_RDWR)) {
DBG_FAIL_MACRO;
goto fail;
@ -192,7 +192,7 @@ bool FatFile::createContiguous(FatFile* dirFile,
return true;
}
close();
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -213,7 +213,7 @@ bool FatFile::dirEntry(DirFat_t* dst) {
memcpy(dst, dir, sizeof(DirFat_t));
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -223,7 +223,7 @@ uint32_t FatFile::dirSize() {
return 0;
}
if (isRootFixed()) {
return FS_DIR_SIZE*m_vol->rootDirEntryCount();
return FS_DIR_SIZE * m_vol->rootDirEntryCount();
}
uint16_t n = 0;
uint32_t c = isRoot32() ? m_vol->rootDirStart() : m_firstCluster;
@ -234,7 +234,7 @@ uint32_t FatFile::dirSize() {
}
n += m_vol->sectorsPerCluster();
} while (fg);
return 512UL*n;
return 512UL * n;
}
//------------------------------------------------------------------------------
int FatFile::fgets(char* str, int num, char* delim) {
@ -288,7 +288,7 @@ bool FatFile::getAccessDate(uint16_t* pdate) {
*pdate = getLe16(dir.accessDate);
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -302,7 +302,7 @@ bool FatFile::getCreateDateTime(uint16_t* pdate, uint16_t* ptime) {
*ptime = getLe16(dir.createTime);
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -316,13 +316,11 @@ bool FatFile::getModifyDateTime(uint16_t* pdate, uint16_t* ptime) {
*ptime = getLe16(dir.modifyTime);
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
bool FatFile::isBusy() {
return m_vol->isBusy();
}
bool FatFile::isBusy() { return m_vol->isBusy(); }
//------------------------------------------------------------------------------
bool FatFile::mkdir(FatFile* parent, const char* path, bool pFlag) {
FatName_t fname;
@ -362,7 +360,7 @@ bool FatFile::mkdir(FatFile* parent, const char* path, bool pFlag) {
}
return mkdir(parent, &fname);
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -433,7 +431,7 @@ bool FatFile::mkdir(FatFile* parent, FatName_t* fname) {
// write first sector
return m_vol->cacheSync();
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -485,7 +483,7 @@ bool FatFile::open(FatFile* dirFile, const char* path, oflag_t oflag) {
}
return open(dirFile, &fname, oflag);
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -509,7 +507,7 @@ bool FatFile::open(FatFile* dirFile, uint16_t index, oflag_t oflag) {
break;
}
if (ldir->order & FAT_ORDER_LAST_LONG_ENTRY) {
if (!dirFile->seekSet(32UL*(index - i))) {
if (!dirFile->seekSet(32UL * (index - i))) {
DBG_FAIL_MACRO;
goto fail;
}
@ -530,7 +528,7 @@ bool FatFile::open(FatFile* dirFile, uint16_t index, oflag_t oflag) {
}
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -591,8 +589,8 @@ bool FatFile::openCachedEntry(FatFile* dirFile, uint16_t dirIndex,
m_dirSector = m_vol->cacheSectorNumber();
// copy first cluster number for directory fields
firstCluster = ((uint32_t)getLe16(dir->firstClusterHigh) << 16)
| getLe16(dir->firstClusterLow);
firstCluster = ((uint32_t)getLe16(dir->firstClusterHigh) << 16) |
getLe16(dir->firstClusterLow);
if (oflag & O_TRUNC) {
if (firstCluster && !m_vol->freeChain(firstCluster)) {
@ -611,7 +609,7 @@ bool FatFile::openCachedEntry(FatFile* dirFile, uint16_t dirIndex,
}
return true;
fail:
fail:
m_attributes = FILE_ATTR_CLOSED;
m_flags = 0;
return false;
@ -638,7 +636,7 @@ bool FatFile::openCwd() {
rewind();
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -655,7 +653,7 @@ bool FatFile::openNext(FatFile* dirFile, oflag_t oflag) {
}
while (1) {
// read entry into cache
index = dirFile->curPosition()/FS_DIR_SIZE;
index = dirFile->curPosition() / FS_DIR_SIZE;
DirFat_t* dir = dirFile->readDirCache();
if (!dir) {
if (dirFile->getError()) {
@ -691,7 +689,7 @@ bool FatFile::openNext(FatFile* dirFile, oflag_t oflag) {
}
}
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -706,34 +704,34 @@ bool FatFile::openRoot(FatVolume* vol) {
m_vol = vol;
switch (vol->fatType()) {
#if FAT12_SUPPORT
case 12:
case 12:
#endif // FAT12_SUPPORT
case 16:
m_attributes = FILE_ATTR_ROOT_FIXED;
break;
case 16:
m_attributes = FILE_ATTR_ROOT_FIXED;
break;
case 32:
m_attributes = FILE_ATTR_ROOT32;
break;
case 32:
m_attributes = FILE_ATTR_ROOT32;
break;
default:
DBG_FAIL_MACRO;
goto fail;
default:
DBG_FAIL_MACRO;
goto fail;
}
// read only
m_flags = FILE_FLAG_READ;
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
int FatFile::peek() {
uint32_t curPosition = m_curPosition;
uint32_t curCluster = m_curCluster;
uint32_t saveCurPosition = m_curPosition;
uint32_t saveCurCluster = m_curCluster;
int c = read();
m_curPosition = curPosition;
m_curCluster = curCluster;
m_curPosition = saveCurPosition;
m_curCluster = saveCurCluster;
return c;
}
//------------------------------------------------------------------------------
@ -754,13 +752,13 @@ bool FatFile::preAllocate(uint32_t length) {
#if USE_FAT_FILE_FLAG_CONTIGUOUS
// Mark contiguous and insure sync() will update dir entry
m_flags |= FILE_FLAG_PREALLOCATE | FILE_FLAG_CONTIGUOUS | FILE_FLAG_DIR_DIRTY;
#else // USE_FAT_FILE_FLAG_CONTIGUOUS
#else // USE_FAT_FILE_FLAG_CONTIGUOUS
// insure sync() will update dir entry
m_flags |= FILE_FLAG_DIR_DIRTY;
#endif // USE_FAT_FILE_FLAG_CONTIGUOUS
return sync();
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -785,7 +783,7 @@ int FatFile::read(void* buf, size_t nbyte) {
}
} else if (isRootFixed()) {
uint16_t tmp16 =
FS_DIR_SIZE*m_vol->m_rootDirEntryCount - (uint16_t)m_curPosition;
FS_DIR_SIZE * m_vol->m_rootDirEntryCount - (uint16_t)m_curPosition;
if (nbyte > tmp16) {
nbyte = tmp16;
}
@ -795,8 +793,8 @@ int FatFile::read(void* buf, size_t nbyte) {
size_t n;
offset = m_curPosition & m_vol->sectorMask(); // offset in sector
if (isRootFixed()) {
sector = m_vol->rootDirStart()
+ (m_curPosition >> m_vol->bytesPerSectorShift());
sector = m_vol->rootDirStart() +
(m_curPosition >> m_vol->bytesPerSectorShift());
} else {
sectorOfCluster = m_vol->sectorOfCluster(m_curPosition);
if (offset == 0 && sectorOfCluster == 0) {
@ -826,8 +824,8 @@ int FatFile::read(void* buf, size_t nbyte) {
}
sector = m_vol->clusterStartSector(m_curCluster) + sectorOfCluster;
}
if (offset != 0 || toRead < m_vol->bytesPerSector()
|| sector == m_vol->cacheSectorNumber()) {
if (offset != 0 || toRead < m_vol->bytesPerSector() ||
sector == m_vol->cacheSectorNumber()) {
// amount to be read from current sector
n = m_vol->bytesPerSector() - offset;
if (n > toRead) {
@ -842,7 +840,7 @@ int FatFile::read(void* buf, size_t nbyte) {
uint8_t* src = pc + offset;
memcpy(dst, src, n);
#if USE_MULTI_SECTOR_IO
} else if (toRead >= 2*m_vol->bytesPerSector()) {
} else if (toRead >= 2 * m_vol->bytesPerSector()) {
uint32_t ns = toRead >> m_vol->bytesPerSectorShift();
if (!isRootFixed()) {
uint32_t mb = m_vol->sectorsPerCluster() - sectorOfCluster;
@ -870,20 +868,19 @@ int FatFile::read(void* buf, size_t nbyte) {
}
return nbyte - toRead;
fail:
fail:
m_error |= READ_ERROR;
return -1;
}
//------------------------------------------------------------------------------
int8_t FatFile::readDir(DirFat_t* dir) {
int16_t n;
// if not a directory file or miss-positioned return an error
if (!isDir() || (0X1F & m_curPosition)) {
return -1;
}
while (1) {
n = read(dir, sizeof(DirFat_t));
int16_t n = read(dir, sizeof(DirFat_t));
if (n != sizeof(DirFat_t)) {
return n == 0 ? 0 : -1;
}
@ -910,7 +907,7 @@ DirFat_t* FatFile::readDirCache(bool skipReadOk) {
if (i == 0 || !skipReadOk) {
int8_t n = read(&n, 1);
if (n != 1) {
if (n != 1) {
if (n != 0) {
DBG_FAIL_MACRO;
}
@ -923,7 +920,7 @@ DirFat_t* FatFile::readDirCache(bool skipReadOk) {
// return pointer to entry
return reinterpret_cast<DirFat_t*>(m_vol->cacheAddress()) + i;
fail:
fail:
return nullptr;
}
//------------------------------------------------------------------------------
@ -935,7 +932,7 @@ bool FatFile::remove(const char* path) {
}
return file.remove();
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -1031,7 +1028,7 @@ bool FatFile::rename(FatFile* dirFile, const char* newPath) {
}
// store new dot dot
sector = m_vol->clusterStartSector(m_firstCluster);
uint8_t* pc = m_vol->dataCachePrepare(sector, FsCache::CACHE_FOR_WRITE);
pc = m_vol->dataCachePrepare(sector, FsCache::CACHE_FOR_WRITE);
dir = reinterpret_cast<DirFat_t*>(pc);
if (!dir) {
DBG_FAIL_MACRO;
@ -1049,7 +1046,7 @@ bool FatFile::rename(FatFile* dirFile, const char* newPath) {
}
return m_vol->cacheSync();
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -1091,7 +1088,7 @@ bool FatFile::rmdir() {
m_flags |= FILE_FLAG_WRITE;
return remove();
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -1105,7 +1102,7 @@ bool FatFile::rmRfStar() {
rewind();
while (1) {
// remember position
index = m_curPosition/FS_DIR_SIZE;
index = m_curPosition / FS_DIR_SIZE;
DirFat_t* dir = readDirCache();
if (!dir) {
@ -1150,8 +1147,8 @@ bool FatFile::rmRfStar() {
}
}
// position to next entry if required
if (m_curPosition != (32UL*(index + 1))) {
if (!seekSet(32UL*(index + 1))) {
if (m_curPosition != (32UL * (index + 1))) {
if (!seekSet(32UL * (index + 1))) {
DBG_FAIL_MACRO;
goto fail;
}
@ -1166,7 +1163,7 @@ bool FatFile::rmRfStar() {
}
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -1194,7 +1191,7 @@ bool FatFile::seekSet(uint32_t pos) {
goto fail;
}
} else if (isRootFixed()) {
if (pos <= FS_DIR_SIZE*m_vol->rootDirEntryCount()) {
if (pos <= FS_DIR_SIZE * m_vol->rootDirEntryCount()) {
goto done;
}
DBG_FAIL_MACRO;
@ -1225,12 +1222,12 @@ bool FatFile::seekSet(uint32_t pos) {
}
}
done:
done:
m_curPosition = pos;
m_flags &= ~FILE_FLAG_PREALLOCATE;
return true;
fail:
fail:
m_curCluster = tmp;
return false;
}
@ -1272,27 +1269,20 @@ bool FatFile::sync() {
}
DBG_FAIL_MACRO;
fail:
fail:
m_error |= WRITE_ERROR;
return false;
}
//------------------------------------------------------------------------------
bool FatFile::timestamp(uint8_t flags, uint16_t year, uint8_t month,
uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) {
uint8_t day, uint8_t hour, uint8_t minute,
uint8_t second) {
uint16_t dirDate;
uint16_t dirTime;
DirFat_t* dir;
if (!isFile()
|| year < 1980
|| year > 2107
|| month < 1
|| month > 12
|| day < 1
|| day > 31
|| hour > 23
|| minute > 59
|| second > 59) {
if (!isFile() || year < 1980 || year > 2107 || month < 1 || month > 12 ||
day < 1 || day > 31 || hour > 23 || minute > 59 || second > 59) {
DBG_FAIL_MACRO;
goto fail;
}
@ -1323,7 +1313,7 @@ bool FatFile::timestamp(uint8_t flags, uint16_t year, uint8_t month,
}
return m_vol->cacheSync();
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -1335,7 +1325,7 @@ bool FatFile::truncate() {
goto fail;
}
if (m_firstCluster == 0) {
return true;
return true;
}
if (m_curCluster) {
toFree = 0;
@ -1367,7 +1357,7 @@ bool FatFile::truncate() {
m_flags |= FILE_FLAG_DIR_DIRTY;
return sync();
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -1414,7 +1404,7 @@ size_t FatFile::write(const void* buf, size_t nbyte) {
goto fail;
}
}
#else // USE_FAT_FILE_FLAG_CONTIGUOUS
#else // USE_FAT_FILE_FLAG_CONTIGUOUS
int8_t fg = m_vol->fatGet(m_curCluster, &m_curCluster);
if (fg < 0) {
DBG_FAIL_MACRO;
@ -1442,8 +1432,7 @@ size_t FatFile::write(const void* buf, size_t nbyte) {
}
}
// sector for data write
uint32_t sector = m_vol->clusterStartSector(m_curCluster)
+ sectorOfCluster;
uint32_t sector = m_vol->clusterStartSector(m_curCluster) + sectorOfCluster;
if (sectorOffset != 0 || nToWrite < m_vol->bytesPerSector()) {
// partial sector - must use cache
@ -1455,7 +1444,7 @@ size_t FatFile::write(const void* buf, size_t nbyte) {
}
if (sectorOffset == 0 &&
(m_curPosition >= m_fileSize || m_flags & FILE_FLAG_PREALLOCATE)) {
(m_curPosition >= m_fileSize || m_flags & FILE_FLAG_PREALLOCATE)) {
// start of new sector don't need to read into cache
cacheOption = FsCache::CACHE_RESERVE_FOR_WRITE;
} else {
@ -1477,7 +1466,7 @@ size_t FatFile::write(const void* buf, size_t nbyte) {
}
}
#if USE_MULTI_SECTOR_IO
} else if (nToWrite >= 2*m_vol->bytesPerSector()) {
} else if (nToWrite >= 2 * m_vol->bytesPerSector()) {
// use multiple sector write command
uint32_t maxSectors = m_vol->sectorsPerCluster() - sectorOfCluster;
uint32_t nSector = nToWrite >> m_vol->bytesPerSectorShift();
@ -1512,7 +1501,7 @@ size_t FatFile::write(const void* buf, size_t nbyte) {
}
return nbyte;
fail:
fail:
// return for write error
m_error |= WRITE_ERROR;
return 0;

View file

@ -28,9 +28,10 @@
* \file
* \brief FatFile class
*/
#include <string.h>
#include <stddef.h>
#include <limits.h>
#include <stddef.h>
#include <string.h>
#include "../common/FmtNumber.h"
#include "../common/FsApiConstants.h"
#include "../common/FsDateTime.h"
@ -38,28 +39,6 @@
#include "FatPartition.h"
class FatVolume;
//------------------------------------------------------------------------------
// Stuff to store strings in AVR flash.
#ifdef __AVR__
#include <avr/pgmspace.h>
#else // __AVR__
#ifndef PSTR
/** store literal string in flash for ARM */
#define PSTR(x) (x)
#endif // PSTR
#ifndef pgm_read_byte
/** read 8-bits from flash for ARM */
#define pgm_read_byte(addr) (*(const unsigned char*)(addr))
#endif // pgm_read_byte
#ifndef pgm_read_word
/** read 16-bits from flash for ARM */
#define pgm_read_word(addr) (*(const uint16_t*)(addr))
#endif // pgm_read_word
#ifndef PROGMEM
/** store in flash for ARM */
#define PROGMEM
#endif // PROGMEM
#endif // __AVR__
//------------------------------------------------------------------------------
/**
* \struct FatPos_t
* \brief Internal type for file position - do not use in user apps.
@ -105,7 +84,7 @@ class FatSfn_t {
#if USE_LONG_FILE_NAMES
/** Internal class for file names */
typedef FatLfn_t FatName_t;
#else // USE_LONG_FILE_NAMES
#else // USE_LONG_FILE_NAMES
/** Internal class for file names */
typedef FatSfn_t FatName_t;
#endif // USE_LONG_FILE_NAMES
@ -116,14 +95,11 @@ const uint8_t FNAME_FLAG_LOST_CHARS = 0X01;
const uint8_t FNAME_FLAG_MIXED_CASE = 0X02;
/** LFN entries are required for file name. */
const uint8_t FNAME_FLAG_NEED_LFN =
FNAME_FLAG_LOST_CHARS | FNAME_FLAG_MIXED_CASE;
FNAME_FLAG_LOST_CHARS | FNAME_FLAG_MIXED_CASE;
/** Filename base-name is all lower case */
const uint8_t FNAME_FLAG_LC_BASE = FAT_CASE_LC_BASE;
/** Filename extension is all lower case. */
const uint8_t FNAME_FLAG_LC_EXT = FAT_CASE_LC_EXT;
#if FNAME_FLAG_NEED_LFN & (FAT_CASE_LC_BASE || FAT_CASE_LC_EXT)
#error FNAME_FLAG_NEED_LFN & (FAT_CASE_LC_BASE || FAT_CASE_LC_EXT)
#endif // FNAME_FLAG_NEED_LFN & (FAT_CASE_LC_BASE || FAT_CASE_LC_EXT)
//==============================================================================
/**
* \class FatFile
@ -140,9 +116,7 @@ class FatFile {
* \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).
*/
FatFile(const char* path, oflag_t oflag) {
open(path, oflag);
}
FatFile(const char* path, oflag_t oflag) { open(path, oflag); }
#if DESTRUCTOR_CLOSES_FILE
/** Destructor */
~FatFile() {
@ -155,7 +129,7 @@ class FatFile {
*
* \return true if a file is open.
*/
operator bool() const {return isOpen();}
operator bool() const { return isOpen(); }
/**
* \return user settable file attributes for success else -1.
*/
@ -190,13 +164,9 @@ class FatFile {
return isFile() ? fileSize() - curPosition() : 0;
}
/** Clear all error bits. */
void clearError() {
m_error = 0;
}
void clearError() { m_error = 0; }
/** Set writeError to zero */
void clearWriteError() {
m_error &= ~WRITE_ERROR;
}
void clearWriteError() { m_error &= ~WRITE_ERROR; }
/** Close a file and force cached data and directory information
* to be written to the storage device.
*
@ -221,8 +191,7 @@ class FatFile {
*
* \return true for success or false for failure.
*/
bool createContiguous(FatFile* dirFile,
const char* path, uint32_t size);
bool createContiguous(FatFile* dirFile, const char* path, uint32_t size);
/** Create and open a new contiguous file of a specified size.
*
* \param[in] path A path with a valid file name.
@ -232,10 +201,10 @@ class FatFile {
*/
bool createContiguous(const char* path, uint32_t size);
/** \return The current cluster number for a file or directory. */
uint32_t curCluster() const {return m_curCluster;}
uint32_t curCluster() const { return m_curCluster; }
/** \return The current position for a file or directory. */
uint32_t curPosition() const {return m_curPosition;}
uint32_t curPosition() const { return m_curPosition; }
/** Return a file's directory entry.
*
* \param[out] dir Location for return of the file's directory entry.
@ -244,7 +213,7 @@ class FatFile {
*/
bool dirEntry(DirFat_t* dir);
/** \return Directory entry index. */
uint16_t dirIndex() const {return m_dirIndex;}
uint16_t dirIndex() const { return m_dirIndex; }
/** \return The number of bytes allocated to a directory or zero
* if an error occurs.
*/
@ -297,13 +266,13 @@ class FatFile {
*/
int fgets(char* str, int num, char* delim = nullptr);
/** \return The total number of bytes in a file. */
uint32_t fileSize() const {return m_fileSize;}
uint32_t fileSize() const { return m_fileSize; }
/** \return first sector of file or zero for empty file. */
uint32_t firstBlock() const {return firstSector();}
uint32_t firstBlock() const { return firstSector(); }
/** \return Address of first sector or zero for empty file. */
uint32_t firstSector() const;
/** Arduino name for sync() */
void flush() {sync();}
void flush() { sync(); }
/** set position for streams
* \param[in] pos struct with value for new position
*/
@ -340,7 +309,7 @@ class FatFile {
*/
bool getCreateDateTime(uint16_t* pdate, uint16_t* ptime);
/** \return All error bits. */
uint8_t getError() const {return m_error;}
uint8_t getError() const { return m_error; }
/** Get a file's modify date and time.
*
* \param[out] pdate Packed date for directory entry.
@ -388,9 +357,7 @@ class FatFile {
*/
size_t getSFN(char* name, size_t size);
/** \return value of writeError */
bool getWriteError() const {
return isOpen() ? m_error & WRITE_ERROR : true;
}
bool getWriteError() const { return isOpen() ? m_error & WRITE_ERROR : true; }
/**
* Check for device busy.
*
@ -398,37 +365,37 @@ class FatFile {
*/
bool isBusy();
#if USE_FAT_FILE_FLAG_CONTIGUOUS
/** \return True if the file is contiguous. */
bool isContiguous() const {return m_flags & FILE_FLAG_CONTIGUOUS;}
/** \return True if the file is contiguous. */
bool isContiguous() const { return m_flags & FILE_FLAG_CONTIGUOUS; }
#endif // USE_FAT_FILE_FLAG_CONTIGUOUS
/** \return True if this is a directory. */
bool isDir() const {return m_attributes & FILE_ATTR_DIR;}
bool isDir() const { return m_attributes & FILE_ATTR_DIR; }
/** \return True if this is a normal file. */
bool isFile() const {return m_attributes & FILE_ATTR_FILE;}
bool isFile() const { return m_attributes & FILE_ATTR_FILE; }
/** \return True if this is a normal file or sub-directory. */
bool isFileOrSubDir() const {return isFile() || isSubDir();}
bool isFileOrSubDir() const { return isFile() || isSubDir(); }
/** \return True if this is a hidden file. */
bool isHidden() const {return m_attributes & FS_ATTRIB_HIDDEN;}
bool isHidden() const { return m_attributes & FS_ATTRIB_HIDDEN; }
/** \return true if this file has a Long File Name. */
bool isLFN() const {return m_lfnOrd;}
bool isLFN() const { return m_lfnOrd; }
/** \return True if this is an open file/directory. */
bool isOpen() const {return m_attributes;}
bool isOpen() const { return m_attributes; }
/** \return True file is readable. */
bool isReadable() const {return m_flags & FILE_FLAG_READ;}
bool isReadable() const { return m_flags & FILE_FLAG_READ; }
/** \return True if file is read-only */
bool isReadOnly() const {return m_attributes & FS_ATTRIB_READ_ONLY;}
bool isReadOnly() const { return m_attributes & FS_ATTRIB_READ_ONLY; }
/** \return True if this is the root directory. */
bool isRoot() const {return m_attributes & FILE_ATTR_ROOT;}
bool isRoot() const { return m_attributes & FILE_ATTR_ROOT; }
/** \return True if this is the FAT32 root directory. */
bool isRoot32() const {return m_attributes & FILE_ATTR_ROOT32;}
bool isRoot32() const { return m_attributes & FILE_ATTR_ROOT32; }
/** \return True if this is the FAT12 of FAT16 root directory. */
bool isRootFixed() const {return m_attributes & FILE_ATTR_ROOT_FIXED;}
bool isRootFixed() const { return m_attributes & FILE_ATTR_ROOT_FIXED; }
/** \return True if this is a sub-directory. */
bool isSubDir() const {return m_attributes & FILE_ATTR_SUBDIR;}
bool isSubDir() const { return m_attributes & FILE_ATTR_SUBDIR; }
/** \return True if this is a system file. */
bool isSystem() const {return m_attributes & FS_ATTRIB_SYSTEM;}
bool isSystem() const { return m_attributes & FS_ATTRIB_SYSTEM; }
/** \return True file is writable. */
bool isWritable() const {return m_flags & FILE_FLAG_WRITE;}
bool isWritable() const { return m_flags & FILE_FLAG_WRITE; }
/** List directory contents.
*
* \param[in] pr Print stream for list.
@ -553,7 +520,7 @@ class FatFile {
* \return true for success or false for failure.
*/
bool open(const char* path, oflag_t oflag = O_RDONLY);
/** Open the current working directory.
/** Open the current working directory.
*
* \return true for success or false for failure.
*/
@ -615,9 +582,7 @@ class FatFile {
*
* \return The number of characters printed.
*/
size_t printAccessDateTime(print_t* pr) {
return printAccessDate(pr);
}
size_t printAccessDateTime(print_t* pr) { return printAccessDate(pr); }
/** Print a file's creation date and time
*
* \param[in] pr Print stream for output.
@ -676,7 +641,7 @@ class FatFile {
template <typename Type>
size_t printField(Type value, char term) {
char sign = 0;
char buf[3*sizeof(Type) + 3];
char buf[3 * sizeof(Type) + 3];
char* str = buf + sizeof(buf);
if (term) {
@ -819,9 +784,7 @@ class FatFile {
*/
bool rename(FatFile* dirFile, const char* newPath);
/** Set the file's current position to zero. */
void rewind() {
seekSet(0);
}
void rewind() { seekSet(0); }
/** Remove a directory file.
*
* The directory file will be removed only if it is empty and is not the
@ -854,9 +817,7 @@ class FatFile {
* \param[in] offset The new position in bytes from the current position.
* \return true for success or false for failure.
*/
bool seekCur(int32_t offset) {
return seekSet(m_curPosition + offset);
}
bool seekCur(int32_t offset) { return seekSet(m_curPosition + offset); }
/** Set the files position to end-of-file + \a offset. See seekSet().
* Can't be used for directory files since file size is not defined.
* \param[in] offset The new position in bytes from end-of-file.
@ -927,24 +888,18 @@ class FatFile {
*
* \return true for success or false for failure.
*/
bool truncate(uint32_t length) {
return seekSet(length) && truncate();
}
bool truncate(uint32_t length) { return seekSet(length) && truncate(); }
/** Write a string to a file. Used by the Arduino Print class.
* \param[in] str Pointer to the string.
* Use getWriteError to check for errors.
* \return count of characters written for success or -1 for failure.
*/
size_t write(const char* str) {
return write(str, strlen(str));
}
size_t write(const char* str) { return write(str, strlen(str)); }
/** Write a single byte.
* \param[in] b The byte to be written.
* \return +1 for success or -1 for failure.
*/
size_t write(uint8_t b) {
return write(&b, 1);
}
size_t write(uint8_t b) { return write(&b, 1); }
/** Write data to an open file.
*
* \note Data is moved to the cache but may not be written to the
@ -973,16 +928,12 @@ class FatFile {
*
* \return true for success or false for failure.
*/
bool ls(uint8_t flags = 0) {
return ls(&Serial, flags);
}
bool ls(uint8_t flags = 0) { return ls(&Serial, flags); }
/** Print a file's name.
*
* \return length for success or zero for failure.
*/
size_t printName() {
return FatFile::printName(&Serial);
}
size_t printName() { return FatFile::printName(&Serial); }
#endif // ENABLE_ARDUINO_SERIAL
private:
@ -1000,8 +951,7 @@ class FatFile {
/** A FAT32 root directory */
static const uint8_t FILE_ATTR_ROOT32 = 0X80;
/** Entry is for root. */
static const uint8_t FILE_ATTR_ROOT =
FILE_ATTR_ROOT_FIXED | FILE_ATTR_ROOT32;
static const uint8_t FILE_ATTR_ROOT = FILE_ATTR_ROOT_FIXED | FILE_ATTR_ROOT32;
/** Directory type bits */
static const uint8_t FILE_ATTR_DIR = FILE_ATTR_SUBDIR | FILE_ATTR_ROOT;
@ -1010,16 +960,16 @@ class FatFile {
bool addCluster();
bool addDirCluster();
DirFat_t* cacheDir(uint16_t index) {
return seekSet(32UL*index) ? readDirCache() : nullptr;
return seekSet(32UL * index) ? readDirCache() : nullptr;
}
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);
uint8_t lfnChecksum(uint8_t* name) {
uint8_t lfnChecksum(const uint8_t* name) {
uint8_t sum = 0;
for (uint8_t i = 0; i < 11; i++) {
sum = (((sum & 1) << 7) | (sum >> 1)) + name[i];
sum = (((sum & 1) << 7) | (sum >> 1)) + name[i];
}
return sum;
}
@ -1043,26 +993,26 @@ class FatFile {
// treat curPosition as valid length.
static const uint8_t FILE_FLAG_PREALLOCATE = 0X20;
// file is contiguous
static const uint8_t FILE_FLAG_CONTIGUOUS = 0X40;
static const uint8_t FILE_FLAG_CONTIGUOUS = 0X40;
// sync of directory entry required
static const uint8_t FILE_FLAG_DIR_DIRTY = 0X80;
// private data
static const uint8_t WRITE_ERROR = 0X1;
static const uint8_t READ_ERROR = 0X2;
static const uint8_t READ_ERROR = 0X2;
uint8_t m_attributes = FILE_ATTR_CLOSED;
uint8_t m_error = 0; // Error bits.
uint8_t m_flags = 0; // See above for definition of m_flags bits
uint8_t m_lfnOrd;
uint16_t m_dirIndex; // index of directory entry in dir file
FatVolume* m_vol; // volume where file is located
uint32_t m_dirCluster;
uint32_t m_curCluster; // cluster for current file position
uint32_t m_curPosition; // current file position
uint32_t m_dirSector; // sector for this files directory entry
uint32_t m_fileSize; // file size in bytes
uint32_t m_firstCluster; // first cluster of file
uint8_t m_attributes = FILE_ATTR_CLOSED;
uint8_t m_error = 0; // Error bits.
uint8_t m_flags = 0; // See above for definition of m_flags bits
uint8_t m_lfnOrd;
uint16_t m_dirIndex; // index of directory entry in dir file
FatVolume* m_vol; // volume where file is located
uint32_t m_dirCluster;
uint32_t m_curCluster; // cluster for current file position
uint32_t m_curPosition; // current file position
uint32_t m_dirSector; // sector for this files directory entry
uint32_t m_fileSize; // file size in bytes
uint32_t m_firstCluster; // first cluster of file
};
#include "../common/ArduinoFiles.h"
@ -1072,7 +1022,7 @@ class FatFile {
*/
class File32 : public StreamFile<FatFile, uint32_t> {
public:
/** Opens the next file or folder in a directory.
/** Opens the next file or folder in a directory.
*
* \param[in] oflag open flags.
* \return a FatStream object.

View file

@ -24,23 +24,17 @@
*/
#define DBG_FILE "FatFileLFN.cpp"
#include "../common/DebugMacros.h"
#include "../common/upcase.h"
#include "../common/FsUtf.h"
#include "../common/upcase.h"
#include "FatLib.h"
#if USE_LONG_FILE_NAMES
//------------------------------------------------------------------------------
static bool isLower(char c) {
return 'a' <= c && c <= 'z';
}
static bool isLower(char c) { return 'a' <= c && c <= 'z'; }
//------------------------------------------------------------------------------
static bool isUpper(char c) {
return 'A' <= c && c <= 'Z';
}
static bool isUpper(char c) { return 'A' <= c && c <= 'Z'; }
//------------------------------------------------------------------------------
// A bit smaller than toupper in AVR 328.
inline char toUpper(char c) {
return isLower(c) ? c - 'a' + 'A' : c;
}
inline char toUpper(char c) { return isLower(c) ? c - 'a' + 'A' : c; }
//------------------------------------------------------------------------------
/**
* Store a 16-bit long file name character.
@ -51,24 +45,13 @@ inline char toUpper(char c) {
*/
static void putLfnChar(DirLfn_t* ldir, uint8_t i, uint16_t c) {
if (i < 5) {
setLe16(ldir->unicode1 + 2*i, c);
setLe16(ldir->unicode1 + 2 * i, c);
} else if (i < 11) {
setLe16(ldir->unicode2 + 2*i -10, c);
setLe16(ldir->unicode2 + 2 * (i - 5), c);
} else if (i < 13) {
setLe16(ldir->unicode3 + 2*i - 22, c);
setLe16(ldir->unicode3 + 2 * (i - 11), c);
}
}
//------------------------------------------------------------------------------
// Daniel Bernstein University of Illinois at Chicago.
// Original had + instead of ^
__attribute__((unused))
static uint16_t Bernstein(const char* bgn, const char* end, uint16_t hash) {
while (bgn < end) {
// hash = hash * 33 ^ str[i];
hash = ((hash << 5) + hash) ^ (*bgn++);
}
return hash;
}
//==============================================================================
bool FatFile::cmpName(uint16_t index, FatLfn_t* fname, uint8_t lfnOrd) {
FatFile dir = *this;
@ -95,7 +78,7 @@ bool FatFile::cmpName(uint16_t index, FatLfn_t* fname, uint8_t lfnOrd) {
if (toUpcase(u) != toUpcase(cp)) {
return false;
}
#else // USE_UTF8_LONG_NAMES
#else // USE_UTF8_LONG_NAMES
if (u > 0X7F || toUpper(u) != toUpper(fname->getch())) {
return false;
}
@ -104,7 +87,7 @@ bool FatFile::cmpName(uint16_t index, FatLfn_t* fname, uint8_t lfnOrd) {
}
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -141,13 +124,13 @@ bool FatFile::createLFN(uint16_t index, FatLfn_t* fname, uint8_t lfnOrd) {
}
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
bool FatFile::makeSFN(FatLfn_t* fname) {
bool is83;
// char c;
// char c;
uint8_t c;
uint8_t bit = FAT_CASE_LC_BASE;
uint8_t lc = 0;
@ -170,15 +153,17 @@ bool FatFile::makeSFN(FatLfn_t* fname) {
// Not 8.3 if starts with dot.
is83 = *ptr == '.' ? false : true;
// Skip leading dots.
for (; *ptr == '.'; ptr++) {}
for (; *ptr == '.'; ptr++) {
}
// Find last dot.
for (dot = end - 1; dot > ptr && *dot != '.'; dot--) {}
for (dot = end - 1; dot > ptr && *dot != '.'; dot--) {
}
for (; ptr < end; ptr++) {
c = *ptr;
if (c == '.' && ptr == dot) {
in = 10; // Max index for full 8.3 name.
i = 8; // Place for extension.
in = 10; // Max index for full 8.3 name.
i = 8; // Place for extension.
bit = FAT_CASE_LC_EXT; // bit for extension.
} else {
if (sfnReservedChar(c)) {
@ -192,7 +177,7 @@ bool FatFile::makeSFN(FatLfn_t* fname) {
if (i > in) {
is83 = false;
if (in == 10 || ptr > dot) {
// Done - extension longer than three characters or no extension.
// Done - extension longer than three characters or no extension.
break;
}
// Skip to dot.
@ -216,7 +201,7 @@ bool FatFile::makeSFN(FatLfn_t* fname) {
goto fail;
}
if (is83) {
fname->flags = lc & uc ? FNAME_FLAG_MIXED_CASE : lc;
fname->flags = (lc & uc) ? FNAME_FLAG_MIXED_CASE : lc;
} else {
fname->flags = FNAME_FLAG_LOST_CHARS;
fname->sfn[fname->seqPos] = '~';
@ -224,7 +209,7 @@ bool FatFile::makeSFN(FatLfn_t* fname) {
}
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -238,17 +223,13 @@ bool FatFile::makeUniqueSfn(FatLfn_t* fname) {
DBG_HALT_IF(fname->sfn[pos] != '~' && fname->sfn[pos + 1] != '1');
for (uint8_t seq = FIRST_HASH_SEQ; seq < 100; seq++) {
DBG_WARN_IF(seq > FIRST_HASH_SEQ);
#ifdef USE_LFN_HASH
hex = Bernstein(fname->begin, fname->end, seq);
#else
DBG_WARN_IF(seq > FIRST_HASH_SEQ);
hex += millis();
#endif
if (pos > 3) {
// Make space in name for ~HHHH.
pos = 3;
}
for (uint8_t i = pos + 4 ; i > pos; i--) {
for (uint8_t i = pos + 4; i > pos; i--) {
uint8_t h = hex & 0XF;
fname->sfn[i] = h < 10 ? h + '0' : h + 'A' - 10;
hex >>= 4;
@ -277,25 +258,26 @@ bool FatFile::makeUniqueSfn(FatLfn_t* fname) {
// fall inti fail - too many tries.
DBG_FAIL_MACRO;
fail:
fail:
return false;
done:
done:
return true;
}
//------------------------------------------------------------------------------
bool FatFile::open(FatFile* dirFile, FatLfn_t* fname, oflag_t oflag) {
bool fnameFound = false;
uint8_t lfnOrd = 0;
uint8_t freeNeed;
uint8_t freeFound = 0;
uint8_t freeNeed;
uint8_t order = 0;
uint8_t checksum = 0;
uint8_t ms10;
uint8_t nameOrd;
uint16_t freeIndex = 0;
uint16_t curIndex;
uint16_t date;
uint16_t freeIndex = 0;
uint16_t freeTotal;
uint16_t time;
DirFat_t* dir;
DirLfn_t* ldir;
@ -306,11 +288,11 @@ bool FatFile::open(FatFile* dirFile, FatLfn_t* fname, oflag_t oflag) {
goto fail;
}
// Number of directory entries needed.
nameOrd = (fname->len + 12)/13;
freeNeed = fname->flags & FNAME_FLAG_NEED_LFN ? 1 + nameOrd : 1;
nameOrd = (fname->len + 12) / 13;
freeNeed = (fname->flags & FNAME_FLAG_NEED_LFN) ? 1 + nameOrd : 1;
dirFile->rewind();
while (1) {
curIndex = dirFile->m_curPosition/FS_DIR_SIZE;
curIndex = dirFile->m_curPosition / FS_DIR_SIZE;
dir = dirFile->readDirCache();
if (!dir) {
if (dirFile->getError()) {
@ -343,7 +325,7 @@ bool FatFile::open(FatFile* dirFile, FatLfn_t* fname, oflag_t oflag) {
if (!lfnOrd) {
order = ldir->order & 0X1F;
if (order != nameOrd ||
(ldir->order & FAT_ORDER_LAST_LONG_ENTRY) == 0) {
(ldir->order & FAT_ORDER_LAST_LONG_ENTRY) == 0) {
continue;
}
lfnOrd = nameOrd;
@ -376,7 +358,7 @@ bool FatFile::open(FatFile* dirFile, FatLfn_t* fname, oflag_t oflag) {
}
}
found:
found:
// Don't open if create only.
if (oflag & O_EXCL) {
DBG_FAIL_MACRO;
@ -384,7 +366,7 @@ bool FatFile::open(FatFile* dirFile, FatLfn_t* fname, oflag_t oflag) {
}
goto open;
create:
create:
// don't create unless O_CREAT and write mode
if (!(oflag & O_CREAT) || !isWriteMode(oflag)) {
DBG_WARN_MACRO;
@ -407,13 +389,16 @@ bool FatFile::open(FatFile* dirFile, FatLfn_t* fname, oflag_t oflag) {
}
freeFound++;
}
while (freeFound < freeNeed) {
// Loop handles the case of huge filename and cluster size one.
freeTotal = freeFound;
while (freeTotal < freeNeed) {
// Will fail if FAT16 root.
if (!dirFile->addDirCluster()) {
DBG_FAIL_MACRO;
goto fail;
}
freeFound += vol->dirEntriesPerCluster();
// 16-bit freeTotal needed for large cluster size.
freeTotal += vol->dirEntriesPerCluster();
}
if (fnameFound) {
if (!dirFile->makeUniqueSfn(fname)) {
@ -456,7 +441,7 @@ bool FatFile::open(FatFile* dirFile, FatLfn_t* fname, oflag_t oflag) {
// Force write of entry to device.
vol->cacheDirty();
open:
open:
// open entry in cache.
if (!openCachedEntry(dirFile, curIndex, oflag, lfnOrd)) {
DBG_FAIL_MACRO;
@ -464,12 +449,12 @@ bool FatFile::open(FatFile* dirFile, FatLfn_t* fname, oflag_t oflag) {
}
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
bool FatFile::parsePathName(const char* path,
FatLfn_t* fname, const char** ptr) {
bool FatFile::parsePathName(const char* path, FatLfn_t* fname,
const char** ptr) {
size_t len = 0;
// Skip leading spaces.
while (*path == ' ') {
@ -491,7 +476,7 @@ bool FatFile::parsePathName(const char* path,
DBG_FAIL_MACRO;
goto fail;
}
#else // USE_UTF8_LONG_NAMES
#else // USE_UTF8_LONG_NAMES
uint8_t cp = *path++;
if (cp >= 0X80 || lfnReservedChar(cp)) {
DBG_FAIL_MACRO;
@ -510,11 +495,12 @@ bool FatFile::parsePathName(const char* path,
goto fail;
}
// Advance to next path component.
for (; *path == ' ' || isDirSeparator(*path); path++) {}
for (; *path == ' ' || isDirSeparator(*path); path++) {
}
*ptr = path;
return makeSFN(fname);
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -570,8 +556,7 @@ bool FatFile::remove() {
goto fail;
}
if (ldir->attributes != FAT_ATTRIB_LONG_NAME ||
order != (ldir->order & 0X1F) ||
checksum != ldir->checksum) {
order != (ldir->order & 0X1F) || checksum != ldir->checksum) {
DBG_FAIL_MACRO;
goto fail;
}
@ -589,7 +574,7 @@ bool FatFile::remove() {
// Fall into fail.
DBG_FAIL_MACRO;
fail:
fail:
return false;
}
#endif // #if USE_LONG_FILE_NAMES

View file

@ -67,7 +67,7 @@ bool FatFile::ls(print_t* pr, uint8_t flags, uint8_t indent) {
}
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -99,7 +99,7 @@ size_t FatFile::printModifyDateTime(print_t* pr) {
//------------------------------------------------------------------------------
size_t FatFile::printFileSize(print_t* pr) {
char buf[11];
char *ptr = buf + sizeof(buf);
char* ptr = buf + sizeof(buf);
*--ptr = 0;
ptr = fmtBase10(ptr, fileSize());
while (ptr > buf) {

View file

@ -46,7 +46,7 @@ bool FatFile::open(FatFile* dirFile, FatSfn_t* fname, oflag_t oflag) {
while (true) {
dir = dirFile->readDirCache(true);
if (!dir) {
if (dirFile->getError()) {
if (dirFile->getError()) {
DBG_FAIL_MACRO;
goto fail;
}
@ -143,7 +143,7 @@ bool FatFile::open(FatFile* dirFile, FatSfn_t* fname, oflag_t oflag) {
// open entry in cache.
return openCachedEntry(dirFile, index, oflag, 0);
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -169,7 +169,7 @@ bool FatFile::openExistingSFN(const char* path) {
} while (*path);
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -192,9 +192,9 @@ bool FatFile::openSFN(FatSfn_t* fname) {
goto fail;
}
if (isFatFileOrSubdir(&dir) && memcmp(fname->sfn, dir.name, 11) == 0) {
uint16_t dirIndex = (m_curPosition - 32) >> 5;
uint32_t dirCluster = m_firstCluster;
memset(this, 0 , sizeof(FatFile));
uint16_t saveDirIndex = (m_curPosition - 32) >> 5;
uint32_t saveDirCluster = m_firstCluster;
memset(this, 0, sizeof(FatFile));
m_attributes = dir.attributes & FS_ATTRIB_COPY;
m_flags = FILE_FLAG_READ;
if (isFatFile(&dir)) {
@ -209,9 +209,9 @@ bool FatFile::openSFN(FatSfn_t* fname) {
m_firstCluster |= getLe16(dir.firstClusterLow);
m_fileSize = getLe32(dir.fileSize);
m_vol = vol;
m_dirCluster = dirCluster;
m_dirCluster = saveDirCluster;
m_dirSector = m_vol->cacheSectorNumber();
m_dirIndex = dirIndex;
m_dirIndex = saveDirIndex;
return true;
} else if (isFatLongName(&dir)) {
ldir = reinterpret_cast<DirLfn_t*>(&dir);
@ -223,7 +223,7 @@ bool FatFile::openSFN(FatSfn_t* fname) {
}
}
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -269,14 +269,14 @@ bool FatFile::parsePathName(const char* path, FatSfn_t* fname,
goto fail;
}
// Set base-name and extension bits.
fname->flags = lc & uc ? 0 : lc;
fname->flags = (lc & uc) ? 0 : lc;
while (isDirSeparator(*path)) {
path++;
}
*ptr = path;
return true;
fail:
fail:
return false;
}
#if !USE_LONG_FILE_NAMES
@ -309,7 +309,7 @@ bool FatFile::remove() {
// Write entry to device.
return m_vol->cacheSync();
fail:
fail:
return false;
}
#endif // !USE_LONG_FILE_NAMES

View file

@ -31,18 +31,20 @@ uint16_t const BU16 = 128;
uint16_t const BU32 = 8192;
// Assume 512 byte sectors.
const uint16_t BYTES_PER_SECTOR = 512;
const uint16_t SECTORS_PER_MB = 0X100000/BYTES_PER_SECTOR;
const uint16_t SECTORS_PER_MB = 0X100000 / BYTES_PER_SECTOR;
const uint16_t FAT16_ROOT_ENTRY_COUNT = 512;
const uint16_t FAT16_ROOT_SECTOR_COUNT =
32*FAT16_ROOT_ENTRY_COUNT/BYTES_PER_SECTOR;
32 * FAT16_ROOT_ENTRY_COUNT / BYTES_PER_SECTOR;
//------------------------------------------------------------------------------
#define PRINT_FORMAT_PROGRESS 1
#if !PRINT_FORMAT_PROGRESS
#define writeMsg(str)
#elif defined(__AVR__)
#define writeMsg(str) if (m_pr) m_pr->print(F(str))
#define writeMsg(str) \
if (m_pr) m_pr->print(F(str))
#else // PRINT_FORMAT_PROGRESS
#define writeMsg(str) if (m_pr) m_pr->write(str)
#define writeMsg(str) \
if (m_pr) m_pr->write(str)
#endif // PRINT_FORMAT_PROGRESS
//------------------------------------------------------------------------------
bool FatFormatter::format(FsBlockDevice* dev, uint8_t* secBuf, print_t* pr) {
@ -51,7 +53,7 @@ bool FatFormatter::format(FsBlockDevice* dev, uint8_t* secBuf, print_t* pr) {
m_secBuf = secBuf;
m_pr = pr;
m_sectorCount = m_dev->sectorCount();
m_capacityMB = (m_sectorCount + SECTORS_PER_MB - 1)/SECTORS_PER_MB;
m_capacityMB = (m_sectorCount + SECTORS_PER_MB - 1) / SECTORS_PER_MB;
if (m_capacityMB <= 6) {
writeMsg("Card is too small.\r\n");
@ -87,9 +89,9 @@ bool FatFormatter::initFatDir(uint8_t fatType, uint32_t sectorCount) {
writeMsg("Writing FAT ");
for (uint32_t i = 1; i < sectorCount; i++) {
if (!m_dev->writeSector(m_fatStart + i, m_secBuf)) {
return false;
return false;
}
if ((i%(sectorCount/32)) == 0) {
if ((i % (sectorCount / 32)) == 0) {
writeMsg(".");
}
}
@ -131,13 +133,12 @@ void FatFormatter::initPbs() {
//------------------------------------------------------------------------------
bool FatFormatter::makeFat16() {
uint32_t nc;
uint32_t r;
PbsFat_t* pbs = reinterpret_cast<PbsFat_t*>(m_secBuf);
for (m_dataStart = 2*BU16; ; m_dataStart += BU16) {
nc = (m_sectorCount - m_dataStart)/m_sectorsPerCluster;
m_fatSize = (nc + 2 + (BYTES_PER_SECTOR/2) - 1)/(BYTES_PER_SECTOR/2);
r = BU16 + 1 + 2*m_fatSize + FAT16_ROOT_SECTOR_COUNT;
for (m_dataStart = 2 * BU16;; m_dataStart += BU16) {
nc = (m_sectorCount - m_dataStart) / m_sectorsPerCluster;
m_fatSize = (nc + 2 + (BYTES_PER_SECTOR / 2) - 1) / (BYTES_PER_SECTOR / 2);
uint32_t r = BU16 + 1 + 2 * m_fatSize + FAT16_ROOT_SECTOR_COUNT;
if (m_dataStart >= r) {
m_relativeSectors = m_dataStart - r + BU16;
break;
@ -150,8 +151,8 @@ bool FatFormatter::makeFat16() {
}
m_reservedSectorCount = 1;
m_fatStart = m_relativeSectors + m_reservedSectorCount;
m_totalSectors = nc*m_sectorsPerCluster
+ 2*m_fatSize + m_reservedSectorCount + 32;
m_totalSectors =
nc * m_sectorsPerCluster + 2 * m_fatSize + m_reservedSectorCount + 32;
if (m_totalSectors < 65536) {
m_partType = 0X04;
} else {
@ -183,15 +184,14 @@ bool FatFormatter::makeFat16() {
//------------------------------------------------------------------------------
bool FatFormatter::makeFat32() {
uint32_t nc;
uint32_t r;
PbsFat_t* pbs = reinterpret_cast<PbsFat_t*>(m_secBuf);
FsInfo_t* fsi = reinterpret_cast<FsInfo_t*>(m_secBuf);
m_relativeSectors = BU32;
for (m_dataStart = 2*BU32; ; m_dataStart += BU32) {
nc = (m_sectorCount - m_dataStart)/m_sectorsPerCluster;
m_fatSize = (nc + 2 + (BYTES_PER_SECTOR/4) - 1)/(BYTES_PER_SECTOR/4);
r = m_relativeSectors + 9 + 2*m_fatSize;
for (m_dataStart = 2 * BU32;; m_dataStart += BU32) {
nc = (m_sectorCount - m_dataStart) / m_sectorsPerCluster;
m_fatSize = (nc + 2 + (BYTES_PER_SECTOR / 4) - 1) / (BYTES_PER_SECTOR / 4);
uint32_t r = m_relativeSectors + 9 + 2 * m_fatSize;
if (m_dataStart >= r) {
break;
}
@ -201,9 +201,9 @@ bool FatFormatter::makeFat32() {
writeMsg("Bad cluster count\r\n");
return false;
}
m_reservedSectorCount = m_dataStart - m_relativeSectors - 2*m_fatSize;
m_reservedSectorCount = m_dataStart - m_relativeSectors - 2 * m_fatSize;
m_fatStart = m_relativeSectors + m_reservedSectorCount;
m_totalSectors = nc*m_sectorsPerCluster + m_dataStart - m_relativeSectors;
m_totalSectors = nc * m_sectorsPerCluster + m_dataStart - m_relativeSectors;
// type depends on address of end sector
// max CHS has lba = 16450560 = 1024*255*63
if ((m_relativeSectors + m_totalSectors) <= 16450560) {
@ -232,14 +232,14 @@ bool FatFormatter::makeFat32() {
pbs->bpb.bpb32.volumeType[2] = 'T';
pbs->bpb.bpb32.volumeType[3] = '3';
pbs->bpb.bpb32.volumeType[4] = '2';
if (!m_dev->writeSector(m_relativeSectors, m_secBuf) ||
if (!m_dev->writeSector(m_relativeSectors, m_secBuf) ||
!m_dev->writeSector(m_relativeSectors + 6, m_secBuf)) {
return false;
}
// write extra boot area and backup
memset(m_secBuf, 0 , BYTES_PER_SECTOR);
memset(m_secBuf, 0, BYTES_PER_SECTOR);
setLe32(fsi->trailSignature, FSINFO_TRAIL_SIGNATURE);
if (!m_dev->writeSector(m_relativeSectors + 2, m_secBuf) ||
if (!m_dev->writeSector(m_relativeSectors + 2, m_secBuf) ||
!m_dev->writeSector(m_relativeSectors + 8, m_secBuf)) {
return false;
}
@ -248,11 +248,11 @@ bool FatFormatter::makeFat32() {
setLe32(fsi->structSignature, FSINFO_STRUCT_SIGNATURE);
setLe32(fsi->freeCount, 0XFFFFFFFF);
setLe32(fsi->nextFree, 0XFFFFFFFF);
if (!m_dev->writeSector(m_relativeSectors + 1, m_secBuf) ||
if (!m_dev->writeSector(m_relativeSectors + 1, m_secBuf) ||
!m_dev->writeSector(m_relativeSectors + 7, m_secBuf)) {
return false;
}
return initFatDir(32, 2*m_fatSize + m_sectorsPerCluster);
return initFatDir(32, 2 * m_fatSize + m_sectorsPerCluster);
}
//------------------------------------------------------------------------------
bool FatFormatter::writeMbr() {
@ -262,8 +262,8 @@ bool FatFormatter::writeMbr() {
#if USE_LBA_TO_CHS
lbaToMbrChs(mbr->part->beginCHS, m_capacityMB, m_relativeSectors);
lbaToMbrChs(mbr->part->endCHS, m_capacityMB,
m_relativeSectors + m_totalSectors -1);
#else // USE_LBA_TO_CHS
m_relativeSectors + m_totalSectors - 1);
#else // USE_LBA_TO_CHS
mbr->part->beginCHS[0] = 1;
mbr->part->beginCHS[1] = 1;
mbr->part->beginCHS[2] = 0;

View file

@ -24,14 +24,16 @@
*/
#ifndef FatFormatter_h
#define FatFormatter_h
#include "../common/SysCall.h"
#include "../common/FsBlockDevice.h"
#include "../common/SysCall.h"
/**
* \class FatFormatter
* \brief Format a FAT volume.
*/
class FatFormatter {
public:
/** Constructor. */
FatFormatter() = default;
/**
* Format a FAT volume.
*

View file

@ -24,6 +24,6 @@
*/
#ifndef FatLib_h
#define FatLib_h
#include "FatVolume.h"
#include "FatFormatter.h"
#include "FatVolume.h"
#endif // FatLib_h

View file

@ -29,11 +29,11 @@
//------------------------------------------------------------------------------
uint16_t FatFile::getLfnChar(DirLfn_t* ldir, uint8_t i) {
if (i < 5) {
return getLe16(ldir->unicode1 + 2*i);
return getLe16(ldir->unicode1 + 2 * i);
} else if (i < 11) {
return getLe16(ldir->unicode2 + 2*i - 10);
return getLe16(ldir->unicode2 + 2 * (i - 5));
} else if (i < 13) {
return getLe16(ldir->unicode3 + 2*i - 22);
return getLe16(ldir->unicode3 + 2 * (i - 11));
}
DBG_HALT_IF(i >= 13);
return 0;
@ -87,11 +87,11 @@ size_t FatFile::getName7(char* name, size_t size) {
name[n++] = c >= 0X7F ? '?' : c;
}
}
done:
done:
name[n] = 0;
return n;
fail:
fail:
name[0] = '\0';
return 0;
}
@ -105,8 +105,8 @@ size_t FatFile::getName8(char* name, size_t size) {
uint16_t hs = 0;
uint32_t cp;
if (!isOpen()) {
DBG_FAIL_MACRO;
goto fail;
DBG_FAIL_MACRO;
goto fail;
}
if (!isLFN()) {
return getSFN(name, size);
@ -156,11 +156,11 @@ size_t FatFile::getName8(char* name, size_t size) {
str = ptr;
}
}
done:
done:
*str = '\0';
return str - name;
fail:
fail:
*name = 0;
return 0;
}
@ -217,7 +217,7 @@ size_t FatFile::getSFN(char* name, size_t size) {
name[j] = '\0';
return j;
fail:
fail:
name[0] = '\0';
return 0;
}
@ -227,10 +227,10 @@ size_t FatFile::printName(print_t* pr) {
return printSFN(pr);
#elif USE_UTF8_LONG_NAMES
return printName8(pr);
# else // USE_LONG_FILE_NAMES
#else // USE_LONG_FILE_NAMES
return printName7(pr);
#endif // !USE_LONG_FILE_NAMES
}
}
//------------------------------------------------------------------------------
size_t FatFile::printName7(print_t* pr) {
FatFile dir;
@ -240,8 +240,8 @@ size_t FatFile::printName7(print_t* pr) {
uint8_t i;
if (!isOpen()) {
DBG_FAIL_MACRO;
goto fail;
DBG_FAIL_MACRO;
goto fail;
}
if (!isLFN()) {
return printSFN(pr);
@ -274,11 +274,11 @@ size_t FatFile::printName7(print_t* pr) {
}
return n;
fail:
fail:
return 0;
}
//------------------------------------------------------------------------------
size_t FatFile::printName8(print_t *pr) {
size_t FatFile::printName8(print_t* pr) {
FatFile dir;
DirLfn_t* ldir;
uint16_t hs = 0;
@ -287,8 +287,8 @@ size_t FatFile::printName8(print_t *pr) {
char buf[5];
char* end = buf + sizeof(buf);
if (!isOpen()) {
DBG_FAIL_MACRO;
goto fail;
DBG_FAIL_MACRO;
goto fail;
}
if (!isLFN()) {
return printSFN(pr);
@ -309,7 +309,7 @@ size_t FatFile::printName8(print_t *pr) {
goto fail;
}
for (uint8_t i = 0; i < 13; i++) {
uint16_t c = getLfnChar(ldir, i);;
uint16_t c = getLfnChar(ldir, i);
if (hs) {
if (!FsUtf::isLowSurrogate(c)) {
DBG_FAIL_MACRO;
@ -334,12 +334,12 @@ size_t FatFile::printName8(print_t *pr) {
DBG_FAIL_MACRO;
goto fail;
}
n += pr->write(buf, str - buf);
n += pr->write(reinterpret_cast<uint8_t*>(buf), str - buf);
}
}
return n;
fail:
fail:
return 0;
}
//------------------------------------------------------------------------------
@ -351,6 +351,6 @@ size_t FatFile::printSFN(print_t* pr) {
}
return pr->write(name);
fail:
fail:
return 0;
}

View file

@ -84,7 +84,7 @@ bool FatPartition::allocateCluster(uint32_t current, uint32_t* next) {
*next = find;
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -149,7 +149,7 @@ bool FatPartition::allocContiguous(uint32_t count, uint32_t* firstCluster) {
*firstCluster = bgnCluster;
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -176,7 +176,7 @@ int8_t FatPartition::fatGet(uint32_t cluster, uint32_t* value) {
next = getLe32(pc + offset);
} else if (fatType() == 16) {
cluster &= 0XFFFF;
sector = m_fatStartSector + (cluster >> (m_bytesPerSectorShift - 1) );
sector = m_fatStartSector + (cluster >> (m_bytesPerSectorShift - 1));
pc = fatCachePrepare(sector, FsCache::CACHE_FOR_READ);
if (!pc) {
DBG_FAIL_MACRO;
@ -216,7 +216,7 @@ int8_t FatPartition::fatGet(uint32_t cluster, uint32_t* value) {
*value = next;
return 1;
fail:
fail:
return -1;
}
//------------------------------------------------------------------------------
@ -245,7 +245,7 @@ bool FatPartition::fatPut(uint32_t cluster, uint32_t value) {
if (fatType() == 16) {
cluster &= 0XFFFF;
sector = m_fatStartSector + (cluster >> (m_bytesPerSectorShift - 1) );
sector = m_fatStartSector + (cluster >> (m_bytesPerSectorShift - 1));
pc = fatCachePrepare(sector, FsCache::CACHE_FOR_WRITE);
if (!pc) {
DBG_FAIL_MACRO;
@ -293,7 +293,7 @@ bool FatPartition::fatPut(uint32_t cluster, uint32_t value) {
goto fail;
}
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -322,7 +322,7 @@ bool FatPartition::freeChain(uint32_t cluster) {
return true;
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -357,7 +357,7 @@ int32_t FatPartition::freeClusterCount() {
DBG_FAIL_MACRO;
goto fail;
}
n = fatType() == 16 ? m_bytesPerSector/2 : m_bytesPerSector/4;
n = fatType() == 16 ? m_bytesPerSector / 2 : m_bytesPerSector / 4;
if (todo < n) {
n = todo;
}
@ -386,12 +386,12 @@ int32_t FatPartition::freeClusterCount() {
setFreeClusterCount(free);
return free;
fail:
fail:
return -1;
}
//------------------------------------------------------------------------------
bool FatPartition::init(FsBlockDevice* dev, uint8_t part, uint32_t volStart) {
uint32_t clusterCount;
uint32_t countOfClusters;
uint32_t totalSectors;
m_blockDev = dev;
pbs_t* pbs;
@ -411,8 +411,8 @@ bool FatPartition::init(FsBlockDevice* dev, uint8_t part, uint32_t volStart) {
DBG_FAIL_MACRO;
goto fail;
}
mbr = reinterpret_cast<MbrSector_t*>
(dataCachePrepare(0, FsCache::CACHE_FOR_READ));
mbr = reinterpret_cast<MbrSector_t*>(
dataCachePrepare(0, FsCache::CACHE_FOR_READ));
if (!mbr) {
DBG_FAIL_MACRO;
goto fail;
@ -424,8 +424,8 @@ bool FatPartition::init(FsBlockDevice* dev, uint8_t part, uint32_t volStart) {
}
volStart = getLe32(mp->relativeSectors);
}
pbs = reinterpret_cast<pbs_t*>
(dataCachePrepare(volStart, FsCache::CACHE_FOR_READ));
pbs = reinterpret_cast<pbs_t*>(
dataCachePrepare(volStart, FsCache::CACHE_FOR_READ));
if (!pbs) {
DBG_FAIL_MACRO;
goto fail;
@ -458,8 +458,10 @@ bool FatPartition::init(FsBlockDevice* dev, uint8_t part, uint32_t volStart) {
// directory start for FAT16 dataStart for FAT32
m_rootDirStart = m_fatStartSector + 2 * m_sectorsPerFat;
// data start for FAT16 and FAT32
m_dataStartSector = m_rootDirStart +
((FS_DIR_SIZE*m_rootDirEntryCount + m_bytesPerSector - 1)/m_bytesPerSector);
m_dataStartSector =
m_rootDirStart +
((FS_DIR_SIZE * m_rootDirEntryCount + m_bytesPerSector - 1) /
m_bytesPerSector);
// total sectors for FAT16 or FAT32
totalSectors = getLe16(bpb->totalSectors16);
@ -467,22 +469,22 @@ bool FatPartition::init(FsBlockDevice* dev, uint8_t part, uint32_t volStart) {
totalSectors = getLe32(bpb->totalSectors32);
}
// total data sectors
clusterCount = totalSectors - (m_dataStartSector - volStart);
countOfClusters = totalSectors - (m_dataStartSector - volStart);
// divide by cluster size to get cluster count
clusterCount >>= m_sectorsPerClusterShift;
m_lastCluster = clusterCount + 1;
countOfClusters >>= m_sectorsPerClusterShift;
m_lastCluster = countOfClusters + 1;
// Indicate unknown number of free clusters.
setFreeClusterCount(-1);
// FAT type is determined by cluster count
if (clusterCount < 4085) {
if (countOfClusters < 4085) {
m_fatType = 12;
if (!FAT12_SUPPORT) {
DBG_FAIL_MACRO;
goto fail;
}
} else if (clusterCount < 65525) {
} else if (countOfClusters < 65525) {
m_fatType = 16;
} else {
m_rootDirStart = getLe32(bpb->fat32RootCluster);
@ -494,6 +496,6 @@ bool FatPartition::init(FsBlockDevice* dev, uint8_t part, uint32_t volStart) {
#endif // USE_SEPARATE_FAT_CACHE
return true;
fail:
fail:
return false;
}

View file

@ -29,10 +29,11 @@
* \brief FatPartition class
*/
#include <stddef.h>
#include "../common/SysCall.h"
#include "../common/FsBlockDevice.h"
#include "../common/FsCache.h"
#include "../common/FsStructs.h"
#include "../common/SysCall.h"
/** Type for FAT12 partition */
const uint8_t FAT_TYPE_FAT12 = 12;
@ -52,7 +53,7 @@ class FatPartition {
public:
/** Create an instance of FatPartition
*/
FatPartition() {}
FatPartition() = default;
/** \return The shift count required to multiply by bytesPerCluster. */
uint8_t bytesPerClusterShift() const {
@ -63,50 +64,32 @@ class FatPartition {
return m_bytesPerSector << m_sectorsPerClusterShift;
}
/** \return Number of bytes per sector. */
uint16_t bytesPerSector() const {
return m_bytesPerSector;
}
uint16_t bytesPerSector() const { return m_bytesPerSector; }
/** \return The shift count required to multiply by bytesPerCluster. */
uint8_t bytesPerSectorShift() const {
return m_bytesPerSectorShift;
}
/** \return Number of directory entries per sector. */
uint8_t bytesPerSectorShift() const { return m_bytesPerSectorShift; }
/** \return Number of directory entries per cluster. */
uint16_t dirEntriesPerCluster() const {
return m_sectorsPerCluster*(m_bytesPerSector/FS_DIR_SIZE);
return m_sectorsPerCluster * (m_bytesPerSector / FS_DIR_SIZE);
}
/** \return Mask for sector offset. */
uint16_t sectorMask() const {
return m_sectorMask;
}
uint16_t sectorMask() const { return m_sectorMask; }
/** \return The volume's cluster size in sectors. */
uint8_t sectorsPerCluster() const {
return m_sectorsPerCluster;
}
uint8_t sectorsPerCluster() const { return m_sectorsPerCluster; }
#ifndef DOXYGEN_SHOULD_SKIP_THIS
uint8_t __attribute__((error("use sectorsPerCluster()"))) blocksPerCluster();
#endif // DOXYGEN_SHOULD_SKIP_THIS
/** \return The number of sectors in one FAT. */
uint32_t sectorsPerFat() const {
return m_sectorsPerFat;
}
uint32_t sectorsPerFat() const { return m_sectorsPerFat; }
/** Clear the cache and returns a pointer to the cache. Not for normal apps.
* \return A pointer to the cache buffer or zero if an error occurs.
*/
uint8_t* cacheClear() {
return m_cache.clear();
}
uint8_t* cacheClear() { return m_cache.clear(); }
/** \return The total number of clusters in the volume. */
uint32_t clusterCount() const {
return m_lastCluster - 1;
}
uint32_t clusterCount() const { return m_lastCluster - 1; }
/** \return The shift count required to multiply by sectorsPerCluster. */
uint8_t sectorsPerClusterShift() const {
return m_sectorsPerClusterShift;
}
uint8_t sectorsPerClusterShift() const { return m_sectorsPerClusterShift; }
/** \return The logical sector number for the start of file data. */
uint32_t dataStartSector() const {
return m_dataStartSector;
}
uint32_t dataStartSector() const { return m_dataStartSector; }
/** End access to volume
* \return pointer to sector size buffer for format.
*/
@ -115,17 +98,11 @@ class FatPartition {
return cacheClear();
}
/** \return The number of File Allocation Tables. */
uint8_t fatCount() const {
return 2;
}
uint8_t fatCount() const { return 2; }
/** \return The logical sector number for the start of the first FAT. */
uint32_t fatStartSector() const {
return m_fatStartSector;
}
uint32_t fatStartSector() const { return m_fatStartSector; }
/** \return The FAT type of the volume. Values are 12, 16 or 32. */
uint8_t fatType() const {
return m_fatType;
}
uint8_t fatType() const { return m_fatType; }
/** \return free cluster count or -1 if an error occurs. */
int32_t freeClusterCount();
/** Initialize a FAT partition.
@ -141,17 +118,13 @@ class FatPartition {
*/
bool init(FsBlockDevice* dev, uint8_t part = 1, uint32_t volStart = 0);
/** \return The number of entries in the root directory for FAT16 volumes. */
uint16_t rootDirEntryCount() const {
return m_rootDirEntryCount;
}
uint16_t rootDirEntryCount() const { return m_rootDirEntryCount; }
/** \return The logical sector number for the start of the root directory
on FAT16 volumes or the first cluster number on FAT32 volumes. */
uint32_t rootDirStart() const {
return m_rootDirStart;
}
uint32_t rootDirStart() const { return m_rootDirStart; }
/** \return The number of sectors in the volume */
uint32_t volumeSectorCount() const {
return sectorsPerCluster()*clusterCount();
return sectorsPerCluster() * clusterCount();
}
/** Debug access to FAT table
*
@ -159,15 +132,13 @@ class FatPartition {
* \param[out] v value of entry
* \return -1 error, 0 EOC, else 1.
*/
int8_t dbgFat(uint32_t n, uint32_t* v) {
return fatGet(n, v);
}
int8_t dbgFat(uint32_t n, uint32_t* v) { return fatGet(n, v); }
/**
* Check for FsBlockDevice busy.
*
* \return true if busy else false.
*/
bool isBusy() {return m_blockDev->isBusy();}
bool isBusy() { return m_blockDev->isBusy(); }
//----------------------------------------------------------------------------
#ifndef DOXYGEN_SHOULD_SKIP_THIS
bool dmpDirSector(print_t* pr, uint32_t sector);
@ -180,22 +151,22 @@ class FatPartition {
/** FatFile allowed access to private members. */
friend class FatFile;
//----------------------------------------------------------------------------
static const uint8_t m_bytesPerSectorShift = 9;
static const uint8_t m_bytesPerSectorShift = 9;
static const uint16_t m_bytesPerSector = 1 << m_bytesPerSectorShift;
static const uint16_t m_sectorMask = m_bytesPerSector - 1;
//----------------------------------------------------------------------------
FsBlockDevice* m_blockDev; // sector device
uint8_t m_sectorsPerCluster; // Cluster size in sectors.
uint8_t m_clusterSectorMask; // Mask to extract sector of cluster.
uint8_t m_sectorsPerClusterShift; // Cluster count to sector count shift.
uint8_t m_fatType = 0; // Volume type (12, 16, OR 32).
uint16_t m_rootDirEntryCount; // Number of entries in FAT16 root dir.
uint32_t m_allocSearchStart; // Start cluster for alloc search.
uint32_t m_sectorsPerFat; // FAT size in sectors
uint32_t m_dataStartSector; // First data sector number.
uint32_t m_fatStartSector; // Start sector for first FAT.
uint32_t m_lastCluster; // Last cluster number in FAT.
uint32_t m_rootDirStart; // Start sector FAT16, cluster FAT32.
FsBlockDevice* m_blockDev; // sector device
uint8_t m_sectorsPerCluster; // Cluster size in sectors.
uint8_t m_clusterSectorMask; // Mask to extract sector of cluster.
uint8_t m_sectorsPerClusterShift; // Cluster count to sector count shift.
uint8_t m_fatType = 0; // Volume type (12, 16, OR 32).
uint16_t m_rootDirEntryCount; // Number of entries in FAT16 root dir.
uint32_t m_allocSearchStart; // Start cluster for alloc search.
uint32_t m_sectorsPerFat; // FAT size in sectors
uint32_t m_dataStartSector; // First data sector number.
uint32_t m_fatStartSector; // Start sector for first FAT.
uint32_t m_lastCluster; // Last cluster number in FAT.
uint32_t m_rootDirStart; // Start sector FAT16, cluster FAT32.
//----------------------------------------------------------------------------
// sector I/O functions.
bool cacheSafeRead(uint32_t sector, uint8_t* dst) {
@ -210,33 +181,22 @@ class FatPartition {
bool cacheSafeWrite(uint32_t sector, const uint8_t* dst, size_t count) {
return m_cache.cacheSafeWrite(sector, dst, count);
}
bool syncDevice() {
return m_blockDev->syncDevice();
}
bool syncDevice() { return m_blockDev->syncDevice(); }
#if MAINTAIN_FREE_CLUSTER_COUNT
int32_t m_freeClusterCount; // Count of free clusters in volume.
void setFreeClusterCount(int32_t value) {
m_freeClusterCount = value;
}
int32_t m_freeClusterCount; // Count of free clusters in volume.
void setFreeClusterCount(int32_t value) { m_freeClusterCount = value; }
void updateFreeClusterCount(int32_t change) {
if (m_freeClusterCount >= 0) {
m_freeClusterCount += change;
}
}
#else // MAINTAIN_FREE_CLUSTER_COUNT
void setFreeClusterCount(int32_t value) {
(void)value;
}
void updateFreeClusterCount(int32_t change) {
(void)change;
}
#else // MAINTAIN_FREE_CLUSTER_COUNT
void setFreeClusterCount(int32_t value) { (void)value; }
void updateFreeClusterCount(int32_t change) { (void)change; }
#endif // MAINTAIN_FREE_CLUSTER_COUNT
// sector caches
// sector caches
FsCache m_cache;
bool cachePrepare(uint32_t sector, uint8_t option) {
return m_cache.prepare(sector, option);
}
FsCache* dataCache() {return &m_cache;}
FsCache* dataCache() { return &m_cache; }
#if USE_SEPARATE_FAT_CACHE
FsCache m_fatCache;
uint8_t* fatCachePrepare(uint32_t sector, uint8_t options) {
@ -246,33 +206,20 @@ class FatPartition {
bool cacheSync() {
return m_cache.sync() && m_fatCache.sync() && syncDevice();
}
#else // USE_SEPARATE_FAT_CACHE
#else // USE_SEPARATE_FAT_CACHE
uint8_t* fatCachePrepare(uint32_t sector, uint8_t options) {
options |= FsCache::CACHE_STATUS_MIRROR_FAT;
return dataCachePrepare(sector, options);
}
bool cacheSync() {
return m_cache.sync() && syncDevice();
}
bool cacheSync() { return m_cache.sync() && syncDevice(); }
#endif // USE_SEPARATE_FAT_CACHE
uint8_t* dataCachePrepare(uint32_t sector, uint8_t options) {
return m_cache.prepare(sector, options);
}
void cacheInvalidate() {
m_cache.invalidate();
}
bool cacheSyncData() {
return m_cache.sync();
}
uint8_t* cacheAddress() {
return m_cache.cacheBuffer();
}
uint32_t cacheSectorNumber() {
return m_cache.sector();
}
void cacheDirty() {
m_cache.dirty();
}
bool cacheSyncData() { return m_cache.sync(); }
uint8_t* cacheAddress() { return m_cache.cacheBuffer(); }
uint32_t cacheSectorNumber() { return m_cache.sector(); }
void cacheDirty() { m_cache.dirty(); }
//----------------------------------------------------------------------------
bool allocateCluster(uint32_t current, uint32_t* next);
bool allocContiguous(uint32_t count, uint32_t* firstCluster);
@ -284,12 +231,8 @@ class FatPartition {
}
int8_t fatGet(uint32_t cluster, uint32_t* value);
bool fatPut(uint32_t cluster, uint32_t value);
bool fatPutEOC(uint32_t cluster) {
return fatPut(cluster, 0x0FFFFFFF);
}
bool fatPutEOC(uint32_t cluster) { return fatPut(cluster, 0x0FFFFFFF); }
bool freeChain(uint32_t cluster);
bool isEOC(uint32_t cluster) const {
return cluster > m_lastCluster;
}
bool isEOC(uint32_t cluster) const { return cluster > m_lastCluster; }
};
#endif // FatPartition

View file

@ -27,7 +27,7 @@
#include "FatLib.h"
FatVolume* FatVolume::m_cwv = nullptr;
//------------------------------------------------------------------------------
bool FatVolume::chdir(const char *path) {
bool FatVolume::chdir(const char* path) {
FatFile dir;
if (!dir.open(vwd(), path, O_RDONLY)) {
DBG_FAIL_MACRO;
@ -40,6 +40,6 @@ bool FatVolume::chdir(const char *path) {
m_vwd = dir;
return true;
fail:
fail:
return false;
}

View file

@ -34,7 +34,7 @@
* \class FatVolume
* \brief Integration class for the FatLib library.
*/
class FatVolume : public FatPartition {
class FatVolume : public FatPartition {
public:
/** Get file's user settable attributes.
* \param[in] path path to file.
@ -63,8 +63,8 @@ class FatVolume : public FatPartition {
* \param[in] volStart Start sector of volume if part is zero.
* \return true for success or false for failure.
*/
bool begin(FsBlockDevice* dev, bool setCwv = true,
uint8_t part = 1, uint32_t volStart = 0) {
bool begin(FsBlockDevice* dev, bool setCwv = true, uint8_t part = 1,
uint32_t volStart = 0) {
if (!init(dev, part, volStart)) {
return false;
}
@ -77,7 +77,7 @@ class FatVolume : public FatPartition {
return true;
}
/** Change global current working volume to this volume. */
void chvol() {m_cwv = this;}
void chvol() { m_cwv = this; }
/**
* Set volume working directory to root.
@ -92,7 +92,7 @@ class FatVolume : public FatPartition {
* \param[in] path Path for volume working directory.
* \return true for success or false for failure.
*/
bool chdir(const char *path);
bool chdir(const char* path);
//----------------------------------------------------------------------------
/**
* Test for the existence of a file.
@ -120,9 +120,7 @@ class FatVolume : public FatPartition {
*
* \return true for success or false for failure.
*/
bool ls(print_t* pr, uint8_t flags = 0) {
return m_vwd.ls(pr, flags);
}
bool ls(print_t* pr, uint8_t flags = 0) { return m_vwd.ls(pr, flags); }
//----------------------------------------------------------------------------
/** List the contents of a directory.
*
@ -164,7 +162,7 @@ class FatVolume : public FatPartition {
* \param[in] oflag open flags.
* \return a File32 object.
*/
File32 open(const char *path, oflag_t oflag = O_RDONLY) {
File32 open(const char* path, oflag_t oflag = O_RDONLY) {
File32 tmpFile;
tmpFile.open(this, path, oflag);
return tmpFile;
@ -195,7 +193,7 @@ class FatVolume : public FatPartition {
*
* \return true for success or false for failure.
*/
bool rename(const char *oldPath, const char *newPath) {
bool rename(const char* oldPath, const char* newPath) {
FatFile file;
return file.open(vwd(), oldPath, O_RDONLY) && file.rename(vwd(), newPath);
}
@ -226,7 +224,7 @@ class FatVolume : public FatPartition {
return file.open(this, path, O_WRONLY) && file.truncate(length);
}
#if ENABLE_ARDUINO_SERIAL
/** List the directory contents of the root directory to Serial.
/** List the directory contents of the root directory to Serial.
*
* \param[in] flags The inclusive OR of
*
@ -238,9 +236,7 @@ class FatVolume : public FatPartition {
*
* \return true for success or false for failure.
*/
bool ls(uint8_t flags = 0) {
return ls(&Serial, flags);
}
bool ls(uint8_t flags = 0) { return ls(&Serial, flags); }
/** List the directory contents of a directory to Serial.
*
* \param[in] path directory to list.
@ -266,19 +262,15 @@ class FatVolume : public FatPartition {
* \param[in] path Path for volume working directory.
* \return true for success or false for failure.
*/
bool chdir(const String& path) {
return chdir(path.c_str());
}
/**
bool chdir(const String& path) { return chdir(path.c_str()); }
/**
* Test for the existence of a file.
*
* \param[in] path Path of the file to be tested for.
*
* \return true if the file exists else false.
*/
bool exists(const String& path) {
return exists(path.c_str());
}
bool exists(const String& path) { return exists(path.c_str()); }
/** Make a subdirectory in the volume root directory.
*
* \param[in] path A path with a valid name for the subdirectory.
@ -297,7 +289,7 @@ class FatVolume : public FatPartition {
* \return a File32 object.
*/
File32 open(const String& path, oflag_t oflag = O_RDONLY) {
return open(path.c_str(), oflag );
return open(path.c_str(), oflag);
}
/** Remove a file from the volume root directory.
*
@ -305,9 +297,7 @@ class FatVolume : public FatPartition {
*
* \return true for success or false for failure.
*/
bool remove(const String& path) {
return remove(path.c_str());
}
bool remove(const String& path) { return remove(path.c_str()); }
/** Rename a file or subdirectory.
*
* \param[in] oldPath Path name to the file or subdirectory to be renamed.
@ -333,9 +323,7 @@ class FatVolume : public FatPartition {
*
* \return true for success or false for failure.
*/
bool rmdir(const String& path) {
return rmdir(path.c_str());
}
bool rmdir(const String& path) { return rmdir(path.c_str()); }
/** Truncate a file to a specified length. The current file position
* will be at the new EOF.
*
@ -351,8 +339,8 @@ class FatVolume : public FatPartition {
private:
friend FatFile;
static FatVolume* cwv() {return m_cwv;}
FatFile* vwd() {return &m_vwd;}
static FatVolume* cwv() { return m_cwv; }
FatFile* vwd() { return &m_vwd; }
static FatVolume* m_cwv;
FatFile m_vwd;
};

View file

@ -34,7 +34,7 @@
/** Indicate FillStack() and UnusedStack() are available. */
#define HAS_UNUSED_STACK 1
/** boundary between stack and heap. */
extern char *__brkval;
extern char* __brkval;
/** End of bss section.*/
extern char __bss_end;
/** Amount of free stack space.
@ -48,9 +48,7 @@ inline int FreeStack() {
#define HAS_UNUSED_STACK 0
#elif defined(PLATFORM_ID) // Particle board
#include "Arduino.h"
inline int FreeStack() {
return System.freeMemory();
}
inline int FreeStack() { return System.freeMemory(); }
#elif defined(__IMXRT1062__)
#define HAS_UNUSED_STACK 1
extern uint8_t _ebss;
@ -69,9 +67,7 @@ inline int FreeStack() {
#ifndef FREE_STACK_CPP
#warning FreeStack is not defined for this system.
#endif // FREE_STACK_CPP
inline int FreeStack() {
return 0;
}
inline int FreeStack() { return 0; }
#endif // defined(__AVR__) || defined(DOXYGEN)
#if defined(HAS_UNUSED_STACK) || defined(DOXYGEN)
/** Fill stack with 0x55 pattern */
@ -89,6 +85,6 @@ int UnusedStack();
#else // HAS_UNUSED_STACK
#define HAS_UNUSED_STACK 0
inline void FillStack() {}
inline int UnusedStack() {return 0;}
inline int UnusedStack() { return 0; }
#endif // defined(HAS_UNUSED_STACK)
#endif // FreeStack_h

View file

@ -37,7 +37,9 @@ FsBaseFile::FsBaseFile(const FsBaseFile& from) {
}
//------------------------------------------------------------------------------
FsBaseFile& FsBaseFile::operator=(const FsBaseFile& from) {
if (this == &from) {return *this;}
if (this == &from) {
return *this;
}
close();
if (from.m_fFile) {
m_fFile = new (m_fileMem) FatFile;

View file

@ -28,9 +28,10 @@
* \file
* \brief FsBaseFile include file.
*/
#include "FsNew.h"
#include "FatLib/FatLib.h"
#include "ExFatLib/ExFatLib.h"
#include "FatLib/FatLib.h"
#include "FsNew.h"
#include "FsVolume.h"
/**
* \class FsBaseFile
* \brief FsBaseFile class.
@ -38,7 +39,7 @@
class FsBaseFile {
public:
/** Create an instance. */
FsBaseFile() {}
FsBaseFile() = default;
/** Create a file object and open it in the current working directory.
*
* \param[in] path A path for a file to be opened.
@ -46,11 +47,9 @@ 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).
*/
FsBaseFile(const char* path, oflag_t oflag) {
open(path, oflag);
}
FsBaseFile(const char* path, oflag_t oflag) { open(path, oflag); }
~FsBaseFile() {close();}
~FsBaseFile() { close(); }
/** Copy constructor.
*
* \param[in] from Object used to initialize this instance.
@ -62,16 +61,15 @@ class FsBaseFile {
*/
FsBaseFile& operator=(const FsBaseFile& from);
/** The parenthesis operator.
*
* \return true if a file is open.
*/
operator bool() const {return isOpen();}
*
* \return true if a file is open.
*/
operator bool() const { return isOpen(); }
/**
* \return user settable file attributes for success else -1.
*/
int attrib() {
return m_fFile ? m_fFile->attrib() :
m_xFile ? m_xFile->attrib() : -1;
return m_fFile ? m_fFile->attrib() : m_xFile ? m_xFile->attrib() : -1;
}
/** Set file attributes
*
@ -82,22 +80,23 @@ class FsBaseFile {
* \return true for success or false for failure.
*/
bool attrib(uint8_t bits) {
return m_fFile ? m_fFile->attrib(bits) :
m_xFile ? m_xFile->attrib(bits) : false;
return m_fFile ? m_fFile->attrib(bits)
: m_xFile ? m_xFile->attrib(bits)
: false;
}
/** \return number of bytes available from the current position to EOF
* or INT_MAX if more than INT_MAX bytes are available.
*/
int available() const {
return m_fFile ? m_fFile->available() :
m_xFile ? m_xFile->available() : 0;
return m_fFile ? m_fFile->available() : m_xFile ? m_xFile->available() : 0;
}
/** \return The number of bytes available from the current position
* to EOF for normal files. Zero is returned for directory files.
*/
uint64_t available64() const {
return m_fFile ? m_fFile->available32() :
m_xFile ? m_xFile->available64() : 0;
return m_fFile ? m_fFile->available32()
: m_xFile ? m_xFile->available64()
: 0;
}
/** Clear writeError. */
void clearWriteError() {
@ -121,23 +120,29 @@ class FsBaseFile {
* \return true for success or false for failure.
*/
bool contiguousRange(uint32_t* bgnSector, uint32_t* endSector) {
return m_fFile ? m_fFile->contiguousRange(bgnSector, endSector) :
m_xFile ? m_xFile->contiguousRange(bgnSector, endSector) : false;
return m_fFile ? m_fFile->contiguousRange(bgnSector, endSector)
: m_xFile ? m_xFile->contiguousRange(bgnSector, endSector)
: false;
}
/** \return The current cluster number for a file or directory. */
uint32_t curCluster() const {
return m_fFile ? m_fFile->curCluster() :
m_xFile ? m_xFile->curCluster() : 0;
return m_fFile ? m_fFile->curCluster()
: m_xFile ? m_xFile->curCluster()
: 0;
}
/** \return The current position for a file or directory. */
uint64_t curPosition() const {
return m_fFile ? m_fFile->curPosition() :
m_xFile ? m_xFile->curPosition() : 0;
return m_fFile ? m_fFile->curPosition()
: m_xFile ? m_xFile->curPosition()
: 0;
}
/** \return Total allocated length for file. */
uint64_t dataLength() const {
return m_fFile ? m_fFile->fileSize() : m_xFile ? m_xFile->dataLength() : 0;
}
/** \return Directory entry index. */
uint32_t dirIndex() const {
return m_fFile ? m_fFile->dirIndex() :
m_xFile ? m_xFile->dirIndex() : 0;
return m_fFile ? m_fFile->dirIndex() : m_xFile ? m_xFile->dirIndex() : 0;
}
/** Test for the existence of a file in a directory
*
@ -151,8 +156,9 @@ class FsBaseFile {
* \return true if the file exists else false.
*/
bool exists(const char* path) {
return m_fFile ? m_fFile->exists(path) :
m_xFile ? m_xFile->exists(path) : false;
return m_fFile ? m_fFile->exists(path)
: m_xFile ? m_xFile->exists(path)
: false;
}
/** get position for streams
* \param[out] pos struct to receive position
@ -161,13 +167,13 @@ class FsBaseFile {
if (m_fFile) m_fFile->fgetpos(pos);
if (m_xFile) m_xFile->fgetpos(pos);
}
/**
/**
* Get a string from a file.
*
* fgets() reads bytes from a file into the array pointed to by \a str, until
* \a num - 1 bytes are read, or a delimiter is read and transferred to \a str,
* or end-of-file is encountered. The string is then terminated
* with a null byte.
* \a num - 1 bytes are read, or a delimiter is read and transferred to \a
* str, or end-of-file is encountered. The string is then terminated with a
* null byte.
*
* fgets() deletes CR, '\\r', from the string. This insures only a '\\n'
* terminates the string for Windows text files which use CRLF for newline.
@ -179,24 +185,26 @@ class FsBaseFile {
* \param[in] delim Optional set of delimiters. The default is "\n".
*
* \return For success fgets() returns the length of the string in \a str.
* If no data is read, fgets() returns zero for EOF or -1 if an error occurred.
* 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) {
return m_fFile ? m_fFile->fgets(str, num, delim) :
m_xFile ? m_xFile->fgets(str, num, delim) : -1;
return m_fFile ? m_fFile->fgets(str, num, delim)
: m_xFile ? m_xFile->fgets(str, num, delim)
: -1;
}
/** \return The total number of bytes in a file. */
uint64_t fileSize() const {
return m_fFile ? m_fFile->fileSize() :
m_xFile ? m_xFile->fileSize() : 0;
return m_fFile ? m_fFile->fileSize() : m_xFile ? m_xFile->fileSize() : 0;
}
/** \return Address of first sector or zero for empty file. */
uint32_t firstSector() const {
return m_fFile ? m_fFile->firstSector() :
m_xFile ? m_xFile->firstSector() : 0;
return m_fFile ? m_fFile->firstSector()
: m_xFile ? m_xFile->firstSector()
: 0;
}
/** Ensure that any bytes written to the file are saved to the SD card. */
void flush() {sync();}
void flush() { sync(); }
/** set position for streams
* \param[in] pos struct with value for new position
*/
@ -212,8 +220,9 @@ class FsBaseFile {
* \return true for success or false for failure.
*/
bool getAccessDateTime(uint16_t* pdate, uint16_t* ptime) {
return m_fFile ? m_fFile->getAccessDateTime(pdate, ptime) :
m_xFile ? m_xFile->getAccessDateTime(pdate, ptime) : false;
return m_fFile ? m_fFile->getAccessDateTime(pdate, ptime)
: m_xFile ? m_xFile->getAccessDateTime(pdate, ptime)
: false;
}
/** Get a file's create date and time.
*
@ -223,13 +232,13 @@ class FsBaseFile {
* \return true for success or false for failure.
*/
bool getCreateDateTime(uint16_t* pdate, uint16_t* ptime) {
return m_fFile ? m_fFile->getCreateDateTime(pdate, ptime) :
m_xFile ? m_xFile->getCreateDateTime(pdate, ptime) : false;
return m_fFile ? m_fFile->getCreateDateTime(pdate, ptime)
: m_xFile ? m_xFile->getCreateDateTime(pdate, ptime)
: false;
}
/** \return All error bits. */
uint8_t getError() const {
return m_fFile ? m_fFile->getError() :
m_xFile ? m_xFile->getError() : 0XFF;
return m_fFile ? m_fFile->getError() : m_xFile ? m_xFile->getError() : 0XFF;
}
/** Get a file's Modify date and time.
*
@ -239,8 +248,9 @@ class FsBaseFile {
* \return true for success or false for failure.
*/
bool getModifyDateTime(uint16_t* pdate, uint16_t* ptime) {
return m_fFile ? m_fFile->getModifyDateTime(pdate, ptime) :
m_xFile ? m_xFile->getModifyDateTime(pdate, ptime) : false;
return m_fFile ? m_fFile->getModifyDateTime(pdate, ptime)
: m_xFile ? m_xFile->getModifyDateTime(pdate, ptime)
: false;
}
/**
* Get a file's name followed by a zero byte.
@ -253,14 +263,16 @@ class FsBaseFile {
*/
size_t getName(char* name, size_t len) {
*name = 0;
return m_fFile ? m_fFile->getName(name, len) :
m_xFile ? m_xFile->getName(name, len) : 0;
return m_fFile ? m_fFile->getName(name, len)
: m_xFile ? m_xFile->getName(name, len)
: 0;
}
/** \return value of writeError */
bool getWriteError() const {
return m_fFile ? m_fFile->getWriteError() :
m_xFile ? m_xFile->getWriteError() : true;
return m_fFile ? m_fFile->getWriteError()
: m_xFile ? m_xFile->getWriteError()
: true;
}
/**
* Check for FsBlockDevice busy.
@ -268,63 +280,67 @@ class FsBaseFile {
* \return true if busy else false.
*/
bool isBusy() {
return m_fFile ? m_fFile->isBusy() :
m_xFile ? m_xFile->isBusy() : true;
return m_fFile ? m_fFile->isBusy() : m_xFile ? m_xFile->isBusy() : true;
}
/** \return True if the file is contiguous. */
bool isContiguous() const {
#if USE_FAT_FILE_FLAG_CONTIGUOUS
return m_fFile ? m_fFile->isContiguous() :
m_xFile ? m_xFile->isContiguous() : false;
#else // USE_FAT_FILE_FLAG_CONTIGUOUS
return m_fFile ? m_fFile->isContiguous()
: m_xFile ? m_xFile->isContiguous()
: false;
#else // USE_FAT_FILE_FLAG_CONTIGUOUS
return m_xFile ? m_xFile->isContiguous() : false;
#endif // USE_FAT_FILE_FLAG_CONTIGUOUS
}
/** \return True if this is a directory else false. */
bool isDir() const {
return m_fFile ? m_fFile->isDir() :
m_xFile ? m_xFile->isDir() : false;
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();}
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;
return m_fFile ? m_fFile->isFile() : m_xFile ? m_xFile->isFile() : false;
}
/** \return True if this is a normal file or sub-directory. */
bool isFileOrSubDir() const {
return m_fFile ? m_fFile->isFileOrSubDir() :
m_xFile ? m_xFile->isFileOrSubDir() : false;
return m_fFile ? m_fFile->isFileOrSubDir()
: m_xFile ? m_xFile->isFileOrSubDir()
: false;
}
/** \return True if this is a hidden file else false. */
bool isHidden() const {
return m_fFile ? m_fFile->isHidden() :
m_xFile ? m_xFile->isHidden() : false;
return m_fFile ? m_fFile->isHidden()
: m_xFile ? m_xFile->isHidden()
: false;
}
/** \return True if this is an open file/directory else false. */
bool isOpen() const {return m_fFile || m_xFile;}
bool isOpen() const { return m_fFile || m_xFile; }
/** \return True file is readable. */
bool isReadable() const {
return m_fFile ? m_fFile->isReadable() :
m_xFile ? m_xFile->isReadable() : false;
}
return m_fFile ? m_fFile->isReadable()
: m_xFile ? m_xFile->isReadable()
: false;
}
/** \return True if file is read-only */
bool isReadOnly() const {
return m_fFile ? m_fFile->isReadOnly() :
m_xFile ? m_xFile->isReadOnly() : false;
return m_fFile ? m_fFile->isReadOnly()
: m_xFile ? m_xFile->isReadOnly()
: false;
}
/** \return True if this is a sub-directory file else false. */
bool isSubDir() const {
return m_fFile ? m_fFile->isSubDir() :
m_xFile ? m_xFile->isSubDir() : false;
return m_fFile ? m_fFile->isSubDir()
: m_xFile ? m_xFile->isSubDir()
: false;
}
/** \return True file is writable. */
bool isWritable() const {
return m_fFile ? m_fFile->isWritable() :
m_xFile ? m_xFile->isWritable() : false;
return m_fFile ? m_fFile->isWritable()
: m_xFile ? m_xFile->isWritable()
: false;
}
#if ENABLE_ARDUINO_SERIAL
/** List directory contents.
@ -336,14 +352,13 @@ class FsBaseFile {
* LS_SIZE - %Print file size.
*
* LS_R - Recursive list of subdirectories.
* \return true for success or false for failure.
*/
bool ls(uint8_t flags) {
return ls(&Serial, flags);
}
/** List directory contents. */
bool ls() {
return ls(&Serial);
}
bool ls(uint8_t flags) { return ls(&Serial, flags); }
/** List directory contents.
* \return true for success or false for failure.
*/
bool ls() { return ls(&Serial); }
#endif // ENABLE_ARDUINO_SERIAL
/** List directory contents.
*
@ -352,8 +367,7 @@ class FsBaseFile {
* \return true for success or false for failure.
*/
bool ls(print_t* pr) {
return m_fFile ? m_fFile->ls(pr) :
m_xFile ? m_xFile->ls(pr) : false;
return m_fFile ? m_fFile->ls(pr) : m_xFile ? m_xFile->ls(pr) : false;
}
/** List directory contents.
*
@ -369,8 +383,9 @@ class FsBaseFile {
* \return true for success or false for failure.
*/
bool ls(print_t* pr, uint8_t flags) {
return m_fFile ? m_fFile->ls(pr, flags) :
m_xFile ? m_xFile->ls(pr, flags) : false;
return m_fFile ? m_fFile->ls(pr, flags)
: m_xFile ? m_xFile->ls(pr, flags)
: false;
}
/** Make a new directory.
*
@ -412,10 +427,12 @@ class FsBaseFile {
* O_CREAT - If the file exists, this flag has no effect except as noted
* under O_EXCL below. Otherwise, the file shall be created
*
* O_EXCL - If O_CREAT and O_EXCL are set, open() shall fail if the file exists.
* O_EXCL - If O_CREAT and O_EXCL are set, open() shall fail if the file
* exists.
*
* O_TRUNC - If the file exists and is a regular file, and the file is
* successfully opened and is not read only, its length shall be truncated to 0.
* successfully opened and is not read only, its length shall be truncated to
* 0.
*
* WARNING: A given file must not be opened by more than one file object
* or file corruption may occur.
@ -464,7 +481,7 @@ class FsBaseFile {
bool open(const char* path, oflag_t oflag = O_RDONLY) {
return FsVolume::m_cwv && open(FsVolume::m_cwv, path, oflag);
}
/** Open a file or directory by index in the current working directory.
/** Open a file or directory by index in the current working directory.
*
* \param[in] index The \a index of the directory entry for the file to be
* opened. The value for \a index is (directory file position)/32.
@ -497,14 +514,13 @@ class FsBaseFile {
*/
bool openRoot(FsVolume* vol);
/** \return the current file position. */
uint64_t position() const {return curPosition();}
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;
*/
int peek() {
return m_fFile ? m_fFile->peek() :
m_xFile ? m_xFile->peek() : -1;
return m_fFile ? m_fFile->peek() : m_xFile ? m_xFile->peek() : -1;
}
/** Allocate contiguous clusters to an empty file.
*
@ -518,8 +534,9 @@ class FsBaseFile {
* \return true for success or false for failure.
*/
bool preAllocate(uint64_t length) {
return m_fFile ? length < (1ULL << 32) && m_fFile->preAllocate(length) :
m_xFile ? m_xFile->preAllocate(length) : false;
return m_fFile ? length < (1ULL << 32) && m_fFile->preAllocate(length)
: m_xFile ? m_xFile->preAllocate(length)
: false;
}
/** Print a file's access date and time
*
@ -528,8 +545,9 @@ class FsBaseFile {
* \return true for success or false for failure.
*/
size_t printAccessDateTime(print_t* pr) {
return m_fFile ? m_fFile->printAccessDateTime(pr) :
m_xFile ? m_xFile->printAccessDateTime(pr) : 0;
return m_fFile ? m_fFile->printAccessDateTime(pr)
: m_xFile ? m_xFile->printAccessDateTime(pr)
: 0;
}
/** Print a file's creation date and time
*
@ -538,8 +556,9 @@ class FsBaseFile {
* \return true for success or false for failure.
*/
size_t printCreateDateTime(print_t* pr) {
return m_fFile ? m_fFile->printCreateDateTime(pr) :
m_xFile ? m_xFile->printCreateDateTime(pr) : 0;
return m_fFile ? m_fFile->printCreateDateTime(pr)
: m_xFile ? m_xFile->printCreateDateTime(pr)
: 0;
}
/** Print a number followed by a field terminator.
* \param[in] value The number to be printed.
@ -548,8 +567,9 @@ class FsBaseFile {
* \return The number of bytes written or -1 if an error occurs.
*/
size_t printField(double value, char term, uint8_t prec = 2) {
return m_fFile ? m_fFile->printField(value, term, prec) :
m_xFile ? m_xFile->printField(value, term, prec) : 0;
return m_fFile ? m_fFile->printField(value, term, prec)
: m_xFile ? m_xFile->printField(value, term, prec)
: 0;
}
/** Print a number followed by a field terminator.
* \param[in] value The number to be printed.
@ -558,17 +578,18 @@ class FsBaseFile {
* \return The number of bytes written or -1 if an error occurs.
*/
size_t printField(float value, char term, uint8_t prec = 2) {
return printField(static_cast<double>(value), term, prec);
return printField(static_cast<double>(value), term, prec);
}
/** Print a number followed by a field terminator.
* \param[in] value The number to be printed.
* \param[in] term The field terminator. Use '\\n' for CR LF.
* \return The number of bytes written or -1 if an error occurs.
*/
template<typename Type>
template <typename Type>
size_t printField(Type value, char term) {
return m_fFile ? m_fFile->printField(value, term) :
m_xFile ? m_xFile->printField(value, term) : 0;
return m_fFile ? m_fFile->printField(value, term)
: m_xFile ? m_xFile->printField(value, term)
: 0;
}
/** Print a file's size.
*
@ -578,8 +599,9 @@ class FsBaseFile {
* for success and zero is returned for failure.
*/
size_t printFileSize(print_t* pr) {
return m_fFile ? m_fFile->printFileSize(pr) :
m_xFile ? m_xFile->printFileSize(pr) : 0;
return m_fFile ? m_fFile->printFileSize(pr)
: m_xFile ? m_xFile->printFileSize(pr)
: 0;
}
/** Print a file's modify date and time
*
@ -588,8 +610,9 @@ class FsBaseFile {
* \return true for success or false for failure.
*/
size_t printModifyDateTime(print_t* pr) {
return m_fFile ? m_fFile->printModifyDateTime(pr) :
m_xFile ? m_xFile->printModifyDateTime(pr) : 0;
return m_fFile ? m_fFile->printModifyDateTime(pr)
: m_xFile ? m_xFile->printModifyDateTime(pr)
: 0;
}
/** Print a file's name
*
@ -598,8 +621,9 @@ class FsBaseFile {
* \return true for success or false for failure.
*/
size_t printName(print_t* pr) {
return m_fFile ? m_fFile->printName(pr) :
m_xFile ? m_xFile->printName(pr) : 0;
return m_fFile ? m_fFile->printName(pr)
: m_xFile ? m_xFile->printName(pr)
: 0;
}
/** Read the next byte from a file.
*
@ -624,8 +648,9 @@ class FsBaseFile {
* or an I/O error occurred.
*/
int read(void* buf, size_t count) {
return m_fFile ? m_fFile->read(buf, count) :
m_xFile ? m_xFile->read(buf, count) : -1;
return m_fFile ? m_fFile->read(buf, count)
: m_xFile ? m_xFile->read(buf, count)
: -1;
}
/** Remove a file.
*
@ -638,7 +663,7 @@ class FsBaseFile {
* \return true for success or false for failure.
*/
bool remove();
/** Remove a file.
/** Remove a file.
*
* The directory entry and all data for the file are deleted.
*
@ -653,8 +678,9 @@ class FsBaseFile {
* \return true for success or false for failure.
*/
bool remove(const char* path) {
return m_fFile ? m_fFile->remove(path) :
m_xFile ? m_xFile->remove(path) : false;
return m_fFile ? m_fFile->remove(path)
: m_xFile ? m_xFile->remove(path)
: false;
}
/** Rename a file or subdirectory.
*
@ -663,8 +689,9 @@ class FsBaseFile {
* \return true for success or false for failure.
*/
bool rename(const char* newPath) {
return m_fFile ? m_fFile->rename(newPath) :
m_xFile ? m_xFile->rename(newPath) : false;
return m_fFile ? m_fFile->rename(newPath)
: m_xFile ? m_xFile->rename(newPath)
: false;
}
/** Rename a file or subdirectory.
*
@ -674,9 +701,9 @@ class FsBaseFile {
* \return true for success or false for failure.
*/
bool rename(FsBaseFile* dir, const char* newPath) {
return m_fFile && dir->m_fFile ? m_fFile->rename(dir->m_fFile, newPath) :
m_xFile && dir->m_xFile ? m_xFile->rename(dir->m_xFile, newPath) :
false;
return m_fFile && dir->m_fFile ? m_fFile->rename(dir->m_fFile, newPath)
: m_xFile && dir->m_xFile ? m_xFile->rename(dir->m_xFile, newPath)
: false;
}
/** Set the file's current position to zero. */
void rewind() {
@ -706,22 +733,18 @@ class FsBaseFile {
* \param[in] pos the new file position.
* \return true for success or false for failure.
*/
bool seek(uint64_t pos) {return seekSet(pos);}
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.
*/
bool seekCur(int64_t offset) {
return seekSet(curPosition() + offset);
}
bool seekCur(int64_t offset) { return seekSet(curPosition() + offset); }
/** Set the files position to end-of-file + \a offset. See seekSet().
* Can't be used for directory files since file size is not defined.
* \param[in] offset The new position in bytes from end-of-file.
* \return true for success or false for failure.
*/
bool seekEnd(int64_t offset = 0) {
return seekSet(fileSize() + offset);
}
bool seekEnd(int64_t offset = 0) { return seekSet(fileSize() + offset); }
/** Sets a file's position.
*
* \param[in] pos The new position in bytes from the beginning of the file.
@ -729,19 +752,19 @@ class FsBaseFile {
* \return true for success or false for failure.
*/
bool seekSet(uint64_t pos) {
return m_fFile ? pos < (1ULL << 32) && m_fFile->seekSet(pos) :
m_xFile ? m_xFile->seekSet(pos) : false;
return m_fFile ? pos < (1ULL << 32) && m_fFile->seekSet(pos)
: m_xFile ? m_xFile->seekSet(pos)
: false;
}
/** \return the file's size. */
uint64_t size() const {return fileSize();}
uint64_t size() const { return fileSize(); }
/** The sync() call causes all modified data and directory fields
* to be written to the storage device.
*
* \return true for success or false for failure.
*/
bool sync() {
return m_fFile ? m_fFile->sync() :
m_xFile ? m_xFile->sync() : false;
return m_fFile ? m_fFile->sync() : m_xFile ? m_xFile->sync() : false;
}
/** Set a file's timestamps in its directory entry.
*
@ -777,19 +800,20 @@ class FsBaseFile {
*/
bool timestamp(uint8_t flags, uint16_t year, uint8_t month, uint8_t day,
uint8_t hour, uint8_t minute, uint8_t second) {
return m_fFile ?
m_fFile->timestamp(flags, year, month, day, hour, minute, second) :
m_xFile ?
m_xFile->timestamp(flags, year, month, day, hour, minute, second) :
false;
return m_fFile ? m_fFile->timestamp(flags, year, month, day, hour, minute,
second)
: m_xFile ? m_xFile->timestamp(flags, year, month, day, hour, minute,
second)
: false;
}
/** Truncate a file to the current position.
*
* \return true for success or false for failure.
*/
bool truncate() {
return m_fFile ? m_fFile->truncate() :
m_xFile ? m_xFile->truncate() : false;
return m_fFile ? m_fFile->truncate()
: m_xFile ? m_xFile->truncate()
: false;
}
/** Truncate a file to a specified length.
* The current file position will be set to end of file.
@ -799,23 +823,22 @@ class FsBaseFile {
* \return true for success or false for failure.
*/
bool truncate(uint64_t length) {
return m_fFile ? length < (1ULL << 32) && m_fFile->truncate(length) :
m_xFile ? m_xFile->truncate(length) : false;
return m_fFile ? length < (1ULL << 32) && m_fFile->truncate(length)
: m_xFile ? m_xFile->truncate(length)
: false;
}
/** Write a string to a file. Used by the Arduino Print class.
* \param[in] str Pointer to the string.
* Use getWriteError to check for errors.
* \return count of characters written for success or -1 for failure.
*/
size_t write(const char* str) {
return write(str, strlen(str));
}
size_t write(const char* str) { return write(str, strlen(str)); }
/** Write a byte to a file. Required by the Arduino Print class.
* \param[in] b the byte to be written.
* Use getWriteError to check for errors.
* \return 1 for success and 0 for failure.
*/
size_t write(uint8_t b) {return write(&b, 1);}
size_t write(uint8_t b) { return write(&b, 1); }
/** Write data to an open file.
*
* \note Data is moved to the cache but may not be written to the
@ -829,13 +852,14 @@ class FsBaseFile {
* \a nbyte. If an error occurs, write() returns zero and writeError is set.
*/
size_t write(const void* buf, size_t count) {
return m_fFile ? m_fFile->write(buf, count) :
m_xFile ? m_xFile->write(buf, count) : 0;
return m_fFile ? m_fFile->write(buf, count)
: m_xFile ? m_xFile->write(buf, count)
: 0;
}
private:
newalign_t m_fileMem[FS_ALIGN_DIM(ExFatFile, FatFile)];
FatFile* m_fFile = nullptr;
FatFile* m_fFile = nullptr;
ExFatFile* m_xFile = nullptr;
};
/**

View file

@ -24,14 +24,16 @@
*/
#ifndef FsFormatter_h
#define FsFormatter_h
#include "FatLib/FatLib.h"
#include "ExFatLib/ExFatLib.h"
#include "FatLib/FatLib.h"
/**
* \class FsFormatter
* \brief Format a exFAT/FAT volume.
*/
class FsFormatter {
public:
/** Constructor. */
FsFormatter() = default;
/**
* Format a FAT volume.
*
@ -46,10 +48,10 @@ class FsFormatter {
if (sectorCount == 0) {
return false;
}
return sectorCount <= 67108864 ?
m_fFmt.format(dev, secBuffer, pr) :
m_xFmt.format(dev, secBuffer, pr);
return sectorCount <= 67108864 ? m_fFmt.format(dev, secBuffer, pr)
: m_xFmt.format(dev, secBuffer, pr);
}
private:
FatFormatter m_fFmt;
ExFatFormatter m_xFmt;

View file

@ -28,7 +28,7 @@
* \file
* \brief FsLib include file.
*/
#include "FsVolume.h"
#include "FsFile.h"
#include "FsFormatter.h"
#include "FsVolume.h"
#endif // FsLib_h

View file

@ -36,7 +36,7 @@ typedef uint32_t newalign_t;
/** Dimension of aligned area. */
#define NEW_ALIGN_DIM(n) \
(((size_t)(n) + sizeof(newalign_t) - 1U)/sizeof(newalign_t))
(((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))

View file

@ -25,23 +25,22 @@
#include "FsLib.h"
FsVolume* FsVolume::m_cwv = nullptr;
//------------------------------------------------------------------------------
bool FsVolume::begin(FsBlockDevice* blockDev, bool setCwv,
uint8_t part, uint32_t volStart) {
m_blockDev = blockDev;
bool FsVolume::begin(FsBlockDevice* blockDev, bool setCwv, uint8_t part,
uint32_t volStart) {
m_fVol = nullptr;
m_xVol = new (m_volMem) ExFatVolume;
if (m_xVol && m_xVol->begin(m_blockDev, false, part, volStart)) {
if (m_xVol && m_xVol->begin(blockDev, false, part, volStart)) {
goto done;
}
m_xVol = nullptr;
m_fVol = new (m_volMem) FatVolume;
if (m_fVol && m_fVol->begin(m_blockDev, false, part, volStart)) {
if (m_fVol && m_fVol->begin(blockDev, false, part, volStart)) {
goto done;
}
m_fVol = nullptr;
return false;
done:
done:
if (setCwv || !m_cwv) {
m_cwv = this;
}
@ -53,14 +52,14 @@ bool FsVolume::ls(print_t* pr, const char* path, uint8_t flags) {
return dir.open(this, path, O_RDONLY) && dir.ls(pr, flags);
}
//------------------------------------------------------------------------------
FsFile FsVolume::open(const char *path, oflag_t oflag) {
FsFile FsVolume::open(const char* path, oflag_t oflag) {
FsFile tmpFile;
tmpFile.open(this, path, oflag);
return tmpFile;
}
#if ENABLE_ARDUINO_STRING
//------------------------------------------------------------------------------
FsFile FsVolume::open(const String &path, oflag_t oflag) {
return open(path.c_str(), oflag );
FsFile FsVolume::open(const String& path, oflag_t oflag) {
return open(path.c_str(), oflag);
}
#endif // ENABLE_ARDUINO_STRING

View file

@ -28,9 +28,9 @@
* \file
* \brief FsVolume include file.
*/
#include "FsNew.h"
#include "../FatLib/FatLib.h"
#include "../ExFatLib/ExFatLib.h"
#include "../FatLib/FatLib.h"
#include "FsNew.h"
class FsFile;
/**
@ -39,16 +39,15 @@ class FsFile;
*/
class FsVolume {
public:
FsVolume() {}
FsVolume() = default;
~FsVolume() {end();}
~FsVolume() { end(); }
/** Get file's user settable attributes.
* \param[in] path path to file.
* \return user settable file attributes for success else -1.
*/
int attrib(const char* path) {
return m_fVol ? m_fVol->attrib(path) :
m_xVol ? m_xVol->attrib(path) : -1;
return m_fVol ? m_fVol->attrib(path) : m_xVol ? m_xVol->attrib(path) : -1;
}
/** Set file's user settable attributes.
* \param[in] path path to file.
@ -58,8 +57,9 @@ class FsVolume {
* \return true for success or false for failure.
*/
bool attrib(const char* path, uint8_t bits) {
return m_fVol ? m_fVol->attrib(path, bits) :
m_xVol ? m_xVol->attrib(path, bits) : false;
return m_fVol ? m_fVol->attrib(path, bits)
: m_xVol ? m_xVol->attrib(path, bits)
: false;
}
/**
* Initialize an FatVolume object.
@ -69,44 +69,45 @@ class FsVolume {
* \param[in] volStart Start sector of volume if part is zero.
* \return true for success or false for failure.
*/
bool begin(FsBlockDevice* blockDev, bool setCwv = true, uint8_t
part = 1, uint32_t volStart = 0);
bool begin(FsBlockDevice* blockDev, bool setCwv = true, uint8_t part = 1,
uint32_t volStart = 0);
#ifndef DOXYGEN_SHOULD_SKIP_THIS
uint32_t __attribute__((error("use sectorsPerCluster()"))) blocksPerCluster();
#endif // DOXYGEN_SHOULD_SKIP_THIS
/** \return the number of bytes in a cluster. */
uint32_t bytesPerCluster() const {
return m_fVol ? m_fVol->bytesPerCluster() :
m_xVol ? m_xVol->bytesPerCluster() : 0;
return m_fVol ? m_fVol->bytesPerCluster()
: m_xVol ? m_xVol->bytesPerCluster()
: 0;
}
/**
* Set volume working directory to root.
* \return true for success or false for failure.
*/
bool chdir() {
return m_fVol ? m_fVol->chdir() :
m_xVol ? m_xVol->chdir() : false;
return m_fVol ? m_fVol->chdir() : m_xVol ? m_xVol->chdir() : false;
}
/**
* Set volume working directory.
* \param[in] path Path for volume working directory.
* \return true for success or false for failure.
*/
bool chdir(const char* path) {
return m_fVol ? m_fVol->chdir(path) :
m_xVol ? m_xVol->chdir(path) : false;
bool chdir(const char* path) {
return m_fVol ? m_fVol->chdir(path) : m_xVol ? m_xVol->chdir(path) : false;
}
/** Change global working volume to this volume. */
void chvol() {m_cwv = this;}
void chvol() { m_cwv = this; }
/** \return The total number of clusters in the volume. */
uint32_t clusterCount() const {
return m_fVol ? m_fVol->clusterCount() :
m_xVol ? m_xVol->clusterCount() : 0;
return m_fVol ? m_fVol->clusterCount()
: m_xVol ? m_xVol->clusterCount()
: 0;
}
/** \return The logical sector number for the start of file data. */
uint32_t dataStartSector() const {
return m_fVol ? m_fVol->dataStartSector() :
m_xVol ? m_xVol->clusterHeapStartSector() : 0;
return m_fVol ? m_fVol->dataStartSector()
: m_xVol ? m_xVol->clusterHeapStartSector()
: 0;
}
/** End access to volume
* \return pointer to sector size buffer for format.
@ -124,25 +125,27 @@ class FsVolume {
* \return true if the file exists else false.
*/
bool exists(const char* path) {
return m_fVol ? m_fVol->exists(path) :
m_xVol ? m_xVol->exists(path) : false;
return m_fVol ? m_fVol->exists(path)
: m_xVol ? m_xVol->exists(path)
: false;
}
/** \return The logical sector number for the start of the first FAT. */
uint32_t fatStartSector() const {
return m_fVol ? m_fVol->fatStartSector() :
m_xVol ? m_xVol->fatStartSector() : 0;
return m_fVol ? m_fVol->fatStartSector()
: m_xVol ? m_xVol->fatStartSector()
: 0;
}
/** \return Partition type, FAT_TYPE_EXFAT, FAT_TYPE_FAT32,
* FAT_TYPE_FAT16, or zero for error.
*/
uint8_t fatType() const {
return m_fVol ? m_fVol->fatType() :
m_xVol ? m_xVol->fatType() : 0;
return m_fVol ? m_fVol->fatType() : m_xVol ? m_xVol->fatType() : 0;
}
/** \return free cluster count or -1 if an error occurs. */
int32_t freeClusterCount() const {
return m_fVol ? m_fVol->freeClusterCount() :
m_xVol ? m_xVol->freeClusterCount() : -1;
return m_fVol ? m_fVol->freeClusterCount()
: m_xVol ? m_xVol->freeClusterCount()
: -1;
}
/**
* Check for device busy.
@ -150,8 +153,7 @@ class FsVolume {
* \return true if busy else false.
*/
bool isBusy() {
return m_fVol ? m_fVol->isBusy() :
m_xVol ? m_xVol->isBusy() : false;
return m_fVol ? m_fVol->isBusy() : m_xVol ? m_xVol->isBusy() : false;
}
/** List directory contents.
*
@ -160,8 +162,7 @@ class FsVolume {
* \return true for success or false for failure.
*/
bool ls(print_t* pr) {
return m_fVol ? m_fVol->ls(pr) :
m_xVol ? m_xVol->ls(pr) : false;
return m_fVol ? m_fVol->ls(pr) : m_xVol ? m_xVol->ls(pr) : false;
}
/** List directory contents.
*
@ -177,8 +178,9 @@ class FsVolume {
* \return true for success or false for failure.
*/
bool ls(print_t* pr, uint8_t flags) {
return m_fVol ? m_fVol->ls(pr, flags) :
m_xVol ? m_xVol->ls(pr, flags) : false;
return m_fVol ? m_fVol->ls(pr, flags)
: m_xVol ? m_xVol->ls(pr, flags)
: false;
}
/** List the directory contents of a directory.
*
@ -197,7 +199,7 @@ class FsVolume {
* \return true for success or false for failure.
*/
bool ls(print_t* pr, const char* path, uint8_t flags);
/** Make a subdirectory in the volume root directory.
/** Make a subdirectory in the volume root directory.
*
* \param[in] path A path with a valid 8.3 DOS name for the subdirectory.
*
@ -205,9 +207,10 @@ class FsVolume {
*
* \return true for success or false for failure.
*/
bool mkdir(const char *path, bool pFlag = true) {
return m_fVol ? m_fVol->mkdir(path, pFlag) :
m_xVol ? m_xVol->mkdir(path, pFlag) : false;
bool mkdir(const char* path, bool pFlag = true) {
return m_fVol ? m_fVol->mkdir(path, pFlag)
: m_xVol ? m_xVol->mkdir(path, pFlag)
: false;
}
/** open a file
*
@ -217,14 +220,15 @@ class FsVolume {
*/
FsFile open(const char* path, oflag_t oflag = O_RDONLY);
/** Remove a file from the volume root directory.
*
* \param[in] path A path with a valid 8.3 DOS name for the file.
*
*
* \param[in] path A path with a valid 8.3 DOS name for the file.
*
* \return true for success or false for failure.
*/
bool remove(const char *path) {
return m_fVol ? m_fVol->remove(path) :
m_xVol ? m_xVol->remove(path) : false;
*/
bool remove(const char* path) {
return m_fVol ? m_fVol->remove(path)
: m_xVol ? m_xVol->remove(path)
: false;
}
/** Rename a file or subdirectory.
*
@ -240,9 +244,10 @@ class FsVolume {
*
* \return true for success or false for failure.
*/
bool rename(const char *oldPath, const char *newPath) {
return m_fVol ? m_fVol->rename(oldPath, newPath) :
m_xVol ? m_xVol->rename(oldPath, newPath) : false;
bool rename(const char* oldPath, const char* newPath) {
return m_fVol ? m_fVol->rename(oldPath, newPath)
: m_xVol ? m_xVol->rename(oldPath, newPath)
: false;
}
/** Remove a subdirectory from the volume's root directory.
*
@ -252,22 +257,20 @@ class FsVolume {
*
* \return true for success or false for failure.
*/
bool rmdir(const char *path) {
return m_fVol ? m_fVol->rmdir(path) :
m_xVol ? m_xVol->rmdir(path) : false;
bool rmdir(const char* path) {
return m_fVol ? m_fVol->rmdir(path) : m_xVol ? m_xVol->rmdir(path) : false;
}
/** \return The volume's cluster size in sectors. */
uint32_t sectorsPerCluster() const {
return m_fVol ? m_fVol->sectorsPerCluster() :
m_xVol ? m_xVol->sectorsPerCluster() : 0;
return m_fVol ? m_fVol->sectorsPerCluster()
: m_xVol ? m_xVol->sectorsPerCluster()
: 0;
}
#if ENABLE_ARDUINO_SERIAL
/** List directory contents.
* \return true for success or false for failure.
*/
bool ls() {
return ls(&Serial);
}
bool ls() { return ls(&Serial); }
/** List directory contents.
*
* \param[in] flags The inclusive OR of
@ -280,9 +283,7 @@ class FsVolume {
*
* \return true for success or false for failure.
*/
bool ls(uint8_t flags) {
return ls(&Serial, flags);
}
bool ls(uint8_t flags) { return ls(&Serial, flags); }
/** List the directory contents of a directory to Serial.
*
* \param[in] path directory to list.
@ -309,18 +310,14 @@ class FsVolume {
* \param[in] path Path for volume working directory.
* \return true for success or false for failure.
*/
bool chdir(const String& path) {
return chdir(path.c_str());
}
bool chdir(const String& path) { return chdir(path.c_str()); }
/** Test for the existence of a file in a directory
*
* \param[in] path Path of the file to be tested for.
*
* \return true if the file exists else false.
*/
bool exists(const String &path) {
return exists(path.c_str());
}
bool exists(const String& path) { return exists(path.c_str()); }
/** Make a subdirectory in the volume root directory.
*
* \param[in] path A path with a valid 8.3 DOS name for the subdirectory.
@ -329,7 +326,7 @@ class FsVolume {
*
* \return true for success or false for failure.
*/
bool mkdir(const String &path, bool pFlag = true) {
bool mkdir(const String& path, bool pFlag = true) {
return mkdir(path.c_str(), pFlag);
}
/** open a file
@ -338,16 +335,14 @@ class FsVolume {
* \param[in] oflag open flags.
* \return a FsBaseFile object.
*/
FsFile open(const String &path, oflag_t oflag = O_RDONLY);
FsFile open(const String& path, oflag_t oflag = O_RDONLY);
/** Remove a file from the volume root directory.
*
* \param[in] path A path with a valid 8.3 DOS name for the file.
*
*
* \param[in] path A path with a valid 8.3 DOS name for the file.
*
* \return true for success or false for failure.
*/
bool remove(const String &path) {
return remove(path.c_str());
}
*/
bool remove(const String& path) { return remove(path.c_str()); }
/** Rename a file or subdirectory.
*
* \param[in] oldPath Path name to the file or subdirectory to be renamed.
@ -373,9 +368,7 @@ class FsVolume {
*
* \return true for success or false for failure.
*/
bool rmdir(const String &path) {
return rmdir(path.c_str());
}
bool rmdir(const String& path) { return rmdir(path.c_str()); }
/** Rename a file or subdirectory.
*
* \param[in] oldPath Path name to the file or subdirectory to be renamed.
@ -393,18 +386,17 @@ class FsVolume {
#endif // ENABLE_ARDUINO_STRING
protected:
newalign_t m_volMem[FS_ALIGN_DIM(ExFatVolume, FatVolume)];
newalign_t m_volMem[FS_ALIGN_DIM(ExFatVolume, FatVolume)];
private:
/** FsBaseFile allowed access to private members. */
friend class FsBaseFile;
static FsVolume* cwv() {return m_cwv;}
static FsVolume* cwv() { return m_cwv; }
FsVolume(const FsVolume& from);
FsVolume& operator=(const FsVolume& from);
static FsVolume* m_cwv;
FatVolume* m_fVol = nullptr;
FatVolume* m_fVol = nullptr;
ExFatVolume* m_xVol = nullptr;
FsBlockDevice* m_blockDev;
};
#endif // FsVolume_h

View file

@ -22,14 +22,11 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "common/SysCall.h"
#if defined(UDR0) || defined(DOXYGEN)
#include "MinimumSerial.h"
const uint16_t MIN_2X_BAUD = F_CPU/(4*(2*0XFFF + 1)) + 1;
#if defined(UDR0) || defined(DOXYGEN)
const uint16_t MIN_2X_BAUD = F_CPU / (4 * (2 * 0XFFF + 1)) + 1;
//------------------------------------------------------------------------------
int MinimumSerial::available() {
return UCSR0A & (1 << RXC0) ? 1 : 0;
}
int MinimumSerial::available() { return UCSR0A & (1 << RXC0) ? 1 : 0; }
//------------------------------------------------------------------------------
void MinimumSerial::begin(uint32_t baud) {
uint16_t baud_setting;
@ -53,7 +50,8 @@ void MinimumSerial::begin(uint32_t baud) {
}
//------------------------------------------------------------------------------
void MinimumSerial::flush() {
while (((1 << UDRIE0) & UCSR0B) || !(UCSR0A & (1 << UDRE0))) {}
while (((1 << UDRIE0) & UCSR0B) || !(UCSR0A & (1 << UDRE0))) {
}
}
//------------------------------------------------------------------------------
int MinimumSerial::read() {
@ -64,7 +62,8 @@ int MinimumSerial::read() {
}
//------------------------------------------------------------------------------
size_t MinimumSerial::write(uint8_t b) {
while (((1 << UDRIE0) & UCSR0B) || !(UCSR0A & (1 << UDRE0))) {}
while (((1 << UDRIE0) & UCSR0B) || !(UCSR0A & (1 << UDRE0))) {
}
UDR0 = b;
return 1;
}

View file

@ -22,7 +22,7 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/**
/**
* \file
* \brief Minimal AVR Serial driver.
*/
@ -37,7 +37,7 @@
class MinimumSerial : public print_t {
public:
/** \return true for hardware serial */
operator bool() {return true;}
operator bool() { return true; }
/**
* \return one if data is available.
*/

View file

@ -28,22 +28,22 @@
* \file
* \brief Ring buffer for data loggers.
*/
#include "common/SysCall.h"
#include "common/FmtNumber.h"
#include "common/SysCall.h"
#ifndef DOXYGEN_SHOULD_SKIP_THIS
// Teensy 3.5/3.6 has hard fault at 0x20000000 for unaligned memcpy.
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
inline bool is_aligned(const void* ptr, uintptr_t alignment) {
auto iptr = reinterpret_cast<uintptr_t>(ptr);
return !(iptr % alignment);
auto iptr = reinterpret_cast<uintptr_t>(ptr);
return !(iptr % alignment);
}
inline void memcpyBuf(void* dst, const void* src, size_t len) {
const uint8_t* b = reinterpret_cast<const uint8_t*>(0X20000000UL);
uint8_t* d = reinterpret_cast<uint8_t*>(dst);
const uint8_t *s = reinterpret_cast<const uint8_t*>(src);
const uint8_t* s = reinterpret_cast<const uint8_t*>(src);
if ((is_aligned(d, 4) && is_aligned(s, 4) && (len & 3) == 0) ||
!((d < b && b <= (d + len)) || (s < b && b <= (s + len)))) {
!((d < b && b <= (d + len)) || (s < b && b <= (s + len)))) {
memcpy(dst, src, len);
} else {
while (len--) {
@ -51,7 +51,7 @@ inline void memcpyBuf(void* dst, const void* src, size_t len) {
}
}
}
#else // defined(__MK64FX512__) || defined(__MK66FX1M0__)
#else // defined(__MK64FX512__) || defined(__MK66FX1M0__)
inline void memcpyBuf(void* dst, const void* src, size_t len) {
memcpy(dst, src, len);
}
@ -59,23 +59,22 @@ inline void memcpyBuf(void* dst, const void* src, size_t len) {
#endif // DOXYGEN_SHOULD_SKIP_THIS
/**
* \class RingBuf
* \brief Ring buffer for data loggers.
* \brief Ring buffer for data loggers and data transmitters.
*
* This ring buffer may be used in ISRs. bytesFreeIsr(), bytesUsedIsr(),
* memcopyIn(), and memcopyOut() are ISR callable. For ISR use call
* memcopyIn() in the ISR and use writeOut() in non-interrupt code
* to write data to a file. readIn() and memcopyOut can be use in a
* similar way to provide file data to an ISR.
* This ring buffer may be used in ISRs. Use beginISR(), endISR(), write()
* and print() in the ISR and use writeOut() in non-interrupt code
* to write data to a file.
*
* Print into a RingBuf in an ISR should also work but has not been verified.
* Use beginISR(), endISR() and read() in an ISR with readIn() in non-interrupt
* code to provide file data to an ISR.
*/
template<class F, size_t Size>
template <class F, size_t Size>
class RingBuf : public Print {
public:
/**
* RingBuf Constructor.
*/
RingBuf() {}
RingBuf() { begin(nullptr); }
/**
* Initialize RingBuf.
* \param[in] file Underlying file.
@ -85,97 +84,41 @@ class RingBuf : public Print {
m_count = 0;
m_head = 0;
m_tail = 0;
m_inISR = false;
clearWriteError();
}
/**
*
* \return the RingBuf free space in bytes. Not ISR callable.
* Disable protection of m_count by noInterrupts()/interrupts.
*/
size_t bytesFree() const {
size_t count;
noInterrupts();
count = m_count;
interrupts();
return Size - count;
}
void beginISR() { m_inISR = true; }
/**
* \return the RingBuf free space in bytes. ISR callable.
* \return the RingBuf free space in bytes.
*/
size_t bytesFreeIsr() const {
return Size - m_count;
}
size_t bytesFree() const { return Size - bytesUsed(); }
/**
* \return the RingBuf used space in bytes. Not ISR callable.
* \return the RingBuf used space in bytes.
*/
size_t bytesUsed() const {
size_t count;
noInterrupts();
count = m_count;
interrupts();
return count;
if (m_inISR) {
return m_count;
} else {
noInterrupts();
size_t rtn = m_count;
interrupts();
return rtn;
}
}
/**
* \return the RingBuf used space in bytes. ISR callable.
* Enable protection of m_count by noInterrupts()/interrupts.
*/
size_t bytesUsedIsr() const {
return m_count;
}
/**
* Copy data to the RingBuf from buf.
* The number of bytes copied may be less than count if
* count is greater than bytesFree.
*
* This function may be used in an ISR with writeOut()
* in non-interrupt code.
*
* \param[in] buf Location of data to be copied.
* \param[in] count number of bytes to be copied.
* \return Number of bytes actually copied.
*/
size_t memcpyIn(const void* buf, size_t count) {
const uint8_t* src = (const uint8_t*)buf;
size_t n = Size - m_count;
if (count > n) {
count = n;
}
size_t nread = 0;
while (nread != count) {
n = minSize(Size - m_head, count - nread);
memcpyBuf(m_buf + m_head, src + nread, n);
m_head = advance(m_head, n);
nread += n;
}
m_count += nread;
return nread;
}
/**
* Copy date from the RingBuf to buf.
* The number of bytes copied may be less than count if
* bytesUsed is less than count.
*
* This function may be used in an ISR with readIn() in
* non-interrupt code.
*
* \param[out] buf Location to receive the data.
* \param[in] count number of bytes to be copied.
* \return Number of bytes actually copied.
*/
size_t memcpyOut(void* buf, size_t count) {
uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
size_t nwrite = 0;
size_t n = m_count;
if (count > n) {
count = n;
}
while (nwrite != count) {
n = minSize(Size - m_tail, count - nwrite);
memcpyBuf(dst + nwrite, m_buf + m_tail, n);
m_tail = advance(m_tail, n);
nwrite += n;
}
m_count -= nwrite;
return nwrite;
}
void endISR() { m_inISR = false; }
#ifndef DOXYGEN_SHOULD_SKIP_THIS
// See write(), read(), beginISR() and endISR().
size_t __attribute__((error("use write(buf, count), beginISR(), endISR()")))
memcpyIn(const void* buf, size_t count);
size_t __attribute__((error("use read(buf, count), beginISR(), endISR()")))
memcpyOut(void* buf, size_t count);
#endif // DOXYGEN_SHOULD_SKIP_THIS
/** Print a number followed by a field terminator.
* \param[in] value The number to be printed.
* \param[in] term The field terminator. Use '\\n' for CR LF.
@ -211,7 +154,7 @@ class RingBuf : public Print {
template <typename Type>
size_t printField(Type value, char term) {
char sign = 0;
char buf[3*sizeof(Type) + 3];
char buf[3 * sizeof(Type) + 3];
char* str = buf + sizeof(buf);
if (term) {
@ -234,34 +177,77 @@ class RingBuf : public Print {
}
return write((const uint8_t*)str, &buf[sizeof(buf)] - str);
}
/** Read data from RingBuf.
* \param[out] buf destination for data.
* \param[in] count number of bytes to read.
* \return Actual count of bytes read.
*/
size_t read(void* buf, size_t count) {
size_t n = bytesFree();
if (count > n) {
count = n;
}
uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
n = minSize(Size - m_tail, count);
if (n == count) {
memcpyBuf(dst, m_buf + m_tail, n);
m_tail = advance(m_tail, n);
} else {
memcpyBuf(dst, m_buf + m_tail, n);
memcpyBuf(dst + n, m_buf, count - n);
m_tail = count - n;
}
adjustCount(-count);
return count;
}
/**
* Efficient read for small types.
*
* \param[in] data location for data item.
* \return true for success else false.
*/
template <typename Type>
bool read(Type* data) {
if (bytesUsed() < sizeof(Type)) {
return false;
}
uint8_t* ptr = reinterpret_cast<uint8_t*>(data);
for (size_t i = 0; i < sizeof(Type); i++) {
ptr[i] = m_buf[m_tail];
m_tail = advance(m_tail);
}
adjustCount(-sizeof(Type));
return true;
}
/**
* Read data into the RingBuf from the underlying file.
* the number of bytes read may be less than count if
* bytesFree is less than count.
*
* This function may be used in non-interrupt code with
* memcopyOut() in an ISR.
* This function must not be used in an ISR.
*
* \param[in] count number of bytes to be read.
* \return Number of bytes actually read.
* \return Number of bytes actually read or negative for read error.
*/
size_t readIn(size_t count) {
size_t nread = 0;
size_t n = bytesFree(); // Protected from interrupts.
int readIn(size_t count) {
size_t n = bytesFree();
if (count > n) {
count = n;
}
while (nread != count) {
n = minSize(Size - m_head, count - nread);
if ((size_t)m_file->read(m_buf + m_head, n) != n) {
return nread;
}
m_head = advance(m_head, n);
nread += n;
n = minSize(Size - m_head, count);
auto rtn = m_file->read(m_buf + m_head, n);
if (rtn <= 0) {
return rtn;
}
noInterrupts();
m_count += nread;
interrupts();
size_t nread = rtn;
if (n < count && nread == n) {
rtn = m_file->read(m_buf, count - n);
if (rtn > 0) {
nread += rtn;
}
}
m_head = advance(m_head, nread);
adjustCount(nread);
return nread;
}
/**
@ -270,25 +256,36 @@ class RingBuf : public Print {
*/
bool sync() {
size_t n = bytesUsed();
return writeOut(n) == n;
return n ? writeOut(n) == n : true;
}
/**
* Copy data to the RingBuf from buf.
*
* The number of bytes copied may be less than count if
* count is greater than bytesFree.
* No data will be copied if count is greater than bytesFree.
* Use getWriteError() to check for print errors and
* clearWriteError() to clear error.
* clearWriteError() to clear the error.
*
* \param[in] buf Location of data to be written.
* \param[in] count number of bytes to be written.
* \return Number of bytes actually written.
*/
size_t write(const void* buf, size_t count) {
if (count > bytesFree()) {
if (bytesFree() < count) {
setWriteError();
return 0;
}
return memcpyIn(buf, count);
const uint8_t* src = (const uint8_t*)buf;
size_t n = minSize(Size - m_head, count);
if (n == count) {
memcpyBuf(m_buf + m_head, src, n);
m_head = advance(m_head, n);
} else {
memcpyBuf(m_buf + m_head, src, n);
memcpyBuf(m_buf, src + n, count - n);
m_head = count - n;
}
adjustCount(count);
return count;
}
/**
* Copy str to RingBuf.
@ -296,9 +293,7 @@ class RingBuf : public Print {
* \param[in] str Location of data to be written.
* \return Number of bytes actually written.
*/
size_t write(const char* str) {
return Print::write(str);
}
size_t write(const char* str) { return Print::write(str); }
/**
* Override virtual function in Print for efficiency.
*
@ -309,13 +304,35 @@ class RingBuf : public Print {
size_t write(const uint8_t* buf, size_t count) override {
return write((const void*)buf, count);
}
/**
* Efficient write for small types.
* \param[in] data Item to be written.
* \return Number of bytes actually written.
*/
template <typename Type>
size_t write(Type data) {
uint8_t* ptr = reinterpret_cast<uint8_t*>(&data);
if (bytesFree() < sizeof(Type)) {
setWriteError();
return 0;
}
for (size_t i = 0; i < sizeof(Type); i++) {
m_buf[m_head] = ptr[i];
m_head = advance(m_head);
}
adjustCount(sizeof(Type));
return sizeof(Type);
}
/**
* Required function for Print.
* \param[in] data Byte to be written.
* \return Number of bytes actually written.
*
* Try to force devirtualization by using final and always_inline.
*/
size_t write(uint8_t data) override {
return write(&data, 1);
size_t write(uint8_t data) final __attribute__((always_inline)) {
// Use this if above does not compile size_t write(uint8_t data) final {
return write<uint8_t>(data);
}
/**
* Write data to file from RingBuf buffer.
@ -324,43 +341,60 @@ class RingBuf : public Print {
* The number of bytes written may be less than count if
* bytesUsed is less than count or if an error occurs.
*
* This function may be used in non-interrupt code with
* memcopyIn() in an ISR.
* This function must only be used in non-interrupt code.
*
* \return Number of bytes actually written.
*/
size_t writeOut(size_t count) {
size_t n = bytesUsed(); // Protected from interrupts;
if (count > n) {
if (count > n) {
count = n;
}
size_t nwrite = 0;
while (nwrite != count) {
n = minSize(Size - m_tail, count - nwrite);
if (m_file->write(m_buf + m_tail, n) != n) {
break;
}
m_tail = advance(m_tail, n);
nwrite += n;
n = minSize(Size - m_tail, count);
auto rtn = m_file->write(m_buf + m_tail, n);
if (rtn <= 0) {
return 0;
}
noInterrupts();
m_count -= nwrite;
interrupts();
size_t nwrite = rtn;
if (n < count && nwrite == n) {
rtn = m_file->write(m_buf, count - n);
if (rtn > 0) {
nwrite += rtn;
}
}
m_tail = advance(m_tail, nwrite);
adjustCount(-nwrite);
return nwrite;
}
private:
uint8_t __attribute__((aligned(4))) m_buf[Size];
F* m_file = nullptr;
F* m_file;
volatile size_t m_count;
size_t m_head;
size_t m_tail;
volatile bool m_inISR;
void adjustCount(int amount) {
if (m_inISR) {
m_count += amount;
} else {
noInterrupts();
m_count += amount;
interrupts();
}
}
size_t advance(size_t index) {
if (!((Size - 1) & Size)) {
return (index + 1) & (Size - 1);
}
return index + 1 < Size ? index + 1 : 0;
}
size_t advance(size_t index, size_t n) {
index += n;
return index < Size ? index : index - Size;
}
// avoid macro MIN
size_t minSize(size_t a, size_t b) {return a < b ? a : b;}
size_t minSize(size_t a, size_t b) { return a < b ? a : b; }
};
#endif // RingBuf_h

View file

@ -22,13 +22,19 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/**
* \file
* \brief Top level include for SPI and SDIO cards.
*/
#ifndef SdCard_h
#define SdCard_h
#include "SdioCard.h"
#include "SdSpiCard.h"
#include "SdioCard.h"
#if HAS_SDIO_CLASS
/** Type for both SPI and SDIO cards. */
typedef SdCardInterface SdCard;
#else // HAS_SDIO_CLASS
#else // HAS_SDIO_CLASS
/** Type for SPI card. */
typedef SdSpiCard SdCard;
#endif // HAS_SDIO_CLASS
/** Determine card configuration type.
@ -36,13 +42,19 @@ typedef SdSpiCard SdCard;
* \param[in] cfg Card configuration.
* \return true if SPI.
*/
inline bool isSpi(SdSpiConfig cfg) {(void)cfg; return true;}
inline bool isSpi(SdSpiConfig cfg) {
(void)cfg;
return true;
}
/** Determine card configuration type.
*
* \param[in] cfg Card configuration.
* \return true if SPI.
*/
inline bool isSpi(SdioConfig cfg) {(void)cfg; return false;}
inline bool isSpi(SdioConfig cfg) {
(void)cfg;
return false;
}
/**
* \class SdCardFactory
* \brief Setup a SPI card or SDIO card.
@ -67,7 +79,7 @@ class SdCardFactory {
#if HAS_SDIO_CLASS
m_sdioCard.begin(config);
return &m_sdioCard;
#else // HAS_SDIO_CLASS
#else // HAS_SDIO_CLASS
(void)config;
return nullptr;
#endif // HAS_SDIO_CLASS

View file

@ -25,21 +25,28 @@
#include "SdCardInfo.h"
//------------------------------------------------------------------------------
#undef SD_CARD_ERROR
#define SD_CARD_ERROR(e, m) case SD_CARD_ERROR_##e: pr->print(F(#e)); break;
#define SD_CARD_ERROR(e, m) \
case SD_CARD_ERROR_##e: \
pr->print(F(#e)); \
break;
void printSdErrorSymbol(print_t* pr, uint8_t code) {
pr->print(F("SD_CARD_ERROR_"));
switch (code) {
SD_ERROR_CODE_LIST
default: pr->print(F("UNKNOWN"));
default:
pr->print(F("UNKNOWN"));
}
}
//------------------------------------------------------------------------------
#undef SD_CARD_ERROR
#define SD_CARD_ERROR(e, m) case SD_CARD_ERROR_##e: pr->print(F(m)); break;
#define SD_CARD_ERROR(e, m) \
case SD_CARD_ERROR_##e: \
pr->print(F(m)); \
break;
void printSdErrorText(print_t* pr, uint8_t code) {
switch
(code) {
switch (code) {
SD_ERROR_CODE_LIST
default: pr->print(F("Unknown error"));
default:
pr->print(F("Unknown error"));
}
}

View file

@ -22,9 +22,14 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/**
* \file
* \brief Definitions for SD cards.
*/
#ifndef SdCardInfo_h
#define SdCardInfo_h
#include <stdint.h>
#include "../common/SysCall.h"
// Based on the document:
//
@ -43,73 +48,81 @@
//------------------------------------------------------------------------------
// SD card errors
// See the SD Specification for command info.
#define SD_ERROR_CODE_LIST\
SD_CARD_ERROR(NONE, "No error")\
SD_CARD_ERROR(CMD0, "Card reset failed")\
SD_CARD_ERROR(CMD2, "SDIO read CID")\
SD_CARD_ERROR(CMD3, "SDIO publish RCA")\
SD_CARD_ERROR(CMD6, "Switch card function")\
SD_CARD_ERROR(CMD7, "SDIO card select")\
SD_CARD_ERROR(CMD8, "Send and check interface settings")\
SD_CARD_ERROR(CMD9, "Read CSD data")\
SD_CARD_ERROR(CMD10, "Read CID data")\
SD_CARD_ERROR(CMD12, "Stop multiple block read")\
SD_CARD_ERROR(CMD13, "Read card status")\
SD_CARD_ERROR(CMD17, "Read single block")\
SD_CARD_ERROR(CMD18, "Read multiple blocks")\
SD_CARD_ERROR(CMD24, "Write single block")\
SD_CARD_ERROR(CMD25, "Write multiple blocks")\
SD_CARD_ERROR(CMD32, "Set first erase block")\
SD_CARD_ERROR(CMD33, "Set last erase block")\
SD_CARD_ERROR(CMD38, "Erase selected blocks")\
SD_CARD_ERROR(CMD58, "Read OCR register")\
SD_CARD_ERROR(CMD59, "Set CRC mode")\
SD_CARD_ERROR(ACMD6, "Set SDIO bus width")\
SD_CARD_ERROR(ACMD13, "Read extended status")\
SD_CARD_ERROR(ACMD23, "Set pre-erased count")\
SD_CARD_ERROR(ACMD41, "Activate card initialization")\
SD_CARD_ERROR(ACMD51, "Read SCR data")\
SD_CARD_ERROR(READ_TOKEN, "Bad read data token")\
SD_CARD_ERROR(READ_CRC, "Read CRC error")\
SD_CARD_ERROR(READ_FIFO, "SDIO fifo read timeout")\
SD_CARD_ERROR(READ_REG, "Read CID or CSD failed.")\
SD_CARD_ERROR(READ_START, "Bad readStart argument")\
SD_CARD_ERROR(READ_TIMEOUT, "Read data timeout")\
SD_CARD_ERROR(STOP_TRAN, "Multiple block stop failed")\
SD_CARD_ERROR(TRANSFER_COMPLETE, "SDIO transfer complete")\
SD_CARD_ERROR(WRITE_DATA, "Write data not accepted")\
SD_CARD_ERROR(WRITE_FIFO, "SDIO fifo write timeout")\
SD_CARD_ERROR(WRITE_START, "Bad writeStart argument")\
SD_CARD_ERROR(WRITE_PROGRAMMING, "Flash programming")\
SD_CARD_ERROR(WRITE_TIMEOUT, "Write timeout")\
SD_CARD_ERROR(DMA, "DMA transfer failed")\
SD_CARD_ERROR(ERASE, "Card did not accept erase commands")\
SD_CARD_ERROR(ERASE_SINGLE_SECTOR, "Card does not support erase")\
SD_CARD_ERROR(ERASE_TIMEOUT, "Erase command timeout")\
SD_CARD_ERROR(INIT_NOT_CALLED, "Card has not been initialized")\
SD_CARD_ERROR(INVALID_CARD_CONFIG, "Invalid card config")\
/** Define error codes and brief description. */
#define SD_ERROR_CODE_LIST \
SD_CARD_ERROR(NONE, "No error") \
SD_CARD_ERROR(CMD0, "Card reset failed") \
SD_CARD_ERROR(CMD2, "SDIO read CID") \
SD_CARD_ERROR(CMD3, "SDIO publish RCA") \
SD_CARD_ERROR(CMD6, "Switch card function") \
SD_CARD_ERROR(CMD7, "SDIO card select") \
SD_CARD_ERROR(CMD8, "Send and check interface settings") \
SD_CARD_ERROR(CMD9, "Read CSD data") \
SD_CARD_ERROR(CMD10, "Read CID data") \
SD_CARD_ERROR(CMD12, "Stop multiple block read") \
SD_CARD_ERROR(CMD13, "Read card status") \
SD_CARD_ERROR(CMD17, "Read single block") \
SD_CARD_ERROR(CMD18, "Read multiple blocks") \
SD_CARD_ERROR(CMD24, "Write single block") \
SD_CARD_ERROR(CMD25, "Write multiple blocks") \
SD_CARD_ERROR(CMD32, "Set first erase block") \
SD_CARD_ERROR(CMD33, "Set last erase block") \
SD_CARD_ERROR(CMD38, "Erase selected blocks") \
SD_CARD_ERROR(CMD58, "Read OCR register") \
SD_CARD_ERROR(CMD59, "Set CRC mode") \
SD_CARD_ERROR(ACMD6, "Set SDIO bus width") \
SD_CARD_ERROR(ACMD13, "Read extended status") \
SD_CARD_ERROR(ACMD23, "Set pre-erased count") \
SD_CARD_ERROR(ACMD41, "Activate card initialization") \
SD_CARD_ERROR(ACMD51, "Read SCR data") \
SD_CARD_ERROR(READ_TOKEN, "Bad read data token") \
SD_CARD_ERROR(READ_CRC, "Read CRC error") \
SD_CARD_ERROR(READ_FIFO, "SDIO fifo read timeout") \
SD_CARD_ERROR(READ_REG, "Read CID or CSD failed.") \
SD_CARD_ERROR(READ_START, "Bad readStart argument") \
SD_CARD_ERROR(READ_TIMEOUT, "Read data timeout") \
SD_CARD_ERROR(STOP_TRAN, "Multiple block stop failed") \
SD_CARD_ERROR(TRANSFER_COMPLETE, "SDIO transfer complete") \
SD_CARD_ERROR(WRITE_DATA, "Write data not accepted") \
SD_CARD_ERROR(WRITE_FIFO, "SDIO fifo write timeout") \
SD_CARD_ERROR(WRITE_START, "Bad writeStart argument") \
SD_CARD_ERROR(WRITE_PROGRAMMING, "Flash programming") \
SD_CARD_ERROR(WRITE_TIMEOUT, "Write timeout") \
SD_CARD_ERROR(DMA, "DMA transfer failed") \
SD_CARD_ERROR(ERASE, "Card did not accept erase commands") \
SD_CARD_ERROR(ERASE_SINGLE_SECTOR, "Card does not support erase") \
SD_CARD_ERROR(ERASE_TIMEOUT, "Erase command timeout") \
SD_CARD_ERROR(INIT_NOT_CALLED, "Card has not been initialized") \
SD_CARD_ERROR(INVALID_CARD_CONFIG, "Invalid card config") \
SD_CARD_ERROR(FUNCTION_NOT_SUPPORTED, "Unsupported SDIO command")
enum {
/** Macro for generation of error codes using an enum. */
#define SD_CARD_ERROR(e, m) SD_CARD_ERROR_##e,
SD_ERROR_CODE_LIST
#undef SD_CARD_ERROR
SD_CARD_ERROR_UNKNOWN
SD_CARD_ERROR_UNKNOWN
};
/** Print the enum symbol for an error code.
* \param[in] pr Print stream.
* \param[in] code enum value for error.
*/
void printSdErrorSymbol(print_t* pr, uint8_t code);
/** Print text for an error code.
* \param[in] pr Print stream.
* \param[in] code enum value for error.
*/
void printSdErrorText(print_t* pr, uint8_t code);
//------------------------------------------------------------------------------
// card types
/** Standard capacity V1 SD card */
const uint8_t SD_CARD_TYPE_SD1 = 1;
const uint8_t SD_CARD_TYPE_SD1 = 1;
/** Standard capacity V2 SD card */
const uint8_t SD_CARD_TYPE_SD2 = 2;
const uint8_t SD_CARD_TYPE_SD2 = 2;
/** High Capacity SD card */
const uint8_t SD_CARD_TYPE_SDHC = 3;
//------------------------------------------------------------------------------
// SD operation timeouts
/** CMD0 retry count */
const uint8_t SD_CMD0_RETRY = 10;
/** command timeout ms */
const uint16_t SD_CMD_TIMEOUT = 300;
/** erase timeout ms */
@ -186,7 +199,7 @@ const uint32_t CARD_STATUS_ADDRESS_ERROR = 1UL << 30;
/** The transferred sector length is not allowed for this card. */
const uint32_t CARD_STATUS_SECTOR_LEN_ERROR = 1UL << 29;
/** An error in the sequence of erase commands occurred. */
const uint32_t CARD_STATUS_ERASE_SEQ_ERROR = 1UL <<28;
const uint32_t CARD_STATUS_ERASE_SEQ_ERROR = 1UL << 28;
/** An invalid selection of write-sectors for erase occurred. */
const uint32_t CARD_STATUS_ERASE_PARAM = 1UL << 27;
/** Set when the host attempts to write to a protected sector. */
@ -207,7 +220,7 @@ const uint32_t CARD_STATUS_CC_ERROR = 1UL << 20;
const uint32_t CARD_STATUS_ERROR = 1UL << 19;
// bits 19, 18, and 17 reserved.
/** Permanent WP set or attempt to change read only values of CSD. */
const uint32_t CARD_STATUS_CSD_OVERWRITE = 1UL <<16;
const uint32_t CARD_STATUS_CSD_OVERWRITE = 1UL << 16;
/** partial address space was erased due to write protect. */
const uint32_t CARD_STATUS_WP_ERASE_SKIP = 1UL << 15;
/** The command has been executed without using the internal ECC. */
@ -260,10 +273,10 @@ const uint8_t DATA_RES_MASK = 0X1F;
const uint8_t DATA_RES_ACCEPTED = 0X05;
//==============================================================================
/**
* \class CID
* \brief Card IDentification (CID) register.
* \class cid_t
* \brief Card Identification (CID) register.
*/
typedef struct CID {
struct cid_t {
// byte 0
/** Manufacturer ID */
uint8_t mid;
@ -287,27 +300,25 @@ typedef struct CID {
uint8_t crc;
// Extract big endian fields.
/** \return major revision number. */
int prvN() const {return prv >> 4;}
int prvN() const { return prv >> 4; }
/** \return minor revision number. */
int prvM() const {return prv & 0XF;}
int prvM() const { return prv & 0XF; }
/** \return Manufacturing Year. */
int mdtYear() const {return 2000 + ((mdt[0] & 0XF) << 4) + (mdt[1] >> 4);}
int mdtYear() const { return 2000 + ((mdt[0] & 0XF) << 4) + (mdt[1] >> 4); }
/** \return Manufacturing Month. */
int mdtMonth() const {return mdt[1] & 0XF;}
int mdtMonth() const { return mdt[1] & 0XF; }
/** \return Product Serial Number. */
uint32_t psn() const {
return (uint32_t)psn8[0] << 24 |
(uint32_t)psn8[1] << 16 |
(uint32_t)psn8[2] << 8 |
(uint32_t)psn8[3];
return (uint32_t)psn8[0] << 24 | (uint32_t)psn8[1] << 16 |
(uint32_t)psn8[2] << 8 | (uint32_t)psn8[3];
}
} __attribute__((packed)) cid_t;
} __attribute__((packed));
//==============================================================================
/**
* \class CSD
* \class csd_t
* \brief Union of old and new style CSD register.
*/
typedef struct CSD {
struct csd_t {
/** union of all CSD versions */
uint8_t csd[16];
// Extract big endian fields.
@ -331,45 +342,45 @@ typedef struct CSD {
}
}
/** \return true if erase granularity is single block. */
bool eraseSingleBlock() const {return csd[10] & 0X40;}
bool eraseSingleBlock() const { return csd[10] & 0X40; }
/** \return erase size in 512 byte blocks if eraseSingleBlock is false. */
int eraseSize() const {return ((csd[10] & 0X3F) << 1 | csd[11] >> 7) + 1;}
int eraseSize() const { return ((csd[10] & 0X3F) << 1 | csd[11] >> 7) + 1; }
/** \return true if the contents is copied or true if original. */
bool copy() const {return csd[14] & 0X40;}
bool copy() const { return csd[14] & 0X40; }
/** \return true if the entire card is permanently write protected. */
bool permWriteProtect() const {return csd[14] & 0X20;}
bool permWriteProtect() const { return csd[14] & 0X20; }
/** \return true if the entire card is temporarily write protected. */
bool tempWriteProtect() const {return csd[14] & 0X10;}
} csd_t;
bool tempWriteProtect() const { return csd[14] & 0X10; }
};
//==============================================================================
/**
* \class SCR
* \class scr_t
* \brief SCR register.
*/
typedef struct SCR {
struct scr_t {
/** Bytes 0-3 SD Association, bytes 4-7 reserved for manufacturer. */
uint8_t scr[8];
/** \return SCR_STRUCTURE field - must be zero.*/
uint8_t srcStructure() {return scr[0] >> 4;}
uint8_t srcStructure() const { return scr[0] >> 4; }
/** \return SD_SPEC field 0 - v1.0 or V1.01, 1 - 1.10, 2 - V2.00 or greater */
uint8_t sdSpec() {return scr[0] & 0XF;}
uint8_t sdSpec() const { return scr[0] & 0XF; }
/** \return false if all zero, true if all one. */
bool dataAfterErase() {return 0X80 & scr[1];}
bool dataAfterErase() const { return scr[1] & 0X80; }
/** \return CPRM Security Version. */
uint8_t sdSecurity() {return (scr[1] >> 4) & 0X7;}
uint8_t sdSecurity() const { return (scr[1] >> 4) & 0X7; }
/** \return 0101b. */
uint8_t sdBusWidths() {return scr[1] & 0XF;}
uint8_t sdBusWidths() const { return scr[1] & 0XF; }
/** \return true if V3.0 or greater. */
bool sdSpec3() {return scr[2] & 0X80;}
bool sdSpec3() const { return scr[2] & 0X80; }
/** \return if true and sdSpecX is zero V4.xx. */
bool sdSpec4() {return scr[2] & 0X4;}
bool sdSpec4() const { return scr[2] & 0X4; }
/** \return nonzero for version 5 or greater if sdSpec == 2,
sdSpec3 == true. Version is return plus four.*/
uint8_t sdSpecX() {return (scr[2] & 0X3) << 2 | scr[3] >> 6;}
uint8_t sdSpecX() const { return (scr[2] & 0X3) << 2 | scr[3] >> 6; }
/** \return bit map for support CMD58/59, CMD48/49, CMD23, and CMD20 */
uint8_t cmdSupport() {return scr[3] &0XF;}
uint8_t cmdSupport() const { return scr[3] & 0XF; }
/** \return SD spec version */
int16_t sdSpecVer() {
int16_t sdSpecVer() const {
if (sdSpec() > 2) {
return -1;
} else if (sdSpec() < 2) {
@ -379,42 +390,88 @@ typedef struct SCR {
} else if (!sdSpec4() && !sdSpecX()) {
return 300;
}
return 400 + 100*sdSpecX();
return 400 + 100 * sdSpecX();
}
} scr_t;
};
//==============================================================================
#ifndef DOXYGEN_SHOULD_SKIP_THIS
/**
* \class sds_t
* \brief SD Status.
*/
// fields are big endian
typedef struct SdStatus {
//
struct sds_t {
/** byte 0, bit 7-6 width, bit 5 secured mode, bits 4-0 reserved. */
uint8_t busWidthSecureMode;
/** byte 1 reserved */
uint8_t reserved1;
// byte 2
/** byte 2-3 zero for SD rd/wr memory card. */
uint8_t sdCardType[2];
// byte 4
/** byte 4-7 size of protected area big endian */
uint8_t sizeOfProtectedArea[4];
// byte 8
uint8_t speedClass;
// byte 9
/** byte 8 speed class. */
uint8_t speed;
/** byte 9 performance move */
uint8_t performanceMove;
// byte 10
/** byte 10 AU size code. */
uint8_t auSize;
// byte 11
/** byte 11-12 erase size big endian */
uint8_t eraseSize[2];
// byte 13
/** byte 13 erase timeout and erase offset */
uint8_t eraseTimeoutOffset;
// byte 14
uint8_t uhsSpeedAuSize;
// byte 15
uint8_t videoSpeed;
// byte 16
/** byte 14 */
uint8_t uhsClassAuSize;
/** byte 15 */
uint8_t videoSpeedClass;
/** byte 16-17 */
uint8_t vscAuSize[2];
// byte 18
/** byte 18-21 */
uint8_t susAddr[3];
// byte 21
uint8_t reserved2[3];
// byte 24
/** byte 21 */
uint8_t appPerfClass;
/** byte 22 */
uint8_t perfEnhance;
/** byte 23 */
uint8_t discardFule;
/** byte 24 */
uint8_t reservedManufacturer[40];
} SdStatus_t;
#endif // DOXYGEN_SHOULD_SKIP_THIS
/** \return appClass. */
int appClass() { return appPerfClass; }
/** \return AU size in KB. or zero for error. */
uint32_t auSizeKB() {
// 0XF mask and uint16_t array helps compiler optimize size on Uno.
uint8_t val = (auSize >> 4) & 0XF;
static const uint16_t au[] = {0, 16, 32, 64, 128,
256, 512, 1024, 2048, 4096,
8192, 12288, 16384, 24576, 32768};
return val < 0XF ? au[val] : 65536UL;
}
/** \return current bus width or -1 for error. */
uint8_t busWidth() const {
uint8_t w = busWidthSecureMode >> 6;
return w == 2 ? 4 : w == 0 ? 1 : -1;
}
/** \return true is discard operation is supported else true. */
bool discard() const { return discardFule & 2; }
/** \return eraseSize in AUs. */
uint16_t eraseSizeAU() const {
return (uint16_t)eraseSize[0] << 8 | (uint16_t)eraseSize[1];
}
/** \return eraseTimeout seconds. */
uint8_t eraseTimeout() const { return eraseTimeoutOffset >> 2; }
/** \return eraseOffset seconds. */
uint8_t eraseOffset() const { return eraseTimeoutOffset & 3; }
/** \return true if full user logical erase is supported else false. */
bool fule() const { return discardFule & 1; }
/** \return true for secure mode else false. */
bool secureMode() const { return busWidthSecureMode & 0X20; }
/** \return speed class or -1 for error. */
int speedClass() const {
return speed < 4 ? 2 * speed : speed == 4 ? 10 : -1;
}
/** \return UHS Speed Grade. */
int uhsClass() const { return uhsClassAuSize >> 4; }
/** \return Video Speed */
int videoClass() { return videoSpeedClass; }
};
#endif // SdCardInfo_h

View file

@ -22,6 +22,10 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/**
* \file
* \brief Abstract interface for an SD card.
*/
#ifndef SdCardInterface_h
#define SdCardInterface_h
#include "../common/FsBlockDeviceInterface.h"
@ -39,9 +43,7 @@ class SdCardInterface : public FsBlockDeviceInterface {
* \return true for success or false for failure.
*/
virtual bool cardCMD6(uint32_t arg, uint8_t* status) = 0;
/** end use of card */
virtual void end() = 0;
/** Erase a range of sectors.
/** Erase a range of sectors.
*
* \param[in] firstSector The address of the first sector in the range.
* \param[in] lastSector The address of the last sector in the range.
@ -53,12 +55,10 @@ class SdCardInterface : public FsBlockDeviceInterface {
virtual uint8_t errorCode() const = 0;
/** \return error data. */
virtual uint32_t errorData() const = 0;
/** \return true if card is busy. */
virtual bool isBusy() = 0;
/** \return false by default */
virtual bool hasDedicatedSpi() {return false;}
virtual bool hasDedicatedSpi() { return false; }
/** \return false by default */
bool virtual isDedicatedSpi() {return false;}
bool virtual isDedicatedSpi() { return false; }
/** Set SPI sharing state
* \param[in] value desired state.
* \return false by default.
@ -75,7 +75,7 @@ class SdCardInterface : public FsBlockDeviceInterface {
* \return true for success or false for failure.
*/
virtual bool readCID(cid_t* cid) = 0;
/**
/**
* Read a card's CSD register.
*
* \param[out] csd pointer to area for returned data.
@ -94,16 +94,14 @@ class SdCardInterface : public FsBlockDeviceInterface {
* \param[out] scr Value of SCR register.
* \return true for success or false for failure.
*/
virtual bool readSCR(scr_t *scr) = 0;
/**
* Determine the size of an SD flash memory card.
*
* \return The number of 512 byte data sectors in the card
* or zero if an error occurs.
virtual bool readSCR(scr_t* scr) = 0;
/** Return the 64 byte SD Status register.
* \param[out] sds location for 64 status bytes.
* \return true for success or false for failure.
*/
virtual uint32_t sectorCount() = 0;
virtual bool readSDS(sds_t* sds) = 0;
/** \return card status. */
virtual uint32_t status() {return 0XFFFFFFFF;}
virtual uint32_t status() { return 0XFFFFFFFF; }
/** Return the card type: SD V1, SD V2 or SDHC/SDXC
* \return 0 - SD V1, 1 - SD V2, or 3 - SDHC/SDXC.
*/

View file

@ -27,14 +27,11 @@
class Timeout {
public:
Timeout() {}
explicit Timeout(uint16_t ms) {set(ms);}
uint16_t millis16() {return millis();}
void set(uint16_t ms) {
m_endTime = ms + millis16();
}
bool timedOut() {
return (int16_t)(m_endTime - millis16()) < 0;
}
explicit Timeout(uint16_t ms) { set(ms); }
uint16_t millis16() { return millis(); }
void set(uint16_t ms) { m_endTime = ms + millis16(); }
bool timedOut() { return (int16_t)(m_endTime - millis16()) < 0; }
private:
uint16_t m_endTime;
};
@ -77,48 +74,44 @@ static uint16_t CRC_CCITT(const uint8_t* data, size_t n) {
// uses the x^16,x^12,x^5,x^1 polynomial.
#ifdef __AVR__
static const uint16_t crctab[] PROGMEM = {
#else // __AVR__
#else // __AVR__
static const uint16_t crctab[] = {
#endif // __AVR__
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
};
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108,
0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210,
0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B,
0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401,
0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE,
0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6,
0x5695, 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D,
0xC7BC, 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5,
0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC,
0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4,
0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD,
0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13,
0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A,
0x9F59, 0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E,
0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x02B1,
0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB,
0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0,
0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8,
0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657,
0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9,
0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882,
0x28A3, 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xFD2E,
0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07,
0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D,
0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74,
0x2E93, 0x3EB2, 0x0ED1, 0x1EF0};
static uint16_t CRC_CCITT(const uint8_t* data, size_t n) {
uint16_t crc = 0;
for (size_t i = 0; i < n; i++) {
#ifdef __AVR__
crc = pgm_read_word(&crctab[(crc >> 8 ^ data[i]) & 0XFF]) ^ (crc << 8);
#else // __AVR__
#else // __AVR__
crc = crctab[(crc >> 8 ^ data[i]) & 0XFF] ^ (crc << 8);
#endif // __AVR__
}
@ -131,10 +124,9 @@ static uint16_t CRC_CCITT(const uint8_t* data, size_t n) {
//------------------------------------------------------------------------------
bool SharedSpiCard::begin(SdSpiConfig spiConfig) {
Timeout timeout;
m_spiActive = false;
m_beginCalled = false;
// Restore state to creator.
initSharedSpiCard();
m_errorCode = SD_CARD_ERROR_NONE;
m_type = 0;
m_csPin = spiConfig.csPin;
#if SPI_DRIVER_SELECT >= 2
m_spiDriverPtr = spiConfig.spiPort;
@ -145,32 +137,28 @@ bool SharedSpiCard::begin(SdSpiConfig spiConfig) {
#endif // SPI_DRIVER_SELECT
sdCsInit(m_csPin);
spiUnselect();
spiSetSckSpeed(1000UL*SD_MAX_INIT_RATE_KHZ);
spiSetSckSpeed(1000UL * SD_MAX_INIT_RATE_KHZ);
spiBegin(spiConfig);
m_beginCalled = true;
uint32_t arg;
m_state = IDLE_STATE;
spiStart();
// must supply min of 74 clock cycles with CS high.
spiUnselect();
for (uint8_t i = 0; i < 10; i++) {
spiSend(0XFF);
spiReceive();
}
spiSelect();
// command to go idle in SPI mode
for (uint8_t i = 1;; i++) {
timeout.set(SD_INIT_TIMEOUT);
while (true) {
// command to go idle in SPI mode
if (cardCommand(CMD0, 0) == R1_IDLE_STATE) {
break;
}
if (i == SD_CMD0_RETRY) {
if (timeout.timedOut()) {
error(SD_CARD_ERROR_CMD0);
goto fail;
}
// Force any active transfer to end for an already initialized card.
for (uint8_t j = 0; j < 0XFF; j++) {
spiSend(0XFF);
}
}
#if USE_SD_CRC
if (cardCommand(CMD59, 1) != R1_IDLE_STATE) {
@ -179,21 +167,26 @@ bool SharedSpiCard::begin(SdSpiConfig spiConfig) {
}
#endif // USE_SD_CRC
// check SD version
if (!(cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) {
type(SD_CARD_TYPE_SD2);
while (true) {
if (cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND) {
type(SD_CARD_TYPE_SD1);
break;
}
// Skip first three bytes.
for (uint8_t i = 0; i < 4; i++) {
m_status = spiReceive();
}
if (m_status != 0XAA) {
if (m_status == 0XAA) {
type(SD_CARD_TYPE_SD2);
break;
}
if (timeout.timedOut()) {
error(SD_CARD_ERROR_CMD8);
goto fail;
}
} else {
type(SD_CARD_TYPE_SD1);
}
// initialize card and send host supports SDHC if SD2
arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0;
timeout.set(SD_INIT_TIMEOUT);
while (cardAcmd(ACMD41, arg) != R1_READY_STATE) {
// check for timeout
if (timeout.timedOut()) {
@ -201,7 +194,6 @@ bool SharedSpiCard::begin(SdSpiConfig spiConfig) {
goto fail;
}
}
// if SD2 read OCR register to check for SDHC card
if (type() == SD_CARD_TYPE_SD2) {
if (cardCommand(CMD58, 0)) {
@ -220,7 +212,7 @@ bool SharedSpiCard::begin(SdSpiConfig spiConfig) {
spiSetSckSpeed(spiConfig.maxSck);
return true;
fail:
fail:
spiStop();
return false;
}
@ -236,7 +228,7 @@ bool SharedSpiCard::cardCMD6(uint32_t arg, uint8_t* status) {
spiStop();
return true;
fail:
fail:
spiStop();
return false;
}
@ -267,7 +259,7 @@ uint8_t SharedSpiCard::cardCommand(uint8_t cmd, uint32_t arg) {
// send message
spiSend(buf, 6);
#else // USE_SD_CRC
#else // USE_SD_CRC
// send command
spiSend(cmd | 0x40);
@ -285,7 +277,7 @@ uint8_t SharedSpiCard::cardCommand(uint8_t cmd, uint32_t arg) {
spiReceive();
// there are 1-8 fill bytes before response. fill bytes should be 0XFF.
uint16_t n = 0;
uint8_t n = 0;
do {
m_status = spiReceive();
} while (m_status & 0X80 && ++n < 10);
@ -294,7 +286,7 @@ uint8_t SharedSpiCard::cardCommand(uint8_t cmd, uint32_t arg) {
//------------------------------------------------------------------------------
void SharedSpiCard::end() {
if (m_beginCalled) {
spiStop();
syncDevice();
spiEnd();
m_beginCalled = false;
}
@ -319,9 +311,8 @@ bool SharedSpiCard::erase(uint32_t firstSector, uint32_t lastSector) {
firstSector <<= 9;
lastSector <<= 9;
}
if (cardCommand(CMD32, firstSector)
|| cardCommand(CMD33, lastSector)
|| cardCommand(CMD38, 0)) {
if (cardCommand(CMD32, firstSector) || cardCommand(CMD33, lastSector) ||
cardCommand(CMD38, 0)) {
error(SD_CARD_ERROR_ERASE);
goto fail;
}
@ -332,7 +323,7 @@ bool SharedSpiCard::erase(uint32_t firstSector, uint32_t lastSector) {
spiStop();
return true;
fail:
fail:
spiStop();
return false;
}
@ -357,9 +348,7 @@ bool SharedSpiCard::isBusy() {
return rtn;
}
//------------------------------------------------------------------------------
bool SharedSpiCard::readData(uint8_t* dst) {
return readData(dst, 512);
}
bool SharedSpiCard::readData(uint8_t* dst) { return readData(dst, 512); }
//------------------------------------------------------------------------------
bool SharedSpiCard::readData(uint8_t* dst, size_t count) {
#if USE_SD_CRC
@ -391,14 +380,14 @@ bool SharedSpiCard::readData(uint8_t* dst, size_t count) {
error(SD_CARD_ERROR_READ_CRC);
goto fail;
}
#else // USE_SD_CRC
#else // USE_SD_CRC
// discard crc
spiReceive();
spiReceive();
#endif // USE_SD_CRC
return true;
fail:
fail:
spiStop();
return false;
}
@ -412,14 +401,14 @@ bool SharedSpiCard::readOCR(uint32_t* ocr) {
for (uint8_t i = 0; i < 4; i++) {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
p[3 - i] = spiReceive();
#else // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#else // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
p[i] = spiReceive();
#endif // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
}
spiStop();
return true;
fail:
fail:
spiStop();
return false;
}
@ -437,7 +426,7 @@ bool SharedSpiCard::readRegister(uint8_t cmd, void* buf) {
spiStop();
return true;
fail:
fail:
spiStop();
return false;
}
@ -454,7 +443,7 @@ bool SharedSpiCard::readSCR(scr_t* scr) {
spiStop();
return true;
fail:
fail:
spiStop();
return false;
}
@ -474,7 +463,7 @@ bool SharedSpiCard::readSector(uint32_t sector, uint8_t* dst) {
spiStop();
return true;
fail:
fail:
spiStop();
return false;
}
@ -489,7 +478,7 @@ bool SharedSpiCard::readSectors(uint32_t sector, uint8_t* dst, size_t ns) {
}
}
return readStop();
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -504,25 +493,25 @@ bool SharedSpiCard::readStart(uint32_t sector) {
m_state = READ_STATE;
return true;
fail:
fail:
spiStop();
return false;
}
//------------------------------------------------------------------------------
bool SharedSpiCard::readStatus(SdStatus* status) {
uint8_t* dst = reinterpret_cast<uint8_t*>(status);
bool SharedSpiCard::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()) {
error(SD_CARD_ERROR_ACMD13);
goto fail;
}
if (!readData(dst, 64)) {
if (!readData(dst, sizeof(sds_t))) {
goto fail;
}
spiStop();
return true;
fail:
fail:
spiStop();
return false;
}
@ -536,7 +525,7 @@ bool SharedSpiCard::readStop() {
spiStop();
return true;
fail:
fail:
spiStop();
return false;
}
@ -547,6 +536,7 @@ uint32_t SharedSpiCard::sectorCount() {
}
//------------------------------------------------------------------------------
void SharedSpiCard::spiStart() {
SPI_ASSERT_NOT_ACTIVE;
if (!m_spiActive) {
spiActivate();
m_spiActive = true;
@ -557,6 +547,7 @@ void SharedSpiCard::spiStart() {
}
//------------------------------------------------------------------------------
void SharedSpiCard::spiStop() {
SPI_ASSERT_ACTIVE;
if (m_spiActive) {
spiUnselect();
// Insure MISO goes to low Z.
@ -597,7 +588,7 @@ bool SharedSpiCard::writeData(const uint8_t* src) {
}
return true;
fail:
fail:
spiStop();
return false;
}
@ -606,7 +597,7 @@ bool SharedSpiCard::writeData(const uint8_t* src) {
bool SharedSpiCard::writeData(uint8_t token, const uint8_t* src) {
#if USE_SD_CRC
uint16_t crc = CRC_CCITT(src, 512);
#else // USE_SD_CRC
#else // USE_SD_CRC
uint16_t crc = 0XFFFF;
#endif // USE_SD_CRC
spiSend(token);
@ -621,7 +612,7 @@ bool SharedSpiCard::writeData(uint8_t token, const uint8_t* src) {
}
return true;
fail:
fail:
spiStop();
return false;
}
@ -655,13 +646,13 @@ bool SharedSpiCard::writeSector(uint32_t sector, const uint8_t* src) {
spiStop();
return true;
fail:
fail:
spiStop();
return false;
}
//------------------------------------------------------------------------------
bool SharedSpiCard::writeSectors(uint32_t sector,
const uint8_t* src, size_t ns) {
bool SharedSpiCard::writeSectors(uint32_t sector, const uint8_t* src,
size_t ns) {
if (!writeStart(sector)) {
goto fail;
}
@ -672,7 +663,7 @@ bool SharedSpiCard::writeSectors(uint32_t sector,
}
return writeStop();
fail:
fail:
spiStop();
return false;
}
@ -689,7 +680,7 @@ bool SharedSpiCard::writeStart(uint32_t sector) {
m_state = WRITE_STATE;
return true;
fail:
fail:
spiStop();
return false;
}
@ -703,7 +694,7 @@ bool SharedSpiCard::writeStop() {
m_state = IDLE_STATE;
return true;
fail:
fail:
error(SD_CARD_ERROR_STOP_TRAN);
spiStop();
return false;
@ -721,8 +712,7 @@ 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) {
bool DedicatedSpiCard::readSectors(uint32_t sector, uint8_t* dst, size_t ns) {
if (sdState() != READ_STATE || sector != m_curSector) {
if (!readStart(sector)) {
goto fail;
@ -737,7 +727,7 @@ bool DedicatedSpiCard::readSectors(
m_curSector += ns;
return m_dedicatedSpi ? true : readStop();
fail:
fail:
return false;
}
//------------------------------------------------------------------------------
@ -756,8 +746,8 @@ bool DedicatedSpiCard::writeSector(uint32_t sector, const uint8_t* src) {
return SharedSpiCard::writeSector(sector, src);
}
//------------------------------------------------------------------------------
bool DedicatedSpiCard::writeSectors(
uint32_t sector, const uint8_t* src, size_t ns) {
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;

View file

@ -24,25 +24,43 @@
*/
/**
* \file
* \brief SdSpiCard class for V2 SD/SDHC cards
* \brief Classes for SPI access to SD/SDHC cards.
*/
#ifndef SdSpiCard_h
#define SdSpiCard_h
#include <stddef.h>
#include "../SpiDriver/SdSpiDriver.h"
#include "../common/SysCall.h"
#include "SdCardInfo.h"
#include "SdCardInterface.h"
#include "../SpiDriver/SdSpiDriver.h"
/** Verify correct SPI active if non-zero. */
#define CHECK_SPI_ACTIVE 0
#if CHECK_SPI_ACTIVE
/** Check SPI active. */
#define SPI_ASSERT_ACTIVE {if (!m_spiActive) {\
Serial.print(F("SPI_ASSERTACTIVE"));\
Serial.println(__LINE__);}}
#define SPI_ASSERT_ACTIVE \
{ \
if (!m_spiActive) { \
Serial.print(F("SPI_ASSERT_ACTIVE")); \
Serial.println(__LINE__); \
while (true) \
; \
} \
}
#define SPI_ASSERT_NOT_ACTIVE \
{ \
if (m_spiActive) { \
Serial.print(F("SPI_ASSERT_NOT_ACTIVE")); \
Serial.println(__LINE__); \
while (true) \
; \
} \
}
#else // CHECK_SPI_ACTIVE
/** Do not check SPI active. */
/** Check for SPI active. */
#define SPI_ASSERT_ACTIVE
/** Check for SPI not active. */
#define SPI_ASSERT_NOT_ACTIVE
#endif // CHECK_SPI_ACTIVE
//==============================================================================
/**
@ -53,7 +71,7 @@
class SharedSpiCard : public SdCardInterface {
#elif USE_BLOCK_DEVICE_INTERFACE
class SharedSpiCard : public FsBlockDeviceInterface {
#else // HAS_SDIO_CLASS
#else // HAS_SDIO_CLASS
class SharedSpiCard {
#endif // HAS_SDIO_CLASS
public:
@ -64,7 +82,7 @@ class SharedSpiCard {
/** SD is in multi-sector write state. */
static const uint8_t WRITE_STATE = 2;
/** Construct an instance of SharedSpiCard. */
SharedSpiCard() {}
SharedSpiCard() { initSharedSpiCard(); }
/** Initialize the SD card.
* \param[in] spiConfig SPI card configuration.
* \return true for success or false for failure.
@ -103,21 +121,18 @@ class SharedSpiCard {
* \param[in] code value for error code.
*/
void error(uint8_t code) {
// (void)code;
// (void)code;
m_errorCode = code;
}
/**
* \return code for the last error. See SdCardInfo.h for a list of error codes.
* \return code for the last error. See SdCardInfo.h for a list of error
* codes.
*/
uint8_t errorCode() const {
return m_errorCode;
}
uint8_t errorCode() const { return m_errorCode; }
/** \return error data for last error. */
uint32_t errorData() const {
return m_status;
}
uint32_t errorData() const { return m_status; }
/** \return false for shared class. */
bool hasDedicatedSpi() {return false;}
bool hasDedicatedSpi() { return false; }
/**
* Check for busy. MISO low indicates the card is busy.
*
@ -125,7 +140,7 @@ class SharedSpiCard {
*/
bool isBusy();
/** \return false, can't be in dedicated state. */
bool isDedicatedSpi() {return false;}
bool isDedicatedSpi() { return false; }
/**
* Read a card's CID register. The CID contains card identification
* information such as Manufacturer ID, Product name, Product serial
@ -135,9 +150,7 @@ class SharedSpiCard {
*
* \return true for success or false for failure.
*/
bool readCID(cid_t* cid) {
return readRegister(CMD10, cid);
}
bool readCID(cid_t* cid) { return readRegister(CMD10, cid); }
/**
* Read a card's CSD register. The CSD contains Card-Specific Data that
* provides information regarding access to the card's contents.
@ -146,9 +159,7 @@ class SharedSpiCard {
*
* \return true for success or false for failure.
*/
bool readCSD(csd_t* csd) {
return readRegister(CMD9, csd);
}
bool readCSD(csd_t* csd) { return readRegister(CMD9, csd); }
/** Read one data sector in a multiple sector read sequence
*
* \param[out] dst Pointer to the location for the data to be read.
@ -196,18 +207,18 @@ class SharedSpiCard {
* \return true for success or false for failure.
*/
bool readStart(uint32_t sector);
/** Return the 64 byte card status
/** Return the 64 byte SD Status register.
* \param[out] status location for 64 status bytes.
* \return true for success or false for failure.
*/
bool readStatus(SdStatus* status);
bool readSDS(sds_t* status);
/** End a read multiple sectors sequence.
*
* \return true for success or false for failure.
*/
bool readStop();
/** \return SD multi-sector read/write state */
uint8_t sdState() {return m_state;}
uint8_t sdState() { return m_state; }
/**
* Determine the size of an SD flash memory card.
*
@ -237,9 +248,7 @@ class SharedSpiCard {
/** Return the card type: SD V1, SD V2 or SDHC/SDXC
* \return 0 - SD V1, 1 - SD V2, or 3 - SDHC/SDXC.
*/
uint8_t type() const {
return m_type;
}
uint8_t type() const { return m_type; }
/**
* Write a 512 byte sector to an SD card.
*
@ -288,32 +297,18 @@ class SharedSpiCard {
uint8_t cardCommand(uint8_t cmd, uint32_t arg);
bool readData(uint8_t* dst, size_t count);
bool readRegister(uint8_t cmd, void* buf);
void spiSelect() {
sdCsWrite(m_csPin, false);
}
void spiSelect() { sdCsWrite(m_csPin, false); }
void spiStart();
void spiStop();
void spiUnselect() {
sdCsWrite(m_csPin, true);
}
void type(uint8_t value) {
m_type = value;
}
void spiUnselect() { sdCsWrite(m_csPin, true); }
void type(uint8_t value) { m_type = value; }
bool waitReady(uint16_t ms);
bool writeData(uint8_t token, const uint8_t* src);
#if SPI_DRIVER_SELECT < 2
void spiActivate() {
m_spiDriver.activate();
}
void spiBegin(SdSpiConfig spiConfig) {
m_spiDriver.begin(spiConfig);
}
void spiDeactivate() {
m_spiDriver.deactivate();
}
void spiEnd() {
m_spiDriver.end();
}
void spiActivate() { m_spiDriver.activate(); }
void spiBegin(SdSpiConfig spiConfig) { m_spiDriver.begin(spiConfig); }
void spiDeactivate() { m_spiDriver.deactivate(); }
void spiEnd() { m_spiDriver.end(); }
uint8_t spiReceive() {
SPI_ASSERT_ACTIVE;
return m_spiDriver.receive();
@ -330,23 +325,13 @@ class SharedSpiCard {
SPI_ASSERT_ACTIVE;
m_spiDriver.send(buf, n);
}
void spiSetSckSpeed(uint32_t maxSck) {
m_spiDriver.setSckSpeed(maxSck);
}
void spiSetSckSpeed(uint32_t maxSck) { m_spiDriver.setSckSpeed(maxSck); }
SdSpiDriver m_spiDriver;
#else // SPI_DRIVER_SELECT < 2
void spiActivate() {
m_spiDriverPtr->activate();
}
void spiBegin(SdSpiConfig spiConfig) {
m_spiDriverPtr->begin(spiConfig);
}
void spiDeactivate() {
m_spiDriverPtr->deactivate();
}
void spiEnd() {
m_spiDriverPtr->end();
}
void spiActivate() { m_spiDriverPtr->activate(); }
void spiBegin(SdSpiConfig spiConfig) { m_spiDriverPtr->begin(spiConfig); }
void spiDeactivate() { m_spiDriverPtr->deactivate(); }
void spiEnd() { m_spiDriverPtr->end(); }
uint8_t spiReceive() {
SPI_ASSERT_ACTIVE;
return m_spiDriverPtr->receive();
@ -363,21 +348,27 @@ class SharedSpiCard {
SPI_ASSERT_ACTIVE;
m_spiDriverPtr->send(buf, n);
}
void spiSetSckSpeed(uint32_t maxSck) {
m_spiDriverPtr->setSckSpeed(maxSck);
}
void spiSetSckSpeed(uint32_t maxSck) { m_spiDriverPtr->setSckSpeed(maxSck); }
SdSpiDriver* m_spiDriverPtr;
#endif // SPI_DRIVER_SELECT < 2
bool m_beginCalled = false;
void initSharedSpiCard() {
m_beginCalled = false;
m_csPin = 0;
m_errorCode = SD_CARD_ERROR_INIT_NOT_CALLED;
m_spiActive = false;
m_state = IDLE_STATE;
m_status = 0;
m_type = 0;
}
bool m_beginCalled;
SdCsPin_t m_csPin;
uint8_t m_errorCode = SD_CARD_ERROR_INIT_NOT_CALLED;
bool m_spiActive;
uint8_t m_errorCode;
bool m_spiActive;
uint8_t m_state;
uint8_t m_status;
uint8_t m_type = 0;
uint8_t m_type;
};
//==============================================================================
/**
* \class DedicatedSpiCard
@ -386,16 +377,16 @@ class SharedSpiCard {
class DedicatedSpiCard : public SharedSpiCard {
public:
/** Construct an instance of DedicatedSpiCard. */
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;}
bool hasDedicatedSpi() { return true; }
/** \return true if in dedicated SPI state. */
bool isDedicatedSpi() {return m_dedicatedSpi;}
bool isDedicatedSpi() { return m_dedicatedSpi; }
/**
* Read a 512 byte sector from an SD card.
*
@ -437,7 +428,7 @@ class DedicatedSpiCard : public SharedSpiCard {
bool writeSectors(uint32_t sector, const uint8_t* src, size_t ns);
private:
uint32_t m_curSector;
uint32_t m_curSector = 0;
bool m_dedicatedSpi = false;
};
//==============================================================================

View file

@ -22,12 +22,17 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/**
* \file
* \brief Classes for SDIO cards.
*/
#ifndef SdioCard_h
#define SdioCard_h
#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
/**
* \class SdioConfig
@ -42,9 +47,10 @@ class SdioConfig {
*/
explicit SdioConfig(uint8_t opt) : m_options(opt) {}
/** \return SDIO card options. */
uint8_t options() {return m_options;}
uint8_t options() { return m_options; }
/** \return true if DMA_SDIO. */
bool useDma() {return m_options & DMA_SDIO;}
bool useDma() { return m_options & DMA_SDIO; }
private:
uint8_t m_options = FIFO_SDIO;
};
@ -73,7 +79,7 @@ class SdioCard : public SdCardInterface {
void end() {}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
uint32_t __attribute__((error("use sectorCount()"))) cardSize();
uint32_t __attribute__((error("use sectorCount()"))) cardSize();
#endif // DOXYGEN_SHOULD_SKIP_THIS
/** Erase a range of sectors.
*
@ -89,7 +95,8 @@ class SdioCard : public SdCardInterface {
*/
bool erase(uint32_t firstSector, uint32_t lastSector);
/**
* \return code for the last error. See SdCardInfo.h for a list of error codes.
* \return code for the last error. See SdCardInfo.h for a list of error
* codes.
*/
uint8_t errorCode() const;
/** \return error data for last error. */
@ -158,7 +165,12 @@ class SdioCard : public SdCardInterface {
* \param[out] scr Value of SCR register.
* \return true for success or false for failure.
*/
bool readSCR(scr_t *scr);
bool readSCR(scr_t* scr);
/** Return the 64 byte SD Status register.
* \param[out] sds location for 64 status bytes.
* \return true for success or false for failure.
*/
bool readSDS(sds_t* sds);
/** Start a read multiple sectors sequence.
*
* \param[in] sector Address of first sector in sequence.
@ -186,7 +198,7 @@ class SdioCard : public SdCardInterface {
bool readStop();
/** \return SDIO card status. */
uint32_t status();
/**
/**
* Determine the size of an SD flash memory card.
*
* \return The number of 512 byte data sectors in the card

View file

@ -24,6 +24,7 @@
*/
#if defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__)
#include "SdioTeensy.h"
#include "SdCardInfo.h"
#include "SdioCard.h"
//==============================================================================
@ -36,39 +37,34 @@ const uint32_t CMD8_RETRIES = 3;
const uint32_t BUSY_TIMEOUT_MICROS = 1000000;
//==============================================================================
const uint32_t SDHC_IRQSTATEN_MASK =
SDHC_IRQSTATEN_DMAESEN | SDHC_IRQSTATEN_AC12ESEN |
SDHC_IRQSTATEN_DEBESEN | SDHC_IRQSTATEN_DCESEN |
SDHC_IRQSTATEN_DTOESEN | SDHC_IRQSTATEN_CIESEN |
SDHC_IRQSTATEN_CEBESEN | SDHC_IRQSTATEN_CCESEN |
SDHC_IRQSTATEN_CTOESEN | SDHC_IRQSTATEN_DINTSEN |
SDHC_IRQSTATEN_TCSEN | SDHC_IRQSTATEN_CCSEN;
SDHC_IRQSTATEN_DMAESEN | SDHC_IRQSTATEN_AC12ESEN | SDHC_IRQSTATEN_DEBESEN |
SDHC_IRQSTATEN_DCESEN | SDHC_IRQSTATEN_DTOESEN | SDHC_IRQSTATEN_CIESEN |
SDHC_IRQSTATEN_CEBESEN | SDHC_IRQSTATEN_CCESEN | SDHC_IRQSTATEN_CTOESEN |
SDHC_IRQSTATEN_DINTSEN | SDHC_IRQSTATEN_TCSEN | SDHC_IRQSTATEN_CCSEN;
const uint32_t SDHC_IRQSTAT_CMD_ERROR =
SDHC_IRQSTAT_CIE | SDHC_IRQSTAT_CEBE |
SDHC_IRQSTAT_CCE | SDHC_IRQSTAT_CTOE;
SDHC_IRQSTAT_CIE | SDHC_IRQSTAT_CEBE | SDHC_IRQSTAT_CCE | SDHC_IRQSTAT_CTOE;
const uint32_t SDHC_IRQSTAT_DATA_ERROR =
SDHC_IRQSTAT_AC12E | SDHC_IRQSTAT_DEBE |
SDHC_IRQSTAT_DCE | SDHC_IRQSTAT_DTOE;
const uint32_t SDHC_IRQSTAT_DATA_ERROR = SDHC_IRQSTAT_AC12E |
SDHC_IRQSTAT_DEBE | SDHC_IRQSTAT_DCE |
SDHC_IRQSTAT_DTOE;
const uint32_t SDHC_IRQSTAT_ERROR =
SDHC_IRQSTAT_DMAE | SDHC_IRQSTAT_CMD_ERROR |
SDHC_IRQSTAT_DATA_ERROR;
SDHC_IRQSTAT_DMAE | SDHC_IRQSTAT_CMD_ERROR | SDHC_IRQSTAT_DATA_ERROR;
const uint32_t SDHC_IRQSIGEN_MASK =
SDHC_IRQSIGEN_DMAEIEN | SDHC_IRQSIGEN_AC12EIEN |
SDHC_IRQSIGEN_DEBEIEN | SDHC_IRQSIGEN_DCEIEN |
SDHC_IRQSIGEN_DTOEIEN | SDHC_IRQSIGEN_CIEIEN |
SDHC_IRQSIGEN_CEBEIEN | SDHC_IRQSIGEN_CCEIEN |
SDHC_IRQSIGEN_CTOEIEN | SDHC_IRQSIGEN_TCIEN;
SDHC_IRQSIGEN_DMAEIEN | SDHC_IRQSIGEN_AC12EIEN | SDHC_IRQSIGEN_DEBEIEN |
SDHC_IRQSIGEN_DCEIEN | SDHC_IRQSIGEN_DTOEIEN | SDHC_IRQSIGEN_CIEIEN |
SDHC_IRQSIGEN_CEBEIEN | SDHC_IRQSIGEN_CCEIEN | SDHC_IRQSIGEN_CTOEIEN |
SDHC_IRQSIGEN_TCIEN;
//==============================================================================
const uint32_t CMD_RESP_NONE = SDHC_XFERTYP_RSPTYP(0);
const uint32_t CMD_RESP_R1 = SDHC_XFERTYP_CICEN | SDHC_XFERTYP_CCCEN |
SDHC_XFERTYP_RSPTYP(2);
const uint32_t CMD_RESP_R1 =
SDHC_XFERTYP_CICEN | SDHC_XFERTYP_CCCEN | SDHC_XFERTYP_RSPTYP(2);
const uint32_t CMD_RESP_R1b = SDHC_XFERTYP_CICEN | SDHC_XFERTYP_CCCEN |
SDHC_XFERTYP_RSPTYP(3);
const uint32_t CMD_RESP_R1b =
SDHC_XFERTYP_CICEN | SDHC_XFERTYP_CCCEN | SDHC_XFERTYP_RSPTYP(3);
const uint32_t CMD_RESP_R2 = SDHC_XFERTYP_CCCEN | SDHC_XFERTYP_RSPTYP(1);
@ -86,26 +82,23 @@ const uint32_t DATA_READ_DMA = DATA_READ | SDHC_XFERTYP_DMAEN;
const uint32_t DATA_READ_MULTI_DMA = DATA_READ_DMA | SDHC_XFERTYP_MSBSEL |
SDHC_XFERTYP_AC12EN | SDHC_XFERTYP_BCEN;
const uint32_t DATA_READ_MULTI_PGM = DATA_READ | SDHC_XFERTYP_MSBSEL |
SDHC_XFERTYP_BCEN;
const uint32_t DATA_READ_MULTI_PGM =
DATA_READ | SDHC_XFERTYP_MSBSEL | SDHC_XFERTYP_BCEN;
const uint32_t DATA_WRITE_DMA = SDHC_XFERTYP_DPSEL | SDHC_XFERTYP_DMAEN;
const uint32_t DATA_WRITE_MULTI_DMA = DATA_WRITE_DMA | SDHC_XFERTYP_MSBSEL |
SDHC_XFERTYP_AC12EN | SDHC_XFERTYP_BCEN;
const uint32_t DATA_WRITE_MULTI_PGM = SDHC_XFERTYP_DPSEL | SDHC_XFERTYP_MSBSEL |
SDHC_XFERTYP_BCEN;
const uint32_t DATA_WRITE_MULTI_PGM =
SDHC_XFERTYP_DPSEL | SDHC_XFERTYP_MSBSEL | SDHC_XFERTYP_BCEN;
#elif defined(__IMXRT1062__)
// Use low bits for SDHC_MIX_CTRL since bits 15-0 of SDHC_XFERTYP are reserved.
const uint32_t SDHC_MIX_CTRL_MASK = SDHC_MIX_CTRL_DMAEN | SDHC_MIX_CTRL_BCEN |
SDHC_MIX_CTRL_AC12EN |
SDHC_MIX_CTRL_DDR_EN |
SDHC_MIX_CTRL_DTDSEL |
SDHC_MIX_CTRL_MSBSEL |
SDHC_MIX_CTRL_NIBBLE_POS |
SDHC_MIX_CTRL_AC23EN;
const uint32_t SDHC_MIX_CTRL_MASK =
SDHC_MIX_CTRL_DMAEN | SDHC_MIX_CTRL_BCEN | SDHC_MIX_CTRL_AC12EN |
SDHC_MIX_CTRL_DDR_EN | SDHC_MIX_CTRL_DTDSEL | SDHC_MIX_CTRL_MSBSEL |
SDHC_MIX_CTRL_NIBBLE_POS | SDHC_MIX_CTRL_AC23EN;
const uint32_t DATA_READ = SDHC_MIX_CTRL_DTDSEL | SDHC_XFERTYP_DPSEL;
@ -116,7 +109,6 @@ const uint32_t DATA_READ_MULTI_DMA = DATA_READ_DMA | SDHC_MIX_CTRL_MSBSEL |
const uint32_t DATA_READ_MULTI_PGM = DATA_READ | SDHC_MIX_CTRL_MSBSEL;
const uint32_t DATA_WRITE_DMA = SDHC_XFERTYP_DPSEL | SDHC_MIX_CTRL_DMAEN;
const uint32_t DATA_WRITE_MULTI_DMA = DATA_WRITE_DMA | SDHC_MIX_CTRL_MSBSEL |
@ -128,10 +120,13 @@ const uint32_t DATA_WRITE_MULTI_PGM = SDHC_XFERTYP_DPSEL | SDHC_MIX_CTRL_MSBSEL;
const uint32_t ACMD6_XFERTYP = SDHC_XFERTYP_CMDINX(ACMD6) | CMD_RESP_R1;
const uint32_t ACMD13_XFERTYP =
SDHC_XFERTYP_CMDINX(ACMD13) | CMD_RESP_R1 | DATA_READ_DMA;
const uint32_t ACMD41_XFERTYP = SDHC_XFERTYP_CMDINX(ACMD41) | CMD_RESP_R3;
const uint32_t ACMD51_XFERTYP = SDHC_XFERTYP_CMDINX(ACMD51) | CMD_RESP_R1 |
DATA_READ_DMA;
const uint32_t ACMD51_XFERTYP =
SDHC_XFERTYP_CMDINX(ACMD51) | CMD_RESP_R1 | DATA_READ_DMA;
const uint32_t CMD0_XFERTYP = SDHC_XFERTYP_CMDINX(CMD0) | CMD_RESP_NONE;
@ -139,8 +134,8 @@ const uint32_t CMD2_XFERTYP = SDHC_XFERTYP_CMDINX(CMD2) | CMD_RESP_R2;
const uint32_t CMD3_XFERTYP = SDHC_XFERTYP_CMDINX(CMD3) | CMD_RESP_R6;
const uint32_t CMD6_XFERTYP = SDHC_XFERTYP_CMDINX(CMD6) | CMD_RESP_R1 |
DATA_READ_DMA;
const uint32_t CMD6_XFERTYP =
SDHC_XFERTYP_CMDINX(CMD6) | CMD_RESP_R1 | DATA_READ_DMA;
const uint32_t CMD7_XFERTYP = SDHC_XFERTYP_CMDINX(CMD7) | CMD_RESP_R1b;
@ -152,28 +147,28 @@ const uint32_t CMD10_XFERTYP = SDHC_XFERTYP_CMDINX(CMD10) | CMD_RESP_R2;
const uint32_t CMD11_XFERTYP = SDHC_XFERTYP_CMDINX(CMD11) | CMD_RESP_R1;
const uint32_t CMD12_XFERTYP = SDHC_XFERTYP_CMDINX(CMD12) | CMD_RESP_R1b |
SDHC_XFERTYP_CMDTYP(3);
const uint32_t CMD12_XFERTYP =
SDHC_XFERTYP_CMDINX(CMD12) | CMD_RESP_R1b | SDHC_XFERTYP_CMDTYP(3);
const uint32_t CMD13_XFERTYP = SDHC_XFERTYP_CMDINX(CMD13) | CMD_RESP_R1;
const uint32_t CMD17_DMA_XFERTYP = SDHC_XFERTYP_CMDINX(CMD17) | CMD_RESP_R1 |
DATA_READ_DMA;
const uint32_t CMD17_DMA_XFERTYP =
SDHC_XFERTYP_CMDINX(CMD17) | CMD_RESP_R1 | DATA_READ_DMA;
const uint32_t CMD18_DMA_XFERTYP = SDHC_XFERTYP_CMDINX(CMD18) | CMD_RESP_R1 |
DATA_READ_MULTI_DMA;
const uint32_t CMD18_DMA_XFERTYP =
SDHC_XFERTYP_CMDINX(CMD18) | CMD_RESP_R1 | DATA_READ_MULTI_DMA;
const uint32_t CMD18_PGM_XFERTYP = SDHC_XFERTYP_CMDINX(CMD18) | CMD_RESP_R1 |
DATA_READ_MULTI_PGM;
const uint32_t CMD18_PGM_XFERTYP =
SDHC_XFERTYP_CMDINX(CMD18) | CMD_RESP_R1 | DATA_READ_MULTI_PGM;
const uint32_t CMD24_DMA_XFERTYP = SDHC_XFERTYP_CMDINX(CMD24) | CMD_RESP_R1 |
DATA_WRITE_DMA;
const uint32_t CMD24_DMA_XFERTYP =
SDHC_XFERTYP_CMDINX(CMD24) | CMD_RESP_R1 | DATA_WRITE_DMA;
const uint32_t CMD25_DMA_XFERTYP = SDHC_XFERTYP_CMDINX(CMD25) | CMD_RESP_R1 |
DATA_WRITE_MULTI_DMA;
const uint32_t CMD25_DMA_XFERTYP =
SDHC_XFERTYP_CMDINX(CMD25) | CMD_RESP_R1 | DATA_WRITE_MULTI_DMA;
const uint32_t CMD25_PGM_XFERTYP = SDHC_XFERTYP_CMDINX(CMD25) | CMD_RESP_R1 |
DATA_WRITE_MULTI_PGM;
const uint32_t CMD25_PGM_XFERTYP =
SDHC_XFERTYP_CMDINX(CMD25) | CMD_RESP_R1 | DATA_WRITE_MULTI_PGM;
const uint32_t CMD32_XFERTYP = SDHC_XFERTYP_CMDINX(CMD32) | CMD_RESP_R1;
@ -212,12 +207,20 @@ static uint32_t m_ocr;
static cid_t m_cid;
static csd_t m_csd;
static scr_t m_scr;
static sds_t m_sds;
//==============================================================================
#define DBG_TRACE Serial.print("TRACE."); Serial.println(__LINE__); delay(200);
#define DBG_TRACE \
Serial.print("TRACE."); \
Serial.println(__LINE__); \
delay(200);
#define USE_DEBUG_MODE 0
#if USE_DEBUG_MODE
#define DBG_IRQSTAT() if (SDHC_IRQSTAT) {Serial.print(__LINE__);\
Serial.print(" IRQSTAT "); Serial.println(SDHC_IRQSTAT, HEX);}
#define DBG_IRQSTAT() \
if (SDHC_IRQSTAT) { \
Serial.print(__LINE__); \
Serial.print(" IRQSTAT "); \
Serial.println(SDHC_IRQSTAT, HEX); \
}
static void printRegs(uint32_t line) {
uint32_t blkattr = SDHC_BLKATTR;
uint32_t xfertyp = SDHC_XFERTYP;
@ -234,36 +237,68 @@ static void printRegs(uint32_t line) {
Serial.print(xfertyp >> 24);
Serial.print(" TYP");
Serial.print((xfertyp >> 2) & 3);
if (xfertyp & SDHC_XFERTYP_DPSEL) {Serial.print(" DPSEL");}
if (xfertyp & SDHC_XFERTYP_DPSEL) {
Serial.print(" DPSEL");
}
Serial.println();
Serial.print("PRSSTAT ");
Serial.print(prsstat, HEX);
if (prsstat & SDHC_PRSSTAT_BREN) {Serial.print(" BREN");}
if (prsstat & SDHC_PRSSTAT_BWEN) {Serial.print(" BWEN");}
if (prsstat & SDHC_PRSSTAT_RTA) {Serial.print(" RTA");}
if (prsstat & SDHC_PRSSTAT_WTA) {Serial.print(" WTA");}
if (prsstat & SDHC_PRSSTAT_SDOFF) {Serial.print(" SDOFF");}
if (prsstat & SDHC_PRSSTAT_PEROFF) {Serial.print(" PEROFF");}
if (prsstat & SDHC_PRSSTAT_HCKOFF) {Serial.print(" HCKOFF");}
if (prsstat & SDHC_PRSSTAT_IPGOFF) {Serial.print(" IPGOFF");}
if (prsstat & SDHC_PRSSTAT_SDSTB) {Serial.print(" SDSTB");}
if (prsstat & SDHC_PRSSTAT_DLA) {Serial.print(" DLA");}
if (prsstat & SDHC_PRSSTAT_CDIHB) {Serial.print(" CDIHB");}
if (prsstat & SDHC_PRSSTAT_CIHB) {Serial.print(" CIHB");}
if (prsstat & SDHC_PRSSTAT_BREN) {
Serial.print(" BREN");
}
if (prsstat & SDHC_PRSSTAT_BWEN) {
Serial.print(" BWEN");
}
if (prsstat & SDHC_PRSSTAT_RTA) {
Serial.print(" RTA");
}
if (prsstat & SDHC_PRSSTAT_WTA) {
Serial.print(" WTA");
}
if (prsstat & SDHC_PRSSTAT_SDOFF) {
Serial.print(" SDOFF");
}
if (prsstat & SDHC_PRSSTAT_PEROFF) {
Serial.print(" PEROFF");
}
if (prsstat & SDHC_PRSSTAT_HCKOFF) {
Serial.print(" HCKOFF");
}
if (prsstat & SDHC_PRSSTAT_IPGOFF) {
Serial.print(" IPGOFF");
}
if (prsstat & SDHC_PRSSTAT_SDSTB) {
Serial.print(" SDSTB");
}
if (prsstat & SDHC_PRSSTAT_DLA) {
Serial.print(" DLA");
}
if (prsstat & SDHC_PRSSTAT_CDIHB) {
Serial.print(" CDIHB");
}
if (prsstat & SDHC_PRSSTAT_CIHB) {
Serial.print(" CIHB");
}
Serial.println();
Serial.print("PROCTL ");
Serial.print(proctl, HEX);
if (proctl & SDHC_PROCTL_SABGREQ) Serial.print(" SABGREQ");
Serial.print(" EMODE");
Serial.print((proctl >>4) & 3);
Serial.print((proctl >> 4) & 3);
Serial.print(" DWT");
Serial.print((proctl >>1) & 3);
Serial.print((proctl >> 1) & 3);
Serial.println();
Serial.print("IRQSTAT ");
Serial.print(irqstat, HEX);
if (irqstat & SDHC_IRQSTAT_BGE) {Serial.print(" BGE");}
if (irqstat & SDHC_IRQSTAT_TC) {Serial.print(" TC");}
if (irqstat & SDHC_IRQSTAT_CC) {Serial.print(" CC");}
if (irqstat & SDHC_IRQSTAT_BGE) {
Serial.print(" BGE");
}
if (irqstat & SDHC_IRQSTAT_TC) {
Serial.print(" TC");
}
if (irqstat & SDHC_IRQSTAT_CC) {
Serial.print(" CC");
}
Serial.print("\nm_irqstat ");
Serial.println(m_irqstat, HEX);
}
@ -298,12 +333,12 @@ static void sdIrs() {
//------------------------------------------------------------------------------
static void enableGPIO(bool enable) {
const uint32_t PORT_CLK = PORT_PCR_MUX(4) | PORT_PCR_DSE;
const uint32_t PORT_CMD_DATA = PORT_CLK | PORT_PCR_PE | PORT_PCR_PS;
const uint32_t PORT_CMD_DATA = PORT_CLK | PORT_PCR_PE | PORT_PCR_PS;
const uint32_t PORT_PUP = PORT_PCR_MUX(1) | PORT_PCR_PE | PORT_PCR_PS;
PORTE_PCR0 = enable ? PORT_CMD_DATA : PORT_PUP; // SDHC_D1
PORTE_PCR1 = enable ? PORT_CMD_DATA : PORT_PUP; // SDHC_D0
PORTE_PCR2 = enable ? PORT_CLK : PORT_PUP; // SDHC_CLK
PORTE_PCR2 = enable ? PORT_CLK : PORT_PUP; // SDHC_CLK
PORTE_PCR3 = enable ? PORT_CMD_DATA : PORT_PUP; // SDHC_CMD
PORTE_PCR4 = enable ? PORT_CMD_DATA : PORT_PUP; // SDHC_D3
PORTE_PCR5 = enable ? PORT_CMD_DATA : PORT_PUP; // SDHC_D2
@ -317,7 +352,7 @@ static void initClock() {
// Enable SDHC clock.
SIM_SCGC3 |= SIM_SCGC3_SDHC;
}
static uint32_t baseClock() { return F_CPU;}
static uint32_t baseClock() { return F_CPU; }
#elif defined(__IMXRT1062__)
//------------------------------------------------------------------------------
@ -335,13 +370,13 @@ static void enableGPIO(bool enable) {
const uint32_t CLOCK_MASK = IOMUXC_SW_PAD_CTL_PAD_PKE |
#if defined(ARDUINO_TEENSY41)
IOMUXC_SW_PAD_CTL_PAD_DSE(7) |
#else // defined(ARDUINO_TEENSY41)
#else // defined(ARDUINO_TEENSY41)
IOMUXC_SW_PAD_CTL_PAD_DSE(4) | ///// WHG
#endif // defined(ARDUINO_TEENSY41)
IOMUXC_SW_PAD_CTL_PAD_SPEED(2);
const uint32_t DATA_MASK = CLOCK_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE |
IOMUXC_SW_PAD_CTL_PAD_PUS(1);
const uint32_t DATA_MASK =
CLOCK_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE | IOMUXC_SW_PAD_CTL_PAD_PUS(1);
if (enable) {
gpioMux(0);
IOMUXC_SW_PAD_CTL_PAD_GPIO_SD_B0_04 = DATA_MASK; // DAT2
@ -365,20 +400,20 @@ static void initClock() {
/* Enable USDHC clock. */
CCM_CCGR6 |= CCM_CCGR6_USDHC1(CCM_CCGR_ON);
CCM_CSCDR1 &= ~(CCM_CSCDR1_USDHC1_CLK_PODF_MASK);
CCM_CSCMR1 |= CCM_CSCMR1_USDHC1_CLK_SEL; // PLL2PFD0
// CCM_CSCDR1 |= CCM_CSCDR1_USDHC1_CLK_PODF((7)); / &0x7 WHG
CCM_CSCMR1 |= CCM_CSCMR1_USDHC1_CLK_SEL; // PLL2PFD0
// CCM_CSCDR1 |= CCM_CSCDR1_USDHC1_CLK_PODF((7)); / &0x7 WHG
CCM_CSCDR1 |= CCM_CSCDR1_USDHC1_CLK_PODF((1));
}
//------------------------------------------------------------------------------
static uint32_t baseClock() {
uint32_t divider = ((CCM_CSCDR1 >> 11) & 0x7) + 1;
return (528000000U * 3)/((CCM_ANALOG_PFD_528 & 0x3F)/6)/divider;
return (528000000U * 3) / ((CCM_ANALOG_PFD_528 & 0x3F) / 6) / divider;
}
#endif // defined(__MK64FX512__) || defined(__MK66FX1M0__)
//==============================================================================
// Static functions.
static bool cardAcmd(uint32_t rca, uint32_t xfertyp, uint32_t arg) {
return cardCommand(CMD55_XFERTYP, rca) && cardCommand (xfertyp, arg);
return cardCommand(CMD55_XFERTYP, rca) && cardCommand(xfertyp, arg);
}
//------------------------------------------------------------------------------
static bool cardCommand(uint32_t xfertyp, uint32_t arg) {
@ -402,8 +437,25 @@ static bool cardCommand(uint32_t xfertyp, uint32_t arg) {
m_irqstat = SDHC_IRQSTAT;
SDHC_IRQSTAT = m_irqstat;
return (m_irqstat & SDHC_IRQSTAT_CC) &&
!(m_irqstat & SDHC_IRQSTAT_CMD_ERROR);
return (m_irqstat & SDHC_IRQSTAT_CC) && !(m_irqstat & SDHC_IRQSTAT_CMD_ERROR);
}
//------------------------------------------------------------------------------
static bool cardACMD13(sds_t* scr) {
// ACMD13 returns 64 bytes.
if (waitTimeout(isBusyCMD13)) {
return sdError(SD_CARD_ERROR_CMD13);
}
enableDmaIrs();
SDHC_DSADDR = (uint32_t)scr;
SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(1) | SDHC_BLKATTR_BLKSIZE(64);
SDHC_IRQSIGEN = SDHC_IRQSIGEN_MASK;
if (!cardAcmd(m_rca, ACMD13_XFERTYP, 0)) {
return sdError(SD_CARD_ERROR_ACMD13);
}
if (!waitDmaStatus()) {
return sdError(SD_CARD_ERROR_DMA);
}
return true;
}
//------------------------------------------------------------------------------
static bool cardACMD51(scr_t* scr) {
@ -412,7 +464,7 @@ static bool cardACMD51(scr_t* scr) {
return sdError(SD_CARD_ERROR_CMD13);
}
enableDmaIrs();
SDHC_DSADDR = (uint32_t)scr;
SDHC_DSADDR = (uint32_t)scr;
SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(1) | SDHC_BLKATTR_BLKSIZE(8);
SDHC_IRQSIGEN = SDHC_IRQSIGEN_MASK;
if (!cardAcmd(m_rca, ACMD51_XFERTYP, 0)) {
@ -435,7 +487,7 @@ static void initSDHC() {
// Disable GPIO clock.
enableGPIO(false);
#if defined (__IMXRT1062__)
#if defined(__IMXRT1062__)
SDHC_MIX_CTRL |= 0x80000000;
#endif // (__IMXRT1062__)
@ -454,7 +506,7 @@ static void initSDHC() {
SDHC_IRQSTATEN = SDHC_IRQSTATEN_MASK;
attachInterruptVector(IRQ_SDHC, sdIrs);
NVIC_SET_PRIORITY(IRQ_SDHC, 6*16);
NVIC_SET_PRIORITY(IRQ_SDHC, 6 * 16);
NVIC_ENABLE_IRQ(IRQ_SDHC);
// Send 80 clocks to card.
@ -475,32 +527,22 @@ static bool isBusyCommandComplete() {
return !(SDHC_IRQSTAT & (SDHC_IRQSTAT_CC | SDHC_IRQSTAT_CMD_ERROR));
}
//------------------------------------------------------------------------------
static bool isBusyCommandInhibit() {
return SDHC_PRSSTAT & SDHC_PRSSTAT_CIHB;
}
static bool isBusyCommandInhibit() { return SDHC_PRSSTAT & SDHC_PRSSTAT_CIHB; }
//------------------------------------------------------------------------------
static bool isBusyDat() {
return SDHC_PRSSTAT & (1 << 24) ? false : true;
}
static bool isBusyDat() { return SDHC_PRSSTAT & (1 << 24) ? false : true; }
//------------------------------------------------------------------------------
static bool isBusyDMA() {
return m_dmaBusy;
}
static bool isBusyDMA() { return m_dmaBusy; }
//------------------------------------------------------------------------------
static bool isBusyFifoRead() {
return !(SDHC_PRSSTAT & SDHC_PRSSTAT_BREN);
}
static bool isBusyFifoRead() { return !(SDHC_PRSSTAT & SDHC_PRSSTAT_BREN); }
//------------------------------------------------------------------------------
static bool isBusyFifoWrite() {
return !(SDHC_PRSSTAT & SDHC_PRSSTAT_BWEN);
}
static bool isBusyFifoWrite() { return !(SDHC_PRSSTAT & SDHC_PRSSTAT_BWEN); }
//------------------------------------------------------------------------------
static bool isBusyTransferComplete() {
return !(SDHC_IRQSTAT & (SDHC_IRQSTAT_TC | SDHC_IRQSTAT_ERROR));
}
//------------------------------------------------------------------------------
static bool rdWrSectors(uint32_t xfertyp,
uint32_t sector, uint8_t* buf, size_t n) {
static bool rdWrSectors(uint32_t xfertyp, uint32_t sector, uint8_t* buf,
size_t n) {
if ((3 & (uint32_t)buf) || n == 0) {
return sdError(SD_CARD_ERROR_DMA);
}
@ -508,10 +550,10 @@ static bool rdWrSectors(uint32_t xfertyp,
return sdError(SD_CARD_ERROR_CMD13);
}
enableDmaIrs();
SDHC_DSADDR = (uint32_t)buf;
SDHC_DSADDR = (uint32_t)buf;
SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(n) | SDHC_BLKATTR_BLKSIZE(512);
SDHC_IRQSIGEN = SDHC_IRQSIGEN_MASK;
if (!cardCommand(xfertyp, m_highCapacity ? sector : 512*sector)) {
if (!cardCommand(xfertyp, m_highCapacity ? sector : 512 * sector)) {
return false;
}
return waitDmaStatus();
@ -525,7 +567,7 @@ static bool readReg16(uint32_t xfertyp, void* data) {
}
uint32_t sr[] = {SDHC_CMDRSP0, SDHC_CMDRSP1, SDHC_CMDRSP2, SDHC_CMDRSP3};
for (int i = 0; i < 15; i++) {
d[14 - i] = sr[i/4] >> 8*(i%4);
d[14 - i] = sr[i / 4] >> 8 * (i % 4);
}
d[15] = 0;
return true;
@ -536,16 +578,17 @@ static void setSdclk(uint32_t kHzMax) {
const uint32_t SDCLKFS_LIMIT = 0X100;
uint32_t dvs = 1;
uint32_t sdclkfs = 1;
uint32_t maxSdclk = 1000*kHzMax;
uint32_t maxSdclk = 1000 * kHzMax;
uint32_t base = baseClock();
while ((base/(sdclkfs*DVS_LIMIT) > maxSdclk) && (sdclkfs < SDCLKFS_LIMIT)) {
while ((base / (sdclkfs * DVS_LIMIT) > maxSdclk) &&
(sdclkfs < SDCLKFS_LIMIT)) {
sdclkfs <<= 1;
}
while ((base/(sdclkfs*dvs) > maxSdclk) && (dvs < DVS_LIMIT)) {
while ((base / (sdclkfs * dvs) > maxSdclk) && (dvs < DVS_LIMIT)) {
dvs++;
}
m_sdClkKhz = base/(1000*sdclkfs*dvs);
m_sdClkKhz = base / (1000 * sdclkfs * dvs);
sdclkfs >>= 1;
dvs--;
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
@ -554,11 +597,12 @@ static void setSdclk(uint32_t kHzMax) {
#endif // defined(__MK64FX512__) || defined(__MK66FX1M0__)
// Change dividers.
uint32_t sysctl = SDHC_SYSCTL & ~(SDHC_SYSCTL_DTOCV_MASK
| SDHC_SYSCTL_DVS_MASK | SDHC_SYSCTL_SDCLKFS_MASK);
uint32_t sysctl =
SDHC_SYSCTL & ~(SDHC_SYSCTL_DTOCV_MASK | SDHC_SYSCTL_DVS_MASK |
SDHC_SYSCTL_SDCLKFS_MASK);
SDHC_SYSCTL = sysctl | SDHC_SYSCTL_DTOCV(0x0E) | SDHC_SYSCTL_DVS(dvs)
| SDHC_SYSCTL_SDCLKFS(sdclkfs);
SDHC_SYSCTL = sysctl | SDHC_SYSCTL_DTOCV(0x0E) | SDHC_SYSCTL_DVS(dvs) |
SDHC_SYSCTL_SDCLKFS(sdclkfs);
// Wait until the SDHC clock is stable.
while (!(SDHC_PRSSTAT & SDHC_PRSSTAT_SDSTB)) {
@ -667,14 +711,15 @@ bool SdioCard::begin(SdioConfig sdioConfig) {
break;
}
SDHC_SYSCTL |= SDHC_SYSCTL_RSTA;
while (SDHC_SYSCTL & SDHC_SYSCTL_RSTA) {}
while (SDHC_SYSCTL & SDHC_SYSCTL_RSTA) {
}
}
// Must support 3.2-3.4 Volts
arg = m_version2 ? 0X40300000 : 0x00300000;
int m = micros();
do {
if (!cardAcmd(0, ACMD41_XFERTYP, arg) ||
((micros() - m) > BUSY_TIMEOUT_MICROS)) {
((micros() - m) > BUSY_TIMEOUT_MICROS)) {
return sdError(SD_CARD_ERROR_ACMD41);
}
} while ((SDHC_CMDRSP0 & 0x80000000) == 0);
@ -713,11 +758,13 @@ bool SdioCard::begin(SdioConfig sdioConfig) {
if (!cardACMD51(&m_scr)) {
return false;
}
if (!cardACMD13(&m_sds)) {
return false;
}
// 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 (m_scr.sdSpec() > 0 &&
cardCMD6(0X00FFFFFF, status) && (2 & status[13]) &&
if (m_scr.sdSpec() > 0 && cardCMD6(0X00FFFFFF, status) && (2 & status[13]) &&
cardCMD6(0X80FFFFF1, status) && (status[16] & 0XF) == 1) {
kHzSdClk = 50000;
} else {
@ -741,7 +788,7 @@ bool SdioCard::cardCMD6(uint32_t arg, uint8_t* status) {
return sdError(SD_CARD_ERROR_CMD13);
}
enableDmaIrs();
SDHC_DSADDR = (uint32_t)status;
SDHC_DSADDR = (uint32_t)status;
SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(1) | SDHC_BLKATTR_BLKSIZE(64);
SDHC_IRQSIGEN = SDHC_IRQSIGEN_MASK;
if (!cardCommand(CMD6_XFERTYP, arg)) {
@ -774,7 +821,7 @@ bool SdioCard::erase(uint32_t firstSector, uint32_t lastSector) {
return sdError(SD_CARD_ERROR_CMD32);
}
if (!cardCommand(CMD33_XFERTYP, lastSector)) {
return sdError(SD_CARD_ERROR_CMD33);
return sdError(SD_CARD_ERROR_CMD33);
}
if (!cardCommand(CMD38_XFERTYP, 0)) {
return sdError(SD_CARD_ERROR_CMD38);
@ -785,17 +832,11 @@ bool SdioCard::erase(uint32_t firstSector, uint32_t lastSector) {
return true;
}
//------------------------------------------------------------------------------
uint8_t SdioCard::errorCode() const {
return m_errorCode;
}
uint8_t SdioCard::errorCode() const { return m_errorCode; }
//------------------------------------------------------------------------------
uint32_t SdioCard::errorData() const {
return m_irqstat;
}
uint32_t SdioCard::errorData() const { return m_irqstat; }
//------------------------------------------------------------------------------
uint32_t SdioCard::errorLine() const {
return m_errorLine;
}
uint32_t SdioCard::errorLine() const { return m_errorLine; }
//------------------------------------------------------------------------------
bool SdioCard::isBusy() {
if (m_sdioConfig.useDma()) {
@ -812,7 +853,7 @@ bool SdioCard::isBusy() {
m_transferActive = false;
stopTransmission(false);
return true;
#else // defined(__MK64FX512__) || defined(__MK66FX1M0__)
#else // defined(__MK64FX512__) || defined(__MK66FX1M0__)
return false;
#endif // defined(__MK64FX512__) || defined(__MK66FX1M0__)
}
@ -821,17 +862,15 @@ bool SdioCard::isBusy() {
}
}
//------------------------------------------------------------------------------
uint32_t SdioCard::kHzSdClk() {
return m_sdClkKhz;
}
uint32_t SdioCard::kHzSdClk() { return m_sdClkKhz; }
//------------------------------------------------------------------------------
bool SdioCard::readCID(cid_t* cid) {
memcpy(cid, &m_cid, 16);
memcpy(cid, &m_cid, sizeof(cid_t));
return true;
}
//------------------------------------------------------------------------------
bool SdioCard::readCSD(csd_t* csd) {
memcpy(csd, &m_csd, 16);
memcpy(csd, &m_csd, sizeof(csd_t));
return true;
}
//------------------------------------------------------------------------------
@ -849,7 +888,7 @@ bool SdioCard::readData(uint8_t* dst) {
if (waitTimeout(isBusyFifoRead)) {
return sdError(SD_CARD_ERROR_READ_FIFO);
}
for (uint32_t iw = 0 ; iw < 512/(4*FIFO_WML); iw++) {
for (uint32_t iw = 0; iw < 512 / (4 * FIFO_WML); iw++) {
while (0 == (SDHC_PRSSTAT & SDHC_PRSSTAT_BREN)) {
}
for (uint32_t i = 0; i < FIFO_WML; i++) {
@ -871,7 +910,12 @@ bool SdioCard::readOCR(uint32_t* ocr) {
}
//------------------------------------------------------------------------------
bool SdioCard::readSCR(scr_t* scr) {
memcpy(scr, &m_scr, 8);
memcpy(scr, &m_scr, sizeof(scr_t));
return true;
}
//------------------------------------------------------------------------------
bool SdioCard::readSDS(sds_t* sds) {
memcpy(sds, &m_sds, sizeof(sds_t));
return true;
}
//------------------------------------------------------------------------------
@ -931,7 +975,7 @@ bool SdioCard::readSectors(uint32_t sector, uint8_t* dst, size_t n) {
}
} else {
for (size_t i = 0; i < n; i++) {
if (!readSector(sector + i, dst + i*512UL)) {
if (!readSector(sector + i, dst + i * 512UL)) {
return false;
}
}
@ -949,28 +993,22 @@ bool SdioCard::readStart(uint32_t sector) {
#if defined(__IMXRT1062__)
// Infinite transfer.
SDHC_BLKATTR = SDHC_BLKATTR_BLKSIZE(512);
#else // defined(__IMXRT1062__)
#else // defined(__IMXRT1062__)
// Errata - can't do infinite transfer.
SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(MAX_BLKCNT) | SDHC_BLKATTR_BLKSIZE(512);
#endif // defined(__IMXRT1062__)
if (!cardCommand(CMD18_PGM_XFERTYP, m_highCapacity ? sector : 512*sector)) {
if (!cardCommand(CMD18_PGM_XFERTYP, m_highCapacity ? sector : 512 * sector)) {
return sdError(SD_CARD_ERROR_CMD18);
}
return true;
}
//------------------------------------------------------------------------------
bool SdioCard::readStop() {
return transferStop();
}
bool SdioCard::readStop() { return transferStop(); }
//------------------------------------------------------------------------------
uint32_t SdioCard::sectorCount() {
return m_csd.capacity();
}
uint32_t SdioCard::sectorCount() { return m_csd.capacity(); }
//------------------------------------------------------------------------------
uint32_t SdioCard::status() {
return statusCMD13();
}
uint32_t SdioCard::status() { return statusCMD13(); }
//------------------------------------------------------------------------------
bool SdioCard::stopTransmission(bool blocking) {
m_curState = IDLE_STATE;
@ -998,8 +1036,8 @@ bool SdioCard::syncDevice() {
}
//------------------------------------------------------------------------------
uint8_t SdioCard::type() const {
return m_version2 ? m_highCapacity ?
SD_CARD_TYPE_SDHC : SD_CARD_TYPE_SD2 : SD_CARD_TYPE_SD1;
return m_version2 ? m_highCapacity ? SD_CARD_TYPE_SDHC : SD_CARD_TYPE_SD2
: SD_CARD_TYPE_SD1;
}
//------------------------------------------------------------------------------
bool SdioCard::writeData(const uint8_t* src) {
@ -1016,7 +1054,7 @@ bool SdioCard::writeData(const uint8_t* src) {
if (waitTimeout(isBusyFifoWrite)) {
return sdError(SD_CARD_ERROR_WRITE_FIFO);
}
for (uint32_t iw = 0 ; iw < 512/(4*FIFO_WML); iw++) {
for (uint32_t iw = 0; iw < 512 / (4 * FIFO_WML); iw++) {
while (0 == (SDHC_PRSSTAT & SDHC_PRSSTAT_BWEN)) {
}
for (uint32_t i = 0; i < FIFO_WML; i++) {
@ -1057,7 +1095,7 @@ bool SdioCard::writeSector(uint32_t sector, const uint8_t* src) {
if (!syncDevice()) {
return false;
}
if (!writeStart(sector )) {
if (!writeStart(sector)) {
return false;
}
m_curSector = sector;
@ -1087,7 +1125,7 @@ bool SdioCard::writeSectors(uint32_t sector, const uint8_t* src, size_t n) {
}
} else {
for (size_t i = 0; i < n; i++) {
if (!writeSector(sector + i, src + i*512UL)) {
if (!writeSector(sector + i, src + i * 512UL)) {
return false;
}
}
@ -1104,17 +1142,15 @@ bool SdioCard::writeStart(uint32_t sector) {
#if defined(__IMXRT1062__)
// Infinite transfer.
SDHC_BLKATTR = SDHC_BLKATTR_BLKSIZE(512);
#else // defined(__IMXRT1062__)
#else // defined(__IMXRT1062__)
// Errata - can't do infinite transfer.
SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(MAX_BLKCNT) | SDHC_BLKATTR_BLKSIZE(512);
#endif // defined(__IMXRT1062__)
if (!cardCommand(CMD25_PGM_XFERTYP, m_highCapacity ? sector : 512*sector)) {
if (!cardCommand(CMD25_PGM_XFERTYP, m_highCapacity ? sector : 512 * sector)) {
return sdError(SD_CARD_ERROR_CMD25);
}
return true;
}
//------------------------------------------------------------------------------
bool SdioCard::writeStop() {
return transferStop();
}
bool SdioCard::writeStop() { return transferStop(); }
#endif // defined(__MK64FX512__) defined(__MK66FX1M0__) defined(__IMXRT1062__)

View file

@ -1,277 +1,530 @@
/**
* \file
* \brief Definitions for Teensy HDHC.
*/
#ifndef SdioTeensy_h
#define SdioTeensy_h
// 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_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 SDHC_BLKATTR_BLKSIZE_MASK MAKE_REG_MASK(0x1FFF,0) //uint32_t)(((n) & 0x1FFF)<<0) // Transfer Block Size Mask
#define SDHC_BLKATTR_BLKSIZE(n) MAKE_REG_SET(n,0x1FFF,0) //uint32_t)(((n) & 0x1FFF)<<0) // Transfer Block Size
#define SDHC_BLKATTR_BLKCNT_MASK MAKE_REG_MASK(0x1FFF,16) //((uint32_t)0x1FFF<<16)
#define SDHC_BLKATTR_BLKCNT(n) MAKE_REG_SET(n,0x1FFF,16) //(uint32_t)(((n) & 0x1FFF)<<16) // Blocks Count For Current Transfer
#define SDHC_BLKATTR_BLKSIZE_MASK \
MAKE_REG_MASK( \
0x1FFF, 0) // uint32_t)(((n) & 0x1FFF)<<0) // Transfer Block Size Mask
#define SDHC_BLKATTR_BLKSIZE(n) \
MAKE_REG_SET(n, 0x1FFF, \
0) // uint32_t)(((n) & 0x1FFF)<<0) // Transfer Block Size
#define SDHC_BLKATTR_BLKCNT_MASK \
MAKE_REG_MASK(0x1FFF, 16) //((uint32_t)0x1FFF<<16)
#define SDHC_BLKATTR_BLKCNT(n) \
MAKE_REG_SET(n, 0x1FFF, 16) //(uint32_t)(((n) & 0x1FFF)<<16) // Blocks Count
// For Current Transfer
#define SDHC_XFERTYP_CMDINX(n) MAKE_REG_SET(n,0x3F,24) //(uint32_t)(((n) & 0x3F)<<24)// Command Index
#define SDHC_XFERTYP_CMDTYP(n) MAKE_REG_SET(n,0x3,22) //(uint32_t)(((n) & 0x3)<<22) // Command Type
#define SDHC_XFERTYP_DPSEL MAKE_REG_MASK(0x1,21) //((uint32_t)0x00200000) // Data Present Select
#define SDHC_XFERTYP_CICEN MAKE_REG_MASK(0x1,20) //((uint32_t)0x00100000) // Command Index Check Enable
#define SDHC_XFERTYP_CCCEN MAKE_REG_MASK(0x1,19) //((uint32_t)0x00080000) // Command CRC Check Enable
#define SDHC_XFERTYP_RSPTYP(n) MAKE_REG_SET(n,0x3,16) //(uint32_t)(((n) & 0x3)<<16) // Response Type Select
#define SDHC_XFERTYP_MSBSEL MAKE_REG_MASK(0x1,5) //((uint32_t)0x00000020) // Multi/Single Block Select
#define SDHC_XFERTYP_DTDSEL MAKE_REG_MASK(0x1,4) //((uint32_t)0x00000010) // Data Transfer Direction Select
#define SDHC_XFERTYP_AC12EN MAKE_REG_MASK(0x1,2) //((uint32_t)0x00000004) // Auto CMD12 Enable
#define SDHC_XFERTYP_BCEN MAKE_REG_MASK(0x1,1) //((uint32_t)0x00000002) // Block Count Enable
#define SDHC_XFERTYP_DMAEN MAKE_REG_MASK(0x3,0) //((uint32_t)0x00000001) // DMA Enable
#define SDHC_XFERTYP_CMDINX(n) \
MAKE_REG_SET(n, 0x3F, 24) //(uint32_t)(((n) & 0x3F)<<24)// Command Index
#define SDHC_XFERTYP_CMDTYP(n) \
MAKE_REG_SET(n, 0x3, 22) //(uint32_t)(((n) & 0x3)<<22) // Command Type
#define SDHC_XFERTYP_DPSEL \
MAKE_REG_MASK(0x1, 21) //((uint32_t)0x00200000) // Data Present Select
#define SDHC_XFERTYP_CICEN \
MAKE_REG_MASK(0x1, \
20) //((uint32_t)0x00100000) // Command Index Check Enable
#define SDHC_XFERTYP_CCCEN \
MAKE_REG_MASK(0x1, \
19) //((uint32_t)0x00080000) // Command CRC Check Enable
#define SDHC_XFERTYP_RSPTYP(n) \
MAKE_REG_SET(n, 0x3, \
16) //(uint32_t)(((n) & 0x3)<<16) // Response Type Select
#define SDHC_XFERTYP_MSBSEL \
MAKE_REG_MASK(0x1, 5) //((uint32_t)0x00000020) // Multi/Single Block Select
#define SDHC_XFERTYP_DTDSEL \
MAKE_REG_MASK( \
0x1, 4) //((uint32_t)0x00000010) // Data Transfer Direction Select
#define SDHC_XFERTYP_AC12EN \
MAKE_REG_MASK(0x1, 2) //((uint32_t)0x00000004) // Auto CMD12 Enable
#define SDHC_XFERTYP_BCEN \
MAKE_REG_MASK(0x1, 1) //((uint32_t)0x00000002) // Block Count Enable
#define SDHC_XFERTYP_DMAEN \
MAKE_REG_MASK(0x3, 0) //((uint32_t)0x00000001) // DMA Enable
#define SDHC_PRSSTAT_DLSL_MASK MAKE_REG_MASK(0xFF,24) //((uint32_t)0xFF000000) // DAT Line Signal Level
#define SDHC_PRSSTAT_CLSL MAKE_REG_MASK(0x1,23) //((uint32_t)0x00800000) // CMD Line Signal Level
#define SDHC_PRSSTAT_WPSPL MAKE_REG_MASK(0x1,19) //
#define SDHC_PRSSTAT_CDPL MAKE_REG_MASK(0x1,18) //
#define SDHC_PRSSTAT_CINS MAKE_REG_MASK(0x1,16) //((uint32_t)0x00010000) // Card Inserted
#define SDHC_PRSSTAT_TSCD MAKE_REG_MASK(0x1,15)
#define SDHC_PRSSTAT_RTR MAKE_REG_MASK(0x1,12)
#define SDHC_PRSSTAT_BREN MAKE_REG_MASK(0x1,11) //((uint32_t)0x00000800) // Buffer Read Enable
#define SDHC_PRSSTAT_BWEN MAKE_REG_MASK(0x1,10) //((uint32_t)0x00000400) // Buffer Write Enable
#define SDHC_PRSSTAT_RTA MAKE_REG_MASK(0x1,9) //((uint32_t)0x00000200) // Read Transfer Active
#define SDHC_PRSSTAT_WTA MAKE_REG_MASK(0x1,8) //((uint32_t)0x00000100) // Write Transfer Active
#define SDHC_PRSSTAT_SDOFF MAKE_REG_MASK(0x1,7) //((uint32_t)0x00000080) // SD Clock Gated Off Internally
#define SDHC_PRSSTAT_PEROFF MAKE_REG_MASK(0x1,6) //((uint32_t)0x00000040) // SDHC clock Gated Off Internally
#define SDHC_PRSSTAT_HCKOFF MAKE_REG_MASK(0x1,5) //((uint32_t)0x00000020) // System Clock Gated Off Internally
#define SDHC_PRSSTAT_IPGOFF MAKE_REG_MASK(0x1,4) //((uint32_t)0x00000010) // Bus Clock Gated Off Internally
#define SDHC_PRSSTAT_SDSTB MAKE_REG_MASK(0x1,3) //((uint32_t)0x00000008) // SD Clock Stable
#define SDHC_PRSSTAT_DLA MAKE_REG_MASK(0x1,2) //((uint32_t)0x00000004) // Data Line Active
#define SDHC_PRSSTAT_CDIHB MAKE_REG_MASK(0x1,1) //((uint32_t)0x00000002) // Command Inhibit (DAT)
#define SDHC_PRSSTAT_CIHB MAKE_REG_MASK(0x1,0) //((uint32_t)0x00000001) // Command Inhibit (CMD)
#define SDHC_PRSSTAT_DLSL_MASK \
MAKE_REG_MASK(0xFF, 24) //((uint32_t)0xFF000000) // DAT Line Signal Level
#define SDHC_PRSSTAT_CLSL \
MAKE_REG_MASK(0x1, 23) //((uint32_t)0x00800000) // CMD Line Signal Level
#define SDHC_PRSSTAT_WPSPL MAKE_REG_MASK(0x1, 19) //
#define SDHC_PRSSTAT_CDPL MAKE_REG_MASK(0x1, 18) //
#define SDHC_PRSSTAT_CINS \
MAKE_REG_MASK(0x1, 16) //((uint32_t)0x00010000) // Card Inserted
#define SDHC_PRSSTAT_TSCD MAKE_REG_MASK(0x1, 15)
#define SDHC_PRSSTAT_RTR MAKE_REG_MASK(0x1, 12)
#define SDHC_PRSSTAT_BREN \
MAKE_REG_MASK(0x1, 11) //((uint32_t)0x00000800) // Buffer Read Enable
#define SDHC_PRSSTAT_BWEN \
MAKE_REG_MASK(0x1, 10) //((uint32_t)0x00000400) // Buffer Write Enable
#define SDHC_PRSSTAT_RTA \
MAKE_REG_MASK(0x1, 9) //((uint32_t)0x00000200) // Read Transfer Active
#define SDHC_PRSSTAT_WTA \
MAKE_REG_MASK(0x1, 8) //((uint32_t)0x00000100) // Write Transfer Active
#define SDHC_PRSSTAT_SDOFF \
MAKE_REG_MASK( \
0x1, 7) //((uint32_t)0x00000080) // SD Clock Gated Off Internally
#define SDHC_PRSSTAT_PEROFF \
MAKE_REG_MASK( \
0x1, 6) //((uint32_t)0x00000040) // SDHC clock Gated Off Internally
#define SDHC_PRSSTAT_HCKOFF \
MAKE_REG_MASK( \
0x1, 5) //((uint32_t)0x00000020) // System Clock Gated Off Internally
#define SDHC_PRSSTAT_IPGOFF \
MAKE_REG_MASK( \
0x1, 4) //((uint32_t)0x00000010) // Bus Clock Gated Off Internally
#define SDHC_PRSSTAT_SDSTB \
MAKE_REG_MASK(0x1, 3) //((uint32_t)0x00000008) // SD Clock Stable
#define SDHC_PRSSTAT_DLA \
MAKE_REG_MASK(0x1, 2) //((uint32_t)0x00000004) // Data Line Active
#define SDHC_PRSSTAT_CDIHB \
MAKE_REG_MASK(0x1, 1) //((uint32_t)0x00000002) // Command Inhibit (DAT)
#define SDHC_PRSSTAT_CIHB \
MAKE_REG_MASK(0x1, 0) //((uint32_t)0x00000001) // Command Inhibit (CMD)
#define SDHC_PROTCT_NONEXACT_BLKRD MAKE_REG_MASK(0x1,30) //
#define SDHC_PROTCT_BURST_LENEN(n) MAKE_REG_SET(n,0x7,12) //
#define SDHC_PROCTL_WECRM MAKE_REG_MASK(0x1,26) //((uint32_t)0x04000000) // Wakeup Event Enable On SD Card Removal
#define SDHC_PROCTL_WECINS MAKE_REG_MASK(0x1,25) //((uint32_t)0x02000000) // Wakeup Event Enable On SD Card Insertion
#define SDHC_PROCTL_WECINT MAKE_REG_MASK(0x1,24) //((uint32_t)0x01000000) // Wakeup Event Enable On Card Interrupt
#define SDHC_PROCTL_RD_DONE_NOBLK MAKE_REG_MASK(0x1,20) //
#define SDHC_PROCTL_IABG MAKE_REG_MASK(0x1,19) //((uint32_t)0x00080000) // Interrupt At Block Gap
#define SDHC_PROCTL_RWCTL MAKE_REG_MASK(0x1,18) //((uint32_t)0x00040000) // Read Wait Control
#define SDHC_PROCTL_CREQ MAKE_REG_MASK(0x1,17) //((uint32_t)0x00020000) // Continue Request
#define SDHC_PROCTL_SABGREQ MAKE_REG_MASK(0x1,16) //((uint32_t)0x00010000) // Stop At Block Gap Request
#define SDHC_PROCTL_DMAS(n) MAKE_REG_SET(n,0x3,8) //(uint32_t)(((n) & 0x3)<<8) // DMA Select
#define SDHC_PROCTL_CDSS MAKE_REG_MASK(0x1,7) //((uint32_t)0x00000080) // Card Detect Signal Selection
#define SDHC_PROCTL_CDTL MAKE_REG_MASK(0x1,6) //((uint32_t)0x00000040) // Card Detect Test Level
#define SDHC_PROCTL_EMODE(n) MAKE_REG_SET(n,0x3,4) //(uint32_t)(((n) & 0x3)<<4) // Endian Mode
#define SDHC_PROCTL_EMODE_MASK MAKE_REG_MASK(0x3,4) //(uint32_t)((0x3)<<4) // Endian Mode
#define SDHC_PROCTL_D3CD MAKE_REG_MASK(0x1,3) //((uint32_t)0x00000008) // DAT3 As Card Detection Pin
#define SDHC_PROCTL_DTW(n) MAKE_REG_SET(n,0x3,1) //(uint32_t)(((n) & 0x3)<<1) // Data Transfer Width, 0=1bit, 1=4bit, 2=8bit
#define SDHC_PROCTL_DTW_MASK MAKE_REG_MASK(0x3,1) //((uint32_t)0x00000006)
#define SDHC_PROCTL_LCTL MAKE_REG_MASK(0x1,0) //((uint32_t)0x00000001) // LED Control
#define SDHC_PROTCT_NONEXACT_BLKRD MAKE_REG_MASK(0x1, 30) //
#define SDHC_PROTCT_BURST_LENEN(n) MAKE_REG_SET(n, 0x7, 12) //
#define SDHC_PROCTL_WECRM \
MAKE_REG_MASK(0x1, 26) //((uint32_t)0x04000000) // Wakeup Event Enable On
// SD Card Removal
#define SDHC_PROCTL_WECINS \
MAKE_REG_MASK(0x1, 25) //((uint32_t)0x02000000) // Wakeup Event Enable On
// SD Card Insertion
#define SDHC_PROCTL_WECINT \
MAKE_REG_MASK(0x1, 24) //((uint32_t)0x01000000) // Wakeup Event Enable On
// Card Interrupt
#define SDHC_PROCTL_RD_DONE_NOBLK MAKE_REG_MASK(0x1, 20) //
#define SDHC_PROCTL_IABG \
MAKE_REG_MASK(0x1, 19) //((uint32_t)0x00080000) // Interrupt At Block Gap
#define SDHC_PROCTL_RWCTL \
MAKE_REG_MASK(0x1, 18) //((uint32_t)0x00040000) // Read Wait Control
#define SDHC_PROCTL_CREQ \
MAKE_REG_MASK(0x1, 17) //((uint32_t)0x00020000) // Continue Request
#define SDHC_PROCTL_SABGREQ \
MAKE_REG_MASK(0x1, \
16) //((uint32_t)0x00010000) // Stop At Block Gap Request
#define SDHC_PROCTL_DMAS(n) \
MAKE_REG_SET(n, 0x3, 8) //(uint32_t)(((n) & 0x3)<<8) // DMA Select
#define SDHC_PROCTL_CDSS \
MAKE_REG_MASK(0x1, \
7) //((uint32_t)0x00000080) // Card Detect Signal Selection
#define SDHC_PROCTL_CDTL \
MAKE_REG_MASK(0x1, 6) //((uint32_t)0x00000040) // Card Detect Test Level
#define SDHC_PROCTL_EMODE(n) \
MAKE_REG_SET(n, 0x3, 4) //(uint32_t)(((n) & 0x3)<<4) // Endian Mode
#define SDHC_PROCTL_EMODE_MASK \
MAKE_REG_MASK(0x3, 4) //(uint32_t)((0x3)<<4) // Endian Mode
#define SDHC_PROCTL_D3CD \
MAKE_REG_MASK(0x1, \
3) //((uint32_t)0x00000008) // DAT3 As Card Detection Pin
#define SDHC_PROCTL_DTW(n) \
MAKE_REG_SET(n, 0x3, 1) //(uint32_t)(((n) & 0x3)<<1) // Data Transfer Width,
// 0=1bit, 1=4bit, 2=8bit
#define SDHC_PROCTL_DTW_MASK MAKE_REG_MASK(0x3, 1) //((uint32_t)0x00000006)
#define SDHC_PROCTL_LCTL \
MAKE_REG_MASK(0x1, 0) //((uint32_t)0x00000001) // LED Control
#define SDHC_SYSCTL_RSTT MAKE_REG_MASK(0x1,28) //
#define SDHC_SYSCTL_INITA MAKE_REG_MASK(0x1,27) //((uint32_t)0x08000000) // Initialization Active
#define SDHC_SYSCTL_RSTD MAKE_REG_MASK(0x1,26) //((uint32_t)0x04000000) // Software Reset For DAT Line
#define SDHC_SYSCTL_RSTC MAKE_REG_MASK(0x1,25) //((uint32_t)0x02000000) // Software Reset For CMD Line
#define SDHC_SYSCTL_RSTA MAKE_REG_MASK(0x1,24) //((uint32_t)0x01000000) // Software Reset For ALL
#define SDHC_SYSCTL_DTOCV(n) MAKE_REG_SET(n,0xF,16) //(uint32_t)(((n) & 0xF)<<16) // Data Timeout Counter Value
#define SDHC_SYSCTL_DTOCV_MASK MAKE_REG_MASK(0xF,16) //((uint32_t)0x000F0000)
#define SDHC_SYSCTL_SDCLKFS(n) MAKE_REG_SET(n,0xFF,8) //(uint32_t)(((n) & 0xFF)<<8) // SDCLK Frequency Select
#define SDHC_SYSCTL_SDCLKFS_MASK MAKE_REG_MASK(0xFF,8) //((uint32_t)0x0000FF00)
#define SDHC_SYSCTL_DVS(n) MAKE_REG_SET(n,0xF,4) //(uint32_t)(((n) & 0xF)<<4) // Divisor
#define SDHC_SYSCTL_DVS_MASK MAKE_REG_MASK(0xF,4) //((uint32_t)0x000000F0)
#define SDHC_SYSCTL_RSTT MAKE_REG_MASK(0x1, 28) //
#define SDHC_SYSCTL_INITA \
MAKE_REG_MASK(0x1, 27) //((uint32_t)0x08000000) // Initialization Active
#define SDHC_SYSCTL_RSTD \
MAKE_REG_MASK( \
0x1, 26) //((uint32_t)0x04000000) // Software Reset For DAT Line
#define SDHC_SYSCTL_RSTC \
MAKE_REG_MASK( \
0x1, 25) //((uint32_t)0x02000000) // Software Reset For CMD Line
#define SDHC_SYSCTL_RSTA \
MAKE_REG_MASK(0x1, 24) //((uint32_t)0x01000000) // Software Reset For ALL
#define SDHC_SYSCTL_DTOCV(n) \
MAKE_REG_SET( \
n, 0xF, \
16) //(uint32_t)(((n) & 0xF)<<16) // Data Timeout Counter Value
#define SDHC_SYSCTL_DTOCV_MASK MAKE_REG_MASK(0xF, 16) //((uint32_t)0x000F0000)
#define SDHC_SYSCTL_SDCLKFS(n) \
MAKE_REG_SET(n, 0xFF, \
8) //(uint32_t)(((n) & 0xFF)<<8) // SDCLK Frequency Select
#define SDHC_SYSCTL_SDCLKFS_MASK \
MAKE_REG_MASK(0xFF, 8) //((uint32_t)0x0000FF00)
#define SDHC_SYSCTL_DVS(n) \
MAKE_REG_SET(n, 0xF, 4) //(uint32_t)(((n) & 0xF)<<4) // Divisor
#define SDHC_SYSCTL_DVS_MASK MAKE_REG_MASK(0xF, 4) //((uint32_t)0x000000F0)
#define SDHC_SYSCTL_SDCLKEN ((uint32_t)0x00000008) // SD Clock Enable
#define SDHC_SYSCTL_PEREN ((uint32_t)0x00000004) // Peripheral Clock Enable
#define SDHC_SYSCTL_HCKEN ((uint32_t)0x00000002) // System Clock Enable
#define SDHC_SYSCTL_IPGEN ((uint32_t)0x00000001) // IPG Clock Enable
#define SDHC_SYSCTL_SDCLKEN ((uint32_t)0x00000008) // SD Clock Enable
#define SDHC_SYSCTL_PEREN ((uint32_t)0x00000004) // Peripheral Clock Enable
#define SDHC_SYSCTL_HCKEN ((uint32_t)0x00000002) // System Clock Enable
#define SDHC_SYSCTL_IPGEN ((uint32_t)0x00000001) // IPG Clock Enable
#define SDHC_IRQSTAT_DMAE MAKE_REG_MASK(0x1,28) //((uint32_t)0x10000000) // DMA Error
#define SDHC_IRQSTAT_TNE MAKE_REG_MASK(0x1,26) //
#define SDHC_IRQSTAT_AC12E MAKE_REG_MASK(0x1,24) //((uint32_t)0x01000000) // Auto CMD12 Error
#define SDHC_IRQSTAT_DEBE MAKE_REG_MASK(0x1,22) //((uint32_t)0x00400000) // Data End Bit Error
#define SDHC_IRQSTAT_DCE MAKE_REG_MASK(0x1,21) //((uint32_t)0x00200000) // Data CRC Error
#define SDHC_IRQSTAT_DTOE MAKE_REG_MASK(0x1,20) //((uint32_t)0x00100000) // Data Timeout Error
#define SDHC_IRQSTAT_CIE MAKE_REG_MASK(0x1,19) //((uint32_t)0x00080000) // Command Index Error
#define SDHC_IRQSTAT_CEBE MAKE_REG_MASK(0x1,18) //((uint32_t)0x00040000) // Command End Bit Error
#define SDHC_IRQSTAT_CCE MAKE_REG_MASK(0x1,17) //((uint32_t)0x00020000) // Command CRC Error
#define SDHC_IRQSTAT_CTOE MAKE_REG_MASK(0x1,16) //((uint32_t)0x00010000) // Command Timeout Error
#define SDHC_IRQSTAT_TP MAKE_REG_MASK(0x1,14) //
#define SDHC_IRQSTAT_RTE MAKE_REG_MASK(0x1,12) //
#define SDHC_IRQSTAT_CINT MAKE_REG_MASK(0x1,8) //((uint32_t)0x00000100) // Card Interrupt
#define SDHC_IRQSTAT_CRM MAKE_REG_MASK(0x1,7) //((uint32_t)0x00000080) // Card Removal
#define SDHC_IRQSTAT_CINS MAKE_REG_MASK(0x1,6) //((uint32_t)0x00000040) // Card Insertion
#define SDHC_IRQSTAT_BRR MAKE_REG_MASK(0x1,5) //((uint32_t)0x00000020) // Buffer Read Ready
#define SDHC_IRQSTAT_BWR MAKE_REG_MASK(0x1,4) //((uint32_t)0x00000010) // Buffer Write Ready
#define SDHC_IRQSTAT_DINT MAKE_REG_MASK(0x1,3) //((uint32_t)0x00000008) // DMA Interrupt
#define SDHC_IRQSTAT_BGE MAKE_REG_MASK(0x1,2) //((uint32_t)0x00000004) // Block Gap Event
#define SDHC_IRQSTAT_TC MAKE_REG_MASK(0x1,1) //((uint32_t)0x00000002) // Transfer Complete
#define SDHC_IRQSTAT_CC MAKE_REG_MASK(0x1,0) //((uint32_t)0x00000001) // Command Complete
#define SDHC_IRQSTAT_DMAE \
MAKE_REG_MASK(0x1, 28) //((uint32_t)0x10000000) // DMA Error
#define SDHC_IRQSTAT_TNE MAKE_REG_MASK(0x1, 26) //
#define SDHC_IRQSTAT_AC12E \
MAKE_REG_MASK(0x1, 24) //((uint32_t)0x01000000) // Auto CMD12 Error
#define SDHC_IRQSTAT_DEBE \
MAKE_REG_MASK(0x1, 22) //((uint32_t)0x00400000) // Data End Bit Error
#define SDHC_IRQSTAT_DCE \
MAKE_REG_MASK(0x1, 21) //((uint32_t)0x00200000) // Data CRC Error
#define SDHC_IRQSTAT_DTOE \
MAKE_REG_MASK(0x1, 20) //((uint32_t)0x00100000) // Data Timeout Error
#define SDHC_IRQSTAT_CIE \
MAKE_REG_MASK(0x1, 19) //((uint32_t)0x00080000) // Command Index Error
#define SDHC_IRQSTAT_CEBE \
MAKE_REG_MASK(0x1, 18) //((uint32_t)0x00040000) // Command End Bit Error
#define SDHC_IRQSTAT_CCE \
MAKE_REG_MASK(0x1, 17) //((uint32_t)0x00020000) // Command CRC Error
#define SDHC_IRQSTAT_CTOE \
MAKE_REG_MASK(0x1, 16) //((uint32_t)0x00010000) // Command Timeout Error
#define SDHC_IRQSTAT_TP MAKE_REG_MASK(0x1, 14) //
#define SDHC_IRQSTAT_RTE MAKE_REG_MASK(0x1, 12) //
#define SDHC_IRQSTAT_CINT \
MAKE_REG_MASK(0x1, 8) //((uint32_t)0x00000100) // Card Interrupt
#define SDHC_IRQSTAT_CRM \
MAKE_REG_MASK(0x1, 7) //((uint32_t)0x00000080) // Card Removal
#define SDHC_IRQSTAT_CINS \
MAKE_REG_MASK(0x1, 6) //((uint32_t)0x00000040) // Card Insertion
#define SDHC_IRQSTAT_BRR \
MAKE_REG_MASK(0x1, 5) //((uint32_t)0x00000020) // Buffer Read Ready
#define SDHC_IRQSTAT_BWR \
MAKE_REG_MASK(0x1, 4) //((uint32_t)0x00000010) // Buffer Write Ready
#define SDHC_IRQSTAT_DINT \
MAKE_REG_MASK(0x1, 3) //((uint32_t)0x00000008) // DMA Interrupt
#define SDHC_IRQSTAT_BGE \
MAKE_REG_MASK(0x1, 2) //((uint32_t)0x00000004) // Block Gap Event
#define SDHC_IRQSTAT_TC \
MAKE_REG_MASK(0x1, 1) //((uint32_t)0x00000002) // Transfer Complete
#define SDHC_IRQSTAT_CC \
MAKE_REG_MASK(0x1, 0) //((uint32_t)0x00000001) // Command Complete
#define SDHC_IRQSTATEN_DMAESEN MAKE_REG_MASK(0x1,28) //((uint32_t)0x10000000) // DMA Error Status Enable
#define SDHC_IRQSTATEN_TNESEN MAKE_REG_MASK(0x1,26) //
#define SDHC_IRQSTATEN_AC12ESEN MAKE_REG_MASK(0x1,24) //((uint32_t)0x01000000) // Auto CMD12 Error Status Enable
#define SDHC_IRQSTATEN_DEBESEN MAKE_REG_MASK(0x1,22) //((uint32_t)0x00400000) // Data End Bit Error Status Enable
#define SDHC_IRQSTATEN_DCESEN MAKE_REG_MASK(0x1,21) //((uint32_t)0x00200000) // Data CRC Error Status Enable
#define SDHC_IRQSTATEN_DTOESEN MAKE_REG_MASK(0x1,20) //((uint32_t)0x00100000) // Data Timeout Error Status Enable
#define SDHC_IRQSTATEN_CIESEN MAKE_REG_MASK(0x1,19) //((uint32_t)0x00080000) // Command Index Error Status Enable
#define SDHC_IRQSTATEN_CEBESEN MAKE_REG_MASK(0x1,18) //((uint32_t)0x00040000) // Command End Bit Error Status Enable
#define SDHC_IRQSTATEN_CCESEN MAKE_REG_MASK(0x1,17) //((uint32_t)0x00020000) // Command CRC Error Status Enable
#define SDHC_IRQSTATEN_CTOESEN MAKE_REG_MASK(0x1,16) //((uint32_t)0x00010000) // Command Timeout Error Status Enable
#define SDHC_IRQSTATEN_TPSEN MAKE_REG_MASK(0x1,14) //
#define SDHC_IRQSTATEN_RTESEN MAKE_REG_MASK(0x1,12) //
#define SDHC_IRQSTATEN_CINTSEN MAKE_REG_MASK(0x1,8) //((uint32_t)0x00000100) // Card Interrupt Status Enable
#define SDHC_IRQSTATEN_CRMSEN MAKE_REG_MASK(0x1,7) //((uint32_t)0x00000080) // Card Removal Status Enable
#define SDHC_IRQSTATEN_CINSEN MAKE_REG_MASK(0x1,6) //((uint32_t)0x00000040) // Card Insertion Status Enable
#define SDHC_IRQSTATEN_BRRSEN MAKE_REG_MASK(0x1,5) //((uint32_t)0x00000020) // Buffer Read Ready Status Enable
#define SDHC_IRQSTATEN_BWRSEN MAKE_REG_MASK(0x1,4) //((uint32_t)0x00000010) // Buffer Write Ready Status Enable
#define SDHC_IRQSTATEN_DINTSEN MAKE_REG_MASK(0x1,3) //((uint32_t)0x00000008) // DMA Interrupt Status Enable
#define SDHC_IRQSTATEN_BGESEN MAKE_REG_MASK(0x1,2) //((uint32_t)0x00000004) // Block Gap Event Status Enable
#define SDHC_IRQSTATEN_TCSEN MAKE_REG_MASK(0x1,1) //((uint32_t)0x00000002) // Transfer Complete Status Enable
#define SDHC_IRQSTATEN_CCSEN MAKE_REG_MASK(0x1,0) //((uint32_t)0x00000001) // Command Complete Status Enable
#define SDHC_IRQSTATEN_DMAESEN \
MAKE_REG_MASK(0x1, 28) //((uint32_t)0x10000000) // DMA Error Status Enable
#define SDHC_IRQSTATEN_TNESEN MAKE_REG_MASK(0x1, 26) //
#define SDHC_IRQSTATEN_AC12ESEN \
MAKE_REG_MASK( \
0x1, 24) //((uint32_t)0x01000000) // Auto CMD12 Error Status Enable
#define SDHC_IRQSTATEN_DEBESEN \
MAKE_REG_MASK( \
0x1, \
22) //((uint32_t)0x00400000) // Data End Bit Error Status Enable
#define SDHC_IRQSTATEN_DCESEN \
MAKE_REG_MASK( \
0x1, 21) //((uint32_t)0x00200000) // Data CRC Error Status Enable
#define SDHC_IRQSTATEN_DTOESEN \
MAKE_REG_MASK( \
0x1, \
20) //((uint32_t)0x00100000) // Data Timeout Error Status Enable
#define SDHC_IRQSTATEN_CIESEN \
MAKE_REG_MASK( \
0x1, \
19) //((uint32_t)0x00080000) // Command Index Error Status Enable
#define SDHC_IRQSTATEN_CEBESEN \
MAKE_REG_MASK( \
0x1, \
18) //((uint32_t)0x00040000) // Command End Bit Error Status Enable
#define SDHC_IRQSTATEN_CCESEN \
MAKE_REG_MASK( \
0x1, 17) //((uint32_t)0x00020000) // Command CRC Error Status Enable
#define SDHC_IRQSTATEN_CTOESEN \
MAKE_REG_MASK( \
0x1, \
16) //((uint32_t)0x00010000) // Command Timeout Error Status Enable
#define SDHC_IRQSTATEN_TPSEN MAKE_REG_MASK(0x1, 14) //
#define SDHC_IRQSTATEN_RTESEN MAKE_REG_MASK(0x1, 12) //
#define SDHC_IRQSTATEN_CINTSEN \
MAKE_REG_MASK(0x1, \
8) //((uint32_t)0x00000100) // Card Interrupt Status Enable
#define SDHC_IRQSTATEN_CRMSEN \
MAKE_REG_MASK(0x1, \
7) //((uint32_t)0x00000080) // Card Removal Status Enable
#define SDHC_IRQSTATEN_CINSEN \
MAKE_REG_MASK(0x1, \
6) //((uint32_t)0x00000040) // Card Insertion Status Enable
#define SDHC_IRQSTATEN_BRRSEN \
MAKE_REG_MASK( \
0x1, 5) //((uint32_t)0x00000020) // Buffer Read Ready Status Enable
#define SDHC_IRQSTATEN_BWRSEN \
MAKE_REG_MASK( \
0x1, 4) //((uint32_t)0x00000010) // Buffer Write Ready Status Enable
#define SDHC_IRQSTATEN_DINTSEN \
MAKE_REG_MASK(0x1, \
3) //((uint32_t)0x00000008) // DMA Interrupt Status Enable
#define SDHC_IRQSTATEN_BGESEN \
MAKE_REG_MASK( \
0x1, 2) //((uint32_t)0x00000004) // Block Gap Event Status Enable
#define SDHC_IRQSTATEN_TCSEN \
MAKE_REG_MASK( \
0x1, 1) //((uint32_t)0x00000002) // Transfer Complete Status Enable
#define SDHC_IRQSTATEN_CCSEN \
MAKE_REG_MASK( \
0x1, 0) //((uint32_t)0x00000001) // Command Complete Status Enable
#define SDHC_IRQSIGEN_DMAEIEN MAKE_REG_MASK(0x1,28) //((uint32_t)0x10000000) // DMA Error Interrupt Enable
#define SDHC_IRQSIGEN_TNEIEN MAKE_REG_MASK(0x1,26) //
#define SDHC_IRQSIGEN_AC12EIEN MAKE_REG_MASK(0x1,24) //((uint32_t)0x01000000) // Auto CMD12 Error Interrupt Enable
#define SDHC_IRQSIGEN_DEBEIEN MAKE_REG_MASK(0x1,22) //((uint32_t)0x00400000) // Data End Bit Error Interrupt Enable
#define SDHC_IRQSIGEN_DCEIEN MAKE_REG_MASK(0x1,21) //((uint32_t)0x00200000) // Data CRC Error Interrupt Enable
#define SDHC_IRQSIGEN_DTOEIEN MAKE_REG_MASK(0x1,20) //((uint32_t)0x00100000) // Data Timeout Error Interrupt Enable
#define SDHC_IRQSIGEN_CIEIEN MAKE_REG_MASK(0x1,19) //((uint32_t)0x00080000) // Command Index Error Interrupt Enable
#define SDHC_IRQSIGEN_CEBEIEN MAKE_REG_MASK(0x1,18) //((uint32_t)0x00040000) // Command End Bit Error Interrupt Enable
#define SDHC_IRQSIGEN_CCEIEN MAKE_REG_MASK(0x1,17) //((uint32_t)0x00020000) // Command CRC Error Interrupt Enable
#define SDHC_IRQSIGEN_CTOEIEN MAKE_REG_MASK(0x1,16) //((uint32_t)0x00010000) // Command Timeout Error Interrupt Enable
#define SDHC_IRQSIGEN_TPIEN MAKE_REG_MASK(0x1,14) //
#define SDHC_IRQSIGEN_RTEIEN MAKE_REG_MASK(0x1,12) //
#define SDHC_IRQSIGEN_CINTIEN MAKE_REG_MASK(0x1,8) //((uint32_t)0x00000100) // Card Interrupt Interrupt Enable
#define SDHC_IRQSIGEN_CRMIEN MAKE_REG_MASK(0x1,7) //((uint32_t)0x00000080) // Card Removal Interrupt Enable
#define SDHC_IRQSIGEN_CINSIEN MAKE_REG_MASK(0x1,6) //((uint32_t)0x00000040) // Card Insertion Interrupt Enable
#define SDHC_IRQSIGEN_BRRIEN MAKE_REG_MASK(0x1,5) //((uint32_t)0x00000020) // Buffer Read Ready Interrupt Enable
#define SDHC_IRQSIGEN_BWRIEN MAKE_REG_MASK(0x1,4) //((uint32_t)0x00000010) // Buffer Write Ready Interrupt Enable
#define SDHC_IRQSIGEN_DINTIEN MAKE_REG_MASK(0x1,3) //((uint32_t)0x00000008) // DMA Interrupt Interrupt Enable
#define SDHC_IRQSIGEN_BGEIEN MAKE_REG_MASK(0x1,2) //((uint32_t)0x00000004) // Block Gap Event Interrupt Enable
#define SDHC_IRQSIGEN_TCIEN MAKE_REG_MASK(0x1,1) //((uint32_t)0x00000002) // Transfer Complete Interrupt Enable
#define SDHC_IRQSIGEN_CCIEN MAKE_REG_MASK(0x1,0) //((uint32_t)0x00000001) // Command Complete Interrupt Enable
#define SDHC_IRQSIGEN_DMAEIEN \
MAKE_REG_MASK(0x1, \
28) //((uint32_t)0x10000000) // DMA Error Interrupt Enable
#define SDHC_IRQSIGEN_TNEIEN MAKE_REG_MASK(0x1, 26) //
#define SDHC_IRQSIGEN_AC12EIEN \
MAKE_REG_MASK( \
0x1, \
24) //((uint32_t)0x01000000) // Auto CMD12 Error Interrupt Enable
#define SDHC_IRQSIGEN_DEBEIEN \
MAKE_REG_MASK( \
0x1, \
22) //((uint32_t)0x00400000) // Data End Bit Error Interrupt Enable
#define SDHC_IRQSIGEN_DCEIEN \
MAKE_REG_MASK( \
0x1, 21) //((uint32_t)0x00200000) // Data CRC Error Interrupt Enable
#define SDHC_IRQSIGEN_DTOEIEN \
MAKE_REG_MASK( \
0x1, \
20) //((uint32_t)0x00100000) // Data Timeout Error Interrupt Enable
#define SDHC_IRQSIGEN_CIEIEN \
MAKE_REG_MASK( \
0x1, \
19) //((uint32_t)0x00080000) // Command Index Error Interrupt Enable
#define SDHC_IRQSIGEN_CEBEIEN \
MAKE_REG_MASK(0x1, 18) //((uint32_t)0x00040000) // Command End Bit Error
// Interrupt Enable
#define SDHC_IRQSIGEN_CCEIEN \
MAKE_REG_MASK( \
0x1, \
17) //((uint32_t)0x00020000) // Command CRC Error Interrupt Enable
#define SDHC_IRQSIGEN_CTOEIEN \
MAKE_REG_MASK(0x1, 16) //((uint32_t)0x00010000) // Command Timeout Error
// Interrupt Enable
#define SDHC_IRQSIGEN_TPIEN MAKE_REG_MASK(0x1, 14) //
#define SDHC_IRQSIGEN_RTEIEN MAKE_REG_MASK(0x1, 12) //
#define SDHC_IRQSIGEN_CINTIEN \
MAKE_REG_MASK( \
0x1, 8) //((uint32_t)0x00000100) // Card Interrupt Interrupt Enable
#define SDHC_IRQSIGEN_CRMIEN \
MAKE_REG_MASK( \
0x1, 7) //((uint32_t)0x00000080) // Card Removal Interrupt Enable
#define SDHC_IRQSIGEN_CINSIEN \
MAKE_REG_MASK( \
0x1, 6) //((uint32_t)0x00000040) // Card Insertion Interrupt Enable
#define SDHC_IRQSIGEN_BRRIEN \
MAKE_REG_MASK( \
0x1, \
5) //((uint32_t)0x00000020) // Buffer Read Ready Interrupt Enable
#define SDHC_IRQSIGEN_BWRIEN \
MAKE_REG_MASK( \
0x1, \
4) //((uint32_t)0x00000010) // Buffer Write Ready Interrupt Enable
#define SDHC_IRQSIGEN_DINTIEN \
MAKE_REG_MASK( \
0x1, 3) //((uint32_t)0x00000008) // DMA Interrupt Interrupt Enable
#define SDHC_IRQSIGEN_BGEIEN \
MAKE_REG_MASK( \
0x1, 2) //((uint32_t)0x00000004) // Block Gap Event Interrupt Enable
#define SDHC_IRQSIGEN_TCIEN \
MAKE_REG_MASK( \
0x1, \
1) //((uint32_t)0x00000002) // Transfer Complete Interrupt Enable
#define SDHC_IRQSIGEN_CCIEN \
MAKE_REG_MASK( \
0x1, \
0) //((uint32_t)0x00000001) // Command Complete Interrupt Enable
#define SDHC_AC12ERR_SMPLCLK_SEL MAKE_REG_MASK(0x1,23) //
#define SDHC_AC12ERR_EXEC_TUNING MAKE_REG_MASK(0x1,22) //
#define SDHC_AC12ERR_CNIBAC12E MAKE_REG_MASK(0x1,7) //((uint32_t)0x00000080) // Command Not Issued By Auto CMD12 Error
#define SDHC_AC12ERR_AC12IE MAKE_REG_MASK(0x1,4) //((uint32_t)0x00000010) // Auto CMD12 Index Error
#define SDHC_AC12ERR_AC12CE MAKE_REG_MASK(0x1,3) //((uint32_t)0x00000008) // Auto CMD12 CRC Error
#define SDHC_AC12ERR_AC12EBE MAKE_REG_MASK(0x1,2) //((uint32_t)0x00000004) // Auto CMD12 End Bit Error
#define SDHC_AC12ERR_AC12TOE MAKE_REG_MASK(0x1,1) //((uint32_t)0x00000002) // Auto CMD12 Timeout Error
#define SDHC_AC12ERR_AC12NE MAKE_REG_MASK(0x1,0) //((uint32_t)0x00000001) // Auto CMD12 Not Executed
#define SDHC_AC12ERR_SMPLCLK_SEL MAKE_REG_MASK(0x1, 23) //
#define SDHC_AC12ERR_EXEC_TUNING MAKE_REG_MASK(0x1, 22) //
#define SDHC_AC12ERR_CNIBAC12E \
MAKE_REG_MASK(0x1, 7) //((uint32_t)0x00000080) // Command Not Issued By
// Auto CMD12 Error
#define SDHC_AC12ERR_AC12IE \
MAKE_REG_MASK(0x1, 4) //((uint32_t)0x00000010) // Auto CMD12 Index Error
#define SDHC_AC12ERR_AC12CE \
MAKE_REG_MASK(0x1, 3) //((uint32_t)0x00000008) // Auto CMD12 CRC Error
#define SDHC_AC12ERR_AC12EBE \
MAKE_REG_MASK(0x1, 2) //((uint32_t)0x00000004) // Auto CMD12 End Bit Error
#define SDHC_AC12ERR_AC12TOE \
MAKE_REG_MASK(0x1, 1) //((uint32_t)0x00000002) // Auto CMD12 Timeout Error
#define SDHC_AC12ERR_AC12NE \
MAKE_REG_MASK(0x1, 0) //((uint32_t)0x00000001) // Auto CMD12 Not Executed
#define SDHC_HTCAPBLT_VS18 MAKE_REG_MASK(0x1,26) //
#define SDHC_HTCAPBLT_VS30 MAKE_REG_MASK(0x1,25) //
#define SDHC_HTCAPBLT_VS33 MAKE_REG_MASK(0x1,24) //
#define SDHC_HTCAPBLT_SRS MAKE_REG_MASK(0x1,23) //
#define SDHC_HTCAPBLT_DMAS MAKE_REG_MASK(0x1,22) //
#define SDHC_HTCAPBLT_HSS MAKE_REG_MASK(0x1,21) //
#define SDHC_HTCAPBLT_ADMAS MAKE_REG_MASK(0x1,20) //
#define SDHC_HTCAPBLT_MBL_VAL MAKE_REG_GET((USDHC1_HOST_CTRL_CAP),0x7,16) //
#define SDHC_HTCAPBLT_RETUN_MODE MAKE_REG_GET((USDHC1_HOST_CTRL_CAP),0x3,14) //
#define SDHC_HTCAPBLT_TUNE_SDR50 MAKE_REG_MASK(0x1,13) //
#define SDHC_HTCAPBLT_TIME_RETUN(n) MAKE_REG_SET(n,0xF,8) //
#define SDHC_HTCAPBLT_VS18 MAKE_REG_MASK(0x1, 26) //
#define SDHC_HTCAPBLT_VS30 MAKE_REG_MASK(0x1, 25) //
#define SDHC_HTCAPBLT_VS33 MAKE_REG_MASK(0x1, 24) //
#define SDHC_HTCAPBLT_SRS MAKE_REG_MASK(0x1, 23) //
#define SDHC_HTCAPBLT_DMAS MAKE_REG_MASK(0x1, 22) //
#define SDHC_HTCAPBLT_HSS MAKE_REG_MASK(0x1, 21) //
#define SDHC_HTCAPBLT_ADMAS MAKE_REG_MASK(0x1, 20) //
#define SDHC_HTCAPBLT_MBL_VAL MAKE_REG_GET((USDHC1_HOST_CTRL_CAP), 0x7, 16) //
#define SDHC_HTCAPBLT_RETUN_MODE \
MAKE_REG_GET((USDHC1_HOST_CTRL_CAP), 0x3, 14) //
#define SDHC_HTCAPBLT_TUNE_SDR50 MAKE_REG_MASK(0x1, 13) //
#define SDHC_HTCAPBLT_TIME_RETUN(n) MAKE_REG_SET(n, 0xF, 8) //
#define SDHC_WML_WR_BRSTLEN_MASK MAKE_REG_MASK(0x1F,24) //
#define SDHC_WML_RD_BRSTLEN_MASK MAKE_REG_MASK(0x1F,8) //
#define SDHC_WML_WR_WML_MASK MAKE_REG_MASK(0xFF,16) //
#define SDHC_WML_RD_WML_MASK MAKE_REG_MASK(0xFF,0) //
#define SDHC_WML_WR_BRSTLEN(n) MAKE_REG_SET(n,0x1F,24) //(uint32_t)(((n) & 0x7F)<<16) // Write Burst Len
#define SDHC_WML_RD_BRSTLEN(n) MAKE_REG_SET(n,0x1F,8) //(uint32_t)(((n) & 0x7F)<<0) // Read Burst Len
#define SDHC_WML_WR_WML(n) MAKE_REG_SET(n,0xFF,16) //(uint32_t)(((n) & 0x7F)<<16) // Write Watermark Level
#define SDHC_WML_RD_WML(n) MAKE_REG_SET(n,0xFF,0) //(uint32_t)(((n) & 0x7F)<<0) // Read Watermark Level
#define SDHC_WML_WRWML(n) MAKE_REG_SET(n,0xFF,16) //(uint32_t)(((n) & 0x7F)<<16) // Write Watermark Level
#define SDHC_WML_RDWML(n) MAKE_REG_SET(n,0xFF,0) //(uint32_t)(((n) & 0x7F)<<0) // Read Watermark Level
#define SDHC_WML_WR_BRSTLEN_MASK MAKE_REG_MASK(0x1F, 24) //
#define SDHC_WML_RD_BRSTLEN_MASK MAKE_REG_MASK(0x1F, 8) //
#define SDHC_WML_WR_WML_MASK MAKE_REG_MASK(0xFF, 16) //
#define SDHC_WML_RD_WML_MASK MAKE_REG_MASK(0xFF, 0) //
#define SDHC_WML_WR_BRSTLEN(n) \
MAKE_REG_SET(n, 0x1F, 24) //(uint32_t)(((n) & 0x7F)<<16) // Write Burst Len
#define SDHC_WML_RD_BRSTLEN(n) \
MAKE_REG_SET(n, 0x1F, 8) //(uint32_t)(((n) & 0x7F)<<0) // Read Burst Len
#define SDHC_WML_WR_WML(n) \
MAKE_REG_SET(n, 0xFF, \
16) //(uint32_t)(((n) & 0x7F)<<16) // Write Watermark Level
#define SDHC_WML_RD_WML(n) \
MAKE_REG_SET(n, 0xFF, \
0) //(uint32_t)(((n) & 0x7F)<<0) // Read Watermark Level
#define SDHC_WML_WRWML(n) \
MAKE_REG_SET(n, 0xFF, \
16) //(uint32_t)(((n) & 0x7F)<<16) // Write Watermark Level
#define SDHC_WML_RDWML(n) \
MAKE_REG_SET(n, 0xFF, \
0) //(uint32_t)(((n) & 0x7F)<<0) // Read Watermark Level
// Teensy 4.0 only
#define SDHC_MIX_CTRL_DMAEN MAKE_REG_MASK(0x1,0) //
#define SDHC_MIX_CTRL_BCEN MAKE_REG_MASK(0x1,1) //
#define SDHC_MIX_CTRL_AC12EN MAKE_REG_MASK(0x1,2) //
#define SDHC_MIX_CTRL_DDR_EN MAKE_REG_MASK(0x1,3) //
#define SDHC_MIX_CTRL_DTDSEL MAKE_REG_MASK(0x1,4) //
#define SDHC_MIX_CTRL_MSBSEL MAKE_REG_MASK(0x1,5) //
#define SDHC_MIX_CTRL_NIBBLE_POS MAKE_REG_MASK(0x1,6) //
#define SDHC_MIX_CTRL_AC23EN MAKE_REG_MASK(0x1,7) //
#define SDHC_MIX_CTRL_DMAEN MAKE_REG_MASK(0x1, 0) //
#define SDHC_MIX_CTRL_BCEN MAKE_REG_MASK(0x1, 1) //
#define SDHC_MIX_CTRL_AC12EN MAKE_REG_MASK(0x1, 2) //
#define SDHC_MIX_CTRL_DDR_EN MAKE_REG_MASK(0x1, 3) //
#define SDHC_MIX_CTRL_DTDSEL MAKE_REG_MASK(0x1, 4) //
#define SDHC_MIX_CTRL_MSBSEL MAKE_REG_MASK(0x1, 5) //
#define SDHC_MIX_CTRL_NIBBLE_POS MAKE_REG_MASK(0x1, 6) //
#define SDHC_MIX_CTRL_AC23EN MAKE_REG_MASK(0x1, 7) //
#define SDHC_FEVT_CINT MAKE_REG_MASK(0x1,31) //((uint32_t)0x80000000) // Force Event Card Interrupt
#define SDHC_FEVT_DMAE MAKE_REG_MASK(0x1,28) //((uint32_t)0x10000000) // Force Event DMA Error
#define SDHC_FEVT_AC12E MAKE_REG_MASK(0x1,24) //((uint32_t)0x01000000) // Force Event Auto CMD12 Error
#define SDHC_FEVT_DEBE MAKE_REG_MASK(0x1,22) //((uint32_t)0x00400000) // Force Event Data End Bit Error
#define SDHC_FEVT_DCE MAKE_REG_MASK(0x1,21) //((uint32_t)0x00200000) // Force Event Data CRC Error
#define SDHC_FEVT_DTOE MAKE_REG_MASK(0x1,20) //((uint32_t)0x00100000) // Force Event Data Timeout Error
#define SDHC_FEVT_CIE MAKE_REG_MASK(0x1,19) //((uint32_t)0x00080000) // Force Event Command Index Error
#define SDHC_FEVT_CEBE MAKE_REG_MASK(0x1,18) //((uint32_t)0x00040000) // Force Event Command End Bit Error
#define SDHC_FEVT_CCE MAKE_REG_MASK(0x1,17) //((uint32_t)0x00020000) // Force Event Command CRC Error
#define SDHC_FEVT_CTOE MAKE_REG_MASK(0x1,16) //((uint32_t)0x00010000) // Force Event Command Timeout Error
#define SDHC_FEVT_CNIBAC12E MAKE_REG_MASK(0x1,7) //((uint32_t)0x00000080) // Force Event Command Not Executed By Auto Command 12 Error
#define SDHC_FEVT_AC12IE MAKE_REG_MASK(0x1,4) //((uint32_t)0x00000010) // Force Event Auto Command 12 Index Error
#define SDHC_FEVT_AC12EBE MAKE_REG_MASK(0x1,3) //((uint32_t)0x00000008) // Force Event Auto Command 12 End Bit Error
#define SDHC_FEVT_AC12CE MAKE_REG_MASK(0x1,2) //((uint32_t)0x00000004) // Force Event Auto Command 12 CRC Error
#define SDHC_FEVT_AC12TOE MAKE_REG_MASK(0x1,1) //((uint32_t)0x00000002) // Force Event Auto Command 12 Time Out Error
#define SDHC_FEVT_AC12NE MAKE_REG_MASK(0x1,0) //((uint32_t)0x00000001) // Force Event Auto Command 12 Not Executed
#define SDHC_FEVT_CINT \
MAKE_REG_MASK(0x1, \
31) //((uint32_t)0x80000000) // Force Event Card Interrupt
#define SDHC_FEVT_DMAE \
MAKE_REG_MASK(0x1, 28) //((uint32_t)0x10000000) // Force Event DMA Error
#define SDHC_FEVT_AC12E \
MAKE_REG_MASK( \
0x1, 24) //((uint32_t)0x01000000) // Force Event Auto CMD12 Error
#define SDHC_FEVT_DEBE \
MAKE_REG_MASK( \
0x1, 22) //((uint32_t)0x00400000) // Force Event Data End Bit Error
#define SDHC_FEVT_DCE \
MAKE_REG_MASK(0x1, \
21) //((uint32_t)0x00200000) // Force Event Data CRC Error
#define SDHC_FEVT_DTOE \
MAKE_REG_MASK( \
0x1, 20) //((uint32_t)0x00100000) // Force Event Data Timeout Error
#define SDHC_FEVT_CIE \
MAKE_REG_MASK( \
0x1, 19) //((uint32_t)0x00080000) // Force Event Command Index Error
#define SDHC_FEVT_CEBE \
MAKE_REG_MASK( \
0x1, \
18) //((uint32_t)0x00040000) // Force Event Command End Bit Error
#define SDHC_FEVT_CCE \
MAKE_REG_MASK( \
0x1, 17) //((uint32_t)0x00020000) // Force Event Command CRC Error
#define SDHC_FEVT_CTOE \
MAKE_REG_MASK( \
0x1, \
16) //((uint32_t)0x00010000) // Force Event Command Timeout Error
#define SDHC_FEVT_CNIBAC12E \
MAKE_REG_MASK(0x1, 7) //((uint32_t)0x00000080) // Force Event Command Not
// Executed By Auto Command 12 Error
#define SDHC_FEVT_AC12IE \
MAKE_REG_MASK(0x1, 4) //((uint32_t)0x00000010) // Force Event Auto Command
// 12 Index Error
#define SDHC_FEVT_AC12EBE \
MAKE_REG_MASK(0x1, 3) //((uint32_t)0x00000008) // Force Event Auto Command
// 12 End Bit Error
#define SDHC_FEVT_AC12CE \
MAKE_REG_MASK( \
0x1, \
2) //((uint32_t)0x00000004) // Force Event Auto Command 12 CRC Error
#define SDHC_FEVT_AC12TOE \
MAKE_REG_MASK(0x1, 1) //((uint32_t)0x00000002) // Force Event Auto Command
// 12 Time Out Error
#define SDHC_FEVT_AC12NE \
MAKE_REG_MASK(0x1, 0) //((uint32_t)0x00000001) // Force Event Auto Command
// 12 Not Executed
#define SDHC_ADMAES_ADMADCE MAKE_REG_MASK(0x1,3) //((uint32_t)0x00000008)
#define SDHC_ADMAES_ADMALME MAKE_REG_MASK(0x1,2) //((uint32_t)0x00000004)
#define SDHC_ADMAES_ADMAES_MASK MAKE_REG_MASK(0x3,0) //((uint32_t)0x00000003)
#define SDHC_ADMAES_ADMADCE MAKE_REG_MASK(0x1, 3) //((uint32_t)0x00000008)
#define SDHC_ADMAES_ADMALME MAKE_REG_MASK(0x1, 2) //((uint32_t)0x00000004)
#define SDHC_ADMAES_ADMAES_MASK MAKE_REG_MASK(0x3, 0) //((uint32_t)0x00000003)
#define SDHC_MMCBOOT_BOOTBLKCNT(n) MAKE_REG_MASK(0xFF,16) //(uint32_t)(((n) & 0xFFF)<<16) // stop at block gap value of automatic mode
#define SDHC_MMCBOOT_AUTOSABGEN MAKE_REG_MASK(0x1,7) //((uint32_t)0x00000080) // enable auto stop at block gap function
#define SDHC_MMCBOOT_BOOTEN MAKE_REG_MASK(0x1,6) //((uint32_t)0x00000040) // Boot Mode Enable
#define SDHC_MMCBOOT_BOOTMODE MAKE_REG_MASK(0x1,5) //((uint32_t)0x00000020) // Boot Mode Select
#define SDHC_MMCBOOT_BOOTACK MAKE_REG_MASK(0x1,4) //((uint32_t)0x00000010) // Boot Ack Mode Select
#define SDHC_MMCBOOT_DTOCVACK(n) MAKE_REG_MASK(0xF,0) //(uint32_t)(((n) & 0xF)<<0) // Boot ACK Time Out Counter Value
//#define SDHC_HOSTVER (*(volatile uint32_t*)0x400B10FC) // Host Controller Version
#define SDHC_MMCBOOT_BOOTBLKCNT(n) \
MAKE_REG_MASK(0xFF, 16) //(uint32_t)(((n) & 0xFFF)<<16) // stop at block gap
// value of automatic mode
#define SDHC_MMCBOOT_AUTOSABGEN \
MAKE_REG_MASK(0x1, 7) //((uint32_t)0x00000080) // enable auto stop at
// block gap function
#define SDHC_MMCBOOT_BOOTEN \
MAKE_REG_MASK(0x1, 6) //((uint32_t)0x00000040) // Boot Mode Enable
#define SDHC_MMCBOOT_BOOTMODE \
MAKE_REG_MASK(0x1, 5) //((uint32_t)0x00000020) // Boot Mode Select
#define SDHC_MMCBOOT_BOOTACK \
MAKE_REG_MASK(0x1, 4) //((uint32_t)0x00000010) // Boot Ack Mode Select
#define SDHC_MMCBOOT_DTOCVACK(n) \
MAKE_REG_MASK( \
0xF, \
0) //(uint32_t)(((n) & 0xF)<<0) // Boot ACK Time Out Counter Value
// #define SDHC_HOSTVER (*(volatile uint32_t*)0x400B10FC) // Host Controller
// 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_PFD1_FRAC_MASK (0x3f<<8)
#define CCM_ANALOG_PFD_528_PFD1_FRAC(n) (((n)<<8) & CCM_ANALOG_PFD_528_PFD1_FRAC_MASK)
#define CCM_ANALOG_PFD_528_PFD2_FRAC_MASK (0x3f<<16)
#define CCM_ANALOG_PFD_528_PFD2_FRAC(n) (((n)<<16) & CCM_ANALOG_PFD_528_PFD2_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)
#define CCM_ANALOG_PFD_528_PFD2_FRAC_MASK (0x3f << 16)
#define CCM_ANALOG_PFD_528_PFD2_FRAC(n) \
(((n) << 16) & CCM_ANALOG_PFD_528_PFD2_FRAC_MASK)
#define CCM_ANALOG_PFD_528_PFD3_FRAC_MASK ((0x3f<<24)
#define CCM_ANALOG_PFD_528_PFD3_FRAC(n) (((n)<<24) & CCM_ANALOG_PFD_528_PFD3_FRAC_MASK)
#define CCM_ANALOG_PFD_528_PFD3_FRAC(n) \
(((n) << 24) & CCM_ANALOG_PFD_528_PFD3_FRAC_MASK)
#define SDHC_DSADDR (USDHC1_DS_ADDR ) // DMA System Address register
#define SDHC_BLKATTR (USDHC1_BLK_ATT) // Block Attributes register
#define SDHC_CMDARG (USDHC1_CMD_ARG) // Command Argument register
#define SDHC_XFERTYP (USDHC1_CMD_XFR_TYP) // Transfer Type register
#define SDHC_CMDRSP0 (USDHC1_CMD_RSP0) // Command Response 0
#define SDHC_CMDRSP1 (USDHC1_CMD_RSP1) // Command Response 1
#define SDHC_CMDRSP2 (USDHC1_CMD_RSP2) // Command Response 2
#define SDHC_CMDRSP3 (USDHC1_CMD_RSP3) // Command Response 3
#define SDHC_DATPORT (USDHC1_DATA_BUFF_ACC_PORT) // Buffer Data Port register
#define SDHC_PRSSTAT (USDHC1_PRES_STATE) // Present State register
#define SDHC_PROCTL (USDHC1_PROT_CTRL) // Protocol Control register
#define SDHC_SYSCTL (USDHC1_SYS_CTRL) // System Control register
#define SDHC_IRQSTAT (USDHC1_INT_STATUS) // Interrupt Status register
#define SDHC_IRQSTATEN (USDHC1_INT_STATUS_EN) // Interrupt Status Enable register
#define SDHC_IRQSIGEN (USDHC1_INT_SIGNAL_EN) // Interrupt Signal Enable register
#define SDHC_AC12ERR (USDHC1_AUTOCMD12_ERR_STATUS) // Auto CMD12 Error Status Register
#define SDHC_HTCAPBLT (USDHC1_HOST_CTRL_CAP) // Host Controller Capabilities
#define SDHC_WML (USDHC1_WTMK_LVL) // Watermark Level Register
#define SDHC_MIX_CTRL (USDHC1_MIX_CTRL) // Mixer Control
#define SDHC_FEVT (USDHC1_FORCE_EVENT) // Force Event register
#define SDHC_ADMAES (USDHC1_ADMA_ERR_STATUS) // ADMA Error Status register
#define SDHC_ADSADDR (USDHC1_ADMA_SYS_ADDR) // ADMA System Addressregister
#define SDHC_VENDOR (USDHC1_VEND_SPEC) // Vendor Specific register
#define SDHC_MMCBOOT (USDHC1_MMC_BOOT) // MMC Boot register
#define SDHC_VENDOR2 (USDHC2_VEND_SPEC2) // Vendor Specific2 register
#define SDHC_DSADDR (USDHC1_DS_ADDR) // DMA System Address register
#define SDHC_BLKATTR (USDHC1_BLK_ATT) // Block Attributes register
#define SDHC_CMDARG (USDHC1_CMD_ARG) // Command Argument register
#define SDHC_XFERTYP (USDHC1_CMD_XFR_TYP) // Transfer Type register
#define SDHC_CMDRSP0 (USDHC1_CMD_RSP0) // Command Response 0
#define SDHC_CMDRSP1 (USDHC1_CMD_RSP1) // Command Response 1
#define SDHC_CMDRSP2 (USDHC1_CMD_RSP2) // Command Response 2
#define SDHC_CMDRSP3 (USDHC1_CMD_RSP3) // Command Response 3
#define SDHC_DATPORT (USDHC1_DATA_BUFF_ACC_PORT) // Buffer Data Port register
#define SDHC_PRSSTAT (USDHC1_PRES_STATE) // Present State register
#define SDHC_PROCTL (USDHC1_PROT_CTRL) // Protocol Control register
#define SDHC_SYSCTL (USDHC1_SYS_CTRL) // System Control register
#define SDHC_IRQSTAT (USDHC1_INT_STATUS) // Interrupt Status register
#define SDHC_IRQSTATEN \
(USDHC1_INT_STATUS_EN) // Interrupt Status Enable register
#define SDHC_IRQSIGEN \
(USDHC1_INT_SIGNAL_EN) // Interrupt Signal Enable register
#define SDHC_AC12ERR \
(USDHC1_AUTOCMD12_ERR_STATUS) // Auto CMD12 Error Status Register
#define SDHC_HTCAPBLT (USDHC1_HOST_CTRL_CAP) // Host Controller Capabilities
#define SDHC_WML (USDHC1_WTMK_LVL) // Watermark Level Register
#define SDHC_MIX_CTRL (USDHC1_MIX_CTRL) // Mixer Control
#define SDHC_FEVT (USDHC1_FORCE_EVENT) // Force Event register
#define SDHC_ADMAES (USDHC1_ADMA_ERR_STATUS) // ADMA Error Status register
#define SDHC_ADSADDR (USDHC1_ADMA_SYS_ADDR) // ADMA System Addressregister
#define SDHC_VENDOR (USDHC1_VEND_SPEC) // Vendor Specific register
#define SDHC_MMCBOOT (USDHC1_MMC_BOOT) // MMC Boot register
#define SDHC_VENDOR2 (USDHC2_VEND_SPEC2) // Vendor Specific2 register
//
#define IRQ_SDHC IRQ_SDHC1
#define IRQ_SDHC IRQ_SDHC1
#define SDHC_MAX_DVS (0xF + 1U)
#define SDHC_MAX_CLKFS (0xFF + 1U)
#define SDHC_PREV_DVS(x) ((x) -= 1U)
#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_MASK (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_PUS_MASK ((0x3)<<14)
#define IOMUXC_SW_PAD_CTL_PAD_DSE(n) (((n)&0x7)<<3)
#define IOMUXC_SW_PAD_CTL_PAD_DSE_MASK ((0x7)<<3)
#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_PUS_MASK ((0x3) << 14)
#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

View file

@ -28,19 +28,19 @@
* \file
* \brief main SdFs include file.
*/
#include "common/SysCall.h"
#include "SdCard/SdCard.h"
#include "ExFatLib/ExFatLib.h"
#include "FatLib/FatLib.h"
#include "FsLib/FsLib.h"
#include "SdCard/SdCard.h"
#include "common/SysCall.h"
#if INCLUDE_SDIOS
#include "sdios.h"
#endif // INCLUDE_SDIOS
//------------------------------------------------------------------------------
/** SdFat version for cpp use. */
#define SD_FAT_VERSION 20200
#define SD_FAT_VERSION 20202
/** SdFat version as string. */
#define SD_FAT_VERSION_STR "2.2.0"
#define SD_FAT_VERSION_STR "2.2.2"
//==============================================================================
/**
* \class SdBase
@ -93,7 +93,7 @@ class SdBase : public Vol {
}
//----------------------------------------------------------------------------
/** \return Pointer to SD card object. */
SdCard* card() {return m_card;}
SdCard* card() { return m_card; }
//----------------------------------------------------------------------------
/** Initialize SD card in SPI mode.
*
@ -136,7 +136,8 @@ class SdBase : public Vol {
} else if (!Vol::fatType()) {
pr->println(F("Check SD format."));
}
while (true) {}
while (true) {
}
}
//----------------------------------------------------------------------------
/** %Print error info and halt.
@ -197,7 +198,7 @@ class SdBase : public Vol {
}
//----------------------------------------------------------------------------
/** \return true if can be in dedicated SPI state */
bool hasDedicatedSpi() {return m_card ? m_card->hasDedicatedSpi() : false;}
bool hasDedicatedSpi() { return m_card ? m_card->hasDedicatedSpi() : false; }
//----------------------------------------------------------------------------
/** %Print error info and halt.
*
@ -205,7 +206,8 @@ class SdBase : public Vol {
*/
void initErrorHalt(print_t* pr) {
initErrorPrint(pr);
while (true) {}
while (true) {
}
}
//----------------------------------------------------------------------------
/** %Print error info and halt.
@ -244,7 +246,7 @@ class SdBase : public Vol {
}
//----------------------------------------------------------------------------
/** \return true if in dedicated SPI state. */
bool isDedicatedSpi() {return m_card ? m_card->isDedicatedSpi() : false;}
bool isDedicatedSpi() { return m_card ? m_card->isDedicatedSpi() : false; }
//----------------------------------------------------------------------------
/** %Print volume FAT/exFAT type.
*
@ -325,7 +327,7 @@ class SdBase : public Vol {
}
//----------------------------------------------------------------------------
/** \return SD card error data. */
uint8_t sdErrorData() {return m_card ? m_card->errorData() : 0;}
uint8_t sdErrorData() { return m_card ? m_card->errorData() : 0; }
//----------------------------------------------------------------------------
/** Set SPI sharing state
* \param[in] value desired state.
@ -339,57 +341,51 @@ class SdBase : public Vol {
}
//----------------------------------------------------------------------------
/** \return pointer to base volume */
Vol* vol() {return reinterpret_cast<Vol*>(this);}
Vol* vol() { return reinterpret_cast<Vol*>(this); }
//----------------------------------------------------------------------------
/** Initialize file system after call to cardBegin.
*
* \return true for success or false for failure.
*/
bool volumeBegin() {
return Vol::begin(m_card);
}
bool volumeBegin() { return Vol::begin(m_card); }
#if ENABLE_ARDUINO_SERIAL
/** Print error details after begin() fails. */
void initErrorPrint() {
initErrorPrint(&Serial);
}
void initErrorPrint() { initErrorPrint(&Serial); }
//----------------------------------------------------------------------------
/** %Print msg to Serial and halt.
*
* \param[in] msg Message to print.
*/
void errorHalt(const __FlashStringHelper* msg) {
errorHalt(&Serial, msg);
}
void errorHalt(const __FlashStringHelper* msg) { errorHalt(&Serial, msg); }
//----------------------------------------------------------------------------
/** %Print error info to Serial and halt. */
void errorHalt() {errorHalt(&Serial);}
void errorHalt() { errorHalt(&Serial); }
//----------------------------------------------------------------------------
/** %Print error info and halt.
*
* \param[in] msg Message to print.
*/
void errorHalt(const char* msg) {errorHalt(&Serial, msg);}
void errorHalt(const char* msg) { errorHalt(&Serial, msg); }
//----------------------------------------------------------------------------
/** %Print error info and halt. */
void initErrorHalt() {initErrorHalt(&Serial);}
void initErrorHalt() { initErrorHalt(&Serial); }
//----------------------------------------------------------------------------
/** %Print msg, any SD error code.
*
* \param[in] msg Message to print.
*/
void errorPrint(const char* msg) {errorPrint(&Serial, msg);}
/** %Print msg, any SD error code.
void errorPrint(const char* msg) { errorPrint(&Serial, msg); }
/** %Print msg, any SD error code.
*
* \param[in] msg Message to print.
*/
void errorPrint(const __FlashStringHelper* msg) {errorPrint(&Serial, msg);}
void errorPrint(const __FlashStringHelper* msg) { errorPrint(&Serial, msg); }
//----------------------------------------------------------------------------
/** %Print error info and halt.
*
* \param[in] msg Message to print.
*/
void initErrorHalt(const char* msg) {initErrorHalt(&Serial, msg);}
void initErrorHalt(const char* msg) { initErrorHalt(&Serial, msg); }
//----------------------------------------------------------------------------
/** %Print error info and halt.
*
@ -473,9 +469,7 @@ class SdFile : public PrintFile<SdBaseFile> {
* \param[in] path path for file.
* \param[in] oflag open flags.
*/
SdFile(const char* path, oflag_t oflag) {
open(path, oflag);
}
SdFile(const char* path, oflag_t oflag) { open(path, oflag); }
/** Set the date/time callback function
*
* \param[in] dateTime The user's call back function. The callback
@ -502,13 +496,11 @@ class SdFile : public PrintFile<SdBaseFile> {
* sync() maintains the last access date and last modify date/time.
*
*/
static void dateTimeCallback(
void (*dateTime)(uint16_t* date, uint16_t* time)) {
static void dateTimeCallback(void (*dateTime)(uint16_t* date,
uint16_t* time)) {
FsDateTime::setCallback(dateTime);
}
/** Cancel the date/time callback function. */
static void dateTimeCallbackCancel() {
FsDateTime::clearCallback();
}
static void dateTimeCallbackCancel() { FsDateTime::clearCallback(); }
};
#endif // SdFat_h

View file

@ -122,14 +122,28 @@
#define SPI_DRIVER_SELECT 0
#endif // SPI_DRIVER_SELECT
/**
* If USE_SPI_ARRAY_TRANSFER is non-zero and the standard SPI library is
* use, the array transfer function, transfer(buf, size), will be used.
* This option will allocate up to a 512 byte temporary buffer for send.
* If USE_SPI_ARRAY_TRANSFER is one and the standard SPI library is
* use, the array transfer function, transfer(buf, count), will be used.
* This option will allocate a 512 byte temporary buffer for send.
* This may be faster for some boards. Do not use this with AVR boards.
*
* Warning: the next options are often fastest but only available for some
* non-Arduino board packages.
*
* If USE_SPI_ARRAY_TRANSFER is two use transfer(nullptr, buf, count) for
* receive and transfer(buf, nullptr, count) for send.
*
* If USE_SPI_ARRAY_TRANSFER is three use transfer(nullptr, buf, count) for
* receive and transfer(buf, rxTmp, count) for send. Try this with Adafruit
* SAMD51.
*
* If USE_SPI_ARRAY_TRANSFER is four use transfer(txTmp, buf, count) for
* receive and transfer(buf, rxTmp, count) for send. Try this with STM32.
*/
#ifndef USE_SPI_ARRAY_TRANSFER
#define USE_SPI_ARRAY_TRANSFER 0
#endif // USE_SPI_ARRAY_TRANSFER
//------------------------------------------------------------------------------
/**
* SD maximum initialization clock rate.
*/
@ -161,7 +175,8 @@
#ifndef USE_BLOCK_DEVICE_INTERFACE
#define USE_BLOCK_DEVICE_INTERFACE 0
#endif // USE_BLOCK_DEVICE_INTERFACE
/**
//------------------------------------------------------------------------------
/**
* SD_CHIP_SELECT_MODE defines how the functions
* void sdCsInit(SdCsPin_t pin) {pinMode(pin, OUTPUT);}
* and
@ -346,8 +361,8 @@ typedef uint8_t SdCsPin_t;
* Set USE_SIMPLE_LITTLE_ENDIAN nonzero for little endian processors
* with no memory alignment restrictions.
*/
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__\
&& (defined(__AVR__) || defined(__ARM_FEATURE_UNALIGNED))
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && \
(defined(__AVR__) || defined(__ARM_FEATURE_UNALIGNED))
#define USE_SIMPLE_LITTLE_ENDIAN 1
#else // __BYTE_ORDER_
#define USE_SIMPLE_LITTLE_ENDIAN 0
@ -394,11 +409,11 @@ typedef uint8_t SdCsPin_t;
#endif // BUILTIN_SDCARD
// SPI for built-in card.
#ifndef SDCARD_SPI
#define SDCARD_SPI SPI1
#define SDCARD_SPI SPI1
#define SDCARD_MISO_PIN 59
#define SDCARD_MOSI_PIN 61
#define SDCARD_SCK_PIN 60
#define SDCARD_SS_PIN 62
#define SDCARD_SCK_PIN 60
#define SDCARD_SS_PIN 62
#endif // SDCARD_SPI
#define HAS_SDIO_CLASS 1
#endif // defined(__MK64FX512__) || defined(__MK66FX1M0__)
@ -409,15 +424,13 @@ typedef uint8_t SdCsPin_t;
/**
* Determine the default SPI configuration.
*/
#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(CORE_TEENSY) && defined(__arm__))
#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(CORE_TEENSY) && defined(__arm__))
#define SD_HAS_CUSTOM_SPI 1
#else // SD_HAS_CUSTOM_SPI
// Use standard SPI library.

View file

@ -38,6 +38,8 @@
*/
class SdSpiArduinoDriver {
public:
/** Constructor. */
SdSpiArduinoDriver() = default;
/** Activate SPI hardware. */
void activate();
/** Initialize the SPI bus.
@ -55,12 +57,12 @@ class SdSpiArduinoDriver {
*/
uint8_t receive();
/** Receive multiple bytes.
*
* \param[out] buf Buffer to receive the data.
* \param[in] count Number of bytes to receive.
*
* \return Zero for no error or nonzero error code.
*/
*
* \param[out] buf Buffer to receive the data.
* \param[in] count Number of bytes to receive.
*
* \return Zero for no error or nonzero error code.
*/
uint8_t receive(uint8_t* buf, size_t count);
/** Send a byte.
*
@ -82,7 +84,7 @@ class SdSpiArduinoDriver {
}
private:
SPIClass *m_spi;
SPIClass* m_spi = nullptr;
SPISettings m_spiSettings;
};
/** Typedef for use of SdSpiArduinoDriver */

View file

@ -25,9 +25,7 @@
#include "SdSpiDriver.h"
#if defined(SD_USE_CUSTOM_SPI) && defined(ARDUINO_ARCH_APOLLO3)
//------------------------------------------------------------------------------
void SdSpiArduinoDriver::activate() {
m_spi->beginTransaction(m_spiSettings);
}
void SdSpiArduinoDriver::activate() { m_spi->beginTransaction(m_spiSettings); }
//------------------------------------------------------------------------------
void SdSpiArduinoDriver::begin(SdSpiConfig spiConfig) {
if (spiConfig.spiPort) {
@ -38,17 +36,11 @@ void SdSpiArduinoDriver::begin(SdSpiConfig spiConfig) {
m_spi->begin();
}
//------------------------------------------------------------------------------
void SdSpiArduinoDriver::deactivate() {
m_spi->endTransaction();
}
void SdSpiArduinoDriver::deactivate() { m_spi->endTransaction(); }
//------------------------------------------------------------------------------
void SdSpiArduinoDriver::end() {
m_spi->end();
}
void SdSpiArduinoDriver::end() { m_spi->end(); }
//------------------------------------------------------------------------------
uint8_t SdSpiArduinoDriver::receive() {
return m_spi->transfer(0XFF);
}
uint8_t SdSpiArduinoDriver::receive() { return m_spi->transfer(0XFF); }
//------------------------------------------------------------------------------
uint8_t SdSpiArduinoDriver::receive(uint8_t* buf, size_t count) {
memset(buf, 0XFF, count);
@ -56,24 +48,22 @@ uint8_t SdSpiArduinoDriver::receive(uint8_t* buf, size_t count) {
return 0;
}
//------------------------------------------------------------------------------
void SdSpiArduinoDriver::send(uint8_t data) {
m_spi->transfer(data);
}
void SdSpiArduinoDriver::send(uint8_t data) { m_spi->transfer(data); }
//------------------------------------------------------------------------------
void SdSpiArduinoDriver::send(const uint8_t* buf, size_t count) {
// If not a multiple of four. Command with CRC used six byte send.
while (count%4) {
while (count % 4) {
send(*buf++);
count--;
}
// Convert byte array to 4 byte array.
uint32_t myArray[count/4]; // NOLINT
for (int x = 0; x < count/4; x++) {
uint32_t myArray[count / 4]; // NOLINT
for (int x = 0; x < count / 4; x++) {
myArray[x] = ((uint32_t)buf[(x * 4) + 3] << (8 * 3)) |
((uint32_t)buf[(x * 4) + 2] << (8 * 2)) |
((uint32_t)buf[(x * 4) + 1] << (8 * 1)) |
((uint32_t)buf[(x * 4) + 0] << (8 * 0));
}
m_spi->transfer(reinterpret_cast<void *>(myArray), count);
m_spi->transfer(reinterpret_cast<void*>(myArray), count);
}
#endif // defined(SD_USE_CUSTOM_SPI) && defined(ARDUINO_ARCH_APOLLO3)

View file

@ -25,7 +25,7 @@
#ifndef SdSpiAvr_h
#define SdSpiAvr_h
// Use of in-line for AVR to save flash.
#define nop asm volatile ("nop\n\t")
#define nop asm volatile("nop\n\t")
//------------------------------------------------------------------------------
inline void SdSpiArduinoDriver::activate() {
SPI.beginTransaction(m_spiSettings);
@ -36,17 +36,11 @@ inline void SdSpiArduinoDriver::begin(SdSpiConfig spiConfig) {
SPI.begin();
}
//------------------------------------------------------------------------------
inline void SdSpiArduinoDriver::deactivate() {
SPI.endTransaction();
}
inline void SdSpiArduinoDriver::deactivate() { SPI.endTransaction(); }
//------------------------------------------------------------------------------
inline void SdSpiArduinoDriver::end() {
SPI.end();
}
inline void SdSpiArduinoDriver::end() { SPI.end(); }
//------------------------------------------------------------------------------
inline uint8_t SdSpiArduinoDriver::receive() {
return SPI.transfer(0XFF);
}
inline uint8_t SdSpiArduinoDriver::receive() { return SPI.transfer(0XFF); }
//------------------------------------------------------------------------------
inline uint8_t SdSpiArduinoDriver::receive(uint8_t* buf, size_t count) {
if (count == 0) {
@ -58,12 +52,14 @@ inline uint8_t SdSpiArduinoDriver::receive(uint8_t* buf, size_t count) {
// nops optimize loop for 16MHz CPU 8 MHz SPI
nop;
nop;
while (!(SPSR & _BV(SPIF))) {}
while (!(SPSR & _BV(SPIF))) {
}
uint8_t in = SPDR;
SPDR = 0XFF;
*buf++ = in;
}
while (!(SPSR & _BV(SPIF))) {}
while (!(SPSR & _BV(SPIF))) {
}
*buf = SPDR;
#elif defined(SPI_RXCIF_bm)
SPI0.DATA = 0XFF;
@ -73,12 +69,14 @@ inline uint8_t SdSpiArduinoDriver::receive(uint8_t* buf, size_t count) {
nop;
nop;
nop;
while (!(SPI0.INTFLAGS & SPI_RXCIF_bm)) {}
while (!(SPI0.INTFLAGS & SPI_RXCIF_bm)) {
}
uint8_t in = SPI0.DATA;
SPI0.DATA = 0XFF;
*buf++ = in;
}
while (!(SPI0.INTFLAGS & SPI_RXCIF_bm)) {}
while (!(SPI0.INTFLAGS & SPI_RXCIF_bm)) {
}
*buf = SPI0.DATA;
#else // SPSR
#error Unsupported AVR CPU - edit SdFatConfig.h to use standard SPI library.
@ -86,11 +84,9 @@ inline uint8_t SdSpiArduinoDriver::receive(uint8_t* buf, size_t count) {
return 0;
}
//------------------------------------------------------------------------------
inline void SdSpiArduinoDriver::send(uint8_t data) {
SPI.transfer(data);
}
inline void SdSpiArduinoDriver::send(uint8_t data) { SPI.transfer(data); }
//------------------------------------------------------------------------------
inline void SdSpiArduinoDriver::send(const uint8_t* buf , size_t count) {
inline void SdSpiArduinoDriver::send(const uint8_t* buf, size_t count) {
if (count == 0) {
return;
}
@ -101,10 +97,12 @@ inline void SdSpiArduinoDriver::send(const uint8_t* buf , size_t count) {
// nops optimize loop for 16MHz CPU 8 MHz SPI
nop;
nop;
while (!(SPSR & (1 << SPIF))) {}
while (!(SPSR & (1 << SPIF))) {
}
SPDR = b;
}
while (!(SPSR & (1 << SPIF))) {}
while (!(SPSR & (1 << SPIF))) {
}
#elif defined(SPI_RXCIF_bm)
SPI0.DATA = *buf++;
while (--count) {
@ -113,10 +111,12 @@ inline void SdSpiArduinoDriver::send(const uint8_t* buf , size_t count) {
nop;
nop;
nop;
while (!(SPI0.INTFLAGS & SPI_RXCIF_bm)) {}
while (!(SPI0.INTFLAGS & SPI_RXCIF_bm)) {
}
SPI0.DATA = b;
}
while (!(SPI0.INTFLAGS & SPI_RXCIF_bm)) {}
while (!(SPI0.INTFLAGS & SPI_RXCIF_bm)) {
}
#else // SPSR
#error Unsupported AVR CPU - edit SdFatConfig.h to use standard SPI library.
#endif // SPSR

View file

@ -30,8 +30,9 @@
*/
#include <avr/interrupt.h>
#include "../common/SysCall.h"
#define nop asm volatile ("nop\n\t")
#define nop asm volatile("nop\n\t")
#ifndef HIGH
#define HIGH 1
#endif // HIGH
@ -79,10 +80,10 @@ inline void unoPinMode(uint8_t pin, uint8_t mode) {
sei();
}
#define UNO_SS 10
#define UNO_SS 10
#define UNO_MOSI 11
#define UNO_MISO 12
#define UNO_SCK 13
#define UNO_SCK 13
//------------------------------------------------------------------------------
/**
* \class SdSpiDriverBareUno
@ -116,16 +117,14 @@ class SdSpiDriverBareUno {
*
* \return The byte.
*/
uint8_t receive() {
return transfer(0XFF);
}
uint8_t receive() { return transfer(0XFF); }
/** Receive multiple bytes.
*
* \param[out] buf Buffer to receive the data.
* \param[in] count Number of bytes to receive.
*
* \return Zero for no error or nonzero error code.
*/
*
* \param[out] buf Buffer to receive the data.
* \param[in] count Number of bytes to receive.
*
* \return Zero for no error or nonzero error code.
*/
uint8_t receive(uint8_t* buf, size_t count) {
if (count == 0) {
return 0;
@ -133,7 +132,8 @@ class SdSpiDriverBareUno {
uint8_t* pr = buf;
SPDR = 0XFF;
while (--count > 0) {
while (!(SPSR & _BV(SPIF))) {}
while (!(SPSR & _BV(SPIF))) {
}
uint8_t in = SPDR;
SPDR = 0XFF;
*pr++ = in;
@ -141,7 +141,8 @@ class SdSpiDriverBareUno {
nop;
nop;
}
while (!(SPSR & _BV(SPIF))) {}
while (!(SPSR & _BV(SPIF))) {
}
*pr = SPDR;
return 0;
}
@ -149,9 +150,7 @@ class SdSpiDriverBareUno {
*
* \param[in] data Byte to send
*/
void send(uint8_t data) {
transfer(data);
}
void send(uint8_t data) { transfer(data); }
/** Send multiple bytes.
*
* \param[in] buf Buffer for data to be sent.
@ -164,18 +163,18 @@ class SdSpiDriverBareUno {
SPDR = *buf++;
while (--count > 0) {
uint8_t b = *buf++;
while (!(SPSR & (1 << SPIF))) {}
while (!(SPSR & (1 << SPIF))) {
}
SPDR = b;
// nops to optimize loop for 16MHz CPU 8 MHz SPI
nop;
nop;
}
while (!(SPSR & (1 << SPIF))) {}
while (!(SPSR & (1 << SPIF))) {
}
}
/** Set CS low. */
void select() {
unoDigitalWrite(m_csPin, LOW);
}
void select() { unoDigitalWrite(m_csPin, LOW); }
/** Save high speed SPISettings after SD initialization.
*
* \param[in] spiConfig SPI options.
@ -186,13 +185,12 @@ class SdSpiDriverBareUno {
}
static uint8_t transfer(uint8_t data) {
SPDR = data;
while (!(SPSR & _BV(SPIF))) {} // wait
while (!(SPSR & _BV(SPIF))) {
} // wait
return SPDR;
}
/** Set CS high. */
void unselect() {
unoDigitalWrite(m_csPin, HIGH);
}
void unselect() { unoDigitalWrite(m_csPin, HIGH); }
private:
SdCsPin_t m_csPin;

View file

@ -51,12 +51,12 @@ class SdSpiBaseClass {
*/
virtual uint8_t receive() = 0;
/** Receive multiple bytes.
*
* \param[out] buf Buffer to receive the data.
* \param[in] count Number of bytes to receive.
*
* \return Zero for no error or nonzero error code.
*/
*
* \param[out] buf Buffer to receive the data.
* \param[in] count Number of bytes to receive.
*
* \return Zero for no error or nonzero error code.
*/
virtual uint8_t receive(uint8_t* buf, size_t count) = 0;
/** Send a byte.
*
@ -73,6 +73,6 @@ class SdSpiBaseClass {
*
* \param[in] maxSck Maximum SCK frequency.
*/
virtual void setSckSpeed(uint32_t maxSck) {(void)maxSck;}
virtual void setSckSpeed(uint32_t maxSck) { (void)maxSck; }
};
#endif // SdSpiBaseClass_h

View file

@ -26,22 +26,14 @@
#if ENABLE_ARDUINO_FEATURES
#if SD_CHIP_SELECT_MODE == 0
//------------------------------------------------------------------------------
void sdCsInit(SdCsPin_t pin) {
pinMode(pin, OUTPUT);
}
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); }
#elif SD_CHIP_SELECT_MODE == 1
//------------------------------------------------------------------------------
__attribute__((weak))
void sdCsInit(SdCsPin_t pin) {
pinMode(pin, OUTPUT);
}
__attribute__((weak)) void sdCsInit(SdCsPin_t pin) { pinMode(pin, OUTPUT); }
//------------------------------------------------------------------------------
__attribute__((weak))
void sdCsWrite(SdCsPin_t pin, bool level) {
__attribute__((weak)) void sdCsWrite(SdCsPin_t pin, bool level) {
digitalWrite(pin, level);
}
#endif // SD_CHIP_SELECT_MODE == 0

View file

@ -52,19 +52,24 @@ const uint8_t DEDICATED_SPI = 1;
* \param[in] opt option field of SdSpiConfig.
* \return true for dedicated SPI.
*/
inline bool spiOptionDedicated(uint8_t opt) {return opt & DEDICATED_SPI;}
#else // ENABLE_DEDICATED_SPI
inline bool spiOptionDedicated(uint8_t opt) { return opt & DEDICATED_SPI; }
#else // ENABLE_DEDICATED_SPI
/**
* \param[in] opt option field of SdSpiConfig.
* \return true for dedicated SPI.
*/
inline bool spiOptionDedicated(uint8_t opt) {(void)opt; return false;}
inline bool spiOptionDedicated(uint8_t opt) {
(void)opt;
return false;
}
#endif // ENABLE_DEDICATED_SPI
/** The user will call begin. Useful for custom SPI configurations. */
const uint8_t USER_SPI_BEGIN = 2;
//------------------------------------------------------------------------------
/** SPISettings for SCK frequency in Hz. */
#define SD_SCK_HZ(maxSpeed) (maxSpeed)
/** SPISettings for SCK frequency in MHz. */
#define SD_SCK_MHZ(maxMhz) (1000000UL*(maxMhz))
#define SD_SCK_MHZ(maxMhz) (1000000UL * (maxMhz))
// SPI divisor constants - obsolete.
/** Set SCK to max rate. */
#define SPI_FULL_SPEED SD_SCK_MHZ(50)
@ -93,8 +98,8 @@ typedef SdSpiSoftDriver SpiPort_t;
class SdSpiBaseClass;
/** Port type for extrernal SPI driver. */
typedef SdSpiBaseClass SpiPort_t;
#else // SPI_DRIVER_SELECT
typedef void* SpiPort_t;
#else // SPI_DRIVER_SELECT
typedef void* SpiPort_t;
#endif // SPI_DRIVER_SELECT
//------------------------------------------------------------------------------
/**
@ -103,15 +108,15 @@ typedef void* SpiPort_t;
*/
class SdSpiConfig {
public:
/** SdSpiConfig constructor.
/** SdSpiConfig constructor.
*
* \param[in] cs Chip select pin.
* \param[in] opt Options.
* \param[in] maxSpeed Maximum SCK frequency.
* \param[in] port The SPI port to use.
*/
SdSpiConfig(SdCsPin_t cs, uint8_t opt, uint32_t maxSpeed, SpiPort_t* port) :
csPin(cs), options(opt), maxSck(maxSpeed), spiPort(port) {}
SdSpiConfig(SdCsPin_t cs, uint8_t opt, uint32_t maxSpeed, SpiPort_t* port)
: csPin(cs), options(opt), maxSck(maxSpeed), spiPort(port) {}
/** SdSpiConfig constructor.
*
@ -119,8 +124,8 @@ class SdSpiConfig {
* \param[in] opt Options.
* \param[in] maxSpeed Maximum SCK frequency.
*/
SdSpiConfig(SdCsPin_t cs, uint8_t opt, uint32_t maxSpeed) :
csPin(cs), options(opt), maxSck(maxSpeed) {}
SdSpiConfig(SdCsPin_t cs, uint8_t opt, uint32_t maxSpeed)
: csPin(cs), options(opt), maxSck(maxSpeed) {}
/** SdSpiConfig constructor.
*
* \param[in] cs Chip select pin.

View file

@ -42,13 +42,9 @@
#define SPI_RX_IDX 2
//------------------------------------------------------------------------------
/* Disable DMA Controller. */
static void dmac_disable() {
DMAC->DMAC_EN &= (~DMAC_EN_ENABLE);
}
static void dmac_disable() { DMAC->DMAC_EN &= (~DMAC_EN_ENABLE); }
/* Enable DMA Controller. */
static void dmac_enable() {
DMAC->DMAC_EN = DMAC_EN_ENABLE;
}
static void dmac_enable() { DMAC->DMAC_EN = DMAC_EN_ENABLE; }
/* Disable DMA Channel. */
static void dmac_channel_disable(uint32_t ul_num) {
DMAC->DMAC_CHDR = DMAC_CHDR_DIS0 << ul_num;
@ -67,14 +63,15 @@ static void spiDmaRX(uint8_t* dst, uint16_t count) {
dmac_channel_disable(SPI_DMAC_RX_CH);
DMAC->DMAC_CH_NUM[SPI_DMAC_RX_CH].DMAC_SADDR = (uint32_t)&SPI0->SPI_RDR;
DMAC->DMAC_CH_NUM[SPI_DMAC_RX_CH].DMAC_DADDR = (uint32_t)dst;
DMAC->DMAC_CH_NUM[SPI_DMAC_RX_CH].DMAC_DSCR = 0;
DMAC->DMAC_CH_NUM[SPI_DMAC_RX_CH].DMAC_CTRLA = count |
DMAC_CTRLA_SRC_WIDTH_BYTE | DMAC_CTRLA_DST_WIDTH_BYTE;
DMAC->DMAC_CH_NUM[SPI_DMAC_RX_CH].DMAC_CTRLB = DMAC_CTRLB_SRC_DSCR |
DMAC_CTRLB_DST_DSCR | DMAC_CTRLB_FC_PER2MEM_DMA_FC |
DMAC->DMAC_CH_NUM[SPI_DMAC_RX_CH].DMAC_DSCR = 0;
DMAC->DMAC_CH_NUM[SPI_DMAC_RX_CH].DMAC_CTRLA =
count | DMAC_CTRLA_SRC_WIDTH_BYTE | DMAC_CTRLA_DST_WIDTH_BYTE;
DMAC->DMAC_CH_NUM[SPI_DMAC_RX_CH].DMAC_CTRLB =
DMAC_CTRLB_SRC_DSCR | DMAC_CTRLB_DST_DSCR | DMAC_CTRLB_FC_PER2MEM_DMA_FC |
DMAC_CTRLB_SRC_INCR_FIXED | DMAC_CTRLB_DST_INCR_INCREMENTING;
DMAC->DMAC_CH_NUM[SPI_DMAC_RX_CH].DMAC_CFG = DMAC_CFG_SRC_PER(SPI_RX_IDX) |
DMAC_CFG_SRC_H2SEL | DMAC_CFG_SOD | DMAC_CFG_FIFOCFG_ASAP_CFG;
DMAC->DMAC_CH_NUM[SPI_DMAC_RX_CH].DMAC_CFG =
DMAC_CFG_SRC_PER(SPI_RX_IDX) | DMAC_CFG_SRC_H2SEL | DMAC_CFG_SOD |
DMAC_CFG_FIFOCFG_ASAP_CFG;
dmac_channel_enable(SPI_DMAC_RX_CH);
}
//------------------------------------------------------------------------------
@ -89,16 +86,17 @@ static void spiDmaTX(const uint8_t* src, uint16_t count) {
dmac_channel_disable(SPI_DMAC_TX_CH);
DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_SADDR = (uint32_t)src;
DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_DADDR = (uint32_t)&SPI0->SPI_TDR;
DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_DSCR = 0;
DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_CTRLA = count |
DMAC_CTRLA_SRC_WIDTH_BYTE | DMAC_CTRLA_DST_WIDTH_BYTE;
DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_DSCR = 0;
DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_CTRLA =
count | DMAC_CTRLA_SRC_WIDTH_BYTE | DMAC_CTRLA_DST_WIDTH_BYTE;
DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_CTRLB = DMAC_CTRLB_SRC_DSCR |
DMAC_CTRLB_DST_DSCR | DMAC_CTRLB_FC_MEM2PER_DMA_FC |
DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_CTRLB =
DMAC_CTRLB_SRC_DSCR | DMAC_CTRLB_DST_DSCR | DMAC_CTRLB_FC_MEM2PER_DMA_FC |
src_incr | DMAC_CTRLB_DST_INCR_FIXED;
DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_CFG = DMAC_CFG_DST_PER(SPI_TX_IDX) |
DMAC_CFG_DST_H2SEL | DMAC_CFG_SOD | DMAC_CFG_FIFOCFG_ALAP_CFG;
DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_CFG =
DMAC_CFG_DST_PER(SPI_TX_IDX) | DMAC_CFG_DST_H2SEL | DMAC_CFG_SOD |
DMAC_CFG_FIFOCFG_ALAP_CFG;
dmac_channel_enable(SPI_DMAC_TX_CH);
}
@ -141,39 +139,36 @@ void SdSpiArduinoDriver::begin(SdSpiConfig spiConfig) {
#endif // USE_SAM3X_DMAC
}
//------------------------------------------------------------------------------
void SdSpiArduinoDriver::deactivate() {
SPI.endTransaction();
}
void SdSpiArduinoDriver::deactivate() { SPI.endTransaction(); }
//------------------------------------------------------------------------------
void SdSpiArduinoDriver::end() {
SPI.end();
}
void SdSpiArduinoDriver::end() { SPI.end(); }
//------------------------------------------------------------------------------
static inline uint8_t spiTransfer(uint8_t b) {
Spi* pSpi = SPI0;
pSpi->SPI_TDR = b;
while ((pSpi->SPI_SR & SPI_SR_RDRF) == 0) {}
while ((pSpi->SPI_SR & SPI_SR_RDRF) == 0) {
}
b = pSpi->SPI_RDR;
return b;
}
//------------------------------------------------------------------------------
uint8_t SdSpiArduinoDriver::receive() {
return spiTransfer(0XFF);
}
uint8_t SdSpiArduinoDriver::receive() { return spiTransfer(0XFF); }
//------------------------------------------------------------------------------
uint8_t SdSpiArduinoDriver::receive(uint8_t* buf, size_t count) {
Spi* pSpi = SPI0;
int rtn = 0;
#if USE_SAM3X_DMAC
// clear overrun error
while (pSpi->SPI_SR & (SPI_SR_OVRES | SPI_SR_RDRF)) {pSpi->SPI_RDR;}
while (pSpi->SPI_SR & (SPI_SR_OVRES | SPI_SR_RDRF)) {
pSpi->SPI_RDR;
}
spiDmaRX(buf, count);
spiDmaTX(0, count);
uint32_t m = millis();
while (!dmac_channel_transfer_done(SPI_DMAC_RX_CH)) {
if ((millis() - m) > SAM3X_DMA_TIMEOUT) {
if ((millis() - m) > SAM3X_DMA_TIMEOUT) {
dmac_channel_disable(SPI_DMAC_RX_CH);
dmac_channel_disable(SPI_DMAC_TX_CH);
rtn = 2;
@ -183,34 +178,39 @@ uint8_t SdSpiArduinoDriver::receive(uint8_t* buf, size_t count) {
if (pSpi->SPI_SR & SPI_SR_OVRES) {
rtn |= 1;
}
#else // USE_SAM3X_DMAC
#else // USE_SAM3X_DMAC
for (size_t i = 0; i < count; i++) {
pSpi->SPI_TDR = 0XFF;
while ((pSpi->SPI_SR & SPI_SR_RDRF) == 0) {}
while ((pSpi->SPI_SR & SPI_SR_RDRF) == 0) {
}
buf[i] = pSpi->SPI_RDR;
}
#endif // USE_SAM3X_DMAC
return rtn;
}
//------------------------------------------------------------------------------
void SdSpiArduinoDriver::send(uint8_t data) {
spiTransfer(data);
}
void SdSpiArduinoDriver::send(uint8_t data) { spiTransfer(data); }
//------------------------------------------------------------------------------
void SdSpiArduinoDriver::send(const uint8_t* buf , size_t count) {
void SdSpiArduinoDriver::send(const uint8_t* buf, size_t count) {
Spi* pSpi = SPI0;
#if USE_SAM3X_DMAC
spiDmaTX(buf, count);
while (!dmac_channel_transfer_done(SPI_DMAC_TX_CH)) {}
#else // #if USE_SAM3X_DMAC
while ((pSpi->SPI_SR & SPI_SR_TXEMPTY) == 0) {}
while (!dmac_channel_transfer_done(SPI_DMAC_TX_CH)) {
}
#else // #if USE_SAM3X_DMAC
while ((pSpi->SPI_SR & SPI_SR_TXEMPTY) == 0) {
}
for (size_t i = 0; i < count; i++) {
pSpi->SPI_TDR = buf[i];
while ((pSpi->SPI_SR & SPI_SR_TDRE) == 0) {}
while ((pSpi->SPI_SR & SPI_SR_TDRE) == 0) {
}
}
#endif // #if USE_SAM3X_DMAC
while ((pSpi->SPI_SR & SPI_SR_TXEMPTY) == 0) {}
while ((pSpi->SPI_SR & SPI_SR_TXEMPTY) == 0) {
}
// leave RDR empty
while (pSpi->SPI_SR & (SPI_SR_OVRES | SPI_SR_RDRF)) {pSpi->SPI_RDR;}
while (pSpi->SPI_SR & (SPI_SR_OVRES | SPI_SR_RDRF)) {
pSpi->SPI_RDR;
}
}
#endif // defined(SD_USE_CUSTOM_SPI) && defined(ARDUINO_SAM_DUE)

Some files were not shown because too many files have changed in this diff Show more