提交V2版本

This commit is contained in:
roger.luo 2022-12-31 22:42:31 +08:00
parent 2c89bb8208
commit af580e9e53
145 changed files with 64975 additions and 55888 deletions

52
.gitignore vendored Normal file
View File

@ -0,0 +1,52 @@
*.pyc
*.map
*.dblite
*.elf
*.bin
*.hex
*.axf
*.exe
*.pdb
*.idb
*.ilk
*.old
documentation/html
*~
*.o
*.obj
*.bak
*.dep
*.lib
*.i
*.d
*.dbgdt
*.crun
*.bat
*.ps1
*.scl
*.dnx
*.regroups
*.wsdt
tools/kconfig-frontends/kconfig-mconf
packages
cconfig.h
GPUCache
*.vs/
*bin/
*obj/
#cscope files
cscope.*
ncscope.*
#ctag files
/samples/linux/output/*
/samples/none_os/iar/Debug/*
/samples/none_os/iar/settings/*
/samples/none_os/mdk/Debug
/samples/none_os/mdk/list
/samples/none_os/mdk/obj
/samples/none_os/mdk/DebugConfig

25
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,25 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "g++ build and debug active file",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/samples/linux/output/demo",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "Build"
}
]
}

9
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,9 @@
{
"makefile.launchConfigurations": [
{
"cwd": "${workspaceFolder}/samples/linux/output",
"binaryPath": "${workspaceFolder}/samples/linux/output/demo",
"binaryArgs": []
}
]
}

38
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,38 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "Build",
"command": "make clean & make",
"options": {
"cwd": "${workspaceFolder}/samples/linux"
},
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
},
"problemMatcher": {
"owner": "cpp",
"fileLocation": [
"relative",
"${workspaceFolder}/samples/linux"
],
"pattern": {
"regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 5
}
},
"group": {
"kind": "build",
"isDefault": true
},
}
]
}

View File

@ -1,534 +0,0 @@
/******************************************************************************
* @brief ATָ<EFBFBD><EFBFBD>ͨ<EFBFBD>Ź<EFBFBD><EFBFBD><EFBFBD>
*
* Copyright (c) 2020~2021, <morro_luo@163.com>
*
* SPDX-License-Identifier: Apathe-2.0
*
* Change Logs:
* Date Author Notes
* 2020-01-02 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* 2021-01-20 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD>debug<EFBFBD><EFBFBD><EFBFBD>Խӿ<EFBFBD>, <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƚӿ<EFBFBD>
* 2021-03-03 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>URC<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӡ<EFBFBD><EFBFBD><EFBFBD>ճ<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
******************************************************************************/
#include "at_chat.h"
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
//<2F><>ʱ<EFBFBD>ж<EFBFBD>
#define AT_IS_TIMEOUT(start, time) (AT_GET_TICK() - (start) > (time))
/**AT<41><54>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><><CAB5><EFBFBD><EFBFBD>4<EFBFBD><34><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD>) -----------------------------------*/
#define AT_TYPE_WORK 0 /* <20><>ͨ<EFBFBD><CDA8>ҵ ----------*/
#define AT_TYPE_CMD 1 /* <20><>׼<EFBFBD><D7BC><EFBFBD><EFBFBD> ----------*/
#define AT_TYPE_MULTILINE 2 /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ----------*/
#define AT_TYPE_SINGLLINE 3 /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ----------*/
#ifndef AT_DEBUG
#define AT_DEBUG(...) do {}while(0)
#endif
typedef int (*base_work)(at_obj_t *at, ...);
static void at_send_line(at_obj_t *at, const char *fmt, va_list args);
static const inline at_adapter_t *__get_adapter(at_obj_t *at)
{
return &at->adap;
}
static bool at_is_timeout(at_obj_t *at, unsigned int ms)
{
return AT_IS_TIMEOUT(at->timer, ms);
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static void send_data(at_obj_t *at, const void *buf, unsigned int len)
{
at->adap.write(buf, len);
}
/**
* @brief <EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӡ
*/
static void print(at_obj_t *at, const char *cmd, ...)
{
va_list args;
va_start(args, cmd);
at_send_line(at, cmd, args);
va_end(args);
}
/**
* @brief <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD>ݽ<EFBFBD><EFBFBD>ճ<EFBFBD><EFBFBD><EFBFBD>
*/
static unsigned int get_recv_count(at_obj_t *at)
{
return at->recv_cnt;
}
/**
* @brief <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static char *get_recv_buf(at_obj_t *at)
{
return (char *)at->adap.recv_buf;
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static void recv_buf_clear(at_obj_t *at)
{
at->recv_cnt = 0;
}
/**ǰ<><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>*/
static char *search_string(at_obj_t *at, const char *str)
{
return strstr(get_recv_buf(at), str);
}
/**
* @brief <EFBFBD><EFBFBD>ִֹ<EFBFBD><EFBFBD>
*/
static bool at_isabort(at_obj_t *at)
{
return at->cursor ? at->cursor->abort : 1;
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD>ü<EFBFBD>ʱ<EFBFBD><EFBFBD>
*/
static void at_reset_timer(at_obj_t *at)
{
at->timer = AT_GET_TICK();
}
/**
* @brief ATִ<EFBFBD>лص<EFBFBD>
*/
static void do_at_callbatk(at_obj_t *a, at_item_t *i, at_callbatk_t cb, at_return ret)
{
at_response_t r;
if ((ret == AT_RET_ERROR || ret == AT_RET_TIMEOUT) && a->adap.error != NULL)
a->adap.error();
if (cb) {
r.param = i->param;
r.recvbuf = get_recv_buf(a);
r.recvcnt = get_recv_count(a);
r.ret = ret;
cb(&r);
}
}
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
static bool add_work(at_obj_t *at, void *params, void *info, int type)
{
at_item_t *i;
if (list_empty(&at->ls_idle)) //<2F>޿<EFBFBD><DEBF><EFBFBD>at_item
return NULL;
i = list_first_entry(&at->ls_idle, at_item_t, node);//<2F>ӿ<EFBFBD><D3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>ҵ
i->info = (void *)info;
i->param = (void *)params;
i->state = AT_STATE_WAIT;
i->type = type;
i->abort = 0;
list_move_tail(&i->node, &at->ls_ready); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return i != 0;
}
/**
* @brief ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ
*/
static int do_work_handler(at_obj_t *at)
{
at_item_t *i = at->cursor;
return ((int (*)(at_env_t *e))i->info)(&at->env);
}
/**
* @brief ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] a - AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return true - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ, false - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ,
*/
static int do_cmd_handler(at_obj_t *a)
{
at_item_t *i = a->cursor;
at_env_t *e = &a->env;
const at_cmd_t *c = (at_cmd_t *)i->info;
switch(e->state) {
case 0: /*<2A><><EFBFBD><EFBFBD>״̬ ------------------------------------------------------*/
c->sender(e);
e->state++;
e->reset_timer(a);
e->recvclr(a);
break;
case 1:
if (search_string(a, c->matcher)) { //<2F><><EFBFBD><EFBFBD>ƥ<EFBFBD><C6A5>
AT_DEBUG("<-\r\n%s\r\n", get_recv_buf(a));
do_at_callbatk(a, i, c->cb, AT_RET_OK);
return true;
} else if (search_string(a, "ERROR")) {
AT_DEBUG("<-\r\n%s\r\n", get_recv_buf(a));
if (++e->i >= c->retry) {
do_at_callbatk(a, i, c->cb, AT_RET_ERROR);
return true;
}
e->state = 2; /* <20><><EFBFBD><EFBFBD>֮<EFBFBD><D6AE><EFBFBD><EFBFBD>ʱһ<CAB1><D2BB>ʱ<EFBFBD><CAB1>*/
e->reset_timer(a); /* <20><><EFBFBD>ö<EFBFBD>ʱ<EFBFBD><CAB1>*/
} else if (e->is_timeout(a, c->timeout)) { /* <20><>Ӧ<EFBFBD><D3A6>ʱ*/
if (++e->i >= c->retry) {
do_at_callbatk(a, i, c->cb, AT_RET_TIMEOUT);
return true;
}
e->state = 0; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ״̬*/
}
break;
case 2:
if (e->is_timeout(a, 500))
e->state = 0; /*<2A><><EFBFBD>س<EFBFBD>ʼ״̬*/
break;
default:
e->state = 0;
}
return false;
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] a - AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return true - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ, false - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ,
*/
static int send_signlline_handler(at_obj_t *a)
{
at_item_t *i = a->cursor;
at_env_t *e = &a->env;
const char *cmd = (const char *)i->param;
at_callbatk_t cb = (at_callbatk_t)i->info;
switch(e->state) {
case 0: /*<2A><><EFBFBD><EFBFBD>״̬ ------------------------------------------------------*/
e->printf(a, cmd);
e->state++;
e->reset_timer(a);
e->recvclr(a);
break;
case 1:
if (search_string(a, "OK")) {
AT_DEBUG("<-\r\n%s\r\n", get_recv_buf(a));
do_at_callbatk(a, i, cb, AT_RET_OK); //<2F><><EFBFBD><EFBFBD>ƥ<EFBFBD><C6A5>
return true;
} else if (search_string(a, "ERROR")) {
AT_DEBUG("<-\r\n%s\r\n", get_recv_buf(a));
if (++e->i >= 3) {
do_at_callbatk(a, i, cb, AT_RET_ERROR);
return true;
}
e->state = 2; /*<2A><><EFBFBD><EFBFBD>֮<EFBFBD><D6AE><EFBFBD><EFBFBD>ʱһ<CAB1><D2BB>ʱ<EFBFBD><CAB1>*/
e->reset_timer(a); /*<2A><><EFBFBD>ö<EFBFBD>ʱ<EFBFBD><CAB1>*/
} else if (e->is_timeout(a, 3000 + e->i * 2000)) {
if (++e->i >= 3) {
do_at_callbatk(a, i, cb, AT_RET_TIMEOUT);
return true;
}
e->state = 0; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ״̬*/
}
break;
case 2:
if (e->is_timeout(a, 500))
e->state = 0; /**<2A><><EFBFBD>س<EFBFBD>ʼ״̬*/
break;
default:
e->state = 0;
}
return false;
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] a - AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return true - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ, false - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ,
*/
static int send_multiline_handler(at_obj_t *a)
{
at_item_t *i = a->cursor;
at_env_t *e = &a->env;
const char **cmds = (const char **)i->param;
at_callbatk_t cb = (at_callbatk_t)i->info;
switch(e->state) {
case 0:
if (cmds[e->i] == NULL) { /**<2A><><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
do_at_callbatk(a, i, cb, AT_RET_OK);
return true;
}
e->printf(a, "%s\r\n", cmds[e->i]);
e->recvclr(a); /**<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
e->reset_timer(a);
e->state++;
break;
case 1:
if (search_string(a, "OK")) {
e->state = 0;
e->i++;
e->j = 0;
AT_DEBUG("<-\r\n%s\r\n", get_recv_buf(a));
} else if (search_string(a, "ERROR")) {
AT_DEBUG("<-\r\n%s\r\n", get_recv_buf(a));
if (++e->j >= 3) {
do_at_callbatk(a, i, cb, AT_RET_ERROR);
return true;
}
e->state = 2; /*<2A><><EFBFBD><EFBFBD>֮<EFBFBD><D6AE><EFBFBD><EFBFBD>ʱһ<CAB1><D2BB>ʱ<EFBFBD><CAB1>*/
e->reset_timer(a); /*<2A><><EFBFBD>ö<EFBFBD>ʱ<EFBFBD><CAB1>*/
} else if (e->is_timeout(a, 3000)) {
do_at_callbatk(a, i, cb, AT_RET_TIMEOUT);
return true;
}
break;
case 2:
if (e->is_timeout(a, 500))
e->state = 0; /**<2A><><EFBFBD>س<EFBFBD>ʼ״̬*/
break;
default:
e->state = 0;
}
return 0;
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] fmt - <EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] args - <EFBFBD>ɱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>
*/
static void at_send_line(at_obj_t *at, const char *fmt, va_list args)
{
char buf[MAX_AT_CMD_LEN];
int len;
const at_adapter_t *adt = __get_adapter(at);
len = vsnprintf(buf, sizeof(buf), fmt, args);
recv_buf_clear(at); //<2F><><EFBFBD>ս<EFBFBD><D5BD>ջ<EFBFBD><D5BB><EFBFBD>
send_data(at, buf, len);
send_data(at, "\r\n", 2);
AT_DEBUG("->\r\n%s\r\n", buf);
}
/**
* @brief urc(unsolicited code) <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] urc - <EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] size - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С
* @return none
*/
static void urc_handler_entry(at_obj_t *at, char *urc, unsigned int size)
{
int i, n;
utc_item_t *tbl = at->adap.utc_tbl;
for (i = 0; i < at->adap.urc_tbl_count; i++, tbl++) {
n = strlen(tbl->prefix);
if (strncmp(urc, tbl->prefix, n) == 0) { /* ƥ<><C6A5>ǰ׺ */
tbl->handler(urc, size); /* <20>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD>*/
break;
}
}
if (at->cursor == NULL)
AT_DEBUG("<=\r\n%s\r\n", urc);
}
/**
* @brief urc <EFBFBD><EFBFBD><EFBFBD>մ<EFBFBD><EFBFBD><EFBFBD>
* @param[in] buf - <EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return none
*/
static void urc_recv_process(at_obj_t *at, char *buf, unsigned int size)
{
char *urc_buf;
int ch;
unsigned short urc_size;
urc_buf = (char *)at->adap.urc_buf;
urc_size = at->adap.urc_bufsize;
if (size == 0 && at->urc_cnt > 0) {
if (AT_IS_TIMEOUT(at->urc_timer, 2000)) { /* <20><><EFBFBD>ճ<EFBFBD>ʱ*/
urc_handler_entry(at, urc_buf, at->urc_cnt);
if (at->urc_cnt > 1)
AT_DEBUG("Urc recv timeout.\r\n");
at->urc_cnt = 0;
}
} else if (urc_buf != NULL){
at->urc_timer = AT_GET_TICK();
while (size--) {
ch = *buf++;
urc_buf[at->urc_cnt++] = ch;
if (ch == '\n' || ch == '\r' || ch == '\0') { /*urc<72><63><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
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 if (at->urc_cnt >= urc_size) /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
at->urc_cnt = 0;
}
}
}
/**
* @brief ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD>մ<EFBFBD><EFBFBD><EFBFBD>
* @return none
*/
static void resp_recv_process(at_obj_t *at, const char *buf, unsigned int size)
{
char *recv_buf;
unsigned short recv_size;
recv_buf = (char *)at->adap.recv_buf;
recv_size = at->adap.recv_bufsize;
if (at->recv_cnt + size >= recv_size) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
at->recv_cnt = 0;
memcpy(recv_buf + at->recv_cnt, buf, size);
at->recv_cnt += size;
recv_buf[at->recv_cnt] = '\0';
}
/**
* @brief AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>
* @param[in] at - AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] adap - AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
void at_obj_init(at_obj_t *at, const at_adapter_t *adap)
{
int i;
at_env_t *e;
at->adap = *adap;
e = &at->env;
at->recv_cnt = 0;
e->is_timeout = at_is_timeout;
e->printf = print;
e->recvbuf = get_recv_buf;
e->recvclr = recv_buf_clear;
e->recvlen = get_recv_count;
e->find = search_string;
e->abort = at_isabort;
e->reset_timer = at_reset_timer;
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>*/
INIT_LIST_HEAD(&at->ls_idle);
INIT_LIST_HEAD(&at->ls_ready);
for (i = 0; i < sizeof(at->items) / sizeof(at_item_t); i++)
list_add_tail(&at->items[i].node, &at->ls_idle);
while (adap->recv_buf == NULL) {} //ȷ<><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>ǿ<EFBFBD>
}
/**
* @brief ִ<EFBFBD><EFBFBD>AT<EFBFBD><EFBFBD>ҵ(<EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ)
* @param[in] a - AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] work - AT<EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] params -
*/
bool at_do_work(at_obj_t *at, int (*work)(at_env_t *e), void *params)
{
return add_work(at, params, (void *)work, AT_TYPE_WORK);
}
/**
* @brief ִ<EFBFBD><EFBFBD>ATָ<EFBFBD><EFBFBD>
* @param[in] a - AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] cmd - cmd<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
bool at_do_cmd(at_obj_t *at, void *params, const at_cmd_t *cmd)
{
return add_work(at, params, (void *)cmd, AT_TYPE_CMD);
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD>AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD>(Ĭ<EFBFBD>ϵȴ<EFBFBD>OK<EFBFBD><EFBFBD><EFBFBD><EFBFBD>, 3s<EFBFBD><EFBFBD>ʱ)
* @param[in] at - AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] cb - ִ<EFBFBD>лص<EFBFBD>
* @param[in] singlline - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @note <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮ǰ,singlline<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч
*/
bool at_send_singlline(at_obj_t *at, at_callbatk_t cb, const char *singlline)
{
return add_work(at, (void *)singlline, (void *)cb, AT_TYPE_SINGLLINE);
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD>Ͷ<EFBFBD><EFBFBD><EFBFBD>AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڳ<EFBFBD>ʼ<EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD>, Ĭ<EFBFBD>ϵȴ<EFBFBD>OK<EFBFBD><EFBFBD><EFBFBD><EFBFBD>, 3s<EFBFBD><EFBFBD>ʱ)
* @param[in] at - AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] cb - ִ<EFBFBD>лص<EFBFBD>
* @param[in] multiline - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @note <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮ǰ,multiline
*/
bool at_send_multiline(at_obj_t *at, at_callbatk_t cb, const char **multiline)
{
return add_work(at, multiline, (void *)cb, AT_TYPE_MULTILINE);
}
/**
* @brief ǿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹAT<EFBFBD><EFBFBD>ҵ
*/
void at_item_abort(at_item_t *i)
{
i->abort = 1;
}
/**
* @brief ATæ<EFBFBD>ж<EFBFBD>
* @return true - <EFBFBD><EFBFBD>ATָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
bool at_obj_busy(at_obj_t *at)
{
return !list_empty(&at->ls_ready);
}
/**
* @brief AT<EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static void at_work_manager(at_obj_t *at)
{
at_env_t *e = &at->env;
/*<2A><>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD> --------------------------------------------------------------*/
static int (*const work_handler_table[])(at_obj_t *) = {
do_work_handler,
do_cmd_handler,
send_multiline_handler,
send_signlline_handler
};
if (at->cursor == NULL) {
if (list_empty(&at->ls_ready)) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>
return;
e->i = 0;
e->j = 0;
e->state = 0;
at->cursor = list_first_entry(&at->ls_ready, at_item_t, node);
e->params = at->cursor->param;
e->recvclr(at);
e->reset_timer(at);
}
/* <20><><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EBB5BD><EFBFBD>й<EFBFBD><D0B9><EFBFBD><EFBFBD><EFBFBD> -------------------------------------*/
if (work_handler_table[at->cursor->type](at) || at->cursor->abort) {
list_move_tail(&at->cursor->node, &at->ls_idle);
at->cursor = NULL;
}
}
/**
* @brief AT<EFBFBD><EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
void at_poll_task(at_obj_t *at)
{
char rbuf[32];
int read_size;
read_size = __get_adapter(at)->read(rbuf, sizeof(rbuf));
urc_recv_process(at, rbuf, read_size);
resp_recv_process(at, rbuf, read_size);
at_work_manager(at);
}

View File

@ -1,148 +0,0 @@
/******************************************************************************
* @brief ATָ<EFBFBD><EFBFBD>ͨ<EFBFBD>Ź<EFBFBD><EFBFBD><EFBFBD>
*
* Copyright (c) 2020~2021, <morro_luo@163.com>
*
* SPDX-License-Identifier: Apathe-2.0
*
* Change Logs:
* Date Author Notes
* 2020-01-02 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* 2021-01-20 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD>debug<EFBFBD><EFBFBD><EFBFBD>Խӿ<EFBFBD>, <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƚӿ<EFBFBD>
* 2021-03-03 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>URC<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӡ<EFBFBD><EFBFBD><EFBFBD>ճ<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
******************************************************************************/
#ifndef _ATCHAT_H_
#define _ATCHAT_H_
#include <list.h>
#include <stdbool.h>
/*<2A><><EFBFBD><EFBFBD>AT<41><54><EFBFBD><EFBFBD><EEB3A4> --------------------------------------------------------------*/
#define MAX_AT_CMD_LEN 128
/* debug <20><>ӡ<EFBFBD>ӿ<EFBFBD> ------------------------------------------------------------*/
#include <stdio.h>
#define AT_DEBUG(...) printf("[AT]:");printf(__VA_ARGS__) /*do{}while(0)*/
/* <20><>ȡϵͳ<CFB5>δ<EFBFBD>(ms) -----------------------------------------------------------*/
#include "platform.h"
#define AT_GET_TICK() get_tick()
struct at_obj;
/*urc<72><63><EFBFBD><EFBFBD><EFBFBD><EFBFBD> -----------------------------------------------------------------*/
typedef struct {
const char *prefix; //<2F><>Ҫƥ<D2AA><C6A5><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7>
void (*handler)(char *recvbuf, int size);
}utc_item_t;
/*AT<41>ӿ<EFBFBD><D3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ---------------------------------------------------------------*/
typedef struct {
unsigned int (*write)(const void *buf, unsigned int len); /* <20><><EFBFBD>ͽӿ<CDBD>*/
unsigned int (*read)(void *buf, unsigned int len); /* <20><><EFBFBD>սӿ<D5BD>*/
void (*error)(void); /* ATִ<54><D6B4><EFBFBD><EFBFBD>¼<EFBFBD>*/
utc_item_t *utc_tbl; /* urc <20><>*/
unsigned char *urc_buf; /* urc<72><63><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>*/
unsigned char *recv_buf; /* <20><><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD><EFBFBD><EFBFBD>*/
unsigned short urc_tbl_count; /* urc<72><63><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
unsigned short urc_bufsize; /* urc<72><63><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С*/
unsigned short recv_bufsize; /* <20><><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С*/
}at_adapter_t;
/*AT<41><54>ҵ<EFBFBD><D2B5><EFBFBD>л<EFBFBD><D0BB><EFBFBD>*/
typedef struct {
int i,j,state;
void *params;
void (*reset_timer)(struct at_obj *at);
bool (*is_timeout)(struct at_obj *at, unsigned int ms); /*ʱ<><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>*/
void (*printf)(struct at_obj *at, const char *fmt, ...);
char * (*find)(struct at_obj *at, const char *expect);
char * (*recvbuf)(struct at_obj *at); /* ָ<><D6B8><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>*/
unsigned int(*recvlen)(struct at_obj *at); /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܳ<EFBFBD><DCB3><EFBFBD>*/
void (*recvclr)(struct at_obj *at); /* <20><><EFBFBD>ս<EFBFBD><D5BD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>*/
bool (*abort)(struct at_obj *at); /* <20><>ִֹ<D6B9><D6B4>*/
}at_env_t;
/*AT<41><54><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>*/
typedef enum {
AT_RET_OK = 0, /* ִ<>гɹ<D0B3>*/
AT_RET_ERROR, /* ִ<>д<EFBFBD><D0B4><EFBFBD>*/
AT_RET_TIMEOUT, /* <20><>Ӧ<EFBFBD><D3A6>ʱ*/
AT_RET_ABORT, /* ǿ<><C7BF><EFBFBD><EFBFBD>ֹ*/
}at_return;
/*AT<41><54>Ӧ */
typedef struct {
void *param;
char *recvbuf; /* <20><><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>*/
unsigned short recvcnt; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>*/
at_return ret; /* ATִ<54>н<EFBFBD><D0BD><EFBFBD>*/
}at_response_t;
typedef void (*at_callbatk_t)(at_response_t *r); /* AT ִ<>лص<D0BB>*/
/*AT״̬ (<28><>ǰ<EFBFBD>汾δ<E6B1BE><CEB4>) ------------------------------------------------------*/
typedef enum {
AT_STATE_IDLE, /* <20><><EFBFBD><EFBFBD>״̬*/
AT_STATE_WAIT, /* <20>ȴ<EFBFBD>ִ<EFBFBD><D6B4>*/
AT_STATE_EXEC, /* <20><><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4>*/
}at_work_state;
/*AT<41><54>ҵ<EFBFBD><D2B5>*/
typedef struct {
unsigned int state : 3;
unsigned int type : 3; /* <20><>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD>*/
unsigned int abort : 1;
void *param; /* ͨ<>ò<EFBFBD><C3B2><EFBFBD>*/
void *info; /* ͨ<><CDA8><EFBFBD><EFBFBD>Ϣָ<CFA2><D6B8>*/
struct list_head node; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
}at_item_t;
/*AT<41><54><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ------------------------------------------------------------------*/
typedef struct at_obj{
at_adapter_t adap;
at_env_t env; /* <20><>ҵ<EFBFBD><D2B5><EFBFBD>л<EFBFBD><D0BB><EFBFBD>*/
at_item_t items[10]; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>10<31><30><EFBFBD><EFBFBD>ҵ*/
at_item_t *cursor; /* <20><>ǰ<EFBFBD><C7B0>ҵ<EFBFBD><D2B5>*/
struct list_head ls_ready, ls_idle; /* <20><><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><D2B5>*/
unsigned int timer;
unsigned int urc_timer; /* urc<72><63><EFBFBD>ռ<EFBFBD>ʱ<EFBFBD><CAB1>*/
at_return ret;
//urc<72><63><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD>
unsigned short urc_cnt, recv_cnt;
unsigned char suspend: 1;
}at_obj_t;
typedef struct {
void (*sender)(at_env_t *e); /*<2A>Զ<EFBFBD><D4B6><EFBFBD><E5B7A2><EFBFBD><EFBFBD> */
const char *matcher; /*<2A><><EFBFBD><EFBFBD>ƥ<EFBFBD>䴮 */
at_callbatk_t cb; /*<2A><>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD> */
unsigned char retry; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD> */
unsigned short timeout; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱʱ<CAB1><CAB1> */
}at_cmd_t;
void at_obj_init(at_obj_t *at, const at_adapter_t *);
bool at_send_singlline(at_obj_t *at, at_callbatk_t cb, const char *singlline);
bool at_send_multiline(at_obj_t *at, at_callbatk_t cb, const char **multiline);
bool at_do_cmd(at_obj_t *at, void *params, const at_cmd_t *cmd);
bool at_do_work(at_obj_t *at, int (*work)(at_env_t *e), void *params);
void at_item_abort(at_item_t *it); /*<2A><>ֹ<EFBFBD><D6B9>ǰ<EFBFBD><C7B0>ҵ*/
bool at_obj_busy(at_obj_t *at); /*æ<>ж<EFBFBD>*/
void at_suspend(at_obj_t *at);
void at_resume(at_obj_t *at);
void at_poll_task(at_obj_t *at);
#endif

View File

@ -1,705 +0,0 @@
#ifndef _LINUX_LIST_H
#define _LINUX_LIST_H
#include <stddef.h>
#if !defined(__GNUC__)
#define typeof (struct list_head)
#endif
#undef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
/**
* container_of - cast a member of a structure out to the containing structure
* @ptr: the pointer to the member.
* @type: the type of the container struct this is embedded in.
* @member: the name of the member within the struct.
*
*/
#if !defined(__GNUC__)
#define container_of(ptr, type, member) ( \
(type *)( (char *)(ptr) - offsetof(type,member) ))
#else
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#endif
/* copy from <linux/poison.h>, */
/*
* used to verify that nobody uses non-initialized list entries.
*/
#define LIST_POISON1 ((void *) 0x0)
#define LIST_POISON2 ((void *) 0x0)
#ifndef ARCH_HAS_PREFETCH
#define ARCH_HAS_PREFETCH
static inline void prefetch(const void *x) {;}
#endif
/*
* Simple doubly linked list implementation.
*
* Some of the internal functions ("__xxx") are useful when
* manipulating whole lists rather than single entries, as
* sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/
struct list_head {
struct list_head *next, *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
/**
* list_add - add a new entry
* @new: new entry to be added
* @head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
/**
* list_add_tail - add a new entry
* @new: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
/*
* Delete a list entry by making the prev/next entries
* point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_del(struct list_head *prev, struct list_head *next)
{
next->prev = prev;
prev->next = next;
}
/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty() on entry does not return true after this, the entry is
* in an undefined state.
*/
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = LIST_POISON1;
entry->prev = LIST_POISON2;
}
/**
* list_replace - replace old entry by new one
* @old : the element to be replaced
* @new : the new element to insert
*
* If @old was empty, it will be overwritten.
*/
static inline void list_replace(struct list_head *old,
struct list_head *new)
{
new->next = old->next;
new->next->prev = new;
new->prev = old->prev;
new->prev->next = new;
}
static inline void list_replace_init(struct list_head *old,
struct list_head *new)
{
list_replace(old, new);
INIT_LIST_HEAD(old);
}
/**
* list_del_init - deletes entry from list and reinitialize it.
* @entry: the element to delete from the list.
*/
static inline void list_del_init(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
INIT_LIST_HEAD(entry);
}
/**
* list_move - delete from one list and add as another's head
* @list: the entry to move
* @head: the head that will precede our entry
*/
static inline void list_move(struct list_head *list, struct list_head *head)
{
__list_del(list->prev, list->next);
list_add(list, head);
}
/**
* list_move_tail - delete from one list and add as another's tail
* @list: the entry to move
* @head: the head that will follow our entry
*/
static inline void list_move_tail(struct list_head *list,
struct list_head *head)
{
__list_del(list->prev, list->next);
list_add_tail(list, head);
}
/**
* list_is_last - tests whether @list is the last entry in list @head
* @list: the entry to test
* @head: the head of the list
*/
static inline int list_is_last(const struct list_head *list,
const struct list_head *head)
{
return list->next == head;
}
/**
* list_empty - tests whether a list is empty
* @head: the list to test.
*/
static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}
/**
* list_empty_careful - tests whether a list is empty and not being modified
* @head: the list to test
*
* Description:
* tests whether a list is empty _and_ checks that no other CPU might be
* in the process of modifying either member (next or prev)
*
* NOTE: using list_empty_careful() without synchronization
* can only be safe if the only activity that can happen
* to the list entry is list_del_init(). Eg. it cannot be used
* if another CPU could re-list_add() it.
*/
static inline int list_empty_careful(const struct list_head *head)
{
struct list_head *next = head->next;
return (next == head) && (next == head->prev);
}
/**
* list_is_singular - tests whether a list has just one entry.
* @head: the list to test.
*/
static inline int list_is_singular(const struct list_head *head)
{
return !list_empty(head) && (head->next == head->prev);
}
static inline void __list_cut_position(struct list_head *list,
struct list_head *head, struct list_head *entry)
{
struct list_head *new_first = entry->next;
list->next = head->next;
list->next->prev = list;
list->prev = entry;
entry->next = list;
head->next = new_first;
new_first->prev = head;
}
/**
* list_cut_position - cut a list into two
* @list: a new list to add all removed entries
* @head: a list with entries
* @entry: an entry within head, could be the head itself
* and if so we won't cut the list
*
* This helper moves the initial part of @head, up to and
* including @entry, from @head to @list. You should
* pass on @entry an element you know is on @head. @list
* should be an empty list or a list you do not care about
* losing its data.
*
*/
static inline void list_cut_position(struct list_head *list,
struct list_head *head, struct list_head *entry)
{
if (list_empty(head))
return;
if (list_is_singular(head) &&
(head->next != entry && head != entry))
return;
if (entry == head)
INIT_LIST_HEAD(list);
else
__list_cut_position(list, head, entry);
}
static inline void __list_splice(const struct list_head *list,
struct list_head *prev,
struct list_head *next)
{
struct list_head *first = list->next;
struct list_head *last = list->prev;
first->prev = prev;
prev->next = first;
last->next = next;
next->prev = last;
}
/**
* list_splice - join two lists, this is designed for stacks
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static inline void list_splice(const struct list_head *list,
struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head, head->next);
}
/**
* list_splice_tail - join two lists, each list being a queue
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static inline void list_splice_tail(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head->prev, head);
}
/**
* list_splice_init - join two lists and reinitialise the emptied list.
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* The list at @list is reinitialised
*/
static inline void list_splice_init(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
__list_splice(list, head, head->next);
INIT_LIST_HEAD(list);
}
}
/**
* list_splice_tail_init - join two lists and reinitialise the emptied list
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* Each of the lists is a queue.
* The list at @list is reinitialised
*/
static inline void list_splice_tail_init(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
__list_splice(list, head->prev, head);
INIT_LIST_HEAD(list);
}
}
/**
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*/
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
/**
* list_first_entry - get the first element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*
* Note, that list is expected to be not empty.
*/
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
/**
* list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*/
#define list_for_each(pos, head) \
for (pos = (head)->next; prefetch(pos->next), pos != (head); \
pos = pos->next)
/**
* __list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*
* This variant differs from list_for_each() in that it's the
* simplest possible list iteration code, no prefetching is done.
* Use this for code that knows the list to be very short (empty
* or 1 entry) most of the time.
*/
#define __list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
/**
* list_for_each_prev - iterate over a list backwards
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*/
#define list_for_each_prev(pos, head) \
for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
pos = pos->prev)
/**
* list_for_each_safe - iterate over a list safe against removal of list entry
* @pos: the &struct list_head to use as a loop cursor.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
/**
* list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
* @pos: the &struct list_head to use as a loop cursor.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define list_for_each_prev_safe(pos, n, head) \
for (pos = (head)->prev, n = pos->prev; \
prefetch(pos->prev), pos != (head); \
pos = n, n = pos->prev)
/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
prefetch(pos->member.next), &pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_reverse - iterate backwards over list of given type.
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_reverse(pos, head, member) \
for (pos = list_entry((head)->prev, typeof(*pos), member); \
prefetch(pos->member.prev), &pos->member != (head); \
pos = list_entry(pos->member.prev, typeof(*pos), member))
/**
* list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
* @pos: the type * to use as a start point
* @head: the head of the list
* @member: the name of the list_struct within the struct.
*
* Prepares a pos entry for use as a start point in list_for_each_entry_continue().
*/
#define list_prepare_entry(pos, head, member) \
((pos) ? : list_entry(head, typeof(*pos), member))
/**
* list_for_each_entry_continue - continue iteration over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Continue to iterate over list of given type, continuing after
* the current position.
*/
#define list_for_each_entry_continue(pos, head, member) \
for (pos = list_entry(pos->member.next, typeof(*pos), member); \
prefetch(pos->member.next), &pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_continue_reverse - iterate backwards from the given point
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Start to iterate over list of given type backwards, continuing after
* the current position.
*/
#define list_for_each_entry_continue_reverse(pos, head, member) \
for (pos = list_entry(pos->member.prev, typeof(*pos), member); \
prefetch(pos->member.prev), &pos->member != (head); \
pos = list_entry(pos->member.prev, typeof(*pos), member))
/**
* list_for_each_entry_from - iterate over list of given type from the current point
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type, continuing from current position.
*/
#define list_for_each_entry_from(pos, head, member) \
for (; prefetch(pos->member.next), &pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
* list_for_each_entry_safe_continue
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type, continuing after current point,
* safe against removal of list entry.
*/
#define list_for_each_entry_safe_continue(pos, n, head, member) \
for (pos = list_entry(pos->member.next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
* list_for_each_entry_safe_from
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type from current point, safe against
* removal of list entry.
*/
#define list_for_each_entry_safe_from(pos, n, head, member) \
for (n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
* list_for_each_entry_safe_reverse
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate backwards over list of given type, safe against removal
* of list entry.
*/
#define list_for_each_entry_safe_reverse(pos, n, head, member) \
for (pos = list_entry((head)->prev, typeof(*pos), member), \
n = list_entry(pos->member.prev, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.prev, typeof(*n), member))
/*
* Double linked lists with a single pointer list head.
* Mostly useful for hash tables where the two pointer list head is
* too wasteful.
* You lose the ability to access the tail in O(1).
*/
struct hlist_head {
struct hlist_node *first;
};
struct hlist_node {
struct hlist_node *next, **pprev;
};
#define HLIST_HEAD_INIT { .first = NULL }
#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
static inline void INIT_HLIST_NODE(struct hlist_node *h)
{
h->next = NULL;
h->pprev = NULL;
}
static inline int hlist_unhashed(const struct hlist_node *h)
{
return !h->pprev;
}
static inline int hlist_empty(const struct hlist_head *h)
{
return !h->first;
}
static inline void __hlist_del(struct hlist_node *n)
{
struct hlist_node *next = n->next;
struct hlist_node **pprev = n->pprev;
*pprev = next;
if (next)
next->pprev = pprev;
}
static inline void hlist_del(struct hlist_node *n)
{
__hlist_del(n);
n->next = LIST_POISON1;
n->pprev = LIST_POISON2;
}
static inline void hlist_del_init(struct hlist_node *n)
{
if (!hlist_unhashed(n)) {
__hlist_del(n);
INIT_HLIST_NODE(n);
}
}
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
struct hlist_node *first = h->first;
n->next = first;
if (first)
first->pprev = &n->next;
h->first = n;
n->pprev = &h->first;
}
/* next must be != NULL */
static inline void hlist_add_before(struct hlist_node *n,
struct hlist_node *next)
{
n->pprev = next->pprev;
n->next = next;
next->pprev = &n->next;
*(n->pprev) = n;
}
static inline void hlist_add_after(struct hlist_node *n,
struct hlist_node *next)
{
next->next = n->next;
n->next = next;
next->pprev = &n->next;
if(next->next)
next->next->pprev = &next->next;
}
#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
#define hlist_for_each(pos, head) \
for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
pos = pos->next)
#define hlist_for_each_safe(pos, n, head) \
for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
pos = n)
/**
* hlist_for_each_entry - iterate over list of given type
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry(tpos, pos, head, member) \
for (pos = (head)->first; \
pos && ({ prefetch(pos->next); 1;}) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/**
* hlist_for_each_entry_continue - iterate over a hlist continuing after current point
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_continue(tpos, pos, member) \
for (pos = (pos)->next; \
pos && ({ prefetch(pos->next); 1;}) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/**
* hlist_for_each_entry_from - iterate over a hlist continuing from current point
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_from(tpos, pos, member) \
for (; pos && ({ prefetch(pos->next); 1;}) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/**
* hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @n: another &struct hlist_node to use as temporary storage
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
for (pos = (head)->first; \
pos && ({ n = pos->next; 1; }) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = n)
#endif

View File

@ -1,201 +0,0 @@
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.

View File

@ -1,77 +0,0 @@
/******************************************************************************
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD>
*
* Copyright (c) 2015-2020, <morro_luo@163.com>
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2015-06-09 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* 2017-07-04 Morro <EFBFBD>Ż<EFBFBD><EFBFBD>ֶηָ<EFBFBD><EFBFBD>
*
* 2020-07-05 Morro ʹ<EFBFBD><EFBFBD>cli_obj_t<EFBFBD><EFBFBD><EFBFBD><EFBFBD>, ֧<EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
******************************************************************************/
#ifndef _CMDLINE_H_
#define _CMDLINE_H_
#include "comdef.h"
#define CLI_MAX_CMD_LEN 64 /*<2A><><EFBFBD><EFBFBD><EFBFBD>г<EFBFBD><D0B3><EFBFBD>*/
#define CLI_MAX_ARGS 16 /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
#define CLI_MAX_CMDS 32 /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
struct cli_obj;
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EEB6A8>*/
typedef struct {
char *name; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
/*<2A><><EFBFBD><EFBFBD><EEB4A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
int (*handler)(struct cli_obj *o, int argc, char *argv[]);
const char *brief; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
}cmd_item_t;
#define __cmd_register(name,handler,brief)\
USED ANONY_TYPE(const cmd_item_t,__cli_cmd_##handler)\
SECTION("cli.cmd.1") = {name, handler, brief}
/*******************************************************************************
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD>
* @params name - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @params handler - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>:int (*handler)(struct cli_obj *s, int argc, char *argv[]);
* @params brief - ʹ<EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD>
*/
#define cmd_register(name,handler,brief)\
__cmd_register(name,handler,brief)
/*cli <20>ӿڶ<D3BF><DAB6><EFBFBD> -------------------------------------------------------------*/
typedef struct {
unsigned int (*write)(const void *buf, unsigned int len);
unsigned int (*read) (void *buf, unsigned int len);
}cli_port_t;
/*<2A><><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><D0B6><EFBFBD>*/
typedef struct cli_obj {
unsigned int (*write)(const void *buf, unsigned int len);
unsigned int (*read) (void *buf, unsigned int len);
void (*print)(struct cli_obj *this, const char *fmt, ...);
char recvbuf[CLI_MAX_CMD_LEN + 1]; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>*/
unsigned short recvcnt; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ճ<EFBFBD><D5B3><EFBFBD>*/
unsigned enable : 1;
}cli_obj_t;
void cli_init(cli_obj_t *obj, const cli_port_t *p);
void cli_enable(cli_obj_t *obj);
void cli_disable (cli_obj_t *obj);
void cli_exec_cmd(cli_obj_t *obj, const char *cmd);
void cli_process(cli_obj_t *obj);
#endif /* __CMDLINE_H */

View File

@ -1,30 +0,0 @@
del *.bak /s
del *.ddk /s
del *.edk /s
del *.lst /s
del *.lnp /s
del *.mpf /s
del *.mpj /s
del *.obj /s
del *.omf /s
::del *.opt /s ::<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɾ<EFBFBD><C9BE>JLINK<4E><4B><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
del *.plg /s
del *.rpt /s
del *.tmp /s
del *.__i /s
del *.crf /s
del *.o /s
del *.d /s
del *.axf /s
del *.tra /s
del *.dep /s
del JLinkLog.txt /s
del *.iex /s
del *.htm /s
del *.sct /s
del *.map /s
del *.pbi /s
del *.out /s
exit

View File

@ -1,251 +0,0 @@
/******************************************************************************
* @brief wifi<EFBFBD><EFBFBD><EFBFBD><EFBFBD>(AT-command<EFBFBD><EFBFBD>ʾ, ʹ<EFBFBD>õ<EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>M169WI-FI)
*
* Copyright (c) 2020, <morro_luo@163.com>
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-01-20 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* 2021-03-03 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD>URCʹ<EFBFBD>ð<EFBFBD><EFBFBD><EFBFBD>
******************************************************************************/
#include "at_chat.h"
#include "wifi_uart.h"
#include "public.h"
#include "module.h"
#include "cli.h"
#include <stdio.h>
#include <stdbool.h>
/* Private function prototypes -----------------------------------------------*/
void wifi_open(void);
void wifi_close(void);
static void at_error(void);
void wifi_query_version(void);
void wifi_ready_handler(char *recvbuf, int size);
void wifi_connected_handler(char *recvbuf, int size);
void wifi_disconnected_handler(char *recvbuf, int size);
/* Private variables ---------------------------------------------------------*/
/*
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static at_obj_t at;
/*
* @brief wifi <EFBFBD><EFBFBD><EFBFBD>ݽ<EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static unsigned char wifi_recvbuf[256];
/*
* @brief wifi URC<EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static unsigned char wifi_urcbuf[128];
/*
* @brief wifi URC<EFBFBD><EFBFBD>
*/
static const utc_item_t urc_table[] = {
"ready", wifi_ready_handler,
"WIFI CONNECTED:", wifi_connected_handler,
"WIFI DISCONNECTED", wifi_disconnected_handler,
};
/*
* @brief AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static const at_adapter_t at_adapter = {
.write = wifi_uart_write,
.read = wifi_uart_read,
.error = at_error,
.utc_tbl = (utc_item_t *)urc_table,
.urc_buf = wifi_urcbuf,
.recv_buf = wifi_recvbuf,
.urc_tbl_count = sizeof(urc_table) / sizeof(urc_table[0]),
.urc_bufsize = sizeof(wifi_urcbuf),
.recv_bufsize = sizeof(wifi_recvbuf)
};
/* Private functions ---------------------------------------------------------*/
/*
* @brief wifi<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>
*/
void wifi_ready_handler(char *recvbuf, int size)
{
printf("WIFI ready...\r\n");
}
/*
* @brief wifi<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>
*/
static void wifi_connected_handler(char *recvbuf, int size)
{
printf("WIFI connection detected...\r\n");
}
/*
* @brief wifi<EFBFBD>Ͽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>
*/
static void wifi_disconnected_handler(char *recvbuf, int size)
{
printf("WIFI disconnect detected...\r\n");
}
/*
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>wifi
*/
void wifi_open(void)
{
GPIO_SetBits(GPIOA, GPIO_Pin_4);
printf("wifi open\r\n");
}
/*
* @brief <EFBFBD>ر<EFBFBD>wifi
*/
void wifi_close(void)
{
GPIO_ResetBits(GPIOA, GPIO_Pin_4);
printf("wifi close\r\n");
}
/*
* @brief WIFI<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD>
* @return true - <EFBFBD>˳<EFBFBD>״̬<EFBFBD><EFBFBD>, false - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD>,
*/
static int wifi_reset_work(at_env_t *e)
{
at_obj_t *a = (at_obj_t *)e->params;
switch (e->state) {
case 0: //<2F>ر<EFBFBD>WIFI<46><49>Դ
wifi_close();
e->reset_timer(a);
e->state++;
break;
case 1:
if (e->is_timeout(a, 2000)) //<2F><>ʱ<EFBFBD>ȴ<EFBFBD>2s
e->state++;
break;
case 2:
wifi_open(); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>wifi
e->state++;
break;
case 3:
if (e->is_timeout(a, 5000)) //<2F><>Լ<EFBFBD><D4BC>ʱ<EFBFBD>ȴ<EFBFBD>5s<35><73>wifi<66><69><EFBFBD><EFBFBD>
return true;
break;
}
return false;
}
/*
* @brief wifi ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static void at_error(void)
{
printf("wifi AT communication error\r\n");
//ִ<><D6B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ
at_do_work(&at, wifi_reset_work, &at);
}
/*
* @brief <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>
*/
static void at_init_callbatk(at_response_t *r)
{
if (r->ret == AT_RET_OK ) {
printf("wifi Initialization successfully...\r\n");
/* <20><>ѯ<EFBFBD><EFBFBD><E6B1BE>*/
wifi_query_version();
} else
printf("wifi Initialization failure...\r\n");
}
/*
* @brief wifi<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static const char *wifi_init_cmds[] = {
"AT+GPIO_WR=1,1\r\n",
"AT+GPIO_WR=2,0\r\n",
"AT+GPIO_WR=3,1\r\n",
NULL
};
/*
* @brief wifi<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>
*/
void wifi_init(void)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA , ENABLE);
gpio_conf(GPIOA, GPIO_Mode_OUT, GPIO_PuPd_NOPULL, GPIO_Pin_4);
wifi_uart_init(115200);
at_obj_init(&at, &at_adapter);
//<2F><><EFBFBD><EFBFBD>WIFI
at_do_work(&at, wifi_reset_work, &at);
//<2F><>ʼ<EFBFBD><CABC>wifi
at_send_multiline(&at, at_init_callbatk, wifi_init_cmds);
//GPIO<49><4F><EFBFBD><EFBFBD>
at_send_singlline(&at, NULL, "AT+GPIO_TEST_EN=1\r\n");
}driver_init("wifi", wifi_init);
/*
* @brief wifi<EFBFBD><EFBFBD><EFBFBD><EFBFBD>(10ms <EFBFBD><EFBFBD>ѯ1<EFBFBD><EFBFBD>)
*/
void wifi_task(void)
{
at_poll_task(&at);
}task_register("wifi", wifi_task, 10);
/** <20>DZ<EFBFBD>׼AT<41><54><EFBFBD><EFBFBD>----------------------------------------------------------------
* <EFBFBD>Բ<EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>:
* -> AT+VER\r\n
* <- VERSION:M169-YH01
*
*/
//<2F><>ʽ1, ʹ<><CAB9>at_do_cmd<6D>ӿ<EFBFBD>
/*
* @brief <EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD>AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static void at_ver_sender(at_env_t *e)
{
e->printf(&at, "AT+VER\r\n");
}
/*
* @brief <EFBFBD><EFBFBD><EFBFBD>ѯ<EFBFBD>ص<EFBFBD>
*/
static void query_version_callback(at_response_t *r)
{
if (r->ret == AT_RET_OK ) {
printf("wifi version info : %s\r\n", r->recvbuf);
} else
printf("wifi version query failure...\r\n");
}
/* <20><><EFBFBD><EFBFBD>AT<41><54><EFBFBD><EFBFBD>*/
static const at_cmd_t at_cmd_ver = {
at_ver_sender, //<2F>Զ<EFBFBD><D4B6><EFBFBD>AT<41><54><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
"VERSION:", //<2F><><EFBFBD><EFBFBD>ƥ<EFBFBD><C6A5>ǰ׺
query_version_callback, //<2F><>ѯ<EFBFBD>ص<EFBFBD>
3, 3000 //<2F><><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱʱ<CAB1><CAB1>
};
/*
* @brief ִ<EFBFBD>а<EFBFBD><EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
void wifi_query_version(void)
{
at_do_cmd(&at, NULL, &at_cmd_ver);
}

201
LICENSE
View File

@ -1,201 +0,0 @@
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.

366
README.md
View File

@ -2,268 +2,176 @@
[![License](https://img.shields.io/badge/license-Apache%202-green.svg)](https://gitee.com/moluo-tech/ril/blob/master/LICENSE) [![License](https://img.shields.io/badge/license-Apache%202-green.svg)](https://gitee.com/moluo-tech/ril/blob/master/LICENSE)
## 介绍 ## 简介
一种AT命令通信解析模块,支持裸机(at_chat)和OS版本(at)。适用于modem、WIFI模块、蓝牙通信。
## 软件架构 AT command(V2) 一款管理AT命令通信交互组件 适用于Modem、WIFI模块、蓝牙等使用AT命令或者ASCII命令行通信的场景它涵盖了大部分AT通信形式如参数设置查询二进制数据发送等同时也支持自定义命令交互管理由于它的每个命令请求都是异步的所以对于无操作系统的环境也支持。相对于V1版本新版本在命令接收匹配URC不定长度数据捕获以及内存安全上做了大量优化让它可以应对更多复杂产品应用。
- at_chat.c at_chat.h list.h ## 基本特性
- 所有命令请求都是异步的,无操作系统也可以运行。
- 支持单行命令批量命令可变参数命令以及自定义AT命令。
- 支持命令响应超时,错误重传,优先级管理。
- 支持不定长度URC(未经请求主动主报)消息捕获。
- 支持多个AT设备通信管理。
- 支持内存使用监视与限制。
- 支持命令请求的生命周期管理,实时监视命令执行状态。
用于无OS版本使用链式队列及异步回调方式处理AT命令收发支持URC处理、自定义命令发送与解析作业。 ## 系统要求
- at.c at.h at_util.h comdef.h
用于OS版本, 使用前需要根据at_util.h规定的操作系统相关的接口进行移植,如提供信号量操作、任务延时等操作。 为了能够使AT命令正常通信目标系统必须满足以下要求
- 动态内存支持。
- RAM 资源:至少 1KB (取决于接收缓冲区与URC缓冲区的设置)建议在可分配3KB内存以上的系统中使用。
- 编译器系统中使用了一些C99的特性(柔性数组、内联)所以编译器需要开启对C99的支持。对于IARGCC它们默认是打开的而Keil MDK需要手动增加编译选项(--c99 --gnu)。
## 新版本与V1版本区别
## 使用说明 V1版本分成了两个模块"at"模块仅适用于在OS环境下运行而"at_chat"模块则适用于无操作系统的环境下运行采用预分配内存的方式管理AT请求不需要动态内存支持也因为如此限制了其应用范围。虽然也可以在OS下运行但是支持并不完善。V2版本主要是针对"at_chat"模块整体上进行优化支持URC功能同时也加强了对OS环境下的支持由于使用动态内存方式管理AT命令请求对于RAM的资源要求更高一些但是使用上会更加便捷。
### at_chat 模块(无OS) ### 如何选择
如果使用的平台RAM资源(如8位单片机)有限而且只用来做一些简单的AT通信使用V1版本是比较合适的而如果RAM资源充足建议使用V2版本。
## 使用入门
#### 基本概念 下面简单介绍如何使用4步完成:
at_chat 模块使用链式队列进行管理包含2条链表空闲链表和就绪链表。它们的每一个基本工作单元称为一个作业项对于将要执行的命令都会放到就绪链表中命令执行完成之后由空闲链表来进行回收作业项的定义如下 ### 1.定义适配器,完成驱动接口及缓冲区设置
```c ```c
/**
/*AT作业项*/ * @brief AT适配器
typedef struct {
unsigned int state : 3;
unsigned int type : 3; /* 作业类型*/
unsigned int abort : 1;
void *param; /* 通用参数*/
void *info; /* 通用信息指针*/
struct list_head node; /* 链表结点*/
}at_item_t;
```
作业是AT控制器定义时固定分配的没有使用动态内存默认支持10个作业项即同时可以允许10个AT命令排队等待处理。
/*...未完,待续*/
#### 基本接口与描述
- at_send_singlline, 发送单行命令默认等待OK响应超时3S
- at_send_multiline, 多行命令默认等待OK响应超时3S
- at_do_cmd支持自定义发送格式与接收匹配串
- at_do_work支持自定义发送与接收解析
#### 效果演示
详细使用可以参考Demo程序wifi_task.c模块
![m169 wifi模组通信效果图](images/wifi.jpg)
#### 使用步骤
1.定义AT控制器及通信适配器接口
```c
/*
* @brief 定义AT控制器
*/ */
static at_obj_t at; static const at_adapter_t at_adapter = {
.lock = at_mutex_lock //多任务上锁(非OS下填NULL)
const at_adapter_t adap = { //AT适配器接口 .unlock = at_mutex_unlock //多任务解锁(非OS下填NULL)
//适配GPRS模块的串口读写接口 .write = at_device_write //数据写接口(非阻塞式)
.write = uart_write, .read = at_device_read //数据读接口(非阻塞式)
.read = uart_read .debug = at_debug //调试打印接口(不需要则填NULL)
... .recv_bufsize = 256 //接收缓冲区大小(按实际情况填写)
}; };
``` ```
2. 初始化AT控制器并放入任务中轮询考虑到处理实时性建议20ms以下 ### 2.使用AT适配器创建AT通信对象
```c ```c
/* at_obj_t *at_obj;
* @brief wifi初始化 //....
*/ at_obj = at_obj_create(&at_adapter);
void wifi_init(void) if (at_obj == NULL) {
{ printf("at object create failed\r\n");
at_obj_init(&at, &adap); }
/*...*/ //...
}driver_init("wifi", wifi_init); ```
/* ### 3.加入定时轮询任务
* @brief wifi任务(10ms 轮询1次) ```c
/**
* @brief 轮询程序
*/ */
void wifi_task(void) void at_device_process(void)
{ {
at_poll_task(&at); static unsigned int timer;
}task_register("wifi", wifi_task, 10); //为了加快AT命令处理响应速度建议5ms以内轮询一次
if (get_tick() - timer > 5) {
timer = get_tick();
at_obj_process(&at_obj);
}
}
```
### 4.发送AT命令
完成上面几个步骤之后就可以执行AT命令请求了下面以查询MODEM信号质量为例演示如何发送AT命令及解析响应内容.
**命令格式如下:**
```shell
=> AT+CSQ
<= +CSQ: <rssi><ber>
<= OK
``` ```
**代码实现:**
#### 例子演示
```C ```C
//WIFI IO配置命令
=> AT+GPIO_TEST_EN=1\r\n
<= OK\r\n
```
```c
/** /**
* @brief AT执行回调处理程序 * @brief 命令响应处理程序
*/ */
static void test_gpio_callback(at_response_t *r) static void csq_respose_callback(at_response_t *r)
{ {
if (r->ret == AT_RET_OK ) { int rssi ber;
printf("Execute successfully\r\n"); //+CSQ: <rssi><ber>
} else { if (r->code == AT_RESP_OK) {
printf("Execute failure\r\n"); //命令响应成功后解析出rssiber.
} if (sscanf(r->prefix "+CSQ:%d%d" &rssi &ber) == 2) {
} printf("rssi:%d ber:%d\r\n" rssi ber);
at_send_singlline(&at, test_gpio_callback, "AT+GPIO_TEST_EN=1"); }
``` } else {
printf("'CSQ' command response failed!\r\n");
### at 模块(OS版本)
由于AT命令通信是一个比较复杂的过程对于没有OS的环境下处理难度比较大也很绕,对于不允许阻塞程序,除了使用状态与+回调没有其它更好的办法,所以推荐使用这个模块
#### 基本接口与描述
- at_do_cmd执行AT命令可以通过这个接口进一步封装出一常用的单行命令、多行命令。
- at_split_respond_lines命令响应分割器。
- at_do_work适用于发送组合命令如GPRS模组发送短信或者发送socket数据需要等待"<"或者"CONNECT"提示符,可以通过这个接口自定义收发。
#### 案例演示
参考我的另外一个项目[RIL(Radio Interface Layer)](https://gitee.com/moluo-tech/ril)
#### 使用步骤
1.定义AT控制器、通信适配器接口(包含URC回调函数表接口缓冲区URC)
```c
static at_obj_t at; //定义AT控制器对象
static char urc_buf[128]; //URC主动上报缓冲区
utc_item_t utc_tbl[] = { //定义URC表
"+CSQ: ", csq_updated_handler
}
const at_adapter_t adap = { //AT适配器接口
.urc_buf = urc_buf,
.urc_bufsize = sizeof(urc_buf),
.utc_tbl = utc_tbl,
.urc_tbl_count = sizeof(utc_tbl) / sizeof(utc_item_t),
//debug调试接口
.debug = at_debug,
//适配GPRS模块的串口读写接口
.write = uart_write,
.read = uart_read
};
```
2.创建AT控制器并创建轮询处理线程
```c
void at_thread(void)
{
at_obj_create(&at, &adap);
while (1) {
at_process(&at);
} }
} }
```
#### 例子演示
##### 例子1(查询无线模组信号质量)
```c
/** at_do_cmd 接口使用演示
查询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);
}
```
##### 例子2(发送TCP数据)
```C
/** at_do_work 接口使用演示
参考自hl8518模组Socket 数据发送命令
=> AT+KTCPSND=<session_id>,<ndata>
<= CONNECT
=> <data>
<= OK
*/
/*
* @brief 数据发送处理
* @retval none
*/
static bool socket_send_handler(at_work_ctx_t *e)
{
struct socket_info *i = (struct socket_info *)e->params;
struct ril_sock *s = i->s;
if (s->type == SOCK_TYPE_TCP)
e->printf(e, "AT+KTCPSND=%d,%d", s->session, i->bufsize);
else
e->printf(e, "AT+KUDPSND=%d,%s,%d,%d",s->session, s->host,
s->port, i->bufsize);
if (e->wait_resp(e, "CONNECT", 5000) != AT_RET_OK) { //等待提示符
goto Error;
}
e->write(i->buf, i->bufsize); //发送数据
e->write("--EOF--Pattern--", strlen("--EOF--Pattern--")); //发送结束符
if (e->wait_resp(e, "OK", 5000) == AT_RET_OK)
return true;
else {
Error:
e->write("--EOF--Pattern--", strlen("--EOF--Pattern--"));
return false;
}
}
/** /**
* @brief socket 数据发送 * @brief 读CSQ值请求
* @param[in] s - socket
* @param[in] buf - 数据缓冲区
* @param[in] len - 缓冲区长度
*/ */
static bool hl8518_sock_send(ril_obj_t *r, struct ril_sock *s, const void *buf, static void read_csq(void)
unsigned int len)
{ {
struct socket_info info = {s, (unsigned char *)buf, len, 0}; //发送命令超时时间为1000ms重发次数为0
if (len == 0) at_send_singlline(at_obj csq_respose_callback 1000 0 "AT+CSQ");
return false;
return at_do_work(&r->at, (at_work)socket_send_handler, &info);
} }
``` ```
**下面是在M169 WIFI上运行的效果图(例子:`at_chat/samples/none_os`)**
![wifi](images/../docs/images/wifi.png)
## 更多案例
如果你想获取更多完整的应用案例可以参考目录'at_chat/samples',里面提供了几个典型平台下的例子。
以Linux平台下的案例为例可以通过终端输入以下命令运行AT通信模拟器:
```shell
cd ./at_chat/samples/linux
make clean & make
./output/demo
```
如果您使用的是vscode直接进入samples/linux目录下按F5开始运行。
如果程序运行正常,您将看到终端打印如下信息。
```c
*******************************************************
This is an asynchronous AT command framework.
Author:roger.luo, Mail:morro_luo@163.com
*******************************************************
Please input test item:
1:Display memory information.
2:Testing singlline command.
3:Testing multiline commands.
4:Testing variable parameter command.
5:Testing response timeout retry.
6:Testing response error retry.
7:Testing command abort.
8:Testing specific response prefix.
9:Testing custom command.
10:Testing buffer send.
11:Testing 'at_do_work' 1.
12:Testing read binary data via 'at work'.
13:Testing capture unsolicited binary data.
14:Testing at context interface.
*******************************************************
<=
+POWER:1
...
Device power on event detected!
```
根据命令行提示,输入的序号并回车就可以验证对应的用例了.
**更多详细的使用说明,请参考:**
- [介绍](https://gitee.com/moluo-tech/AT-Command/docs/readme.md)
- [快速上手](https://gitee.com/moluo-tech/AT-Command/docs/quickStart.md)
- [高级教程](https://gitee.com/moluo-tech/AT-Command/docs/Expert.md)
- [平台移植](https://gitee.com/moluo-tech/AT-Command/docs/Porting.md)

416
at.c
View File

@ -1,416 +0,0 @@
/**
******************************************************************************
* @brief AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD>Ź<EFBFBD><EFBFBD><EFBFBD>(OS<EFBFBD>)
*
* Copyright (c) 2020, <morro_luo@163.com>
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-01-02 Morro Initial version.
* 2021-02-01 Morro ֧<EFBFBD><EFBFBD>URC<EFBFBD>ص<EFBFBD><EFBFBD>н<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
* 2021-02-05 Morro 1.<EFBFBD>޸<EFBFBD>struct at_obj,ȥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* 2.ɾ<EFBFBD><EFBFBD> at_obj_destroy<EFBFBD>ӿ<EFBFBD>
* 2021-03-21 Morro ɾ<EFBFBD><EFBFBD>at_obj<EFBFBD>е<EFBFBD>at_work_ctx_t<EFBFBD><EFBFBD>,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>ʹ<EFBFBD><EFBFBD>
* 2021-04-08 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><EFBFBD>ͷ<EFBFBD><EFBFBD>ź<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵȴ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* 2021-05-15 Morro <EFBFBD>Ż<EFBFBD>URCƥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* 2021-07-20 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD>at_do_workʱurc<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݶ<EFBFBD>ʧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* 2021-11-20 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>urc<EFBFBD>¼<EFBFBD><EFBFBD>ж<EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ
* <EFBFBD><EFBFBD><EFBFBD>º<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݶ<EFBFBD>ʧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
******************************************************************************
*/
#include "at.h"
#include "comdef.h"
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include <stddef.h>
#define MAX_AT_LOCK_TIME 60 * 1000 //AT<41><54><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
static void urc_recv_process(at_obj_t *at, const char *buf, unsigned int size);
/**
* @brief Ĭ<EFBFBD>ϵ<EFBFBD><EFBFBD>Խӿ<EFBFBD>
*/
static void nop_dbg(const char *fmt, ...){}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
*/
static void put_string(at_obj_t *at, const char *s)
{
while (*s != '\0')
at->adap.write(s++, 1);
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
*/
static void put_line(at_obj_t *at, const char *s)
{
put_string(at, s);
put_string(at, "\r\n");
at->adap.debug("->\r\n%s\r\n", s);
}
/**
* @brief <EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
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); //<2F>ݽ<EFBFBD><DDBD><EFBFBD>URC<52><43><EFBFBD>д<EFBFBD><D0B4><EFBFBD>
return len;
}
/**
* @brief <EFBFBD><EFBFBD>ҵд<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static unsigned int at_work_write(struct at_work_ctx *e, const void *buf, unsigned int len)
{
return e->at->adap.write(buf, len);
}
//<2F><>ӡ<EFBFBD><D3A1><EFBFBD><EFBFBD>
static void at_work_print(struct at_work_ctx *e, const char *cmd, ...)
{
va_list args;
va_start(args, cmd);
char buf[MAX_AT_CMD_LEN];
vsnprintf(buf, sizeof(buf), cmd, args);
put_line(e->at, buf);
va_end(args);
}
//<2F>ȴ<EFBFBD>AT<41><54><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ
static at_return wait_resp(at_obj_t *at, at_respond_t *r)
{
at->ret = AT_RET_TIMEOUT;
at->resp_timer = at_get_ms();
at->rcv_cnt = 0; //<2F><><EFBFBD>ս<EFBFBD><D5BD>ջ<EFBFBD><D5BB><EFBFBD>
at->resp = r;
at_sem_wait(at->completed, r->timeout);
at->adap.debug("<-\r\n%s\r\n", r->recvbuf);
at->resp = NULL;
return at->ret;
}
/**
* @brief <EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] resp - <EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>մ<EFBFBD>(<EFBFBD><EFBFBD>"OK",">")
* @param[in] timeout - <EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD>ʱʱ<EFBFBD><EFBFBD>
*/
at_return wait_recv(struct at_work_ctx *e, const char *resp, unsigned int timeout)
{
char buf[64];
int cnt = 0, len;
at_obj_t *at = e->at;
at_return ret = AT_RET_TIMEOUT;
unsigned int timer = at_get_ms();
while (at_get_ms() - timer < timeout) {
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;
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] adap - AT<EFBFBD>ӿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
void at_obj_init(at_obj_t *at, const at_adapter_t *adap)
{
at->adap = *adap;
at->rcv_cnt = 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;
}
/**
* @brief ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] fmt - <EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] r - <EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>NULL, Ĭ<EFBFBD>Ϸ<EFBFBD><EFBFBD><EFBFBD>OK<EFBFBD><EFBFBD>ʾ<EFBFBD>ɹ<EFBFBD>,<EFBFBD>ȴ<EFBFBD>5s
* @param[in] args - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>
*/
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), 5000};
if (r == NULL) {
r = &default_resp; //Ĭ<><C4AC><EFBFBD><EFBFBD>Ӧ
}
if (!at_sem_wait(at->send_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->send_lock);
at->busy = false;
return ret;
}
/**
* @brief ִ<EFBFBD><EFBFBD>AT<EFBFBD><EFBFBD>ҵ
* @param[in] at - AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] work - <EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD>ں<EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD> - int (*)(at_work_ctx_t *))
* @param[in] params- <EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>work<EFBFBD>ķ<EFBFBD><EFBFBD><EFBFBD>ֵ
*/
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->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;
//<2F><><EFBFBD><EFBFBD>at_work_ctx_t
ctx.params = params;
ctx.printf = at_work_print;
ctx.read = at_work_read;
ctx.write = at_work_write;
ctx.wait_resp = wait_recv;
ctx.at = at;
at->rcv_cnt = 0;
ret = work(&ctx);
at_sem_post(at->recv_lock);
at_sem_post(at->send_lock);
at->busy = false;
return ret;
}
/**
* @brief <EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD>
* @param[in] recvbuf - <EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[out] lines - <EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] separator- <EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD>(, \n)
* @return <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
int at_split_respond_lines(char *recvbuf, char *lines[], int count, char separator)
{
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; /*ָ<><D6B8><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>Ӵ<EFBFBD>*/
}
s++;
}
return i;
}
/**
* @brief <EFBFBD><EFBFBD>URC<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD>ѯURC<EFBFBD><EFBFBD>
* @param[in] urcline - URC<EFBFBD><EFBFBD>
* @return true - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʶ<EFBFBD>𲢴<EFBFBD><EFBFBD><EFBFBD>, false - δʶ<EFBFBD><EFBFBD>URC
*/
const urc_item_t *find_urc_item(at_obj_t *at, char *urc_buf, unsigned int size)
{
const urc_item_t *tbl = at->adap.utc_tbl;
int i;
if (size < 2)
return NULL;
for (i = 0; i < at->adap.urc_tbl_count; i++) {
if (strstr(urc_buf, tbl->prefix))
return tbl;
tbl++;
}
return NULL;
}
/**
* @brief urc <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] urcline - URC<EFBFBD><EFBFBD>
*/
static void urc_handler_entry(at_obj_t *at, char *urcline, unsigned int size)
{
at_urc_ctx_t context = {at->adap.read, urcline, at->adap.urc_bufsize, size};
at->adap.debug("<=\r\n%s\r\n", urcline);
at->urc_item->handler(&context); /* <20>ݽ<EFBFBD><DDBD><EFBFBD><EFBFBD>ϲ<CFB2><E3B4A6> */
}
/**
* @brief urc <EFBFBD><EFBFBD><EFBFBD>մ<EFBFBD><EFBFBD><EFBFBD>
* @param[in] ch - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>
* @return none
*/
static void urc_recv_process(at_obj_t *at, const char *buf, unsigned int size)
{
register char *urc_buf;
int ch;
urc_buf = at->adap.urc_buf;
//<2F><><EFBFBD>ճ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><><C4AC>MAX_URC_RECV_TIMEOUT
if (at->urc_cnt > 0 && at_istimeout(at->urc_timer, MAX_URC_RECV_TIMEOUT)) {
urc_buf[at->urc_cnt] = '\0';
if (at->urc_cnt > 2)
at->adap.debug("urc recv timeout=>%s\r\n", urc_buf);
at->urc_cnt = 0;
at->urc_item = NULL;
}
while (size--) {
at->urc_timer = at_get_ms();
ch = *buf++;
urc_buf[at->urc_cnt++] = ch;
if (strchr(SPEC_URC_END_MARKS, ch) || ch == '\0') { //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>
urc_buf[at->urc_cnt] = '\0';
if (at->urc_item == NULL)
at->urc_item = find_urc_item(at, urc_buf, at->urc_cnt);
if (at->urc_item != NULL){
if (strchr(at->urc_item->end_mark, ch)) { //ƥ<><C6A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
urc_handler_entry(at, urc_buf, at->urc_cnt);
at->urc_cnt = 0;
at->urc_item = NULL;
}
} else if (ch == '\r' || ch == '\n'|| ch == '\0') {
if (at->urc_cnt > 2 && !at->busy) {
at->adap.debug("%s\r\n", urc_buf); //δʶ<CEB4>𵽵<EFBFBD>URC
}
at->urc_cnt = 0;
}
} else if (at->urc_cnt >= at->adap.urc_bufsize) { //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
at->urc_cnt = 0;
at->urc_item = NULL;
}
}
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ֪ͨ
* @return none
*/
static void resp_notification(at_obj_t *at, at_return ret)
{
at->ret = ret;
at->resp = NULL;
at_sem_post(at->completed);
}
/**
* @brief ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD>մ<EFBFBD><EFBFBD><EFBFBD>
* @param[in] buf - <EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] size - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><EFBFBD><EFBFBD>
* @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) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return;
if (size) {
rcv_buf = (char *)resp->recvbuf;
rcv_size = resp->bufsize;
if (at->rcv_cnt + size >= rcv_size) { //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
at->rcv_cnt = 0;
at->adap.debug("Receive overflow:%s", rcv_buf);
}
/*<2A><><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݷ<EFBFBD><DDB7><EFBFBD>rcv_buf<75><66> ---------------------------------------------*/
memcpy(rcv_buf + at->rcv_cnt, buf, size);
at->rcv_cnt += size;
rcv_buf[at->rcv_cnt] = '\0';
if (strstr(rcv_buf, resp->matcher)) { //<2F><><EFBFBD><EFBFBD>ƥ<EFBFBD><C6A5>
resp_notification(at, AT_RET_OK);
return;
} else if (strstr(rcv_buf, "ERROR")) {
resp_notification(at, AT_RET_ERROR);
return;
}
}
if (at_istimeout(at->resp_timer, resp->timeout)) //<2F><><EFBFBD>ճ<EFBFBD>ʱ
resp_notification(at, AT_RET_TIMEOUT);
else if (at->suspend) //ǿ<><C7BF><EFBFBD><EFBFBD>ֹ
resp_notification(at, AT_RET_ABORT);
}
/**
* @brief ATæ<EFBFBD>ж<EFBFBD>
* @return true - <EFBFBD><EFBFBD>ATָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
bool at_obj_busy(at_obj_t *at)
{
return !at->busy && at_istimeout(at->urc_timer, 2000);
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>AT<EFBFBD><EFBFBD>ҵ
* @return none
*/
void at_suspend(at_obj_t *at)
{
at->suspend = 1;
}
/**
* @brief <EFBFBD>ָ<EFBFBD>AT<EFBFBD><EFBFBD>ҵ
* @return none
*/
void at_resume(at_obj_t *at)
{
at->suspend = 0;
}
/**
* @brief AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return none
*/
void at_process(at_obj_t *at)
{
char buf[1];
unsigned int len;
if (!at_sem_wait(at->recv_lock, MAX_AT_LOCK_TIME))
return;
do {
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);
}

193
at.h
View File

@ -1,193 +0,0 @@
/******************************************************************************
* @brief AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD>Ź<EFBFBD><EFBFBD><EFBFBD>(OS<EFBFBD>)
*
* Copyright (c) 2020, <morro_luo@163.com>
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-01-02 Morro Initial version.
* 2021-02-01 Morro ֧<EFBFBD><EFBFBD>URC<EFBFBD>ص<EFBFBD><EFBFBD>н<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
* 2021-02-05 Morro 1.<EFBFBD>޸<EFBFBD>struct at_obj,ȥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* 2.ɾ<EFBFBD><EFBFBD> at_obj_destroy<EFBFBD>ӿ<EFBFBD>
* 2021-03-21 Morro ɾ<EFBFBD><EFBFBD>at_obj<EFBFBD>е<EFBFBD>at_work_ctx_t<EFBFBD><EFBFBD>,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>ʹ<EFBFBD><EFBFBD>
* 2021-04-08 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><EFBFBD>ͷ<EFBFBD><EFBFBD>ź<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵȴ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* 2021-05-15 Morro <EFBFBD>Ż<EFBFBD>URCƥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* 2021-07-20 Morro <EFBFBD><EFBFBD><EFBFBD>ӽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD>at_do_workʱurc<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݶ<EFBFBD>ʧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
******************************************************************************/
#ifndef _AT_H_
#define _AT_H_
#include "at_util.h"
#include <stdbool.h>
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EEB3A4> */
#define MAX_AT_CMD_LEN 128
/* <20><><EFBFBD><EFBFBD>urc<72><63><EFBFBD>ճ<EFBFBD>ʱʱ<CAB1><CAB1>*/
#define MAX_URC_RECV_TIMEOUT 300
/* ָ<><D6B8><EFBFBD><EFBFBD>URC <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD> */
#define SPEC_URC_END_MARKS ":,\r\n"
struct at_obj; /* AT<41><54><EFBFBD><EFBFBD>*/
/*AT<41><54><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6> ---------------------------------------------------------------*/
typedef enum {
AT_RET_OK = 0, /* ִ<>гɹ<D0B3>*/
AT_RET_ERROR, /* ִ<>д<EFBFBD><D0B4><EFBFBD>*/
AT_RET_TIMEOUT, /* <20><>Ӧ<EFBFBD><D3A6>ʱ*/
AT_RET_ABORT, /* δ֪<CEB4><D6AA><EFBFBD><EFBFBD>*/
}at_return;
/**
* @brief URC <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(Context) <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
typedef struct {
/**
* @brief <EFBFBD><EFBFBD><EFBFBD>ݶ<EFBFBD>ȡ<EFBFBD>ӿ<EFBFBD>
* @params buf - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @params len - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С
*/
unsigned int (*read)(void *buf, unsigned int len);
char *buf; /* <20><><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD><EFBFBD><EFBFBD> */
int bufsize; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С */
int recvlen; /* <20>ѽ<EFBFBD><D1BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>*/
} at_urc_ctx_t;
/*(Unsolicited Result Codes (URCs))<29><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ------------------------------------*/
typedef struct {
/**
* @brief urc ǰ׺(<EFBFBD><EFBFBD>"+CSQ: ")
*/
const char *prefix;
/**
* @brief urc ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<EFBFBD>ο<EFBFBD>DEF_URC_END_MARKS<EFBFBD>б<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><EFBFBD>"\n")
* @note
*/
const char *end_mark;
/**
* @brief urc<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @params ctx - URC <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
void (*handler)(at_urc_ctx_t *ctx);
}urc_item_t;
/**
* @brief AT<EFBFBD>ӿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD>ڳ<EFBFBD>ʼ<EFBFBD><EFBFBD>AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
*/
typedef struct {
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD>ӿ<EFBFBD>
*/
unsigned int (*write)(const void *buf, unsigned int len);
/**
* @brief <EFBFBD><EFBFBD><EFBFBD>ݶ<EFBFBD><EFBFBD>ӿ<EFBFBD>
*/
unsigned int (*read)(void *buf, unsigned int len);
/**
* @brief <EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD>ӡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӿ<EFBFBD>,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>NULL
*/
void (*debug)(const char *fmt, ...);
/**
* @brief urc <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>NULL
*/
urc_item_t *utc_tbl;
/**
* @brief urc<EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>NULL
*/
char *urc_buf;
/**
* @brief utc_tbl<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>0
*/
unsigned short urc_tbl_count;
/**
* @brief urc<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>0
*/
unsigned short urc_bufsize;
}at_adapter_t;
/**
* @brief AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
typedef struct {
const char *matcher; /* <20><><EFBFBD><EFBFBD>ƥ<EFBFBD>䴮 */
char *recvbuf; /* <20><><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD> */
unsigned short bufsize; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
unsigned int timeout; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱʱ<CAB1><CAB1> */
} at_respond_t;
/** work context ------------------------------------------------------------*/
/**
* @brief AT<EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(Work Context) <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
typedef struct at_work_ctx {
struct at_obj *at;
//<2F><>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD>,<2C><>at_do_work<72>ӿڴ<D3BF><DAB4><EFBFBD>
void *params;
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
unsigned int (*write)(struct at_work_ctx *self, const void *buf, unsigned int len);
/**
* @brief <EFBFBD><EFBFBD><EFBFBD>ݶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
unsigned int (*read)(struct at_work_ctx *self, void *buf, unsigned int len);
/**
* @brief <EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
void (*printf)(struct at_work_ctx *self, const char *fmt, ...);
/*
* @brief <EFBFBD>ȴ<EFBFBD><EFBFBD>ظ<EFBFBD>
* @param[in] prefix - <EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ׺(<EFBFBD><EFBFBD>"OK",">")
* @param[in] timeout - <EFBFBD>ȴ<EFBFBD><EFBFBD><EFBFBD>ʱʱ<EFBFBD><EFBFBD>
*/
at_return (*wait_resp)(struct at_work_ctx *self, const char *prefix,
unsigned int timeout);
}at_work_ctx_t;
/*AT<41><54><EFBFBD><EFBFBD> ---------------------------------------------------------------------*/
typedef struct at_obj {
at_adapter_t adap; /* <20>ӿ<EFBFBD><D3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
at_sem_t send_lock; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
at_sem_t recv_lock; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
at_sem_t completed; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ź<EFBFBD>*/
at_respond_t *resp; /* ATӦ<54><D3A6><EFBFBD><EFBFBD>Ϣ*/
const urc_item_t *urc_item; /* <20><>ǰURC<52><43>*/
unsigned int resp_timer; /* <20><>Ӧ<EFBFBD><D3A6><EFBFBD>ն<EFBFBD>ʱ<EFBFBD><CAB1>*/
unsigned int urc_timer; /* URC<52><43>ʱ<EFBFBD><CAB1> */
at_return ret; /* <20><><EFBFBD><EFBFBD>ִ<EFBFBD>н<EFBFBD><D0BD><EFBFBD>*/
unsigned short urc_cnt, rcv_cnt; /* <20><><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD>*/
unsigned char busy : 1;
unsigned char suspend: 1;
unsigned char dowork : 1;
}at_obj_t;
typedef int (*at_work)(at_work_ctx_t *);
void at_obj_init(at_obj_t *at, const at_adapter_t *adap); /* AT<41><54>ʼ<EFBFBD><CABC>*/
bool at_obj_busy(at_obj_t *at);
void at_suspend(at_obj_t *at); /* <20><><EFBFBD><EFBFBD>*/
void at_resume(at_obj_t *at); /* <20>ָ<EFBFBD>*/
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_do_work(at_obj_t *at, at_work work, void *params); /* <20>Զ<EFBFBD><D4B6><EFBFBD>AT<41><54>ҵ*/
void at_process(at_obj_t *at); /* AT<41><54><EFBFBD>մ<EFBFBD><D5B4><EFBFBD>*/
#endif

534
at_chat.c
View File

@ -1,534 +0,0 @@
/******************************************************************************
* @brief ATָ<EFBFBD><EFBFBD>ͨ<EFBFBD>Ź<EFBFBD><EFBFBD><EFBFBD>
*
* Copyright (c) 2020~2021, <morro_luo@163.com>
*
* SPDX-License-Identifier: Apathe-2.0
*
* Change Logs:
* Date Author Notes
* 2020-01-02 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* 2021-01-20 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD>debug<EFBFBD><EFBFBD><EFBFBD>Խӿ<EFBFBD>, <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƚӿ<EFBFBD>
* 2021-03-03 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>URC<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӡ<EFBFBD><EFBFBD><EFBFBD>ճ<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
******************************************************************************/
#include "at_chat.h"
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
//<2F><>ʱ<EFBFBD>ж<EFBFBD>
#define AT_IS_TIMEOUT(start, time) (AT_GET_TICK() - (start) > (time))
/**AT<41><54>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><><CAB5><EFBFBD><EFBFBD>4<EFBFBD><34><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD>) -----------------------------------*/
#define AT_TYPE_WORK 0 /* <20><>ͨ<EFBFBD><CDA8>ҵ ----------*/
#define AT_TYPE_CMD 1 /* <20><>׼<EFBFBD><D7BC><EFBFBD><EFBFBD> ----------*/
#define AT_TYPE_MULTILINE 2 /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ----------*/
#define AT_TYPE_SINGLLINE 3 /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ----------*/
#ifndef AT_DEBUG
#define AT_DEBUG(...) do {}while(0)
#endif
typedef int (*base_work)(at_obj_t *at, ...);
static void at_send_line(at_obj_t *at, const char *fmt, va_list args);
static const inline at_adapter_t *__get_adapter(at_obj_t *at)
{
return &at->adap;
}
static bool at_is_timeout(at_obj_t *at, unsigned int ms)
{
return AT_IS_TIMEOUT(at->timer, ms);
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static void send_data(at_obj_t *at, const void *buf, unsigned int len)
{
at->adap.write(buf, len);
}
/**
* @brief <EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӡ
*/
static void print(at_obj_t *at, const char *cmd, ...)
{
va_list args;
va_start(args, cmd);
at_send_line(at, cmd, args);
va_end(args);
}
/**
* @brief <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD>ݽ<EFBFBD><EFBFBD>ճ<EFBFBD><EFBFBD><EFBFBD>
*/
static unsigned int get_recv_count(at_obj_t *at)
{
return at->recv_cnt;
}
/**
* @brief <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static char *get_recv_buf(at_obj_t *at)
{
return (char *)at->adap.recv_buf;
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static void recv_buf_clear(at_obj_t *at)
{
at->recv_cnt = 0;
}
/**ǰ<><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>*/
static char *search_string(at_obj_t *at, const char *str)
{
return strstr(get_recv_buf(at), str);
}
/**
* @brief <EFBFBD><EFBFBD>ִֹ<EFBFBD><EFBFBD>
*/
static bool at_isabort(at_obj_t *at)
{
return at->cursor ? at->cursor->abort : 1;
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD>ü<EFBFBD>ʱ<EFBFBD><EFBFBD>
*/
static void at_reset_timer(at_obj_t *at)
{
at->timer = AT_GET_TICK();
}
/**
* @brief ATִ<EFBFBD>лص<EFBFBD>
*/
static void do_at_callbatk(at_obj_t *a, at_item_t *i, at_callbatk_t cb, at_return ret)
{
at_response_t r;
if ((ret == AT_RET_ERROR || ret == AT_RET_TIMEOUT) && a->adap.error != NULL)
a->adap.error();
if (cb) {
r.param = i->param;
r.recvbuf = get_recv_buf(a);
r.recvcnt = get_recv_count(a);
r.ret = ret;
cb(&r);
}
}
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
static bool add_work(at_obj_t *at, void *params, void *info, int type)
{
at_item_t *i;
if (list_empty(&at->ls_idle)) //<2F>޿<EFBFBD><DEBF><EFBFBD>at_item
return NULL;
i = list_first_entry(&at->ls_idle, at_item_t, node);//<2F>ӿ<EFBFBD><D3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>ҵ
i->info = (void *)info;
i->param = (void *)params;
i->state = AT_STATE_WAIT;
i->type = type;
i->abort = 0;
list_move_tail(&i->node, &at->ls_ready); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return i != 0;
}
/**
* @brief ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ
*/
static int do_work_handler(at_obj_t *at)
{
at_item_t *i = at->cursor;
return ((int (*)(at_env_t *e))i->info)(&at->env);
}
/**
* @brief ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] a - AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return true - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ, false - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ,
*/
static int do_cmd_handler(at_obj_t *a)
{
at_item_t *i = a->cursor;
at_env_t *e = &a->env;
const at_cmd_t *c = (at_cmd_t *)i->info;
switch(e->state) {
case 0: /*<2A><><EFBFBD><EFBFBD>״̬ ------------------------------------------------------*/
c->sender(e);
e->state++;
e->reset_timer(a);
e->recvclr(a);
break;
case 1:
if (search_string(a, c->matcher)) { //<2F><><EFBFBD><EFBFBD>ƥ<EFBFBD><C6A5>
AT_DEBUG("<-\r\n%s\r\n", get_recv_buf(a));
do_at_callbatk(a, i, c->cb, AT_RET_OK);
return true;
} else if (search_string(a, "ERROR")) {
AT_DEBUG("<-\r\n%s\r\n", get_recv_buf(a));
if (++e->i >= c->retry) {
do_at_callbatk(a, i, c->cb, AT_RET_ERROR);
return true;
}
e->state = 2; /* <20><><EFBFBD><EFBFBD>֮<EFBFBD><D6AE><EFBFBD><EFBFBD>ʱһ<CAB1><D2BB>ʱ<EFBFBD><CAB1>*/
e->reset_timer(a); /* <20><><EFBFBD>ö<EFBFBD>ʱ<EFBFBD><CAB1>*/
} else if (e->is_timeout(a, c->timeout)) { /* <20><>Ӧ<EFBFBD><D3A6>ʱ*/
if (++e->i >= c->retry) {
do_at_callbatk(a, i, c->cb, AT_RET_TIMEOUT);
return true;
}
e->state = 0; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ״̬*/
}
break;
case 2:
if (e->is_timeout(a, 500))
e->state = 0; /*<2A><><EFBFBD>س<EFBFBD>ʼ״̬*/
break;
default:
e->state = 0;
}
return false;
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] a - AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return true - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ, false - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ,
*/
static int send_signlline_handler(at_obj_t *a)
{
at_item_t *i = a->cursor;
at_env_t *e = &a->env;
const char *cmd = (const char *)i->param;
at_callbatk_t cb = (at_callbatk_t)i->info;
switch(e->state) {
case 0: /*<2A><><EFBFBD><EFBFBD>״̬ ------------------------------------------------------*/
e->printf(a, cmd);
e->state++;
e->reset_timer(a);
e->recvclr(a);
break;
case 1:
if (search_string(a, "OK")) {
AT_DEBUG("<-\r\n%s\r\n", get_recv_buf(a));
do_at_callbatk(a, i, cb, AT_RET_OK); //<2F><><EFBFBD><EFBFBD>ƥ<EFBFBD><C6A5>
return true;
} else if (search_string(a, "ERROR")) {
AT_DEBUG("<-\r\n%s\r\n", get_recv_buf(a));
if (++e->i >= 3) {
do_at_callbatk(a, i, cb, AT_RET_ERROR);
return true;
}
e->state = 2; /*<2A><><EFBFBD><EFBFBD>֮<EFBFBD><D6AE><EFBFBD><EFBFBD>ʱһ<CAB1><D2BB>ʱ<EFBFBD><CAB1>*/
e->reset_timer(a); /*<2A><><EFBFBD>ö<EFBFBD>ʱ<EFBFBD><CAB1>*/
} else if (e->is_timeout(a, 3000 + e->i * 2000)) {
if (++e->i >= 3) {
do_at_callbatk(a, i, cb, AT_RET_TIMEOUT);
return true;
}
e->state = 0; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ״̬*/
}
break;
case 2:
if (e->is_timeout(a, 500))
e->state = 0; /**<2A><><EFBFBD>س<EFBFBD>ʼ״̬*/
break;
default:
e->state = 0;
}
return false;
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] a - AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return true - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ, false - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ,
*/
static int send_multiline_handler(at_obj_t *a)
{
at_item_t *i = a->cursor;
at_env_t *e = &a->env;
const char **cmds = (const char **)i->param;
at_callbatk_t cb = (at_callbatk_t)i->info;
switch(e->state) {
case 0:
if (cmds[e->i] == NULL) { /**<2A><><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
do_at_callbatk(a, i, cb, AT_RET_OK);
return true;
}
e->printf(a, "%s\r\n", cmds[e->i]);
e->recvclr(a); /**<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
e->reset_timer(a);
e->state++;
break;
case 1:
if (search_string(a, "OK")) {
e->state = 0;
e->i++;
e->j = 0;
AT_DEBUG("<-\r\n%s\r\n", get_recv_buf(a));
} else if (search_string(a, "ERROR")) {
AT_DEBUG("<-\r\n%s\r\n", get_recv_buf(a));
if (++e->j >= 3) {
do_at_callbatk(a, i, cb, AT_RET_ERROR);
return true;
}
e->state = 2; /*<2A><><EFBFBD><EFBFBD>֮<EFBFBD><D6AE><EFBFBD><EFBFBD>ʱһ<CAB1><D2BB>ʱ<EFBFBD><CAB1>*/
e->reset_timer(a); /*<2A><><EFBFBD>ö<EFBFBD>ʱ<EFBFBD><CAB1>*/
} else if (e->is_timeout(a, 3000)) {
do_at_callbatk(a, i, cb, AT_RET_TIMEOUT);
return true;
}
break;
case 2:
if (e->is_timeout(a, 500))
e->state = 0; /**<2A><><EFBFBD>س<EFBFBD>ʼ״̬*/
break;
default:
e->state = 0;
}
return 0;
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] fmt - <EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] args - <EFBFBD>ɱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>
*/
static void at_send_line(at_obj_t *at, const char *fmt, va_list args)
{
char buf[MAX_AT_CMD_LEN];
int len;
const at_adapter_t *adt = __get_adapter(at);
len = vsnprintf(buf, sizeof(buf), fmt, args);
recv_buf_clear(at); //<2F><><EFBFBD>ս<EFBFBD><D5BD>ջ<EFBFBD><D5BB><EFBFBD>
send_data(at, buf, len);
send_data(at, "\r\n", 2);
AT_DEBUG("->\r\n%s\r\n", buf);
}
/**
* @brief urc(unsolicited code) <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] urc - <EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] size - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С
* @return none
*/
static void urc_handler_entry(at_obj_t *at, char *urc, unsigned int size)
{
int i, n;
utc_item_t *tbl = at->adap.utc_tbl;
for (i = 0; i < at->adap.urc_tbl_count; i++, tbl++) {
n = strlen(tbl->prefix);
if (strncmp(urc, tbl->prefix, n) == 0) { /* ƥ<><C6A5>ǰ׺ */
tbl->handler(urc, size); /* <20>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD>*/
break;
}
}
if (at->cursor == NULL)
AT_DEBUG("<=\r\n%s\r\n", urc);
}
/**
* @brief urc <EFBFBD><EFBFBD><EFBFBD>մ<EFBFBD><EFBFBD><EFBFBD>
* @param[in] buf - <EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return none
*/
static void urc_recv_process(at_obj_t *at, char *buf, unsigned int size)
{
char *urc_buf;
int ch;
unsigned short urc_size;
urc_buf = (char *)at->adap.urc_buf;
urc_size = at->adap.urc_bufsize;
if (size == 0 && at->urc_cnt > 0) {
if (AT_IS_TIMEOUT(at->urc_timer, 2000)) { /* <20><><EFBFBD>ճ<EFBFBD>ʱ*/
urc_handler_entry(at, urc_buf, at->urc_cnt);
if (at->urc_cnt > 1)
AT_DEBUG("Urc recv timeout.\r\n");
at->urc_cnt = 0;
}
} else if (urc_buf != NULL){
at->urc_timer = AT_GET_TICK();
while (size--) {
ch = *buf++;
urc_buf[at->urc_cnt++] = ch;
if (ch == '\n' || ch == '\r' || ch == '\0') { /*urc<72><63><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
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 if (at->urc_cnt >= urc_size) /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
at->urc_cnt = 0;
}
}
}
/**
* @brief ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD><EFBFBD>մ<EFBFBD><EFBFBD><EFBFBD>
* @return none
*/
static void resp_recv_process(at_obj_t *at, const char *buf, unsigned int size)
{
char *recv_buf;
unsigned short recv_size;
recv_buf = (char *)at->adap.recv_buf;
recv_size = at->adap.recv_bufsize;
if (at->recv_cnt + size >= recv_size) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
at->recv_cnt = 0;
memcpy(recv_buf + at->recv_cnt, buf, size);
at->recv_cnt += size;
recv_buf[at->recv_cnt] = '\0';
}
/**
* @brief AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>
* @param[in] at - AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] adap - AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
void at_obj_init(at_obj_t *at, const at_adapter_t *adap)
{
int i;
at_env_t *e;
at->adap = *adap;
e = &at->env;
at->recv_cnt = 0;
e->is_timeout = at_is_timeout;
e->printf = print;
e->recvbuf = get_recv_buf;
e->recvclr = recv_buf_clear;
e->recvlen = get_recv_count;
e->find = search_string;
e->abort = at_isabort;
e->reset_timer = at_reset_timer;
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>*/
INIT_LIST_HEAD(&at->ls_idle);
INIT_LIST_HEAD(&at->ls_ready);
for (i = 0; i < sizeof(at->items) / sizeof(at_item_t); i++)
list_add_tail(&at->items[i].node, &at->ls_idle);
while (adap->recv_buf == NULL) {} //ȷ<><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>ǿ<EFBFBD>
}
/**
* @brief ִ<EFBFBD><EFBFBD>AT<EFBFBD><EFBFBD>ҵ(<EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ)
* @param[in] a - AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] work - AT<EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] params -
*/
bool at_do_work(at_obj_t *at, int (*work)(at_env_t *e), void *params)
{
return add_work(at, params, (void *)work, AT_TYPE_WORK);
}
/**
* @brief ִ<EFBFBD><EFBFBD>ATָ<EFBFBD><EFBFBD>
* @param[in] a - AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] cmd - cmd<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
bool at_do_cmd(at_obj_t *at, void *params, const at_cmd_t *cmd)
{
return add_work(at, params, (void *)cmd, AT_TYPE_CMD);
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD>AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD>(Ĭ<EFBFBD>ϵȴ<EFBFBD>OK<EFBFBD><EFBFBD><EFBFBD><EFBFBD>, 3s<EFBFBD><EFBFBD>ʱ)
* @param[in] at - AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] cb - ִ<EFBFBD>лص<EFBFBD>
* @param[in] singlline - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @note <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮ǰ,singlline<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч
*/
bool at_send_singlline(at_obj_t *at, at_callbatk_t cb, const char *singlline)
{
return add_work(at, (void *)singlline, (void *)cb, AT_TYPE_SINGLLINE);
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD>Ͷ<EFBFBD><EFBFBD><EFBFBD>AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڳ<EFBFBD>ʼ<EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD>, Ĭ<EFBFBD>ϵȴ<EFBFBD>OK<EFBFBD><EFBFBD><EFBFBD><EFBFBD>, 3s<EFBFBD><EFBFBD>ʱ)
* @param[in] at - AT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] cb - ִ<EFBFBD>лص<EFBFBD>
* @param[in] multiline - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @note <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮ǰ,multiline
*/
bool at_send_multiline(at_obj_t *at, at_callbatk_t cb, const char **multiline)
{
return add_work(at, multiline, (void *)cb, AT_TYPE_MULTILINE);
}
/**
* @brief ǿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹAT<EFBFBD><EFBFBD>ҵ
*/
void at_item_abort(at_item_t *i)
{
i->abort = 1;
}
/**
* @brief ATæ<EFBFBD>ж<EFBFBD>
* @return true - <EFBFBD><EFBFBD>ATָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
bool at_obj_busy(at_obj_t *at)
{
return !list_empty(&at->ls_ready);
}
/**
* @brief AT<EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static void at_work_manager(at_obj_t *at)
{
at_env_t *e = &at->env;
/*<2A><>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD> --------------------------------------------------------------*/
static int (*const work_handler_table[])(at_obj_t *) = {
do_work_handler,
do_cmd_handler,
send_multiline_handler,
send_signlline_handler
};
if (at->cursor == NULL) {
if (list_empty(&at->ls_ready)) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>
return;
e->i = 0;
e->j = 0;
e->state = 0;
at->cursor = list_first_entry(&at->ls_ready, at_item_t, node);
e->params = at->cursor->param;
e->recvclr(at);
e->reset_timer(at);
}
/* <20><><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EBB5BD><EFBFBD>й<EFBFBD><D0B9><EFBFBD><EFBFBD><EFBFBD> -------------------------------------*/
if (work_handler_table[at->cursor->type](at) || at->cursor->abort) {
list_move_tail(&at->cursor->node, &at->ls_idle);
at->cursor = NULL;
}
}
/**
* @brief AT<EFBFBD><EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
void at_poll_task(at_obj_t *at)
{
char rbuf[32];
int read_size;
read_size = __get_adapter(at)->read(rbuf, sizeof(rbuf));
urc_recv_process(at, rbuf, read_size);
resp_recv_process(at, rbuf, read_size);
at_work_manager(at);
}

148
at_chat.h
View File

@ -1,148 +0,0 @@
/******************************************************************************
* @brief ATָ<EFBFBD><EFBFBD>ͨ<EFBFBD>Ź<EFBFBD><EFBFBD><EFBFBD>
*
* Copyright (c) 2020~2021, <morro_luo@163.com>
*
* SPDX-License-Identifier: Apathe-2.0
*
* Change Logs:
* Date Author Notes
* 2020-01-02 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* 2021-01-20 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD>debug<EFBFBD><EFBFBD><EFBFBD>Խӿ<EFBFBD>, <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƚӿ<EFBFBD>
* 2021-03-03 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>URC<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӡ<EFBFBD><EFBFBD><EFBFBD>ճ<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
******************************************************************************/
#ifndef _ATCHAT_H_
#define _ATCHAT_H_
#include <list.h>
#include <stdbool.h>
/*<2A><><EFBFBD><EFBFBD>AT<41><54><EFBFBD><EFBFBD><EEB3A4> --------------------------------------------------------------*/
#define MAX_AT_CMD_LEN 128
/* debug <20><>ӡ<EFBFBD>ӿ<EFBFBD> ------------------------------------------------------------*/
#include <stdio.h>
#define AT_DEBUG(...) printf("[AT]:");printf(__VA_ARGS__) /*do{}while(0)*/
/* <20><>ȡϵͳ<CFB5>δ<EFBFBD>(ms) -----------------------------------------------------------*/
#include "platform.h"
#define AT_GET_TICK() get_tick()
struct at_obj;
/*urc<72><63><EFBFBD><EFBFBD><EFBFBD><EFBFBD> -----------------------------------------------------------------*/
typedef struct {
const char *prefix; //<2F><>Ҫƥ<D2AA><C6A5><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7>
void (*handler)(char *recvbuf, int size);
}utc_item_t;
/*AT<41>ӿ<EFBFBD><D3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ---------------------------------------------------------------*/
typedef struct {
unsigned int (*write)(const void *buf, unsigned int len); /* <20><><EFBFBD>ͽӿ<CDBD>*/
unsigned int (*read)(void *buf, unsigned int len); /* <20><><EFBFBD>սӿ<D5BD>*/
void (*error)(void); /* ATִ<54><D6B4><EFBFBD><EFBFBD>¼<EFBFBD>*/
utc_item_t *utc_tbl; /* urc <20><>*/
unsigned char *urc_buf; /* urc<72><63><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>*/
unsigned char *recv_buf; /* <20><><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD><EFBFBD><EFBFBD>*/
unsigned short urc_tbl_count; /* urc<72><63><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
unsigned short urc_bufsize; /* urc<72><63><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С*/
unsigned short recv_bufsize; /* <20><><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С*/
}at_adapter_t;
/*AT<41><54>ҵ<EFBFBD><D2B5><EFBFBD>л<EFBFBD><D0BB><EFBFBD>*/
typedef struct {
int i,j,state;
void *params;
void (*reset_timer)(struct at_obj *at);
bool (*is_timeout)(struct at_obj *at, unsigned int ms); /*ʱ<><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>*/
void (*printf)(struct at_obj *at, const char *fmt, ...);
char * (*find)(struct at_obj *at, const char *expect);
char * (*recvbuf)(struct at_obj *at); /* ָ<><D6B8><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>*/
unsigned int(*recvlen)(struct at_obj *at); /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܳ<EFBFBD><DCB3><EFBFBD>*/
void (*recvclr)(struct at_obj *at); /* <20><><EFBFBD>ս<EFBFBD><D5BD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>*/
bool (*abort)(struct at_obj *at); /* <20><>ִֹ<D6B9><D6B4>*/
}at_env_t;
/*AT<41><54><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6>*/
typedef enum {
AT_RET_OK = 0, /* ִ<>гɹ<D0B3>*/
AT_RET_ERROR, /* ִ<>д<EFBFBD><D0B4><EFBFBD>*/
AT_RET_TIMEOUT, /* <20><>Ӧ<EFBFBD><D3A6>ʱ*/
AT_RET_ABORT, /* ǿ<><C7BF><EFBFBD><EFBFBD>ֹ*/
}at_return;
/*AT<41><54>Ӧ */
typedef struct {
void *param;
char *recvbuf; /* <20><><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>*/
unsigned short recvcnt; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>*/
at_return ret; /* ATִ<54>н<EFBFBD><D0BD><EFBFBD>*/
}at_response_t;
typedef void (*at_callbatk_t)(at_response_t *r); /* AT ִ<>лص<D0BB>*/
/*AT״̬ (<28><>ǰ<EFBFBD>汾δ<E6B1BE><CEB4>) ------------------------------------------------------*/
typedef enum {
AT_STATE_IDLE, /* <20><><EFBFBD><EFBFBD>״̬*/
AT_STATE_WAIT, /* <20>ȴ<EFBFBD>ִ<EFBFBD><D6B4>*/
AT_STATE_EXEC, /* <20><><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4>*/
}at_work_state;
/*AT<41><54>ҵ<EFBFBD><D2B5>*/
typedef struct {
unsigned int state : 3;
unsigned int type : 3; /* <20><>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD>*/
unsigned int abort : 1;
void *param; /* ͨ<>ò<EFBFBD><C3B2><EFBFBD>*/
void *info; /* ͨ<><CDA8><EFBFBD><EFBFBD>Ϣָ<CFA2><D6B8>*/
struct list_head node; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
}at_item_t;
/*AT<41><54><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ------------------------------------------------------------------*/
typedef struct at_obj{
at_adapter_t adap;
at_env_t env; /* <20><>ҵ<EFBFBD><D2B5><EFBFBD>л<EFBFBD><D0BB><EFBFBD>*/
at_item_t items[10]; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>10<31><30><EFBFBD><EFBFBD>ҵ*/
at_item_t *cursor; /* <20><>ǰ<EFBFBD><C7B0>ҵ<EFBFBD><D2B5>*/
struct list_head ls_ready, ls_idle; /* <20><><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><D2B5>*/
unsigned int timer;
unsigned int urc_timer; /* urc<72><63><EFBFBD>ռ<EFBFBD>ʱ<EFBFBD><CAB1>*/
at_return ret;
//urc<72><63><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD>
unsigned short urc_cnt, recv_cnt;
unsigned char suspend: 1;
}at_obj_t;
typedef struct {
void (*sender)(at_env_t *e); /*<2A>Զ<EFBFBD><D4B6><EFBFBD><E5B7A2><EFBFBD><EFBFBD> */
const char *matcher; /*<2A><><EFBFBD><EFBFBD>ƥ<EFBFBD>䴮 */
at_callbatk_t cb; /*<2A><>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD> */
unsigned char retry; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD> */
unsigned short timeout; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱʱ<CAB1><CAB1> */
}at_cmd_t;
void at_obj_init(at_obj_t *at, const at_adapter_t *);
bool at_send_singlline(at_obj_t *at, at_callbatk_t cb, const char *singlline);
bool at_send_multiline(at_obj_t *at, at_callbatk_t cb, const char **multiline);
bool at_do_cmd(at_obj_t *at, void *params, const at_cmd_t *cmd);
bool at_do_work(at_obj_t *at, int (*work)(at_env_t *e), void *params);
void at_item_abort(at_item_t *it); /*<2A><>ֹ<EFBFBD><D6B9>ǰ<EFBFBD><C7B0>ҵ*/
bool at_obj_busy(at_obj_t *at); /*æ<>ж<EFBFBD>*/
void at_suspend(at_obj_t *at);
void at_resume(at_obj_t *at);
void at_poll_task(at_obj_t *at);
#endif

View File

@ -1,82 +0,0 @@
/******************************************************************************
* @brief atģ<EFBFBD><EFBFBD>OS<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֲ<EFBFBD>ӿ<EFBFBD>
*
* Copyright (c) 2020, <morro_luo@163.com>
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-01-02 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
******************************************************************************/
#ifndef _ATUTIL_H_
#define _ATUTIL_H_
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
typedef void *at_sem_t; /*<2A>ź<EFBFBD><C5BA><EFBFBD>*/
/*
* @brief <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>ǰϵͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static inline unsigned int at_get_ms(void)
{
/*Add here...*/
return 0;
}
/*
* @brief <EFBFBD><EFBFBD>ʱ<EFBFBD>ж<EFBFBD>
* @retval true | false
*/
static inline bool at_istimeout(unsigned int start_time, unsigned int timeout)
{
return at_get_ms() - start_time > timeout;
}
/*
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ
* @retval none
*/
static inline void at_delay(uint32_t ms)
{
}
/*
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ź<EFBFBD>
* @retval none
*/
static inline at_sem_t at_sem_new(int value)
{
return NULL;
}
/*
* @brief <EFBFBD>ȴ<EFBFBD><EFBFBD>ź<EFBFBD>
* @retval none
*/
static inline bool at_sem_wait(at_sem_t s, uint32_t timeout)
{
return false;
}
/*
* @brief <EFBFBD>ͷ<EFBFBD><EFBFBD>ź<EFBFBD>
* @retval none
*/
static inline void at_sem_post(at_sem_t s)
{
}
/*
* @brief <EFBFBD><EFBFBD><EFBFBD>ٵ<EFBFBD><EFBFBD>ź<EFBFBD>
* @retval none
*/
static inline void at_sem_free(at_sem_t s)
{
}
#endif

0
docs/.nojekyll Normal file
View File

553
docs/Expert.md Normal file
View File

@ -0,0 +1,553 @@
# 高级教程
了解完一般命令处理之后下面我们来讲一下一些特殊场景下的AT命令请求及其处理方式以及了解处理这些请求涉及到的相关概念和接口同时我也会详细说明有关URC消息处理办法和在OS上的应用。
本节导读如下:
- 组合命令处理
- 自定义AT作业
- URC消息处理
- 多实例并存
- AT作业上下文
- OS应用之异步转同步
- 内存监视器
## 组合命令处理
在一些场景下主机与从机之前间需要通过组合命令来交换信息即主机与从机间完成一次业务需要进行多次命令交互例如sms收发socket数据收发不同模组产商命令可能是不一样的下面是几个组合命令的例子。
发送短信流程(参考SIM900A模组)
```shell
主机 =>
AT+CMGS=<Phone numer> + \x1A //发送目标手机号+ctrl+z
从机 <=
'<' //从机回复提示符'<'
主机 =>
<sms message> //发送短信内容
从机 <=
OK //从机回复OK
```
发送Socket数据流程(参考移远EC21模组)
```shell
主机 =>
AT+QISEND=<connectID><send_length>
从机 <=
'<' //从机回复提示符'<'
主机 =>
<data> //发送二进制数据内容
\x1A //发送CTRL+z启动发送
从机 <=
OK //从机回复OK
```
发送TCP Socket数据流程(参考Sierra 模组)
```shell
主机 =>
AT+KTCPSND=<session>,<send_length>
从机 <=
'CONNECT' //从机回复提示符'CONNECT'
主机 =>
<data> //发送二进制数据内容
"--EOF--Pattern--"" //发送结束符
从机 <=
OK //从机回复OK
```
接收TCP Socket数据(参考Sierra 模组)
```shell
主机 =>
AT+KTCPRCV=<session_id>,<recv_length>
从机 <=
'CONNECT' //从机回复提示符'CONNECT'
<data> //二进制数据内容
"--EOF--Pattern--"" //结束符
OK //状态码
```
组合命令与一般AT命令最大的不同体现在命令交互的流程结构上它们进行一次通信(数据)业务时需要交互2次或多次以上所以软件设计需要考虑并发冲突的可能因为在进行某项业务交互时如果需要进行两次AT命令请求才能完成有可能在进行第一次时过程中就被其它命令穿插打断了从而造成该项业务执行失败。
对于这个问题除了利用OS的锁解决之外还可以利用自定义作业来处理它允许你在一个AT作业中进行多次命令交互同时能够让应用层自行控制命令收发流程。
## 自定义AT作业
自定义AT作业使用`at_work_t`表示,它实际是一个状态机轮询程序,通过'at_env_t'参数提供了基本的状态变量数据收发超时管理等接口。除了能用来收发命令之外你甚至可以用它来控制硬件IO,例如有时序控制要求开关机操作,这样做也有利于处理设备状态同步的问题。
**原型定义如下:**
```c
/**
*@brief AT作业轮询处理程序
*@param env AT作业的公共运行环境包括一些通用的变量和进行AT命令通信所需的相关接口。
*@return 作业处理状态, 它决定了是否在下一个循环中是否继续运行该作业。
* @arg true 指示当前作业已经处理完成可以被中止同时作业的状态码会被设置为AT_RESP_OK。
* @arg false 指示当前作业未处理完成,继续运行。
*@note 需要注意的是如果在当前作业中执行了env->finish()操作,则作业立即终止运行。
*/
typedef int (*at_work_t)(at_env_t *env);
```
其中:
`at_env_t` 定义了一些通信上下文环境相关接口与公共状态变量,通过它你可以实现自己的通信交互逻辑。
```c
/**
* @brief AT作业公共运行环境
*/
typedef struct at_env {
struct at_obj *obj;
//公共状态(根据需要添加),每次新作业启动时,这些值会被重置
int i, j, state;
//附属参数(引用自->at_attr_t)
void *params;
//设置下一个轮询等待间隔(只生效1次)
void (*next_wait)(struct at_env *self, unsigned int ms);
//复位计时器
void (*reset_timer)(struct at_env *self);
//作业超时判断
bool (*is_timeout)(struct at_env *self, unsigned int ms);
//带换行的格式化打印输出
void (*println)(struct at_env *self, const char *fmt, ...);
//接收内容包含判断
char * (*contains)(struct at_env *self, const char *str);
//获取接收缓冲区
char * (*recvbuf)(struct at_env *self);
//获取接收缓冲区长度
unsigned int(*recvlen)(struct at_env *self);
//清空接收缓冲区
void (*recvclr)(struct at_env *self);
//指示当前作业是否已被强行终止
bool (*disposing)(struct at_env *self);
//结束作业,并设置响应码
void (*finish)(struct at_env *self, at_resp_code code);
} at_env_t;
```
**示例1:(Sierra 模组发送socket数据)**
命令格式:
```shell
主机 =>
AT+KTCPSND=<session>,<send_length>
从机 <=
'CONNECT' //从机回复提示符'CONNECT'
主机 =>
<data> //发送二进制数据内容
"--EOF--Pattern--"" //发送结束符
从机 <=
OK //从机回复OK
```
**代码实现:**
```c
//socket定义
typedef struct {
//....
int id;
unsigned char *sendptr;
int sendcnt;
//...
}socket_t;
/*
* @brief socket 数据发送处理
* @return true - 结束运行 false - 保持运行
*/
static int socket_send_handler(at_env_t *env)
{
socket_t *sk = (socket_t *)env->params;
switch (env->state) {
case 0:
env->println(env, "AT+KTCPSND=%d,%d", sk->id, sk->sendcnt);
env->reset_timer(env); /*重置定时器*/
env->state++;
break;
case 1:
if (env->contains(env, "CONNECT")) {
env->obj->adap->write(sk->sendptr, sk->sendcnt); /*发送数据*/
env->println(env, "--EOF--Pattern--"); /*发送结束符*/
env->reset_timer(env);
env->recvclr(env);
env->state++;
} else if (env->contains(env, "ERROR")) { /*匹配到错误,结束作业*/
env->finish(env, AT_RESP_ERROR);
} else if (env->is_timeout(env, 1000)) {
if (++env->i > 3) {
env->finish(env, AT_RESP_ERROR);
}
env->state--; /*重新发送*/
}
break;
case 2:
if (env->contains(env, "OK"))
env->finish(env, AT_RESP_OK); /*发送成功设置状态为OK后退出*/
else if (env->contains(env, "ERROR") ||
env->is_timeout(env, 1000)) {
env->finish(env, AT_RESP_ERROR);
}
break;
}
return 0;
}
/**
* @brief socket数据发送请求
*/
static void sock_send_data(socket_t *sock)
{
at_do_work(at_obj, sock, socket_send_handler);
}
```
## URC消息处理
未经请求主动上报的消息又称URC(Unsolicited Result Code),在主机方未下发送命令请求的情况下,设备会根据自身的运行状态或者事件主动上报消息给主机。
根据URC消息格式的不同,可以分为以下几类:
1. 对于大多数URC消息通常是单行输出的一般是以“+”为前缀,回车换行结束,例如:
```c
+SIM: 1 \r\n //SIM卡状态
+CREG: 1,"24A4","000012CF",1\r\n //网络注册状态更新
```
2. 也有不带前缀'+'的URC
```c
RDY \r\n //开机就绪
```
```c
WIFI DISCONNECTED //WIFI断开
```
3. 非回车换行结束的URC
socket数据接收(参考sim800 模组)。
```c
+IPD,<socket id>,<data length>:<bin data>
```
可以看到每个URC消息都有其特定的前缀信息前两类是以'\n'作为结束符的最后一种只有前缀而整个URC消息帧是可变长度的没有特定的结束符。那么该如何将这几类消息识别并提取出来的呢实际上URC处理程序也是通过匹配"前缀"+"结束符"的方式来提取URC消息的对于前两种消息它们都有特定的结束符('\n'),只要匹配到消息"前缀"+"后缀"就可以将整条消息完整的提取出来而对于最后一种消息由于没有固定的结束符而且消息长度是可变的所以URC处理程序无法一次性将整条消息匹配并提取出来往往需要分成多次进行第一次是匹配它的头部信息然后再由订阅者(通过回调)告诉它剩余待接收的数据长度当剩余数据长度为0时则该则URC消息接收完毕。这种处理方法其实同样也适用于前两类URC不过这些消息的剩余数据长度为0罢了。
如下所示我们可以把第3类URC消息拆分成两部分看待固定头部+剩余数据。
![带二进制URC消息](images/urcbin.png)
由于URC具有一定的随机性所以URC处理程序会实时读取来自设备端的上报的信息然后再进行消息匹配处理。至于匹配哪种URC消息则是由用户通过`at_obj_set_urc`设置的表来决定的。另外考虑到性能的原因URC处理程序不会一接收到任何一个字符都会启动匹配程序工作而是遇到`AT_URC_END_MARKS`中规定的字符才会触发执行。
下面是`at_obj_set_urc`原型:
```c
/**
* @brief Set the AT urc table.
*/
void at_obj_set_urc(at_obj_t *at, const urc_item_t *tbl, int count);
```
### URC处理项(urc_item_t)
URC表的基本单位是`urc_item_t`,它用于描述每一条URC消息的处理规则包括了消息头结束标志还有该消息的处理程序。
```c
/**
* @brief urc处理项
*/
typedef struct {
const char *prefix; /* 需要匹配的帧前缀,如+CSQ:25,*/
const char endmark; /* urc结束标志(参考@AT_URC_END_MARKS*/
/**
* @brief urc处理程序(prefix与endmark满足时触发)
* @params ctx - 上下文(Context)
* @return 表示当前URC帧剩余未接收字节数
* @arg 0 当前URC帧已接收完成,可以接收下一个URC
* @arg n 仍需要等待接收n个字节(AT管理器继续接收剩余数据并继续回调此接口)
*/
int (*handler)(at_urc_ctx_t *ctx);
} urc_item_t;
```
其中`at_urc_ctx_t`存储URC的接收状态和数据。
```c
/**
* @brief URC 上下文(Context) 定义
*/
typedef struct {
urc_recv_state state; /* urc接收状态*/
char *urcbuf; /* urc数据缓冲区 */
int urclen; /* urc缓冲区已接收数据长度*/
} at_urc_ctx_t;
```
**示例1(WIFI断开连接)**
消息格式:
```c
WIFI DISCONNECTED <\r\n>
```
代码实现:
```c
/**
* @brief wifi断开事件
*/
static int wifi_connected_handler(at_urc_info_t *info)
{
printf("WIFI connection detected...\r\n");
return 0;
}
//...
/**
* @brief urc订阅表
*/
static const urc_item_t urc_table[] =
{
//其它URC...
{.prefix = "WIFI DISCONNECTED", .endmark = '\n', .handler = wifi_connected_handler}
};
```
**示例2(socket数据接收)**
URC消息格式:
```c
+IPD,<socket id>,<data length>:.....
```
代码实现:
```c
/**
* @brief socket数据接收处理
*/
static int urc_socket_data_handler(at_urc_info_t *ctx)
{
int length, total_length, sockid, i;
char *data;
if (sscanf(ctx->urcbuf, "+IPD,%d,%d:", &sockid, &length) == 2) { //解析出总数据长度
data = strchr(ctx->urcbuf, ':');
if (data == NULL)
return 0;
data++;
total_length = (data - ctx->urcbuf) + length; //计算头部长度
if (ctx->urclen < total_length) { //未接收全,返回剩余待接收数据
printf("Need to receive %d more bytes\r\n", total_length - ctx->urclen);
return total_length - ctx->urclen;
}
printf("%d bytes of data were received form socket %d!\r\n", length, sockid);
}
return 0;
}
//....
/**
* @brief urc订阅表
*/
static const urc_item_t urc_table[] =
{
//其它URC...
{.prefix = "+IPD,", .endmark = ':', .handler = urc_socket_data_handler}
};
```
## 多实例并存
AT通信对象并不只限于一个, at_obj_create允许你在同一个系统中创建多个共存的AT通信设备而且每个都拥有自己独立的用于配置和资源.
```c
//wifi 适配器
const at_adapter_t adap_wifi = {
//...
};
//modem适配器
const at_adapter_t adap_modem = {
//...
};
//...
at_obj_t *at_modem = at_obj_create(&modem_adapter);
at_obj_t *at_wifi = at_obj_create(&wifi_adapter);
//...
//轮询任务
/**
* @brief AT轮询程序
*/
void at_device_process(void)
{
static unsigned int timer = 0;
//(为了加快AT命令处理响应速度,建议5ms以内轮询一次)
if (at_get_ms() - timer > 5) {
timer = at_get_ms();
at_obj_process(at_modem);
at_obj_process(at_wifi);
}
}
```
## AT作业上下文(at_context_t)
使用异步的一个弊端是它会让程序执行状态过于分散增加程序编码和理解难度。比如一些代码需要根据异步的结果来执行下一步动作一般是在异步回调中添加对应的状态标识然后主程序根据这些状态标识来控制状态机或者程序分支的跳转这使得代码间没有明显的流程线代码执行流不好追踪管理。那么在不使用同步或者不支持OS的情况下如何避免异步带来的状态分散问题? 一种比较常用的方式是使用状态机轮询法,通过实时查询每一个异步请求的状态,并根据根据上一个结果执行下一个请求,这样代码执行上下文就紧密衔接在一块了,达到类似同步的效果。
对于异步AT请求可以使用`at_context_t`获取其实时信息包含当前的作业运行状态命令执行结果及命令响应信息。使用AT上下文相关功能需要先启用`AT_WORK_CONTEXT_EN`宏, 相关API定义如下
| 函数原型 | 说明 |
| ------------------------------------------------------------ | ------------------------------------------------ |
| void at_context_init(at_context_t *ctx, void *respbuf, unsigned bufsize); | 初始化一个`at_context_t`同时设置命令接收缓冲区。 |
| void at_context_attach(at_attr_t *attr, at_context_t *ctx); | 将`at_context_t`绑定到AT属性中。 |
| at_work_state at_work_get_state(at_context_t *ctx); | 通过`at_context_t`获取AT作业运行状态。 |
| bool at_work_is_finish(at_context_t *ctx); | 通过`at_context_t`获取AT作业完成状态。 |
| at_resp_code at_work_get_result(at_context_t *ctx); | 通过`at_context_t`获取AT请求状态码。 |
## OS应用之异步转同步
如果是在OS环境下使用很多时候我们更希望采用同步的方式执行AT命令请求即原地等待命令执行完成下面介绍两种异步转同步的方式。
### 轮询方式
轮询方式主要是基于`at_context_t`实现的,发送请求前通过绑定一个`at_context_t`实时监视命令的执行状态,然后循环检测命令是否执行完成。
示例:
```c
/**
* @brief 发送命令(同步方式)
* @param respbuf 响应缓冲区
* @param bufsize 缓冲区大小
* @param timeout 超时时间
* @param cmd 命令
* @retval 命令执行状态
*/
static at_resp_code at_send_cmd_sync(char *respbuf, int bufsize, int timeout, const char *cmd, ...)
{
at_attr_t attr;
at_context_t ctx;
va_list args;
bool ret;
//属性初始化
at_attr_deinit(&attr);
attr.timeout = timeout;
attr.retry = 1;
//初始化context,并设置响应缓冲区
at_context_init(&ctx, respbuf, bufsize);
//为工作项绑定context
at_context_attach(&attr, &ctx);
va_start(args, cmd);
ret = at_exec_vcmd(at_obj, &attr, cmd, args);
va_end(args);
if (!ret) {
return AT_RESP_ERROR;
}
//等待命令执行完毕
while (!at_work_is_finish(&ctx)) {
usleep(1000);
}
return at_work_get_result(&ctx);
}
```
### 信号量方式
使用轮询方式会造成CPU空转可以通过使用信号量来优化不过实现起来比轮询方式要稍微复杂一些
示例:
```c
//...
#include "at_chat.h"
#include <pthread.h>
#include <semaphore.h>
typedef struct {
pthread_mutex_t cmd_lock; //命令锁
sem_t sem_finish; //完成信号
char *recvbuf; //命令接收缓冲区
unsigned short bufsize; //缓冲区大小
unsigned short recvcnt; //接收计数器
at_resp_code resp_code; //命令响应码
} at_watch_t;
static at_watch_t at_watch;
/**
* @brief 命令锁及信号相关初始化
*/
void at_sync_init(void)
{
sem_init(&at_watch.sem_finish, 0, 0);
pthread_mutex_init(&at_watch.cmd_lock, NULL);
}
/**
* @brief AT命令响应处理
*/
static void at_callback_handler(at_response_t *r)
{
int cnt = r->recvcnt;
at_watch.resp_code = r->code;
if (at_watch.recvbuf != NULL) {
if (cnt > at_watch.bufsize) {
//接收缓存不足
cnt = at_watch.bufsize;
}
memcpy(at_watch.recvbuf, r->recvbuf, cnt);
at_watch.recvcnt = cnt;
}
//通知命令已执行完毕
sem_post(&at_watch.sem_finish);
}
/**
* @brief 发送命令(同步方式)
* @param respbuf 响应缓冲区
* @param bufsize 缓冲区大小
* @param timeout 超时时间
* @param cmd 命令
* @retval 命令执行状态
*/
static at_resp_code at_send_cmd_sync(char *respbuf, int bufsize, int timeout, const char *cmd, ...)
{
at_attr_t attr;
va_list args;
bool ret;
//属性初始化
at_attr_deinit(&attr);
attr.timeout = timeout;
attr.retry = 1;
attr.cb = at_callback_handler;
va_start(args, cmd);
pthread_mutex_lock(&gw.sync_cmd_lock);
//设置接收缓冲区
at_watch.recvbuf = respbuf;
at_watch.bufsize = bufsize;
at_watch.recvcnt = 0;
at_watch.resp_code = AT_RESP_ERROR;
if (at_exec_vcmd(at_obj, &attr, cmd, args)) {
sem_wait(&at_watch.sem_finish); //等待命令执行完成
}
pthread_mutex_unlock(&gw.sync_cmd_lock);
va_end(args);
return at_watch.resp_code;
}
```
## 内存监视器
嵌入式系统的内存资源极其有限,不当的使用动态内存,除了产生内存碎片、内存泄露这些问题外,严重时会导致死机,崩溃等事故,所以在使用动态内存时有必要加上一定限制手段,确保系统在一定安全边际下正常运行。`AT_MEM_LIMIT_SIZE`规定了AT请求所用的最大内存数量这样可以避免程序异常执行时过度执行AT请求导致内存不足的问题。至于分配多少主要取决于你的应用如果你一开始并不确定用多少比较合适可以先设置一个相对来说大一些的值然后让程序运行一段时间观察使用情况再设置通过`at_max_used_memory``at_cur_used_memory`可以获取历史最大内存使用量和当前内存使用量。

112
docs/Porting.md Normal file
View File

@ -0,0 +1,112 @@
# 平台移植及配置
在使用前,你需要先进行平台移植,下面是下整个组件的目录结构:
```shell
at_chat
|───docs 使用文档
|───samples 演示案例
|───inlcude 头文件目录
| │───at_chat.h
| │───at_port.h
| │───linux_list.h
└───src
│───at_port.c
│───at_chat.c
```
## 平台移植
移植只涉及到3个接口实现及若干配置定义(at_port.h中声明了这些需要实现的接口及配置).
```c
//内存申请,释放
void *at_malloc(unsigned int nbytes);
void at_free(void *ptr);
//获取系统毫秒数(从开机开始)
unsigned int at_get_ms(void);
```
### 内存相关接口实现
```C
void *at_malloc(unsigned int nbytes)
{
return malloc(nbytes);
}
void at_free(void *ptr)
{
free(ptr);
}
```
### 系统时间获取接口实现
**如果你使用的是MCU,可以通过定时器计数方式实现,参考下面的例程:**
```c
/* 滴答计数器*/
static volatile unsigned int tick = 0;
/**
* @brief 定时器中断服务程序(1ms 1次)
*/
void timer_handler(void)
{
tick++;
}
/**
* @brief 获取系统毫秒数
*/
unsigned int at_get_ms(void)
{
return tick;
}
```
**对于linux系统,可以参考下面方式获取:**
```C
/**
* @brief 获取系统毫秒数
*/
unsigned int at_get_ms(void)
{
struct timeval tv_now;
//这里需要注意的是,当系统时间被更改后,会获取到一个错误的值,造成命令超时(代码仅做的演示)。
gettimeofday(&tv_now, NULL);
return (tv_now.tv_sec * 1000000 + tv_now.tv_usec) / 1000;
}
```
## 配置说明
这些配置项主用于命令交互响应设置,内存使用限制及模块开关等,实际应用时需要考虑你所在系统的资源情况,对于大多数情况,默认值已经够用。
| 配置项 | 默认值 | 配置说明 |
| ------------------ | ---------- | ---------------------------------------------------------- |
| AT_DEF_RESP_OK | "OK" | 默认AT命令正确响应,当匹配到此值到,状态码返回AT_RESP_OK |
| AT_DEF_RESP_ERR | "ERROR" | 默认AT命令错误响应,当匹配到此值到,状态码返回AT_RESP_ERR |
| AT_DEF_TIMEOUT | 500 | 默认AT响应超时时间(ms),当命令超时时,状态码返回AT_RESP_TIMEOUT |
| AT_DEF_RETRY | 2 | 当发生AT响应错误或者超时时重发次数 |
| AT_URC_TIMEOUT | 1000 | 默认URC帧超时时间(ms) |
| AT_MAX_CMD_LEN | 256 | 最大命令长度(用于可变参数命令内存限制). |
| AT_LIST_WORK_COUNT | 32 | 它规定了同时能够支持的AT异步请求个数, 他可以限制应用程序(使用不当时)短时间内大量突发请求造成内存不足的问题,一般来说8-16已经够用了. |
| AT_URC_WARCH_EN | 1 | URC消息监视使能 |
| AT_URC_END_MARKS | ":,\n" | URC结束标记列表,越少越好,因为URC匹配程序会根据此列表对接收到的字符做URC结束帧匹配处理,列表太大会影响程序性能. |
| AT_MEM_WATCH_EN | 1u | 内存监视使能 |
| AT_MEM_LIMIT_SIZE | (3 * 1024) | 内存使用限制 |
| AT_WORK_CONTEXT_EN | 1u | AT作业上下文相关接口 |

13
docs/cover.md Normal file
View File

@ -0,0 +1,13 @@
<!-- coverpage.md -->
![logo](images/logo.png)
> **AT命令通信组件(V2)**
- 异步方式实现,无操作系统也能运行
- 支持不定长度URC捕获
- 多实例并存
[Gitee](https://gitee.com/moluo-tech/AT)
[GitHub](https://gitee.com/moluo-tech/AT)

BIN
docs/images/atfsm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

BIN
docs/images/atresp.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

BIN
docs/images/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
docs/images/urcbin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

BIN
docs/images/urcflow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
docs/images/wifi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
docs/images/workfsm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

42
docs/index.html Normal file
View File

@ -0,0 +1,42 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="description" content="Description">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify@4/lib/themes/vue.css">
</head>
<body>
<nav>
<a href="#/">中文</a>
<a href="#/">English</a>
</nav>
<div data-app id="app">Loading...</div>
<script>
window.$docsify = {
name: 'AT Command(V2)',
repo: 'https://gitee.com/moluo-tech/AT-Command',
subMaxLevel: 3,
coverpage: true,
// Custom file name
coverpage: 'cover.md',
// multiple covers and custom file name
coverpage: {
'/': 'cover.md',
'/en/': 'cover.md',
},
loadSidebar: true,
loadSidebar: 'sidebar.md',
}
</script>
<!-- Docsify v4 -->
<script src="//cdn.jsdelivr.net/npm/docsify@4"></script>
<script src="//unpkg.com/docsify-copy-code"></script>
<!-- 代码高亮 -->
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-c.min.js"></script>
</body>
</html>

4437
docs/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

5
docs/package.json Normal file
View File

@ -0,0 +1,5 @@
{
"dependencies": {
"docsify-pdf-converter": "^2.0.7"
}
}

561
docs/quickStart.md Normal file
View File

@ -0,0 +1,561 @@
# 快速上手
有了对整个框架的基本认识之后,接下来我们看一下如何在你的平台下使用。
## 准备工作
在使用前,您需要做一些准备工作,包括:
- 工程配置与移植
- 驱动接口适配
- 创建AT通信对象
- 加入轮询任务
### 工程配置与移植
如下所示,使用前您需要先将AT通信组件添加到你的项目中, 涉及的文件只有inlcude及src这两个目录,另外根据你所有平台不同,还需要进行简单的移植配置才能正常使用,有关这部分可以参考[平台移植指南](Porting.md#平台移植)平台移植及配置.
```shell
at_chat
|───docs 使用文档
|───samples 演示案例
|───inlcude 头文件目录
| │───at_chat.h
| │───at_port.h
| │───linux_list.h
└───src
│───at_port.c
│───at_chat.c
```
### 驱动接口适配
完成平台移植这些工作之后为了能够使AT通信对象与硬件关联起来你需要提供相关的驱动接口进行适配对接,包括:
1. 串口读写接口
因为通常使用是串口进行AT通信所以只需要提供串口中读写驱动接口即可不过这里需要注意的是串口驱动接口必须是带缓冲区**非阻塞**的对于LINUX的平台需要将串口文件IO设置为O_NONBLOCK而如果你使用的是MCU可以使用队列或者环形缓存区实现死等收发不保证能正常工作)有经验的工程师对这个应该已经比较熟悉了对于刚入门不久的小伙可以参考samples/none_os中的例子。
2. 互斥锁接口
如果你是在OS环境下使用并且跨线程执行了AT请求,你需要提供上锁/解锁接口如果你都是在单线程中运行的则直接填NULL即可。
3. 缓冲区大小设置
包括接收缓冲与URC缓冲区,接收缓冲区用于缓存命令请求时设备端响应的数据,它取决于你的设备最大响应内容长度;URC缓冲区也是取决于最长上报的URC数据长度。
4. 日志打印与异常接口
如果你需要查看所有AT命令通信的细节你需要实现debug接口在进行AT命令通信过程中他会将所有收发消息输出出来如果执行过中出现异常(出错,超时)则可以通过实现error接口来进行监视。
完整的适配器定义如下:
```c
/**
* @brief AT interface adapter
*/
typedef struct {
//Lock, used in OS environment, fill in NULL if not required.
void (*lock)(void);
//Unlock, used in OS environment, fill in NULL if not required.
void (*unlock)(void);
//Data write operation (non-blocking)
unsigned int (*write)(const void *buf, unsigned int len);
//Data read operation (non-blocking)
unsigned int (*read)(void *buf, unsigned int len);
//AT error event ( if not required, fill in NULL)
void (*error)(at_response_t *);
//Log output interface, which can print the complete AT interaction process, fill in NULL if not required.
void (*debug)(const char *fmt, ...);
#if AT_URC_WARCH_EN
//URC buffer size, set according to the actual maximum URC frame when used.
unsigned short urc_bufsize;
#endif
//Command response receiving buffer size, set according to the actual maximum command response length
unsigned short recv_bufsize;
} at_adapter_t;
```
示例:
```c
/**
* @brief AT适配器
*/
static const at_adapter_t at_adapter = {
.lock = at_mutex_lock, //多任务上锁(非OS下填NULL)
.unlock = at_mutex_unlock, //多任务解锁(非OS下填NULL)
.write = at_device_write, //数据写接口
.read = at_device_read, //数据读接口)
.debug = at_debug, //调试打印接口
.recv_bufsize = 256, //接收缓冲区大小
.urc_bufsize = 512
};
```
### 创建AT通信对象
下一步就是使用刚刚创建好的驱动接口来创建AT通信对象。
原型如下:
```c
at_obj_t *at_obj_create(const at_adapter_t *);
```
!> 这里有一点需要特别注意,为了节省内存使用AT组件只存储了`at_adapter_t`对象的指针,而不是对象本身,所以`at_adapter_t`定义的对象必须是常驻内存的,建议使用`const`进行修饰,这样可以存储在ROM中减少内存使用。
示例:
```c
at_obj_t *at_obj;
//....
at_obj = at_obj_create(&at_adapter);
if (at_obj == NULL) {
printf("at object create failed\r\n");
}
//...
```
### 加入轮询任务
最后你需要再提供一个任务定时轮询以便它能够及时处理AT请求以及URC消息轮询时间越短越好原型如下
```c
/**
* @brief AT轮询处理程序
*/
void at_obj_process(at_obj_t *at);
```
示例:
```c
/**
* @brief AT轮询程序
*/
void at_device_process(void)
{
static unsigned int timer = 0;
//(为了加快AT命令处理响应速度,建议5ms以内轮询一次)
if (at_get_ms() - timer > 5) {
timer = at_get_ms();
at_obj_process(&at_obj);
}
}
```
## 基础应用
完成上面几个步骤之后你就可以使用AT命令请求相关接口了不过在开始使用之前,我先带你了解一下有关一般AT命令格式和使用过程中涉及到的一些基本概念了解这些有助深入理解整个AT组件是如何针对各种不同场景处理那些业务交互的实现原理。
### 一般AT命令类型与处理
以常见的GPRS/WIFI模组AT命令为例它们常用格式的可分以下几种类型
1. **测试命令**
命令格式为AT+&lt;x&gt;=?,用于查询设置命令设置的参数以及其取值范围。
2. **查询命令**
命令格式为AT+&lt;x&gt;?,用于返回参数的当前值。
3. **设置命令**
命令格式为AT+&lt;x&gt;=<...>,用于设置用户配置参数。
4. **执行命令**
命令格式为AT+&lt;x&gt;不带参数常用于执行系统相关操作如查询系统信息读取IMEI号等。
上面列举的4种格式基本上覆盖了常见AT通信场景通信双方都是一问一答式的主机发送1行命令请求从机响应数据及状态双方只交互一次。由于流程结构一样所以在软件设计时比较容易统一设计成一种类型接口。
```shell
主机:
=> AT+XXX...
从机:
<= +XXX
<= OK/ERROR
```
对主机端来说,命令都是以行为单位执行的,只是携带的参数类型或者个数不同,唯一需要特殊处理的是数据响应信息解析,因为各个命令响应并没有统一格式,所以无法在底层实现一个通用解析模块,这需要上层应用根据不同的命令类型进行分别处理。我们可以按照谁发的命令谁来处理的原则,将命令响应内容返还给命令发送者,由它来进行处理。但是在此之前,需要鉴别响应内容从哪开始到哪结束,这就涉及到内容匹配提取的问题,归纳起来如有下两种情况:
- 对于设置类命令,命令响应全是以"OK"状态返回。
- 对于查询类命令,返回的内容包含数据+状态,命令状态也是以"OK"返回,而数据部分对于不同命令有不一样的信息格式。
由此可以通过统一为匹配"前缀+后缀"的方式提取到AT命令响应的内容这也是这个组件处理AT命令请求的基本实现原理它通过可以为每个命令附带一个属性信息(包含响应前缀,响应后缀)用于告诉AT解析器如何正确提取响应的内容。
以无线模组查询信号质量命令为例,如下图所示,"+CSQ:"作为响应内容前缀,"OK"作为响应内容后缀。
![命令发送-响应示意图](images/atresp.png)
### 命令属性
AT命令属性使用**at_attr_t**描述在发送AT请求之前你可以为每个AT请求设置一个属性它可以控制AT状态机的行为如控制命令响应内容匹配规则、超时时间、错误重试等。所有AT作业对象都共享以下属性:
- 用户私有参数(params)
- 响应内容前后缀(prefix,suffix)
- 回调处理程序(cb)
- 响应超时时间(timeout)
- 重次次数(retry)
- 优先级(priority)
**AT属性数据结构定义如下:**
```c
/**
*@brief AT Command attributes.
*/
typedef struct {
void *params; /* User parameter, fill in NULL if not required. */
const char *prefix; /* Response prefix, fill in NULL if not required. */
const char *suffix; /* Response suffix, fill in NULL if not required. */
at_callback_t cb; /* Response callback handler, fill in NULL if not needed. */
unsigned short timeout; /* Response timeout(ms). */
unsigned char retry; /* Response error retries. */
at_cmd_priority priority; /* Command execution priority. */
} at_attr_t;
```
在使用AT属性之前你需要为它的每个字段都进行初始化设置,但每次发送请求都将所有属性设置一遍太过繁琐,大多数情况下命令的属性都差不多,您可以先使用**at_attr_deinit**进行默认设置,然后再设置关注的属性即可。
**示例1:**
```c
at_attr_t attr;
//设置属性为默认值
at_attr_deinit(&attr);
attr.cb = my_handler; //设置回调处理程序
```
**示例2:**
```c
at_attr_t attr;
//设置属性为默认值
at_attr_deinit(&attr);
attr.cb = my_handler; //设置回调处理程序
attr.prefix = "+CSQ:" //设置响应内容前缀
attr.suffix = "OK"; //设置响应内容后缀
...
```
### AT回调与响应
对于是异步的命令所有请求的结果都是通过回调方式通知应用程序的同时它会返回命令响应的相关信息你可以在AT属性中指定相应的回调处理程序。
**回调程序原型如下:**
```c
/**
*@brief AT 执行回调
*@param r AT响应信息(包含执行结果,设备端返回的内容信息)
*/
typedef void (*at_callback_t)(at_response_t *r);
```
其中`at_response_t`包含了所有请求响应相关的信息,它包含了请求命令的执行状态和命令响应内容。
```c
/**
* @brief AT响应信息
*/
typedef struct {
struct at_obj *obj; /* 所属AT通信对象*/
void *params; /* 附属参数*/
at_resp_code code; /* AT命令响应码*/
unsigned short recvcnt; /* 接收数据长度*/
char *recvbuf; /* 接收缓冲区(原始数据)*/
/* 接收内容前缀当code=AT_RESP_OK时有效如果未指定匹配前缀则它指向recvbuf*/
char *prefix;
/* 接收内容后缀当code=AT_RESP_OK时有效如果未指定匹配后缀则它指向recvbuf*/
char *suffix;
} at_response_t;
```
- obj:所属AT通信对象你可以通过它在响应处理程序中根据状态发送下一个请求。
- param:附属参数,对应`at_attr_t`中的params。
- code:AT命令响应码
- recvcnt:指示了接收缓冲区recvbuf有效接收数据长度。
- recvbuf:缓存了此次命令请求时返回的数据。
- prefix:接收内容前缀,例如当你期望接收到'+CSQ:'开始的数据时当code==AT_RESP_OK则prefix就是指向了'recvbuf'中'+CSQ:'的开始位置。
- suffix:接收内容后缀。
了解完上面的几个基本概念之后,下面看一下如何使用。
### 单行命令发送(at_send_singlline)
通过`at_send_singlline`函数可以执行单行命令请求,其原型如下:
```c
/**
* @brief Send a single -line command
* @param cb Response callback handler Fill in NULL if not required
* @param timeout command execution timeout(ms)
* @param retry command retries( >= 0)
* @param singlline command
* @retval Indicates whether the asynchronous work was enqueued successfully.
* @note Only the address is saved so the 'singlline' can not be a local variable which will be destroyed.
*/
bool at_send_singlline(at_obj_t *at, at_callback_t cb, int timeout, int retry, const char *singlline);
```
**返回值:**
当请求成功返回true否则返回false。
**参数说明:**
- at : AT对象
- cb : 回调处理程序,当命令执行完成之后,将以这个接口通知上层应用,并携带命令响应内容及状态。
- timeout命令执行超时时间单位为ms。
- retry命令出错或者超时重试次数。
- singlline命令名称。
>注:AT作业只会缓存singlline的指针这意味者它指向的命令不能是局部数据。
**示例1查询网络注册状态(SIM900模块):**
命令格式:
```c
=> AT+CREG?
<= +CREG:<mode>,<stat>[,< lac>,< ci>]
<= OK
```
代码实现:
```c
/**
* @brief 命令响应处理程序
*/
static void read_creg_callback(at_response_t *r)
{
int mode, state;
if (r->code == AT_RESP_OK) {
//提取出工作模式及注册状态
if (sscanf(r->prefix, "+CREG:%d,%d", &mode, &state) == 2) {
printf("Mode:%d, state:%d\r\n", mode, state);
}
} else {
printf("'CREG' command response failed!\r\n");
}
}
/**
* @brief 读网络注册状态
*/
static void read_creg(void)
{
//发送CREG查询命令,超时时间为1000ms,重发次数为0
at_send_singlline(at_obj, read_creg_callback, 500, 1, "AT+CREG?");
}
```
**示例2,IO控制:**
如果你不关心命令响应结果,直接可以这样使用。
```c
at_send_singlline(at_obj, NULL, 500, 0, "AT+SETIO=1,FF"); //设置设备IO类型
at_send_singlline(at_obj, NULL, 500, 0, "AT+OUTIO=1,55"); //设置IO电平
```
### 多行命令发送(at_send_multiline)
实际工程应用中,特别是进行设备初始化配置时,往往一次需要发送大量命令,一种实现方式是通过`at_send_singlline`在每个命令的回调中根据命令状态进行下一条命令的请求,命令较少时还可以接受,命令一多就会形成恐怖的回调地狱链,造成代码难以理解和维护,现实中应尽量避免这种写法。这里提供了一个支持批量发送的接口来应对这种情况,其原型如下:
```c
/**
* @brief Send multiline commands
* @param attr AT attributes(NULL to use the default value)
* @param multiline Command table, with the last item ending in NULL.
* @example :
* const char *multiline = {
* "AT+XXX",
* "AT+XXX",
* NULL
* };
* at_send_multiline(at_dev, NULL, multiline);
*
* @retval Indicates whether the asynchronous work was enqueued successfully.
* @note Only the address is saved, so the array can not be a local variable which will be destroyed.
*/
bool at_send_multiline(at_obj_t *at, const at_attr_t *attr, const char **multiline);
```
**返回值:**
当请求成功返回true否则返回false。
**参数说明:**
- at : AT对象
- attr : 命令属性,通过它可以设置命令回调程序,超时时间等。
- multiline命令表以NULL结尾。
**示例SIM800C 模组初始化):**
```c
/**
* @brief 命令响应处理程序
*/
static void simcom_init_callback(at_response_t *r)
{
printf("SIM800C Init %s!\r\n",r->code == AT_RESP_OK ? "ok" : "error");
}
/*
* @brief 模块初始化
*/
static void simcom_init(void)
{
at_attr_t attr;
static const char *cmds[] = {
"AT+CSCLK=0",
"AT+CIPHEAD=1", //+RECEIVE,<n>,<data length>:
"AT+CIPQSEND=1", //快发模式
"AT+CIPMUX=1", //多IP支持
"AT+CIPSPRT=>",
"AT+CIPSRIP=0",
NULL
};
at_attr_deinit(&attr);
attr.cb = simcom_init_callback; //设置命令回调
at_send_multiline(at_obj, &attr, cmds);
}
```
!> 批量命令表中最后一项必须是NULL且整个命令表不能是局部变量。
### 可变参数命令(at_exec_cmd)
前面讲的单行命令与多行命令都是用于发送固定参数的命令的,如果你的命令参数(如设置类命令)是可变的,可以通过 `at_exec_cmd`执行请求,其原型如下:
```c
/**
* @brief Execute one command
* @param attr AT attributes(NULL to use the default value)
* @param cmd Formatted arguments
* @param ... Variable argument list (same usage as printf)
* @retval Indicates whether the asynchronous work was enqueued successfully
*/
bool at_exec_cmd(at_obj_t *at, const at_attr_t *attr, const char *cmd, ...);
```
**返回值:**
当请求成功返回true否则返回false。
**参数说明:**
- at : AT对象
- attr : 命令属性,通过它可以设置命令回调程序,超时时间等。
- cmd : 格式化命令用法与printf一样。
**示例1,EC20设置APN:**
```c
/**
* @brief 命令响应处理程序
*/
static void set_apn_callback(at_response_t *r)
{
printf("Setting APN %s!\r\n",r->code == AT_RESP_OK ? "ok" : "error");
}
/**
* @brief 设置APN
*/
static bool set_apn(const char *apn, const char *username, const char *pwd)
{
at_attr_t attr;
at_attr_deinit(&attr);
attr.cb = set_apn_callback; //设置命令回调
at_exec_cmd(at_obj, &attr, "AT+QICSGP=1,1,\"%s\",\"%s\",\"%s\",0", apn, username, pwd);
}
```
### 可变参数列表(at_exec_vcmd)
通常`at_obj_t`对象并不会直接公开给第第三方模块使用为了能够使其它模块也能进行AT请求你可能需要对命令请求的接口进行2次封装当需要支持可变参数时可以使用`at_exec_vcmd`,它支持传递变参列表,其原型如下:
```c
/**
* @brief execute command (with variable argument list)
* @param attr AT attributes(NULL to use the default value)
* @param cmd Format the command.
* @param va Variable parameter list
* @return Indicates whether the asynchronous work was enqueued successfully
*/
bool at_exec_vcmd(at_obj_t *at, const at_attr_t *attr, const char *cmd, va_list va);
```
**返回值:**
当请求成功返回true否则返回false。
**参数说明:**
- at : AT对象
- attr : 命令属性,通过它可以设置命令回调程序,超时时间等。
- cmd : 格式化命令
- va : 参数列表
**示例:**
```c
/**
* @brief 发送AT命令
* @param attr 命令属性
* @param cmd,.. 格式化命令参数用法与printf一样
*/
bool at_send_cmd(const at_attr_t *attr, const char *cmd, ...)
{
bool ret;
va_list args;
va_start(args, cmd);
ret = at_exec_vcmd(at_obj, attr, cmd, args);
va_end(args);
return ret;
}
```
### 发送原始数据(at_send_data)
当命令类型非纯文本或者格式化的命令无法满足要求时,可以使用`at_send_data`接口,以原始数据的方式发送。
```c
/**
* @brief Send (binary) data
* @param attr AT attributes(NULL to use the default value)
* @param databuf Binary data
* @param bufsize Binary data length
* @retval Indicates whether the asynchronous work was enqueued successfully
*/
bool at_send_data(at_obj_t *at, const at_attr_t *attr, const void *databuf, unsigned int bufsize);
```
**返回值:**
当请求成功返回true否则返回false。
**参数说明:**
- at : AT对象
- attr : 命令属性,通过它可以设置命令回调程序,超时时间等。
- databuf : 原始数据
- bufsize : 数据长度
### 自定义命令(at_custom_cmd)
在进行变参命令或者原始数据发送时系统会他们单独分配一块区域进行暂存然后跟随AT作业一块缓存到队列中如果短期需要发送大量的数据或者命令队列不能及时被处理那么那段时间内命令队列占用的总内存会激增严重时导致无可用内存。即使在内存使用的上做限制但是遇到这种情况也会造成命令请求失败使用自定义命令的方式可以在一定程度缓解这个问题它不直接缓存调用者的任何数据而只暂存一个发送器指针当真正发送命令时再上调用者请求数据其原型如下
```c
/**
* @brief Execute custom command
* @param attr AT attributes(NULL to use the default value)
* @param sender Command sending handler (such as sending any type of data through the env->obj->adap-write interface)
* @retval Indicates whether the asynchronous work was enqueued successfully
*/
bool at_custom_cmd(at_obj_t *at, const at_attr_t *attr, void (*sender)(at_env_t *env));
```
**返回值:**
当请求成功返回true否则返回false。
**参数说明:**
- at : AT对象
- attr : 命令属性,通过它可以设置命令回调程序,超时时间等。
- sender : 数据发送器调用者可以通过env->obj->write接口发送任何形式的数据。
**示例:(ESP8266创建TCP socket)**
```c
/**
* @brief 命令响应处理程序
*/
static void create_socket_callback(at_response_t *r)
{
printf("Create socket %s!\r\n",r->code == AT_RESP_OK ? "ok" : "error");
}
/**
* @brief 发送创建socket命令
*/
void create_socket_sender(at_env_t *env)
{
socket_t *sock = (socket_t *)env->params;
env->println(env, "AT+CIPSTART=\"TCP\",\"%s\",%d", sock->ip, sock->port);
}
/**
* @brief 创建socket
*/
static bool create_socket(socket_t *sock)
{
at_attr_t attr;
at_attr_deinit(&attr);
attr.params = sock; //用户参数(里面存储了socket id,目标IP端口)
attr.cb = create_socket_callback; //设置命令回调
attr.suffix = "CONNECT OK"; //设置响应后缀
return at_custom_cmd(at_obj, &attr, create_socket_sender);
}
```

66
docs/readme.md Normal file
View File

@ -0,0 +1,66 @@
# 简介
AT command(V2) 一款管理AT命令通信交互组件 适用于Modem、WIFI模块、蓝牙等使用AT命令或者ASCII命令行通信的场景它涵盖了大部分AT通信形式如参数设置查询二进制数据发送等同时也支持自定义命令交互管理由于它的每个命令请求都是异步的所以对于无操作系统的环境也支持。相对于V1版本新版本在命令接收匹配URC不定长度数据捕获以及内存安全上做了大量优化让它可以应对更多复杂产品应用。
下面是一个最基本使用的演示:
```c
/**
* @brief 命令响应处理程序
*/
static void read_csq_callback(at_response_t *r)
{
int rssi, ber;
//+CSQ: <rssi>,<ber>
if (r->code == AT_RESP_OK) {
//命令响应成功后,解析出rssi,ber.
if (sscanf(r->prefix, "+CSQ:%d,%d", &rssi, &ber) == 2) {
printf("rssi:%d, ber:%d\r\n", rssi, ber);
}
} else {
printf("'CSQ' command response failed!\r\n");
}
}
/**
* @brief 读CSQ值请求
*/
static void read_csq(void)
{
//发送CSQ查询命令,超时时间为1000ms,重发次数为0
at_send_singlline(at_obj, read_csq_callback, 1000, 0, "AT+CSQ");
}
```
上面的示例展示了AT命令通信的基本使用方式
- 命令请求:执行命令发送之后,命令并不会立即从数据通道发送出去,而是先进入命令队列。
- 异步通知:无论命令执行成功与否,都会以异步方式通知请求者。
# 框架介绍
整个组件由两部分内容组成:
- AT 作业管理, 管理所有AT异步请求及命令收发工作。
- URC(主动上报) 处理模块,实时捕获URC消息并上报事件,它跟AT作业是并行的,是一个可选的模块。
## AT 作业
'AT Command'组件的基本处理单元是AT作业, 它实际上是一个状态机轮询程序不仅仅可以处理单个命令收发还可以是批量命令自定义命令等应用程序在进行AT通信请求时系统会根据请求类型生成一个新的作业对象然后将对象按照执行优先级预先缓存到队列中接着系统会从队列逐个取出并选择相应的状态机处理程序进行处理处理完毕之后再以回调方式将结果上报给应用程序整个环节跟流水作业生产产品一样它的基本处理流程图如下所示
![AT处理框架](images/atfsm.png)
### AT作业生命周期
AT作业生命周期可以简单分为五个阶段创建阶段、就绪阶段、运行阶段、完成/终止阶段、销毁阶段。
<img src="images/workfsm.png" alt="AT作业" style="zoom:75%;" />
- **创建阶段:** 根据请求类型生成作业项,这个阶段可以为新作业项绑定一个上下文,用来监视作业的整个工作过程,包含运行状态,AT命令响应信息等.
- **就绪阶段:** 作业被提交入队列之后就进入了就绪状态,系统按队列顺序一个接着一个取出来并运行.
- **运行阶段:** 此时进入运行一个状态机,以一般AT命令为例,它包含了命令发送,数据接收匹配,超时重试等处理.
- **完成/终止阶段:** 当命令请求的响应信息匹配成功之后,则进入完成状态,如果在这之前命令请求被提示终止,则进入终止状态。
- **销毁阶段:** 在这个阶段系统会将作业从队列中移出同时将相关内存释放.
## URC 处理模块
URC 处理模块可以实时捕获URC消息上层应用需要提供URC消息的匹配规则(消息前后缀)及事件处理入口它们共同组成了URC订阅表一旦URC解析器匹配到表中某项规则时立即以事件方式返回给订阅者进行处理(有关这部分的使用可以参考[URC消息处理](Expert.md#URC消息处理))。
![AT作业](images/urcflow.png)

6
docs/sidebar.md Normal file
View File

@ -0,0 +1,6 @@
<!-- navbar.md -->
* [介绍](readme#简介)
* [快速上手](quickStart#基础应用)
* [高级教程](Expert#高级教程)
* [平台移植](Porting#平台移植)

BIN
docs/图表.eddx Normal file

Binary file not shown.

1302
docs/异步AT框架说明.md Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

279
include/at_chat.h Normal file
View File

@ -0,0 +1,279 @@
/******************************************************************************
* @brief AT command communication management V2
*
* Copyright (c) 2020~2022, <morro_luo@163.com>
*
* SPDX-License-Identifier: Apathe-2.0
*
* Change Logs:
* Date Author Notes
* 2020-01-02 roger.luo Initial version
* 2021-01-20 roger.luo Add debugging interface, and at the same time solve
* the problem of uninitialized linked list leading to
* segment fault.
* 2021-03-03 roger.luo Fix the problem of frequent print receive timeout caused by not clearing the URC counter.
* 2022-10-01 roger.luo Redesign the entire AT framework and release V2.0.
******************************************************************************/
#ifndef _AT_CHAT_H_
#define _AT_CHAT_H_
#include "at_port.h"
#include <stdbool.h>
#include <stdarg.h>
struct at_obj;
struct at_adapter;
struct at_response;
/**
*@brief AT work running state.
*/
typedef enum {
AT_WORK_STAT_IDLE,
AT_WORK_STAT_READY,
AT_WORK_STAT_RUN,
AT_WORK_STAT_FINISH,
AT_WORK_STAT_ABORT,
} at_work_state;
/**
*@brief AT command response code
*/
typedef enum {
AT_RESP_OK = 0,
AT_RESP_ERROR,
AT_RESP_TIMEOUT,
AT_RESP_ABORT
} at_resp_code;
/**
*@brief AT command request priority
*/
typedef enum {
AT_PRIORITY_LOW = 0,
AT_PRIORITY_HIGH
} at_cmd_priority;
/**
*@brief URC frame receiving status
*/
typedef enum {
URC_RECV_OK = 0, /* URC frame received successfully. */
URC_RECV_TIMEOUT /* Receive timeout (The frame prefix is matched but the suffix is not matched within AT_URC_TIMEOUT) */
} urc_recv_status;
/**
* @brief URC frame info.
*/
typedef struct {
urc_recv_status status; /* URC frame receiving status.*/
char *urcbuf; /* URC frame buffer*/
int urclen; /* URC frame buffer length*/
} at_urc_info_t;
/**
* @brief URC subscription item.
*/
typedef struct {
const char *prefix; /* URC frame prefix,such as '+CSQ:'*/
const char endmark; /* URC frame end mark (can only be selected from AT_URC_END_MARKS)*/
/**
* @brief URC handler (triggered when matching prefix and mark are match)
* @params info - URC frame info.
* @return Indicates the remaining unreceived bytes of the current URC frame.
* @retval 0 Indicates that the current URC frame has been completely received
* @retval n It still needs to wait to receive n bytes (AT manager continues
* to receive the remaining data and continues to call back this interface).
*/
int (*handler)(at_urc_info_t *info);
} urc_item_t;
/**
* @brief AT response information
*/
typedef struct {
struct at_obj *obj; /* AT object*/
void *params; /* User parameters (referenced from ->at_attr_t.params)*/
at_resp_code code; /* AT command response code.*/
unsigned short recvcnt; /* Receive data length*/
char *recvbuf; /* Receive buffer (raw data)*/
/* Pointer to the receiving content prefix, valid when code=AT_RESP_OK,
if no prefix is specified, it pointer to recvbuf
*/
char *prefix;
/* Pointer to the receiving content suffix, valid when code=AT_RESP_OK,
if no suffix is specified, it pointer to recvbuf
*/
char *suffix;
} at_response_t;
/**
* @brief AT interface adapter
*/
typedef struct {
//Lock, used in OS environment, fill in NULL if not required.
void (*lock)(void);
//Unlock, used in OS environment, fill in NULL if not required.
void (*unlock)(void);
//Data write operation (non-blocking)
unsigned int (*write)(const void *buf, unsigned int len);
//Data read operation (non-blocking)
unsigned int (*read)(void *buf, unsigned int len);
//AT error event ( if not required, fill in NULL)
void (*error)(at_response_t *);
//Log output interface, which can print the complete AT interaction process, fill in NULL if not required.
void (*debug)(const char *fmt, ...);
#if AT_URC_WARCH_EN
//URC buffer size, set according to the actual maximum URC frame when used.
unsigned short urc_bufsize;
#endif
//Command response receiving buffer size, set according to the actual maximum command response length
unsigned short recv_bufsize;
} at_adapter_t;
/**
* @brief Public environment for AT work
*/
typedef struct at_env {
struct at_obj *obj;
//Public variables (add as needed), these values are reset every time a new work starts.
int i, j, state;
//User parameters (referenced from ->at_attr_t.params)
void *params;
//Set the next polling wait interval (only takes effect once)
void (*next_wait)(struct at_env *self, unsigned int ms);
//Reset timer
void (*reset_timer)(struct at_env *self);
//Timeout indication
bool (*is_timeout)(struct at_env *self, unsigned int ms);
//Formatted printout with newlines
void (*println)(struct at_env *self, const char *fmt, ...);
//Find a keyword from the received content
char * (*contains)(struct at_env *self, const char *str);
//Get receives buffer
char * (*recvbuf)(struct at_env *self);
//Get receives buffer length
unsigned int(*recvlen)(struct at_env *self);
//Clear the receives buffer
void (*recvclr)(struct at_env *self);
//Indicates whether the current work has been abort
bool (*disposing)(struct at_env *self);
//End the work and set the response code
void (*finish)(struct at_env *self, at_resp_code code);
} at_env_t;
/**
*@brief AT execution callback
*@param r AT response information (including execution results, content information returned by the device)
*/
typedef void (*at_callback_t)(at_response_t *r);
/**
*@brief AT work polling handler
*@param env The public operating environment for AT work, including some common
* variables and relevant interfaces needed to communicate AT commands.
*@return Work processing status, which determines whether to continue running the
* work on the next polling cycle.
*
* @retval true Indicates that the current work processing has been finished,
* and the work response code is set to AT_RESP_OK
* @retval false Indicates unfinished work processing, keep running.
*@note It must be noted that if the env->finish() operation is invoked in the
* current work, the work will be forcibly terminated regardless of the return value.
*/
typedef int (*at_work_t)(at_env_t *env);
#if AT_WORK_CONTEXT_EN
/**
*@brief AT work item context (used to monitor the entire life cycle of AT work item)
*/
typedef struct {
at_work_state work_state; /* Indicates the state at which the AT work item is running. */
at_resp_code code; /* Indicates the response code after the AT command has been run.*/
unsigned short bufsize; /* Indicates receive buffer size*/
unsigned short resplen; /* Indicates the actual response valid data length*/
unsigned char *respbuf; /* Point to the receive buffer*/
} at_context_t;
#endif
/**
*@brief AT attributes
*/
typedef struct {
#if AT_WORK_CONTEXT_EN
at_context_t *ctx; /* Pointer to the Work context. */
#endif
void *params; /* User parameter, fill in NULL if not required. */
const char *prefix; /* Response prefix, fill in NULL if not required. */
const char *suffix; /* Response suffix, fill in NULL if not required. */
at_callback_t cb; /* Response callback handler, Fill in NULL if not required. */
unsigned short timeout; /* Response timeout(ms).. */
unsigned char retry; /* Response error retries. */
at_cmd_priority priority; /* Command execution priority. */
} at_attr_t;
/**
*@brief AT object.
*/
typedef struct at_obj {
const at_adapter_t *adap;
void *user_data;
} at_obj_t;
at_obj_t *at_obj_create(const at_adapter_t *);
void at_obj_destroy(at_obj_t *at);
bool at_obj_busy(at_obj_t *at);
void at_obj_set_user_data(at_obj_t *at, void *user_data);
void *at_obj_get_user_data(at_obj_t *at);
#if AT_URC_WARCH_EN
void at_obj_set_urc(at_obj_t *at, const urc_item_t *tbl, int count);
#endif
void at_obj_process(at_obj_t *at);
void at_attr_deinit(at_attr_t *attr);
bool at_exec_cmd(at_obj_t *at, const at_attr_t *attr, const char *cmd, ...);
bool at_exec_vcmd(at_obj_t *at, const at_attr_t *attr, const char *cmd, va_list va);
bool at_send_singlline(at_obj_t *at, at_callback_t cb, int timeout, int retry, const char *singlline);
bool at_send_multiline(at_obj_t *at, const at_attr_t *attr, const char **multiline);
bool at_send_data(at_obj_t *at, const at_attr_t *attr, const void *databuf, unsigned int bufsize);
bool at_custom_cmd(at_obj_t *at, const at_attr_t *attr, void (*sender)(at_env_t *env));
bool at_do_work(at_obj_t *at, void *params, at_work_t work);
void at_work_abort_all(at_obj_t *at);
#if AT_MEM_WATCH_EN
unsigned int at_max_used_memory(void);
unsigned int at_cur_used_memory(void);
#endif
#if AT_WORK_CONTEXT_EN
void at_context_init(at_context_t *ctx, void *respbuf, unsigned bufsize);
void at_context_attach(at_attr_t *attr, at_context_t *ctx);
at_work_state at_work_get_state(at_context_t *ctx);
bool at_work_is_finish(at_context_t *ctx);
at_resp_code at_work_get_result(at_context_t *ctx);
#endif //End of AT_WORK_CONTEXT_EN
#endif //End of _AT_CHAT_H_

76
include/at_port.h Normal file
View File

@ -0,0 +1,76 @@
/**
* @Brief: The AT component drives the interface implementation
* @Author: roger.luo
* @Date: 2021-04-04
* @Last Modified by: roger.luo
* @Last Modified time: 2021-11-27
*/
#ifndef __AT_PORT_H__
#define __AT_PORT_H__
/**
*@brief Default correct response identifier.
*/
#define AT_DEF_RESP_OK "OK"
/**
*@brief Default error response identifier.
*/
#define AT_DEF_RESP_ERR "ERROR"
/**
*@brief Default command timeout (ms)
*/
#define AT_DEF_TIMEOUT 500
/**
*@brief Number of retries when a command timeout/error occurs.
*/
#define AT_DEF_RETRY 2
/**
*@brief Default URC frame receive timeout (ms).
*/
#define AT_URC_TIMEOUT 500
/**
*@brief Maximum AT command send data length (only for variable parameter commands).
*/
#define AT_MAX_CMD_LEN 256
/**
*@brief Maximum number of work in queue (limit memory usage).
*/
#define AT_LIST_WORK_COUNT 32
/**
*@brief Enable URC watcher.
*/
#define AT_URC_WARCH_EN 1
/**
*@brief A list of specified URC end marks (fill in as needed, the fewer the better).
*/
#define AT_URC_END_MARKS ":,\n"
/**
*@brief Enable memory watcher.
*/
#define AT_MEM_WATCH_EN 1u
/**
*@brief Maximum memory usage limit (Valid when AT_MEM_WATCH_EN is enabled)
*/
#define AT_MEM_LIMIT_SIZE (3 * 1024)
/**
*@brief Enable AT work context interfaces.
*/
#define AT_WORK_CONTEXT_EN 1u
void *at_malloc(unsigned int nbytes);
void at_free(void *ptr);
unsigned int at_get_ms(void);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,24 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/../**",
"${workspaceFolder}/../../**"
],
"defines": [],
"intelliSenseMode": "gcc-x64",
"browse": {
"path": [
"${workspaceFolder}/**"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
},
"compilerPath": "/usr/bin/gcc",
"cStandard": "c11",
"cppStandard": "c++17"
}
],
"version": 4
}

3
samples/linux/.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"recommendations": ["ms-vscode.cpptools"]
}

25
samples/linux/.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,25 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "g++ build and debug active file",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/output/demo",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "Build"
}
]
}

9
samples/linux/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,9 @@
{
"makefile.launchConfigurations": [
{
"cwd": "${workspaceFolder}/output",
"binaryPath": "${workspaceFolder}/output/demo",
"binaryArgs": []
}
]
}

38
samples/linux/.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,38 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "Build",
"command": "make clean & make",
"options": {
"cwd": "${workspaceFolder}"
},
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
},
"problemMatcher": {
"owner": "cpp",
"fileLocation": [
"relative",
"${workspaceFolder}"
],
"pattern": {
"regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 5
}
},
"group": {
"kind": "build",
"isDefault": true
},
}
]
}

128
samples/linux/cmd/cmd_gsm.c Normal file
View File

@ -0,0 +1,128 @@
/******************************************************************************
* @brief GSM AT命令模拟器
* Change Logs:
* Date Author Notes
* 2022-04-01 Roger.luo
******************************************************************************/
#include "cli.h"
#include <stddef.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
/**
* @brief AT测试
*/
static int do_cmd_at(struct cli_obj *obj, int argc, char *argv[])
{
return true;
}
cmd_register("AT", do_cmd_at, NULL);
/**
* @brief SIM卡状态
*/
static int do_cmd_cpin(struct cli_obj *obj, int argc, char *argv[])
{
obj->print(obj, "+CPIN:READY\r\n");
return true;
}
cmd_register("CPIN", do_cmd_cpin, NULL);
/**
* @brief
*/
static int do_cmd_csq(struct cli_obj *obj, int argc, char *argv[])
{
obj->print(obj, "+CSQ:31,99\r\n");
return true;
}
cmd_register("CSQ",do_cmd_csq, NULL);
/**
* @brief
*/
static int do_cmd_creg(struct cli_obj *obj, int argc, char *argv[])
{
obj->print(obj, "+CREG: 2,1,\"1052\",\"D619\",0\r\n");
return true;
}
cmd_register("CREG", do_cmd_creg, NULL);
/**
* @brief IMEI
*/
static int do_cmd_cgsn(struct cli_obj *obj, int argc, char *argv[])
{
obj->print(obj, "123456789012345\r\n");
return true;
}
cmd_register("CGSN", do_cmd_cgsn, NULL);
/**
* @brief
*/
static int do_cmd_ver(struct cli_obj *obj, int argc, char *argv[])
{
obj->print(obj, "+VER:V1.02\r\n");
return true;
}
cmd_register("VER", do_cmd_ver, NULL);
/**
* @brief
*/
static int do_cmd_param(struct cli_obj *obj, int argc, char *argv[])
{
static int a = 0, b = 0;
char *p;
if (obj->type == CLI_CMD_TYPE_QUERY) { //参数查询
obj->print(obj, "+PARAM=%d,%d\r\n" ,a, b);
return true;
} else { //参数设置
p = strchr(obj->recvbuf, '=');
if (argc == 2 && p != NULL) {
a = atoi(p + 1);
b = atoi(argv[1]);
obj->print(obj, "Parameter setting is successfully, a=%d, b=%d\r\n", a, b);
return true;
}
}
return false;
}
cmd_register("PARAM", do_cmd_param, NULL);
/**
* @brief
*/
static int do_cmd_read_bin(struct cli_obj *obj, int argc, char *argv[])
{
int i;
unsigned char check; //数据校验码
int len;
char buf[256];
srand((unsigned)time(NULL));
len = rand() % sizeof(buf);
for (i = 1, check = 0; i < len; i++) {
buf[i] = rand() % 128;
check ^= buf[i]; //计算校验码
}
buf[0] = check;
//=> AT+RDBIN=<socket id>,<read size>
//
//<= +BINDAT:<socket id>,<real size>\r\n<raw data......>
//
//<= OK
obj->print(obj, "+BINDAT:%d,%d\r\n" ,1, len);
obj->write(buf, len);
return true;
}
cmd_register("BINDAT", do_cmd_read_bin, NULL);

View File

@ -0,0 +1,22 @@
/******************************************************************************
* @brief AT命令模拟器
* Change Logs:
* Date Author Notes
* 2022-04-01 Roger.luo
******************************************************************************/
#ifndef __AT_DEVICE_H__
#define __AT_DEVICE_H__
void at_device_init(void);
void at_device_open(void);
void at_device_close(void);
unsigned int at_device_write(const void *buf, unsigned int size);
unsigned int at_device_read(void *buf, unsigned int size);
void at_device_emit_urc(const void *urc, int size);
#endif

115
samples/linux/include/cli.h Normal file
View File

@ -0,0 +1,115 @@
/******************************************************************************
* @brief
*
* Copyright (c) 2015-2022, <master_roger@sina.com>
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2015-06-09 Morro
*
* 2017-07-04 Morro
*
* 2020-07-05 roger.luo 使cli_obj_t对象,
* 2021-08-29 roger.luo AT指令解析及回显控制
* 2022-02-16 roger.luo
******************************************************************************/
#ifndef _CMDLINE_H_
#define _CMDLINE_H_
#include "comdef.h"
#define CLI_MAX_CMD_LEN 256 /*命令行长度*/
#define CLI_MAX_ARGS 16 /*最大参数个数*/
#define CLI_MAX_CMDS 64 /*最大允许定义的命令个数*/
/**
* @brief CLI作为AT解析器使用,"AT+",
*/
#define CLI_AT_ENABLE 1
/*命令类型 */
#define CLI_CMD_TYPE_EXEC 0 /* 普通执行命令*/
#define CLI_CMD_TYPE_QUERY 1 /* 查询命令 (XXX?)*/
#define CLI_CMD_TYPE_SET 2 /* 设备命令 (XXX=YY)*/
struct cli_obj;
/*命令项定义*/
typedef struct {
char *name; /*命令名*/
/**
* @brief ,
* @params o - cli
* @params argc -
* @params argv -
* @return , AT指令, true时会自动响应OK,false时则
* ERROR
*/
int (*handler)(struct cli_obj *o, int argc, char *argv[]);
const char *brief; /*命令简介*/
void *reserved;
}cmd_item_t;
#define __cmd_register(name,handler,brief)\
USED ANONY_TYPE(const cmd_item_t,__cli_cmd_##handler)\
SECTION("cli.cmd.1") = {name, handler, brief}
/*******************************************************************************
* @brief
* @params name -
* @params handler -
* :int (*handler)(struct cli_obj *s, int argc, char *argv[]);
* @params brief - 使
*/
#define cmd_register(name,handler,brief)\
__cmd_register(name,handler,brief)
/*cli 接口定义 -------------------------------------------------------------*/
typedef struct {
/**
* @brief ()
*/
unsigned int (*write)(const void *buf, unsigned int len);
/**
* @brief ()
*/
unsigned int (*read) (void *buf, unsigned int len);
/**
* @brief (NULL,)
* @retval true - , false -
*/
int (*cmd_guard)(char *cmdline);
}cli_port_t;
/*命令行对象*/
typedef struct cli_obj {
int (*guard)(char *cmdline);
unsigned int (*write)(const void *buf, unsigned int len);
unsigned int (*read) (void *buf, unsigned int len);
void (*print)(struct cli_obj *this, const char *fmt, ...);
int (*get_val)(struct cli_obj *this);
char recvbuf[CLI_MAX_CMD_LEN + 1]; /* 命令接收缓冲区*/
unsigned short recvcnt; /* 最大接收长度*/
unsigned type : 3; /* 命令类型*/
unsigned enable : 1; /* CLI 开关控制*/
unsigned echo : 1; /* 回显设置*/
}cli_obj_t;
void cli_init(cli_obj_t *obj, const cli_port_t *p);
void cli_enable(cli_obj_t *obj);
void cli_disable (cli_obj_t *obj);
void cli_echo_ctrl (cli_obj_t *obj, int echo);
void cli_exec_cmd(cli_obj_t *obj, const char *cmd);
void cli_process(cli_obj_t *obj);
#endif /* __CMDLINE_H */

View File

@ -1,58 +1,51 @@
/****************************************************************************** /******************************************************************************
* @brief ͨ<EFBFBD>ú<EFBFBD><EFBFBD> * @brief
* *
* Copyright (c) 2018~2020, <morro_luo@163.com> * Change Logs:
* * Date Author Notes
* SPDX-License-Identifier: Apache-2.0 * 2018-02-01 Roger.luo Initial version.
* ******************************************************************************/
* Change Logs:
* Date Author Notes #ifndef _COM_DEF_H_
* 2018-02-01 Morro Initial version. #define _COM_DEF_H_
******************************************************************************/
#ifdef __cplusplus
#ifndef _COM_DEF_H_ extern "C" {
#define _COM_DEF_H_ #endif
#ifdef __cplusplus /*匿名类型定义 -----------------------------------------------------------*/
extern "C" { #define ANONY_CONN(type, var, line) type var##line
#endif #define ANONY_DEF(type,prefix,line) ANONY_CONN(type, prefix, line)
#define ANONY_TYPE(type,prefix) ANONY_DEF(type, prefix, __LINE__)
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD> -----------------------------------------------------------*/
#define ANONY_CONN(type, var, line) type var##line /**
#define ANONY_DEF(type,prefix,line) ANONY_CONN(type, prefix, line) * container_of - cast a member of a structure out to the containing structure
#define ANONY_TYPE(type,prefix) ANONY_DEF(type, prefix, __LINE__) * @ptr: the pointer to the member.
* @type: the type of the container struct this is embedded in.
/** * @member: the name of the member within the struct.
* container_of - cast a member of a structure out to the containing structure *
* @ptr: the pointer to the member. */
* @type: the type of the container struct this is embedded in. #define container_of(ptr, type, member) ( \
* @member: the name of the member within the struct. (type *)( (char *)(ptr) - offsetof(type,member) ))
*
*/
#define container_of(ptr, type, member) ( \ #if defined(__CC_ARM) || defined(__GNUC__) /* ARM,GCC*/
(type *)( (char *)(ptr) - offsetof(type,member) )) #define SECTION(x) __attribute__((section(x)))
#define UNUSED __attribute__((unused))
#define USED __attribute__((used))
#if defined(__CC_ARM) || defined(__GNUC__) /* ARM,GCC*/ #define ALIGN(n) __attribute__((aligned(n)))
#define SECTION(x) __attribute__((section(x))) #define WEAK __attribute__((weak))
#define UNUSED __attribute__((unused)) #elif defined (__ICCARM__) /*IAR */
#define USED __attribute__((used)) #define SECTION(x) @ x
#define ALIGN(n) __attribute__((aligned(n))) #define UNUSED
#define WEAK __attribute__((weak)) #define USED __root
#elif defined (__ICCARM__) /*IAR */ #define WEAK __weak
#define SECTION(x) @ x #else
#define UNUSED #error "Current tool chain haven't supported yet!"
#define USED __root #endif
#define WEAK __weak
#else #ifdef __cplusplus
#error "Current tool chain haven't supported yet!" }
#endif #endif
/*<2A><><EFBFBD><EFBFBD>Ԫ<EFBFBD>ظ<EFBFBD><D8B8><EFBFBD> ---------------------------------------------------------------*/ #endif
#define ARRAY_COUNT(Array) (sizeof(Array) / sizeof(Array[0]))
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,45 +1,47 @@
/****************************************************************************** /******************************************************************************
* @brief <EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<EFBFBD>ο<EFBFBD>linux/kfifo) * @brief <EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<EFBFBD>ο<EFBFBD>linux/kfifo)
* *
* Copyright (c) 2016~2020, <morro_luo@163.com> * Copyright (c) 2016~2021, <morro_luo@163.com>
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2016-05-30 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * 2016-05-30 Morro Initial version.
******************************************************************************/ * 2021-02-05 Morro <EFBFBD><EFBFBD><EFBFBD>ӿ<EFBFBD><EFBFBD>пռ<EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD>ӿ<EFBFBD>.
******************************************************************************/
#ifndef _RING_BUF_H_
#define _RING_BUF_H_ #ifndef _RING_BUF_H_
#define _RING_BUF_H_
#include <stdbool.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" { #ifdef __cplusplus
#endif extern "C" {
#endif
/*<2A><><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
typedef struct { /*<2A><><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
unsigned char *buf; /*<2A><><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD> */ typedef struct {
unsigned int size; /*<2A><><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD> */ unsigned char *buf; /*<2A><><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD> */
unsigned int front; /*ͷָ<CDB7><D6B8> */ unsigned int size; /*<2A><><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD> */
unsigned int rear; /*βָ<CEB2><D6B8> */ unsigned int front; /*ͷָ<CDB7><D6B8> */
}ring_buf_t; unsigned int rear; /*βָ<CEB2><D6B8> */
}ring_buf_t;
bool ring_buf_init(ring_buf_t *r,unsigned char *buf,unsigned int size);
bool ring_buf_init(ring_buf_t *r,unsigned char *buf,unsigned int size);
void ring_buf_clr(ring_buf_t *r);
void ring_buf_clr(ring_buf_t *r);
unsigned int ring_buf_len(ring_buf_t *r);
unsigned int ring_buf_len(ring_buf_t *r);
unsigned int ring_buf_put(ring_buf_t *r,unsigned char *buf,unsigned int len);
unsigned int ring_buf_put(ring_buf_t *r,unsigned char *buf,unsigned int len);
unsigned int ring_buf_get(ring_buf_t *r,unsigned char *buf,unsigned int len);
unsigned int ring_buf_get(ring_buf_t *r,unsigned char *buf,unsigned int len);
#ifdef __cplusplus unsigned int ring_buf_free_space(ring_buf_t *r);
}
#endif #ifdef __cplusplus
}
#endif #endif
#endif

228
samples/linux/linker.lds Normal file
View File

@ -0,0 +1,228 @@
/* Script for -z combreloc: combine and sort reloc sections */
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
"elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(_start)
SEARCH_DIR("/usr/x86_64-linux-gnu/lib64"); SEARCH_DIR("=/usr/local/lib/x86_64-linux-gnu"); SEARCH_DIR("=/usr/local/lib64"); SEARCH_DIR("=/lib/x86_64-linux-gnu"); SEARCH_DIR("=/lib64"); SEARCH_DIR("=/usr/lib/x86_64-linux-gnu"); SEARCH_DIR("=/usr/lib64"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib");
SECTIONS
{
/* Read-only sections, merged into text segment: */
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
.interp : { *(.interp) }
.note.gnu.build-id : { *(.note.gnu.build-id) }
.hash : { *(.hash) }
.gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rela.dyn :
{
*(.rela.init)
*(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
*(.rela.fini)
*(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
*(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
*(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
*(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
*(.rela.ctors)
*(.rela.dtors)
*(.rela.got)
*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
*(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
*(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
*(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
*(.rela.ifunc)
}
.rela.plt :
{
*(.rela.plt)
PROVIDE_HIDDEN (__rela_iplt_start = .);
*(.rela.iplt)
PROVIDE_HIDDEN (__rela_iplt_end = .);
}
.init :
{
KEEP (*(SORT_NONE(.init)))
}
.plt : { *(.plt) *(.iplt) }
.text :
{
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
*(.text.exit .text.exit.*)
*(.text.startup .text.startup.*)
*(.text.hot .text.hot.*)
*(.text .stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
}
.atcmd :
{
KEEP (*(SORT(cli.cmd.*)))
}
.fini :
{
KEEP (*(SORT_NONE(.fini)))
}
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
.eh_frame_hdr : { *(.eh_frame_hdr) }
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table
.gcc_except_table.*) }
/* These sections are generated by the Sun/Oracle C++ compiler. */
.exception_ranges : ONLY_IF_RO { *(.exception_ranges
.exception_ranges*) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
/* Exception handling */
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
.exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) }
/* Thread Local Storage sections */
.tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
}
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
}
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
}
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
}
.jcr : { KEEP (*(.jcr)) }
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
.dynamic : { *(.dynamic) }
.got : { *(.got) *(.igot) }
. = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
.got.plt : { *(.got.plt) *(.igot.plt) }
.data :
{
*(.data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
}
.data1 : { *(.data1) }
_edata = .; PROVIDE (edata = .);
. = .;
__bss_start = .;
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections.
FIXME: Why do we need it? When there is no .bss section, we don't
pad the .data section. */
. = ALIGN(. != 0 ? 64 / 8 : 1);
}
.lbss :
{
*(.dynlbss)
*(.lbss .lbss.* .gnu.linkonce.lb.*)
*(LARGE_COMMON)
}
. = ALIGN(64 / 8);
. = SEGMENT_START("ldata-segment", .);
.lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
{
*(.lrodata .lrodata.* .gnu.linkonce.lr.*)
}
.ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
{
*(.ldata .ldata.* .gnu.linkonce.l.*)
. = ALIGN(. != 0 ? 64 / 8 : 1);
}
. = ALIGN(64 / 8);
_end = .; PROVIDE (end = .);
. = DATA_SEGMENT_END (.);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* DWARF 3 */
.debug_pubtypes 0 : { *(.debug_pubtypes) }
.debug_ranges 0 : { *(.debug_ranges) }
/* DWARF Extension. */
.debug_macro 0 : { *(.debug_macro) }
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
}

628
samples/linux/main.c Normal file
View File

@ -0,0 +1,628 @@
/******************************************************************************
* @brief AT命令测试程序
* Change Logs:
* Date Author Notes
* 2022-04-01 Roger.luo
******************************************************************************/
#include "at_chat.h"
#include "at_port.h"
#include "at_device.h"
#include <sys/poll.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
static at_obj_t *at_obj; //AT
static pthread_mutex_t at_lock; //互斥锁
typedef struct {
pthread_mutex_t completed; //完成信号量
} at_watch_t;
/**
* @brief
*/
typedef struct {
void (*handler)(void);
const char *brief;
} test_item_t;
/**
* @brief
*/
static void at_mutex_lock(void)
{
pthread_mutex_lock(&at_lock);
}
/**
* @brief
*/
static void at_mutex_unlock(void)
{
pthread_mutex_unlock(&at_lock);
}
/**
* @brief
*/
static void at_error_handler(at_response_t *r)
{
printf("Error detected!\r\n");
}
/**
* @brief
*/
static void at_debug(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
#if AT_URC_WARCH_EN
/**
* @brief /URC处理程序
*/
static int urc_power_handler(at_urc_info_t *ctx)
{
int status;
if (sscanf(ctx->urcbuf, "+POWER:%d",&status) == 1) {
printf("Device power %s event detected!\r\n", status ? "on" : "off");
}
return 0;
}
/**
* @brief socket数据包(+IPD,<socket id>,<data length>:.....)
*/
static int urc_socket_data_handler(at_urc_info_t *ctx)
{
int length, total_length, sockid, i;
char *data;
unsigned char check = 0;
if (sscanf(ctx->urcbuf, "+IPD,%d,%d:", &sockid, &length) == 2) { //解析出总数据长度
data = strchr(ctx->urcbuf, ':');
if (data == NULL)
return 0;
data++;
total_length = (data - ctx->urcbuf) + length; //计算头部长度
if (ctx->urclen < total_length) { //未接收全,返回剩余待接收数据
printf("Need to receive %d more bytes\r\n", total_length - ctx->urclen);
return total_length - ctx->urclen;
}
for (i = 1, check = 0; i < length; i++) {
check ^= data[i];
}
printf("%d bytes of data were received form socket %d, check %s!\r\n",
length, sockid, check == data[0] ? "ok": "error");
}
return 0;
}
/**
* @brief urc订阅表
*/
static const urc_item_t urc_table[] =
{
{.prefix = "+POWER:", .endmark = '\n', .handler = urc_power_handler},
{.prefix = "+IPD,", .endmark = ':', .handler = urc_socket_data_handler}
};
#endif
/**
* @brief 使
*/
static void sample_show_memory(void)
{
#if AT_MEM_WATCH_EN
printf("max memory:%d, current memory:%d\r\n", at_max_used_memory(), at_cur_used_memory());
#else
printf("Unknown memory usage, please enable 'AT_MEM_WATCH_EN' macro first.\r\n");
#endif
}
/**
* @brief
*/
static void sample_singlline(void)
{
// => AT+CSQ
// <= +CSQ:<rssi>,<ber>
// <= OK
at_send_singlline(at_obj, NULL, 200, 1, "AT+CSQ");
}
/**
* @brief
*/
static void sample_multiline(void)
{
static const char *cmd_table[] = {
"AT+CPIN?",
"AT+CSQ",
"AT+CREG",
"AT+PARAM?",
NULL
};
at_send_multiline(at_obj, NULL, cmd_table);
}
/**
* @brief
*/
static void sample_variable_param_cmd(void)
{
srand((unsigned)time(NULL));
at_exec_cmd(at_obj, NULL, "AT+PARAM=%d,%d",rand() % 100,rand() % 200);
at_exec_cmd(at_obj, NULL, "AT+PARAM?");
}
/**
* @brief
*/
static void sample_timeout_retry(void)
{
at_attr_t attr;
at_attr_deinit(&attr);
attr.retry = 3;
attr.timeout = 1000;
at_exec_cmd(at_obj, &attr, "AAA");
}
/**
* @brief
*/
static void sample_error_retry(void)
{
at_attr_t attr;
at_attr_deinit(&attr);
attr.retry = 2;
at_exec_cmd(at_obj, &attr, "AT+CMD");
}
/**
* @brief
*/
static void sample_abort_command(void)
{
at_exec_cmd(at_obj, NULL, "AT+CMD");
at_work_abort_all(at_obj);
}
/**
* @brief
*/
static void read_ver_cb(at_response_t *r)
{
char verbuf[16];
if (r->code == AT_RESP_OK) {
sscanf(r->prefix, "+VER:%s\r\n", verbuf);
printf("Version info:%s\r\n", verbuf);
}
}
/**
* @brief
* => AT+VER
* <= +VER:Vxxxx
* <= OK
*/
static void sample_specific_prefix(void)
{
at_attr_t attr;
at_attr_deinit(&attr);
//匹配介于[+VER -> \r\n]之间的内容
attr.prefix = "+VER",
attr.suffix = "\r";
attr.cb = read_ver_cb;
at_exec_cmd(at_obj, &attr, "AT+VER");
}
/**
* @brief
*/
static void custom_sender(at_env_t *env)
{
env->println(env, "AT+CSQ\r\n");
}
/**
* @brief
*/
static void sample_custom_cmd(void)
{
at_custom_cmd(at_obj, NULL, custom_sender);
}
/**
* @brief
*/
static void sample_send_buffer(void)
{
char buf[] = "AT+CSQ\r\n";
at_send_data(at_obj, NULL, buf, sizeof(buf));
}
/**
* @brief CSQ
*/
static int at_work_query_csq(at_env_t *env)
{
char *p;
int rssi, ber;
switch (env->state)
{
case 0:
env->println(env, "AT+CSQ\r\n");
env->state++; //转到接收状态
env->recvclr(env); //清空接口
env->reset_timer(env); //重置计时器
break;
case 1:
if (env->contains(env, "OK")) {
//+CSQ:<rssi>,<ber>
if ((p = env->contains(env, "+CSQ")) != NULL &&
sscanf(p, "+CSQ:%d,%d", &rssi, &ber) == 2) {
printf("The CSQ read ok, rssi:%d, ber:%d\r\n", rssi, ber);
}
return true;
} else if (env->contains(env, "ERROR")) { //错误处理
printf("The CSQ read failed.\r\n");
return true;
} else if (env->is_timeout(env, 1000)) { //错误处理
printf("The CSQ read timeout.\r\n");
return true;
}
break;
default:
return true;
}
return false;
}
/**
* @brief 1
*/
static void sample_at_work_1(void)
{
at_do_work(at_obj, NULL, at_work_query_csq);
}
static unsigned char check_bin_data(unsigned char *buf, int len)
{
unsigned char check = 0;
while (len--) {
check ^= *buf++;
}
return check;
}
/**
* @brief socket数制
*/
static int at_work_read_bin(at_env_t *env)
{
#define READ_STAT_START 0
#define READ_STAT_HEAD 1
#define READ_STAT_DATA 2
static char *start, *end;
static int total, sockid;
unsigned char buf[256];
//=> AT+BINDAT=<socket id>,<read size>
//
//<= +BINDAT:<socket id>,<real size>\r\n<raw data......>
//
//<= OK
switch (env->state)
{
case READ_STAT_START:
env->println(env, "AT+BINDAT=%d,%d\r\n", 1, sizeof(buf));
env->recvclr(env);
env->reset_timer(env);
env->state = READ_STAT_HEAD;
break;
case READ_STAT_HEAD:
if ((start = env->contains(env, "+BINDAT:")) != NULL) {
end = strchr(start, '\n');
if (end == NULL)
break;
end++;
if (sscanf(start, "+BINDAT:%d,%d" ,&sockid, &total) == 2) {
env->reset_timer(env);
env->state++;
printf("Next receive %d bytes data from socket %d\r\n", total, sockid);
}
} else if (env->contains(env, "ERROR")) {
env->finish(env, AT_RESP_ERROR);
return true;
} else if (env->is_timeout(env, 1000)) {
if (env->i++ > 3) {
/*产生发送异常事件 */
printf("recv error!!!\r\n");
return true;
}
env->state = READ_STAT_START; /*重新发送*/
}
break;
case READ_STAT_DATA:
//
//recvbuf...start....end....data ....
// |---- total ----|
//|---------- recvlen ---------------|
if (env->recvlen(env) >= total + (end - env->recvbuf(env))) { //数据接收完成
memcpy(buf, end, total);
printf("recv ok!!!\r\n");
if (total > 0 && buf[0] == check_bin_data(&buf[1], total - 1))
printf("check ok!!!\r\n");
return true;
} else if (env->is_timeout(env, 1000)){
printf("recv error!!!\r\n");
return true;
}
break;
default:
break;
}
return false;
}
/**
* @brief Read binary data via 'at work'
*/
static void sample_read_bin_data(void)
{
at_do_work(at_obj, NULL, at_work_read_bin);
}
/**
* @brief Capture unsolicited binary data
*/
static void sample_urc_bin_data(void)
{
int i;
unsigned char check; //数据校验码
int len;
char buf[256];
char head[32];
srand((unsigned)time(NULL));
len = rand() % sizeof(buf);
for (i = 1, check = 0; i < len; i++) {
buf[i] = rand() % 128;
check ^= buf[i]; //计算校验码
}
buf[0] = check;
//BCC+DATA
//+IPD,<socket id>,<data length>:.....
snprintf(head, sizeof(head),"+IPD,%d,%d:",rand() % 16, len);
at_device_emit_urc(head, strlen(head));
at_device_emit_urc(buf, len);
}
#if AT_WORK_CONTEXT_EN
/**
* @brief ()
* @param respbuf
* @param bufsize
* @param timeout
* @param cmd
* @retval
*/
static at_resp_code at_send_cmd_sync(char *respbuf, int bufsize, int timeout, const char *cmd, ...)
{
at_attr_t attr;
at_context_t ctx;
va_list args;
bool ret;
//属性初始化
at_attr_deinit(&attr);
attr.timeout = timeout;
attr.retry = 1;
//初始化context
at_context_init(&ctx, respbuf, bufsize);
//为工作项绑定context
at_context_attach(&attr, &ctx);
va_start(args, cmd);
ret = at_exec_vcmd(at_obj, &attr, cmd, args);
va_end(args);
if (!ret) {
return AT_RESP_ERROR;
}
//等待命令执行完毕
while (!at_work_is_finish(&ctx)) {
usleep(1000);
}
return at_work_get_result(&ctx);
}
/**
* @brief
*/
static void sample_at_sync(void)
{
int rssi, error_rate;
char csqbuf[64];
at_resp_code code;
code = at_send_cmd_sync(csqbuf, sizeof(csqbuf), 200, "AT+CSQ");
if (code == AT_RESP_OK) {
sscanf(csqbuf, "+CSQ:%d,%d", &rssi, &error_rate);
printf("The CSQ value is read successfully\r\n=>rssi:%d, error_rate:%d\r\n", rssi, error_rate);
} else if (code == AT_RESP_TIMEOUT) {
printf("The CSQ read timeout.\r\n");
} else {
printf("The CSQ read failed.\r\n");
}
}
#endif
/**
* @brief
*/
static const test_item_t test_cases[] = {
{sample_show_memory, "Display memory information."},
{sample_singlline, "Testing singlline command."},
{sample_multiline, "Testing multiline commands."},
{sample_variable_param_cmd, "Testing variable parameter command."},
{sample_timeout_retry, "Testing response timeout retry."},
{sample_error_retry, "Testing response error retry."},
{sample_abort_command, "Testing command abort."},
{sample_specific_prefix, "Testing specific response prefix."},
{sample_custom_cmd, "Testing custom command."},
{sample_send_buffer, "Testing buffer send."},
{sample_at_work_1, "Testing 'at_do_work' 1."},
{sample_read_bin_data, "Testing read binary data via 'at work'."},
{sample_urc_bin_data, "Testing capture unsolicited binary data."},
#if AT_WORK_CONTEXT_EN
{sample_at_sync, "Testing at context interface."},
#endif
};
/**
* @brief
*/
static void show_test_case(void)
{
int i;
printf("Please input test item:\r\n");
for (i = 0; i < sizeof(test_cases) / sizeof(test_cases[0]); i++)
printf("\t%d:%s\r\n", i + 1, test_cases[i].brief);
printf("*******************************************************\r\n");
}
/**
* @brief
*/
static void input_process(void)
{
const test_item_t *item;
char buf[128];
int num;
fgets(buf, sizeof(buf), stdin);
num = atoi(buf);
if (num > 0 && num <= sizeof(test_cases) / sizeof(test_cases[0])) {
item = &test_cases[num - 1];
printf("Start '%s'\r\n", item->brief);
item->handler();
} else {
show_test_case();
}
}
/**
* @brief at适配器
*/
static const at_adapter_t at_adapter = {
.lock = at_mutex_lock,
.unlock = at_mutex_unlock,
.write = at_device_write,
.read = at_device_read,
.error = at_error_handler,
.debug = at_debug,
#if AT_URC_WARCH_EN
.urc_bufsize = 300,
#endif
.recv_bufsize = 300
};
/**
* @brief at通信处理线程
*/
static void *at_thread(void *args)
{
pthread_detach(pthread_self());
printf("at thread running...\r\n");
while(1) {
usleep(1000);
at_obj_process(at_obj);
}
return NULL;
}
int main(int argc, char **argv)
{
pthread_t tid;
at_obj = at_obj_create(&at_adapter);
if (at_obj == NULL) {
printf("at object create failed\r\n");
_exit(0);
}
at_obj_set_urc(at_obj, urc_table, sizeof(urc_table) / sizeof(urc_table[0]) );
at_device_init();
pthread_mutex_init(&at_lock, NULL);
pthread_create(&tid, NULL, at_thread, NULL);
printf("*******************************************************\r\n");
printf("This is an asynchronous AT command framework.\r\n");
printf("Author:roger.luo, Mail:morro_luo@163.com\r\n");
printf("*******************************************************\r\n\r\n");
//Open AT emulator device
at_device_open();
show_test_case();
while(1){
input_process();
usleep(10 * 1000);
}
}
//....
typedef struct {
//....
int id;
unsigned char *sendptr;
int sendcnt;
}socket_t;
//....
/*
* @brief socket
* @return true - false -
*/
static int socket_send_handler(at_env_t *env)
{
socket_t *sk = (socket_t *)env->params;
switch (env->state) {
case 0:
env->println(env, "AT+KTCPSND=%d,%d", sk->id, sk->sendcnt);
env->reset_timer(env); /*重置定时器*/
env->state++;
break;
case 1:
if (env->contains(env, "CONNECT")) {
env->obj->adap->write(sk->sendptr, sk->sendcnt); /*发送数据*/
env->println(env, "--EOF--Pattern--"); /*发送结束符*/
env->reset_timer(env);
env->recvclr(env);
env->state++;
} else if (env->contains(env, "ERROR")) { /*匹配到错误,结束作业*/
env->finish(env, AT_RESP_ERROR);
} else if (env->is_timeout(env, 1000)) {
if (++env->i > 3) {
env->finish(env, AT_RESP_ERROR);
}
env->state--; /*重新发送*/
}
break;
case 2:
if (env->contains(env, "OK"))
env->finish(env, AT_RESP_OK); /*发送成功设置状态为OK后退出*/
else if (env->contains(env, "ERROR") ||
env->is_timeout(env, 1000)) {
env->finish(env, AT_RESP_ERROR);
}
break;
}
return 0;
}

111
samples/linux/makefile Normal file
View File

@ -0,0 +1,111 @@
# Specify the compiler name
CROSS_COMPILE ?=
# Name of the target
TARGET_NAME := demo
# Source File Directory
source_path := ./ ../../src
source_path += ./src
source_path += ./cmd
# Source Files
source_files :=
# Header file directory
include_path := ./include ../../include
# Exclude files that do not participate in compilation
exclude_files := ../../src/at_port.c
#Dependency library
LIB =
#MAKEFLAGS := -j $(shell nproc)
#
# 警告选项
#
WARNINGS := -Wall -Wextra -Werror\
-Wshadow -Wundef -Wmaybe-uninitialized \
-Wno-unused-function -Wno-error=strict-prototypes -Wpointer-arith -fno-strict-aliasing -Wno-error=cpp -Wuninitialized \
-Wno-missing-field-initializers -Wno-parentheses -Wno-format-nonliteral -Wno-cast-qual -Wunreachable-code -Wno-switch-default \
-Wreturn-type -Wmultichar -Wformat-security -Wno-ignored-qualifiers -Wno-error=pedantic -Wno-sign-compare -Wno-error=missing-prototypes -Wdouble-promotion -Wclobbered -Wdeprecated \
-Wempty-body -Wstack-usage=4096 -Wno-unused-parameter \
-Wtype-limits -Wsizeof-pointer-memaccess -Wpointer-arith -Wno-pointer-to-int-cast -Wno-pointer-sign
##############################################################################
# Compile options
#
CFLAGS := -O0 -g -fPIC -Wall $(WARNINGS)
CFLAGS += -std=gnu99
#############################################################################
# Linker options
#
# Link script
LDFLAGS = -Tlinker.lds -Wl,-Map=$(TARGET).map
#pthread
LDFLAGS += -pthread -lpthread
#############################################################################
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
#Target directory
BIN_DIR := ./output/
OBJ_DIR := ./output/obj/
TARGET := $(BIN_DIR)$(TARGET_NAME)
TOPDIR := $(shell pwd)/
#Source file directory
SRC_DIRS := $(source_path)
#Search the list of source files
CSRCS := $(shell find $(SRC_DIRS) -maxdepth 1 -path '*.c')
CSRCS += $(source_files)
CSRCS := $(notdir $(CSRCS))
#排除文件列表
EXCLUDE_LIST := $(notdir $(exclude_files))
CSRCS := $(filter-out $(EXCLUDE_LIST), $(CSRCS))
#
# Target files(*.o)
#
OBJS := $(addprefix $(OBJ_DIR),$(CSRCS:.c=.o) )
CFLAGS += $(patsubst %,-I$(TOPDIR)%,$(subst ./, ,$(SRC_DIRS)))
CFLAGS += $(addprefix -I$(TOPDIR),$(include_path) )
#指定搜索目录
VPATH += $(addprefix :, $(SRC_DIRS))
all: default $(TARGET)
$(TARGET):$(OBJS)
@$(CC) $(LDFLAGS) -o $@ $^
@echo Creating $(notdir $(TARGET)) ...
$(OBJ_DIR)%.o: %.c
@echo 'Compiling ' $< ...
@$(CC) $(CFLAGS) -c -o $@ $<
.PHONY: all clean default
#创建输出目录
default:
@rm -rf $(TARGET)
@mkdir -p $(BIN_DIR)
@mkdir -p $(OBJ_DIR)
clean:
rm -rf $(TARGET).map
rm -rf $(TARGET)
@rm -rf $(OBJS)
@rm -rf tmp

6
samples/linux/readme.md Normal file
View File

@ -0,0 +1,6 @@
.atcmd :
{
KEEP (*(SORT(cli.cmd.*)))
}

View File

@ -0,0 +1,125 @@
/******************************************************************************
* @brief AT命令模拟器
* Change Logs:
* Date Author Notes
* 2022-04-01 Roger.luo
******************************************************************************/
#include "cli.h"
#include "at_device.h"
#include "ringbuffer.h"
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/poll.h>
#include <sys/stat.h>
#include <pthread.h>
/**
* @brief AT设备
*/
typedef struct {
cli_obj_t cli;
ring_buf_t rb_tx;
ring_buf_t rb_rx;
unsigned char txbuf[1024];
unsigned char rxbuf[512];
} at_device_t;
static at_device_t at_device;
/**
* @brief
*/
static unsigned int cli_write(const void *buf, unsigned int size)
{
return ring_buf_put(&at_device.rb_tx, (unsigned char *)buf, size);
}
/**
* @brief
*/
static unsigned int cli_read(void *buf, unsigned int size)
{
return ring_buf_get(&at_device.rb_rx, buf, size);
}
/**
* @brief
*/
static void *at_device_thread(void *args)
{
pthread_detach(pthread_self());
printf("at devicce running...\r\n");
while(1) {
usleep(1000);
cli_process(&at_device.cli);
}
return NULL;
}
/**
* @brief AT模拟器初始化()
*/
void at_device_init(void)
{
cli_port_t p = {cli_write, cli_read, NULL}; /*读写接口 */
/*初始化环形缓冲区 */
ring_buf_init(&at_device.rb_rx, at_device.rxbuf, sizeof(at_device.rxbuf));
ring_buf_init(&at_device.rb_tx, at_device.txbuf, sizeof(at_device.txbuf));
cli_init(&at_device.cli, &p); /*初始化命令行对象 */
cli_enable(&at_device.cli);
pthread_t tid;
pthread_create(&tid, NULL, at_device_thread, NULL);
}
/**
* @brief
* @param buf
* @param size
* @retval
*/
unsigned int at_device_write(const void *buf, unsigned int size)
{
return ring_buf_put(&at_device.rb_rx, (unsigned char *)buf, size);
}
/**
* @brief
* @param buf
* @param size
* @retval
*/
unsigned int at_device_read(void *buf, unsigned int size)
{
return ring_buf_get(&at_device.rb_tx, buf, size);
}
/**
* @brief URC消息
*/
void at_device_emit_urc(const void *urc, int size)
{
cli_write(urc, size);
}
/**
* @brief AT设备( "+POWER:1" URC消息)
*/
void at_device_open(void)
{
char *s = "+POWER:1\r\n";
at_device_emit_urc(s, strlen(s));
}
/**
* @brief AT设备( "+POWER:0" URC消息)
*/
void at_device_close(void)
{
char *s = "+POWER:0\r\n";
at_device_emit_urc(s, strlen(s));
}

View File

@ -0,0 +1,35 @@
/**
* @Brief: The AT component drives the interface implementation
* @Author: roger.luo
* @Date: 2021-04-04
* @Last Modified by: roger.luo
* @Last Modified time: 2021-11-27
*/
#include <stddef.h>
#include <stdlib.h>
/**
* @brief Custom malloc for AT component.
*/
void *at_malloc(unsigned int nbytes)
{
return malloc(nbytes);
}
/**
* @brief Custom free for AT component.
*/
void at_free(void *ptr)
{
free(ptr);
}
/**
* @brief Gets the total number of milliseconds in the system.
*/
unsigned int at_get_ms(void)
{
struct timeval tv_now;
gettimeofday(&tv_now, NULL);
return (tv_now.tv_sec * 1000000 + tv_now.tv_usec) / 1000;
}

307
samples/linux/src/cli.c Normal file
View File

@ -0,0 +1,307 @@
/******************************************************************************
* @brief
*
* Copyright (c) 2015-2022, <master_roger@sina.com>
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2015-06-09 Morro
*
* 2017-07-04 Morro
*
* 2020-07-05 roger.luo 使cli_obj_t对象,
* 2021-08-29 roger.luo AT指令解析及回显控制
* 2022-02-16 roger.luo
******************************************************************************/
#include "cli.h"
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdbool.h>
static const cmd_item_t cmd_tbl_start SECTION("cli.cmd.0") = {0};
static const cmd_item_t cmd_tbl_end SECTION("cli.cmd.4") = {0};
/**
* @brief
* @param[in] keyword -
* @return
*/
static const cmd_item_t *find_cmd(const char *keyword, int n)
{
const cmd_item_t *it;
for (it = &cmd_tbl_start + 1; it < &cmd_tbl_end; it++) {
if (it->name != NULL && !strncasecmp(keyword, it->name, n))
return it;
}
return NULL;
}
/*******************************************************************************
* @brief - separator指定的分隔符
* (',')'\0'list
*
* @example
* input=> s = "abc,123,456,,fb$"
* separator = ",$"
*
* output=>s = abc'\0' 123'\0' 456'\0' '\0' fb'\0''\0'
* list[0] = "abc"
* list[1] = "123"
* list[2] = "456"
* list[3] = ""
* list[4] = "fb"
* list[5] = ""
*
* @param[in] str -
* @param[in] separator -
* @param[in] list -
* @param[in] len -
* @return list指针列表项数6
******************************************************************************/
static size_t strsplit(char *s, const char *separator, char *list[], size_t len)
{
size_t count = 0;
if (s == NULL || list == NULL || len == 0)
return 0;
list[count++] = s;
while(*s && count < len) {
if (strchr(separator, *s) != NULL) {
*s = '\0';
list[count++] = s + 1; /*指向下一个子串*/
}
s++;
}
return count;
}
/**
*@brief
*@retval
*/
static void cli_print(cli_obj_t *obj, const char *format, ...)
{
va_list args;
int len;
char buf[CLI_MAX_CMD_LEN + CLI_MAX_CMD_LEN / 2];
va_start (args, format);
len = vsnprintf (buf, sizeof(buf), format, args);
va_end (args);
obj->write(buf, len);
}
/**
* @brief
* @param[in] line -
* @return none
**/
static void process_line(cli_obj_t *obj)
{
char *argv[CLI_MAX_ARGS];
int argc, ret, isat = 0;
const cmd_item_t *it;
//命令拦截
if (obj->guard && !obj->guard(obj->recvbuf))
return;
if (obj->echo) { //回显
obj->print(obj,"%s\r\n",obj->recvbuf);
}
argc = strsplit(obj->recvbuf, ",",argv, CLI_MAX_ARGS);
const char *start, *end;
if (argv[0] == NULL)
return;
#if CLI_AT_ENABLE != 0
isat = strncasecmp(argv[0], "AT+", 3) == 0;
#endif
start= !isat ? argv[0] : argv[0] + 3;
if ((end = strchr(start, '=')) != NULL) {
obj->type = CLI_CMD_TYPE_SET;
} else if ((end = strchr(start, '?')) != NULL) {
obj->type = CLI_CMD_TYPE_QUERY;
} else {
obj->type = CLI_CMD_TYPE_EXEC;
end = start + strlen(argv[0]);
}
if (start == end)
return;
if ((it = find_cmd(start, end - start)) == NULL) {
obj->print(obj, "%s\r\n", isat ? "ERROR" : "");
return;
}
ret = it->handler(obj, argc, argv);
if (isat) {
obj->print(obj, "%s\r\n" ,ret ? "OK":"ERROR");
}
}
/**
* @brief
*/
static int get_val(struct cli_obj *self)
{
char *p;
p = strchr(self->recvbuf, '=');
if ( p == NULL)
return 0;
return atoi(p + 1);
}
/**
* @brief cli
* @param[in] p - cli驱动接口
* @return none
*/
void cli_init(cli_obj_t *obj, const cli_port_t *p)
{
obj->read = p->read;
obj->write = p->write;
obj->print = cli_print;
obj->enable = true;
obj->get_val = get_val;
obj->guard = p->cmd_guard;
}
/**
* @brief cli命令模式(cli此时自动处理用户输入的命令)
* @param[in] none
* @return none
**/
void cli_enable(cli_obj_t *obj)
{
char a;
obj->enable = true;
obj->recvcnt = 0;
while (obj->read(&a, 1) > 0) {}
}
/**
* @brief 退cli命令模式(cli此时不再处理用户输入的命令)
* @param[in] none
* @return none
**/
void cli_disable (cli_obj_t *obj)
{
obj->enable = false;
}
/**
* @brief
* @param[in] echo - (0/1)
* @return none
**/
void cli_echo_ctrl (cli_obj_t *obj, int echo)
{
obj->echo = echo;
}
/**
* @brief (cli是否运行,)
* @param[in] none
* @return none
**/
void cli_exec_cmd(cli_obj_t *obj, const char *cmd)
{
int len = strlen(cmd);
if (len >= CLI_MAX_CMD_LEN - 1)
return;
strcpy(obj->recvbuf, cmd);
process_line(obj);
}
/**
* @brief
* @param[in] none
* @return none
**/
void cli_process(cli_obj_t *obj)
{
int i;
if (!obj->read || !obj->enable)
return;
i = obj->recvcnt;
obj->recvcnt += obj->read(&obj->recvbuf[i], CLI_MAX_CMD_LEN - i);
while (i < obj->recvcnt) {
if (obj->recvbuf[i] == '\r' || obj->recvbuf[i] == '\n' || obj->recvbuf[i] == '\0') { /*读取1行*/
obj->recvbuf[i] = '\0';
process_line(obj);
obj->recvcnt = 0;
}
i++;
}
if (obj->recvcnt >= CLI_MAX_CMD_LEN) /*缓冲区满之后强制清空*/
obj->recvcnt = 0;
}
#if 1
/*******************************************************************************
* @brief
* @param[in] none
* @return strcmp
*******************************************************************************/
static int cmd_item_comparer(const void *item1,const void *item2)
{
cmd_item_t *it1 = *((cmd_item_t **)item1);
cmd_item_t *it2 = *((cmd_item_t **)item2);
return strcmp(it1->name, it2->name);
}
#endif
/*
* @brief
*/
static int do_help (struct cli_obj *s, int argc, char *argv[])
{
int i,j, count;
const cmd_item_t *item_start = &cmd_tbl_start + 1;
const cmd_item_t *item_end = &cmd_tbl_end;
const cmd_item_t *cmdtbl[CLI_MAX_CMDS];
if (argc == 2) {
if ((item_start = find_cmd(argv[1], strlen(argv[1]))) != NULL)
{
s->print(s, item_start->brief); /*命令使用信息----*/
s->print(s, "\r\n");
}
return 0;
}
for (i = 0; i < item_end - item_start && i < CLI_MAX_ARGS; i++)
cmdtbl[i] = &item_start[i];
count = i;
/*对命令进行排序 ---------------------------------------------------------*/
qsort(cmdtbl, i, sizeof(cmd_item_t*), cmd_item_comparer);
s->print(s, "\r\n");
for (i = 0; i < count; i++) {
s->print(s, cmdtbl[i]->name); /*打印命令名------*/
/*对齐调整*/
j = strlen(cmdtbl[i]->name);
if (j < 10)
j = 10 - j;
while (j--)
s->print(s, " ");
s->print(s, "- ");
s->print(s, cmdtbl[i]->brief); /*命令使用信息----*/
s->print(s, "\r\n");
}
return 1;
}
/*注册帮助命令 ---------------------------------------------------------------*/
cmd_register("help", do_help, "list all command.");
cmd_register("?", do_help, "alias for 'help'");

View File

@ -0,0 +1,99 @@
/******************************************************************************
* @brief (linux/kfifo)
*
* Copyright (c) 2016~2021, <morro_luo@163.com>
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2016-05-30 Morro Initial version
* 2021-02-05 Morro .
******************************************************************************/
#include "ringbuffer.h"
#include <string.h>
#include <stddef.h>
#define min(a,b) ( (a) < (b) )? (a):(b)
/*
*@brief
*@param[in] r -
*@param[in] buf -
*@param[in] len - buf长度(2N次幂)
*@retval bool
*/
bool ring_buf_init(ring_buf_t *r,unsigned char *buf, unsigned int len)
{
r->buf = buf;
r->size = len;
r->front = r->rear = 0;
return buf != NULL && (len & len -1) == 0;
}
/*
*@brief
*@param[in] r -
*@retval none
*/
void ring_buf_clr(ring_buf_t *r)
{
r->front = r->rear = 0;
}
/*
*@brief
*@retval
*/
unsigned int ring_buf_len(ring_buf_t *r)
{
return r->rear - r->front;
}
/*
*@brief
*@retval
*/
unsigned int ring_buf_free_space(ring_buf_t *r)
{
return r->size - (unsigned int)(r->rear - r->front);
}
/*
*@brief
*@param[in] buf -
* len -
*@retval
*/
unsigned int ring_buf_put(ring_buf_t *r,unsigned char *buf,unsigned int len)
{
unsigned int i;
unsigned int left;
left = r->size + r->front - r->rear;
len = min(len , left);
i = min(len, r->size - (r->rear & r->size - 1));
memcpy(r->buf + (r->rear & r->size - 1), buf, i);
memcpy(r->buf, buf + i, len - i);
r->rear += len;
return len;
}
/*
*@brief
*@param[in] len -
*@param[out] buf -
*@retval
*/
unsigned int ring_buf_get(ring_buf_t *r,unsigned char *buf,unsigned int len)
{
unsigned int i;
unsigned int left;
left = r->rear - r->front;
len = min(len , left);
i = min(len, r->size - (r->front & r->size - 1));
memcpy(buf, r->buf + (r->front & r->size - 1), i);
memcpy(buf + i, r->buf, len - i);
r->front += len;
return len;
}

View File

@ -1,201 +1,201 @@
Apache License Apache License
Version 2.0, January 2004 Version 2.0, January 2004
http://www.apache.org/licenses/ http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions. 1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, "License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document. and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by "Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License. the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all "Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition, control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the "control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity. outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity "You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License. exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, "Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation including but not limited to software source code, documentation
source, and configuration files. source, and configuration files.
"Object" form shall mean any form resulting from mechanical "Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation, not limited to compiled object code, generated documentation,
and conversions to other media types. and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or "Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work copyright notice that is included in or attached to the work
(an example is provided in the Appendix below). (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object "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 form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of, separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof. the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including "Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner 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 or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted" the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution." designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity "Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work. subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of 2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual, this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of, copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form. Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of 3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual, this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made, (except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work, use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s) Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate granted to You under this License for that Work shall terminate
as of the date such litigation is filed. as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the 4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You modifications, and in Source or Object form, provided that You
meet the following conditions: meet the following conditions:
(a) You must give any other recipients of the Work or (a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices (b) You must cause any modified files to carry prominent notices
stating that You changed the files; and stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works (c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work, attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of excluding those notices that do not pertain to any part of
the Derivative Works; and the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its (d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or, documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed that such additional attribution notices cannot be construed
as modifying the License. as modifying the License.
You may add Your own copyright statement to Your modifications and You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use, for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License. the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, 5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions. this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions. with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade 6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor, names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file. origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or 7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS, Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License. risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, 8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise, whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the 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 (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages. has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing 9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer, the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity, and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify, of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability. of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work. APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]" boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier same "printed page" as the copyright notice for easier
identification within third-party archives. identification within third-party archives.
Copyright [2015~2020] [master_roger@sina.com] Copyright [2015~2020] [master_roger@sina.com]
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.

View File

@ -1,21 +1,21 @@
/****************************************************************************** /******************************************************************************
* @brief ST mcu Ƭ<EFBFBD><EFBFBD>flash<EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @brief ST mcu Ƭ<EFBFBD><EFBFBD>flash<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* *
* Copyright (c) 2018~2020, <morro_luo@163.com> * Copyright (c) 2018~2020, <morro_luo@163.com>
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2018-09-09 Morro Initial version * 2018-09-09 roger.luo Initial version
******************************************************************************/ ******************************************************************************/
#ifndef _MCU_FLASH_H_ #ifndef _MCU_FLASH_H_
#define _MCU_FLASH_H_ #define _MCU_FLASH_H_
#include <stddef.h> #include <stddef.h>
int mcu_flash_erase(unsigned int addr, size_t size); int mcu_flash_erase(unsigned int addr, size_t size);
int mcu_flash_write(unsigned int addr ,const void *buf, size_t size); int mcu_flash_write(unsigned int addr ,const void *buf, size_t size);
int mcu_flash_read(unsigned int addr ,void *buf, size_t size); int mcu_flash_read(unsigned int addr ,void *buf, size_t size);
#endif #endif

View File

@ -1,30 +1,30 @@
/****************************************************************************** /******************************************************************************
* @brief tty<EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>ӡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @brief tty<EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>ӡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* *
* Copyright (c) 2015, <morro_luo@163.com> * Copyright (c) 2015, <morro_luo@163.com>
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2015-07-03 Morro * 2015-07-03 Morro
******************************************************************************/ ******************************************************************************/
#ifndef _TTY_H_ #ifndef _TTY_H_
#define _TTY_H_ #define _TTY_H_
#define TTY_RXBUF_SIZE 256 #define TTY_RXBUF_SIZE 256
#define TTY_TXBUF_SIZE 1024 #define TTY_TXBUF_SIZE 1024
/*<2A>ӿ<EFBFBD><D3BF><EFBFBD><EFBFBD><EFBFBD> --------------------------------------------------------------------*/ /*<2A>ӿ<EFBFBD><D3BF><EFBFBD><EFBFBD><EFBFBD> --------------------------------------------------------------------*/
typedef struct { typedef struct {
void (*init)(int baudrate); void (*init)(int baudrate);
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);
bool (*tx_isfull)(void); /*<2A><><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/ bool (*tx_isfull)(void); /*<2A><><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
bool (*rx_isempty)(void); /*<2A><><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/ bool (*rx_isempty)(void); /*<2A><><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
}tty_t; }tty_t;
extern const tty_t tty; extern const tty_t tty;
#endif #endif

View File

@ -1,28 +1,28 @@
/****************************************************************************** /******************************************************************************
* @brief wifi<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @brief wifi<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* *
* Copyright (c) 2021, <morro_luo@163.com> * Copyright (c) 2021, <morro_luo@163.com>
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2021-01-20 Morro <EFBFBD><EFBFBD>ʼ<EFBFBD> * 2021-01-20 roger.luo <EFBFBD><EFBFBD>ʼ<EFBFBD>
******************************************************************************/ ******************************************************************************/
#ifndef _WIFI_UART_H_ #ifndef _WIFI_UART_H_
#define _WIFI_UART_H_ #define _WIFI_UART_H_
#define WIFI_RXBUF_SIZE 256 #define WIFI_RXBUF_SIZE 256
#define WIFI_TXBUF_SIZE 1024 #define WIFI_TXBUF_SIZE 1024
/*<2A>ӿ<EFBFBD><D3BF><EFBFBD><EFBFBD><EFBFBD> --------------------------------------------------------------------*/ /*<2A>ӿ<EFBFBD><D3BF><EFBFBD><EFBFBD><EFBFBD> --------------------------------------------------------------------*/
void wifi_uart_init(int baud_rate); void wifi_uart_init(int baud_rate);
unsigned int wifi_uart_write(const void *buf, unsigned int len); unsigned int wifi_uart_write(const void *buf, unsigned int len);
unsigned int wifi_uart_read(void *buf, unsigned int len); unsigned int wifi_uart_read(void *buf, unsigned int len);
bool wifi_uart_rx_empty(void); bool wifi_uart_rx_empty(void);
#endif #endif

View File

@ -1,161 +1,161 @@
/****************************************************************************** /******************************************************************************
* @brief ST mcu Ƭ<EFBFBD><EFBFBD>flash<EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @brief ST mcu Ƭ<EFBFBD><EFBFBD>flash<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* *
* Copyright (c) 2018~2020, <morro_luo@163.com> * Copyright (c) 2018~2020, <morro_luo@163.com>
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2018-09-09 Morro Initial version * 2018-09-09 roger.luo Initial version
******************************************************************************/ ******************************************************************************/
#include "mcu_flash.h" #include "mcu_flash.h"
#include "stm32f4xx.h" #include "stm32f4xx.h"
#include <string.h> #include <string.h>
typedef struct { typedef struct {
unsigned int start; unsigned int start;
unsigned int size; unsigned int size;
unsigned int secnum; unsigned int secnum;
}sec_info_t; }sec_info_t;
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַӳ<D6B7><D3B3> ---------------------------------------------------------------*/ /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַӳ<D6B7><D3B3> ---------------------------------------------------------------*/
const sec_info_t sec_map[] = const sec_info_t sec_map[] =
{ {
{0x08000000, 16*1024, FLASH_Sector_0}, {0x08000000, 16*1024, FLASH_Sector_0},
{0x08004000, 16*1024, FLASH_Sector_1}, {0x08004000, 16*1024, FLASH_Sector_1},
{0x08008000, 16*1024, FLASH_Sector_2}, {0x08008000, 16*1024, FLASH_Sector_2},
{0x0800C000, 16*1024, FLASH_Sector_3}, {0x0800C000, 16*1024, FLASH_Sector_3},
{0x08010000, 64*1024, FLASH_Sector_4}, {0x08010000, 64*1024, FLASH_Sector_4},
{0x08020000, 128*1024, FLASH_Sector_5}, {0x08020000, 128*1024, FLASH_Sector_5},
{0x08040000, 128*1024, FLASH_Sector_6}, {0x08040000, 128*1024, FLASH_Sector_6},
{0x08040000, 128*1024, FLASH_Sector_7} {0x08040000, 128*1024, FLASH_Sector_7}
}; };
/* /*
* @brief stm32 mcu <EFBFBD>ڲ<EFBFBD>flash<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @brief stm32 mcu <EFBFBD>ڲ<EFBFBD>flash<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] addr - <EFBFBD><EFBFBD>ַ * @param[in] addr - <EFBFBD><EFBFBD>ַ
* @param[in] ̽<EFBFBD>մ<EFBFBD>С - size * @param[in] ̽<EFBFBD>մ<EFBFBD>С - size
* @return 0 - ʧ<EFBFBD><EFBFBD>, <EFBFBD><EFBFBD>0 - <EFBFBD>ɹ<EFBFBD> * @return 0 - ʧ<EFBFBD><EFBFBD>, <EFBFBD><EFBFBD>0 - <EFBFBD>ɹ<EFBFBD>
*/ */
int mcu_flash_erase(unsigned int addr, size_t size) int mcu_flash_erase(unsigned int addr, size_t size)
{ {
int i; int i;
int len = sizeof(sec_map) / sizeof(sec_info_t); int len = sizeof(sec_map) / sizeof(sec_info_t);
const sec_info_t *sec = &sec_map[len - 1]; const sec_info_t *sec = &sec_map[len - 1];
FLASH_Status status; FLASH_Status status;
/*Խ<><EFBFBD><E7B4A6>*/ /*Խ<><EFBFBD><E7B4A6>*/
if (addr > sec->start + sec->size) if (addr > sec->start + sec->size)
return 0; return 0;
FLASH_Unlock(); FLASH_Unlock();
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
{ {
sec = &sec_map[i]; sec = &sec_map[i];
if ( (sec->start >= addr && sec->start < addr + size) || if ( (sec->start >= addr && sec->start < addr + size) ||
(sec->start + sec->size > addr && sec->start + sec->size <= addr + size)) (sec->start + sec->size > addr && sec->start + sec->size <= addr + size))
{ {
//FLASH_OB_WRPConfig(); //FLASH_OB_WRPConfig();
status = FLASH_EraseSector(sec->secnum, VoltageRange_2); status = FLASH_EraseSector(sec->secnum, VoltageRange_2);
if (status != FLASH_COMPLETE) if (status != FLASH_COMPLETE)
{ {
FLASH_Lock(); FLASH_Lock();
return 0; return 0;
} }
} }
} }
FLASH_Lock(); FLASH_Lock();
return 1; return 1;
} }
/* /*
* @brief stm32 mcu <EFBFBD>ڲ<EFBFBD>flashд<EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @brief stm32 mcu <EFBFBD>ڲ<EFBFBD>flashд<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] addr - <EFBFBD><EFBFBD>ַ * @param[in] addr - <EFBFBD><EFBFBD>ַ
* @param[in] buf - <EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @param[in] buf - <EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] д<EFBFBD><EFBFBD><EFBFBD><EFBFBD>С - size * @param[in] д<EFBFBD><EFBFBD><EFBFBD><EFBFBD>С - size
* @return 0 - ʧ<EFBFBD><EFBFBD>, <EFBFBD><EFBFBD>0 - <EFBFBD>ɹ<EFBFBD> * @return 0 - ʧ<EFBFBD><EFBFBD>, <EFBFBD><EFBFBD>0 - <EFBFBD>ɹ<EFBFBD>
*/ */
int mcu_flash_write(unsigned int addr ,const void *buf, size_t size) int mcu_flash_write(unsigned int addr ,const void *buf, size_t size)
{ {
unsigned char *p = (uint8_t *)buf; unsigned char *p = (uint8_t *)buf;
// unsigned int base = addr; // unsigned int base = addr;
// size_t tlen = size; // size_t tlen = size;
int wrlen; int wrlen;
FLASH_Status status = FLASH_COMPLETE; FLASH_Status status = FLASH_COMPLETE;
int ret = 0; int ret = 0;
FLASH_Unlock(); FLASH_Unlock();
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_OPERR | FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_OPERR |
FLASH_FLAG_PGAERR); FLASH_FLAG_PGAERR);
while (size) { while (size) {
#if 0 #if 0
/*<2A><><EFBFBD>ݶ<EFBFBD><DDB6>ʽ<EBB7BD>Ż<EFBFBD>д<EFBFBD><EFBFBD><EBB3A4>*/ /*<2A><><EFBFBD>ݶ<EFBFBD><DDB6>ʽ<EBB7BD>Ż<EFBFBD>д<EFBFBD><EFBFBD><EBB3A4>*/
if ((addr & 7) == 0 && size > 8) /*8<>ֽڶ<D6BD><DAB6><EFBFBD>,<2C><>˫<EFBFBD><CBAB>д<EFBFBD><D0B4>*/ if ((addr & 7) == 0 && size > 8) /*8<>ֽڶ<D6BD><DAB6><EFBFBD>,<2C><>˫<EFBFBD><CBAB>д<EFBFBD><D0B4>*/
{ {
status = FLASH_ProgramDoubleWord(addr, *((uint64_t *)p)); status = FLASH_ProgramDoubleWord(addr, *((uint64_t *)p));
if (status != FLASH_COMPLETE) if (status != FLASH_COMPLETE)
goto _quit; goto _quit;
wrlen = 8; wrlen = 8;
} }
else if ((addr & 3) == 0 && size > 4) /*4<>ֽڶ<D6BD><DAB6><EFBFBD>,<2C><><EFBFBD><EFBFBD>д<EFBFBD><D0B4>*/ else if ((addr & 3) == 0 && size > 4) /*4<>ֽڶ<D6BD><DAB6><EFBFBD>,<2C><><EFBFBD><EFBFBD>д<EFBFBD><D0B4>*/
{ {
status = FLASH_ProgramWord(addr, *((uint32_t *)p)); status = FLASH_ProgramWord(addr, *((uint32_t *)p));
if (status != FLASH_COMPLETE) if (status != FLASH_COMPLETE)
goto _quit; goto _quit;
wrlen = 4; wrlen = 4;
} }
else if ((addr & 1) == 0 && size > 2) /*2<>ֽڶ<D6BD><DAB6><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4>*/ else if ((addr & 1) == 0 && size > 2) /*2<>ֽڶ<D6BD><DAB6><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4>*/
{ {
status = FLASH_ProgramHalfWord(addr, *((uint16_t *)p)); status = FLASH_ProgramHalfWord(addr, *((uint16_t *)p));
if (status != FLASH_COMPLETE) if (status != FLASH_COMPLETE)
goto _quit; goto _quit;
wrlen = 2; wrlen = 2;
} }
else /*<2A><><EFBFBD>ֽ<EFBFBD>д<EFBFBD><D0B4> --------*/ else /*<2A><><EFBFBD>ֽ<EFBFBD>д<EFBFBD><D0B4> --------*/
{ {
status = FLASH_ProgramByte(addr, *((uint8_t *)p)); status = FLASH_ProgramByte(addr, *((uint8_t *)p));
if (status != FLASH_COMPLETE) if (status != FLASH_COMPLETE)
goto _quit; goto _quit;
wrlen = 1; wrlen = 1;
} }
#endif #endif
if ((addr & 1) == 0 && size > 2) /*2<>ֽڶ<D6BD><DAB6><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4>*/ if ((addr & 1) == 0 && size > 2) /*2<>ֽڶ<D6BD><DAB6><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4>*/
{ {
status = FLASH_ProgramHalfWord(addr, *((uint16_t *)p)); status = FLASH_ProgramHalfWord(addr, *((uint16_t *)p));
if (status != FLASH_COMPLETE) if (status != FLASH_COMPLETE)
goto _quit; goto _quit;
wrlen = 2; wrlen = 2;
} }
else /*<2A><><EFBFBD>ֽ<EFBFBD>д<EFBFBD><D0B4> --------*/ else /*<2A><><EFBFBD>ֽ<EFBFBD>д<EFBFBD><D0B4> --------*/
{ {
status = FLASH_ProgramByte(addr, *((uint8_t *)p)); status = FLASH_ProgramByte(addr, *((uint8_t *)p));
if (status != FLASH_COMPLETE) if (status != FLASH_COMPLETE)
goto _quit; goto _quit;
wrlen = 1; wrlen = 1;
} }
/*<2A><>ַƫ<D6B7><C6AB> -------------------------------------------------------*/ /*<2A><>ַƫ<D6B7><C6AB> -------------------------------------------------------*/
size -= wrlen; size -= wrlen;
addr += wrlen; addr += wrlen;
p += wrlen; p += wrlen;
} }
_quit: _quit:
ret = status == FLASH_COMPLETE;// && memcmp(buf, (void *)base, tlen) ? 1 : 0; ret = status == FLASH_COMPLETE;// && memcmp(buf, (void *)base, tlen) ? 1 : 0;
FLASH_Lock(); FLASH_Lock();
return ret; return ret;
} }
/* /*
* @brief stm32 mcu <EFBFBD>ڲ<EFBFBD>flash<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @brief stm32 mcu <EFBFBD>ڲ<EFBFBD>flash<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] addr - <EFBFBD><EFBFBD>ַ * @param[in] addr - <EFBFBD><EFBFBD>ַ
* @param[in] buf - <EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @param[in] buf - <EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - size * @param[in] <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - size
* @return 0 - ʧ<EFBFBD><EFBFBD>, <EFBFBD><EFBFBD>0 - <EFBFBD>ɹ<EFBFBD> * @return 0 - ʧ<EFBFBD><EFBFBD>, <EFBFBD><EFBFBD>0 - <EFBFBD>ɹ<EFBFBD>
*/ */
int mcu_flash_read(unsigned int addr ,void *buf, size_t size) int mcu_flash_read(unsigned int addr ,void *buf, size_t size)
{ {
memcpy(buf, (void *)addr, size); memcpy(buf, (void *)addr, size);
return 0; return 0;
} }

View File

@ -1,125 +1,125 @@
/****************************************************************************** /******************************************************************************
* @brief tty<EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>ӡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @brief tty<EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>ӡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* *
* Copyright (c) 2015, <morro_luo@163.com> * Copyright (c) 2015, <morro_luo@163.com>
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2015-07-03 Morro * 2015-07-03 roger.luo
******************************************************************************/ ******************************************************************************/
#include "stm32f4xx.h" #include "stm32f4xx.h"
#include "ringbuffer.h" #include "ringbuffer.h"
#include "tty.h" #include "tty.h"
#include "public.h" #include "public.h"
#include <string.h> #include <string.h>
#if (TTY_RXBUF_SIZE & (TTY_RXBUF_SIZE - 1)) != 0 #if (TTY_RXBUF_SIZE & (TTY_RXBUF_SIZE - 1)) != 0
#error "TTY_RXBUF_SIZE must be power of 2!" #error "TTY_RXBUF_SIZE must be power of 2!"
#endif #endif
#if (TTY_TXBUF_SIZE & (TTY_TXBUF_SIZE - 1)) != 0 #if (TTY_TXBUF_SIZE & (TTY_TXBUF_SIZE - 1)) != 0
#error "TTY_RXBUF_SIZE must be power of 2!" #error "TTY_RXBUF_SIZE must be power of 2!"
#endif #endif
static unsigned char rxbuf[TTY_RXBUF_SIZE]; /*<2A><><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD> */ static unsigned char rxbuf[TTY_RXBUF_SIZE]; /*<2A><><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD> */
static unsigned char txbuf[TTY_TXBUF_SIZE]; /*<2A><><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD> */ static unsigned char txbuf[TTY_TXBUF_SIZE]; /*<2A><><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD> */
static ring_buf_t rbsend, rbrecv; /*<2A>շ<EFBFBD><D5B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/ static ring_buf_t rbsend, rbrecv; /*<2A>շ<EFBFBD><D5B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
/* /*
* @brief <EFBFBD><EFBFBD><EFBFBD>ڳ<EFBFBD>ʼ<EFBFBD><EFBFBD> * @brief <EFBFBD><EFBFBD><EFBFBD>ڳ<EFBFBD>ʼ<EFBFBD><EFBFBD>
* @param[in] baudrate - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @param[in] baudrate - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return none * @return none
*/ */
static void uart_init(int baudrate) static void uart_init(int baudrate)
{ {
ring_buf_init(&rbsend, txbuf, sizeof(txbuf));/*<2A><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD> */ ring_buf_init(&rbsend, txbuf, sizeof(txbuf));/*<2A><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD> */
ring_buf_init(&rbrecv, rxbuf, sizeof(rxbuf)); ring_buf_init(&rbrecv, rxbuf, sizeof(rxbuf));
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA , ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA , ENABLE);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
gpio_conf(GPIOA, GPIO_Mode_AF, GPIO_PuPd_NOPULL, gpio_conf(GPIOA, GPIO_Mode_AF, GPIO_PuPd_NOPULL,
GPIO_Pin_9 | GPIO_Pin_10); GPIO_Pin_9 | GPIO_Pin_10);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
uart_conf(USART1, baudrate); /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/ uart_conf(USART1, baudrate); /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
nvic_conf(USART1_IRQn, 1, 1); nvic_conf(USART1_IRQn, 1, 1);
} }
/* /*
* @brief <EFBFBD>򴮿ڷ<EFBFBD><EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @brief <EFBFBD>򴮿ڷ<EFBFBD><EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] buf - <EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD> * @param[in] buf - <EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD>
* @param[in] len - <EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><EFBFBD><EFBFBD> * @param[in] len - <EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><EFBFBD><EFBFBD>
* @return ʵ<EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<EFBFBD>򷵻<EFBFBD>len) * @return ʵ<EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<EFBFBD>򷵻<EFBFBD>len)
*/ */
static unsigned int uart_write(const void *buf, unsigned int len) static unsigned int uart_write(const void *buf, unsigned int len)
{ {
unsigned int ret; unsigned int ret;
ret = ring_buf_put(&rbsend, (unsigned char *)buf, len); ret = ring_buf_put(&rbsend, (unsigned char *)buf, len);
USART_ITConfig(USART1, USART_IT_TXE, ENABLE); USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
return ret; return ret;
} }
/* /*
* @brief <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>ڽ<EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @brief <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>ڽ<EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] buf - <EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD> * @param[in] buf - <EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD>
* @param[in] len - <EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><EFBFBD><EFBFBD> * @param[in] len - <EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><EFBFBD><EFBFBD>
* @return (ʵ<EFBFBD>ʶ<EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD><EFBFBD><EFBFBD>len<EFBFBD>򷵻<EFBFBD>len<EFBFBD><EFBFBD><EFBFBD>򷵻ػ<EFBFBD><EFBFBD><EFBFBD> * @return (ʵ<EFBFBD>ʶ<EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD><EFBFBD><EFBFBD>len<EFBFBD>򷵻<EFBFBD>len<EFBFBD><EFBFBD><EFBFBD>򷵻ػ<EFBFBD><EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><EFBFBD><EFBFBD>ݵij<EFBFBD><EFBFBD><EFBFBD> * <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><EFBFBD><EFBFBD>ݵij<EFBFBD><EFBFBD><EFBFBD>
*/ */
static unsigned int uart_read(void *buf, unsigned int len) static unsigned int uart_read(void *buf, unsigned int len)
{ {
return ring_buf_get(&rbrecv, (unsigned char *)buf, len); return ring_buf_get(&rbrecv, (unsigned char *)buf, len);
} }
/*<2A><><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/ /*<2A><><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
static bool tx_isfull(void) static bool tx_isfull(void)
{ {
return ring_buf_len(&rbsend) == TTY_TXBUF_SIZE; return ring_buf_len(&rbsend) == TTY_TXBUF_SIZE;
} }
/*<2A><><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/ /*<2A><><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
bool rx_isempty(void) bool rx_isempty(void)
{ {
return ring_buf_len(&rbrecv) == 0; return ring_buf_len(&rbrecv) == 0;
} }
/*<2A><><EFBFBD><EFBFBD>̨<EFBFBD>ӿڶ<D3BF><DAB6><EFBFBD> -------------------------------------------------------------*/ /*<2A><><EFBFBD><EFBFBD>̨<EFBFBD>ӿڶ<D3BF><DAB6><EFBFBD> -------------------------------------------------------------*/
const tty_t tty = { const tty_t tty = {
uart_init, uart_init,
uart_write, uart_write,
uart_read, uart_read,
tx_isfull, tx_isfull,
rx_isempty rx_isempty
}; };
/* /*
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>1<EFBFBD>շ<EFBFBD><EFBFBD>ж<EFBFBD> * @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>1<EFBFBD>շ<EFBFBD><EFBFBD>ж<EFBFBD>
* @param[in] none * @param[in] none
* @return none * @return none
*/ */
void USART1_IRQHandler(void) void USART1_IRQHandler(void)
{ {
unsigned char data; unsigned char data;
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
data = USART_ReceiveData(USART1); data = USART_ReceiveData(USART1);
ring_buf_put(&rbrecv, &data, 1); /*<2A><><EFBFBD><EFBFBD><EFBFBD>ݷ<EFBFBD><DDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>*/ ring_buf_put(&rbrecv, &data, 1); /*<2A><><EFBFBD><EFBFBD><EFBFBD>ݷ<EFBFBD><DDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>*/
} }
if (USART_GetITStatus(USART1, USART_IT_TXE) != RESET) { if (USART_GetITStatus(USART1, USART_IT_TXE) != RESET) {
if (ring_buf_get(&rbsend, &data, 1)) /*<2A>ӻ<EFBFBD><D3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>---*/ if (ring_buf_get(&rbsend, &data, 1)) /*<2A>ӻ<EFBFBD><D3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>---*/
USART_SendData(USART1, data); USART_SendData(USART1, data);
else{ else{
USART_ITConfig(USART1, USART_IT_TXE, DISABLE); USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
} }
} }
if (USART_GetITStatus(USART1, USART_IT_ORE_RX) != RESET) { if (USART_GetITStatus(USART1, USART_IT_ORE_RX) != RESET) {
data = USART_ReceiveData(USART1); data = USART_ReceiveData(USART1);
} }
} }

View File

@ -1,108 +1,108 @@
/****************************************************************************** /******************************************************************************
* @brief wifi<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @brief wifi<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* *
* Copyright (c) 2021, <morro_luo@163.com> * Copyright (c) 2021, <morro_luo@163.com>
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2021-01-20 Morro <EFBFBD><EFBFBD>ʼ<EFBFBD> * 2021-01-20 roger.luo <EFBFBD><EFBFBD>ʼ<EFBFBD>
******************************************************************************/ ******************************************************************************/
#include "stm32f4xx.h" #include "stm32f4xx.h"
#include "ringbuffer.h" #include "ringbuffer.h"
#include "wifi_uart.h" #include "wifi_uart.h"
#include "public.h" #include "public.h"
#include <string.h> #include <string.h>
#if (TTY_RXBUF_SIZE & (TTY_RXBUF_SIZE - 1)) != 0 #if (TTY_RXBUF_SIZE & (TTY_RXBUF_SIZE - 1)) != 0
#error "TTY_RXBUF_SIZE must be power of 2!" #error "TTY_RXBUF_SIZE must be power of 2!"
#endif #endif
#if (TTY_TXBUF_SIZE & (TTY_TXBUF_SIZE - 1)) != 0 #if (TTY_TXBUF_SIZE & (TTY_TXBUF_SIZE - 1)) != 0
#error "TTY_RXBUF_SIZE must be power of 2!" #error "TTY_RXBUF_SIZE must be power of 2!"
#endif #endif
static unsigned char rxbuf[WIFI_RXBUF_SIZE]; /*<2A><><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD> */ static unsigned char rxbuf[WIFI_RXBUF_SIZE]; /*<2A><><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD> */
static unsigned char txbuf[WIFI_TXBUF_SIZE]; /*<2A><><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD> */ static unsigned char txbuf[WIFI_TXBUF_SIZE]; /*<2A><><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD> */
static ring_buf_t rbsend, rbrecv; /*<2A>շ<EFBFBD><D5B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/ static ring_buf_t rbsend, rbrecv; /*<2A>շ<EFBFBD><D5B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
/* /*
* @brief wifi<EFBFBD><EFBFBD><EFBFBD>ڳ<EFBFBD>ʼ<EFBFBD><EFBFBD> * @brief wifi<EFBFBD><EFBFBD><EFBFBD>ڳ<EFBFBD>ʼ<EFBFBD><EFBFBD>
* @param[in] baudrate - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @param[in] baudrate - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return none * @return none
*/ */
void wifi_uart_init(int baud_rate) void wifi_uart_init(int baud_rate)
{ {
ring_buf_init(&rbsend, txbuf, sizeof(txbuf));/*<2A><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD> */ ring_buf_init(&rbsend, txbuf, sizeof(txbuf));/*<2A><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD> */
ring_buf_init(&rbrecv, rxbuf, sizeof(rxbuf)); ring_buf_init(&rbrecv, rxbuf, sizeof(rxbuf));
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB , ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB , ENABLE);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3); GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_USART3); GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_USART3);
gpio_conf(GPIOB, GPIO_Mode_AF, GPIO_PuPd_NOPULL, GPIO_Pin_10 | GPIO_Pin_11); gpio_conf(GPIOB, GPIO_Mode_AF, GPIO_PuPd_NOPULL, GPIO_Pin_10 | GPIO_Pin_11);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
uart_conf(USART3, baud_rate); /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/ uart_conf(USART3, baud_rate); /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
nvic_conf(USART3_IRQn, 1, 1); nvic_conf(USART3_IRQn, 1, 1);
} }
/* /*
* @brief <EFBFBD>򴮿ڷ<EFBFBD><EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @brief <EFBFBD>򴮿ڷ<EFBFBD><EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] buf - <EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD> * @param[in] buf - <EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD>
* @param[in] len - <EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><EFBFBD><EFBFBD> * @param[in] len - <EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><EFBFBD><EFBFBD>
* @return ʵ<EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<EFBFBD>򷵻<EFBFBD>len) * @return ʵ<EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<EFBFBD>򷵻<EFBFBD>len)
*/ */
unsigned int wifi_uart_write(const void *buf, unsigned int len) unsigned int wifi_uart_write(const void *buf, unsigned int len)
{ {
unsigned int ret; unsigned int ret;
ret = ring_buf_put(&rbsend, (unsigned char *)buf, len); ret = ring_buf_put(&rbsend, (unsigned char *)buf, len);
USART_ITConfig(USART3, USART_IT_TXE, ENABLE); USART_ITConfig(USART3, USART_IT_TXE, ENABLE);
return ret; return ret;
} }
/* /*
* @brief <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>ڽ<EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @brief <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>ڽ<EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] buf - <EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD> * @param[in] buf - <EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD>
* @param[in] len - <EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><EFBFBD><EFBFBD> * @param[in] len - <EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><EFBFBD><EFBFBD>
* @return (ʵ<EFBFBD>ʶ<EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD><EFBFBD><EFBFBD>len<EFBFBD>򷵻<EFBFBD>len<EFBFBD><EFBFBD><EFBFBD>򷵻ػ<EFBFBD><EFBFBD><EFBFBD> * @return (ʵ<EFBFBD>ʶ<EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD><EFBFBD><EFBFBD>len<EFBFBD>򷵻<EFBFBD>len<EFBFBD><EFBFBD><EFBFBD>򷵻ػ<EFBFBD><EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><EFBFBD><EFBFBD>ݵij<EFBFBD><EFBFBD><EFBFBD> * <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD><EFBFBD><EFBFBD>ݵij<EFBFBD><EFBFBD><EFBFBD>
*/ */
unsigned int wifi_uart_read(void *buf, unsigned int len) unsigned int wifi_uart_read(void *buf, unsigned int len)
{ {
return ring_buf_get(&rbrecv, (unsigned char *)buf, len); return ring_buf_get(&rbrecv, (unsigned char *)buf, len);
} }
/*<2A><><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/ /*<2A><><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
bool wifi_uart_rx_empty(void) bool wifi_uart_rx_empty(void)
{ {
return ring_buf_len(&rbrecv) == 0; return ring_buf_len(&rbrecv) == 0;
} }
/* /*
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>1<EFBFBD>շ<EFBFBD><EFBFBD>ж<EFBFBD> * @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>1<EFBFBD>շ<EFBFBD><EFBFBD>ж<EFBFBD>
* @param[in] none * @param[in] none
* @return none * @return none
*/ */
void USART3_IRQHandler(void) void USART3_IRQHandler(void)
{ {
unsigned char data; unsigned char data;
if (USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) { if (USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) {
data = USART_ReceiveData(USART3); data = USART_ReceiveData(USART3);
ring_buf_put(&rbrecv, &data, 1); /*<2A><><EFBFBD><EFBFBD><EFBFBD>ݷ<EFBFBD><DDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>*/ ring_buf_put(&rbrecv, &data, 1); /*<2A><><EFBFBD><EFBFBD><EFBFBD>ݷ<EFBFBD><DDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>*/
} }
if (USART_GetITStatus(USART3, USART_IT_TXE) != RESET) { if (USART_GetITStatus(USART3, USART_IT_TXE) != RESET) {
if (ring_buf_get(&rbsend, &data, 1)) /*<2A>ӻ<EFBFBD><D3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>---*/ if (ring_buf_get(&rbsend, &data, 1)) /*<2A>ӻ<EFBFBD><D3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>---*/
USART_SendData(USART3, data); USART_SendData(USART3, data);
else{ else{
USART_ITConfig(USART3, USART_IT_TXE, DISABLE); USART_ITConfig(USART3, USART_IT_TXE, DISABLE);
} }
} }
if (USART_GetITStatus(USART3, USART_IT_ORE_RX) != RESET) { if (USART_GetITStatus(USART3, USART_IT_ORE_RX) != RESET) {
data = USART_ReceiveData(USART3); data = USART_ReceiveData(USART3);
} }
} }

View File

@ -1,94 +1,94 @@
/****************************************************************************** /******************************************************************************
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˸<EFBFBD><EFBFBD><EFBFBD><EFBFBD>(dev, motor, buzzer)<EFBFBD><EFBFBD><EFBFBD>(dev, motor, buzzer)<EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˸<EFBFBD><EFBFBD><EFBFBD><EFBFBD>(dev, motor, buzzer)<EFBFBD><EFBFBD><EFBFBD>(dev, motor, buzzer)<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* *
* Copyright (c) 2019, <morro_luo@163.com> * Copyright (c) 2019, <morro_luo@163.com>
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2019-04-01 Morro Initial version * 2019-04-01 roger.luo Initial version
******************************************************************************/ ******************************************************************************/
#include "module.h" /*get_tick()*/ #include "module.h" /*get_tick()*/
#include "blink.h" #include "blink.h"
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
static blink_dev_t *head = NULL; /*ͷ<><CDB7><EFBFBD><EFBFBD> -*/ static blink_dev_t *head = NULL; /*ͷ<><CDB7><EFBFBD><EFBFBD> -*/
/* /*
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>blink<EFBFBD> * @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>blink<EFBFBD>
* @param[in] dev - <EFBFBD> * @param[in] dev - <EFBFBD>
* @param[in] ioctrl - IO<EFBFBD><EFBFBD><EFBFBD>ƺ<EFBFBD><EFBFBD><EFBFBD> * @param[in] ioctrl - IO<EFBFBD><EFBFBD><EFBFBD>ƺ<EFBFBD><EFBFBD><EFBFBD>
* @return none * @return none
*/ */
void blink_dev_create(blink_dev_t *dev, void (*ioctrl)(bool enable)) void blink_dev_create(blink_dev_t *dev, void (*ioctrl)(bool enable))
{ {
blink_dev_t *tail = head; blink_dev_t *tail = head;
memset(dev, 0, sizeof(blink_dev_t)); memset(dev, 0, sizeof(blink_dev_t));
dev->ioctrl = ioctrl; dev->ioctrl = ioctrl;
dev->next = NULL; dev->next = NULL;
if (head == NULL) { if (head == NULL) {
head = dev; head = dev;
return; return;
} }
while (tail->next != NULL) while (tail->next != NULL)
tail = tail->next; tail = tail->next;
tail->next = dev; tail->next = dev;
} }
/* /*
* @brief blink <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @brief blink <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] name - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @param[in] name - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] ontime - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵΪ0<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ùر<EFBFBD>) * @param[in] ontime - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵΪ0<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ùر<EFBFBD>)
* @param[in] offtime- <EFBFBD>ر<EFBFBD>ʱ<EFBFBD><EFBFBD> * @param[in] offtime- <EFBFBD>ر<EFBFBD>ʱ<EFBFBD><EFBFBD>
* @param[in] repeats- <EFBFBD>ظ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(0<EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD>) * @param[in] repeats- <EFBFBD>ظ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(0<EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><EFBFBD>)
* @return none * @return none
*/ */
void blink_dev_ctrl(blink_dev_t *dev, int ontime, int offtime, int repeats) void blink_dev_ctrl(blink_dev_t *dev, int ontime, int offtime, int repeats)
{ {
dev->ontime = ontime; dev->ontime = ontime;
dev->offtime = offtime + ontime; dev->offtime = offtime + ontime;
dev->repeats = repeats; dev->repeats = repeats;
dev->tick = get_tick(); dev->tick = get_tick();
dev->count = 0; dev->count = 0;
if (ontime == 0) { if (ontime == 0) {
dev->ioctrl(false); dev->ioctrl(false);
dev->enable = false; dev->enable = false;
} }
} }
/* /*
* @brief blink<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @brief blink<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] none * @param[in] none
* @return none * @return none
*/ */
void blink_dev_process(void) void blink_dev_process(void)
{ {
blink_dev_t *dev; blink_dev_t *dev;
for (dev = head; dev != NULL; dev = dev->next) { for (dev = head; dev != NULL; dev = dev->next) {
if (dev->ontime == 0) { if (dev->ontime == 0) {
continue; continue;
} else if (get_tick() - dev->tick < dev->ontime) { } else if (get_tick() - dev->tick < dev->ontime) {
if (!dev->enable) { if (!dev->enable) {
dev->enable = true; dev->enable = true;
dev->ioctrl(true); dev->ioctrl(true);
} }
} else if(get_tick() - dev->tick < dev->offtime) { /**/ } else if(get_tick() - dev->tick < dev->offtime) { /**/
if (dev->enable) { if (dev->enable) {
dev->enable = false; dev->enable = false;
dev->ioctrl(false); dev->ioctrl(false);
} }
} else { } else {
dev->tick = get_tick(); dev->tick = get_tick();
if (dev->repeats) { if (dev->repeats) {
if (++dev->count >= dev->repeats) { if (++dev->count >= dev->repeats) {
dev->ontime = 0; dev->ontime = 0;
dev->ioctrl(false); dev->ioctrl(false);
dev->enable = false; dev->enable = false;
} }
} }
} }
} }
} }

View File

@ -1,43 +1,43 @@
/****************************************************************************** /******************************************************************************
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˸<EFBFBD><EFBFBD><EFBFBD><EFBFBD>(dev, motor, buzzer)<EFBFBD><EFBFBD><EFBFBD>(dev, motor, buzzer)<EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˸<EFBFBD><EFBFBD><EFBFBD><EFBFBD>(dev, motor, buzzer)<EFBFBD><EFBFBD><EFBFBD>(dev, motor, buzzer)<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* *
* Copyright (c) 2019, <morro_luo@163.com> * Copyright (c) 2019, <morro_luo@163.com>
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2019-04-01 Morro Initial version * 2019-04-01 roger.luo Initial version
******************************************************************************/ ******************************************************************************/
#ifndef _BLINK_H_ #ifndef _BLINK_H_
#define _BLINK_H_ #define _BLINK_H_
#include "module.h" #include "module.h"
#include <stdbool.h> #include <stdbool.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*Blink <20><EFBFBD><E8B1B8><EFBFBD><EFBFBD>*/ /*Blink <20><EFBFBD><E8B1B8><EFBFBD><EFBFBD>*/
typedef struct blink_dev { typedef struct blink_dev {
unsigned short ontime; /*<2A><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>*/ unsigned short ontime; /*<2A><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>*/
unsigned short offtime; /*<2A>ر<EFBFBD>ʱ<EFBFBD><CAB1>*/ unsigned short offtime; /*<2A>ر<EFBFBD>ʱ<EFBFBD><CAB1>*/
unsigned short repeats; /*<2A>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD>*/ unsigned short repeats; /*<2A>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD>*/
unsigned char count; unsigned char count;
unsigned char enable; unsigned char enable;
unsigned int tick; unsigned int tick;
void (*ioctrl)(bool enable); /*io<69><6F><EFBFBD>ƽӿ<C6BD>*/ void (*ioctrl)(bool enable); /*io<69><6F><EFBFBD>ƽӿ<C6BD>*/
struct blink_dev *next; struct blink_dev *next;
}blink_dev_t; }blink_dev_t;
void blink_dev_create(blink_dev_t *dev, void (*ioctrl)(bool enable)); void blink_dev_create(blink_dev_t *dev, void (*ioctrl)(bool enable));
void blink_dev_ctrl(blink_dev_t *dev, int ontime, int offtime, int repeat); void blink_dev_ctrl(blink_dev_t *dev, int ontime, int offtime, int repeat);
void blink_dev_process(void); void blink_dev_process(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif

View File

@ -1,235 +1,318 @@
/****************************************************************************** /******************************************************************************
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD> * @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD>
* *
* Copyright (c) 2015-2020, <morro_luo@163.com> * Copyright (c) 2015-2020, <morro_luo@163.com>
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2015-06-09 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD> * 2015-06-09 roger.luo <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* *
* 2017-07-04 Morro <EFBFBD>Ż<EFBFBD><EFBFBD>ֶηָ<EFBFBD><EFBFBD> * 2017-07-04 roger.luo <EFBFBD>Ż<EFBFBD><EFBFBD>ֶηָ<EFBFBD><EFBFBD>
* *
* 2020-07-05 Morro ʹ<EFBFBD><EFBFBD>cli_obj_t<EFBFBD><EFBFBD><EFBFBD><EFBFBD>, ֧<EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> * 2020-07-05 roger.luo ʹ<EFBFBD><EFBFBD>cli_obj_t<EFBFBD><EFBFBD><EFBFBD><EFBFBD>, ֧<EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
******************************************************************************/ ******************************************************************************/
#include "cli.h" #include "cli.h"
#include <string.h> #include <stdio.h>
#include <stdio.h> #include <string.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
static const cmd_item_t cmd_tbl_start SECTION("cli.cmd.0") = {0}; static const cmd_item_t cmd_tbl_start SECTION("cli.cmd.0") = {0};
static const cmd_item_t cmd_tbl_end SECTION("cli.cmd.4") = {0}; static const cmd_item_t cmd_tbl_end SECTION("cli.cmd.4") = {0};
/* /**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] keyword - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD><EFBFBD><EFBFBD> * @param[in] keyword - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD><EFBFBD><EFBFBD>
* @return <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @return <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/ */
static const cmd_item_t *find_cmd(const char *keyword) static const cmd_item_t *find_cmd(const char *keyword, int n)
{ {
const cmd_item_t *it; const cmd_item_t *it;
for (it = &cmd_tbl_start + 1; it < &cmd_tbl_end; it++) { for (it = &cmd_tbl_start + 1; it < &cmd_tbl_end; it++) {
if (!strcasecmp(keyword, it->name)) if (!strncasecmp(keyword, it->name, n))
return it; return it;
} }
return NULL; return NULL;
} }
/******************************************************************************* /*******************************************************************************
* @brief <EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD> - <EFBFBD><EFBFBD>Դ<EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>separatorָ<EFBFBD><EFBFBD><EFBFBD>ķָ<EFBFBD><EFBFBD><EFBFBD> * @brief <EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD> - <EFBFBD><EFBFBD>Դ<EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>separatorָ<EFBFBD><EFBFBD><EFBFBD>ķָ<EFBFBD><EFBFBD><EFBFBD>
* (<EFBFBD><EFBFBD>',')<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>'\0'<EFBFBD>γ<EFBFBD><EFBFBD>Ӵ<EFBFBD><EFBFBD><EFBFBD>ͬʱ<EFBFBD><EFBFBD>list * (<EFBFBD><EFBFBD>',')<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>'\0'<EFBFBD>γ<EFBFBD><EFBFBD>Ӵ<EFBFBD><EFBFBD><EFBFBD>ͬʱ<EFBFBD><EFBFBD>list
* ָ<EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><EFBFBD>е<EFBFBD>ÿһ<EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>ָ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>Ӵ<EFBFBD> * ָ<EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><EFBFBD>е<EFBFBD>ÿһ<EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>ָ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>Ӵ<EFBFBD>
* @example * @example
* input=> s = "abc,123,456,,fb$" * input=> s = "abc,123,456,,fb$"
* separator = ",$" * separator = ",$"
* *
* output=>s = abc'\0' 123'\0' 456'\0' '\0' fb'\0''\0' * output=>s = abc'\0' 123'\0' 456'\0' '\0' fb'\0''\0'
* list[0] = "abc" * list[0] = "abc"
* list[1] = "123" * list[1] = "123"
* list[2] = "456" * list[2] = "456"
* list[3] = "" * list[3] = ""
* list[4] = "fb" * list[4] = "fb"
* list[5] = "" * list[5] = ""
* *
* @param[in] str - Դ<EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD> * @param[in] str - Դ<EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
* @param[in] separator - <EFBFBD>ָ<EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD> * @param[in] separator - <EFBFBD>ָ<EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>
* @param[in] list - <EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD>б<EFBFBD> * @param[in] list - <EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>
* @param[in] len - <EFBFBD>б<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @param[in] len - <EFBFBD>б<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return listָ<EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>򷵻<EFBFBD>6 * @return listָ<EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>򷵻<EFBFBD>6
******************************************************************************/ ******************************************************************************/
static size_t strsplit(char *s, const char *separator, char *list[], size_t len) static size_t strsplit(char *s, const char *separator, char *list[], size_t len)
{ {
size_t count = 0; size_t count = 0;
if (s == NULL || list == NULL || len == 0) if (s == NULL || list == NULL || len == 0)
return 0; return 0;
list[count++] = s; list[count++] = s;
while(*s && count < len) { while(*s && count < len) {
if (strchr(separator, *s) != NULL) { if (strchr(separator, *s) != NULL) {
*s = '\0'; *s = '\0';
list[count++] = s + 1; /*ָ<><D6B8><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>Ӵ<EFBFBD>*/ list[count++] = s + 1; /*ָ<><D6B8><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>Ӵ<EFBFBD>*/
} }
s++; s++;
} }
return count; return count;
} }
/*
*@brief <EFBFBD><EFBFBD>ӡһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڿ<EFBFBD><EFBFBD><EFBFBD>̨
*@retval /**
*/ * @brief <EFBFBD><EFBFBD>ӡһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڿ<EFBFBD><EFBFBD><EFBFBD>̨
static void cli_print(cli_obj_t *obj, const char *format, ...) * @retval
{ */
va_list args; static void cli_print(cli_obj_t *obj, const char *format, ...)
int len; {
char buf[CLI_MAX_CMD_LEN + CLI_MAX_CMD_LEN / 2]; va_list args;
va_start (args, format); int len;
len = vsnprintf (buf, sizeof(buf), format, args); char buf[CLI_MAX_CMD_LEN + CLI_MAX_CMD_LEN / 2];
obj->write(buf, len); va_start (args, format);
} len = vsnprintf (buf, sizeof(buf), format, args);
va_end (args);
obj->write(buf, len);
/* }
* @brief cli <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>
* @param[in] p - cli<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӿ<EFBFBD>
* @return none /**
*/ * @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void cli_init(cli_obj_t *obj, const cli_port_t *p) * @param[in] line - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{ * @return none
obj->read = p->read; **/
obj->write = p->write; static void process_line(cli_obj_t *obj)
obj->print = cli_print; {
obj->enable = true; char *argv[CLI_MAX_ARGS];
} int argc, ret, isat = 0;
const cmd_item_t *it;
/*
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>cli<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ(cli<EFBFBD><EFBFBD>ʱ<EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] none if (obj->guard && !obj->guard(obj->recvbuf))
* @return none return;
**/
void cli_enable(cli_obj_t *obj) if (obj->echo) { //<2F><><EFBFBD><EFBFBD>
{ obj->print(obj,"%s\r\n",obj->recvbuf);
obj->enable = true; }
}
argc = strsplit(obj->recvbuf, ",",argv, CLI_MAX_ARGS);
/*
* @brief <EFBFBD>˳<EFBFBD>cli<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ(cli<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>ٴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>) const char *start, *end;
* @param[in] none
* @return none if (argv[0] == NULL)
**/ return;
void cli_disable (cli_obj_t *obj)
{ if (strcasecmp("AT", argv[0]) == 0) {
obj->enable = false; obj->print(obj, "OK\r\n");
} return;
}
/* #if CLI_AT_ENABLE != 0
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> isat = strncasecmp(argv[0], "AT+", 3) == 0;
* @param[in] line - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> #endif
* @return none
**/ start= !isat ? argv[0] : argv[0] + 3;
static void process_line(cli_obj_t *obj)
{ if ((end = strchr(start, '=')) != NULL) {
char *argv[CLI_MAX_ARGS]; obj->type = CLI_CMD_TYPE_SET;
int argc;
const cmd_item_t *it; } else if ((end = strchr(start, '?')) != NULL) {
argc = strsplit(obj->recvbuf, " ,",argv, CLI_MAX_ARGS); obj->type = CLI_CMD_TYPE_QUERY;
if ((it = find_cmd(argv[0])) == NULL) {
obj->print(obj, "Unknown command '%s' - try 'help'\r\n", argv[0]); } else {
return; obj->type = CLI_CMD_TYPE_EXEC;
} end = start + strlen(argv[0]);
it->handler(obj, argc, argv); }
} if (start == end)
return;
/*
* @brief ִ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD>cli<EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD>) if ((it = find_cmd(start, end - start)) == NULL) {
* @param[in] none obj->print(obj, "%s\r\n", isat ? "ERROR" : "");
* @return none return;
**/ }
void cli_exec_cmd(cli_obj_t *obj, const char *cmd) ret = it->handler(obj, argc, argv);
{ if (isat) {
snprintf(obj->recvbuf, CLI_MAX_CMD_LEN, "%s", cmd); obj->print(obj, "%s\r\n" ,ret ? "OK":"ERROR");
process_line(obj); }
} }
/* /**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @brief <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
* @param[in] none */
* @return none static int get_val(struct cli_obj *self)
**/ {
void cli_process(cli_obj_t *obj) char *p;
{ p = strchr(self->recvbuf, '=');
if ( p == NULL)
int i; return 0;
if (!obj->read || !obj->enable) return atoi(p + 1);
return;
i = obj->recvcnt; }
obj->recvcnt += obj->read(&obj->recvbuf[i], CLI_MAX_CMD_LEN - i);
while (i < obj->recvcnt) { /**
if (obj->recvbuf[i] == '\r' || obj->recvbuf[i] == '\n') { /*<2A><>ȡ1<C8A1><31>*/ * @brief cli <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>
obj->recvbuf[i] = '\0'; * @param[in] p - cli<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӿ<EFBFBD>
process_line(obj); * @return none
obj->recvcnt = 0; */
} void cli_init(cli_obj_t *obj, const cli_port_t *p)
i++; {
} obj->read = p->read;
} obj->write = p->write;
obj->print = cli_print;
obj->enable = true;
/******************************************************************************* obj->get_val = get_val;
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƚ<EFBFBD><EFBFBD><EFBFBD> obj->guard = p->cmd_guard;
* @param[in] none }
* @return <EFBFBD>ο<EFBFBD>strcmp
*******************************************************************************/ /**
static int cmd_item_comparer(const void *item1,const void *item2) * @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>cli<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ(cli<EFBFBD><EFBFBD>ʱ<EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
{ * @param[in] none
cmd_item_t *it1 = *((cmd_item_t **)item1); * @return none
cmd_item_t *it2 = *((cmd_item_t **)item2); **/
return strcmp(it1->name, it2->name); void cli_enable(cli_obj_t *obj)
} {
char a;
/* obj->enable = true;
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> obj->recvcnt = 0;
*/ while (obj->read(&a, 1) > 0) {}
static int do_help (struct cli_obj *s, int argc, char *argv[]) }
{
int i,j, count; /**
const cmd_item_t *item_start = &cmd_tbl_start + 1; * @brief <EFBFBD>˳<EFBFBD>cli<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģʽ(cli<EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD>ٴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
const cmd_item_t *item_end = &cmd_tbl_end; * @param[in] none
const cmd_item_t *cmdtbl[CLI_MAX_CMDS]; * @return none
**/
if (argc == 2) { void cli_disable (cli_obj_t *obj)
if ((item_start = find_cmd(argv[1])) != NULL) {
{ obj->enable = false;
s->print(s, item_start->brief); /*<2A><><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD>Ϣ----*/ }
s->print(s, "\r\n");
} /**
return 0; * @brief <EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD>
} * @param[in] echo - <EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD>ؿ<EFBFBD><EFBFBD><EFBFBD>(0/1)
for (i = 0; i < item_end - item_start && i < CLI_MAX_ARGS; i++) * @return none
cmdtbl[i] = &item_start[i]; **/
count = i; void cli_echo_ctrl (cli_obj_t *obj, int echo)
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ---------------------------------------------------------*/ {
qsort(cmdtbl, i, sizeof(cmd_item_t*), cmd_item_comparer); obj->echo = echo;
s->print(s, "\r\n"); }
for (i = 0; i < count; i++) {
s->print(s, cmdtbl[i]->name); /*<2A><>ӡ<EFBFBD><D3A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>------*/ /**
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/ * @brief ִ<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD>cli<EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD>)
j = strlen(cmdtbl[i]->name); * @param[in] none
if (j < 10) * @return none
j = 10 - j; **/
void cli_exec_cmd(cli_obj_t *obj, const char *cmd)
while (j--) {
s->print(s, " "); int len = strlen(cmd);
if (len >= CLI_MAX_CMD_LEN - 1)
s->print(s, "- "); return;
s->print(s, cmdtbl[i]->brief); /*<2A><><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD>Ϣ----*/ strcpy(obj->recvbuf, cmd);
s->print(s, "\r\n"); process_line(obj);
} }
return 1;
} /**
/*ע<><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ---------------------------------------------------------------*/ * @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
cmd_register("help", do_help, "list all command."); * @param[in] none
cmd_register("?", do_help, "alias for 'help'"); * @return none
**/
void cli_process(cli_obj_t *obj)
{
char buf[32];
int i, readcnt;
if (!obj->read || !obj->enable)
return;
readcnt = obj->read(buf, sizeof(buf));
if (readcnt) {
for (i = 0; i < readcnt; i++) {
if (buf[i] == '\r' || buf[i] == '\n' || buf[i] == '\0') {
obj->recvbuf[obj->recvcnt] = '\0';
if (obj->recvcnt > 1)
process_line(obj);
obj->recvcnt = 0;
} else {
obj->recvbuf[obj->recvcnt++] = buf[i];
if (obj->recvcnt >= CLI_MAX_CMD_LEN) /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><D6AE>ǿ<EFBFBD><C7BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
obj->recvcnt = 0;
}
}
}
}
#if 1
/*******************************************************************************
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƚ<EFBFBD><EFBFBD><EFBFBD>
* @param[in] none
* @return <EFBFBD>ο<EFBFBD>strcmp
*******************************************************************************/
static int cmd_item_comparer(const void *item1,const void *item2)
{
cmd_item_t *it1 = *((cmd_item_t **)item1);
cmd_item_t *it2 = *((cmd_item_t **)item2);
return strcmp(it1->name, it2->name);
}
#endif
/*
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
static int do_help (struct cli_obj *s, int argc, char *argv[])
{
int i,j, count;
const cmd_item_t *item_start = &cmd_tbl_start + 1;
const cmd_item_t *item_end = &cmd_tbl_end;
const cmd_item_t *cmdtbl[CLI_MAX_CMDS];
if (argc == 2) {
if ((item_start = find_cmd(argv[1], strlen(argv[1]))) != NULL)
{
s->print(s, item_start->brief); /*<2A><><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD>Ϣ----*/
s->print(s, "\r\n");
}
return 0;
}
for (i = 0; i < item_end - item_start && i < CLI_MAX_ARGS; i++)
cmdtbl[i] = &item_start[i];
count = i;
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ---------------------------------------------------------*/
qsort(cmdtbl, i, sizeof(cmd_item_t*), cmd_item_comparer);
s->print(s, "\r\n");
for (i = 0; i < count; i++) {
s->print(s, cmdtbl[i]->name); /*<2A><>ӡ<EFBFBD><D3A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>------*/
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
j = strlen(cmdtbl[i]->name);
if (j < 10)
j = 10 - j;
while (j--)
s->print(s, " ");
s->print(s, "- ");
s->print(s, cmdtbl[i]->brief); /*<2A><><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD>Ϣ----*/
s->print(s, "\r\n");
}
return 1;
}
/*ע<><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ---------------------------------------------------------------*/
cmd_register("help", do_help, "list all command.");
cmd_register("?", do_help, "alias for 'help'");

View File

@ -0,0 +1,114 @@
/******************************************************************************
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD>
*
* Copyright (c) 2015-2020, <master_roger@sina.com>
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2015-06-09 roger.luo <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* 2017-07-04 roger.luo <EFBFBD>Ż<EFBFBD><EFBFBD>ֶηָ<EFBFBD><EFBFBD>
*
* 2020-07-05 roger.luo ʹ<EFBFBD><EFBFBD>cli_obj_t<EFBFBD><EFBFBD><EFBFBD><EFBFBD>, ֧<EFBFBD>ֶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* 2020-08-29 roger.luo ֧<EFBFBD><EFBFBD>ATָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD><EFBFBD><EFBFBD>
* 2020-02-16 roger.luo <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
******************************************************************************/
#ifndef _CMDLINE_H_
#define _CMDLINE_H_
#include "comdef.h"
#define CLI_MAX_CMD_LEN 256 /*<2A><><EFBFBD><EFBFBD><EFBFBD>г<EFBFBD><D0B3><EFBFBD>*/
#define CLI_MAX_ARGS 16 /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
#define CLI_MAX_CMDS 64 /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
/**
* @brief CLI<EFBFBD><EFBFBD>ΪAT<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><EFBFBD>,<EFBFBD>ڽ<EFBFBD><EFBFBD><EFBFBD>ƥ<EFBFBD><EFBFBD>ʱ<EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"AT+",
*/
#define CLI_AT_ENABLE 1
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
#define CLI_CMD_TYPE_EXEC 0 /* <20><>ִͨ<CDA8><D6B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
#define CLI_CMD_TYPE_QUERY 1 /* <20><>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD> (XXX?)*/
#define CLI_CMD_TYPE_SET 2 /* <20><EFBFBD><E8B1B8><EFBFBD><EFBFBD> (XXX=YY)*/
struct cli_obj;
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EEB6A8>*/
typedef struct {
char *name; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @params o - cli <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @params argc - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @params argv - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>н<EFBFBD><EFBFBD><EFBFBD>, <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ATָ<EFBFBD><EFBFBD>, <EFBFBD><EFBFBD><EFBFBD><EFBFBD>trueʱ<EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD><EFBFBD><EFBFBD>ӦOK,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>falseʱ<EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD>ӦERROR
*/
int (*handler)(struct cli_obj *o, int argc, char *argv[]);
const char *brief; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
}cmd_item_t;
#define __cmd_register(name,handler,brief)\
USED ANONY_TYPE(const cmd_item_t,__cli_cmd_##handler)\
SECTION("cli.cmd.1") = {name, handler, brief}
/*******************************************************************************
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD>
* @params name - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @params handler - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>:int (*handler)(struct cli_obj *s, int argc, char *argv[]);
* @params brief - ʹ<EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD>
*/
#define cmd_register(name,handler,brief)\
__cmd_register(name,handler,brief)
/*cli <20>ӿڶ<D3BF><DAB6><EFBFBD> -------------------------------------------------------------*/
typedef struct {
/**
* @brief ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)д<EFBFBD>ӿ<EFBFBD>
*/
unsigned int (*write)(const void *buf, unsigned int len);
/**
* @brief ͨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)<EFBFBD><EFBFBD><EFBFBD>ӿ<EFBFBD>
*/
unsigned int (*read) (void *buf, unsigned int len);
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>дNULL,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD>)
* @retval true - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><EFBFBD>, false - <EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
int (*cmd_guard)(char *cmdline);
}cli_port_t;
/*<2A><><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><D0B6><EFBFBD>*/
typedef struct cli_obj {
int (*guard)(char *cmdline);
unsigned int (*write)(const void *buf, unsigned int len);
unsigned int (*read) (void *buf, unsigned int len);
void (*print)(struct cli_obj *this, const char *fmt, ...);
int (*get_val)(struct cli_obj *this);
char recvbuf[CLI_MAX_CMD_LEN + 1]; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>*/
unsigned short recvcnt; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ճ<EFBFBD><D5B3><EFBFBD>*/
unsigned type : 3; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
unsigned enable : 1; /* CLI <20><><EFBFBD>ؿ<EFBFBD><D8BF><EFBFBD>*/
unsigned echo : 1; /* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
}cli_obj_t;
void cli_init(cli_obj_t *obj, const cli_port_t *p);
void cli_enable(cli_obj_t *obj);
void cli_disable (cli_obj_t *obj);
void cli_echo_ctrl (cli_obj_t *obj, int echo);
void cli_exec_cmd(cli_obj_t *obj, const char *cmd);
void cli_process(cli_obj_t *obj);
#endif /* __CMDLINE_H */

View File

@ -1,55 +1,55 @@
/****************************************************************************** /******************************************************************************
* @brief ͨ<EFBFBD>ú<EFBFBD><EFBFBD> * @brief ͨ<EFBFBD>ú<EFBFBD><EFBFBD>
* *
* Copyright (c) 2018~2020, <morro_luo@163.com> * Copyright (c) 2018~2020, <morro_luo@163.com>
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2018-02-01 Morro Initial version. * 2018-02-01 roger.luo Initial version.
******************************************************************************/ ******************************************************************************/
#ifndef _COM_DEF_H_ #ifndef _COM_DEF_H_
#define _COM_DEF_H_ #define _COM_DEF_H_
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD> -----------------------------------------------------------*/ /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD> -----------------------------------------------------------*/
#define ANONY_CONN(type, var, line) type var##line #define ANONY_CONN(type, var, line) type var##line
#define ANONY_DEF(type,prefix,line) ANONY_CONN(type, prefix, line) #define ANONY_DEF(type,prefix,line) ANONY_CONN(type, prefix, line)
#define ANONY_TYPE(type,prefix) ANONY_DEF(type, prefix, __LINE__) #define ANONY_TYPE(type,prefix) ANONY_DEF(type, prefix, __LINE__)
/** /**
* container_of - cast a member of a structure out to the containing structure * container_of - cast a member of a structure out to the containing structure
* @ptr: the pointer to the member. * @ptr: the pointer to the member.
* @type: the type of the container struct this is embedded in. * @type: the type of the container struct this is embedded in.
* @member: the name of the member within the struct. * @member: the name of the member within the struct.
* *
*/ */
#define container_of(ptr, type, member) ( \ #define container_of(ptr, type, member) ( \
(type *)( (char *)(ptr) - offsetof(type,member) )) (type *)( (char *)(ptr) - offsetof(type,member) ))
#if defined(__CC_ARM) || defined(__GNUC__) /* ARM,GCC*/ #if defined(__CC_ARM) || defined(__GNUC__) /* ARM,GCC*/
#define SECTION(x) __attribute__((section(x))) #define SECTION(x) __attribute__((section(x)))
#define UNUSED __attribute__((unused)) #define UNUSED __attribute__((unused))
#define USED __attribute__((used)) #define USED __attribute__((used))
#define ALIGN(n) __attribute__((aligned(n))) #define ALIGN(n) __attribute__((aligned(n)))
#define WEAK __attribute__((weak)) #define WEAK __attribute__((weak))
#elif defined (__ICCARM__) /*IAR */ #elif defined (__ICCARM__) /*IAR */
#define SECTION(x) @ x #define SECTION(x) @ x
#define UNUSED #define UNUSED
#define USED __root #define USED __root
#define WEAK __weak #define WEAK __weak
#else #else
#error "Current tool chain haven't supported yet!" #error "Current tool chain haven't supported yet!"
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif

View File

@ -1,73 +1,73 @@
/****************************************************************************** /******************************************************************************
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* *
* Copyright (c) 2017~2020, <morro_luo@163.com> * Copyright (c) 2017~2020, <morro_luo@163.com>
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2017-08-10 Morro Initial version * 2017-08-10 roger.luo Initial version
******************************************************************************/ ******************************************************************************/
#include "key.h" #include "key.h"
#include <stddef.h> #include <stddef.h>
static key_t *keyhead = NULL; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD>*/ static key_t *keyhead = NULL; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD>*/
/******************************************************************************* /*******************************************************************************
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] key - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @param[in] key - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] readkey - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ժ<EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD> * @param[in] readkey - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ժ<EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>
* @param[in] event - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD> * @param[in] event - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>
* @return true - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>, false - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD> * @return true - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>, false - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD>
******************************************************************************/ ******************************************************************************/
bool key_create(key_t *key, int (*readkey)(void), bool key_create(key_t *key, int (*readkey)(void),
void (*event)(int type, unsigned int duration)) void (*event)(int type, unsigned int duration))
{ {
key_t *keytail = keyhead; key_t *keytail = keyhead;
if (key == NULL || readkey == NULL || event == NULL) if (key == NULL || readkey == NULL || event == NULL)
return 0; return 0;
key->event = event; key->event = event;
key->readkey = readkey; key->readkey = readkey;
key->next = NULL; key->next = NULL;
if (keyhead == NULL) { if (keyhead == NULL) {
keyhead = key; keyhead = key;
return 1; return 1;
} }
while (keytail->next != NULL) /*ת<><D7AA><EFBFBD><EFBFBD>β*/ while (keytail->next != NULL) /*ת<><D7AA><EFBFBD><EFBFBD>β*/
keytail = keytail->next; keytail = keytail->next;
keytail->next = key; keytail->next = key;
return 1; return 1;
} }
/******************************************************************************* /*******************************************************************************
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɨ<EFBFBD><EFBFBD><EFBFBD> * @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɨ<EFBFBD><EFBFBD><EFBFBD>
* @return none * @return none
******************************************************************************/ ******************************************************************************/
void key_scan_process(void) void key_scan_process(void)
{ {
key_t *k; key_t *k;
for (k = keyhead; k != NULL; k = k->next) { for (k = keyhead; k != NULL; k = k->next) {
if (k->readkey()) { if (k->readkey()) {
if (k->tick) { if (k->tick) {
if (is_timeout(k->tick, LONG_PRESS_TIME)) /*<2A><><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD> */ if (is_timeout(k->tick, LONG_PRESS_TIME)) /*<2A><><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD> */
k->event(KEY_LONG_DOWN, get_tick() - k->tick); k->event(KEY_LONG_DOWN, get_tick() - k->tick);
} else { } else {
k->tick = get_tick(); /*<2A><>¼<EFBFBD>״ΰ<D7B4><CEB0><EFBFBD>ʱ<EFBFBD><CAB1>*/ k->tick = get_tick(); /*<2A><>¼<EFBFBD>״ΰ<D7B4><CEB0><EFBFBD>ʱ<EFBFBD><CAB1>*/
} }
} else if (k->tick) { } else if (k->tick) {
if (is_timeout(k->tick, LONG_PRESS_TIME)) { /*<2A><><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD> */ if (is_timeout(k->tick, LONG_PRESS_TIME)) { /*<2A><><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD> */
k->event(KEY_LONG_UP, get_tick() - k->tick); k->event(KEY_LONG_UP, get_tick() - k->tick);
} }
/*<2A>̰<EFBFBD><CCB0>ͷŲ<CDB7><C5B2><EFBFBD> ---------------------------------------------------*/ /*<2A>̰<EFBFBD><CCB0>ͷŲ<CDB7><C5B2><EFBFBD> ---------------------------------------------------*/
if (is_timeout(k->tick, KEY_DEBOUNCE_TIME) && if (is_timeout(k->tick, KEY_DEBOUNCE_TIME) &&
!is_timeout(k->tick, LONG_PRESS_TIME)) { !is_timeout(k->tick, LONG_PRESS_TIME)) {
k->event(KEY_PRESS, get_tick() - k->tick); k->event(KEY_PRESS, get_tick() - k->tick);
} }
k->tick = 0; k->tick = 0;
} }
} }
} }

View File

@ -1,56 +1,56 @@
/****************************************************************************** /******************************************************************************
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* *
* Copyright (c) 2017~2020, <morro_luo@163.com> * Copyright (c) 2017~2020, <morro_luo@163.com>
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2017-08-10 Morro Initial version * 2017-08-10 roger.luo Initial version
******************************************************************************/ ******************************************************************************/
#ifndef _KEY_H_ #ifndef _KEY_H_
#define _KEY_H_ #define _KEY_H_
#include "module.h" #include "module.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#define LONG_PRESS_TIME 1500 /*<2A><><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7>ʱ<EFBFBD><CAB1> ------------*/ #define LONG_PRESS_TIME 1500 /*<2A><><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7>ʱ<EFBFBD><CAB1> ------------*/
#define KEY_DEBOUNCE_TIME 20 /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1> ------------*/ #define KEY_DEBOUNCE_TIME 20 /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1> ------------*/
#define KEY_PRESS 0 /*<2A>̰<EFBFBD> --------------------*/ #define KEY_PRESS 0 /*<2A>̰<EFBFBD> --------------------*/
#define KEY_LONG_DOWN 1 /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ----------------*/ #define KEY_LONG_DOWN 1 /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ----------------*/
#define KEY_LONG_UP 2 /*<2A><><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD> ----------------*/ #define KEY_LONG_UP 2 /*<2A><><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD> ----------------*/
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> -----------------------------------------------------------------*/ /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> -----------------------------------------------------------------*/
typedef struct key_t { typedef struct key_t {
/* /*
*@brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD>ӿ<EFBFBD> *@brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD>ӿ<EFBFBD>
*@param[in] none *@param[in] none
*@return 0 - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <EFBFBD><EFBFBD>0 - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> *@return 0 - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <EFBFBD><EFBFBD>0 - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/ */
int (*readkey)(void); int (*readkey)(void);
/* /*
*@brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> *@brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*@param[in] type - <EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(KEY_SHORT_PRESS - <EFBFBD>̰<EFBFBD>, KEY_LONG_PRESS - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>) *@param[in] type - <EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(KEY_SHORT_PRESS - <EFBFBD>̰<EFBFBD>, KEY_LONG_PRESS - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
*@param[in] duration <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч *@param[in] duration <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>,<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч
*@return none *@return none
*/ */
void (*event)(int type, unsigned int duration);/*<2A><><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD> ------------*/ void (*event)(int type, unsigned int duration);/*<2A><><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD> ------------*/
unsigned int tick; /*<2A>δ<EFBFBD><CEB4><EFBFBD>ʱ<EFBFBD><CAB1> --------------*/ unsigned int tick; /*<2A>δ<EFBFBD><CEB4><EFBFBD>ʱ<EFBFBD><CAB1> --------------*/
struct key_t *next; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */ struct key_t *next; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
}key_t; }key_t;
bool key_create(key_t *key, int (*readkey)(void), /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/ bool key_create(key_t *key, int (*readkey)(void), /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
void (*event)(int type, unsigned int duration)); void (*event)(int type, unsigned int duration));
void key_scan_process(void); /*<2A><><EFBFBD><EFBFBD>ɨ<EFBFBD><EFBFBD><E8B4A6>*/ void key_scan_process(void); /*<2A><><EFBFBD><EFBFBD>ɨ<EFBFBD><EFBFBD><E8B4A6>*/
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif

View File

@ -1,98 +1,98 @@
/****************************************************************************** /******************************************************************************
* @brief (,) * @brief (,)
* *
* Copyright (c) 2017~2020, <morro_luo@163.com> * Copyright (c) 2017~2020, <morro_luo@163.com>
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2016-06-24 Morro * 2016-06-24 roger.luo
* 2020-05-23 Morro , * 2020-05-23 roger.luo ,
* 2020-06-28 Morro is_timeout超时判断接口 * 2020-06-28 roger.luo is_timeout超时判断接口
* 2020-09-28 Morro timer * 2020-09-28 roger.luo timer
* *
******************************************************************************/ ******************************************************************************/
#include "module.h" #include "module.h"
static volatile unsigned int tick; //系统滴答计时 static volatile unsigned int tick; //系统滴答计时
/* /*
* @brief (,1ms 1) * @brief (,1ms 1)
*/ */
void systick_increase(unsigned int ms) void systick_increase(unsigned int ms)
{ {
tick += ms; tick += ms;
} }
/* /*
* @brief (1ms) * @brief (1ms)
*/ */
unsigned int get_tick(void) unsigned int get_tick(void)
{ {
return tick; return tick;
} }
/* /*
* @brief * @brief
* @param[in] start - * @param[in] start -
* @param[in] timeout - (ms) * @param[in] timeout - (ms)
*/ */
bool is_timeout(unsigned int start, unsigned int timeout) bool is_timeout(unsigned int start, unsigned int timeout)
{ {
return get_tick() - start > timeout; return get_tick() - start > timeout;
} }
/* /*
* @brief , * @brief ,
*/ */
static void nop_process(void) {} static void nop_process(void) {}
//第一个初始化项 //第一个初始化项
const init_item_t init_tbl_start SECTION("init.item.0") = { const init_item_t init_tbl_start SECTION("init.item.0") = {
"", nop_process "", nop_process
}; };
//最后个初始化项 //最后个初始化项
const init_item_t init_tbl_end SECTION("init.item.4") = { const init_item_t init_tbl_end SECTION("init.item.4") = {
"", nop_process "", nop_process
}; };
//第一个任务项 //第一个任务项
const task_item_t task_tbl_start SECTION("task.item.0") = { const task_item_t task_tbl_start SECTION("task.item.0") = {
"", nop_process "", nop_process
}; };
//最后个任务项 //最后个任务项
const task_item_t task_tbl_end SECTION("task.item.2") = { const task_item_t task_tbl_end SECTION("task.item.2") = {
"", nop_process "", nop_process
}; };
/* /*
* @brief * @brief
* system_init > driver_init > module_init * system_init > driver_init > module_init
* @param[in] none * @param[in] none
* @return none * @return none
*/ */
void module_task_init(void) void module_task_init(void)
{ {
const init_item_t *it = &init_tbl_start; const init_item_t *it = &init_tbl_start;
while (it < &init_tbl_end) { while (it < &init_tbl_end) {
it++->init(); it++->init();
} }
} }
/* /*
* @brief * @brief
* @param[in] none * @param[in] none
* @return none * @return none
*/ */
void module_task_process(void) void module_task_process(void)
{ {
const task_item_t *t; const task_item_t *t;
for (t = &task_tbl_start + 1; t < &task_tbl_end; t++) { for (t = &task_tbl_start + 1; t < &task_tbl_end; t++) {
if ((get_tick() - *t->timer) >= t->interval) { if ((get_tick() - *t->timer) >= t->interval) {
*t->timer = get_tick(); *t->timer = get_tick();
t->handle(); t->handle();
} }
} }
} }

View File

@ -1,66 +1,66 @@
/****************************************************************************** /******************************************************************************
* @brief ϵͳģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>,ʱ<EFBFBD><EFBFBD>Ƭ<EFBFBD><EFBFBD>ѯϵͳ) * @brief ϵͳģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>,ʱ<EFBFBD><EFBFBD>Ƭ<EFBFBD><EFBFBD>ѯϵͳ)
* *
* Copyright (c) 2017~2020, <morro_luo@163.com> * Copyright (c) 2017~2020, <morro_luo@163.com>
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2016-06-24 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * 2016-06-24 roger.luo <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* 2020-05-23 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<EFBFBD><EFBFBD>ֹģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * 2020-05-23 roger.luo <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<EFBFBD><EFBFBD>ֹģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* 2020-06-28 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD>is_timeout<EFBFBD><EFBFBD>ʱ<EFBFBD>жϽӿ<EFBFBD> * 2020-06-28 roger.luo <EFBFBD><EFBFBD><EFBFBD><EFBFBD>is_timeout<EFBFBD><EFBFBD>ʱ<EFBFBD>жϽӿ<EFBFBD>
******************************************************************************/ ******************************************************************************/
#ifndef _MODULE_H_ #ifndef _MODULE_H_
#define _MODULE_H_ #define _MODULE_H_
#include "comdef.h" #include "comdef.h"
#include <stdbool.h> #include <stdbool.h>
/*ģ<><C4A3><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>*/ /*ģ<><C4A3><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>*/
typedef struct { typedef struct {
const char *name; //ģ<><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> const char *name; //ģ<><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void (*init)(void); //<2F><>ʼ<EFBFBD><CABC><EFBFBD>ӿ<EFBFBD> void (*init)(void); //<2F><>ʼ<EFBFBD><CABC><EFBFBD>ӿ<EFBFBD>
}init_item_t; }init_item_t;
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/ /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
typedef struct { typedef struct {
const char *name; //ģ<><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> const char *name; //ģ<><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void (*handle)(void); //<2F><>ʼ<EFBFBD><CABC><EFBFBD>ӿ<EFBFBD> void (*handle)(void); //<2F><>ʼ<EFBFBD><CABC><EFBFBD>ӿ<EFBFBD>
unsigned int interval; //<2F><>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD> unsigned int interval; //<2F><>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD>
unsigned int *timer; //ָ<><D6B8><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>ָ<EFBFBD><D6B8> unsigned int *timer; //ָ<><D6B8><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>ָ<EFBFBD><D6B8>
}task_item_t; }task_item_t;
#define __module_initialize(name,func,level) \ #define __module_initialize(name,func,level) \
USED ANONY_TYPE(const init_item_t, init_tbl_##func)\ USED ANONY_TYPE(const init_item_t, init_tbl_##func)\
SECTION("init.item."level) = {name,func} SECTION("init.item."level) = {name,func}
/* /*
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD> * @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD>
* @param[in] name - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @param[in] name - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] handle - <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(void func(void){...}) * @param[in] handle - <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(void func(void){...})
* @param[in] interval- <EFBFBD><EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>(ms) * @param[in] interval- <EFBFBD><EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>(ms)
*/ */
#define task_register(name, handle,interval) \ #define task_register(name, handle,interval) \
static unsigned int __task_timer_##handle; \ static unsigned int __task_timer_##handle; \
USED ANONY_TYPE(const task_item_t, task_item_##handle) \ USED ANONY_TYPE(const task_item_t, task_item_##handle) \
SECTION("task.item.1") = \ SECTION("task.item.1") = \
{name,handle, interval, &__task_timer_##handle} {name,handle, interval, &__task_timer_##handle}
/* /*
* @brief ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD> * @brief ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD>
* @param[in] name - ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @param[in] name - ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] func - <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ں<EFBFBD><EFBFBD><EFBFBD>(void func(void){...}) * @param[in] func - <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ں<EFBFBD><EFBFBD><EFBFBD>(void func(void){...})
*/ */
#define system_init(name,func) __module_initialize(name,func,"1") #define system_init(name,func) __module_initialize(name,func,"1")
#define driver_init(name,func) __module_initialize(name,func,"2") #define driver_init(name,func) __module_initialize(name,func,"2")
#define module_init(name,func) __module_initialize(name,func,"3") #define module_init(name,func) __module_initialize(name,func,"3")
void systick_increase(unsigned int ms); void systick_increase(unsigned int ms);
unsigned int get_tick(void); unsigned int get_tick(void);
bool is_timeout(unsigned int start, unsigned int timeout); bool is_timeout(unsigned int start, unsigned int timeout);
void module_task_init(void); void module_task_init(void);
void module_task_process(void); void module_task_process(void);
#endif #endif

View File

@ -1,100 +1,100 @@
/******************************************************************************* /*******************************************************************************
* @brief <EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>(queue link)<EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @brief <EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>(queue link)<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* *
* Copyright (c) 2017~2020, <morro_luo@163.com> * Copyright (c) 2017~2020, <morro_luo@163.com>
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* Change Logs * Change Logs
* Date Author Notes * Date Author Notes
* 2016-06-24 Morro <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD> * 2016-06-24 Morro <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>
* 2018-03-17 Morro <EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD>ͳ<EFBFBD>ƹ<EFBFBD><EFBFBD><EFBFBD> * 2018-03-17 Morro <EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD>ͳ<EFBFBD>ƹ<EFBFBD><EFBFBD><EFBFBD>
*******************************************************************************/ *******************************************************************************/
#ifndef _QLINK_H_ #ifndef _QLINK_H_
#define _QLINK_H_ #define _QLINK_H_
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#include <stddef.h> #include <stddef.h>
/*<2A><>ʽ<EFBFBD><CABD><EFBFBD>н<EFBFBD><D0BD><EFBFBD> ---------------------------------------------------------------*/ /*<2A><>ʽ<EFBFBD><CABD><EFBFBD>н<EFBFBD><D0BD><EFBFBD> ---------------------------------------------------------------*/
struct qlink_node { struct qlink_node {
struct qlink_node *next; struct qlink_node *next;
}; };
/*<2A><>ʽ<EFBFBD><CABD><EFBFBD>й<EFBFBD><D0B9><EFBFBD><EFBFBD><EFBFBD> -------------------------------------------------------------*/ /*<2A><>ʽ<EFBFBD><CABD><EFBFBD>й<EFBFBD><D0B9><EFBFBD><EFBFBD><EFBFBD> -------------------------------------------------------------*/
struct qlink { struct qlink {
unsigned int count; unsigned int count;
struct qlink_node *front, *rear; struct qlink_node *front, *rear;
}; };
/******************************************************************************* /*******************************************************************************
* @brief <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @brief <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] q - <EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @param[in] q - <EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return none * @return none
******************************************************************************/ ******************************************************************************/
static inline void qlink_init(struct qlink *q) static inline void qlink_init(struct qlink *q)
{ {
q->front = q->rear= NULL; q->front = q->rear= NULL;
q->count = 0; q->count = 0;
} }
/******************************************************************************* /*******************************************************************************
* @brief <EFBFBD><EFBFBD><EFBFBD>Ӳ<EFBFBD><EFBFBD><EFBFBD> * @brief <EFBFBD><EFBFBD><EFBFBD>Ӳ<EFBFBD><EFBFBD><EFBFBD>
* @param[in] q - <EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @param[in] q - <EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return nond * @return nond
******************************************************************************/ ******************************************************************************/
static inline void qlink_put(struct qlink *q, struct qlink_node *n) static inline void qlink_put(struct qlink *q, struct qlink_node *n)
{ {
if (q->count == 0) if (q->count == 0)
q->front = n; q->front = n;
else else
q->rear->next = n; q->rear->next = n;
q->rear = n; q->rear = n;
n->next = NULL; n->next = NULL;
q->count++; q->count++;
} }
/******************************************************************************* /*******************************************************************************
* @brief Ԥ<EFBFBD><EFBFBD><EFBFBD>Ӳ<EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>׽<EFBFBD><EFBFBD><EFBFBD>) * @brief Ԥ<EFBFBD><EFBFBD><EFBFBD>Ӳ<EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>׽<EFBFBD><EFBFBD><EFBFBD>)
* @param[in] q - <EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @param[in] q - <EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return nond * @return nond
******************************************************************************/ ******************************************************************************/
static inline struct qlink_node *qlink_peek(struct qlink *q) static inline struct qlink_node *qlink_peek(struct qlink *q)
{ {
return q->front; return q->front;
} }
/******************************************************************************* /*******************************************************************************
* @brief <EFBFBD><EFBFBD><EFBFBD>Ӳ<EFBFBD><EFBFBD><EFBFBD> * @brief <EFBFBD><EFBFBD><EFBFBD>Ӳ<EFBFBD><EFBFBD><EFBFBD>
* @param[in] q - <EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @param[in] q - <EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return nond * @return nond
******************************************************************************/ ******************************************************************************/
static inline struct qlink_node *qlink_get(struct qlink *q) static inline struct qlink_node *qlink_get(struct qlink *q)
{ {
struct qlink_node *n; struct qlink_node *n;
if (q->count == 0) if (q->count == 0)
return NULL; return NULL;
n = q->front; n = q->front;
q->front = q->front->next; q->front = q->front->next;
q->count--; q->count--;
return n; return n;
} }
/******************************************************************************* /*******************************************************************************
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>ظ<EFBFBD><EFBFBD><EFBFBD> * @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>ظ<EFBFBD><EFBFBD><EFBFBD>
* @param[in] q - <EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @param[in] q - <EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return nond * @return nond
******************************************************************************/ ******************************************************************************/
static inline int qlink_count(struct qlink *q) static inline int qlink_count(struct qlink *q)
{ {
return q->count; return q->count;
} }
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif

View File

@ -1,117 +1,117 @@
/****************************************************************************** /******************************************************************************
* @brief ͨ<EFBFBD>ö<EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD> * @brief ͨ<EFBFBD>ö<EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>
* *
* Copyright (c) 2017~2020, <morro_luo@163.com> * Copyright (c) 2017~2020, <morro_luo@163.com>
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2017-03-19 Morro Initial version. * 2017-03-19 roger.luo Initial version.
******************************************************************************/ ******************************************************************************/
#include "queue.h" #include "queue.h"
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
/* @brief <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD> /* @brief <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] q - <EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @param[in] q - <EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param[in] base - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ * @param[in] base - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ
* @param[in] size - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>ظ<EFBFBD><EFBFBD><EFBFBD> * @param[in] size - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>ظ<EFBFBD><EFBFBD><EFBFBD>
* @param[in] element_size - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>ش<EFBFBD>С(sizeof(type)) * @param[in] element_size - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>ش<EFBFBD>С(sizeof(type))
* @return true - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD>, false - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD> * @return true - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD>, false - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>
*/ */
bool queue_create(queue_t *q, void *base, int size, int element_size) bool queue_create(queue_t *q, void *base, int size, int element_size)
{ {
if (q == NULL || base == NULL || size== 0 || element_size == 0) if (q == NULL || base == NULL || size== 0 || element_size == 0)
return false; return false;
q->base = base; q->base = base;
q->size = size; q->size = size;
q->element_size = element_size; q->element_size = element_size;
q->front = q->rear = 0; q->front = q->rear = 0;
return true; return true;
} }
/* @brief <20>ж϶<D0B6><CFB6><EFBFBD><EFBFBD>Ƿ<EFBFBD>Ϊ<EFBFBD><CEAA> /* @brief <20>ж϶<D0B6><CFB6><EFBFBD><EFBFBD>Ƿ<EFBFBD>Ϊ<EFBFBD><CEAA>
* @return true - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>, false - <EFBFBD><EFBFBD><EFBFBD>зǿ<EFBFBD> * @return true - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>, false - <EFBFBD><EFBFBD><EFBFBD>зǿ<EFBFBD>
*/ */
bool queue_is_empty(queue_t *q) bool queue_is_empty(queue_t *q)
{ {
return q->front == q->rear; return q->front == q->rear;
} }
/* @brief <20>ж϶<D0B6><CFB6><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD> /* @brief <20>ж϶<D0B6><CFB6><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>
* @return true - <EFBFBD><EFBFBD><EFBFBD>з<EFBFBD><EFBFBD><EFBFBD>, false - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD> * @return true - <EFBFBD><EFBFBD><EFBFBD>з<EFBFBD><EFBFBD><EFBFBD>, false - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD>
*/ */
bool queue_is_full(queue_t *q) bool queue_is_full(queue_t *q)
{ {
return (q->rear + 1) % q->size == q->front; return (q->rear + 1) % q->size == q->front;
} }
/* @brief <20><><EFBFBD><EFBFBD>(<28><><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>β) /* @brief <20><><EFBFBD><EFBFBD>(<28><><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>β)
* @param[in] element - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD> * @param[in] element - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><EFBFBD>
* @return true - <EFBFBD>ɹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, false - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * @return true - <EFBFBD>ɹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, false - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/ */
bool queue_put(queue_t *q, void *element) bool queue_put(queue_t *q, void *element)
{ {
if (queue_is_full(q)) if (queue_is_full(q))
return false; return false;
memcpy((unsigned char *)q->base + q->rear * q->element_size, element, memcpy((unsigned char *)q->base + q->rear * q->element_size, element,
q->element_size); q->element_size);
q->rear = (q->rear + 1) % q->size; q->rear = (q->rear + 1) % q->size;
return true; return true;
} }
/* @brief <20><><EFBFBD><EFBFBD>(<28>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA>) /* @brief <20><><EFBFBD><EFBFBD>(<28>Ƴ<EFBFBD><C6B3><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA>)
* @param[in] element - ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>صĵ<EFBFBD>ַ * @param[in] element - ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>صĵ<EFBFBD>ַ
* @return true - <EFBFBD>ɹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, false - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD> * @return true - <EFBFBD>ɹ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, false - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>
*/ */
bool queue_get(queue_t *q, void *element) bool queue_get(queue_t *q, void *element)
{ {
if (queue_is_empty(q)) if (queue_is_empty(q))
return false; return false;
memcpy(element, (unsigned char *)q->base + q->front * q->element_size, memcpy(element, (unsigned char *)q->base + q->front * q->element_size,
q->element_size); q->element_size);
q->front = (q->front + 1) % q->size; q->front = (q->front + 1) % q->size;
return true; return true;
} }
/* @brief <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>Ԫ<EFBFBD>ص<EFBFBD>ַ(Ԥ<><D4A4>ȡ) /* @brief <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>Ԫ<EFBFBD>ص<EFBFBD>ַ(Ԥ<><D4A4>ȡ)
* @param[in] element - ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>صĵ<EFBFBD>ַ * @param[in] element - ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>صĵ<EFBFBD>ַ
* @return true - <EFBFBD><EFBFBD>ȡ<EFBFBD>ɹ<EFBFBD>, false - <EFBFBD><EFBFBD>ȡʧ<EFBFBD>ܶ<EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD> * @return true - <EFBFBD><EFBFBD>ȡ<EFBFBD>ɹ<EFBFBD>, false - <EFBFBD><EFBFBD>ȡʧ<EFBFBD>ܶ<EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>
*/ */
bool queue_peek(queue_t *q, void **element) bool queue_peek(queue_t *q, void **element)
{ {
if (queue_is_empty(q)) if (queue_is_empty(q))
return false; return false;
*element = (void *)((unsigned char *)q->base + q->front * *element = (void *)((unsigned char *)q->base + q->front *
q->element_size); q->element_size);
return true; return true;
} }
/* @brief ɾ<><C9BE><EFBFBD><EFBFBD>βԪ<CEB2><D4AA> /* @brief ɾ<><C9BE><EFBFBD><EFBFBD>βԪ<CEB2><D4AA>
* @return true - <EFBFBD>ɹ<EFBFBD><EFBFBD>Ƴ<EFBFBD>, false - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>, * @return true - <EFBFBD>ɹ<EFBFBD><EFBFBD>Ƴ<EFBFBD>, false - <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>,
*/ */
bool queue_del(queue_t *q) bool queue_del(queue_t *q)
{ {
if (queue_is_empty(q)) if (queue_is_empty(q))
return false; return false;
q->front = (q->front + 1) % q->size; q->front = (q->front + 1) % q->size;
return true; return true;
} }
/* @brief <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>Ԫ<EFBFBD>ظ<EFBFBD><D8B8><EFBFBD> /* @brief <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>Ԫ<EFBFBD>ظ<EFBFBD><D8B8><EFBFBD>
* @return <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>ظ<EFBFBD><EFBFBD><EFBFBD> * @return <EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>ظ<EFBFBD><EFBFBD><EFBFBD>
*/ */
int queue_size(queue_t *q) int queue_size(queue_t *q)
{ {
return (q->rear + q->size - q->front ) % q->size; return (q->rear + q->size - q->front ) % q->size;
} }
/* @brief <20><><EFBFBD>ն<EFBFBD><D5B6><EFBFBD> /* @brief <20><><EFBFBD>ն<EFBFBD><D5B6><EFBFBD>
* @return none * @return none
*/ */
void queue_clr(queue_t *q) void queue_clr(queue_t *q)
{ {
q->front = q->rear = 0; q->front = q->rear = 0;
} }

View File

@ -1,41 +1,41 @@
/****************************************************************************** /******************************************************************************
* @brief ͨ<EFBFBD>ö<EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD> * @brief ͨ<EFBFBD>ö<EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>
* *
* Copyright (c) 2017~2020, <morro_luo@163.com> * Copyright (c) 2017~2020, <morro_luo@163.com>
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2017-03-19 Morro Initial version. * 2017-03-19 roger.luo Initial version.
******************************************************************************/ ******************************************************************************/
#ifndef _QUEUE_H_ #ifndef _QUEUE_H_
#define _QUEUE_H_ #define _QUEUE_H_
#include <stdbool.h> #include <stdbool.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
typedef struct { typedef struct {
void *base; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ*/ void *base; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ*/
unsigned short element_size; /*<2A><><EFBFBD><EFBFBD>Ԫ<EFBFBD>ش<EFBFBD>С*/ unsigned short element_size; /*<2A><><EFBFBD><EFBFBD>Ԫ<EFBFBD>ش<EFBFBD>С*/
unsigned short size; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>ظ<EFBFBD><D8B8><EFBFBD>*/ unsigned short size; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD>ظ<EFBFBD><D8B8><EFBFBD>*/
unsigned short front; /*<2A><><EFBFBD><EFBFBD>*/ unsigned short front; /*<2A><><EFBFBD><EFBFBD>*/
unsigned short rear; /*<2A><>β*/ unsigned short rear; /*<2A><>β*/
}queue_t; }queue_t;
bool queue_create(queue_t *q, void *container, int size, int element_size); bool queue_create(queue_t *q, void *container, int size, int element_size);
bool queue_peek (queue_t *q, void **element); bool queue_peek (queue_t *q, void **element);
bool queue_put (queue_t *q, void *element); bool queue_put (queue_t *q, void *element);
bool queue_get (queue_t *q, void *element); bool queue_get (queue_t *q, void *element);
bool queue_del (queue_t *q); bool queue_del (queue_t *q);
void queue_clr (queue_t *q); void queue_clr (queue_t *q);
int queue_len (queue_t *q); int queue_len (queue_t *q);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif

View File

@ -1,89 +1,101 @@
/****************************************************************************** /******************************************************************************
* @brief <EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<EFBFBD>ο<EFBFBD>linux/kfifo) * @brief <EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<EFBFBD>ο<EFBFBD>linux/kfifo)
* *
* Copyright (c) 2016~2020, <morro_luo@163.com> * Copyright (c) 2016~2021, <morro_luo@163.com>
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2016-05-30 Morro <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * 2016-05-30 roger.luo Initial version
******************************************************************************/ * 2021-02-05 roger.luo <EFBFBD><EFBFBD><EFBFBD>ӿ<EFBFBD><EFBFBD>пռ<EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD>ӿ<EFBFBD>.
#include "ringbuffer.h" ******************************************************************************/
#include <string.h> #include "ringbuffer.h"
#include <stddef.h> #include <string.h>
#include <stddef.h>
#define min(a,b) ( (a) < (b) )? (a):(b)
#define min(a,b) ( (a) < (b) )? (a):(b)
/*
*@brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> /*
*@param[in] r - <EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> *@brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*@param[in] buf - <EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> *@param[in] r - <EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*@param[in] len - buf<EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD><EFBFBD>N<EFBFBD><EFBFBD><EFBFBD><EFBFBD>) *@param[in] buf - <EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*@retval bool *@param[in] len - buf<EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD><EFBFBD>N<EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
*/ *@retval bool
bool ring_buf_init(ring_buf_t *r,unsigned char *buf, unsigned int len) */
{ bool ring_buf_init(ring_buf_t *r,unsigned char *buf, unsigned int len)
r->buf = buf; {
r->size = len; r->buf = buf;
r->front = r->rear = 0; r->size = len;
return buf != NULL && (len & len -1) == 0; r->front = r->rear = 0;
} return buf != NULL && (len & len -1) == 0;
}
/*
*@brief <EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> /*
*@param[in] r - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>յĻ<EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> *@brief <EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*@retval none *@param[in] r - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>յĻ<EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/ *@retval none
void ring_buf_clr(ring_buf_t *r) */
{ void ring_buf_clr(ring_buf_t *r)
r->front = r->rear = 0; {
} r->front = r->rear = 0;
}
/*
*@brief <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><EFBFBD><EFBFBD> /*
*@retval <EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD> *@brief <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><EFBFBD><EFBFBD>
*/ *@retval <EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ч<EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD>
unsigned int ring_buf_len(ring_buf_t *r) */
{ unsigned int ring_buf_len(ring_buf_t *r)
return r->rear - r->front; {
} return r->rear - r->front;
}
/*
*@brief <EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݷŵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> /*
*@param[in] buf - <EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> *@brief <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>пռ<EFBFBD>
* len - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> *@retval <EFBFBD><EFBFBD><EFBFBD>пռ<EFBFBD>
*@retval ʵ<EFBFBD>ʷŵ<EFBFBD><EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
*/ unsigned int ring_buf_free_space(ring_buf_t *r)
unsigned int ring_buf_put(ring_buf_t *r,unsigned char *buf,unsigned int len) {
{ return r->size - (unsigned int)(r->rear - r->front);
unsigned int i; }
unsigned int left;
left = r->size + r->front - r->rear; /*
len = min(len , left); *@brief <EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݷŵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
i = min(len, r->size - (r->rear & r->size - 1)); *@param[in] buf - <EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
memcpy(r->buf + (r->rear & r->size - 1), buf, i); * len - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
memcpy(r->buf, buf + i, len - i); *@retval ʵ<EFBFBD>ʷŵ<EFBFBD><EFBFBD>е<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
r->rear += len; */
return len; unsigned int ring_buf_put(ring_buf_t *r,unsigned char *buf,unsigned int len)
{
} unsigned int i;
unsigned int left;
/* left = r->size + r->front - r->rear;
*@brief <EFBFBD>ӻ<EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>ȡָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> len = min(len , left);
*@param[in] len - <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> i = min(len, r->size - (r->rear & r->size - 1));
*@param[out] buf - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> memcpy(r->buf + (r->rear & r->size - 1), buf, i);
*@retval ʵ<EFBFBD>ʶ<EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> memcpy(r->buf, buf + i, len - i);
*/ r->rear += len;
unsigned int ring_buf_get(ring_buf_t *r,unsigned char *buf,unsigned int len) return len;
{
unsigned int i; }
unsigned int left;
left = r->rear - r->front; /*
len = min(len , left); *@brief <EFBFBD>ӻ<EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>ȡָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
i = min(len, r->size - (r->front & r->size - 1)); *@param[in] len - <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
memcpy(buf, r->buf + (r->front & r->size - 1), i); *@param[out] buf - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
memcpy(buf + i, r->buf, len - i); *@retval ʵ<EFBFBD>ʶ<EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
r->front += len; */
return len; unsigned int ring_buf_get(ring_buf_t *r,unsigned char *buf,unsigned int len)
} {
unsigned int i;
unsigned int left;
if (ring_buf_len(r) == 0)
return 0;
left = r->rear - r->front;
len = min(len , left);
i = min(len, r->size - (r->front & r->size - 1));
memcpy(buf, r->buf + (r->front & r->size - 1), i);
memcpy(buf + i, r->buf, len - i);
r->front += len;
return len;
}

View File

@ -0,0 +1,47 @@
/******************************************************************************
* @brief <EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<EFBFBD>ο<EFBFBD>linux/kfifo)
*
* Copyright (c) 2016~2021, <morro_luo@163.com>
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2016-05-30 roger.luo Initial version.
* 2021-02-05 roger.luo <EFBFBD><EFBFBD><EFBFBD>ӿ<EFBFBD><EFBFBD>пռ<EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD>ӿ<EFBFBD>.
******************************************************************************/
#ifndef _RING_BUF_H_
#define _RING_BUF_H_
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/*<2A><><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
typedef struct {
unsigned char *buf; /*<2A><><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD> */
unsigned int size; /*<2A><><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD> */
unsigned int front; /*ͷָ<CDB7><D6B8> */
unsigned int rear; /*βָ<CEB2><D6B8> */
}ring_buf_t;
bool ring_buf_init(ring_buf_t *r,unsigned char *buf,unsigned int size);
void ring_buf_clr(ring_buf_t *r);
unsigned int ring_buf_len(ring_buf_t *r);
unsigned int ring_buf_put(ring_buf_t *r,unsigned char *buf,unsigned int len);
unsigned int ring_buf_get(ring_buf_t *r,unsigned char *buf,unsigned int len);
unsigned int ring_buf_free_space(ring_buf_t *r);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="iso-8859-1"?> <?xml version="1.0" encoding="iso-8859-1"?>
<workspace> <workspace>
<project> <project>
<path>$WS_DIR$\codebrick.ewp</path> <path>$WS_DIR$\codebrick.ewp</path>
</project> </project>
<batchBuild/> <batchBuild/>
</workspace> </workspace>

View File

@ -1,35 +1,35 @@
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
* Copyright (C) 2010 ARM Limited. All rights reserved. * Copyright (C) 2010 ARM Limited. All rights reserved.
* *
* $Date: 11. November 2010 * $Date: 11. November 2010
* $Revision: V1.0.2 * $Revision: V1.0.2
* *
* Project: CMSIS DSP Library * Project: CMSIS DSP Library
* Title: arm_common_tables.h * Title: arm_common_tables.h
* *
* Description: This file has extern declaration for common tables like Bitreverse, reciprocal etc which are used across different functions * Description: This file has extern declaration for common tables like Bitreverse, reciprocal etc which are used across different functions
* *
* Target Processor: Cortex-M4/Cortex-M3 * Target Processor: Cortex-M4/Cortex-M3
* *
* Version 1.0.2 2010/11/11 * Version 1.0.2 2010/11/11
* Documentation updated. * Documentation updated.
* *
* Version 1.0.1 2010/10/05 * Version 1.0.1 2010/10/05
* Production release and review comments incorporated. * Production release and review comments incorporated.
* *
* Version 1.0.0 2010/09/20 * Version 1.0.0 2010/09/20
* Production release and review comments incorporated. * Production release and review comments incorporated.
* -------------------------------------------------------------------- */ * -------------------------------------------------------------------- */
#ifndef _ARM_COMMON_TABLES_H #ifndef _ARM_COMMON_TABLES_H
#define _ARM_COMMON_TABLES_H #define _ARM_COMMON_TABLES_H
#include "arm_math.h" #include "arm_math.h"
extern uint16_t armBitRevTable[256]; extern uint16_t armBitRevTable[256];
extern q15_t armRecipTableQ15[64]; extern q15_t armRecipTableQ15[64];
extern q31_t armRecipTableQ31[64]; extern q31_t armRecipTableQ31[64];
extern const q31_t realCoefAQ31[1024]; extern const q31_t realCoefAQ31[1024];
extern const q31_t realCoefBQ31[1024]; extern const q31_t realCoefBQ31[1024];
#endif /* ARM_COMMON_TABLES_H */ #endif /* ARM_COMMON_TABLES_H */

View File

@ -1,99 +1,99 @@
/** /**
****************************************************************************** ******************************************************************************
* @file system_stm32f4xx.h * @file system_stm32f4xx.h
* @author MCD Application Team * @author MCD Application Team
* @version V1.0.0 * @version V1.0.0
* @date 30-September-2011 * @date 30-September-2011
* @brief CMSIS Cortex-M4 Device System Source File for STM32F4xx devices. * @brief CMSIS Cortex-M4 Device System Source File for STM32F4xx devices.
****************************************************************************** ******************************************************************************
* @attention * @attention
* *
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
* *
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2> * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
****************************************************************************** ******************************************************************************
*/ */
/** @addtogroup CMSIS /** @addtogroup CMSIS
* @{ * @{
*/ */
/** @addtogroup stm32f4xx_system /** @addtogroup stm32f4xx_system
* @{ * @{
*/ */
/** /**
* @brief Define to prevent recursive inclusion * @brief Define to prevent recursive inclusion
*/ */
#ifndef __SYSTEM_STM32F4XX_H #ifndef __SYSTEM_STM32F4XX_H
#define __SYSTEM_STM32F4XX_H #define __SYSTEM_STM32F4XX_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/** @addtogroup STM32F4xx_System_Includes /** @addtogroup STM32F4xx_System_Includes
* @{ * @{
*/ */
/** /**
* @} * @}
*/ */
/** @addtogroup STM32F4xx_System_Exported_types /** @addtogroup STM32F4xx_System_Exported_types
* @{ * @{
*/ */
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
/** /**
* @} * @}
*/ */
/** @addtogroup STM32F4xx_System_Exported_Constants /** @addtogroup STM32F4xx_System_Exported_Constants
* @{ * @{
*/ */
/** /**
* @} * @}
*/ */
/** @addtogroup STM32F4xx_System_Exported_Macros /** @addtogroup STM32F4xx_System_Exported_Macros
* @{ * @{
*/ */
/** /**
* @} * @}
*/ */
/** @addtogroup STM32F4xx_System_Exported_Functions /** @addtogroup STM32F4xx_System_Exported_Functions
* @{ * @{
*/ */
extern void SystemInit(void); extern void SystemInit(void);
extern void SystemCoreClockUpdate(void); extern void SystemCoreClockUpdate(void);
/** /**
* @} * @}
*/ */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /*__SYSTEM_STM32F4XX_H */ #endif /*__SYSTEM_STM32F4XX_H */
/** /**
* @} * @}
*/ */
/** /**
* @} * @}
*/ */
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

View File

@ -1,427 +1,427 @@
;******************** (C) COPYRIGHT 2011 STMicroelectronics ******************** ;******************** (C) COPYRIGHT 2011 STMicroelectronics ********************
;* File Name : startup_stm32f4xx.s ;* File Name : startup_stm32f4xx.s
;* Author : MCD Application Team ;* Author : MCD Application Team
;* Version : V1.0.0 ;* Version : V1.0.0
;* Date : 30-September-2011 ;* Date : 30-September-2011
;* Description : STM32F4xx devices vector table for MDK-ARM toolchain. ;* Description : STM32F4xx devices vector table for MDK-ARM toolchain.
;* This module performs: ;* This module performs:
;* - Set the initial SP ;* - Set the initial SP
;* - Set the initial PC == Reset_Handler ;* - Set the initial PC == Reset_Handler
;* - Set the vector table entries with the exceptions ISR address ;* - Set the vector table entries with the exceptions ISR address
;* - Configure the system clock and the external SRAM mounted on ;* - Configure the system clock and the external SRAM mounted on
;* STM324xG-EVAL board to be used as data memory (optional, ;* STM324xG-EVAL board to be used as data memory (optional,
;* to be enabled by user) ;* to be enabled by user)
;* - Branches to __main in the C library (which eventually ;* - Branches to __main in the C library (which eventually
;* calls main()). ;* calls main()).
;* After Reset the CortexM4 processor is in Thread mode, ;* After Reset the CortexM4 processor is in Thread mode,
;* priority is Privileged, and the Stack is set to Main. ;* priority is Privileged, and the Stack is set to Main.
;* <<< Use Configuration Wizard in Context Menu >>> ;* <<< Use Configuration Wizard in Context Menu >>>
;******************************************************************************* ;*******************************************************************************
; THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS ; THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
; WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. ; WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
; AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, ; AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
; INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE ; INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
; CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING ; CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
; INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. ; INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
;******************************************************************************* ;*******************************************************************************
; Amount of memory (in bytes) allocated for Stack ; Amount of memory (in bytes) allocated for Stack
; Tailor this value to your application needs ; Tailor this value to your application needs
; <h> Stack Configuration ; <h> Stack Configuration
; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> ; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h> ; </h>
Stack_Size EQU 0x00000400 Stack_Size EQU 0x00000400
AREA STACK, NOINIT, READWRITE, ALIGN=3 AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size Stack_Mem SPACE Stack_Size
__initial_sp __initial_sp
; <h> Heap Configuration ; <h> Heap Configuration
; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> ; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h> ; </h>
Heap_Size EQU 0x00000200 Heap_Size EQU 0x00000200
AREA HEAP, NOINIT, READWRITE, ALIGN=3 AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base __heap_base
Heap_Mem SPACE Heap_Size Heap_Mem SPACE Heap_Size
__heap_limit __heap_limit
PRESERVE8 PRESERVE8
THUMB THUMB
; Vector Table Mapped to Address 0 at Reset ; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY AREA RESET, DATA, READONLY
EXPORT __Vectors EXPORT __Vectors
EXPORT __Vectors_End EXPORT __Vectors_End
EXPORT __Vectors_Size EXPORT __Vectors_Size
__Vectors DCD __initial_sp ; Top of Stack __Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler DCD UsageFault_Handler ; Usage Fault Handler
DCD 0 ; Reserved DCD 0 ; Reserved
DCD 0 ; Reserved DCD 0 ; Reserved
DCD 0 ; Reserved DCD 0 ; Reserved
DCD 0 ; Reserved DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler DCD SysTick_Handler ; SysTick Handler
; External Interrupts ; External Interrupts
DCD WWDG_IRQHandler ; Window WatchDog DCD WWDG_IRQHandler ; Window WatchDog
DCD PVD_IRQHandler ; PVD through EXTI Line detection DCD PVD_IRQHandler ; PVD through EXTI Line detection
DCD TAMP_STAMP_IRQHandler ; Tamper and TimeStamps through the EXTI line DCD TAMP_STAMP_IRQHandler ; Tamper and TimeStamps through the EXTI line
DCD RTC_WKUP_IRQHandler ; RTC Wakeup through the EXTI line DCD RTC_WKUP_IRQHandler ; RTC Wakeup through the EXTI line
DCD FLASH_IRQHandler ; FLASH DCD FLASH_IRQHandler ; FLASH
DCD RCC_IRQHandler ; RCC DCD RCC_IRQHandler ; RCC
DCD EXTI0_IRQHandler ; EXTI Line0 DCD EXTI0_IRQHandler ; EXTI Line0
DCD EXTI1_IRQHandler ; EXTI Line1 DCD EXTI1_IRQHandler ; EXTI Line1
DCD EXTI2_IRQHandler ; EXTI Line2 DCD EXTI2_IRQHandler ; EXTI Line2
DCD EXTI3_IRQHandler ; EXTI Line3 DCD EXTI3_IRQHandler ; EXTI Line3
DCD EXTI4_IRQHandler ; EXTI Line4 DCD EXTI4_IRQHandler ; EXTI Line4
DCD DMA1_Stream0_IRQHandler ; DMA1 Stream 0 DCD DMA1_Stream0_IRQHandler ; DMA1 Stream 0
DCD DMA1_Stream1_IRQHandler ; DMA1 Stream 1 DCD DMA1_Stream1_IRQHandler ; DMA1 Stream 1
DCD DMA1_Stream2_IRQHandler ; DMA1 Stream 2 DCD DMA1_Stream2_IRQHandler ; DMA1 Stream 2
DCD DMA1_Stream3_IRQHandler ; DMA1 Stream 3 DCD DMA1_Stream3_IRQHandler ; DMA1 Stream 3
DCD DMA1_Stream4_IRQHandler ; DMA1 Stream 4 DCD DMA1_Stream4_IRQHandler ; DMA1 Stream 4
DCD DMA1_Stream5_IRQHandler ; DMA1 Stream 5 DCD DMA1_Stream5_IRQHandler ; DMA1 Stream 5
DCD DMA1_Stream6_IRQHandler ; DMA1 Stream 6 DCD DMA1_Stream6_IRQHandler ; DMA1 Stream 6
DCD ADC_IRQHandler ; ADC1, ADC2 and ADC3s DCD ADC_IRQHandler ; ADC1, ADC2 and ADC3s
DCD CAN1_TX_IRQHandler ; CAN1 TX DCD CAN1_TX_IRQHandler ; CAN1 TX
DCD CAN1_RX0_IRQHandler ; CAN1 RX0 DCD CAN1_RX0_IRQHandler ; CAN1 RX0
DCD CAN1_RX1_IRQHandler ; CAN1 RX1 DCD CAN1_RX1_IRQHandler ; CAN1 RX1
DCD CAN1_SCE_IRQHandler ; CAN1 SCE DCD CAN1_SCE_IRQHandler ; CAN1 SCE
DCD EXTI9_5_IRQHandler ; External Line[9:5]s DCD EXTI9_5_IRQHandler ; External Line[9:5]s
DCD TIM1_BRK_TIM9_IRQHandler ; TIM1 Break and TIM9 DCD TIM1_BRK_TIM9_IRQHandler ; TIM1 Break and TIM9
DCD TIM1_UP_TIM10_IRQHandler ; TIM1 Update and TIM10 DCD TIM1_UP_TIM10_IRQHandler ; TIM1 Update and TIM10
DCD TIM1_TRG_COM_TIM11_IRQHandler ; TIM1 Trigger and Commutation and TIM11 DCD TIM1_TRG_COM_TIM11_IRQHandler ; TIM1 Trigger and Commutation and TIM11
DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare
DCD TIM2_IRQHandler ; TIM2 DCD TIM2_IRQHandler ; TIM2
DCD TIM3_IRQHandler ; TIM3 DCD TIM3_IRQHandler ; TIM3
DCD TIM4_IRQHandler ; TIM4 DCD TIM4_IRQHandler ; TIM4
DCD I2C1_EV_IRQHandler ; I2C1 Event DCD I2C1_EV_IRQHandler ; I2C1 Event
DCD I2C1_ER_IRQHandler ; I2C1 Error DCD I2C1_ER_IRQHandler ; I2C1 Error
DCD I2C2_EV_IRQHandler ; I2C2 Event DCD I2C2_EV_IRQHandler ; I2C2 Event
DCD I2C2_ER_IRQHandler ; I2C2 Error DCD I2C2_ER_IRQHandler ; I2C2 Error
DCD SPI1_IRQHandler ; SPI1 DCD SPI1_IRQHandler ; SPI1
DCD SPI2_IRQHandler ; SPI2 DCD SPI2_IRQHandler ; SPI2
DCD USART1_IRQHandler ; USART1 DCD USART1_IRQHandler ; USART1
DCD USART2_IRQHandler ; USART2 DCD USART2_IRQHandler ; USART2
DCD USART3_IRQHandler ; USART3 DCD USART3_IRQHandler ; USART3
DCD EXTI15_10_IRQHandler ; External Line[15:10]s DCD EXTI15_10_IRQHandler ; External Line[15:10]s
DCD RTC_Alarm_IRQHandler ; RTC Alarm (A and B) through EXTI Line DCD RTC_Alarm_IRQHandler ; RTC Alarm (A and B) through EXTI Line
DCD OTG_FS_WKUP_IRQHandler ; USB OTG FS Wakeup through EXTI line DCD OTG_FS_WKUP_IRQHandler ; USB OTG FS Wakeup through EXTI line
DCD TIM8_BRK_TIM12_IRQHandler ; TIM8 Break and TIM12 DCD TIM8_BRK_TIM12_IRQHandler ; TIM8 Break and TIM12
DCD TIM8_UP_TIM13_IRQHandler ; TIM8 Update and TIM13 DCD TIM8_UP_TIM13_IRQHandler ; TIM8 Update and TIM13
DCD TIM8_TRG_COM_TIM14_IRQHandler ; TIM8 Trigger and Commutation and TIM14 DCD TIM8_TRG_COM_TIM14_IRQHandler ; TIM8 Trigger and Commutation and TIM14
DCD TIM8_CC_IRQHandler ; TIM8 Capture Compare DCD TIM8_CC_IRQHandler ; TIM8 Capture Compare
DCD DMA1_Stream7_IRQHandler ; DMA1 Stream7 DCD DMA1_Stream7_IRQHandler ; DMA1 Stream7
DCD FSMC_IRQHandler ; FSMC DCD FSMC_IRQHandler ; FSMC
DCD SDIO_IRQHandler ; SDIO DCD SDIO_IRQHandler ; SDIO
DCD TIM5_IRQHandler ; TIM5 DCD TIM5_IRQHandler ; TIM5
DCD SPI3_IRQHandler ; SPI3 DCD SPI3_IRQHandler ; SPI3
DCD UART4_IRQHandler ; UART4 DCD UART4_IRQHandler ; UART4
DCD UART5_IRQHandler ; UART5 DCD UART5_IRQHandler ; UART5
DCD TIM6_DAC_IRQHandler ; TIM6 and DAC1&2 underrun errors DCD TIM6_DAC_IRQHandler ; TIM6 and DAC1&2 underrun errors
DCD TIM7_IRQHandler ; TIM7 DCD TIM7_IRQHandler ; TIM7
DCD DMA2_Stream0_IRQHandler ; DMA2 Stream 0 DCD DMA2_Stream0_IRQHandler ; DMA2 Stream 0
DCD DMA2_Stream1_IRQHandler ; DMA2 Stream 1 DCD DMA2_Stream1_IRQHandler ; DMA2 Stream 1
DCD DMA2_Stream2_IRQHandler ; DMA2 Stream 2 DCD DMA2_Stream2_IRQHandler ; DMA2 Stream 2
DCD DMA2_Stream3_IRQHandler ; DMA2 Stream 3 DCD DMA2_Stream3_IRQHandler ; DMA2 Stream 3
DCD DMA2_Stream4_IRQHandler ; DMA2 Stream 4 DCD DMA2_Stream4_IRQHandler ; DMA2 Stream 4
DCD ETH_IRQHandler ; Ethernet DCD ETH_IRQHandler ; Ethernet
DCD ETH_WKUP_IRQHandler ; Ethernet Wakeup through EXTI line DCD ETH_WKUP_IRQHandler ; Ethernet Wakeup through EXTI line
DCD CAN2_TX_IRQHandler ; CAN2 TX DCD CAN2_TX_IRQHandler ; CAN2 TX
DCD CAN2_RX0_IRQHandler ; CAN2 RX0 DCD CAN2_RX0_IRQHandler ; CAN2 RX0
DCD CAN2_RX1_IRQHandler ; CAN2 RX1 DCD CAN2_RX1_IRQHandler ; CAN2 RX1
DCD CAN2_SCE_IRQHandler ; CAN2 SCE DCD CAN2_SCE_IRQHandler ; CAN2 SCE
DCD OTG_FS_IRQHandler ; USB OTG FS DCD OTG_FS_IRQHandler ; USB OTG FS
DCD DMA2_Stream5_IRQHandler ; DMA2 Stream 5 DCD DMA2_Stream5_IRQHandler ; DMA2 Stream 5
DCD DMA2_Stream6_IRQHandler ; DMA2 Stream 6 DCD DMA2_Stream6_IRQHandler ; DMA2 Stream 6
DCD DMA2_Stream7_IRQHandler ; DMA2 Stream 7 DCD DMA2_Stream7_IRQHandler ; DMA2 Stream 7
DCD USART6_IRQHandler ; USART6 DCD USART6_IRQHandler ; USART6
DCD I2C3_EV_IRQHandler ; I2C3 event DCD I2C3_EV_IRQHandler ; I2C3 event
DCD I2C3_ER_IRQHandler ; I2C3 error DCD I2C3_ER_IRQHandler ; I2C3 error
DCD OTG_HS_EP1_OUT_IRQHandler ; USB OTG HS End Point 1 Out DCD OTG_HS_EP1_OUT_IRQHandler ; USB OTG HS End Point 1 Out
DCD OTG_HS_EP1_IN_IRQHandler ; USB OTG HS End Point 1 In DCD OTG_HS_EP1_IN_IRQHandler ; USB OTG HS End Point 1 In
DCD OTG_HS_WKUP_IRQHandler ; USB OTG HS Wakeup through EXTI DCD OTG_HS_WKUP_IRQHandler ; USB OTG HS Wakeup through EXTI
DCD OTG_HS_IRQHandler ; USB OTG HS DCD OTG_HS_IRQHandler ; USB OTG HS
DCD DCMI_IRQHandler ; DCMI DCD DCMI_IRQHandler ; DCMI
DCD CRYP_IRQHandler ; CRYP crypto DCD CRYP_IRQHandler ; CRYP crypto
DCD HASH_RNG_IRQHandler ; Hash and Rng DCD HASH_RNG_IRQHandler ; Hash and Rng
DCD FPU_IRQHandler ; FPU DCD FPU_IRQHandler ; FPU
__Vectors_End __Vectors_End
__Vectors_Size EQU __Vectors_End - __Vectors __Vectors_Size EQU __Vectors_End - __Vectors
AREA |.text|, CODE, READONLY AREA |.text|, CODE, READONLY
; Reset handler ; Reset handler
Reset_Handler PROC Reset_Handler PROC
EXPORT Reset_Handler [WEAK] EXPORT Reset_Handler [WEAK]
IMPORT SystemInit IMPORT SystemInit
IMPORT __main IMPORT __main
LDR R0, =SystemInit LDR R0, =SystemInit
BLX R0 BLX R0
LDR R0, =__main LDR R0, =__main
BX R0 BX R0
ENDP ENDP
; Dummy Exception Handlers (infinite loops which can be modified) ; Dummy Exception Handlers (infinite loops which can be modified)
NMI_Handler PROC NMI_Handler PROC
EXPORT NMI_Handler [WEAK] EXPORT NMI_Handler [WEAK]
B . B .
ENDP ENDP
HardFault_Handler\ HardFault_Handler\
PROC PROC
EXPORT HardFault_Handler [WEAK] EXPORT HardFault_Handler [WEAK]
B . B .
ENDP ENDP
MemManage_Handler\ MemManage_Handler\
PROC PROC
EXPORT MemManage_Handler [WEAK] EXPORT MemManage_Handler [WEAK]
B . B .
ENDP ENDP
BusFault_Handler\ BusFault_Handler\
PROC PROC
EXPORT BusFault_Handler [WEAK] EXPORT BusFault_Handler [WEAK]
B . B .
ENDP ENDP
UsageFault_Handler\ UsageFault_Handler\
PROC PROC
EXPORT UsageFault_Handler [WEAK] EXPORT UsageFault_Handler [WEAK]
B . B .
ENDP ENDP
SVC_Handler PROC SVC_Handler PROC
EXPORT SVC_Handler [WEAK] EXPORT SVC_Handler [WEAK]
B . B .
ENDP ENDP
DebugMon_Handler\ DebugMon_Handler\
PROC PROC
EXPORT DebugMon_Handler [WEAK] EXPORT DebugMon_Handler [WEAK]
B . B .
ENDP ENDP
PendSV_Handler PROC PendSV_Handler PROC
EXPORT PendSV_Handler [WEAK] EXPORT PendSV_Handler [WEAK]
B . B .
ENDP ENDP
SysTick_Handler PROC SysTick_Handler PROC
EXPORT SysTick_Handler [WEAK] EXPORT SysTick_Handler [WEAK]
B . B .
ENDP ENDP
Default_Handler PROC Default_Handler PROC
EXPORT WWDG_IRQHandler [WEAK] EXPORT WWDG_IRQHandler [WEAK]
EXPORT PVD_IRQHandler [WEAK] EXPORT PVD_IRQHandler [WEAK]
EXPORT TAMP_STAMP_IRQHandler [WEAK] EXPORT TAMP_STAMP_IRQHandler [WEAK]
EXPORT RTC_WKUP_IRQHandler [WEAK] EXPORT RTC_WKUP_IRQHandler [WEAK]
EXPORT FLASH_IRQHandler [WEAK] EXPORT FLASH_IRQHandler [WEAK]
EXPORT RCC_IRQHandler [WEAK] EXPORT RCC_IRQHandler [WEAK]
EXPORT EXTI0_IRQHandler [WEAK] EXPORT EXTI0_IRQHandler [WEAK]
EXPORT EXTI1_IRQHandler [WEAK] EXPORT EXTI1_IRQHandler [WEAK]
EXPORT EXTI2_IRQHandler [WEAK] EXPORT EXTI2_IRQHandler [WEAK]
EXPORT EXTI3_IRQHandler [WEAK] EXPORT EXTI3_IRQHandler [WEAK]
EXPORT EXTI4_IRQHandler [WEAK] EXPORT EXTI4_IRQHandler [WEAK]
EXPORT DMA1_Stream0_IRQHandler [WEAK] EXPORT DMA1_Stream0_IRQHandler [WEAK]
EXPORT DMA1_Stream1_IRQHandler [WEAK] EXPORT DMA1_Stream1_IRQHandler [WEAK]
EXPORT DMA1_Stream2_IRQHandler [WEAK] EXPORT DMA1_Stream2_IRQHandler [WEAK]
EXPORT DMA1_Stream3_IRQHandler [WEAK] EXPORT DMA1_Stream3_IRQHandler [WEAK]
EXPORT DMA1_Stream4_IRQHandler [WEAK] EXPORT DMA1_Stream4_IRQHandler [WEAK]
EXPORT DMA1_Stream5_IRQHandler [WEAK] EXPORT DMA1_Stream5_IRQHandler [WEAK]
EXPORT DMA1_Stream6_IRQHandler [WEAK] EXPORT DMA1_Stream6_IRQHandler [WEAK]
EXPORT ADC_IRQHandler [WEAK] EXPORT ADC_IRQHandler [WEAK]
EXPORT CAN1_TX_IRQHandler [WEAK] EXPORT CAN1_TX_IRQHandler [WEAK]
EXPORT CAN1_RX0_IRQHandler [WEAK] EXPORT CAN1_RX0_IRQHandler [WEAK]
EXPORT CAN1_RX1_IRQHandler [WEAK] EXPORT CAN1_RX1_IRQHandler [WEAK]
EXPORT CAN1_SCE_IRQHandler [WEAK] EXPORT CAN1_SCE_IRQHandler [WEAK]
EXPORT EXTI9_5_IRQHandler [WEAK] EXPORT EXTI9_5_IRQHandler [WEAK]
EXPORT TIM1_BRK_TIM9_IRQHandler [WEAK] EXPORT TIM1_BRK_TIM9_IRQHandler [WEAK]
EXPORT TIM1_UP_TIM10_IRQHandler [WEAK] EXPORT TIM1_UP_TIM10_IRQHandler [WEAK]
EXPORT TIM1_TRG_COM_TIM11_IRQHandler [WEAK] EXPORT TIM1_TRG_COM_TIM11_IRQHandler [WEAK]
EXPORT TIM1_CC_IRQHandler [WEAK] EXPORT TIM1_CC_IRQHandler [WEAK]
EXPORT TIM2_IRQHandler [WEAK] EXPORT TIM2_IRQHandler [WEAK]
EXPORT TIM3_IRQHandler [WEAK] EXPORT TIM3_IRQHandler [WEAK]
EXPORT TIM4_IRQHandler [WEAK] EXPORT TIM4_IRQHandler [WEAK]
EXPORT I2C1_EV_IRQHandler [WEAK] EXPORT I2C1_EV_IRQHandler [WEAK]
EXPORT I2C1_ER_IRQHandler [WEAK] EXPORT I2C1_ER_IRQHandler [WEAK]
EXPORT I2C2_EV_IRQHandler [WEAK] EXPORT I2C2_EV_IRQHandler [WEAK]
EXPORT I2C2_ER_IRQHandler [WEAK] EXPORT I2C2_ER_IRQHandler [WEAK]
EXPORT SPI1_IRQHandler [WEAK] EXPORT SPI1_IRQHandler [WEAK]
EXPORT SPI2_IRQHandler [WEAK] EXPORT SPI2_IRQHandler [WEAK]
EXPORT USART1_IRQHandler [WEAK] EXPORT USART1_IRQHandler [WEAK]
EXPORT USART2_IRQHandler [WEAK] EXPORT USART2_IRQHandler [WEAK]
EXPORT USART3_IRQHandler [WEAK] EXPORT USART3_IRQHandler [WEAK]
EXPORT EXTI15_10_IRQHandler [WEAK] EXPORT EXTI15_10_IRQHandler [WEAK]
EXPORT RTC_Alarm_IRQHandler [WEAK] EXPORT RTC_Alarm_IRQHandler [WEAK]
EXPORT OTG_FS_WKUP_IRQHandler [WEAK] EXPORT OTG_FS_WKUP_IRQHandler [WEAK]
EXPORT TIM8_BRK_TIM12_IRQHandler [WEAK] EXPORT TIM8_BRK_TIM12_IRQHandler [WEAK]
EXPORT TIM8_UP_TIM13_IRQHandler [WEAK] EXPORT TIM8_UP_TIM13_IRQHandler [WEAK]
EXPORT TIM8_TRG_COM_TIM14_IRQHandler [WEAK] EXPORT TIM8_TRG_COM_TIM14_IRQHandler [WEAK]
EXPORT TIM8_CC_IRQHandler [WEAK] EXPORT TIM8_CC_IRQHandler [WEAK]
EXPORT DMA1_Stream7_IRQHandler [WEAK] EXPORT DMA1_Stream7_IRQHandler [WEAK]
EXPORT FSMC_IRQHandler [WEAK] EXPORT FSMC_IRQHandler [WEAK]
EXPORT SDIO_IRQHandler [WEAK] EXPORT SDIO_IRQHandler [WEAK]
EXPORT TIM5_IRQHandler [WEAK] EXPORT TIM5_IRQHandler [WEAK]
EXPORT SPI3_IRQHandler [WEAK] EXPORT SPI3_IRQHandler [WEAK]
EXPORT UART4_IRQHandler [WEAK] EXPORT UART4_IRQHandler [WEAK]
EXPORT UART5_IRQHandler [WEAK] EXPORT UART5_IRQHandler [WEAK]
EXPORT TIM6_DAC_IRQHandler [WEAK] EXPORT TIM6_DAC_IRQHandler [WEAK]
EXPORT TIM7_IRQHandler [WEAK] EXPORT TIM7_IRQHandler [WEAK]
EXPORT DMA2_Stream0_IRQHandler [WEAK] EXPORT DMA2_Stream0_IRQHandler [WEAK]
EXPORT DMA2_Stream1_IRQHandler [WEAK] EXPORT DMA2_Stream1_IRQHandler [WEAK]
EXPORT DMA2_Stream2_IRQHandler [WEAK] EXPORT DMA2_Stream2_IRQHandler [WEAK]
EXPORT DMA2_Stream3_IRQHandler [WEAK] EXPORT DMA2_Stream3_IRQHandler [WEAK]
EXPORT DMA2_Stream4_IRQHandler [WEAK] EXPORT DMA2_Stream4_IRQHandler [WEAK]
EXPORT ETH_IRQHandler [WEAK] EXPORT ETH_IRQHandler [WEAK]
EXPORT ETH_WKUP_IRQHandler [WEAK] EXPORT ETH_WKUP_IRQHandler [WEAK]
EXPORT CAN2_TX_IRQHandler [WEAK] EXPORT CAN2_TX_IRQHandler [WEAK]
EXPORT CAN2_RX0_IRQHandler [WEAK] EXPORT CAN2_RX0_IRQHandler [WEAK]
EXPORT CAN2_RX1_IRQHandler [WEAK] EXPORT CAN2_RX1_IRQHandler [WEAK]
EXPORT CAN2_SCE_IRQHandler [WEAK] EXPORT CAN2_SCE_IRQHandler [WEAK]
EXPORT OTG_FS_IRQHandler [WEAK] EXPORT OTG_FS_IRQHandler [WEAK]
EXPORT DMA2_Stream5_IRQHandler [WEAK] EXPORT DMA2_Stream5_IRQHandler [WEAK]
EXPORT DMA2_Stream6_IRQHandler [WEAK] EXPORT DMA2_Stream6_IRQHandler [WEAK]
EXPORT DMA2_Stream7_IRQHandler [WEAK] EXPORT DMA2_Stream7_IRQHandler [WEAK]
EXPORT USART6_IRQHandler [WEAK] EXPORT USART6_IRQHandler [WEAK]
EXPORT I2C3_EV_IRQHandler [WEAK] EXPORT I2C3_EV_IRQHandler [WEAK]
EXPORT I2C3_ER_IRQHandler [WEAK] EXPORT I2C3_ER_IRQHandler [WEAK]
EXPORT OTG_HS_EP1_OUT_IRQHandler [WEAK] EXPORT OTG_HS_EP1_OUT_IRQHandler [WEAK]
EXPORT OTG_HS_EP1_IN_IRQHandler [WEAK] EXPORT OTG_HS_EP1_IN_IRQHandler [WEAK]
EXPORT OTG_HS_WKUP_IRQHandler [WEAK] EXPORT OTG_HS_WKUP_IRQHandler [WEAK]
EXPORT OTG_HS_IRQHandler [WEAK] EXPORT OTG_HS_IRQHandler [WEAK]
EXPORT DCMI_IRQHandler [WEAK] EXPORT DCMI_IRQHandler [WEAK]
EXPORT CRYP_IRQHandler [WEAK] EXPORT CRYP_IRQHandler [WEAK]
EXPORT HASH_RNG_IRQHandler [WEAK] EXPORT HASH_RNG_IRQHandler [WEAK]
EXPORT FPU_IRQHandler [WEAK] EXPORT FPU_IRQHandler [WEAK]
WWDG_IRQHandler WWDG_IRQHandler
PVD_IRQHandler PVD_IRQHandler
TAMP_STAMP_IRQHandler TAMP_STAMP_IRQHandler
RTC_WKUP_IRQHandler RTC_WKUP_IRQHandler
FLASH_IRQHandler FLASH_IRQHandler
RCC_IRQHandler RCC_IRQHandler
EXTI0_IRQHandler EXTI0_IRQHandler
EXTI1_IRQHandler EXTI1_IRQHandler
EXTI2_IRQHandler EXTI2_IRQHandler
EXTI3_IRQHandler EXTI3_IRQHandler
EXTI4_IRQHandler EXTI4_IRQHandler
DMA1_Stream0_IRQHandler DMA1_Stream0_IRQHandler
DMA1_Stream1_IRQHandler DMA1_Stream1_IRQHandler
DMA1_Stream2_IRQHandler DMA1_Stream2_IRQHandler
DMA1_Stream3_IRQHandler DMA1_Stream3_IRQHandler
DMA1_Stream4_IRQHandler DMA1_Stream4_IRQHandler
DMA1_Stream5_IRQHandler DMA1_Stream5_IRQHandler
DMA1_Stream6_IRQHandler DMA1_Stream6_IRQHandler
ADC_IRQHandler ADC_IRQHandler
CAN1_TX_IRQHandler CAN1_TX_IRQHandler
CAN1_RX0_IRQHandler CAN1_RX0_IRQHandler
CAN1_RX1_IRQHandler CAN1_RX1_IRQHandler
CAN1_SCE_IRQHandler CAN1_SCE_IRQHandler
EXTI9_5_IRQHandler EXTI9_5_IRQHandler
TIM1_BRK_TIM9_IRQHandler TIM1_BRK_TIM9_IRQHandler
TIM1_UP_TIM10_IRQHandler TIM1_UP_TIM10_IRQHandler
TIM1_TRG_COM_TIM11_IRQHandler TIM1_TRG_COM_TIM11_IRQHandler
TIM1_CC_IRQHandler TIM1_CC_IRQHandler
TIM2_IRQHandler TIM2_IRQHandler
TIM3_IRQHandler TIM3_IRQHandler
TIM4_IRQHandler TIM4_IRQHandler
I2C1_EV_IRQHandler I2C1_EV_IRQHandler
I2C1_ER_IRQHandler I2C1_ER_IRQHandler
I2C2_EV_IRQHandler I2C2_EV_IRQHandler
I2C2_ER_IRQHandler I2C2_ER_IRQHandler
SPI1_IRQHandler SPI1_IRQHandler
SPI2_IRQHandler SPI2_IRQHandler
USART1_IRQHandler USART1_IRQHandler
USART2_IRQHandler USART2_IRQHandler
USART3_IRQHandler USART3_IRQHandler
EXTI15_10_IRQHandler EXTI15_10_IRQHandler
RTC_Alarm_IRQHandler RTC_Alarm_IRQHandler
OTG_FS_WKUP_IRQHandler OTG_FS_WKUP_IRQHandler
TIM8_BRK_TIM12_IRQHandler TIM8_BRK_TIM12_IRQHandler
TIM8_UP_TIM13_IRQHandler TIM8_UP_TIM13_IRQHandler
TIM8_TRG_COM_TIM14_IRQHandler TIM8_TRG_COM_TIM14_IRQHandler
TIM8_CC_IRQHandler TIM8_CC_IRQHandler
DMA1_Stream7_IRQHandler DMA1_Stream7_IRQHandler
FSMC_IRQHandler FSMC_IRQHandler
SDIO_IRQHandler SDIO_IRQHandler
TIM5_IRQHandler TIM5_IRQHandler
SPI3_IRQHandler SPI3_IRQHandler
UART4_IRQHandler UART4_IRQHandler
UART5_IRQHandler UART5_IRQHandler
TIM6_DAC_IRQHandler TIM6_DAC_IRQHandler
TIM7_IRQHandler TIM7_IRQHandler
DMA2_Stream0_IRQHandler DMA2_Stream0_IRQHandler
DMA2_Stream1_IRQHandler DMA2_Stream1_IRQHandler
DMA2_Stream2_IRQHandler DMA2_Stream2_IRQHandler
DMA2_Stream3_IRQHandler DMA2_Stream3_IRQHandler
DMA2_Stream4_IRQHandler DMA2_Stream4_IRQHandler
ETH_IRQHandler ETH_IRQHandler
ETH_WKUP_IRQHandler ETH_WKUP_IRQHandler
CAN2_TX_IRQHandler CAN2_TX_IRQHandler
CAN2_RX0_IRQHandler CAN2_RX0_IRQHandler
CAN2_RX1_IRQHandler CAN2_RX1_IRQHandler
CAN2_SCE_IRQHandler CAN2_SCE_IRQHandler
OTG_FS_IRQHandler OTG_FS_IRQHandler
DMA2_Stream5_IRQHandler DMA2_Stream5_IRQHandler
DMA2_Stream6_IRQHandler DMA2_Stream6_IRQHandler
DMA2_Stream7_IRQHandler DMA2_Stream7_IRQHandler
USART6_IRQHandler USART6_IRQHandler
I2C3_EV_IRQHandler I2C3_EV_IRQHandler
I2C3_ER_IRQHandler I2C3_ER_IRQHandler
OTG_HS_EP1_OUT_IRQHandler OTG_HS_EP1_OUT_IRQHandler
OTG_HS_EP1_IN_IRQHandler OTG_HS_EP1_IN_IRQHandler
OTG_HS_WKUP_IRQHandler OTG_HS_WKUP_IRQHandler
OTG_HS_IRQHandler OTG_HS_IRQHandler
DCMI_IRQHandler DCMI_IRQHandler
CRYP_IRQHandler CRYP_IRQHandler
HASH_RNG_IRQHandler HASH_RNG_IRQHandler
FPU_IRQHandler FPU_IRQHandler
B . B .
ENDP ENDP
ALIGN ALIGN
;******************************************************************************* ;*******************************************************************************
; User Stack and Heap initialization ; User Stack and Heap initialization
;******************************************************************************* ;*******************************************************************************
IF :DEF:__MICROLIB IF :DEF:__MICROLIB
EXPORT __initial_sp EXPORT __initial_sp
EXPORT __heap_base EXPORT __heap_base
EXPORT __heap_limit EXPORT __heap_limit
ELSE ELSE
IMPORT __use_two_region_memory IMPORT __use_two_region_memory
EXPORT __user_initial_stackheap EXPORT __user_initial_stackheap
__user_initial_stackheap __user_initial_stackheap
LDR R0, = Heap_Mem LDR R0, = Heap_Mem
LDR R1, =(Stack_Mem + Stack_Size) LDR R1, =(Stack_Mem + Stack_Size)
LDR R2, = (Heap_Mem + Heap_Size) LDR R2, = (Heap_Mem + Heap_Size)
LDR R3, = Stack_Mem LDR R3, = Stack_Mem
BX LR BX LR
ALIGN ALIGN
ENDIF ENDIF
END END
;******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE***** ;******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE*****

View File

@ -1,172 +1,172 @@
/** /**
****************************************************************************** ******************************************************************************
* @file misc.h * @file misc.h
* @author MCD Application Team * @author MCD Application Team
* @version V1.0.0 * @version V1.0.0
* @date 30-September-2011 * @date 30-September-2011
* @brief This file contains all the functions prototypes for the miscellaneous * @brief This file contains all the functions prototypes for the miscellaneous
* firmware library functions (add-on to CMSIS functions). * firmware library functions (add-on to CMSIS functions).
****************************************************************************** ******************************************************************************
* @attention * @attention
* *
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
* *
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2> * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
****************************************************************************** ******************************************************************************
*/ */
/* Define to prevent recursive inclusion -------------------------------------*/ /* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MISC_H #ifndef __MISC_H
#define __MISC_H #define __MISC_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* Includes ------------------------------------------------------------------*/ /* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h" #include "stm32f4xx.h"
/** @addtogroup STM32F4xx_StdPeriph_Driver /** @addtogroup STM32F4xx_StdPeriph_Driver
* @{ * @{
*/ */
/** @addtogroup MISC /** @addtogroup MISC
* @{ * @{
*/ */
/* Exported types ------------------------------------------------------------*/ /* Exported types ------------------------------------------------------------*/
/** /**
* @brief NVIC Init Structure definition * @brief NVIC Init Structure definition
*/ */
typedef struct typedef struct
{ {
uint8_t NVIC_IRQChannel; /*!< Specifies the IRQ channel to be enabled or disabled. uint8_t NVIC_IRQChannel; /*!< Specifies the IRQ channel to be enabled or disabled.
This parameter can be an enumerator of @ref IRQn_Type This parameter can be an enumerator of @ref IRQn_Type
enumeration (For the complete STM32 Devices IRQ Channels enumeration (For the complete STM32 Devices IRQ Channels
list, please refer to stm32f4xx.h file) */ list, please refer to stm32f4xx.h file) */
uint8_t NVIC_IRQChannelPreemptionPriority; /*!< Specifies the pre-emption priority for the IRQ channel uint8_t NVIC_IRQChannelPreemptionPriority; /*!< Specifies the pre-emption priority for the IRQ channel
specified in NVIC_IRQChannel. This parameter can be a value specified in NVIC_IRQChannel. This parameter can be a value
between 0 and 15 as described in the table @ref MISC_NVIC_Priority_Table between 0 and 15 as described in the table @ref MISC_NVIC_Priority_Table
A lower priority value indicates a higher priority */ A lower priority value indicates a higher priority */
uint8_t NVIC_IRQChannelSubPriority; /*!< Specifies the subpriority level for the IRQ channel specified uint8_t NVIC_IRQChannelSubPriority; /*!< Specifies the subpriority level for the IRQ channel specified
in NVIC_IRQChannel. This parameter can be a value in NVIC_IRQChannel. This parameter can be a value
between 0 and 15 as described in the table @ref MISC_NVIC_Priority_Table between 0 and 15 as described in the table @ref MISC_NVIC_Priority_Table
A lower priority value indicates a higher priority */ A lower priority value indicates a higher priority */
FunctionalState NVIC_IRQChannelCmd; /*!< Specifies whether the IRQ channel defined in NVIC_IRQChannel FunctionalState NVIC_IRQChannelCmd; /*!< Specifies whether the IRQ channel defined in NVIC_IRQChannel
will be enabled or disabled. will be enabled or disabled.
This parameter can be set either to ENABLE or DISABLE */ This parameter can be set either to ENABLE or DISABLE */
} NVIC_InitTypeDef; } NVIC_InitTypeDef;
/* Exported constants --------------------------------------------------------*/ /* Exported constants --------------------------------------------------------*/
/** @defgroup MISC_Exported_Constants /** @defgroup MISC_Exported_Constants
* @{ * @{
*/ */
/** @defgroup MISC_Vector_Table_Base /** @defgroup MISC_Vector_Table_Base
* @{ * @{
*/ */
#define NVIC_VectTab_RAM ((uint32_t)0x20000000) #define NVIC_VectTab_RAM ((uint32_t)0x20000000)
#define NVIC_VectTab_FLASH ((uint32_t)0x08000000) #define NVIC_VectTab_FLASH ((uint32_t)0x08000000)
#define IS_NVIC_VECTTAB(VECTTAB) (((VECTTAB) == NVIC_VectTab_RAM) || \ #define IS_NVIC_VECTTAB(VECTTAB) (((VECTTAB) == NVIC_VectTab_RAM) || \
((VECTTAB) == NVIC_VectTab_FLASH)) ((VECTTAB) == NVIC_VectTab_FLASH))
/** /**
* @} * @}
*/ */
/** @defgroup MISC_System_Low_Power /** @defgroup MISC_System_Low_Power
* @{ * @{
*/ */
#define NVIC_LP_SEVONPEND ((uint8_t)0x10) #define NVIC_LP_SEVONPEND ((uint8_t)0x10)
#define NVIC_LP_SLEEPDEEP ((uint8_t)0x04) #define NVIC_LP_SLEEPDEEP ((uint8_t)0x04)
#define NVIC_LP_SLEEPONEXIT ((uint8_t)0x02) #define NVIC_LP_SLEEPONEXIT ((uint8_t)0x02)
#define IS_NVIC_LP(LP) (((LP) == NVIC_LP_SEVONPEND) || \ #define IS_NVIC_LP(LP) (((LP) == NVIC_LP_SEVONPEND) || \
((LP) == NVIC_LP_SLEEPDEEP) || \ ((LP) == NVIC_LP_SLEEPDEEP) || \
((LP) == NVIC_LP_SLEEPONEXIT)) ((LP) == NVIC_LP_SLEEPONEXIT))
/** /**
* @} * @}
*/ */
/** @defgroup MISC_Preemption_Priority_Group /** @defgroup MISC_Preemption_Priority_Group
* @{ * @{
*/ */
#define NVIC_PriorityGroup_0 ((uint32_t)0x700) /*!< 0 bits for pre-emption priority #define NVIC_PriorityGroup_0 ((uint32_t)0x700) /*!< 0 bits for pre-emption priority
4 bits for subpriority */ 4 bits for subpriority */
#define NVIC_PriorityGroup_1 ((uint32_t)0x600) /*!< 1 bits for pre-emption priority #define NVIC_PriorityGroup_1 ((uint32_t)0x600) /*!< 1 bits for pre-emption priority
3 bits for subpriority */ 3 bits for subpriority */
#define NVIC_PriorityGroup_2 ((uint32_t)0x500) /*!< 2 bits for pre-emption priority #define NVIC_PriorityGroup_2 ((uint32_t)0x500) /*!< 2 bits for pre-emption priority
2 bits for subpriority */ 2 bits for subpriority */
#define NVIC_PriorityGroup_3 ((uint32_t)0x400) /*!< 3 bits for pre-emption priority #define NVIC_PriorityGroup_3 ((uint32_t)0x400) /*!< 3 bits for pre-emption priority
1 bits for subpriority */ 1 bits for subpriority */
#define NVIC_PriorityGroup_4 ((uint32_t)0x300) /*!< 4 bits for pre-emption priority #define NVIC_PriorityGroup_4 ((uint32_t)0x300) /*!< 4 bits for pre-emption priority
0 bits for subpriority */ 0 bits for subpriority */
#define IS_NVIC_PRIORITY_GROUP(GROUP) (((GROUP) == NVIC_PriorityGroup_0) || \ #define IS_NVIC_PRIORITY_GROUP(GROUP) (((GROUP) == NVIC_PriorityGroup_0) || \
((GROUP) == NVIC_PriorityGroup_1) || \ ((GROUP) == NVIC_PriorityGroup_1) || \
((GROUP) == NVIC_PriorityGroup_2) || \ ((GROUP) == NVIC_PriorityGroup_2) || \
((GROUP) == NVIC_PriorityGroup_3) || \ ((GROUP) == NVIC_PriorityGroup_3) || \
((GROUP) == NVIC_PriorityGroup_4)) ((GROUP) == NVIC_PriorityGroup_4))
#define IS_NVIC_PREEMPTION_PRIORITY(PRIORITY) ((PRIORITY) < 0x10) #define IS_NVIC_PREEMPTION_PRIORITY(PRIORITY) ((PRIORITY) < 0x10)
#define IS_NVIC_SUB_PRIORITY(PRIORITY) ((PRIORITY) < 0x10) #define IS_NVIC_SUB_PRIORITY(PRIORITY) ((PRIORITY) < 0x10)
#define IS_NVIC_OFFSET(OFFSET) ((OFFSET) < 0x000FFFFF) #define IS_NVIC_OFFSET(OFFSET) ((OFFSET) < 0x000FFFFF)
/** /**
* @} * @}
*/ */
/** @defgroup MISC_SysTick_clock_source /** @defgroup MISC_SysTick_clock_source
* @{ * @{
*/ */
#define SysTick_CLKSource_HCLK_Div8 ((uint32_t)0xFFFFFFFB) #define SysTick_CLKSource_HCLK_Div8 ((uint32_t)0xFFFFFFFB)
#define SysTick_CLKSource_HCLK ((uint32_t)0x00000004) #define SysTick_CLKSource_HCLK ((uint32_t)0x00000004)
#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \ #define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \
((SOURCE) == SysTick_CLKSource_HCLK_Div8)) ((SOURCE) == SysTick_CLKSource_HCLK_Div8))
/** /**
* @} * @}
*/ */
/** /**
* @} * @}
*/ */
/* Exported macro ------------------------------------------------------------*/ /* Exported macro ------------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/ /* Exported functions --------------------------------------------------------*/
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup); void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct); void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset); void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);
void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState); void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource); void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* __MISC_H */ #endif /* __MISC_H */
/** /**
* @} * @}
*/ */
/** /**
* @} * @}
*/ */
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

View File

@ -1,177 +1,177 @@
/** /**
****************************************************************************** ******************************************************************************
* @file stm32f4xx_exti.h * @file stm32f4xx_exti.h
* @author MCD Application Team * @author MCD Application Team
* @version V1.0.0 * @version V1.0.0
* @date 30-September-2011 * @date 30-September-2011
* @brief This file contains all the functions prototypes for the EXTI firmware * @brief This file contains all the functions prototypes for the EXTI firmware
* library. * library.
****************************************************************************** ******************************************************************************
* @attention * @attention
* *
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
* *
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2> * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
****************************************************************************** ******************************************************************************
*/ */
/* Define to prevent recursive inclusion -------------------------------------*/ /* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F4xx_EXTI_H #ifndef __STM32F4xx_EXTI_H
#define __STM32F4xx_EXTI_H #define __STM32F4xx_EXTI_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* Includes ------------------------------------------------------------------*/ /* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h" #include "stm32f4xx.h"
/** @addtogroup STM32F4xx_StdPeriph_Driver /** @addtogroup STM32F4xx_StdPeriph_Driver
* @{ * @{
*/ */
/** @addtogroup EXTI /** @addtogroup EXTI
* @{ * @{
*/ */
/* Exported types ------------------------------------------------------------*/ /* Exported types ------------------------------------------------------------*/
/** /**
* @brief EXTI mode enumeration * @brief EXTI mode enumeration
*/ */
typedef enum typedef enum
{ {
EXTI_Mode_Interrupt = 0x00, EXTI_Mode_Interrupt = 0x00,
EXTI_Mode_Event = 0x04 EXTI_Mode_Event = 0x04
}EXTIMode_TypeDef; }EXTIMode_TypeDef;
#define IS_EXTI_MODE(MODE) (((MODE) == EXTI_Mode_Interrupt) || ((MODE) == EXTI_Mode_Event)) #define IS_EXTI_MODE(MODE) (((MODE) == EXTI_Mode_Interrupt) || ((MODE) == EXTI_Mode_Event))
/** /**
* @brief EXTI Trigger enumeration * @brief EXTI Trigger enumeration
*/ */
typedef enum typedef enum
{ {
EXTI_Trigger_Rising = 0x08, EXTI_Trigger_Rising = 0x08,
EXTI_Trigger_Falling = 0x0C, EXTI_Trigger_Falling = 0x0C,
EXTI_Trigger_Rising_Falling = 0x10 EXTI_Trigger_Rising_Falling = 0x10
}EXTITrigger_TypeDef; }EXTITrigger_TypeDef;
#define IS_EXTI_TRIGGER(TRIGGER) (((TRIGGER) == EXTI_Trigger_Rising) || \ #define IS_EXTI_TRIGGER(TRIGGER) (((TRIGGER) == EXTI_Trigger_Rising) || \
((TRIGGER) == EXTI_Trigger_Falling) || \ ((TRIGGER) == EXTI_Trigger_Falling) || \
((TRIGGER) == EXTI_Trigger_Rising_Falling)) ((TRIGGER) == EXTI_Trigger_Rising_Falling))
/** /**
* @brief EXTI Init Structure definition * @brief EXTI Init Structure definition
*/ */
typedef struct typedef struct
{ {
uint32_t EXTI_Line; /*!< Specifies the EXTI lines to be enabled or disabled. uint32_t EXTI_Line; /*!< Specifies the EXTI lines to be enabled or disabled.
This parameter can be any combination value of @ref EXTI_Lines */ This parameter can be any combination value of @ref EXTI_Lines */
EXTIMode_TypeDef EXTI_Mode; /*!< Specifies the mode for the EXTI lines. EXTIMode_TypeDef EXTI_Mode; /*!< Specifies the mode for the EXTI lines.
This parameter can be a value of @ref EXTIMode_TypeDef */ This parameter can be a value of @ref EXTIMode_TypeDef */
EXTITrigger_TypeDef EXTI_Trigger; /*!< Specifies the trigger signal active edge for the EXTI lines. EXTITrigger_TypeDef EXTI_Trigger; /*!< Specifies the trigger signal active edge for the EXTI lines.
This parameter can be a value of @ref EXTITrigger_TypeDef */ This parameter can be a value of @ref EXTITrigger_TypeDef */
FunctionalState EXTI_LineCmd; /*!< Specifies the new state of the selected EXTI lines. FunctionalState EXTI_LineCmd; /*!< Specifies the new state of the selected EXTI lines.
This parameter can be set either to ENABLE or DISABLE */ This parameter can be set either to ENABLE or DISABLE */
}EXTI_InitTypeDef; }EXTI_InitTypeDef;
/* Exported constants --------------------------------------------------------*/ /* Exported constants --------------------------------------------------------*/
/** @defgroup EXTI_Exported_Constants /** @defgroup EXTI_Exported_Constants
* @{ * @{
*/ */
/** @defgroup EXTI_Lines /** @defgroup EXTI_Lines
* @{ * @{
*/ */
#define EXTI_Line0 ((uint32_t)0x00001) /*!< External interrupt line 0 */ #define EXTI_Line0 ((uint32_t)0x00001) /*!< External interrupt line 0 */
#define EXTI_Line1 ((uint32_t)0x00002) /*!< External interrupt line 1 */ #define EXTI_Line1 ((uint32_t)0x00002) /*!< External interrupt line 1 */
#define EXTI_Line2 ((uint32_t)0x00004) /*!< External interrupt line 2 */ #define EXTI_Line2 ((uint32_t)0x00004) /*!< External interrupt line 2 */
#define EXTI_Line3 ((uint32_t)0x00008) /*!< External interrupt line 3 */ #define EXTI_Line3 ((uint32_t)0x00008) /*!< External interrupt line 3 */
#define EXTI_Line4 ((uint32_t)0x00010) /*!< External interrupt line 4 */ #define EXTI_Line4 ((uint32_t)0x00010) /*!< External interrupt line 4 */
#define EXTI_Line5 ((uint32_t)0x00020) /*!< External interrupt line 5 */ #define EXTI_Line5 ((uint32_t)0x00020) /*!< External interrupt line 5 */
#define EXTI_Line6 ((uint32_t)0x00040) /*!< External interrupt line 6 */ #define EXTI_Line6 ((uint32_t)0x00040) /*!< External interrupt line 6 */
#define EXTI_Line7 ((uint32_t)0x00080) /*!< External interrupt line 7 */ #define EXTI_Line7 ((uint32_t)0x00080) /*!< External interrupt line 7 */
#define EXTI_Line8 ((uint32_t)0x00100) /*!< External interrupt line 8 */ #define EXTI_Line8 ((uint32_t)0x00100) /*!< External interrupt line 8 */
#define EXTI_Line9 ((uint32_t)0x00200) /*!< External interrupt line 9 */ #define EXTI_Line9 ((uint32_t)0x00200) /*!< External interrupt line 9 */
#define EXTI_Line10 ((uint32_t)0x00400) /*!< External interrupt line 10 */ #define EXTI_Line10 ((uint32_t)0x00400) /*!< External interrupt line 10 */
#define EXTI_Line11 ((uint32_t)0x00800) /*!< External interrupt line 11 */ #define EXTI_Line11 ((uint32_t)0x00800) /*!< External interrupt line 11 */
#define EXTI_Line12 ((uint32_t)0x01000) /*!< External interrupt line 12 */ #define EXTI_Line12 ((uint32_t)0x01000) /*!< External interrupt line 12 */
#define EXTI_Line13 ((uint32_t)0x02000) /*!< External interrupt line 13 */ #define EXTI_Line13 ((uint32_t)0x02000) /*!< External interrupt line 13 */
#define EXTI_Line14 ((uint32_t)0x04000) /*!< External interrupt line 14 */ #define EXTI_Line14 ((uint32_t)0x04000) /*!< External interrupt line 14 */
#define EXTI_Line15 ((uint32_t)0x08000) /*!< External interrupt line 15 */ #define EXTI_Line15 ((uint32_t)0x08000) /*!< External interrupt line 15 */
#define EXTI_Line16 ((uint32_t)0x10000) /*!< External interrupt line 16 Connected to the PVD Output */ #define EXTI_Line16 ((uint32_t)0x10000) /*!< External interrupt line 16 Connected to the PVD Output */
#define EXTI_Line17 ((uint32_t)0x20000) /*!< External interrupt line 17 Connected to the RTC Alarm event */ #define EXTI_Line17 ((uint32_t)0x20000) /*!< External interrupt line 17 Connected to the RTC Alarm event */
#define EXTI_Line18 ((uint32_t)0x40000) /*!< External interrupt line 18 Connected to the USB OTG FS Wakeup from suspend event */ #define EXTI_Line18 ((uint32_t)0x40000) /*!< External interrupt line 18 Connected to the USB OTG FS Wakeup from suspend event */
#define EXTI_Line19 ((uint32_t)0x80000) /*!< External interrupt line 19 Connected to the Ethernet Wakeup event */ #define EXTI_Line19 ((uint32_t)0x80000) /*!< External interrupt line 19 Connected to the Ethernet Wakeup event */
#define EXTI_Line20 ((uint32_t)0x00100000) /*!< External interrupt line 20 Connected to the USB OTG HS (configured in FS) Wakeup event */ #define EXTI_Line20 ((uint32_t)0x00100000) /*!< External interrupt line 20 Connected to the USB OTG HS (configured in FS) Wakeup event */
#define EXTI_Line21 ((uint32_t)0x00200000) /*!< External interrupt line 21 Connected to the RTC Tamper and Time Stamp events */ #define EXTI_Line21 ((uint32_t)0x00200000) /*!< External interrupt line 21 Connected to the RTC Tamper and Time Stamp events */
#define EXTI_Line22 ((uint32_t)0x00400000) /*!< External interrupt line 22 Connected to the RTC Wakeup event */ #define EXTI_Line22 ((uint32_t)0x00400000) /*!< External interrupt line 22 Connected to the RTC Wakeup event */
#define IS_EXTI_LINE(LINE) ((((LINE) & (uint32_t)0xFF800000) == 0x00) && ((LINE) != (uint16_t)0x00)) #define IS_EXTI_LINE(LINE) ((((LINE) & (uint32_t)0xFF800000) == 0x00) && ((LINE) != (uint16_t)0x00))
#define IS_GET_EXTI_LINE(LINE) (((LINE) == EXTI_Line0) || ((LINE) == EXTI_Line1) || \ #define IS_GET_EXTI_LINE(LINE) (((LINE) == EXTI_Line0) || ((LINE) == EXTI_Line1) || \
((LINE) == EXTI_Line2) || ((LINE) == EXTI_Line3) || \ ((LINE) == EXTI_Line2) || ((LINE) == EXTI_Line3) || \
((LINE) == EXTI_Line4) || ((LINE) == EXTI_Line5) || \ ((LINE) == EXTI_Line4) || ((LINE) == EXTI_Line5) || \
((LINE) == EXTI_Line6) || ((LINE) == EXTI_Line7) || \ ((LINE) == EXTI_Line6) || ((LINE) == EXTI_Line7) || \
((LINE) == EXTI_Line8) || ((LINE) == EXTI_Line9) || \ ((LINE) == EXTI_Line8) || ((LINE) == EXTI_Line9) || \
((LINE) == EXTI_Line10) || ((LINE) == EXTI_Line11) || \ ((LINE) == EXTI_Line10) || ((LINE) == EXTI_Line11) || \
((LINE) == EXTI_Line12) || ((LINE) == EXTI_Line13) || \ ((LINE) == EXTI_Line12) || ((LINE) == EXTI_Line13) || \
((LINE) == EXTI_Line14) || ((LINE) == EXTI_Line15) || \ ((LINE) == EXTI_Line14) || ((LINE) == EXTI_Line15) || \
((LINE) == EXTI_Line16) || ((LINE) == EXTI_Line17) || \ ((LINE) == EXTI_Line16) || ((LINE) == EXTI_Line17) || \
((LINE) == EXTI_Line18) || ((LINE) == EXTI_Line19) || \ ((LINE) == EXTI_Line18) || ((LINE) == EXTI_Line19) || \
((LINE) == EXTI_Line20) || ((LINE) == EXTI_Line21) ||\ ((LINE) == EXTI_Line20) || ((LINE) == EXTI_Line21) ||\
((LINE) == EXTI_Line22)) ((LINE) == EXTI_Line22))
/** /**
* @} * @}
*/ */
/** /**
* @} * @}
*/ */
/* Exported macro ------------------------------------------------------------*/ /* Exported macro ------------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/ /* Exported functions --------------------------------------------------------*/
/* Function used to set the EXTI configuration to the default reset state *****/ /* Function used to set the EXTI configuration to the default reset state *****/
void EXTI_DeInit(void); void EXTI_DeInit(void);
/* Initialization and Configuration functions *********************************/ /* Initialization and Configuration functions *********************************/
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct); void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);
void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct); void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);
void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line); void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);
/* Interrupts and flags management functions **********************************/ /* Interrupts and flags management functions **********************************/
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line); FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);
void EXTI_ClearFlag(uint32_t EXTI_Line); void EXTI_ClearFlag(uint32_t EXTI_Line);
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line); ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
void EXTI_ClearITPendingBit(uint32_t EXTI_Line); void EXTI_ClearITPendingBit(uint32_t EXTI_Line);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* __STM32F4xx_EXTI_H */ #endif /* __STM32F4xx_EXTI_H */
/** /**
* @} * @}
*/ */
/** /**
* @} * @}
*/ */
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

Some files were not shown because too many files have changed in this diff Show More