Kaynağa Gözat

🐛 Fix SDIO for STM32 (#24470)

Followup to #24271
Scott Lahteine 2 yıl önce
ebeveyn
işleme
f101aeb3ec
1 değiştirilmiş dosya ile 355 ekleme ve 172 silme
  1. 355
    172
      Marlin/src/HAL/STM32/sdio.cpp

+ 355
- 172
Marlin/src/HAL/STM32/sdio.cpp Dosyayı Görüntüle

@@ -33,227 +33,410 @@
33 33
 #include <stdint.h>
34 34
 #include <stdbool.h>
35 35
 
36
-// use local drivers
37 36
 #if defined(STM32F103xE) || defined(STM32F103xG)
38
-  #include <stm32f1xx.h>
37
+  #include <stm32f1xx_hal_rcc_ex.h>
38
+  #include <stm32f1xx_hal_sd.h>
39 39
 #elif defined(STM32F4xx)
40
-  #include <stm32f4xx.h>
40
+  #include <stm32f4xx_hal_rcc.h>
41
+  #include <stm32f4xx_hal_dma.h>
42
+  #include <stm32f4xx_hal_gpio.h>
43
+  #include <stm32f4xx_hal_sd.h>
41 44
 #elif defined(STM32F7xx)
42
-  #include <stm32f7xx.h>
45
+  #include <stm32f7xx_hal_rcc.h>
46
+  #include <stm32f7xx_hal_dma.h>
47
+  #include <stm32f7xx_hal_gpio.h>
48
+  #include <stm32f7xx_hal_sd.h>
43 49
 #elif defined(STM32H7xx)
44
-  #include <stm32h7xx.h>
50
+  #define SDIO_FOR_STM32H7
51
+  #include <stm32h7xx_hal_rcc.h>
52
+  #include <stm32h7xx_hal_dma.h>
53
+  #include <stm32h7xx_hal_gpio.h>
54
+  #include <stm32h7xx_hal_sd.h>
45 55
 #else
46
-  #error "SDIO only supported with STM32F103xE, STM32F103xG, STM32F4xx, STM32F7xx, or STM32H7xx."
56
+  #error "SDIO is only supported with STM32F103xE, STM32F103xG, STM32F4xx, STM32F7xx, and STM32H7xx."
47 57
 #endif
48 58
 
59
+// SDIO Max Clock (naming from STM Manual, don't change)
60
+#define SDIOCLK 48000000
61
+
49 62
 // Target Clock, configurable. Default is 18MHz, from STM32F1
50 63
 #ifndef SDIO_CLOCK
51 64
   #define SDIO_CLOCK 18000000 // 18 MHz
52 65
 #endif
53 66
 
54
-#define SD_TIMEOUT              1000 // ms
67
+SD_HandleTypeDef hsd;  // SDIO structure
55 68
 
56
-// SDIO Max Clock (naming from STM Manual, don't change)
57
-#define SDIOCLK 48000000
69
+static uint32_t clock_to_divider(uint32_t clk) {
70
+  #ifdef SDIO_FOR_STM32H7
71
+    // SDMMC_CK frequency = sdmmc_ker_ck / [2 * CLKDIV].
72
+    uint32_t sdmmc_clk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC);
73
+    return sdmmc_clk / (2U * SDIO_CLOCK) + (sdmmc_clk % (2U * SDIO_CLOCK) != 0);
74
+  #else
75
+    // limit the SDIO master clock to 8/3 of PCLK2. See STM32 Manuals
76
+    // Also limited to no more than 48Mhz (SDIOCLK).
77
+    const uint32_t pclk2 = HAL_RCC_GetPCLK2Freq();
78
+    clk = min(clk, (uint32_t)(pclk2 * 8 / 3));
79
+    clk = min(clk, (uint32_t)SDIOCLK);
80
+    // Round up divider, so we don't run the card over the speed supported,
81
+    // and subtract by 2, because STM32 will add 2, as written in the manual:
82
+    // SDIO_CK frequency = SDIOCLK / [CLKDIV + 2]
83
+    return pclk2 / clk + (pclk2 % clk != 0) - 2;
84
+  #endif
85
+}
58 86
 
