Wiz-IO / Arduino-Quectel-BC66

Arduino port for Quectel BC66 LTE Narow Band modules ( OpenCPU based )
46 stars 21 forks source link

BC66 : use "errno" in nbUdp.cpp cause reset #17

Closed artofdestroy closed 3 years ago

artofdestroy commented 4 years ago

Hello

My application is using BC66 module to send UDP data and receive ack from sever, but when I use nbUDP::parsePacket() to check for an incoming packet, the module suddenly reset.

After some printf debug, I suspect that program reset at line 194 in nbUdp.cpp when its try to call errno macro, so I end up comment that section from

    if ((len = lwip_recvfrom(udp_server, buf, 1460, MSG_DONTWAIT, (struct sockaddr *)&si_other, (socklen_t *)&slen)) == -1)
    {
        delete[] buf;
        if (errno == EWOULDBLOCK)
        {
            return 0;
        }
        DEBUG_UDP("could not receive data: %d", errno);
        return 0;
    }

to

    if ((len = lwip_recvfrom(udp_server, buf, 1460, MSG_DONTWAIT, (struct sockaddr *)&si_other, (socklen_t *)&slen)) == -1)
    {
        delete[] buf;
        // if (errno == EWOULDBLOCK)
        // {
        //     return 0;
        // }
        // DEBUG_UDP("could not receive data: %d", errno);
        return 0;
    }

and every thing work fine(till now). Am I do something wrong or not use nbUDP correct way.

code

#include <Arduino.h>
#include "nbUdp.h"

nbUDP udp_obj;
uint16_t local_port = 5006;
uint16_t svr_port = 5005;
IPAddress svr_ip(11,22,33,44);
char dummy_data[] = "test bc66 udp";

unsigned int sys_sec = 0;
unsigned int snd_sec = 0;
unsigned int snd_interval_sec = 60;
char resp[128];

static inline bool chk_interval(unsigned int time_current,unsigned int t0,unsigned int interval)
{
  return (time_current > t0 + interval || (time_current < t0 && time_current > interval));
}

void setup() {
    Serial.begin(115200);
    Serial.debug();
    Serial.println("App start");
    Dev.waitSimReady();
    Dev.waitCereg();
    delay(500);
    Serial.println("Net rdy");
    udp_obj.begin(local_port);
    sys_sec = seconds();
    snd_sec = sys_sec;
}

void loop()
{
    bool snd_flag;
    int pkt_size;
    sys_sec = seconds();

    snd_flag = chk_interval(sys_sec, snd_sec, snd_interval_sec);
    if (snd_flag == true) {
        Serial.println("Sending...");
        udp_obj.beginPacket(svr_ip, svr_port);
        udp_obj.write((const uint8_t *)dummy_data, strlen(dummy_data));
        udp_obj.endPacket();
        Serial.println("Sended");
        snd_sec = sys_sec;
    }

    pkt_size = udp_obj.parsePacket();
    if (pkt_size > 0) {
        Serial.println("Packet received");
        udp_obj.read(resp, pkt_size);
        Serial.write(resp, pkt_size);
        Serial.println("");
    }

    delay(100);
}

Board : Olimex-NB-IoT-DevKit with BC66NBR01A07 FW Platform version : 5dbec3f platformio.ini

[env:Olimex-NB-IoT-DevKit]
platform = quectel
board = Olimex-NB-IoT-DevKit
framework = arduino
board_build.firmware = BC66R01A07
upload_port = COM59
monitor_port = COM59
monitor_speed = 115200
Wiz-IO commented 4 years ago

Thanks, will correct soon..

try play:

int ERROR = 0; getsockopt (socket_fd, SOL_SOCKET, SO_ERROR, &ERROR, sizeof(ERROR)); to detect EWOULDBLOCK

artofdestroy commented 4 years ago

got error when compile getsockopt was not declared in this scope but use lwip_getsockopt is ok. Edit nbUDP::parsePacket() to

int nbUDP::parsePacket()
{
    int ERROR = 0;
    socklen_t optlen = sizeof(ERROR);

    if (rx_buffer)
        return 0;
    struct sockaddr_in si_other;
    int slen = sizeof(si_other), len;
    char *buf = new char[1460];
    if (!buf)
        return 0;
    if ((len = lwip_recvfrom(udp_server, buf, 1460, MSG_DONTWAIT, (struct sockaddr *)&si_other, (socklen_t *)&slen)) == -1)
    {
        delete[] buf;
        lwip_getsockopt (udp_server, SOL_SOCKET, SO_ERROR, &ERROR, &optlen);
        if (ERROR == EWOULDBLOCK) // use lwip_getsockopt to detect instead of "errno" macro
        {
            return 0;
        }
        DEBUG_UDP("could not receive data: %d", errno);
        return 0;
    }
    remote_ip = IPAddress(si_other.sin_addr.s_addr);
    remote_port = ntohs(si_other.sin_port);
    if (len > 0)
    {
        rx_buffer = new cbuf(len);
        rx_buffer->write(buf, len);
    }
    delete[] buf;
    return len;
}

confirmed can detect EWOULDBLOCK.

Wiz-IO commented 4 years ago

yep :) will correct soon