|
35 | 35 | *
|
36 | 36 | ******************************************************************************
|
37 | 37 | */
|
| 38 | +#include "wiring_time.h" |
38 | 39 | #include "core_debug.h"
|
39 | 40 | #include "stm32_def.h"
|
40 | 41 | #include "utility/spi_com.h"
|
@@ -183,6 +184,28 @@ uint32_t spi_getClkFreq(spi_t *obj)
|
183 | 184 | return spi_freq;
|
184 | 185 | }
|
185 | 186 |
|
| 187 | + |
| 188 | +#if defined(STM32H7xx) || defined(STM32MP1xx) |
| 189 | +/** |
| 190 | + * @brief Compute delay before disabling SPI |
| 191 | + * See https://github.com/stm32duino/Arduino_Core_STM32/issues/1294 |
| 192 | + * Computed delay is half SPI clock |
| 193 | + * @param obj : pointer to spi_t structure |
| 194 | + * @retval Disable delay in microsecondes |
| 195 | + */ |
| 196 | +static uint32_t compute_disable_delay(spi_t *obj) |
| 197 | +{ |
| 198 | + uint32_t spi_freq = spi_getClkFreqInst(obj->spi); |
| 199 | + uint32_t disable_delay; |
| 200 | + uint32_t prescaler; |
| 201 | + SPI_HandleTypeDef *handle = &(obj->handle); |
| 202 | + |
| 203 | + prescaler = 1 << ((handle->Init.BaudRatePrescaler >> SPI_CFG1_MBR_Pos) + 1); |
| 204 | + disable_delay = ((prescaler * 1000000) / spi_freq) / 2; |
| 205 | + return disable_delay; |
| 206 | +} |
| 207 | +#endif |
| 208 | + |
186 | 209 | /**
|
187 | 210 | * @brief SPI initialization function
|
188 | 211 | * @param obj : pointer to spi_t structure
|
@@ -258,6 +281,11 @@ void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb)
|
258 | 281 | handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
|
259 | 282 | }
|
260 | 283 |
|
| 284 | +#if defined(STM32H7xx) || defined(STM32MP1xx) |
| 285 | + // Compute disable delay as baudrate has been modified |
| 286 | + obj->disable_delay = compute_disable_delay(obj); |
| 287 | +#endif |
| 288 | + |
261 | 289 | handle->Init.Direction = SPI_DIRECTION_2LINES;
|
262 | 290 |
|
263 | 291 | if ((mode == SPI_MODE_0) || (mode == SPI_MODE_2)) {
|
@@ -490,6 +518,11 @@ spi_status_e spi_transfer(spi_t *obj, uint8_t *tx_buffer, uint8_t *rx_buffer,
|
490 | 518 | }
|
491 | 519 |
|
492 | 520 | #if defined(STM32H7xx) || defined(STM32MP1xx)
|
| 521 | + // Add a delay before disabling SPI otherwise last-bit/last-clock may be truncated |
| 522 | + // See https://github.com/stm32duino/Arduino_Core_STM32/issues/1294 |
| 523 | + // Computed delay is half SPI clock |
| 524 | + delayMicroseconds(obj->disable_delay); |
| 525 | + |
493 | 526 | /* Close transfer */
|
494 | 527 | /* Clear flags */
|
495 | 528 | LL_SPI_ClearFlag_EOT(_SPI);
|
|
0 commit comments