59
-#if defined(STM32F1xx)
60
-  DMA_HandleTypeDef hdma_sdio;
61
-  extern "C" void DMA2_Channel4_5_IRQHandler(void) {
62
-    HAL_DMA_IRQHandler(&hdma_sdio);
63
-  }
64
-#elif defined(STM32F4xx)
65
-  DMA_HandleTypeDef hdma_sdio_rx;
66
-  DMA_HandleTypeDef hdma_sdio_tx;
67
-  extern "C" void DMA2_Stream3_IRQHandler(void) {
68
-    HAL_DMA_IRQHandler(&hdma_sdio_rx);
87
+// Start the SDIO clock
88
+void HAL_SD_MspInit(SD_HandleTypeDef *hsd) {
89
+  UNUSED(hsd);
90
+  #ifdef SDIO_FOR_STM32H7
91
+    pinmap_pinout(PC_12, PinMap_SD);
92
+    pinmap_pinout(PD_2,  PinMap_SD);
93
+    pinmap_pinout(PC_8,  PinMap_SD);
94
+    #if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3)  // Define D1-D3 only for 4-bit wide SDIO bus
95
+      pinmap_pinout(PC_9,  PinMap_SD);
96
+      pinmap_pinout(PC_10, PinMap_SD);
97
+      pinmap_pinout(PC_11, PinMap_SD);
98
+    #endif
99
+    __HAL_RCC_SDMMC1_CLK_ENABLE();
100
+    HAL_NVIC_EnableIRQ(SDMMC1_IRQn);
101
+  #else
102
+    __HAL_RCC_SDIO_CLK_ENABLE();
103
+  #endif
104
+}
105
+
106
+#ifdef SDIO_FOR_STM32H7
107
+
108
+  #define SD_TIMEOUT              1000 // ms
109
+
110
+  extern "C" void SDMMC1_IRQHandler(void) { HAL_SD_IRQHandler(&hsd); }
111
+
112
+  uint8_t waitingRxCplt = 0, waitingTxCplt = 0;
113
+  void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsdio) { waitingTxCplt = 0; }
114
+  void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsdio) { waitingRxCplt = 0; }
115
+
116
+  void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd) {
117
+    __HAL_RCC_SDMMC1_FORCE_RESET();   delay(10);
118
+    __HAL_RCC_SDMMC1_RELEASE_RESET(); delay(10);
69 119
   }
70 120
 
71
-  extern "C" void DMA2_Stream6_IRQHandler(void) {
72
-    HAL_DMA_IRQHandler(&hdma_sdio_tx);
121
+  bool SDIO_Init() {
122
+    HAL_StatusTypeDef sd_state = HAL_OK;
123
+    if (hsd.Instance == SDMMC1) HAL_SD_DeInit(&hsd);
124
+
125
+    // HAL SD initialization
126
+    hsd.Instance = SDMMC1;
127
+    hsd.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
128
+    hsd.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
129
+    hsd.Init.BusWide = SDMMC_BUS_WIDE_1B;
130
+    hsd.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
131
+    hsd.Init.ClockDiv = clock_to_divider(SDIO_CLOCK);
132
+    sd_state = HAL_SD_Init(&hsd);
133
+
134
+    #if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3)
135
+      if (sd_state == HAL_OK)
136
+        sd_state = HAL_SD_ConfigWideBusOperation(&hsd, SDMMC_BUS_WIDE_4B);
137
+    #endif
138
+
139
+    return (sd_state == HAL_OK);
73 140
   }
74
-#elif defined(STM32H7xx)
75
-  #define __HAL_RCC_SDIO_FORCE_RESET          __HAL_RCC_SDMMC1_FORCE_RESET
76
-  #define __HAL_RCC_SDIO_RELEASE_RESET        __HAL_RCC_SDMMC1_RELEASE_RESET
77
-  #define __HAL_RCC_SDIO_CLK_ENABLE           __HAL_RCC_SDMMC1_CLK_ENABLE
78
-  #define SDIO                                SDMMC1
79
-  #define SDIO_IRQn                           SDMMC1_IRQn
80
-  #define SDIO_IRQHandler                     SDMMC1_IRQHandler
81
-  #define SDIO_CLOCK_EDGE_RISING              SDMMC_CLOCK_EDGE_RISING
82
-  #define SDIO_CLOCK_POWER_SAVE_DISABLE       SDMMC_CLOCK_POWER_SAVE_DISABLE
83
-  #define SDIO_BUS_WIDE_1B                    SDMMC_BUS_WIDE_1B
84
-  #define SDIO_BUS_WIDE_4B                    SDMMC_BUS_WIDE_4B
85
-  #define SDIO_HARDWARE_FLOW_CONTROL_DISABLE  SDMMC_HARDWARE_FLOW_CONTROL_DISABLE
86
-#endif
87 141
 
88
-uint8_t waitingRxCplt = 0;
89
-uint8_t waitingTxCplt = 0;
90
-SD_HandleTypeDef hsd;
142
+#else // !SDIO_FOR_STM32H7
91 143
 
92
-extern "C" void SDIO_IRQHandler(void) {
93
-  HAL_SD_IRQHandler(&hsd);
94
-}
144
+  #define SD_TIMEOUT               500 // ms
95 145
 
96
-void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsdio) {
97
-  waitingTxCplt = 0;
98
-}
146
+  // SDIO retries, configurable. Default is 3, from STM32F1
147
+  #ifndef SDIO_READ_RETRIES
148
+    #define SDIO_READ_RETRIES 3
149
+  #endif
99 150
 
