2016-02-17 21:25:25 -04:00
|
|
|
#pragma once
|
2012-08-20 15:37:46 -03:00
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
#include "AP_HAL_Namespace.h"
|
2012-08-20 20:54:01 -03:00
|
|
|
#include "utility/BetterStream.h"
|
2024-04-06 13:09:59 -03:00
|
|
|
#include <AP_Logger/AP_Logger_config.h>
|
2012-08-20 15:37:46 -03:00
|
|
|
|
2022-01-08 06:56:52 -04:00
|
|
|
#ifndef HAL_UART_STATS_ENABLED
|
|
|
|
#define HAL_UART_STATS_ENABLED !defined(HAL_NO_UARTDRIVER)
|
2023-06-26 06:51:48 -03:00
|
|
|
#endif
|
2022-01-08 06:56:52 -04:00
|
|
|
|
2023-06-26 06:51:48 -03:00
|
|
|
#ifndef AP_UART_MONITOR_ENABLED
|
|
|
|
#define AP_UART_MONITOR_ENABLED 0
|
2022-01-08 06:56:52 -04:00
|
|
|
#endif
|
|
|
|
|
2021-06-05 00:50:05 -03:00
|
|
|
class ExpandingString;
|
2023-06-26 06:51:48 -03:00
|
|
|
class ByteBuffer;
|
2021-06-05 00:50:05 -03:00
|
|
|
|
2012-08-20 15:37:46 -03:00
|
|
|
/* Pure virtual UARTDriver class */
|
2012-08-20 20:54:01 -03:00
|
|
|
class AP_HAL::UARTDriver : public AP_HAL::BetterStream {
|
2012-08-20 15:37:46 -03:00
|
|
|
public:
|
|
|
|
UARTDriver() {}
|
2020-12-05 15:16:05 -04:00
|
|
|
/* Do not allow copies */
|
2022-09-30 06:50:43 -03:00
|
|
|
CLASS_NO_COPY(UARTDriver);
|
2020-12-05 15:16:05 -04:00
|
|
|
|
2023-06-26 06:51:48 -03:00
|
|
|
/*
|
|
|
|
the individual HALs need to implement the protected versions of these calls, _begin(), _write(), _read()
|
|
|
|
port locking is checked by the top level AP_HAL functions
|
|
|
|
*/
|
|
|
|
void begin(uint32_t baud);
|
|
|
|
|
|
|
|
/*
|
|
|
|
begin with specified minimum tx and rx buffer sizes
|
|
|
|
*/
|
|
|
|
void begin(uint32_t baud, uint16_t rxSpace, uint16_t txSpace);
|
|
|
|
|
|
|
|
/*
|
|
|
|
begin for use when the port is write locked. Note that this does
|
|
|
|
not lock the port, an existing write_key from lock_port() must
|
|
|
|
be used
|
|
|
|
*/
|
|
|
|
void begin_locked(uint32_t baud, uint16_t rxSpace, uint16_t txSpace, uint32_t write_key);
|
|
|
|
|
|
|
|
/*
|
|
|
|
single and multi-byte write methods
|
|
|
|
*/
|
|
|
|
size_t write(uint8_t c) override;
|
|
|
|
size_t write(const uint8_t *buffer, size_t size) override;
|
|
|
|
size_t write(const char *str) override;
|
|
|
|
|
|
|
|
/*
|
|
|
|
single and multi-byte read methods
|
|
|
|
*/
|
|
|
|
int16_t read(void) override;
|
|
|
|
bool read(uint8_t &b) override WARN_IF_UNUSED;
|
|
|
|
ssize_t read(uint8_t *buffer, uint16_t count) override;
|
|
|
|
|
|
|
|
void end();
|
|
|
|
void flush();
|
|
|
|
|
2012-08-21 18:11:24 -03:00
|
|
|
virtual bool is_initialized() = 0;
|
|
|
|
virtual bool tx_pending() = 0;
|
2014-02-10 20:22:08 -04:00
|
|
|
|
2018-04-02 03:00:13 -03:00
|
|
|
// lock a port for exclusive use. Use a key of 0 to unlock
|
2023-06-26 06:51:48 -03:00
|
|
|
bool lock_port(uint32_t write_key, uint32_t read_key);
|
|
|
|
|
|
|
|
// check data available for read, return 0 is not available
|
|
|
|
uint32_t available() override;
|
|
|
|
uint32_t available_locked(uint32_t key);
|
2018-04-02 03:00:13 -03:00
|
|
|
|
2023-06-26 06:51:48 -03:00
|
|
|
// discard any pending input
|
|
|
|
bool discard_input() override;
|
2020-05-31 09:13:03 -03:00
|
|
|
|
2018-04-02 03:00:13 -03:00
|
|
|
// write to a locked port. If port is locked and key is not correct then 0 is returned
|
|
|
|
// and write is discarded
|
2023-06-26 06:51:48 -03:00
|
|
|
size_t write_locked(const uint8_t *buffer, size_t size, uint32_t key);
|
2018-11-10 05:45:12 -04:00
|
|
|
|
2023-06-26 06:51:48 -03:00
|
|
|
// read buffer from a locked port. If port is locked and key is not correct then -1 is returned
|
|
|
|
ssize_t read_locked(uint8_t *buf, size_t count, uint32_t key) WARN_IF_UNUSED;
|
2018-12-19 07:23:40 -04:00
|
|
|
|
2018-11-10 05:45:12 -04:00
|
|
|
// control optional features
|
2021-11-28 05:46:08 -04:00
|
|
|
virtual bool set_options(uint16_t options) { _last_options = options; return options==0; }
|
|
|
|
virtual uint16_t get_options(void) const { return _last_options; }
|
2018-11-10 05:45:12 -04:00
|
|
|
|
|
|
|
enum {
|
2020-07-03 19:03:23 -03:00
|
|
|
OPTION_RXINV = (1U<<0), // invert RX line
|
|
|
|
OPTION_TXINV = (1U<<1), // invert TX line
|
|
|
|
OPTION_HDPLEX = (1U<<2), // half-duplex (one-wire) mode
|
|
|
|
OPTION_SWAP = (1U<<3), // swap RX and TX pins
|
|
|
|
OPTION_PULLDOWN_RX = (1U<<4), // apply pulldown to RX
|
|
|
|
OPTION_PULLUP_RX = (1U<<5), // apply pullup to RX
|
|
|
|
OPTION_PULLDOWN_TX = (1U<<6), // apply pulldown to TX
|
|
|
|
OPTION_PULLUP_TX = (1U<<7), // apply pullup to TX
|
|
|
|
OPTION_NODMA_RX = (1U<<8), // don't use DMA for RX
|
|
|
|
OPTION_NODMA_TX = (1U<<9), // don't use DMA for TX
|
|
|
|
OPTION_MAVLINK_NO_FORWARD = (1U<<10), // don't forward MAVLink data to or from this device
|
2021-07-07 19:24:25 -03:00
|
|
|
OPTION_NOFIFO = (1U<<11), // disable hardware FIFO
|
2021-11-28 05:46:08 -04:00
|
|
|
OPTION_NOSTREAMOVERRIDE = (1U<<12), // don't allow GCS to override streamrates
|
2018-11-10 05:45:12 -04:00
|
|
|
};
|
|
|
|
|
2014-02-10 20:22:08 -04:00
|
|
|
enum flow_control {
|
2023-01-24 00:29:27 -04:00
|
|
|
FLOW_CONTROL_DISABLE=0,
|
|
|
|
FLOW_CONTROL_ENABLE=1,
|
|
|
|
FLOW_CONTROL_AUTO=2,
|
2024-04-10 15:46:03 -03:00
|
|
|
FLOW_CONTROL_RTS_DE=3, // RTS pin is used as a driver enable (used in RS-485)
|
2014-02-10 20:22:08 -04:00
|
|
|
};
|
2014-02-11 19:51:58 -04:00
|
|
|
virtual void set_flow_control(enum flow_control flow_control_setting) {};
|
2016-07-01 02:35:07 -03:00
|
|
|
virtual enum flow_control get_flow_control(void) { return FLOW_CONTROL_DISABLE; }
|
2013-09-21 23:20:59 -03:00
|
|
|
|
2024-04-10 15:46:03 -03:00
|
|
|
// Return true if flow control is currently enabled
|
|
|
|
bool flow_control_enabled() { return flow_control_enabled(get_flow_control()); }
|
|
|
|
|
2017-11-22 13:38:34 -04:00
|
|
|
virtual void configure_parity(uint8_t v){};
|
|
|
|
virtual void set_stop_bits(int n){};
|
|
|
|
|
|
|
|
/* unbuffered writes bypass the ringbuffer and go straight to the
|
|
|
|
* file descriptor
|
|
|
|
*/
|
|
|
|
virtual bool set_unbuffered_writes(bool on){ return false; };
|
|
|
|
|
2018-01-05 03:07:23 -04:00
|
|
|
/*
|
|
|
|
wait for at least n bytes of incoming data, with timeout in
|
|
|
|
milliseconds. Return true if n bytes are available, false if
|
|
|
|
timeout
|
|
|
|
*/
|
|
|
|
virtual bool wait_timeout(uint16_t n, uint32_t timeout_ms) { return false; }
|
2018-01-21 15:44:53 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Optional method to control the update of the motors. Derived classes
|
|
|
|
* can implement it if their HAL layer requires.
|
|
|
|
*/
|
|
|
|
virtual void _timer_tick(void) { }
|
2018-05-15 21:42:14 -03:00
|
|
|
|
|
|
|
/*
|
|
|
|
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.
|
|
|
|
*/
|
2024-01-02 02:47:25 -04:00
|
|
|
virtual uint64_t receive_time_constraint_us(uint16_t nbytes);
|
2018-04-05 22:58:09 -03:00
|
|
|
|
2023-01-18 03:45:42 -04:00
|
|
|
virtual uint32_t bw_in_bytes_per_second() const {
|
|
|
|
return 5760;
|
2018-04-05 22:58:09 -03:00
|
|
|
}
|
2021-05-01 09:00:36 -03:00
|
|
|
|
2022-12-14 16:32:49 -04:00
|
|
|
virtual uint32_t get_baud_rate() const { return 0; }
|
|
|
|
|
2021-05-01 09:00:36 -03:00
|
|
|
/*
|
|
|
|
return true if this UART has DMA enabled on both RX and TX
|
|
|
|
*/
|
|
|
|
virtual bool is_dma_enabled() const { return false; }
|
2021-06-05 00:50:05 -03:00
|
|
|
|
2022-01-08 06:56:52 -04:00
|
|
|
#if HAL_UART_STATS_ENABLED
|
2024-03-15 11:18:55 -03:00
|
|
|
// Helper to keep track of data usage since last call
|
|
|
|
struct StatsTracker {
|
|
|
|
class ByteTracker {
|
|
|
|
public:
|
|
|
|
// Take cumulative bytes and return the change since last call
|
|
|
|
uint32_t update(uint32_t bytes);
|
|
|
|
private:
|
|
|
|
uint32_t last_bytes;
|
|
|
|
};
|
|
|
|
ByteTracker tx;
|
|
|
|
ByteTracker rx;
|
|
|
|
};
|
|
|
|
|
2021-06-05 00:50:05 -03:00
|
|
|
// request information on uart I/O for this uart, for @SYS/uarts.txt
|
2024-03-15 11:18:55 -03:00
|
|
|
virtual void uart_info(ExpandingString &str, StatsTracker &stats, const uint32_t dt_ms) {}
|
2024-04-06 13:09:59 -03:00
|
|
|
|
|
|
|
#if HAL_LOGGING_ENABLED
|
|
|
|
// Log stats for this instance
|
|
|
|
void log_stats(const uint8_t inst, StatsTracker &stats, const uint32_t dt_ms);
|
2022-01-08 06:56:52 -04:00
|
|
|
#endif
|
2024-04-06 13:09:59 -03:00
|
|
|
#endif // HAL_UART_STATS_ENABLED
|
2021-07-08 03:35:06 -03:00
|
|
|
|
|
|
|
/*
|
|
|
|
software control of the CTS/RTS pins if available. Return false if
|
|
|
|
not available
|
|
|
|
*/
|
|
|
|
virtual bool set_RTS_pin(bool high) { return false; };
|
|
|
|
virtual bool set_CTS_pin(bool high) { return false; };
|
2021-07-10 15:17:27 -03:00
|
|
|
|
|
|
|
// return true requested baud on USB port
|
|
|
|
virtual uint32_t get_usb_baud(void) const { return 0; }
|
2021-11-05 01:33:40 -03:00
|
|
|
|
|
|
|
// disable TX/RX pins for unusued uart
|
|
|
|
virtual void disable_rxtx(void) const {}
|
2023-06-26 06:51:48 -03:00
|
|
|
|
|
|
|
#if AP_UART_MONITOR_ENABLED
|
|
|
|
// a way to monitor all reads from the UART, putting them in a
|
|
|
|
// buffer. Used by AP_Periph for GPS debug
|
|
|
|
bool set_monitor_read_buffer(ByteBuffer *buffer) {
|
|
|
|
_monitor_read_buffer = buffer;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2024-01-17 19:34:59 -04:00
|
|
|
/*
|
|
|
|
return true if the port is currently locked for writing
|
|
|
|
*/
|
|
|
|
bool is_write_locked(void) const {
|
|
|
|
return lock_write_key != 0;
|
|
|
|
}
|
|
|
|
|
2023-06-26 06:51:48 -03:00
|
|
|
protected:
|
|
|
|
// key for a locked port
|
|
|
|
uint32_t lock_write_key;
|
|
|
|
uint32_t lock_read_key;
|
|
|
|
|
|
|
|
/*
|
|
|
|
backend begin method
|
|
|
|
*/
|
|
|
|
virtual void _begin(uint32_t baud, uint16_t rxSpace, uint16_t txSpace) = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
backend write method
|
|
|
|
*/
|
|
|
|
virtual size_t _write(const uint8_t *buffer, size_t size) = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
backend read method
|
|
|
|
*/
|
|
|
|
virtual ssize_t _read(uint8_t *buffer, uint16_t count) WARN_IF_UNUSED = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
end control of the port, freeing buffers
|
|
|
|
*/
|
|
|
|
virtual void _end() = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
flush any pending data
|
|
|
|
*/
|
|
|
|
virtual void _flush() = 0;
|
|
|
|
|
|
|
|
// check available data on the port
|
|
|
|
virtual uint32_t _available() = 0;
|
|
|
|
|
|
|
|
// discard incoming data on the port
|
|
|
|
virtual bool _discard_input(void) = 0;
|
2024-04-06 13:06:55 -03:00
|
|
|
|
2024-04-10 15:46:03 -03:00
|
|
|
// Helper to check if flow control is enabled given the passed setting
|
|
|
|
bool flow_control_enabled(enum flow_control flow_control_setting) const;
|
|
|
|
|
2024-04-06 13:06:55 -03:00
|
|
|
#if HAL_UART_STATS_ENABLED
|
|
|
|
// Getters for cumulative tx and rx counts
|
|
|
|
virtual uint32_t get_total_tx_bytes() const { return 0; }
|
|
|
|
virtual uint32_t get_total_rx_bytes() const { return 0; }
|
|
|
|
#endif
|
|
|
|
|
2023-06-26 06:51:48 -03:00
|
|
|
private:
|
|
|
|
// option bits for port
|
|
|
|
uint16_t _last_options;
|
|
|
|
|
|
|
|
#if AP_UART_MONITOR_ENABLED
|
|
|
|
ByteBuffer *_monitor_read_buffer;
|
|
|
|
#endif
|
2012-08-20 20:54:01 -03:00
|
|
|
};
|