本站动态:

RFID代码编写问题汇总

最近在做RFID的开发,驱动由另外一个同事负责,而OEM/AEE和上层的Applet全部由我开发。

OEM层的作用主要是实现IRFID接口,该接口主要通过调用驱动提供的函数读取芯片里的数据。驱动在收到请求后做出处理,最后通过回调的方式将请求结果发还给OEMRfid,OEMRfid再通知上层Applet将数据显示到界面上。

OEM向Applet发送请求结果的方式,当时主要考虑了回调的方式、ISHELL_SendEvent和ISHELL_PostEvent。因为可选的方式较多,所以当初在设计的时候定义了一个宏来向Applet发送结果,这样一来可以简化代码,看上去更简洁,二是如果想选择另外的方式,不需要到处修改代码,而只需要将这个宏的定义调整一下就好。

最开始的时候其实允许Applet来选择是否使用回调,如果注册了回调函数,则通过回调函数返回请求结果,否则就使用ISHELL_SendEvent的方式。之所以没有选择ISHELL_PostEvent,是因为ISHELL_SendEvent是同步调用,可以不用考虑异步的问题,相对会比较简单一点。

问题一:不能使用同步的方法:
不过很快当我测试的时候,发现一个很奇怪的现象,就是Applet在回调函数中将数据显示到界面上的时候,却发现不是我想要的显示效果,而是乱乱的。不过我怎么也找不出问题出现在哪里,最后找来我们部门的高人——我的老大来帮我分析。他通过JTAG看Call Stack发现因为UI的绘制没有发生在UI Task里,也就是说,OEM层的回调函数是在另一个Task里执行的(UIM Task),然后调用Applet的回调用BUIW显示界面,所以发生了问题。所以OEMRfid不能通过Applet注册的回调函数也不能通过ISHELL_SendEvent向Applet发送结果。所以最后将IRFID提供的注册回调的接口删除掉了,并改用了ISHELL_PostEvent的方式。

问题二:两个前后紧挨在一起的语句需要设定顺序:
IRFID的其中一个功能是允许使用这查询交易记录,交易记录是按照顺序一条一条查询的。OEMRfid为了防止使用者连续查询多条交易记录(上一条交易记录还没有查询好就有开始了下一天交易记录的查询),同时为了保存当前正在查询的交易记录ID号,在Applet调用IRFID的接口查询某条交易记录的时候,OEMRfid会将该记录ID号记录下来,在OEMRfid提供给驱动的回调函数中如果收到查询交易记录的响应的时候,再将刚才保存的交易记录ID号设置为无效值,表示允许用户查询另一条交易记录了。所以在IRFID的查询交易记录的接口实现中会判断该变量,如果发现当前还在查询上一条记录,用户的这次调用会返回失败。概括起来说,Applet主动发起查询第一条交易记录请求,OEMRfid发现当前没有正在查询的交易记录,就向驱动发送请求,驱动在处理完请求之后调用回调函数将数据交给OEMRfid,OEMRfid对数据进行一定地处理变拷贝到自己的临时变量空间里,然后通过ISHELL_PostEvent通知Applet,让后再将正在查询的交易记录好设置回无效的ID号,Applet会收到Post过来的Event,将数据按照一定的规则显示到Form里,再去发送下一条请求。最开始OEMRfid回调函数中的POST_EVENT语句位于设置正在查询的记录ID号为无效值的语句之前。

后来被发现有的时候显示的交易记录数目少于实际保存在芯片中的交易记录数,而且时多时少,不是确定的。通过分析Trace终于被我发现那两条语句需要调整一下顺序,因为在正常情况下(没有在刚好发完ISHELL_PostEvent就将活动Task切换到UI Task),两条语句会连续执行的,不会有问题。但是在刚好在刚发完ISHELL_PostEvent的时候活动Task从UIM切换到UI,这样Applet调用IRFID_QueryRecordById的时候就会因为OEMRfid保存的正在查询的ID号还是上一条查询的ID号,就会返回失败而不会向驱动发送查询请求。

最后调整了两句语句的顺序后,果然如果所预期的,一切正常了。

问题三:ISHELL_PostEvent发送保存在局部变量中的数据
最开始使用的是同步的回调或ISHELL_SendEvent,所以数据的保存很简单,只要在OEM提供给驱动的回调函数里申请个局部变量(一个结构体)就好了,数据在处理完后该回调函数才会结束,这个局部变量才会失效。不过后来改成了异步的ISHELL_PostEvent,却忘记了数据是否还是有效的问题。这个问题一直都没有被我注意到,因为一直以来,不过是查询余额,还是查询交易记录,抑或是天线测试,都没有发生任何问题,Applet都能从这个局部变量中获取正确的数据并显示到屏幕上。今天又完成了COS Version的查询功能,结果意外地发现最后两条数据显示有问题(在OEMRfid里使用数据Format出来的保存在那个局部变量中的时间字符串),前面的两个时间显示正常,第三个时间却显示经常显示乱码,并且显示的乱码也不是总是相同的,而有的时候却也能显示正常。本来就感觉那个Format时间字符串的函数没有问题,因为前面的两个时间Format出来都没有问题,而通过Trace更加确定如此了。这是才让我想起PostEvent的异步和局部变量的问题。可是想不明白的是:既然PostEvent异步,局部变量放在栈中,按理说很有可能发生当Applet收到事件的时候,那个局部变量应该已经归还,而且空间是在栈中的,所以数据是不可能不被改写的(只要后面还有入栈的操作,内存中的数据就会被改写),为什么之前测试了那么多次的余额查询和交易记录查询都没有问题?难道是ISHELL_PostEvent做了特殊的处理?可是ISHELL_PostEvent根本无法知道最后的那个参数所代表的含义(即使知道是指针,也无法知道是什么类型的指针),所以ISHELL_PostEvent是不可能作任何保护的。后来才想明白,之所以在查询记录、查询余额、天线测试的时候都没有发现问题,是因为他们的操作比较少,速度比较快,而那个局部变量是在UIM的栈中申请的空间,所以即使那个变量的生命周期到了,那栈里的数据还是可以保存一定时间的,COS Version之所以最后的数据有问题,正是因为在读取完UIM栈里的数据之前,UIM发生了出入栈的事情,所以前面的数据是正常的,后面的数据是错误的。后来我在Applet收到COS Version的事件的时候,先将数据拷贝到自己的临时变量里,让后再处理将数据显示当屏幕到,结果果然没有了问题——这证实了我的猜测。

虽然这样解决了问题,而且看上去不会有问题发生,不过为了确保不发生意外,所以不再使用OEMRfid回调函数里的那个局部变量,而将其放到了OEMRfid的结构体里,这样就可以保证不会发生问题了。

以上这些问题主要是同步异步、任务切换和栈空间的使用问题,平时写代码可能不怎么会碰到(尤其是上层开发时任务切换的问题),这样的问题都让我碰到了,感觉很有意思。


[本日志由 shosh 于 2010-04-02 01:03 AM 编辑]
文章来自: Shosh原创
引用通告: 查看所有引用 | 我要引用此文章
Tags:
相关日志:
评论: 0 | 引用: 0 | 查看次数: 304
发表评论
昵 称:
密 码: 游客发言不需要密码.
内 容:
验证码: 验证码
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册帐号.
字数限制 1000 字 | UBB代码 开启 | [img]标签 关闭