drivers: at: many improvements

This commit is contained in:
Kaspar Schleiser 2017-08-28 11:01:07 +02:00
parent 7340e77328
commit 0199f36bb3
3 changed files with 64 additions and 44 deletions

View File

@ -22,8 +22,10 @@ ifneq (,$(filter apa102,$(USEMODULE)))
endif endif
ifneq (,$(filter at,$(USEMODULE))) ifneq (,$(filter at,$(USEMODULE)))
USEMODULE += fmt FEATURES_REQUIRED += periph_uart
USEMODULE += xtimer USEMODULE += fmt
USEMODULE += xtimer
USEMODULE += isrpipe
endif endif
ifneq (,$(filter at30tse75x,$(USEMODULE))) ifneq (,$(filter at30tse75x,$(USEMODULE)))

View File

@ -32,19 +32,18 @@ int at_dev_init(at_dev_t *dev, uart_t uart, uint32_t baudrate, char *buf, size_t
return 0; return 0;
} }
int at_expect_bytes(at_dev_t *dev, const char *bytes, size_t len, uint32_t timeout) int at_expect_bytes(at_dev_t *dev, const char *bytes, uint32_t timeout)
{ {
while (len) { while (*bytes) {
char c; char c;
int res; int res;
if ((res = isrpipe_read_timeout(&dev->isrpipe, &c, 1, timeout)) == 1) { if ((res = isrpipe_read_timeout(&dev->isrpipe, &c, 1, timeout)) == 1) {
if (AT_PRINT_INCOMING) { if (AT_PRINT_INCOMING) {
print(&c, 1); print(&c, 1);
} }
if (!(c == *bytes++)) { if (c != *bytes++) {
return -1; return -1;
} }
len--;
} }
else { else {
return res; return res;
@ -61,17 +60,19 @@ void at_send_bytes(at_dev_t *dev, const char *bytes, size_t len)
int at_send_cmd(at_dev_t *dev, const char *command, uint32_t timeout) int at_send_cmd(at_dev_t *dev, const char *command, uint32_t timeout)
{ {
unsigned cmdlen = strlen(command); size_t cmdlen = strlen(command);
uart_write(dev->uart, (const uint8_t *)command, cmdlen); uart_write(dev->uart, (const uint8_t *)command, cmdlen);
uart_write(dev->uart, (const uint8_t *)AT_END_OF_LINE, sizeof(AT_END_OF_LINE) - 1); uart_write(dev->uart, (const uint8_t *)AT_SEND_EOL, AT_SEND_EOL_LEN);
if (at_expect_bytes(dev, command, cmdlen, timeout)) { if (AT_SEND_ECHO) {
return -1; if (at_expect_bytes(dev, command, timeout)) {
} return -1;
}
if (at_expect_bytes(dev, AT_END_OF_LINE "\r\n", sizeof(AT_END_OF_LINE) + 1, timeout)) { if (at_expect_bytes(dev, AT_SEND_EOL "\r\n", timeout)) {
return -2; return -2;
}
} }
return 0; return 0;
@ -83,13 +84,15 @@ void at_drain(at_dev_t *dev)
int res; int res;
do { do {
/* consider no character within 10ms "drained" */
res = isrpipe_read_timeout(&dev->isrpipe, _tmp, sizeof(_tmp), 10000U); res = isrpipe_read_timeout(&dev->isrpipe, _tmp, sizeof(_tmp), 10000U);
} while (res > 0); } while (res > 0);
} }
ssize_t at_send_cmd_get_resp(at_dev_t *dev, const char *command, char *resp_buf, size_t len, uint32_t timeout) ssize_t at_send_cmd_get_resp(at_dev_t *dev, const char *command,
char *resp_buf, size_t len, uint32_t timeout)
{ {
ssize_t res = -1; ssize_t res;
at_drain(dev); at_drain(dev);
@ -108,9 +111,10 @@ out:
return res; return res;
} }
ssize_t at_send_cmd_get_lines(at_dev_t *dev, const char *command, char *resp_buf, size_t len, uint32_t timeout) ssize_t at_send_cmd_get_lines(at_dev_t *dev, const char *command,
char *resp_buf, size_t len, uint32_t timeout)
{ {
ssize_t res = -1; ssize_t res;
size_t bytes_left = len - 1; size_t bytes_left = len - 1;
char *pos = resp_buf; char *pos = resp_buf;
@ -123,7 +127,7 @@ ssize_t at_send_cmd_get_lines(at_dev_t *dev, const char *command, char *resp_buf
goto out; goto out;
} }
while(1) { while (1) {
res = at_readline(dev, pos, bytes_left, timeout); res = at_readline(dev, pos, bytes_left, timeout);
if (res == 0) { if (res == 0) {
continue; continue;
@ -140,6 +144,9 @@ ssize_t at_send_cmd_get_lines(at_dev_t *dev, const char *command, char *resp_buf
else if (strncmp(pos, "+CME ERROR:", 11) == 0) { else if (strncmp(pos, "+CME ERROR:", 11) == 0) {
return -1; return -1;
} }
else if (strncmp(pos, "+CMS ERROR:", 11) == 0) {
return -1;
}
else { else {
pos += res; pos += res;
if (bytes_left) { if (bytes_left) {
@ -167,17 +174,17 @@ int at_send_cmd_wait_prompt(at_dev_t *dev, const char *command, uint32_t timeout
at_drain(dev); at_drain(dev);
uart_write(dev->uart, (const uint8_t *)command, cmdlen); uart_write(dev->uart, (const uint8_t *)command, cmdlen);
uart_write(dev->uart, (const uint8_t *)AT_END_OF_LINE, sizeof(AT_END_OF_LINE) - 1); uart_write(dev->uart, (const uint8_t *)AT_SEND_EOL, AT_SEND_EOL_LEN);
if (at_expect_bytes(dev, command, cmdlen, timeout)) { if (at_expect_bytes(dev, command, timeout)) {
return -1; return -1;
} }
if (at_expect_bytes(dev, AT_END_OF_LINE "\n", sizeof(AT_END_OF_LINE), timeout)) { if (at_expect_bytes(dev, AT_SEND_EOL "\n", timeout)) {
return -2; return -2;
} }
if (at_expect_bytes(dev, ">", 1, timeout)) { if (at_expect_bytes(dev, ">", timeout)) {
return -3; return -3;
} }
@ -187,7 +194,7 @@ int at_send_cmd_wait_prompt(at_dev_t *dev, const char *command, uint32_t timeout
int at_send_cmd_wait_ok(at_dev_t *dev, const char *command, uint32_t timeout) int at_send_cmd_wait_ok(at_dev_t *dev, const char *command, uint32_t timeout)
{ {
int res; int res;
char resp_buf[32]; char resp_buf[64];
res = at_send_cmd_get_resp(dev, command, resp_buf, sizeof(resp_buf), timeout); res = at_send_cmd_get_resp(dev, command, resp_buf, sizeof(resp_buf), timeout);
if (res > 0) { if (res > 0) {
@ -234,5 +241,8 @@ ssize_t at_readline(at_dev_t *dev, char *resp_buf, size_t len, uint32_t timeout)
} }
out: out:
if (res < 0) {
*resp_buf = '\0';
}
return res; return res;
} }

View File

@ -16,7 +16,7 @@
* Most functions compare the bytes echoed by the device with what they * Most functions compare the bytes echoed by the device with what they
* intended to send, and bail out if there's no match. * intended to send, and bail out if there's no match.
* *
* Furthermore, the library tries to copy with difficulties regarding different * Furthermore, the library tries to cope with difficulties regarding different
* line endings. It usually sends "<command><CR>", but expects * line endings. It usually sends "<command><CR>", but expects
* "<command>\LF\CR" as echo. * "<command>\LF\CR" as echo.
* *
@ -34,6 +34,7 @@
#define AT_H #define AT_H
#include <stdint.h> #include <stdint.h>
#include <unistd.h>
#include "isrpipe.h" #include "isrpipe.h"
#include "periph/uart.h" #include "periph/uart.h"
@ -42,11 +43,19 @@
extern "C" { extern "C" {
#endif #endif
#ifndef AT_END_OF_LINE #ifndef AT_SEND_EOL
/** End of line character to send after the AT command */ /** End of line character to send after the AT command */
#define AT_END_OF_LINE "\r" #define AT_SEND_EOL "\r"
#endif #endif
#ifndef AT_SEND_ECHO
/** Enable/disable the expected echo after an AT command is sent */
#define AT_SEND_ECHO 1
#endif
/** Shortcut for getting send end of line length */
#define AT_SEND_EOL_LEN (sizeof(AT_SEND_EOL) - 1)
/** /**
* @brief AT device structure * @brief AT device structure
*/ */
@ -55,7 +64,6 @@ typedef struct {
uart_t uart; /**< UART device where the AT device is attached */ uart_t uart; /**< UART device where the AT device is attached */
} at_dev_t; } at_dev_t;
/** /**
* @brief Initialize AT device struct * @brief Initialize AT device struct
* *
@ -71,7 +79,7 @@ typedef struct {
int at_dev_init(at_dev_t *dev, uart_t uart, uint32_t baudrate, char *buf, size_t bufsize); int at_dev_init(at_dev_t *dev, uart_t uart, uint32_t baudrate, char *buf, size_t bufsize);
/** /**
* @brief simple command helper * @brief Simple command helper
* *
* This function sends an AT command to the device and waits for "OK". * This function sends an AT command to the device and waits for "OK".
* *
@ -85,10 +93,10 @@ int at_dev_init(at_dev_t *dev, uart_t uart, uint32_t baudrate, char *buf, size_t
int at_send_cmd_wait_ok(at_dev_t *dev, const char *command, uint32_t timeout); int at_send_cmd_wait_ok(at_dev_t *dev, const char *command, uint32_t timeout);
/** /**
* @brief send AT command, wait for a prompt * @brief Send AT command, wait for a prompt
* *
* This function will send the supplied @p command, then wait for the prompt (>) * This function sends the supplied @p command, then waits for the prompt (>)
* character and return * character and returns
* *
* @param[in] dev device to operate on * @param[in] dev device to operate on
* @param[in] command command string to send * @param[in] command command string to send
@ -100,9 +108,9 @@ int at_send_cmd_wait_ok(at_dev_t *dev, const char *command, uint32_t timeout);
int at_send_cmd_wait_prompt(at_dev_t *dev, const char *command, uint32_t timeout); int at_send_cmd_wait_prompt(at_dev_t *dev, const char *command, uint32_t timeout);
/** /**
* @brief send AT command, wait for response * @brief Send AT command, wait for response
* *
* This function will send the supplied @p command, then wait and return one * This function sends the supplied @p command, then waits and returns one
* line of response. * line of response.
* *
* A possible empty line will be skipped. * A possible empty line will be skipped.
@ -113,15 +121,15 @@ int at_send_cmd_wait_prompt(at_dev_t *dev, const char *command, uint32_t timeout
* @param[in] len len of @p buffer * @param[in] len len of @p buffer
* @param[in] timeout timeout (in usec) * @param[in] timeout timeout (in usec)
* *
* @returns lenght of response on success * @returns length of response on success
* @returns <0 on error * @returns <0 on error
*/ */
ssize_t at_send_cmd_get_resp(at_dev_t *dev, const char *command, char *resp_buf, size_t len, uint32_t timeout); ssize_t at_send_cmd_get_resp(at_dev_t *dev, const char *command, char *resp_buf, size_t len, uint32_t timeout);
/** /**
* @brief send AT command, wait for multiline response * @brief Send AT command, wait for multiline response
* *
* This function will send the supplied @p command, then return all response * This function sends the supplied @p command, then returns all response
* lines until the device sends "OK". * lines until the device sends "OK".
* *
* If a line starts with "ERROR" or "+CME ERROR:", or the buffer is full, the * If a line starts with "ERROR" or "+CME ERROR:", or the buffer is full, the
@ -133,7 +141,7 @@ ssize_t at_send_cmd_get_resp(at_dev_t *dev, const char *command, char *resp_buf,
* @param[in] len len of @p buffer * @param[in] len len of @p buffer
* @param[in] timeout timeout (in usec) * @param[in] timeout timeout (in usec)
* *
* @returns lenght of response on success * @returns length of response on success
* @returns <0 on error * @returns <0 on error
*/ */
ssize_t at_send_cmd_get_lines(at_dev_t *dev, const char *command, char *resp_buf, size_t len, uint32_t timeout); ssize_t at_send_cmd_get_lines(at_dev_t *dev, const char *command, char *resp_buf, size_t len, uint32_t timeout);
@ -142,17 +150,16 @@ ssize_t at_send_cmd_get_lines(at_dev_t *dev, const char *command, char *resp_buf
* @brief Expect bytes from device * @brief Expect bytes from device
* *
* @param[in] dev device to operate on * @param[in] dev device to operate on
* @param[in] bytes buffer containing bytes to expect * @param[in] bytes buffer containing bytes to expect (NULL-terminated)
* @param[in] len number of bytes to expect
* @param[in] timeout timeout (in usec) * @param[in] timeout timeout (in usec)
* *
* @returns 0 on success * @returns 0 on success
* @returns <0 otherwise * @returns <0 otherwise
*/ */
int at_expect_bytes(at_dev_t *dev, const char *bytes, size_t len, uint32_t timeout); int at_expect_bytes(at_dev_t *dev, const char *bytes, uint32_t timeout);
/** /**
* @brief Send raw bytes to a device * @brief Send raw bytes to a device
* *
* @param[in] dev device to operate on * @param[in] dev device to operate on
* @param[in] bytes buffer containing bytes to send * @param[in] bytes buffer containing bytes to send
@ -161,7 +168,7 @@ int at_expect_bytes(at_dev_t *dev, const char *bytes, size_t len, uint32_t timeo
void at_send_bytes(at_dev_t *dev, const char *bytes, size_t len); void at_send_bytes(at_dev_t *dev, const char *bytes, size_t len);
/** /**
* @brief send command to device * @brief Send command to device
* *
* @param[in] dev device to operate on * @param[in] dev device to operate on
* @param[in] command command to send * @param[in] command command to send
@ -173,7 +180,7 @@ void at_send_bytes(at_dev_t *dev, const char *bytes, size_t len);
int at_send_cmd(at_dev_t *dev, const char *command, uint32_t timeout); int at_send_cmd(at_dev_t *dev, const char *command, uint32_t timeout);
/** /**
* @brief read a line from device * @brief Read a line from device
* *
* @param[in] dev device to operate on * @param[in] dev device to operate on
* @param[in] resp_buf buffer to store line * @param[in] resp_buf buffer to store line
@ -186,7 +193,7 @@ int at_send_cmd(at_dev_t *dev, const char *command, uint32_t timeout);
ssize_t at_readline(at_dev_t *dev, char *resp_buf, size_t len, uint32_t timeout); ssize_t at_readline(at_dev_t *dev, char *resp_buf, size_t len, uint32_t timeout);
/** /**
* @brief drain device input buffer * @brief Drain device input buffer
* *
* This function drains any possible bytes waiting in the device's input * This function drains any possible bytes waiting in the device's input
* buffer. * buffer.
@ -200,3 +207,4 @@ void at_drain(at_dev_t *dev);
#endif #endif
#endif /* AT_H */ #endif /* AT_H */
/** @} */