From: Michael McMaster Date: Thu, 16 Jun 2016 11:21:00 +0000 (+1000) Subject: SD hotswap, SD fixes, SCSI interface fixes, performance improvements. X-Git-Tag: v6.0BETA2^0 X-Git-Url: http://git.codesrc.com/gitweb.cgi?a=commitdiff_plain;h=d33b3ceb7298cbd90ac680ef9dbfd604bd71d11b;p=SCSI2SD-V6.git SD hotswap, SD fixes, SCSI interface fixes, performance improvements. --- diff --git a/CHANGELOG b/CHANGELOG index 28485201..03414da6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,2 +1,8 @@ +20160616 6.01 + - Improved SD card compatibility + - Fixed SCSI interfaces on slower SCSI controllers + - Significant performance improvements + - Added SD card hotswap support. + 20160528 6.0 - First BETA firmware for the 6.0 hardware version of the SCSI2SD. diff --git a/STM32CubeMX/SCSI2SD-V6/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_sd.c b/STM32CubeMX/SCSI2SD-V6/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_sd.c index 399b7de6..418163e4 100755 --- a/STM32CubeMX/SCSI2SD-V6/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_sd.c +++ b/STM32CubeMX/SCSI2SD-V6/Drivers/STM32F2xx_HAL_Driver/Src/stm32f2xx_hal_sd.c @@ -178,7 +178,6 @@ /* Includes ------------------------------------------------------------------*/ #include "stm32f2xx_hal.h" - #ifdef HAL_SD_MODULE_ENABLED /** @addtogroup STM32F2xx_HAL_Driver diff --git a/STM32CubeMX/SCSI2SD-V6/Src/sdio.c b/STM32CubeMX/SCSI2SD-V6/Src/sdio.c index 49b4de96..d1bb9dca 100755 --- a/STM32CubeMX/SCSI2SD-V6/Src/sdio.c +++ b/STM32CubeMX/SCSI2SD-V6/Src/sdio.c @@ -84,14 +84,16 @@ void HAL_SD_MspInit(SD_HandleTypeDef* hsd) GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 |GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + //GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; // MM GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; GPIO_InitStruct.Alternate = GPIO_AF12_SDIO; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; + //GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pull = GPIO_PULLUP; // MM GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; GPIO_InitStruct.Alternate = GPIO_AF12_SDIO; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); diff --git a/doc/SCSI2SD_QuickStartGuide.odt b/doc/SCSI2SD_QuickStartGuide.odt index 61b1bba2..9dbcb0ff 100644 Binary files a/doc/SCSI2SD_QuickStartGuide.odt and b/doc/SCSI2SD_QuickStartGuide.odt differ diff --git a/include/scsi2sd.h b/include/scsi2sd.h index cee3be07..a59fd38d 100755 --- a/include/scsi2sd.h +++ b/include/scsi2sd.h @@ -192,7 +192,12 @@ typedef enum // uint32_t Sector Number (MSB) // Response: // 512 bytes of data - S2S_CMD_SD_READ + S2S_CMD_SD_READ, + + // Command content: + // uint8_t S2S_CFG_DEBUG + // Response: + S2S_CMD_DEBUG, } S2S_COMMAND; typedef enum diff --git a/rtl/fpga_bitmap.o b/rtl/fpga_bitmap.o index 55c02c0e..16130841 100644 Binary files a/rtl/fpga_bitmap.o and b/rtl/fpga_bitmap.o differ diff --git a/src/firmware/config.c b/src/firmware/config.c index 1015ae34..a19087d8 100755 --- a/src/firmware/config.c +++ b/src/firmware/config.c @@ -38,7 +38,7 @@ #include -static const uint16_t FIRMWARE_VERSION = 0x0600; +static const uint16_t FIRMWARE_VERSION = 0x0601; // 1 flash row static const uint8_t DEFAULT_CONFIG[128] = @@ -68,19 +68,6 @@ static int usbDebugEpState; #endif static int usbReady; // TODO MM REMOVE. Unused ? -static void initS2S_BoardCfg(S2S_BoardCfg* config) { - if (memcmp(config->magic, "BCFG", 4)) { - config->selectionDelay = 255; // auto - config->flags6 = S2S_CFG_ENABLE_TERMINATOR; - - memcpy( - s2s_cfg + sizeof(S2S_BoardCfg), - DEFAULT_CONFIG, - sizeof(S2S_TargetCfg)); - } -} - - void s2s_configInit(S2S_BoardCfg* config) { @@ -88,7 +75,7 @@ void s2s_configInit(S2S_BoardCfg* config) usbReady = 0; // We don't know if host is connected yet. - if (blockDev.state & DISK_PRESENT && sdDev.capacity) + if ((blockDev.state & DISK_PRESENT) && sdDev.capacity) { int cfgSectors = (S2S_CFG_SIZE + 511) / 512; BSP_SD_ReadBlocks_DMA( @@ -98,11 +85,35 @@ void s2s_configInit(S2S_BoardCfg* config) cfgSectors); memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg)); - } - initS2S_BoardCfg(config); + if (memcmp(config->magic, "BCFG", 4)) + { + // Invalid SD card config, use default. + memset(&s2s_cfg[0], 0, S2S_CFG_SIZE); + memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg)); + memcpy(config->magic, "BCFG", 4); + config->selectionDelay = 255; // auto + config->flags6 = S2S_CFG_ENABLE_TERMINATOR; + + memcpy( + &s2s_cfg[0] + sizeof(S2S_BoardCfg), + DEFAULT_CONFIG, + sizeof(S2S_TargetCfg)); + } + } + else + { + // No SD card, use existing config if valid + if (memcmp(config->magic, "BCFG", 4)) + { + // Not valid, use empty config with no disks. + memset(&s2s_cfg[0], 0, S2S_CFG_SIZE); + memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg)); + config->selectionDelay = 255; // auto + config->flags6 = S2S_CFG_ENABLE_TERMINATOR; + } + } - scsiPhyConfig(); } @@ -154,6 +165,32 @@ scsiDevInfoCommand() hidPacket_send(response, sizeof(response)); } +static void +debugCommand() +{ + uint8_t response[32]; + memcpy(&response, &scsiDev.cdb, 12); + response[12] = scsiDev.msgIn; + response[13] = scsiDev.msgOut; + response[14] = scsiDev.lastStatus; + response[15] = scsiDev.lastSense; + response[16] = scsiDev.phase; + response[17] = scsiStatusBSY(); + response[18] = *SCSI_STS_SELECTED; + response[19] = scsiStatusATN(); + response[20] = scsiStatusRST(); + response[21] = scsiDev.rstCount; + response[22] = scsiDev.selCount; + response[23] = scsiDev.msgCount; + response[24] = scsiDev.cmdCount; + response[25] = scsiDev.watchdogTick; + response[26] = blockDev.state; + response[27] = scsiDev.lastSenseASC >> 8; + response[28] = scsiDev.lastSenseASC; + response[29] = *SCSI_STS_DBX; + response[30] = LastTrace; + hidPacket_send(response, sizeof(response)); +} static void sdWriteCommand(const uint8_t* cmd, size_t cmdSize) @@ -230,6 +267,10 @@ processCommand(const uint8_t* cmd, size_t cmdSize) sdReadCommand(cmd, cmdSize); break; + case S2S_CMD_DEBUG: + debugCommand(); + break; + case S2S_CMD_NONE: // invalid default: break; diff --git a/src/firmware/disk.c b/src/firmware/disk.c index 886bfe25..d4c826b7 100755 --- a/src/firmware/disk.c +++ b/src/firmware/disk.c @@ -35,12 +35,7 @@ static int doSdInit() int result = 0; if (blockDev.state & DISK_PRESENT) { - result = sdInit(); - - if (result) - { - blockDev.state = blockDev.state | DISK_INITIALISED; - } + blockDev.state = blockDev.state | DISK_INITIALISED; } return result; } @@ -628,7 +623,6 @@ void scsiDiskPoll() scsiWriteDMA(&scsiDev.data[SD_SECTOR_SIZE * (i % buffers)], dmaBytes); scsiActive = 1; } - } // We've finished transferring the data to the FPGA, now wait until it's @@ -656,6 +650,11 @@ void scsiDiskPoll() const int sdPerScsi = SDSectorsPerSCSISector(bytesPerSector); int totalSDSectors = transfer.blocks * sdPerScsi; + uint32_t sdLBA = + SCSISector2SD( + scsiDev.target->cfg->sdSectorStart, + bytesPerSector, + transfer.lba); // int buffers = sizeof(scsiDev.data) / SD_SECTOR_SIZE; // int prep = 0; int i = 0; @@ -677,7 +676,7 @@ void scsiDiskPoll() uint32_t sectors = totalSDSectors < maxSectors ? totalSDSectors : maxSectors; scsiRead(&scsiDev.data[0], sectors * SD_SECTOR_SIZE); - sdTmpWrite(&scsiDev.data[0], i + transfer.lba, sectors); + sdTmpWrite(&scsiDev.data[0], i + sdLBA, sectors); i += sectors; #if 0 // Wait for the next DMA interrupt. It's beneficial to halt the @@ -863,13 +862,5 @@ void scsiDiskInit() // Don't require the host to send us a START STOP UNIT command blockDev.state = DISK_STARTED; - // WP pin not available for micro-sd - // TODO read card WP register - #if 0 - if (SD_WP_Read()) - { - blockDev.state = blockDev.state | DISK_WP; - } - #endif } diff --git a/src/firmware/main.c b/src/firmware/main.c index 04d2c3b0..a2317626 100755 --- a/src/firmware/main.c +++ b/src/firmware/main.c @@ -32,6 +32,7 @@ const char* Notice = "Copyright (C) 2016 Michael McMaster "; +uint32_t lastSDPoll; void mainEarlyInit() { @@ -51,10 +52,11 @@ void mainInit() scsiDiskInit(); sdInit(); s2s_configInit(&scsiDev.boardCfg); + scsiPhyConfig(); + scsiInit(); s2s_debugInit(); - scsiInit(); MX_USB_DEVICE_Init(); // USB lun config now available. @@ -72,10 +74,7 @@ void mainInit() ++delaySeconds; } -#if 0 - uint32_t lastSDPoll = getTime_ms(); - sdCheckPresent(); -#endif + lastSDPoll = s2s_getTime_ms(); } void mainLoop() @@ -89,16 +88,28 @@ void mainLoop() #if 0 sdPoll(); +#endif if (unlikely(scsiDev.phase == BUS_FREE)) { - if (unlikely(elapsedTime_ms(lastSDPoll) > 200)) + if (unlikely(s2s_elapsedTime_ms(lastSDPoll) > 200)) { - lastSDPoll = getTime_ms(); - sdCheckPresent(); + lastSDPoll = s2s_getTime_ms(); + if (sdInit()) + { + s2s_configInit(&scsiDev.boardCfg); + scsiPhyConfig(); + scsiInit(); + + + USBD_Stop(&hUsbDeviceFS); + s2s_delay_ms(128); + USBD_Start(&hUsbDeviceFS); + } } else { +#if 0 // Wait for our 1ms timer to save some power. // There's an interrupt on the SEL signal to ensure we respond // quickly to any SCSI commands. The selection abort time is @@ -110,13 +121,13 @@ void mainLoop() __WFI(); // Will wake on interrupt, regardless of mask } CyExitCriticalSection(interruptState); +#endif } } else if (scsiDev.phase >= 0) { // don't waste time scanning SD cards while we're doing disk IO - lastSDPoll = getTime_ms(); + lastSDPoll = s2s_getTime_ms(); } -#endif } diff --git a/src/firmware/scsi.c b/src/firmware/scsi.c index 297a1bd8..c4b53a57 100755 --- a/src/firmware/scsi.c +++ b/src/firmware/scsi.c @@ -70,6 +70,7 @@ static void enter_BusFree() // Bus settle delay + bus clear delay = 1200ns s2s_delay_us(2); + s2s_ledOff(); scsiDev.phase = BUS_FREE; } @@ -459,7 +460,6 @@ static void scsiReset() s2s_ledOff(); scsiPhyReset(); - // TODO SCSI_Out_Ctl_Write(0); scsiDev.parityError = 0; scsiDev.phase = BUS_FREE; @@ -896,6 +896,8 @@ void scsiPoll(void) void scsiInit() { + static int firstInit = 1; + scsiDev.atnFlag = 0; scsiDev.resetFlag = 1; scsiDev.phase = BUS_FREE; @@ -920,10 +922,18 @@ void scsiInit() } scsiDev.targets[i].reservedId = -1; scsiDev.targets[i].reserverId = -1; - scsiDev.targets[i].unitAttention = POWER_ON_RESET; + if (firstInit) + { + scsiDev.targets[i].unitAttention = POWER_ON_RESET; + } + else + { + scsiDev.targets[i].unitAttention = PARAMETERS_CHANGED; + } scsiDev.targets[i].sense.code = NO_SENSE; scsiDev.targets[i].sense.asc = NO_ADDITIONAL_SENSE_INFORMATION; } + firstInit = 0; } /* TODO REENABLE diff --git a/src/firmware/scsiPhy.c b/src/firmware/scsiPhy.c index bdaef589..1a8a6aea 100755 --- a/src/firmware/scsiPhy.c +++ b/src/firmware/scsiPhy.c @@ -26,6 +26,8 @@ #include "fpga.h" #include "led.h" +#include + // Private DMA variables. static int dmaInProgress = 0; @@ -133,7 +135,7 @@ scsiReadDMA(uint8_t* data, uint32_t count) scsiTxDMAComplete = 1; // TODO not used much scsiRxDMAComplete = 0; // TODO not used much - HAL_DMA_Start(&fsmcToMem, (uint32_t) SCSI_FIFO_DATA, (uint32_t) data, count); // TODO MM count/4 for tx + HAL_DMA_Start(&fsmcToMem, (uint32_t) SCSI_FIFO_DATA, (uint32_t) data, count); } int @@ -424,6 +426,61 @@ void scsiPhyReset() } #endif + // FPGA comms test code + #ifdef FPGA_TEST + + while(1) + { + for (int j = 0; j < SCSI_FIFO_DEPTH; ++j) + { + scsiDev.data[j] = j; + } + + *SCSI_CTRL_PHASE = DATA_IN; + HAL_DMA_Start( + &memToFSMC, + (uint32_t) &scsiDev.data[0], + (uint32_t) SCSI_FIFO_DATA, + SCSI_FIFO_DEPTH / 4); + + HAL_DMA_PollForTransfer( + &memToFSMC, + HAL_DMA_FULL_TRANSFER, + 0xffffffff); + + memset(&scsiDev.data[0], 0, SCSI_FIFO_DEPTH); + + *SCSI_CTRL_PHASE = DATA_OUT; + HAL_DMA_Start( + &fsmcToMem, + (uint32_t) SCSI_FIFO_DATA, + (uint32_t) &scsiDev.data[0], + SCSI_FIFO_DEPTH); + + HAL_DMA_PollForTransfer( + &fsmcToMem, + HAL_DMA_FULL_TRANSFER, + 0xffffffff); + + for (int j = 0; j < SCSI_FIFO_DEPTH; ++j) + { + if (scsiDev.data[j] != (uint8_t) j) + { + while (1) + { + s2s_ledOn(); + s2s_delay_ms(100); + s2s_ledOff(); + s2s_delay_ms(100); + } + } + } + + s2s_fpgaReset(); + + } + #endif + } static void scsiPhyInitDMA() diff --git a/src/firmware/scsiPhy.h b/src/firmware/scsiPhy.h index dff2f345..6c72e415 100755 --- a/src/firmware/scsiPhy.h +++ b/src/firmware/scsiPhy.h @@ -30,13 +30,14 @@ #define SCSI_STS_FIFO_COMPLETE ((volatile uint8_t*)0x60000012) #define SCSI_STS_SELECTED ((volatile uint8_t*)0x60000013) #define SCSI_STS_SCSI ((volatile uint8_t*)0x60000014) +#define SCSI_STS_DBX ((volatile uint8_t*)0x60000015) #define SCSI_FIFO_DATA ((volatile uint8_t*)0x60000020) #define SCSI_FIFO_DEPTH 512 -#define scsiPhyFifoFull() ((*SCSI_STS_FIFO & 0x02) == 0x02) -#define scsiPhyFifoEmpty() ((*SCSI_STS_FIFO & 0x01) == 0x01) +#define scsiPhyFifoFull() ((*SCSI_STS_FIFO & 0x01) == 0x01) +#define scsiPhyFifoEmpty() ((*SCSI_STS_FIFO & 0x02) == 0x02) #define scsiPhyFifoFlip() \ {\ @@ -44,9 +45,6 @@ *SCSI_FIFO_SEL = scsiPhyFifoSel; \ } -// Clear 4 byte fifo -#define scsiPhyFifoClear() (void) scsiPhyRx(); (void) scsiPhyRx(); (void) scsiPhyRx(); (void) scsiPhyRx(); - #define scsiPhyTx(val) *SCSI_FIFO_DATA = (val) #define scsiPhyRx() *SCSI_FIFO_DATA #define scsiPhyComplete() ((*SCSI_STS_FIFO_COMPLETE & 0x01) == 0x01) diff --git a/src/firmware/sd.c b/src/firmware/sd.c index 08d6a195..8f0d5034 100755 --- a/src/firmware/sd.c +++ b/src/firmware/sd.c @@ -787,35 +787,12 @@ static void sdInitDMA() { init = 1; - //TODO MM SEE STUPID SD_DMA_RxCplt that require the SD IRQs to preempt -// Configured with 4 bits preemption, NO sub priority. - HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 8, 0); - HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn); - HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 8, 0); - HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn); -#if 0 - sdDMATxChan = - SD_TX_DMA_DmaInitialize( - 2, // Bytes per burst - 1, // request per burst - HI16(CYDEV_SRAM_BASE), - HI16(CYDEV_PERIPH_BASE) - ); - - sdDMARxChan = - SD_RX_DMA_DmaInitialize( - 1, // Bytes per burst - 1, // request per burst - HI16(CYDEV_PERIPH_BASE), - HI16(CYDEV_SRAM_BASE) - ); - - CyDmaChDisable(sdDMATxChan); - CyDmaChDisable(sdDMARxChan); - - SD_RX_DMA_COMPLETE_StartEx(sdRxISR); - SD_TX_DMA_COMPLETE_StartEx(sdTxISR); -#endif + //TODO MM SEE STUPID SD_DMA_RxCplt that require the SD IRQs to preempt + // Configured with 4 bits preemption, NO sub priority. + HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 8, 0); + HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn); + HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 8, 0); + HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn); } } @@ -829,97 +806,24 @@ void sdTmpWrite(uint8_t* data, uint32_t lba, int sectors) BSP_SD_WriteBlocks_DMA((uint32_t*) data, lba * 512ll, 512, sectors); } -int sdInit() +static void sdClear() { - int result = 0; - //int i; - - // TODO sdCmdState = CMD_STATE_IDLE; sdDev.version = 0; sdDev.ccs = 0; sdDev.capacity = 0; memset(sdDev.csd, 0, sizeof(sdDev.csd)); memset(sdDev.cid, 0, sizeof(sdDev.cid)); +} -// TODO should be in POLL method! - - sdInitDMA(); -#if 0 - - SD_CS_SetDriveMode(SD_CS_DM_STRONG); - SD_CS_Write(1); // Set CS inactive (active low) - - // Set the SPI clock for 400kHz transfers - // 25MHz / 400kHz approx factor of 63. - // The register contains (divider - 1) - uint16_t clkDiv25MHz = SD_Data_Clk_GetDividerRegister(); - SD_Data_Clk_SetDivider(((clkDiv25MHz + 1) * 63) - 1); - // Wait for the clock to settle. - CyDelayUs(1); - - SDCard_Start(); // Enable SPI hardware - - // Power on sequence. 74 clock cycles of a "1" while CS unasserted. - for (i = 0; i < 10; ++i) - { - sdSpiByte(0xFF); - } - - SD_CS_Write(0); // Set CS active (active low) - CyDelayUs(1); - - sdSpiByte(0xFF); - v = sdDoCommand(SD_GO_IDLE_STATE, 0, 1, 0); - if(v != 1){goto bad;} - - ledOn(); - if (!sendIfCond()) goto bad; // Sets V1 or V2 flag CMD8 - if (!sdOpCond()) goto bad; // ACMD41. Wait for init completes. - if (!sdReadOCR()) goto bad; // CMD58. Get CCS flag. Only valid after init. - - // This command will be ignored if sdDev.ccs is set. - // SDHC and SDXC are always 512bytes. - v = sdCRCCommandAndResponse(SD_SET_BLOCKLEN, SD_SECTOR_SIZE); //Force sector size - if(v){goto bad;} - v = sdCRCCommandAndResponse(SD_CRC_ON_OFF, 0); //crc off - if(v){goto bad;} - - // now set the sd card back to full speed. - // The SD Card spec says we can run SPI @ 25MHz - SDCard_Stop(); - - // We can't run at full-speed with the pullup resistors enabled. - SD_MISO_SetDriveMode(SD_MISO_DM_DIG_HIZ); - SD_MOSI_SetDriveMode(SD_MOSI_DM_STRONG); - SD_SCK_SetDriveMode(SD_SCK_DM_STRONG); - - SD_Data_Clk_SetDivider(clkDiv25MHz); - CyDelayUs(1); - SDCard_Start(); - - // Clear out rubbish data through clock change - CyDelayUs(1); - SDCard_ReadRxStatus(); - SDCard_ReadTxStatus(); - SDCard_ClearFIFO(); - - if (!sdReadCSD()) goto bad; - sdReadCID(); - - result = 1; - goto out; +static int sdDoInit() +{ + int result = 0; -bad: - SD_Data_Clk_SetDivider(clkDiv25MHz); // Restore the clock for our next retry - sdDev.capacity = 0; + // TODO sdCmdState = CMD_STATE_IDLE; + sdClear(); -out: - sdClearStatus(); - ledOff(); - return result; -#endif - uint8_t error = BSP_SD_Init(); + int8_t error = BSP_SD_Init(); if (error == MSD_OK) { memcpy(sdDev.csd, &SDCardInfo.SD_csd, sizeof(sdDev.csd)); @@ -1019,37 +923,54 @@ void sdPoll() } } -void sdCheckPresent() +#endif +int sdInit() { // Check if there's an SD card present. + int result = 0; + +#if 0 if ((scsiDev.phase == BUS_FREE) && (sdIOState == SD_IDLE) && (sdCmdState == CMD_STATE_IDLE)) +#endif + static int firstInit = 1; + + if (firstInit) { - // The CS line is pulled high by the SD card. - // De-assert the line, and check if it's high. - // This isn't foolproof as it'll be left floating without - // an SD card. We can't use the built-in pull-down resistor as it will - // overpower the SD pullup resistor. - SD_CS_Write(0); - SD_CS_SetDriveMode(SD_CS_DM_DIG_HIZ); - - // Delay extended to work with 60cm cables running cards at 2.85V - CyDelayCycles(128); - uint8_t cs = SD_CS_Read(); - SD_CS_SetDriveMode(SD_CS_DM_STRONG) ; + blockDev.state &= ~(DISK_PRESENT | DISK_INITIALISED); + sdClear(); + sdInitDMA(); + } + + if (scsiDev.phase == BUS_FREE) + { + uint8_t cs = HAL_GPIO_ReadPin(nSD_CD_GPIO_Port, nSD_CD_Pin) ? 0 : 1; + uint8_t wp = HAL_GPIO_ReadPin(nSD_WP_GPIO_Port, nSD_WP_Pin) ? 0 : 1; if (cs && !(blockDev.state & DISK_PRESENT)) { - static int firstInit = 1; + s2s_ledOn(); // Debounce - CyDelay(250); + if (!firstInit) + { + s2s_delay_ms(250); + } - if (sdInit()) + if (sdDoInit()) { blockDev.state |= DISK_PRESENT | DISK_INITIALISED; + if (wp) + { + blockDev.state |= DISK_WP; + } + else + { + blockDev.state &= ~DISK_WP; + } + // Always "start" the device. Many systems (eg. Apple System 7) // won't respond properly to // LOGICAL_UNIT_NOT_READY_INITIALIZING_COMMAND_REQUIRED sense @@ -1057,15 +978,21 @@ void sdCheckPresent() // START STOP UNIT command. blockDev.state |= DISK_STARTED; - if (!firstInit) + result = 1; + + s2s_ledOff(); + } + else + { + for (int i = 0; i < 10; ++i) { - int i; - for (i = 0; i < MAX_SCSI_TARGETS; ++i) - { - scsiDev.targets[i].unitAttention = PARAMETERS_CHANGED; - } + // visual indicator of SD error + s2s_ledOff(); + s2s_delay_ms(50); + s2s_ledOn(); + s2s_delay_ms(50); } - firstInit = 0; + s2s_ledOff(); } } else if (!cs && (blockDev.state & DISK_PRESENT)) @@ -1074,12 +1001,16 @@ void sdCheckPresent() blockDev.state &= ~DISK_PRESENT; blockDev.state &= ~DISK_INITIALISED; int i; - for (i = 0; i < MAX_SCSI_TARGETS; ++i) + for (i = 0; i < S2S_MAX_TARGETS; ++i) { scsiDev.targets[i].unitAttention = PARAMETERS_CHANGED; } + + HAL_SD_DeInit(&hsd); } } + firstInit = 0; + + return result; } -#endif diff --git a/src/firmware/sd.h b/src/firmware/sd.h index 878d9f06..bb8c0574 100755 --- a/src/firmware/sd.h +++ b/src/firmware/sd.h @@ -82,7 +82,6 @@ void sdReadSingleSectorDMA(uint32_t lba, uint8_t* outputBuffer); int sdReadSectorDMAPoll(); void sdCompleteTransfer(void); -void sdCheckPresent(); void sdPoll(); #endif diff --git a/src/firmware/usb_device/usbd_msc_storage_sd.c b/src/firmware/usb_device/usbd_msc_storage_sd.c index db6e411b..3cb44873 100755 --- a/src/firmware/usb_device/usbd_msc_storage_sd.c +++ b/src/firmware/usb_device/usbd_msc_storage_sd.c @@ -20,6 +20,7 @@ #include "stm32f2xx.h" #include "bsp_driver_sd.h" #include "../bsp.h" +#include "../disk.h" #include "../led.h" #include "../sd.h" #include "../config.h" @@ -114,15 +115,20 @@ uint32_t s2s_usbd_storage_Inquiry (uint8_t lun, uint8_t* buf, uint8_t maxlen) return s2s_getStandardInquiry(cfg, buf, maxlen); } -int8_t s2s_usbd_storage_IsReady (uint8_t lun) +int8_t s2s_usbd_storage_IsReady (uint8_t lun) { - return (0); + const S2S_TargetCfg* cfg = getUsbConfig(lun); + return ( + cfg && + (blockDev.state & DISK_PRESENT) && + (blockDev.state & DISK_INITIALISED) + ) ? 0 : 1; // inverse logic } int8_t s2s_usbd_storage_IsWriteProtected (uint8_t lun) { - return 0; + return blockDev.state & DISK_WP; } int8_t s2s_usbd_storage_Read (uint8_t lun,