diff --git a/Demo/user/task/wifi_task.c b/Demo/user/task/wifi_task.c index 85922c9..d608134 100644 --- a/Demo/user/task/wifi_task.c +++ b/Demo/user/task/wifi_task.c @@ -95,7 +95,12 @@ static int wifi_reset_work(at_env_t *e) break; case 2: wifi_open(); //重启启动wifi - return true; + e->state++; + break; + case 3: + if (e->is_timeout(a, 2000)) //延时等待2s + return true; + break; } return false; } @@ -146,7 +151,8 @@ void wifi_init(void) wifi_uart_init(115200); at_obj_init(&at, &at_adapter); - wifi_open(); + //启动WIFI + at_do_work(&at, wifi_reset_work, &at); //初始化wifi at_send_multiline(&at, at_init_callbatk, wifi_init_cmds); diff --git a/README.md b/README.md index a625181..53a7469 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # AT Command + ## 浠嬬粛 涓绉岮T鍛戒护閫氫俊瑙f瀽妯″潡,鏀寔瑁告満(at_chat)鍜孫S鐗堟湰(at)銆傞傜敤浜巑odem銆乄IFI妯″潡銆佽摑鐗欓氫俊銆 @@ -22,7 +23,7 @@ at_chat 妯″潡浣跨敤閾惧紡闃熷垪杩涜绠$悊锛屽寘鍚2鏉¢摼琛紝绌洪棽閾捐〃鍜屽氨缁摼琛ㄣ傚畠浠殑姣忎竴涓熀鏈伐浣滃崟鍏冪О涓轰竴涓綔涓氶」锛屽浜庡皢瑕佹墽琛岀殑鍛戒护閮戒細鏀惧埌灏辩华閾捐〃涓紝鍛戒护鎵ц瀹屾垚涔嬪悗鐢辩┖闂查摼琛ㄦ潵杩涜鍥炴敹锛屼綔涓氶」鐨勫畾涔夊涓嬶細 -``` +```c /*AT浣滀笟椤*/ typedef struct { @@ -51,7 +52,7 @@ typedef struct { 璇︾粏浣跨敤鍙互鍙傝僁emo绋嬪簭wifi_task.c妯″潡 ![m169 wifi妯$粍閫氫俊鏁堟灉鍥綸(images/wifi.jpg) -``` +```c /* * @brief 瀹氫箟AT鎺у埗鍣 @@ -70,7 +71,7 @@ const at_adapter_t adap = { //AT閫傞厤鍣ㄦ帴鍙 3. 鍒濆鍖朅T鎺у埗鍣 -``` +```c at_obj_init(&at, &adap); @@ -79,7 +80,7 @@ at_obj_init(&at, &adap); 4. 灏咥T鎺у埗鍣ㄦ斁鍏ヤ换鍔′腑杞锛堣冭檻鍒板鐞嗗疄鏃舵э紝寤鸿20ms浠ヤ笅锛 -``` +```c /* * @brief wifi浠诲姟(10ms 杞1娆) */ @@ -99,7 +100,7 @@ void wifi_task(void) <= OK\r\n -``` +```c /** * @brief AT鎵ц鍥炶皟澶勭悊绋嬪簭 @@ -124,12 +125,12 @@ at_send_singlline(&at, test_gpio_callback, "AT+GPIO_TEST_EN=1"); - at_do_cmd锛屾墽琛孉T鍛戒护锛屽彲浠ラ氳繃杩欎釜鎺ュ彛杩涗竴姝ュ皝瑁呭嚭涓甯哥敤鐨勫崟琛屽懡浠ゃ佸琛屽懡浠ゃ - at_split_respond_lines锛屽懡浠ゅ搷搴斿垎鍓插櫒銆 -- at_do_work锛屽鏋滃彂閫佺殑鏁版嵁姣旇緝澶嶆潅锛屽GPRS妯$粍鍙戦佺煭淇℃垨鑰呭彂閫乻ocket鏁版嵁闇瑕佺瓑寰"<"鎻愮ず绗︼紝鍙互閫氳繃杩欎釜鎺ュ彛鑷畾涔夋敹鍙戙 +- at_do_work锛岄傜敤浜庡彂閫佺粍鍚堝懡浠わ紝濡侴PRS妯$粍鍙戦佺煭淇℃垨鑰呭彂閫乻ocket鏁版嵁闇瑕佺瓑寰"<"鎴栬"CONNECT"鎻愮ず绗︼紝鍙互閫氳繃杩欎釜鎺ュ彛鑷畾涔夋敹鍙戙 ##### 浣跨敤婕旂ず(鍚庣画浼氭彁渚涗竴涓棤绾縂PRS妯″潡婕旂ず绋嬪簭鍑烘潵) -``` +```c -static at_obj_t at; //瀹氫箟AT鎺у埗鍣 +static at_obj_t at; //瀹氫箟AT鎺у埗鍣ㄥ璞 static char urc_buf[128]; //URC涓诲姩涓婃姤缂撳啿鍖 @@ -142,7 +143,8 @@ const at_adapter_t adap = { //AT閫傞厤鍣ㄦ帴鍙 .urc_bufsize = sizeof(urc_buf), .utc_tbl = utc_tbl, .urc_tbl_count = sizeof(utc_tbl) / sizeof(utc_item_t), - + //debug璋冭瘯鎺ュ彛 + .debug = at_debug, //閫傞厤GPRS妯″潡鐨勪覆鍙h鍐欐帴鍙 .write = uart_write, .read = uart_read @@ -150,15 +152,15 @@ const at_adapter_t adap = { //AT閫傞厤鍣ㄦ帴鍙 ``` -3. 鍒濆鍖朅T鎺у埗鍣ㄥ苟鍒涘缓AT绾跨▼ +3. 鍒濆鍖朅T鎺у埗鍣ㄥ苟鍒涘缓AT鎺ユ敹澶勭悊绾跨▼ -``` +```c void at_thread(void) { at_obj_create(&at, &adap); while (1) { - at_thread(&at); + at_process(&at); } } @@ -172,7 +174,7 @@ void at_thread(void) <= +CSQ: 24, 0 <= OK -``` +```c /* * @brief 鑾峰彇csq鍊 */ @@ -191,4 +193,7 @@ bool read_csq_value(at_obj_t *at, int *rssi, int *error_rate) } + + + ``` diff --git a/at.c b/at.c index cb08659..b6c1b90 100644 --- a/at.c +++ b/at.c @@ -8,17 +8,33 @@ * Change Logs: * Date Author Notes * 2020-01-02 Morro Initial version. + * 2021-02-01 Morro 支持URC回调中接收数据. + * 2021-02-05 Morro 1.修改struct at_obj,去除链表管理机制 + * 2.删除 at_obj_destroy接口 ******************************************************************************/ - -#include "at.h" +#include "at/at.h" +#include "misc/comdef.h" #include #include #include +#include //超时判断 #define AT_IS_TIMEOUT(start, time) (at_get_ms() - (start) > (time)) -static LIST_HEAD(atlist); /*链表头结点 ----------------*/ +/* + * @brief 默认调试接口 + */ +static void nop_dbg(const char *fmt, ...){} + +/* + * @brief 获取at控制器 + */ +at_obj_t *get_at_obj(struct at_work_ctx *e) +{ + return container_of(e, at_obj_t, ctx); +} + /* * @brief 输出字符串 @@ -41,22 +57,22 @@ static void put_line(at_obj_t *at, const char *s) } //打印输出 -static void at_print(at_obj_t *at, const char *cmd, ...) +static void at_print(struct at_work_ctx *e, const char *cmd, ...) { - va_list args; + va_list args; va_start(args, cmd); char buf[MAX_AT_CMD_LEN]; vsnprintf(buf, sizeof(buf), cmd, args); - put_line(at, buf); + put_line(get_at_obj(e), buf); va_end(args); } /* * @brief 清除数据缓冲区 */ -static void recvbuf_clr(at_obj_t *at) +static void recvbuf_clr(struct at_work_ctx *e) { - at->rcv_cnt = 0; + get_at_obj(e)->rcv_cnt = 0; } //等待AT命令响应 @@ -65,12 +81,10 @@ 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->rcv_cnt = 0; //清空接收缓存 + at_sem_wait(at->completed, r->timeout); at->adap.debug("<-\r\n%s\r\n", r->recvbuf); at->resp = NULL; - at->wait = 0; return at->ret; } @@ -79,11 +93,13 @@ static at_return wait_resp(at_obj_t *at, at_respond_t *r) * @param[in] resp - 等待接收串(如"OK",">") * @param[in] timeout - 等待超时时间 */ -at_return wait_resp_sync(struct at_obj *at, const char *resp, +at_return wait_resp_sync(struct at_work_ctx *e, const char *resp, unsigned int timeout) { char buf[64]; int cnt = 0, len; + at_obj_t *at = get_at_obj(e); + at_return ret = AT_RET_TIMEOUT; unsigned int timer = at_get_ms(); while (at_get_ms() - timer < timeout) { @@ -105,58 +121,54 @@ at_return wait_resp_sync(struct at_obj *at, const char *resp, /* - * @brief AT内核配置 + * @brief 创建AT控制器 */ void at_obj_create(at_obj_t *at, const at_adapter_t *adap) { - at_work_env_t *e; - at->adap = *adap; + at_work_ctx_t *ctx; + at->adap = *adap; at->rcv_cnt = 0; - at->cmd_lock = at_sem_new(1); - at->completed = at_sem_new(0); - e = &at->env; - e->at = at; - e->printf = at_print; - e->recvclr = recvbuf_clr; - e->read = adap->read; - e->write = adap->write; - e->wait_resp = wait_resp_sync; + at->cmd_lock = ril_sem_new(1); + at->completed = ril_sem_new(0); + ctx = &at->ctx; + ctx->printf = at_print; + ctx->recvclr = recvbuf_clr; + ctx->read = adap->read; + ctx->write = adap->write; + ctx->wait_resp = wait_resp_sync; + + if (at->adap.debug == NULL) + at->adap.debug = nop_dbg; - 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] r - 响应参数,如果填NULL, 默认返回OK表示成功,等待5s * @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}; + at_respond_t default_resp = {"OK", defbuf, sizeof(defbuf), 5000}; if (r == NULL) { r = &default_resp; //默认响应 } if (!at_sem_wait(at->cmd_lock, r->timeout)) { return AT_RET_TIMEOUT; } + at->busy = true; + while (at->urc_cnt) { at_delay(10); } put_line(at, cmd); ret = wait_resp(at, r); at_sem_post(at->cmd_lock); + at->busy = false; return ret; } @@ -171,14 +183,17 @@ at_return at_do_work(at_obj_t *at, at_work work, void *params) if (!at_sem_wait(at->cmd_lock, 150 * 1000)) { return AT_RET_TIMEOUT; } - while (at->urc_cnt) { + at->busy = true; + while (at->urc_cnt) { //等待URC处理完成 at_delay(1); } - at->env.params = params; - at->dowork = true; - ret = work(&at->env); + at->ctx.params = params; + at->dowork = true; + at->rcv_cnt = 0; + ret = work(&at->ctx); at->dowork = false; at_sem_post(at->cmd_lock); + at->busy = false; return ret; } @@ -204,73 +219,98 @@ int at_split_respond_lines(char *recvbuf, char *lines[], int count, char separat } s++; } - return i; + return i; } /* * @brief urc 处理总入口 * @param[in] urcline - URC行 - * @return none + * @return true - 正常识别并处理, false - 未识别URC */ -static void urc_handler_entry(at_obj_t *at, char *urcline, unsigned int size) +static bool urc_handler_entry(at_obj_t *at, char *urcline, unsigned int size) { - int i, n; - utc_item_t *tbl = at->adap.utc_tbl; + int i; + int ch = urcline[size - 1]; + at_urc_ctx_t context = {at->adap.read, urcline, at->adap.urc_bufsize, size}; - for (i = 0; i < at->adap.urc_tbl_count; i++){ - n = strlen(tbl->prefix); - if (n > 0 && strncmp(urcline, tbl->prefix, n) == 0) { - tbl->handler(urcline, size); + const utc_item_t *tbl = at->adap.utc_tbl; + + if (tbl == NULL) + return true; + + for (i = 0; i < at->adap.urc_tbl_count; i++) { + if (strstr(urcline, tbl->prefix)) { /* 匹配前缀*/ + + if (tbl->end_mark) { /* 匹配结束标记*/ + if (!strchr(tbl->end_mark, ch)) + return false; + } else if (!(ch == '\r' || ch == '\n'|| ch == '\0')) + return false; + at->adap.debug("<=\r\n%s\r\n", urcline); - return; + + tbl->handler(&context); /* 递交到上层处理 */ + return true; } tbl++; } - - if (size >= 2 && !at->wait) //自动输出 - at->adap.debug("%s\r\n", urcline); + return false; } /* * @brief urc 接收处理 - * @param[in] buf - 接收缓存 + * @param[in] ch - 接收字符 * @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->adap.urc_buf; - urc_size = at->adap.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->adap.debug("urc recv timeout=>%s\r\n", urc_buf); - } - } else { + register char *urc_buf; + int ch; + urc_buf = at->adap.urc_buf; + + //接收超时处理,默认MAX_URC_RECV_TIMEOUT + if (at->urc_cnt > 0 && AT_IS_TIMEOUT(at->urc_timer, MAX_URC_RECV_TIMEOUT)) { + urc_buf[at->urc_cnt] = '\0'; + at->urc_cnt = 0; + at->adap.debug("urc recv timeout=>%s\r\n", urc_buf); + } + + while (size--) { 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); + ch = *buf++; + urc_buf[at->urc_cnt++] = ch; + + if (strchr(SPEC_URC_END_MARKS, ch) || ch == '\0') { //结束标记 + urc_buf[at->urc_cnt] = '\0'; + + if (ch == '\r' || ch == '\n'|| ch == '\0') { //检测到1行URC + if (at->urc_cnt > 2) { + if (!urc_handler_entry(at, urc_buf, at->urc_cnt) && !at->busy) + at->adap.debug("%s\r\n", urc_buf); //未识别到的URC + } + at->urc_cnt = 0; + } else if (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; } - } + } else if (at->urc_cnt >= at->adap.urc_bufsize) //溢出处理 + at->urc_cnt = 0; } } +/* + * @brief 命令响应通知 + * @return none + */ +static void resp_notification(at_obj_t *at, at_return ret) +{ + at->ret = ret; + at_sem_post(at->completed); +} + /* * @brief 指令响应接收处理 * @param[in] buf - 接收缓冲区 - * @param[in] size - 缓冲区数据长度 + * @param[in] size - 缓冲区数据长度 * @return none */ static void resp_recv_process(at_obj_t *at, const char *buf, unsigned int size) @@ -279,36 +319,34 @@ static void resp_recv_process(at_obj_t *at, const char *buf, unsigned int size) 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->adap.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 + if (resp == NULL) //无命令请求 return; - at_sem_post(at->completed); + if (size) { + rcv_buf = (char *)resp->recvbuf; + rcv_size = resp->bufsize; + + if (at->rcv_cnt + size >= rcv_size) { //接收溢出 + at->rcv_cnt = 0; + at->adap.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 (strstr(rcv_buf, resp->matcher)) { //接收匹配 + resp_notification(at, AT_RET_OK); + } else if (strstr(rcv_buf, "ERROR")) { + resp_notification(at, AT_RET_ERROR); + } + } + + if (AT_IS_TIMEOUT(at->resp_timer, resp->timeout)) //接收超时 + resp_notification(at, AT_RET_TIMEOUT); + else if (at->suspend) //强制终止 + resp_notification(at, AT_RET_ABORT); + } /* @@ -317,7 +355,7 @@ static void resp_recv_process(at_obj_t *at, const char *buf, unsigned int size) */ bool at_obj_busy(at_obj_t *at) { - return at->wait == 0 && AT_IS_TIMEOUT(at->urc_timer, 2000); + return !at->busy && AT_IS_TIMEOUT(at->urc_timer, 2000); } /* @@ -339,28 +377,18 @@ void at_resume(at_obj_t *at) } /* - * @brief AT轮询线程 + * @brief AT处理 * @return none */ -void at_thread(void) +void at_process(at_obj_t *at) { - 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->adap.read(buf, sizeof(buf)); - urc_recv_process(at, (char *)buf, len); - if (len > 0) { - resp_recv_process(at, buf, len); - } - } - } - at_delay(1); - } + char c; + unsigned int len; + if (at->dowork) /* 自定义命令处理 */ + return; + do { + len = at->adap.read(&c, 1); + urc_recv_process(at, &c,len); + resp_recv_process(at, &c, len); + } while (len); } diff --git a/at.h b/at.h index 85bfa10..c75daf9 100644 --- a/at.h +++ b/at.h @@ -8,101 +8,150 @@ * Change Logs: * Date Author Notes * 2020-01-02 Morro Initial version. + * 2021-02-01 Morro 支持URC回调中接收数据. + * 2021-02-05 Morro 1.修改struct at_obj,去除链表管理机制 + * 2.删除 at_obj_destroy接口 ******************************************************************************/ #ifndef _AT_H_ #define _AT_H_ #include "at_util.h" -#include "list.h" #include +/* 单行最大命令长度 */ #define MAX_AT_CMD_LEN 128 -struct at_obj; /*AT对象*/ +/* 单行urc接收超时时间*/ +#define MAX_URC_RECV_TIMEOUT 300 -/*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; /* urc表项个数*/ - unsigned short urc_bufsize; /* urc缓冲区大小*/ -}at_adapter_t; +/* 指定的URC 结束标记列表 */ +#define SPEC_URC_END_MARKS ",\r\n" + +struct at_obj; /* AT对象*/ /*AT命令响应码 ---------------------------------------------------------------*/ typedef enum { - AT_RET_OK = 0, /*执行成功*/ - AT_RET_ERROR, /*执行错误*/ - AT_RET_TIMEOUT, /*响应超时*/ - AT_RET_ABORT, /*未知错误*/ + AT_RET_OK = 0, /* 执行成功*/ + AT_RET_ERROR, /* 执行错误*/ + AT_RET_TIMEOUT, /* 响应超时*/ + AT_RET_ABORT, /* 未知错误*/ }at_return; +/** + * @brief URC 上下文(Context) 定义 + */ +typedef struct { + /** + * @brief 数据读取接口 + * @params buf - 缓冲区 + * @params len - 缓冲区大小 + */ + unsigned int (*read)(void *buf, unsigned int len); + char *buf; /* 数据缓冲区 */ + int bufsize; /* 缓冲区大小 */ + int recvlen; /* 已接收数据长度*/ +} at_urc_ctx_t; + +/*(Unsolicited Result Codes (URCs))处理项 ------------------------------------*/ +typedef struct { + /** + * @brief urc 前缀(如"+CSQ: ") + */ + const char *prefix; + /** + * @brief urc 指定结束字符标记(参考DEF_URC_END_MARKS列表,如果不指定则默认"\n") + * @note + */ + const char *end_mark; + /** + * @brief urc处理程序 + * @params ctx - URC 上下文 + */ + void (*handler)(at_urc_ctx_t *ctx); +}utc_item_t; + +/**AT接口适配器 --------------------------------------------------------------*/ +typedef struct { + //数据写操作 + unsigned int (*write)(const void *buf, unsigned int len); + //数据读操作 + unsigned int (*read)(void *buf, unsigned int len); + //调试打印输出,如果不需要则填NULL + void (*debug)(const char *fmt, ...); + //utc 处理函数表,如果不需要则填NULL + utc_item_t *utc_tbl; + //urc接收缓冲区,如果不需要则填NULL + char *urc_buf; + //urc表项个数,如果不需要则填0 + unsigned short urc_tbl_count; + //urc缓冲区大小,如果不需要则填0 + unsigned short urc_bufsize; +}at_adapter_t; + /*AT响应参数 -----------------------------------------------------------------*/ typedef struct { - const char *matcher; /*接收匹配串*/ - char *recvbuf; /*接收缓冲区*/ - unsigned short bufsize; /*最大接收长度*/ - unsigned int timeout; /*最大超时时间 */ + const char *matcher; /* 接收匹配串 */ + char *recvbuf; /* 接收缓冲区 */ + unsigned short bufsize; /* 缓冲区长度 */ + unsigned int timeout; /* 最大超时时间 */ }at_respond_t; -/*AT作业 ---------------------------------------------------------------------*/ -typedef struct at_work_env { - struct at_obj *at; +/** work context ------------------------------------------------------------*/ +/** + * @brief AT作业上下文(Work Context) 定义 + */ +typedef struct at_work_ctx { + //作业参数,由at_do_work接口传入 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; + //打印输出 + void (*printf)(struct at_work_ctx *self, const char *fmt, ...); + //响应等待 + at_return (*wait_resp)(struct at_work_ctx *self, const char *prefix, + unsigned int timeout); + //清除接收缓存 + void (*recvclr)(struct at_work_ctx *self); +}at_work_ctx_t; /*AT对象 ---------------------------------------------------------------------*/ typedef struct at_obj { - struct list_head node; - at_adapter_t adap; - 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; + at_adapter_t adap; /* 接口适配器*/ + at_work_ctx_t ctx; /* work context*/ + at_sem_t cmd_lock; /* 命令锁*/ + at_sem_t completed; /* 命令完成信号*/ + at_respond_t *resp; /* AT应答信息*/ + unsigned int resp_timer; /* 响应接收定时器*/ + unsigned int urc_timer; /* URC定时器 */ + at_return ret; /* 命令执行结果*/ //urc接收计数, 命令响应接收计数器 unsigned short urc_cnt, rcv_cnt; - unsigned char wait : 1; + unsigned char busy : 1; unsigned char suspend: 1; unsigned char dowork : 1; }at_obj_t; -typedef at_return (*at_work)(at_work_env_t *); +typedef at_return (*at_work)(at_work_ctx_t *); -void at_obj_create(at_obj_t *at, const at_adapter_t *adap); /*AT初始化*/ +void at_obj_create(at_obj_t *at, const at_adapter_t *adap); /* 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_suspend(at_obj_t *at); /* 挂起*/ -void at_resume(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, char separator); -at_return at_do_work(at_obj_t *at, at_work work, void *params);/*执行AT作业*/ +at_return at_do_work(at_obj_t *at, at_work work, void *params);/* 自定义AT作业*/ -void at_thread(void); /*AT线程*/ +void at_process(at_obj_t *at); /* AT接收处理*/ #endif