Closed
Description
Description of defect
When trying to write to a TCP socket, AT command will trigger binary syntax mode meaning it sends socker_id + number of bytes and than <CR>
which is fine.
But then the lib should wait until character @
is received. And this is where the problem is - current implementation doesn't wait and sends it straight after AT command resulting in -3012
error because library is waiting for a response from mdm, but mdm is waiting for that binary data.
[00081375ms][INFO][CELL]: AT TX ( 9): AT+USOWR=
[00081381ms][INFO][CELL]: AT TX ( 1): 0
[00081385ms][INFO][CELL]: AT TX ( 1): ,
[00081390ms][INFO][CELL]: AT TX ( 1): 4
[00081395ms][INFO][CELL]: AT TX ( 1): <cr>
[00081400ms][INFO][CELL]: AT TX ( 5): TEST<00>
[00081406ms][INFO][CELL]: AT RX (13): AT+USOWR=0,4<cr>
[00081424ms][INFO][CELL]: AT RX ( 3): <cr><ln>@
[00141376ms][DBG ][CELL]: AT error -3012
[00141381ms][ERR ][CELL]: Socket 0 sendto 52.215.34.155 error -3012
Target(s) affected by this defect ?
SARA-G350
Toolchain(s) (name and version) displaying this defect ?
GCC-ARM 8.3.1
What version of Mbed-os are you using (tag or sha) ?
What version(s) of tools are you using. List all that apply (E.g. mbed-cli)
mbed-cli 1.10.1
How is this defect reproduced ?
#include "mbed.h"
#include "UBLOX_AT.h"
#include "CellularContext.h"
#if MBED_CONF_MBED_TRACE_ENABLE
#include "CellularLog.h"
#endif
EventQueue eQueue(32 * EVENTS_EVENT_SIZE);
CellularContext *mdm;
CellularDevice *mdm_device;
#define MDM_HW_FLOW
class myUblox : public UBLOX_AT {
public:
explicit myUblox(FileHandle *fh);
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 soft_power_off();
private:
DigitalOut pwrOn;
DigitalOut rst;
};
myUblox::myUblox(FileHandle *fh) :
UBLOX_AT(fh),
pwrOn(MDM_PWRON_pin, 0),
rst(MDM_RST_pin, 1) {
}
nsapi_error_t myUblox::hard_power_on() {
rst.write(0);
ThisThread::sleep_for(1000);
return NSAPI_ERROR_OK;
}
nsapi_error_t myUblox::hard_power_off() {
rst.write(1);
return NSAPI_ERROR_OK;
}
nsapi_error_t myUblox::soft_power_on() {
pwrOn.write(1);
ThisThread::sleep_for(150);
pwrOn.write(0);
ThisThread::sleep_for(100);
return NSAPI_ERROR_OK;
}
nsapi_error_t myUblox::soft_power_off() {
pwrOn.write(1);
ThisThread::sleep_for(1000);
pwrOn.write(0);
return NSAPI_ERROR_OK;
}
CellularDevice *CellularDevice::get_target_default_instance() {
static BufferedSerial serial(MDM_TX_pin, MDM_RX_pin, 115200);
#if defined(MDM_HW_FLOW)
serial.set_flow_control(SerialBase::RTSCTS, MDM_RTS_pin, MDM_CTS_pin);
#else
static DigitalOut rts(MDM_RTS_pin, 0);
#endif
static myUblox device(&serial);
return &device;
}
bool serverConnect() {
debug("Server connect\n");
nsapi_error_t ret = NSAPI_ERROR_PARAMETER;
TCPSocket socket;
const char *echo_string = "TEST";
char recv_buf[4];
SocketAddress server;
ret = mdm->gethostbyname("echo.mbedcloudtesting.com", &server);
if (ret == NSAPI_ERROR_OK) {
server.set_port(7);
ret = socket.open(mdm);
if (ret == NSAPI_ERROR_OK) {
debug("open OK\n");
ret = socket.connect(server);
if (ret == NSAPI_ERROR_OK || ret == NSAPI_ERROR_IS_CONNECTED) {
debug("connected\n");
ret = socket.send((void*) echo_string, strlen(echo_string));
if (ret >= NSAPI_ERROR_OK) {
debug("TCP: Sent %i Bytes\n", ret);
nsapi_size_or_error_t n = socket.recv((void*) recv_buf, sizeof(recv_buf));
socket.close();
if (n > 0) {
debug("Received from echo server %i bytes\n", n);
return true;
} else {
debug("Socket recv FAILED: %i\n", n);
}
} else {
debug("Socket send FAILED: %i\n", ret);
}
} else {
debug("connect FAILED: %i\n", ret);
}
} else {
debug("open FAILED\n");
}
} else {
printf("Couldn't resolve remote host, code: %d\n", ret);
}
return false;
}
void mdmConnect() {
debug("MDM connect\n");
nsapi_error_t ret = mdm->connect();
if (ret == NSAPI_ERROR_OK) {
debug("Network connected\n");
serverConnect();
return;
}
debug("Connecting failed\n");
}
bool mdmSetup() {
debug("Device setup\n");
mdm = CellularContext::get_default_instance();
if (mdm != NULL) {
mdm_device = mdm->get_device();
if (mdm_device != NULL) {
mdm_device->hard_power_on();
uint16_t timeout[8] = {1, 2, 4, 8, 16, 32, 64, 128};
mdm_device->set_retry_timeout_array(timeout, 8);
mdm->set_credentials("internet");
// mdm->attach(mdmCb);
mdm->set_blocking(true);
mdmConnect();
return true;
} else {
debug("No interface\n");
}
} else {
debug("No device\n");
}
return false;
}
#if MBED_CONF_MBED_TRACE_ENABLE
static Mutex trace_mutex;
static char time_st[50];
static char* trace_time(size_t ss) {
snprintf(time_st, 49, "[%08llums]", Kernel::get_ms_count());
return time_st;
}
static void trace_wait() {
trace_mutex.lock();
}
static void trace_release() {
trace_mutex.unlock();
}
void trace_init() {
mbed_trace_init();
mbed_trace_prefix_function_set(&trace_time);
mbed_trace_mutex_wait_function_set(trace_wait);
mbed_trace_mutex_release_function_set(trace_release);
mbed_cellular_trace::mutex_wait_function_set(trace_wait);
mbed_cellular_trace::mutex_release_function_set(trace_release);
}
#endif
int main() {
#if MBED_CONF_MBED_TRACE_ENABLE
trace_init();
#endif
Thread eQueueThread;
if (eQueueThread.start(callback(&eQueue, &EventQueue::dispatch_forever)) != osOK) {
debug("eQueueThread error\n");
}
mdmSetup();
mdm->disconnect();
while (1) {
ThisThread::sleep_for(osWaitForever);
}
}