@@ -58,6 +58,8 @@ ESP8266::ESP8266(PinName tx, PinName rx, bool debug, PinName rts, PinName cts)
5858 _error(false ),
5959 _busy(false ),
6060 _reset_done(false ),
61+ _prev_send_ok_pending(false ),
62+ _send_fail_received(false ),
6163 _conn_status(NSAPI_STATUS_DISCONNECTED)
6264{
6365 _serial.set_baud (MBED_CONF_ESP8266_SERIAL_BAUDRATE);
@@ -614,7 +616,16 @@ bool ESP8266::dns_lookup(const char *name, char *ip)
614616
615617nsapi_error_t ESP8266::send (int id, const void *data, uint32_t amount)
616618{
619+ if (_prev_send_ok_pending && _sock_i[id].proto == NSAPI_TCP) {
620+ tr_debug (" send(): Previous packet was not ACK-ed with SEND OK." );
621+ return NSAPI_ERROR_WOULD_BLOCK;
622+ }
623+
617624 nsapi_error_t ret = NSAPI_ERROR_DEVICE_ERROR;
625+ _send_fail_received = false ;
626+ int bytes_confirmed = 0 ;
627+ constexpr unsigned int send_ack_retries = 3 ;
628+
618629 // +CIPSEND supports up to 2048 bytes at a time
619630 // Data stream can be truncated
620631 if (amount > 2048 && _sock_i[id].proto == NSAPI_TCP) {
@@ -635,35 +646,83 @@ nsapi_error_t ESP8266::send(int id, const void *data, uint32_t amount)
635646 }
636647
637648 if (!_parser.recv (" >" )) {
649+ // This means ESP8266 hasn't even started to receive data
638650 tr_debug (" send(): Didn't get \" >\" " );
639- ret = NSAPI_ERROR_WOULD_BLOCK;
651+ if (_sock_i[id].proto == NSAPI_TCP) {
652+ ret = NSAPI_ERROR_WOULD_BLOCK; // Not neccesarily critical error.
653+ } else if (_sock_i[id].proto == NSAPI_UDP) {
654+ ret = NSAPI_ERROR_NO_MEMORY;
655+ }
656+ goto END;
657+ }
658+
659+ if (_parser.write ((char *)data, (int )amount) < 0 ) {
660+ tr_debug (" send(): Failed to write serial data" );
661+ // Serial is not working, serious error, reset needed.
662+ ret = NSAPI_ERROR_DEVICE_ERROR;
640663 goto END;
641664 }
642665
643- if (_parser.write ((char *)data, (int )amount) >= 0 && _parser.recv (" SEND OK" )) {
644- ret = NSAPI_ERROR_OK;
666+ // The "Recv X bytes" is not documented.
667+ if (!_parser.recv (" Recv %d bytes" , &bytes_confirmed)) {
668+ tr_debug (" send(): Bytes not confirmed." );
669+ ret = NSAPI_ERROR_DEVICE_ERROR;
670+ goto END;
671+ } else if (bytes_confirmed != amount) {
672+ tr_debug (" send(): Error: confirmed %d bytes, but expected %d." , bytes_confirmed, amount);
673+ ret = NSAPI_ERROR_DEVICE_ERROR;
674+ goto END;
675+ }
676+
677+ // We might receive "busy s/p...", "SEND OK" or "SEND FAIL" from modem, so we need to check that also
678+ _parser.oob (" SEND FAIL" , callback (this , &ESP8266::_oob_send_fail_received));
679+ for (unsigned int i = send_ack_retries; i > 0 ; i--) {
680+ if (!_parser.recv (" SEND OK" )) {
681+ if (_error || _send_fail_received) {
682+ _parser.remove_oob (" SEND FAIL" );
683+ goto END;
684+ }
685+ if (_busy) {
686+ _busy = false ;
687+ tr_debug (" send(): Busy, %d retries left..." , i - 1 );
688+ } else {
689+ tr_debug (" send(): Not busy, but no SEND OK. %d retries left..." , i - 1 );
690+ }
691+ } else {
692+ ret = amount; // Got "SEND OK" - return number of bytes.
693+ goto END;
694+ }
645695 }
646696
697+ // ESP8266 ACKed data over serial, but did not ACK over TCP or report any error.
698+ _prev_send_ok_pending = true ;
699+ _parser.oob (" SEND OK" , callback (this , &ESP8266::_oob_send_ok_received));
700+ ret = amount;
701+
647702END:
648703 _process_oob (ESP8266_RECV_TIMEOUT, true ); // Drain USART receive register to avoid data overrun
649704
650705 // error hierarchy, from low to high
651706 if (_busy) {
652707 ret = NSAPI_ERROR_WOULD_BLOCK;
653- tr_debug (" send(): Modem busy. " );
654- }
655-
656- if (ret == NSAPI_ERROR_DEVICE_ERROR) {
657- ret = NSAPI_ERROR_WOULD_BLOCK;
658- tr_debug (" send(): Send failed." );
708+ tr_debug (" send(): Modem busy." );
659709 }
660710
661711 if (_error) {
662712 ret = NSAPI_ERROR_CONNECTION_LOST;
663713 tr_debug (" send(): Connection disrupted." );
664714 }
665715
666- if (!_sock_i[id].open && ret != NSAPI_ERROR_OK) {
716+ if (_send_fail_received) {
717+ if (_sock_i[id].proto == NSAPI_TCP) {
718+ ret = NSAPI_ERROR_DEVICE_ERROR;
719+ } else {
720+ ret = NSAPI_ERROR_NO_MEMORY;
721+ }
722+ tr_debug (" send(): SEND FAIL received." );
723+ }
724+
725+ if (!_sock_i[id].open && ret < 0 ) {
667726 ret = NSAPI_ERROR_CONNECTION_LOST;
668727 tr_debug (" send(): Socket closed abruptly." );
669728 }
@@ -1205,6 +1264,18 @@ void ESP8266::_oob_connection_status()
12051264 _conn_stat_cb ();
12061265}
12071266
1267+ void ESP8266::_oob_send_ok_received ()
1268+ {
1269+ tr_debug (" _oob_send_ok_received called" );
1270+ _prev_send_ok_pending = false ;
1271+ }
1272+
1273+ void ESP8266::_oob_send_fail_received ()
1274+ {
1275+ tr_debug (" _oob_send_fail_received called" );
1276+ _send_fail_received = true ;
1277+ }
1278+
12081279int8_t ESP8266::default_wifi_mode ()
12091280{
12101281 int8_t mode;
0 commit comments