深入剖析RT-Thread串口驱动:基于STM32H750的FinSH Shell全链路Trace分析与实战解密(上)

0. 概述

这是cherryusb代码trace分析系列文章之七。

RT-Thread串口驱动框架与FinSH Shell运行机制深度解析:针对STM32H750 ART-PI平台,本文独辟蹊径采用创新的代码trace分析方法,破解庞大串口框架下的复杂运行逻辑。通过精确trace日志与drv_usart_v2.c、dev_serial_v2.c、kservice.c等核心驱动源码的深度结合,系统揭示了从rt_hw_usart_init串口硬件初始化、rt_console_set_device控制台设备配置、rt_kprintf调试输出机制到FinSH Shell交互的全链路执行流程。

文章特别抓取了系统启动过程中7次rt_kprintf调用的轮询发送机制细节,深入剖析UART4中断处理与FinSH Shell的完整交互过程,包括rt_ringbuffer缓冲区管理、rt_completion同步机制、NVIC中断优先级配置等关键技术点。通过trace分析,完整呈现了FinSH Shell与串口通信的底层细节,精确捕获了所有关键中断处理流程和时序关系。

本文为工程师和嵌入式爱好者提供了宝贵的技术参考,帮助他们深入理解RT-Thread底层串口通信机制,并能够针对性修改代码以适应板载串口、USB CDC_ACM等不同接口需求。文档以实际trace数据为基础,结合精确的函数调用链分析,为RT-Thread串口驱动框架的定制化开发和问题定位提供了强有力的技术支撑。

1. 运行的输入与输出

  • 我们的处理方法是, 首先在如下与串口驱动和finsh有关的c源文件上, 每个函数开头和关键节点处, 用my_printf和my_printf2进行trace record. 这些文件包括:
    drv_usart_v2.c
    dev_serial_v2.c
    kservice.c
    ringbuffer.c
    device.c
    shell.c
  • STM32H750 ART-PI平台的RT-Thread配置为最精简模式, 只保留串口, 其它都不开启
  • 烧录板子后, 正常输出开机rt-thread的log, 然后运行一个命令"list device\r\n". 输出结果如下:
