rt-thread icon indicating copy to clipboard operation
rt-thread copied to clipboard

STM32使用serialV2框架,上位机发送太快,导致ringbuff长度与消息队列接收长度不一致问题

Open wdfk-prog opened this issue 3 years ago • 0 comments

硬件:STM32F429IGT6核心板 操作系统:RTT V4.1.5 串口框架:使用串口V2。配置如下 #define BSP_USING_UART #define BSP_USING_UART1 #define BSP_UART1_RX_USING_DMA #define BSP_UART1_TX_USING_DMA #define BSP_UART1_RX_BUFSIZE 256 #define BSP_UART1_TX_BUFSIZE 256 #define BSP_USING_UART2 #define BSP_UART2_RX_USING_DMA #define BSP_UART2_TX_USING_DMA #define BSP_UART2_RX_BUFSIZE 256 #define BSP_UART2_TX_BUFSIZE 256

/ 以 DMA 接收及轮询发送方式打开串口设备 / rt_device_open(serial, RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING);

DEBUG的时候,打断点停止程序运行,让上位机一直发送数据。然后在恢复程序运行。会发现线程被挂起了。。。。 这个线程使用串口V2,在接收回调函数中使用消息队列发送。线程阻塞接收。

打断点运行了一下,发现DMA的半满中断,全满中断,和空闲中断都进了一次后,线程才会进入一次去接收读到的长度。导致RINGBUFFER缓冲长度与接收消息长度不一致。 估计是中断进入太快,线程来不及响应。等到线程响应时,DMA的半满中断,全满中断,和空闲中断都进去过了。这个时候的RINGBUFFER缓冲长度是第三个中断处理完运算的长度了,而线程接收到的长度却是第一个中断运算后的缓存长度,导致长度不一致,挂起线程

裸机使用时,dma+串口接收+fifo缓冲区。我放入中断进入时就做判断处理。这样就不会有问题的。

是不是可以做个啥判断,保证线程处理的长度值一定是最新运算后的呢? 比如记录一下运算后的缓存长度是进入哪个中断处理的,线程接收时判断一下缓存长度的进入中断与线程接收时的进入中断是否一致。不一致在怎么处理之类的

代码如下

`代码如下

/**

  • @brief MODBUS线程
  • @param p:无用,不定义创建线程有警告
  • @retval None.
  • @note None. / static void modbus_thread(void p) { //初始化modbusRTU,从站地址为0x01,波特率为115200,无校验。 eMBRTUInit(&ucRTU_DCB,&ucMB_RTU_PORT,SLAVE_ADDRESS,BAUD_RATE,MB_PAR_NONE); eMBRTUStart(&ucRTU_DCB); //F4使能空闲中断不会立马进入中断函数进行状态转换,手动切换 ucRTU_DCB.eRcvState = STATE_RX_IDLE; while(1) { struct rx_msg msg; rt_memset(&msg, 0, sizeof(msg)); /* 从消息队列中读取消息 / rt_err_t result = rt_mq_recv(rx_mq, &msg, sizeof(msg), RT_WAITING_FOREVER); if (result == RT_EOK) { / 从串口读取数据 / rt_uint32_t rx_length = rt_device_read(msg.dev, 0,(CHAR )ucRTU_DCB.ucBuffer, msg.size); if(rx_length != msg.size) { LOG_W("Incorrect receive length"); break; } else { ucRTU_DCB.ucBufferCount = rx_length; //写入读取大小 xMBPortEventPost(&ucRTU_DCB,EV_FRAME_RECEIVED); //改变事件状态为接收事件 rt_mutex_take(mb_slave_mutex, RT_WAITING_FOREVER);//保存内存 eMBRTUPoll(&ucRTU_DCB); //读写内存 rt_mutex_release(mb_slave_mutex); //允许操作内存 rt_sem_release(mb_buff_sem); //释放MB处理线程信号量 } } } } /串口收发处理函数************************/ /**
  • @brief This function will set the reception indication callback function. This callback function
  •    is invoked when this device receives data.
    
  • @param dev is the pointer of device driver structure.
  • @param rx_ind is the indication callback function.
  • @return RT_EOK / static rt_err_t uart_input(rt_device_t dev, rt_size_t size) { struct rx_msg msg; rt_err_t result; msg.dev = dev; msg.size = size; result = rt_mq_send(rx_mq, &msg, sizeof(msg)); if (result == -RT_EFULL) { / 消息队列满 */ LOG_E("message queue full!"); } return 1; }

挂起代码如下,这段代码在serial_v2.c的_serial_fifo_rx函数中

if (recv_len < size) { /* When recv_len is less than size, rx_cpt_index is updated to the size * and rt_current_thread is suspend until rx_cpt_index is equal to 0 `

wdfk-prog avatar Sep 02 '22 03:09 wdfk-prog