100
-void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsdio) {
101
-  waitingRxCplt = 0;
102
-}
151
+  // F4 supports one DMA for RX and another for TX, but Marlin will never
152
+  // do read and write at same time, so we use the same DMA for both.
153
+  DMA_HandleTypeDef hdma_sdio;
103 154
 
104
-void HAL_SD_MspInit(SD_HandleTypeDef *hsd) {
105
-  pinmap_pinout(PC_12, PinMap_SD);
106
-  pinmap_pinout(PD_2, PinMap_SD);
107
-  pinmap_pinout(PC_8, PinMap_SD);
108
-  #if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3)  // define D1-D3 only if have a four bit wide SDIO bus
109
-    // D1-D3
110
-    pinmap_pinout(PC_9, PinMap_SD);
111
-    pinmap_pinout(PC_10, PinMap_SD);
112
-    pinmap_pinout(PC_11, PinMap_SD);
155
+  #ifdef STM32F1xx
156
+    #define DMA_IRQ_HANDLER DMA2_Channel4_5_IRQHandler
157
+  #elif defined(STM32F4xx)
158
+    #define DMA_IRQ_HANDLER DMA2_Stream3_IRQHandler
159
+  #else
160
+    #error "Unknown STM32 architecture."
113 161
   #endif
114 162
 
115
-  __HAL_RCC_SDIO_CLK_ENABLE();
116
-  HAL_NVIC_EnableIRQ(SDIO_IRQn);
163
+  extern "C" void SDIO_IRQHandler(void) { HAL_SD_IRQHandler(&hsd); }
164
+  extern "C" void DMA_IRQ_HANDLER(void) { HAL_DMA_IRQHandler(&hdma_sdio); }
165
+
166
+  /*
167
+    SDIO_INIT_CLK_DIV is 118
168
+    SDIO clock frequency is 48MHz / (TRANSFER_CLOCK_DIV + 2)
169
+    SDIO init clock frequency should not exceed 400kHz = 48MHz / (118 + 2)
170
+
171
+    Default TRANSFER_CLOCK_DIV is 2 (118 / 40)
172
+    Default SDIO clock frequency is 48MHz / (2 + 2) = 12 MHz
173
+    This might be too fast for stable SDIO operations
174
+
175
+    MKS Robin SDIO seems stable with BusWide 1bit and ClockDiv 8 (i.e., 4.8MHz SDIO clock frequency)
176
+    More testing is required as there are clearly some 4bit init problems.
177
+  */
178
+
179
+  void go_to_transfer_speed() {
180
+    /* Default SDIO peripheral configuration for SD card initialization */
181
+    hsd.Init.ClockEdge           = hsd.Init.ClockEdge;
182
+    hsd.Init.ClockBypass         = hsd.Init.ClockBypass;
183
+    hsd.Init.ClockPowerSave      = hsd.Init.ClockPowerSave;
184
+    hsd.Init.BusWide             = hsd.Init.BusWide;
185
+    hsd.Init.HardwareFlowControl = hsd.Init.HardwareFlowControl;
186
+    hsd.Init.ClockDiv            = clock_to_divider(SDIO_CLOCK);
187
+
188
+    /* Initialize SDIO peripheral interface with default configuration */
189
+    SDIO_Init(hsd.Instance, hsd.Init);
190
+  }
117 191
 
118
-  // DMA Config
119
-  #if defined(STM32F1xx)
120
-    __HAL_RCC_DMA2_CLK_ENABLE();
121
-    HAL_NVIC_EnableIRQ(DMA2_Channel4_5_IRQn);
122
-    hdma_sdio.Instance = DMA2_Channel4;
123
-    hdma_sdio.Init.Direction = DMA_PERIPH_TO_MEMORY;
192
+  void SD_LowLevel_Init() {
193
+    uint32_t tempreg;
194
+
195
+    // Enable GPIO clocks
196
+    __HAL_RCC_GPIOC_CLK_ENABLE();
197
+    __HAL_RCC_GPIOD_CLK_ENABLE();
198
+
199
+    GPIO_InitTypeDef  GPIO_InitStruct;
200
+
201
+    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
202
+    GPIO_InitStruct.Pull = 1;  // GPIO_NOPULL
203
+    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
204
+
205
+    #if DISABLED(STM32F1xx)
206
+      GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
207
+    #endif
208
+
209
+    GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_12;  // D0 & SCK
210
+    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
211
+
212
+    #if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3)  // define D1-D3 only if have a four bit wide SDIO bus
213
+      GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11;  // D1-D3
214
+      HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
215
+    #endif
216
+
217
+    // Configure PD.02 CMD line
218
+    GPIO_InitStruct.Pin = GPIO_PIN_2;
219
+    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
220
+
221
+    // Setup DMA
222
+    #ifdef STM32F1xx
223
+      hdma_sdio.Init.Mode = DMA_NORMAL;
224
+      hdma_sdio.Instance = DMA2_Channel4;
225
+      HAL_NVIC_EnableIRQ(DMA2_Channel4_5_IRQn);
226
+    #elif defined(STM32F4xx)
227
+      hdma_sdio.Init.Mode = DMA_PFCTRL;
228
+      hdma_sdio.Instance = DMA2_Stream3;
229
+      hdma_sdio.Init.Channel = DMA_CHANNEL_4;
230
+      hdma_sdio.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
231
+      hdma_sdio.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
232
+      hdma_sdio.Init.MemBurst = DMA_MBURST_INC4;
233
+      hdma_sdio.Init.PeriphBurst = DMA_PBURST_INC4;
234
+      HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
235
+    #endif
236
+    HAL_NVIC_EnableIRQ(SDIO_IRQn);
124 237
     hdma_sdio.Init.PeriphInc = DMA_PINC_DISABLE;
125 238
     hdma_sdio.Init.MemInc = DMA_MINC_ENABLE;
126 239
     hdma_sdio.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
127 240
     hdma_sdio.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
128
-    hdma_sdio.Init.Mode = DMA_NORMAL;
129 241
     hdma_sdio.Init.Priority = DMA_PRIORITY_LOW;
130
-    HAL_DMA_Init(&hdma_sdio);
242
+    __HAL_LINKDMA(&hsd, hdmarx, hdma_sdio);
243
+    __HAL_LINKDMA(&hsd, hdmatx, hdma_sdio);
244
+
245
+    #ifdef STM32F1xx
246
+      __HAL_RCC_SDIO_CLK_ENABLE();
247
+      __HAL_RCC_DMA2_CLK_ENABLE();
248
+    #else
249
+      __HAL_RCC_SDIO_FORCE_RESET();   delay(2);
250
+      __HAL_RCC_SDIO_RELEASE_RESET(); delay(2);
251
+      __HAL_RCC_SDIO_CLK_ENABLE();
252
+
253
+      __HAL_RCC_DMA2_FORCE_RESET();   delay(2);
254
+      __HAL_RCC_DMA2_RELEASE_RESET(); delay(2);
255
+      __HAL_RCC_DMA2_CLK_ENABLE();
256
+    #endif
257
+
258
+    // Initialize the SDIO (with initial <400Khz Clock)
259
+    tempreg = 0                   // Reset value
260
+            | SDIO_CLKCR_CLKEN    // Clock enabled
261
+            | SDIO_INIT_CLK_DIV;  // Clock Divider. Clock = 48000 / (118 + 2) = 400Khz
262
+                                  // Keep the rest at 0 => HW_Flow Disabled, Rising Clock Edge, Disable CLK ByPass, Bus Width = 0, Power save Disable
263
+    SDIO->CLKCR = tempreg;
264
+
265
+    // Power up the SDIO
266
+    SDIO_PowerState_ON(SDIO);
267
+    hsd.Instance = SDIO;
268
+  }
131 269
 
132
-    __HAL_LINKDMA(hsd, hdmarx ,hdma_sdio);
133
-    __HAL_LINKDMA(hsd, hdmatx, hdma_sdio);
134
-  #elif defined(STM32F4xx)
135
-    __HAL_RCC_DMA2_CLK_ENABLE();
136
-    HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
137
-    HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);
138
-    hdma_sdio_rx.Instance = DMA2_Stream3;
139
-    hdma_sdio_rx.Init.Channel = DMA_CHANNEL_4;
140
-    hdma_sdio_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
141
-    hdma_sdio_rx.Init.PeriphInc = DMA_PINC_DISABLE;
142
-    hdma_sdio_rx.Init.MemInc = DMA_MINC_ENABLE;
143
-    hdma_sdio_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
144
-    hdma_sdio_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
145
-    hdma_sdio_rx.Init.Mode = DMA_PFCTRL;
146
-    hdma_sdio_rx.Init.Priority = DMA_PRIORITY_LOW;
147
-    hdma_sdio_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
148
-    hdma_sdio_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
149
-    hdma_sdio_rx.Init.MemBurst = DMA_MBURST_INC4;
150
-    hdma_sdio_rx.Init.PeriphBurst = DMA_PBURST_INC4;
151
-    HAL_DMA_Init(&hdma_sdio_rx);
152
-
153
-    __HAL_LINKDMA(hsd,hdmarx,hdma_sdio_rx);
154
-
155
-    hdma_sdio_tx.Instance = DMA2_Stream6;
156
-    hdma_sdio_tx.Init.Channel = DMA_CHANNEL_4;
157
-    hdma_sdio_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
158
-    hdma_sdio_tx.Init.PeriphInc = DMA_PINC_DISABLE;
159
-    hdma_sdio_tx.Init.MemInc = DMA_MINC_ENABLE;
160
-    hdma_sdio_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
161
-    hdma_sdio_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
162
-    hdma_sdio_tx.Init.Mode = DMA_PFCTRL;
163
-    hdma_sdio_tx.Init.Priority = DMA_PRIORITY_LOW;
164
-    hdma_sdio_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
165
-    hdma_sdio_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
166
-    hdma_sdio_tx.Init.MemBurst = DMA_MBURST_INC4;
167
-    hdma_sdio_tx.Init.PeriphBurst = DMA_PBURST_INC4;
168
-    HAL_DMA_Init(&hdma_sdio_tx);
169
-
170
-    __HAL_LINKDMA(hsd,hdmatx,hdma_sdio_tx);
171
-  #endif
172
-}
270
+  bool SDIO_Init() {
271
+    uint8_t retryCnt = SDIO_READ_RETRIES;
173 272
 
174
-void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd) {
175
-  #if !defined(STM32F1xx)
176
-    __HAL_RCC_SDIO_FORCE_RESET();
177
-    delay(10);
178
-    __HAL_RCC_SDIO_RELEASE_RESET();
179
-    delay(10);
180
-  #endif
181
-}
273
+    bool status;
274
+    hsd.Instance = SDIO;
275
+    hsd.State = HAL_SD_STATE_RESET;
182 276
 
