QCT6085AT命令模块设计与实现(XXXX0331).docx
1AT命令模块框架设计11.1ATCOP 功能划分11.2AT 命令处理流程详解31.3AT 命令表结构71.4命令表项解释111.5增加一条 AT 命令151.5.1基本流程151.5.2增加一条同步AT命令范例181.5.3增加一条异步AT命令范例201.5.4主动上报的AT事件如何实现实现方法272高通AT命令模块主要文件功能333AT 命令 的流程343.1同步 AT 命令 的流程343.2异步 AT 命令 的流程343.3主动上报 AT 命令 的流程34 QCT6085 AT命令模块设计与实现1 AT命令模块框架设计本节对 AT 命令模块的总体设计与实现进行了详细描述,并对 AT 命令表结构内容做了说明,最后解释了如何添加一条 AT 命令。1.1 ATCOP 功能划分高通的 AT 模块,也就是 AT 命令处理器(ATCOP)完成了多种 AT 命令的解析、处理以及产生和发送命令响应消息,同时也处理在 AT 命令执行过程中的各种AT 相关的事件。在高通的软件平台中,ATCOP 作为数据服务模块(DS data services)的一个子任务来实现。在 ds_task 中完成对 dsat_task 的初始化和调用功能,所有的AT 命令通过 TE 和 TA 之间的串行接口发送。收到的 AT 命令缓存在 DS 的消息队列 dsi_cmd_q 中,并由 ds 的消息分发机制统一分发给各个子任务。ATCOP 的处理流程包括 SIO 数据预处理模块、AT 命令解析器、AT 命令处理器、AT 命令响应产生器、AT 命令表及命令处理功能模块。1通过串口设备(SIO)接收的AT命令数据,首先由SIO数据预处理,产生一个null-terminated命令行并由DS分发给AT命令解析器。2产生的null-terminated命令行由AT命令解析器解析,解析器为每个要解析的命令产生一个token结构,并送到处理队列由AT命令处理器处理。在AT命令处理器被调用前,解析器将每个命令的token结构放入队列中。3AT命令处理器完成对每个token结构进行表查找,同时将该token结构从队列中移除。如果查找到,对应的处理函数被调用处理该命令;AT命令在命令表中定义,每个命令表入口包含对应命令执行函数的指针。4AT命令响应产生器将命令响应数据格式化,产生结果编码,并将响应数据发送给DTE。5ATCOP每次处理一条AT命令行命令,如果任何命令行的命令产生一个错误,在错误前就会产生命令处理的响应,同时产生一个错误代码,不再对该命令进行后续处理。1.2 AT 命令处理流程详解 图 1 AT 命令处理流程图详细描述了 AT 命令模块在处理各类 AT 命令的具体具体流程。1 DS_Task的建立,SIO 唤醒 rx收到数据,将sio唤醒2初始化解析函数dsat_process_sio_command去掉命令行中的"AT"前缀,然后把以NULL结尾的命令行传给函数dsat_process_cmd_line来进行后续的分析和处理。dsatpar_parse_cmd_line函数完成对命令行的解析,检查每个AT命令的首字符然后根据AT命令的类型调用相应的解析函数。每个AT命令名(包括首符号,如,$QCDMG) 以及相关的命令参数都被从命令行中解析出来,然后放到一个tokendata structure中。命令行中的每个命令都产生一个token structure,放到token排队上等待后续处理,此时一个命令行解析完成。一般添加或修改AT命令时不改动这部分代码。3命令解析根据命令的不同首字符,不同的解析函数解析AT命令后,把解析的信息填充到上一步产生的tokendata structure中,然后返回结果。如果结果是OK (意味着参数、参数个数以及特殊处理码specialprocessing code等等都已经存好),此时token data structure已放在队列中等待AT命令处理器(AT command processor)后续处理。命令行中的每个命令都在队列中放一个tokenstructure。例如,extended or proprietary AT 命令调用的分析函数是 parse_extended_cmd。4命令执行每个命令产生的tokenstructure被函数dsatcmdp_queue_token放入队列中。命令解析完成后,调用函数 process_at_cmd_line处理队列中的每个tokenstructure。从队列中取出并删除一个命令tokenstructure后,在命令表中搜索该命令。顶层命令表(top level 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 继续处理命令行的命令。1.3 AT 命令表结构AT 命令的处理是由命令表驱动的,ATCOP 实现的命令表是一个分级的表结构,主要分为:主表(master table)、子表(sub table)、命令表(command table),如图 4.2 所示。其中主表是一个二维的数组,数组的行表示 AT 命令的分类,分为:基本 AT命令(basic_table)、寄存器 AT 命令(sreg_table)、扩展 AT 命令(extended_table)、厂商 AT 命令(vendor_table)四大类;数组的列表示是 ETSI 模式还是其它模式的AT 命令。图 2 AT 命令表结构图主表定义在 dsati.h文件中:typedef struct dsati_cmd_structbyte name20;uint32 attrib;byte special;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;typedef structconst dsati_cmd_type *table_ptr;const unsigned int *table_size; dsati_at_cmd_table_entry_type;typedef dsati_at_cmd_table_entry_type*dsati_at_cmd_table_typeNUM_AT_CMD_CATEGORIESNUM_OPER_CMD_MODES;分类表定义在文件 dsatetsitgt.c 中:const dsati_at_cmd_table_type at_cmd_table = basic_table_entries, NULL , sreg_table_entries, NULL , extended_table_entries, NULL , vendor_table_entries, NULL ;1基本命令表基本命令的格式为:<command><number>其中<command>或者是单个字母(A-Z),或者是“&”字符接单个字母。<number>是一个十进制数,可以是一位,也可以是多位。<number>最前面的 0 会被忽略。默认<number>为 0。如果一个不带<number>的基本命令带了<number>,则返回 TOO MANYPARAMETERS。2寄存器命令表所有以字母“S”开头的命令统称为 S 寄存器命令,格式如下:S<parameter number>? S<parameter number>=<value>S 寄存器命令名由字母“S”接上一个十进制数构成,这个十进制数称为寄存器序号(parameter number)。如果寄存器序号不被识别,说明不存在该命令,返回COMMAND NOT SUPPORT。每个 S 寄存器保存一个字符。命令名后面如果接“?”表示是 READ 命令,返回此 S 寄存器当前保存的字符的 ASCII 码值,以 3 位十进制数表示,位数不足的前面补 0;如果接“=”表示是 SET 命令,将<value>值对应的字符替换此 S 寄存器保存的字符。3扩展命令表和厂商提供的命令表扩展命令均由“+”开头,厂商定义的命令也是由一个特殊符号开头,例如“$”,“%”等。本文中所实现的命令均为扩展命令。所有的扩展命令和厂商定义命令又可以分为两类:Actioncommand 和 Parameter command。1)action commandaction command 指完成某个具体的动作,而不仅仅是与 MS 本地的参数打交道的命令,例如 AT+CMGS 等。action command 可以带参数也可以不带。Action command 包含 EXECUTION 命令和 TEST 命令。(1)EXECUTION 命令EXECUTION 命令格式如下:不带参数:<name>带 1 个参数:<name>=<value>带多个参数:<name>=<compound_value><compound_value>表示多个参数,中间以“,”分隔。对于有默认值的参数,可以在命令中省略,此时以默认值代替。如果所有的参数都省略,则<name>后面的“=”也一并略去。如果<name>不被识别,则表示此命令不存在,返回 COMMAND NOT SUPPORT。<name>可识别的前提下,如果不能带参数的命令带了参数,或者参数个数超出定义,则返回 TOOMANY PARAMETERS。(2)TEST 命令TEST 命令格式:<name>=?如果 MS 不能识别<name>,返回 COMMAND NOT SUPPORT。如果 MS 可以识别<name>,且命令是不带参数的,则返回 OK。如果命令带参数,则先返回各个参数的可取值范围,最后再加上 OK。2)parameter commandparameter command 包括与 MS 本地的参数打交道的命令,这些参数有些会影响到 atcioncommand 的执行。parameter command 又分为 SET 命令、READ 命令和TEST 命令。(1)SET 命令命令格式为:带 1 个参数:<name>=<value>带多个参数:<name>=<compound_value>SET 命令用于设置参数。<compound_value>表示多个参数,中间以“,”分隔。对于有默认值的参数,可以在命令中省略,此时以默认值代替。如果所有的参数都省略,则<name>后面的“=”也一并略去。如果<name>不被识别,则表示此命令不存在,返回 COMMAND NOT SUPPORT。<name>可识别的前提下,如果不能带参数的 命令 带了 参数 ,或者 参数 个数 超出 定义, 则返 回 TOO MANY PARAMETERS。(2)READ 命令命令格式:<name>?READ 命令用于读取参数当前值。(3)TEST 命令命令格式:<name>=?如果 MS 不能识别<name>,返回 COMMAND NOT SUPPORT。如果 MS 可以识别<name>,且命令是不带参数的,则返回 OK。如果命令带参数,则先返回各个参数的可取值范围,最后再加上 OK。1.4 命令表项解释 下面依次介绍各个表项的含义:1nameAT命令名,包括需要处理的+,$,&和终止的NULL。如+IPR,$QCDMG,S6,&C,Z。2attitude32位的掩码,用来指定单个或多个命令属性。表4.1列出了AT命令的所有属性,后面给出了具有该属性的命令。3special如果有需要,就指定处理编码,否则就是SPECIAL_NONE,指定处理编码定义在dsati.h。只是用在与外部软件的兼容性时。表1 AT命令属性列表4compound数字命令的参数个数或是字符串命令的最大长度(不包括NULL)。例如:S0,带有一个数字参数,compound=1;对于一个命令的字符串参数定义大小为30,compound=29。5value_ptr指针变量,存储参数值。如果变量是一个数组(具有多个参数的命令),该指针指向数组的第一个元素。具有LIST属性的命令,存储在*val_ptr中的值不是真正的参数值,而是数组list_v指向的地址。对于带有MIXED_PARAM属性的命令,指针指向dsat_mixed_param_val_type,这是一个字符串或是数字值的联合体union类型。数组的成员是字符串还是数值依赖于对应数组成员的属性def_lim_ptr。该指针指向的变量可以是下面的类型之一:1)dsat_num_item_type带有数字参数或是LIST属性的命令;2)dsat_string_item_type带有字符串参数的命令;3)dsat_mixed_param_val_type带有混合类型参数的命令,参数可以是规定值的字符串,某一范围的数字,或是限定长度的字符串;4)NULL表示命令没有参数。6default limit ptr定义默认值和允许范围的参数该指针的变量可以是下面类型中的一个:1)dflm_type带有CONFIG属性的命令;2)def_list_type带有LIST属性的命令;3)mixed_def_s_type带有MIXED_PARAM属性的参数;4)NULL带有STRING属性的命令或是没有参数的命令。7process function ptr函数指针被调用用于执行在命令表入口定义的命令。函数指针参数是:1)dsat_mode_enum_type定义当前AT命令模式,表4.2列出模式和对应的含义。表 2 AT命令模式表2)dsati_cmd_struct*是dsati_cmd_struct结构入口指针,对于包含这个命令表入口指定命令。3)token_struct_type*是一个定义好的token structure解析器指针,这个token结构包含处理该命令所要求的信息。4)dsm_item_type*是DSM buffer的指针,存储命令响应。如果命令响应超出了一个DSM buffer的容量,可以将多个DSM buffer可以链接到一起。函数返回类型应该是表 .3 列出值中的一个。表4.3 函数返回类型表8abort function ptr函数指针通过命令表入口调用定义的abort命令,函数指针值不是NULL表示命令表入口定义的命令是可以abort的。函数指针参数是:dsati_cmd_struct*是dsati_cmd_struct结构入口指针,用于指示包含该命令表入口的指定命令。函数返回类型是一个Boolen表示:如果值是TRUE,表示数据调用可以通过Dsmgr Abort,否则不需要任何动作。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_typeMixed_def_s_type用于存储AT命令中混合参数的默认值和可能值,混合参数类型表示AT命令的参数可以是不同类型的,其允许值范围也是个集合,如果是数值类型需要指定在某一范围内,如果是字符串类型则限定长度。如果命令有N个不同类型参数,默认的可能值范围包含一个长度为N的mixed_def_s_type数组,类型参数i是数组下标,如mixed_argus定义为mixed_argusi.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命令的默认和可能的范围值。1.5 增加一条 AT 命令1.5.1 基本流程AT命令处理器方便扩展以支持新的AT命令,图4.3所示的是添加一条新的AT命令的具体流程。1. Select a unique name for the command. The command name can be up to 10 characters in length, including the leading +, $, or &.首先选择一个唯一的命令名称,命令名长度最大10个字符,包括开始的+,$,&。本文中所用AT命令均为扩展命令,所以用的都是+。2. Determine the command attributes. The various command attributes and their meanings are Are 14 listed in Table 4-3决定命令属性不同命令属性和含义在表1 AT命令属性列表中列出。3. Create a variable to store the argument value(s). If the command has one or more arguments, declare a variable of the appropriate type in dsatctab.c or dsatetsictab.c to store the argument values. Command tables must be exported internal to the ATCoP unit in dsatctab.h or dsatetsictab.h. If the argument values are referenced by modules external to ATCoP, declare ,this variable as an extern in dsat.h.产生一个变量存储参数值,如果命令包含一个或多个参数,在dsatctab.c中定义一个对应类型的变量来存储参数值,命令表应该定义在dsatctab.c或dsatctab.h中。如果参数值用于ATCOP模块外部,将该变量声明在dsat.h中。4. Define the default value and the allowed range for the command arguments. For commands with simple numeric arguments, use the dflm_type. Initialize the default value and the lowerand upper bounds. For commands of type LIST, use the def_list_type. Create the list_v and list_t data structures, and initialize the default value. For commands of type mixed parameter, create and initialize the appropriate dflm_type and def_list_type for each parameter of thistype. For string arguments, this is not applicable. All of these variables should be declared in dsatctab.c or dsatetsictab.c. For AT commands whose defaults and/or limits need to be initialized at run-time, this initialization may be performed in the function dsatctab_data_init.定义命令参数的默认值和允许范围对于简单数字型参数的命令,使用dflm_type,初始化默认值和最小最大界限。对于LIST类型命令,使用def_list_type,产生list_v和list_t数据结构,并初始化默认值。对于混合参数类型命令,为每个类型参数产生并初始化相应dflm_type和def_list_type,对于string参数类型,不需要这些。所有这些变量应该声明在dsatctab.c或是dsatctab.h中,对应AT命令默认的限制需要在run-time初始化,初始化功能由dsatctab_data_init实现。 5. Add the Command Execution function, if any. If the command requires special processing code outside the generic parameter processing functions defined in dsatparm.c, add a new Command Execution function to the appropriate command-processing file (dsatparm.c,dsatact.c, dsatvend.c, dsatetsicall.c, dsatetsipkt.c, dsatetsime.c, dsatetsismsc.c, dsatgsmfax.c).Take advantage of any AT command processing utilities exported by dsati.h or parameter processing exported by dsatparm.h. 添加命令执行函数(如果需要)如果命令需要指定额外处理函数,而不是在dsatparm.c中定义的通用函数,添加一个新的命令执行函数到对应的命令处理文件(dsatparm.c dsatact.c dsatvend.c dsatetsicall.c, dsatetsipkt.c, dsatetsime.c, dsatetsismsc.c)。可以使用任何AT命令处理单元在dsati.h中或是dsatparm.h中exported的。还有可能修改命令解析部分的代码,在文件dsatpar.c中,比如增加的以开始的命令,需要增加相应的解析代码。6Add the Abort Command function, if any. If the command is abortable, an Abort Command function must be defined in the appropriate command processing file. The command processing files are the same as those identified in step 5.添加abort命令函数(如果需要)如果命令是可终止的,一个终止命令函数定义在对应命令处理文件中。7. Add the command to the appropriate command table. First, determine which command table the AT command belongs to, based on the command syntax and command type. Then, add the dsati_cmd_type entry to the selected command table. Initialize the dsati_cmd_type command table entry. Initialize the dsati_cmd_type command table entry to point to this newCommand Execution function. If no new special processing code is required, initialize the command table entry to point to the appropriate Parameter Processing function or NULL,depending on the command response desired. Initialize the Abort Command function pointerto NULL if the command is not abortable, otherwise initialize it to point to the AbortCommand function 添加 命令表单 首先,决定命令属于 AT 命令表中那个表,基于命令的语法和命令类型。然后添加 dsati_cmd_type 入口到选定的命令表。初始化 dsati_cmd_type 命令表入口,初始化 dsati_cmd_type 命令表入口指向这个新的命令执行函数。如果不需要指定新的处理代码,初始化命令表入口指向相应处理函数或是 NULL,依赖于命令响应要求。如果命令不能 abort,初始化 abort 函数指针到 NULL,否则将其初始化到 abort 命令函数。图 3 添加一条AT命令的流程图1.5.2 增加一条同步AT命令范例Suppose that you want to add a new AT command, AT$MYCMD, which has two numericThe first argument takes values from 0 to 7, with a default value of 0, and the secondargument takes values from 0 to 3, with a default value of 2. The command is not abortable 1. Name (首先选择一个唯一的命令名称) The command name is $MYCMD.2. Attributes (决定命令属性)This command has the following attributes: CONFIG The command has two argumentsEXTENDED The command uses extended syntax (begins with $) 3. Argument storage(产生一个变量存储参数值)In dsatctab.c:dsat_num_item_type dsat_mycmd_val2;For reference external to ATCoP, in dsat.h, otherwise in dsatctab.h:extern dsat_num_item_type dsat_mycmd_val;4. Defaults and limits In dsatctab.c:LOCAL const dflm_type dsat_mycmd_dflm = 0, 0, 7 , /* argument 1: default = 0, range = 0 7 */ 2, 0, 3 /* argument 2: default = 2, range = 0 3 */ ;5. Special processing(添加命令执行函数)Suppose that a special function, mycmd_action(), must be invoked each time AT$MYCMD is issued, after the parameter values have been stored. Accordingly, a Command Execution function must be defined in dsatvend.c. This function must call the appropriate Parameter Processing function exported by dsatparm.h and call mycmd_action(), then return theappropriate result code. An example of this command execution function is:dsat_result_enum_type dsatvend_exec_mycmd_cmd(dsat_mode_enum_type mode, /* AT command mode */const dsati_cmd_type *cmd_table, /* Ptr to cmd in command table */const tokens_struct_type *tok_ptr, /* Command tokens from parser */dsm_item_type *res_buff_ptr /* Place to put response */)dsat_result_enum_type result;/*-Perform command parameter processing :-*/result = dsatparm_exec_param_cmd( mode,cmd_table,tok_ptr,res_buff_ptr );/*-Perform special processing :-*/result = mycmd_action( );return result; /* dsatvend_exec_mycmd_cmd */6. Abort command processing (添加abort命令函数) Since the command is not abortable, no Abort Command function needs to be defined.7. Command table entry (添加 命令表单)Since the command uses vendor-specific (extended) syntax, it should be added to thedsat_vendor_table in dsatctab.c. The command table entry looks like this: "$MYCMD", EXTENDED | CONFIG,SPECIAL_NONE, 2, &dsat_mycmd_val0, &dsat_mycmd_dflm0, dsatvend_exec_mycmd_cmd, NULL ,8. Compile and testThe AT command is now installed in the command table. Recompile the files that were modified and execute.在超级终端输入: AT$MYCMD ;观察输出9参考/ CC SPECelement * CHECKEDOUTelement qct_6085.