2424 * THE SOFTWARE.
2525 */
2626
27+ #include <string.h>
28+
2729#include "py/nlr.h"
2830#include "py/runtime.h"
2931#include "lib/fatfs/ff.h"
@@ -192,18 +194,31 @@ void SDIO_IRQHandler(void) {
192194}
193195
194196mp_uint_t sdcard_read_blocks (uint8_t * dest , uint32_t block_num , uint32_t num_blocks ) {
195- // check that dest pointer is aligned on a 4-byte boundary
196- if (((uint32_t )dest & 3 ) != 0 ) {
197- return SD_ERROR ;
198- }
199-
200197 // check that SD card is initialised
201198 if (sd_handle .Instance == NULL ) {
202199 return SD_ERROR ;
203200 }
204201
205202 HAL_SD_ErrorTypedef err = SD_OK ;
206203
204+ // check that dest pointer is aligned on a 4-byte boundary
205+ uint8_t * orig_dest = NULL ;
206+ uint32_t saved_word ;
207+ if (((uint32_t )dest & 3 ) != 0 ) {
208+ // Pointer is not aligned so it needs fixing.
209+ // We could allocate a temporary block of RAM (as sdcard_write_blocks
210+ // does) but instead we are going to use the dest buffer inplace. We
211+ // are going to align the pointer, save the initial word at the aligned
212+ // location, read into the aligned memory, move the memory back to the
213+ // unaligned location, then restore the initial bytes at the aligned
214+ // location. We should have no trouble doing this as those initial
215+ // bytes at the aligned location should be able to be changed for the
216+ // duration of this function call.
217+ orig_dest = dest ;
218+ dest = (uint8_t * )((uint32_t )dest & ~3 );
219+ saved_word = * (uint32_t * )dest ;
220+ }
221+
207222 if (query_irq () == IRQ_STATE_ENABLED ) {
208223 // we must disable USB irqs to prevent MSC contention with SD card
209224 uint32_t basepri = raise_irq_pri (IRQ_PRI_OTG_FS );
@@ -225,22 +240,41 @@ mp_uint_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blo
225240 err = HAL_SD_ReadBlocks_BlockNumber (& sd_handle , (uint32_t * )dest , block_num , SDCARD_BLOCK_SIZE , num_blocks );
226241 }
227242
243+ if (orig_dest != NULL ) {
244+ // move the read data to the non-aligned position, and restore the initial bytes
245+ memmove (orig_dest , dest , num_blocks * SDCARD_BLOCK_SIZE );
246+ memcpy (dest , & saved_word , orig_dest - dest );
247+ }
248+
228249 return err ;
229250}
230251
231252mp_uint_t sdcard_write_blocks (const uint8_t * src , uint32_t block_num , uint32_t num_blocks ) {
232- // check that src pointer is aligned on a 4-byte boundary
233- if (((uint32_t )src & 3 ) != 0 ) {
234- return SD_ERROR ;
235- }
236-
237253 // check that SD card is initialised
238254 if (sd_handle .Instance == NULL ) {
239255 return SD_ERROR ;
240256 }
241257
242258 HAL_SD_ErrorTypedef err = SD_OK ;
243259
260+ // check that src pointer is aligned on a 4-byte boundary
261+ if (((uint32_t )src & 3 ) != 0 ) {
262+ // pointer is not aligned, so allocate a temporary block to do the write
263+ uint8_t * src_aligned = m_new_maybe (uint8_t , SDCARD_BLOCK_SIZE );
264+ if (src_aligned == NULL ) {
265+ return SD_ERROR ;
266+ }
267+ for (size_t i = 0 ; i < num_blocks ; ++ i ) {
268+ memcpy (src_aligned , src + i * SDCARD_BLOCK_SIZE , SDCARD_BLOCK_SIZE );
269+ err = sdcard_write_blocks (src_aligned , block_num + i , 1 );
270+ if (err != SD_OK ) {
271+ break ;
272+ }
273+ }
274+ m_del (uint8_t , src_aligned , SDCARD_BLOCK_SIZE );
275+ return err ;
276+ }
277+
244278 if (query_irq () == IRQ_STATE_ENABLED ) {
245279 // we must disable USB irqs to prevent MSC contention with SD card
246280 uint32_t basepri = raise_irq_pri (IRQ_PRI_OTG_FS );
0 commit comments