183
-static uint32_t clock_to_divider(uint32_t clk) {
184
-  #if defined(STM32H7xx)
185
-    // SDMMC_CK frequency = sdmmc_ker_ck / [2 * CLKDIV].
186
-    uint32_t sdmmc_clk     = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC);
187
-    return sdmmc_clk / (2U * SDIO_CLOCK) + (sdmmc_clk % (2U * SDIO_CLOCK) != 0);
188
-  #else
189
-    // limit the SDIO master clock to 8/3 of PCLK2. See STM32 Manuals
190
-    // Also limited to no more than 48Mhz (SDIOCLK).
191
-    const uint32_t pclk2 = HAL_RCC_GetPCLK2Freq();
192
-    clk = min(clk, (uint32_t)(pclk2 * 8 / 3));
193
-    clk = min(clk, (uint32_t)SDIOCLK);
194
-    // Round up divider, so we don't run the card over the speed supported,
195
-    // and subtract by 2, because STM32 will add 2, as written in the manual:
196
-    // SDIO_CK frequency = SDIOCLK / [CLKDIV + 2]
197
-    return pclk2 / clk + (pclk2 % clk != 0) - 2;
198
-  #endif
199
-}
277
+    SD_LowLevel_Init();
200 278
 
201
-bool SDIO_Init() {
202
-  HAL_StatusTypeDef sd_state = HAL_OK;
203
-  if (hsd.Instance == SDIO)
204
-    HAL_SD_DeInit(&hsd);
205
-
206
-  /* HAL SD initialization */
207
-  hsd.Instance = SDIO;
208
-  hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
209
-  hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
210
-  hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
211
-  hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
212
-  hsd.Init.ClockDiv = clock_to_divider(SDIO_CLOCK);
213
-  sd_state = HAL_SD_Init(&hsd);
214
-
215
-  #if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3)
216
-    if (sd_state == HAL_OK) {
217
-      sd_state = HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B);
279
+    uint8_t retry_Cnt = retryCnt;
280
+    for (;;) {
281
+      hal.watchdog_refresh();
282
+      status = (bool) HAL_SD_Init(&hsd);
283
+      if (!status) break;
284
+      if (!--retry_Cnt) return false;   // return failing status if retries are exhausted
218 285
     }
219
-  #endif
220 286
 
221
-  return (sd_state == HAL_OK) ? true : false;
222
-}
287
+    go_to_transfer_speed();
288
+
289
+    #if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3) // go to 4 bit wide mode if pins are defined
290
+      retry_Cnt = retryCnt;
291
+      for (;;) {
292
+        hal.watchdog_refresh();
293
+        if (!HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B)) break;  // some cards are only 1 bit wide so a pass here is not required
294
+        if (!--retry_Cnt) break;
295
+      }
296
+      if (!retry_Cnt) {  // wide bus failed, go back to one bit wide mode
297
+        hsd.State = (HAL_SD_StateTypeDef) 0;  // HAL_SD_STATE_RESET
298
+        SD_LowLevel_Init();
299
+        retry_Cnt = retryCnt;
300
+        for (;;) {
301
+          hal.watchdog_refresh();
302
+          status = (bool) HAL_SD_Init(&hsd);
303
+          if (!status) break;
304
+          if (!--retry_Cnt) return false;   // return failing status if retries are exhausted
305
+        }
306
+        go_to_transfer_speed();
307
+      }
308
+    #endif
309
+
310
+    return true;
311
+  }
223 312
 
