5 UART DMA接收报错

发布于 2021-04-08 15:43:58

大家好,我在测试uart dma接收功能时,出现了下列现象,查找论坛资料,没有解决,请教一下串口dma接收的正确用法。
RTT4.0.3 / stm32f103re
依据bsp模板,新建核心板bsp,只添加了串口功能(中断接收模式收发正常)
测试代码:

// drv_usart.c
result = rt_hw_serial_register(&uart_obj[i].serial, uart_obj[i].config->name,
                                       RT_DEVICE_FLAG_RDWR
                                       | RT_DEVICE_FLAG_INT_RX
                                       | RT_DEVICE_FLAG_INT_TX
                                       | RT_DEVICE_FLAG_DMA_RX  // 添加DMA收发
                                       | RT_DEVICE_FLAG_DMA_TX
                                       | uart_obj[i].uart_dma_flag
                                       , NULL);
#include <rtdevice.h>

#define LOG_TAG              "app.uart"
#define LOG_LVL              LOG_LVL_DBG
//#define LOG_LVL              LOG_LVL_INFO
#include <ulog.h>

#define DEVICE_UART2        "uart2"
#define THREAD_PRIORITY     25
#define THREAD_STACK_SIZE   512
#define THREAD_TIMESLICE    10
static rt_device_t  dev_uart2_handle;

static struct rt_messagequeue u2_mq;

static struct rt_thread u2_thread;
static rt_uint8_t   u2_thread_stack[THREAD_STACK_SIZE];

typedef struct uart_rx_msg
{
    rt_device_t dev;
    rt_size_t size;
}uart_rx_msg_t;

static rt_err_t u2_uart_input(rt_device_t dev, rt_size_t size)
{
    uart_rx_msg_t msg;
    rt_err_t ret;
    
    msg.dev = dev;
    msg.size = size;
    
    ret = rt_mq_send(&u2_mq, &msg, sizeof(msg));
    if(ret == -RT_EFULL)
    {
        //LOG_W("mq full...\r\n");
    }
    
    return ret;
}

static void u2_read_thread_entry(void *para)
{
    uart_rx_msg_t msg;
    rt_err_t ret;
    rt_uint32_t rx_length;
    static char rx_buf[RT_SERIAL_RB_BUFSZ + 1];  // 要根据串口初始化时 control 设置的大小调整,这里写rtt默认的串口大小

    while(1)
    {
        rt_memset(&msg, 0, sizeof(uart_rx_msg_t));
        rt_memset(rx_buf, 0, RT_SERIAL_RB_BUFSZ + 1);
        
        // 从消息队列读消息
        ret = rt_mq_recv(&u2_mq, &msg, sizeof(msg), RT_WAITING_FOREVER);
        
        if(ret == RT_EOK)
        {
            // 从串口读取数据
            rx_length = rt_device_read(msg.dev, 0, rx_buf, msg.size);
            rx_buf[rx_length] = '\0';
            
            LOG_D("uart rx data, dev:%s, size:%d, data:%s\r\n", msg.dev, rx_length, rx_buf);
            
            // 解析数据
            // TODO
            
        }
        
    }
}


static int dy_uart_send(rt_device_t dev, void* buf)
{
    rt_err_t ret = -1;
    
    ret = rt_device_write(dev, 0, buf, rt_strlen(buf));
    return ret;
}

static int app_uart_init(void)
{
    rt_err_t ret = RT_EOK;
    static char msg_pool[256];
    
    struct serial_configure u2config = RT_SERIAL_CONFIG_DEFAULT;
    
    // find 
    dev_uart2_handle = rt_device_find(DEVICE_UART2);
    
    if(dev_uart2_handle == RT_NULL)
    {
        LOG_E("can't find %s device.\r\n", DEVICE_UART2);
        return RT_ERROR;
    }
    
    // mq
    ret = rt_mq_init(&u2_mq, "u2_rx_mq",
                msg_pool,               // 消息缓存
                sizeof(uart_rx_msg_t),  // 一条消息的最大长度
                sizeof(msg_pool),       // 消息缓存区大小
                RT_IPC_FLAG_FIFO);
    ASSERT(ret == RT_EOK);
    
    // control
//    u2config.bufsz = 128; // 修改缓冲区大小
//    rt_device_control(dev_uart2_handle, RT_DEVICE_CTRL_CONFIG, &u2config);
    
    // open  
    ret = rt_device_open(dev_uart2_handle, RT_DEVICE_FLAG_DMA_RX); // 以DMA接收及轮询发送方式打开
    if(ret != RT_EOK)
    {
        LOG_E("can't open %s device. ret:%d\r\n", DEVICE_UART2, ret);
    }
                
    // rx callback
    rt_device_set_rx_indicate(dev_uart2_handle, u2_uart_input);
    
    ret = rt_thread_init(&u2_thread,
                        "u2_rx",
                        u2_read_thread_entry,
                        RT_NULL,
                        u2_thread_stack,
                        THREAD_STACK_SIZE,
                        THREAD_PRIORITY,
                        THREAD_TIMESLICE);

    ASSERT(ret == RT_EOK);
    rt_thread_startup(&u2_thread);   
                
    return RT_EOK;
}
INIT_APP_EXPORT(app_uart_init);

static void uart_send_test(void)
{
    rt_err_t ret = -1;
    char str_buf[] = "uart send test.\n";  // 15+1
    
    ret = dy_uart_send(dev_uart2_handle, str_buf);
    if(ret == 0)
    {
        LOG_E("uart send failed.\r\n");
    }
    else
    {
        LOG_D("send ok. ret:%d\r\n", ret);
    }
    
}
MSH_CMD_EXPORT(uart_send_test, u2 send test);

现象:
uartlog.png

查看更多

关注者
0
被浏览
83
3 个回答
flashman2002
flashman2002 2021-04-08

串口设置是轮训,终端,DMA模式3选1,你的串口设置不对。

mii
mii 2021-04-08

`result = rt_hw_serial_register(&uart_obj[i].serial, uart_obj[i].config->name,

                                   RT_DEVICE_FLAG_RDWR
                                   | RT_DEVICE_FLAG_INT_RX
                                   | RT_DEVICE_FLAG_INT_TX
                                   | RT_DEVICE_FLAG_DMA_RX  // 添加DMA收发
                                   | RT_DEVICE_FLAG_DMA_TX
                                   | uart_obj[i].uart_dma_flag
                                   , NULL);`

这一部分代码你修改了?官方指导并不要求修改。
https://docs.rt-thread.org/#/rt-thread-version/rt-thread-standard/programming-manual/device/uart/uart?id=%e4%b8%b2%e5%8f%a3%e8%ae%be%e5%a4%87%e4%bd%bf%e7%94%a8%e7%a4%ba%e4%be%8b

Ka$ha
Ka$ha 2021-04-08

v5编译器数据收发正常;v6编译的固件,发数据正常,收数据报hard fault on handler错误...
编译器.png
v5编译.png


测试发现,AC6编译器-Ofast-Os编译出的固件是可以正常工作的,-Oz编译运行后会提示“未对齐”错误
ac6优化.png

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览