mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
drivers/sdcard_spi: adapted to SPI interface changes
This commit is contained in:
parent
49118f8c2e
commit
24ceb954ea
@ -185,13 +185,14 @@ typedef struct {
|
||||
* @brief Device descriptor for sdcard_spi
|
||||
*/
|
||||
struct {
|
||||
sdcard_spi_params_t params; /**< parameters for pin and spi config */
|
||||
bool use_block_addr; /**< true if block adressing (vs. byte adressing) is used */
|
||||
bool init_done; /**< set to true once the init procedure completed sucessfully */
|
||||
sd_version_t card_type; /**< version of SD-card */
|
||||
int csd_structure; /**< version of the CSD register structure */
|
||||
cid_t cid; /**< CID register */
|
||||
csd_t csd; /**< CSD register */
|
||||
sdcard_spi_params_t params; /**< parameters for pin and spi config */
|
||||
spi_clk_t spi_clk; /**< active SPI clock speed */
|
||||
bool use_block_addr; /**< true if block adressing (vs. byte adressing) is used */
|
||||
bool init_done; /**< set to true once the init procedure completed sucessfully */
|
||||
sd_version_t card_type; /**< version of SD-card */
|
||||
int csd_structure; /**< version of the CSD register structure */
|
||||
cid_t cid; /**< CID register */
|
||||
csd_t csd; /**< CSD register */
|
||||
} typedef sdcard_spi_t;
|
||||
|
||||
/**
|
||||
|
@ -139,13 +139,13 @@ extern "C" {
|
||||
/* memory capacity in bytes = (C_SIZE+1) * SD_CSD_V2_C_SIZE_BLOCK_MULT * BLOCK_LEN */
|
||||
#define SD_CSD_V2_C_SIZE_BLOCK_MULT 1024
|
||||
|
||||
#define SD_CARD_SPI_MODE SPI_CONF_FIRST_RISING
|
||||
#define SD_CARD_SPI_MODE SPI_MODE_0
|
||||
|
||||
/* this speed setting is only used while the init procedure is performed */
|
||||
#define SD_CARD_SPI_SPEED_PREINIT SPI_SPEED_400KHZ
|
||||
#define SD_CARD_SPI_SPEED_PREINIT SPI_CLK_400KHZ
|
||||
|
||||
/* after init procedure is finished the driver auto sets the card to this speed */
|
||||
#define SD_CARD_SPI_SPEED_POSTINIT SPI_SPEED_10MHZ
|
||||
#define SD_CARD_SPI_SPEED_POSTINIT SPI_CLK_10MHZ
|
||||
|
||||
#define SD_CARD_DUMMY_BYTE 0xFF
|
||||
|
||||
|
@ -30,7 +30,7 @@ extern "C" {
|
||||
* @{
|
||||
*/
|
||||
#ifndef SDCARD_SPI_PARAM_SPI
|
||||
#define SDCARD_SPI_PARAM_SPI (SPI_0)
|
||||
#define SDCARD_SPI_PARAM_SPI (SPI_DEV(0))
|
||||
#endif
|
||||
#ifndef SDCARD_SPI_PARAM_CS
|
||||
#define SDCARD_SPI_PARAM_CS (GPIO_PIN(2,4))
|
||||
|
@ -65,6 +65,7 @@ int sdcard_spi_init(sdcard_spi_t *card, const sdcard_spi_params_t *params)
|
||||
{
|
||||
sd_init_fsm_state_t state = SD_INIT_START;
|
||||
memcpy(&card->params, params, sizeof(sdcard_spi_params_t));
|
||||
card->spi_clk = SD_CARD_SPI_SPEED_PREINIT;
|
||||
|
||||
do {
|
||||
state = _init_sd_fsm_step(card, state);
|
||||
@ -88,7 +89,7 @@ static sd_init_fsm_state_t _init_sd_fsm_step(sdcard_spi_t *card, sd_init_fsm_sta
|
||||
if ((gpio_init(card->params.mosi, GPIO_OUT) == 0) &&
|
||||
(gpio_init(card->params.clk, GPIO_OUT) == 0) &&
|
||||
(gpio_init(card->params.cs, GPIO_OUT) == 0) &&
|
||||
(gpio_init(card->params.miso, GPIO_IN) == 0) &&
|
||||
(gpio_init(card->params.miso, GPIO_IN_PU) == 0) &&
|
||||
( (card->params.power == GPIO_UNDEF) ||
|
||||
(gpio_init(card->params.power, GPIO_OUT) == 0)) ) {
|
||||
|
||||
@ -125,43 +126,37 @@ static sd_init_fsm_state_t _init_sd_fsm_step(sdcard_spi_t *card, sd_init_fsm_sta
|
||||
DEBUG("SD_INIT_SEND_CMD0\n");
|
||||
|
||||
gpio_clear(card->params.mosi);
|
||||
gpio_clear(card->params.cs); /* select sdcard for cmd0 */
|
||||
|
||||
/* use soft-spi to perform init command to allow use of internal pull-ups on miso */
|
||||
_dyn_spi_rxtx_byte = &_sw_spi_rxtx_byte;
|
||||
|
||||
_select_card_spi(card);
|
||||
/* select sdcard for cmd0 */
|
||||
gpio_clear(card->params.cs);
|
||||
char cmd0_r1 = sdcard_spi_send_cmd(card, SD_CMD_0, SD_CMD_NO_ARG, INIT_CMD0_RETRY_CNT);
|
||||
gpio_set(card->params.cs);
|
||||
|
||||
if (R1_VALID(cmd0_r1) && !R1_ERROR(cmd0_r1) && R1_IDLE_BIT_SET(cmd0_r1)) {
|
||||
DEBUG("CMD0: [OK]\n");
|
||||
_unselect_card_spi(card);
|
||||
|
||||
if (spi_init_master(card->params.spi_dev, SD_CARD_SPI_MODE,
|
||||
SD_CARD_SPI_SPEED_PREINIT) == 0) {
|
||||
DEBUG("spi_init_master(): [OK]\n");
|
||||
|
||||
/* switch to hw spi since sd card is now in real spi mode */
|
||||
_dyn_spi_rxtx_byte = &_hw_spi_rxtx_byte;
|
||||
return SD_INIT_ENABLE_CRC;
|
||||
}
|
||||
|
||||
DEBUG("spi_init_master(): [ERROR]\n");
|
||||
return SD_INIT_CARD_UNKNOWN;
|
||||
/* give control over SPI pins back to HW SPI device */
|
||||
spi_init_pins(card->params.spi_dev);
|
||||
/* switch to HW SPI since SD card is now in real SPI mode */
|
||||
_dyn_spi_rxtx_byte = &_hw_spi_rxtx_byte;
|
||||
return SD_INIT_ENABLE_CRC;
|
||||
}
|
||||
|
||||
_unselect_card_spi(card);
|
||||
return SD_INIT_CARD_UNKNOWN;
|
||||
|
||||
case SD_INIT_ENABLE_CRC:
|
||||
DEBUG("SD_INIT_ENABLE_CRC\n");
|
||||
_select_card_spi(card);
|
||||
char r1 = sdcard_spi_send_cmd(card, SD_CMD_59, SD_CMD_59_ARG_EN, INIT_CMD_RETRY_CNT);
|
||||
_unselect_card_spi(card);
|
||||
|
||||
if (R1_VALID(r1) && !R1_ERROR(r1)) {
|
||||
DEBUG("CMD59: [OK]\n");
|
||||
_unselect_card_spi(card);
|
||||
return SD_INIT_SEND_CMD8;
|
||||
}
|
||||
_unselect_card_spi(card);
|
||||
return SD_INIT_CARD_UNKNOWN;
|
||||
|
||||
case SD_INIT_SEND_CMD8:
|
||||
@ -327,15 +322,9 @@ static sd_init_fsm_state_t _init_sd_fsm_step(sdcard_spi_t *card, sd_init_fsm_sta
|
||||
|
||||
case SD_INIT_SET_MAX_SPI_SPEED:
|
||||
DEBUG("SD_INIT_SET_MAX_SPI_SPEED\n");
|
||||
if (spi_init_master(card->params.spi_dev, SD_CARD_SPI_MODE,
|
||||
SD_CARD_SPI_SPEED_POSTINIT) == 0) {
|
||||
DEBUG("SD_INIT_SET_MAX_SPI_SPEED: [OK]\n");
|
||||
return SD_INIT_FINISH;
|
||||
}
|
||||
else {
|
||||
DEBUG("SD_INIT_SET_MAX_SPI_SPEED: [ERROR]\n");
|
||||
return SD_INIT_CARD_UNKNOWN;
|
||||
}
|
||||
card->spi_clk = SD_CARD_SPI_SPEED_POSTINIT;
|
||||
DEBUG("SD_INIT_SET_MAX_SPI_SPEED: [OK]\n");
|
||||
return SD_INIT_FINISH;
|
||||
|
||||
default:
|
||||
DEBUG("SD-INIT-FSM REACHED INVALID STATE!\n");
|
||||
@ -350,18 +339,14 @@ static inline bool _wait_for_token(sdcard_spi_t *card, char token, int32_t max_r
|
||||
|
||||
do {
|
||||
char read_byte = 0;
|
||||
if (spi_transfer_byte(card->params.spi_dev, SD_CARD_DUMMY_BYTE, &read_byte) == 1) {
|
||||
if (read_byte == token) {
|
||||
DEBUG("_wait_for_token: [MATCH]\n");
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
DEBUG("_wait_for_token: [NO MATCH] (0x%02x)\n", read_byte);
|
||||
}
|
||||
read_byte = spi_transfer_byte(card->params.spi_dev, GPIO_UNDEF, true,
|
||||
SD_CARD_DUMMY_BYTE);
|
||||
if (read_byte == token) {
|
||||
DEBUG("_wait_for_token: [MATCH]\n");
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
DEBUG("spi_transfer_byte: [FAILED]\n");
|
||||
return false;
|
||||
DEBUG("_wait_for_token: [NO MATCH] (0x%02x)\n", read_byte);
|
||||
}
|
||||
|
||||
tried++;
|
||||
@ -557,7 +542,8 @@ static inline char _wait_for_r1(sdcard_spi_t *card, int32_t max_retries)
|
||||
|
||||
void _select_card_spi(sdcard_spi_t *card)
|
||||
{
|
||||
spi_acquire(card->params.spi_dev);
|
||||
spi_acquire(card->params.spi_dev, GPIO_UNDEF,
|
||||
SD_CARD_SPI_MODE, card->spi_clk);
|
||||
gpio_clear(card->params.cs);
|
||||
}
|
||||
|
||||
@ -587,7 +573,8 @@ static inline int _sw_spi_rxtx_byte(sdcard_spi_t *card, char out, char *in){
|
||||
}
|
||||
|
||||
static inline int _hw_spi_rxtx_byte(sdcard_spi_t *card, char out, char *in){
|
||||
return spi_transfer_byte(card->params.spi_dev, out, in);
|
||||
*in = spi_transfer_byte(card->params.spi_dev, GPIO_UNDEF, true, out);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int _transfer_bytes(sdcard_spi_t *card, char *out, char *in, unsigned int length){
|
||||
@ -720,66 +707,54 @@ int sdcard_spi_read_blocks(sdcard_spi_t *card, int blockaddr, char *data, int bl
|
||||
static sd_rw_response_t _write_data_packet(sdcard_spi_t *card, char token, char *data, int size)
|
||||
{
|
||||
|
||||
if (spi_transfer_byte(card->params.spi_dev, token, 0) == 1) {
|
||||
spi_transfer_byte(card->params.spi_dev, GPIO_UNDEF, true, token);
|
||||
|
||||
if (_transfer_bytes(card, data, 0, size) == size) {
|
||||
if (_transfer_bytes(card, data, 0, size) == size) {
|
||||
|
||||
uint16_t data__crc_16 = _crc_16(data, size);
|
||||
char crc[sizeof(uint16_t)] = { data__crc_16 >> 8, data__crc_16 & 0xFF };
|
||||
uint16_t data__crc_16 = _crc_16(data, size);
|
||||
char crc[sizeof(uint16_t)] = { data__crc_16 >> 8, data__crc_16 & 0xFF };
|
||||
|
||||
if (_transfer_bytes(card, crc, 0, sizeof(crc)) == sizeof(crc)) {
|
||||
if (_transfer_bytes(card, crc, 0, sizeof(crc)) == sizeof(crc)) {
|
||||
|
||||
char data_response;
|
||||
char data_response;
|
||||
|
||||
if (spi_transfer_byte(card->params.spi_dev, SD_CARD_DUMMY_BYTE,
|
||||
&data_response) == 1) {
|
||||
data_response = (char)spi_transfer_byte(card->params.spi_dev, GPIO_UNDEF,
|
||||
true, SD_CARD_DUMMY_BYTE);
|
||||
|
||||
DEBUG("_write_data_packet: DATA_RESPONSE: 0x%02x\n", data_response);
|
||||
|
||||
if (DATA_RESPONSE_IS_VALID(data_response)) {
|
||||
|
||||
if (DATA_RESPONSE_ACCEPTED(data_response)) {
|
||||
DEBUG("_write_data_packet: DATA_RESPONSE: [OK]\n");
|
||||
return SD_RW_OK;
|
||||
}
|
||||
else {
|
||||
|
||||
if (DATA_RESPONSE_WRITE_ERR(data_response)) {
|
||||
DEBUG("_write_data_packet: DATA_RESPONSE: [WRITE_ERROR]\n");
|
||||
}
|
||||
|
||||
if (DATA_RESPONSE_CRC_ERR(data_response)) {
|
||||
DEBUG("_write_data_packet: DATA_RESPONSE: [CRC_ERROR]\n");
|
||||
}
|
||||
return SD_RW_WRITE_ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
DEBUG("_write_data_packet: DATA_RESPONSE invalid\n");
|
||||
return SD_RW_RX_TX_ERROR;
|
||||
}
|
||||
DEBUG("_write_data_packet: DATA_RESPONSE: 0x%02x\n", data_response);
|
||||
|
||||
if (DATA_RESPONSE_IS_VALID(data_response)) {
|
||||
|
||||
if (DATA_RESPONSE_ACCEPTED(data_response)) {
|
||||
DEBUG("_write_data_packet: DATA_RESPONSE: [OK]\n");
|
||||
return SD_RW_OK;
|
||||
}
|
||||
else {
|
||||
DEBUG("_write_data_packet: [RX_TX_ERROR] (while transmitting data response)\n");
|
||||
return SD_RW_RX_TX_ERROR;
|
||||
|
||||
if (DATA_RESPONSE_WRITE_ERR(data_response)) {
|
||||
DEBUG("_write_data_packet: DATA_RESPONSE: [WRITE_ERROR]\n");
|
||||
}
|
||||
|
||||
if (DATA_RESPONSE_CRC_ERR(data_response)) {
|
||||
DEBUG("_write_data_packet: DATA_RESPONSE: [CRC_ERROR]\n");
|
||||
}
|
||||
return SD_RW_WRITE_ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
DEBUG("_write_data_packet: [RX_TX_ERROR] (while transmitting CRC16)\n");
|
||||
DEBUG("_write_data_packet: DATA_RESPONSE invalid\n");
|
||||
return SD_RW_RX_TX_ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
DEBUG("_write_data_packet: [RX_TX_ERROR] (while transmitting payload)\n");
|
||||
DEBUG("_write_data_packet: [RX_TX_ERROR] (while transmitting CRC16)\n");
|
||||
return SD_RW_RX_TX_ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
DEBUG("_write_data_packet: [RX_TX_ERROR] (while transmitting token)\n");
|
||||
DEBUG("_write_data_packet: [RX_TX_ERROR] (while transmitting payload)\n");
|
||||
return SD_RW_RX_TX_ERROR;
|
||||
}
|
||||
}
|
||||
@ -823,16 +798,10 @@ static inline int _write_blocks(sdcard_spi_t *card, char cmd_idx, int bladdr, ch
|
||||
|
||||
/* if this is a multi-block write it is needed to issue a stop command*/
|
||||
if (cmd_idx == SD_CMD_25) {
|
||||
char data_response;
|
||||
if (spi_transfer_byte(card->params.spi_dev, SD_DATA_TOKEN_CMD_25_STOP,
|
||||
&data_response) == 1) {
|
||||
DEBUG("_write_blocks: write multi (%d) blocks: [OK]\n", nbl);
|
||||
}
|
||||
else {
|
||||
DEBUG("_write_blocks: spi_transfer_byte: [FAILED] (SD_DATA_TOKEN_CMD_25_STOP)\n");
|
||||
_unselect_card_spi(card);
|
||||
*state = SD_RW_RX_TX_ERROR;
|
||||
}
|
||||
spi_transfer_byte(card->params.spi_dev, GPIO_UNDEF, true,
|
||||
SD_DATA_TOKEN_CMD_25_STOP);
|
||||
DEBUG("_write_blocks: write multi (%d) blocks: [OK]\n", nbl);
|
||||
|
||||
_send_dummy_byte(card); //sd card needs dummy byte before we can wait for not-busy state
|
||||
if (!_wait_for_not_busy(card, SD_WAIT_FOR_NOT_BUSY_CNT)) {
|
||||
_unselect_card_spi(card);
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#ifdef MODULE_SDCARD_SPI
|
||||
|
||||
#include "log.h"
|
||||
#include "sdcard_spi.h"
|
||||
#include "sdcard_spi_params.h"
|
||||
|
||||
@ -40,11 +41,12 @@ sdcard_spi_t sdcard_spi_devs[SDCARD_SPI_NUM];
|
||||
|
||||
void auto_init_sdcard_spi(void)
|
||||
{
|
||||
for (int i = 0; i < SDCARD_SPI_NUM; i++) {
|
||||
DEBUG("sdcard_spi_auto_init(): initializing device [%i]...\n", i);
|
||||
int resu = sdcard_spi_init(&sdcard_spi_devs[i], &sdcard_spi_params[i]);
|
||||
if(resu != 0){
|
||||
DEBUG("error initializing device [%i]\n", i);
|
||||
for (unsigned i = 0; i < SDCARD_SPI_NUM; i++) {
|
||||
LOG_DEBUG("[auto_init_storage] initializing sdcard_spi #%u\n", i);
|
||||
|
||||
if (sdcard_spi_init(&sdcard_spi_devs[i], &sdcard_spi_params[i]) !=
|
||||
SDCARD_SPI_OK) {
|
||||
LOG_ERROR("[auto_init_storage] error initializing sdcard_spi #%u\n", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user