30 #include <libopencmsis/core_cm3.h> 31 #include <libopencm3/stm32/rcc.h> 32 #include <libopencm3/stm32/gpio.h> 33 #include <libopencm3/stm32/spi.h> 41 #define FLASH_SDCARD_SPI 1 45 static bool initialized = false; 65 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
66 0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26, 0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e,
67 0x32, 0x3b, 0x20, 0x29, 0x16, 0x1f, 0x04, 0x0d, 0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45,
68 0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14, 0x63, 0x6a, 0x71, 0x78, 0x47, 0x4e, 0x55, 0x5c,
69 0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b, 0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13,
70 0x7d, 0x74, 0x6f, 0x66, 0x59, 0x50, 0x4b, 0x42, 0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a,
71 0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69, 0x1e, 0x17, 0x0c, 0x05, 0x3a, 0x33, 0x28, 0x21,
72 0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70, 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38,
73 0x41, 0x48, 0x53, 0x5a, 0x65, 0x6c, 0x77, 0x7e, 0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36,
74 0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67, 0x10, 0x19, 0x02, 0x0b, 0x34, 0x3d, 0x26, 0x2f,
75 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04,
76 0x6a, 0x63, 0x78, 0x71, 0x4e, 0x47, 0x5c, 0x55, 0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d,
77 0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a, 0x6d, 0x64, 0x7f, 0x76, 0x49, 0x40, 0x5b, 0x52,
78 0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03, 0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b,
79 0x17, 0x1e, 0x05, 0x0c, 0x33, 0x3a, 0x21, 0x28, 0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60,
80 0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31, 0x46, 0x4f, 0x54, 0x5d, 0x62, 0x6b, 0x70, 0x79
123 for (uint8_t i=0; i<
LENGTH(command); i++) {
125 crc7 = (
crc7_table[((crc7<<1)^command[i])])&0x7f;
146 for (uint8_t i=0; i<8 && r1&0x80; i++) {
149 if (0x00==(r1&0xfe) && 0!=size && NULL!=response) {
150 for (
size_t i=0; i<size; i++) {
170 if (size%2 || 0==size || NULL==data) {
174 uint8_t token = 0xff;
175 for (uint32_t i=0; i<
n_ac && token==0xff; i++) {
178 if (0==(token&0xf0)) {
179 if (0==(token&0x0f)) {
182 }
else if (0xfe==token) {
192 for (
size_t i=0; i<size/2; i++) {
194 data[i*2+0] = (word>>8);
195 data[i*2+1] = (word>>0);
224 if (size%2 || 0==size || NULL==data) {
239 for (
size_t i=0; i<size/2; i++) {
240 uint16_t word = (data[i*2+0]<<8)+data[i*2+1];
253 uint8_t token = 0xff;
254 while (0x01!=(token&0x11)) {
279 uint16_t r2 = 0xffff;
280 for (uint8_t i=0; i<8 && r2&0x8000; i++) {
283 if (0==(r2&0x8000)) {
311 if (size%2 || 0==size || NULL==data) {
322 for (uint8_t i=0; i<8 && r1&0x80; i++) {
351 if (size%2 || 0==size || NULL==data) {
362 for (uint8_t i=0; i<8 && r1&0x80; i++) {
404 rcc_periph_clock_enable(RCC_AFIO);
407 spi_init_master(
SPI(
FLASH_SDCARD_SPI), SPI_CR1_BAUDRATE_FPCLK_DIV_256, SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE, SPI_CR1_CPHA_CLK_TRANSITION_1, SPI_CR1_DFF_8BIT, SPI_CR1_MSBFIRST);
429 }
else if (0xaa!=r7[3]) {
432 }
else if (0x05!=r1) {
440 }
else if (!(r3[1]&0x30)) {
461 if (0x00==(r3[0]&0x80)) {
464 sdsc = (0==(r3[0]&0x40));
475 uint8_t csd[16] = {0};
481 if ((
sdsc && (csd[0]>>6)) || (!
sdsc && 0==(csd[0]>>6))) {
486 static const float TAAC_UNITS[] = {1E-9, 10E-9, 100E-9, 1E-6, 10E-6, 100E-6, 1E-3, 10E-3};
487 static const float TAAC_VALUES[] = {10.0, 1.0, 1.2, 1.3, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 7.0, 8.0};
488 double taac = TAAC_VALUES[(csd[1]>>2)&0xf]*TAAC_UNITS[csd[1]&0x7];
489 n_ac=100*((taac*16E6)+(csd[2]*100))/8;
495 uint16_t c_size = (((uint16_t)csd[6]&0x03)<<10)+((uint16_t)csd[7]<<2)+(csd[8]>>6);
496 uint8_t c_size_mutl = ((csd[9]&0x03)<<1)+((csd[10]&0x80)>>7);
497 uint8_t read_bl_len = (csd[5]&0x0f);
498 sdcard_size = ((c_size+1)*(1UL<<(c_size_mutl+2)))*(1UL<<read_bl_len);
500 uint32_t c_size = ((uint32_t)(csd[7]&0x3f)<<16)+((uint16_t)csd[8]<<8)+csd[9];
505 erase_size = (((csd[10]&0x3f)<<1)+((csd[11]&0x80)>>7)+1)<<(((csd[12]&0x03)<<2)+(csd[13]>>6));
507 uint8_t status[64] = {0};
525 uint32_t n_ac_back =
n_ac;
526 n_ac = 100E-3*16E6/8;
528 uint8_t fnc[64] = {0};
533 if (0x1==(fnc[16]&0x0f)) {
538 if (0x1!=(fnc[16]&0x0f)) {
573 if (block>UINT32_MAX/512) {
589 if (block>UINT32_MAX/512) {
597 if (0x05!=(drt&0x1f)) {
#define SPI_MOSI_PORT(x)
get SPI port for MOSI signal based on SPI identifier
static uint8_t flash_sdcard_write_block(uint8_t *data, size_t size)
write a data block
library to communicate with an SD card flash memory using the SPI mode (API)
static bool flash_sdcard_card_detect(void)
test if card is present
static uint8_t flash_sdcard_data_write(uint8_t index, uint32_t argument, uint8_t *data, size_t size)
transmit command token, receive response token and write data block
#define SPI_NSS_PORT(x)
get SPI port for NSS signal based on SPI identifier
#define SPI_CRC_PR(x)
get SPI CRC polynomial register based on SPI identifier
#define SPI_MOSI_PIN(x)
get SPI pin for MOSI signal based on SPI identifier
static bool initialized
if the card has been initialized successfully
static bool sdsc
is it a Standard Capacity SD card (true), or High Capacity SD cards (false)
global definitions and methods (API)
enum menu_argument_t argument
what kind of argument it accepts
#define SPI_CRC_RXR(x)
get SPI CRC receive register based on SPI identifier
static uint16_t flash_sdcard_status(uint8_t *status)
get card status
#define RCC_SPI_MISO_PORT(x)
get RCC for GPIO port for SPI MISO signals
static uint32_t n_ac
maximum N_AC value (in 8-clock cycles) (time between the response token R1 and data block when readin...
#define RCC_SPI_MOSI_PORT(x)
get RCC for GPIO port for SPI MOSI signals
#define RCC_SPI(x)
get RCC for SPI based on SPI identifier
uint64_t flash_sdcard_size(void)
get size of SD card flash memory
#define SPI_NSS_PIN(x)
get SPI pin for NSS signal based on SPI identifier
#define SPI_SCK_PORT(x)
get SPI port for SCK signal based on SPI identifier
static uint16_t flash_sdcard_spi_read(void)
read one SPI word
static uint8_t flash_sdcard_read_block(uint8_t *data, size_t size)
read a data block
static void flash_sdcard_spi_wait(void)
wait one SPI round (one SPI word)
#define SPI_MISO_PORT(x)
get SPI port for MISO signal based on SPI identifier
#define SPI(x)
get SPI based on SPI identifier
static uint8_t flash_sdcard_data_read(uint8_t index, uint32_t argument, uint8_t *data, size_t size)
transmit command token, receive response token and data block
#define RCC_SPI_SCK_PORT(x)
get RCC for GPIO port for SPI SCK signals
bool flash_sdcard_read_data(uint32_t block, uint8_t *data)
read data on flash of SD card
#define LENGTH(x)
get the length of an array
static uint8_t flash_sdcard_command_response(uint8_t index, uint32_t argument, uint8_t *response, size_t size)
transmit command token and receive response token
bool flash_sdcard_setup(void)
setup communication with SD card
static uint64_t sdcard_size
size of card in bytes
#define SPI_MISO_PIN(x)
get SPI pin for MISO signal based on SPI identifier
bool flash_sdcard_write_data(uint32_t block, uint8_t *data)
write data on flash of SD card
static uint32_t erase_size
size of an erase block bytes
#define RCC_SPI_NSS_PORT(x)
get RCC for GPIO port for SPI NSS signals
static void flash_sdcard_send_command(uint8_t index, uint32_t argument)
transmit command token
#define FLASH_SDCARD_SPI
SPI peripheral.
#define SPI_SCK_PIN(x)
get SPI pin for SCK signal based on SPI identifier
uint32_t flash_sdcard_erase_size(void)
get size of a erase block
static const uint8_t crc7_table[]
table for CRC-7 calculation for the command messages (see section 4.5)