✨ MSC Support for STM32 + SDIO boards -> SKR 2 (#22354)
This commit is contained in:
		
				
					committed by
					
						 Scott Lahteine
						Scott Lahteine
					
				
			
			
				
	
			
			
			
						parent
						
							8cf15e8546
						
					
				
				
					commit
					8334e92b6f
				
			| @@ -28,319 +28,296 @@ | ||||
| #include <stdint.h> | ||||
| #include <stdbool.h> | ||||
|  | ||||
| #if NONE(STM32F103xE, STM32F103xG, STM32F4xx, STM32F7xx) | ||||
|   #error "ERROR - Only STM32F103xE, STM32F103xG, STM32F4xx or STM32F7xx CPUs supported" | ||||
| // use local drivers | ||||
| #if defined(STM32F103xE) || defined(STM32F103xG) | ||||
|   #include <stm32f1xx_hal_rcc_ex.h> | ||||
|   #include <stm32f1xx_hal_sd.h> | ||||
| #elif defined(STM32F4xx) | ||||
|   #include <stm32f4xx_hal_rcc.h> | ||||
|   #include <stm32f4xx_hal_dma.h> | ||||
|   #include <stm32f4xx_hal_gpio.h> | ||||
|   #include <stm32f4xx_hal_sd.h> | ||||
| #elif defined(STM32F7xx) | ||||
|   #include <stm32f7xx_hal_rcc.h> | ||||
|   #include <stm32f7xx_hal_dma.h> | ||||
|   #include <stm32f7xx_hal_gpio.h> | ||||
|   #include <stm32f7xx_hal_sd.h> | ||||
| #else | ||||
|   #error "SDIO only supported with STM32F103xE, STM32F103xG, STM32F4xx, or STM32F7xx." | ||||
| #endif | ||||
|  | ||||
| #if HAS_SD_HOST_DRIVE | ||||
| // Fixed | ||||
| #define SDIO_D0_PIN   PC8 | ||||
| #define SDIO_D1_PIN   PC9 | ||||
| #define SDIO_D2_PIN   PC10 | ||||
| #define SDIO_D3_PIN   PC11 | ||||
| #define SDIO_CK_PIN   PC12 | ||||
| #define SDIO_CMD_PIN  PD2 | ||||
|  | ||||
|   // use USB drivers | ||||
| SD_HandleTypeDef hsd;  // create SDIO structure | ||||
| // F4 supports one DMA for RX and another for TX, but Marlin will never | ||||
| // do read and write at same time, so we use the same DMA for both. | ||||
| DMA_HandleTypeDef hdma_sdio; | ||||
|  | ||||
|   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; | ||||
|   } | ||||
| /* | ||||
|   SDIO_INIT_CLK_DIV is 118 | ||||
|   SDIO clock frequency is 48MHz / (TRANSFER_CLOCK_DIV + 2) | ||||
|   SDIO init clock frequency should not exceed 400KHz = 48MHz / (118 + 2) | ||||
|  | ||||
|   bool SDIO_Init() { | ||||
|     return hsd.State == HAL_SD_STATE_READY;  // return pass/fail status | ||||
|   } | ||||
|   Default TRANSFER_CLOCK_DIV is 2 (118 / 40) | ||||
|   Default SDIO clock frequency is 48MHz / (2 + 2) = 12 MHz | ||||
|   This might be too fast for stable SDIO operations | ||||
|  | ||||
|   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; | ||||
|   } | ||||
|   MKS Robin board seems to have stable SDIO with BusWide 1bit and ClockDiv 8 i.e. 4.8MHz SDIO clock frequency | ||||
|   Additional testing is required as there are clearly some 4bit initialization problems | ||||
| */ | ||||
|  | ||||
|   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; | ||||
|   } | ||||
| #ifndef USBD_OK | ||||
|   #define USBD_OK 0 | ||||
| #endif | ||||
|  | ||||
| #else // !USBD_USE_CDC_COMPOSITE | ||||
| // Target Clock, configurable. Default is 18MHz, from STM32F1 | ||||
| #ifndef SDIO_CLOCK | ||||
|   #define SDIO_CLOCK 18000000 // 18 MHz | ||||
| #endif | ||||
|  | ||||
|   // use local drivers | ||||
|   #if defined(STM32F103xE) || defined(STM32F103xG) | ||||
|     #include <stm32f1xx_hal_rcc_ex.h> | ||||
|     #include <stm32f1xx_hal_sd.h> | ||||
|   #elif defined(STM32F4xx) | ||||
|     #include <stm32f4xx_hal_rcc.h> | ||||
|     #include <stm32f4xx_hal_dma.h> | ||||
|     #include <stm32f4xx_hal_gpio.h> | ||||
|     #include <stm32f4xx_hal_sd.h> | ||||
|   #elif defined(STM32F7xx) | ||||
|     #include <stm32f7xx_hal_rcc.h> | ||||
|     #include <stm32f7xx_hal_dma.h> | ||||
|     #include <stm32f7xx_hal_gpio.h> | ||||
|     #include <stm32f7xx_hal_sd.h> | ||||
|   #else | ||||
|     #error "ERROR - Only STM32F103xE, STM32F103xG, STM32F4xx or STM32F7xx CPUs supported" | ||||
| // SDIO retries, configurable. Default is 3, from STM32F1 | ||||
| #ifndef SDIO_READ_RETRIES | ||||
|   #define SDIO_READ_RETRIES 3 | ||||
| #endif | ||||
|  | ||||
| // SDIO Max Clock (naming from STM Manual, don't change) | ||||
| #define SDIOCLK 48000000 | ||||
|  | ||||
| static uint32_t clock_to_divider(uint32_t clk) { | ||||
|   // limit the SDIO master clock to 8/3 of PCLK2. See STM32 Manuals | ||||
|   // Also limited to no more than 48Mhz (SDIOCLK). | ||||
|   const uint32_t pclk2 = HAL_RCC_GetPCLK2Freq(); | ||||
|   clk = min(clk, (uint32_t)(pclk2 * 8 / 3)); | ||||
|   clk = min(clk, (uint32_t)SDIOCLK); | ||||
|   // Round up divider, so we don't run the card over the speed supported, | ||||
|   // and subtract by 2, because STM32 will add 2, as written in the manual: | ||||
|   // SDIO_CK frequency = SDIOCLK / [CLKDIV + 2] | ||||
|   return pclk2 / clk + (pclk2 % clk != 0) - 2; | ||||
| } | ||||
|  | ||||
| void go_to_transfer_speed() { | ||||
|   /* Default SDIO peripheral configuration for SD card initialization */ | ||||
|   hsd.Init.ClockEdge           = hsd.Init.ClockEdge; | ||||
|   hsd.Init.ClockBypass         = hsd.Init.ClockBypass; | ||||
|   hsd.Init.ClockPowerSave      = hsd.Init.ClockPowerSave; | ||||
|   hsd.Init.BusWide             = hsd.Init.BusWide; | ||||
|   hsd.Init.HardwareFlowControl = hsd.Init.HardwareFlowControl; | ||||
|   hsd.Init.ClockDiv            = clock_to_divider(SDIO_CLOCK); | ||||
|  | ||||
|   /* Initialize SDIO peripheral interface with default configuration */ | ||||
|   SDIO_Init(hsd.Instance, hsd.Init); | ||||
| } | ||||
|  | ||||
| void SD_LowLevel_Init(void) { | ||||
|   uint32_t tempreg; | ||||
|  | ||||
|   __HAL_RCC_GPIOC_CLK_ENABLE(); //enable GPIO clocks | ||||
|   __HAL_RCC_GPIOD_CLK_ENABLE(); //enable GPIO clocks | ||||
|  | ||||
|   GPIO_InitTypeDef  GPIO_InitStruct; | ||||
|  | ||||
|   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; | ||||
|   GPIO_InitStruct.Pull = 1;  //GPIO_NOPULL; | ||||
|   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; | ||||
|  | ||||
|   #if DISABLED(STM32F1xx) | ||||
|     GPIO_InitStruct.Alternate = GPIO_AF12_SDIO; | ||||
|   #endif | ||||
|  | ||||
|   // Fixed | ||||
|   #define SDIO_D0_PIN   PC8 | ||||
|   #define SDIO_D1_PIN   PC9 | ||||
|   #define SDIO_D2_PIN   PC10 | ||||
|   #define SDIO_D3_PIN   PC11 | ||||
|   #define SDIO_CK_PIN   PC12 | ||||
|   #define SDIO_CMD_PIN  PD2 | ||||
|   GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_12;  // D0 & SCK | ||||
|   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); | ||||
|  | ||||
|   SD_HandleTypeDef hsd;  // create SDIO structure | ||||
|   // F4 supports one DMA for RX and another for TX, but Marlin will never | ||||
|   // do read and write at same time, so we use the same DMA for both. | ||||
|   DMA_HandleTypeDef hdma_sdio; | ||||
|  | ||||
|   /* | ||||
|     SDIO_INIT_CLK_DIV is 118 | ||||
|     SDIO clock frequency is 48MHz / (TRANSFER_CLOCK_DIV + 2) | ||||
|     SDIO init clock frequency should not exceed 400KHz = 48MHz / (118 + 2) | ||||
|  | ||||
|     Default TRANSFER_CLOCK_DIV is 2 (118 / 40) | ||||
|     Default SDIO clock frequency is 48MHz / (2 + 2) = 12 MHz | ||||
|     This might be too fast for stable SDIO operations | ||||
|  | ||||
|     MKS Robin board seems to have stable SDIO with BusWide 1bit and ClockDiv 8 i.e. 4.8MHz SDIO clock frequency | ||||
|     Additional testing is required as there are clearly some 4bit initialization problems | ||||
|   */ | ||||
|  | ||||
|   #ifndef USBD_OK | ||||
|     #define USBD_OK 0 | ||||
|   #endif | ||||
|  | ||||
|   // Target Clock, configurable. Default is 18MHz, from STM32F1 | ||||
|   #ifndef SDIO_CLOCK | ||||
|     #define SDIO_CLOCK 18000000 // 18 MHz | ||||
|   #endif | ||||
|  | ||||
|   // SDIO retries, configurable. Default is 3, from STM32F1 | ||||
|   #ifndef SDIO_READ_RETRIES | ||||
|     #define SDIO_READ_RETRIES 3 | ||||
|   #endif | ||||
|  | ||||
|   // SDIO Max Clock (naming from STM Manual, don't change) | ||||
|   #define SDIOCLK 48000000 | ||||
|  | ||||
|   static uint32_t clock_to_divider(uint32_t clk) { | ||||
|     // limit the SDIO master clock to 8/3 of PCLK2. See STM32 Manuals | ||||
|     // Also limited to no more than 48Mhz (SDIOCLK). | ||||
|     const uint32_t pclk2 = HAL_RCC_GetPCLK2Freq(); | ||||
|     clk = min(clk, (uint32_t)(pclk2 * 8 / 3)); | ||||
|     clk = min(clk, (uint32_t)SDIOCLK); | ||||
|     // Round up divider, so we don't run the card over the speed supported, | ||||
|     // and subtract by 2, because STM32 will add 2, as written in the manual: | ||||
|     // SDIO_CK frequency = SDIOCLK / [CLKDIV + 2] | ||||
|     return pclk2 / clk + (pclk2 % clk != 0) - 2; | ||||
|   } | ||||
|  | ||||
|   void go_to_transfer_speed() { | ||||
|     /* Default SDIO peripheral configuration for SD card initialization */ | ||||
|     hsd.Init.ClockEdge           = hsd.Init.ClockEdge; | ||||
|     hsd.Init.ClockBypass         = hsd.Init.ClockBypass; | ||||
|     hsd.Init.ClockPowerSave      = hsd.Init.ClockPowerSave; | ||||
|     hsd.Init.BusWide             = hsd.Init.BusWide; | ||||
|     hsd.Init.HardwareFlowControl = hsd.Init.HardwareFlowControl; | ||||
|     hsd.Init.ClockDiv            = clock_to_divider(SDIO_CLOCK); | ||||
|  | ||||
|     /* Initialize SDIO peripheral interface with default configuration */ | ||||
|     SDIO_Init(hsd.Instance, hsd.Init); | ||||
|   } | ||||
|  | ||||
|   void SD_LowLevel_Init(void) { | ||||
|     uint32_t tempreg; | ||||
|  | ||||
|     __HAL_RCC_GPIOC_CLK_ENABLE(); //enable GPIO clocks | ||||
|     __HAL_RCC_GPIOD_CLK_ENABLE(); //enable GPIO clocks | ||||
|  | ||||
|     GPIO_InitTypeDef  GPIO_InitStruct; | ||||
|  | ||||
|     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; | ||||
|     GPIO_InitStruct.Pull = 1;  //GPIO_NOPULL; | ||||
|     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; | ||||
|  | ||||
|     #if DISABLED(STM32F1xx) | ||||
|       GPIO_InitStruct.Alternate = GPIO_AF12_SDIO; | ||||
|     #endif | ||||
|  | ||||
|     GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_12;  // D0 & SCK | ||||
|   #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 | ||||
|     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); | ||||
|   #endif | ||||
|  | ||||
|     #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 | ||||
|       HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); | ||||
|     #endif | ||||
|   // Configure PD.02 CMD line | ||||
|   GPIO_InitStruct.Pin = GPIO_PIN_2; | ||||
|   HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); | ||||
|  | ||||
|     // Configure PD.02 CMD line | ||||
|     GPIO_InitStruct.Pin = GPIO_PIN_2; | ||||
|     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); | ||||
|   // Setup DMA | ||||
|   #if defined(STM32F1xx) | ||||
|     hdma_sdio.Init.Mode = DMA_NORMAL; | ||||
|     hdma_sdio.Instance = DMA2_Channel4; | ||||
|     HAL_NVIC_EnableIRQ(DMA2_Channel4_5_IRQn); | ||||
|   #elif defined(STM32F4xx) | ||||
|     hdma_sdio.Init.Mode = DMA_PFCTRL; | ||||
|     hdma_sdio.Instance = DMA2_Stream3; | ||||
|     hdma_sdio.Init.Channel = DMA_CHANNEL_4; | ||||
|     hdma_sdio.Init.FIFOMode = DMA_FIFOMODE_ENABLE; | ||||
|     hdma_sdio.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; | ||||
|     hdma_sdio.Init.MemBurst = DMA_MBURST_INC4; | ||||
|     hdma_sdio.Init.PeriphBurst = DMA_PBURST_INC4; | ||||
|     HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn); | ||||
|   #endif | ||||
|   HAL_NVIC_EnableIRQ(SDIO_IRQn); | ||||
|   hdma_sdio.Init.PeriphInc = DMA_PINC_DISABLE; | ||||
|   hdma_sdio.Init.MemInc = DMA_MINC_ENABLE; | ||||
|   hdma_sdio.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; | ||||
|   hdma_sdio.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; | ||||
|   hdma_sdio.Init.Priority = DMA_PRIORITY_LOW; | ||||
|   __HAL_LINKDMA(&hsd, hdmarx, hdma_sdio); | ||||
|   __HAL_LINKDMA(&hsd, hdmatx, hdma_sdio); | ||||
|  | ||||
|     // Setup DMA | ||||
|     #if defined(STM32F1xx) | ||||
|       hdma_sdio.Init.Mode = DMA_NORMAL; | ||||
|       hdma_sdio.Instance = DMA2_Channel4; | ||||
|       HAL_NVIC_EnableIRQ(DMA2_Channel4_5_IRQn); | ||||
|     #elif defined(STM32F4xx) | ||||
|       hdma_sdio.Init.Mode = DMA_PFCTRL; | ||||
|       hdma_sdio.Instance = DMA2_Stream3; | ||||
|       hdma_sdio.Init.Channel = DMA_CHANNEL_4; | ||||
|       hdma_sdio.Init.FIFOMode = DMA_FIFOMODE_ENABLE; | ||||
|       hdma_sdio.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; | ||||
|       hdma_sdio.Init.MemBurst = DMA_MBURST_INC4; | ||||
|       hdma_sdio.Init.PeriphBurst = DMA_PBURST_INC4; | ||||
|       HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn); | ||||
|     #endif | ||||
|     HAL_NVIC_EnableIRQ(SDIO_IRQn); | ||||
|     hdma_sdio.Init.PeriphInc = DMA_PINC_DISABLE; | ||||
|     hdma_sdio.Init.MemInc = DMA_MINC_ENABLE; | ||||
|     hdma_sdio.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; | ||||
|     hdma_sdio.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; | ||||
|     hdma_sdio.Init.Priority = DMA_PRIORITY_LOW; | ||||
|     __HAL_LINKDMA(&hsd, hdmarx, hdma_sdio); | ||||
|     __HAL_LINKDMA(&hsd, hdmatx, hdma_sdio); | ||||
|   #if defined(STM32F1xx) | ||||
|     __HAL_RCC_SDIO_CLK_ENABLE(); | ||||
|     __HAL_RCC_DMA2_CLK_ENABLE(); | ||||
|   #else | ||||
|     __HAL_RCC_SDIO_FORCE_RESET(); | ||||
|     delay(2); | ||||
|     __HAL_RCC_SDIO_RELEASE_RESET(); | ||||
|     delay(2); | ||||
|     __HAL_RCC_SDIO_CLK_ENABLE(); | ||||
|  | ||||
|     #if defined(STM32F1xx) | ||||
|       __HAL_RCC_SDIO_CLK_ENABLE(); | ||||
|       __HAL_RCC_DMA2_CLK_ENABLE(); | ||||
|     #else | ||||
|       __HAL_RCC_SDIO_FORCE_RESET(); | ||||
|       delay(2); | ||||
|       __HAL_RCC_SDIO_RELEASE_RESET(); | ||||
|       delay(2); | ||||
|       __HAL_RCC_SDIO_CLK_ENABLE(); | ||||
|     __HAL_RCC_DMA2_FORCE_RESET(); | ||||
|     delay(2); | ||||
|     __HAL_RCC_DMA2_RELEASE_RESET(); | ||||
|     delay(2); | ||||
|     __HAL_RCC_DMA2_CLK_ENABLE(); | ||||
|   #endif | ||||
|  | ||||
|       __HAL_RCC_DMA2_FORCE_RESET(); | ||||
|       delay(2); | ||||
|       __HAL_RCC_DMA2_RELEASE_RESET(); | ||||
|       delay(2); | ||||
|       __HAL_RCC_DMA2_CLK_ENABLE(); | ||||
|     #endif | ||||
|   //Initialize the SDIO (with initial <400Khz Clock) | ||||
|   tempreg = 0;  //Reset value | ||||
|   tempreg |= SDIO_CLKCR_CLKEN;  // Clock enabled | ||||
|   tempreg |= SDIO_INIT_CLK_DIV; // 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; | ||||
|  | ||||
|     //Initialize the SDIO (with initial <400Khz Clock) | ||||
|     tempreg = 0;  //Reset value | ||||
|     tempreg |= SDIO_CLKCR_CLKEN;  // Clock enabled | ||||
|     tempreg |= SDIO_INIT_CLK_DIV; // 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; | ||||
|   // Power up the SDIO | ||||
|   SDIO_PowerState_ON(SDIO); | ||||
|   hsd.Instance = SDIO; | ||||
| } | ||||
|  | ||||
|     // Power up the SDIO | ||||
|     SDIO_PowerState_ON(SDIO); | ||||
|     hsd.Instance = SDIO; | ||||
| 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 | ||||
| } | ||||
|  | ||||
| bool SDIO_Init() { | ||||
|   uint8_t retryCnt = SDIO_READ_RETRIES; | ||||
|  | ||||
|   bool status; | ||||
|   hsd.Instance = SDIO; | ||||
|   hsd.State = HAL_SD_STATE_RESET; | ||||
|  | ||||
|   SD_LowLevel_Init(); | ||||
|  | ||||
|   uint8_t retry_Cnt = retryCnt; | ||||
|   for (;;) { | ||||
|     TERN_(USE_WATCHDOG, HAL_watchdog_refresh()); | ||||
|     status = (bool) HAL_SD_Init(&hsd); | ||||
|     if (!status) break; | ||||
|     if (!--retry_Cnt) return false;   // return failing status if retries are exhausted | ||||
|   } | ||||
|  | ||||
|   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 | ||||
|   } | ||||
|   go_to_transfer_speed(); | ||||
|  | ||||
|   bool SDIO_Init() { | ||||
|     uint8_t retryCnt = SDIO_READ_RETRIES; | ||||
|  | ||||
|     bool status; | ||||
|     hsd.Instance = SDIO; | ||||
|     hsd.State = HAL_SD_STATE_RESET; | ||||
|  | ||||
|     SD_LowLevel_Init(); | ||||
|  | ||||
|     uint8_t retry_Cnt = retryCnt; | ||||
|   #if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3) // go to 4 bit wide mode if pins are defined | ||||
|     retry_Cnt = retryCnt; | ||||
|     for (;;) { | ||||
|       TERN_(USE_WATCHDOG, HAL_watchdog_refresh()); | ||||
|       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; | ||||
|     } | ||||
|  | ||||
|     go_to_transfer_speed(); | ||||
|  | ||||
|     #if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3) // go to 4 bit wide mode if pins are defined | ||||
|     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 (;;) { | ||||
|         TERN_(USE_WATCHDOG, HAL_watchdog_refresh()); | ||||
|         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(); | ||||
|         retry_Cnt = retryCnt; | ||||
|         for (;;) { | ||||
|           TERN_(USE_WATCHDOG, HAL_watchdog_refresh()); | ||||
|           status = (bool) HAL_SD_Init(&hsd); | ||||
|           if (!status) break; | ||||
|           if (!--retry_Cnt) return false;   // return failing status if retries are exhausted | ||||
|         } | ||||
|         go_to_transfer_speed(); | ||||
|       } | ||||
|     #endif | ||||
|       go_to_transfer_speed(); | ||||
|     } | ||||
|   #endif | ||||
|  | ||||
|     return true; | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| static bool SDIO_ReadWriteBlock_DMA(uint32_t block, const uint8_t *src, uint8_t *dst) { | ||||
|   if (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) return false; | ||||
|  | ||||
|   TERN_(USE_WATCHDOG, HAL_watchdog_refresh()); | ||||
|  | ||||
|   HAL_StatusTypeDef ret; | ||||
|   if (src) { | ||||
|     hdma_sdio.Init.Direction = DMA_MEMORY_TO_PERIPH; | ||||
|     HAL_DMA_Init(&hdma_sdio); | ||||
|     ret = HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t *)src, block, 1); | ||||
|   } | ||||
|   else { | ||||
|     hdma_sdio.Init.Direction = DMA_PERIPH_TO_MEMORY; | ||||
|     HAL_DMA_Init(&hdma_sdio); | ||||
|     ret = HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t *)dst, block, 1); | ||||
|   } | ||||
|  | ||||
|   static bool SDIO_ReadWriteBlock_DMA(uint32_t block, const uint8_t *src, uint8_t *dst) { | ||||
|     if (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) return false; | ||||
|   if (ret != HAL_OK) { | ||||
|     HAL_DMA_Abort_IT(&hdma_sdio); | ||||
|     HAL_DMA_DeInit(&hdma_sdio); | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|     TERN_(USE_WATCHDOG, HAL_watchdog_refresh()); | ||||
|  | ||||
|     HAL_StatusTypeDef ret; | ||||
|     if (src) { | ||||
|       hdma_sdio.Init.Direction = DMA_MEMORY_TO_PERIPH; | ||||
|       HAL_DMA_Init(&hdma_sdio); | ||||
|       ret = HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t *)src, block, 1); | ||||
|     } | ||||
|     else { | ||||
|       hdma_sdio.Init.Direction = DMA_PERIPH_TO_MEMORY; | ||||
|       HAL_DMA_Init(&hdma_sdio); | ||||
|       ret = HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t *)dst, block, 1); | ||||
|     } | ||||
|  | ||||
|     if (ret != HAL_OK) { | ||||
|   millis_t timeout = millis() + 500; | ||||
|   // Wait the transfer | ||||
|   while (hsd.State != HAL_SD_STATE_READY) { | ||||
|     if (ELAPSED(millis(), timeout)) { | ||||
|       HAL_DMA_Abort_IT(&hdma_sdio); | ||||
|       HAL_DMA_DeInit(&hdma_sdio); | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|     millis_t timeout = millis() + 500; | ||||
|     // Wait the transfer | ||||
|     while (hsd.State != HAL_SD_STATE_READY) { | ||||
|       if (ELAPSED(millis(), timeout)) { | ||||
|         HAL_DMA_Abort_IT(&hdma_sdio); | ||||
|         HAL_DMA_DeInit(&hdma_sdio); | ||||
|         return false; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     while (__HAL_DMA_GET_FLAG(&hdma_sdio, __HAL_DMA_GET_TC_FLAG_INDEX(&hdma_sdio)) != 0 | ||||
|         || __HAL_DMA_GET_FLAG(&hdma_sdio, __HAL_DMA_GET_TE_FLAG_INDEX(&hdma_sdio)) != 0) { /* nada */ } | ||||
|  | ||||
|     HAL_DMA_Abort_IT(&hdma_sdio); | ||||
|     HAL_DMA_DeInit(&hdma_sdio); | ||||
|  | ||||
|     timeout = millis() + 500; | ||||
|     while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) if (ELAPSED(millis(), timeout)) return false; | ||||
|  | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   bool SDIO_ReadBlock(uint32_t block, uint8_t *dst) { | ||||
|     uint8_t retries = SDIO_READ_RETRIES; | ||||
|     while (retries--) if (SDIO_ReadWriteBlock_DMA(block, NULL, dst)) return true; | ||||
|     return false; | ||||
|   } | ||||
|   while (__HAL_DMA_GET_FLAG(&hdma_sdio, __HAL_DMA_GET_TC_FLAG_INDEX(&hdma_sdio)) != 0 | ||||
|       || __HAL_DMA_GET_FLAG(&hdma_sdio, __HAL_DMA_GET_TE_FLAG_INDEX(&hdma_sdio)) != 0) { /* nada */ } | ||||
|  | ||||
|   bool SDIO_WriteBlock(uint32_t block, const uint8_t *src) { | ||||
|     uint8_t retries = SDIO_READ_RETRIES; | ||||
|     while (retries--) if (SDIO_ReadWriteBlock_DMA(block, src, NULL)) return true; | ||||
|     return false; | ||||
|   } | ||||
|   HAL_DMA_Abort_IT(&hdma_sdio); | ||||
|   HAL_DMA_DeInit(&hdma_sdio); | ||||
|  | ||||
|   #if defined(STM32F1xx) | ||||
|     #define DMA_IRQ_HANDLER DMA2_Channel4_5_IRQHandler | ||||
|   #elif defined(STM32F4xx) | ||||
|     #define DMA_IRQ_HANDLER DMA2_Stream3_IRQHandler | ||||
|   #else | ||||
|     #error "Unknown STM32 architecture." | ||||
|   #endif | ||||
|   timeout = millis() + 500; | ||||
|   while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) if (ELAPSED(millis(), timeout)) return false; | ||||
|  | ||||
|   extern "C" void SDIO_IRQHandler(void) { HAL_SD_IRQHandler(&hsd); } | ||||
|   extern "C" void DMA_IRQ_HANDLER(void) { HAL_DMA_IRQHandler(&hdma_sdio); } | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| bool SDIO_ReadBlock(uint32_t block, uint8_t *dst) { | ||||
|   uint8_t retries = SDIO_READ_RETRIES; | ||||
|   while (retries--) if (SDIO_ReadWriteBlock_DMA(block, NULL, dst)) return true; | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| bool SDIO_WriteBlock(uint32_t block, const uint8_t *src) { | ||||
|   uint8_t retries = SDIO_READ_RETRIES; | ||||
|   while (retries--) if (SDIO_ReadWriteBlock_DMA(block, src, NULL)) return true; | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| bool SDIO_IsReady() { | ||||
|   return hsd.State == HAL_SD_STATE_READY; | ||||
| } | ||||
|  | ||||
| uint32_t SDIO_GetCardSize() { | ||||
|   return (uint32_t)(hsd.SdCard.BlockNbr) * (hsd.SdCard.BlockSize); | ||||
| } | ||||
|  | ||||
| #if defined(STM32F1xx) | ||||
|   #define DMA_IRQ_HANDLER DMA2_Channel4_5_IRQHandler | ||||
| #elif defined(STM32F4xx) | ||||
|   #define DMA_IRQ_HANDLER DMA2_Stream3_IRQHandler | ||||
| #else | ||||
|   #error "Unknown STM32 architecture." | ||||
| #endif | ||||
|  | ||||
| extern "C" void SDIO_IRQHandler(void) { HAL_SD_IRQHandler(&hsd); } | ||||
| extern "C" void DMA_IRQ_HANDLER(void) { HAL_DMA_IRQHandler(&hdma_sdio); } | ||||
|  | ||||
| #endif // !USBD_USE_CDC_COMPOSITE | ||||
| #endif // SDIO_SUPPORT | ||||
| #endif // ARDUINO_ARCH_STM32 && !STM32GENERIC && !MAPLE_STM32F1 | ||||
|   | ||||
| @@ -19,10 +19,10 @@ | ||||
|  | ||||
| #if HAS_SD_HOST_DRIVE | ||||
|  | ||||
| #include "../shared/Marduino.h" | ||||
| #include "msc_sd.h" | ||||
| #include "usbd_core.h" | ||||
|  | ||||
| #include "../shared/Marduino.h" | ||||
| #include "../../sd/cardreader.h" | ||||
|  | ||||
| #include <USB.h> | ||||
|   | ||||
| @@ -184,6 +184,10 @@ bool SDIO_WriteBlock(uint32_t blockAddress, const uint8_t *data) { | ||||
|  | ||||
| inline uint32_t SDIO_GetCardState() { return SDIO_CmdSendStatus(SdCard.RelCardAdd << 16U) ? (SDIO_GetResponse(SDIO_RESP1) >> 9U) & 0x0FU : SDIO_CARD_ERROR; } | ||||
|  | ||||
| // No F1 board with SDIO + MSC using Maple, that I aware of... | ||||
| bool SDIO_IsReady() { return true; } | ||||
| uint32_t SDIO_GetCardSize() { return 0; } | ||||
|  | ||||
| // ------------------------ | ||||
| // SD Commands and Responses | ||||
| // ------------------------ | ||||
|   | ||||
| @@ -594,9 +594,9 @@ | ||||
| #elif MB(BTT_E3_RRF) | ||||
|   #include "stm32f4/pins_BTT_E3_RRF.h"          // STM32F4                                env:BIGTREE_E3_RRF | ||||
| #elif MB(BTT_SKR_V2_0_REV_A) | ||||
|   #include "stm32f4/pins_BTT_SKR_V2_0_REV_A.h"  // STM32F4                                env:BIGTREE_SKR_2 | ||||
|   #include "stm32f4/pins_BTT_SKR_V2_0_REV_A.h"  // STM32F4                                env:BIGTREE_SKR_2 env:BIGTREE_SKR_2_USB | ||||
| #elif MB(BTT_SKR_V2_0_REV_B) | ||||
|   #include "stm32f4/pins_BTT_SKR_V2_0_REV_B.h"  // STM32F4                                env:BIGTREE_SKR_2 | ||||
|   #include "stm32f4/pins_BTT_SKR_V2_0_REV_B.h"  // STM32F4                                env:BIGTREE_SKR_2 env:BIGTREE_SKR_2_USB | ||||
| #elif MB(BTT_OCTOPUS_V1_0) | ||||
|   #include "stm32f4/pins_BTT_OCTOPUS_V1_0.h"    // STM32F4                                env:BIGTREE_OCTOPUS_V1 env:BIGTREE_OCTOPUS_V1_USB | ||||
| #elif MB(BTT_OCTOPUS_V1_1) | ||||
|   | ||||
| @@ -29,6 +29,8 @@ | ||||
| bool SDIO_Init(); | ||||
| bool SDIO_ReadBlock(uint32_t block, uint8_t *dst); | ||||
| bool SDIO_WriteBlock(uint32_t block, const uint8_t *src); | ||||
| bool SDIO_IsReady(); | ||||
| uint32_t SDIO_GetCardSize(); | ||||
|  | ||||
| class DiskIODriver_SDIO : public DiskIODriver { | ||||
|   public: | ||||
| @@ -36,20 +38,22 @@ class DiskIODriver_SDIO : public DiskIODriver { | ||||
|  | ||||
|     bool readCSD(csd_t *csd)                              override { return false; } | ||||
|  | ||||
|     bool readStart(const uint32_t block)                  override { return false; } | ||||
|     bool readData(uint8_t *dst)                           override { return false; } | ||||
|     bool readStop()                                       override { return false; } | ||||
|     bool readStart(const uint32_t block)                  override { curBlock = block; return true; } | ||||
|     bool readData(uint8_t *dst)                           override { return readBlock(curBlock++, dst); } | ||||
|     bool readStop()                                       override { curBlock = -1; return true; } | ||||
|  | ||||
|     bool writeStart(const uint32_t block, const uint32_t) override { return false; } | ||||
|     bool writeData(const uint8_t *src)                    override { return false; } | ||||
|     bool writeStop()                                      override { return false; } | ||||
|     bool writeStart(const uint32_t block, const uint32_t) override { curBlock = block; return true; } | ||||
|     bool writeData(const uint8_t *src)                    override { return writeBlock(curBlock++, src); } | ||||
|     bool writeStop()                                      override { curBlock = -1; return true; } | ||||
|  | ||||
|     bool readBlock(uint32_t block, uint8_t *dst)          override { return SDIO_ReadBlock(block, dst); } | ||||
|     bool writeBlock(uint32_t block, const uint8_t *src)   override { return SDIO_WriteBlock(block, src); } | ||||
|  | ||||
|     uint32_t cardSize()                                   override { return 0; } | ||||
|     uint32_t cardSize()                                   override { return SDIO_GetCardSize(); } | ||||
|  | ||||
|     bool isReady()                                        override { return true; } | ||||
|     bool isReady()                                        override { return SDIO_IsReady(); } | ||||
|  | ||||
|     void idle()                                           override {} | ||||
|   private: | ||||
|     uint32_t curBlock; | ||||
| }; | ||||
|   | ||||
| @@ -243,6 +243,16 @@ build_flags       = ${stm_flash_drive.build_flags} | ||||
|   -DUSE_USBHOST_HS -DUSE_USB_HS_IN_FS -DUSBD_IRQ_PRIO=5 -DUSBD_IRQ_SUBPRIO=6 | ||||
|   -DHSE_VALUE=8000000U -DHAL_SD_MODULE_ENABLED | ||||
|  | ||||
| # | ||||
| # BigTreeTech SKR V2.0 (STM32F407VGT6 ARM Cortex-M4) with USB Media Share Support | ||||
| # | ||||
| [env:BIGTREE_SKR_2_USB] | ||||
| platform          = ${common_stm32.platform} | ||||
| extends           = env:BIGTREE_SKR_2 | ||||
| platform_packages = ${stm_flash_drive.platform_packages} | ||||
| build_unflags     = -DUSBD_USE_CDC | ||||
| build_flags       = ${env:BIGTREE_SKR_2.build_flags} -DUSBD_USE_CDC_MSC | ||||
|  | ||||
| # | ||||
| # BigTreeTech Octopus V1.0/1.1 (STM32F446ZET6 ARM Cortex-M4) | ||||
| # | ||||
|   | ||||
		Reference in New Issue
	
	Block a user