mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
drivers/at: Add at_urc_isr module to process URCs upon arrival
This commit is contained in:
parent
028c0d4b3c
commit
955efd85ff
@ -43,6 +43,14 @@ ifneq (,$(filter at,$(USEMODULE)))
|
||||
USEMODULE += fmt
|
||||
USEMODULE += isrpipe
|
||||
USEMODULE += isrpipe_read_timeout
|
||||
|
||||
_AT_ISR_MODULE := $(filter at_urc_isr_%,$(USEMODULE))
|
||||
ifneq (,$(_AT_ISR_MODULE))
|
||||
# pull in the correspondant event_thread_<priority> module
|
||||
USEMODULE += $(_AT_ISR_MODULE:at_urc_isr_%=event_thread_%)
|
||||
USEMODULE += at_urc
|
||||
USEMODULE += at_urc_isr
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter at24c%,$(USEMODULE)))
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "isrpipe.h"
|
||||
#include "isrpipe/read_timeout.h"
|
||||
#include "periph/uart.h"
|
||||
#include "event/thread.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
@ -22,39 +23,79 @@
|
||||
#define AT_PRINT_INCOMING (0)
|
||||
#endif
|
||||
|
||||
static void _isrpipe_write_one_wrapper(void *_isrpipe, uint8_t data)
|
||||
#if defined(MODULE_AT_URC_ISR_LOW)
|
||||
#define AT_EVENT_PRIO EVENT_PRIO_LOW
|
||||
#elif defined(MODULE_AT_URC_ISR_MEDIUM)
|
||||
#define AT_EVENT_PRIO EVENT_PRIO_MEDIUM
|
||||
#elif defined(MODULE_AT_URC_ISR_HIGH)
|
||||
#define AT_EVENT_PRIO EVENT_PRIO_HIGH
|
||||
#endif
|
||||
|
||||
#if defined(MODULE_AT_URC_ISR)
|
||||
static void _event_process_urc(event_t *_event)
|
||||
{
|
||||
isrpipe_write_one(_isrpipe, data);
|
||||
at_dev_t *dev = (at_dev_t *)container_of(_event, at_dev_t, event);
|
||||
at_process_urc(dev, 1000);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void _isrpipe_write_one_wrapper(void *_dev, uint8_t data)
|
||||
{
|
||||
at_dev_t *dev = (at_dev_t *) _dev;
|
||||
isrpipe_write_one(&dev->isrpipe, data);
|
||||
#if defined(MODULE_AT_URC_ISR)
|
||||
if (data == AT_RECV_EOL_2[0] && !dev->awaiting_response) {
|
||||
event_post(AT_EVENT_PRIO, &dev->event);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int at_dev_init(at_dev_t *dev, uart_t uart, uint32_t baudrate, char *buf, size_t bufsize)
|
||||
{
|
||||
dev->uart = uart;
|
||||
|
||||
#if IS_USED(MODULE_AT_URC_ISR)
|
||||
dev->awaiting_response = false;
|
||||
dev->event.handler = _event_process_urc;
|
||||
#endif
|
||||
|
||||
isrpipe_init(&dev->isrpipe, (uint8_t *)buf, bufsize);
|
||||
|
||||
return uart_init(uart, baudrate, _isrpipe_write_one_wrapper,
|
||||
&dev->isrpipe);
|
||||
dev);
|
||||
}
|
||||
|
||||
int at_expect_bytes(at_dev_t *dev, const char *bytes, uint32_t timeout)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
#if IS_USED(MODULE_AT_URC_ISR)
|
||||
dev->awaiting_response = true;
|
||||
#endif
|
||||
|
||||
while (*bytes) {
|
||||
char c;
|
||||
int res;
|
||||
if ((res = isrpipe_read_timeout(&dev->isrpipe, (uint8_t *)&c, 1, timeout)) == 1) {
|
||||
if (AT_PRINT_INCOMING) {
|
||||
print(&c, 1);
|
||||
}
|
||||
if (c != *bytes++) {
|
||||
return -1;
|
||||
res = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return res;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
res = 0;
|
||||
|
||||
return 0;
|
||||
out:
|
||||
#if IS_USED(MODULE_AT_URC_ISR)
|
||||
dev->awaiting_response = false;
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void at_send_bytes(at_dev_t *dev, const char *bytes, size_t len)
|
||||
@ -66,6 +107,10 @@ ssize_t at_recv_bytes(at_dev_t *dev, char *bytes, size_t len, uint32_t timeout)
|
||||
{
|
||||
char *resp_pos = bytes;
|
||||
|
||||
#if IS_USED(MODULE_AT_URC_ISR)
|
||||
dev->awaiting_response = true;
|
||||
#endif
|
||||
|
||||
while (len) {
|
||||
int read_res;
|
||||
if ((read_res = isrpipe_read_timeout(&dev->isrpipe, (uint8_t *)resp_pos,
|
||||
@ -78,6 +123,10 @@ ssize_t at_recv_bytes(at_dev_t *dev, char *bytes, size_t len, uint32_t timeout)
|
||||
}
|
||||
}
|
||||
|
||||
#if IS_USED(MODULE_AT_URC_ISR)
|
||||
dev->awaiting_response = false;
|
||||
#endif
|
||||
|
||||
return (resp_pos - bytes);
|
||||
}
|
||||
|
||||
@ -86,9 +135,13 @@ int at_recv_bytes_until_string(at_dev_t *dev, const char *string,
|
||||
{
|
||||
size_t len = 0;
|
||||
char *_string = (char *)string;
|
||||
int res = 0;
|
||||
|
||||
#if IS_USED(MODULE_AT_URC_ISR)
|
||||
dev->awaiting_response = true;
|
||||
#endif
|
||||
|
||||
while (*_string && len < *bytes_len) {
|
||||
int res;
|
||||
char c;
|
||||
if ((res = isrpipe_read_timeout(&dev->isrpipe, (uint8_t *)&c, 1, timeout)) == 1) {
|
||||
if (AT_PRINT_INCOMING) {
|
||||
@ -101,12 +154,16 @@ int at_recv_bytes_until_string(at_dev_t *dev, const char *string,
|
||||
len++;
|
||||
}
|
||||
else {
|
||||
*bytes_len = len;
|
||||
return res;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*bytes_len = len;
|
||||
return 0;
|
||||
|
||||
#if IS_USED(MODULE_AT_URC_ISR)
|
||||
dev->awaiting_response = false;
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int at_send_cmd(at_dev_t *dev, const char *command, uint32_t timeout)
|
||||
@ -134,10 +191,18 @@ void at_drain(at_dev_t *dev)
|
||||
uint8_t _tmp[16];
|
||||
int res;
|
||||
|
||||
#if IS_USED(MODULE_AT_URC_ISR)
|
||||
dev->awaiting_response = true;
|
||||
#endif
|
||||
|
||||
do {
|
||||
/* consider no character within 10ms "drained" */
|
||||
res = isrpipe_read_timeout(&dev->isrpipe, _tmp, sizeof(_tmp), 10000U);
|
||||
} while (res > 0);
|
||||
|
||||
#if IS_USED(MODULE_AT_URC_ISR)
|
||||
dev->awaiting_response = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
ssize_t at_send_cmd_get_resp(at_dev_t *dev, const char *command,
|
||||
@ -285,6 +350,10 @@ ssize_t at_readline(at_dev_t *dev, char *resp_buf, size_t len, bool keep_eol, ui
|
||||
ssize_t res = -1;
|
||||
char *resp_pos = resp_buf;
|
||||
|
||||
#if IS_USED(MODULE_AT_URC_ISR)
|
||||
dev->awaiting_response = true;
|
||||
#endif
|
||||
|
||||
memset(resp_buf, 0, len);
|
||||
|
||||
while (len) {
|
||||
@ -315,6 +384,10 @@ ssize_t at_readline(at_dev_t *dev, char *resp_buf, size_t len, bool keep_eol, ui
|
||||
}
|
||||
|
||||
out:
|
||||
#if IS_USED(MODULE_AT_URC_ISR)
|
||||
dev->awaiting_response = false;
|
||||
#endif
|
||||
|
||||
if (res < 0) {
|
||||
*resp_buf = '\0';
|
||||
}
|
||||
|
@ -22,6 +22,28 @@
|
||||
*
|
||||
* As a debugging aid, when compiled with "-DAT_PRINT_INCOMING=1", every input
|
||||
* byte gets printed.
|
||||
*
|
||||
* ## Unsolicited Result Codes (URC) ##
|
||||
* An unsolicited result code is a string message that is not triggered as a
|
||||
* information text response to a previous AT command and can be output at any
|
||||
* time to inform a specific event or status change.
|
||||
*
|
||||
* The module provides a basic URC handling by adding the `at_urc` module to the
|
||||
* application. This allows to @ref at_add_urc "register" and
|
||||
* @ref at_remove_urc "de-register" URC strings to check. Later,
|
||||
* @ref at_process_urc can be called to check if any of the registered URCs have
|
||||
* been detected. If a registered URC has been detected the correspondant
|
||||
* @ref at_urc_t::cb "callback function" is called. The mode of operation
|
||||
* requires that the user of the module processes periodically the URCs.
|
||||
*
|
||||
* Alternatively, one of the `at_urc_isr_<priority>` modules can be included.
|
||||
* `priority` can be one of `low`, `medium` or `highest`, which correspond to
|
||||
* the priority of the thread that processes the URCs. For more information on
|
||||
* the priorities check the @ref sys_event module. This will extend the
|
||||
* functionality of `at_urc` by processing the URCs when the @ref AT_RECV_EOL_2
|
||||
* character is detected and there is no pending response. This works by posting
|
||||
* an @ref sys_event "event" to an event thread that processes the URCs.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
@ -42,6 +64,8 @@
|
||||
#include "clist.h"
|
||||
#include "kernel_defines.h"
|
||||
|
||||
#include "event.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -169,6 +193,10 @@ typedef struct {
|
||||
uart_t uart; /**< UART device where the AT device is attached */
|
||||
#ifdef MODULE_AT_URC
|
||||
clist_node_t urc_list; /**< list to keep track of all registered urc's */
|
||||
#ifdef MODULE_AT_URC_ISR
|
||||
bool awaiting_response; /**< indicates if the driver waits for a response */
|
||||
event_t event; /**< event posted from ISR to process urc's */
|
||||
#endif
|
||||
#endif
|
||||
} at_dev_t;
|
||||
|
||||
|
@ -1,4 +1,8 @@
|
||||
PSEUDOMODULES += at_urc
|
||||
PSEUDOMODULES += at_urc_isr
|
||||
PSEUDOMODULES += at_urc_isr_low
|
||||
PSEUDOMODULES += at_urc_isr_medium
|
||||
PSEUDOMODULES += at_urc_isr_highest
|
||||
PSEUDOMODULES += at24c%
|
||||
PSEUDOMODULES += base64url
|
||||
PSEUDOMODULES += can_mbox
|
||||
|
@ -2,6 +2,9 @@ include ../Makefile.tests_common
|
||||
|
||||
USEMODULE += shell
|
||||
USEMODULE += at
|
||||
USEMODULE += at_urc
|
||||
USEMODULE += at_urc_isr_medium
|
||||
|
||||
# we are printing from the event thread, we need more stack
|
||||
CFLAGS += -DEVENT_THREAD_MEDIUM_STACKSIZE=1024
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
||||
|
Loading…
Reference in New Issue
Block a user