From 7996923082a9c924bac3e0807da93dc20b3ea804 Mon Sep 17 00:00:00 2001 From: Morio Date: Fri, 4 Oct 2024 11:26:08 -0700 Subject: [PATCH] Add SD card speed class warning This change warns the user if they are using an SD card below the speed class of 10. Based on the ZuluSCSI commit https://github.com/ZuluSCSI/ZuluSCSI-firmware/commit/28f68ac033c99e66ba21adc5bf02a5007e5c61b4 which is based off of https://github.com/BlueSCSI/BlueSCSI-v2/pull/191 Co-authored-by: androda <3105206+androda@users.noreply.github.com> --- lib/ZuluIDE_platform_RP2040/rp2040_sdio.cpp | 41 +++++++++++++++++--- lib/ZuluIDE_platform_RP2040/rp2040_sdio.h | 5 ++- lib/ZuluIDE_platform_RP2040/sd_card_sdio.cpp | 21 +++++++++- platformio.ini | 2 +- src/ZuluIDE.cpp | 9 +++++ src/ZuluIDE_config.h | 2 +- src/ide_imagefile.cpp | 1 - src/ide_rigid.cpp | 12 ------ 8 files changed, 70 insertions(+), 23 deletions(-) diff --git a/lib/ZuluIDE_platform_RP2040/rp2040_sdio.cpp b/lib/ZuluIDE_platform_RP2040/rp2040_sdio.cpp index d62d1ea..a8b337f 100644 --- a/lib/ZuluIDE_platform_RP2040/rp2040_sdio.cpp +++ b/lib/ZuluIDE_platform_RP2040/rp2040_sdio.cpp @@ -1,7 +1,8 @@ /** - * ZuluIDE™ - Copyright (c) 2023 Rabbit Hole Computing™ + * ZuluIDE™ - Copyright (c) 2023-2024 Rabbit Hole Computing™ + * Copyright (c) 2024 Tech by Androda, LLC * - * ZuluIDE™ firmware is licensed under the GPL version 3 or any later version.  + * ZuluIDE™ firmware is licensed under the GPL version 3 or any later version. * * https://www.gnu.org/licenses/gpl-3.0.html * ---- @@ -369,7 +370,7 @@ sdio_status_t rp2040_sdio_command_R3(uint8_t command, uint32_t arg, uint32_t *re * Data reception from SD card *******************************************************/ -sdio_status_t rp2040_sdio_rx_start(uint8_t *buffer, uint32_t num_blocks) +sdio_status_t rp2040_sdio_rx_start(uint8_t *buffer, uint32_t num_blocks, uint32_t block_size) { // Buffer must be aligned assert(((uint32_t)buffer & 3) == 0 && num_blocks <= SDIO_MAX_BLOCKS); @@ -386,8 +387,8 @@ sdio_status_t rp2040_sdio_rx_start(uint8_t *buffer, uint32_t num_blocks) // and then 8 bytes to g_sdio.received_checksums. for (int i = 0; i < num_blocks; i++) { - g_sdio.dma_blocks[i * 2].write_addr = buffer + i * SDIO_BLOCK_SIZE; - g_sdio.dma_blocks[i * 2].transfer_count = SDIO_BLOCK_SIZE / sizeof(uint32_t); + g_sdio.dma_blocks[i * 2].write_addr = buffer + i * block_size; + g_sdio.dma_blocks[i * 2].transfer_count = block_size / sizeof(uint32_t); g_sdio.dma_blocks[i * 2 + 1].write_addr = &g_sdio.received_checksums[i]; g_sdio.dma_blocks[i * 2 + 1].transfer_count = 2; @@ -419,7 +420,7 @@ sdio_status_t rp2040_sdio_rx_start(uint8_t *buffer, uint32_t num_blocks) pio_sm_set_consecutive_pindirs(SDIO_PIO, SDIO_DATA_SM, SDIO_D0, 4, false); // Write number of nibbles to receive to Y register - pio_sm_put(SDIO_PIO, SDIO_DATA_SM, SDIO_BLOCK_SIZE * 2 + 16 - 1); + pio_sm_put(SDIO_PIO, SDIO_DATA_SM, block_size * 2 + 16 - 1); pio_sm_exec(SDIO_PIO, SDIO_DATA_SM, pio_encode_out(pio_y, 32)); // Enable RX FIFO join because we don't need the TX FIFO during transfer. @@ -749,6 +750,34 @@ sdio_status_t rp2040_sdio_stop() return SDIO_OK; } +/******************************************************* + * Status Register Receiver + *******************************************************/ +sdio_status_t receive_status_register(uint8_t* sds) { + rp2040_sdio_rx_start(sds, 1, 64); + // Wait for the DMA operation to complete, or fail if it took too long +waitagain: + while (dma_channel_is_busy(SDIO_DMA_CHB) || dma_channel_is_busy(SDIO_DMA_CH)) + { + if ((uint32_t)(millis() - g_sdio.transfer_start_time) > 2) + { + // Reset the state machine program + dma_channel_abort(SDIO_DMA_CHB); + pio_sm_set_enabled(SDIO_PIO, SDIO_CMD_SM, false); + pio_sm_clear_fifos(SDIO_PIO, SDIO_CMD_SM); + return SDIO_ERR_RESPONSE_TIMEOUT; + } + } + // Assert that both DMA channels are complete + if(dma_channel_is_busy(SDIO_DMA_CHB) || dma_channel_is_busy(SDIO_DMA_CH)) { + // Wait failure, go back. + goto waitagain; + } + pio_sm_set_enabled(SDIO_PIO, SDIO_DATA_SM, false); + g_sdio.transfer_state = SDIO_IDLE; + return SDIO_OK; +} + void rp2040_sdio_init(int clock_divider) { // Mark resources as being in use, unless it has been done already. diff --git a/lib/ZuluIDE_platform_RP2040/rp2040_sdio.h b/lib/ZuluIDE_platform_RP2040/rp2040_sdio.h index cc5c423..b42dfea 100644 --- a/lib/ZuluIDE_platform_RP2040/rp2040_sdio.h +++ b/lib/ZuluIDE_platform_RP2040/rp2040_sdio.h @@ -54,7 +54,7 @@ sdio_status_t rp2040_sdio_command_R3(uint8_t command, uint32_t arg, uint32_t *re // Start transferring data from SD card to memory buffer // Transfer block size is always 512 bytes. -sdio_status_t rp2040_sdio_rx_start(uint8_t *buffer, uint32_t num_blocks); +sdio_status_t rp2040_sdio_rx_start(uint8_t *buffer, uint32_t num_blocks, uint32_t block_size = SDIO_BLOCK_SIZE); // Check if reception is complete // Returns SDIO_BUSY while transferring, SDIO_OK when done and error on failure. @@ -69,5 +69,8 @@ sdio_status_t rp2040_sdio_tx_poll(uint32_t *bytes_complete = nullptr); // Force everything to idle state sdio_status_t rp2040_sdio_stop(); +// Receives the SD Status register. Does not return until the register has been received. +sdio_status_t receive_status_register(uint8_t* sds); + // (Re)initialize the SDIO interface void rp2040_sdio_init(int clock_divider = 1); diff --git a/lib/ZuluIDE_platform_RP2040/sd_card_sdio.cpp b/lib/ZuluIDE_platform_RP2040/sd_card_sdio.cpp index 7a3a6a4..73fe88d 100644 --- a/lib/ZuluIDE_platform_RP2040/sd_card_sdio.cpp +++ b/lib/ZuluIDE_platform_RP2040/sd_card_sdio.cpp @@ -1,5 +1,6 @@ /** - * ZuluIDE™ - Copyright (c) 2023 Rabbit Hole Computing™ + * ZuluIDE™ - Copyright (c) 2023-2024 Rabbit Hole Computing™ + * Copyright (c) 2024 Tech by Androda, LLC * * ZuluIDE™ firmware is licensed under the GPL version 3 or any later version.  * @@ -35,6 +36,7 @@ static uint32_t g_sdio_ocr; // Operating condition register from card static uint32_t g_sdio_rca; // Relative card address static cid_t g_sdio_cid; static csd_t g_sdio_csd; +static sds_t __attribute__((aligned(4))) g_sdio_sds; static int g_sdio_error_line; static sdio_status_t g_sdio_error; static uint32_t g_sdio_dma_buf[128]; @@ -167,6 +169,17 @@ bool SdioCard::begin(SdioConfig sdioConfig) return false; } + // Read SD Status field + memset(&g_sdio_sds, 0, sizeof(sds_t)); + uint8_t* stat_pointer = (uint8_t*) &g_sdio_sds; + if (!checkReturnOk(rp2040_sdio_command_R1(CMD55, g_sdio_rca, &reply)) || + !checkReturnOk(rp2040_sdio_command_R1(ACMD13, 0, &reply)) || + !checkReturnOk(receive_status_register(stat_pointer))) + { + dbgmsg("SDIO failed to get SD Status"); + return false; + } + // Increase to 25 MHz clock rate rp2040_sdio_init(1); @@ -210,6 +223,12 @@ bool SdioCard::readCSD(csd_t* csd) return true; } +bool SdioCard::readSDS(sds_t* sds) +{ + *sds = g_sdio_sds; + return true; +} + bool SdioCard::readOCR(uint32_t* ocr) { // SDIO mode does not have CMD58, but main program uses this to diff --git a/platformio.ini b/platformio.ini index a74cfb2..8fdbfa3 100644 --- a/platformio.ini +++ b/platformio.ini @@ -12,7 +12,7 @@ extra_scripts = src/build_bootloader.py board_build.ldscript = lib/ZuluIDE_platform_RP2040/rp2040.ld ldscript_bootloader = lib/ZuluIDE_platform_RP2040/rp2040_btldr.ld lib_deps = - SdFat=https://github.com/rabbitholecomputing/SdFat#2.2.0-gpt + SdFat=https://github.com/rabbitholecomputing/SdFat#2.2.3-gpt minIni ZuluControl CUEParser=https://github.com/rabbitholecomputing/CUEParser diff --git a/src/ZuluIDE.cpp b/src/ZuluIDE.cpp index 7445b75..676b2fc 100644 --- a/src/ZuluIDE.cpp +++ b/src/ZuluIDE.cpp @@ -66,6 +66,8 @@ void status_observer(const zuluide::status::SystemStatus& current); void loadFirstImage(); void load_image(const zuluide::images::Image& toLoad, bool insert = true); +#define SD_SPEED_CLASS_WARN_BELOW 10 + /************************************/ /* Status reporting by blinking led */ /************************************/ @@ -172,6 +174,13 @@ void print_sd_info() logmsg("SD Date: ", (int)sd_cid.mdtMonth(), "/", sd_cid.mdtYear()); logmsg("SD Serial: ", sd_cid.psn()); } + + sds_t sds = {0}; + SD.card()->readSDS(&sds); + if ( sds.speedClass() < SD_SPEED_CLASS_WARN_BELOW) + { + logmsg("WARNING: Your SD Card Speed Class is ", (int)sds.speedClass(), ". Class ", (int) SD_SPEED_CLASS_WARN_BELOW," or better is recommended for best performance."); + } } diff --git a/src/ZuluIDE_config.h b/src/ZuluIDE_config.h index 0c004f7..3da5073 100644 --- a/src/ZuluIDE_config.h +++ b/src/ZuluIDE_config.h @@ -27,7 +27,7 @@ #include // Use variables for version number -#define FW_VER_NUM "2024.09.17" +#define FW_VER_NUM "2024.10.04" #define FW_VER_SUFFIX "devel" #define ZULU_FW_VERSION FW_VER_NUM "-" FW_VER_SUFFIX diff --git a/src/ide_imagefile.cpp b/src/ide_imagefile.cpp index 0f28264..1b4a2f4 100644 --- a/src/ide_imagefile.cpp +++ b/src/ide_imagefile.cpp @@ -259,7 +259,6 @@ bool IDEImageFile::write(uint64_t startpos, size_t blocksize, size_t num_blocks, sd_cb_state.blocks_available = 0; sd_cb_state.bufsize_blocks = m_buffer_size / blocksize; - bool first_run = true; while (sd_cb_state.blocks_done < num_blocks && !sd_cb_state.error) { platform_poll(); diff --git a/src/ide_rigid.cpp b/src/ide_rigid.cpp index 4c9eb86..79956a6 100644 --- a/src/ide_rigid.cpp +++ b/src/ide_rigid.cpp @@ -28,18 +28,6 @@ extern uint8_t g_ide_signals; static uint8_t ide_disk_buffer[512]; -// Map from command index for command name for logging -static const char *get_atapi_command_name(uint8_t cmd) -{ - switch (cmd) - { -#define CMD_NAME_TO_STR(name, code) case code: return #name; - ATAPI_COMMAND_LIST(CMD_NAME_TO_STR) -#undef CMD_NAME_TO_STR - default: return "UNKNOWN_CMD"; - } -} - static bool find_chs_capacity(uint64_t lba, uint16_t max_cylinders, uint8_t min_heads, uint16_t &c, uint8_t &h, uint8_t &s) { bool found_chs = false;