Skip to content

Commit 559abd3

Browse files
author
Ari Parkkila
committed
Cellular: AT requests are to be processed within time period
1 parent 98ef516 commit 559abd3

File tree

2 files changed

+75
-78
lines changed

2 files changed

+75
-78
lines changed

features/cellular/framework/AT/ATHandler.cpp

Lines changed: 70 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@
1515
* limitations under the License.
1616
*/
1717

18+
#include <ctype.h>
19+
#include <stdio.h>
1820
#include "ATHandler.h"
1921
#include "mbed_poll.h"
2022
#include "FileHandle.h"
21-
#include "Timer.h"
2223
#include "mbed_wait_api.h"
2324
#include "mbed_debug.h"
2425
#ifdef MBED_CONF_RTOS_PRESENT
@@ -31,7 +32,6 @@ using namespace mbed;
3132
using namespace events;
3233
using namespace mbed_cellular_util;
3334

34-
//#define MBED_TRACE_MAX_LEVEL TRACE_LEVEL_DEBUG
3535
#include "CellularLog.h"
3636

3737
#if MBED_CONF_MBED_TRACE_ENABLE
@@ -40,6 +40,9 @@ using namespace mbed_cellular_util;
4040
#define at_debug(...)
4141
#endif
4242

43+
// URCs should be handled fast, if you add debug traces within URC processing then you also need to increase this time
44+
#define PROCESS_URC_TIME 20
45+
4346
const char *mbed::OK = "OK\r\n";
4447
const uint8_t OK_LENGTH = 4;
4548
const char *mbed::CRLF = "\r\n";
@@ -63,6 +66,7 @@ static const uint8_t map_3gpp_errors[][2] = {
6366

6467
ATHandler::ATHandler(FileHandle *fh, EventQueue &queue, int timeout, const char *output_delimiter, uint16_t send_delay) :
6568
_nextATHandler(0),
69+
_fileHandle(fh),
6670
_queue(queue),
6771
_last_err(NSAPI_ERROR_OK),
6872
_last_3gpp_error(0),
@@ -82,7 +86,8 @@ ATHandler::ATHandler(FileHandle *fh, EventQueue &queue, int timeout, const char
8286
_error_found(false),
8387
_max_resp_length(MAX_RESP_LENGTH),
8488
_debug_on(false),
85-
_cmd_start(false)
89+
_cmd_start(false),
90+
_start_time(0)
8691
{
8792
//enable_debug(true);
8893

@@ -108,7 +113,9 @@ ATHandler::ATHandler(FileHandle *fh, EventQueue &queue, int timeout, const char
108113
set_tag(&_info_stop, CRLF);
109114
set_tag(&_elem_stop, ")");
110115

111-
set_file_handle(fh);
116+
_fileHandle->set_blocking(false);
117+
118+
set_filehandle_sigio();
112119
}
113120

114121
void ATHandler::enable_debug(bool enable)
@@ -150,20 +157,7 @@ FileHandle *ATHandler::get_file_handle()
150157

151158
void ATHandler::set_file_handle(FileHandle *fh)
152159
{
153-
_fh_sigio_set = false;
154160
_fileHandle = fh;
155-
_fileHandle->set_blocking(false);
156-
set_filehandle_sigio();
157-
}
158-
159-
void ATHandler::set_filehandle_sigio()
160-
{
161-
if (_fh_sigio_set) {
162-
return;
163-
}
164-
165-
_fileHandle->sigio(mbed::Callback<void()>(this, &ATHandler::event));
166-
_fh_sigio_set = true;
167161
}
168162

169163
nsapi_error_t ATHandler::set_urc_handler(const char *prefix, mbed::Callback<void()> callback)
@@ -243,6 +237,7 @@ void ATHandler::lock()
243237
#endif
244238
_processing = true;
245239
clear_error();
240+
_start_time = rtos::Kernel::get_ms_count();
246241
}
247242

248243
void ATHandler::unlock()
@@ -287,31 +282,24 @@ void ATHandler::process_oob()
287282
tr_debug("process_oob %d", (_fileHandle->readable() || (_recv_pos < _recv_len)));
288283
if (_fileHandle->readable() || (_recv_pos < _recv_len)) {
289284
_current_scope = NotSet;
290-
Timer timer;
291-
timer.start();
292-
do {
285+
uint32_t timeout = _at_timeout;
286+
_at_timeout = PROCESS_URC_TIME;
287+
while (true) {
293288
if (match_urc()) {
294-
timer.reset();
295-
if (_fileHandle->readable() || (_recv_pos < _recv_len)) {
296-
continue;
289+
if (!(_fileHandle->readable() || (_recv_pos < _recv_len))) {
290+
break; // we have nothing to read anymore
297291
}
298-
break;
299-
}
300-
// If no match found, look for CRLF and consume everything up to CRLF
301-
if (mem_str(_recv_buff, _recv_len, CRLF, CRLF_LENGTH)) {
292+
_start_time = rtos::Kernel::get_ms_count(); // time to process next (potential) URC
293+
} else if (mem_str(_recv_buff, _recv_len, CRLF, CRLF_LENGTH)) {
294+
// If no match found, look for CRLF and consume everything up to CRLF
302295
consume_to_tag(CRLF, true);
303-
timer.reset();
304296
} else {
305-
if (_fileHandle->readable()) {
306-
timer.reset();
307-
fill_buffer();
308-
} else {
309-
#ifdef MBED_CONF_RTOS_PRESENT
310-
wait_ms(1);
311-
#endif
297+
if (!fill_buffer()) {
298+
break;
312299
}
313300
}
314-
} while (timer.read_ms() < 100); // URC's are very short
301+
}
302+
_at_timeout = timeout;
315303
}
316304
tr_debug("process_oob exit");
317305

@@ -320,6 +308,15 @@ void ATHandler::process_oob()
320308
unlock();
321309
}
322310

311+
void ATHandler::set_filehandle_sigio()
312+
{
313+
if (_fh_sigio_set) {
314+
return;
315+
}
316+
_fileHandle->sigio(mbed::Callback<void()>(this, &ATHandler::event));
317+
_fh_sigio_set = true;
318+
}
319+
323320
void ATHandler::reset_buffer()
324321
{
325322
tr_debug("%s", __func__);
@@ -338,48 +335,41 @@ void ATHandler::rewind_buffer()
338335
}
339336
}
340337

341-
// we are always expecting to receive something so there is wait timeout
342-
void ATHandler::fill_buffer()
338+
bool ATHandler::fill_buffer()
343339
{
344340
tr_debug("%s", __func__);
345341
// Reset buffer when full
346342
if (sizeof(_recv_buff) == _recv_len) {
347343
reset_buffer();
348344
}
349345

350-
Timer timer;
351-
timer.start();
352-
do {
353-
ssize_t len = _fileHandle->read(_recv_buff + _recv_len, sizeof(_recv_buff) - _recv_len);
354-
if (len > 0) {
355-
_recv_len += len;
356-
at_debug("\n----------readable----------: %d\n", _recv_len);
357-
for (size_t i = _recv_pos; i < _recv_len; i++) {
358-
at_debug("%c", _recv_buff[i]);
359-
}
360-
at_debug("\n----------readable----------\n");
361-
return;
362-
} else if (len != -EAGAIN && len != 0) {
363-
tr_warn("%s error: %d while reading", __func__, len);
364-
break;
346+
int timeout = (_start_time + _at_timeout) - rtos::Kernel::get_ms_count();
347+
if (timeout >= 0) {
348+
pollfh fhs;
349+
fhs.fh = _fileHandle;
350+
fhs.events = POLLIN;
351+
int count = poll(&fhs, 1, timeout);
352+
if (count > 0 && (fhs.revents & POLLIN)) {
353+
ssize_t len = _fileHandle->read(_recv_buff + _recv_len, sizeof(_recv_buff) - _recv_len);
354+
if (len > 0) {
355+
_recv_len += len;
356+
return true;
357+
}
365358
}
366-
#ifdef MBED_CONF_RTOS_PRESENT
367-
wait_ms(1);
368-
#endif
369-
} while ((uint32_t)timer.read_ms() < _at_timeout);
359+
}
370360

371361
set_error(NSAPI_ERROR_DEVICE_ERROR);
372-
tr_debug("AT TIMEOUT, scope: %d timeout: %lu", _current_scope, _at_timeout);
362+
363+
return false;
373364
}
374365

375366
int ATHandler::get_char()
376367
{
377368
if (_recv_pos == _recv_len) {
378369
tr_debug("%s", __func__);
379370
reset_buffer(); // try to read as much as possible
380-
fill_buffer();
381-
if (get_last_error()) {
382-
tr_debug("%s: -1", __func__);
371+
if (!fill_buffer()) {
372+
tr_warn("AT TIMEOUT");
383373
return -1; // timeout to read
384374
}
385375
}
@@ -792,7 +782,7 @@ void ATHandler::resp(const char *prefix, bool check_urc)
792782
if (!prefix && ((_recv_len-_recv_pos) >= _max_resp_length)) {
793783
return;
794784
}
795-
fill_buffer();
785+
(void)fill_buffer();
796786
}
797787
}
798788

@@ -810,7 +800,10 @@ void ATHandler::resp_start(const char *prefix, bool stop)
810800

811801
// Try get as much data as possible
812802
rewind_buffer();
813-
fill_buffer();
803+
if (!fill_buffer()) {
804+
tr_error("fill failed %s", prefix);
805+
return;
806+
}
814807

815808
if (prefix) {
816809
if ((strlen(prefix) < sizeof(_info_resp_prefix))) {
@@ -891,8 +884,11 @@ bool ATHandler::consume_char(char ch)
891884
{
892885
tr_debug("%s: %c", __func__, ch);
893886
int read_char = get_char();
887+
if (read_char == -1) {
888+
return false;
889+
}
894890
// If we read something else than ch, recover it
895-
if (read_char != ch && read_char != -1) {
891+
if (read_char != ch) {
896892
_recv_pos--;
897893
return false;
898894
}
@@ -1014,14 +1010,8 @@ void ATHandler::cmd_start(const char* cmd)
10141010
{
10151011

10161012
if (_at_send_delay) {
1017-
uint64_t current_time = rtos::Kernel::get_ms_count();
1018-
uint64_t time_difference = current_time - _last_response_stop;
1019-
1020-
if (time_difference < (uint64_t)_at_send_delay) {
1021-
wait_ms((uint64_t)_at_send_delay - time_difference);
1022-
tr_debug("AT wait %llu %llu", current_time, _last_response_stop);
1023-
}
1024-
}
1013+
rtos::Thread::wait_until(_last_response_stop + _at_send_delay);
1014+
}
10251015

10261016
at_debug("AT cmd %s (err %d)\n", cmd, _last_err);
10271017

@@ -1085,7 +1075,7 @@ void ATHandler::cmd_stop()
10851075
size_t ATHandler::write_bytes(const uint8_t *data, size_t len)
10861076
{
10871077
at_debug("AT write bytes %d (err %d)\n", len, _last_err);
1088-
1078+
10891079
if (_last_err != NSAPI_ERROR_OK) {
10901080
return 0;
10911081
}
@@ -1100,7 +1090,12 @@ size_t ATHandler::write(const void *data, size_t len)
11001090
fhs.events = POLLOUT;
11011091
size_t write_len = 0;
11021092
for (; write_len < len; ) {
1103-
int count = poll(&fhs, 1, _at_timeout);
1093+
int timeout = (_start_time + _at_timeout) - rtos::Kernel::get_ms_count();
1094+
if (timeout < 0) {
1095+
set_error(NSAPI_ERROR_DEVICE_ERROR);
1096+
return 0;
1097+
}
1098+
int count = poll(&fhs, 1, timeout);
11041099
if (count <= 0 || !(fhs.revents & POLLOUT)) {
11051100
set_error(NSAPI_ERROR_DEVICE_ERROR);
11061101
return 0;
@@ -1140,7 +1135,7 @@ void ATHandler::flush()
11401135
{
11411136
while (_fileHandle->readable()) {
11421137
reset_buffer();
1143-
fill_buffer();
1138+
(void) fill_buffer();
11441139
}
11451140
reset_buffer();
11461141
}

features/cellular/framework/AT/ATHandler.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
#define AT_HANDLER_H_
2020

2121
#include "platform/mbed_retarget.h"
22-
#include "stdio.h"
2322

2423
#include "EventQueue.h"
2524
#include "PlatformMutex.h"
@@ -421,6 +420,9 @@ class ATHandler
421420
bool _debug_on;
422421
bool _cmd_start;
423422

423+
// time when a command or an URC processing was started
424+
uint64_t _start_time;
425+
424426
// Gets char from receiving buffer.
425427
// Resets and fills the buffer if all are already read (receiving position equals receiving length).
426428
int get_char();
@@ -429,8 +431,8 @@ class ATHandler
429431
// Reading position set to 0 and buffer's unread content moved to beginning
430432
void rewind_buffer();
431433
// Reads from serial to receiving buffer.
432-
// Returns on first successful read OR on timeout.
433-
void fill_buffer();
434+
// Returns true on successful read OR false on timeout.
435+
bool fill_buffer();
434436

435437
void set_tag(tag_t* tag_dest, const char *tag_seq);
436438

0 commit comments

Comments
 (0)