Skip to content

Commit

Permalink
drivers/sdcard_spi: make ztimer_usec optional
Browse files Browse the repository at this point in the history
Most delays are in ms units, only a couple are < 1ms an in those
cases its for timeout in cases of retries erros, paying the price
of waiting x10 more before failing can be worth the price of
avoiding the use of ztimer_usec.
  • Loading branch information
fjmolinas committed Feb 10, 2022
1 parent 41531c0 commit 8436d78
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 12 deletions.
5 changes: 4 additions & 1 deletion drivers/sdcard_spi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,8 @@ config MODULE_SDCARD_SPI
select MODULE_PERIPH_GPIO
select MODULE_PERIPH_SPI
select MODULE_PERIPH_SPI_RECONFIGURE if HAS_PERIPH_SPI_RECONFIGURE
select MODULE_PERIPH_SPI_GPIO_MODE if HAS_PERIPH_SPI_GPIO_MODE
select MODULE_ZTIMER
select MODULE_ZTIMER_MSEC
select ZTIMER_USEC if !HAS_PERIPH_SPI_GPIO_MODE
select MODULE_CHECKSUM
select ZTIMER_USEC
19 changes: 18 additions & 1 deletion drivers/sdcard_spi/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,21 @@ FEATURES_REQUIRED += periph_spi
FEATURES_OPTIONAL += periph_spi_reconfigure
USEMODULE += checksum
USEMODULE += ztimer
USEMODULE += ztimer_usec
USEMODULE += ztimer_msec