224
-bool SDIO_ReadBlock(uint32_t block, uint8_t *dst) {
225
-  uint32_t timeout = HAL_GetTick() + SD_TIMEOUT;
313
+  /**
314
+   * @brief Read or Write a block
315
+   * @details Read or Write a block with SDIO
316
+   *
317
+   * @param block The block index
318
+   * @param src The data buffer source for a write
319
+   * @param dst The data buffer destination for a read
320
+   *
321
+   * @return true on success
322
+   */
323
+  static bool SDIO_ReadWriteBlock_DMA(uint32_t block, const uint8_t *src, uint8_t *dst) {
324
+    if (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) return false;
325
+
326
+    hal.watchdog_refresh();
327
+
328
+    HAL_StatusTypeDef ret;
329
+    if (src) {
330
+      hdma_sdio.Init.Direction = DMA_MEMORY_TO_PERIPH;
331
+      HAL_DMA_Init(&hdma_sdio);
332
+      ret = HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t*)src, block, 1);
333
+    }
334
+    else {
335
+      hdma_sdio.Init.Direction = DMA_PERIPH_TO_MEMORY;
336
+      HAL_DMA_Init(&hdma_sdio);
337
+      ret = HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t*)dst, block, 1);
338
+    }
226 339
 
227
-  while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) {
228
-    if (HAL_GetTick() >= timeout) return false;
340
+    if (ret != HAL_OK) {
341
+      HAL_DMA_Abort_IT(&hdma_sdio);
342
+      HAL_DMA_DeInit(&hdma_sdio);
343
+      return false;
344
+    }
345
+
346
+    millis_t timeout = millis() + SD_TIMEOUT;
347
+    // Wait the transfer
348
+    while (hsd.State != HAL_SD_STATE_READY) {
349
+      if (ELAPSED(millis(), timeout)) {
350
+        HAL_DMA_Abort_IT(&hdma_sdio);
351
+        HAL_DMA_DeInit(&hdma_sdio);
352
+        return false;
353
+      }
354
+    }
355
+
356
+    while (__HAL_DMA_GET_FLAG(&hdma_sdio, __HAL_DMA_GET_TC_FLAG_INDEX(&hdma_sdio)) != 0
357
+        || __HAL_DMA_GET_FLAG(&hdma_sdio, __HAL_DMA_GET_TE_FLAG_INDEX(&hdma_sdio)) != 0) { /* nada */ }
358
+
359
+    HAL_DMA_Abort_IT(&hdma_sdio);
360
+    HAL_DMA_DeInit(&hdma_sdio);
361
+
362
+    timeout = millis() + SD_TIMEOUT;
363
+    while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) if (ELAPSED(millis(), timeout)) return false;
364
+
365
+    return true;
229 366
   }
