mirror of https://github.com/ARMmbed/mbed-os.git
Cellular: Fix BG96 power on and connect
parent
5a6bf446d2
commit
cb20277701
|
@ -43,6 +43,7 @@ set(unittest-test-sources
|
|||
stubs/SerialBase_stub.cpp
|
||||
stubs/CellularStateMachine_stub.cpp
|
||||
stubs/CellularContext_stub.cpp
|
||||
stubs/ThisThread_stub.cpp
|
||||
stubs/ConditionVariable_stub.cpp
|
||||
stubs/Mutex_stub.cpp
|
||||
)
|
||||
|
|
|
@ -926,7 +926,7 @@ void ATHandler::set_3gpp_error(int err, DeviceErrorType error_type)
|
|||
for (size_t i = 0; i < sizeof(map_3gpp_errors) / sizeof(map_3gpp_errors[0]); i++) {
|
||||
if (map_3gpp_errors[i][0] == err) {
|
||||
_last_3gpp_error = map_3gpp_errors[i][1];
|
||||
tr_debug("AT3GPP error code %d", get_3gpp_error());
|
||||
tr_error("AT3GPP error code %d", get_3gpp_error());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -943,7 +943,7 @@ void ATHandler::at_error(bool error_code_expected, DeviceErrorType error_type)
|
|||
set_3gpp_error(err, error_type);
|
||||
_last_at_err.errCode = err;
|
||||
_last_at_err.errType = error_type;
|
||||
tr_error("AT error code %ld", err);
|
||||
tr_warn("AT error code %ld", err);
|
||||
} else {
|
||||
tr_warn("ATHandler ERROR reading failed");
|
||||
}
|
||||
|
|
|
@ -608,6 +608,7 @@ nsapi_error_t AT_CellularContext::open_data_channel()
|
|||
connected, or timeout after 30 seconds*/
|
||||
nsapi_error_t err = nsapi_ppp_connect(_at.get_file_handle(), callback(this, &AT_CellularContext::ppp_status_cb), _uname, _pwd, (nsapi_ip_stack_t)_pdp_type);
|
||||
if (err) {
|
||||
tr_error("nsapi_ppp_connect failed");
|
||||
ppp_disconnected();
|
||||
}
|
||||
|
||||
|
@ -993,6 +994,7 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
|
|||
tr_info("cellular_callback: PPP mode and NSAPI_STATUS_DISCONNECTED");
|
||||
_cb_data.error = NSAPI_ERROR_NO_CONNECTION;
|
||||
_is_connected = false;
|
||||
ppp_disconnected();
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "rtos/ThisThread.h"
|
||||
#include "CellularUtil.h"
|
||||
#include "AT_CellularDevice.h"
|
||||
#include "AT_CellularInformation.h"
|
||||
|
@ -202,6 +203,7 @@ nsapi_error_t AT_CellularDevice::get_sim_state(SimState &state)
|
|||
_at->flush();
|
||||
nsapi_error_t error = _at->at_cmd_str("+CPIN", "?", simstr, sizeof(simstr));
|
||||
ssize_t len = strlen(simstr);
|
||||
device_err_t err = _at->get_last_device_error();
|
||||
_at->unlock();
|
||||
|
||||
if (len != -1) {
|
||||
|
@ -213,7 +215,6 @@ nsapi_error_t AT_CellularDevice::get_sim_state(SimState &state)
|
|||
state = SimStatePukNeeded;
|
||||
} else {
|
||||
simstr[len] = '\0';
|
||||
tr_error("Unknown SIM state %s", simstr);
|
||||
state = SimStateUnknown;
|
||||
}
|
||||
} else {
|
||||
|
@ -229,7 +230,11 @@ nsapi_error_t AT_CellularDevice::get_sim_state(SimState &state)
|
|||
tr_error("SIM PUK required");
|
||||
break;
|
||||
case SimStateUnknown:
|
||||
tr_warn("SIM state unknown");
|
||||
if (err.errType == DeviceErrorTypeErrorCME && err.errCode == 14) {
|
||||
tr_info("SIM busy");
|
||||
} else {
|
||||
tr_warn("SIM state unknown");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
tr_info("SIM is ready");
|
||||
|
@ -443,12 +448,18 @@ nsapi_error_t AT_CellularDevice::init()
|
|||
setup_at_handler();
|
||||
|
||||
_at->lock();
|
||||
_at->flush();
|
||||
_at->at_cmd_discard("E0", "");
|
||||
|
||||
_at->at_cmd_discard("+CMEE", "=1");
|
||||
|
||||
_at->at_cmd_discard("+CFUN", "=1");
|
||||
for (int retry = 1; retry <= 3; retry++) {
|
||||
_at->clear_error();
|
||||
_at->flush();
|
||||
_at->at_cmd_discard("E0", "");
|
||||
_at->at_cmd_discard("+CMEE", "=1");
|
||||
_at->at_cmd_discard("+CFUN", "=1");
|
||||
if (_at->get_last_error() == NSAPI_ERROR_OK) {
|
||||
break;
|
||||
}
|
||||
tr_debug("Wait 100ms to init modem");
|
||||
rtos::ThisThread::sleep_for(100); // let modem have time to get ready
|
||||
}
|
||||
|
||||
return _at->unlock_return_error();
|
||||
}
|
||||
|
|
|
@ -211,8 +211,9 @@ nsapi_error_t AT_CellularNetwork::set_registration(const char *plmn)
|
|||
if (!plmn) {
|
||||
tr_debug("Automatic network registration");
|
||||
NWRegisteringMode mode;
|
||||
get_network_registering_mode(mode);
|
||||
|
||||
if (get_network_registering_mode(mode) != NSAPI_ERROR_OK) {
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
if (mode != NWModeAutomatic) {
|
||||
return _at.at_cmd_discard("+COPS", "=0");
|
||||
}
|
||||
|
|
|
@ -234,6 +234,9 @@ nsapi_error_t CellularDevice::shutdown()
|
|||
}
|
||||
CellularContext *curr = get_context_list();
|
||||
while (curr) {
|
||||
if (curr->is_connected()) {
|
||||
curr->disconnect();
|
||||
}
|
||||
curr->cellular_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED);
|
||||
curr = (CellularContext *)curr->_next;
|
||||
}
|
||||
|
|
|
@ -367,6 +367,7 @@ void CellularStateMachine::state_device_ready()
|
|||
}
|
||||
} else {
|
||||
_status = 0;
|
||||
_is_retry = true;
|
||||
enter_to_state(STATE_INIT);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,92 +97,35 @@ void QUECTEL_BG96::set_ready_cb(Callback<void()> callback)
|
|||
_at->set_urc_handler(DEVICE_READY_URC, callback);
|
||||
}
|
||||
|
||||
nsapi_error_t QUECTEL_BG96::hard_power_on()
|
||||
{
|
||||
if (_pwr.is_connected()) {
|
||||
tr_info("Modem power on");
|
||||
ThisThread::sleep_for(250);
|
||||
_pwr = !_active_high;
|
||||
ThisThread::sleep_for(250); // BG96_Hardware_Design_V1.1 says 100 ms, but 250 ms seems to be more robust
|
||||
_pwr = _active_high;
|
||||
ThisThread::sleep_for(500);
|
||||
}
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t QUECTEL_BG96::soft_power_on()
|
||||
{
|
||||
if (!_rst.is_connected()) {
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
tr_info("Reset modem");
|
||||
_rst = !_active_high;
|
||||
ThisThread::sleep_for(100);
|
||||
_rst = _active_high;
|
||||
ThisThread::sleep_for(150 + 460); // RESET_N timeout from BG96_Hardware_Design_V1.1
|
||||
_rst = !_active_high;
|
||||
ThisThread::sleep_for(500);
|
||||
|
||||
// wait for RDY
|
||||
_at->lock();
|
||||
_at->set_at_timeout(10 * 1000);
|
||||
_at->resp_start();
|
||||
_at->set_stop_tag("RDY");
|
||||
bool rdy = _at->consume_to_stop_tag();
|
||||
_at->set_stop_tag(OK);
|
||||
_at->restore_at_timeout();
|
||||
|
||||
if (!rdy) {
|
||||
// check if modem was silently powered on
|
||||
_at->clear_error();
|
||||
_at->set_at_timeout(100);
|
||||
_at->at_cmd_discard("", ""); //Send AT
|
||||
_at->restore_at_timeout();
|
||||
}
|
||||
return _at->unlock_return_error();
|
||||
}
|
||||
|
||||
nsapi_error_t QUECTEL_BG96::hard_power_off()
|
||||
{
|
||||
if (_pwr.is_connected()) {
|
||||
tr_info("Modem power off");
|
||||
_pwr = _active_high;
|
||||
ThisThread::sleep_for(650); // from BG96_Hardware_Design_V1.1
|
||||
_pwr = !_active_high;
|
||||
tr_info("QUECTEL_BG96::soft_power_on");
|
||||
// check if modem was powered on already
|
||||
if (wake_up()) {
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
if (!wake_up(true)) {
|
||||
tr_error("Modem not responding");
|
||||
soft_power_off();
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
nsapi_error_t QUECTEL_BG96::init()
|
||||
nsapi_error_t QUECTEL_BG96::soft_power_off()
|
||||
{
|
||||
setup_at_handler();
|
||||
|
||||
int retry = 0;
|
||||
|
||||
_at->lock();
|
||||
_at->flush();
|
||||
_at->at_cmd_discard("E0", ""); // echo off
|
||||
|
||||
_at->at_cmd_discard("+CMEE", "=1"); // verbose responses
|
||||
|
||||
_at->cmd_start("AT+QPOWD");
|
||||
_at->cmd_stop_read_resp();
|
||||
if (_at->get_last_error() != NSAPI_ERROR_OK) {
|
||||
return _at->unlock_return_error();
|
||||
}
|
||||
|
||||
do {
|
||||
_at->clear_error();
|
||||
_at->at_cmd_discard("+CFUN", "=1"); // set full functionality
|
||||
if (_at->get_last_error() == NSAPI_ERROR_OK) {
|
||||
break;
|
||||
tr_warn("Force modem off");
|
||||
if (_pwr.is_connected()) {
|
||||
press_button(_pwr, 650); // BG96_Hardware_Design_V1.1: Power off signal at least 650 ms
|
||||
}
|
||||
// wait some time that modem gets ready for CFUN command, and try again
|
||||
retry++;
|
||||
ThisThread::sleep_for(64); // experimental value
|
||||
} while (retry < 3);
|
||||
|
||||
}
|
||||
return _at->unlock_return_error();
|
||||
}
|
||||
|
||||
|
@ -215,3 +158,52 @@ void QUECTEL_BG96::urc_pdpdeact()
|
|||
}
|
||||
send_disconnect_to_context(cid);
|
||||
}
|
||||
|
||||
void QUECTEL_BG96::press_button(DigitalOut &button, uint32_t timeout)
|
||||
{
|
||||
if (!button.is_connected()) {
|
||||
return;
|
||||
}
|
||||
button = _active_high;
|
||||
ThisThread::sleep_for(timeout);
|
||||
button = !_active_high;
|
||||
}
|
||||
|
||||
bool QUECTEL_BG96::wake_up(bool reset)
|
||||
{
|
||||
// check if modem is already ready
|
||||
_at->lock();
|
||||
_at->flush();
|
||||
_at->set_at_timeout(30);
|
||||
_at->cmd_start("AT");
|
||||
_at->cmd_stop_read_resp();
|
||||
nsapi_error_t err = _at->get_last_error();
|
||||
_at->restore_at_timeout();
|
||||
_at->unlock();
|
||||
// modem is not responding, power it on
|
||||
if (err != NSAPI_ERROR_OK) {
|
||||
if (!reset) {
|
||||
// BG96_Hardware_Design_V1.1 requires VBAT to be stable over 30 ms, that's handled above
|
||||
tr_info("Power on modem");
|
||||
press_button(_pwr, 250); // BG96_Hardware_Design_V1.1 requires time 100 ms, but 250 ms seems to be more robust
|
||||
} else {
|
||||
tr_warn("Reset modem");
|
||||
press_button(_rst, 150); // BG96_Hardware_Design_V1.1 requires RESET_N timeout at least 150 ms
|
||||
}
|
||||
_at->lock();
|
||||
// According to BG96_Hardware_Design_V1.1 USB is active after 4.2s, but it seems to take over 5s
|
||||
_at->set_at_timeout(6000);
|
||||
_at->resp_start();
|
||||
_at->set_stop_tag("RDY");
|
||||
bool rdy = _at->consume_to_stop_tag();
|
||||
_at->set_stop_tag(OK);
|
||||
_at->restore_at_timeout();
|
||||
_at->unlock();
|
||||
if (!rdy) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// sync to check that AT is really responsive and to clear garbage
|
||||
return _at->sync(500);
|
||||
}
|
||||
|
|
|
@ -41,17 +41,16 @@ protected: // AT_CellularDevice
|
|||
virtual AT_CellularContext *create_context_impl(ATHandler &at, const char *apn, bool cp_req = false, bool nonip_req = false);
|
||||
virtual AT_CellularInformation *open_information_impl(ATHandler &at);
|
||||
virtual void set_ready_cb(Callback<void()> callback);
|
||||
virtual nsapi_error_t hard_power_on();
|
||||
virtual nsapi_error_t hard_power_off();
|
||||
virtual nsapi_error_t soft_power_on();
|
||||
virtual nsapi_error_t init();
|
||||
virtual nsapi_error_t soft_power_off();
|
||||
virtual void set_at_urcs_impl();
|
||||
|
||||
public:
|
||||
void handle_urc(FileHandle *fh);
|
||||
|
||||
private:
|
||||
nsapi_error_t press_power_button(uint32_t timeout);
|
||||
void press_button(DigitalOut &button, uint32_t timeout);
|
||||
bool wake_up(bool reset = false);
|
||||
bool _active_high;
|
||||
DigitalOut _pwr;
|
||||
DigitalOut _rst;
|
||||
|
|
Loading…
Reference in New Issue