首页 > 其他分享 >RTThread使用DMA串口接收数据不连续的问题

RTThread使用DMA串口接收数据不连续的问题

时间:2023-05-03 23:56:51浏览次数:34  
标签:rt DMA -- rx result 串口 serial 接收数据

RTThread使用DMA接收串口数据的问题

问题/现象

使用RTThread的DMA接收串口数据,数据不连续,即IDLE中断没有起到作为一个frame的判定.

经过对serial和drv_uarts源码的分析,得出原因:

graph LR RX_INT[USART1_IRQHandler] -->process1(...) process1 -->rx_isr1[dma_recv_isr] rx_isr1 -->flag1{isr_flag} flag1 -->|UART_RX_DMA_IT_IDLE_FLAG| serial_isr1[rt_hw_serial_isr] serial_isr1 -->event{event} DMA_INT[UART1_DMA_RX_IRQHandler] -->process2(...) process2 -->rx_isr2[dma_recv_isr] rx_isr2 -->flag2{isr_flag} flag2 -->|UART_RX_DMA_IT_HT_FLAG| serial_isr2[rt_hw_serial_isr] flag2 -->|UART_RX_DMA_IT_TC_FLAG| serial_isr2[rt_hw_serial_isr] serial_isr2 -->event{event} event -->|RT_SERIAL_EVENT_RX_DMADONE|do_something(...)

从上图可知,发生IDLE中断时,USART1_IRQHandler调用的是和UART1_DMA_RX_IRQHandler相同的接口 —— rt_hw_serial_isr.

这就造成无法区分是IDLE中断还是DMA中断.


不改变源码的情况下,仍使用DMA+IDLE中断,目前这两种方式是比较好的

解决方式①

  • 接收数据
/* 接收数据回调函数 */
static rt_err_t uart2_input(rt_device_t dev, rt_size_t size)
{
    rt_err_t result;
    result = rt_sem_release(&serial2_sem);/*通知serial_thread_entry线程,有数据了*/
    if ( result == RT_EOK)
    {
        rt_kprintf("sem release error!\n");
    }
    return result;
}

static void serial_thread_entry(void *parameter)
{
    rt_err_t result;
    rt_uint8_t c = 0;
    rt_uint8_t i = 0, rx_state = SERIAL2_STATE_WAIT_FRAME;
    rt_device_t serial2 = rt_device_find("uart2");
    struct frame_msg msg;
    while (1)
    {
		switch(rx_state)
		{
			case SERIAL2_STATE_WAIT_FRAME:
			{
				result = rt_sem_take(&serial2_sem, RT_WAITING_FOREVER); /* 等待新的一帧数据 */
				if (result == RT_EOK)
				{
					rt_kprintf("%s: frame start\n", __func__);
					rx_state = SERIAL2_STATE_RECV_DATA;
					i = 0;
				}
				break;
			}
			case SERIAL2_STATE_RECV_DATA:
			{
				/* 读取一段数据 —— 数个字节(不足一帧) */
				while(rt_device_read(serial2, 0, &c, 1) != 0)
				{
					framebuf[i] = c;
					i++;
				}

				result = rt_sem_take(&serial2_sem, 10); /* 将信号量设置为带有超时的信号量,等待下一段数据 */
				if(result == -RT_ETIMEOUT)  /* 超过10个OSTicks没有读到数据,判定该帧结束 */
				{
					framebuf[i] = '\0';
					msg.data = framebuf;
					msg.size = i;
					result = rt_mq_send(&rtc_rx_mq, (void*)&msg, sizeof(struct frame_msg)); /* 给其它线程通信 */
					if(result != RT_EOK)
					{
						rt_kprintf("%s: msgqueue send error-[%d]\n", __func__, result);
					}
					rx_state = SERIAL2_STATE_WAIT_FRAME;    /* 一帧结束 */
					rt_kprintf("%s: frame end\n", __func__);
				}
				else
				{
					/*接收下一段数据*/
					rt_kprintf("%s: frame recv ing...\n", __func__);
				}
				break;
			}
			default:
				break;
		}
    }
}

解决方式②

把信号量换成消息队列.


其它问题

代码中的几个局部变量在线程中具有了和线程一样长的生成周期

