蓝牙技术
直播中

刘丽

8年用户 1353经验值
私信 关注
[问答]

CYW20829全双工UART和I2C Master同时工作导致UART log输出异常怎么解决?

CYW20829使用code example HAL_I2C_Master, 修改UART使用P1_3, P1_2, 修改I2C Master使用P0_3, P0_2, uart log和I2C 读写Device都可以正常工作.
在此基础上, 参考example code UART_Transmit_and_Receive, 使用cyhal_uart_getc(&cy_retarget_io_uart_obj,  &read_data, 0)从串口终端读取数据的功能后会导致输出异常. 如再使用
cyhal_uart_putc(&cy_retarget_io_uart_obj, read_data)回显数据,会造成完全没有log输出的情况.


请帮忙看看应该如何解决?

回帖(1)

张华

2025-7-3 18:17:41

在CYW20829上同时使用全双工UART(用于日志输出)和I2C Master时,添加UART接收回显功能后导致日志输出异常,可能是由于阻塞式读取占用CPU资源中断冲突所致。以下是解决步骤和代码修改建议:




1. 检查UART接收模式


问题cyhal_uart_getc(&cy_retarget_io_uart_obj, &read_data, 0)使用非阻塞模式(超时=0),但频繁轮询可能导致CPU负载过高,影响其他任务(如I2C通信)。
改进:改用事件驱动接收(中断回调),避免轮询占用资源:


   // 注册回调函数
   cyhal_uart_register_callback(&cy_retarget_io_uart_obj, uart_rx_handler, NULL);
   cyhal_uart_enable_event(&cy_retarget_io_uart_obj, CYHAL_UART_IRQ_RX_NOT_EMPTY, CYHAL_ISR_PRIORITY_DEFAULT, true);

   // 中断回调处理接收
   void uart_rx_handler(void *arg, cyhal_uart_event_t const *event)
   {
       if (event->event_type & CYHAL_UART_IRQ_RX_NOT_EMPTY) {
           uint8_t data;
           if (CY_RSLT_SUCCESS == cyhal_uart_getc(&cy_retarget_io_uart_obj, &data, 0)) {
               // 回显字符(非阻塞方式)
               cyhal_uart_putc(&cy_retarget_io_uart_obj, data);
               // 其他处理逻辑
           }
       }
   }



2. 优化日志输出和回显优先级



  • 回显延迟问题:直接调用cyhal_uart_putc()回显可能阻塞日志输出。


  • 方案:将回显数据存入队列,在后台(如主循环)发送:


     QueueHandle_t uart_tx_queue; // FreeRTOS队列

    // 在回调中入队数据
    if (xQueueSendFromISR(uart_tx_queue, &data, pdFALSE) != pdTRUE) {
         // 队列满时丢弃数据(或扩展队列)
    }

    // 主循环中发送数据
    void task_uart_tx(void *arg) {
         uint8_t data;
         while (1) {
             if (xQueueReceive(uart_tx_queue, &data, portMAX_DELAY)) {
                 cyhal_uart_putc(&cy_retarget_io_uart_obj, data);
             }
         }
    }





3. 调整中断优先级



  • 冲突分析:UART和I2C使用不同引脚,但共享内核中断资源。

  • 解决:显式设置中断优先级,确保UART接收中断优先级高于I2C
     // UART中断优先级设为高(数值越低优先级越高)
    cyhal_uart_set_irq_priority(&cy_retarget_io_uart_obj, CYHAL_ISR_PRIORITY_HIGH);
    // I2C中断优先级设为中/低
    cyhal_i2c_set_irq_priority(&i2c_master, CYHAL_ISR_PRIORITY_MEDIUM);




4. 检查DMA冲突


如果使用DMA进行UART/I2C传输:



  • 确保两者使用不同的DMA通道。


  • 初始化时手动分配资源:


     // 分配UART的DMA通道
    cyhal_dma_t uart_dma;
    cyhal_dma_init(&uart_dma, CYHAL_DMA_CHANNEL_0);
    cyhal_uart_configure_dma(&cy_retarget_io_uart_obj, &uart_dma, &uart_dma);

    // I2C使用另一通道
    cyhal_dma_t i2c_dma;
    cyhal_dma_init(&i2c_dma, CYHAL_DMA_CHANNEL_1);





5. 验证硬件连接



  • 确保UART/I2C引脚无短路或过载。

  • 测量信号质量(如噪声、电压)。




6. 最小化测试



  • 暂时禁用I2C功能,验证UART回显是否正常。

  • 若问题消失,则问题在资源协调;若仍存在,检查UART配置。




最终建议组合方案



  1. 使用中断回调处理UART接收(非轮询)。

  2. 队列管理回显数据(避免在中断中直接发送)。

  3. 提高UART中断优先级

  4. 分离DMA通道


这样确保:



  • UART接收不影响主循环。

  • I2C操作不被阻塞。

  • 日志输出和回显通过队列解耦。


通过以上步骤,应能解决UART日志异常和I2C工作冲突问题。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分