1.删除at_obj中的at_work_ctx_t域,减少内存使用

2.解决重复释放信号量导致命令出现等待超时的问题
This commit is contained in:
魔罗技术 2021-04-18 14:47:22 +08:00
parent 44cd306a95
commit 8f56581724
2 changed files with 142 additions and 138 deletions

110
at.c
View File

@ -1,4 +1,5 @@
/****************************************************************************** /**
******************************************************************************
* @brief AT命令通信管理(OS版本) * @brief AT命令通信管理(OS版本)
* *
* Copyright (c) 2020, <morro_luo@163.com> * Copyright (c) 2020, <morro_luo@163.com>
@ -11,7 +12,10 @@
* 2021-02-01 Morro URC回调中接收数据. * 2021-02-01 Morro URC回调中接收数据.
* 2021-02-05 Morro 1.struct at_obj, * 2021-02-05 Morro 1.struct at_obj,
* 2. at_obj_destroy接口 * 2. at_obj_destroy接口
******************************************************************************/ * 2021-03-21 Morro at_obj中的at_work_ctx_t域,使
* 2021-04-08 Morro
******************************************************************************
*/
#include "at.h" #include "at.h"
#include "comdef.h" #include "comdef.h"
#include <stdarg.h> #include <stdarg.h>
@ -19,24 +23,13 @@
#include <stdio.h> #include <stdio.h>
#include <stddef.h> #include <stddef.h>
//超时判断 /**
#define AT_IS_TIMEOUT(start, time) (at_get_ms() - (start) > (time))
/*
* @brief * @brief
*/ */
static void nop_dbg(const char *fmt, ...){} 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 * @brief
*/ */
static void put_string(at_obj_t *at, const char *s) static void put_string(at_obj_t *at, const char *s)
@ -46,7 +39,7 @@ static void put_string(at_obj_t *at, const char *s)
} }
/* /**
* @brief () * @brief ()
*/ */
static void put_line(at_obj_t *at, const char *s) static void put_line(at_obj_t *at, const char *s)
@ -63,43 +56,42 @@ static void at_print(struct at_work_ctx *e, const char *cmd, ...)
va_start(args, cmd); va_start(args, cmd);
char buf[MAX_AT_CMD_LEN]; char buf[MAX_AT_CMD_LEN];
vsnprintf(buf, sizeof(buf), cmd, args); vsnprintf(buf, sizeof(buf), cmd, args);
put_line(get_at_obj(e), buf); put_line(e->at, buf);
va_end(args); va_end(args);
} }
/* /**
* @brief * @brief
*/ */
static void recvbuf_clr(struct at_work_ctx *e) static void recvbuf_clr(struct at_work_ctx *e)
{ {
get_at_obj(e)->rcv_cnt = 0; e->at->rcv_cnt = 0;
} }
//等待AT命令响应 //等待AT命令响应
static at_return wait_resp(at_obj_t *at, at_respond_t *r) static at_return wait_resp(at_obj_t *at, at_respond_t *r)
{ {
at->resp = r;
at->ret = AT_RET_TIMEOUT; at->ret = AT_RET_TIMEOUT;
at->resp_timer = at_get_ms(); at->resp_timer = at_get_ms();
at->rcv_cnt = 0; //清空接收缓存 at->rcv_cnt = 0; //清空接收缓存
at->resp = r;
at_sem_wait(at->completed, r->timeout); at_sem_wait(at->completed, r->timeout);
at->adap.debug("<-\r\n%s\r\n", r->recvbuf); at->adap.debug("<-\r\n%s\r\n", r->recvbuf);
at->resp = NULL; at->resp = NULL;
return at->ret; return at->ret;
} }
/* /**
* @brief AT响应 * @brief
* @param[in] resp - ("OK",">") * @param[in] resp - ("OK",">")
* @param[in] timeout - * @param[in] timeout -
*/ */
at_return wait_resp_sync(struct at_work_ctx *e, const char *resp, at_return wait_recv(struct at_work_ctx *e, const char *resp,
unsigned int timeout) unsigned int timeout)
{ {
char buf[64]; char buf[64];
int cnt = 0, len; int cnt = 0, len;
at_obj_t *at = get_at_obj(e); at_obj_t *at = e->at;
at_return ret = AT_RET_TIMEOUT; at_return ret = AT_RET_TIMEOUT;
unsigned int timer = at_get_ms(); unsigned int timer = at_get_ms();
while (at_get_ms() - timer < timeout) { while (at_get_ms() - timer < timeout) {
@ -119,31 +111,24 @@ at_return wait_resp_sync(struct at_work_ctx *e, const char *resp,
return ret; return ret;
} }
/**
/*
* @brief AT控制器 * @brief AT控制器
* @param[in] adap - AT接口适配器
*/ */
void at_obj_create(at_obj_t *at, const at_adapter_t *adap) void at_obj_init(at_obj_t *at, const at_adapter_t *adap)
{ {
at_work_ctx_t *ctx;
at->adap = *adap; at->adap = *adap;
at->rcv_cnt = 0; at->rcv_cnt = 0;
at->cmd_lock = ril_sem_new(1); at->cmd_lock = ril_sem_new(1);
at->completed = ril_sem_new(0); 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) if (at->adap.debug == NULL)
at->adap.debug = nop_dbg; at->adap.debug = nop_dbg;
} }
/* /**
* @brief * @brief
* @param[in] fmt - * @param[in] fmt -
* @param[in] r - ,NULL, OK表示成功,5s * @param[in] r - ,NULL, OK表示成功,5s
@ -172,14 +157,17 @@ at_return at_do_cmd(at_obj_t *at, at_respond_t *r, const char *cmd)
return ret; return ret;
} }
/* /**
* @brief AT作业 * @brief AT作业
* @param[in] urc * @param[in] at - AT控制器
* @return none * @param[in] work - ( - int (*)(at_work_ctx_t *))
* @param[in] params-
* @return work的返回值
*/ */
at_return at_do_work(at_obj_t *at, at_work work, void *params) int at_do_work(at_obj_t *at, at_work work, void *params)
{ {
at_return ret; at_work_ctx_t ctx;
int ret;
if (!at_sem_wait(at->cmd_lock, 150 * 1000)) { if (!at_sem_wait(at->cmd_lock, 150 * 1000)) {
return AT_RET_TIMEOUT; return AT_RET_TIMEOUT;
} }
@ -187,17 +175,24 @@ at_return at_do_work(at_obj_t *at, at_work work, void *params)
while (at->urc_cnt) { //等待URC处理完成 while (at->urc_cnt) { //等待URC处理完成
at_delay(1); at_delay(1);
} }
at->ctx.params = params; //构造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.wait_resp = wait_recv;
ctx.at = at;
at->dowork = true; at->dowork = true;
at->rcv_cnt = 0; at->rcv_cnt = 0;
ret = work(&at->ctx); ret = work(&ctx);
at->dowork = false; at->dowork = false;
at_sem_post(at->cmd_lock); at_sem_post(at->cmd_lock);
at->busy = false; at->busy = false;
return ret; return ret;
} }
/* /**
* @brief * @brief
* @param[in] recvbuf - * @param[in] recvbuf -
* @param[out] lines - * @param[out] lines -
@ -222,7 +217,7 @@ int at_split_respond_lines(char *recvbuf, char *lines[], int count, char separat
return i; return i;
} }
/* /**
* @brief urc * @brief urc
* @param[in] urcline - URC行 * @param[in] urcline - URC行
* @return true - , false - URC * @return true - , false - URC
@ -257,7 +252,7 @@ static bool urc_handler_entry(at_obj_t *at, char *urcline, unsigned int size)
return false; return false;
} }
/* /**
* @brief urc * @brief urc
* @param[in] ch - * @param[in] ch -
* @return none * @return none
@ -269,9 +264,10 @@ static void urc_recv_process(at_obj_t *at, const char *buf, unsigned int size)
urc_buf = at->adap.urc_buf; urc_buf = at->adap.urc_buf;
//接收超时处理,默认MAX_URC_RECV_TIMEOUT //接收超时处理,默认MAX_URC_RECV_TIMEOUT
if (at->urc_cnt > 0 && AT_IS_TIMEOUT(at->urc_timer, MAX_URC_RECV_TIMEOUT)) { if (at->urc_cnt > 0 && at_istimeout(at->urc_timer, MAX_URC_RECV_TIMEOUT)) {
urc_buf[at->urc_cnt] = '\0'; urc_buf[at->urc_cnt] = '\0';
at->urc_cnt = 0; at->urc_cnt = 0;
if (at->urc_cnt > 2)
at->adap.debug("urc recv timeout=>%s\r\n", urc_buf); at->adap.debug("urc recv timeout=>%s\r\n", urc_buf);
} }
@ -297,7 +293,7 @@ static void urc_recv_process(at_obj_t *at, const char *buf, unsigned int size)
} }
} }
/* /**
* @brief * @brief
* @return none * @return none
*/ */
@ -307,7 +303,7 @@ static void resp_notification(at_obj_t *at, at_return ret)
at_sem_post(at->completed); at_sem_post(at->completed);
} }
/* /**
* @brief * @brief
* @param[in] buf - * @param[in] buf -
* @param[in] size - * @param[in] size -
@ -337,28 +333,30 @@ static void resp_recv_process(at_obj_t *at, const char *buf, unsigned int size)
if (strstr(rcv_buf, resp->matcher)) { //接收匹配 if (strstr(rcv_buf, resp->matcher)) { //接收匹配
resp_notification(at, AT_RET_OK); resp_notification(at, AT_RET_OK);
return;
} else if (strstr(rcv_buf, "ERROR")) { } else if (strstr(rcv_buf, "ERROR")) {
resp_notification(at, AT_RET_ERROR); resp_notification(at, AT_RET_ERROR);
return;
} }
} }
if (AT_IS_TIMEOUT(at->resp_timer, resp->timeout)) //接收超时 if (at_istimeout(at->resp_timer, resp->timeout)) //接收超时
resp_notification(at, AT_RET_TIMEOUT); resp_notification(at, AT_RET_TIMEOUT);
else if (at->suspend) //强制终止 else if (at->suspend) //强制终止
resp_notification(at, AT_RET_ABORT); resp_notification(at, AT_RET_ABORT);
} }
/* /**
* @brief AT忙判断 * @brief AT忙判断
* @return true - AT指令或者任务正在执行中 * @return true - AT指令或者任务正在执行中
*/ */
bool at_obj_busy(at_obj_t *at) bool at_obj_busy(at_obj_t *at)
{ {
return !at->busy && AT_IS_TIMEOUT(at->urc_timer, 2000); return !at->busy && at_istimeout(at->urc_timer, 2000);
} }
/* /**
* @brief AT作业 * @brief AT作业
* @return none * @return none
*/ */
@ -367,7 +365,7 @@ void at_suspend(at_obj_t *at)
at->suspend = 1; at->suspend = 1;
} }
/* /**
* @brief AT作业 * @brief AT作业
* @return none * @return none
*/ */
@ -376,7 +374,7 @@ void at_resume(at_obj_t *at)
at->suspend = 0; at->suspend = 0;
} }
/* /**
* @brief AT处理 * @brief AT处理
* @return none * @return none
*/ */