FEATURES_OPTIONAL += periph_spi_gpio_mode
# HACK: periph_spi_gpio_mode will get used only in the next iteration but an updated
# state for FEATURES_USED is needed here so include `features_check.inc.mk`
# here instead.
# An other option would be to check FEATURES_PROVIDED this would avoid the
# order of inclusion problem but it would no take into account possible conflicts
# and is also currently not allowed in the build system.
# An other alternative would be to delay to the next loop, but this produce a
# case where another loop is not executed and the conditional not evaluated
# If these kind of usecases pop up before Kconfig migration is completed
# then another alternative would be introduce a variable to require an extra
# loop independent of USEMODULE, FEATURES_REQUIRED and USEPKG
include $(RIOTMAKE)/features_check.inc.mk
ifeq (,$(filter periph_spi_gpio_mode,$(FEATURES_USED)))
USEMODULE += ztimer_usec
endif
2 changes: 1 addition & 1 deletion drivers/sdcard_spi/include/sdcard_spi_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ extern "C" {
#define SD_POWERSEQUENCE_CLOCK_COUNT 74

#define SD_CARD_PREINIT_CLOCK_PERIOD_US 10 /* used to generate 100 kHz clock in init phase*/
#define SD_CARD_WAIT_AFTER_POWER_UP_US 1000
#define SD_CARD_WAIT_AFTER_POWER_UP_MS 1

/* R1 response bits (see sd spec. 7.3.2.1 Format R1) */
#define SD_R1_RESPONSE_PARAM_ERROR (1<<6)
Expand Down
26 changes: 17 additions & 9 deletions drivers/sdcard_spi/sdcard_spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@
#include <string.h>
#include <inttypes.h>

#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
#define ROUND_UP(N, S) ((((N) + (S)-1) / (S)) * (S))

/* number of used sd cards */
#define SDCARD_SPI_NUM ARRAY_SIZE(sdcard_spi_params)

static inline uint8_t _wait_for_r1(sdcard_spi_t *card, uint32_t retry_us);
static inline void _send_dummy_byte(sdcard_spi_t *card);
Expand All @@ -45,9 +48,6 @@ static sd_rw_response_t _read_data_packet(sdcard_spi_t *card, uint8_t token, uin
static sd_rw_response_t _write_data_packet(sdcard_spi_t *card, uint8_t token, const uint8_t *data,
int size);

/* number of used sd cards */
#define SDCARD_SPI_NUM ARRAY_SIZE(sdcard_spi_params)

/* Allocate memory for the device descriptors */
sdcard_spi_t sdcard_spi_devs[SDCARD_SPI_NUM];

Expand All @@ -59,12 +59,20 @@ static int (*_dyn_spi_rxtx_byte)(sdcard_spi_t *card, uint8_t out, uint8_t *in);

static inline uint32_t _deadline_from_interval(uint32_t interval)
{
# if IS_USED(MODULE_ZTIMER_USEC)
return ztimer_now(ZTIMER_USEC) + interval;
#else
return ztimer_now(ZTIMER_MSEC) * US_PER_MS + interval;
#endif
}

static inline uint32_t _deadline_left(uint32_t deadline)
{
# if IS_USED(MODULE_ZTIMER_USEC)
int32_t left = (int32_t)(deadline - ztimer_now(ZTIMER_USEC));
#else
int32_t left = (int32_t)(deadline - ztimer_now(ZTIMER_MSEC) * US_PER_MS);
#endif

if (left < 0) {
left = 0;
Expand Down Expand Up @@ -179,7 +187,6 @@ static sd_init_fsm_state_t _init_sd_fsm_step(sdcard_spi_t *card, sd_init_fsm_sta
.miso = GPIO_IN_PU,
.sclk = GPIO_OUT,
};

if ((spi_init_with_gpio_mode(card->params.spi_dev, &gpio_modes) == 0) &&
(gpio_init(card->params.cs, GPIO_OUT) == 0) &&
((!gpio_is_valid(card->params.power)) ||
Expand Down Expand Up @@ -214,7 +221,7 @@ static sd_init_fsm_state_t _init_sd_fsm_step(sdcard_spi_t *card, sd_init_fsm_sta

if (gpio_is_valid(card->params.power)) {
gpio_write(card->params.power, card->params.power_act_high);
ztimer_sleep(ZTIMER_USEC, SD_CARD_WAIT_AFTER_POWER_UP_US);
ztimer_sleep(ZTIMER_MSEC, SD_CARD_WAIT_AFTER_POWER_UP_MS);
}

/* powersequence: perform at least 74 clockcycles sending dummy bytes with 0xFF,
Expand Down Expand Up @@ -520,7 +527,7 @@ uint8_t sdcard_spi_send_cmd(sdcard_spi_t *card, uint8_t sd_cmd_idx, uint32_t arg
do {
DEBUG(
"sdcard_spi_send_cmd: CMD%02d (0x%08" PRIx32 ") (remaining retry time %" PRIu32 " usec)\n", sd_cmd_idx, argument,
(retry_timeout > ztimer_now(ZTIMER_USEC)) ? (uint32_t)(retry_timeout - ztimer_now(ZTIMER_USEC)) : 0);
_deadline_left(retry_timeout));

if (!_wait_for_not_busy(card, SD_WAIT_FOR_NOT_BUSY_US)) {
DEBUG("sdcard_spi_send_cmd: timeout while waiting for bus to be not busy!\n");
Expand Down Expand Up @@ -568,8 +575,9 @@ uint8_t sdcard_spi_send_acmd(sdcard_spi_t *card, uint8_t sd_cmd_idx, uint32_t ar
uint8_t r1_resu;

do {
DEBUG("sdcard_spi_send_acmd: CMD%02d (0x%08" PRIx32 ") (remaining retry time %" PRIu32 " usec)\n", sd_cmd_idx, argument,
(retry_timeout > ztimer_now(ZTIMER_USEC)) ? (uint32_t)(retry_timeout - ztimer_now(ZTIMER_USEC)) : 0);
DEBUG(
"sdcard_spi_send_acmd: CMD%02d (0x%08" PRIx32 ") (remaining retry time %" PRIu32 " usec)\n",
sd_cmd_idx, argument, _deadline_left(retry_timeout));
r1_resu = sdcard_spi_send_cmd(card, SD_CMD_55, SD_CMD_NO_ARG, 0);
if (R1_VALID(r1_resu) && !R1_ERROR(r1_resu)) {
r1_resu = sdcard_spi_send_cmd(card, sd_cmd_idx, argument, 0);
Expand Down

0 comments on commit 8436d78

Please sign in to comment.