Skip to content

Commit 1623b14

Browse files
authored
Merge pull request ARMmbed#12083 from AriParkkila/cell-bc95-congestion
Cellular: Add check for network congestion in BC95 driver
2 parents 789a193 + 6b37480 commit 1623b14

File tree

5 files changed

+80
-6
lines changed

5 files changed

+80
-6
lines changed

TESTS/netsocket/udp/udpsocket_echotest_burst.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,9 @@ void UDPSOCKET_ECHOTEST_BURST()
100100
if (check_oversized_packets(sent, tx_buffers[x].len)) {
101101
TEST_IGNORE_MESSAGE("This device does not handle oversized packets");
102102
}
103-
TEST_ASSERT_EQUAL(tx_buffers[x].len, sent);
103+
if (sent != NSAPI_ERROR_NO_MEMORY) {
104+
TEST_ASSERT_EQUAL(tx_buffers[x].len, sent);
105+
}
104106
}
105107

106108
bt_total = 0;

features/cellular/framework/AT/AT_CellularStack.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,10 @@ nsapi_error_t AT_CellularStack::socket_close(nsapi_socket_t handle)
233233
tr_info("Socket %d close (id %d, started %d, error %d)", index, sock_id, socket->started, err);
234234
}
235235

236+
_socket_mutex.lock();
236237
_socket[index] = NULL;
237238
delete socket;
239+
_socket_mutex.unlock();
238240

239241
_at.unlock();
240242

features/cellular/framework/AT/AT_CellularStack.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@ class AT_CellularStack : public NetworkStack {
114114
started(false),
115115
tx_ready(false),
116116
tls_socket(false),
117-
pending_bytes(0)
117+
pending_bytes(0),
118+
txfull_event(false)
118119
{
119120
}
120121
// Socket identifier, generally it will be the socket ID assigned by the
@@ -132,6 +133,7 @@ class AT_CellularStack : public NetworkStack {
132133
bool tx_ready; // socket is ready for sending on modem stack
133134
bool tls_socket; // socket uses modem's internal TLS socket functionality
134135
nsapi_size_t pending_bytes; // The number of received bytes pending
136+
bool txfull_event; // socket event after wouldblock
135137
};
136138

137139
/**
@@ -231,10 +233,10 @@ class AT_CellularStack : public NetworkStack {
231233

232234
int get_socket_index_by_port(uint16_t port);
233235

234-
// mutex for write/read to a _socket array, needed when multiple threads may open sockets simultaneously
236+
protected:
237+
// mutex for write/read to a _socket array, needed when multiple threads may use sockets simultaneously
235238
PlatformMutex _socket_mutex;
236239

237-
protected:
238240
ATHandler &_at;
239241

240242
AT_CellularDevice &_device;

features/cellular/framework/targets/QUECTEL/BC95/QUECTEL_BC95_CellularStack.cpp

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,39 @@
1515
* limitations under the License.
1616
*/
1717

18+
#include "rtos/ThisThread.h"
19+
#include "mbed_error.h"
20+
#include "platform/mbed_atomic.h"
21+
#include "events/EventQueue.h"
22+
#include "events/mbed_shared_queues.h"
23+
1824
#include "QUECTEL_BC95_CellularStack.h"
1925
#include "CellularUtil.h"
2026
#include "CellularLog.h"
2127

2228
#define PACKET_SIZE_MAX 1358
29+
#define TXFULL_EVENT_TIMEOUT (1 * 1000) // ms
30+
31+
#define AT_UPLINK_BUSY 159
32+
#define AT_UART_BUFFER_ERROR 536
33+
#define AT_BACK_OFF_TIMER 537
2334

2435
using namespace mbed;
2536
using namespace mbed_cellular_util;
2637

2738
QUECTEL_BC95_CellularStack::QUECTEL_BC95_CellularStack(ATHandler &atHandler, int cid, nsapi_ip_stack_t stack_type, AT_CellularDevice &device) :
28-
AT_CellularStack(atHandler, cid, stack_type, device)
39+
AT_CellularStack(atHandler, cid, stack_type, device), _event_queue(mbed_event_queue()), _txfull_event_id(0)
2940
{
3041
_at.set_urc_handler("+NSONMI:", mbed::Callback<void()>(this, &QUECTEL_BC95_CellularStack::urc_nsonmi));
3142
_at.set_urc_handler("+NSOCLI:", mbed::Callback<void()>(this, &QUECTEL_BC95_CellularStack::urc_nsocli));
3243
}
3344

3445
QUECTEL_BC95_CellularStack::~QUECTEL_BC95_CellularStack()
3546
{
47+
if (_txfull_event_id) {
48+
_event_queue->cancel(_txfull_event_id);
49+
}
50+
3651
_at.set_urc_handler("+NSONMI:", NULL);
3752
_at.set_urc_handler("+NSOCLI:", NULL);
3853
}
@@ -130,6 +145,9 @@ nsapi_error_t QUECTEL_BC95_CellularStack::socket_close_impl(int sock_id)
130145
if (sock && sock->closed) {
131146
return NSAPI_ERROR_OK;
132147
}
148+
149+
sock->txfull_event = false;
150+
133151
nsapi_error_t err = _at.at_cmd_discard("+NSOCL", "=", "%d", sock_id);
134152

135153
tr_info("Close socket: %d error: %d", sock_id, err);
@@ -186,6 +204,8 @@ nsapi_size_or_error_t QUECTEL_BC95_CellularStack::socket_sendto_impl(CellularSoc
186204
return NSAPI_ERROR_PARAMETER;
187205
}
188206

207+
int retry = 0;
208+
retry_send:
189209
if (socket->proto == NSAPI_UDP) {
190210
_at.cmd_start("AT+NSOST=");
191211
_at.write_int(socket->id);
@@ -212,6 +232,36 @@ nsapi_size_or_error_t QUECTEL_BC95_CellularStack::socket_sendto_impl(CellularSoc
212232
return sent_len;
213233
}
214234

235+
// check for network congestion
236+
device_err_t err = _at.get_last_device_error();
237+
if (err.errType == DeviceErrorTypeErrorCME &&
238+
(err.errCode == AT_UART_BUFFER_ERROR || err.errCode == AT_BACK_OFF_TIMER) || err.errCode == AT_UPLINK_BUSY) {
239+
if (socket->proto == NSAPI_UDP) {
240+
if (retry < 3) {
241+
retry++;
242+
tr_warn("Socket %d sendto EAGAIN", socket->id);
243+
rtos::ThisThread::sleep_for(30);
244+
_at.clear_error();
245+
goto retry_send;
246+
}
247+
return NSAPI_ERROR_NO_MEMORY;
248+
}
249+
_socket_mutex.lock();
250+
if (!socket->txfull_event && !_txfull_event_id) {
251+
tr_warn("socket %d tx full", socket->id);
252+
socket->txfull_event = true;
253+
_txfull_event_id = _event_queue->call_in(TXFULL_EVENT_TIMEOUT, callback(this, &QUECTEL_BC95_CellularStack::txfull_event_timeout));
254+
if (!_txfull_event_id) {
255+
MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER, MBED_ERROR_CODE_ENOMEM), \
256+
"QUECTEL_BC95_CellularStack::socket_sendto_impl(): unable to add event to queue. Increase \"events.shared-eventsize\"\n");
257+
_socket_mutex.unlock();
258+
return NSAPI_ERROR_NO_MEMORY;
259+
}
260+
}
261+
_socket_mutex.unlock();
262+
return NSAPI_ERROR_WOULD_BLOCK;
263+
}
264+
215265
return _at.get_last_error();
216266
}
217267

