AT 组件构造-RT thread源码解析

AT 组件构造client,server-RT thread源码解析


AT命令的框架如下图,在官方手册中有详细介绍:https://www.rt-thread.org/document/site/programming-manual/at/at/


AT 命令框架

分析源码的时候,可能一团乱麻,无从着手.首先整理下心情,从调用关系着手.rt-thread是类linux风格,所以里面驱动的普遍在初始化时注册方法(函数)指针.这样做的目的是在更高层的屏蔽不同硬件特征,统一流程.


AT server

直接看函数 static rt_err_t at_cmd_process(at_cmd_t cmd, const char *cmd_args)

是不是比较熟悉, 跟int main(int argc, char* argv[]),有点点像.

看传入的第一个参数的类型

struct at_cmd

{

    char name[AT_CMD_NAME_LEN];

    char *args_expr;

    at_result_t (*test)(void);

    at_result_t (*query)(void);

    at_result_t (*setup)(const char *args);

    at_result_t (*exec)(void);

};

typedef struct at_cmd *at_cmd_t;

先猜测:看起来该方法是想使用参数cmd中的方法test 先去test解析第二个参数,符合某种条件,再去执行exec.

再看实现

看多条的if检测条件cmd_args[0] == AT_CMD_EQUAL_MARK cmd_args[0] == AT_CMD_QUESTION_MARK

看起来猜的不对.去看宏定义

#define AT_CMD_CHAR_0 '0'

#define AT_CMD_CHAR_9                  '9'

#define AT_CMD_QUESTION_MARK          '?'

#define AT_CMD_EQUAL_MARK              '='

#define AT_CMD_L_SQ_BRACKET            '['

#define AT_CMD_R_SQ_BRACKET            ']'

#define AT_CMD_L_ANGLE_BRACKET        '<'

#define AT_CMD_R_ANGLE_BRACKET        '>'

#define AT_CMD_COMMA_MARK              ','

#define AT_CMD_SEMICOLON              ';'

#define AT_CMD_CR                      '\r'

#define AT_CMD_LF                      '\n'

那么可以确认是命令下面的不同分支方法.

这个时候就是提醒我们去熟悉AT指令的规则了.

AT Server 目前默认支持的基础命令如下:

• AT:AT 测试命令;

• ATZ:设备恢复出厂设置;

• AT+RST:设备重启;

• ATE:ATE1 开启回显,ATE0 关闭回显;

• AT&L:列出全部命令列表;

• AT+UART:设置串口设置信息。

AT 命令根据传入的参数格式不同可以实现不同的功能,对于每个 AT 命令最多包含四种功能,如下所述:

• 测试功能:AT+=? 用于查询命令参数格式及取值范围;

• 查询功能:AT+? 用于返回命令参数当前值;

• 设置功能:AT+=... 用于用户自定义参数值;

• 执行功能:AT+ 用于执行相关操作。

这个函数实现了每个AT指令功能统一调用,这就是结构体指针,函数指针的好处,类似对象的处理.可以看出这是基层的核心

接下来直接看server服务的主流程函数 static void server_parser(at_server_t server)

同样先分析传入参数,先猜测一下实现,或者思考换作自己该怎么做.

struct at_server

{

    rt_device_t device; //这个是rt 自己的设备类,实现通用的open close read write ctrl 跟linux open close接口一样

    at_status_t status; //状态

    char (*get_char)(void); //获取字符串

    rt_bool_t echo_mode; //回显

    char recv_buffer[AT_SERVER_RECV_BUFF_LEN]; //接受buffer

    rt_size_t cur_recv_len;//接收长度

    rt_sem_t rx_notice;//信号

    char end_mark[AT_END_MARK_LEN];//结束mask集合

    rt_thread_t parser; //解析的线程指针? 似乎是可以创建多个解析线程

    void (*parser_entry)(struct at_server *server);//解析函数入口指针??指向自己

};

typedef struct at_server *at_server_t;

再来看主流程:

while(getcahr())

{

    //echo

    //判断是否到了endmark

    //获取位于字符串头部cmd的名字 at_cmd_get_name

    //根据cmd的字符串, 找到cmd的结构体对象at_cmd_t

    //调用at_cmd_process 处理, 通过at_server_print_result 发送结果

}

那么什么时候调用server_parser,或者说怎么让它成为一个名副其实的SERVER呢?看at_server_init

at_server_init将结构体at_server_t的成员初始化.里面有几个重要的成员将自己关联到其他机制中

device /* Find and open command device */

get_char /*使用device读取字符,同时使用信号量唤醒机制 */

parser /* 创建线程 rt_thread_create  "at_svr", (void (*)(void *parameter))server_parser, at_server_local */

这样成就了一个线程服务,再然后client怎么到server, 一会client再说




AT client

AT client承担承上启下的功能, 发送 AT 命令、接收数据并解析数据(server发回的字符串,转化为status)

需要结合官方手册进行分析

核心函数 rt_err_t at_exec_cmd(at_response_t resp, const char *cmd_expr, ...);

第一个参数 跟server类似

struct at_client

{

    rt_device_t device;

    at_status_t status;

    char end_sign;

    /* the current received one line data buffer */

    char *recv_line_buf;

    /* The length of the currently received one line data */

    rt_size_t recv_line_len;

    /* The maximum supported receive data length */

    rt_size_t recv_bufsz;

    rt_sem_t rx_notice;

    rt_mutex_t lock;

    at_response_t resp;

    rt_sem_t resp_notice;

    at_resp_status_t resp_status;

    struct at_urc_table *urc_table;

    rt_size_t urc_table_size;

    rt_thread_t parser;

};

typedef struct at_client *at_client_t;

后面是可变参数,这部分处理print中一样的机制 va_list,将字符串写到设备中

va_start(args, cmd_expr);

at_vprintfln(client->device, cmd_expr, args);

va_end(args);

再有

if (resp != RT_NULL)

{

    if (rt_sem_take(client->resp_notice, resp->timeout) != RT_EOK)

    ...

}

resp != RT_NULL时候表明需要等待响应. rt_sem_take 实现了超时功能.

综上这个函数功能是发送给设备的AT指令字符串,并等待响应字符串,解析成status code码返回.

结合上面server创建时,需要打开设备.所以 client和server的通信是通过访问同一个device实现的.

client的初始化函数 int at_client_init(const char *dev_name, rt_size_t recv_bufsz)

可以看出,作者想设计的机制是一个client 对应多个server.

另外还有个URC并不熟悉.可以参考手册.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,045评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,114评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,120评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,902评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,828评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,132评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,590评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,258评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,408评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,335评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,385评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,068评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,660评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,747评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,967评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,406评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,970评论 2 341

推荐阅读更多精彩内容

  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom阅读 2,689评论 0 3
  • 大纲 一.Socket简介 二.BSD Socket编程准备 1.地址 2.端口 3.网络字节序 4.半相关与全相...
    VD2012阅读 2,249评论 0 5
  • linux 内核定时器timer_list用法作者 codercjg 在 30 十月 2015, 2:27 下午 ...
    codercjg阅读 998评论 0 0
  • 概念: FastDFS是余庆(前阿里巴巴架构师,现易到用车架构师)开发的一个开源的轻量级分布式文件系统,对于小文件...
    yingyingguigui阅读 5,693评论 0 2
  • 我是从2016年开始接触“时间管理”这个概念,开始认真去做这件事情,是在2017年。 在践行时间管理这段时间后,我...
    岳读阅读 401评论 0 1