3#include "gpio_interface.h"
6 _spi(spi), _initialized(false), _isV200(false),
7 _isSDHC(false), _blockCount(0), _sd_status(0) { }
9blockio_status_t sd_spi_drv::initialize() {
12 if (_initialized)
return 0;
15 bool sd_init_ok =
false;
16 for (
int tries = 0; tries < 10; ++tries) {
24 return BLOCKIO::NOINIT;
27 if (sd_read_status())
return BLOCKIO::NOINIT;
28 if (sd_read_cid())
return BLOCKIO::NOINIT;
29 if (sd_read_csd())
return BLOCKIO::NOINIT;
35blockio_status_t sd_spi_drv::status() {
37 return BLOCKIO::NOINIT;
43BLOCKIO::result_t sd_spi_drv::readBlock (uint8_t* buff, uint32_t block, uint16_t count) {
44 if (!_initialized) initialize();
46 for (
int i=0; i < count; ++i) {
47 int r = sd_readsector(block+i, buff+512*i);
48 if (r)
return BLOCKIO::ERROR;
53BLOCKIO::result_t sd_spi_drv::writeBlock(
const uint8_t* buff, uint32_t block, uint16_t count) {
54 if (!_initialized) initialize();
56 for (
int i=0; i < count; ++i) {
57 int r = sd_writesector(block+i, buff+512*i);
58 if (r)
return BLOCKIO::ERROR;
64uint32_t sd_spi_drv::getBlockCount() {
65 if (!_initialized) initialize();
71int sd_spi_drv::sd_init()
78 _spi.generateCS(
false);
82 _spi.setSpeed(400000);
85 for (
int i=0; i < 10; i++)
94 if (r == 0xff)
return -1;
95 if (r != 0x01)
return -2;
103 if (r == 0xff)
return -1;
104 if (r & 0xfa)
return -2;
105 if (r == 0x01) _isV200 =
true;
113 if (r == 0xff)
return -1;
114 if (r & 0xfe)
return -2;
116 for (tries=100; tries > 0; --tries) {
123 if (r == 0xff)
return -1;
124 if (r & 0xfe)
return -2;
129 r3 = (tries > 50) ? 0x40000000 : 0;
134 if (r == 0xff)
return -1;
135 if (r & 0xfe)
return -2;
138 if (tries == 0)
return -2;
147 if (r == 0xff)
return -1;
148 if (r & 0xfe)
return -2;
149 _isSDHC = r3 & 0x40000000;
161 if (r == 0xff)
return -1;
162 if (r & 0xfe)
return -2;
171 if (r == 0xff)
return -1;
172 if (r & 0xfe)
return -2;
175 _spi.setSpeed(24000000);
179int sd_spi_drv::sd_read_status()
184 uint16_t r2 = sd_get_r2();
196 int sd_spi_drv::sd_read_cid()
210 r = sd_get_data(_cid, 16);
218int sd_spi_drv::sd_read_csd()
234 r = sd_get_data(_csd, 16);
240 if ((_csd[0] & 0xc0) == 0) {
242 uint32_t c_size = (((_csd[6] & 3) << 10) | (_csd[7] << 2) | (_csd[8] >> 6));
243 uint32_t c_mult = ((_csd[9] & 3) << 1) | (_csd[10] >> 7);
244 uint32_t blk_len = (_csd[5] & 0xf);
245 _blockCount = (c_size+1) * (1 << (c_mult + blk_len - 7));
248 uint32_t c_size = (_csd[7]<<16) | (_csd[8]<<8) | _csd[9];
249 _blockCount = c_size *1024;
254void sd_spi_drv::sd_cmd(uint8_t cmd, uint32_t arg)
257 spi_txrx(0x40 | cmd);
258 crc = crc7_one(crc, 0x40 | cmd);
260 crc = crc7_one(crc, arg >> 24);
262 crc = crc7_one(crc, arg >> 16);
264 crc = crc7_one(crc, arg >> 8);
266 crc = crc7_one(crc, arg);
270uint8_t sd_spi_drv::sd_get_r1()
272 for (
int tries=0; tries < 1000; ++tries) {
273 uint8_t r = spi_txrx(0xff);
280uint16_t sd_spi_drv::sd_get_r2()
291 r = r<<8 | spi_txrx(0xff);
295uint8_t sd_spi_drv::sd_get_r37(uint32_t *r37) {
300 r = spi_txrx(0xff) << 24;
301 r |= spi_txrx(0xff) << 16;
302 r |= spi_txrx(0xff) << 8;
308int sd_spi_drv::sd_get_data(uint8_t *buf,
int len)
324 _spi.spiRx(0xff, buf, len);
326 _crc16 = spi_txrx(0xff) << 8;
327 _crc16 |= spi_txrx(0xff);
329 calc_crc = crc16(buf, len);
330 if (_crc16 != calc_crc) {
336int sd_spi_drv::sd_put_data(
const uint8_t *buf,
int len)
347 _spi.spiTx(buf, len);
349 crc = crc16(buf, len);
356 b[bi++] = r = spi_txrx(0xff);
366 if (spi_txrx(0xff) == 0xff)
373 if ((r & 0x1f) == 0x05)
379void sd_spi_drv::sd_nec()
381 for (
int i=0; i<8; i++)
385uint8_t sd_spi_drv::spi_txrx(uint8_t data)
388 _spi.spiTxRx(&data, &out, 1);
394uint8_t sd_spi_drv::crc7_one(uint8_t t, uint8_t data)
397 const uint8_t g = 0x89;
399 for (i=0; i<8; i++) {
407uint16_t sd_spi_drv::crc16(
const uint8_t *p,
int len)
411 for (i=0; i<len; i++)
412 crc = crc16_ccitt(crc, p[i]);
416uint16_t sd_spi_drv::crc16_ccitt(uint16_t crc, uint8_t ser_data)
418 crc = (uint8_t)(crc >> 8) | (crc << 8);
420 crc ^= (uint8_t)(crc & 0xff) >> 4;
421 crc ^= (crc << 8) << 4;
422 crc ^= ((crc & 0xff) << 4) << 1;
426int sd_spi_drv::sd_readsector(uint32_t sector, uint8_t *buf)
431 if (_isSDHC) sd_cmd(17, sector);
432 else sd_cmd(17, sector * 512);
443 r = sd_get_data(buf, 512);
449int sd_spi_drv::sd_writesector(uint32_t sector,
const uint8_t *buf)
453 if (_isSDHC) sd_cmd(24, sector);
454 else sd_cmd(24, sector * 512);
456 uint8_t r = sd_get_r1();
467 r = sd_put_data(buf, 512);