230 367
 
231
-  waitingRxCplt = 1;
232
-  if (HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t *)dst, block, 1) != HAL_OK)
233
-    return false;
368
+#endif // !SDIO_FOR_STM32H7
369
+
370
+/**
371
+ * @brief Read a block
372
+ * @details Read a block from media with SDIO
373
+ *
374
+ * @param block The block index
375
+ * @param src The block buffer
376
+ *
377
+ * @return true on success
378
+ */
379
+bool SDIO_ReadBlock(uint32_t block, uint8_t *dst) {
380
+  #ifdef SDIO_FOR_STM32H7
381
+
382
+    uint32_t timeout = HAL_GetTick() + SD_TIMEOUT;
383
+
384
+    while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER)
385
+      if (HAL_GetTick() >= timeout) return false;
234 386
 
235
-  timeout = HAL_GetTick() + SD_TIMEOUT;
236
-  while (waitingRxCplt)
237
-    if (HAL_GetTick() >= timeout) return false;
387
+    waitingRxCplt = 1;
388
+    if (HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t*)dst, block, 1) != HAL_OK)
389
+      return false;
390
+
391
+    timeout = HAL_GetTick() + SD_TIMEOUT;
392
+    while (waitingRxCplt)
393
+      if (HAL_GetTick() >= timeout) return false;
394
+
395
+    return true;
396
+
397
+  #else
398
+
399
+    uint8_t retries = SDIO_READ_RETRIES;
400
+    while (retries--) if (SDIO_ReadWriteBlock_DMA(block, nullptr, dst)) return true;
401
+    return false;
238 402
 
