15
15
* limitations under the License.
16
16
*/
17
17
18
+ #include < ctype.h>
19
+ #include < stdio.h>
18
20
#include " ATHandler.h"
19
21
#include " mbed_poll.h"
20
22
#include " FileHandle.h"
21
- #include " Timer.h"
22
23
#include " mbed_wait_api.h"
23
24
#include " mbed_debug.h"
24
25
#ifdef MBED_CONF_RTOS_PRESENT
@@ -31,7 +32,6 @@ using namespace mbed;
31
32
using namespace events ;
32
33
using namespace mbed_cellular_util ;
33
34
34
- // #define MBED_TRACE_MAX_LEVEL TRACE_LEVEL_DEBUG
35
35
#include " CellularLog.h"
36
36
37
37
#if MBED_CONF_MBED_TRACE_ENABLE
@@ -40,6 +40,9 @@ using namespace mbed_cellular_util;
40
40
#define at_debug (...)
41
41
#endif
42
42
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
+
43
46
const char *mbed::OK = " OK\r\n " ;
44
47
const uint8_t OK_LENGTH = 4 ;
45
48
const char *mbed::CRLF = " \r\n " ;
@@ -63,6 +66,7 @@ static const uint8_t map_3gpp_errors[][2] = {
63
66
64
67
ATHandler::ATHandler (FileHandle *fh, EventQueue &queue, int timeout, const char *output_delimiter, uint16_t send_delay) :
65
68
_nextATHandler(0 ),
69
+ _fileHandle(fh),
66
70
_queue(queue),
67
71
_last_err(NSAPI_ERROR_OK),
68
72
_last_3gpp_error(0 ),
@@ -82,7 +86,8 @@ ATHandler::ATHandler(FileHandle *fh, EventQueue &queue, int timeout, const char
82
86
_error_found(false ),
83
87
_max_resp_length(MAX_RESP_LENGTH),
84
88
_debug_on(false ),
85
- _cmd_start(false )
89
+ _cmd_start(false ),
90
+ _start_time(0 )
86
91
{
87
92
// enable_debug(true);
88
93
@@ -108,7 +113,9 @@ ATHandler::ATHandler(FileHandle *fh, EventQueue &queue, int timeout, const char
108
113
set_tag (&_info_stop, CRLF);
109
114
set_tag (&_elem_stop, " )" );
110
115
111
- set_file_handle (fh);
116
+ _fileHandle->set_blocking (false );
117
+
118
+ set_filehandle_sigio ();
112
119
}
113
120
114
121
void ATHandler::enable_debug (bool enable)
@@ -150,20 +157,7 @@ FileHandle *ATHandler::get_file_handle()
150
157
151
158
void ATHandler::set_file_handle (FileHandle *fh)
152
159
{
153
- _fh_sigio_set = false ;
154
160
_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 ;
167
161
}
168
162
169
163
nsapi_error_t ATHandler::set_urc_handler (const char *prefix, mbed::Callback<void ()> callback)
@@ -243,6 +237,7 @@ void ATHandler::lock()
243
237
#endif
244
238
_processing = true ;
245
239
clear_error ();
240
+ _start_time = rtos::Kernel::get_ms_count ();
246
241
}
247
242
248
243
void ATHandler::unlock ()
@@ -287,31 +282,24 @@ void ATHandler::process_oob()
287
282
tr_debug (" process_oob %d" , (_fileHandle->readable () || (_recv_pos < _recv_len)));
288
283
if (_fileHandle->readable () || (_recv_pos < _recv_len)) {
289
284
_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 ) {
293
288
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
297
291
}
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
302
295
consume_to_tag (CRLF, true );
303
- timer.reset ();
304
296
} 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 ;
312
299
}
313
300
}
314
- } while (timer.read_ms () < 100 ); // URC's are very short
301
+ }
302
+ _at_timeout = timeout;
315
303
}
316
304
tr_debug (" process_oob exit" );
317
305
@@ -320,6 +308,15 @@ void ATHandler::process_oob()
320
308
unlock ();
321
309
}
322
310
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
+
323
320
void ATHandler::reset_buffer ()
324
321
{
325
322
tr_debug (" %s" , __func__);
@@ -338,48 +335,41 @@ void ATHandler::rewind_buffer()
338
335
}
339
336
}
340
337
341
- // we are always expecting to receive something so there is wait timeout
342
- void ATHandler::fill_buffer ()
338
+ bool ATHandler::fill_buffer ()
343
339
{
344
340
tr_debug (" %s" , __func__);
345
341
// Reset buffer when full
346
342
if (sizeof (_recv_buff) == _recv_len) {
347
343
reset_buffer ();
348
344
}
349
345
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
+ }
365
358
}
366
- #ifdef MBED_CONF_RTOS_PRESENT
367
- wait_ms (1 );
368
- #endif
369
- } while ((uint32_t )timer.read_ms () < _at_timeout);
359
+ }
370
360
371
361
set_error (NSAPI_ERROR_DEVICE_ERROR);
372
- tr_debug (" AT TIMEOUT, scope: %d timeout: %lu" , _current_scope, _at_timeout);
362
+
363
+ return false ;
373
364
}
374
365
375
366
int ATHandler::get_char ()
376
367
{
377
368
if (_recv_pos == _recv_len) {
378
369
tr_debug (" %s" , __func__);
379
370
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" );
383
373
return -1 ; // timeout to read
384
374
}
385
375
}
@@ -792,7 +782,7 @@ void ATHandler::resp(const char *prefix, bool check_urc)
792
782
if (!prefix && ((_recv_len-_recv_pos) >= _max_resp_length)) {
793
783
return ;
794
784
}
795
- fill_buffer ();
785
+ ( void ) fill_buffer ();
796
786
}
797
787
}
798
788
@@ -810,7 +800,10 @@ void ATHandler::resp_start(const char *prefix, bool stop)
810
800
811
801
// Try get as much data as possible
812
802
rewind_buffer ();
813
- fill_buffer ();
803
+ if (!fill_buffer ()) {
804
+ tr_error (" fill failed %s" , prefix);
805
+ return ;
806
+ }
814
807
815
808
if (prefix) {
816
809
if ((strlen (prefix) < sizeof (_info_resp_prefix))) {
@@ -891,8 +884,11 @@ bool ATHandler::consume_char(char ch)
891
884
{
892
885
tr_debug (" %s: %c" , __func__, ch);
893
886
int read_char = get_char ();
887
+ if (read_char == -1 ) {
888
+ return false ;
889
+ }
894
890
// If we read something else than ch, recover it
895
- if (read_char != ch && read_char != - 1 ) {
891
+ if (read_char != ch) {
896
892
_recv_pos--;
897
893
return false ;
898
894
}
@@ -1014,14 +1010,8 @@ void ATHandler::cmd_start(const char* cmd)
1014
1010
{
1015
1011
1016
1012
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
+ }
1025
1015
1026
1016
at_debug (" AT cmd %s (err %d)\n " , cmd, _last_err);
1027
1017
@@ -1085,7 +1075,7 @@ void ATHandler::cmd_stop()
1085
1075
size_t ATHandler::write_bytes (const uint8_t *data, size_t len)
1086
1076
{
1087
1077
at_debug (" AT write bytes %d (err %d)\n " , len, _last_err);
1088
-
1078
+
1089
1079
if (_last_err != NSAPI_ERROR_OK) {
1090
1080
return 0 ;
1091
1081
}
@@ -1100,7 +1090,12 @@ size_t ATHandler::write(const void *data, size_t len)
1100
1090
fhs.events = POLLOUT;
1101
1091
size_t write_len = 0 ;
1102
1092
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);
1104
1099
if (count <= 0 || !(fhs.revents & POLLOUT)) {
1105
1100
set_error (NSAPI_ERROR_DEVICE_ERROR);
1106
1101
return 0 ;
@@ -1140,7 +1135,7 @@ void ATHandler::flush()
1140
1135
{
1141
1136
while (_fileHandle->readable ()) {
1142
1137
reset_buffer ();
1143
- fill_buffer ();
1138
+ ( void ) fill_buffer ();
1144
1139
}
1145
1140
reset_buffer ();
1146
1141
}
0 commit comments