Skip to content

Commit 978296a

Browse files
authored
Merge pull request #11372 from AriParkkila/bg96-pwr
Cellular: Fix BG96 power on and connect
2 parents 0427bb7 + cb20277 commit 978296a

File tree

9 files changed

+100
-90
lines changed

9 files changed

+100
-90
lines changed

UNITTESTS/features/cellular/framework/AT/at_cellulardevice/unittest.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ set(unittest-test-sources
4343
stubs/SerialBase_stub.cpp
4444
stubs/CellularStateMachine_stub.cpp
4545
stubs/CellularContext_stub.cpp
46+
stubs/ThisThread_stub.cpp
4647
stubs/ConditionVariable_stub.cpp
4748
stubs/Mutex_stub.cpp
4849
)

features/cellular/framework/AT/ATHandler.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -926,7 +926,7 @@ void ATHandler::set_3gpp_error(int err, DeviceErrorType error_type)
926926
for (size_t i = 0; i < sizeof(map_3gpp_errors) / sizeof(map_3gpp_errors[0]); i++) {
927927
if (map_3gpp_errors[i][0] == err) {
928928
_last_3gpp_error = map_3gpp_errors[i][1];
929-
tr_debug("AT3GPP error code %d", get_3gpp_error());
929+
tr_error("AT3GPP error code %d", get_3gpp_error());
930930
break;
931931
}
932932
}
@@ -943,7 +943,7 @@ void ATHandler::at_error(bool error_code_expected, DeviceErrorType error_type)
943943
set_3gpp_error(err, error_type);
944944
_last_at_err.errCode = err;
945945
_last_at_err.errType = error_type;
946-
tr_error("AT error code %ld", err);
946+
tr_warn("AT error code %ld", err);
947947
} else {
948948
tr_warn("ATHandler ERROR reading failed");
949949
}

features/cellular/framework/AT/AT_CellularContext.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,7 @@ nsapi_error_t AT_CellularContext::open_data_channel()
608608
connected, or timeout after 30 seconds*/
609609
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);
610610
if (err) {
611+
tr_error("nsapi_ppp_connect failed");
611612
ppp_disconnected();
612613
}
613614

@@ -993,6 +994,7 @@ void AT_CellularContext::cellular_callback(nsapi_event_t ev, intptr_t ptr)
993994
tr_info("cellular_callback: PPP mode and NSAPI_STATUS_DISCONNECTED");
994995
_cb_data.error = NSAPI_ERROR_NO_CONNECTION;
995996
_is_connected = false;
997+
ppp_disconnected();
996998
}
997999
}
9981000
#else

features/cellular/framework/AT/AT_CellularDevice.cpp

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* limitations under the License.
1616
*/
1717

18+
#include "rtos/ThisThread.h"
1819
#include "CellularUtil.h"
1920
#include "AT_CellularDevice.h"
2021
#include "AT_CellularInformation.h"
@@ -202,6 +203,7 @@ nsapi_error_t AT_CellularDevice::get_sim_state(SimState &state)
202203
_at->flush();
203204
nsapi_error_t error = _at->at_cmd_str("+CPIN", "?", simstr, sizeof(simstr));
204205
ssize_t len = strlen(simstr);
206+
device_err_t err = _at->get_last_device_error();
205207
_at->unlock();
206208

207209
if (len != -1) {
@@ -213,7 +215,6 @@ nsapi_error_t AT_CellularDevice::get_sim_state(SimState &state)
213215
state = SimStatePukNeeded;
214216
} else {
215217
simstr[len] = '\0';
216-
tr_error("Unknown SIM state %s", simstr);
217218
state = SimStateUnknown;
218219
}
219220
} else {
@@ -229,7 +230,11 @@ nsapi_error_t AT_CellularDevice::get_sim_state(SimState &state)
229230
tr_error("SIM PUK required");
230231
break;
231232
case SimStateUnknown:
232-
tr_warn("SIM state unknown");
233+
if (err.errType == DeviceErrorTypeErrorCME && err.errCode == 14) {
234+
tr_info("SIM busy");
235+
} else {
236+
tr_warn("SIM state unknown");
237+
}
233238
break;
234239
default:
235240
tr_info("SIM is ready");
@@ -443,12 +448,18 @@ nsapi_error_t AT_CellularDevice::init()
443448
setup_at_handler();
444449

445450
_at->lock();
446-
_at->flush();
447-
_at->at_cmd_discard("E0", "");
448-
449-
_at->at_cmd_discard("+CMEE", "=1");
450-
451-
_at->at_cmd_discard("+CFUN", "=1");
451+
for (int retry = 1; retry <= 3; retry++) {
452+
_at->clear_error();
453+
_at->flush();
454+
_at->at_cmd_discard("E0", "");
455+
_at->at_cmd_discard("+CMEE", "=1");
456+
_at->at_cmd_discard("+CFUN", "=1");
457+
if (_at->get_last_error() == NSAPI_ERROR_OK) {
458+
break;
459+
}
460+
tr_debug("Wait 100ms to init modem");
461+
rtos::ThisThread::sleep_for(100); // let modem have time to get ready
462+
}
452463

453464
return _at->unlock_return_error();
454465
}

