Skip to content

Commit ec73c8a

Browse files
author
Teppo Järvelin
committed
Cellular: fix connect-disconnect sequence called many times
Fix syncing back to at mode after ppp disconnect. Fix AT_CellularContext flags and states to allow new connect after disconnect. Fix that state machine is not reseted in disconnect is it's running (might be running because of another context or new connect already started).
1 parent 7027eac commit ec73c8a

File tree

9 files changed

+93
-50
lines changed

9 files changed

+93
-50
lines changed

UNITTESTS/stubs/CellularDevice_stub.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,6 @@ nsapi_error_t CellularDevice::shutdown()
103103
return NSAPI_ERROR_OK;
104104
}
105105

106-
void CellularDevice::cellular_callback(nsapi_event_t ev, intptr_t ptr)
106+
void CellularDevice::cellular_callback(nsapi_event_t ev, intptr_t ptr, CellularContext *ctx)
107107
{
108108
}

features/cellular/framework/API/CellularContext.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ class CellularContext : public CellularInterface {
133133
* The parameters on the callback are the event type and event type dependent reason parameter.
134134
*
135135
* @remark deleting CellularDevice/CellularContext in callback is not allowed.
136+
* @remark Allocating/adding lots of traces not recommended as callback is called mostly from State machines thread which
137+
* is now 2048. You can change to main thread for example via EventQueue.
136138
*
137139
* @param status_cb The callback for status changes.
138140
*/

features/cellular/framework/API/CellularDevice.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,8 @@ class CellularDevice {
283283
* The parameters on the callback are the event type and event-type dependent reason parameter.
284284
*
285285
* @remark deleting CellularDevice/CellularContext in callback not allowed.
286-
* @remark application should not attach to this function if using CellularContext::attach as it will contain the
287-
* same information.
286+
* @remark Allocating/adding lots of traces not recommended as callback is called mostly from State machines thread which
287+
* is now 2048. You can change to main thread for example via EventQueue.
288288
*
289289
* @param status_cb The callback for status changes.
290290
*/
@@ -420,8 +420,8 @@ class CellularDevice {
420420
* This method will broadcast to every interested classes:
421421
* CellularContext (might be many) and CellularStateMachine if available.
422422
*/
423-
void cellular_callback(nsapi_event_t ev, intptr_t ptr);
424-
423+
void cellular_callback(nsapi_event_t ev, intptr_t ptr, CellularContext *ctx = NULL);
424+
void stm_callback(nsapi_event_t ev, intptr_t ptr);
425425
int _network_ref_count;
426426
int _sms_ref_count;
427427
int _info_ref_count;

features/cellular/framework/API/CellularNetwork.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,10 @@ class CellularNetwork {
319319
* on the network. The parameters on the callback are the event type and
320320
* event-type dependent reason parameter.
321321
*
322+
* @remark Application should not call attach if using CellularContext class. Call instead CellularContext::attach
323+
* as CellularDevice is dependent of this attach if CellularContext/CellularDevice is used to get
324+
* device/sim ready, registered, attached, connected.
325+
*
322326
* @param status_cb The callback for status changes
323327
*/
324328
virtual void attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb) = 0;

features/cellular/framework/AT/ATHandler.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,22 +1256,27 @@ void ATHandler::debug_print(const char *p, int len)
12561256
bool ATHandler::sync(int timeout_ms)
12571257
{
12581258
tr_debug("AT sync");
1259+
lock();
1260+
uint32_t timeout = _at_timeout;
1261+
_at_timeout = timeout_ms;
12591262
// poll for 10 seconds
12601263
for (int i = 0; i < 10; i++) {
1261-
lock();
1262-
set_at_timeout(timeout_ms, false);
12631264
// For sync use an AT command that is supported by all modems and likely not used frequently,
12641265
// especially a common response like OK could be response to previous request.
1266+
clear_error();
1267+
_start_time = rtos::Kernel::get_ms_count();
12651268
cmd_start("AT+CMEE?");
12661269
cmd_stop();
12671270
resp_start("+CMEE:");
12681271
resp_stop();
1269-
restore_at_timeout();
1270-
unlock();
12711272
if (!_last_err) {
1273+
_at_timeout = timeout;
1274+
unlock();
12721275
return true;
12731276
}
12741277
}
12751278
tr_error("AT sync failed");
1279+
_at_timeout = timeout;
1280+
unlock();
12761281
return false;
12771282
}

features/cellular/framework/AT/AT_CellularContext.cpp

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,6 @@ nsapi_error_t AT_CellularContext::activate_context()
498498
if (err != NSAPI_ERROR_OK) {
499499
_at.unlock();
500500
tr_error("Failed to activate network context! (%d)", err);
501-
call_network_cb(NSAPI_STATUS_DISCONNECTED);
502501
return err;
503502
}
504503

@@ -551,16 +550,18 @@ void AT_CellularContext::do_connect()
551550
{
552551
if (!_is_context_active) {
553552
_cb_data.error = do_activate_context();
553+
} else {
554+
_cb_data.error = NSAPI_ERROR_OK;
555+
}
556+
554557
#if !NSAPI_PPP_AVAILABLE
555-
// in PPP mode we did not activate any context, just searched the correct _cid
556-
if (_status_cb) {
557-
_status_cb((nsapi_event_t)CellularActivatePDPContext, (intptr_t)&_cb_data);
558-
}
559-
#endif // !NSAPI_PPP_AVAILABLE
558+
// in PPP mode we did not activate any context, just searched the correct _cid
559+
if (_status_cb) {
560+
_status_cb((nsapi_event_t)CellularActivatePDPContext, (intptr_t)&_cb_data);
560561
}
562+
#endif // !NSAPI_PPP_AVAILABLE
561563

562564
if (_cb_data.error != NSAPI_ERROR_OK) {
563-
call_network_cb(NSAPI_STATUS_DISCONNECTED);
564565
_is_connected = false;
565566
return;
566567
}
@@ -630,16 +631,23 @@ void AT_CellularContext::ppp_status_cb(nsapi_event_t ev, intptr_t ptr)
630631
tr_debug("ppp_status_cb: event %d, ptr %d", ev, ptr);
631632
if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_GLOBAL_UP) {
632633
_is_connected = true;
633-
} else if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_DISCONNECTED) {
634-
ppp_disconnected();
635634
} else {
636635
_is_connected = false;
637636
}
638637

639638
_connect_status = (nsapi_connection_status_t)ptr;
640639

640+
// catch all NSAPI_STATUS_DISCONNECTED events but send to device only when we did not ask for disconnect.
641+
if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_DISCONNECTED) {
642+
if (_is_connected) {
643+
ppp_disconnected();
644+
_device->cellular_callback(ev, ptr, this);
645+
}
646+
return;
647+
}
648+
641649
// call device's callback, it will broadcast this to here (cellular_callback)
642-
_device->cellular_callback(ev, ptr);
650+
_device->cellular_callback(ev, ptr, this);
643651
}
644652

