diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ec5b8c5 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [2015~2020] [master_roger@sina.com] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index 0f08239..7f59d58 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # AT Command #### 介绍 -一种AT命令通信管理模块(支持单行发),支持裸机和OS版本。适用于modem、WIFI模块、蓝牙通信。 +一种AT命令通信解析模块,支持裸机(at_chat)和OS版本(at)。适用于modem、WIFI模块、蓝牙通信。 #### 软件架构 软件架构说明 @@ -56,4 +56,69 @@ static void read_csq_callback(at_response_t *r) at_send_singlline(&at, read_csq_callback, "AT+CSQ"); ``` +##### at 模块(OS版本) + +``` + +static at_obj_t at; //定义AT管理器 + +char urc_buf[128]; //URC主动上报缓冲区 + +utc_item_t utc_tbl[] = { //定义URC表 + "+CSQ: ", csq_updated_handler +} + +const at_conf_t conf = { //AT管理器配置参数 + .urc_buf = urc_buf, + .urc_bufsize = sizeof(urc_buf), + .utc_tbl = utc_tbl, + .urc_tbl_count = sizeof(utc_tbl) / sizeof(utc_item_t), + + //适配GPRS模块的串口读写接口 + .write = uart_write, + .read = uart_read +}; +``` + +3. 初始化AT管理器并创建AT线程 + +``` +void at_thread(void) +{ + at_obj_create(&at, &conf); + while (1) { + /*do something ...*/ + at_thread(&at); + } +} + +``` + + +4. 使用例子 +查询GPRS模块信号质量: + => AT+CSQ + + <= +CSQ: 24, 0 + <= OK +``` +/* + * @brief 获取csq值 + */ +bool read_csq_value(at_obj_t *at, int *rssi, int *error_rate) +{ + //接收缓冲区 + unsigned char recvbuf[32]; + //AT响应 + at_respond_t r = {"OK", recvbuf, sizeof(recvbuf), 3000}; + // + if (at_do_cmd(at, &r, "AT+CSQ") != AT_RET_OK) + return false; + //解析响应响应 + return (sscanf(recv, "%*[^+]+CSQ: %d,%d", rssi, error_rate) == 2); + +} + + +``` diff --git a/at.c b/at.c new file mode 100644 index 0000000..44328a4 --- /dev/null +++ b/at.c @@ -0,0 +1,366 @@ +/******************************************************************************* +* @file at.h +* @brief ATͨŹ +* +* @version 5.0 +* @date 2020-05-11 +* @author roger.luo +* +* Change Logs: +* Date Author Notes +* 2016-01-22 roger.luo Initial version. +* 2017-05-21 roger.luo 1.1 ״̬ +* 2018-02-11 roger.luo 3.0 +* 2020-01-02 roger.luo 4.0 os汾 +*******************************************************************************/ +#include "at.h" +#include +#include +#include + +//ʱж +#define AT_IS_TIMEOUT(start, time) (at_get_ms() - (start) > (time)) + +static LIST_HEAD(atlist); /*ͷ ----------------*/ + +/* + * @brief ַ + */ +static void put_string(at_obj_t *at, const char *s) +{ + while (*s != '\0') + at->cfg.write(s++, 1); +} + + +/* + * @brief ַ() + */ +static void put_line(at_obj_t *at, const char *s) +{ + put_string(at, s); + put_string(at, "\r\n"); + at->cfg.debug("->\r\n%s\r\n", s); +} + +//ӡ +static void at_print(at_obj_t *at, const char *cmd, ...) +{ + va_list args; + va_start(args, cmd); + char buf[MAX_AT_CMD_LEN]; + vsnprintf(buf, sizeof(buf), cmd, args); + put_line(at, buf); + va_end(args); +} + +/* + * @brief ݻ + */ +static void recvbuf_clr(at_obj_t *at) +{ + at->rcv_cnt = 0; +} + +//ȴATӦ +static at_return wait_resp(at_obj_t *at, at_respond_t *r) +{ + at->resp = r; + at->ret = AT_RET_TIMEOUT; + at->resp_timer = at_get_ms(); + recvbuf_clr(at); //սջ + at->wait = 1; + at_sem_wait(&at->completed, r->timeout); + at->cfg.debug("<-\r\n%s\r\n", r->recvbuf); + at->resp = NULL; + at->wait = 0; + return at->ret; +} + +/* + * @brief ͬӦATӦ + * @param[in] resp - ȴմ("OK",">") + * @param[in] timeout - ȴʱʱ + */ +at_return wait_resp_sync(struct at_obj *at, const char *resp, + unsigned int timeout) +{ + char buf[64]; + int cnt = 0, len; + at_return ret = AT_RET_TIMEOUT; + unsigned int timer = at_get_ms(); + while (at_get_ms() - timer < timeout) { + len = at->cfg.read(buf, sizeof(buf) - cnt); + cnt += len; + buf[cnt] = '\0'; + if (strstr(buf, resp)) { + ret = AT_RET_OK; + break; + } else if (strstr(buf, "ERROR")) { + ret = AT_RET_ERROR; + break; + } + at_delay(10); + } + at->cfg.debug("%s", buf); + return ret; +} + + +/* + * @brief ATں + */ +void at_obj_create(at_obj_t *at, const at_conf_t cfg) +{ + at_work_env_t *e; + at->cfg = cfg; + at->rcv_cnt = 0; + + at_sem_init(&at->cmd_lock, 1); + at_sem_init(&at->completed, 0); + e = &at->env; + e->at = at; + e->printf = at_print; + e->recvclr = recvbuf_clr; + e->read = cfg.read; + e->write = cfg.write; + e->wait_resp = wait_resp_sync; + + list_add_tail(&at->node, &atlist); + +} + +/* + * @brief AT + */ +void at_obj_destroy(at_obj_t *at) +{ + list_del(&at->node); +} + +/* + * @brief ִ + * @param[in] fmt - ʽ + * @param[in] r - Ӧ,NULL, ĬϷOKʾɹ,ȴ3s + * @param[in] args - б + */ +at_return at_do_cmd(at_obj_t *at, at_respond_t *r, const char *cmd) +{ + at_return ret; + char defbuf[64]; + at_respond_t default_resp = {"OK", defbuf, sizeof(defbuf), 3000}; + if (r == NULL) { + r = &default_resp; //ĬӦ + } + if (!at_sem_wait(&at->cmd_lock, r->timeout)) { + return AT_RET_TIMEOUT; + } + while (at->urc_cnt) { + at_delay(10); + } + put_line(at, cmd); + ret = wait_resp(at, r); + at_sem_post(&at->cmd_lock); + return ret; +} + +/* + * @brief ִATҵ + * @param[in] urc + * @return none + */ +int at_do_work(at_obj_t *at, at_work work, void *params) +{ + int ret; + if (!at_sem_wait(&at->cmd_lock, 150 * 1000)) { + return AT_RET_TIMEOUT; + } + at->env.params = params; + at->dowork = true; + ret = work(&at->env); + at->dowork = false; + at_sem_post(&at->cmd_lock); + return ret; +} + +/* + * @brief ָӦ + * @param[in] recvbuf - ջ + * @param[out] lines - Ӧ + * @return + */ +int at_split_respond_lines(char *recvbuf, char *lines[], int count) +{ + char *s = recvbuf; + size_t i = 0; + if (s == NULL || lines == NULL) + return 0; + + lines[i++] = s; + while(*s && i < count) { + if (*s == ',') { + *s = '\0'; + lines[i++] = s + 1; /*ָһӴ*/ + } + s++; + } + return i; +} + +/* + * @brief urc + * @param[in] urcline - URC + * @return none + */ +static void urc_handler_entry(at_obj_t *at, char *urcline, unsigned int size) +{ + int i, n; + utc_item_t *tbl = at->cfg.utc_tbl; + + for (i = 0; i < at->cfg.urc_tbl_count; i++){ + n = strlen(tbl->prefix); + if (n > 0 && strncmp(urcline, tbl->prefix, n) == 0) { + tbl->handler(urcline, size); + at->cfg.debug("<=\r\n%s\r\n", urcline); + return; + } + tbl++; + } + + if (size >= 2 && !at->wait) //Զ + at->cfg.debug("%s\r\n", urcline); +} + +/* + * @brief urc մ + * @param[in] buf - ջ + * @return none + */ +static void urc_recv_process(at_obj_t *at, const char *buf, unsigned int size) +{ + char *urc_buf; + unsigned short urc_size; + unsigned char c; + urc_buf = (char *)at->cfg.urc_buf; + urc_size = at->cfg.urc_bufsize; + if (at->urc_cnt > 0 && size == 0) { + if (AT_IS_TIMEOUT(at->urc_timer, 100)) { //100msʱ + urc_buf[at->urc_cnt] = '\0'; + at->urc_cnt = 0; + at->cfg.debug("urc recv timeout=>%s\r\n", urc_buf); + } + } else { + at->urc_timer = at_get_ms(); + while (size--) { + c = *buf++; + if (c == '\r' || c == '\n') { //յ1 + urc_buf[at->urc_cnt] = '\0'; + if (at->urc_cnt > 2) + urc_handler_entry(at, urc_buf, at->urc_cnt); + at->urc_cnt = 0; + } else { + urc_buf[at->urc_cnt++] = c; + if (at->urc_cnt >= urc_size) // + at->urc_cnt = 0; + } + } + } +} + +/* + * @brief ָӦմ + * @param[in] buf - ջ + * @param[in] size - ݳ + * @return none + */ +static void resp_recv_process(at_obj_t *at, const char *buf, unsigned int size) +{ + char *rcv_buf; + unsigned short rcv_size; + at_respond_t *resp = at->resp; + + if (resp == NULL || size == 0) + return; + + rcv_buf = (char *)resp->recvbuf; + rcv_size = resp->bufsize; + + if (at->rcv_cnt + size >= rcv_size) { // + at->rcv_cnt = 0; + at->cfg.debug("Receive overflow:%s", rcv_buf); + } + /*յݷrcv_buf ---------------------------------------------*/ + memcpy(rcv_buf + at->rcv_cnt, buf, size); + at->rcv_cnt += size; + rcv_buf[at->rcv_cnt] = '\0'; + + + if (!at->wait) + return; + if (strstr(rcv_buf, resp->matcher)) { //ƥ + at->ret = AT_RET_OK; + } else if (strstr(rcv_buf, "ERROR")) { + at->ret = AT_RET_ERROR; + } else if (AT_IS_TIMEOUT(at->resp_timer, resp->timeout)) { + at->ret = AT_RET_TIMEOUT; + } else if (at->suspend) //ǿֹ + at->ret = AT_RET_ABORT; + else + return; + + at_sem_post(&at->completed); +} + +/* + * @brief ATæж + * @return true - ATִָ + */ +bool at_obj_busy(at_obj_t *at) +{ + return at->wait == 0 && AT_IS_TIMEOUT(at->urc_timer, 2000); +} + +/* + * @brief ATҵ + * @return none + */ +void at_suspend(at_obj_t *at) +{ + at->suspend = 1; +} + +/* + * @brief ָATҵ + * @return none + */ +void at_resume(at_obj_t *at) +{ + at->suspend = 0; +} + +/* + * @brief ATѯ߳ + * @return none + */ +void at_thread(void) +{ + at_obj_t *at; + struct list_head *list ,*n = NULL; + int len; + char buf[32]; + while (1) { + /*at_obj*/ + list_for_each_safe(list, n, &atlist) { + at = list_entry(list, at_obj_t, node); + if (!at->dowork) { +#warning "ȡŻ(readline) ..." + len = at->cfg.read(buf, sizeof(buf)); + urc_recv_process(at, (char *)buf, len); + if (len > 0) { + resp_recv_process(at, buf, len); + } + } + } + at_delay(1); + } +} diff --git a/at.h b/at.h new file mode 100644 index 0000000..218be02 --- /dev/null +++ b/at.h @@ -0,0 +1,111 @@ +/******************************************************************************* +* @file at.h +* @brief ATͨŹ +* +* @version 5.0 +* @date 2020-05-11 +* @author roger.luo +* +* Change Logs: +* Date Author Notes +* 2016-01-22 roger.luo Initial version. +* 2017-05-21 roger.luo 1.1 ״̬ +* 2018-02-11 roger.luo 3.0 +* 2020-01-02 roger.luo 4.0 os汾 +*******************************************************************************/ +#ifndef _AT_H_ +#define _AT_H_ + +#include "at_util.h" +#include "list.h" +#include + +#define MAX_AT_CMD_LEN 64 + +struct at_obj; /*AT*/ + +/*urc -----------------------------------------------------------------*/ +typedef struct { + const char *prefix; //URCǰ׺ + void (*handler)(char *recvbuf, int size); +}utc_item_t; + +/*AT -------------------------------------------------------------------*/ +typedef struct { + /*ݶдӿ -----------------------------------------------------------*/ + unsigned int (*read)(void *buf, unsigned int len); + unsigned int (*write)(const void *buf, unsigned int len); + void (*debug)(const char *fmt, ...); + utc_item_t *utc_tbl; /*utc */ + char *urc_buf; /*urcջ*/ + unsigned short urc_tbl_count; + unsigned short urc_bufsize; /*urcС*/ +}at_conf_t; + +/*ATӦ ---------------------------------------------------------------*/ +typedef enum { + AT_RET_OK = 0, /*ִгɹ*/ + AT_RET_ERROR, /*ִд*/ + AT_RET_TIMEOUT, /*Ӧʱ*/ + AT_RET_ABORT, /*δ֪*/ +}at_return; + +/*ATӦ -----------------------------------------------------------------*/ +typedef struct { + const char *matcher; /*ƥ䴮*/ + char *recvbuf; /*ջ*/ + unsigned short bufsize; /*ճ*/ + unsigned int timeout; /*ʱʱ */ +}at_respond_t; + +/*ATҵ ---------------------------------------------------------------------*/ +typedef struct at_work_env{ + struct at_obj *at; + void *params; + unsigned int (*write)(const void *buf, unsigned int len); + unsigned int (*read)(void *buf, unsigned int len); + + void (*printf)(struct at_obj *at, const char *frm, ...); + at_return (*wait_resp)(struct at_obj *at, const char *resp, unsigned int timeout); + void (*recvclr)(struct at_obj *at); /*սջ*/ +}at_work_env_t; + +/*AT ---------------------------------------------------------------------*/ +typedef struct at_obj { + struct list_head node; + at_conf_t cfg; + at_work_env_t env; + at_sem_t cmd_lock; /**/ + at_sem_t completed; /**/ + at_respond_t *resp; + unsigned int resp_timer; + unsigned int urc_timer; + at_return ret; + //urcռ, Ӧռ + unsigned short urc_cnt, rcv_cnt; + unsigned char wait : 1; + unsigned char suspend: 1; + unsigned char dowork : 1; +}at_obj_t; + +typedef int (*at_work)(at_work_env_t *); + +void at_obj_create(at_obj_t *at, const at_conf_t cfg); /*ATʼ*/ + +void at_obj_destroy(at_obj_t *at); + +bool at_obj_busy(at_obj_t *at); + +void at_suspend(at_obj_t *at); /**/ + +void at_resume(at_obj_t *at); /*ָ*/ + +at_return at_do_cmd(at_obj_t *at, at_respond_t *r, const char *cmd); + +int at_split_respond_lines(char *recvbuf, char *lines[], int count); + +int at_do_work(at_obj_t *at, at_work work, void *params); /*ִATҵ*/ + +void at_thread(void); /*AT߳*/ + +#endif diff --git a/at_chat.c b/at_chat.c index ac6dad3..7dbec56 100644 --- a/at_chat.c +++ b/at_chat.c @@ -1,17 +1,19 @@ -/****************************************************************************** - * @brief AT ͨŹ(OS汾) - * - * Copyright (c) 2019, - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes -* 2016-01-22 Morro Initial version. -* 2018-02-11 Morro ʹʽйATҵ -* 2020-05-21 Morro ֧at_core - ******************************************************************************/ - +/******************************************************************************* +* @file at_core.h +* @brief AT command communications. +* +* @version 5.0 +* @date 2020-05-11 +* @author roger.luo +* +* Change Logs: +* Date Author Notes +* 2016-01-22 roger.luo Initial version. +* 2017-05-21 roger.luo 1.1 ״̬ +* 2018-02-11 roger.luo 3.0 +* 2020-01-02 roger.luo 4.0 os version +* 2020-05-21 roger.luo 5.0 OS汾 +*******************************************************************************/ #include "at_chat.h" #include #include @@ -52,10 +54,10 @@ static void send_data(at_core_t *ac, const void *buf, unsigned int len) */ static void print(at_core_t *ac, const char *cmd, ...) { - va_list args; + va_list args; va_start(args, cmd); at_send_line(ac, cmd, args); - va_end(args); + va_end(args); } /* * @brief ȡǰݽճ @@ -90,7 +92,7 @@ static char *search_string(at_core_t *ac, const char *str) /*ǰִ*/ static bool at_isabort(at_core_t *ac) { - return ac->cursor ? ac->cursor->abort : 1; + return ac->cursor ? ac->cursor->abort : 1; } @@ -164,7 +166,7 @@ static int do_cmd_handler(at_core_t *a) { at_item_t *i = a->cursor; at_env_t *e = &a->env; - const at_cmd_t *c = (at_cmd_t *)i->info; + const at_respond_t *c = (at_respond_t *)i->info; switch(e->state) { case 0: /*״̬ ------------------------------------------------------*/ c->sender(e); @@ -173,7 +175,7 @@ static int do_cmd_handler(at_core_t *a) e->recvclr(a); break; case 1: /*״̬ ------------------------------------------------------*/ - if (search_string(a, c->matcher)) { + if (search_string(a, c->matcher)) { do_at_callback(a, i, c->cb, AT_RET_OK); return true; } else if (search_string(a, "ERROR")) { @@ -221,7 +223,7 @@ static int send_signlline_handler(at_core_t *a) e->recvclr(a); break; case 1: /*״̬ ------------------------------------------------------*/ - if (search_string(a, "OK")) { + if (search_string(a, "OK")) { do_at_callback(a, i, cb, AT_RET_OK); return true; } else if (search_string(a, "ERROR")) { @@ -332,10 +334,10 @@ static void urc_handler_entry(at_core_t *ac, char *urc, unsigned int size) */ static void urc_recv_process(at_core_t *ac, char *buf, unsigned int size) { - char *urc_buf; + char *urc_buf; unsigned short urc_size; urc_buf = (char *)ac->cfg.urc_buf; - urc_size = ac->cfg.urc_bufsize; + urc_size = ac->cfg.urc_bufsize; if (size == 0 && ac->urc_cnt > 0) { if (AT_IS_TIMEOUT(ac->urc_timer, 2000)){ urc_handler_entry(ac, urc_buf, ac->urc_cnt); @@ -364,7 +366,7 @@ static void urc_recv_process(at_core_t *ac, char *buf, unsigned int size) static void resp_recv_process(at_core_t *ac, const char *buf, unsigned int size) { char *rcv_buf; - unsigned short rcv_size; + unsigned short rcv_size; rcv_buf = (char *)ac->cfg.rcv_buf; rcv_size = ac->cfg.rcv_bufsize; @@ -372,7 +374,7 @@ static void resp_recv_process(at_core_t *ac, const char *buf, unsigned int size) if (ac->rcv_cnt + size >= rcv_size) // ac->rcv_cnt = 0; - memcpy(rcv_buf, buf, size); + memcpy(rcv_buf + rcv_cnt, buf, size); ac->rcv_cnt += size; rcv_buf[ac->rcv_cnt] = '\0'; @@ -394,7 +396,7 @@ bool at_do_work(at_core_t *ac, int (*work)(at_env_t *e), void *params) * @param[in] a - AT * @param[in] cmd - cmd */ -bool at_do_cmd(at_core_t *ac, void *params, const at_cmd_t *cmd) +bool at_do_cmd(at_core_t *ac, void *params, const at_respond_t *cmd) { return add_work(ac, params, (void *)cmd, AT_TYPE_CMD); } @@ -429,7 +431,7 @@ bool at_send_multiline(at_core_t *ac, at_callback_t cb, const char **multiline) void at_item_abort(at_item_t *i) { - i->abort = 1; + i->abort = 1; } /* @@ -450,7 +452,7 @@ static void at_work_manager(at_core_t *ac) at_env_t *e = &ac->env; /*ͨù ---------------------------------------------------------*/ static int (*const work_handler_table[])(at_core_t *) = { - do_work_handler, + do_work_handler, do_cmd_handler, send_signlline_handler, send_multiline_handler @@ -468,10 +470,10 @@ static void at_work_manager(at_core_t *ac) } /*ִ,뵽й ------------------------------------*/ if (work_handler_table[cursor->type](ac) || cursor->abort) { - ac->cfg.lock(); - list_move_tail(&ac->cursor->node, &ac->ls_idle); - ac->cursor = NULL; - ac->cfg.unlock(); + ac->cfg.lock(); + list_move_tail(&ac->cursor->node, &ac->ls_idle); + ac->cursor = NULL; + ac->cfg.unlock(); } } diff --git a/at_chat.h b/at_chat.h index b539e6d..75a834f 100644 --- a/at_chat.h +++ b/at_chat.h @@ -1,16 +1,20 @@ -/****************************************************************************** - * @brief AT ͨŹ(OS汾) - * - * Copyright (c) 2019, - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Notes -* 2016-01-22 Morro Initial version. -* 2018-02-11 Morro ʹʽйATҵ -* 2020-05-21 Morro ֧at_core - ******************************************************************************/ +/******************************************************************************* +* Copyright(C)20 roger.luo +* All rights reserved. +* @file atchat.h +* @brief AT command communications. +* +* @version 3.0 +* @date 2018-02-11 +* @author roger.luo +* +* Change Logs: +* Date Author Notes +* 2016-01-22 roger.luo Initial version. +* 2017-05-21 roger.luo 1.1 ״̬ +* 2018-02-11 roger.luo 3.0 +* 2020-01-02 roger.luo 4.0 os version +*******************************************************************************/ #ifndef _ATCHAT_H_ #define _ATCHAT_H_ @@ -37,22 +41,22 @@ typedef struct { void (*before_at)(void); /*ʼִAT*/ void (*after_at)(void); void (*error)(void); - utc_item_t *utc_tbl; /*utc */ - unsigned char *urc_buf; /*urcջ*/ + utc_item_t *utc_tbl; /*utc */ + unsigned char *urc_buf; /*urcջ*/ unsigned char *rcv_buf; - unsigned short urc_tbl_count; - unsigned short urc_bufsize; /*urcС*/ + unsigned short urc_tbl_count; + unsigned short urc_bufsize; /*urcС*/ unsigned short rcv_bufsize; /*ջ*/ }at_core_conf_t; /*ATҵл*/ typedef struct { - int i,j,state; - void *params; + int i,j,state; + void *params; void (*reset_timer)(struct at_core *ac); - bool (*is_timeout)(struct at_core *ac, unsigned int ms); /*ʱж*/ - void (*printf)(struct at_core *ac, const char *fmt, ...); - char * (*find)(struct at_core *ac, const char *expect); + bool (*is_timeout)(struct at_core *ac, unsigned int ms); /*ʱж*/ + void (*printf)(struct at_core *ac, const char *fmt, ...); + char * (*find)(struct at_core *ac, const char *expect); char * (*recvbuf)(struct at_core *ac); /*ָջ*/ unsigned int(*recvlen)(struct at_core *ac); /*ܳ*/ void (*recvclr)(struct at_core *ac); /*սջ*/ @@ -64,14 +68,14 @@ typedef enum { AT_RET_OK = 0, /*ִгɹ*/ AT_RET_ERROR, /*ִд*/ AT_RET_TIMEOUT, /*Ӧʱ*/ - AT_RET_ABORT, /*ǿֹ*/ + AT_RET_ABORT, /*ǿֹ*/ }at_return; /*ATӦ */ typedef struct { void *param; - char *recvbuf; - unsigned short recvcnt; + char *recvbuf; + unsigned short recvcnt; at_return ret; }at_response_t; @@ -90,23 +94,23 @@ typedef struct { unsigned char type : 3; unsigned char abort : 1; void *param; - void *info; + void *info; struct list_head node; }at_item_t; /*AT ------------------------------------------------------------------*/ typedef struct at_core{ - at_core_conf_t cfg; + at_core_conf_t cfg; at_env_t env; - at_item_t tbl[10]; + at_item_t tbl[10]; at_item_t *cursor; struct list_head ls_ready, ls_idle; /*,ҵ*/ - unsigned int resp_timer; - unsigned int urc_timer; - at_return ret; - //urcռ, Ӧռ - unsigned short urc_cnt, rcv_cnt; - unsigned char suspend: 1; + unsigned int resp_timer; + unsigned int urc_timer; + at_return ret; + //urcռ, Ӧռ + unsigned short urc_cnt, rcv_cnt; + unsigned char suspend: 1; }at_core_t; typedef struct {