31#define PX_SD_CMD0_GO_IDLE_STATE 0
32#define PX_SD_CMD1_SEND_OP_COND 1
33#define PX_SD_CMD6_SWITCH_FUNC 6
34#define PX_SD_CMD8_SEND_IF_COND 8
35#define PX_SD_CMD9_SEND_CSD 9
36#define PX_SD_CMD10_SEND_CID 10
37#define PX_SD_CMD12_STOP_TRANSMISSION 12
38#define PX_SD_CMD13_SEND_STATUS 13
39#define PX_SD_CMD16_SET_BLOCKLEN 16
40#define PX_SD_CMD17_READ_SINGLE_BLOCK 17
41#define PX_SD_CMD18_READ_MULT_BLOCK 18
42#define PX_SD_CMD24_WRITE_BLOCK 24
43#define PX_SD_CMD25_WRITE_MULT_BLOCK 25
44#define PX_SD_CMD27_PROGRAM_CSD 27
45#define PX_SD_CMD28_SET_WRITE_PROT 28
46#define PX_SD_CMD29_CLR_WRITE_PROT 29
47#define PX_SD_CMD30_SEND_WRITE_PROT 30
48#define PX_SD_CMD32_ERASE_WR_BLK_START_ADR 32
49#define PX_SD_CMD33_ERASE_WR_BLK_END_ADR 33
50#define PX_SD_CMD38_ERASE 38
51#define PX_SD_CMD42_LOCK_UNLOCK 42
52#define PX_SD_CMD48_READ_EXTR_SINGLE 48
53#define PX_SD_CMD49_WRITE_EXTR_SINGLE 49
54#define PX_SD_CMD55_APP_CMD 55
55#define PX_SD_CMD56_GEN_CMD 56
56#define PX_SD_CMD58_READ_OCR 58
57#define PX_SD_CMD59_CRC_ON_OFF 59
61#define PX_SD_ACMD_MARKER_BIT 7
64#define PX_SD_ACMD13_SD_STATUS ((1 << PX_SD_ACMD_MARKER_BIT) + 13)
65#define PX_SD_ACMD22_SEND_NUM_WR_BLOCKS ((1 << PX_SD_ACMD_MARKER_BIT) + 22)
66#define PX_SD_ACMD23_SET_WR_BLOCK_COUNT ((1 << PX_SD_ACMD_MARKER_BIT) + 23)
67#define PX_SD_ACMD41_SD_SEND_OP_COND ((1 << PX_SD_ACMD_MARKER_BIT) + 41)
68#define PX_SD_ACMD42_SET_CLR_CARD_DETECT ((1 << PX_SD_ACMD_MARKER_BIT) + 42)
69#define PX_SD_ACMD51_SEND_SCR ((1 << PX_SD_ACMD_MARKER_BIT) + 51)
72#define PX_SD_RESP_R1_START_BIT 7
73#define PX_SD_RESP_R1_ERR_PARAM 6
74#define PX_SD_RESP_R1_ERR_ADR 5
75#define PX_SD_RESP_R1_ERR_ERASE_SEQ 4
76#define PX_SD_RESP_R1_ERR_COM_CRC 3
77#define PX_SD_RESP_R1_ILLEGAL_CMD 2
78#define PX_SD_RESP_R1_ERASE_RESET 1
79#define PX_SD_RESP_R1_IDLE_STATE 0
82#define PX_SD_TOKEN_DATA_BLOCK_START 0xfe
83#define PX_SD_TOKEN_DATA_BLOCK_START_MULT_WR 0xfc
84#define PX_SD_TOKEN_DATA_BLOCK_STOP_MULT_WR 0xfd
87#define PX_SD_TOKEN_DATA_RESP_MASK 0x1f
88#define PX_SD_TOKEN_DATA_RESP_DATA_OK 0x05
89#define PX_SD_TOKEN_DATA_RESP_CRC_ERROR 0x0b
90#define PX_SD_TOKEN_DATA_RESP_WRITE_ERROR 0x0d
98static uint8_t px_sd_rx_data[4];
99static px_sd_card_type_t px_sd_card_type;
104static uint8_t px_sd_spi_xc_u8(uint8_t data)
110 px_spi_xc(px_spi_handle_sd, data_tx, data_rx, 1, 0);
115static uint8_t px_sd_spi_rd_u8(
void)
117 return px_sd_spi_xc_u8(0xff);
120static void px_sd_spi_rd(
void *data,
size_t nr_of_bytes)
122 uint8_t * data_u8 = (uint8_t *)data;
123 while(nr_of_bytes != 0)
125 *data_u8++ = px_sd_spi_rd_u8();
130static void px_sd_spi_wr_u8(uint8_t data)
132 px_sd_spi_xc_u8(data);
135static void px_sd_spi_wr(
const void * data,
size_t nr_of_bytes)
137 const uint8_t * data_u8 = (uint8_t * )data;
138 while(nr_of_bytes != 0)
140 px_sd_spi_xc_u8(*data_u8++);
145static void px_sd_spi_cs_lo(
void)
150static void px_sd_spi_cs_end(
void)
158static bool px_sd_wait_ready(
void)
163 for(retry = 5000; retry != 0; retry--)
165 if(px_sd_spi_rd_u8() == 0xff)
173 PX_LOG_E(
"Timed-out waiting for SD card to be ready");
177static uint8_t px_sd_tx_cmd_rx_resp_r1(uint8_t cmd, uint32_t arg)
187 r1 = px_sd_tx_cmd_rx_resp_r1(PX_SD_CMD55_APP_CMD, 0);
189 if((r1 & ~(1 << PX_SD_RESP_R1_IDLE_STATE)) != 0)
191 PX_LOG_E(
"CMD55 received R1 = 0x%02x", r1);
205 if(!px_sd_wait_ready())
211 px_sd_spi_wr_u8(0x40 | cmd);
220 case PX_SD_CMD0_GO_IDLE_STATE:
222 px_sd_spi_wr_u8(0x95);
224 case PX_SD_CMD8_SEND_IF_COND:
226 px_sd_spi_wr_u8(0x87);
235 for(retry = 8; retry != 0; retry--)
237 r1 = px_sd_spi_rd_u8();
247 PX_LOG_E(
"Timed out waiting for R1 response (received 0x%02x)", r1);
258static uint8_t px_sd_rx_data_block(uint8_t * data,
size_t nr_of_bytes)
262 uint8_t px_crc_hi, px_crc_lo;
265 for(retry = 1000; retry != 0; retry--)
267 data_token = px_sd_spi_rd_u8();
268 if(data_token != 0xff)
270 PX_LOG_D(
"Data token = %02hX", data_token);
279 PX_LOG_E(
"Timed-out waiting for data token");
283 px_sd_spi_rd(data, nr_of_bytes);
285 px_crc_hi = px_sd_spi_rd_u8();
286 px_crc_lo = px_sd_spi_rd_u8();
289 PX_LOG_D(
"CRC = %02hX %02hX", px_crc_hi, px_crc_lo);
301static uint8_t px_sd_tx_data_block(
const uint8_t * data,
size_t nr_of_bytes, uint8_t data_token_start)
306 if(!px_sd_wait_ready())
311 px_sd_spi_wr_u8(data_token_start);
313 px_sd_spi_wr(data, nr_of_bytes);
318 data_token = px_sd_spi_rd_u8();
319 PX_LOG_D(
"Data response token = 0x%02X", data_token);
328 px_spi_handle_sd = handle;
337 px_sd_card_type = PX_SD_CARD_TYPE_INVALID;
344 for(retry = 10; retry != 0 ; retry--)
349 for(retry = 100; retry != 0; retry--)
352 r1 = px_sd_tx_cmd_rx_resp_r1(PX_SD_CMD0_GO_IDLE_STATE, 0);
354 if(r1 == (1 << PX_SD_RESP_R1_IDLE_STATE))
362 PX_LOG_E(
"Unable to put SD Card in idle state (R1 = 0x%02X)", r1);
374 r1 = px_sd_tx_cmd_rx_resp_r1(PX_SD_CMD8_SEND_IF_COND, 0x000001aa);
376 if(r1 == (1 << PX_SD_RESP_R1_IDLE_STATE))
379 PX_LOG_D(
"Ver 2.00 or later SD Card");
381 px_sd_spi_rd(px_sd_rx_data, 4);
382 if( (px_sd_rx_data[2] != 0x01)
383 ||(px_sd_rx_data[3] != 0xaa) )
386 if(px_sd_rx_data[2] != 0x01)
388 PX_LOG_E(
"Voltage not accepted (received 0x%02X)", px_sd_rx_data[2]);
390 if(px_sd_rx_data[3] != 0xaa)
392 PX_LOG_E(
"Expected 0xaa, but received 0x%02X echo", px_sd_rx_data[3]);
399 r1 = px_sd_tx_cmd_rx_resp_r1(PX_SD_CMD59_CRC_ON_OFF, 0);
400 if(r1 != (1 << PX_SD_RESP_R1_IDLE_STATE))
402 PX_LOG_E(
"Incorrect response to CMD59 (R1 = 0x%02X)", r1);
407 for(wait = 1000; wait != 0; wait--)
415 if(px_sd_tx_cmd_rx_resp_r1(PX_SD_ACMD41_SD_SEND_OP_COND, (1ul << 30)) == 0)
418 r1 = px_sd_tx_cmd_rx_resp_r1(PX_SD_CMD58_READ_OCR, 0);
423 px_sd_spi_rd(px_sd_rx_data, 4);
424 PX_LOG_D(
"OCR = 0x%02x%02x%02x%02x",
425 px_sd_rx_data[0], px_sd_rx_data[1],
426 px_sd_rx_data[2], px_sd_rx_data[3]);
428 if(px_sd_rx_data[0] & (1 << 6))
430 PX_LOG_D(
"Ver 2.00 HCSD or XCSD Card");
431 px_sd_card_type = PX_SD_CARD_TYPE_VER_2_HCSD_XCSD;
436 px_sd_card_type = PX_SD_CARD_TYPE_VER_2_SCSD;
441 PX_LOG_E(
"Incorrect response to CMD58 (R1 = 0x%02X)", r1);
453 PX_LOG_E(
"Timed out waiting for ACMD41 init to finish");
461 PX_LOG_D(
"Ver 1.xx SD Card (or not?)");
463 r1 = px_sd_tx_cmd_rx_resp_r1(PX_SD_CMD59_CRC_ON_OFF, 0);
464 if(r1 != (1 << PX_SD_RESP_R1_IDLE_STATE))
466 PX_LOG_E(
"Incorrect response to CMD59 (R1 = 0x%02X)", r1);
471 for(wait = 1000; wait != 0; wait--)
479 r1 = px_sd_tx_cmd_rx_resp_r1(PX_SD_ACMD41_SD_SEND_OP_COND, 0);
491 PX_LOG_E(
"Timed out waiting for ACMD41 init to finish (R1 = 0x%02X)", r1);
499 PX_LOG_E(
"Incorrect response to CMD16 (R1 = 0x%02X)", r1);
504 px_sd_card_type = PX_SD_CARD_TYPE_VER_1_SD;
516 uint8_t r1, data_token;
519 r1 = px_sd_tx_cmd_rx_resp_r1(PX_SD_CMD10_SEND_CID, 0);
523 PX_LOG_E(
"Incorrect response to CMD10 (R1 = 0x%02X)", r1);
528 data_token = px_sd_rx_data_block((uint8_t *) cid,
sizeof(*cid));
529 if(data_token != PX_SD_TOKEN_DATA_BLOCK_START)
541 uint8_t r1, data_token;
544 r1 = px_sd_tx_cmd_rx_resp_r1(PX_SD_CMD9_SEND_CSD, 0);
548 PX_LOG_E(
"Incorrect response to CMD9 (R1 = 0x%02X)", r1);
553 data_token = px_sd_rx_data_block((uint8_t *) csd,
sizeof(*csd));
554 if(data_token != PX_SD_TOKEN_DATA_BLOCK_START)
556 PX_LOG_E(
"Incorrect data token (received 0x%02X)", data_token);
576 r1 = px_sd_tx_cmd_rx_resp_r1(PX_SD_CMD13_SEND_STATUS, 0);
580 PX_LOG_E(
"Incorrect response to CMD13 (R1 = 0x%02X)", r1);
585 r2 = px_sd_spi_rd_u8();
587 *status = ((uint16_t)r1<<8) + r2;
595 uint32_t capacity = 0;
602 PX_LOG_D(
"c_size_mult_hi = %02hX", csd->ver.csd_1_0.c_size_mult_hi);
603 PX_LOG_D(
"c_size_mult_lo = %02hX", csd->ver.csd_1_0.c_size_mult_lo);
607 + (csd->ver.csd_1_0.c_size_mult_hi << 1)
608 + csd->ver.csd_1_0.c_size_mult_lo + 2;
612 PX_LOG_D(
"c_size_hi = %02hX", csd->ver.csd_1_0.c_size_hi);
613 PX_LOG_D(
"c_size_mid = %02hX", csd->ver.csd_1_0.c_size_mid);
614 PX_LOG_D(
"c_size_lo = %02hX", csd->ver.csd_1_0.c_size_lo);
617 capacity = ( ((uint16_t)csd->ver.csd_1_0.c_size_hi << 10)
618 | ((uint16_t)csd->ver.csd_1_0.c_size_mid << 2)
619 | (csd->ver.csd_1_0.c_size_lo ) )
622 PX_LOG_D(
"capacity = %08lX", capacity);
625 capacity = capacity << (n - 9);
627 PX_LOG_D(
"capacity = %08lX", capacity);
631 PX_LOG_D(
"c_size_hi = %02hX", csd->ver.csd_2_0.c_size_hi);
632 PX_LOG_D(
"c_size_mid = %02hX", csd->ver.csd_2_0.c_size_mid);
633 PX_LOG_D(
"c_size_lo = %02hX", csd->ver.csd_2_0.c_size_lo);
636 capacity = ((uint32_t)csd->ver.csd_2_0.c_size_hi << 16)
637 | ((uint16_t)csd->ver.csd_2_0.c_size_mid << 8)
638 | (csd->ver.csd_2_0.c_size_lo + 1);
640 PX_LOG_D(
"capacity = %08lX", capacity);
646 PX_LOG_D(
"capacity = %08lX", capacity);
654 uint8_t r1, data_token;
659 if(px_sd_card_type != PX_SD_CARD_TYPE_VER_2_HCSD_XCSD)
665 r1 = px_sd_tx_cmd_rx_resp_r1(PX_SD_CMD17_READ_SINGLE_BLOCK, block_adr);
669 PX_LOG_E(
"Incorrect response to CMD17 (R1 = 0x%02X)", r1);
675 if(data_token != PX_SD_TOKEN_DATA_BLOCK_START)
687 uint8_t r1, data_token, blocks_read;
691 if(nr_of_blocks == 0)
695 if(nr_of_blocks == 1)
708 if(px_sd_card_type != PX_SD_CARD_TYPE_VER_2_HCSD_XCSD)
714 r1 = px_sd_tx_cmd_rx_resp_r1(PX_SD_CMD18_READ_MULT_BLOCK, block_adr);
718 PX_LOG_E(
"Incorrect response to CMD18 (R1 = 0x%02X)", r1);
723 for(blocks_read = 0; blocks_read < nr_of_blocks; blocks_read++)
727 if(data_token != PX_SD_TOKEN_DATA_BLOCK_START)
736 px_sd_tx_cmd_rx_resp_r1(PX_SD_CMD12_STOP_TRANSMISSION, 0);
745 uint8_t r1, data_resp_token;
750 if(px_sd_card_type != PX_SD_CARD_TYPE_VER_2_HCSD_XCSD)
756 r1 = px_sd_tx_cmd_rx_resp_r1(PX_SD_CMD24_WRITE_BLOCK, block_adr);
760 PX_LOG_E(
"Incorrect response to CMD24 (R1 = 0x%02X)", r1);
765 data_resp_token = px_sd_tx_data_block(data,
PX_SD_BLOCK_SIZE, PX_SD_TOKEN_DATA_BLOCK_START);
767 if((data_resp_token & PX_SD_TOKEN_DATA_RESP_MASK) != PX_SD_TOKEN_DATA_RESP_DATA_OK)
769 PX_LOG_E(
"Data response token = 0x%02X", data_resp_token);
779uint8_t
px_sd_wr_blocks(
const uint8_t * data, uint32_t block_adr, uint8_t nr_of_blocks)
781 uint8_t r1, data_resp_token, blocks_written;
783 PX_LOG_D(
"px_sd_write_blocks(%04X, %08lX, %hd)", data, block_adr, nr_of_blocks);
786 if(nr_of_blocks == 0)
790 if(nr_of_blocks == 1)
803 if(px_sd_card_type != PX_SD_CARD_TYPE_VER_2_HCSD_XCSD)
809 r1 = px_sd_tx_cmd_rx_resp_r1(PX_SD_CMD25_WRITE_MULT_BLOCK, block_adr);
813 PX_LOG_E(
"Incorrect response to CMD25 (R1 = 0x%02X)", r1);
818 r1 = px_sd_tx_cmd_rx_resp_r1(PX_SD_ACMD23_SET_WR_BLOCK_COUNT, nr_of_blocks);
822 PX_LOG_E(
"Incorrect response to ACMD23 (R1 = 0x%02X)", r1);
827 for(blocks_written = 0; blocks_written < nr_of_blocks; blocks_written++)
830 data_resp_token = px_sd_tx_data_block(data,
PX_SD_BLOCK_SIZE, PX_SD_TOKEN_DATA_BLOCK_START_MULT_WR);
833 if((data_resp_token & PX_SD_TOKEN_DATA_RESP_MASK) != PX_SD_TOKEN_DATA_RESP_DATA_OK)
835 PX_LOG_E(
"Data response token = 0x%02X", data_resp_token);
838 px_sd_tx_cmd_rx_resp_r1(PX_SD_CMD12_STOP_TRANSMISSION, 0);
841 return blocks_written;
851 px_sd_spi_xc_u8(PX_SD_TOKEN_DATA_BLOCK_STOP_MULT_WR);
854 PX_LOG_D(
"%hd block(s) written", blocks_written);
855 return blocks_written;
865 flag = px_sd_wait_ready();
void px_board_delay_us(uint16_t delay_us)
Blocking delay for specified number of microseconds.
#define NULL
NULL pointer.
#define PX_U32_LO8(data)
Extract the low 8 bits (bits 7..0) of a 32-bit value.
#define PX_U32_HI8(data)
Extract the high 8 bits (bits 31..24) of a 32-bit value.
#define PX_BIT_IS_LO(var, bit)
Test if a bit is cleared (0?)
#define PX_U32_MH8(data)
Extract the middle high 8 bits (bits 23..16) of a 32-bit value.
#define PX_U32_ML8(data)
Extract the middle low 8 bits (bits 15..8) of a 32-bit value.
#define PX_BIT_SET_LO(var, bit)
Clear a bit (0)
#define PX_BIT_IS_HI(var, bit)
Test if a bit is set (1?)
#define PX_LOG_D(format,...)
Macro to display a formatted DEBUG message.
#define PX_LOG_TRACE(format,...)
Macro to output a user format string if PX_LOG=1.
#define PX_LOG_TRACE_DATA(data, nr_of_bytes)
Macro to output the content of a buffer if PX_LOG=1.
#define PX_LOG_NAME(name)
Macro to declare a log name string once for each file to reduce code size.
#define PX_LOG_LEVEL_IS_D()
Debug level enabled?
#define PX_LOG_E(format,...)
Macro to display a formatted ERROR message.
#define PX_LOG_ASSERT(expression)
Macro that will test an expression, and block indefinitely if false.
uint8_t csd_structure
CSD structure version 1.0 or 2.0.
uint8_t read_bl_len
max. read data block length
bool px_sd_reset(void)
Detect and reset SD card.
#define PX_SD_BLOCK_SIZE
Size of each data block.
bool px_sd_rd_block(uint8_t *data, uint32_t block_adr)
Read a data block from the SD card.
uint8_t px_sd_wr_blocks(const uint8_t *data, uint32_t block_adr, uint8_t nr_of_blocks)
Write a number of data blocks to the SD card.
#define PX_SD_MAX_SPI_CLOCK_HZ
Maximum SPI Clock rate.
bool px_sd_wait_wr_is_finished(void)
Wait up to 500 ms for write block transaction to finish.
void px_sd_init(px_spi_handle_t *handle)
Initialise driver.
bool px_sd_rd_cid(px_sd_cid_t *cid)
Read Card ID Register.
bool px_sd_wr_block(const uint8_t *data, uint32_t block_adr)
Write a data block to the SD card.
uint32_t px_sd_get_capacity_in_blocks(const px_sd_csd_t *csd)
Extract and calculate card capacity from Card Specific Data (CSD).
bool px_sd_get_status(uint16_t *status)
Read Card Status.
bool px_sd_rd_csd(px_sd_csd_t *csd)
Read Card Specific Data.
uint8_t px_sd_rd_blocks(uint8_t *data, uint32_t block_adr, uint8_t nr_of_blocks)
Read a number of data blocks from the SD card.
CID - Card ID register; Ref 1. Paragraph "5.2 CID Register", page 113.
CSD - Card Specific Data register; Paragraph "5.3 CSD Register", page 114.
#define PX_SPI_FLAG_START
Begin SPI transaction (take SPI slave's Chip Select line low)
void px_spi_xc(px_spi_handle_t *handle, const void *data_wr, void *data_rd, size_t nr_of_bytes, uint8_t flags)
Perform an SPI exchange (write and read) transaction with an SPI slave.
void px_spi_wr(px_spi_handle_t *handle, const void *data, size_t nr_of_bytes, uint8_t flags)
Perform an SPI write transaction with an SPI slave.
void px_spi_change_baud(px_spi_handle_t *handle, px_spi_baud_t baud)
Change SPI peripheral baud.
#define PX_SPI_FLAG_STOP
Finish SPI transaction (take SPI slave's Chip Select line high)
px_spi_baud_t px_spi_util_baud_hz_to_clk_div(uint32_t baud_hz)
Calculate clock divisor that will yield closest frequency equal to or less than specified baud rate (...