645653
void AT_CellularContext::ppp_disconnected()
@@ -660,10 +668,13 @@ void AT_CellularContext::ppp_disconnected()
660668

661669
nsapi_error_t AT_CellularContext::disconnect()
662670
{
663-
tr_info("CellularContext disconnect");
671+
tr_info("CellularContext disconnect()");
664672
if (!_nw || !_is_connected) {
665673
return NSAPI_ERROR_NO_CONNECTION;
666674
}
675+
676+
// set false here so callbacks know that we are not connected and so should not send DISCONNECTED
677+
_is_connected = false;
667678
#if NSAPI_PPP_AVAILABLE
668679
nsapi_error_t err = nsapi_ppp_disconnect(_at.get_file_handle());
669680
if (err != NSAPI_ERROR_OK) {
@@ -681,11 +692,12 @@ nsapi_error_t AT_CellularContext::disconnect()
681692
} else {
682693
deactivate_ip_context();
683694
}
684-
} else {
685-
call_network_cb(NSAPI_STATUS_DISCONNECTED);
686695
}
696+
_is_context_active = false;
697+
_connect_status = NSAPI_STATUS_DISCONNECTED;
687698

688-
_is_connected = false;
699+
// call device's callback, it will broadcast this to here (cellular_callback)
700+
_device->cellular_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED, this);
689701