features/cellular/framework/AT/AT_CellularNetwork.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,9 @@ nsapi_error_t AT_CellularNetwork::set_registration(const char *plmn)
211211
if (!plmn) {
212212
tr_debug("Automatic network registration");
213213
NWRegisteringMode mode;
214-
get_network_registering_mode(mode);
215-
214+
if (get_network_registering_mode(mode) != NSAPI_ERROR_OK) {
215+
return NSAPI_ERROR_DEVICE_ERROR;
216+
}
216217
if (mode != NWModeAutomatic) {
217218
return _at.at_cmd_discard("+COPS", "=0");
218219
}

features/cellular/framework/device/CellularDevice.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,9 @@ nsapi_error_t CellularDevice::shutdown()
234234
}
235235
CellularContext *curr = get_context_list();
236236
while (curr) {
237+
if (curr->is_connected()) {
238+
curr->disconnect();
239+
}
237240
curr->cellular_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED);
238241
curr = (CellularContext *)curr->_next;
239242
}

features/cellular/framework/device/CellularStateMachine.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ void CellularStateMachine::state_device_ready()
367367
}
368368
} else {
369369
_status = 0;
370+
_is_retry = true;
370371
enter_to_state(STATE_INIT);
371372
}
372373
}

features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96.cpp

Lines changed: 66 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -97,92 +97,35 @@ void QUECTEL_BG96::set_ready_cb(Callback<void()> callback)
9797
_at->set_urc_handler(DEVICE_READY_URC, callback);
9898
}
9999

100-
nsapi_error_t QUECTEL_BG96::hard_power_on()
101-
{
102-
if (_pwr.is_connected()) {
103-
tr_info("Modem power on");
104-
ThisThread::sleep_for(250);
105-
_pwr = !_active_high;
106-
ThisThread::sleep_for(250); // BG96_Hardware_Design_V1.1 says 100 ms, but 250 ms seems to be more robust
107-
_pwr = _active_high;
108-
ThisThread::sleep_for(500);
109-
}
110-
111-
return NSAPI_ERROR_OK;
112-
}
113-
114100
nsapi_error_t QUECTEL_BG96::soft_power_on()
115-
{
116-
if (!_rst.is_connected()) {
117-
return NSAPI_ERROR_OK;
118-
}
119-
120-
tr_info("Reset modem");
121-
_rst = !_active_high;
122-
ThisThread::sleep_for(100);
123-
_rst = _active_high;
124-
ThisThread::sleep_for(150 + 460); // RESET_N timeout from BG96_Hardware_Design_V1.1
125-
_rst = !_active_high;
126-
ThisThread::sleep_for(500);
127-
128-
// wait for RDY
129-
_at->lock();
130-
_at->set_at_timeout(10 * 1000);
131-
_at->resp_start();
132-
_at->set_stop_tag("RDY");
133-
bool rdy = _at->consume_to_stop_tag();
134-
_at->set_stop_tag(OK);
135-
_at->restore_at_timeout();
136-
137-
if (!rdy) {
138-
// check if modem was silently powered on
139-
_at->clear_error();
140-
_at->set_at_timeout(100);
141-
_at->at_cmd_discard("", ""); //Send AT
142-
_at->restore_at_timeout();
143-
}
144-
return _at->unlock_return_error();
145-
}
146-
147-
nsapi_error_t QUECTEL_BG96::hard_power_off()
148101
{
149102
if (_pwr.is_connected()) {
150-
tr_info("Modem power off");
151-
_pwr = _active_high;
152-
ThisThread::sleep_for(650); // from BG96_Hardware_Design_V1.1
153-
_pwr = !_active_high;
103+
tr_info("QUECTEL_BG96::soft_power_on");
104+
// check if modem was powered on already
105+
if (wake_up()) {
106+
return NSAPI_ERROR_OK;
107+
}
108+
if (!wake_up(true)) {
109+
tr_error("Modem not responding");
110+
soft_power_off();
111+
return NSAPI_ERROR_DEVICE_ERROR;
112+
}
154113
}
155114

156115
return NSAPI_ERROR_OK;
157116
}
158117

