mirror of
https://gitee.com/moluo-tech/AT-Command
synced 2025-08-12 13:12:52 +00:00
增加接收锁,解决执行at_do_work时urc部分数据丢失问题
This commit is contained in:
parent
76d13e373b
commit
321be4256f
106
at.c
106
at.c
@ -15,6 +15,7 @@
|
||||
* 2021-03-21 Morro 删除at_obj中的at_work_ctx_t域,减少内存使用
|
||||
* 2021-04-08 Morro 解决重复释放信号量导致命令出现等待超时的问题
|
||||
* 2021-05-15 Morro 优化URC匹配程序
|
||||
* 2021-07-20 Morro 增加锁,解决执行at_do_work时urc部分数据丢失问题
|
||||
******************************************************************************
|
||||
*/
|
||||
#include "at.h"
|
||||
@ -24,6 +25,10 @@
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define MAX_AT_LOCK_TIME 60 * 1000 //AT命令锁定时间
|
||||
|
||||
static void urc_recv_process(at_obj_t *at, const char *buf, unsigned int size);
|
||||
|
||||
/**
|
||||
* @brief 默认调试接口
|
||||
*/
|
||||
@ -39,7 +44,6 @@ static void put_string(at_obj_t *at, const char *s)
|
||||
at->adap.write(s++, 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 输出字符串(带换行)
|
||||
*/
|
||||
@ -50,8 +54,28 @@ static void put_line(at_obj_t *at, const char *s)
|
||||
at->adap.debug("->\r\n%s\r\n", s);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 作业读操作
|
||||
*/
|
||||
static unsigned int at_work_read(struct at_work_ctx *e, void *buf, unsigned int len)
|
||||
{
|
||||
at_obj_t *at = e->at;
|
||||
len = at->adap.read(buf, len);
|
||||
urc_recv_process(at, buf, len); //递交到URC进行处理
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 作业写操作
|
||||
*/
|
||||
static unsigned int at_work_write(struct at_work_ctx *e, const void *buf, unsigned int len)
|
||||
{
|
||||
return e->at->adap.write(buf, len);
|
||||
}
|
||||
|
||||
//打印输出
|
||||
static void at_print(struct at_work_ctx *e, const char *cmd, ...)
|
||||
static void at_work_print(struct at_work_ctx *e, const char *cmd, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, cmd);
|
||||
@ -61,14 +85,6 @@ static void at_print(struct at_work_ctx *e, const char *cmd, ...)
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 清除数据缓冲区
|
||||
*/
|
||||
static void recvbuf_clr(struct at_work_ctx *e)
|
||||
{
|
||||
e->at->rcv_cnt = 0;
|
||||
}
|
||||
|
||||
//等待AT命令响应
|
||||
static at_return wait_resp(at_obj_t *at, at_respond_t *r)
|
||||
{
|
||||
@ -87,8 +103,7 @@ static at_return wait_resp(at_obj_t *at, at_respond_t *r)
|
||||
* @param[in] resp - 期待待接收串(如"OK",">")
|
||||
* @param[in] timeout - 等待超时时间
|
||||
*/
|
||||
at_return wait_recv(struct at_work_ctx *e, const char *resp,
|
||||
unsigned int timeout)
|
||||
at_return wait_recv(struct at_work_ctx *e, const char *resp, unsigned int timeout)
|
||||
{
|
||||
char buf[64];
|
||||
int cnt = 0, len;
|
||||
@ -96,17 +111,19 @@ at_return wait_recv(struct at_work_ctx *e, const char *resp,
|
||||
at_return ret = AT_RET_TIMEOUT;
|
||||
unsigned int timer = at_get_ms();
|
||||
while (at_get_ms() - timer < timeout) {
|
||||
len = at->adap.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);
|
||||
len = e->read(e, &buf[cnt], sizeof(buf) - cnt);
|
||||
if (len > 0) {
|
||||
cnt += len;
|
||||
buf[cnt] = '\0';
|
||||
if (strstr(buf, resp)) {
|
||||
ret = AT_RET_OK;
|
||||
break;
|
||||
} else if (strstr(buf, "ERROR")) {
|
||||
ret = AT_RET_ERROR;
|
||||
break;
|
||||
}
|
||||
} else
|
||||
at_delay(1);
|
||||
}
|
||||
at->adap.debug("%s\r\n", buf);
|
||||
return ret;
|
||||
@ -120,9 +137,9 @@ void at_obj_init(at_obj_t *at, const at_adapter_t *adap)
|
||||
{
|
||||
at->adap = *adap;
|
||||
at->rcv_cnt = 0;
|
||||
|
||||
at->cmd_lock = ril_sem_new(1);
|
||||
at->completed = ril_sem_new(0);
|
||||
at->send_lock = at_sem_new(1);
|
||||
at->recv_lock = at_sem_new(1);
|
||||
at->completed = at_sem_new(0);
|
||||
at->urc_item = NULL;
|
||||
if (at->adap.debug == NULL)
|
||||
at->adap.debug = nop_dbg;
|
||||
@ -143,7 +160,7 @@ at_return at_do_cmd(at_obj_t *at, at_respond_t *r, const char *cmd)
|
||||
if (r == NULL) {
|
||||
r = &default_resp; //默认响应
|
||||
}
|
||||
if (!at_sem_wait(at->cmd_lock, r->timeout)) {
|
||||
if (!at_sem_wait(at->send_lock, r->timeout)) {
|
||||
return AT_RET_TIMEOUT;
|
||||
}
|
||||
at->busy = true;
|
||||
@ -153,7 +170,7 @@ at_return at_do_cmd(at_obj_t *at, at_respond_t *r, const char *cmd)
|
||||
}
|
||||
put_line(at, cmd);
|
||||
ret = wait_resp(at, r);
|
||||
at_sem_post(at->cmd_lock);
|
||||
at_sem_post(at->send_lock);
|
||||
at->busy = false;
|
||||
return ret;
|
||||
}
|
||||
@ -169,26 +186,25 @@ int at_do_work(at_obj_t *at, at_work work, void *params)
|
||||
{
|
||||
at_work_ctx_t ctx;
|
||||
int ret;
|
||||
if (!at_sem_wait(at->cmd_lock, 150 * 1000)) {
|
||||
if (!at_sem_wait(at->send_lock, MAX_AT_LOCK_TIME)) {
|
||||
return AT_RET_TIMEOUT;
|
||||
}
|
||||
if (!at_sem_wait(at->recv_lock, MAX_AT_LOCK_TIME))
|
||||
return AT_RET_TIMEOUT;
|
||||
|
||||
at->busy = true;
|
||||
while (at->urc_cnt) { //等待URC处理完成
|
||||
at_delay(1);
|
||||
}
|
||||
//构造at_work_ctx_t
|
||||
ctx.params = params;
|
||||
ctx.printf = at_print;
|
||||
ctx.recvclr = recvbuf_clr;
|
||||
ctx.read = at->adap.read;
|
||||
ctx.write = at->adap.write;
|
||||
ctx.printf = at_work_print;
|
||||
ctx.read = at_work_read;
|
||||
ctx.write = at_work_write;
|
||||
ctx.wait_resp = wait_recv;
|
||||
ctx.at = at;
|
||||
at->dowork = true;
|
||||
|
||||
at->rcv_cnt = 0;
|
||||
ret = work(&ctx);
|
||||
at->dowork = false;
|
||||
at_sem_post(at->cmd_lock);
|
||||
at_sem_post(at->recv_lock);
|
||||
at_sem_post(at->send_lock);
|
||||
at->busy = false;
|
||||
return ret;
|
||||
}
|
||||
@ -381,13 +397,15 @@ void at_resume(at_obj_t *at)
|
||||
*/
|
||||
void at_process(at_obj_t *at)
|
||||
{
|
||||
char c;
|
||||
char buf[16];
|
||||
unsigned int len;
|
||||
if (at->dowork) /* 自定义命令处理 */
|
||||
if (!at_sem_wait(at->recv_lock, MAX_AT_LOCK_TIME))
|
||||
return;
|
||||
do {
|
||||
len = at->adap.read(&c, 1);
|
||||
urc_recv_process(at, &c,len);
|
||||
resp_recv_process(at, &c, len);
|
||||
len = at->adap.read(buf, sizeof(buf));
|
||||
urc_recv_process(at, buf,len);
|
||||
resp_recv_process(at, buf, len);
|
||||
} while (len);
|
||||
|
||||
at_sem_post(at->recv_lock);
|
||||
}
|
||||
|
62
at.h
62
at.h
@ -14,6 +14,7 @@
|
||||
* 2021-03-21 Morro 删除at_obj中的at_work_ctx_t域,减少内存使用
|
||||
* 2021-04-08 Morro 解决重复释放信号量导致命令出现等待超时的问题
|
||||
* 2021-05-15 Morro 优化URC匹配程序
|
||||
* 2021-07-20 Morro 增加接收锁,解决执行at_do_work时urc部分数据丢失问题
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _AT_H_
|
||||
@ -74,31 +75,52 @@ typedef struct {
|
||||
void (*handler)(at_urc_ctx_t *ctx);
|
||||
}urc_item_t;
|
||||
|
||||
/**AT接口适配器 --------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief AT接口适配器(用于初始化AT控制器)
|
||||
*/
|
||||
typedef struct {
|
||||
//数据写操作
|
||||
|
||||
/**
|
||||
* @brief 数据写接口
|
||||
*/
|
||||
unsigned int (*write)(const void *buf, unsigned int len);
|
||||
//数据读操作
|
||||
|
||||
/**
|
||||
* @brief 数据读接口
|
||||
*/
|
||||
unsigned int (*read)(void *buf, unsigned int len);
|
||||
//调试打印输出,如果不需要则填NULL
|
||||
/**
|
||||
* @brief 调试打印输出接口,如果不需要则填NULL
|
||||
*/
|
||||
void (*debug)(const char *fmt, ...);
|
||||
//utc 处理函数表,如果不需要则填NULL
|
||||
|
||||
/**
|
||||
* @brief urc 处理函数表,如果不需要则填NULL
|
||||
*/
|
||||
urc_item_t *utc_tbl;
|
||||
//urc接收缓冲区,如果不需要则填NULL
|
||||
/**
|
||||
* @brief urc接收缓冲区,如果不需要则填NULL
|
||||
*/
|
||||
char *urc_buf;
|
||||
//urc表项个数,如果不需要则填0
|
||||
/**
|
||||
* @brief utc_tbl项个数,如果不需要则填0
|
||||
*/
|
||||
unsigned short urc_tbl_count;
|
||||
//urc缓冲区大小,如果不需要则填0
|
||||
/**
|
||||
* @brief urc缓冲区大小,如果不需要则填0
|
||||
*/
|
||||
unsigned short urc_bufsize;
|
||||
}at_adapter_t;
|
||||
|
||||
/*AT响应参数 -----------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief AT命令响应参数
|
||||
*/
|
||||
typedef struct {
|
||||
const char *matcher; /* 接收匹配串 */
|
||||
char *recvbuf; /* 接收缓冲区 */
|
||||
unsigned short bufsize; /* 缓冲区长度 */
|
||||
unsigned int timeout; /* 最大超时时间 */
|
||||
}at_respond_t;
|
||||
} at_respond_t;
|
||||
|
||||
/** work context ------------------------------------------------------------*/
|
||||
/**
|
||||
@ -106,12 +128,17 @@ typedef struct {
|
||||
*/
|
||||
typedef struct at_work_ctx {
|
||||
struct at_obj *at;
|
||||
|
||||
//作业参数,由at_do_work接口传入
|
||||
void *params;
|
||||
|
||||
unsigned int (*write)(const void *buf, unsigned int len);
|
||||
|
||||
unsigned int (*read)(void *buf, unsigned int len);
|
||||
/**
|
||||
* @brief 数据写操作
|
||||
*/
|
||||
unsigned int (*write)(struct at_work_ctx *self, const void *buf, unsigned int len);
|
||||
/**
|
||||
* @brief 数据读操作
|
||||
*/
|
||||
unsigned int (*read)(struct at_work_ctx *self, void *buf, unsigned int len);
|
||||
|
||||
/**
|
||||
* @brief 格式化打印输出
|
||||
@ -124,14 +151,14 @@ typedef struct at_work_ctx {
|
||||
*/
|
||||
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 {
|
||||
at_adapter_t adap; /* 接口适配器*/
|
||||
at_sem_t cmd_lock; /* 命令锁*/
|
||||
at_sem_t send_lock; /* 发送锁*/
|
||||
at_sem_t recv_lock; /* 接收锁*/
|
||||
at_sem_t completed; /* 命令完成信号*/
|
||||
at_respond_t *resp; /* AT应答信息*/
|
||||
const urc_item_t *urc_item; /* 当前URC项*/
|
||||
@ -160,6 +187,7 @@ int at_split_respond_lines(char *recvbuf, char *lines[], int count, char separat
|
||||
|
||||
int at_do_work(at_obj_t *at, at_work work, void *params); /* 自定义AT作业*/
|
||||
|
||||
|
||||
void at_process(at_obj_t *at); /* AT接收处理*/
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user