690702
return _at.unlock_return_error();
691703
}
@@ -928,27 +940,32 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
928940
if (_is_blocking) {
929941
if (data->error != NSAPI_ERROR_OK) {
930942
// operation failed, release semaphore
943+
_current_op = OP_INVALID;
931944
_semaphore.release();
932945
} else {
933946
if ((st == CellularDeviceReady && _current_op == OP_DEVICE_READY) ||
934947
(st == CellularSIMStatusChanged && _current_op == OP_SIM_READY &&
935948
data->status_data == CellularDevice::SimStateReady)) {
936949
// target reached, release semaphore
950+
_current_op = OP_INVALID;
937951
_semaphore.release();
938952
} else if (st == CellularRegistrationStatusChanged && (data->status_data == CellularNetwork::RegisteredHomeNetwork ||
939953
data->status_data == CellularNetwork::RegisteredRoaming || data->status_data == CellularNetwork::AlreadyRegistered) && _current_op == OP_REGISTER) {
940954
// target reached, release semaphore
955+
_current_op = OP_INVALID;
941956
_semaphore.release();
942957
} else if (st == CellularAttachNetwork && (_current_op == OP_ATTACH || _current_op == OP_CONNECT) &&
943958
data->status_data == CellularNetwork::Attached) {
944959
// target reached, release semaphore
960+
_current_op = OP_INVALID;
945961
_semaphore.release();
946962
}
947963
}
948964
} else {
949965
// non blocking
950966
if (st == CellularAttachNetwork && _current_op == OP_CONNECT && data->error == NSAPI_ERROR_OK &&
951967
data->status_data == CellularNetwork::Attached) {
968+
_current_op = OP_INVALID;
952969
// forward to application
953970
if (_status_cb) {
954971
_status_cb(ev, ptr);
@@ -963,14 +980,18 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
963980
if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_GLOBAL_UP) {
964981
tr_info("CellularContext IP %s", get_ip_address());
965982
_cb_data.error = NSAPI_ERROR_OK;
966-
_semaphore.release();
967983
} else if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_DISCONNECTED) {
968984
tr_info("PPP disconnected");
969985
_cb_data.error = NSAPI_ERROR_NO_CONNECTION;
970-
_semaphore.release();
971986
}
972987
}
973-
#endif
988+
#else
989+
#if MBED_CONF_MBED_TRACE_ENABLE
990+
if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_DISCONNECTED) {
991+
tr_info("cb: CellularContext disconnected");
992+
}
993+
#endif // MBED_CONF_MBED_TRACE_ENABLE
994+
#endif // NSAPI_PPP_AVAILABLE
974995
}
975996

976997
// forward to application
@@ -1044,8 +1065,7 @@ void AT_CellularContext::ciot_opt_cb(mbed::CellularNetwork::CIoT_Supported_Opt
10441065

10451066
void AT_CellularContext::set_disconnect()
10461067
{
1068+
tr_debug("AT_CellularContext::set_disconnect()");
10471069
_is_connected = false;
1048-
cell_callback_data_t data;
1049-
data.error = NSAPI_STATUS_DISCONNECTED;
1050-
_device->cellular_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, (intptr_t)&data);
1070+
_device->cellular_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED, this);
10511071
}

features/cellular/framework/AT/AT_CellularNetwork.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ void AT_CellularNetwork::read_reg_params_and_compare(RegistrationType type)
171171
reg_params._status == RegisteredRoaming)) {
172172
if (previous_registration_status == RegisteredHomeNetwork ||
173173
previous_registration_status == RegisteredRoaming) {
174-
_connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED);
174+
call_network_cb(NSAPI_STATUS_DISCONNECTED);
175175
}
176176
}
177177
}
@@ -200,11 +200,8 @@ void AT_CellularNetwork::urc_cgreg()
200200

201201
void AT_CellularNetwork::call_network_cb(nsapi_connection_status_t status)
202202
{
203-
if (_connect_status != status) {
204-
_connect_status = status;
205-
if (_connection_status_cb) {
206-
_connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _connect_status);
207-
}
203+
if (_connection_status_cb) {
204+
_connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _connect_status);
208205
}
209206
}
210207

