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
|
* @brief Device descriptor for sdcard_spi
|
||||||
*/
|
*/
|
||||||
struct {
|
struct {
|
||||||
sdcard_spi_params_t params; /**< parameters for pin and spi config */
|
sdcard_spi_params_t params; /**< parameters for pin and spi config */
|
||||||
bool use_block_addr; /**< true if block adressing (vs. byte adressing) is used */
|
spi_clk_t spi_clk; /**< active SPI clock speed */
|
||||||
bool init_done; /**< set to true once the init procedure completed sucessfully */
|
bool use_block_addr; /**< true if block adressing (vs. byte adressing) is used */
|
||||||
sd_version_t card_type; /**< version of SD-card */
|
bool init_done; /**< set to true once the init procedure completed sucessfully */
|
||||||
int csd_structure; /**< version of the CSD register structure */
|
sd_version_t card_type; /**< version of SD-card */
|
||||||
cid_t cid; /**< CID register */
|
int csd_structure; /**< version of the CSD register structure */
|
||||||
csd_t csd; /**< CSD register */
|
cid_t cid; /**< CID register */
|
||||||
|
csd_t csd; /**< CSD register */
|
||||||
} typedef sdcard_spi_t;
|
} 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 */
|
/* 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_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 */
|
/* 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 */
|
/* 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
|
#define SD_CARD_DUMMY_BYTE 0xFF
|
||||||
|
|
||||||
|
|||||||
@ -30,7 +30,7 @@ extern "C" {
|
|||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#ifndef SDCARD_SPI_PARAM_SPI
|
#ifndef SDCARD_SPI_PARAM_SPI
|
||||||
#define SDCARD_SPI_PARAM_SPI (SPI_0)
|
#define SDCARD_SPI_PARAM_SPI (SPI_DEV(0))
|
||||||
#endif
|
#endif
|
||||||
#ifndef SDCARD_SPI_PARAM_CS
|
#ifndef SDCARD_SPI_PARAM_CS
|
||||||
#define SDCARD_SPI_PARAM_CS (GPIO_PIN(2,4))
|
#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;
|
sd_init_fsm_state_t state = SD_INIT_START;
|
||||||
memcpy(&card->params, params, sizeof(sdcard_spi_params_t));
|
memcpy(&card->params, params, sizeof(sdcard_spi_params_t));
|
||||||
|
card->spi_clk = SD_CARD_SPI_SPEED_PREINIT;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
state = _init_sd_fsm_step(card, state);
|
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) &&
|
if ((gpio_init(card->params.mosi, GPIO_OUT) == 0) &&
|
||||||
(gpio_init(card->params.clk, GPIO_OUT) == 0) &&
|
(gpio_init(card->params.clk, GPIO_OUT) == 0) &&
|
||||||
(gpio_init(card->params.cs, 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) ||
|
( (card->params.power == GPIO_UNDEF) ||
|
||||||
(gpio_init(card->params.power, GPIO_OUT) == 0)) ) {
|
(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");
|
DEBUG("SD_INIT_SEND_CMD0\n");
|
||||||
|
|
||||||
gpio_clear(card->params.mosi);
|
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 */
|
/* use soft-spi to perform init command to allow use of internal pull-ups on miso */
|
||||||
_dyn_spi_rxtx_byte = &_sw_spi_rxtx_byte;
|
_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);
|
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)) {
|
if (R1_VALID(cmd0_r1) && !R1_ERROR(cmd0_r1) && R1_IDLE_BIT_SET(cmd0_r1)) {
|
||||||
DEBUG("CMD0: [OK]\n");
|
DEBUG("CMD0: [OK]\n");
|
||||||
_unselect_card_spi(card);
|
|
||||||
|
|
||||||
if (spi_init_master(card->params.spi_dev, SD_CARD_SPI_MODE,
|
/* give control over SPI pins back to HW SPI device */
|
||||||
SD_CARD_SPI_SPEED_PREINIT) == 0) {
|
spi_init_pins(card->params.spi_dev);
|
||||||
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;
|
||||||
/* switch to hw spi since sd card is now in real spi mode */
|
return SD_INIT_ENABLE_CRC;
|
||||||
_dyn_spi_rxtx_byte = &_hw_spi_rxtx_byte;
|
|
||||||
return SD_INIT_ENABLE_CRC;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG("spi_init_master(): [ERROR]\n");
|
|
||||||
return SD_INIT_CARD_UNKNOWN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_unselect_card_spi(card);
|
|
||||||
return SD_INIT_CARD_UNKNOWN;
|
return SD_INIT_CARD_UNKNOWN;
|
||||||
|
|
||||||
case SD_INIT_ENABLE_CRC:
|
case SD_INIT_ENABLE_CRC:
|
||||||
DEBUG("SD_INIT_ENABLE_CRC\n");
|
DEBUG("SD_INIT_ENABLE_CRC\n");
|
||||||
_select_card_spi(card);
|
_select_card_spi(card);
|
||||||
char r1 = sdcard_spi_send_cmd(card, SD_CMD_59, SD_CMD_59_ARG_EN, INIT_CMD_RETRY_CNT);
|
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)) {
|
if (R1_VALID(r1) && !R1_ERROR(r1)) {
|
||||||
DEBUG("CMD59: [OK]\n");
|
DEBUG("CMD59: [OK]\n");
|
||||||
_unselect_card_spi(card);
|
|
||||||
return SD_INIT_SEND_CMD8;
|
return SD_INIT_SEND_CMD8;
|
||||||
}
|
}
|
||||||
_unselect_card_spi(card);
|
|
||||||
return SD_INIT_CARD_UNKNOWN;
|
return SD_INIT_CARD_UNKNOWN;
|
||||||
|
|
||||||
case SD_INIT_SEND_CMD8:
|
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:
|
case SD_INIT_SET_MAX_SPI_SPEED:
|
||||||
DEBUG("SD_INIT_SET_MAX_SPI_SPEED\n");
|
DEBUG("SD_INIT_SET_MAX_SPI_SPEED\n");
|
||||||
if (spi_init_master(card->params.spi_dev, SD_CARD_SPI_MODE,
|
card->spi_clk = SD_CARD_SPI_SPEED_POSTINIT;
|
||||||
SD_CARD_SPI_SPEED_POSTINIT) == 0) {
|
DEBUG("SD_INIT_SET_MAX_SPI_SPEED: [OK]\n");
|
||||||
DEBUG("SD_INIT_SET_MAX_SPI_SPEED: [OK]\n");
|
return SD_INIT_FINISH;
|
||||||
return SD_INIT_FINISH;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
DEBUG("SD_INIT_SET_MAX_SPI_SPEED: [ERROR]\n");
|
|
||||||
return SD_INIT_CARD_UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DEBUG("SD-INIT-FSM REACHED INVALID STATE!\n");
|
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 {
|
do {
|
||||||
char read_byte = 0;
|
char read_byte = 0;
|
||||||
if (spi_transfer_byte(card->params.spi_dev, SD_CARD_DUMMY_BYTE, &read_byte) == 1) {
|
read_byte = spi_transfer_byte(card->params.spi_dev, GPIO_UNDEF, true,
|
||||||
if (read_byte == token) {
|
SD_CARD_DUMMY_BYTE);
|
||||||
DEBUG("_wait_for_token: [MATCH]\n");
|
if (read_byte == token) {
|
||||||
return true;
|
DEBUG("_wait_for_token: [MATCH]\n");
|
||||||
}
|
return true;
|
||||||
else {
|
|
||||||
DEBUG("_wait_for_token: [NO MATCH] (0x%02x)\n", read_byte);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
DEBUG("spi_transfer_byte: [FAILED]\n");
|
DEBUG("_wait_for_token: [NO MATCH] (0x%02x)\n", read_byte);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tried++;
|
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)
|
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);
|
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){
|
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){
|
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)
|
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);
|
uint16_t data__crc_16 = _crc_16(data, size);
|
||||||
char crc[sizeof(uint16_t)] = { data__crc_16 >> 8, data__crc_16 & 0xFF };
|
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 = (char)spi_transfer_byte(card->params.spi_dev, GPIO_UNDEF,
|
||||||
&data_response) == 1) {
|
true, SD_CARD_DUMMY_BYTE);
|
||||||
|
|
||||||
DEBUG("_write_data_packet: DATA_RESPONSE: 0x%02x\n", data_response);
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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 {
|
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 {
|
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;
|
return SD_RW_RX_TX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
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;
|
return SD_RW_RX_TX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
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;
|
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 this is a multi-block write it is needed to issue a stop command*/
|
||||||
if (cmd_idx == SD_CMD_25) {
|
if (cmd_idx == SD_CMD_25) {
|
||||||
char data_response;
|
spi_transfer_byte(card->params.spi_dev, GPIO_UNDEF, true,
|
||||||
if (spi_transfer_byte(card->params.spi_dev, SD_DATA_TOKEN_CMD_25_STOP,
|
SD_DATA_TOKEN_CMD_25_STOP);
|
||||||
&data_response) == 1) {
|
DEBUG("_write_blocks: write multi (%d) blocks: [OK]\n", nbl);
|
||||||
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;
|
|
||||||
}
|
|
||||||
_send_dummy_byte(card); //sd card needs dummy byte before we can wait for not-busy state
|
_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)) {
|
if (!_wait_for_not_busy(card, SD_WAIT_FOR_NOT_BUSY_CNT)) {
|
||||||
_unselect_card_spi(card);
|
_unselect_card_spi(card);
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#ifdef MODULE_SDCARD_SPI
|
#ifdef MODULE_SDCARD_SPI
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
#include "sdcard_spi.h"
|
#include "sdcard_spi.h"
|
||||||
#include "sdcard_spi_params.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)
|
void auto_init_sdcard_spi(void)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < SDCARD_SPI_NUM; i++) {
|
for (unsigned i = 0; i < SDCARD_SPI_NUM; i++) {
|
||||||
DEBUG("sdcard_spi_auto_init(): initializing device [%i]...\n", i);
|
LOG_DEBUG("[auto_init_storage] initializing sdcard_spi #%u\n", i);
|
||||||
int resu = sdcard_spi_init(&sdcard_spi_devs[i], &sdcard_spi_params[i]);
|
|
||||||
if(resu != 0){
|
if (sdcard_spi_init(&sdcard_spi_devs[i], &sdcard_spi_params[i]) !=
|
||||||
DEBUG("error initializing device [%i]\n", i);
|
SDCARD_SPI_OK) {
|
||||||
|
LOG_ERROR("[auto_init_storage] error initializing sdcard_spi #%u\n", i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user