@@ -93,19 +93,53 @@ static uint8_t CRC7(const uint8_t *data, uint8_t n) {
93
93
}
94
94
95
95
#define READY_TIMEOUT_NS (300 * 1000 * 1000) // 300ms
96
- STATIC void wait_for_ready (sdcardio_sdcard_obj_t * self ) {
96
+ STATIC int wait_for_ready (sdcardio_sdcard_obj_t * self ) {
97
97
uint64_t deadline = common_hal_time_monotonic_ns () + READY_TIMEOUT_NS ;
98
98
while (common_hal_time_monotonic_ns () < deadline ) {
99
99
uint8_t b ;
100
100
common_hal_busio_spi_read (self -> bus , & b , 1 , 0xff );
101
101
if (b == 0xff ) {
102
- break ;
102
+ return 0 ;
103
+ }
104
+ }
105
+ return - ETIMEDOUT ;
106
+ }
107
+
108
+ // Note: this is never called while "in cmd25" (in fact, it's only used by `exit_cmd25`)
109
+ STATIC bool cmd_nodata (sdcardio_sdcard_obj_t * self , int cmd , int response ) {
110
+ uint8_t cmdbuf [2 ] = {cmd , 0xff };
111
+
112
+ assert (!self -> in_cmd25 );
113
+
114
+ common_hal_busio_spi_write (self -> bus , cmdbuf , sizeof (cmdbuf ));
115
+
116
+ // Wait for the response (response[7] == response)
117
+ for (int i = 0 ; i < CMD_TIMEOUT ; i ++ ) {
118
+ common_hal_busio_spi_read (self -> bus , cmdbuf , 1 , 0xff );
119
+ if (cmdbuf [0 ] == response ) {
120
+ return 0 ;
103
121
}
104
122
}
123
+ return - EIO ;
124
+ }
125
+
126
+
127
+ STATIC int exit_cmd25 (sdcardio_sdcard_obj_t * self ) {
128
+ if (self -> in_cmd25 ) {
129
+ DEBUG_PRINT ("exit cmd25\n" );
130
+ self -> in_cmd25 = false;
131
+ return cmd_nodata (self , TOKEN_STOP_TRAN , 0 );
132
+ }
133
+ return 0 ;
105
134
}
106
135
107
136
// In Python API, defaults are response=None, data_block=True, wait=True
108
137
STATIC int cmd (sdcardio_sdcard_obj_t * self , int cmd , int arg , void * response_buf , size_t response_len , bool data_block , bool wait ) {
138
+ int r = exit_cmd25 (self );
139
+ if (r < 0 ) {
140
+ return r ;
141
+ }
142
+
109
143
DEBUG_PRINT ("cmd % 3d [%02x] arg=% 11d [%08x] len=%d%s%s\n" , cmd , cmd , arg , arg , response_len , data_block ? " data" : "" , wait ? " wait" : "" );
110
144
uint8_t cmdbuf [6 ];
111
145
cmdbuf [0 ] = cmd | 0x40 ;
@@ -116,7 +150,10 @@ STATIC int cmd(sdcardio_sdcard_obj_t *self, int cmd, int arg, void *response_buf
116
150
cmdbuf [5 ] = CRC7 (cmdbuf , 5 );
117
151
118
152
if (wait ) {
119
- wait_for_ready (self );
153
+ r = wait_for_ready (self );
154
+ if (r < 0 ) {
155
+ return r ;
156
+ }
120
157
}
121
158
122
159
common_hal_busio_spi_write (self -> bus , cmdbuf , sizeof (cmdbuf ));
@@ -161,21 +198,6 @@ STATIC int block_cmd(sdcardio_sdcard_obj_t *self, int cmd_, int block, void *res
161
198
return cmd (self , cmd_ , block * self -> cdv , response_buf , response_len , true, true);
162
199
}
163
200
164
- STATIC bool cmd_nodata (sdcardio_sdcard_obj_t * self , int cmd , int response ) {
165
- uint8_t cmdbuf [2 ] = {cmd , 0xff };
166
-
167
- common_hal_busio_spi_write (self -> bus , cmdbuf , sizeof (cmdbuf ));
168
-
169
- // Wait for the response (response[7] == response)
170
- for (int i = 0 ; i < CMD_TIMEOUT ; i ++ ) {
171
- common_hal_busio_spi_read (self -> bus , cmdbuf , 1 , 0xff );
172
- if (cmdbuf [0 ] == response ) {
173
- return 0 ;
174
- }
175
- }
176
- return - EIO ;
177
- }
178
-
179
201
STATIC const compressed_string_t * init_card_v1 (sdcardio_sdcard_obj_t * self ) {
180
202
for (int i = 0 ; i < CMD_TIMEOUT ; i ++ ) {
181
203
if (cmd (self , 41 , 0 , NULL , 0 , true, true) == 0 ) {
@@ -298,6 +320,7 @@ void common_hal_sdcardio_sdcard_deinit(sdcardio_sdcard_obj_t *self) {
298
320
if (!self -> bus ) {
299
321
return ;
300
322
}
323
+ common_hal_sdcardio_sdcard_sync (self );
301
324
self -> bus = 0 ;
302
325
common_hal_digitalio_digitalinout_deinit (& self -> cs );
303
326
}
@@ -423,37 +446,43 @@ STATIC int _write(sdcardio_sdcard_obj_t *self, uint8_t token, void *buf, size_t
423
446
STATIC int writeblocks (sdcardio_sdcard_obj_t * self , uint32_t start_block , mp_buffer_info_t * buf ) {
424
447
common_hal_sdcardio_check_for_deinit (self );
425
448
uint32_t nblocks = buf -> len / 512 ;
426
- if (nblocks == 1 ) {
427
- // Use CMD24 to write a single block
428
- int r = block_cmd (self , 24 , start_block , NULL , 0 , true, true);
429
- if (r < 0 ) {
430
- return r ;
431
- }
432
- r = _write (self , TOKEN_DATA , buf -> buf , buf -> len );
433
- if (r < 0 ) {
434
- return r ;
435
- }
436
- } else {
449
+
450
+ DEBUG_PRINT ("cmd25? %d next_block %d start_block %d\n" , self -> in_cmd25 , self -> next_block , start_block );
451
+
452
+ if (!self -> in_cmd25 || start_block != self -> next_block ) {
453
+ DEBUG_PRINT ("entering CMD25 at %d\n" , (int )start_block );
437
454
// Use CMD25 to write multiple block
438
455
int r = block_cmd (self , 25 , start_block , NULL , 0 , true, true);
439
456
if (r < 0 ) {
440
457
return r ;
441
458
}
459
+ self -> in_cmd25 = true;
460
+ }
442
461
443
- uint8_t * ptr = buf -> buf ;
444
- while (nblocks -- ) {
445
- r = _write (self , TOKEN_CMD25 , ptr , 512 );
446
- if (r < 0 ) {
447
- return r ;
448
- }
449
- ptr += 512 ;
450
- }
462
+ self -> next_block = start_block ;
451
463
452
- cmd_nodata (self , TOKEN_STOP_TRAN , 0 );
464
+ uint8_t * ptr = buf -> buf ;
465
+ while (nblocks -- ) {
466
+ int r = _write (self , TOKEN_CMD25 , ptr , 512 );
467
+ if (r < 0 ) {
468
+ self -> in_cmd25 = false;
469
+ return r ;
470
+ }
471
+ self -> next_block ++ ;
472
+ ptr += 512 ;
453
473
}
474
+
454
475
return 0 ;
455
476
}
456
477
478
+ int common_hal_sdcardio_sdcard_sync (sdcardio_sdcard_obj_t * self ) {
479
+ common_hal_sdcardio_check_for_deinit (self );
480
+ lock_and_configure_bus (self );
481
+ int r = exit_cmd25 (self );
482
+ extraclock_and_unlock_bus (self );
483
+ return r ;
484
+ }
485
+
457
486
int common_hal_sdcardio_sdcard_writeblocks (sdcardio_sdcard_obj_t * self , uint32_t start_block , mp_buffer_info_t * buf ) {
458
487
common_hal_sdcardio_check_for_deinit (self );
459
488
if (buf -> len % 512 != 0 ) {
0 commit comments