At Command:从初级到大师的修炼历程(三)

AT Command流程分析之AtCop解析

 

 

   

        这篇博客是起步于At Commands学习系列的第三部分。

        该系列的学习文章主要分有以下几个部分,

            (一):基础知识及相关的一些概念介绍

            (二):At Commands的测试指导教程

            (三):AT Command流程分析之AtCop解析

            (四):AT Command流程分析之ATFWD解析

            (五):AT Command流程分析之具体实现

        该篇主题主要介绍的是ATCommandProcessor,那么,什么是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命令的修改和新增。

简单的来说,ATCoP接收串口(SerialPort)处传来的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命令表

Dsatctab.h

通用AT命令表定义、函数和数据结构,供ATCoP内部模块使用

Dsatcmif.c

通用呼叫管理接口

Dsatcmif.h

通用呼叫管理接口定义、函数和数据结构,供ATCoP内部模块使用

Dsatvoice.c

通用语音呼叫处理控制

Dsatvoice.h

通用语音呼叫处理控制的定义、函数和数据结构,供ATCoP内部模块使用

Dsatetsicall.c

ETSI呼叫控制命令处理

Dsatetsicall.h

ETSI呼叫控制命令处理的定义、函数和数据结构,供ATCoP内部模块使用

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命令主要涉及到的一些文件:

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)以及相关的命令参数都被从命令行中解析出来,然后放到一个tokendatastructure中。命令行中的每个命令都产生一个tokenstructure,放到token排队上等待后续处理,此时一个命令行解析完成。一般添加或修改AT命令时不改动这部分代码。

  2. CommandParsing:根据命令的不同首字符,不同的解析函数解析AT命令后,把解析的信息填充到上一步产生的tokendatastructure中,然后返回结果。如果结果是OK(意味着参数、参数个数以及特殊处理码specialprocessingcode等等都已经存好),此时tokendata structure已放在队列中等待AT命令处理器(ATcommand processor)后续处理。命令行中的每个命令都在队列中放一个tokenstructure。例如,extendedor proprietary AT 命令调用的分析函数是parse_extended_cmd。

  3. 每个命令产生的tokenstructure被函数dsatcmdp_queue_token放入队列中。命令解析完成后,调用函数process_at_cmd_line处理队列中的每个tokenstructure。从队列中取出并删除一个命令tokenstructure后,在命令表中搜索该命令。顶层命令表(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_ASYNC_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()
 

<span style="font-size:14px;">
switch(dsi_callstate){
             caseDS_IDLE_CSTATE:
             ds_atcop_process_sio_command();
         }</span>

<span style="font-size:14px;">
/*从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();//发送
}</span>

    其中涉及到的Token Struct数据结构:

<span style="font-size:14px;">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;</span>
 

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命令。

·AT命令表分类具体介绍:

1.基本命令表

基本命令的格式为:<command>[<number>]

其中<command>或者是单个字母(A-Z),或者是“&”字符接单个字母。

<number>是一个十进制数,可以是一位,也可以是多位。<number>最前面的0会被忽略。默认<number>为0。如果一个不带<number>的基本命令带了<number>,则返回TOO MANYPARAMETERS。

2.寄存器命令表

所有以字母“S”开头的命令统称为S寄存器命令,格式如下:

S<parameter number>? S<parameternumber>=<value>

S 寄存器命令名由字母“S”接上一个十进制数构成,这个十进制数称为寄存器序号(parameternumber)。如果寄存器序号不被识别,说明不存在该命令,返回COMMANDNOT SUPPORT。

每个 S寄存器保存一个字符。命令名后面如果接“?”表示是READ命令,返回此S寄存器当前保存的字符的ASCII 码值,以3 位十进制数表示,位数不足的前面补0;如果接“=”表示是SET命令,将<value>值对应的字符替换此S寄存器保存的字符。

3.扩展命令表和厂商提供的命令表

扩展命令均由“+”开头,厂商定义的命令也是由一个特殊符号开头,例如“$”,“%”等。本文中所实现的命令均为扩展命令。所有的扩展命令和厂商定义命令又可以分为两类:Actioncommand和Parameter command。

1)actioncommand

action command 指完成某个具体的动作,而不仅仅是与MS 本地的参数打交道的命令,例如AT+CMGS 等。actioncommand 可以带参数也可以不带。Actioncommand 包含EXECUTION 命令和TEST 命令。

(1)EXECUTION命令

EXECUTION 命令格式如下:

不带参数:<name>

带 1个参数:<name>[=<value>]

带多个参数:<name>[=<compound_value>]

<compound_value>表示多个参数,中间以“,”分隔。对于有默认值的参数,可以在命令中省略,此时以默认值代替。

如果所有的参数都省略,则<name>后面的“=”也一并略去。如果<name>不被识别,则表示此命令不存在,返回COMMAND NOTSUPPORT。<name>可识别的前提下,如果不能带参数的命令带了参数,或者参数个数超出定义,则返回TOOMANY PARAMETERS。

(2)TEST命令

TEST 命令格式:<name>=?

如果 MS不能识别<name>,返回COMMAND NOT SUPPORT。如果MS可以识别<name>,且命令是不带参数的,则返回OK。如果命令带参数,则先返回各个参数的可取值范围,最后再加上OK。

2)parametercommand

parameter command包括与MS本地的参数打交道的命令,这些参数有些会影响到atcioncommand的执行。parametercommand又分为SET命令、READ命令和TEST命令。

(1)SET命令

命令格式为:带1个参数:<name>[=<value>]

带多个参数:<name>[=<compound_value>]

SET命令用于设置参数。<compound_value>表示多个参数,中间以“,”分隔。对于有默认值的参数,可以在命令中省略,此时以默认值代替。如果所有的参数都省略,则<name>后面的“=”也一并略去。如果<name>不被识别,则表示此命令不存在,返回COMMAND NOTSUPPORT。<name>可识别的前提下,如果不能带参数的命令 带了 参数 ,或者 参数 个数 超出 定义, 则返回TOO MANYPARAMETERS。

(2)READ命令

命令格式:<name>?

READ 命令用于读取参数当前值。

(3)TEST命令

命令格式:<name>=?

如果 MS不能识别<name>,返回COMMAND NOTSUPPORT。如果MS可以识别<name>,且命令是不带参数的,则返回OK。如果命令带参数,则先返回各个参数的可取值范围,最后再加上OK。

·命令表项(主表定义dsati.h)

<span style="font-size:14px;">typedef struct dsati_cmd_struct
{
byte name[20];           // AT cmd 的名字,包含"+", "$" 等
uint32 attrib;             // AT cmd 的属性
byte special;             // AT cmd 的 special processing code
byte compound;          // 传递的参数个数(若参数为字符串,则是它的最大长度)
const void *val_ptr;       // 指向参数的指针
const void *def_lim_ptr;   // 定义了参数的默认值以及取值范围
dsat_result_enum_type (*proc_func)( dsat_mode_enum_type,
const struct dsati_cmd_struct*,
const tokens_struct_type*,
dsm_item_type* );
boolean (*abort_func)( const struct dsati_cmd_struct* );
} dsati_cmd_type;</span>

针对不同的软件版本可能对应的dsati_cmd_type定义略有差别。

详解:

1.name

AT命令名,包括需要处理的+,$,&和终止的NULL。如+IPR,$QCDMG,

S6,&C,Z。

2.attitude

32位的掩码,用来指定单个或多个命令属性。表4.1列出了AT命令的所有属性,后面给出了具有该属性的命令。

3.special

如果有需要,就指定处理编码,否则就是SPECIAL_NONE,指定处理编码定义在dsati.h。只是用在与外部软件的兼容性时。

表1 AT命令属性列表

4.compound

2)dsati_cmd_struct*是dsati_cmd_struct结构入口指针,对于包含这个命令表入口指定命令。

3)token_struct_type*是一个定义好的tokenstructure解析器指针,这个token结构包含处理该命令所要求的信息。

4)dsm_item_type*是DSMbuffer的指针,存储命令响应。如果命令响应超出了一个DSMbuffer的容量,可以将多个DSMbuffer可以链接到一起。函数返回类型

应该是表 .3列出值中的一个。

表4.3函数返回类型表

8.abortfunction ptr

函数指针通过命令表入口调用定义的abort命令,函数指针值不是NULL表示命令表入口定义的命令是可以abort的。函数指针参数是:dsati_cmd_struct*是dsati_cmd_struct结构入口指针,用于指示包含该命令表入口的指定命令。函数返回类型是一个Boolen表示:如果值是TRUE,表示数据调用可以通过DsmgrAbort,否则不需要任何动作。

9.dflm_type

定义AT命令中数字参数的最大值和最小值参数,这里的数字参数一定是连续的取值类型。如果参数取值为{0,1,255}这种参数应该设置为list类型。Default_v为默认值,lower和upper为最小和最大取值。

10.def_list_type

用于定义LIST类型的参数取值范围,其中:

Default_v代表参数的默认值,它是指向list_v数组的指针。

List_v是一个8-byte字符串的数组指针,代表该参数允许的所有值,数组的最后一项必须是NULL来终止参数列表。AT命令处理器完成该数组的字符串匹配,以决定参数值是否在有效的范围内。

List_t是一个字符串指针,逐字返回测试命令的响应。

AT命令如果含有多个参数,每个参数都关联于def_list_type结构。

11.mixed_def_s_type和dsat_mixed_param_val_type

Mixed_def_s_type用于存储AT命令中混合参数的默认值和可能值,混合参数类型表示AT命令的参数可以是不同类型的,其允许值范围也是个集合,如果是数值类型需要指定在某一范围内,如果是字符串类型则限定长度。如果命令有N个不同类型参数,默认的可能值范围包含一个长度为N的mixed_def_s_type数组,类型参数i是数组下标,如mixed_argus[]定义为mixed_argus[i].attrib。如果AT命令有N种不同类型参数,参数的当前值包含在长度为N的dsat_mixed_param_val_type数组中。该数组用于联系mixed_def_s_type数组Dsat_mixed_param_val_type数组下标为i的元素,在mixed_def_s_type数组对应i分量为该AT命令的默认和可能的范围值。

其实,针对于ATCoP的学习是比较混乱的,因为本身的内容就比较混杂,如果不是对整个架构比较清楚的话,很难学得清楚,并且就后面所要展开的AT Commands的自定义实现是在这一章的基础上实现的。在这我主要也是就ATCoP的标准协议文档进行翻译理解,并结合网上和个人的一些总结进行整理,希望有帮助。

就这一块的理解问题应该是挺多的,欢迎大家提出来一些探讨探讨!

接下来的学习:AT Command流程分析之ATFWD解析

 

 
  • 3
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值