From 33bb7859d446a42d699761f6b5c0a449b40a7d35 Mon Sep 17 00:00:00 2001 From: Bob Kuhn Date: Wed, 22 Apr 2020 15:00:10 -0500 Subject: [PATCH] Composite USB for STM32 SDIO (experimental) (#17222) --- .../src/HAL/STM32/Sd2Card_sdio_stm32duino.cpp | 405 +++++++++--------- .../src/pins/stm32f4/pins_STEVAL_3DP001V1.h | 1 + platformio.ini | 5 +- 3 files changed, 214 insertions(+), 197 deletions(-) diff --git a/Marlin/src/HAL/STM32/Sd2Card_sdio_stm32duino.cpp b/Marlin/src/HAL/STM32/Sd2Card_sdio_stm32duino.cpp index ebe15f939..3d8e56019 100644 --- a/Marlin/src/HAL/STM32/Sd2Card_sdio_stm32duino.cpp +++ b/Marlin/src/HAL/STM32/Sd2Card_sdio_stm32duino.cpp @@ -27,248 +27,263 @@ #include #include -//#include "SdMscDriver.h" - -//#include "usbd_msc_bot.h" -//#include "usbd_msc_scsi.h" -//#include "usbd_msc_composite.h" -//#include "usbd_msc_cdc_composite.h" - -//#include "usbd_msc_data.h" - -#if defined(STM32F103xE) || defined(STM32F103xG) - #include - #include -#elif defined(STM32F4xx) - #include - #include - #include - #include -#elif defined(STM32F7xx) - #include - #include - #include - #include -#else +#if NONE(STM32F103xE, STM32F103xG, STM32F4xx, STM32F7xx) #error "ERROR - Only STM32F103xE, STM32F103xG, STM32F4xx or STM32F7xx CPUs supported" #endif -SD_HandleTypeDef hsd; // create SDIO structure +#ifdef USBD_USE_CDC_COMPOSITE -#define TRANSFER_CLOCK_DIV ((uint8_t)SDIO_INIT_CLK_DIV/40) + // use USB drivers -#ifndef USBD_OK - #define USBD_OK 0 -#endif + extern "C" { int8_t SD_MSC_Read(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len); + int8_t SD_MSC_Write(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len); + extern SD_HandleTypeDef hsd; + } -void go_to_transfer_speed() { + bool SDIO_Init() { + if (hsd.State == HAL_SD_STATE_READY) return 1; // return passing status + return 0; // return failing status + } - SD_InitTypeDef Init; + bool SDIO_ReadBlock(uint32_t block, uint8_t *src) { + int8_t status = SD_MSC_Read(0, (uint8_t*)src, block, 1); // read one 512 byte block + return (bool) status; + } - /* Default SDIO peripheral configuration for SD card initialization */ - Init.ClockEdge = hsd.Init.ClockEdge; - Init.ClockBypass = hsd.Init.ClockBypass; - Init.ClockPowerSave = hsd.Init.ClockPowerSave; - Init.BusWide = hsd.Init.BusWide; - Init.HardwareFlowControl = hsd.Init.HardwareFlowControl; - Init.ClockDiv = TRANSFER_CLOCK_DIV; + bool SDIO_WriteBlock(uint32_t block, const uint8_t *src) { + int8_t status = SD_MSC_Write(0, (uint8_t*)src, block, 1); // write one 512 byte block + return (bool) status; + } - /* Initialize SDIO peripheral interface with default configuration */ - SDIO_Init(hsd.Instance, Init); -} +#else // !USBD_USE_CDC_COMPOSITE -void SD_LowLevel_Init(void) { + // use local drivers - uint32_t tempreg; + #if defined(STM32F103xE) || defined(STM32F103xG) + #include + #include + #elif defined(STM32F4xx) + #include + #include + #include + #include + #elif defined(STM32F7xx) + #include + #include + #include + #include + #else + #error "ERROR - Only STM32F103xE, STM32F103xG, STM32F4xx or STM32F7xx CPUs supported" + #endif - GPIO_InitTypeDef GPIO_InitStruct; + SD_HandleTypeDef hsd; // create SDIO structure - __HAL_RCC_GPIOC_CLK_ENABLE(); //enable GPIO clocks - __HAL_RCC_GPIOD_CLK_ENABLE(); //enable GPIO clocks + #define TRANSFER_CLOCK_DIV (uint8_t(SDIO_INIT_CLK_DIV) / 40) - GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_12; // D0 & SCK - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = 1; //GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF12_SDIO; - HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + #ifndef USBD_OK + #define USBD_OK 0 + #endif - #if defined(SDIO_D1_PIN) && defined(SDIO_D2_PIN) && defined(SDIO_D3_PIN) // define D1-D3 only if have a four bit wide SDIO bus - GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11; // D1-D3 + void go_to_transfer_speed() { + SD_InitTypeDef Init; + + /* Default SDIO peripheral configuration for SD card initialization */ + Init.ClockEdge = hsd.Init.ClockEdge; + Init.ClockBypass = hsd.Init.ClockBypass; + Init.ClockPowerSave = hsd.Init.ClockPowerSave; + Init.BusWide = hsd.Init.BusWide; + Init.HardwareFlowControl = hsd.Init.HardwareFlowControl; + Init.ClockDiv = TRANSFER_CLOCK_DIV; + + /* Initialize SDIO peripheral interface with default configuration */ + SDIO_Init(hsd.Instance, Init); + } + + void SD_LowLevel_Init(void) { + uint32_t tempreg; + + GPIO_InitTypeDef GPIO_InitStruct; + + __HAL_RCC_GPIOC_CLK_ENABLE(); //enable GPIO clocks + __HAL_RCC_GPIOD_CLK_ENABLE(); //enable GPIO clocks + + GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_12; // D0 & SCK GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = 1; //GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF12_SDIO; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); - #endif - // Configure PD.02 CMD line - GPIO_InitStruct.Pin = GPIO_PIN_2; - HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); + #if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3) // define D1-D3 only if have a four bit wide SDIO bus + GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11; // D1-D3 + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = 1; // GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF12_SDIO; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + #endif - RCC->APB2RSTR &= ~RCC_APB2RSTR_SDIORST_Msk; // take SDIO out of reset - RCC->APB2ENR |= RCC_APB2RSTR_SDIORST_Msk; // enable SDIO clock + // Configure PD.02 CMD line + GPIO_InitStruct.Pin = GPIO_PIN_2; + HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); - // Enable the DMA2 Clock + RCC->APB2RSTR &= ~RCC_APB2RSTR_SDIORST_Msk; // take SDIO out of reset + RCC->APB2ENR |= RCC_APB2RSTR_SDIORST_Msk; // enable SDIO clock - //Initialize the SDIO (with initial <400Khz Clock) - tempreg = 0; //Reset value - tempreg |= SDIO_CLKCR_CLKEN; //Clock is enabled - tempreg |= (uint32_t)0x76; //Clock Divider. Clock = 48000/(118+2) = 400Khz - //Keep the rest at 0 => HW_Flow Disabled, Rising Clock Edge, Disable CLK ByPass, Bus Width = 0, Power save Disable - SDIO->CLKCR = tempreg; + // Enable the DMA2 Clock - //Power up the SDIO - SDIO->POWER = 0x03; -} + //Initialize the SDIO (with initial <400Khz Clock) + tempreg = 0; //Reset value + tempreg |= SDIO_CLKCR_CLKEN; // Clock enabled + tempreg |= (uint32_t)0x76; // Clock Divider. Clock = 48000 / (118 + 2) = 400Khz + // Keep the rest at 0 => HW_Flow Disabled, Rising Clock Edge, Disable CLK ByPass, Bus Width = 0, Power save Disable + SDIO->CLKCR = tempreg; - -void HAL_SD_MspInit(SD_HandleTypeDef *hsd) { // application specific init - UNUSED(hsd); /* Prevent unused argument(s) compilation warning */ - __HAL_RCC_SDIO_CLK_ENABLE(); // turn on SDIO clock -} - -constexpr uint8_t SD_RETRY_COUNT = (1 - #if ENABLED(SD_CHECK_AND_RETRY) - + 2 - #endif -); - -bool SDIO_Init() { - //init SDIO and get SD card info - - uint8_t retryCnt = SD_RETRY_COUNT; - - bool status; - hsd.Instance = SDIO; - hsd.State = (HAL_SD_StateTypeDef) 0; // HAL_SD_STATE_RESET - SD_LowLevel_Init(); - - uint8_t retry_Cnt = retryCnt; - for (;;) { - status = (bool) HAL_SD_Init(&hsd); - if (!status) break; - if (!--retry_Cnt) return false; // return failing status if retries are exhausted + // Power up the SDIO + SDIO->POWER = 0x03; } - go_to_transfer_speed(); + void HAL_SD_MspInit(SD_HandleTypeDef *hsd) { // application specific init + UNUSED(hsd); /* Prevent unused argument(s) compilation warning */ + __HAL_RCC_SDIO_CLK_ENABLE(); // turn on SDIO clock + } - #if defined(SDIO_D1_PIN) && defined(SDIO_D2_PIN) && defined(SDIO_D3_PIN) // go to 4 bit wide mode if pins are defined - retry_Cnt = retryCnt; + constexpr uint8_t SD_RETRY_COUNT = 1 + 2 * ENABLED(SD_CHECK_AND_RETRY); + + bool SDIO_Init() { + //init SDIO and get SD card info + + uint8_t retryCnt = SD_RETRY_COUNT; + + bool status; + hsd.Instance = SDIO; + hsd.State = (HAL_SD_StateTypeDef) 0; // HAL_SD_STATE_RESET + SD_LowLevel_Init(); + + uint8_t retry_Cnt = retryCnt; for (;;) { - if (!HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B)) break; // some cards are only 1 bit wide so a pass here is not required - if (!--retry_Cnt) break; + status = (bool) HAL_SD_Init(&hsd); + if (!status) break; + if (!--retry_Cnt) return false; // return failing status if retries are exhausted } - if (!retry_Cnt) { // wide bus failed, go back to one bit wide mode - hsd.State = (HAL_SD_StateTypeDef) 0; // HAL_SD_STATE_RESET - SD_LowLevel_Init(); + + go_to_transfer_speed(); + + #if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3) // go to 4 bit wide mode if pins are defined retry_Cnt = retryCnt; for (;;) { - status = (bool) HAL_SD_Init(&hsd); - if (!status) break; - if (!--retry_Cnt) return false; // return failing status if retries are exhausted + if (!HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B)) break; // some cards are only 1 bit wide so a pass here is not required + if (!--retry_Cnt) break; } + if (!retry_Cnt) { // wide bus failed, go back to one bit wide mode + hsd.State = (HAL_SD_StateTypeDef) 0; // HAL_SD_STATE_RESET + SD_LowLevel_Init(); + retry_Cnt = retryCnt; + for (;;) { + status = (bool) HAL_SD_Init(&hsd); + if (!status) break; + if (!--retry_Cnt) return false; // return failing status if retries are exhausted + } + } + #endif + + return true; + } + + void init_SDIO_pins(void) { + GPIO_InitTypeDef GPIO_InitStruct = {0}; + + /**SDIO GPIO Configuration + PC8 ------> SDIO_D0 + PC12 ------> SDIO_CK + PD2 ------> SDIO_CMD + */ + GPIO_InitStruct.Pin = GPIO_PIN_8; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF12_SDIO; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = GPIO_PIN_12; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_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.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF12_SDIO; + HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); + } + + //bool SDIO_init() { return (bool) (SD_SDIO_Init() ? 1 : 0);} + //bool SDIO_Init_C() { return (bool) (SD_SDIO_Init() ? 1 : 0);} + + bool SDIO_ReadBlock(uint32_t block, uint8_t *dst) { + hsd.Instance = SDIO; + uint8_t retryCnt = SD_RETRY_COUNT; + + bool status; + for (;;) { + status = (bool) HAL_SD_ReadBlocks(&hsd, (uint8_t*)dst, block, 1, 1000); // read one 512 byte block with 500mS timeout + status |= (bool) HAL_SD_GetCardState(&hsd); // make sure all is OK + if (!status) break; // return passing status + if (!--retryCnt) break; // return failing status if retries are exhausted } - #endif + return status; - return true; -} + /* + return (bool) ((status_read | status_card) ? 1 : 0); -void init_SDIO_pins(void) { - GPIO_InitTypeDef GPIO_InitStruct = {0}; + if (SDIO_GetCardState() != SDIO_CARD_TRANSFER) return false; + if (blockAddress >= SdCard.LogBlockNbr) return false; + if ((0x03 & (uint32_t)data)) return false; // misaligned data - /**SDIO GPIO Configuration - PC8 ------> SDIO_D0 - PC12 ------> SDIO_CK - PD2 ------> SDIO_CMD - */ - GPIO_InitStruct.Pin = GPIO_PIN_8; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF12_SDIO; - HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + if (SdCard.CardType != CARD_SDHC_SDXC) { blockAddress *= 512U; } - GPIO_InitStruct.Pin = GPIO_PIN_12; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF12_SDIO; - HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + if (!SDIO_CmdReadSingleBlock(blockAddress)) { + SDIO_CLEAR_FLAG(SDIO_ICR_CMD_FLAGS); + dma_disable(SDIO_DMA_DEV, SDIO_DMA_CHANNEL); + return false; + } - GPIO_InitStruct.Pin = GPIO_PIN_2; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF12_SDIO; - HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); -} + while (!SDIO_GET_FLAG(SDIO_STA_DATAEND | SDIO_STA_TRX_ERROR_FLAGS)) {} -//bool SDIO_init() { return (bool) (SD_SDIO_Init() ? 1 : 0);} -//bool SDIO_Init_C() { return (bool) (SD_SDIO_Init() ? 1 : 0);} - -bool SDIO_ReadBlock(uint32_t block, uint8_t *dst) { - bool status; - - hsd.Instance = SDIO; - - uint8_t retryCnt = SD_RETRY_COUNT; - - for (;;) { - bool status = (bool) HAL_SD_ReadBlocks(&hsd, (uint8_t*)dst, block, 1, 1000); // read one 512 byte block with 500mS timeout - status |= (bool) HAL_SD_GetCardState(&hsd); // make sure all is OK - if (!status) return false; // return passing status - if (!--retryCnt) return true; // return failing status if retries are exhausted - } - - /* - return (bool) ((status_read | status_card) ? 1 : 0); - - if (SDIO_GetCardState() != SDIO_CARD_TRANSFER) return false; - if (blockAddress >= SdCard.LogBlockNbr) return false; - if ((0x03 & (uint32_t)data)) return false; // misaligned data - - if (SdCard.CardType != CARD_SDHC_SDXC) { blockAddress *= 512U; } - - if (!SDIO_CmdReadSingleBlock(blockAddress)) { - SDIO_CLEAR_FLAG(SDIO_ICR_CMD_FLAGS); dma_disable(SDIO_DMA_DEV, SDIO_DMA_CHANNEL); - return false; - } - while (!SDIO_GET_FLAG(SDIO_STA_DATAEND | SDIO_STA_TRX_ERROR_FLAGS)) {} + if (SDIO->STA & SDIO_STA_RXDAVL) { + while (SDIO->STA & SDIO_STA_RXDAVL) (void)SDIO->FIFO; + SDIO_CLEAR_FLAG(SDIO_ICR_CMD_FLAGS | SDIO_ICR_DATA_FLAGS); + return false; + } - dma_disable(SDIO_DMA_DEV, SDIO_DMA_CHANNEL); - - if (SDIO->STA & SDIO_STA_RXDAVL) { - while (SDIO->STA & SDIO_STA_RXDAVL) (void)SDIO->FIFO; + if (SDIO_GET_FLAG(SDIO_STA_TRX_ERROR_FLAGS)) { + SDIO_CLEAR_FLAG(SDIO_ICR_CMD_FLAGS | SDIO_ICR_DATA_FLAGS); + return false; + } SDIO_CLEAR_FLAG(SDIO_ICR_CMD_FLAGS | SDIO_ICR_DATA_FLAGS); - return false; + */ + + return true; } - if (SDIO_GET_FLAG(SDIO_STA_TRX_ERROR_FLAGS)) { - SDIO_CLEAR_FLAG(SDIO_ICR_CMD_FLAGS | SDIO_ICR_DATA_FLAGS); - return false; + bool SDIO_WriteBlock(uint32_t block, const uint8_t *src) { + hsd.Instance = SDIO; + uint8_t retryCnt = SD_RETRY_COUNT; + + bool status; + for (;;) { + status = (bool) HAL_SD_WriteBlocks(&hsd, (uint8_t*)src, block, 1, 500); // write one 512 byte block with 500mS timeout + status |= (bool) HAL_SD_GetCardState(&hsd); // make sure all is OK + if (!status) break; // return passing status + if (!--retryCnt) break; // return failing status if retries are exhausted + } + return status; } - SDIO_CLEAR_FLAG(SDIO_ICR_CMD_FLAGS | SDIO_ICR_DATA_FLAGS); - */ - - return true; -} - -bool SDIO_WriteBlock(uint32_t block, const uint8_t *src) { - bool status; - - hsd.Instance = SDIO; - - uint8_t retryCnt = SD_RETRY_COUNT; - - for (;;) { - status = (bool) HAL_SD_WriteBlocks(&hsd, (uint8_t*)src, block, 1, 500); // write one 512 byte block with 500mS timeout - status |= (bool) HAL_SD_GetCardState(&hsd); // make sure all is OK - if (!status) return (bool) status; // return passing status - if (!--retryCnt) return (bool) status; // return failing status if retries are exhausted - } -} +#endif // !USBD_USE_CDC_COMPOSITE #endif // SDIO_SUPPORT diff --git a/Marlin/src/pins/stm32f4/pins_STEVAL_3DP001V1.h b/Marlin/src/pins/stm32f4/pins_STEVAL_3DP001V1.h index 40b00bcc4..e9ae3f570 100644 --- a/Marlin/src/pins/stm32f4/pins_STEVAL_3DP001V1.h +++ b/Marlin/src/pins/stm32f4/pins_STEVAL_3DP001V1.h @@ -247,6 +247,7 @@ #ifndef SDIO_SUPPORT #define SOFTWARE_SPI // Use soft SPI for onboard SD + #undef SDSS #define SDSS SDIO_D3_PIN #define SCK_PIN SDIO_CK_PIN #define MISO_PIN SDIO_D0_PIN diff --git a/platformio.ini b/platformio.ini index d4c56876f..9a6dbad1f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -646,7 +646,7 @@ platform_packages = framework-arduinoststm32@>=3.10700,<4 build_flags = ${common.build_flags} -DTARGET_STM32F4 -DARDUINO_STEVAL -DSTM32F401xE -DUSBCON -DUSBD_USE_CDC -DUSBD_VID=0x0483 -DUSB_PRODUCT=\"STEVAL_F401VE\" - -DDISABLE_GENERIC_SERIALUSB + -DDISABLE_GENERIC_SERIALUSB -DUSBD_USE_CDC_COMPOSITE -DUSE_USB_FS -IMarlin/src/HAL/STM32 build_unflags = -std=gnu++11 extra_scripts = pre:buildroot/share/PlatformIO/scripts/generic_create_variant.py @@ -704,7 +704,8 @@ platform_packages = framework-arduinoststm32@>=3.10700,<4 build_flags = ${common.build_flags} -DTARGET_STM32F4 -DARDUINO_BLACK_F407VE -DUSBCON -DUSBD_USE_CDC -DUSBD_VID=0x0483 -DUSB_PRODUCT=\"BLACK_F407VE\" - -IMarlin/src/HAL/STM32 + -DUSBD_USE_CDC_COMPOSITE -DUSE_USB_FS + -IMarlin/src/HAL/STM32 build_unflags = -std=gnu++11 extra_scripts = pre:buildroot/share/PlatformIO/scripts/generic_create_variant.py lib_ignore = Adafruit NeoPixel, TMCStepper, SailfishLCD, SlowSoftI2CMaster, SoftwareSerial