features/cellular/framework/device/CellularDevice.cpp

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,20 @@ nsapi_error_t CellularDevice::create_state_machine()
113113
nsapi_error_t err = NSAPI_ERROR_OK;
114114
if (!_state_machine) {
115115
_state_machine = new CellularStateMachine(*this, *get_queue());
116-
_state_machine->set_cellular_callback(callback(this, &CellularDevice::cellular_callback));
116+
_state_machine->set_cellular_callback(callback(this, &CellularDevice::stm_callback));
117117
err = _state_machine->start_dispatch();
118118
if (err) {
119119
tr_error("Start state machine failed.");
120120
delete _state_machine;
121121
_state_machine = NULL;
122122
}
123+
124+
if (strlen(_plmn)) {
125+
_state_machine->set_plmn(_plmn);
126+
}
127+
if (strlen(_sim_pin)) {
128+
_state_machine->set_sim_pin(_sim_pin);
129+
}
123130
}
124131
return err;
125132
}
@@ -156,7 +163,12 @@ void CellularDevice::attach(Callback<void(nsapi_event_t, intptr_t)> status_cb)
156163
_status_cb = status_cb;
157164
}
158165

159-
void CellularDevice::cellular_callback(nsapi_event_t ev, intptr_t ptr)
166+
void CellularDevice::stm_callback(nsapi_event_t ev, intptr_t ptr)
167+
{
168+
cellular_callback(ev, ptr);
169+
}
170+
171+
void CellularDevice::cellular_callback(nsapi_event_t ev, intptr_t ptr, CellularContext *ctx)
160172
{
161173
if (ev >= NSAPI_EVENT_CELLULAR_STATUS_BASE && ev <= NSAPI_EVENT_CELLULAR_STATUS_END) {
162174
cell_callback_data_t *ptr_data = (cell_callback_data_t *)ptr;
@@ -166,40 +178,42 @@ void CellularDevice::cellular_callback(nsapi_event_t ev, intptr_t ptr)
166178
// broadcast only network registration changes to state machine
167179
_state_machine->cellular_event_changed(ev, ptr);
168180
}
169-
170181
if (cell_ev == CellularDeviceReady && ptr_data->error == NSAPI_ERROR_OK) {
171182
// Here we can create mux and give new filehandles as mux reserves the one what was in use.
172183
// if mux we would need to set new filehandle:_state_machine->set_filehandle( get fh from mux);
173184
_nw = open_network(_fh);
174185
// Attach to network so we can get update status from the network
175-
_nw->attach(callback(this, &CellularDevice::cellular_callback));
176-
if (strlen(_plmn)) {
177-
_state_machine->set_plmn(_plmn);
178-
}
179-
} else if (cell_ev == CellularSIMStatusChanged && ptr_data->error == NSAPI_ERROR_OK &&
180-
ptr_data->status_data == SimStatePinNeeded) {
181-
if (strlen(_sim_pin)) {
182-
_state_machine->set_sim_pin(_sim_pin);
183-
}
186+
_nw->attach(callback(this, &CellularDevice::stm_callback));
184187
}
185188
} else {
186189
tr_debug("callback: %d, ptr: %d", ev, ptr);
187190
if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_DISCONNECTED) {
188191
// we have been disconnected, reset state machine so that application can start connect sequence again
189192
if (_state_machine) {
190-
_state_machine->reset();
193+
CellularStateMachine::CellularState current_state, targeted_state;
194+
bool is_running = _state_machine->get_current_status(current_state, targeted_state);
195+
if (!is_running) {
196+
_state_machine->reset();
197+
}
191198
}
192199
}
193200
}
194201

195202
// broadcast network and cellular changes to state machine and CellularContext.
196203
CellularContext *curr = get_context_list();
197204
while (curr) {
198-
curr->cellular_callback(ev, ptr);
205+
if (ctx) {
206+
if (ctx == curr) {
207+
curr->cellular_callback(ev, ptr);
208+
break;
209+
}
210+
} else {
211+
curr->cellular_callback(ev, ptr);
212+
}
199213
curr = curr->_next;
200214
}
201215

202-
// forward to callback function if set by attach(...)
216+
// forward to callback function if set by attach(...).
203217
if (_status_cb) {
204218
_status_cb(ev, ptr);
205219
}

features/cellular/framework/device/CellularStateMachine.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ void CellularStateMachine::retry_state_or_fail()
320320
tr_debug("%s: retry %d/%d", get_state_string(_state), _retry_count, RETRY_ARRAY_SIZE);
321321
_event_timeout = _retry_timeout_array[_retry_count];
322322
_is_retry = true;
323+
_cb_data.error = NSAPI_ERROR_OK;
323324
} else {
324325
report_failure(get_state_string(_state));
325326
return;

0 commit comments

Comments
 (0)