mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-08-18 02:58:57 +08:00
fix[stm32][spi]: add usage_freq and compute transfer timeout by frequency
RT-Thread BSP Static Build Check / 🔍 Summary of Git Diff Changes (push) Has been cancelled
doc_doxygen / doxygen_doc generate (push) Has been cancelled
pkgs_test / change (push) Has been cancelled
utest_auto_run / A9 :components/dfs.cfg (push) Has been cancelled
utest_auto_run / A9 :components/lwip.cfg (push) Has been cancelled
utest_auto_run / A9 :components/netdev.cfg (push) Has been cancelled
utest_auto_run / A9 :components/sal.cfg (push) Has been cancelled
utest_auto_run / A9 :cpp11/cpp11.cfg (push) Has been cancelled
utest_auto_run / AARCH64-rtsmart :default.cfg (push) Has been cancelled
utest_auto_run / A9-rtsmart :default.cfg (push) Has been cancelled
utest_auto_run / RISCV-rtsmart :default.cfg (push) Has been cancelled
utest_auto_run / XUANTIE-rtsmart :default.cfg (push) Has been cancelled
utest_auto_run / AARCH64 :default.cfg (push) Has been cancelled
utest_auto_run / AARCH64-smp :default.cfg (push) Has been cancelled
utest_auto_run / A9 :default.cfg (push) Has been cancelled
utest_auto_run / A9-smp :default.cfg (push) Has been cancelled
utest_auto_run / RISCV :default.cfg (push) Has been cancelled
utest_auto_run / RISCV-smp :default.cfg (push) Has been cancelled
utest_auto_run / A9 :kernel/atomic_c11.cfg (push) Has been cancelled
utest_auto_run / RISCV :kernel/atomic_c11.cfg (push) Has been cancelled
utest_auto_run / A9 :kernel/ipc.cfg (push) Has been cancelled
utest_auto_run / A9 :kernel/kernel_basic.cfg (push) Has been cancelled
utest_auto_run / A9 :kernel/mem.cfg (push) Has been cancelled
RT-Thread BSP Static Build Check / ${{ matrix.legs.RTT_BSP }} (push) Has been cancelled
RT-Thread BSP Static Build Check / collect-artifacts (push) Has been cancelled
doc_doxygen / deploy (push) Has been cancelled
Weekly CI Scheduler / Trigger and Monitor CIs (push) Has been cancelled
Weekly CI Scheduler / Create Discussion Report (push) Has been cancelled
RT-Thread BSP Static Build Check / 🔍 Summary of Git Diff Changes (push) Has been cancelled
doc_doxygen / doxygen_doc generate (push) Has been cancelled
pkgs_test / change (push) Has been cancelled
utest_auto_run / A9 :components/dfs.cfg (push) Has been cancelled
utest_auto_run / A9 :components/lwip.cfg (push) Has been cancelled
utest_auto_run / A9 :components/netdev.cfg (push) Has been cancelled
utest_auto_run / A9 :components/sal.cfg (push) Has been cancelled
utest_auto_run / A9 :cpp11/cpp11.cfg (push) Has been cancelled
utest_auto_run / AARCH64-rtsmart :default.cfg (push) Has been cancelled
utest_auto_run / A9-rtsmart :default.cfg (push) Has been cancelled
utest_auto_run / RISCV-rtsmart :default.cfg (push) Has been cancelled
utest_auto_run / XUANTIE-rtsmart :default.cfg (push) Has been cancelled
utest_auto_run / AARCH64 :default.cfg (push) Has been cancelled
utest_auto_run / AARCH64-smp :default.cfg (push) Has been cancelled
utest_auto_run / A9 :default.cfg (push) Has been cancelled
utest_auto_run / A9-smp :default.cfg (push) Has been cancelled
utest_auto_run / RISCV :default.cfg (push) Has been cancelled
utest_auto_run / RISCV-smp :default.cfg (push) Has been cancelled
utest_auto_run / A9 :kernel/atomic_c11.cfg (push) Has been cancelled
utest_auto_run / RISCV :kernel/atomic_c11.cfg (push) Has been cancelled
utest_auto_run / A9 :kernel/ipc.cfg (push) Has been cancelled
utest_auto_run / A9 :kernel/kernel_basic.cfg (push) Has been cancelled
utest_auto_run / A9 :kernel/mem.cfg (push) Has been cancelled
RT-Thread BSP Static Build Check / ${{ matrix.legs.RTT_BSP }} (push) Has been cancelled
RT-Thread BSP Static Build Check / collect-artifacts (push) Has been cancelled
doc_doxygen / deploy (push) Has been cancelled
Weekly CI Scheduler / Trigger and Monitor CIs (push) Has been cancelled
Weekly CI Scheduler / Create Discussion Report (push) Has been cancelled
This commit is contained in:
@@ -138,54 +138,54 @@ static rt_err_t stm32_spi_init(struct stm32_spi *spi_drv, struct rt_spi_configur
|
||||
|
||||
spi_handle->Init.NSS = SPI_NSS_SOFT;
|
||||
|
||||
uint32_t SPI_CLOCK = 0UL;
|
||||
uint32_t spi_clock = 0UL;
|
||||
/* Some series may only have APBPERIPH_BASE, but don't have HAL_RCC_GetPCLK2Freq */
|
||||
#if defined(APBPERIPH_BASE)
|
||||
SPI_CLOCK = HAL_RCC_GetPCLK1Freq();
|
||||
spi_clock = HAL_RCC_GetPCLK1Freq();
|
||||
#elif defined(APB1PERIPH_BASE) || defined(APB2PERIPH_BASE)
|
||||
/* The SPI clock for H7 cannot be configured with a peripheral bus clock, so it needs to be written separately */
|
||||
#if defined(SOC_SERIES_STM32H7)
|
||||
/* When the configuration is generated using CUBEMX, the configuration for the SPI clock is placed in the HAL_SPI_Init function.
|
||||
Therefore, it is necessary to initialize and configure the SPI clock to automatically configure the frequency division */
|
||||
HAL_SPI_Init(spi_handle);
|
||||
SPI_CLOCK = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI123);
|
||||
spi_clock = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI123);
|
||||
#else
|
||||
if ((rt_uint32_t)spi_drv->config->Instance >= APB2PERIPH_BASE)
|
||||
{
|
||||
SPI_CLOCK = HAL_RCC_GetPCLK2Freq();
|
||||
spi_clock = HAL_RCC_GetPCLK2Freq();
|
||||
}
|
||||
else
|
||||
{
|
||||
SPI_CLOCK = HAL_RCC_GetPCLK1Freq();
|
||||
spi_clock = HAL_RCC_GetPCLK1Freq();
|
||||
}
|
||||
#endif /* SOC_SERIES_STM32H7) */
|
||||
#endif /* APBPERIPH_BASE */
|
||||
|
||||
if (cfg->max_hz >= SPI_CLOCK / 2)
|
||||
if (cfg->max_hz >= spi_clock / 2)
|
||||
{
|
||||
spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
|
||||
}
|
||||
else if (cfg->max_hz >= SPI_CLOCK / 4)
|
||||
else if (cfg->max_hz >= spi_clock / 4)
|
||||
{
|
||||
spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
|
||||
}
|
||||
else if (cfg->max_hz >= SPI_CLOCK / 8)
|
||||
else if (cfg->max_hz >= spi_clock / 8)
|
||||
{
|
||||
spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
|
||||
}
|
||||
else if (cfg->max_hz >= SPI_CLOCK / 16)
|
||||
else if (cfg->max_hz >= spi_clock / 16)
|
||||
{
|
||||
spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
|
||||
}
|
||||
else if (cfg->max_hz >= SPI_CLOCK / 32)
|
||||
else if (cfg->max_hz >= spi_clock / 32)
|
||||
{
|
||||
spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
|
||||
}
|
||||
else if (cfg->max_hz >= SPI_CLOCK / 64)
|
||||
else if (cfg->max_hz >= spi_clock / 64)
|
||||
{
|
||||
spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
|
||||
}
|
||||
else if (cfg->max_hz >= SPI_CLOCK / 128)
|
||||
else if (cfg->max_hz >= spi_clock / 128)
|
||||
{
|
||||
spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
|
||||
}
|
||||
@@ -195,15 +195,21 @@ static rt_err_t stm32_spi_init(struct stm32_spi *spi_drv, struct rt_spi_configur
|
||||
spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
|
||||
}
|
||||
|
||||
#if defined(SOC_SERIES_STM32H7)
|
||||
cfg->usage_freq = spi_clock / (rt_size_t)(1 << ((spi_handle->Init.BaudRatePrescaler >> SPI_CFG1_MBR_Pos) + 1));
|
||||
#else
|
||||
cfg->usage_freq = spi_clock / (rt_size_t)(1 << ((spi_handle->Init.BaudRatePrescaler >> SPI_CR1_BR_Pos) + 1));
|
||||
#endif /* SOC_SERIES_STM32H7 */
|
||||
|
||||
LOG_D("sys freq: %d, pclk freq: %d, SPI limiting freq: %d, SPI usage freq: %d",
|
||||
#if defined(SOC_SERIES_STM32MP1)
|
||||
HAL_RCC_GetSystemCoreClockFreq(),
|
||||
#else
|
||||
HAL_RCC_GetSysClockFreq(),
|
||||
#endif
|
||||
SPI_CLOCK,
|
||||
spi_clock,
|
||||
cfg->max_hz,
|
||||
SPI_CLOCK / (rt_size_t)pow(2,(spi_handle->Init.BaudRatePrescaler >> 28) + 1));
|
||||
cfg->usage_freq);
|
||||
|
||||
if (cfg->mode & RT_SPI_MSB)
|
||||
{
|
||||
@@ -294,6 +300,15 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
|
||||
|
||||
struct stm32_spi *spi_drv = rt_container_of(device->bus, struct stm32_spi, spi_bus);
|
||||
SPI_HandleTypeDef *spi_handle = &spi_drv->handle;
|
||||
rt_uint64_t total_byte_ms = (rt_uint64_t)message->length * 1000;
|
||||
rt_uint32_t speed_bytes_per_sec = spi_drv->cfg->usage_freq / 8;
|
||||
if (speed_bytes_per_sec == 0)
|
||||
{
|
||||
speed_bytes_per_sec = 1;
|
||||
}
|
||||
|
||||
rt_uint32_t timeout_ms = total_byte_ms / speed_bytes_per_sec + 100;
|
||||
rt_tick_t timeout_tick = rt_tick_from_millisecond(timeout_ms);
|
||||
|
||||
if (message->cs_take && !(device->config.mode & RT_SPI_NO_CS) && (device->cs_pin != PIN_NONE))
|
||||
{
|
||||
@@ -424,7 +439,7 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
|
||||
}
|
||||
else
|
||||
{
|
||||
state = HAL_SPI_TransmitReceive(spi_handle, (uint8_t *)send_buf, (uint8_t *)recv_buf, send_length, 1000);
|
||||
state = HAL_SPI_TransmitReceive(spi_handle, (uint8_t *)send_buf, (uint8_t *)recv_buf, send_length, timeout_ms);
|
||||
}
|
||||
}
|
||||
else if (message->send_buf)
|
||||
@@ -435,7 +450,7 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
|
||||
}
|
||||
else
|
||||
{
|
||||
state = HAL_SPI_Transmit(spi_handle, (uint8_t *)send_buf, send_length, 1000);
|
||||
state = HAL_SPI_Transmit(spi_handle, (uint8_t *)send_buf, send_length, timeout_ms);
|
||||
}
|
||||
|
||||
if (message->cs_release && (device->config.mode & RT_SPI_3WIRE))
|
||||
@@ -455,7 +470,7 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
|
||||
{
|
||||
/* clear the old error flag */
|
||||
__HAL_SPI_CLEAR_OVRFLAG(spi_handle);
|
||||
state = HAL_SPI_Receive(spi_handle, (uint8_t *)recv_buf, send_length, 1000);
|
||||
state = HAL_SPI_Receive(spi_handle, (uint8_t *)recv_buf, send_length, timeout_ms);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -482,7 +497,7 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
|
||||
if ((spi_drv->spi_dma_flag & (SPI_USING_TX_DMA_FLAG | SPI_USING_RX_DMA_FLAG)) && (send_length >= DMA_TRANS_MIN_LEN))
|
||||
{
|
||||
/* blocking the thread,and the other tasks can run */
|
||||
if (rt_completion_wait(&spi_drv->cpt, 1000) != RT_EOK)
|
||||
if (rt_completion_wait(&spi_drv->cpt, timeout_tick) != RT_EOK)
|
||||
{
|
||||
state = HAL_ERROR;
|
||||
LOG_E("wait for DMA interrupt overtime!");
|
||||
@@ -491,7 +506,20 @@ static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *m
|
||||
}
|
||||
else
|
||||
{
|
||||
while (HAL_SPI_GetState(spi_handle) != HAL_SPI_STATE_READY);
|
||||
rt_uint32_t timeout = timeout_ms;
|
||||
while (HAL_SPI_GetState(spi_handle) != HAL_SPI_STATE_READY)
|
||||
{
|
||||
if (timeout-- > 0)
|
||||
{
|
||||
rt_thread_mdelay(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_E("timeout! SPI state did not become READY.");
|
||||
state = HAL_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(dma_aligned_buffer != RT_NULL) /* re-aligned, so need to copy the data to recv_buf */
|
||||
|
||||
@@ -161,6 +161,7 @@ struct rt_spi_configuration
|
||||
#endif
|
||||
|
||||
rt_uint32_t max_hz;
|
||||
rt_uint32_t usage_freq;
|
||||
};
|
||||
|
||||
struct rt_spi_ops;
|
||||
|
||||
Reference in New Issue
Block a user