26
at.h
View File

@ -11,6 +11,8 @@
* 2021-02-01 Morro URC回调中接收数据. * 2021-02-01 Morro URC回调中接收数据.
* 2021-02-05 Morro 1.struct at_obj, * 2021-02-05 Morro 1.struct at_obj,
* 2. at_obj_destroy接口 * 2. at_obj_destroy接口
* 2021-03-21 Morro at_obj中的at_work_ctx_t域,使
* 2021-04-08 Morro
******************************************************************************/ ******************************************************************************/
#ifndef _AT_H_ #ifndef _AT_H_
@ -102,14 +104,23 @@ typedef struct {
* @brief AT作业上下文(Work Context) * @brief AT作业上下文(Work Context)
*/ */
typedef struct at_work_ctx { typedef struct at_work_ctx {
struct at_obj *at;
//作业参数,由at_do_work接口传入 //作业参数,由at_do_work接口传入
void *params; void *params;
unsigned int (*write)(const void *buf, unsigned int len); unsigned int (*write)(const void *buf, unsigned int len);
unsigned int (*read)(void *buf, unsigned int len); unsigned int (*read)(void *buf, unsigned int len);
//打印输出 /**
* @brief
*/
void (*printf)(struct at_work_ctx *self, const char *fmt, ...); void (*printf)(struct at_work_ctx *self, const char *fmt, ...);
//响应等待 /*
* @brief
* @param[in] prefix - ("OK",">")
* @param[in] timeout -
*/
at_return (*wait_resp)(struct at_work_ctx *self, const char *prefix, at_return (*wait_resp)(struct at_work_ctx *self, const char *prefix,
unsigned int timeout); unsigned int timeout);
//清除接收缓存 //清除接收缓存
@ -119,25 +130,21 @@ typedef struct at_work_ctx {
/*AT对象 ---------------------------------------------------------------------*/ /*AT对象 ---------------------------------------------------------------------*/
typedef struct at_obj { typedef struct at_obj {
at_adapter_t adap; /* 接口适配器*/ at_adapter_t adap; /* 接口适配器*/
at_work_ctx_t ctx; /* work context*/
at_sem_t cmd_lock; /* 命令锁*/ at_sem_t cmd_lock; /* 命令锁*/
at_sem_t completed; /* 命令完成信号*/ at_sem_t completed; /* 命令完成信号*/
at_respond_t *resp; /* AT应答信息*/ at_respond_t *resp; /* AT应答信息*/
unsigned int resp_timer; /* 响应接收定时器*/ unsigned int resp_timer; /* 响应接收定时器*/
unsigned int urc_timer; /* URC定时器 */ unsigned int urc_timer; /* URC定时器 */
at_return ret; /* 命令执行结果*/ at_return ret; /* 命令执行结果*/
//urc接收计数, 命令响应接收计数器
unsigned short urc_cnt, rcv_cnt; unsigned short urc_cnt, rcv_cnt;
unsigned char busy : 1; unsigned char busy : 1;
unsigned char suspend: 1; unsigned char suspend: 1;
unsigned char dowork : 1; unsigned char dowork : 1;
}at_obj_t; }at_obj_t;
typedef at_return (*at_work)(at_work_ctx_t *); typedef int (*at_work)(at_work_ctx_t *);
void at_obj_create(at_obj_t *at, const at_adapter_t *adap); /* AT初始化*/ void at_obj_init(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); bool at_obj_busy(at_obj_t *at);
@ -147,10 +154,9 @@ void at_resume(at_obj_t *at); /*
at_return at_do_cmd(at_obj_t *at, at_respond_t *r, const char *cmd); 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); 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作业*/ int at_do_work(at_obj_t *at, at_work work, void *params); /* 自定义AT作业*/
void at_process(at_obj_t *at); /* AT接收处理*/ void at_process(at_obj_t *at); /* AT接收处理*/