[0m[D/drv.sdram] sdram init success, mapped at 0xC0000000, size is 33554432 bytes, data width is 16[0m\ | /
- RT -     Thread Operating System/ | \     5.2.0 build Aug  3 2025 14:32:022006 - 2024 Copyright by RT-Thread team
msh >list device
device           type         ref count
-------- -------------------- ----------
uart4    Character Device     2       
pin      Pin Device           0       
msh >
msh >
  • 过10秒后, trace record记录完毕, 开始打印trace到的log. 这个case的完整log文件有1723行. 我们以附录的方式提供.

2. 运行过程流程图

在这里插入图片描述

2.1 rt_hw_usart_init的执行

  • rt_hw_usart_init是drv_common.c中rt_hw_board_init函数中实现的
/*** This function will initial STM32 board.*/
rt_weak void rt_hw_board_init(void)
{
#ifdef BSP_SCB_ENABLE_I_CACHE/* Enable I-Cache---------------------------------------------------------*/SCB_EnableICache();
#endif#ifdef BSP_SCB_ENABLE_D_CACHE/* Enable D-Cache---------------------------------------------------------*/SCB_EnableDCache();
#endif/* HAL_Init() function is called at the beginning of the program */HAL_Init();/* System clock initialization */SystemClock_Config();#if defined(RT_USING_HEAP)/* Heap initialization */rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END);
#endif#ifdef RT_USING_PINrt_hw_pin_init();
#endif#ifdef RT_USING_SERIALrt_hw_usart_init();
#endif#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)/* Set the shell console output device */rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif#if defined(RT_USING_CONSOLE) && defined(RT_USING_NANO)extern void rt_hw_console_init(void);rt_hw_console_init();
#endif#ifdef RT_USING_COMPONENTS_INIT/* Board underlying hardware initialization */rt_components_board_init();
#endif
}
  • 经过对trace log分析的解读, rt_hw_usart_init的函数调用链如下所示
/*来自drv_common.c中的rt_hw_board_init*/
/*
rt_hw_usart_init|-> stm32_uart_get_config|-> rt_hw_serial_register-> rt_device_register-> rt_device_find
*/
  • trace到的运行log如下
drv_usart_v2.c    :1380| rt_hw_usart_init                      
drv_usart_v2.c    :1384| rt_hw_usart_init                                                go=> stm32_uart_get_config
drv_usart_v2.c    :972 | stm32_uart_get_config                 
drv_usart_v2.c    :1392| rt_hw_usart_init                                                go=> rt_hw_serial_register
dev_serial_v2.c   :1543| rt_hw_serial_register                 
dev_serial_v2.c   :1567| rt_hw_serial_register                                           go=> rt_device_register
device.c          :72  | rt_device_register                    
device.c          :73  | rt_device_register                                              uart4
device.c          :74  | rt_device_register                                3(0x00000003) <= flags
device.c          :78  | rt_device_register                                              go=> rt_device_find
device.c          :130 | rt_device_find                        
device.c          :131 | rt_device_find                                                  uart4

2.2 rt_console_set_device的执行(为了实现rt_kprintf)

  • rt_console_set_device是drv_common.c中rt_hw_board_init函数中实现的, 上面已经列出来了. 这个函数主要是为了实现rt_kprintf, 在系统调度没有启动之前就能运行, 打印系统初始化过程日志.
  • 经过对trace log分析的解读, rt_console_set_device的函数调用链如下所示
/*来自drv_common.c中的rt_hw_board_init*/
/*
rt_console_set_device|-> rt_device_find|-> rt_device_open|-> device_init->rt_serial_init->stm32_configure->HAL_UART_Init|-> device_open->rt_serial_open->rt_serial_rx_enable|-> rt_ringbuffer_init|-> stm32_control-> stm32_control-> NVIC_EnableIRQ|->rt_serial_tx_enable|-> stm32_control|-> rt_ringbuffer_init|-> rt_completion_init
*/
  • trace到的运行log如下
kservice.c        :192 | rt_console_set_device                 
kservice.c        :194 | rt_console_set_device                                           go=> rt_device_find
device.c          :130 | rt_device_find                        
device.c          :131 | rt_device_find                                                  uart4
kservice.c        :207 | rt_console_set_device                                           go=> rt_device_open
device.c          :235 | rt_device_open                        
device.c          :236 | rt_device_open                                                  uart4
/*rt_console_set_device用0x43打开uart4*/
/*oflag=0x43=> RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM*/
device.c          :237 | rt_device_open                                   67(0x00000043) <= oflag
device.c          :249 | rt_device_open                                                  go=> device_init
dev_serial_v2.c   :979 | rt_serial_init                        
drv_usart_v2.c    :120 | stm32_configure                       
drv_usart_v2.c    :197 | stm32_configure                                                 go=> HAL_UART_Init
device.c          :276 | rt_device_open                                                  go=> device_open
dev_serial_v2.c   :1006| rt_serial_open                        
dev_serial_v2.c   :1007| rt_serial_open                                   67(0x00000043) <= oflag
dev_serial_v2.c   :1043| rt_serial_open                                                  go=> rt_serial_rx_enable
dev_serial_v2.c   :800 | rt_serial_rx_enable                   
dev_serial_v2.c   :801 | rt_serial_rx_enable                            8192(0x00002000) <= rx_oflag
dev_serial_v2.c   :833 | rt_serial_rx_enable                                             go=> rt_ringbuffer_init
ringbuffer.c      :43  | rt_ringbuffer_init                    
ringbuffer.c      :44  | rt_ringbuffer_init                              256(0x00000100) <= size
dev_serial_v2.c   :846 | rt_serial_rx_enable                                             go=> serial->ops->control
drv_usart_v2.c    :208 | stm32_control                         
drv_usart_v2.c    :209 | stm32_control                                     3(0x00000003) <= cmd/*CONFIG*/
drv_usart_v2.c    :213 | stm32_control                                  8192(0x00002000) <= ctrl_arg/*RT_DEVICE_FLAG_RX_NON_BLOCKING*/
drv_usart_v2.c    :232 | stm32_control                                   256(0x00000100) <= ctrl_arg/*RT_DEVICE_FLAG_INT_RX*/
drv_usart_v2.c    :293 | stm32_control                                                   cmd: RT_DEVICE_CTRL_CONFIG
drv_usart_v2.c    :304 | stm32_control                                                   go=> stm32_control
drv_usart_v2.c    :208 | stm32_control                         
drv_usart_v2.c    :209 | stm32_control                                     6(0x00000006) <= cmd/*SET_INT*/
drv_usart_v2.c    :213 | stm32_control                                   256(0x00000100) <= ctrl_arg
drv_usart_v2.c    :232 | stm32_control                                   256(0x00000100) <= ctrl_arg
drv_usart_v2.c    :280 | stm32_control                                                   cmd: RT_DEVICE_CTRL_SET_INT
drv_usart_v2.c    :281 | stm32_control                                                   go=> HAL_NVIC_SetPriority
drv_usart_v2.c    :283 | stm32_control                                                   go=> NVIC_EnableIRQ
dev_serial_v2.c   :1051| rt_serial_open                                                  go=> rt_serial_tx_enable
dev_serial_v2.c   :672 | rt_serial_tx_enable                   
dev_serial_v2.c   :673 | rt_serial_tx_enable                           16384(0x00004000) <= tx_oflag
dev_serial_v2.c   :707 | rt_serial_tx_enable                                             go=> serial->ops->control
drv_usart_v2.c    :208 | stm32_control                         
drv_usart_v2.c    :209 | stm32_control                                    32(0x00000020) <= cmd/*RT_DEVICE_CHECK_OPTMODE*/
drv_usart_v2.c    :213 | stm32_control                                 16384(0x00004000) <= ctrl_arg/*RT_DEVICE_FLAG_TX_BLOCKING*/
drv_usart_v2.c    :232 | stm32_control                                  1024(0x00000400) <= ctrl_arg/*RT_DEVICE_FLAG_INT_TX*/
drv_usart_v2.c    :310 | stm32_control                                                   cmd: RT_DEVICE_CHECK_OPTMODE
dev_serial_v2.c   :718 | rt_serial_tx_enable                                             go=> rt_ringbuffer_init
ringbuffer.c      :43  | rt_ringbuffer_init                    
ringbuffer.c      :44  | rt_ringbuffer_init                              256(0x00000100) <= size
dev_serial_v2.c   :755 | rt_serial_tx_enable                                             go=> rt_completion_init
/*初始化完毕*/

2.3 rt_kprintf的执行

  • 经过对trace log分析的解读, rt_kprintf的函数调用链如下所示. 可见rt_kprintf是通过_serial_poll_tx方式轮询发送的.
/*
rt_kprintf (kservice.c)|-> _kputs (kservice.c)|-> rt_console_get_device (kservice.c)|-> rt_device_write (device.c)|-> device_write (dev_serial_v2.c)|-> _serial_fifo_tx_blocking_buf (dev_serial_v2.c)|-> _serial_poll_tx (dev_serial_v2.c)|-> stm32_putc (drv_usart_v2.c) [多次调用]
*/
  • 系统启动初始化过程中, trace到了7次rt_kprintf打印过程, 每次打印的数据量不同. 完整的运行log如下
/*rt_kprintf正式被调用了*/
kservice.c        :372 | rt_kprintf                            
kservice.c        :391 | rt_kprintf                                                      go=> _kputs
kservice.c        :321 | _kputs                                
kservice.c        :323 | _kputs                                                          go=> rt_console_get_device
kservice.c        :337 | _kputs                                                          go=> rt_device_write
device.c          :407 | rt_device_write                       
device.c          :408 | rt_device_write                                                 uart4
device.c          :409 | rt_device_write                                  18(0x00000012) <= size
device.c          :423 | rt_device_write                                                 go=> device_write
dev_serial_v2.c   :536 | _serial_fifo_tx_blocking_buf          
dev_serial_v2.c   :537 | _serial_fifo_tx_blocking_buf                     18(0x00000012) <= size
dev_serial_v2.c   :555 | _serial_fifo_tx_blocking_buf                                    go=> _serial_poll_tx
dev_serial_v2.c   :369 | _serial_poll_tx                       
dev_serial_v2.c   :370 | _serial_poll_tx                                  18(0x00000012) <= size
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
dev_serial_v2.c   :397 | _serial_poll_tx                                  18(0x00000012) <= putc_size - size/*第2次调用rt_kprintf*/
kservice.c        :372 | rt_kprintf                            
kservice.c        :391 | rt_kprintf                                                      go=> _kputs
kservice.c        :321 | _kputs                                
kservice.c        :323 | _kputs                                                          go=> rt_console_get_device
kservice.c        :337 | _kputs                                                          go=> rt_device_write
device.c          :407 | rt_device_write                       
device.c          :408 | rt_device_write                                                 uart4
device.c          :409 | rt_device_write                                  82(0x00000052) <= size
device.c          :423 | rt_device_write                                                 go=> device_write
dev_serial_v2.c   :536 | _serial_fifo_tx_blocking_buf          
dev_serial_v2.c   :537 | _serial_fifo_tx_blocking_buf                     82(0x00000052) <= size
dev_serial_v2.c   :555 | _serial_fifo_tx_blocking_buf                                    go=> _serial_poll_tx
dev_serial_v2.c   :369 | _serial_poll_tx                       
dev_serial_v2.c   :370 | _serial_poll_tx                                  82(0x00000052) <= size
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
dev_serial_v2.c   :397 | _serial_poll_tx                                  82(0x00000052) <= putc_size - size/*第3次调用rt_kprintf*/
kservice.c        :372 | rt_kprintf                            
kservice.c        :391 | rt_kprintf                                                      go=> _kputs
kservice.c        :321 | _kputs                                
kservice.c        :323 | _kputs                                                          go=> rt_console_get_device
kservice.c        :337 | _kputs                                                          go=> rt_device_write
device.c          :407 | rt_device_write                       
device.c          :408 | rt_device_write                                                 uart4
device.c          :409 | rt_device_write                                   5(0x00000005) <= size
device.c          :423 | rt_device_write                                                 go=> device_write
dev_serial_v2.c   :536 | _serial_fifo_tx_blocking_buf          
dev_serial_v2.c   :537 | _serial_fifo_tx_blocking_buf                      5(0x00000005) <= size
dev_serial_v2.c   :555 | _serial_fifo_tx_blocking_buf                                    go=> _serial_poll_tx
dev_serial_v2.c   :369 | _serial_poll_tx                       
dev_serial_v2.c   :370 | _serial_poll_tx                                   5(0x00000005) <= size
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
dev_serial_v2.c   :397 | _serial_poll_tx                                   5(0x00000005) <= putc_size - size/*第4次调用rt_kprintf*/
kservice.c        :372 | rt_kprintf                            
kservice.c        :391 | rt_kprintf                                                      go=> _kputs
kservice.c        :321 | _kputs                                
kservice.c        :323 | _kputs                                                          go=> rt_console_get_device
kservice.c        :337 | _kputs                                                          go=> rt_device_write
device.c          :407 | rt_device_write                       
device.c          :408 | rt_device_write                                                 uart4
device.c          :409 | rt_device_write                                   8(0x00000008) <= size
device.c          :423 | rt_device_write                                                 go=> device_write
dev_serial_v2.c   :536 | _serial_fifo_tx_blocking_buf          
dev_serial_v2.c   :537 | _serial_fifo_tx_blocking_buf                      8(0x00000008) <= size
dev_serial_v2.c   :555 | _serial_fifo_tx_blocking_buf                                    go=> _serial_poll_tx
dev_serial_v2.c   :369 | _serial_poll_tx                       
dev_serial_v2.c   :370 | _serial_poll_tx                                   8(0x00000008) <= size
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
dev_serial_v2.c   :397 | _serial_poll_tx                                   8(0x00000008) <= putc_size - size/*第5次调用rt_kprintf*/
kservice.c        :372 | rt_kprintf                            
kservice.c        :391 | rt_kprintf                                                      go=> _kputs
kservice.c        :321 | _kputs                                
kservice.c        :323 | _kputs                                                          go=> rt_console_get_device
kservice.c        :337 | _kputs                                                          go=> rt_device_write
device.c          :407 | rt_device_write                       
device.c          :408 | rt_device_write                                                 uart4
device.c          :409 | rt_device_write                                  35(0x00000023) <= size
device.c          :423 | rt_device_write                                                 go=> device_write
dev_serial_v2.c   :536 | _serial_fifo_tx_blocking_buf          
dev_serial_v2.c   :537 | _serial_fifo_tx_blocking_buf                     35(0x00000023) <= size
dev_serial_v2.c   :555 | _serial_fifo_tx_blocking_buf                                    go=> _serial_poll_tx
dev_serial_v2.c   :369 | _serial_poll_tx                       
dev_serial_v2.c   :370 | _serial_poll_tx                                  35(0x00000023) <= size
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
dev_serial_v2.c   :397 | _serial_poll_tx                                  35(0x00000023) <= putc_size - size/*第6次调用rt_kprintf*/
kservice.c        :372 | rt_kprintf                            
kservice.c        :391 | rt_kprintf                                                      go=> _kputs
kservice.c        :321 | _kputs                                
kservice.c        :323 | _kputs                                                          go=> rt_console_get_device
kservice.c        :337 | _kputs                                                          go=> rt_device_write
device.c          :407 | rt_device_write                       
device.c          :408 | rt_device_write                                                 uart4
device.c          :409 | rt_device_write                                  44(0x0000002c) <= size
device.c          :423 | rt_device_write                                                 go=> device_write
dev_serial_v2.c   :536 | _serial_fifo_tx_blocking_buf          
dev_serial_v2.c   :537 | _serial_fifo_tx_blocking_buf                     44(0x0000002c) <= size
dev_serial_v2.c   :555 | _serial_fifo_tx_blocking_buf                                    go=> _serial_poll_tx
dev_serial_v2.c   :369 | _serial_poll_tx                       
dev_serial_v2.c   :370 | _serial_poll_tx                                  44(0x0000002c) <= size
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
dev_serial_v2.c   :397 | _serial_poll_tx                                  44(0x0000002c) <= putc_size - size/*第7次调用rt_kprintf*/
kservice.c        :372 | rt_kprintf                            
kservice.c        :391 | rt_kprintf                                                      go=> _kputs
kservice.c        :321 | _kputs                                
kservice.c        :323 | _kputs                                                          go=> rt_console_get_device
kservice.c        :337 | _kputs                                                          go=> rt_device_write
device.c          :407 | rt_device_write                       
device.c          :408 | rt_device_write                                                 uart4
device.c          :409 | rt_device_write                                  41(0x00000029) <= size
device.c          :423 | rt_device_write                                                 go=> device_write
dev_serial_v2.c   :536 | _serial_fifo_tx_blocking_buf          
dev_serial_v2.c   :537 | _serial_fifo_tx_blocking_buf                     41(0x00000029) <= size
dev_serial_v2.c   :555 | _serial_fifo_tx_blocking_buf                                    go=> _serial_poll_tx
dev_serial_v2.c   :369 | _serial_poll_tx                       
dev_serial_v2.c   :370 | _serial_poll_tx                                  41(0x00000029) <= size
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
dev_serial_v2.c   :397 | _serial_poll_tx                                  41(0x00000029) <= putc_size - size

2.4 finsh_system_init与finsh_thread_entry的执行(创建一个finsh shell单独的线程, 处理shell的收发)

  • finsh_system_init是在shell.c中实现的, 它主要是创建了一个finsh线程, 并在finsh线程中用finsh_set_device设置了device, 配置了不同的oflag属性. finsh_set_device相比rt_console_set_device, 多了一个RT_DEVICE_FLAG_INT_RX属性, 以满足中断接收的要求.
  • 经过对trace log分析的解读, finsh_system_init的函数调用链如下所示
/*finsh_system_init是用INIT_APP_EXPORT初始化的*/
/*
finsh_system_init (shell.c)|-> rt_thread_create (shell.c)|-> rt_sem_init (shell.c)|-> finsh_set_prompt_mode (shell.c)|-> finsh_thread_entry (shell.c)|-> rt_console_get_device (shell.c)|-> finsh_set_device (shell.c)|-> rt_device_find (device.c) [uart4]|-> rt_device_open (device.c) [uart4, oflag=0x143]|-> rt_serial_open (dev_serial_v2.c)|-> rt_device_set_rx_indicate (device.c) [uart4]
*/
  • trace到的运行log如下
shell.c           :799 | finsh_system_init                     
shell.c           :848 | finsh_system_init                                               go=> rt_thread_create
shell.c           :862 | finsh_system_init                                               go=> rt_sem_init
shell.c           :864 | finsh_system_init                                               go=> finsh_set_prompt_mode
shell.c           :157 | finsh_set_prompt_mode                 
shell.c           :503 | finsh_thread_entry                    
shell.c           :519 | finsh_thread_entry                                              go=> rt_console_get_device
shell.c           :523 | finsh_thread_entry                                              go=> finsh_set_device
shell.c           :233 | finsh_set_device                      
shell.c           :237 | finsh_set_device                                                go=> rt_device_find
device.c          :130 | rt_device_find                        
device.c          :131 | rt_device_find                                                  uart4
shell.c           :248 | finsh_set_device                                                go=> rt_device_open
device.c          :235 | rt_device_open                        
device.c          :236 | rt_device_open                                                  uart4
/*finsh_set_device用0x143打开uart4, 相比rt_console_set_device多了一个RT_DEVICE_FLAG_INT_RX*/
/*oflag=0x143=> RT_DEVICE_OFLAG_RDWR|RT_DEVICE_FLAG_INT_RX|RT_DEVICE_FLAG_STREAM*/
device.c          :237 | rt_device_open                                  323(0x00000143) <= oflag
device.c          :276 | rt_device_open                                                  go=> device_open
dev_serial_v2.c   :1006| rt_serial_open                        
dev_serial_v2.c   :1007| rt_serial_open                                  323(0x00000143) <= oflag
shell.c           :266 | finsh_set_device                                                go=> rt_device_set_rx_indicate
device.c          :479 | rt_device_set_rx_indicate             
device.c          :480 | rt_device_set_rx_indicate                                       uart4
shell.c           :542 | finsh_thread_entry                                              go=> rt_kprintf
/*执行rt_kprintf(FINSH_PROMPT), 因为#define FINSH_PROMPT  finsh_get_prompt(), 所以先执行finsh_get_prompt*/
shell.c           :99  | finsh_get_prompt /*第8次调用rt_kprintf, 打印rt_kprintf(FINSH_PROMPT)*/
kservice.c        :372 | rt_kprintf                            
kservice.c        :391 | rt_kprintf                                                      go=> _kputs
kservice.c        :321 | _kputs                                
kservice.c        :323 | _kputs                                                          go=> rt_console_get_device
kservice.c        :337 | _kputs                                                          go=> rt_device_write
device.c          :407 | rt_device_write                       
device.c          :408 | rt_device_write                                                 uart4
device.c          :409 | rt_device_write                                   5(0x00000005) <= size
device.c          :423 | rt_device_write                                                 go=> device_write
dev_serial_v2.c   :536 | _serial_fifo_tx_blocking_buf          
dev_serial_v2.c   :537 | _serial_fifo_tx_blocking_buf                      5(0x00000005) <= size
dev_serial_v2.c   :555 | _serial_fifo_tx_blocking_buf                                    go=> _serial_poll_tx
dev_serial_v2.c   :369 | _serial_poll_tx                       
dev_serial_v2.c   :370 | _serial_poll_tx                                   5(0x00000005) <= size
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
dev_serial_v2.c   :397 | _serial_poll_tx                                   5(0x00000005) <= putc_size - size

2.5 finsh_thread_entry的执行过程

  • 线程循环体的执行逻辑就是finsh_getchar-> process(ch), 这里proces()过程细节就非常多了, 包括回显, push历史, 命令执行等
static void finsh_thread_entry(void *parameter)
{rt_device_t console = rt_console_get_device();finsh_set_device(console->parent.name);while (1){ch = (int)finsh_getchar();if (ch < 0){continue;}process(ch);}
}

2.6 finsh_getchar的执行(console如何获取一个char?)

  • 经过对trace log分析的解读, finsh_getchar的函数调用链如下所示. 在finsh_getchar底层调用了rt_ringbuffer_get, 如果ringbuffer为空, 那么就会调用rt_sem_take等待.
/*读取第1个char*/
/*
finsh_getchar (shell.c)|-> rt_device_read (device.c)|-> device_read (dev_serial_v2.c)|-> _serial_fifo_rx (dev_serial_v2.c)|-> rt_ringbuffer_get (ringbuffer.c)|-> rt_ringbuffer_data_len (ringbuffer.c)|-> rt_sem_take (when buffer empty)|-> ......|-> rt_device_read (after wakeup)|-> device_read (dev_serial_v2.c)|-> _serial_fifo_rx (dev_serial_v2.c)|-> rt_ringbuffer_get (ringbuffer.c)|-> rt_ringbuffer_data_len (ringbuffer.c)
*/
  • trace到的finsh_getchar获取一个char的完整运行log如下. 启动读后, 因为ringbuffer此时为空, 因此会调用rt_sem_take睡眠. 直到串口发生rx中断, 接收到了char, 并通过rt_ringbuffer_putchar存入ringbuff, 然后调用rt_hw_serial_isr发送信号量, finsh_getchar被唤醒继续执行, 成功读取到一个char.
/*进入finsh_thread_entry循环体执行*/
/*读取第1个char*/
shell.c           :547 | finsh_thread_entry                                              go=> finsh_getchar
shell.c           :164 | finsh_getchar                         
shell.c           :187 | finsh_getchar                                                   go=> rt_device_read
device.c          :360 | rt_device_read                        
device.c          :361 | rt_device_read                                                  uart4
device.c          :362 | rt_device_read                                    1(0x00000001) <= size
device.c          :376 | rt_device_read                                                  go=> device_read
dev_serial_v2.c   :415 | _serial_fifo_rx                       
dev_serial_v2.c   :416 | _serial_fifo_rx                                   1(0x00000001) <= size
dev_serial_v2.c   :460 | _serial_fifo_rx                                                 go=> rt_ringbuffer_get
ringbuffer.c      :189 | rt_ringbuffer_get                     
ringbuffer.c      :394 | rt_ringbuffer_data_len                
ringbuffer.c      :21  | rt_ringbuffer_status                  
ringbuffer.c      :398 | rt_ringbuffer_data_len                            0(0x00000000) <= data_len
dev_serial_v2.c   :465 | _serial_fifo_rx                                   0(0x00000000) <= recv_len
shell.c           :190 | finsh_getchar                                                   go=> rt_sem_take...
/*进入睡眠状态*//*中断唤醒, 串口收到数据了*/
/*基本操作就是先用rt_ringbuffer_putchar存入ringbuff, 然后调用rt_hw_serial_isr发送信号量*/
drv_usart_v2.c    :703 | UART4_IRQHandler                      
drv_usart_v2.c    :707 | UART4_IRQHandler                                                go=> uart_isr
drv_usart_v2.c    :475 | uart_isr                              
drv_usart_v2.c    :488 | uart_isr                                                        go=> rt_ringbuffer_putchar
drv_usart_v2.c    :346 | stm32_uart_get_mask                   
ringbuffer.c      :285 | rt_ringbuffer_putchar                 
ringbuffer.c      :394 | rt_ringbuffer_data_len                
ringbuffer.c      :21  | rt_ringbuffer_status                  
ringbuffer.c      :398 | rt_ringbuffer_data_len                            0(0x00000000) <= data_len
drv_usart_v2.c    :491 | uart_isr                                                        go=> rt_hw_serial_isr
/*调用rt_hw_serial_isr, 最终结果是发送rt_sem_release*/
dev_serial_v2.c   :1584| rt_hw_serial_isr                      
dev_serial_v2.c   :1585| rt_hw_serial_isr                                  1(0x00000001) <= event
dev_serial_v2.c   :1613| rt_hw_serial_isr                                                go=> rt_ringbuffer_data_len
ringbuffer.c      :394 | rt_ringbuffer_data_len                
ringbuffer.c      :21  | rt_ringbuffer_status                  
ringbuffer.c      :410 | rt_ringbuffer_data_len                            1(0x00000001) <= data_len
dev_serial_v2.c   :1628| rt_hw_serial_isr                                                go=> serial->parent.rx_indicate
shell.c           :214 | finsh_rx_ind                          
shell.c           :218 | finsh_rx_ind                                                    go=> rt_sem_release/*finsh_getchar被唤醒*/
shell.c           :192 | finsh_getchar                                                   wakeup from rt_sem_take...
shell.c           :201 | finsh_getchar                                                   go=> rt_device_read
device.c          :360 | rt_device_read                        
device.c          :361 | rt_device_read                                                  uart4
device.c          :362 | rt_device_read                                    1(0x00000001) <= size
device.c          :376 | rt_device_read                                                  go=> device_read
dev_serial_v2.c   :415 | _serial_fifo_rx                       
dev_serial_v2.c   :416 | _serial_fifo_rx                                   1(0x00000001) <= size
dev_serial_v2.c   :460 | _serial_fifo_rx                                                 go=> rt_ringbuffer_get
ringbuffer.c      :189 | rt_ringbuffer_get                     
ringbuffer.c      :394 | rt_ringbuffer_data_len                
ringbuffer.c      :21  | rt_ringbuffer_status                  
ringbuffer.c      :410 | rt_ringbuffer_data_len                            1(0x00000001) <= data_len
/*_serial_fifo_rx函数返回1, 终于读到了数据*/
dev_serial_v2.c   :465 | _serial_fifo_rx                                   1(0x00000001) <= recv_len

2.7 UART4_IRQHandler的执行(如何获取一个char? 这个char如何存放?)

  • 串口接收数据是通过中断来实现的. 我们在调用finsh_set_device的时候, 其中包含RT_DEVICE_FLAG_INT_RX属性, 以满足中断接收的要求.
  • 经过对trace log分析的解读, UART4_IRQHandler的函数调用链如下所示. 基本操作就是先用rt_ringbuffer_putchar存入ringbuff, 然后调用rt_hw_serial_isr发送信号量.
/*中断唤醒, 串口收到数据了*/
/*基本操作就是先用rt_ringbuffer_putchar存入ringbuff, 然后调用rt_hw_serial_isr发送信号量*/
/*
UART4_IRQHandler (drv_usart_v2.c)|-> uart_isr (drv_usart_v2.c)|-> rt_ringbuffer_putchar (ringbuffer.c)|-> rt_ringbuffer_data_len (ringbuffer.c)|-> rt_ringbuffer_status (ringbuffer.c)|-> rt_hw_serial_isr (dev_serial_v2.c)|-> rt_ringbuffer_data_len (ringbuffer.c)|-> rt_ringbuffer_status (ringbuffer.c)|-> serial->parent.rx_indicate (shell.c)|-> rt_sem_release
*/
  • trace到的运行log如下
/*中断唤醒, 串口收到数据了*/
/*基本操作就是先用rt_ringbuffer_putchar存入ringbuff, 然后调用rt_hw_serial_isr发送信号量*/
drv_usart_v2.c    :703 | UART4_IRQHandler                      
drv_usart_v2.c    :707 | UART4_IRQHandler                                                go=> uart_isr
drv_usart_v2.c    :475 | uart_isr                              
drv_usart_v2.c    :488 | uart_isr                                                        go=> rt_ringbuffer_putchar
drv_usart_v2.c    :346 | stm32_uart_get_mask                   
ringbuffer.c      :285 | rt_ringbuffer_putchar                 
ringbuffer.c      :394 | rt_ringbuffer_data_len                
ringbuffer.c      :21  | rt_ringbuffer_status                  
ringbuffer.c      :398 | rt_ringbuffer_data_len                            0(0x00000000) <= data_len
drv_usart_v2.c    :491 | uart_isr                                                        go=> rt_hw_serial_isr
/*调用rt_hw_serial_isr, 最终结果是发送rt_sem_release*/
dev_serial_v2.c   :1584| rt_hw_serial_isr                      
dev_serial_v2.c   :1585| rt_hw_serial_isr                                  1(0x00000001) <= event
dev_serial_v2.c   :1613| rt_hw_serial_isr                                                go=> rt_ringbuffer_data_len
ringbuffer.c      :394 | rt_ringbuffer_data_len                
ringbuffer.c      :21  | rt_ringbuffer_status                  
ringbuffer.c      :410 | rt_ringbuffer_data_len                            1(0x00000001) <= data_len
dev_serial_v2.c   :1628| rt_hw_serial_isr                                                go=> serial->parent.rx_indicate
shell.c           :214 | finsh_rx_ind                          
shell.c           :218 | finsh_rx_ind                                                    go=> rt_sem_release

2.8 finish如何识别命令并执行?

  • 在finsh_thread_entry循环体中, 通过finsh_getchar成功获得char之后, 就交给process()处理.
  • 在process()中有如下这样的一段, 它是以判断当前字符是’\r’或者’\n’来作为命令接收完毕的判据.
  • 这意味着, 如果我们输入的命令是"list device\r\n", 当收到"list device\r"时, 就认为收到一个完整命令, 然后运行. 毫无疑问, 这会发生一次成功的命令执行.
  • 接着继续接收到一个’\n’, 满足条件, 也认为是收到一个完整命令, 然后运行. 毫无疑问, 这是一次无效的命令执行, 因为命令为空.
        /* handle end of line, break */if (ch == '\r' || ch == '\n'){
#ifdef FINSH_USING_HISTORYshell_push_history(shell);
#endifif (shell->echo_mode)rt_kprintf("\n");msh_exec(shell->line, shell->line_position);rt_kprintf(FINSH_PROMPT);rt_memset(shell->line, 0, sizeof(shell->line));shell->line_curpos = shell->line_position = 0;continue;}
  • trace到的运行log如下
.....
...../*finsh_thread_entry循环体继续执行*/
/*读取第11个char*/
shell.c           :547 | finsh_thread_entry                                              go=> finsh_getchar
shell.c           :164 | finsh_getchar                         
shell.c           :187 | finsh_getchar                                                   go=> rt_device_read
device.c          :360 | rt_device_read                        
device.c          :361 | rt_device_read                                                  uart4
device.c          :362 | rt_device_read                                    1(0x00000001) <= size
device.c          :376 | rt_device_read                                                  go=> device_read
dev_serial_v2.c   :415 | _serial_fifo_rx                       
dev_serial_v2.c   :416 | _serial_fifo_rx                                   1(0x00000001) <= size
dev_serial_v2.c   :460 | _serial_fifo_rx                                                 go=> rt_ringbuffer_get
ringbuffer.c      :189 | rt_ringbuffer_get                     
ringbuffer.c      :394 | rt_ringbuffer_data_len                
ringbuffer.c      :21  | rt_ringbuffer_status                  
ringbuffer.c      :410 | rt_ringbuffer_data_len                            3(0x00000003) <= data_len
dev_serial_v2.c   :465 | _serial_fifo_rx                                   1(0x00000001) <= recv_len
shell.c           :740 | finsh_thread_entry                                              go=> rt_kprintf
kservice.c        :372 | rt_kprintf                            
kservice.c        :391 | rt_kprintf                                                      go=> _kputs
kservice.c        :321 | _kputs                                
kservice.c        :323 | _kputs                                                          go=> rt_console_get_device
kservice.c        :337 | _kputs                                                          go=> rt_device_write
device.c          :407 | rt_device_write                       
device.c          :408 | rt_device_write                                                 uart4
device.c          :409 | rt_device_write                                   1(0x00000001) <= size
device.c          :423 | rt_device_write                                                 go=> device_write
dev_serial_v2.c   :536 | _serial_fifo_tx_blocking_buf          
dev_serial_v2.c   :537 | _serial_fifo_tx_blocking_buf                      1(0x00000001) <= size
dev_serial_v2.c   :555 | _serial_fifo_tx_blocking_buf                                    go=> _serial_poll_tx
dev_serial_v2.c   :369 | _serial_poll_tx                       
dev_serial_v2.c   :370 | _serial_poll_tx                                   1(0x00000001) <= size
drv_usart_v2.c    :332 | stm32_putc                            
dev_serial_v2.c   :397 | _serial_poll_tx                                   1(0x00000001) <= putc_size - size/*finsh_thread_entry循环体继续执行*/
/*读取第12个char*/
shell.c           :547 | finsh_thread_entry                                              go=> finsh_getchar
shell.c           :164 | finsh_getchar                         
shell.c           :187 | finsh_getchar                                                   go=> rt_device_read
device.c          :360 | rt_device_read                        
device.c          :361 | rt_device_read                                                  uart4
device.c          :362 | rt_device_read                                    1(0x00000001) <= size
device.c          :376 | rt_device_read                                                  go=> device_read
dev_serial_v2.c   :415 | _serial_fifo_rx                       
dev_serial_v2.c   :416 | _serial_fifo_rx                                   1(0x00000001) <= size
dev_serial_v2.c   :460 | _serial_fifo_rx                                                 go=> rt_ringbuffer_get
ringbuffer.c      :189 | rt_ringbuffer_get                     
ringbuffer.c      :394 | rt_ringbuffer_data_len                
ringbuffer.c      :21  | rt_ringbuffer_status                  
ringbuffer.c      :410 | rt_ringbuffer_data_len                            2(0x00000002) <= data_len
dev_serial_v2.c   :465 | _serial_fifo_rx                                   1(0x00000001) <= recv_len
/*到此, 接收到了list device\r, 一共12个char. 因为收到了 '\r'或'\n', 认为命令接收完毕*/
/*执行shell_push_history, 将命令压入历史堆栈*/
shell.c           :702 | finsh_thread_entry                                              go=> shell_push_history
shell.c           :443 | shell_push_history                    
shell.c           :706 | finsh_thread_entry                                              go=> rt_kprintf
kservice.c        :372 | rt_kprintf                            
kservice.c        :391 | rt_kprintf                                                      go=> _kputs
kservice.c        :321 | _kputs                                
kservice.c        :323 | _kputs                                                          go=> rt_console_get_device
kservice.c        :337 | _kputs                                                          go=> rt_device_write
device.c          :407 | rt_device_write                       
device.c          :408 | rt_device_write                                                 uart4
device.c          :409 | rt_device_write                                   1(0x00000001) <= size
device.c          :423 | rt_device_write                                                 go=> device_write
dev_serial_v2.c   :536 | _serial_fifo_tx_blocking_buf          
dev_serial_v2.c   :537 | _serial_fifo_tx_blocking_buf                      1(0x00000001) <= size
dev_serial_v2.c   :555 | _serial_fifo_tx_blocking_buf                                    go=> _serial_poll_tx
dev_serial_v2.c   :369 | _serial_poll_tx                       
dev_serial_v2.c   :370 | _serial_poll_tx                                   1(0x00000001) <= size
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
dev_serial_v2.c   :397 | _serial_poll_tx                                   1(0x00000001) <= putc_size - size/*命令接收完毕, 开始执行命令msh_exec*/
shell.c           :707 | finsh_thread_entry                                              go=> msh_exec/*msh_exec命令执行过程, 我们的命令是list device, 因此开始产生一些输出*/
kservice.c        :372 | rt_kprintf                            
kservice.c        :391 | rt_kprintf                                                      go=> _kputs
kservice.c        :321 | _kputs                                
kservice.c        :323 | _kputs                                                          go=> rt_console_get_device
kservice.c        :337 | _kputs                                                          go=> rt_device_write
device.c          :407 | rt_device_write                       
device.c          :408 | rt_device_write                                                 uart4
device.c          :409 | rt_device_write                                  40(0x00000028) <= size
device.c          :423 | rt_device_write                                                 go=> device_write
dev_serial_v2.c   :536 | _serial_fifo_tx_blocking_buf          
dev_serial_v2.c   :537 | _serial_fifo_tx_blocking_buf                     40(0x00000028) <= size
dev_serial_v2.c   :555 | _serial_fifo_tx_blocking_buf                                    go=> _serial_poll_tx
dev_serial_v2.c   :369 | _serial_poll_tx                       
dev_serial_v2.c   :370 | _serial_poll_tx                                  40(0x00000028) <= size
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.....
.....drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
dev_serial_v2.c   :397 | _serial_poll_tx                                  39(0x00000027) <= putc_size - size
shell.c           :710 | finsh_thread_entry                                              go=> rt_kprintf
/*msh_exe执行完毕, 最后执行rt_kprintf(FINSH_PROMPT)*/
shell.c           :99  | finsh_get_prompt                      
kservice.c        :372 | rt_kprintf                            
kservice.c        :391 | rt_kprintf                                                      go=> _kputs
kservice.c        :321 | _kputs                                
kservice.c        :323 | _kputs                                                          go=> rt_console_get_device
kservice.c        :337 | _kputs                                                          go=> rt_device_write
device.c          :407 | rt_device_write                       
device.c          :408 | rt_device_write                                                 uart4
device.c          :409 | rt_device_write                                   5(0x00000005) <= size
device.c          :423 | rt_device_write                                                 go=> device_write
dev_serial_v2.c   :536 | _serial_fifo_tx_blocking_buf          
dev_serial_v2.c   :537 | _serial_fifo_tx_blocking_buf                      5(0x00000005) <= size
dev_serial_v2.c   :555 | _serial_fifo_tx_blocking_buf                                    go=> _serial_poll_tx
dev_serial_v2.c   :369 | _serial_poll_tx                       
dev_serial_v2.c   :370 | _serial_poll_tx                                   5(0x00000005) <= size
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
dev_serial_v2.c   :397 | _serial_poll_tx                                   5(0x00000005) <= putc_size - size/*finsh_thread_entry循环体继续执行*/
/*读取第13个char, 此时读到的是'\n', 再次进入这一段逻辑(这一遍实际是无效的).*/
shell.c           :547 | finsh_thread_entry                                              go=> finsh_getchar
shell.c           :164 | finsh_getchar                         
shell.c           :187 | finsh_getchar                                                   go=> rt_device_read
device.c          :360 | rt_device_read                        
device.c          :361 | rt_device_read                                                  uart4
device.c          :362 | rt_device_read                                    1(0x00000001) <= size
device.c          :376 | rt_device_read                                                  go=> device_read
dev_serial_v2.c   :415 | _serial_fifo_rx                       
dev_serial_v2.c   :416 | _serial_fifo_rx                                   1(0x00000001) <= size
dev_serial_v2.c   :460 | _serial_fifo_rx                                                 go=> rt_ringbuffer_get
ringbuffer.c      :189 | rt_ringbuffer_get                     
ringbuffer.c      :394 | rt_ringbuffer_data_len                
ringbuffer.c      :21  | rt_ringbuffer_status                  
ringbuffer.c      :410 | rt_ringbuffer_data_len                            1(0x00000001) <= data_len
dev_serial_v2.c   :465 | _serial_fifo_rx                                   1(0x00000001) <= recv_len
/*于是再次触发shell_push_history*/
shell.c           :702 | finsh_thread_entry                                              go=> shell_push_history
shell.c           :443 | shell_push_history
/*回显'\n'*/                    
shell.c           :706 | finsh_thread_entry                                              go=> rt_kprintf
kservice.c        :372 | rt_kprintf                            
kservice.c        :391 | rt_kprintf                                                      go=> _kputs
kservice.c        :321 | _kputs                                
kservice.c        :323 | _kputs                                                          go=> rt_console_get_device
kservice.c        :337 | _kputs                                                          go=> rt_device_write
device.c          :407 | rt_device_write                       
device.c          :408 | rt_device_write                                                 uart4
device.c          :409 | rt_device_write                                   1(0x00000001) <= size
device.c          :423 | rt_device_write                                                 go=> device_write
dev_serial_v2.c   :536 | _serial_fifo_tx_blocking_buf          
dev_serial_v2.c   :537 | _serial_fifo_tx_blocking_buf                      1(0x00000001) <= size
dev_serial_v2.c   :555 | _serial_fifo_tx_blocking_buf                                    go=> _serial_poll_tx
dev_serial_v2.c   :369 | _serial_poll_tx                       
dev_serial_v2.c   :370 | _serial_poll_tx                                   1(0x00000001) <= size
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
dev_serial_v2.c   :397 | _serial_poll_tx                                   1(0x00000001) <= putc_size - size
/*再次触发msh_exec, 实际上没有有效的命令*/
shell.c           :707 | finsh_thread_entry                                              go=> msh_exec
shell.c           :710 | finsh_thread_entry                                              go=> rt_kprintf
/*再次执行rt_kprintf(FINSH_PROMPT)*/
shell.c           :99  | finsh_get_prompt                      
kservice.c        :372 | rt_kprintf                            
kservice.c        :391 | rt_kprintf                                                      go=> _kputs
kservice.c        :321 | _kputs                                
kservice.c        :323 | _kputs                                                          go=> rt_console_get_device
kservice.c        :337 | _kputs                                                          go=> rt_device_write
device.c          :407 | rt_device_write                       
device.c          :408 | rt_device_write                                                 uart4
device.c          :409 | rt_device_write                                   5(0x00000005) <= size
device.c          :423 | rt_device_write                                                 go=> device_write
dev_serial_v2.c   :536 | _serial_fifo_tx_blocking_buf          
dev_serial_v2.c   :537 | _serial_fifo_tx_blocking_buf                      5(0x00000005) <= size
dev_serial_v2.c   :555 | _serial_fifo_tx_blocking_buf                                    go=> _serial_poll_tx
dev_serial_v2.c   :369 | _serial_poll_tx                       
dev_serial_v2.c   :370 | _serial_poll_tx                                   5(0x00000005) <= size
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
drv_usart_v2.c    :332 | stm32_putc                            
dev_serial_v2.c   :397 | _serial_poll_tx                                   5(0x00000005) <= putc_size - size/*finsh_thread_entry循环体继续执行*/
shell.c           :547 | finsh_thread_entry                                              go=> finsh_getchar
shell.c           :164 | finsh_getchar                         
shell.c           :187 | finsh_getchar                                                   go=> rt_device_read
device.c          :360 | rt_device_read                        
device.c          :361 | rt_device_read                                                  uart4
device.c          :362 | rt_device_read                                    1(0x00000001) <= size
device.c          :376 | rt_device_read                                                  go=> device_read
dev_serial_v2.c   :415 | _serial_fifo_rx                       
dev_serial_v2.c   :416 | _serial_fifo_rx                                   1(0x00000001) <= size
dev_serial_v2.c   :460 | _serial_fifo_rx                                                 go=> rt_ringbuffer_get
ringbuffer.c      :189 | rt_ringbuffer_get                     
ringbuffer.c      :394 | rt_ringbuffer_data_len                
ringbuffer.c      :21  | rt_ringbuffer_status                  
ringbuffer.c      :398 | rt_ringbuffer_data_len                            0(0x00000000) <= data_len
dev_serial_v2.c   :465 | _serial_fifo_rx                                   0(0x00000000) <= recv_len
shell.c           :190 | finsh_getchar                                                   go=> rt_sem_take...

2.9 存在的问题: finsh假唤醒问题?

通过对trace log的仔细分析,我们发现,当finsh执行完一条命令后,后面每次finsh_getchar()运行,因为没有获得数据(rt_ringbuffer_data_len返回0),从而执行rt_sem_take,但马上就被唤醒了。通过查代码,找不到任何唤醒源。感觉是假唤醒。具体的log如下面所示:

......
....../*finsh_thread_entry循环体继续执行*/
/*读取第14个char*/
shell.c           :547 | finsh_thread_entry                                              go=> finsh_getchar
shell.c           :164 | finsh_getchar                         
shell.c           :187 | finsh_getchar                                                   go=> rt_device_read
device.c          :360 | rt_device_read                        
device.c          :361 | rt_device_read                                                  uart4
device.c          :362 | rt_device_read                                    1(0x00000001) <= size
device.c          :376 | rt_device_read                                                  go=> device_read
dev_serial_v2.c   :415 | _serial_fifo_rx                       
dev_serial_v2.c   :416 | _serial_fifo_rx                                   1(0x00000001) <= size
dev_serial_v2.c   :460 | _serial_fifo_rx                                                 go=> rt_ringbuffer_get
ringbuffer.c      :189 | rt_ringbuffer_get                     
ringbuffer.c      :394 | rt_ringbuffer_data_len                
ringbuffer.c      :21  | rt_ringbuffer_status                  
ringbuffer.c      :398 | rt_ringbuffer_data_len                            0(0x00000000) <= data_len
dev_serial_v2.c   :465 | _serial_fifo_rx                                   0(0x00000000) <= recv_len
shell.c           :190 | finsh_getchar                                                   go=> rt_sem_take...
/*这里, 都没有recv到数据, 为什么会wakeup?*/
shell.c           :192 | finsh_getchar                                                   wakeup from rt_sem_take...
shell.c           :201 | finsh_getchar                                                   go=> rt_device_read
device.c          :360 | rt_device_read                        
device.c          :361 | rt_device_read                                                  uart4
device.c          :362 | rt_device_read                                    1(0x00000001) <= size
device.c          :376 | rt_device_read                                                  go=> device_read
dev_serial_v2.c   :415 | _serial_fifo_rx                       
dev_serial_v2.c   :416 | _serial_fifo_rx                                   1(0x00000001) <= size
dev_serial_v2.c   :460 | _serial_fifo_rx                                                 go=> rt_ringbuffer_get
ringbuffer.c      :189 | rt_ringbuffer_get                     
ringbuffer.c      :394 | rt_ringbuffer_data_len                
ringbuffer.c      :21  | rt_ringbuffer_status                  
ringbuffer.c      :398 | rt_ringbuffer_data_len                            0(0x00000000) <= data_len
dev_serial_v2.c   :465 | _serial_fifo_rx                                   0(0x00000000) <= recv_len
shell.c           :190 | finsh_getchar                                                   go=> rt_sem_take...
/*这里, 都没有recv到数据, 为什么会wakeup?*/
shell.c           :192 | finsh_getchar                                                   wakeup from rt_sem_take...
shell.c           :201 | finsh_getchar                                                   go=> rt_device_read
device.c          :360 | rt_device_read                        
device.c          :361 | rt_device_read                                                  uart4
device.c          :362 | rt_device_read                                    1(0x00000001) <= size
device.c          :376 | rt_device_read                                                  go=> device_read
dev_serial_v2.c   :415 | _serial_fifo_rx                       
dev_serial_v2.c   :416 | _serial_fifo_rx                                   1(0x00000001) <= size
dev_serial_v2.c   :460 | _serial_fifo_rx                                                 go=> rt_ringbuffer_get
ringbuffer.c      :189 | rt_ringbuffer_get                     
ringbuffer.c      :394 | rt_ringbuffer_data_len                
ringbuffer.c      :21  | rt_ringbuffer_status                  
ringbuffer.c      :398 | rt_ringbuffer_data_len                            0(0x00000000) <= data_len
dev_serial_v2.c   :465 | _serial_fifo_rx                                   0(0x00000000) <= recv_len
shell.c           :190 | finsh_getchar                                                   go=> rt_sem_take...
/*这里, 都没有recv到数据, 为什么会wakeup?*/
shell.c           :192 | finsh_getchar                                                   wakeup from rt_sem_take...
shell.c           :201 | finsh_getchar                                                   go=> rt_device_read
device.c          :360 | rt_device_read                        
device.c          :361 | rt_device_read                                                  uart4
device.c          :362 | rt_device_read                                    1(0x00000001) <= size
device.c          :376 | rt_device_read                                                  go=> device_read
dev_serial_v2.c   :415 | _serial_fifo_rx                       
dev_serial_v2.c   :416 | _serial_fifo_rx                                   1(0x00000001) <= size
dev_serial_v2.c   :460 | _serial_fifo_rx                                                 go=> rt_ringbuffer_get
ringbuffer.c      :189 | rt_ringbuffer_get                     
ringbuffer.c      :394 | rt_ringbuffer_data_len                
ringbuffer.c      :21  | rt_ringbuffer_status                  
ringbuffer.c      :398 | rt_ringbuffer_data_len                            0(0x00000000) <= data_len
dev_serial_v2.c   :465 | _serial_fifo_rx                                   0(0x00000000) <= recv_len
shell.c           :190 | finsh_getchar                                                   go=> rt_sem_take...
/*这里, 都没有recv到数据, 为什么会wakeup?*/
shell.c           :192 | finsh_getchar                                                   wakeup from rt_sem_take...
shell.c           :201 | finsh_getchar                                                   go=> rt_device_read
device.c          :360 | rt_device_read                        
device.c          :361 | rt_device_read                                                  uart4
device.c          :362 | rt_device_read                                    1(0x00000001) <= size
device.c          :376 | rt_device_read                                                  go=> device_read
dev_serial_v2.c   :415 | _serial_fifo_rx                       
......
......

3. 总结与反思

  • 假设我们要让自己的某个接口(比如usb cdc_acm) 作为rt-thread的console, 如何修改代码实现呢?
  • 我们的想法是尽量模仿uart串口的行为, 只要把底层的收发char的功能用我们自己的接口来替换. 来看看stm32_uart定义了那些操作函数吧.
  • 首先我们观察stm32_uart_ops, 在rt_hw_usart_init中需要调用rt_hw_serial_register注册串口设备. 一共有5个操作函数.
static const struct rt_uart_ops stm32_uart_ops =
{.configure = stm32_configure,.control = stm32_control,.putc = stm32_putc,.getc = stm32_getc,.transmit = stm32_transmit
};
  • 从rt_console_set_device函数调用链可以看到, stm32_configure和stm32_control被调用了, 因此必须要有. 但如果我们只需要固定一种配置即可, 那么这2个函数无用, 可以是空函数, 直接返回RET_OK即可.
  • 从rt_console_set_device函数调用链可以看到, rx和tx的rt_ringbuffer_init都已经定义好了, 不用用户定义. 直接用即可.
  • 从rt_kprintf函数调用链可以看到, 底层只需要实现stm32_putc即可.
  • finish_getchar是如何获得char的呢? 从finish_getchar函数调用关系可见, finsh_getchar就是通过rt_ringbuffer_get从ringbuffer中读取的. 因此我们需要负责往ringbuffer中填充数据.
  • 从UART4_IRQHandler接收的处理过程可以看到, 基本操作就是把读取到的ch先用rt_ringbuffer_putchar存入ringbuff, 然后调用rt_hw_serial_isr发送信号量. 因此, 我们只需要负责把接收到的数据用rt_ringbuffer_putchar存入ringbuff, 然后调用rt_hw_serial_isr发送信号即可. 比如对于usb cdc_acm, 我们可以usbd_cdc_acm_bulk_out函数中执行这2个操作. 因此stm32_getc不是必须的.
  • 对于rt-thread console和finsh设备, stm32_transmit用不到. 不用定义.
  • 总结以上, 假设要用usb cdc_acm作为rt-thread的console和finsh设备, 代码框架大致如下
void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
{struct rt_serial_rx_fifo *rx_fifo;rx_fifo = (struct rt_serial_rx_fifo *)_serial_cdc_acm.serial_rx;RT_ASSERT(rx_fifo != RT_NULL);for(int i=0; i < nbytes; i++){rt_ringbuffer_putchar(&(rx_fifo->rb), read_buffer[i]);rt_hw_serial_isr(&_serial_cdc_acm, RT_SERIAL_EVENT_RX_IND);      }// 继续接收数据usbd_ep_start_read(busid, ep, &read_buffer[0], usbd_get_ep_mps(busid, ep));    
}void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{// USB_LOG_RAW("actual in len:%d\r\n", nbytes);if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {/* send zlp */usbd_ep_start_write(busid, CDC_IN_EP, NULL, 0);} else {ep_tx_busy_flag = false;}
}static rt_err_t _cdc_acm_cfg(struct rt_serial_device *serial, struct serial_configure *cfg)
{return RT_EOK;
}static rt_err_t _cdc_acm_ctrl(struct rt_serial_device *serial, int cmd, void *arg)
{return RT_EOK;
}
static int _cdc_acm_putc(struct rt_serial_device *serial, char c)
{ep_tx_busy_flag = true;rt_memcpy(write_buffer, &c, 1);  /*必须借助于write_buffer, 因为它是nonchache的。否则输出乱码。*/usbd_ep_start_write(0, CDC_IN_EP, write_buffer, 1);while (ep_tx_busy_flag) {}return RT_EOK;
}static int _cdc_acm_getc(struct rt_serial_device *serial)
{/*这个函数不是必须的, 因为阅读源码发现, finsh_getchar-->rt_device_read-->_serial_fifo_rx-->rt_ringbuffer_get直接从ringbuffer get的, 不需要这个函数*/char ch=-1;return ch;
}static struct rt_uart_ops _cdc_acm_ops =
{.configure= _cdc_acm_cfg,.control = _cdc_acm_ctrl,.putc = _cdc_acm_putc,.getc = _cdc_acm_getc,
#ifdef RT_USING_SERIAL_V2.transmit = NULL
#endif    
};int rt_hw_cdc_acm_init(void)
{cdc_acm_init(0, HPM_USB0_BASE);struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;_serial_cdc_acm.ops = &_cdc_acm_ops;_serial_cdc_acm.config = config;m_cdc_acm_cfg.serial = &_serial_cdc_acm;rt_hw_serial_register(&_serial_cdc_acm, "cdcRtt", \RT_DEVICE_FLAG_RDWR | RT_SERIAL_EVENT_RX_IND,  &m_cdc_acm_cfg);return 0;
}int rtt_hw_cdc_console_init(void)
{rt_hw_cdc_acm_init();rt_console_set_device("cdcRtt");return 0;
}
INIT_APP_EXPORT(rtt_hw_cdc_console_init);

4. 附录: 完整版的trace log

详见
《深入剖析RT-Thread串口驱动:基于STM32H750的FinSH Shell全链路Trace分析与实战解密(下)》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/94312.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/94312.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python与C++通信教程:C++打包dll,供Python调用(1)

目录 1,新建一个工程 math_functions.cpp内容: 先编译一下看是否可以正常运行: 2,编译成dll,并用Python调用 有两种方式: 命令 1(使用静态链接): 可移植性: 命令 2(动态链接): 可移植性: 这里我使用的是静态链接的方式: python调用实例 test_dll.py 1,…

编程与数学 03-002 计算机网络 19_网络新技术研究

编程与数学 03-002 计算机网络 19_网络新技术研究一、软件定义网络&#xff08;SDN&#xff09;&#xff08;一&#xff09;SDN的基本原理与架构&#xff08;二&#xff09;SDN的应用场景与优势二、网络功能虚拟化&#xff08;NFV&#xff09;&#xff08;一&#xff09;NFV的概…

uniapp 跨端开发

一、创建uniapp项目 1. 项目架构2. 初始化项目3. pages.json 和 tabBar 案例4. uni-app和原生小程序开发区别5. 用命令行创建uni-app项目 官网链接&#xff1a;https://uniapp.dcloud.net.cn/quickstart-cli.html#创建uni-app6. 用vscode开发uni-app在uni-app中只有manifest.js…

区块链支付技术的核心原理

区块链支付利用分布式账本技术&#xff08;DLT&#xff09;实现点对点的价值转移&#xff0c;无需传统银行或支付网关的中介。核心特点是去中心化、透明、可追溯。• 基本流程&#xff1a;1. 用户发起交易&#xff1a;通过加密货币钱包发送支付请求&#xff08;例如用ETH支付&a…

linux中 多进程 导致cuda错误的问题解决

问题总结与解决方案 核心问题 在使用 Linux 系统时&#xff0c;多进程并行计算中加载模型到 GPU 时出现错误&#xff1a;_MODEL SentenceTransformer( model_path, device "cuda" if torch.cuda.is_available() else "cpu" )根本原因&#xff1a; CUDA 上…

智能感知的新入口:AIGC 与低延迟视频通路的深度融合

✳️ 引言&#xff1a;AIGC&#xff0c;正在重构视觉智能的“生成逻辑” AI生成内容&#xff08;AIGC&#xff09;正在从“内容创作工具”跃升为计算机视觉系统的新引擎。它不再只是“文生图”、“图生文”的演示技术&#xff0c;而是实实在在地改变着我们构建、处理和理解视觉…

Ubuntu 内网多台服务器时间同步方案(适用于临时能上外网的环境)

哎&#xff0c;最近项目是运行在内网环境下的&#xff0c;出现了由于时间不同步导致的bug。一般来讲&#xff0c;几台服务器的时间不一致&#xff0c;会带来很多问题&#xff0c;比如日志时间对不上、分布式服务出现异常&#xff0c;等等。项目上现在有三台服务器&#xff0c;其…

延长电池寿命的低Iq技术

本文章是笔者整理的备忘笔记。希望在帮助自己温习避免遗忘的同时&#xff0c;也能帮助其他需要参考的朋友。如有谬误&#xff0c;欢迎大家进行指正。一、概述随着电池供电型应用的激增&#xff0c;人们对质优价廉的电池和电池包的需求持续猛涨。电池制造商们不断采用新的化学物…

QT 如何实现enum与字符串的互转

将enum中定义的枚举值&#xff0c;以字符串的形式写入文件&#xff0c;同时也能从字符串转为枚举值。举例说明&#xff1a; ColorSelector中的Colors枚举&#xff0c;我们希望 kColorRed 这个写入到本地文件时&#xff0c;可以直接保存“kColorRed”&#xff0c;而非kColorRed对…

SLAM卷不动了,机器人还有哪些方向能做?

关注gongzhonghao【CVPR顶会精选】众所周知&#xff0c;机器人因复杂环境适应性差、硬件部署成本高&#xff0c;对高效泛化一直需求迫切。再加上多传感器协同难题、真实场景数据获取不易&#xff0c;当下对迁移学习 机器人智能融合的研究也就更热烈了。不过显然&#xff0c;这…

H.266 vs H.265/AV1/H.264:从工程落地看下一代视频系统的技术演进

一、背景&#xff1a;编解码标准演进背后的技术驱动 视频编码标准的更迭&#xff0c;从未只是一次简单的技术升级&#xff0c;而是对码率压缩效率、编码复杂度与画质质量三者之间平衡点的持续探索。在 H.264 成为全平台事实标准的十余年里&#xff0c;它成功支撑了 SD 至 1080…

Javascript面试题及详细答案150道之(031-045)

《前后端面试题》专栏集合了前后端各个知识模块的面试题&#xff0c;包括html&#xff0c;javascript&#xff0c;css&#xff0c;vue&#xff0c;react&#xff0c;java&#xff0c;Openlayers&#xff0c;leaflet&#xff0c;cesium&#xff0c;mapboxGL&#xff0c;threejs&…

Git如何同步本地与远程仓库并解决冲突

在团队协作开发中&#xff0c;保持本地仓库与远程仓库同步是至关重要的。本文将详细介绍如何使用 Git 更新本地仓库至最新远程版本&#xff0c;并深入解析冲突的产生原因及解决方法。一、同步本地与远程仓库1. 检查远程仓库配置首先&#xff0c;确保本地仓库已正确关联远程仓库…

Hadoop MapReduce 3.3.4 讲解~

✨博客主页&#xff1a; https://blog.csdn.net/m0_63815035?typeblog &#x1f497;《博客内容》&#xff1a;.NET、Java.测试开发、Python、Android、Go、Node、Android前端小程序等相关领域知识 &#x1f4e2;博客专栏&#xff1a; https://blog.csdn.net/m0_63815035/cat…

1、【数学】【硬币悖论】旋转硬币问题

问题描述&#xff1a; 两个相同的硬币&#xff0c;半径都是 rrr。一个硬币&#xff08;称为“动硬币”&#xff09;沿着另一个固定不动的硬币&#xff08;“静硬币”&#xff09;的外边缘无滑动地滚动一圈&#xff0c;回到起始位置。问&#xff1a;动硬币自身旋转了几圈&#x…

【盘古100Pro+开发板实验例程】FPGA学习 | PCIE 通信测试实验例程

本原创文章由深圳市小眼睛科技有限公司创作&#xff0c;版权归本公司所有&#xff0c;如需转载&#xff0c;需授权并注明出处&#xff08;www.meyesemi.com) 1. 实验简介 实验目的&#xff1a; 完成 PCIE 通信测试。 实验环境&#xff1a; Window11 PDS2022.2-SP6.4 硬件环…

基于高阶累积量的调制识别

基于高阶累积量的调制识别是一种利用信号的高阶统计特性来识别不同调制方式的方法。 1. 基本原理 高阶累积量&#xff08;Higher-Order Cumulants&#xff09;是信号处理中的一个重要工具&#xff0c;能够捕捉信号的非高斯特性。与高阶矩相比&#xff0c;高阶累积量对高斯噪声具…

Java常用数据结构入门

Java常用数据结构入门 前言 数据结构是程序设计中的基础&#xff0c;掌握常用数据结构能帮助你更高效地解决问题。本文面向Java初学者&#xff0c;介绍Java中常用的数据结构及其基本使用方法。 1. 数组 (Array) 数组是最基础的数据结构&#xff0c;可以存储固定大小的同类型…

Android GPU测试

一、Basemark GPU 可选择进行vulkan和opengl测试&#xff1a; 二、GFXBench 进行各种offscreen测试&#xff08;包括曼哈顿离屏&#xff09; 这是由GFXBench图形性能测试套件提供的一个著名3D图形渲染场景。 它模拟了一个复杂的未来都市环境&#xff08;类似曼哈顿&#xff…

2025年6月最新SCI-灰熊脂肪增长优化算法Grizzly Bear Fat Increase-附Matlab免费代码

引言 本期介绍一种受自然启发的创新算法——灰熊脂肪增长优化算法Grizzly Bear Fat Increase optimizer&#xff0c;GBFIO。GBFIO算法模仿灰熊为准备过冬而积累身体脂肪的自然行为&#xff0c;借鉴了它们的狩猎、捕鱼、吃草、蜂蜜等策略。于2025年6月发表在JCR 1区&#xff0c…