Skip to content

Commit bd423ca

Browse files
author
Teppo Järvelin
committed
Cellular: new state machine state and better info from stm
Added new state (signal quality) and more information about progress so application/driver can build recovery logic.
1 parent d1da622 commit bd423ca

File tree

9 files changed

+104
-59
lines changed

9 files changed

+104
-59
lines changed

UNITTESTS/features/cellular/framework/device/cellulardevice/cellulardevicetest.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,12 @@ TEST_F(TestCellularDevice, test_set_sim_ready)
118118
CellularStateMachine_stub::nsapi_error_value = NSAPI_ERROR_OK;
119119
ASSERT_EQ(dev->set_sim_ready(), NSAPI_ERROR_OK);
120120

121-
CellularStateMachine_stub::get_current_current_state = STATE_MANUAL_REGISTERING_NETWORK;
121+
CellularStateMachine_stub::get_current_current_state = STATE_REGISTERING_NETWORK;
122122
CellularStateMachine_stub::nsapi_error_value = NSAPI_ERROR_OK;
123123
ASSERT_EQ(dev->set_sim_ready(), NSAPI_ERROR_ALREADY);
124124

125125
CellularStateMachine_stub::bool_value = true;
126-
CellularStateMachine_stub::get_current_target_state = STATE_MANUAL_REGISTERING_NETWORK;
126+
CellularStateMachine_stub::get_current_target_state = STATE_REGISTERING_NETWORK;
127127
CellularStateMachine_stub::get_current_current_state = STATE_POWER_ON;
128128
ASSERT_EQ(dev->set_sim_ready(), NSAPI_ERROR_IN_PROGRESS);
129129
delete dev;

UNITTESTS/features/cellular/framework/device/cellularstatemachine/cellularstatemachinetest.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ enum UT_CellularState {
3333
UT_STATE_POWER_ON,
3434
UT_STATE_DEVICE_READY,
3535
UT_STATE_SIM_PIN,
36+
UT_STATE_SIGNAL_QUALITY,
3637
UT_STATE_REGISTERING_NETWORK,
3738
UT_STATE_ATTACHING_NETWORK,
3839
UT_STATE_MAX_FSM_STATE

UNITTESTS/stubs/CellularStateMachine_stub.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ enum CellularStubState {
2424
STATE_POWER_ON,
2525
STATE_DEVICE_READY,
2626
STATE_SIM_PIN,
27+
STATE_SIGNAL_QUALITY,
2728
STATE_REGISTERING_NETWORK,
28-
STATE_MANUAL_REGISTERING_NETWORK,
2929
STATE_ATTACHING_NETWORK,
3030
STATE_MAX_FSM_STATE
3131
};

UNITTESTS/target_h/myCellularDevice.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ class myCellularDevice : public CellularDevice {
7272

7373
virtual CellularNetwork *open_network(FileHandle *fh = NULL)
7474
{
75+
if (_network) {
76+
return _network;
77+
}
7578
EventQueue que;
7679
FileHandle_stub fh1;
7780
ATHandler at(&fh1, que, 0, ",");

features/cellular/framework/AT/AT_CellularContext.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ nsapi_error_t AT_CellularContext::check_operation(nsapi_error_t err, ContextOper
196196
tr_warning("No cellular connection");
197197
return NSAPI_ERROR_TIMEOUT;
198198
}
199-
return NSAPI_ERROR_OK;
199+
return _cb_data.error;// callback might have been completed with an error, must return that error here
200200
}
201201
}
202202

@@ -932,11 +932,11 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
932932
}
933933
#endif // USE_APN_LOOKUP
934934