239
-  return true;
403
+  #endif
240 404
 }
241 405
 
406
+/**
407
+ * @brief Write a block
408
+ * @details Write a block to media with SDIO
409
+ *
410
+ * @param block The block index
411
+ * @param src The block data
412
+ *
413
+ * @return true on success
414
+ */
242 415
 bool SDIO_WriteBlock(uint32_t block, const uint8_t *src) {
243
-  uint32_t timeout = HAL_GetTick() + SD_TIMEOUT;
416
+  #ifdef SDIO_FOR_STM32H7
244 417
 
245
-  while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER)
246
-    if (HAL_GetTick() >= timeout) return false;
418
+    uint32_t timeout = HAL_GetTick() + SD_TIMEOUT;
247 419
 
248
-  waitingTxCplt = 1;
249
-  if (HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t *)src, block, 1) != HAL_OK)
250
-    return false;
420
+    while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER)
421
+      if (HAL_GetTick() >= timeout) return false;
422
+
423
+    waitingTxCplt = 1;
424
+    if (HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t*)src, block, 1) != HAL_OK)
425
+      return false;
251 426
 
252
-  timeout = HAL_GetTick() + SD_TIMEOUT;
253
-  while (waitingTxCplt)
254
-    if (HAL_GetTick() >= timeout) return false;
427
+    timeout = HAL_GetTick() + SD_TIMEOUT;
428
+    while (waitingTxCplt)
429
+      if (HAL_GetTick() >= timeout) return false;
255 430
 
256
-  return true;
431
+    return true;
432
+
433
+  #else
434
+
435
+    uint8_t retries = SDIO_READ_RETRIES;
436
+    while (retries--) if (SDIO_ReadWriteBlock_DMA(block, src, nullptr)) return true;
437
+    return false;
438
+
439
+  #endif
257 440
 }
258 441
 
259 442
 bool SDIO_IsReady() {

Loading…
İptal
Kaydet