原文在 2009/10/14 发表于broncho论坛,转载请写出处,谢谢!
在MTK平台上部署CDMA
[注] 我们用的MTK版本是6225 ,CDMA 模组是威盛via的。此项目没有量产,代码放在那也是加密冷藏没有价值,写思路出来与大家讨论关于程序设计。本人不是MTK专家,有分析不对之处,请指出,谢谢。
[硬件篇]
加一个cdma模组,具体操作本人不知道,就不讲述了。
[软件篇]
让我们来分析一下。既然在MTK平台,上层应用最好不要改动,就只能在底层修改。在L4层我们发现,MTK提供了mmi接口,那么我们就有机会重写这些函数,这个就是最大前提。对于CDMA,要对AT做封装,适配于L4(适配器设计模式)。我们可以开一个task,专门处理CDMA AT,串口数据的读取。考虑到CDMA的AT比较弱,特别是三方通话,呼叫保持,对AT的处理,得用较多全局变量来保存上下文。
代码目录:
代码: 全选
Vendor -|
|- ATCMD -| at_cdma
| at_gsm
| at_l4a
| at_thread
At_thread 主要是处理AT的线程.
首先创建一个task.
/* task */
void AT_Cmd_main(task_entry_struct * task_entry_ptr); 一个while 循环,处理消息。
At_gsm 是一个参考物,为了测试cdma方便,我们自己实现MTK的AT封装。At_cdma 是cdma编解码目录。可以说,at_cdma继承于at_gsm,两者有统一的接口(主要是gsm标准,cdma适应于gsm),所以很多的工作,在at_cdma做了很大的调动。如果实现和gsm不一样,我们就要rewrite接口实现,基于函数替换。
上面已有提到过,我们要重新实现mtk提供的l4a层,那么at_l4a 就是干这样的活了。为了不直接在mtk l4a的函数里修改,我们采用include 的方式。所有的处理函数放在AT_L4c_Funs_V07B.c
写我们自己的 l4a_callback_ex.c ,在ps\l4a\src\l4a_callback.c 的末尾 #include “l4a_callback_ex.c” ,然后在 l4a_main.c的 l4a_recvmsg(ilm_struct *ilm_ptr)里加以区别:如果 l4c_current_mod_id == l4c_atcmd_mod_id,就调用我们实现的接口函数处理cdma,否则,就调用mtk提供的处理gsm(不变)。
串口通讯的处理
利用w32_uart.c 里提供的一些函数,打开串口,设置波特率,数据控制流等参数。
对数据的发送,接收,加入休眠模式,以免功耗过大。
AT的处理
在MTK上对CDMA AT的处理,则采用赤裸裸的封装,源于有开发过Firebird BBS的经历,我更喜欢这种最原始的美,不要和我谈什么软件架构,设计模式的,考虑越多,项目越难以进展,领导只关心是否能跑起来,不然项目取消,大家散伙吧。说远了。AT具有随意性,我们假设发出请求的AT,就有相应的响应,设一个定时器,来处理超时问题。如果超时了,我们再发AT,如果有OK回应,就说明模组还能正常工作,那么这个AT的请求就是失败的。对自动上报的消息的处理,在获取AT响应时,我们判断是自动上报的消息,则当场处理,继续读下一行数据,直到有期望的响应值。如果请求发出一个AT, 既有自动上报消息,又有自身的请求响应,该如何处理呢?举个例子,查询网络注册情况,发出AT+CREG?后,
+CREG:1,0×3614,0x2
+CREG:1,0×3614,0x2
+CREG: 2,1,0x00C3,0x00AD
我们发现,请求的响应有4个参数,而自动上报的有三个参数。再举个例子:
开机时,模块会自动开启一个15min的计时器,如果15分钟内没有收到AT+LCT指令,模块就自动关机,如果收到了该指令,15min的计时器又重新开始计时。所以我们看到+LCT主动上报时,就发出AT+LCT。问题来了,我们打电话时,查询CLCC,那么问题出现如下:
AT+CLCC?
+LCT
AT+LCT
+CLCC:1,0,1
ok
ok
两个响应消息交错在一起,就难以分析了,我们就得保证消息串化。
等等。AT响应的处理,大部分工作是解析字符串,取出你想得到的数据,填充结构体。总之,在做AT处理时,要反复测试,考虑很多的异常,这便是软件设计的难点之一。
AT层上GSM 与CDMA的差异
就列举几个比较重要的差别,很多小细节还是非常多的,请参阅厂家的AT SPEC。
(1)AT测试命令,比如信号查询 GSM是AT+CSQ;CDMA则是 AT+CSQ? 很多种情况如此,CDMA在后面要加上一个“?”号。
(2)AT响应字符串
比如, GSM:
+CCLK: “04/01/19,15:38:32″
+CCLK:后面有空格
CDMA:
+CCLK:2008/8/6,13:57:5,3
+CCLK: 后面没有空格
响应字符串解析函数必须能处理空格问题。可以写一个类似于sscanf的函数,专用解析AT响应字符串。
(3) CDMA中”UIM”的字符串,这个主要出现在电话本与短信。MTK上是”SIM” 对应 0, “ME”对应1;CDMA把”UIM”对应为0即可。此外,短信与电话本,gsm从1开始读取,cdma则从0开始读。
(4) TE特征字符串设定
GSM: AT+CSCS
CDMA没有这方面的设定,默认为UNICODE,在电话本处理中,AT请求和响应要特别指出.
(5) 短信的PDU编解码完全不同.请参考 GSM0707与3gpp2 的C.S0015-B
(6) 电话状态查询CLCC,CDMA提供的功能很弱,不管有没有来电,拨出电话,查询CLCC总有一个+CLCC:响应,GSM则不然。CDMA处于三方通话,呼叫保持,呼叫等待时,查询CLCC也是只有一路+CLCC:响应,这样,我们得自己构建适应于GSM的CLCC,维护,更新CLCC列表。
开关机流程
(1)开机
+VPUP
模块上报开机启动标志,也可根据该命令判断模块重启,收到该命令后进行初始化设置. (模组有问题时,这个上报是不可靠的.)
+MSStatus:0
模块上报协议栈已打开。
+VROM:1
模块上报漫游状态(1 为非漫游状态)。 这个上报是不可靠的,就是说,并不是每次开机都会有这个上报。不过,如果出现这个,我们认为可以显示中国电信了,其他手机已开机就显示运营商,估计也是照这个来做。
AT+ISF?
查询模块初始化状态,2s~3s 执行一次
+ISF:1
模块初始化完成。
接下来才可以对电话本,短信,通话记录初始化。
由上,在+MSStatus:0与 +ISF:1之间,可以操作的行为有:
(0)ATE0 软件已经默认关闭回显,该步骤可省。
(1)注册网络与信号上报. AT+CREG=2 AT+ARSI=1
(2)查询UIM是否插好?AT+CPIN?
(3)查询信号 AT+CSQ?
(4)查询国家码,网络码 AT+VMCC? AT+VMNC?
(5)选择语音通道 AT+SPEAKER=0
开机流程比较繁琐,要适应与MTK的启动流程,比如开启Pin码,手机密码,网络运营商的获取,信号强度上报等。一般情况下,模块加电后会自行开启协议栈。不插UIM卡启动,模块不会自行打开协议栈。需要输入PIN的情况下,只有在用户输入正确的PIN,模块才会开启协议栈。在以上任何情形下开机,模块都会上报(+VPUP),客户可以根据此上报来判断正常使用中的模块是否重启。
(2)关机:
由于关机需要在网络上进行一些登记操作,因此正常的关机步骤是建议+CPOF关闭协议栈后延迟一段时间断电。
(3)飞行模式:
模块实现飞行模式可以直接使用+CPOF关闭协议栈,+CPON打开协议栈返回正常模式。
查询当前是否在飞行模式:+VPON.
细节:
长短信的发送:
Cdma不能无缝的发送长短信,一般要等到 +CDS:上报才能发出下一条,一般情况下,发出一条短信过4-5秒后就有+CDS上报,不过,如果发给自己的话,这个时间会更长,我们采用延时30秒。一般如果发多条短信,第二条一般会返回+CDS:2,2,66 ,就是说,发不成功。我们要把它保存起来,重发一次。
结尾
当然,要做到符合最新电信需求规范,就比较困难了。MTK本是在GSM协议上做起来的,GSM于CDMA本来就存在很大的差别。说不定过不久MTK会发布C+G的版本,啥东西人家都帮你弄好了,就等着只改界面换个图片铃声吧。