935-
if (!_nw && st == CellularDeviceReady && data->error == NSAPI_ERROR_OK) {
935+
if (!_nw && st == CellularDeviceReady && _cb_data.error == NSAPI_ERROR_OK) {
936936
_nw = _device->open_network(_fh);
937937
}
938938

939-
if (_cp_req && !_cp_in_use && (data->error == NSAPI_ERROR_OK) &&
939+
if (_cp_req && !_cp_in_use && (_cb_data.error == NSAPI_ERROR_OK) &&
940940
(st == CellularSIMStatusChanged && data->status_data == CellularDevice::SimStateReady)) {
941941
if (setup_control_plane_opt() != NSAPI_ERROR_OK) {
942942
tr_error("Control plane SETUP failed!");
@@ -946,7 +946,7 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
946946
}
947947

948948
if (_is_blocking) {
949-
if (data->error != NSAPI_ERROR_OK) {
949+
if (_cb_data.error != NSAPI_ERROR_OK) {
950950
// operation failed, release semaphore
951951
_current_op = OP_INVALID;
952952
_semaphore.release();
@@ -971,7 +971,7 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
971971
}
972972
} else {
973973
// non blocking
974-
if (st == CellularAttachNetwork && _current_op == OP_CONNECT && data->error == NSAPI_ERROR_OK &&
974+
if (st == CellularAttachNetwork && _current_op == OP_CONNECT && _cb_data.error == NSAPI_ERROR_OK &&
975975
data->status_data == CellularNetwork::Attached) {
976976
_current_op = OP_INVALID;
977977
// forward to application

features/cellular/framework/common/CellularCommon.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,23 @@ struct cell_callback_data_t {
2727
nsapi_error_t error; /* possible error code */
2828
int status_data; /* cellular_event_status related enum or other info in int format. Check cellular_event_status comments.*/
2929
bool final_try; /* This flag is true if state machine is used and this was the last try. State machine does goes to idle. */
30-
30+
const void *data; /* possible extra data in any form. Format specified in cellular_connection_status_t per event if any. */
3131
cell_callback_data_t()
3232
{
3333
error = NSAPI_ERROR_OK;
3434
status_data = -1;
3535
final_try = false;
36+
data = NULL;
37+
}
38+
};
39+
40+
struct cell_signal_quality_t {
41+
int rssi; /* received signal strength */
42+
int ber; /* channel bit error rate */
43+
cell_signal_quality_t()
44+
{
45+
rssi = -1;
46+
ber = -1;
3647
}
3748
};
3849

@@ -51,6 +62,9 @@ typedef enum cellular_event_status {
5162
CellularRadioAccessTechnologyChanged = NSAPI_EVENT_CELLULAR_STATUS_BASE + 5, /* Network roaming status have changed. cell_callback_data_t.status_data will be enum RadioAccessTechnology See enum RadioAccessTechnology in ../API/CellularNetwork.h*/
5263
CellularAttachNetwork = NSAPI_EVENT_CELLULAR_STATUS_BASE + 6, /* cell_callback_data_t.status_data will be enum AttachStatus. See enum AttachStatus in ../API/CellularNetwork.h */
5364
CellularActivatePDPContext = NSAPI_EVENT_CELLULAR_STATUS_BASE + 7, /* NSAPI_ERROR_OK in cell_callback_data_t.error on successfully PDP Context activated or negative error */
65+
CellularSignalQuality = NSAPI_EVENT_CELLULAR_STATUS_BASE + 8, /* cell_callback_data_t.error will contains return value when signal quality was queried. data will hold the pointer to cell_signal_quality struct. See possible values from ../API/CellularNetwork.h*/
66+
CellularStateRetryEvent = NSAPI_EVENT_CELLULAR_STATUS_BASE + 9, /* cell_callback_data_t.error contain an error if any. cell_callback_data_t.status_data contains cellular_event_status and it specifies the operation which is retried.
67+
cellular_event_status.data contains current retrycount */
5468
} cellular_connection_status_t;
5569

5670
#endif // CELLULAR_COMMON_

features/cellular/framework/device/CellularDevice.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ nsapi_error_t CellularDevice::attach_to_network()
116116

117117
nsapi_error_t CellularDevice::create_state_machine()
118118
{
119+
_nw = open_network(_fh);
120+
// Attach to network so we can get update status from the network
121+
_nw->attach(callback(this, &CellularDevice::stm_callback));
122+
119123
nsapi_error_t err = NSAPI_ERROR_OK;
120124
if (!_state_machine) {
121125
_state_machine = new CellularStateMachine(*this, *get_queue());
@@ -178,19 +182,17 @@ void CellularDevice::cellular_callback(nsapi_event_t ev, intptr_t ptr, CellularC
178182
{
179183
if (ev >= NSAPI_EVENT_CELLULAR_STATUS_BASE && ev <= NSAPI_EVENT_CELLULAR_STATUS_END) {
180184
cell_callback_data_t *ptr_data = (cell_callback_data_t *)ptr;
181-
tr_debug("callback: %d, err: %d, data: %d", ev, ptr_data->error, ptr_data->status_data);
182185
cellular_connection_status_t cell_ev = (cellular_connection_status_t)ev;
186+
if (cell_ev == CellularStateRetryEvent) {
187+
tr_debug("callback: CellularStateRetryEvent, err: %d, data: %d, retrycount: %d", ptr_data->error, ptr_data->status_data, *(const int *)ptr_data->data);
188+
} else {
189+
tr_debug("callback: %d, err: %d, data: %d", ev, ptr_data->error, ptr_data->status_data);
190+
}
191+
183192
if (cell_ev == CellularRegistrationStatusChanged && _state_machine) {
184193
// broadcast only network registration changes to state machine
185194
_state_machine->cellular_event_changed(ev, ptr);
186195
}
187-
if (cell_ev == CellularDeviceReady && ptr_data->error == NSAPI_ERROR_OK) {
188-
// Here we can create mux and give new filehandles as mux reserves the one what was in use.
189-
// if mux we would need to set new filehandle:_state_machine->set_filehandle( get fh from mux);
190-
_nw = open_network(_fh);
191-
// Attach to network so we can get update status from the network
192-
_nw->attach(callback(this, &CellularDevice::stm_callback));
193-
}
194196
} else {
195197
tr_debug("callback: %d, ptr: %d", ev, ptr);
196198
if (ev == NSAPI_EVENT_CONNECTION_STATUS_CHANGE && ptr == NSAPI_STATUS_DISCONNECTED) {

features/cellular/framework/device/CellularStateMachine.cpp

Lines changed: 62 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ CellularStateMachine::CellularStateMachine(CellularDevice &device, events::Event
4747
_cellularDevice(device), _state(STATE_INIT), _next_state(_state), _target_state(_state),
4848
_event_status_cb(0), _network(0), _queue(queue), _queue_thread(0), _sim_pin(0),
4949
_retry_count(0), _event_timeout(-1), _event_id(-1), _plmn(0), _command_success(false),
50-
_is_retry(false), _cb_data(), _current_event(NSAPI_EVENT_CONNECTION_STATUS_CHANGE), _status(0)
50+
_is_retry(false), _cb_data(), _current_event(CellularDeviceReady), _status(0)
5151
{
5252
#if MBED_CONF_CELLULAR_RANDOM_MAX_START_DELAY == 0
5353
_start_time = 0;
@@ -138,10 +138,8 @@ bool CellularStateMachine::open_sim()
138138
}
139139

140140
// report current state so callback can set sim pin if needed
141-
if (_event_status_cb) {
142-
_cb_data.status_data = state;
143-
_event_status_cb((nsapi_event_t)CellularSIMStatusChanged, (intptr_t)&_cb_data);
144-
}
141+
_cb_data.status_data = state;
142+
send_event_cb(CellularSIMStatusChanged);
145143

146144
if (state == CellularDevice::SimStatePinNeeded) {
147145
if (_sim_pin) {
@@ -161,13 +159,10 @@ bool CellularStateMachine::open_sim()
161159
bool sim_ready = state == CellularDevice::SimStateReady;
162160

163161
if (sim_ready) {
164-
// If plmn is set, we should it right after sim is opened so that registration is forced to correct network.
165-
if (_plmn && strlen(_plmn)) {
166-
_cb_data.error = _network->set_registration(_plmn);
167-
tr_debug("STM: manual set_registration: %d, plmn: %s", _cb_data.error, _plmn);
168-
if (_cb_data.error) {
169-
return false;
170-
}
162+
_cb_data.error = _network->set_registration(_plmn);
163+
tr_debug("STM: set_registration: %d, plmn: %s", _cb_data.error, _plmn);
164+
if (_cb_data.error) {
165+
return false;
171166
}
172167
}
173168

@@ -255,18 +250,16 @@ void CellularStateMachine::report_failure(const char *msg)
255250
tr_error("CellularStateMachine failure: %s", msg);
256251

257252
_event_id = -1;
258-
if (_event_status_cb) {
259-
_cb_data.final_try = true;
260-
_event_status_cb(_current_event, (intptr_t)&_cb_data);
261-
}
253+
_cb_data.final_try = true;
254+
send_event_cb(_current_event);
262255

263256
tr_error("CellularStateMachine target state %s, current state %s", get_state_string(_target_state), get_state_string(_state));
264257
}
265258

266259
const char *CellularStateMachine::get_state_string(CellularState state) const
267260
{
268261
#if MBED_CONF_MBED_TRACE_ENABLE
269-
static const char *strings[STATE_MAX_FSM_STATE] = { "Init", "Power", "Device ready", "SIM pin", "Registering network", "Attaching network"};
262+
static const char *strings[STATE_MAX_FSM_STATE] = { "Init", "Power", "Device ready", "SIM pin", "Signal quality", "Registering network", "Attaching network"};
270263
return strings[state];
271264
#else
272265
return NULL;
@@ -287,12 +280,17 @@ void CellularStateMachine::retry_state_or_fail()
287280
{
288281
if (++_retry_count < CELLULAR_RETRY_ARRAY_SIZE) {
289282
tr_debug("%s: retry %d/%d", get_state_string(_state), _retry_count, CELLULAR_RETRY_ARRAY_SIZE);
283+
// send info to application/driver about error logic so it can implement proper error logic
284+
_cb_data.status_data = _current_event;
285+
_cb_data.data = &_retry_count;
286+
_cb_data.error = NSAPI_ERROR_OK;
287+
send_event_cb(CellularStateRetryEvent);
288+
290289
_event_timeout = _retry_timeout_array[_retry_count];
291290
_is_retry = true;
292291
_cb_data.error = NSAPI_ERROR_OK;
293292
} else {
294293
report_failure(get_state_string(_state));
295-
return;
296294
}
297295
}
298296

@@ -343,9 +341,7 @@ bool CellularStateMachine::device_ready()
343341
}
344342
#endif // MBED_CONF_CELLULAR_DEBUG_AT
345343

346-
if (_event_status_cb) {
347-
_event_status_cb((nsapi_event_t)CellularDeviceReady, (intptr_t)&_cb_data);
348-
}
344+
send_event_cb(CellularDeviceReady);
349345
_cellularDevice.set_ready_cb(0);
350346

351347
return true;
@@ -411,12 +407,25 @@ void CellularStateMachine::state_sim_pin()
411407
} else if (_cb_data.error) {
412408
tr_warning("Packet domain event reporting set failed!");
413409
}
414-
enter_to_state(STATE_REGISTERING_NETWORK);
410+
enter_to_state(STATE_SIGNAL_QUALITY);
415411
} else {
416412
retry_state_or_fail();
417413
}
418414
}
419415

416+
void CellularStateMachine::state_signal_quality()
417+
{
418+
_cb_data.error = _network->get_signal_quality(_signal_quality.rssi, &_signal_quality.ber);
419+
420+
if (_cb_data.error != NSAPI_ERROR_OK) {
421+
retry_state_or_fail();
422+
} else {
423+
_cb_data.data = &_signal_quality;
424+
send_event_cb(_current_event);
425+
enter_to_state(STATE_REGISTERING_NETWORK);
426+
}
427+
}
428+
420429
void CellularStateMachine::state_registering()
421430
{
422431
_cellularDevice.set_timeout(TIMEOUT_NETWORK);
@@ -428,7 +437,7 @@ void CellularStateMachine::state_registering()
428437
_cb_data.status_data = CellularNetwork::AlreadyRegistered;
429438
}
430439
_cb_data.error = NSAPI_ERROR_OK;
431-
_event_status_cb(_current_event, (intptr_t)&_cb_data);
440+
send_event_cb(_current_event);
432441
// we are already registered, go to attach
433442
enter_to_state(STATE_ATTACHING_NETWORK);
434443
} else {
@@ -449,10 +458,8 @@ void CellularStateMachine::state_attaching()
449458
_cb_data.error = _network->set_attach();
450459
}
451460
if (_cb_data.error == NSAPI_ERROR_OK) {
452-
if (_event_status_cb) {
453-
_cb_data.status_data = CellularNetwork::Attached;
454-
_event_status_cb(_current_event, (intptr_t)&_cb_data);
455-
}
461+
_cb_data.status_data = CellularNetwork::Attached;
462+
send_event_cb(_current_event);
456463
} else {
457464
retry_state_or_fail();
458465
}
@@ -533,45 +540,51 @@ bool CellularStateMachine::get_current_status(CellularStateMachine::CellularStat
533540

534541
void CellularStateMachine::event()
535542
{
536-
#if MBED_CONF_MBED_TRACE_ENABLE
537-
if (_network) {
538-
int rssi;
539-
if (_network->get_signal_quality(rssi) == NSAPI_ERROR_OK) {
540-
if (rssi == CellularNetwork::SignalQualityUnknown) {
543+
// Don't send Signal quality when in signal quality state or it can confuse callback functions when running retry logic
544+
if (_network && _state != STATE_SIGNAL_QUALITY) {
545+
_cb_data.error = _network->get_signal_quality(_signal_quality.rssi, &_signal_quality.ber);
546+
_cb_data.data = &_signal_quality;
547+
548+
if (_cb_data.error == NSAPI_ERROR_OK) {
549+
send_event_cb(CellularSignalQuality);
550+
if (_signal_quality.rssi == CellularNetwork::SignalQualityUnknown) {
541551
tr_info("RSSI unknown");
542552
} else {
543-
tr_info("RSSI %d dBm", rssi);
553+
tr_info("RSSI %d dBm", _signal_quality.rssi);
544554
}
545555
}
546556
}
547-
#endif
548557

549558
_event_timeout = -1;
550559
_is_retry = false;
551560

552561
switch (_state) {
553562
case STATE_INIT:
554-
_current_event = (nsapi_event_t)CellularDeviceReady;
563+
_current_event = CellularDeviceReady;
555564
state_init();
556565
break;
557566
case STATE_POWER_ON:
558-
_current_event = (nsapi_event_t)CellularDeviceReady;
567+
_current_event = CellularDeviceReady;
559568
state_power_on();
560569
break;
561570
case STATE_DEVICE_READY:
562-
_current_event = (nsapi_event_t)CellularDeviceReady;
571+
_current_event = CellularDeviceReady;
563572
state_device_ready();
564573
break;
565574
case STATE_SIM_PIN:
566-
_current_event = (nsapi_event_t)CellularSIMStatusChanged;
575+
_current_event = CellularSIMStatusChanged;
567576
state_sim_pin();
568577
break;
578+
case STATE_SIGNAL_QUALITY:
579+
_current_event = CellularSignalQuality;
580+
state_signal_quality();
581+
break;
569582
case STATE_REGISTERING_NETWORK:
570-
_current_event = (nsapi_event_t)CellularRegistrationStatusChanged;
583+
_current_event = CellularRegistrationStatusChanged;
571584
state_registering();
572585
break;
573586
case STATE_ATTACHING_NETWORK:
574-
_current_event = (nsapi_event_t)CellularAttachNetwork;
587+
_current_event = CellularAttachNetwork;
575588
state_attaching();
576589
break;
577590
default:
@@ -623,6 +636,13 @@ void CellularStateMachine::set_cellular_callback(mbed::Callback<void(nsapi_event
623636
_event_status_cb = status_cb;
624637
}
625638

639+
void CellularStateMachine::send_event_cb(cellular_connection_status_t status)
640+
{
641+
if (_event_status_cb) {
642+
_event_status_cb((nsapi_event_t)status, (intptr_t)&_cb_data);
643+
}
644+
}
645+
626646
bool CellularStateMachine::check_is_target_reached()
627647
{
628648
if (((_target_state == _state || _target_state < _next_state) && _cb_data.error == NSAPI_ERROR_OK && !_is_retry) ||
@@ -640,7 +660,8 @@ bool CellularStateMachine::check_is_target_reached()
640660
void CellularStateMachine::cellular_event_changed(nsapi_event_t ev, intptr_t ptr)
641661
{
642662
cell_callback_data_t *data = (cell_callback_data_t *)ptr;
643-
if ((cellular_connection_status_t)ev == CellularRegistrationStatusChanged && _state == STATE_REGISTERING_NETWORK) {
663+
if ((cellular_connection_status_t)ev == CellularRegistrationStatusChanged && (
664+
_state == STATE_REGISTERING_NETWORK || _state == STATE_SIGNAL_QUALITY)) {
644665
// expect packet data so only these states are valid
645666
CellularNetwork::registration_params_t reg_params;
646667
nsapi_error_t err = _network->get_registration_params(reg_params);

0 commit comments

Comments
 (0)