life_circle(serial_thread_entry) = life_circle(variable(i))
                                = life_circle(variable(rx_state))
                                = life_circle(variable(serial2))
                                = ...

这样是不是意味着thread的stack一直被占用?

嗯,是的.

标签:rt,DMA,--,rx,result,串口,serial,接收数据
From: https://www.cnblogs.com/Rabbit-susu/p/17369923.html

相关文章

  • 套接字接收数据时抛出异常, 远程端口已关闭。
    while(true){byte[]bytes=UdpClient.Receive(refremoteEndPoint);NetMessagenetMessage=NetMessage.Parse(newArraySegment<byte>(bytes));OnReceiveMessage?.Invoke(netMessage,remoteEndPoint);}因为在接收数据的时候,也用这个端口发送数据了。。......
  • LINUX C、QT上位机间串口传输数据库文件
    在串口传输文件时,我们通常希望以二进制形式将文件发送出去,因为这样可以避免文件内容被解释为ASCII码,并且可以减少数据传输的时间和数据量。在QT上位机中可以使用以下方式将文件读取并发送出去://读取本地SQLite3数据库文件QStringfilename="wifi_UAV.db";QFilefil......
  • LINUX 串口设备行规程——回车检测机制
    做项目时调用串口,遇到了只有存在回车时才能read到数据的情况,这是设置了行规程的结果。禁用行规程即可取消按行读取机制,如下:(建议大部分情况下都禁用)newtio.c_lflag&=~ICANON;......
  • J-link自带的串口发不出校验位
    买了个j-link,外观如下图: 安装驱动之后它的5号引脚和17号引脚可以当做串口的TXD和RXD,在设备管理器中显示如下图: 用起来非常的方便。但是最近参与的项目中要用到校验位,发现了问题。用逻辑分析仪测试发现即便串口调试助手中设置了校验位,但是发送出去的数据中依然不......
  • Codeforces Round #459 (Div. 2) D. MADMAX DAG&&博弈
    Asweallknow,Maxisthebestvideogameplayeramongherfriends.Herfriendsweresojealousofhers,thattheycreatedanactualgamejusttoprovethatshe’snotthebestatgames.Thegameisplayedonadirectedacyclicgraph(aDAG)withnvertic......
  • RS485串口MODBUS通讯仪器表自动存储到数据库的方法
    参考资料链接:https://blog.csdn.net/qq_15627707/article/details/113059580 软件名称:DAQforIIOT通用工业数据采集系统 www.daq-iot.com 19936624847 ......
  • AXI DMA 设计分析
    AXIDMA架构SBIUSBIU:SlaveBusInterfaceUnit。从机总线接口模块:通过外部AHB/APB4主机访问DW_axi_dmac的内部寄存器的读写控制逻辑。从机总线接口可以通过DMAX_SLVIF_MODE参数进行配置。DMAX_SLVIF_MODE:用于从机接口的协议。AHB(0),APB4(2)根据子系统要求,可以选择......
  • 3DMax Ornatrix to UE Groom制作毛发动态效果
    Hello,大家好,今天给大家带来3DMaxOrnatrix毛发插件导入UEGroom毛发动态效果,我是沙漠骆驼-JFD。1、使用Ornatrix毛发插件生成毛发2、添加编辑器Clump和Frizz3、导出格式:OrnatrixAlembic(.abc)4、导入到虚幻引擎,注意毛发的路径不要有中文,缩放Y要-1,不然毛发是反的;5......
  • 全志v851s 的uart3 设置成普通串口收发
    本文转载自:https://bbs.aw-ol.com/topic/3281/由于UART0被设定为系统dubug输出(简单来说就是将ttyS0设定为console),所以使用UART3作为普通的串口,进行与别的设备通信。1.查看硬件电路图SCH_Schematic1_2022-11-23,查看uart3的TXRXpin脚电路图pdf路径:Yuzukilizard/Hardware/......
  • STM32CubeMx配置串口,并控制LED灯亮灭
    一、环境配置软件:stm32cubemx6.4.0keil5.30大虾丁丁串口调试助手硬件:正点原子stm32f103ZET6开发板二、配置stm32cubemx项目选择USART1,Asynchronous(异步通讯),RS232是异步通讯,就是没有同步时钟也没有同步线进行通讯。 设置串口基础配置:波特率:115200Bit/s;数据长度8位;无校......