Add SD library
parent
6814cb57dd
commit
14d026d81d
|
@ -0,0 +1,7 @@
|
||||||
|
intellectual property is bullshit. be gay, do crime
|
||||||
|
|
||||||
|
some of this code comes from people who like licenses. if you care about that
|
||||||
|
kinda shit see the accompanying license files. i'm supposed to mention them
|
||||||
|
here:
|
||||||
|
|
||||||
|
sd-spi/: Wade Penson, 2015, Apache 2.0
|
|
@ -1,14 +1,16 @@
|
||||||
project('poly1', 'cpp', default_options: ['optimization=s', 'cpp_std=c++17'])
|
project('poly1', ['cpp', 'c'], default_options: ['optimization=s', 'cpp_std=c++17'])
|
||||||
|
|
||||||
atpack_zip = 'Microchip.AVR-Dx_DFP.2.1.152.atpack'
|
atpack_zip = 'Microchip.AVR-Dx_DFP.2.1.152.atpack'
|
||||||
dependencies = []
|
dependencies = []
|
||||||
|
|
||||||
local_headers = ['.', 'etl/include']
|
local_headers = ['.', 'etl/include', 'sd-spi']
|
||||||
|
|
||||||
sources = [
|
sources = [
|
||||||
'main.cpp',
|
'main.cpp',
|
||||||
'board.cpp',
|
'board.cpp',
|
||||||
'midix.cpp',
|
'midix.cpp',
|
||||||
|
'sd-spi/sd_spi.c',
|
||||||
|
'sd-spi/sd_spi_platform_dependencies.c',
|
||||||
]
|
]
|
||||||
|
|
||||||
_includes = local_headers
|
_includes = local_headers
|
||||||
|
|
|
@ -0,0 +1,202 @@
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright {yyyy} {name of copyright owner}
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
From https://github.com/wpenson/sd-spi-communications-library
|
||||||
|
See LICENSE
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,530 @@
|
||||||
|
/******************************************************************************/
|
||||||
|
/**
|
||||||
|
@file sd_spi.h
|
||||||
|
@author Wade Penson
|
||||||
|
@date June, 2015
|
||||||
|
@brief SD RAW library header.
|
||||||
|
@details This library supports MMC, SD1, SD2, and SDHC/SDXC type cards.
|
||||||
|
By defining SD_BUFFER, the library also implements a 512 byte buffer
|
||||||
|
for reading and writing.
|
||||||
|
|
||||||
|
@copyright Copyright 2015 Wade Penson
|
||||||
|
|
||||||
|
@license Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied. See the License for the specific language governing
|
||||||
|
permissions and limitations under the License.
|
||||||
|
|
||||||
|
@todo Support for AVR and SAMX AVR without using the Arduino SPI library.
|
||||||
|
@todo Support for using Software SPI (bit banging).
|
||||||
|
@todo Use CMD6 during initialization to switch card to high speed mode if
|
||||||
|
it supports it. This will be helpful for the due since the SPI
|
||||||
|
speed can be up to 84MHz.
|
||||||
|
@todo Allow setting CS high when card is in busy state for operations
|
||||||
|
instead of waiting. However, if an error is thrown for the
|
||||||
|
operation, the host will get that error on the next command it
|
||||||
|
sends.
|
||||||
|
@todo Send_status should be sent after all busy signals
|
||||||
|
(look at ch 4.3.7).
|
||||||
|
@todo Send stop_transmission if there was an error during
|
||||||
|
write continuous (and read continuous??).
|
||||||
|
@todo Get the number of well written blocks for sequential writing just in
|
||||||
|
case if there was an error.
|
||||||
|
@todo Card reads take up to 100ms and writes take up to 500ms. Make
|
||||||
|
timeouts reflect this.
|
||||||
|
@todo Reduce the number of error codes.
|
||||||
|
*/
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
#if !defined(SD_SPI_H_)
|
||||||
|
#define SD_SPI_H_
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "sd_spi_info.h"
|
||||||
|
#include "sd_spi_commands.h"
|
||||||
|
|
||||||
|
/** Define to enable the block buffer. */
|
||||||
|
#define SD_SPI_BUFFER
|
||||||
|
|
||||||
|
/** State variables used by the SD raw library. */
|
||||||
|
typedef struct sd_spi_card {
|
||||||
|
/** Digital pin for setting CS high or low. */
|
||||||
|
uint8_t chip_select_pin: 8;
|
||||||
|
/** The speed of the SPI bus. Use 0 for 25KHz and 1 for 25MHz. */
|
||||||
|
uint8_t spi_speed: 3;
|
||||||
|
/** Determines if the card is MMC, SD1, SD2, or SDHC/SDXC. */
|
||||||
|
uint8_t card_type: 3;
|
||||||
|
/** Flag to see if CS has already been set to high or low. */
|
||||||
|
uint8_t is_chip_select_high: 1;
|
||||||
|
/** True if currently reading continually and false otherwise. */
|
||||||
|
uint8_t is_read_write_continuous: 1;
|
||||||
|
/** True if currently writing continually and false otherwise. */
|
||||||
|
uint8_t is_write_continuous: 1;
|
||||||
|
/** If the card is being read or written to continually, this keeps track
|
||||||
|
of the block being read or written to. */
|
||||||
|
uint32_t continuous_block_address;
|
||||||
|
|
||||||
|
#if defined(SD_SPI_BUFFER)
|
||||||
|
/** Buffer for SD blocks. */
|
||||||
|
uint8_t sd_spi_buffer[512];
|
||||||
|
/** The address of the block currently being buffered. */
|
||||||
|
uint32_t buffered_block_address;
|
||||||
|
/** Keeps track of the consistency of the buffer for reading. */
|
||||||
|
uint8_t is_buffer_current: 1;
|
||||||
|
/** Keeps track if the buffer has been flushed or not. */
|
||||||
|
uint8_t is_buffer_written: 1;
|
||||||
|
#endif
|
||||||
|
} sd_spi_card_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@defgroup sd_spi_timeouts SD Timeouts
|
||||||
|
@brief Timeouts are used so that the SD does not freeze on
|
||||||
|
a task if a failure occurs.
|
||||||
|
@{
|
||||||
|
*/
|
||||||
|
#define SD_INIT_TIMEOUT 5000
|
||||||
|
#define SD_WRITE_TIMEOUT 5000
|
||||||
|
#define SD_READ_TIMEOUT 5000
|
||||||
|
#define SD_ERASE_TIMEOUT 500000
|
||||||
|
|
||||||
|
/** @} End of group sd_spi_timeouts */
|
||||||
|
|
||||||
|
/**
|
||||||
|
@defgroup sd_spi_card_types SD/MMC Card Types
|
||||||
|
@brief Types of cards.
|
||||||
|
@{
|
||||||
|
*/
|
||||||
|
#define SD_CARD_TYPE_UNKNOWN 0
|
||||||
|
#define SD_CARD_TYPE_SD1 1
|
||||||
|
#define SD_CARD_TYPE_SD2 2
|
||||||
|
#define SD_CARD_TYPE_SDHC 3
|
||||||
|
#define SD_CARD_TYPE_MMC 4
|
||||||
|
|
||||||
|
/** @} End of group sd_spi_card_types */
|
||||||
|
|
||||||
|
/**
|
||||||
|
@defgroup sd_spi_error_codes SD Error Codes
|
||||||
|
@brief Error codes for the SD library.
|
||||||
|
@{
|
||||||
|
*/
|
||||||
|
#define SD_ERR_OK 0
|
||||||
|
|
||||||
|
#define SD_ERR_ALREADY_INITIALIZED 1
|
||||||
|
#define SD_ERR_NOT_INITIALIZED 2
|
||||||
|
#define SD_ERR_UNKNOWN_CARD_TYPE 3
|
||||||
|
#define SD_ERR_INIT_TIMEOUT 4
|
||||||
|
#define SD_ERR_COMMAND_TIMEOUT 5
|
||||||
|
#define SD_ERR_OUTSIDE_VOLTAGE_RANGE 6
|
||||||
|
#define SD_ERR_SEND_IF_COND_WRONG_TEST_PATTERN 7
|
||||||
|
#define SD_ERR_OCR_REGISTER 8
|
||||||
|
#define SD_ERR_SETTING_BLOCK_LENGTH 9
|
||||||
|
|
||||||
|
#define SD_ERR_ILLEGAL_COMMAND 10
|
||||||
|
#define SD_ERR_COMMUNICATION_CRC 11
|
||||||
|
#define SD_ERR_ILLEGAL_ADDRESS 12
|
||||||
|
#define SD_ERR_ILLEGAL_PARAMETER 13
|
||||||
|
#define SD_ERR_CARD_IS_LOCKED 14
|
||||||
|
#define SD_ERR_CARD_CONTROLLER 15
|
||||||
|
#define SD_ERR_CARD_ECC_FAILURE 16
|
||||||
|
#define SD_ERR_ARGUMENT_OUT_OF_RANGE 17
|
||||||
|
#define SD_ERR_GENERAL 18
|
||||||
|
|
||||||
|
#define SD_ERR_WRITE_FAILURE 19
|
||||||
|
#define SD_ERR_WRITE_TIMEOUT 20
|
||||||
|
#define SD_ERR_WRITE_OUTSIDE_OF_BLOCK 21
|
||||||
|
#define SD_ERR_WRITE_DATA_REJECTED 22
|
||||||
|
#define SD_ERR_WRITE_DATA_CRC_REJECTED 23
|
||||||
|
#define SD_ERR_WRITE_PRE_ERASE 24
|
||||||
|
#define SD_ERR_WRITE_PROTECTION_VIOLATION 25
|
||||||
|
|
||||||
|
#define SD_ERR_READ_FAILURE 26
|
||||||
|
#define SD_ERR_READ_TIMEOUT 27
|
||||||
|
#define SD_ERR_READ_OUTSIDE_OF_BLOCK 28
|
||||||
|
|
||||||
|
#define SD_ERR_READ_WRITE_CONTINUOUS 29
|
||||||
|
|
||||||
|
#define SD_ERR_ERASE_FAILURE 30
|
||||||
|
#define SD_ERR_ERASE_TIMEOUT 31
|
||||||
|
#define SD_ERR_ERASE_RESET 32
|
||||||
|
#define SD_ERR_WRITE_PROTECTION_ERASE_SKIP 33
|
||||||
|
#define SD_ERR_ERASE_PARAMETER 34
|
||||||
|
#define SD_ERR_ERASE_SEQUENCE 35
|
||||||
|
|
||||||
|
#define SD_ERR_READ_REGISTER 36
|
||||||
|
|
||||||
|
/** @} End of group sd_spi_error_codes */
|
||||||
|
/* R1 token responses */
|
||||||
|
#define SD_IN_IDLE_STATE 0x01
|
||||||
|
#define SD_ERASE_RESET 0x02
|
||||||
|
#define SD_ILLEGAL_COMMAND 0x04
|
||||||
|
#define SD_COMMUNICATION_CRC_ERR 0x08
|
||||||
|
#define SD_ERASE_SEQUENCE_ERR 0x10
|
||||||
|
#define SD_ADDRESS_ERR 0x20
|
||||||
|
#define SD_PARAMETER_ERR 0x40
|
||||||
|
|
||||||
|
/* R2 token responses */
|
||||||
|
#define SD_CARD_IS_LOCKED 0x01
|
||||||
|
#define SD_WP_ERASE_SKIP 0x02
|
||||||
|
#define SD_GENERAL_ERR 0x04
|
||||||
|
#define SD_CC_ERR 0x08
|
||||||
|
#define SD_CARD_ECC_FAILURE 0x10
|
||||||
|
#define SD_WP_VIOLATION 0x20
|
||||||
|
#define SD_ERASE_PARAM 0x40
|
||||||
|
#define SD_OUT_OF_RANGE 0x80
|
||||||
|
|
||||||
|
/* Reading and writing tokens */
|
||||||
|
#define SD_TOKEN_START_BLOCK 0xFE
|
||||||
|
#define SD_TOKEN_MULTIPLE_WRITE_START_BLOCK 0xFC
|
||||||
|
#define SD_TOKEN_MULTIPLE_WRITE_STOP_TRANSFER 0xFD
|
||||||
|
#define SD_TOKEN_DATA_ACCEPTED 0x05
|
||||||
|
#define SD_TOKEN_DATA_REJECTED_CRC 0x0B
|
||||||
|
#define SD_TOKEN_DATA_REJECTED_WRITE_ERR 0x0D
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Initializes the card with the given chip select pin.
|
||||||
|
@details The card is put into a state where it can be sent read, write, and
|
||||||
|
other commands.
|
||||||
|
|
||||||
|
@param chip_select_pin The digital pin connected to the CS on the card.
|
||||||
|
|
||||||
|
@return An error code as defined by one of the SD_ERR_* definitions.
|
||||||
|
*/
|
||||||
|
int8_t
|
||||||
|
sd_spi_init(
|
||||||
|
uint8_t chip_select_pin
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Writes data to a block on the card.
|
||||||
|
@details If buffering is enabled, the card will read the block on the card
|
||||||
|
into the buffer. The passed in data will then be stored in
|
||||||
|
the buffer. The data will be only written out to the card when a
|
||||||
|
different block is written to, read is called, write is called,
|
||||||
|
erase is called, or sd_spi_flush() is explicitly called.
|
||||||
|
If buffering is not enabled, the card will write out the data and
|
||||||
|
pad the rest of the block with zeros if number_of_bytes is less
|
||||||
|
than 512.
|
||||||
|
|
||||||
|
@param block_address The address of the block on the card.
|
||||||
|
@param[in] data An array of data / an address to the data in
|
||||||
|
memory.
|
||||||
|
@param number_of_bytes The size of the data in bytes.
|
||||||
|
@param byte_offset The byte offset of where to start writing in the
|
||||||
|
block.
|
||||||
|
|
||||||
|
@return An error code as defined by one of the SD_ERR_* definitions.
|
||||||
|
*/
|
||||||
|
int8_t
|
||||||
|
sd_spi_write(
|
||||||
|
uint32_t block_address,
|
||||||
|
void *data,
|
||||||
|
uint16_t number_of_bytes,
|
||||||
|
uint16_t byte_offset
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Writes a block of data to a block on the card.
|
||||||
|
@details When buffering is enabled, this is faster than using sd_spi_write
|
||||||
|
since it does not buffer in the block from the card.
|
||||||
|
|
||||||
|
@param block_address The address of the block on the card.
|
||||||
|
@param[in] data An array of data / an address to the data in
|
||||||
|
memory.
|
||||||
|
|
||||||
|
@return An error code as defined by one of the SD_ERR_* definitions.
|
||||||
|
*/
|
||||||
|
int8_t
|
||||||
|
sd_spi_write_block(
|
||||||
|
uint32_t block_address,
|
||||||
|
void *data
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Writes out the data in the buffer to the card if it has not been
|
||||||
|
flushed already. If writing continually, this will also advance to
|
||||||
|
the next block in the sequence.
|
||||||
|
@details This is to be used in conjunction with sd_spi_write or
|
||||||
|
sd_spi_continuous_write.
|
||||||
|
|
||||||
|
@return An error code as defined by one of the SD_ERR_* definitions.
|
||||||
|
*/
|
||||||
|
int8_t
|
||||||
|
sd_spi_flush(
|
||||||
|
void
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Notifies the card to prepare for sequential writing starting at the
|
||||||
|
specified block address.
|
||||||
|
@details A sequential write must be stopped by calling
|
||||||
|
sd_spi_write_continuous_stop(). When buffering is enabled, use
|
||||||
|
sd_spi_write_continuous() in conjunction with sd_spi_write_next().
|
||||||
|
If buffering is disabled, use sd_spi_write_continuous() to write out
|
||||||
|
the data and it will advance to the next block in the sequence
|
||||||
|
automatically.
|
||||||
|
|
||||||
|
@param start_block_address The address of the first block in the
|
||||||
|
sequence.
|
||||||
|
@param num_blocks_pre_erase (Optional) The number of block to pre-erase
|
||||||
|
to potentially speed up writing. It can be
|
||||||
|
set to 0 if the number if the number of
|
||||||
|
blocks is unknown or an estimate can be
|
||||||
|
given since it does not have to be exact.
|
||||||
|
|
||||||
|
@return An error code as defined by one of the SD_ERR_* definitions.
|
||||||
|
*/
|
||||||
|
int8_t
|
||||||
|
sd_spi_write_continuous_start(
|
||||||
|
uint32_t start_block_address,
|
||||||
|
uint32_t num_blocks_pre_erase
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Writes data to the current block in the sequence on the card.
|
||||||
|
@details If buffering is enabled, the data will be stored in the buffer which
|
||||||
|
has been cleared with zeros (current data in the block on the card
|
||||||
|
is not pre-buffered). The data will be only written out to the card
|
||||||
|
when sd_spi_write_continuous_next() or sd_spi_flush() is explicitly
|
||||||
|
called. If the buffering is not enabled, the card will write out the
|
||||||
|
data and advance to the next block in the sequence. If the number of
|
||||||
|
bytes given is less than 512, the rest of the block will be padded
|
||||||
|
with zeros.
|
||||||
|
|
||||||
|
@param[in] data An array of data / an address to the data in
|
||||||
|
memory.
|
||||||
|
@param number_of_bytes The size of the data in bytes.
|
||||||
|
@param byte_offset The byte offset of where to start writing in the
|
||||||
|
block.
|
||||||
|
|
||||||
|
@return An error code as defined by one of the SD_ERR_* definitions.
|
||||||
|
*/
|
||||||
|
int8_t
|
||||||
|
sd_spi_write_continuous(
|
||||||
|
void *data,
|
||||||
|
uint16_t number_of_bytes,
|
||||||
|
uint16_t byte_offset
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Used only when buffering is enabled to write out the data in the
|
||||||
|
buffer to the card for continuous writing and advancing to the
|
||||||
|
next block in the sequence.
|
||||||
|
@details If buffering is not enabled, only use sd_spi_write_continuous().
|
||||||
|
|
||||||
|
@return An error code as defined by one of the SD_ERR_* definitions.
|
||||||
|
*/
|
||||||
|
int8_t
|
||||||
|
sd_spi_write_continuous_next(
|
||||||
|
void
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Notifies the card to stop sequential writing and flushes the buffer
|
||||||
|
to the card if buffering is enabled.
|
||||||
|
@details This may take some time since it waits for the card to complete the
|
||||||
|
write.
|
||||||
|
|
||||||
|
@return An error code as defined by one of the SD_ERR_* definitions.
|
||||||
|
*/
|
||||||
|
int8_t
|
||||||
|
sd_spi_write_continuous_stop(
|
||||||
|
void
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Reads data from a block on the card.
|
||||||
|
@details If buffering is enabled, this will write in the block to the buffer.
|
||||||
|
Otherwise, the device will have to read in the data from the card
|
||||||
|
on every call (it has to read a 512 byte block only the relevant
|
||||||
|
data will be kept).
|
||||||
|
|
||||||
|
@param block_address The address of the block on the card.
|
||||||
|
@param[out] data_buffer A location in memory to write the data to.
|
||||||
|
@param number_of_bytes The number of bytes to read.
|
||||||
|
@param byte_offset The byte offset of where to start reading in the
|
||||||
|
block.
|
||||||
|
|
||||||
|
@return An error code as defined by one of the SD_ERR_* definitions.
|
||||||
|
*/
|
||||||
|
int8_t
|
||||||
|
sd_spi_read(
|
||||||
|
uint32_t block_address,
|
||||||
|
void *data_buffer,
|
||||||
|
uint16_t number_of_bytes,
|
||||||
|
uint16_t byte_offset
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Notifies the card to prepare for sequential reading starting at the
|
||||||
|
specified block address.
|
||||||
|
@details A sequential read must be stopped by calling
|
||||||
|
sd_spi_read_continuous_stop(). When buffering is enabled, use
|
||||||
|
sd_spi_read_continuous() in conjunction with sd_spi_read_next().
|
||||||
|
If buffering is disabled, use sd_spi_read_block() to read in data
|
||||||
|
and advance to the next block in the sequence.
|
||||||
|
|
||||||
|
@param start_block_address The address of the first block in the
|
||||||
|
sequence.
|
||||||
|
|
||||||
|
@return An error code as defined by one of the SD_ERR_* definitions.
|
||||||
|
*/
|
||||||
|
int8_t
|
||||||
|
sd_spi_read_continuous_start(
|
||||||
|
uint32_t start_block_address
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Reads in data from the current block in the sequence on the card.
|
||||||
|
@details If buffering is enabled, the block will be stored in the buffer.
|
||||||
|
To advance to the next block, sd_spi_read_continuous_next() must
|
||||||
|
be explicitly called. If the buffering is not enabled, the card will
|
||||||
|
read in the data and advance to the next block in the sequence.
|
||||||
|
|
||||||
|
@param[out] data_buffer A location in memory to write the data to.
|
||||||
|
@param number_of_bytes The number of bytes to read.
|
||||||
|
@param byte_offset The byte offset of where to start reading in the
|
||||||
|
block.
|
||||||
|
|
||||||
|
@return An error code as defined by one of the SD_ERR_* definitions.
|
||||||
|
*/
|
||||||
|
int8_t
|
||||||
|
sd_spi_read_continuous(
|
||||||
|
void *data_buffer,
|
||||||
|
uint16_t number_of_bytes,
|
||||||
|
uint16_t byte_offset
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Used only when buffering is enabled to advancing to the
|
||||||
|
next block in the sequence.
|
||||||
|
@details If buffering is not enabled, only use sd_spi_read_continuous().
|
||||||
|
|
||||||
|
@return An error code as defined by one of the SD_ERR_* definitions.
|
||||||
|
*/
|
||||||
|
int8_t
|
||||||
|
sd_spi_read_continuous_next(
|
||||||
|
void
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Notifies the card to stop sequential reading.
|
||||||
|
|
||||||
|
@return An error code as defined by one of the SD_ERR_* definitions.
|
||||||
|
*/
|
||||||
|
int8_t
|
||||||
|
sd_spi_read_continuous_stop(
|
||||||
|
void
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Erases all the blocks on the card.
|
||||||
|
@details All of the bits will be set with the default value of 0 or 1
|
||||||
|
HC depending on the card.
|
||||||
|
|
||||||
|
@return An error code as defined by one of the SD_ERR_* definitions.
|
||||||
|
*/
|
||||||
|
int8_t
|
||||||
|
sd_spi_erase_all(
|
||||||
|
void
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Erases the given sequence of blocks on the card.
|
||||||
|
@details All of the bits will be set with the default value of 0 or 1
|
||||||
|
depending on the card.
|
||||||
|
|
||||||
|
@param start_block_address The address of the first block in the
|
||||||
|
sequence.
|
||||||
|
@param end_block_address The address of the last block in the
|
||||||
|
sequence.
|
||||||
|
|
||||||
|
@return An error code as defined by one of the SD_ERR_* definitions.
|
||||||
|
*/
|
||||||
|
int8_t
|
||||||
|
sd_spi_erase_blocks(
|
||||||
|
uint32_t start_block_address,
|
||||||
|
uint32_t end_block_address
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Gets the number of blocks the card has. Blocks are 512 bytes.
|
||||||
|
|
||||||
|
@return An error code as defined by one of the SD_ERR_* definitions.
|
||||||
|
*/
|
||||||
|
uint32_t
|
||||||
|
sd_spi_card_size(
|
||||||
|
void
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Gets the type of the card. 1 = SD1, 2 = SD2, 3 = SDHC, and 4 = MMC.
|
||||||
|
|
||||||
|
@return An error code as defined by one of the SD_ERR_* definitions.
|
||||||
|
*/
|
||||||
|
uint8_t
|
||||||
|
sd_spi_card_type(
|
||||||
|
void
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Reads the Card Identification (CID) register on the card.
|
||||||
|
@details Information is stored in the sd_spi_cid_t structure. The details of
|
||||||
|
the structure can be found in sd_spi_info.h.
|
||||||
|
|
||||||
|
@return An error code as defined by one of the SD_ERR_* definitions.
|
||||||
|
*/
|
||||||
|
int8_t
|
||||||
|
sd_spi_read_cid_register(
|
||||||
|
sd_spi_cid_t *cid
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Reads the Card Specific Data (CSD) register on the card.
|
||||||
|
@details Information is stored in the sd_spi_csd_t structure. The details of
|
||||||
|
the structure can be found in sd_spi_info.h.
|
||||||
|
|
||||||
|
@return An error code as defined by one of the SD_ERR_* definitions.
|
||||||
|
*/
|
||||||
|
int8_t
|
||||||
|
sd_spi_read_csd_register(
|
||||||
|
sd_spi_csd_t *csd
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Returns the first error code (if any) found in the R2 response on
|
||||||
|
from the card.
|
||||||
|
|
||||||
|
@return An error code as defined by one of the SD_ERR_* definitions.
|
||||||
|
*/
|
||||||
|
int8_t
|
||||||
|
sd_spi_card_status(
|
||||||
|
void
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Getter for the address of the block that is currently buffered.
|
||||||
|
|
||||||
|
@return Current buffered block address.
|
||||||
|
*/
|
||||||
|
uint32_t
|
||||||
|
sd_spi_current_buffered_block(
|
||||||
|
void
|
||||||
|
);
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SD_SPI_H_ */
|
|
@ -0,0 +1,280 @@
|
||||||
|
/******************************************************************************/
|
||||||
|
/**
|
||||||
|
@file sd_spi_commands.h
|
||||||
|
@author Wade Penson
|
||||||
|
@date June, 2015
|
||||||
|
@brief SPI bus commands for SD/MMC.
|
||||||
|
@details The set of commands can be found in the simplified physical
|
||||||
|
SD specifications from the SD Association.
|
||||||
|
@copyright Copyright 2015 Wade Penson
|
||||||
|
|
||||||
|
@license Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied. See the License for the specific language governing
|
||||||
|
permissions and limitations under the License.
|
||||||
|
*/
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
#if !defined(SD_SPI_COMMANDS_H_)
|
||||||
|
#define SD_SPI_COMMANDS_H_
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CMD0: Resets card.
|
||||||
|
@param [31:0] Stuff bits
|
||||||
|
@return Register R1
|
||||||
|
*/
|
||||||
|
#define SD_CMD_GO_IDLE_STATE 0x00
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CMD1: Host sends HCS (Host Capacity Support) information. The card then
|
||||||
|
initializes.
|
||||||
|
@param [31] Zero bit
|
||||||
|
@param [30] HCS
|
||||||
|
@param [29:0] Zero bits
|
||||||
|
@return Register R1
|
||||||
|
*/
|
||||||
|
#define SD_CMD_SEND_OP_COND 0x01
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CMD8: Host sends supply voltage and card replies with whether the card
|
||||||
|
can operate based on the voltage or not.
|
||||||
|
@param [31:12] Zero bits
|
||||||
|
@param [11:8] Supply voltage range
|
||||||
|
@param [7:0] Check pattern
|
||||||
|
@return Register R7
|
||||||
|
*/
|
||||||
|
#define SD_CMD_SEND_IF_COND 0x08
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CMD9: Get the card specific data (CSD).
|
||||||
|
@param [31:0] Stuff bits
|
||||||
|
@return Register R1
|
||||||
|
*/
|
||||||
|
#define SD_CMD_SEND_CSD 0x09
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CMD10: Get the card identification (CID).
|
||||||
|
@param [31:0] Stuff bits
|
||||||
|
@return Register R1
|
||||||
|
*/
|
||||||
|
#define SD_CMD_SEND_CID 0x0A
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CMD12: Stops the transmission for the multiple block read operation.
|
||||||
|
@param [31:0] Stuff bits
|
||||||
|
@return Register R1b (R1 with busy signal after)
|
||||||
|
*/
|
||||||
|
#define SD_CMD_STOP_TRANSMISSION 0x0C
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CMD13: Get status from status register.
|
||||||
|
@param [31:0] Stuff bits
|
||||||
|
@return Register R2
|
||||||
|
*/
|
||||||
|
#define SD_CMD_SEND_STATUS 0x0D
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CMD16: Sets the block length, in bytes, for read and write commands of a
|
||||||
|
standard capacity card. However, the standard capacity cards usually
|
||||||
|
only support this command for the read commands. SDHC and SHXC only
|
||||||
|
support reading and writing blocks of size 512 bytes.
|
||||||
|
@param [31:0] Block length
|
||||||
|
@return Register R1
|
||||||
|
*/
|
||||||
|
#define SD_CMD_SET_BLOCKLEN 0x10
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CMD17: Read a single block. The size can be set using CMD_SET_BLOCKLEN
|
||||||
|
for standard capacity cards.
|
||||||
|
@param [31:0] Data address. The address is determined by bytes for standard sd
|
||||||
|
cards and by blocks (512 bytes) for SDHC and SHXC cards.
|
||||||
|
@return Register R1
|
||||||
|
*/
|
||||||
|
#define SD_CMD_READ_SINGLE_BLOCK 0x11
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CMD18: Read blocks continuously and end transmission by sending
|
||||||
|
CMD_STOP_TRANSMISSION.
|
||||||
|
@param [31:0] Data address. The address is determined by bytes for standard
|
||||||
|
sd cards and by blocks (512 bytes) for SDHC and SHXC cards.
|
||||||
|
@return Register R1
|
||||||
|
*/
|
||||||
|
#define SD_CMD_READ_MULTIPLE_BLOCK 0x12
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CMD24: Write a single block.
|
||||||
|
@param [31:0] Data address. The address is determined by bytes for standard
|
||||||
|
sd cards and by blocks (512 bytes) for SDHC and SHXC cards.
|
||||||
|
@return Register R1
|
||||||
|
*/
|
||||||
|
#define SD_CMD_SET_WRITE_BLOCK 0x18
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CMD25: Write blocks continuously and end transmission by sending
|
||||||
|
STOP_TRAN_TOKEN.
|
||||||
|
@param [31:0] Data address. The address is determined by bytes for standard
|
||||||
|
sd cards and by blocks (512 bytes) for SDHC and SHXC cards.
|
||||||
|
@return Register R1
|
||||||
|
*/
|
||||||
|
#define SD_CMD_WRITE_MULTIPLE_BLOCK 0x19
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CMD27: Program the programmable bits of the CSD. These include being
|
||||||
|
able to write multiple times to the TMP_WRITE_PROTECT and CRC fields
|
||||||
|
and writing a single time to the FILE_FORMAT_GRP, COPY,
|
||||||
|
PERM_WRITE_PROTECT, and FILE_FORMAT fields.
|
||||||
|
@param [31:0] Stuff bits
|
||||||
|
@return Register R1
|
||||||
|
*/
|
||||||
|
#define SD_CMD_PROGRAM_CSD 0x1B
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CMD28: Sets write protection for the addressed group for standard
|
||||||
|
capacity cards that support write protected features. WP_GRP_ENABLE
|
||||||
|
in the CSD register can be used to determine if this command is
|
||||||
|
supported and WP_GROUP_SIZE determines the size of a group.
|
||||||
|
@param [31:0] Data address
|
||||||
|
@return Register R1b (R1 with busy signal after)
|
||||||
|
*/
|
||||||
|
#define SD_CMD_SET_WRITE_PROT 0x1C
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CMD29: Clears write protection for the addressed group for standard
|
||||||
|
capacity cards that support write protected features. WP_GRP_ENABLE
|
||||||
|
in the CSD register can be used to determine if this command is
|
||||||
|
supported and WP_GROUP_SIZE determines the size of a group.
|
||||||
|
@param [31:0] Data address
|
||||||
|
@return Register R1b (R1 with busy signal after)
|
||||||
|
*/
|
||||||
|
#define SD_CMD_CLR_WRITE_PROT 0x1D
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CMD30: Send status of the addressed group for standard capacity cards
|
||||||
|
that support write protected features. WP_GRP_ENABLE in the CSD register
|
||||||
|
can be used to determine if this command is supported and WP_GROUP_SIZE
|
||||||
|
determines the size of a group.
|
||||||
|
@param [31:0] Data address
|
||||||
|
@return Register R1
|
||||||
|
*/
|
||||||
|
#define SD_CMD_SEND_WRITE_PROT 0x1E
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CMD32: Sets the address of the first block for writing to be erased.
|
||||||
|
@param [31:0] Data address. The address is determined by bytes for standard
|
||||||
|
sd cards and by blocks (512 bytes) for SDHC and SHXC cards.
|
||||||
|
@return Register R1
|
||||||
|
*/
|
||||||
|
#define SD_CMD_ERASE_WR_BLK_START 0x20
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CMD33: Sets the address of the last block for writing to be erased.
|
||||||
|
@param [31:0] Data address. The address is determined by bytes for standard
|
||||||
|
sd cards and by blocks (512 bytes) for SDHC and SHXC cards.
|
||||||
|
@return Register R1
|
||||||
|
*/
|
||||||
|
#define SD_CMD_ERASE_WR_BLK_END 0x21
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CMD38: Erase the blocks selected by CMD_ERASE_WR_BLK_START and
|
||||||
|
CMD_ERASE_WR_BLK_END.
|
||||||
|
@param [31:0] Stuff bits
|
||||||
|
@return Register R1b (R1 with busy signal after)
|
||||||
|
*/
|
||||||
|
#define SD_CMD_ERASE 0x26
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CMD58: Reads OCR register. CCS bit is assigned to OCR[30].
|
||||||
|
@param [31:0] Stuff bits
|
||||||
|
@return Register R3
|
||||||
|
*/
|
||||||
|
#define SD_CMD_READ_OCR 0x3A
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CMD59: Turns CRC on or off.
|
||||||
|
@param [31:1] Stuff bits
|
||||||
|
@param [0:0] A '1' to turn CRC on and '0' to turn CRC off
|
||||||
|
@return Register R1
|
||||||
|
*/
|
||||||
|
#define SD_CMD_CRC_ON_OFF 0x3B
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CMD55: Tells the card that the next command is an application specific
|
||||||
|
command (ACMD).
|
||||||
|
@param [31:0] Stuff bits
|
||||||
|
@return Register R1
|
||||||
|
*/
|
||||||
|
#define SD_CMD_APP 0x37
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CMD56: For application specific commands, transfer a datablock to or
|
||||||
|
from the card.
|
||||||
|
@param [31:1] Stuff bits
|
||||||
|
@param [0:0] A '1' for reading data and '0' for writing data
|
||||||
|
@return Register R1
|
||||||
|
*/
|
||||||
|
#define SD_CMD_GEN 0x38
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief ACMD13: Get the SD status.
|
||||||
|
@param [31:0] Stuff bits
|
||||||
|
@return Register R2
|
||||||
|
*/
|
||||||
|
#define SD_ACMD_STATUS 0x0D
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief ACMD22: Get the number of blocks that were written without errors.
|
||||||
|
@param [31:0] Stuff bits
|
||||||
|
@return Register R1
|
||||||
|
*/
|
||||||
|
#define SD_ACMD_SEND_NUM_WR_BLOCKS 0x16
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief ACMD23: Set the number of blocks to be erased before writing.
|
||||||
|
@param [31:23] Stuff bits
|
||||||
|
@param [22:0] Number of blocks
|
||||||
|
@return Register R1
|
||||||
|
*/
|
||||||
|
#define SD_ACMD_SET_WR_BLK_ERASE_COUNT 0x17
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief ACMD41: Host sends HCS (Host Capacity Support) information. The card
|
||||||
|
then initializes.
|
||||||
|
@param [31] Zero bit
|
||||||
|
@param [30] HCS
|
||||||
|
@param [29:0] Zero bits
|
||||||
|
@return Register R1
|
||||||
|
*/
|
||||||
|
#define SD_ACMD_SEND_OP_COND 0x29
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief ACMD42: Connects or disconnects the pull-up resistor on the CS pin of
|
||||||
|
the card. May be used for card detection.
|
||||||
|
@param [31:1] Stuff bits
|
||||||
|
@param [0:0] A '1' to connect pull-up and '0' to disconnect pull-up
|
||||||
|
@return Register R1
|
||||||
|
*/
|
||||||
|
#define SD_ACMD_SET_CLR_CARD_DETECT 0x2A
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief ACMD51: Reads SCR (SD configuration) register.
|
||||||
|
@param [31:0] Stuff bits
|
||||||
|
@return Register R1
|
||||||
|
*/
|
||||||
|
#define SD_ACMD_SEND_SCR 0x33
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SD_SPI_COMMANDS_H_ */
|
|
@ -0,0 +1,201 @@
|
||||||
|
/******************************************************************************/
|
||||||
|
/**
|
||||||
|
@file sd_spi_info.h
|
||||||
|
@author Wade Penson
|
||||||
|
@date June, 2015
|
||||||
|
@brief Structures to store information from CID (Card Identification)
|
||||||
|
and CSD (Card Specific Data) registers for SD cards.
|
||||||
|
@details Information about the fields can be found in the simplified
|
||||||
|
physical SD specifications from the SD Association.
|
||||||
|
@copyright Copyright 2015 Wade Penson
|
||||||
|
|
||||||
|
@license Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied. See the License for the specific language governing
|
||||||
|
permissions and limitations under the License.
|
||||||
|
*/
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
#if !defined(SD_SPI_INFO_H_)
|
||||||
|
#define SD_SPI_INFO_H_
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CID register information
|
||||||
|
*/
|
||||||
|
typedef struct sd_spi_cid
|
||||||
|
{
|
||||||
|
/** Manufacturer ID. */
|
||||||
|
unsigned int mid: 8;
|
||||||
|
/** OEM/Application ID. Composed of 2 characters. */
|
||||||
|
char oid[2];
|
||||||
|
/** Product name. Composed of 5 characters. */
|
||||||
|
char pnm[5];
|
||||||
|
/** n part of the product revision number, which is in the form of n.m */
|
||||||
|
unsigned int prv_n: 4;
|
||||||
|
/** m part of the product revision number, which is in the form of n.m */
|
||||||
|
unsigned int prv_m: 4;
|
||||||
|
/** Bits [31:24] of the 4 byte product serial number. */
|
||||||
|
unsigned int psn_high: 8;
|
||||||
|
/** Bits [23:16] of the 4 byte product serial number. */
|
||||||
|
unsigned int psn_mid_high: 8;
|
||||||
|
/** Bits [15:8] of the 4 byte product serial number. */
|
||||||
|
unsigned int psn_mid_low: 8;
|
||||||
|
/** Bits [7:0] of the 4 byte product serial number. */
|
||||||
|
unsigned int psn_low: 8;
|
||||||
|
/** Year manufactured. */
|
||||||
|
unsigned int mdt_year: 8;
|
||||||
|
/** Month manufactured. */
|
||||||
|
unsigned int mdt_month: 4;
|
||||||
|
/* Bitfield padding */
|
||||||
|
unsigned int: 4;
|
||||||
|
/** Checksum for the CID. */
|
||||||
|
unsigned int crc: 7;
|
||||||
|
/* Bitfield padding */
|
||||||
|
unsigned int: 1;
|
||||||
|
} sd_spi_cid_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Information exclusive to CSD register version 1.
|
||||||
|
|
||||||
|
@details The following formula is used to compute the card's size:<br><br>
|
||||||
|
Card size in MB = Number of blocks * 512 / 1000000<br>
|
||||||
|
Number of blocks = ((c_size + 1) * 2<SUP>c_size_mult + 2</SUP>) *
|
||||||
|
(2<SUP>max_read_bl_len</SUP> / 512)<br>
|
||||||
|
*/
|
||||||
|
typedef struct sd_spi_csd_v1
|
||||||
|
{
|
||||||
|
/** Low bits of c_size. Used to compute the card's size. */
|
||||||
|
unsigned int c_size_low: 8;
|
||||||
|
/** High bits of c_size. Used to compute the card's size. */
|
||||||
|
unsigned int c_size_high: 4;
|
||||||
|
/** Max read current for minimal supply voltage. */
|
||||||
|
unsigned int vdd_r_curr_min: 3;
|
||||||
|
/* Bitfield padding */
|
||||||
|
unsigned int: 1;
|
||||||
|
/** Max read current for max supply voltage. */
|
||||||
|
unsigned int vdd_r_curr_max: 3;
|
||||||
|
/** Max write current for minimal supply voltage. */
|
||||||
|
unsigned int vdd_w_curr_min: 3;
|
||||||
|
/* Bitfield padding */
|
||||||
|
unsigned int: 2;
|
||||||
|
/** Max write current for max supply voltage. */
|
||||||
|
unsigned int vdd_w_curr_max: 3;
|
||||||
|
/** Multiplier used to compute the card's size. */
|
||||||
|
unsigned int c_size_mult: 3;
|
||||||
|
/* Bitfield padding */
|
||||||
|
unsigned int: 2;
|
||||||
|
} sd_spi_csd_v1_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Information exclusive to CSD register version 2
|
||||||
|
|
||||||
|
@details The card size is computed as follows:<br><br>
|
||||||
|
Card size in MB = (c_size + 1) * 512 / 1000
|
||||||
|
*/
|
||||||
|
typedef struct sd_spi_csd_v2
|
||||||
|
{
|
||||||
|
/** Low bits of c_size. Used to compute the card's size. */
|
||||||
|
unsigned int c_size_low: 8;
|
||||||
|
/** Mid bits of c_size. Used to compute the card's size. */
|
||||||
|
unsigned int c_size_mid: 8;
|
||||||
|
/** High bits of c_size. Used to compute the card's size. */
|
||||||
|
unsigned int c_size_high: 6;
|
||||||
|
/* Bitfield padding */
|
||||||
|
unsigned int: 2;
|
||||||
|
} sd_spi_csd_v2_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief The CSD register is either version 1 or version 2. Space is saved by
|
||||||
|
unioning the specific version information for version 1 and 2. The
|
||||||
|
csd_v1 structure is for version 1 and the csd_v2 is for version 2.
|
||||||
|
*/
|
||||||
|
typedef union sd_spi_csd_v_info
|
||||||
|
{
|
||||||
|
sd_spi_csd_v1_t v1;
|
||||||
|
sd_spi_csd_v2_t v2;
|
||||||
|
} sd_spi_csd_v_info_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CSD register information
|
||||||
|
@details The CSD version is determined by the csd_structure value. If the
|
||||||
|
value is 0, the CSD is version 1 so the csvi will contain the
|
||||||
|
v1 type specific information. Otherwise, the CSD is version 2 so
|
||||||
|
the csvi will contain the v2 type specific information. Further
|
||||||
|
details about the fields can be found in the SD specifications.
|
||||||
|
*/
|
||||||
|
typedef struct sd_spi_csd
|
||||||
|
{
|
||||||
|
/** Union of the CSD version specific info. */
|
||||||
|
sd_spi_csd_v_info_t cvsi;
|
||||||
|
/** CSD version. */
|
||||||
|
unsigned int csd_structure: 2;
|
||||||
|
/** The file format of the card. */
|
||||||
|
unsigned int file_format: 2;
|
||||||
|
/* Bitfield padding */
|
||||||
|
unsigned int: 4;
|
||||||
|
/** Asynchronous part of data access time. Table of the corresponding
|
||||||
|
values are found in the SD specifications. */
|
||||||
|
unsigned int taac: 8;
|
||||||
|
/** Worst case for the clock dependent factor of the data access time.*/
|
||||||
|
unsigned int nsac: 8;
|
||||||
|
/** Max data transfer speed for a single data line. */
|
||||||
|
unsigned int tran_speed: 8;
|
||||||
|
/** Low bits of the ccc; the command class of the card. */
|
||||||
|
unsigned int ccc_low: 8;
|
||||||
|
/** High bits of the ccc; the command class of the card. */
|
||||||
|
unsigned int ccc_high: 4;
|
||||||
|
/** Max block length. */
|
||||||
|
unsigned int max_read_bl_len: 4;
|
||||||
|
/** Defines if the card can read partial blocks. */
|
||||||
|
unsigned int read_bl_partial: 1;
|
||||||
|
/** Defines if a data block can be spanned over a block boundary when
|
||||||
|
written. */
|
||||||
|
unsigned int write_bl_misalign: 1;
|
||||||
|
/** Defines if a data can be read over block boundaries. */
|
||||||
|
unsigned int read_bl_misalign: 1;
|
||||||
|
/** Defines if the configurable driver stage is implemented in the card. */
|
||||||
|
unsigned int dsr_imp: 1;
|
||||||
|
/** Defines the unit size of data being erased. */
|
||||||
|
unsigned int erase_bl_en: 1;
|
||||||
|
/** Ratio of read to write time. */
|
||||||
|
unsigned int r2w_factor: 3;
|
||||||
|
/** The size of an erasable sector. */
|
||||||
|
unsigned int erase_sector_size: 7;
|
||||||
|
/** Defines if write group protection is possible. */
|
||||||
|
unsigned int wp_grp_enable: 1;
|
||||||
|
/** The size of a write protected group. */
|
||||||
|
unsigned int wp_grp_size: 7;
|
||||||
|
/** Defines if the card can write partial blocks. */
|
||||||
|
unsigned int write_bl_partial: 1;
|
||||||
|
/** The max write block length. */
|
||||||
|
unsigned int write_bl_len: 4;
|
||||||
|
/** The file format group of the card. */
|
||||||
|
unsigned int file_format_grp: 1;
|
||||||
|
/** Defines if the cards content is original or is a copy. */
|
||||||
|
unsigned int copy: 1;
|
||||||
|
/** Determines if the card is permanently write protected or not. */
|
||||||
|
unsigned int perm_write_protect: 1;
|
||||||
|
/** Determines if the card is temporarily write protected or not. */
|
||||||
|
unsigned int tmp_write_protect: 1;
|
||||||
|
/** Checksum for the CSD. */
|
||||||
|
unsigned int crc: 7;
|
||||||
|
/* Bitfield padding */
|
||||||
|
unsigned int: 1;
|
||||||
|
} sd_spi_csd_t;
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SD_SPI_INFO_H_ */
|
|
@ -0,0 +1,67 @@
|
||||||
|
#include "sd_spi_platform_dependencies.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
sd_spi_pin_mode(
|
||||||
|
uint8_t pin,
|
||||||
|
uint8_t mode
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sd_spi_digital_write(
|
||||||
|
uint8_t pin,
|
||||||
|
uint8_t state
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
sd_spi_millis(
|
||||||
|
void
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sd_spi_begin(
|
||||||
|
void
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sd_spi_begin_transaction(
|
||||||
|
uint32_t transfer_speed_hz
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sd_spi_end_transaction(
|
||||||
|
void
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sd_spi_send_byte(
|
||||||
|
uint8_t b
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t
|
||||||
|
sd_spi_receive_byte(
|
||||||
|
void
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
/******************************************************************************/
|
||||||
|
/**
|
||||||
|
@file sd_spi_platform_dependencies.cpp
|
||||||
|
@author Wade Penson
|
||||||
|
@date June, 2015
|
||||||
|
@brief Interface for the dependencies needed by the SD SPI library.
|
||||||
|
@copyright Copyright 2015 Wade Penson
|
||||||
|
|
||||||
|
@license Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied. See the License for the specific language governing
|
||||||
|
permissions and limitations under the License.
|
||||||
|
*/
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
#if !defined(SD_SPI_PLATFORM_DEPENDENCIES_H_)
|
||||||
|
#define SD_SPI_PLATFORM_DEPENDENCIES_H_
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#if !defined(INPUT)
|
||||||
|
#define INPUT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(OUTPUT)
|
||||||
|
#define OUTPUT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(LOW)
|
||||||
|
#define LOW 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(HIGH)
|
||||||
|
#define HIGH 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
sd_spi_pin_mode(
|
||||||
|
uint8_t pin,
|
||||||
|
uint8_t mode
|
||||||
|
);
|
||||||
|
|
||||||
|
void
|
||||||
|
sd_spi_digital_write(
|
||||||
|
uint8_t pin,
|
||||||
|
uint8_t state
|
||||||
|
);
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
sd_spi_millis(
|
||||||
|
void
|
||||||
|
);
|
||||||
|
|
||||||
|
void
|
||||||
|
sd_spi_begin(
|
||||||
|
void
|
||||||
|
);
|
||||||
|
|
||||||
|
void
|
||||||
|
sd_spi_begin_transaction(
|
||||||
|
uint32_t transfer_speed_hz
|
||||||
|
);
|
||||||
|
|
||||||
|
void
|
||||||
|
sd_spi_end_transaction(
|
||||||
|
void
|
||||||
|
);
|
||||||
|
|
||||||
|
void
|
||||||
|
sd_spi_send_byte(
|
||||||
|
uint8_t b
|
||||||
|
);
|
||||||
|
|
||||||
|
uint8_t
|
||||||
|
sd_spi_receive_byte(
|
||||||
|
void
|
||||||
|
);
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SD_SPI_PLATFORM_DEPENDENCIES_H_ */
|
Loading…
Reference in New Issue