“满纸荒唐言,一把辛酸泪。 都云作者痴,谁解其中味?”引用一下老曹的诗,来做一下我的这篇文章的开头,做技术的人,有时候感觉挺可悲的,是个青春饭,“一把辛酸泪”,曾在公交车上听别人说起“谁说的做技术的就是吃青春饭呀,我公司里人家还有四十多岁的还在写代码”,我心里暗想,你不知道他干的有多累。
别说四十了,当你写代码写到个30多岁的时候,就有点心有余而力不足了,新的技术层出不穷,年轻后生的活力永远比你旺盛,你再也没有激情和热情,再撒播在这片看似神圣而实则劳苦的“高技术”中。你所有剩下的就是吃你的老保---经验,等你的经验被磨灭,无用武之地的时候,就油尽灯枯了。
写的有点悲伤,扯远了,进入正题吧。
今天是周天了,为了中秋今天要上班了,从这周的周一接了老板的一个任务,调试WIFI,模块选择了网上铺天盖地的WM-G-MR-09,这个模块不是主要的,主要的是这个模块封装的WIFI,就是鼎鼎大名的Marvel8686,我们的平台是S3C2440,接口Marvel8686给提供了两种:1、SDIO 2、SPI接口。用的最多的还是SDIO接口的,我们根据平台的富余情况,选择了SPI接口的。明确了要做的事情,就开始去网上扫荡了,恩,不错,还能扫荡到源码,关于这个驱动有Linux的也有Wince5.0的,一看挺好并且有SPI的源码,心想这下好了,不费吹灰之力就能搞定。谁知“好戏还在后面”,后来在芯片厂家也得到了SPI的源码,只可惜是PXA3xx的,因此重点就放在了s3c2440的SPI协议的实现。
源码包的结构是IF IO WLAN ,网上下的还多了一个WLAN_CUSTOM,最终我还是用了网上的这个源码。
IO是SPI底层驱动文件,IF是重新封装了IO中的一些函数,做为IO和WLAN之间的中间层,因此换不同的屏台一般只需要改动IO文件夹的内容即可。
SPI的驱动我用过的POLL Mode,方便,从调试的结果来看,还算可以,上网之类的还能接受。
接下来就说一下调试的时候遇到的问题,后来看网上的上传这个代码的人说PXA270的已经调通,S3C2440的还有问题,请高手调通了,还望指点。晕,还没有通,看来要头痛一番了,不过这位仁兄总体来说已经实现了99%,只是在移植的时候漏掉了一些东西,漏掉的看似无用,其实可能蕴藏着巨大的危险。所以我的移植原则是,比着葫芦画瓢的时候,如果你对这一段的作用不理解,最后就别去掉,画上。
我在调试的时候觉得比较糗,我看网上调试这个模块的时候遇到的问题,几乎我都遇上了,下面就总结一下,这把辛酸泪:
1、拿过下载的代码来,不出意外,很容易编译通过,只要搞过驱动的,添加注册表,platfom.bib中调用驱动,应该不在话下。当执行的时候,第一个问题,就跳出来了,什么问题,没问题,因为进入了系统,什么网络也没有,右下角那该死的图标也没有,控制面板中,那该死的连接也没有,郁闷,咋办,调呗,程序员在求爷爷告奶奶希望不要出问题而爷爷奶奶不理的时候怎么办,调呗。
首先,找到打印信息的宏控制,打印信息就是程序员的生命,没有了它,大家都得玩儿完,就像硬件工程师离开了示波器和万用表(当然驱动工程师,对这两样也是必须的),就像鱼儿离开了水,就像酒鬼离开了酒,就像。。。。,Wlan/igxBug.h目录中,#define MRVL_PRINT_DBG_MSG #define DBG_MSG_TO_RETAILMSG,就基本上OK了,也不用太多的打印了,重新编译下载,调试,发现在开机启动的时候只打印了DBGPRINT(DBG_ERROR,(L"INIT - Enter DriverEntry/n"));
DBGPRINT(DBG_ERROR, (L"*** Driver version %s ***/n",
TEXT(MRVDRV_DRIVER_BUILD_VERSION)));
DBGPRINT(DBG_ERROR, (L"*** Built on %s %s ***/n",
TEXT(__DATE__),
TEXT(__TIME__)));,DBGPRINT(DBG_LOAD,(L"<== DriverEntry: register miniport success/n"));
就结束了,进到系统涛声依旧。怎么办,看代码,NdisMRegisterMiniport,是注册驱动的,This will cause MrvDrvInitialize to be called before returning,结果MrvDrvInitialize ()函数中有打印为啥没打印,那就是说没有调用,why,于是再去网上扫荡,恩,真给我扫着了,需要改源码中注册表中的"NoDeviceCreate"由1改为0,就OK了,MrvDrvInitialize 也执行了,也打印了。下一个问题出现了,go on...
2、SPI读出的ID是错误的,代码中体现了8686的芯片ID是0x000b,而我读出的是0x00FF或者是0xFFFF,这个问题肯定怀疑的是两个问题:1、SPI协议写的不正确 2、芯片根本没有工作。看了一阵子SPI协议,也根据Linux的那个源码,改了SPI试了,仍旧。。。,最终转向了硬件,首先看芯片的文档,看看有什么蛛丝马迹,首先测测各个引脚的电压是否正常,一测均正常,奇怪了,这个问题足足耗了我两天多的时间,最后还是仔细的看芯片文档的要求和我们的原理图,最终发现了一个问题,我们的芯片上有两个电阻,你们到这里可以猜猜是哪两个电阻了吧,对,就是IF_SEL_1 IF_SEL_2两个引脚的电阻,文档中明确规定,如果是选择SDIO模式可以不接,如果是SPI模式必须下拉100K的电阻,而我们这里没有接,芯片认为我们的是SDIO模式,当然就工作不正常了,最终焊上两个电阻,一测OK,ID 0x000b正确了,问题又来了
3、产生了异常,网上有位仁兄也是,难兄难弟呀,后来发现这个异常总是在中断处理函数中的回调函数引用那一句就异常,pDeviceContext->IsrCallBack(pDeviceContext->isrContext);有时没有异常(这句话注意了,这是我刚才所说的照葫芦画瓢的地方,这就是网上好多人可以搜索到网络,但是连接不上的原因,这是画瓢没有画全的一个表象),这里感觉很奇怪,就是感觉中断来的太快了,中断线程刚注册了,就来了一个中断,而这时候,这个回调函数pDeviceContext->IsrCallBack还没有被赋值,因此出现了异常,可以看看代码,赋值在IF文件中,的初始化后的注册中断中。不管了,当时可没有考虑这么多,就想那就过滤掉吧,if是NULL的就不执行了。就这样当做解决了,其实如果所有的代码都正确的话,这时候不会来中断的。为了增强程序的健壮性和调试程序的方便性,就加了判断为NULL的语句。接着下一个问题
4、ID正确了,不异常了,但是,在下载Firmware的时候,sbi_download_wlan_fw_image函数中的第一句,是个无线循环读取SCRATCH_1_REG的值,要么是在这里就不动了,要么就是读了个非零值,在接下来的一个循环中读到的又是0值,导致下载Firmware失败,当然写的是成功,但是你看他的下载的字节数cnt=0,因此不正确,这又让我怀疑起SPI不对?,又折腾了好一阵子SPI协议,又捯饬了好几套代码方案,最终还是到网上继续扫荡,不留下一根鸡毛,终于在有个问题跟我一样的帖子上找到了答案,虽然这篇帖子我已经看了无数遍,再一次看的时候忽然发现,它的讨论还有2、3页,平时我只看了看第一页,没注意还有2和3页,在1页中他说这个问题在调了SPI 的cs时序之后,就好了,奶奶的,怎么调的,结果在2页找到了答案,说是每次写完需要等到写结束之后才可以,于是我就在IO文件夹中的spi文件中的函数p_s3c_spi_write_short()中写了句while((pDeviceContext->spi->SPSTA0 & (0x1<<0))==0);然后还有个收获是有位网友,还指出了这个代码的一个错误之处是p_s3c_spi_read_short()函数中*pData = (u8)(pDeviceContext->spi->SPRDAT0<<8);不正确,一想果然,应该是*pData = (unsigned short)(pDeviceContext->spi->SPRDAT0<<8);试了试,编译烧写,当时的场景忘了,好像是烧了之后起来了,网络搜到了,但是不能连接上,这次的问题网上的帖子层出不穷,80%遇到了这个问题。但是别高兴的太早,我还没到这一步,也许下一个问题,全世界可能就我一个人遇到了
5、我每次烧写完进入系统后,有20%可以跳出无线配置框,还有更怪的问题是我重启后就100%不跳出无线配置框了。只有在第一次烧写起来后,可以。郁闷这个问题,可能我再也查不出,也不需要再查出原因了
6、怎么办上面的那个破问题,怎么办,我于是想,既然只是平台换了,我就只改IO的东西,(网上的代码,IF接口也是不太相同的),我所有的其他的都不改,因为网上说PXA270调通了,我就以他为蓝本,试试。结果经过我今天半天的努力(细心的朋友,可以看出来了,这时已经折磨了我6天半了),终于把2440的SPI添加到了PXA70的封装函数中了,不过需要注意的是,我看PXA270270每次都传输DWORD,而2440只传输u8,稍微改动了一点点,结果试试,唉,可以跳出无线配置框,但是就是搜索不到无线网络,郁闷,但是这次是每次重启100%跳出无线配置框,我想老天是拿我开涮啊,有钱的时候没时间,有时间的时候没钱啊。。。好不容易能每次都启动了,结果又不能搜到网络了,这时候怎么办,怎么办,怎么办,想既然那个代码能搜索到,并且别人也没有出现我的5问题,那就还是以上一种方案为蓝本,WLAN和IF应该没什么大问题,肯定还是IO的问题,结果就对比着修改过的PXA270修改,这时候已经是今天(周天)下午1点多了。当我边整理代码规范,边对比的时候发现,p_s3c_wlan_isr_init()的中断初始化和PXA270有点不同的地方,InterruptDisable(pDeviceContext->sysintr_wlan);加在了InterruptInitialize之前,函数的最后添加了
CeSetThreadPriority(pDeviceContext->thread_wlan, 97);
ResumeThread(pDeviceContext->thread_wlan);
InterruptDone(pDeviceContext->sysintr_wlan); 第一个设置中断处理线程的优先级,第二个不是很明白,继续执行线程,既然没挂起,为何来的继续呢??高手指点。第三句通知内核中断处理,并且开中断,一般用在中断处理线程中,用在这里也怪怪的!!!我还改了一些地方,感觉应该对程序没什么影响,感觉应该是这个,编译完,下载,哇哇 ,可以看到网络了,并且每次重启都可以看到,一试连接,OK,很顺畅的就连接上了。也能够ping通,但是先上来不能上网,我后来又整理了一些代码,写到函数里,如统一通过函数来使能SPI还是结束,再重新烧写,也能上网了,这一步比较奇怪,等会我把S3c-spi.c的代码贴上,大家看看吧,肯定对你调这个芯片的代码有很大的帮助。
下面就是S3c-spi.c的代码,上面提到的一些改动都在下面显示了