Zynq 【SDK裸机开发之PS】——串口接收缓存
最近项目上在使用Zynq开发,也是第一次使用,期间会遇到各种各样的问题,属于Zynq本身问题的我会更新到我的另一篇博客《Zynq开发调试踩坑指南》中,这个版块将会陆续记录我自身在程序开发中的问题。
这次的问题是串口收数据问题,众所周知,我在一个月前就已经把串口调通了,收发试着也没啥问题。现在正在加一个通过串口远程升级的功能,也就是发的数据量大了,几十毫秒一帧数据,每一帧都有个一百多字节,然后就发现偶尔收的数据CRC校验对不上,仔细核对发现是少收了一个字节了。
我一开始是怀疑收数据的软件层驱动不对。毕竟整个软件层都是我自己写的,也没大量验证过,于是直接看串口收的memory中数据确实是少一个字节。
于是就怀疑串口线的问题,因为我现在跑的波特率是2Mbps,就单独拿串口线自发自收,倒是没有问题,说明硬件链路是没问题的。
这时候我就开始合理推测了,我看到丢字节的数组位置大概在第64这个位置,心里一个不成熟的想法就浮出水面。
我的Zynq串口收数据是使用FIFO溢出中断+超时中断的方式来获取数据的。超时中断大家都懂,stm32单片机里有这个概念。就是单个字节发完后多长时间内如果没有新的比特进来,就认为是超时了,这时候你想要的数据就都已经在缓存区里了。不同于stm32超时中断需要配置DMA,Zynq本身有FIFO,中断后直接读FIFO就可以了。但是这个FIFO是有空间限制的,收发缓存都只有64字节的大小。如果一次收到的数据不足64字节,倒是可以直接读完一帧,那如果收到的数据比64字节多呢?
这时候就需要FIFO溢出中断和超时中断一起配合使用了。我开辟一个空间,FIFO溢出后我把FIFO里的数据全部读走,再来数据在之前的空间上叠加数据,当产生超时中断时,则认为数据全部收完了。收完这些数据,再把数据放进环形缓存区,供再上一层软件调用。
以下是我串口中断的配置方法,注意,其中有一处是需要改动的,下面再提
/*** 配置超时中断。如果设置为N,则超时时间为N*4个比特时钟。* 例如115200波特率,每比特时钟为0.00000868s,即8.68us。* 如果N=8,则8.68us * 8 *4 = 277.76us*/
XUartPs_SetRecvTimeout(&Uart0Ps, 40);
/*设置FIFO触发条件 */
/*** FIFO最大值64,此处的值是FIFO溢出的中断,也即RXOVR中断* 设置为最大值,和timout配合,如果接受字节小于64则在TOUT* 中断里读走数据。如果接受字节大于64字节,则首先由RXOVR* 中断接收前64字节数据,再由TOUT中断接受剩下的字节,两者配合。*/
XUartPs_SetFifoThreshold(&Uart0Ps, 64 - 1) ;
/* 设置中断触发类型 */
XUartPs_SetInterruptMask(&Uart0Ps, XUARTPS_IXR_RXOVR | XUARTPS_IXR_TOUT);
可以看到上面我把缓存溢出的阈值设置为了64,也就是Zynq本身硬件上的最大串口缓存大小。
下面是我串口中断函数里做的操作,注意,recv函数我传递的参数是100,实际这个数填大点都没事,他只会返回缓存区有的数据长度,并不会溢出。
//接收fifo满if (UartSrValue & XUARTPS_IXR_RXOVR) /* check if receiver FIFO trigger */{u32 Len = XUartPs_Recv(UartInstPtr, Usart1DataRcevSture.RecvOffsetPtr, 100);Usart1DataRcevSture.RecvOffsetPtr += Len;/* clear trigger interrupt */UART_PS_INTR_CLEAR(UartInstPtr->Config.BaseAddress, XUARTPS_IXR_RXOVR);}//空闲中断else if (UartSrValue & XUARTPS_IXR_TOUT){gpio_toggle(PL_LED_PIN);u32 Len = XUartPs_Recv(UartInstPtr, Usart1DataRcevSture.RecvOffsetPtr, 100);Usart1DataRcevSture.RecvOffsetPtr += Len;Usart1DataRcevSture.RecvDataLen = Usart1DataRcevSture.RecvOffsetPtr - &Usart1DataRcevSture.RecvBuffer[0];Usart1DataRcevSture.RecvOffsetPtr = &Usart1DataRcevSture.RecvBuffer[0];Usart1DataRcevSture.RecvFlg |= 0x01;/* clear trigger interrupt */UART_PS_INTR_CLEAR(UartInstPtr->Config.BaseAddress, XUARTPS_IXR_TOUT) ;}
这样的配置和接收方法本身没什么问题,但是当像我这样高速率通信,高频率发帧时候就会出现我上面说的,丢字节的情况。为什么会丢呢?恰恰就是因为我们把缓存区的大小设置的和硬件允许的缓存一样大,当我们产生FIFO溢出中断时,如果中断没来得及把所有数据读走,这时候再来一个新数据,他就没有地方可存放了,就会丢失字节。当然,这种事情发生的概率取决于硬件对中断的响应速度和程序执行中断的时间。
我现在波特率太高,则会更容易出现这样的问题。
XUartPs_SetFifoThreshold(&Uart0Ps, 50 - 1) ;
所以我们只需要更改这里,把FIFO溢出的阈值设置稍小一点,就可以给硬件留出一定的裕量了。
改完之后测试就再没出现过问题。
如果您觉得这篇文章帮到了你,请点赞或者留下您的评论,您的鼓励是我前进的动力~
关注博主公众号 “嵌入式电子创客街” 获取更多及时技术分享~
关注+星标公众号,及时获取更多技术分享~
Zynq 【SDK裸机开发之PS】——串口接收缓存相关推荐
- 复旦微FMQL(国产Zynq) 【IAR裸机开发之PS】——前言
关注+星标公众号,及时获取更多技术分享~ 作者 | 冰茶奥利奥 微信公众号 | 嵌入式电子创客街 前一段时间写了不少使用Xilinx的Zynq芯片的文章,说实话在整个开发过程中几乎没有遇到什么疑难杂症 ...
- android清除缓存 代码,Android应用开发之Android应用清除缓存一般清理目录和代码的教程...
本文将带你了解Android应用开发Android应用清除缓存一般清理目录和代码的教程,希望本文对大家学Android有所帮助. 一个应用安装完成,会有缓存,缓存一般分为内部存储的和外置的,内存中路径 ...
- OK6410裸机开发之LED灯
平台:WinXP+eclipse+OpenJTAG 开发板:OK6410A 128M DDR 1G NandFlash ---------------------------------------- ...
- 方案设计:IPC产品系统设计 - 基于芯片商提供的SDK API开发之二
方案:安霸.海思(君正.Mstar.安凯) 1.每个模块都是开N(1,2,3...)个pthread线程,线程之间通过生产者,消费者模型(或者进程间通信机制)实现数据同步/异步.通过数据队列缓冲模块数 ...
- Android NDK开发之旅14 JNI 缓存策略
###缓存策略 有两种: ####一.使用局部的static变量: JNIEXPORT void JNICALL Java_com_test_JniTest_cache (JNIEnv * env, ...
- 如何写一个高效的串口接收程序
导读:学单片机的大概最先.最常写的通信程序应该就是串口程序了,但是如何写出一个健壮且高效的串口接收程序呢?接下来鱼鹰将根据多年的开发经验教你如何编写串口接收程序(可在公众号获取个人编写的串口接收源码) ...
- 如何写一个健壮且高效的串口接收程序?
正文:13923字 阅读时间:35分钟 建议先马后看 导读:学单片机的大概最先.最常写的通信程序应该就是串口程序了,但是如何写出一个健壮且高效的串口接收程序呢?接下来鱼鹰将根据多年的开发经验教你 ...
- ZYNQ开发系列——PS开发之HelloWorld
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 ZYNQ开发系列--PS开发之HelloWorld 前言 外设接口 SDK建立工程相关操作记录 前言 俗话说一日不见,如隔三秋.两年没 ...
- 嵌入式开发之zynqMp ---Zynq UltraScale+ MPSoC 图像编码板zcu102
嵌入式开发之zynqMp -Zynq UltraScale+ MPSoC 图像编码板zcu102 1.1 xilinx zynqMp 架构 1.1.1 16nm 级别工艺 Zynq UltraScal ...
最新文章
- 20159208 《网络攻防实践》第七周学习总结
- php 随机调用文章,zblog PHP调用热门文章、随机文章和热评文章代码
- mysql 免安装重装_MYSQL的免安装的重装
- 跟我学XSL(二) -XSL的运算符
- 清除浮动php,CSS清除浮动
- 老板:再用Log4j就收拾东西回家吧!
- parameter与localparam使用区别
- csdn 不登录浏览全文 chrome 浏览器
- php的ob函数详解
- rtx二次开发 java_RTX二次开发集成
- Spring源代码解析
- Linux设备模型 (1)
- python实例代码爬虫_python 网络爬虫实例代码
- 阿里图标管理网站[iconfont.cn](iconfont.cn)的正确打开方式
- 企业微信小程序体验版必须打开调试模式才能获取相关数据的问题,qy.selectEnterpriseContact接口调用问题
- 分分钟穿透手机,实现远程控制
- 基于macos M1 python3.8的tensorflow安装(简单方便几步完成)
- 基于springboot的资产管理系统
- AndroidStudio报错:Entry name ‘META-INF/androidx.legacy_legacy-support-core-utils.version‘ collided
- 初学者必学:绘画初学者如何设计人物?