@@ -234,7 +284,7 @@ nsapi_size_or_error_t QUECTEL_BC95_CellularStack::socket_recvfrom_impl(CellularS
234284
_at.read_string(ip_address, sizeof(ip_address));
235285
port = _at.read_int();
236286
recv_len = _at.read_int();
237-
int hexlen = _at.read_hex_string((char *)buffer, size);
287+
int hexlen = _at.read_hex_string((char *)buffer, recv_len);
238288
// remaining length
239289
_at.skip_param();
240290
_at.resp_stop();
@@ -253,3 +303,17 @@ nsapi_size_or_error_t QUECTEL_BC95_CellularStack::socket_recvfrom_impl(CellularS
253303
}
254304
return recv_len;
255305
}
306+
307+
void QUECTEL_BC95_CellularStack::txfull_event_timeout()
308+
{
309+
_socket_mutex.lock();
310+
_txfull_event_id = 0;
311+
for (int i = 0; i < get_max_socket_count(); i++) {
312+
CellularSocket *sock = _socket[i];
313+
if (sock && sock->_cb && sock->txfull_event) {
314+
sock->txfull_event = false;
315+
sock->_cb(sock->_data);
316+
}
317+
}
318+
_socket_mutex.unlock();
319+
}

features/cellular/framework/targets/QUECTEL/BC95/QUECTEL_BC95_CellularStack.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ class QUECTEL_BC95_CellularStack : public AT_CellularStack {
5858
// URC handlers
5959
void urc_nsonmi();
6060
void urc_nsocli();
61+
62+
events::EventQueue *_event_queue;
63+
int _txfull_event_id;
64+
void txfull_event_timeout();
6165
};
6266
} // namespace mbed
6367
#endif /* QUECTEL_BC95_CELLULARSTACK_H_ */

0 commit comments

Comments
 (0)