Skip to content

Commit daaaaef

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 daaaaef

File tree

2 files changed

+62
-17
lines changed

2 files changed

+62
-17
lines changed

ports/mimxrt/sdcard.c

Lines changed: 60 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,20 @@ 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+
__DSB(); // Ensure error is visible before status flag
293+
card->state->transfer_status |= SDCARD_TRANSFER_ERROR;
294+
}
295+
}
296+
278297
static void sdcard_error_recovery(USDHC_Type *base) {
279298
uint32_t status = 0U;
280299
/* get host present status */
@@ -306,23 +325,46 @@ static status_t sdcard_transfer_blocking(USDHC_Type *base, usdhc_handle_t *handl
306325
dma_config.admaTable = sdcard_adma_descriptor_table;
307326
dma_config.admaTableWords = DMA_DESCRIPTOR_BUFFER_SIZE;
308327

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);
328+
// Get the card object from handle's userData
329+
mimxrt_sdcard_obj_t *card = (mimxrt_sdcard_obj_t *)handle->userData;
330+
331+
// Clear transfer status flags
332+
card->state->transfer_status = 0;
333+
card->state->transfer_error = kStatus_Success;
334+
335+
// Determine expected completion flags
336+
uint32_t expected_flags = SDCARD_TRANSFER_CMD_COMPLETE;
337+
if (transfer->data != NULL) {
338+
expected_flags |= SDCARD_TRANSFER_DATA_COMPLETE;
339+
}
340+
341+
// Start non-blocking transfer
342+
status = USDHC_TransferNonBlocking(base, handle, &dma_config, transfer);
343+
if (status != kStatus_Success) {
344+
return status;
345+
}
346+
347+
// Wait for transfer completion with timeout
348+
// Read transfer_status into local variable to avoid race with ISR between condition checks
349+
uint32_t start = mp_hal_ticks_ms();
350+
uint32_t xfer_status;
351+
while (((xfer_status = card->state->transfer_status) != expected_flags) &&
352+
!(xfer_status & SDCARD_TRANSFER_ERROR) &&
353+
(mp_hal_ticks_ms() - start) < timeout_ms) {
354+
MICROPY_EVENT_POLL_HOOK;
355+
}
356+
357+
if (xfer_status == 0) {
358+
// Timeout - no status flags set
359+
sdcard_error_recovery(base);
360+
return kStatus_Timeout;
361+
} else if (xfer_status != expected_flags) {
362+
// Error occurred
363+
sdcard_error_recovery(base);
364+
return card->state->transfer_error;
323365
}
324-
return status;
325366

367+
return kStatus_Success;
326368
}
327369

328370
static void sdcard_decode_csd(mimxrt_sdcard_obj_t *card, csd_t *csd) {
@@ -725,10 +767,11 @@ void sdcard_init(mimxrt_sdcard_obj_t *card, uint32_t base_clk) {
725767
.CardRemoved = sdcard_card_removed_callback,
726768
.SdioInterrupt = sdcard_dummy_callback,
727769
.BlockGap = sdcard_dummy_callback,
770+
.TransferComplete = sdcard_transfer_complete_callback,
728771
.ReTuning = sdcard_dummy_callback,
729772
};
730773

731-
USDHC_TransferCreateHandle(card->usdhc_inst, &card->handle, &callbacks, NULL);
774+
USDHC_TransferCreateHandle(card->usdhc_inst, &card->handle, &callbacks, card);
732775
}
733776

734777
void sdcard_deinit(mimxrt_sdcard_obj_t *card) {
@@ -987,7 +1030,7 @@ bool sdcard_power_on(mimxrt_sdcard_obj_t *card) {
9871030

9881031
bool sdcard_power_off(mimxrt_sdcard_obj_t *card) {
9891032
// Only send GO_IDLE_STATE command if card was successfully initialized
990-
// Sending commands to a non-existent card will deadlock waiting for response
1033+
// Sending commands to a non-existent card can timeout/hang waiting for response
9911034
if (card->state->initialized) {
9921035
(void)sdcard_cmd_go_idle_state(card);
9931036
}

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)