159-
nsapi_error_t QUECTEL_BG96::init()
118+
nsapi_error_t QUECTEL_BG96::soft_power_off()
160119
{
161-
setup_at_handler();
162-
163-
int retry = 0;
164-
165120
_at->lock();
166-
_at->flush();
167-
_at->at_cmd_discard("E0", ""); // echo off
168-
169-
_at->at_cmd_discard("+CMEE", "=1"); // verbose responses
170-
121+
_at->cmd_start("AT+QPOWD");
122+
_at->cmd_stop_read_resp();
171123
if (_at->get_last_error() != NSAPI_ERROR_OK) {
172-
return _at->unlock_return_error();
173-
}
174-
175-
do {
176-
_at->clear_error();
177-
_at->at_cmd_discard("+CFUN", "=1"); // set full functionality
178-
if (_at->get_last_error() == NSAPI_ERROR_OK) {
179-
break;
124+
tr_warn("Force modem off");
125+
if (_pwr.is_connected()) {
126+
press_button(_pwr, 650); // BG96_Hardware_Design_V1.1: Power off signal at least 650 ms
180127
}
181-
// wait some time that modem gets ready for CFUN command, and try again
182-
retry++;
183-
ThisThread::sleep_for(64); // experimental value
184-
} while (retry < 3);
185-
128+
}
186129
return _at->unlock_return_error();
187130
}
188131

@@ -215,3 +158,52 @@ void QUECTEL_BG96::urc_pdpdeact()
215158
}
216159
send_disconnect_to_context(cid);
217160
}
161+
162+
void QUECTEL_BG96::press_button(DigitalOut &button, uint32_t timeout)
163+
{
164+
if (!button.is_connected()) {
165+
return;
166+
}
167+
button = _active_high;
168+
ThisThread::sleep_for(timeout);
169+
button = !_active_high;
170+
}
171+
172+
bool QUECTEL_BG96::wake_up(bool reset)
173+
{
174+
// check if modem is already ready
175+
_at->lock();
176+
_at->flush();
177+
_at->set_at_timeout(30);
178+
_at->cmd_start("AT");
179+
_at->cmd_stop_read_resp();
180+
nsapi_error_t err = _at->get_last_error();
181+
_at->restore_at_timeout();
182+
_at->unlock();
183+
// modem is not responding, power it on
184+
if (err != NSAPI_ERROR_OK) {
185+
if (!reset) {
186+
// BG96_Hardware_Design_V1.1 requires VBAT to be stable over 30 ms, that's handled above
187+
tr_info("Power on modem");
188+
press_button(_pwr, 250); // BG96_Hardware_Design_V1.1 requires time 100 ms, but 250 ms seems to be more robust
189+
} else {
190+
tr_warn("Reset modem");
191+
press_button(_rst, 150); // BG96_Hardware_Design_V1.1 requires RESET_N timeout at least 150 ms
192+
}
193+
_at->lock();
194+
// According to BG96_Hardware_Design_V1.1 USB is active after 4.2s, but it seems to take over 5s
195+
_at->set_at_timeout(6000);
196+
_at->resp_start();
197+
_at->set_stop_tag("RDY");
198+
bool rdy = _at->consume_to_stop_tag();
199+
_at->set_stop_tag(OK);
200+
_at->restore_at_timeout();
201+
_at->unlock();
202+
if (!rdy) {
203+
return false;
204+
}
205+
}
206+
207+
// sync to check that AT is really responsive and to clear garbage
208+
return _at->sync(500);
209+
}

features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,16 @@ class QUECTEL_BG96 : public AT_CellularDevice {
4141
virtual AT_CellularContext *create_context_impl(ATHandler &at, const char *apn, bool cp_req = false, bool nonip_req = false);
4242
virtual AT_CellularInformation *open_information_impl(ATHandler &at);
4343
virtual void set_ready_cb(Callback<void()> callback);
44-
virtual nsapi_error_t hard_power_on();
45-
virtual nsapi_error_t hard_power_off();
4644
virtual nsapi_error_t soft_power_on();
47-
virtual nsapi_error_t init();
45+
virtual nsapi_error_t soft_power_off();
4846
virtual void set_at_urcs_impl();
4947

5048
public:
5149
void handle_urc(FileHandle *fh);
5250

5351
private:
54-
nsapi_error_t press_power_button(uint32_t timeout);
52+
void press_button(DigitalOut &button, uint32_t timeout);
53+
bool wake_up(bool reset = false);
5554
bool _active_high;
5655
DigitalOut _pwr;
5756
DigitalOut _rst;

0 commit comments

Comments
 (0)