Skip to content

Commit 354cfe9

Browse files
committed
mimxrt/sdcard: Add cache coherency operations for DMA transfers.
Add explicit data cache management to ensure DMA transfers work correctly on systems with data cache enabled (e.g., MIMXRT1170). For writes: Clean cache to RAM before transfer so DMA reads correct data. For reads: Clean and invalidate cache before transfer, then invalidate again after transfer completes to discard any speculative cache line fills that may have occurred during the DMA. Also fix writeblocks to use MP_BUFFER_READ (reading from buffer to write to card) and update read/writeblocks to raise OSError on failure. Signed-off-by: Andrew Leech <[email protected]>
1 parent 7b68e74 commit 354cfe9

File tree

3 files changed

+23
-13
lines changed

3 files changed

+23
-13
lines changed

ports/mimxrt/machine_sdcard.c

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,10 @@ static mp_obj_t machine_sdcard_readblocks(mp_obj_t self_in, mp_obj_t block_num,
104104
mp_buffer_info_t bufinfo;
105105
mimxrt_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in);
106106
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE);
107-
108-
if (sdcard_read(self, bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / SDCARD_DEFAULT_BLOCK_SIZE)) {
109-
return MP_OBJ_NEW_SMALL_INT(0);
110-
} else {
111-
return MP_OBJ_NEW_SMALL_INT(-MP_EIO);
107+
if (!sdcard_read(self, bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / SDCARD_DEFAULT_BLOCK_SIZE)) {
108+
mp_raise_OSError(MP_EIO);
112109
}
110+
return mp_const_none;
113111
}
114112
static MP_DEFINE_CONST_FUN_OBJ_3(machine_sdcard_readblocks_obj, machine_sdcard_readblocks);
115113

@@ -142,13 +140,11 @@ static MP_DEFINE_CONST_FUN_OBJ_1(machine_sdcard_info_obj, machine_sdcard_info);
142140
static mp_obj_t machine_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t block_num, mp_obj_t buf) {
143141
mp_buffer_info_t bufinfo;
144142
mimxrt_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in);
145-
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE);
146-
147-
if (sdcard_write(self, bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / SDCARD_DEFAULT_BLOCK_SIZE)) {
148-
return MP_OBJ_NEW_SMALL_INT(0);
149-
} else {
150-
return MP_OBJ_NEW_SMALL_INT(-MP_EIO);
143+
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ);
144+
if (!sdcard_write(self, bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / SDCARD_DEFAULT_BLOCK_SIZE)) {
145+
mp_raise_OSError(MP_EIO);
151146
}
147+
return mp_const_none;
152148
}
153149
static MP_DEFINE_CONST_FUN_OBJ_3(machine_sdcard_writeblocks_obj, machine_sdcard_writeblocks);
154150

ports/mimxrt/sdcard.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -867,11 +867,19 @@ void sdcard_init_pins(mimxrt_sdcard_obj_t *card) {
867867
}
868868
}
869869

870+
// Note on buffer alignment: The cache operations extend to 32-byte (cache line) boundaries.
871+
// For buffers that are part of larger structures, this could affect adjacent memory.
872+
// The MicroPython VFS layer typically provides properly allocated buffers that are safe.
873+
// DMA requires 4-byte alignment which is checked implicitly by the hardware.
870874
bool sdcard_read(mimxrt_sdcard_obj_t *card, uint8_t *buffer, uint32_t block_num, uint32_t block_count) {
871875
if (!card->state->initialized) {
872876
return false;
873877
}
874878

879+
// Ensure cache is flushed and invalidated so when DMA updates RAM
880+
// from the peripheral, the CPU reads the new data.
881+
MP_HAL_CLEANINVALIDATE_DCACHE(buffer, block_count * card->block_len);
882+
875883
usdhc_data_t data = {
876884
.enableAutoCommand12 = true,
877885
.enableAutoCommand23 = false,
@@ -900,17 +908,23 @@ bool sdcard_read(mimxrt_sdcard_obj_t *card, uint8_t *buffer, uint32_t block_num,
900908

901909
if (status == kStatus_Success) {
902910
card->status = command.response[0];
911+
// Invalidate cache again after DMA completes to discard any speculative
912+
// cache line fills that may have occurred during the transfer.
913+
MP_HAL_CLEANINVALIDATE_DCACHE(buffer, block_count * card->block_len);
903914
return true;
904915
} else {
905916
return false;
906917
}
907918
}
908919

909-
bool sdcard_write(mimxrt_sdcard_obj_t *card, uint8_t *buffer, uint32_t block_num, uint32_t block_count) {
920+
bool sdcard_write(mimxrt_sdcard_obj_t *card, const uint8_t *buffer, uint32_t block_num, uint32_t block_count) {
910921
if (!card->state->initialized) {
911922
return false;
912923
}
913924

925+
// Ensure cache is flushed to RAM so DMA can read the correct data.
926+
MP_HAL_CLEAN_DCACHE(buffer, block_count * card->block_len);
927+
914928
usdhc_data_t data = {
915929
.enableAutoCommand12 = true,
916930
.enableAutoCommand23 = false,

ports/mimxrt/sdcard.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ void sdcard_init(mimxrt_sdcard_obj_t *card, uint32_t base_clk);
9999
void sdcard_deinit(mimxrt_sdcard_obj_t *card);
100100
void sdcard_init_pins(mimxrt_sdcard_obj_t *card);
101101
bool sdcard_read(mimxrt_sdcard_obj_t *card, uint8_t *buffer, uint32_t block_num, uint32_t block_count);
102-
bool sdcard_write(mimxrt_sdcard_obj_t *card, uint8_t *buffer, uint32_t block_num, uint32_t block_count);
102+
bool sdcard_write(mimxrt_sdcard_obj_t *card, const uint8_t *buffer, uint32_t block_num, uint32_t block_count);
103103
bool sdcard_set_active(mimxrt_sdcard_obj_t *card);
104104
bool sdcard_volt_validation(mimxrt_sdcard_obj_t *card);
105105
bool sdcard_power_on(mimxrt_sdcard_obj_t *self);

0 commit comments

Comments
 (0)