|
@@ -88,18 +88,37 @@
|
88
|
88
|
|
89
|
89
|
MKS Robin board seems to have stable SDIO with BusWide 1bit and ClockDiv 8 i.e. 4.8MHz SDIO clock frequency
|
90
|
90
|
Additional testing is required as there are clearly some 4bit initialization problems
|
91
|
|
-
|
92
|
|
- Add -DTRANSFER_CLOCK_DIV=8 to build parameters to improve SDIO stability
|
93
|
91
|
*/
|
94
|
92
|
|
95
|
|
- #ifndef TRANSFER_CLOCK_DIV
|
96
|
|
- #define TRANSFER_CLOCK_DIV (uint8_t(SDIO_INIT_CLK_DIV) / 40)
|
97
|
|
- #endif
|
98
|
|
-
|
99
|
93
|
#ifndef USBD_OK
|
100
|
94
|
#define USBD_OK 0
|
101
|
95
|
#endif
|
102
|
96
|
|
|
97
|
+ // Target Clock, configurable. Default is 18MHz, from STM32F1
|
|
98
|
+ #ifndef SDIO_CLOCK
|
|
99
|
+ #define SDIO_CLOCK 18000000 /* 18 MHz */
|
|
100
|
+ #endif
|
|
101
|
+
|
|
102
|
+ // SDIO retries, configurable. Default is 3, from STM32F1
|
|
103
|
+ #ifndef SDIO_READ_RETRIES
|
|
104
|
+ #define SDIO_READ_RETRIES 3
|
|
105
|
+ #endif
|
|
106
|
+
|
|
107
|
+ // SDIO Max Clock (naming from STM Manual, don't change)
|
|
108
|
+ #define SDIOCLK 48000000
|
|
109
|
+
|
|
110
|
+ static uint32_t clock_to_divider(uint32_t clk) {
|
|
111
|
+ // limit the SDIO master clock to 8/3 of PCLK2. See STM32 Manuals
|
|
112
|
+ // Also limited to no more than 48Mhz (SDIOCLK).
|
|
113
|
+ const uint32_t pclk2 = HAL_RCC_GetPCLK2Freq();
|
|
114
|
+ clk = min(clk, (uint32_t)(pclk2 * 8 / 3));
|
|
115
|
+ clk = min(clk, (uint32_t)SDIOCLK);
|
|
116
|
+ // Round up divider, so we don't run the card over the speed supported,
|
|
117
|
+ // and subtract by 2, because STM32 will add 2, as written in the manual:
|
|
118
|
+ // SDIO_CK frequency = SDIOCLK / [CLKDIV + 2]
|
|
119
|
+ return pclk2 / clk + (pclk2 % clk != 0) - 2;
|
|
120
|
+ }
|
|
121
|
+
|
103
|
122
|
void go_to_transfer_speed() {
|
104
|
123
|
SD_InitTypeDef Init;
|
105
|
124
|
|
|
@@ -109,7 +128,7 @@
|
109
|
128
|
Init.ClockPowerSave = hsd.Init.ClockPowerSave;
|
110
|
129
|
Init.BusWide = hsd.Init.BusWide;
|
111
|
130
|
Init.HardwareFlowControl = hsd.Init.HardwareFlowControl;
|
112
|
|
- Init.ClockDiv = TRANSFER_CLOCK_DIV;
|
|
131
|
+ Init.ClockDiv = clock_to_divider(SDIO_CLOCK);
|
113
|
132
|
|
114
|
133
|
/* Initialize SDIO peripheral interface with default configuration */
|
115
|
134
|
SDIO_Init(hsd.Instance, Init);
|
|
@@ -155,38 +174,25 @@
|
155
|
174
|
//Initialize the SDIO (with initial <400Khz Clock)
|
156
|
175
|
tempreg = 0; //Reset value
|
157
|
176
|
tempreg |= SDIO_CLKCR_CLKEN; // Clock enabled
|
158
|
|
- tempreg |= (uint32_t)0x76; // Clock Divider. Clock = 48000 / (118 + 2) = 400Khz
|
|
177
|
+ tempreg |= SDIO_INIT_CLK_DIV; // Clock Divider. Clock = 48000 / (118 + 2) = 400Khz
|
159
|
178
|
// Keep the rest at 0 => HW_Flow Disabled, Rising Clock Edge, Disable CLK ByPass, Bus Width = 0, Power save Disable
|
160
|
179
|
SDIO->CLKCR = tempreg;
|
161
|
180
|
|
162
|
181
|
// Power up the SDIO
|
163
|
|
- SDIO->POWER = 0x03;
|
|
182
|
+ SDIO_PowerState_ON(SDIO);
|
164
|
183
|
}
|
165
|
184
|
|
166
|
185
|
void HAL_SD_MspInit(SD_HandleTypeDef *hsd) { // application specific init
|
167
|
|
- UNUSED(hsd); /* Prevent unused argument(s) compilation warning */
|
|
186
|
+ UNUSED(hsd); // Prevent unused argument(s) compilation warning
|
168
|
187
|
__HAL_RCC_SDIO_CLK_ENABLE(); // turn on SDIO clock
|
169
|
188
|
}
|
170
|
189
|
|
171
|
|
- constexpr uint8_t SD_RETRY_COUNT = TERN(SD_CHECK_AND_RETRY, 3, 1);
|
172
|
|
-
|
173
|
190
|
bool SDIO_Init() {
|
174
|
|
- //init SDIO and get SD card info
|
175
|
|
-
|
176
|
|
- uint8_t retryCnt = SD_RETRY_COUNT;
|
|
191
|
+ uint8_t retryCnt = SDIO_READ_RETRIES;
|
177
|
192
|
|
178
|
193
|
bool status;
|
179
|
194
|
hsd.Instance = SDIO;
|
180
|
|
- hsd.State = (HAL_SD_StateTypeDef) 0; // HAL_SD_STATE_RESET
|
181
|
|
-
|
182
|
|
- /*
|
183
|
|
- hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
|
184
|
|
- hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
|
185
|
|
- hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
|
186
|
|
- hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
|
187
|
|
- hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
|
188
|
|
- hsd.Init.ClockDiv = 8;
|
189
|
|
- */
|
|
195
|
+ hsd.State = HAL_SD_STATE_RESET;
|
190
|
196
|
|
191
|
197
|
SD_LowLevel_Init();
|
192
|
198
|
|
|
@@ -258,7 +264,7 @@
|
258
|
264
|
|
259
|
265
|
bool SDIO_ReadBlock(uint32_t block, uint8_t *dst) {
|
260
|
266
|
hsd.Instance = SDIO;
|
261
|
|
- uint8_t retryCnt = SD_RETRY_COUNT;
|
|
267
|
+ uint8_t retryCnt = SDIO_READ_RETRIES;
|
262
|
268
|
|
263
|
269
|
bool status;
|
264
|
270
|
for (;;) {
|
|
@@ -307,7 +313,7 @@
|
307
|
313
|
|
308
|
314
|
bool SDIO_WriteBlock(uint32_t block, const uint8_t *src) {
|
309
|
315
|
hsd.Instance = SDIO;
|
310
|
|
- uint8_t retryCnt = SD_RETRY_COUNT;
|
|
316
|
+ uint8_t retryCnt = SDIO_READ_RETRIES;
|
311
|
317
|
bool status;
|
312
|
318
|
for (;;) {
|
313
|
319
|
status = (bool) HAL_SD_WriteBlocks(&hsd, (uint8_t*)src, block, 1, 500); // write one 512 byte block with 500mS timeout
|