⾼通与At指令:AtCop解析
背景
在某个新基线上移植AT指令,发现有问题,因此收集了这个系列的⽂章作为这⽅⾯的知识补充。
原⽂作者:,本⽂有删改。
AT指令在产线中是⼀类⽐较重要的问题,⼀天没来得及解决,则会拖延⽣产的有关进度。
前⾔
该篇主题主要介绍的是ATCommandProcessor。
ATCoP是什么?ATCommandProcessor,是⾼通AMSS(modem)software下的⼀套对AT命令的具体实现模块,也只有真正弄懂ATCoP,才能真正的了解AT命令有关软件的实现。
下⾯,我将就:
AtCoP具体功能
AtCoP实现架构
AtCoP处理流程
At命令解析(ATCommand Parser)
At命令表(ATCommand Table)
这四个⽅⾯来做具体介绍,学习完,便能结合具体的实例具体的去分析整个的AT命令实现,也只有在深⼊了解ATCoP的基础上,才能实现对ATCommand的修改和新增。
AtCoP具体功能
ATCoP,ATCommand processor,AT命令处理器。是对AT命令具体软件实现的模块,通过ATCoP,我们可以实现对AT命令的修改和新增。
这个部分是由modem侧(BP侧)实现的。
基本上它遵循以下过程:
串⼝(sio)接收到串⼝发送过来的字符串--> AT Command Parser --> 产⽣⼀个重要的Token结构,它包含了命令名称,接收到的参数,以及response的buffer--> 之后AT Command ProcessorProcess 通过Token⾥⾯的信息查调⽤相应的AT 命令处理函数 -->处理完成后产⽣相应的response给TE。
简单的来说,ATCoP接收串⼝(Serial Port)处传来的ATCommand,进⾏解析(Parse),根据解析的结果到ATCommand Tables中寻相应的表项,若匹配,则执⾏对应的处理函数,处理完以后response其对应的返回数据到串⼝。
⽬前,Qualcomm(⾼通)DMSS采⽤IS-707AT Command Set作为它的DataServices的命令集。
下⾯列举出与ATCoP相关的⼀些主要的资源⽬录:
filename Description
Dsat.h ATCoP外部模块使⽤的定义,函数和数据结构
Dsat.h ATCoP外部模块使⽤的定义,函数和数据结构
Dsati.h ATCoP内部使⽤的定义,函数和数据结构
Dsatprep.c接收⾃串⼝设备的数据的预处理
Dsatpar.c AT命令解析器,将命令⾏的AT命令解析到token结构中
Dsatcmdp.c AT命令处理器,查token结构中的包含的命令并从命令列表中调⽤相应的命令处理函数处
理命令
Dsatrsp.c产⽣AT命令响应和格式化
Dsatutil.c产⽣AT命令处理器
Dsatparm.c通⽤AT参数类型命令过程
Dsatarm.h ATCoP内部使⽤的通⽤AT参数类型命令处理定义,函数和数据结构
Dsatact.c通⽤ATactive type命令处理函数
Dsatact.h通⽤AT动作类型命令处理的定义、函数和数据结构,供ATCoP内部模块使⽤
Dsatvend.c通⽤AT指定提供商类型命令处理
Dsatvend.h通⽤AT指定提供商类型命令处理的定义、函数和数据结构,供ATCoP内部模块使⽤
Dsatctab.c通⽤AT命令表
filename Description
Dsatctab.h通⽤AT命令表定义、函数和数据结构,供ATCoP内部模块使⽤
Dsatcmif.c通⽤呼叫管理接⼝
Dsatcmif.h通⽤呼叫管理接⼝定义、函数和数据结构,供ATCoP内部模块使⽤
Dsatvoice.c通⽤语⾳呼叫处理控制
Dsatvoice.h通⽤语⾳呼叫处理控制的定义、函数和数据结构,供ATCoP内部模块使⽤
Dsatetsicall.c ETSI呼叫控制命令处理
Dsatetsicall.h ETSI呼叫控制命令处理的定义、函数和数据结构,供ATCoP内部模块使⽤字符串处理函数 如果是a展示b
Dsatetsicmif.c ETSI命令呼叫管理接⼝
Dsatetsicmif.h ETSI命令呼叫管理接⼝的定义、函数和数据结构,供ATCoP内部模块使⽤
Dsatetsipkt.c ETSI包数据命令处理
Dsatetsipkt.h ETSI包数据命令处理的定义、函数和数据结构,供ATCoP内部模块使⽤
Dsatetsime.c ETSI移动设备命令处理
Dsatetsime.h ETSI移动设备命令处理的定义、函数和数据结构,供ATCoP内部模块使⽤
Dsatetsismsc.c ETSI短消息服务命令处理
Dsatetsismsa.c ETSI短消息服务异步事件处理
Dsatetsismsu.c ETSI短消息服务命令处理实体
Dsatetsisms.h ETSI短消息服务命令处理的定义、函数和数据结构,供ATCoP内部模块使⽤
Dsatetsismsi.h ETSI短消息服务命令处理的定义、函数和数据结构,供ATCoP内部模块的短消息服务单元使⽤
Dsatetsictab.c ETSIAT命令表
Dsatetsictab.h ETSIAT命令表的定义、函数和数据结构,供ATCoP内部模块使⽤
Dsatetsitgt.c顶层AT命令表,命令表指针数组,ETSI指定⽬标的命令表,同步事件处理表。定义ETSI⽬标⽀持的AT命令集Dsatgsmfax.c GSMfax命令处理
Dsatgsmfax.h GSMfax命令处理的定义、函数和数据结构,供ATCoP内部模块使⽤
数据服务任务源⽂件列表:
filename Description
Dstask.h数据服务任务的外部或内部模块使⽤的定义,函数和数据结构
Dsatsk.c数据服务任务和顶层分发
对修改或者新增⼀个AT命令主要涉及到的⼀些⽂件:
The files of interest for adding new AT commands or modifying existing AT commands are:
dstask.c dstask.h dsat.h
dsati.h dsatutil.c dsatparm.c
dsatparm.h dsatact.c dsatact.h
dsatvend.c dsatvend.h dsatctab.c
dsatctab.h
ATCoP实现架构
⾸先我们来看⼀张图:
ATCoP的基本架构主要有⼀下⼏个部分:
SIOData Preprocessor(SIO数据预处理模块)
ATCommand Parser(AT命令解析器)
ATCommand Processor(AT命令处理器)
ATCommand Response Generator(AT命令响应产⽣器)
ATCommand Tables and Command Processing Functionality(AT命令表及命令处理功能模块)
1、通过串⼝设备(SIO)接收的AT命令数据,⾸先由SIO数据预处理,产⽣⼀个null-terminated命令⾏并由DS分发给AT命令解析器。
2、产⽣的null-terminated命令⾏由AT命令解析器解析,解析器为每个要解析的命令产⽣⼀个token结构,并送到处理队列由AT命令处理器处理。在AT命令处理器被调⽤前,解析器将每个命令的token结构放⼊队列中。
3、AT命令处理器完成对每个token结构进⾏表查,同时将该token结构从队列中移除。如果查到,对应的处理函数被调⽤处理该命令;AT命令在命令表中定义,每个命令表⼊⼝包含对应命令执⾏函数的指针。
4、AT命令响应产⽣器将命令响应数据格式化,产⽣结果编码,并将响应数据发送给DTE。
5、ATCOP每次处理⼀条AT命令⾏命令,如果任何命令⾏的命令产⽣⼀个错误,在错误前就会产⽣命令处理的响应,同时产⽣⼀个错误代
码,不再对该命令进⾏后续处理。
下⾯图同样展⽰的是ATCoP的实现框架,从USB接收到AT命令,到初始化创建SIO,再到命令的实际处理到返回,可详读下⾯这张图。ATCoP处理流程
其实在ATCoP的实现架构就已经简单介绍到了ATCoP对AT命令的处理流程,在这我们将对其进⾏更加具体的详解。
ATCoP处理控制流⼤致可以分有三个步:
Initial Parsing:初始化解析
CommandParsing:命令解析
Command Execution:命令执⾏处理(包括返回结果)
1、InitialParsing:函数dsat_process_sio_command去掉命令⾏中的"AT"前缀,然后把以NULL结尾的命令⾏传给函数
dsat_process_cmd_line来进⾏后续的分析和处理。dsatpar_parse_cmd_line函数完成对命令⾏的解析,检查每个AT命令的⾸字符然后根据AT命令的类型调⽤相应的解析函数。每个AT命令名(包括⾸符号,如,$QCDMG)以及相关的命令参数都被从命令⾏中解析出来,然后放到⼀个token data structure中。命令⾏中的每个命令都产⽣⼀个token structure,放到token排队上等待后续处理,此时⼀个命令⾏解析完成。⼀般添加或修改AT命令时不改动这部分代码。
2、CommandParsing:根据命令的不同⾸字符,不同的解析函数解析AT命令后,把解析的信息填充到上⼀步产⽣的token data structure 中,然后返回结果。如果结果是OK(意味着参数、参数个数以及特殊处理码special processing code等等都已经存好),此时token data structure已放在队列中等待AT命
令处理器(ATcommand processor)后续处理。命令⾏中的每个命令都在队列中放⼀个token structure。例如,extendedor proprietary AT 命令调⽤的分析函数是parse_extended_cmd。
3、每个命令产⽣的token structure被函数dsatcmdp_queue_token放⼊队列中。命令解析完成后,调⽤函数process_at_cmd_line处理队列中的每个token structure。从队列中取出并删除⼀个命令token structure后,在命令表中搜索该命令。顶层命令表(toplevel command table)在⽂件dsatetsitgt.c中。顶层命令表⼜指向⽂件dsatctab.c和dsatetsictab.c中的多个命令表,这些表定义了所⽀持的AT命令集。
如果在表中查到该命令,调⽤表中对应的处理函数执⾏该命令。命令执⾏后如果有返回数据时,返回的响应数据在函数
dsat_fmt_response中格式化。每个token结构都进⾏这样的处理。最后调⽤函数dsatrsp_send_response把命令响应送到DTE。
注:对于异步AT命令处理流程与正常AT命令略有不同,在命令预处理、命令解析过程都是⼀样的,在命令处理过程中
(process_at_cmd_line),如果命令处理函数返回DSAT_OK,说明命令处理完成调⽤dsat_fmt_response函数格式化响应数据并发送,正常的命令处理流程;如果命令处理函数返回DSAT_A
SYNC_CMD说明当前命令是异步命令,此时函数process_at_cmd_line 设置变量dsatcmdp_processing_async_cmd= TRUE,表⽰当前正在处理异步命令,然后返回,不再进⾏后续处理,直到该命令处理完成,函数返回DSAT_OK(未必⼀定是DSAT_OK,当返回不是DSAT_ASYNC_CMD和DSAT_ASYNC_EVENT时,说明异步命令/事件处理完成)。当DS收到异步事件经任务分发器,再次调⽤dsat_process_async_cmd函数,在该函数中通过查异步事件表async_event_table,调⽤相应的事件处理函数继续处理,如果事件处理函数返回值不是DSAT_ASYNC_CMD或DSAT_ASYNC_EVENT,说明异步事件处理完成,调⽤process_at_cmd_line继续处理命令⾏的命令。
下⾯我们可以通过⼀个流程图更加直观的了解ATCoP的处理流程:
基本遵循过程:
SIOData Preprocessor接收串⼝发送过来的字符串(这⾥是AT Command),并向DS TASK发送信号要求其处理;DS TASK 知晓并获得控制权后,由AT Command Parser解析AT Command,将得到的结果存⼊相应的token结构中(包含了命令名称,接收到的参数,以及response 的buffer);AT Command Processor到AT Command Tables匹配相应的表项;AT Command Response Generator根据匹配的结果调⽤对应的Command Processing Function进⾏处理;处理完成后产⽣相应的response给 TE。
AT命令解析(ATCommand Parser)
ATCommand Parser对命令⾏进⾏解析时,将解析的结果存到token中,并在下⼀步到Parse Table中进⾏匹配。
下⾯就以代码流程具体展⽰:
DS_AUTODETECT_SRVC_MODE模式下,串⼝检测到A字符,则发送DS_1ST_SIO_RX_SIG给DSTASK
DSTASK调⽤dsi_mgr()进⾏分发处理
ds_process_rxbuf_event()
switch(dsi_callstate){
caseDS_IDLE_CSTATE:
ds_atcop_process_sio_command();
}
/*从watermark中取出data尝试建⽴⼀个命令⾏*/
while(cc!=NULL)
{
cc = cce & 0x7F //只使⽤⾼7位
switch (at_state)
{
case HUNT:
if (UPCASE (cc) == 'A')
// 转到FOUND_A状态
break;
case FOUND_A:
if (UPCASE (cc) == '/')
//从buf取出上个AT命令来执⾏(ds_atcop()),执⾏完毕后转到HUNT状态
else if (UPCASE (cc) == 'T')
//转到CAT状态
else if (UPCASE (cc) != 'A')
//转到HUNT状态
break;
case CAT:
if (cc != ds_atcop_s3_val) // if not EOL
{
if (cc != ds_atcop_s5_val) // if not backspace
{
if OVERFLOW
//转到ERROR状态
else if (cc >= 0x20 && cc <= 0x7E)
//fill buffer;
} // if backspace
else
// remove the most immediate character from the buffer
}
else
if EOL
/
/对命令⾏进⾏处理(ds_atcop()),处理完毕后转到HUNT状态
break;
case ERROR:
//执⾏相应出错处理,处理完毕后转到HUNT状态
break;
}
}
//ds_atcop() 对命令⾏进⾏处理
switch (UPCASE (*curr_char_ptr)){
case '+': /* Extended format specified in IS-99 */
case '$': /* Extended format proprietary command */
/
/对命令⾏进⾏解析
curr_char_ptr = ds_atcop_parse_ex (curr_char_ptr, &tok);
if SUCCEED
//根据解析的结果到parse table匹配,进⾏相应处理
ds_atcop_exec_param_cmd ();
//若匹配不到,则强制解析
if (ds_atcop_result == DS_ATCOP_DO_HARD_PARSE)
ds_atcop_hard_to_parse();
break;
}
//If not originating or answering a call
ds_atcop_fmt_response(); //generate a final result code
if (ds_atcop_result == DS_ATCOP_CXT_ORIG){
ds_atcop_discard_results();
}
else if (mode == DS_ATCOP_CMD){
ds_atcop_send_results();//发送
}
其中涉及到的Token Struct数据结构:
typedef struct
{
byte working_at_line[MAX_LINE_SIZE]; // Stores command lines to be processed、Each line
/
/ is referenced by a line number
byte *name; // The name of the AT command
unsigned int op; // Syntax flags、Can be one of four valid values (NA,
// EQ, QU, AR) or an invalid value
byte * arg[MAX_ARG]; // AT command arguments
unsigned int args_found; // Keeps track of the number of AT command
//arguments found
} tokens_struct_type;
AT命令表(ATCommand Table)
AT命令的处理是由命令表驱动的,ATCOP实现的命令表是⼀个分级的表结构,主要分为:主表(master table)
⼦表(sub table)
命令表(command table)。
其中主表是⼀个⼆维的数组,数组的⾏表⽰AT命令的分类,分为:
基本AT命令(basic_table)
寄存器AT命令(sreg_table)
扩展AT命令(extended_table)
⼚商AT命令(vendor_table)
四⼤类;数组的列表⽰是ETSI模式还是其它模式的AT命令。
基本命令表
基本命令的格式为:[]
其中或者是单个字母(A-Z),或者是“&”字符接单个字母。
是⼀个⼗进制数,可以是⼀位,也可以是多位。最前⾯的0会被忽略。默认为0。如果⼀个不带的基本命令带了,则返回TOO MANYPARAMETERS。
寄存器命令表
所有以字母“S”开头的命令统称为S寄存器命令,格式如下:
S? S=
S 寄存器命令名由字母“S”接上⼀个⼗进制数构成,这个⼗进制数称为寄存器序号(parameternumber)。如果寄存器序号不被识别,说明不存在该命令,返回COMMANDNOT SUPPORT。
每个 S寄存器保存⼀个字符。命令名后⾯如果接“?”表⽰是READ命令,返回此S寄存器当前保存的字符的ASCII 码值,以3 位⼗进制数表⽰,位数不⾜的前⾯补0;如果接“=”表⽰是SET命令,将值对应的字符替换此S寄存器保存的字符。
扩展命令和⼚商命令表
扩展命令均由“+”开头,⼚商定义的命令也是由⼀个特殊符号开头,例如“$”,“%”等。本⽂中所实现的命令均为扩展命令。
所有的扩展命令和⼚商定义命令⼜可以分为两类:Actioncommand和Parameter command。
actioncommand
action command 指完成某个具体的动作,⽽不仅仅是与MS 本地的参数打交道的命令,例如AT+CMGS 等。actioncommand 可以带参数也可以不带。
Actioncommand 包含EXECUTION 命令和TEST 命令。
(1)EXECUTION命令
EXECUTION 命令格式如下:
不带参数
带 1个参数:[=]
带多个参数:[=],中间以“,”分隔表⽰多个参数。
对于有默认值的参数,可以在命令中省略,此时以默认值代替。
如果所有的参数都省略,则后⾯的“=”也⼀并略去。如果不被识别,则表⽰此命令不存在,返回COMMAND NOTSUPPORT。可识别的前提下,如果不能带参数的命令带了参数,或者参数个数超出
定义,则返回TOOMANY PARAMETERS。
(2)TEST命令
TEST 命令格式:=?
如果 MS不能识别,返回COMMAND NOT SUPPORT。如果MS可以识别,且命令是不带参数的,则返回OK。如果命令带参数,则先返回各个参数的可取值范围,最后再加上OK。
parametercommand
parameter command包括与MS本地的参数打交道的命令,这些参数有些会影响到atcioncommand的执⾏。
parametercommand⼜分为SET命令、READ命令和TEST命令。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论