Skip to content

Commit ed0899e

Browse files
committed
mimxrt/sdcard: Implement timeout using non-blocking SDK API.
Replace USDHC_TransferBlocking() with USDHC_TransferNonBlocking() to enable proper timeout handling. The non-blocking API uses interrupt-driven callbacks to signal transfer completion. Implementation: - Added transfer_status and transfer_error fields to card state - Implemented sdcard_transfer_complete_callback() for ISR context - Register callback via USDHC_TransferCreateHandle() (SDK enables IRQs) - Use USDHC_TransferNonBlocking() to start transfers - Poll volatile status flags with timeout and MICROPY_EVENT_POLL_HOOK - Return timeout error if transfer doesn't complete within specified time This follows the same pattern as ports/mimxrt/sdio.c. Signed-off-by: Andrew Leech <[email protected]>
1 parent 5dd59d4 commit ed0899e

File tree

2 files changed

+61
-17
lines changed

2 files changed

+61
-17
lines changed

ports/mimxrt/sdcard.c

Lines changed: 59 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@
3838
#define SDCARD_SWITCH_1_8V_CAPACITY ((uint32_t)0x01000000U)
3939
#define SDCARD_MAX_VOLT_TRIAL ((uint32_t)0x000000FFU)
4040

41+
// Transfer status flags
42+
#define SDCARD_TRANSFER_CMD_COMPLETE (1U << 0)
43+
#define SDCARD_TRANSFER_DATA_COMPLETE (1U << 1)
44+
#define SDCARD_TRANSFER_ERROR (1U << 2)
45+
4146
// Error
4247
#define SDCARD_STATUS_OUT_OF_RANGE_SHIFT (31U)
4348
#define SDCARD_STATUS_ADDRESS_ERROR_SHIFT (30U)
@@ -275,6 +280,19 @@ void sdcard_dummy_callback(USDHC_Type *base, void *userData) {
275280
return;
276281
}
277282

283+
void sdcard_transfer_complete_callback(USDHC_Type *base, usdhc_handle_t *handle, status_t status, void *userData) {
284+
mimxrt_sdcard_obj_t *card = (mimxrt_sdcard_obj_t *)userData;
285+
286+
if (status == kStatus_USDHC_TransferDataComplete) {
287+
card->state->transfer_status |= SDCARD_TRANSFER_DATA_COMPLETE;
288+
} else if (status == kStatus_USDHC_SendCommandSuccess) {
289+
card->state->transfer_status |= SDCARD_TRANSFER_CMD_COMPLETE;
290+
} else if (status != kStatus_USDHC_BusyTransferring) {
291+
card->state->transfer_error = status;
292+
card->state->transfer_status |= SDCARD_TRANSFER_ERROR;
293+
}
294+
}
295+
278296
static void sdcard_error_recovery(USDHC_Type *base) {
279297
uint32_t status = 0U;
280298
/* get host present status */
@@ -306,23 +324,46 @@ static status_t sdcard_transfer_blocking(USDHC_Type *base, usdhc_handle_t *handl
306324
dma_config.admaTable = sdcard_adma_descriptor_table;
307325
dma_config.admaTableWords = DMA_DESCRIPTOR_BUFFER_SIZE;
308326

309-
// Wait while the card is busy before a transfer
310-
status = kStatus_Timeout;
311-
for (int i = 0; i < timeout_ms * 100; i++) {
312-
// Wait until Data0 is low any more. Low indicates "Busy".
313-
if (((transfer->data->txData == NULL) && (transfer->data->rxData == NULL)) ||
314-
(USDHC_GetPresentStatusFlags(base) & (uint32_t)kUSDHC_Data0LineLevelFlag) != 0) {
315-
// Not busy anymore or no TX-Data
316-
status = USDHC_TransferBlocking(base, &dma_config, transfer);
317-
if (status != kStatus_Success) {
318-
sdcard_error_recovery(base);
319-
}
320-
break;
321-
}
322-
ticks_delay_us64(10);
327+
// Get the card object from handle's userData
328+
mimxrt_sdcard_obj_t *card = (mimxrt_sdcard_obj_t *)handle->userData;
329+
330+
// Clear transfer status flags
331+
card->state->transfer_status = 0;
332+
card->state->transfer_error = kStatus_Success;
333+
334+
// Determine expected completion flags
335+
uint32_t expected_flags = SDCARD_TRANSFER_CMD_COMPLETE;
336+
if (transfer->data != NULL) {
337+
expected_flags |= SDCARD_TRANSFER_DATA_COMPLETE;
338+
}
339+
340+
// Start non-blocking transfer
341+
status = USDHC_TransferNonBlocking(base, handle, &dma_config, transfer);
342+
if (status != kStatus_Success) {
343+
return status;
344+
}
345+
346+
// Wait for transfer completion with timeout
347+
uint64_t start = ticks_us64();
348+
uint64_t timeout_us = (uint64_t)timeout_ms * 1000ULL;
349+
350+
while ((card->state->transfer_status != expected_flags) &&
351+
!(card->state->transfer_status & SDCARD_TRANSFER_ERROR) &&
352+
((ticks_us64() - start) < timeout_us)) {
353+
MICROPY_EVENT_POLL_HOOK;
354+
}
355+
356+
if (card->state->transfer_status == 0) {
357+
// Timeout - no status flags set
358+
sdcard_error_recovery(base);
359+
return kStatus_Timeout;
360+
} else if (card->state->transfer_status != expected_flags) {
361+
// Error occurred
362+
sdcard_error_recovery(base);
363+
return card->state->transfer_error;
323364
}
324-
return status;
325365

366+
return kStatus_Success;
326367
}
327368

328369
static void sdcard_decode_csd(mimxrt_sdcard_obj_t *card, csd_t *csd) {
@@ -725,10 +766,11 @@ void sdcard_init(mimxrt_sdcard_obj_t *card, uint32_t base_clk) {
725766
.CardRemoved = sdcard_card_removed_callback,
726767
.SdioInterrupt = sdcard_dummy_callback,
727768
.BlockGap = sdcard_dummy_callback,
769+
.TransferComplete = sdcard_transfer_complete_callback,
728770
.ReTuning = sdcard_dummy_callback,
729771
};
730772

731-
USDHC_TransferCreateHandle(card->usdhc_inst, &card->handle, &callbacks, NULL);
773+
USDHC_TransferCreateHandle(card->usdhc_inst, &card->handle, &callbacks, card);
732774
}
733775

734776
void sdcard_deinit(mimxrt_sdcard_obj_t *card) {
@@ -987,7 +1029,7 @@ bool sdcard_power_on(mimxrt_sdcard_obj_t *card) {
9871029

9881030
bool sdcard_power_off(mimxrt_sdcard_obj_t *card) {
9891031
// Only send GO_IDLE_STATE command if card was successfully initialized
990-
// Sending commands to a non-existent card will deadlock waiting for response
1032+
// Sending commands to a non-existent card can timeout/hang waiting for response
9911033
if (card->state->initialized) {
9921034
(void)sdcard_cmd_go_idle_state(card);
9931035
}

ports/mimxrt/sdcard.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ typedef struct _mimxrt_sdcard_obj_pins_t {
5757
typedef volatile struct _mimxrt_sdcard_status_obj_t {
5858
bool initialized;
5959
bool inserted;
60+
uint32_t transfer_status;
61+
status_t transfer_error;
6062
} mimxrt_sdcard_status_obj_t;
6163

6264
typedef struct _mimxrt_sdcard_obj_t {

0 commit comments

Comments
 (0)