STM32F107——OTG模块之USB设备之虚拟串口移植(四)

来源:互联网 发布:手机编辑epub软件 编辑:程序博客网 时间:2024/05/19 16:36

第一次移植的时候,可能由于对这个USB库还是太了解,可能改动了底层的我一个关键值,当移植完成之后,在测试的过程发现,总是会出现某一次的数据只发送了一小段,而剩下的部分只有在我再次获取的时候会被发送,且对应这次的数据也会发送。

我的具体实现过程是这样的:通过上位机下发一条指令,当单片机识别指令之后会一次上传2000字节的数据,而测试中出现第4*n次要求数据的时候,总是会只上传一部分,剩下的会在4*n+1次上传,且4*n+1对应的2000字节也会上传。(图1、图2)。



第一步:先来看看USB发送数据的机制,从usbd_conf.h文件中可以知道"#define APP_RX_DATA_SIZE  2048"这个宏定义,结合usbd_cdc_core.c文件中的函数usbd_cdc_DataIn()可以看出USB的发送方式是通过一个2048字节的FIFO,每次发送不大于64Byte的数据(图3);


第二步:通过查找方式可以找到,函数usbd_cdc_DataIn()是被函数Handle_USBAsynchXfer()调用的,而在分析该函数的时候会发现,数据在发送的时候,如果这次发送的数据不会越过2048,则这次的数据会被一次发送完成,如果超过2048(循环FIFO),数据会分两次发送(图4);


第三步:知道了上面的发送原理,接下来可以看看我遇到的问题,第一次发送2000字节OK,第二次发送2000字节OK,第三次发送2000字节OK,第四次144字节!并且会在第五次发送1856+2000字节!我画了一张图如下所示,一行代表一次传输,蓝色为某次的开始,红色为某次的结束,阴影重的地方是空白没有传输,阴影轻的地方是出错的地方(图5);


第四步:经过多次测试发现,这种错误很规律,在传输的次数是4的倍数的时候就会出现这种错误,刚开始分析以为是FIFO溢出了,但是我是通过指令来让一次数据进行传输的,而我发的指令之间的间隔很长,且每次只发送2000,离2048还有剩余,所以排除了溢出的可能(个人认为排除!);

第五步:无奈之下只能进行仿真了,分析可行的方式之后,在函数usbd_cdc_DataIn()中if条件语句里的"USB_Tx_State = 0;"这条语句之前添加断点,将变量APP_Rx_ptr_out和APP_Rx_ptr_in和APP_Rx_length添加到watch窗口(图6);


第六步:开始仿真。先让程序全速运行,然后下发指令,再全速运行,再下发指令,如此重复,直到第五次数据传输结束,记录每一步传输过程中这几个变量的变化情况(图7);


第七步:从仿真的结果来看,上层变量在出错的地方值的变化是正确的,从这里也可以反应出来,目前接触到的上层和中间层已经处理好了数据的发送,在更底层的发送中可能存在缓存方面的逻辑,导致到了第4*n次发送的时候出现问题,而对于我进行第二次移植的时候这个问题目前还没出现,分析可能是由于自己刚开始不懂,修改了底层某个地方,现在找不到了,由于精力有限就不继续追究了,等闲下来的时候再找找问题所在,当然,有哪位大神知道的望告知一声,多谢啦!