Skip to content

Commit 99c16be

Browse files
committed
fix[stm32][spi]: add usage_freq and compute transfer timeout by frequency
1 parent fe548e1 commit 99c16be

2 files changed

Lines changed: 44 additions & 19 deletions

File tree

  • bsp/stm32/libraries/HAL_Drivers/drivers
  • components/drivers/include/drivers

bsp/stm32/libraries/HAL_Drivers/drivers/drv_spi.c

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -138,54 +138,54 @@ static rt_err_t stm32_spi_init(struct stm32_spi *spi_drv, struct rt_spi_configur
138138

139139
spi_handle->Init.NSS = SPI_NSS_SOFT;
140140

141-
uint32_t SPI_CLOCK = 0UL;
141+
uint32_t spi_clock = 0UL;
142142
/* Some series may only have APBPERIPH_BASE, but don't have HAL_RCC_GetPCLK2Freq */
143143
#if defined(APBPERIPH_BASE)
144-
SPI_CLOCK = HAL_RCC_GetPCLK1Freq();
144+
spi_clock = HAL_RCC_GetPCLK1Freq();
145145
#elif defined(APB1PERIPH_BASE) || defined(APB2PERIPH_BASE)
146146
/* The SPI clock for H7 cannot be configured with a peripheral bus clock, so it needs to be written separately */
147147
#if defined(SOC_SERIES_STM32H7)
148148
/* When the configuration is generated using CUBEMX, the configuration for the SPI clock is placed in the HAL_SPI_Init function.
149149
Therefore, it is necessary to initialize and configure the SPI clock to automatically configure the frequency division */
150150
HAL_SPI_Init(spi_handle);
151-
SPI_CLOCK = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI123);
151+
spi_clock = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI123);
152152
#else
153153
if ((rt_uint32_t)spi_drv->config->Instance >= APB2PERIPH_BASE)
154154
{
155-
SPI_CLOCK = HAL_RCC_GetPCLK2Freq();
155+
spi_clock = HAL_RCC_GetPCLK2Freq();
156156
}
157157
else
158158
{
159-
SPI_CLOCK = HAL_RCC_GetPCLK1Freq();
159+
spi_clock = HAL_RCC_GetPCLK1Freq();
160160
}
161161
#endif /* SOC_SERIES_STM32H7) */
162162
#endif /* APBPERIPH_BASE */
163163

164-
if (cfg->max_hz >= SPI_CLOCK / 2)
164+
if (cfg->max_hz >= spi_clock / 2)
165165
{
166166
spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
167167
}
168-
else if (cfg->max_hz >= SPI_CLOCK / 4)
168+
else if (cfg->max_hz >= spi_clock / 4)
169169
{
170170
spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
171171
}
172-
else if (cfg->max_hz >= SPI_CLOCK / 8)
172+
else if (cfg->max_hz >= spi_clock / 8)
173173
{
174174
spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
175175
}
176-
else if (cfg->max_hz >= SPI_CLOCK / 16)
176+
else if (cfg->max_hz >= spi_clock / 16)
177177
{
178178
spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
179179
}
180-
else if (cfg->max_hz >= SPI_CLOCK / 32)
180+
else if (cfg->max_hz >= spi_clock / 32)
181181
{
182182
spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
183183
}
184-
else if (cfg->max_hz >= SPI_CLOCK / 64)
184+
else if (cfg->max_hz >= spi_clock / 64)
185185
{
186186
spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
187187
}
188-
else if (cfg->max_hz >= SPI_CLOCK / 128)
188+
else if (cfg->max_hz >= spi_clock / 128)
189189
{
190190
spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
191191
}
@@ -195,15 +195,17 @@ static rt_err_t stm32_spi_init(struct stm32_spi *spi_drv, struct rt_spi_configur
195195
spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
196196
}
197197

198+
cfg->usage_freq = spi_clock / (rt_size_t)(1 << ((spi_handle->Init.BaudRatePrescaler >> SPI_CR1_BR_Pos) + 1));
199+
198200
LOG_D("sys freq: %d, pclk freq: %d, SPI limiting freq: %d, SPI usage freq: %d",
199201
#if defined(SOC_SERIES_STM32MP1)
200202
HAL_RCC_GetSystemCoreClockFreq(),
201203
#else
202204
HAL_RCC_GetSysClockFreq(),
203205
#endif
204-
SPI_CLOCK,
206+
spi_clock,
205207
cfg->max_hz,
206-
SPI_CLOCK / (rt_size_t)pow(2,(spi_handle->Init.BaudRatePrescaler >> 28) + 1));
208+
cfg->usage_freq);
207209

