From 8b029777e2cb6824950701919c34ec818462112a Mon Sep 17 00:00:00 2001 From: Daniel Tombeil Date: Tue, 2 May 2023 09:26:57 +1000 Subject: [PATCH] AP_HAL_ESP32: Adding receive_time_constraint_us() to UARTDriver to address GPS init and health issues - more work on receive_time_constraint_us() --- libraries/AP_HAL_ESP32/UARTDriver.cpp | 39 +++++++++++++++++++++++++++ libraries/AP_HAL_ESP32/UARTDriver.h | 20 ++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/libraries/AP_HAL_ESP32/UARTDriver.cpp b/libraries/AP_HAL_ESP32/UARTDriver.cpp index 1017476323..fb051800a6 100644 --- a/libraries/AP_HAL_ESP32/UARTDriver.cpp +++ b/libraries/AP_HAL_ESP32/UARTDriver.cpp @@ -72,6 +72,7 @@ void UARTDriver::begin(uint32_t b, uint16_t rxS, uint16_t txS) } } + _baudrate = b; } void UARTDriver::end() @@ -136,18 +137,26 @@ ssize_t IRAM_ATTR UARTDriver::read(uint8_t *buffer, uint16_t count) return 0; } + + _receive_timestamp_update(); + return ret; } bool IRAM_ATTR UARTDriver::read(uint8_t &byte) { + if (!_initialized) { return false; } if (!_readbuf.read_byte(&byte)) { return false; } + + _receive_timestamp_update(); + return true; + } void IRAM_ATTR UARTDriver::_timer_tick(void) @@ -212,4 +221,34 @@ bool UARTDriver::discard_input() return false; } +// record timestamp of new incoming data +void IRAM_ATTR UARTDriver::_receive_timestamp_update(void) +{ + _receive_timestamp[_receive_timestamp_idx^1] = AP_HAL::micros64(); + _receive_timestamp_idx ^= 1; +} + + +/* + return timestamp estimate in microseconds for when the start of + a nbytes packet arrived on the uart. This should be treated as a + time constraint, not an exact time. It is guaranteed that the + packet did not start being received after this time, but it + could have been in a system buffer before the returned time. + This takes account of the baudrate of the link. For transports + that have no baudrate (such as USB) the time estimate may be + less accurate. + A return value of zero means the HAL does not support this API +*/ +uint64_t UARTDriver::receive_time_constraint_us(uint16_t nbytes) +{ + uint64_t last_receive_us = _receive_timestamp[_receive_timestamp_idx]; + if (_baudrate > 0) { + // assume 10 bits per byte. For USB we assume zero transport delay + uint32_t transport_time_us = (1000000UL * 10UL / _baudrate) * (nbytes + available()); + last_receive_us -= transport_time_us; + } + return last_receive_us; +} + } diff --git a/libraries/AP_HAL_ESP32/UARTDriver.h b/libraries/AP_HAL_ESP32/UARTDriver.h index b38dfb2172..22b0174ada 100644 --- a/libraries/AP_HAL_ESP32/UARTDriver.h +++ b/libraries/AP_HAL_ESP32/UARTDriver.h @@ -79,6 +79,19 @@ public: //bool lock_port(uint32_t write_key, uint32_t read_key) override; //size_t write_locked(const uint8_t *buffer, size_t size, uint32_t key) override; + // + /* + return timestamp estimate in microseconds for when the start of + a nbytes packet arrived on the uart. This should be treated as a + time constraint, not an exact time. It is guaranteed that the + packet did not start being received after this time, but it + could have been in a system buffer before the returned time. + This takes account of the baudrate of the link. For transports + that have no baudrate (such as USB) the time estimate may be + less accurate. + A return value of zero means the HAL does not support this API */ + + uint64_t receive_time_constraint_us(uint16_t nbytes) override; private: bool _initialized; const size_t TX_BUF_SIZE = 1024; @@ -91,6 +104,13 @@ private: void write_data(); uint8_t uart_num; + + // timestamp for receiving data on the UART, avoiding a lock + uint64_t _receive_timestamp[2]; + uint8_t _receive_timestamp_idx; + uint32_t _baudrate; + + void _receive_timestamp_update(void); }; }