diff --git a/src/proto/fd/tiny_fd.c b/src/proto/fd/tiny_fd.c index a13cd3ca..7b030fa3 100644 --- a/src/proto/fd/tiny_fd.c +++ b/src/proto/fd/tiny_fd.c @@ -583,11 +583,12 @@ int tiny_fd_run_rx(tiny_fd_handle_t handle, uint16_t timeout) { uint16_t ts = tiny_millis(); int result; - LOG(TINY_LOG_DEB, "[%p] FD run rx cycle ENTER with timeout %u ms\n", handle, timeout); +// LOG(TINY_LOG_DEB, "[%p] FD run rx cycle ENTER with timeout %u ms\n", handle, timeout); do { uint8_t data; result = handle->read_func( handle->user_data, &data, sizeof(data) ); +// LOG(TINY_LOG_DEB, "[%p] FD run rx process data ENTER\n", handle); if ( result > 0 ) { int len; @@ -602,8 +603,9 @@ int tiny_fd_run_rx(tiny_fd_handle_t handle, uint16_t timeout) } } while ( len == 0); } +// LOG(TINY_LOG_DEB, "[%p] FD run rx process data EXIT\n", handle); } while ((uint16_t)(tiny_millis() - ts) < timeout); - LOG(TINY_LOG_DEB, "[%p] FD run rx cycle EXIT\n", handle); +// LOG(TINY_LOG_DEB, "[%p] FD run rx cycle EXIT\n", handle); return result; } @@ -719,7 +721,9 @@ static void tiny_fd_connected_on_idle_timeout( tiny_fd_handle_t handle ) static void tiny_fd_disconnected_on_idle_timeout( tiny_fd_handle_t handle ) { - if ( __time_passed_since_last_frame_received( handle ) >= handle->retry_timeout ) + tiny_mutex_lock( &handle->frames.mutex ); + if ( __time_passed_since_last_frame_received( handle ) >= handle->retry_timeout || + __number_of_awaiting_tx_i_frames( handle ) > 0 ) { LOG(TINY_LOG_ERR, "[%p] ABM connection is not established\n", handle); // Try to establish ABM connection @@ -730,6 +734,7 @@ static void tiny_fd_disconnected_on_idle_timeout( tiny_fd_handle_t handle ) __put_u_s_frame_to_tx_queue( handle, &frame, 2 ); handle->frames.last_ka_ts = tiny_millis(); } + tiny_mutex_unlock( &handle->frames.mutex ); } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/proto/hdlc/tiny_hdlc.c b/src/proto/hdlc/tiny_hdlc.c index 7486579b..46e7c278 100644 --- a/src/proto/hdlc/tiny_hdlc.c +++ b/src/proto/hdlc/tiny_hdlc.c @@ -274,7 +274,7 @@ static int hdlc_send_end( hdlc_handle_t handle ) int hdlc_run_tx( hdlc_handle_t handle ) { - LOG(TINY_LOG_DEB, "[HDLC:%p] hdlc_run_tx\n", handle); + LOG(TINY_LOG_DEB, "[HDLC:%p] hdlc_run_tx ENTER\n", handle); int result = 0; for (;;) { @@ -290,6 +290,7 @@ int hdlc_run_tx( hdlc_handle_t handle ) result += temp_result; // break; } + LOG(TINY_LOG_DEB, "[HDLC:%p] hdlc_run_tx EXIT\n", handle); return result; } @@ -564,7 +565,7 @@ int hdlc_run_rx( hdlc_handle_t handle, const void *data, int len, int *error ) { *error = TINY_SUCCESS; } - while ( len ) + while ( len || handle->rx.state == hdlc_read_end ) { int temp_result = handle->rx.state( handle, (const uint8_t *)data, len ); if ( temp_result <=0 ) diff --git a/unittest/fd_tests.cpp b/unittest/fd_tests.cpp index e03974e9..81b7dc74 100644 --- a/unittest/fd_tests.cpp +++ b/unittest/fd_tests.cpp @@ -90,15 +90,14 @@ TEST(FD, multithread_alternate_read_test) TEST(FD, arduino_to_pc) { std::atomic arduino_timedout_frames{}; - FakeConnection conn( 4096, 32 ); // PC side has larger UART buffer: 4096, arduino side has small uart buffer + FakeConnection conn( 4096, 64 ); // PC side has larger UART buffer: 4096, arduino side has small uart buffer TinyHelperFd pc( &conn.endpoint1(), 4096, nullptr, 4, 400 ); TinyHelperFd arduino( &conn.endpoint2(), tiny_fd_buffer_size_by_mtu(64,4), [&arduino, &arduino_timedout_frames](uint16_t,uint8_t*b,int s)->void { if ( arduino.send(b, s) == TINY_ERR_TIMEOUT ) arduino_timedout_frames++; }, 4, 0 ); conn.endpoint2().setTimeout( 0 ); conn.endpoint2().disable(); - // TODO: Due to slow emulator - conn.setSpeed( 256000 ); + conn.setSpeed( 115200 ); pc.run(true); // sent 100 small packets from pc to arduino pc.send( 100, "Generated frame. test in progress" ); @@ -112,8 +111,8 @@ TEST(FD, arduino_to_pc) arduino.run_tx(); if ( static_cast(tiny_millis() - start_ms) > 2000 ) break; } while ( pc.tx_count() != 100 && pc.rx_count() + arduino_timedout_frames < 99 ); - // it is allowed to miss several frames - if ( 98 - arduino_timedout_frames > pc.rx_count() ) + // it is allowed to miss several frames due to arduino cycle completes before last messages are delivered + if ( 96 - arduino_timedout_frames > pc.rx_count() ) { CHECK_EQUAL( 100 - arduino_timedout_frames, pc.rx_count() ); } @@ -149,21 +148,22 @@ TEST(FD, error_on_single_I_send) // TX2: U, U, I, FakeConnection conn; uint16_t nsent = 0; - TinyHelperFd helper1( &conn.endpoint1(), 4096, nullptr, 7, 250 ); - TinyHelperFd helper2( &conn.endpoint2(), 4096, nullptr, 7, 250 ); + TinyHelperFd helper1( &conn.endpoint1(), 4096, nullptr, 7, 1000 ); + TinyHelperFd helper2( &conn.endpoint2(), 4096, nullptr, 7, 1000 ); conn.line2().generate_single_error( 6 + 6 + 3 ); // Put error on I-frame helper1.run(true); helper2.run(true); - for (nsent = 0; nsent < 1; nsent++) + // retransmissiomn must happen very quickly since FD detects out-of-order frames + for (nsent = 0; nsent < 2; nsent++) { uint8_t txbuf[4] = { 0xAA, 0xFF, 0xCC, 0x66 }; int result = helper2.send( txbuf, sizeof(txbuf) ); CHECK_EQUAL( TINY_SUCCESS, result ); } // wait until last frame arrives - helper1.wait_until_rx_count( 1, 250 ); - CHECK_EQUAL( 1, helper1.rx_count() ); + helper1.wait_until_rx_count( 2, 300 ); + CHECK_EQUAL( 2, helper1.rx_count() ); } TEST(FD, error_on_rej) diff --git a/unittest/hdlc_tests.cpp b/unittest/hdlc_tests.cpp index 8f4cf6fb..df30af33 100644 --- a/unittest/hdlc_tests.cpp +++ b/unittest/hdlc_tests.cpp @@ -138,7 +138,7 @@ TEST(HDLC, arduino_to_pc) { uint8_t ardu_buffer[512]; // PC side has a larger buffer - FakeConnection conn( 128, 32 ); + FakeConnection conn( 4096, 64 ); TinyHdlcHelper pc( &conn.endpoint1(), nullptr, nullptr, 512 ); TinyHdlcHelper arduino( &conn.endpoint2(), [&ardu_buffer, &arduino](uint8_t *buf, int len)->void { memcpy( ardu_buffer, buf,len ); @@ -161,12 +161,14 @@ TEST(HDLC, arduino_to_pc) arduino.run_rx(); arduino.run_tx(); if ( static_cast(tiny_millis() - startTs) > 2000 ) break; - } while (pc.tx_count() != 100 && arduino.tx_count() < 100 - tx_count); + } while (pc.tx_count() != 100 || arduino.tx_count() < 100 - tx_count); CHECK_EQUAL( 100, pc.tx_count() ); if ( arduino.rx_count() < 97 - tx_count ) CHECK_EQUAL( 100 - tx_count, arduino.rx_count() ); - CHECK_EQUAL( arduino.rx_count(), arduino.tx_count() ); + // Some frames can be lost on send due to very small tx buffer on arduino side + if ( arduino.rx_count() - 5 > arduino.tx_count() ) + CHECK_EQUAL( arduino.rx_count(), arduino.tx_count() ); if ( 95 - tx_count > pc.rx_count() ) CHECK_EQUAL( arduino.tx_count(), pc.rx_count() ); if ( conn.lostBytes() > 10 ) diff --git a/unittest/helpers/fake_endpoint.h b/unittest/helpers/fake_endpoint.h index 57b5dbc3..f73a186e 100644 --- a/unittest/helpers/fake_endpoint.h +++ b/unittest/helpers/fake_endpoint.h @@ -40,7 +40,7 @@ class FakeEndpoint FakeWire &m_tx; FakeWire &m_rx; std::mutex m_mutex; - int m_timeout = 1000; + int m_timeout = 10; }; diff --git a/unittest/helpers/fake_wire.h b/unittest/helpers/fake_wire.h index eb5bca14..b408c46d 100644 --- a/unittest/helpers/fake_wire.h +++ b/unittest/helpers/fake_wire.h @@ -33,8 +33,8 @@ class FakeWire public: FakeWire(int readbuf_size = 1024, int writebuf_size = 1024); ~FakeWire(); - int read(uint8_t * data, int length, int timeout = 200); - int write(const uint8_t * data, int length, int timeout = 200); + int read(uint8_t * data, int length, int timeout = 10); + int write(const uint8_t * data, int length, int timeout = 10); void generate_error_every_n_byte(int n) { m_errors.push_back( ErrorDesc{0, n, -1} ); }; void generate_single_error(int position) { m_errors.push_back( ErrorDesc{position, position, 1} ); }; void generate_error(int first, int period, int count = -1) { m_errors.push_back( ErrorDesc{first, period, count} ); };