208210
if (cfg->mode & RT_SPI_MSB)
209211
{
@@ -294,6 +296,15 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
294296

295297
struct stm32_spi *spi_drv = rt_container_of(device->bus, struct stm32_spi, spi_bus);
296298
SPI_HandleTypeDef *spi_handle = &spi_drv->handle;
299+
rt_uint64_t total_byte_ms = (rt_uint64_t)message->length * 1000;
300+
rt_uint32_t speed_bytes_per_sec = spi_drv->cfg->usage_freq / 8;
301+
if (speed_bytes_per_sec == 0)
302+
{
303+
speed_bytes_per_sec = 1;
304+
}
305+
306+
rt_uint32_t timeout_ms = total_byte_ms / speed_bytes_per_sec + 100;
307+
rt_tick_t timeout_tick = rt_tick_from_millisecond(timeout_ms);
297308

298309
if (message->cs_take && !(device->config.mode & RT_SPI_NO_CS) && (device->cs_pin != PIN_NONE))
299310
{
@@ -424,7 +435,7 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
424435
}
425436
else
426437
{
427-
state = HAL_SPI_TransmitReceive(spi_handle, (uint8_t *)send_buf, (uint8_t *)recv_buf, send_length, 1000);
438+
state = HAL_SPI_TransmitReceive(spi_handle, (uint8_t *)send_buf, (uint8_t *)recv_buf, send_length, timeout_ms);
428439
}
429440
}
430441
else if (message->send_buf)
@@ -435,7 +446,7 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
435446
}
436447
else
437448
{
438-
state = HAL_SPI_Transmit(spi_handle, (uint8_t *)send_buf, send_length, 1000);
449+
state = HAL_SPI_Transmit(spi_handle, (uint8_t *)send_buf, send_length, timeout_ms);
439450
}
440451

441452
if (message->cs_release && (device->config.mode & RT_SPI_3WIRE))
@@ -455,7 +466,7 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
455466
{
456467
/* clear the old error flag */
457468
__HAL_SPI_CLEAR_OVRFLAG(spi_handle);
458-
state = HAL_SPI_Receive(spi_handle, (uint8_t *)recv_buf, send_length, 1000);
469+
state = HAL_SPI_Receive(spi_handle, (uint8_t *)recv_buf, send_length, timeout_ms);
459470
}
460471
}
461472
else
@@ -482,7 +493,7 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
482493
if ((spi_drv->spi_dma_flag & (SPI_USING_TX_DMA_FLAG | SPI_USING_RX_DMA_FLAG)) && (send_length >= DMA_TRANS_MIN_LEN))
483494
{
484495
/* blocking the thread,and the other tasks can run */
485-
if (rt_completion_wait(&spi_drv->cpt, 1000) != RT_EOK)
496+
if (rt_completion_wait(&spi_drv->cpt, timeout_tick) != RT_EOK)
486497
{
487498
state = HAL_ERROR;
488499
LOG_E("wait for DMA interrupt overtime!");
@@ -491,7 +502,20 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
491502
}
492503
else
493504
{
494-
while (HAL_SPI_GetState(spi_handle) != HAL_SPI_STATE_READY);
505+
rt_uint32_t timeout = timeout_ms;
506+
while (HAL_SPI_GetState(spi_handle) != HAL_SPI_STATE_READY)
507+
{
508+
if (timeout-- > 0)
509+
{
510+
rt_thread_mdelay(1);
511+
}
512+
else
513+
{
514+
LOG_E("timeout! SPI state did not become READY.");
515+
state = HAL_TIMEOUT;
516+
break;
517+
}
518+
}
495519
}
496520

497521
if(dma_aligned_buffer != RT_NULL) /* re-aligned, so need to copy the data to recv_buf */

components/drivers/include/drivers/dev_spi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ struct rt_spi_configuration
161161
#endif
162162

163163
rt_uint32_t max_hz;
164+
rt_uint32_t usage_freq;
164165
};
165166

166167
struct rt_spi_ops;

0 commit comments

Comments
 (0)