mirror of
https://github.com/Ai-Thinker-Open/Ai-Thinker-Open_RTL8710BX_ALIOS_SDK.git
synced 2026-07-03 01:25:38 +00:00
rel_1.6.0 init
This commit is contained in:
commit
27b3e2883d
19359 changed files with 8093121 additions and 0 deletions
9
Living_SDK/framework/atparser/README
Normal file
9
Living_SDK/framework/atparser/README
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
The atparser component is used for AT command communication.
|
||||
|
||||
To use this component:
|
||||
1. Include atparser.h header file;
|
||||
2. Declare the atparser module in makefile;
|
||||
3. Configure an AT UART;
|
||||
4. Initialize atparser (at.init API);
|
||||
5. atparser APIS: at_send, at_recv, at_send_raw, etc.
|
||||
6. Please refer to example/atapp for example on how to use atparser component.
|
||||
779
Living_SDK/framework/atparser/atparser.c
Normal file
779
Living_SDK/framework/atparser/atparser.c
Normal file
|
|
@ -0,0 +1,779 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <aos/log.h>
|
||||
#include "atparser.h"
|
||||
|
||||
#define MODULE_NAME "atparser"
|
||||
#define TASK_DEFAULT_WAIT_TIME 5000
|
||||
|
||||
static uint8_t inited = 0;
|
||||
static uart_dev_t at_uart;
|
||||
|
||||
static void at_worker(void *arg);
|
||||
|
||||
static void at_uart_configure(uart_dev_t *u)
|
||||
{
|
||||
u->port = AT_UART_PORT;
|
||||
u->config.baud_rate = AT_UART_BAUDRATE;
|
||||
u->config.data_width = AT_UART_DATA_WIDTH;
|
||||
u->config.parity = AT_UART_PARITY;
|
||||
u->config.stop_bits = AT_UART_STOP_BITS;
|
||||
u->config.flow_control = AT_UART_FLOW_CONTROL;
|
||||
u->config.mode = AT_UART_MODE;
|
||||
}
|
||||
|
||||
static int at_init_uart()
|
||||
{
|
||||
at_uart_configure(&at_uart);
|
||||
|
||||
if (hal_uart_init(&at_uart) != 0) {
|
||||
return -1;
|
||||
}
|
||||
at._pstuart = &at_uart;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void at_set_timeout(int timeout)
|
||||
{
|
||||
at._timeout = timeout;
|
||||
}
|
||||
|
||||
static void at_set_recv_delimiter(const char *recv_prefix, const char *recv_success_postfix,
|
||||
const char *recv_fail_postfix)
|
||||
{
|
||||
at._default_recv_prefix = (char *)recv_prefix;
|
||||
at._default_recv_success_postfix = (char *)recv_success_postfix;
|
||||
at._default_recv_fail_postfix = (char *)recv_fail_postfix;
|
||||
at._recv_prefix_len = strlen(recv_prefix);
|
||||
at._recv_success_postfix_len = strlen(recv_success_postfix);
|
||||
at._recv_fail_postfix_len = strlen(recv_fail_postfix);
|
||||
}
|
||||
|
||||
static void at_set_send_delimiter(const char *delimiter)
|
||||
{
|
||||
at._send_delimiter = (char *)delimiter;
|
||||
at._send_delim_size = strlen(delimiter);
|
||||
}
|
||||
|
||||
static int at_init_task_mutex()
|
||||
{
|
||||
if (0 != aos_mutex_new(&at.task_mutex)) {
|
||||
LOGE(MODULE_NAME, "Creating task mutex failed\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void at_uinit_task_mutex()
|
||||
{
|
||||
if (aos_mutex_is_valid(&at.task_mutex)) {
|
||||
aos_mutex_free(&at.task_mutex);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static int at_init_at_mutex()
|
||||
{
|
||||
if (0 != aos_mutex_new(&at.at_mutex)) {
|
||||
LOGE(MODULE_NAME, "Creating at mutex failed\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void at_uinit_at_mutex()
|
||||
{
|
||||
if (aos_mutex_is_valid(&at.at_mutex)) {
|
||||
aos_mutex_free(&at.at_mutex);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static int at_worker_uart_send_mutex_init()
|
||||
{
|
||||
if (0 != aos_mutex_new(&at.at_uart_send_mutex)) {
|
||||
LOGE(MODULE_NAME, "Creating at worker sem failed\r\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void at_worker_uart_send_mutex_uinit()
|
||||
{
|
||||
if (aos_mutex_is_valid(&at.at_uart_send_mutex)) {
|
||||
aos_mutex_free(&at.at_uart_send_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static int at_init(const char *recv_prefix, const char *recv_success_postfix,
|
||||
const char *recv_fail_postfix, const char *send_delimiter, int timeout)
|
||||
{
|
||||
if (!recv_prefix || !recv_success_postfix || !recv_fail_postfix
|
||||
|| !send_delimiter || (timeout < 0)) {
|
||||
LOGE(MODULE_NAME, "%s: invalid argument", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (inited == 1) {
|
||||
LOGI(MODULE_NAME, "have already inited ,it will init again\r\n");
|
||||
inited = 0;
|
||||
}
|
||||
|
||||
if (at_init_uart() != 0) {
|
||||
LOGE(MODULE_NAME, "at uart init fail \r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(at._oobs, 0, sizeof(oob_t) * OOB_MAX);
|
||||
|
||||
at_set_timeout(timeout);
|
||||
at_set_recv_delimiter(recv_prefix, recv_success_postfix, recv_fail_postfix);
|
||||
at_set_send_delimiter(send_delimiter);
|
||||
|
||||
LOGD(MODULE_NAME, "at worker rcv prefix is %s success postfix is %s fail postfix is %s \r\n", recv_prefix,
|
||||
recv_success_postfix, recv_fail_postfix);
|
||||
if (at_init_at_mutex() != 0) {
|
||||
LOGE(MODULE_NAME, "at uart mutex init fail \r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (at_init_task_mutex() != 0) {
|
||||
at_uinit_at_mutex();
|
||||
LOGE(MODULE_NAME, "at mutex init fail \r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
slist_init(&at.task_l);
|
||||
|
||||
if (at_worker_uart_send_mutex_init() != 0) {
|
||||
at_uinit_at_mutex();
|
||||
at_uinit_task_mutex();
|
||||
LOGE(MODULE_NAME, "fail to creat at worker sem\r\n");
|
||||
}
|
||||
|
||||
if (aos_task_new("at_worker", at_worker, NULL, 1024)) {
|
||||
at_uinit_at_mutex();
|
||||
at_uinit_task_mutex();
|
||||
at_worker_uart_send_mutex_uinit();
|
||||
LOGE(MODULE_NAME, "fail to creat at task\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
inited = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void at_set_mode(at_mode_t m)
|
||||
{
|
||||
if (m == at._mode) {
|
||||
return ;
|
||||
}
|
||||
/*at operate mode changed, it should wait the uart read operate finished in the origin operate mode*/
|
||||
aos_mutex_lock(&at.at_mutex, AOS_WAIT_FOREVER);
|
||||
at._mode = m;
|
||||
aos_mutex_unlock(&at.at_mutex);
|
||||
}
|
||||
|
||||
static int at_putc(char c)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (inited == 0) {
|
||||
LOGE(MODULE_NAME, "at have not init yet\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (at._mode != ASYN) {
|
||||
LOGE(MODULE_NAME, "AT mode is normal, can no use at_putc \r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOGD(MODULE_NAME, "uart sending %c(0x%02x)\r\n", c, c);
|
||||
aos_mutex_lock(&at.at_uart_send_mutex, AOS_WAIT_FOREVER);
|
||||
ret = hal_uart_send(at._pstuart, (void *)&c, 1, at._timeout);
|
||||
aos_mutex_unlock(&at.at_uart_send_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int at_getc(char *c)
|
||||
{
|
||||
char data;
|
||||
uint32_t recv_size = 0;
|
||||
|
||||
if (NULL == c) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (inited == 0) {
|
||||
LOGE(MODULE_NAME, "at have not init yet\r\n");
|
||||
return -1;
|
||||
}
|
||||
#if 1
|
||||
if (at._mode != ASYN) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
aos_mutex_lock(&at.at_mutex, AOS_WAIT_FOREVER);
|
||||
if (hal_uart_recv_II(at._pstuart, (void *)&data, 1,
|
||||
&recv_size, at._timeout) != 0) {
|
||||
return -1;
|
||||
}
|
||||
aos_mutex_unlock(&at.at_mutex);
|
||||
|
||||
if (recv_size == 1) {
|
||||
*c = data;
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int at_write(const char *data, int size)
|
||||
{
|
||||
if (inited == 0) {
|
||||
LOGE(MODULE_NAME, "at have not init yet\r\n");
|
||||
return -1;
|
||||
}
|
||||
#if 0
|
||||
if (at._mode != NORMAL) {
|
||||
LOGE(MODULE_NAME, "AT mode is aysn, can no use at_write \r\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
aos_mutex_lock(&at.at_uart_send_mutex, AOS_WAIT_FOREVER);
|
||||
if (hal_uart_send(at._pstuart, (void *)data, size, AOS_WAIT_FOREVER) != 0) {
|
||||
return -1;
|
||||
}
|
||||
aos_mutex_unlock(&at.at_uart_send_mutex);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static int at_read(char *data, int size)
|
||||
{
|
||||
uint32_t recv_size, total_read = 0;
|
||||
|
||||
if (inited == 0) {
|
||||
LOGE(MODULE_NAME, "at have not init yet\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (at._mode != NORMAL) {
|
||||
LOGE(MODULE_NAME, "AT mode is aysn, can no use at_read \r\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
aos_mutex_lock(&at.at_mutex, AOS_WAIT_FOREVER);
|
||||
while (total_read < size) {
|
||||
if (hal_uart_recv_II(at._pstuart, (void *)(data + total_read), size - total_read,
|
||||
&recv_size, at._timeout) != 0) {
|
||||
LOGE(MODULE_NAME, "at_read failed on uart_recv.");
|
||||
return -1;
|
||||
}
|
||||
if (recv_size <= 0) {
|
||||
continue;
|
||||
}
|
||||
total_read += recv_size;
|
||||
if (total_read >= size) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
aos_mutex_unlock(&at.at_mutex);
|
||||
|
||||
return recv_size;
|
||||
}
|
||||
|
||||
static int at_worker_task_add(at_task_t *tsk)
|
||||
{
|
||||
if (NULL == tsk) {
|
||||
LOGE(MODULE_NAME, "invalid input %s \r\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
aos_mutex_lock(&at.task_mutex, AOS_WAIT_FOREVER);
|
||||
slist_add_tail(&tsk->next, &at.task_l);
|
||||
aos_mutex_unlock(&at.task_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int at_worker_task_del(at_task_t *tsk)
|
||||
{
|
||||
if (NULL == tsk) {
|
||||
LOGE(MODULE_NAME, "invalid input %s \r\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
aos_mutex_lock(&at.task_mutex, AOS_WAIT_FOREVER);
|
||||
slist_del(&tsk->next, &at.task_l);
|
||||
aos_mutex_unlock(&at.task_mutex);
|
||||
if (aos_sem_is_valid(&tsk->smpr)) {
|
||||
aos_sem_free(&tsk->smpr);
|
||||
}
|
||||
if (tsk) {
|
||||
aos_free(tsk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int at_send_raw_self_define_respone_formate_internal(const char *command, uint32_t cmdlen, char *rsp,
|
||||
uint32_t rsplen,
|
||||
char *rsp_prefix, char *rsp_success_postfix, char *rsp_fail_postfix)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (inited == 0) {
|
||||
LOGE(MODULE_NAME, "at have not init yet\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (at._mode != ASYN) {
|
||||
LOGE(MODULE_NAME, "Operation not supported in non asyn mode \r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (NULL == command || NULL == rsp || 0 == rsplen) {
|
||||
LOGE(MODULE_NAME, "%s invalid input \r\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
at_task_t *tsk = (at_task_t *)aos_malloc(sizeof(at_task_t));
|
||||
if (NULL == tsk) {
|
||||
LOGE(MODULE_NAME, "tsk buffer allocating failed");
|
||||
return -1;
|
||||
}
|
||||
memset(tsk, 0, sizeof(at_task_t));
|
||||
|
||||
if ((ret = aos_sem_new(&tsk->smpr, 0)) != 0) {
|
||||
LOGE(MODULE_NAME, "failed to allocate semaphore");
|
||||
goto end;
|
||||
}
|
||||
|
||||
LOGD(MODULE_NAME, "at task created: %d, smpr: %d",
|
||||
(uint32_t)tsk, (uint32_t)&tsk->smpr);
|
||||
|
||||
if (NULL != rsp_prefix) {
|
||||
tsk->rsp_prefix = rsp_prefix;
|
||||
tsk->rsp_prefix_len = strlen(rsp_prefix);
|
||||
}
|
||||
|
||||
if (NULL != rsp_success_postfix) {
|
||||
tsk->rsp_success_postfix = rsp_success_postfix;
|
||||
tsk->rsp_success_postfix_len = strlen(rsp_success_postfix);
|
||||
}
|
||||
|
||||
if (NULL != rsp_fail_postfix) {
|
||||
tsk->rsp_fail_postfix = rsp_fail_postfix;
|
||||
tsk->rsp_fail_postfix_len = strlen(rsp_fail_postfix);
|
||||
}
|
||||
|
||||
tsk->command = (char *)command;
|
||||
tsk->rsp = rsp;
|
||||
tsk->rsp_len = rsplen;
|
||||
|
||||
at_worker_task_add(tsk);
|
||||
|
||||
// uart operation should be inside mutex lock
|
||||
if ((ret = hal_uart_send(at._pstuart, (void *)command,
|
||||
cmdlen, at._timeout)) != 0) {
|
||||
LOGE(MODULE_NAME, "uart send command failed");
|
||||
goto end;
|
||||
}
|
||||
LOGD(MODULE_NAME, "Sending command %s", command);
|
||||
|
||||
if ((ret = hal_uart_send(at._pstuart, (void *)at._send_delimiter,
|
||||
strlen(at._send_delimiter), at._timeout)) != 0) {
|
||||
LOGE(MODULE_NAME, "uart send delimiter failed");
|
||||
goto end;
|
||||
}
|
||||
LOGD(MODULE_NAME, "Sending delimiter %s", at._send_delimiter);
|
||||
|
||||
if ((ret = aos_sem_wait(&tsk->smpr, TASK_DEFAULT_WAIT_TIME)) != 0) {
|
||||
LOGD(MODULE_NAME, "sem_wait failed");
|
||||
goto end;
|
||||
}
|
||||
|
||||
LOGD(MODULE_NAME, "sem_wait succeed.");
|
||||
end:
|
||||
at_worker_task_del(tsk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int at_send_raw_self_define_respone_formate(const char *command, char *rsp, uint32_t rsplen,
|
||||
char *rsp_prefix, char *rsp_success_postfix, char *rsp_fail_postfix)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
aos_mutex_lock(&at.at_uart_send_mutex, AOS_WAIT_FOREVER);
|
||||
ret = at_send_raw_self_define_respone_formate_internal(command, strlen(command), rsp, rsplen,
|
||||
rsp_prefix, rsp_success_postfix, rsp_fail_postfix);
|
||||
aos_mutex_unlock(&at.at_uart_send_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int at_send_raw(const char *command, char *rsp, uint32_t rsplen)
|
||||
{
|
||||
if (inited == 0) {
|
||||
LOGE(MODULE_NAME, "at have not init yet\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (at._mode != ASYN) {
|
||||
LOGE(MODULE_NAME, "Operation not supported in non asyn mode");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return at_send_raw_self_define_respone_formate(command, rsp, rsplen, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Example:
|
||||
* AT+ENETRAWSEND=<len>
|
||||
* ><data>
|
||||
* OK
|
||||
*
|
||||
* Send data in 2 stages. These 2 stages must be finished inside
|
||||
* one mutex lock.
|
||||
* 1. Send 'fst' string (first stage);
|
||||
* 2. Receving prompt, usually ">" character;
|
||||
* 3. Send data (second stage) in 'len' length.
|
||||
*/
|
||||
static int at_send_data_2stage(const char *fst, const char *data,
|
||||
uint32_t len, char *rsp, uint32_t rsplen)
|
||||
{
|
||||
int ret = 0;
|
||||
char datadelimiter[2] = {0};
|
||||
|
||||
datadelimiter[0] = 0x1a;
|
||||
|
||||
if (inited == 0) {
|
||||
LOGE(MODULE_NAME, "at have not init yet\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (at._mode != ASYN) {
|
||||
LOGE(MODULE_NAME, "Operation not supported in non asyn mode \r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (NULL == fst || NULL == rsp || 0 == rsplen) {
|
||||
LOGE(MODULE_NAME, "%s invalid input \r\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
at_task_t *tsk = (at_task_t *)aos_malloc(sizeof(at_task_t));
|
||||
if (NULL == tsk) {
|
||||
LOGE(MODULE_NAME, "tsk buffer allocating failed");
|
||||
return -1;
|
||||
}
|
||||
memset(tsk, 0, sizeof(at_task_t));
|
||||
|
||||
if ((ret = aos_sem_new(&tsk->smpr, 0)) != 0) {
|
||||
LOGE(MODULE_NAME, "failed to allocate semaphore");
|
||||
goto end;
|
||||
}
|
||||
|
||||
LOGD(MODULE_NAME, "at task created: %d, smpr: %d",
|
||||
(uint32_t)tsk, (uint32_t)&tsk->smpr);
|
||||
|
||||
tsk->command = (char *)fst;
|
||||
tsk->rsp = rsp;
|
||||
tsk->rsp_len = rsplen;
|
||||
|
||||
aos_mutex_lock(&at.at_uart_send_mutex, AOS_WAIT_FOREVER);
|
||||
at_worker_task_add(tsk);
|
||||
|
||||
// uart operation should be inside mutex lock
|
||||
if ((ret = hal_uart_send(at._pstuart, (void *)fst,
|
||||
strlen(fst), at._timeout)) != 0) {
|
||||
LOGE(MODULE_NAME, "uart send command failed");
|
||||
goto end;
|
||||
}
|
||||
LOGD(MODULE_NAME, "Sending command %s", fst);
|
||||
|
||||
if ((ret = hal_uart_send(at._pstuart, (void *)at._send_delimiter,
|
||||
strlen(at._send_delimiter), at._timeout)) != 0) {
|
||||
LOGE(MODULE_NAME, "uart send delimiter failed");
|
||||
goto end;
|
||||
}
|
||||
LOGD(MODULE_NAME, "Sending delimiter %s", at._send_delimiter);
|
||||
|
||||
aos_msleep(20);
|
||||
|
||||
if ((ret = hal_uart_send(at._pstuart, (void *)data,
|
||||
len, at._timeout)) != 0) {
|
||||
LOGE(MODULE_NAME, "uart send 2stage data failed");
|
||||
goto end;
|
||||
}
|
||||
LOGD(MODULE_NAME, "Sending 2stage data %s", data);
|
||||
|
||||
if ((ret = aos_sem_wait(&tsk->smpr, TASK_DEFAULT_WAIT_TIME)) != 0) {
|
||||
LOGE(MODULE_NAME, "sem_wait failed");
|
||||
goto end;
|
||||
}
|
||||
|
||||
LOGD(MODULE_NAME, "sem_wait succeed.");
|
||||
end:
|
||||
at_worker_task_del(tsk);
|
||||
aos_mutex_unlock(&at.at_uart_send_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// register oob
|
||||
static int at_oob(const char *prefix, const char *postfix, int maxlen,
|
||||
oob_cb cb, void *arg)
|
||||
{
|
||||
oob_t *oob = NULL;
|
||||
int i = 0;
|
||||
|
||||
LOGD(MODULE_NAME, "New oob to register pre (%s) post %s \r\n", prefix, postfix);
|
||||
|
||||
if (maxlen < 0 || NULL == prefix) {
|
||||
LOGE(MODULE_NAME, "%s invalid input \r\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (at._oobs_num >= OOB_MAX) {
|
||||
LOGW(MODULE_NAME, "No place left in OOB.\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*check oob is exit*/
|
||||
for (i = 0; i < at._oobs_num; i++) {
|
||||
if (strcmp(prefix, at._oobs[i].prefix) == 0) {
|
||||
LOGW(MODULE_NAME, "oob prefix %s is already exist.\r\n", prefix);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
oob = &(at._oobs[at._oobs_num++]);
|
||||
|
||||
oob->oobinputdata = NULL;
|
||||
if (postfix != NULL) {
|
||||
oob->oobinputdata = aos_malloc(maxlen);
|
||||
if (NULL == oob->oobinputdata) {
|
||||
LOGE(MODULE_NAME, "fail to malloc len %d at %s for prefix %s \r\n", maxlen, __func__, prefix);
|
||||
return -1;
|
||||
}
|
||||
memset(oob->oobinputdata, 0, maxlen);
|
||||
}
|
||||
|
||||
|
||||
oob->maxlen = maxlen;
|
||||
oob->prefix = (char *)prefix;
|
||||
oob->postfix = (char *)postfix;
|
||||
oob->cb = cb;
|
||||
oob->arg = arg;
|
||||
oob->reallen = 0;
|
||||
|
||||
LOGD(MODULE_NAME, "New oob registered (%s)", oob->prefix);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define RECV_BUFFER_SIZE 512
|
||||
static void at_worker(void *arg)
|
||||
{
|
||||
int offset = 0;
|
||||
int ret = 0;
|
||||
int at_task_empty = 0;
|
||||
int at_task_reponse_begin = 0;
|
||||
int memcpy_size = 0;
|
||||
int rsp_prefix_len = 0;
|
||||
int rsp_success_postfix_len = 0;
|
||||
int rsp_fail_postfix_len = 0;
|
||||
char c;
|
||||
at_task_t *tsk;
|
||||
char *buf = NULL;
|
||||
char *rsp_prefix = NULL;
|
||||
char *rsp_success_postfix = NULL;
|
||||
char *rsp_fail_postfix = NULL;
|
||||
oob_t *oob = NULL;
|
||||
|
||||
LOGD(MODULE_NAME, "at_work started.");
|
||||
|
||||
buf = aos_malloc(RECV_BUFFER_SIZE);
|
||||
if (NULL == buf) {
|
||||
LOGE(MODULE_NAME, "AT worker fail to malloc ,task exist \r\n");
|
||||
aos_task_exit(0);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(buf, 0, RECV_BUFFER_SIZE);
|
||||
|
||||
while (true) {
|
||||
// read from uart and store buf
|
||||
if (at._mode != ASYN) {
|
||||
aos_msleep(1);
|
||||
}
|
||||
|
||||
ret = at_getc(&c);
|
||||
if (ret != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (offset + 1 >= RECV_BUFFER_SIZE) {
|
||||
LOGE(MODULE_NAME, "Fatal error, no one is handling AT uart");
|
||||
continue;
|
||||
}
|
||||
buf[offset++] = c;
|
||||
buf[offset] = 0;
|
||||
|
||||
for (int k = 0; k < at._oobs_num; k++) {
|
||||
oob = &(at._oobs[k]);
|
||||
if (oob->reallen > 0 || (offset >= strlen(oob->prefix) &&
|
||||
memcmp(oob->prefix, buf + offset - strlen(oob->prefix), strlen(oob->prefix)) == 0)) {
|
||||
LOGD(MODULE_NAME, "AT! %s\r\n", oob->prefix);
|
||||
if (oob->postfix == NULL) {
|
||||
oob->cb(oob->arg, NULL, 0);
|
||||
memset(buf + offset - strlen(oob->prefix), 0, offset);
|
||||
offset -= strlen(oob->prefix);
|
||||
} else {
|
||||
if (oob->reallen == 0) {
|
||||
memset(oob->oobinputdata, 0, oob->maxlen);
|
||||
memcpy(oob->oobinputdata, oob->prefix, strlen(oob->prefix) - 1);
|
||||
oob->reallen += strlen(oob->prefix) - 1;
|
||||
}
|
||||
|
||||
if (oob->reallen < oob->maxlen) {
|
||||
oob->oobinputdata[oob->reallen] = c;
|
||||
oob->reallen++;
|
||||
if ((oob->reallen >= strlen(oob->prefix) + strlen(oob->postfix))
|
||||
&& (strncmp(oob->oobinputdata + oob->reallen - strlen(oob->postfix), oob->postfix, strlen(oob->postfix)) == 0)) {
|
||||
/*recv postfix*/
|
||||
oob->cb(oob->arg, oob->oobinputdata, oob->reallen);
|
||||
memset(oob->oobinputdata, 0, oob->reallen);
|
||||
oob->reallen = 0;
|
||||
memset(buf, 0, offset);
|
||||
offset = 0;
|
||||
}
|
||||
} else {
|
||||
LOGE(MODULE_NAME, "invalid oob %s input , for oversize %s \r\n", oob->prefix, oob->oobinputdata);
|
||||
memset(oob->oobinputdata, 0, oob->reallen);
|
||||
oob->reallen = 0;
|
||||
memset(buf, 0, offset);
|
||||
offset = 0;
|
||||
}
|
||||
/*oob data maybe more than buf size */
|
||||
if (offset > (RECV_BUFFER_SIZE - 2)) {
|
||||
memset(buf, 0, offset);
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
at_task_empty = slist_empty(&at.task_l);
|
||||
// if no task, continue recv
|
||||
if (at_task_empty) {
|
||||
LOGD(MODULE_NAME, "No task in queue");
|
||||
goto check_buffer;
|
||||
}
|
||||
|
||||
aos_mutex_lock(&at.task_mutex, AOS_WAIT_FOREVER);
|
||||
// otherwise, get the first task in list
|
||||
tsk = slist_first_entry(&at.task_l, at_task_t, next);
|
||||
aos_mutex_unlock(&at.task_mutex);
|
||||
|
||||
if (NULL != tsk->rsp_prefix && 0 != tsk->rsp_prefix_len) {
|
||||
rsp_prefix = tsk->rsp_prefix;
|
||||
rsp_prefix_len = tsk->rsp_prefix_len;
|
||||
} else {
|
||||
rsp_prefix = at._default_recv_prefix;
|
||||
rsp_prefix_len = at._recv_prefix_len;
|
||||
}
|
||||
|
||||
if (NULL != tsk->rsp_success_postfix && 0 != tsk->rsp_success_postfix_len) {
|
||||
rsp_success_postfix = tsk->rsp_success_postfix;
|
||||
rsp_success_postfix_len = tsk->rsp_success_postfix_len;
|
||||
} else {
|
||||
rsp_success_postfix = at._default_recv_success_postfix;
|
||||
rsp_success_postfix_len = at._recv_success_postfix_len;
|
||||
}
|
||||
|
||||
if (NULL != tsk->rsp_fail_postfix && 0 != tsk->rsp_fail_postfix_len) {
|
||||
rsp_fail_postfix = tsk->rsp_fail_postfix;
|
||||
rsp_fail_postfix_len = tsk->rsp_fail_postfix_len;
|
||||
} else {
|
||||
rsp_fail_postfix = at._default_recv_fail_postfix;
|
||||
rsp_fail_postfix_len = at._recv_fail_postfix_len;
|
||||
}
|
||||
|
||||
if (offset >= rsp_prefix_len && at_task_reponse_begin == 0 &&
|
||||
(strncmp(buf + offset - rsp_prefix_len , rsp_prefix , rsp_prefix_len) == 0)) {
|
||||
at_task_reponse_begin = 1;
|
||||
}
|
||||
|
||||
if (at_task_reponse_begin == 1) {
|
||||
if (tsk->rsp_offset < tsk->rsp_len) {
|
||||
tsk->rsp[tsk->rsp_offset] = c;
|
||||
tsk->rsp_offset++;
|
||||
|
||||
if ((tsk->rsp_offset >= rsp_success_postfix_len &&
|
||||
strncmp(tsk->rsp + tsk->rsp_offset - rsp_success_postfix_len, rsp_success_postfix, rsp_success_postfix_len) == 0)
|
||||
|| (tsk->rsp_offset >= rsp_fail_postfix_len &&
|
||||
strncmp(tsk->rsp + tsk->rsp_offset - rsp_fail_postfix_len, rsp_fail_postfix, rsp_fail_postfix_len) == 0)) {
|
||||
aos_sem_signal(&tsk->smpr);
|
||||
at_task_reponse_begin = 0;
|
||||
memset(buf, 0, offset);
|
||||
offset = 0;
|
||||
}
|
||||
} else {
|
||||
memset(tsk->rsp, 0, tsk->rsp_len);
|
||||
strcpy(tsk->rsp, rsp_fail_postfix);
|
||||
aos_sem_signal(&tsk->smpr);
|
||||
at_task_reponse_begin = 0;
|
||||
memset(buf, 0, offset);
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
check_buffer:
|
||||
// in case buffer is full
|
||||
if (offset > (RECV_BUFFER_SIZE - 2) ) {
|
||||
printf("buffer full \r\n");
|
||||
memcpy_size = rsp_prefix_len > rsp_success_postfix_len ? rsp_prefix_len : rsp_success_postfix_len;
|
||||
memcpy_size = memcpy_size > rsp_fail_postfix_len ? memcpy_size : rsp_fail_postfix_len;
|
||||
memcpy(buf, buf + offset - memcpy_size, memcpy_size);
|
||||
memset(buf + memcpy_size, 0, offset - memcpy_size);
|
||||
offset = memcpy_size;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
at_parser_t at = {
|
||||
._oobs = {{0}},
|
||||
._oobs_num = 0,
|
||||
._mode = ASYN, // default mode - atworker
|
||||
.init = at_init,
|
||||
.set_mode = at_set_mode,
|
||||
.set_timeout = at_set_timeout,
|
||||
.set_recv_delimiter = at_set_recv_delimiter,
|
||||
.set_send_delimiter = at_set_send_delimiter,
|
||||
.send_raw_self_define_respone_formate = at_send_raw_self_define_respone_formate,
|
||||
.send_raw = at_send_raw,
|
||||
.send_data_2stage = at_send_data_2stage,
|
||||
.putch = at_putc,
|
||||
.getch = at_getc,
|
||||
.write = at_write,
|
||||
.read = at_read,
|
||||
.oob = at_oob
|
||||
};
|
||||
174
Living_SDK/framework/atparser/atparser.h
Normal file
174
Living_SDK/framework/atparser/atparser.h
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef _AT_PARSER_H_
|
||||
#define _AT_PARSER_H_
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <hal/soc/soc.h>
|
||||
#include <aos/aos.h>
|
||||
|
||||
#ifdef AOS_ATCMD
|
||||
#include <hal/atcmd.h>
|
||||
#endif
|
||||
|
||||
#ifndef bool
|
||||
#define bool unsigned char
|
||||
#endif
|
||||
|
||||
#ifndef true
|
||||
#define true 1
|
||||
#endif
|
||||
#ifndef false
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
#define OOB_MAX 5
|
||||
|
||||
typedef void (*oob_cb)(void *arg, char *buf, int buflen);
|
||||
|
||||
typedef struct oob_s {
|
||||
char *prefix;
|
||||
char *postfix;
|
||||
char *oobinputdata;
|
||||
uint32_t reallen;
|
||||
uint32_t maxlen;
|
||||
oob_cb cb;
|
||||
void *arg;
|
||||
} oob_t;
|
||||
|
||||
/*
|
||||
* --> | slist | --> | slist | --> NULL
|
||||
* --------- ---------
|
||||
* | smhr | | smpr |
|
||||
* --------- ---------
|
||||
* | rsp | | rsp |
|
||||
* --------- ---------
|
||||
*/
|
||||
typedef struct at_task_s {
|
||||
slist_t next;
|
||||
aos_sem_t smpr;
|
||||
char *command;
|
||||
char *rsp;
|
||||
char *rsp_prefix;
|
||||
char *rsp_success_postfix;
|
||||
char *rsp_fail_postfix;
|
||||
uint32_t rsp_prefix_len;
|
||||
uint32_t rsp_success_postfix_len;
|
||||
uint32_t rsp_fail_postfix_len;
|
||||
uint32_t rsp_offset;
|
||||
uint32_t rsp_len;
|
||||
} at_task_t;
|
||||
|
||||
typedef enum {
|
||||
NORMAL = 0,
|
||||
ASYN
|
||||
} at_mode_t;
|
||||
|
||||
typedef enum {
|
||||
AT_SEND_RAW = 0,
|
||||
AT_SEND_PBUF
|
||||
}at_send_t;
|
||||
|
||||
/**
|
||||
* Parser structure for parsing AT commands
|
||||
*/
|
||||
typedef struct {
|
||||
/// used only internally
|
||||
uart_dev_t *_pstuart;
|
||||
int _timeout;
|
||||
char *_default_recv_prefix;
|
||||
char *_default_recv_success_postfix;
|
||||
char *_default_recv_fail_postfix;
|
||||
char *_send_delimiter;
|
||||
int _recv_prefix_len;
|
||||
int _recv_success_postfix_len;
|
||||
int _recv_fail_postfix_len;
|
||||
int _send_delim_size;
|
||||
oob_t _oobs[OOB_MAX];
|
||||
int _oobs_num;
|
||||
aos_mutex_t at_mutex;
|
||||
aos_mutex_t at_uart_send_mutex;
|
||||
aos_mutex_t task_mutex;
|
||||
|
||||
at_mode_t _mode;
|
||||
|
||||
// can be used externally
|
||||
slist_t task_l;
|
||||
|
||||
/**
|
||||
* initialization
|
||||
*
|
||||
* @param u uart port used for AT communication.
|
||||
* @param send_delimiter string of characters to use as line delimiters for sending
|
||||
* @param recv_delimiter string of characters to use as line delimiters for receiving
|
||||
* @param timeout timeout of the connection
|
||||
*/
|
||||
int (*init)(const char *recv_prefix, const char *recv_success_postfix,
|
||||
const char *recv_fail_postfix, const char *send_delimiter, int timeout);
|
||||
|
||||
void (*set_mode)(at_mode_t m);
|
||||
|
||||
void (*set_timeout)(int timeout);
|
||||
|
||||
void (*set_recv_delimiter)(const char *recv_prefix, const char *recv_success_postfix, const char *recv_fail_postfix);
|
||||
|
||||
void (*set_send_delimiter)(const char *delimiter);
|
||||
|
||||
int (*send_raw_self_define_respone_formate)(const char *command, char *rsp, uint32_t rsplen,
|
||||
char *rsp_prefix, char *rsp_success_postfix, char *rsp_fail_postfix);
|
||||
/*
|
||||
* This is a blocking API. It hanbles raw command sending, then is blocked
|
||||
* to wait for response.
|
||||
*
|
||||
* This API sends raw command (prepared by caller) and wait for raw response.
|
||||
* The caller is responsible for preparing the ready-to-send command
|
||||
* as well as parsing the response result. The caller is also responsible
|
||||
* for allocating/freeing rsp buffer.
|
||||
*/
|
||||
int (*send_raw)(const char *command, char *rsp, uint32_t rsplen);
|
||||
|
||||
/*
|
||||
* This is a blocking API. It hanbles data sending, it inside follows
|
||||
* below steps:
|
||||
* 1. Send first line (with send_delimeter);
|
||||
* 2. Waiting for prompt symbol, usually '>' character;
|
||||
* 3. Send data with 'len' length, and without send_delimeter.
|
||||
*
|
||||
* This API sends prefix command and data, and wait for raw response.
|
||||
* The caller is responsible for preparing the ready-to-send first line
|
||||
* as well as parsing the response result. The caller is also responsible
|
||||
* for allocating/freeing rsp buffer.
|
||||
*/
|
||||
int (*send_data_2stage)(const char *fst, const char *data,
|
||||
uint32_t len, char *rsp, uint32_t rsplen);
|
||||
/**
|
||||
* Write a single byte to the buffer.
|
||||
*/
|
||||
int (*putch)(char c);
|
||||
|
||||
/**
|
||||
* Get a single byte from the buffer.
|
||||
*/
|
||||
int (*getch)(char *c);
|
||||
|
||||
/**
|
||||
* Write an array of bytes to the underlying stream.
|
||||
*/
|
||||
int (*write)(const char *data, int size);
|
||||
|
||||
/**
|
||||
* Read an array of bytes from the underlying stream.
|
||||
*/
|
||||
int (*read)(char *data, int size);
|
||||
|
||||
/**
|
||||
* Attach a callback for out-of-band data.
|
||||
*/
|
||||
void (*oob)(const char *prefix, const char *postfix, int maxlen,
|
||||
oob_cb cb, void *arg);
|
||||
} at_parser_t;
|
||||
|
||||
extern at_parser_t at;
|
||||
#endif
|
||||
13
Living_SDK/framework/atparser/atparser.mk
Normal file
13
Living_SDK/framework/atparser/atparser.mk
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
##
|
||||
# Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
##
|
||||
|
||||
NAME := atparser
|
||||
|
||||
with_atparser ?= 1
|
||||
|
||||
GLOBAL_INCLUDES += ./
|
||||
|
||||
$(NAME)_SOURCES := atparser.c
|
||||
|
||||
GLOBAL_DEFINES += AOS_ATCMD
|
||||
9
Living_SDK/framework/atparser/ucube.py
Normal file
9
Living_SDK/framework/atparser/ucube.py
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
src = Split('''
|
||||
atparser.c
|
||||
''')
|
||||
|
||||
component = aos_component('atparser', src)
|
||||
|
||||
component.add_global_includes('./')
|
||||
|
||||
component.add_global_macros('AOS_ATCMD')
|
||||
Loading…
Add table
Add a link
Reference in a new issue