Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug][serial_v1] 主频较高时可能会导致发送不完整 #9964

Open
kaidegit opened this issue Feb 3, 2025 · 10 comments
Open

[Bug][serial_v1] 主频较高时可能会导致发送不完整 #9964

kaidegit opened this issue Feb 3, 2025 · 10 comments

Comments

@kaidegit
Copy link
Contributor

kaidegit commented Feb 3, 2025

RT-Thread Version

master

Hardware Type/Architectures

H730 with internal flash

Develop Toolchain

MDK Keil

Describe the bug

在主频550M,打开优化时,使用rt_kprintf只能打出首字符。

调查发现在stm32的serial_v1驱动中,会使用一个较为硬编码(由库中define)的值检查是否发送超时。在主频较高且波特率较低时可能会触发。

static int stm32_putc(struct rt_serial_device *serial, char c)
{
struct stm32_uart *uart;
RT_ASSERT(serial != RT_NULL);
uart = rt_container_of(serial, struct stm32_uart, serial);
rt_uint32_t block_timeout = uart->tx_block_timeout;
UART_INSTANCE_CLEAR_FUNCTION(&(uart->handle), UART_FLAG_TC);
#if defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32WL) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32F0) \
|| defined(SOC_SERIES_STM32L0) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32H7) || defined(SOC_SERIES_STM32L5) \
|| defined(SOC_SERIES_STM32G4) || defined(SOC_SERIES_STM32MP1) || defined(SOC_SERIES_STM32WB) || defined(SOC_SERIES_STM32F3) \
|| defined(SOC_SERIES_STM32U5) || defined(SOC_SERIES_STM32H5) || defined(SOC_SERIES_STM32H7RS)
uart->handle.Instance->TDR = c;
#else
uart->handle.Instance->DR = c;
#endif
while (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_TC) == RESET && --block_timeout);
return (block_timeout != 0) ? 1 : -1;

rt_kpinrtf调用_kputs发送时未处理rt_device_write的返回值,没有重发。

rt-thread/src/kservice.c

Lines 312 to 335 in 0cc4dc4

static void _kputs(const char *str, long len)
{
#ifdef RT_USING_DEVICE
rt_device_t console_device = rt_console_get_device();
#endif /* RT_USING_DEVICE */
CONSOLE_TAKE;
#ifdef RT_USING_DEVICE
if (console_device == RT_NULL)
{
rt_hw_console_output(str);
}
else
{
rt_device_write(console_device, 0, str, len);
}
#else
RT_UNUSED(len);
rt_hw_console_output(str);
#endif /* RT_USING_DEVICE */
CONSOLE_RELEASE;
}

相关PR:#9543

这个PR把代码改正确了,但是导致了这个问题 改回去会导致没发完就接着发中间缺字符🤦‍♂️

Other additional context

No response

@CYFS3
Copy link
Contributor

CYFS3 commented Feb 3, 2025

这个问题我感觉还是要改TX_BLOCK_TIMEOUT,实际上在f1 9600波特率也会遇到数据发不完整,在 #9543 我也有提到是否能根据不同的波特率改变TX_BLOCK_TIMEOUT,当时我的解决方法是把TX_BLOCK_TIMEOUT这个宏手动调大了。

@supperthomas
Copy link
Member

这个是不是要考虑把TX_BLOCK_TIMEOUT 这个放到Kconfig中,给不同平台适配?

@kaidegit
Copy link
Contributor Author

kaidegit commented Feb 5, 2025

我觉得既然是stm32 driver里的适配问题,拿hal的api获取一下主频算一下就好了

@CYFS3
Copy link
Contributor

CYFS3 commented Feb 5, 2025

我觉得既然是stm32 driver里的适配问题,拿hal的api获取一下主频算一下就好了

好像确实是只有STM32 driver是这样适配的,当时我有特意看了一下

@supperthomas
Copy link
Member

我觉得既然是stm32 driver里的适配问题,拿hal的api获取一下主频算一下就好了

欢迎PR修复一下。

@kaidegit
Copy link
Contributor Author

kaidegit commented Feb 5, 2025

主要是有cache、flash等待、art加速器这些因素在我怕算不准😂

@supperthomas
Copy link
Member

主要是有cache、flash等待、art加速器这些因素在我怕算不准😂

那就加个Kconfig,每个stm32 自己配一下,默认一个最大值。

@supperthomas
Copy link
Member

不过v1是不是用的不多了?都要转V2了?可以试试v2

@kaidegit
Copy link
Contributor Author

kaidegit commented Feb 5, 2025

主要看默认config都是v1

@CYFS3
Copy link
Contributor

CYFS3 commented Feb 5, 2025

主要是有cache、flash等待、art加速器这些因素在我怕算不准😂

那就加个Kconfig,每个stm32 自己配一下,默认一个最大值。

有下面几个方案,看一下哪个合适

  • 可以直接像其他mcu适配方案一样直接,死等发送标志位完成,我看stm32 v2也是这样做的
  • 每款stm32加个kconfig,调整合适的值
  • 根据mcu的频率和波特率计算适合的值,因为我之前在f1上面遇到的情况是9600会超时而已,其他的波特率能够正常发送

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants