CC1310: 如何为串口添加uDMA?

Part Number: CC1310

我没有找到对应的demo,自己写的有点问题,卡死在urat忙,
若在    UART_DMASend(dmaTxBuffer, numLen); 后面添加 UART_write能够正常dma输出,但输出结束立刻卡死?

 

#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>

#include <ti/drivers/GPIO.h>
#include <ti/drivers/UART.h>

#include <ti/devices/cc13x0/driverlib/udma.h>
#include <ti/devices/cc13x0/driverlib/uart.h>
#include <ti/devices/cc13x0/driverlib/prcm.h>
#include <ti/devices/cc13x0/inc/hw_memmap.h>
#include <ti/devices/cc13x0/inc/hw_uart.h>

#include "Board.h"


#define DMA_CONTROL_TABLE_SIZE  32
#pragma DATA_ALIGN(g_pDMAControlTable, 1024)
static tDMAControlTable g_pDMAControlTable[DMA_CONTROL_TABLE_SIZE];// 发送缓冲区
static uint8_t dmaTxBuffer[128];


// 用于调试输出的 UART 句柄(普通模式)
static UART_Handle uart;


// 辅助调试打印(使用普通 UART_write)

static void dbg_print(const char *s) {
    UART_write(uart, (uint8_t*)s, strlen(s));
}


// 初始化 µDMA 控制器

static void DMA_Init(void) {
    // 检查控制表对齐
    if ((uint32_t)g_pDMAControlTable & 0x3FF) {
        while (1); // 对齐失败,应检查链接脚本
    }

    // 使能 µDMA 外设时钟
    PRCMPeripheralRunEnable(PRCM_PERIPH_UDMA);
    PRCMLoadSet();
    while (!PRCMLoadGet());

    // 设置 DMA 控制表基址
    uDMAControlBaseSet(UDMA0_BASE, g_pDMAControlTable);
    uDMAEnable(UDMA0_BASE);

    // 配置 UART TX 通道属性
    uDMAChannelAttributeEnable(UDMA0_BASE, UDMA_CHAN_UART0_TX, UDMA_ATTR_HIGH_PRIORITY);
    uDMAChannelControlSet(UDMA0_BASE, UDMA_PRI_SELECT | UDMA_CHAN_UART0_TX,
                          UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_8);
}


// DMA 发送函数(阻塞,带固定延时,不依赖中断)

static void UART_DMASend(const uint8_t *data, uint32_t len) {
    // 1. 等待前一次 UART 完全空闲(防止冲突)
  while (HWREG(UART0_BASE + UART_O_FR) & (1 << 3));  // BUSY

    // 2. 确保 UART TX DMA 请求使能(bit1 = 0x02)
    HWREG(UART0_BASE + UART_O_DMACTL) |= 0x02;

    // 3. 配置 DMA 传输(BASIC 模式 + 软件触发)
    uDMAChannelTransferSet(UDMA0_BASE, UDMA_PRI_SELECT | UDMA_CHAN_UART0_TX,
                           UDMA_MODE_BASIC,
                           (void*)data,
                           (void*)(UART0_BASE + UART_O_DR),
                           len);
    uDMAChannelEnable(UDMA0_BASE, UDMA_CHAN_UART0_TX);
    uDMAChannelRequest(UDMA0_BASE, UDMA_CHAN_UART0_TX);

    // 4. 固定延时等待 DMA 完成(115200bps 每个字节约87us,加2ms余量)
    uint32_t delay_us = len * 100 + 2000;
    usleep(delay_us);

    // 5. 等待 UART 真正发送完毕(FIFO 空 + 不忙),带短超时避免卡死
    uint32_t timeout = 10000;
    while (!(HWREG(UART0_BASE + UART_O_FR) & (1 << 7))) { // TX FIFO 空
        if (--timeout == 0) break;
    }
    timeout = 10000;
    while (HWREG(UART0_BASE + UART_O_FR) & (1 << 3)) {    // BUSY
        if (--timeout == 0) break;
    }

    // 6. 禁用 DMA 通道,为下次发送准备
   // uDMAChannelDisable(UDMA0_BASE, UDMA_CHAN_UART0_TX);
}

//============================================================================
// 主线程(TI-RTOS 任务)
//============================================================================
void *mainThread(void *arg0) {
    // 初始化基础驱动
    GPIO_init();
    UART_init();

    // 配置 LED(指示运行状态)
    GPIO_setConfig(Board_GPIO_LED0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
    GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON);

    // 打开 UART(普通模式,用于调试输出)
    UART_Params uartParams;
    UART_Params_init(&uartParams);
    uartParams.baudRate = 115200;
    uartParams.writeDataMode = UART_DATA_BINARY;
    uartParams.readDataMode = UART_DATA_BINARY;
    uart = UART_open(Board_UART0, &uartParams);
    if (uart == NULL) while (1);

    dbg_print("\r\n=== UART DMA Final Version ===\r\n");

    // 初始化 DMA
    DMA_Init();
    dbg_print("DMA initialized.\r\n");

    // 准备发送数据(复制到 SRAM 缓冲区)
    const char *helloMsg = "Hello from UART DMA!\r\n";
    uint32_t msgLen = strlen(helloMsg);
    memcpy(dmaTxBuffer, helloMsg, msgLen);

    // 主循环:每隔一秒发送一次
    uint32_t counter = 0;
    while (1) {
        // 发送固定消息
        UART_DMASend(dmaTxBuffer, msgLen);
        // 发送计数器数值(仍使用 dm aTxBuffer)
        char numBuf[32];
        snprintf(numBuf, sizeof(numBuf), "Counter: %lu\r\n", counter++);
        uint32_t numLen = strlen(numBuf);
        memcpy(dmaTxBuffer, numBuf, numLen);
        UART_DMASend(dmaTxBuffer, numLen);
        // 延时 1 秒
        sleep(1);
    }
}