Skip to content

Commit bb09517

Browse files
authored
Merge pull request #191 from BlueSCSI/SDSpeedClassWarn
Log a warning for slow SD cards
2 parents be2d0d9 + 416dc80 commit bb09517

File tree

5 files changed

+68
-11
lines changed

5 files changed

+68
-11
lines changed

lib/BlueSCSI_platform_RP2040/rp2040_sdio.cpp

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,39 @@ void cycleSdClock() {
156156
pio_sm_exec(SDIO_PIO, SDIO_CMD_SM, pio_encode_nop() | pio_encode_sideset_opt(1, 0) | pio_encode_delay(1));
157157
}
158158

159+
/*******************************************************
160+
* Status Register Receiver
161+
*******************************************************/
162+
sdio_status_t receive_status_register(uint8_t* sds) {
163+
rp2040_sdio_rx_start(sds, 1, 64);
164+
165+
// Wait for the DMA operation to complete, or fail if it took too long
166+
waitagain:
167+
while (dma_channel_is_busy(SDIO_DMA_CHB) || dma_channel_is_busy(SDIO_DMA_CH))
168+
{
169+
if ((uint32_t)(millis() - g_sdio.transfer_start_time) > 2)
170+
{
171+
// Reset the state machine program
172+
dma_channel_abort(SDIO_DMA_CHB);
173+
pio_sm_set_enabled(SDIO_PIO, SDIO_CMD_SM, false);
174+
pio_sm_clear_fifos(SDIO_PIO, SDIO_CMD_SM);
175+
return SDIO_ERR_RESPONSE_TIMEOUT;
176+
}
177+
}
178+
179+
// Assert that both DMA channels are complete
180+
if(dma_channel_is_busy(SDIO_DMA_CHB) || dma_channel_is_busy(SDIO_DMA_CH)) {
181+
// Wait failure, go back.
182+
goto waitagain;
183+
}
184+
185+
pio_sm_set_enabled(SDIO_PIO, SDIO_DATA_SM, false);
186+
g_sdio.transfer_state = SDIO_IDLE;
187+
188+
return SDIO_OK;
189+
}
190+
191+
159192
/*******************************************************
160193
* Basic SDIO command execution
161194
*******************************************************/
@@ -437,7 +470,7 @@ sdio_status_t rp2040_sdio_command_R3(uint8_t command, uint32_t arg, uint32_t *re
437470
* Data reception from SD card
438471
*******************************************************/
439472

440-
sdio_status_t rp2040_sdio_rx_start(uint8_t *buffer, uint32_t num_blocks)
473+
sdio_status_t rp2040_sdio_rx_start(uint8_t *buffer, uint32_t num_blocks, uint32_t block_size)
441474
{
442475
// Buffer must be aligned
443476
assert(((uint32_t)buffer & 3) == 0 && num_blocks <= SDIO_MAX_BLOCKS);
@@ -450,12 +483,12 @@ sdio_status_t rp2040_sdio_rx_start(uint8_t *buffer, uint32_t num_blocks)
450483
g_sdio.blocks_checksumed = 0;
451484
g_sdio.checksum_errors = 0;
452485

453-
// Create DMA block descriptors to store each block of 512 bytes of data to buffer
486+
// Create DMA block descriptors to store each block of block_size bytes of data to buffer
454487
// and then 8 bytes to g_sdio.received_checksums.
455488
for (int i = 0; i < num_blocks; i++)
456489
{
457-
g_sdio.dma_blocks[i * 2].write_addr = buffer + i * SDIO_BLOCK_SIZE;
458-
g_sdio.dma_blocks[i * 2].transfer_count = SDIO_BLOCK_SIZE / sizeof(uint32_t);
490+
g_sdio.dma_blocks[i * 2].write_addr = buffer + (i * block_size);
491+
g_sdio.dma_blocks[i * 2].transfer_count = block_size / sizeof(uint32_t);
459492

460493
g_sdio.dma_blocks[i * 2 + 1].write_addr = &g_sdio.received_checksums[i];
461494
g_sdio.dma_blocks[i * 2 + 1].transfer_count = 2;
@@ -488,7 +521,7 @@ sdio_status_t rp2040_sdio_rx_start(uint8_t *buffer, uint32_t num_blocks)
488521
pio_sm_set_consecutive_pindirs(SDIO_PIO, SDIO_DATA_SM, SDIO_D0, 4, false);
489522

490523
// Write number of nibbles to receive to Y register
491-
pio_sm_put(SDIO_PIO, SDIO_DATA_SM, SDIO_BLOCK_SIZE * 2 + 16 - 1);
524+
pio_sm_put(SDIO_PIO, SDIO_DATA_SM, (block_size * 2) + 16 - 1);
492525
pio_sm_exec(SDIO_PIO, SDIO_DATA_SM, pio_encode_out(pio_y, 32));
493526

494527
// Enable RX FIFO join because we don't need the TX FIFO during transfer.

lib/BlueSCSI_platform_RP2040/rp2040_sdio.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@ sdio_status_t rp2040_sdio_command_R2(uint8_t command, uint32_t arg, uint8_t *res
3232
sdio_status_t rp2040_sdio_command_R3(uint8_t command, uint32_t arg, uint32_t *response);
3333

3434
// Start transferring data from SD card to memory buffer
35-
// Transfer block size is always 512 bytes.
36-
sdio_status_t rp2040_sdio_rx_start(uint8_t *buffer, uint32_t num_blocks);
35+
// num_blocks is the count of data blocks to transfer
36+
// block_size is the number of *bytes* to transfer in each block (must be evenly divisible by 4)
37+
// A CRC is expected after every data block
38+
sdio_status_t rp2040_sdio_rx_start(uint8_t *buffer, uint32_t num_blocks, uint32_t block_size);
3739

3840
// Check if reception is complete
3941
// Returns SDIO_BUSY while transferring, SDIO_OK when done and error on failure.
@@ -51,5 +53,8 @@ sdio_status_t rp2040_sdio_stop();
5153
// Performs one full CLK line cycle
5254
void cycleSdClock();
5355

56+
// Receives the SD Status register. Does not return until the register has been received.
57+
sdio_status_t receive_status_register(uint8_t* sds);
58+
5459
// (Re)initialize the SDIO interface
5560
void rp2040_sdio_init(int clock_divider = 1);

lib/BlueSCSI_platform_RP2040/sd_card_sdio.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ static int g_sdio_error_line;
2121
static sdio_status_t g_sdio_error;
2222
static uint32_t g_sdio_dma_buf[128];
2323
static uint32_t g_sdio_sector_count;
24-
static uint8_t cardType;
24+
uint8_t sdSpeedClass;
2525

2626
#define checkReturnOk(call) ((g_sdio_error = (call)) == SDIO_OK ? true : logSDError(__LINE__))
2727
static bool logSDError(int line)
@@ -149,6 +149,19 @@ bool SdioCard::begin(SdioConfig sdioConfig)
149149
return false;
150150
}
151151

152+
// Read SD Status field
153+
sds_t sd_stat;
154+
memset(&sd_stat, 0, sizeof(sds_t));
155+
uint8_t* stat_pointer = (uint8_t*) &sd_stat;
156+
if (!checkReturnOk(rp2040_sdio_command_R1(CMD55, g_sdio_rca, &reply)) ||
157+
!checkReturnOk(rp2040_sdio_command_R1(ACMD13, 0, &reply)) ||
158+
!checkReturnOk(receive_status_register(stat_pointer)))
159+
{
160+
debuglog("SDIO failed to get SD Status");
161+
return false;
162+
}
163+
sdSpeedClass = sd_stat.speedClass();
164+
152165
// Increase to 25 MHz clock rate
153166
rp2040_sdio_init(1);
154167

@@ -428,7 +441,7 @@ bool SdioCard::readSector(uint32_t sector, uint8_t* dst)
428441
if (
429442
!checkReturnOk(rp2040_sdio_command_R1(16, 512, &reply)) || // SET_BLOCKLEN
430443
!checkReturnOk(rp2040_sdio_command_R1(CMD17, address, &reply)) || // READ_SINGLE_BLOCK
431-
!checkReturnOk(rp2040_sdio_rx_start(dst, 1)) // Prepare for reception
444+
!checkReturnOk(rp2040_sdio_rx_start(dst, 1, SDIO_BLOCK_SIZE)) // Prepare for reception
432445
)
433446
{
434447
return false;
@@ -481,7 +494,7 @@ bool SdioCard::readSectors(uint32_t sector, uint8_t* dst, size_t n)
481494
if (
482495
!checkReturnOk(rp2040_sdio_command_R1(16, 512, &reply)) || // SET_BLOCKLEN
483496
!checkReturnOk(rp2040_sdio_command_R1(CMD18, address, &reply)) || // READ_MULTIPLE_BLOCK
484-
!checkReturnOk(rp2040_sdio_rx_start(dst, n)) // Prepare for reception
497+
!checkReturnOk(rp2040_sdio_rx_start(dst, n, SDIO_BLOCK_SIZE)) // Prepare for reception
485498
)
486499
{
487500
return false;

platformio.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ debug_tool = cmsis-dap ; new picoprobe.uf2's emulate cmsis-dap
2323
; extra_scripts = src/build_bootloader.py
2424
; ldscript_bootloader = lib/BlueSCSI_platform_RP2040/rp2040_btldr.ld
2525
lib_deps =
26-
SdFat=https://github.com/BlueSCSI/SdFat#2.2.0-gpt
26+
SdFat=https://github.com/BlueSCSI/SdFat#3447b2eabb6c4d1e22c421b34d077bffecb7f81b
2727
minIni
2828
BlueSCSI_platform_RP2040
2929
SCSI2SD

src/BlueSCSI_disk.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
#include <assert.h>
2424
#include <SdFat.h>
2525

26+
extern uint8_t sdSpeedClass;
27+
#define SD_SPEED_CLASS_WARN_BELOW 10
28+
2629
extern "C" {
2730
#include <scsi2sd_time.h>
2831
#include <sd.h>
@@ -1026,6 +1029,9 @@ void s2s_configInit(S2S_BoardCfg* config)
10261029
config->scsiSpeed = PLATFORM_MAX_SCSI_SPEED;
10271030

10281031
int maxSyncSpeed = ini_getl("SCSI", "MaxSyncSpeed", defaults.maxSyncSpeed, CONFIGFILE);
1032+
if (sdSpeedClass < SD_SPEED_CLASS_WARN_BELOW) {
1033+
log_f("---- WARNING: Your SD Card Speed Class is %d. Class 10 or better is recommended for best performance.", sdSpeedClass);
1034+
}
10291035
if (maxSyncSpeed < 5 && config->scsiSpeed > S2S_CFG_SPEED_ASYNC_50)
10301036
config->scsiSpeed = S2S_CFG_SPEED_ASYNC_50;
10311037
else if (maxSyncSpeed < 10 && config->scsiSpeed > S2S_CFG_SPEED_SYNC_5)

0 commit comments

Comments
 (0)