From b400d18a0c6e1c2b2ec8ccaeb02f9411bc9188a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teppo=20J=C3=A4rvelin?= Date: Fri, 16 Mar 2018 11:10:04 +0200 Subject: [PATCH] Wait for modem ready signal in startup sequence. --- .../easy_cellular/CellularConnectionFSM.cpp | 66 +++++++++++++------ .../easy_cellular/CellularConnectionFSM.h | 5 +- .../cellular/framework/API/CellularPower.h | 16 +++++ features/cellular/framework/AT/ATHandler.cpp | 19 ++++++ features/cellular/framework/AT/ATHandler.h | 7 ++ .../framework/AT/AT_CellularPower.cpp | 19 +++++- .../cellular/framework/AT/AT_CellularPower.h | 4 ++ .../targets/QUECTEL/BG96/QUECTEL_BG96.h | 8 +-- 8 files changed, 113 insertions(+), 31 deletions(-) diff --git a/features/cellular/easy_cellular/CellularConnectionFSM.cpp b/features/cellular/easy_cellular/CellularConnectionFSM.cpp index 1333b9552c..b0e28d247c 100644 --- a/features/cellular/easy_cellular/CellularConnectionFSM.cpp +++ b/features/cellular/easy_cellular/CellularConnectionFSM.cpp @@ -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; diff --git a/features/cellular/easy_cellular/CellularConnectionFSM.h b/features/cellular/easy_cellular/CellularConnectionFSM.h index a15dee545b..817a234dc2 100644 --- a/features/cellular/easy_cellular/CellularConnectionFSM.h +++ b/features/cellular/easy_cellular/CellularConnectionFSM.h @@ -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; diff --git a/features/cellular/framework/API/CellularPower.h b/features/cellular/framework/API/CellularPower.h index 9d15be1f8a..16f89bd212 100644 --- a/features/cellular/framework/API/CellularPower.h +++ b/features/cellular/framework/API/CellularPower.h @@ -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 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 callback) = 0; }; } // namespace mbed diff --git a/features/cellular/framework/AT/ATHandler.cpp b/features/cellular/framework/AT/ATHandler.cpp index e242009f48..b09a4cc80c 100644 --- a/features/cellular/framework/AT/ATHandler.cpp +++ b/features/cellular/framework/AT/ATHandler.cpp @@ -181,6 +181,25 @@ nsapi_error_t ATHandler::set_urc_handler(const char *prefix, mbed::Callback 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 callback) { struct oob_t *oob = _oobs; diff --git a/features/cellular/framework/AT/ATHandler.h b/features/cellular/framework/AT/ATHandler.h index de425f1c9e..699f4b46ad 100644 --- a/features/cellular/framework/AT/ATHandler.h +++ b/features/cellular/framework/AT/ATHandler.h @@ -114,6 +114,13 @@ public: */ nsapi_error_t set_urc_handler(const char *prefix, mbed::Callback 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 callback); + ATHandler *_nextATHandler; // linked list /** returns the last error while parsing AT responses. diff --git a/features/cellular/framework/AT/AT_CellularPower.cpp b/features/cellular/framework/AT/AT_CellularPower.cpp index 0b31542dac..23d379c547 100644 --- a/features/cellular/framework/AT/AT_CellularPower.cpp +++ b/features/cellular/framework/AT/AT_CellularPower.cpp @@ -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 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 callback) +{ +#ifdef DEVICE_READY_URC + _at.remove_urc_handler(DEVICE_READY_URC, callback); +#endif // DEVICE_READY_URC +} diff --git a/features/cellular/framework/AT/AT_CellularPower.h b/features/cellular/framework/AT/AT_CellularPower.h index 0aaeafcb8d..e29c02a17e 100644 --- a/features/cellular/framework/AT/AT_CellularPower.h +++ b/features/cellular/framework/AT/AT_CellularPower.h @@ -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 callback); + + virtual void remove_device_ready_urc_cb(mbed::Callback callback); }; } // namespace mbed diff --git a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96.h b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96.h index 2fe2ea0b87..92dff47e9a 100644 --- a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96.h +++ b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96.h @@ -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 {