//=====================================================================
//TITLE:
// C#程序导致MFDeploy无法ping通的问题
//AUTHOR:
// norains
//DATE:
// Thursday 05-May-2011
//Environment:
// .Net Micro Framework Porting V4.1
// Keil MDK 4.02
// STM32F103ZE Redcow Board
// Visual Studio 2010
//=====================================================================
为了测试编写USB驱动是否正常,编写了一个C#程序,其完整的代码如下:
这段代码看起来没什么问题,用VS2010也能正常下载,并且从串口中也能看到打印出来的字符串。但奇怪的事情就此发生了,自从成功下载该程序,并且正常运行之后,我的板子插到电脑上虽然可以枚举,但通过MFDeploy的Ping指令,却经常无法正常通讯。如果用Bus Hound软件来查看,发现PC端发送一个OUT包之后就卡死了,如图所示:
如果将NAND上的C#程序给擦除,那么一切又恢复了正常。这究竟是怎么一回事呢?
通过MDK的断点调试,会发现代码一直在执行Systick中断函数,而查看Systick的寄存器,发现reload的数值非常小,如图所示:
造成频繁执行Systick中断函数的原因是否源于此呢?通过MDK来强制更改NVIC_ST_RELOAD寄存器的数值为0x00FFFFFF来试试。结果不出所料,Bus Bound监控到USB数据又开始交互,MFDeploy也不再假死,而检测到板子为TinyCLR了!
转回来想想,为什么Systick的Reload的数值太小,导致MFDeploy假死呢?原因很简单,Reload是每次systick中断的间隔,而这个时间太小,很可能在刚执行完systick中断函数的时候,下一次中断又发生了,从而导致主线程的代码没有获得CPU时间执行!
原因找到了,那么我们该如何解决这个问题呢?首先我们来看看Systick的中断函数。一般来说,根据.NMF的示例代码,我们的中断函数无非如此:
这个中断函数逻辑很简单,如果当前的ticks大于要比较的ticks值,就执行HAL_COMPLETION::DequeueAndExec()函数。我们进到该函数看看。因为该函数比较大,有一些东西并不需要我们了解,所以下面罗列的是缩减后的主要部分,如下所示:
从中可以看到,该函数其实会调用HAL_Time_SetCompare来设置下一次的中断时间。但如果我们使用MDK单步调试,却会惊讶发现,该函数一直没有被调用,因为ptrNext一直为NULL!如果再仔细点,在还没执行C#程序之前,ptrNext不是为NULL的!
根据经验推测,问题就出在于C#程序。具体点,问题在于C#的Main函数返回了!因为C#的Main函数返回,导致Node的结点被释放,于是ptrNext就为NULL。如果此时又刚好Systick的间隔很小,代码又因为ptrNext为NULL而不执行HAL_Time_SetCompare函数,那么最终结果就是:不停地发生Systick中断,而无瑕执行主线程代码!
原因找到之后,可能大家想到的最简单的解决方式就是在C#的Main函数中执行一个死循环,如下所示:
结果没错,这样更改之后,的确一切都正常了。似乎一切都很美好,不是么?但是,这样的健壮性是不够的,因为我们无法确保做应用的程序员能够遵守这个约定。而万一他们忘记的话,那么结果将是灾难性的:因为USB已经无法PING通,更谈不上下载程序,所以做应用的程序员无法凭一己之力来挽回自己的错误。除了你,.NMF的移植者,通过MDK来设置Systick的Reload寄存器,让CPU跑到正常的轨道上,除此以外,再无它法。
为了避免这情况,我们可以将中断函数修正一下。我们自己来检测ptrNext,如果它为NULL的话,那么我们手动调用HAL_Time_SetCompare函数即可,如下所示:
经过这么一更改,那么引发MFDeploy无法响应的问题不再存在,我们也不用再担心应用程序员忘记最后写死循环啦!
分享到:
相关推荐
C#完成中文可视化PING命令程序,附程序源码,Windows中的PING命令是基于命令提示符的,有些英文不太懂的朋友可能不知道PING 出来的数据是什么意思,现在好了,中文语言界面的PING命令用C#编写实现了,而且代码也超...
用c#写的多线程PING的程序 可以将结果统计
C# 判断IP地址是否能够PING通
本程序采用VS2010软件开发,用的是C#语言,提供源码,主要功能如下 1, 可持续ping 1个IP地址或多个IP地址,可选择记录在指定的文件或自动生成文件记录或不记录。可查看IP什么时候丢包。保存的文件的路径也会做相应...
C#实例 C#程序实例 C#程序设计实例 C#程序设计案例 C#实例 C#程序实例 C#程序设计实例 C#程序设计案例
C#程序时钟 C#程序时钟 C#程序时钟 C#程序时钟 C#程序时钟C#程序时钟 C#程序时钟
屏保C#程序屏保C#程序屏保C#程序屏保C#程序屏保C#程序
C# ping程序测试网络连通性,测试局域网电脑在线数目,网卡地址
很实用的程序测试网络连接状态的C#程序,简单易懂
自己编写的一个可视化的Ping程序,感兴趣的可以参考下
C#实现PING的功能 让 你 成为WINDOWS编程高手,慢慢的积累~
c#程序设计300例,主要涉及基础的常用的代码案例,新手可以用来练习代码,高手就没必要了
C#做的局域网Ping和消息发送程序
互联网应用程序开发,应用程序ping在VS2005中的实现代码。
c#程序开发c#程序开发c#程序开发c#程序开发c#程序开发c#程序开发c#程序开发c#程序开发c#程序开发c#程序开发c#程序开发
[源码]C#做的局域网Ping和消息发送程序
Visual C#程序设计基础教程
实现批量PING功能,不再调用cmd窗体,另启用窗体进行调用
是自己用c#做的一个简单的小程序(windows下的ping)
PING程序是我们使用的比较多的用于测试网络连通性的程序。PING程序基于ICMP,使用ICMP的回送请求和回送应答来工作。由计算机网络课程知道,ICMP是基于IP的一个协议,ICMP包通过IP的封装之后传递。有两个程序,一个是...