Wait for modem ready signal in startup sequence.

pull/6496/head
Teppo Järvelin 2018-03-16 11:10:04 +02:00
parent 231458dc36
commit b400d18a0c
8 changed files with 113 additions and 31 deletions

View File

@ -303,6 +303,8 @@ bool CellularConnectionFSM::is_automatic_registering()
nsapi_error_t CellularConnectionFSM::continue_from_state(CellularState state)
{
_state = state;
_next_state = state;
_retry_count = 0;
if (!_queue.call_in(0, callback(this, &CellularConnectionFSM::event))) {
stop();
return NSAPI_ERROR_NO_MEMORY;
@ -313,6 +315,7 @@ nsapi_error_t CellularConnectionFSM::continue_from_state(CellularState state)
nsapi_error_t CellularConnectionFSM::continue_to_state(CellularState state)
{
_retry_count = 0;
if (state < _state) {
_state = state;
} else {
@ -336,7 +339,7 @@ void CellularConnectionFSM::enter_to_state(CellularState state)
void CellularConnectionFSM::retry_state_or_fail()
{
if (++_retry_count < MAX_RETRY_ARRAY_SIZE) {
tr_info("Retry State %s, retry %d/%d", get_state_string(_state), _retry_count, MAX_RETRY_ARRAY_SIZE);
tr_debug("Retry State %s, retry %d/%d", get_state_string(_state), _retry_count, MAX_RETRY_ARRAY_SIZE);
_event_timeout = _retry_timeout_array[_retry_count];
} else {
report_failure(get_state_string(_state));
@ -363,30 +366,41 @@ void CellularConnectionFSM::state_power_on()
}
}
bool CellularConnectionFSM::device_ready()
{
tr_info("Cellular device ready");
if (_event_status_cb) {
_event_status_cb(NSAPI_EVENT_CELLULAR_STATUS_CHANGE, CellularDeviceReady);
}
_power->remove_device_ready_urc_cb(mbed::callback(this, &CellularConnectionFSM::ready_urc_cb));
bool success = false;
for (int type = 0; type < CellularNetwork::C_MAX; type++) {
if (!_network->set_registration_urc((CellularNetwork::RegistrationType)type, true)) {
success = true;
}
}
if (!success) {
tr_error("Failed to set any URC's for registration");
report_failure(get_state_string(_state));
return false;
}
return true;
}
void CellularConnectionFSM::state_device_ready()
{
_cellularDevice->set_timeout(TIMEOUT_POWER_ON);
if (_power->set_at_mode() == NSAPI_ERROR_OK) { // TODO: ask once, then wait for urc is possible as 3gpp does not define any first at command or such what we could listen
// This could be done by adding module specific at command which to listen
tr_info("Cellular device ready");
if (_event_status_cb) {
_event_status_cb(NSAPI_EVENT_CELLULAR_STATUS_CHANGE, CellularDeviceReady);
if (_power->set_at_mode() == NSAPI_ERROR_OK) {
if (device_ready()) {
enter_to_state(STATE_SIM_PIN);
}
bool success = false;
for (int type = 0; type < CellularNetwork::C_MAX; type++) {
if (!_network->set_registration_urc((CellularNetwork::RegistrationType)type, true)) {
success = true;
}
}
if (!success) {
tr_error("Failed to set any URC's for registration");
report_failure(get_state_string(_state));
return;
}
enter_to_state(STATE_SIM_PIN);
} else {
if (_retry_count == 0) {
(void)_power->set_device_ready_urc_cb(mbed::callback(this, &CellularConnectionFSM::ready_urc_cb));
}
retry_state_or_fail();
}
}
@ -563,6 +577,18 @@ void CellularConnectionFSM::network_callback(nsapi_event_t ev, intptr_t ptr)
}
}
void CellularConnectionFSM::ready_urc_cb()
{
tr_info("Device ready URC func called");
if (_state == STATE_DEVICE_READY && _power->set_at_mode() == NSAPI_ERROR_OK) {
tr_info("State was STATE_DEVICE_READY and at mode ready, cancel state and move to next");
_queue.cancel(_eventID);
if (device_ready()) {
continue_from_state(STATE_SIM_PIN);
}
}
}
events::EventQueue *CellularConnectionFSM::get_queue()
{
return &_queue;

View File

@ -29,10 +29,9 @@
#include "CellularNetwork.h"
#include "CellularPower.h"
#include "CellularSIM.h"
#include "CellularUtil.h"
// modem type is defined as CELLULAR_DEVICE macro
#define _CELLULAR_STRINGIFY(a) #a
#define CELLULAR_STRINGIFY(a) _CELLULAR_STRINGIFY(a)
#include CELLULAR_STRINGIFY(CELLULAR_DEVICE.h)
namespace mbed {
@ -149,6 +148,7 @@ private:
bool get_attach_network(CellularNetwork::AttachStatus &status);
bool set_attach_network();
bool is_registered();
bool device_ready();
// state functions to keep state machine simple
void state_init();
@ -171,6 +171,7 @@ private:
private:
void report_failure(const char* msg);
void event();
void ready_urc_cb();
UARTSerial *_serial;
CellularState _state;

View File

@ -18,6 +18,7 @@
#define CELLULAR_API_CELLULARPOWER_H_
#include "nsapi_types.h"
#include "Callback.h"
namespace mbed {
@ -118,6 +119,21 @@ public:
* @return zero on success
*/
virtual nsapi_error_t opt_receive_period(int mode, EDRXAccessTechnology act_type, uint8_t edrx_value) = 0;
/** Set URC callback function for device specific ready urc. URC is defined in device specific
* header (for example in QUECTEL_BG96.h). Used in startup sequence to listen when device is ready
* for using at commands and possible sim.
*
* @param callback Callback function called when urc received
* @return zero on success
*/
virtual nsapi_error_t set_device_ready_urc_cb(mbed::Callback<void()> callback) = 0;
/** Removes the device ready urc from the list of urc's.
*
* @param callback callback to remove from the list of urc's
*/
virtual void remove_device_ready_urc_cb(mbed::Callback<void()> callback) = 0;
};
} // namespace mbed

View File

@ -181,6 +181,25 @@ nsapi_error_t ATHandler::set_urc_handler(const char *prefix, mbed::Callback<void
return NSAPI_ERROR_OK;
}
void ATHandler::remove_urc_handler(const char *prefix, mbed::Callback<void()> callback)
{
struct oob_t *current = _oobs;
struct oob_t *prev = NULL;
while (current) {
if (strcmp(prefix, current->prefix) == 0 && current->cb == callback) {
if (prev) {
prev->next = current->next;
} else {
_oobs = current->next;
}
delete current;
break;
}
prev = current;
current = prev->next;
}
}
bool ATHandler::check_urc_existance(const char *prefix, mbed::Callback<void()> callback)
{
struct oob_t *oob = _oobs;

View File

@ -114,6 +114,13 @@ public:
*/
nsapi_error_t set_urc_handler(const char *prefix, mbed::Callback<void()> callback);
/** Remove urc handler from linked list of urc's
*
* @param prefix Register urc prefix for callback. Urc could be for example "+CMTI: "
* @param callback Callback, which is called if urc is found in AT response
*/
void remove_urc_handler(const char *prefix, mbed::Callback<void()> callback);
ATHandler *_nextATHandler; // linked list
/** returns the last error while parsing AT responses.

View File

@ -19,6 +19,7 @@
#include "CellularUtil.h"
#include "CellularLog.h"
#include "nsapi_types.h"
#include CELLULAR_STRINGIFY(CELLULAR_DEVICE.h)
static const int PSMTimerBits = 5;
@ -43,8 +44,6 @@ nsapi_error_t AT_CellularPower::off()
return NSAPI_ERROR_UNSUPPORTED;
}
// wiat filehandle irq
nsapi_error_t AT_CellularPower::set_at_mode()
{
_at.lock();
@ -233,3 +232,19 @@ nsapi_error_t AT_CellularPower::opt_receive_period(int mode, EDRXAccessTechnolog
return _at.unlock_return_error();
}
nsapi_error_t AT_CellularPower::set_device_ready_urc_cb(mbed::Callback<void()> callback)
{
#ifdef DEVICE_READY_URC
return _at.set_urc_handler(DEVICE_READY_URC, callback);
#else
return NSAPI_ERROR_UNSUPPORTED;
#endif // DEVICE_READY_URC
}
void AT_CellularPower::remove_device_ready_urc_cb(mbed::Callback<void()> callback)
{
#ifdef DEVICE_READY_URC
_at.remove_urc_handler(DEVICE_READY_URC, callback);
#endif // DEVICE_READY_URC
}

View File

@ -48,6 +48,10 @@ public:
virtual nsapi_error_t opt_power_save_mode(int periodic_time, int active_time);
virtual nsapi_error_t opt_receive_period(int mode, EDRXAccessTechnology act_type, uint8_t edrx_value);
virtual nsapi_error_t set_device_ready_urc_cb(mbed::Callback<void()> callback);
virtual void remove_device_ready_urc_cb(mbed::Callback<void()> callback);
};
} // namespace mbed

View File

@ -22,13 +22,7 @@
namespace mbed {
#ifdef TARGET_MCU_K64F
#define CELLULAR_SERIAL_TX PTC17
#define CELLULAR_SERIAL_RX PTC16
#else
#define CELLULAR_SERIAL_TX PC_1
#define CELLULAR_SERIAL_RX PC_0
#endif
#define DEVICE_READY_URC "CPIN:"
class QUECTEL_BG96 : public AT_CellularDevice
{