针对XMC7100 UART2 DMA的问题,以下是根本原因分析和解决方案:
cyhal_uart_write内部机制与DMA发送存在资源竞争。// 修改RX DMA初始化 - 启用循环模式
cyhal_dma_set_descriptor(&dma_rx_obj,
NULL,
CYHAL_DMA_DESCRIPTOR_CONTINUOUS, // 循环模式
sizeof(rx_buffer));
// 添加UART回调函数
void uart_event_handler(void *arg, cyhal_uart_event_t event)
{
if(event & CYHAL_UART_RX_DMA_DONE) {
// 1. 处理接收数据
process_rx_data();
// 2. 重新配置DMA(指向新缓冲区)
cyhal_dma_set_dst_addr(&dma_rx_obj, (uint32_t)rx_buffer);
cyhal_dma_set_transfer(&dma_rx_obj, sizeof(rx_buffer));
// 3. 重新启用RX DMA
cyhal_dma_enable(&dma_rx_obj);
}
}
// 配置UART事件
cyhal_uart_register_callback(&uart_obj, uart_event_handler, NULL);
cyhal_uart_enable_event(&uart_obj,
CYHAL_UART_RX_DMA_DONE,
3); // 优先级// 直接使用DMA发送替代cyhal_uart_write
void uart_dma_send(const uint8_t *data, size_t len)
{
// 等待上一次传输完成
while(cyhal_dma_is_busy(&dma_tx_obj));
// 配置DMA传输
cyhal_dma_set_src_addr(&dma_tx_obj, (uint32_t)data);
cyhal_dma_set_transfer(&dma_tx_obj, len);
// 手动触发UART DMA请求
Cy_SCB_SetRxFifoLevel(uart_obj.base, CY_SCB_FIFO_SIZE - 1);
cyhal_dma_start_transfer(&dma_tx_obj);
}// 初始化UART时增加配置
cyhal_uart_cfg_t uart_cfg = {
.data_bits = 8,
.stop_bits = 1,
.parity = CYHAL_UART_PARITY_NONE,
.rx_buffer = NULL,
.rx_buffer_size = 0,
.flow_control = CYHAL_UART_FLOW_CTRL_RTS_CTS // 启用硬件流控
};
// 配置FIFO深度匹配DMA
Cy_SCB_SetRxFifoLevel(uart_obj.base, 3); // 当FIFO>=3字节时触发DMA
Cy_SCB_SetTxFifoLevel(uart_obj.base, 0); // TX空时立即触发DMA// TX DMA配置 (MEM->UART)
cyhal_dma_init(&dma_tx_obj, CYHAL_DMA_CHANNEL_0, NULL);
cyhal_dma_configure(&dma_tx_obj,
CYHAL_DMA_DIRECTION_MEM2PERIPH,
CYHAL_DMA_PRIORITY_HIGH);
cyhal_dma_set_src_addr(&dma_tx_obj, 0); // 动态设置
cyhal_dma_set_dst_addr(&dma_tx_obj, (uint32_t)&uart_obj.base->TX_FIFO_WR);
// RX DMA配置 (UART->MEM) - 循环模式
cyhal_dma_init(&dma_rx_obj, CYHAL_DMA_CHANNEL_1, NULL);
cyhal_dma_configure(&dma_rx_obj,
CYHAL_DMA_DIRECTION_PERIPH2MEM,
CYHAL_DMA_PRIORITY_VERY_HIGH,
CYHAL_DMA_DESCRIPTOR_CONTINUOUS); // 关键配置!!!
cyhal_dma_set_src_addr(&dma_rx_obj, (uint32_t)&uart_obj.base->RX_FIFO_RD);
cyhal_dma_set_dst_addr(&dma_rx_obj, (uint32_t)rx_buffer);
cyhal_dma_set_transfer(&dma_rx_obj, sizeof(rx_buffer));printf("DMA TX State: %sn", cyhal_dma_is_busy(&dma_tx_obj) ? "Busy":"Ready");
printf("UART Status: 0x%08lXn", Cy_SCB_GetInterruptStatus(uart_obj.base));// 确保UART时钟>=4x波特率
if(cyhal_uart_get_clock(&uart_obj) < (4 * baudrate)) {
// 调整时钟分配器
}
注意:在波特率超过1Mbps时必须使用硬件流控(RTS/CTS),PCB布线需保证信号完整性。如果仍存在问题,建议检查MPN配置工具生成的时钟树设置是否正确。
举报
更多回帖