Line data Source code
1 : #pragma once
2 :
3 : #include <stdint.h>
4 :
5 : #include "AP_HAL_Namespace.h"
6 : #include "utility/BetterStream.h"
7 : #include <AP_Logger/AP_Logger_config.h>
8 :
9 : #ifndef HAL_UART_STATS_ENABLED
10 : #define HAL_UART_STATS_ENABLED AP_HAL_UARTDRIVER_ENABLED
11 : #endif
12 :
13 : #ifndef AP_UART_MONITOR_ENABLED
14 : #define AP_UART_MONITOR_ENABLED 0
15 : #endif
16 :
17 : class ExpandingString;
18 : class ByteBuffer;
19 :
20 : /* Pure virtual UARTDriver class */
21 : class AP_HAL::UARTDriver : public AP_HAL::BetterStream {
22 : public:
23 36637 : UARTDriver() {}
24 : /* Do not allow copies */
25 : CLASS_NO_COPY(UARTDriver);
26 :
27 : /*
28 : the individual HALs need to implement the protected versions of these calls, _begin(), _write(), _read()
29 : port locking is checked by the top level AP_HAL functions
30 : */
31 : void begin(uint32_t baud);
32 :
33 : /*
34 : begin with specified minimum tx and rx buffer sizes
35 : */
36 : void begin(uint32_t baud, uint16_t rxSpace, uint16_t txSpace);
37 :
38 : /*
39 : begin for use when the port is write locked. Note that this does
40 : not lock the port, an existing write_key from lock_port() must
41 : be used
42 : */
43 : void begin_locked(uint32_t baud, uint16_t rxSpace, uint16_t txSpace, uint32_t write_key);
44 :
45 : /*
46 : single and multi-byte write methods
47 : */
48 : size_t write(uint8_t c) override;
49 : size_t write(const uint8_t *buffer, size_t size) override;
50 : size_t write(const char *str) override;
51 :
52 : /*
53 : single and multi-byte read methods
54 : */
55 : int16_t read(void) override;
56 : bool read(uint8_t &b) override WARN_IF_UNUSED;
57 : ssize_t read(uint8_t *buffer, uint16_t count) override;
58 :
59 : void end();
60 : void flush();
61 :
62 : virtual bool is_initialized() = 0;
63 : virtual bool tx_pending() = 0;
64 :
65 : // lock a port for exclusive use. Use a key of 0 to unlock
66 : bool lock_port(uint32_t write_key, uint32_t read_key);
67 :
68 : // check data available for read, return 0 is not available
69 : uint32_t available() override;
70 : uint32_t available_locked(uint32_t key);
71 :
72 : // discard any pending input
73 : bool discard_input() override;
74 :
75 : // write to a locked port. If port is locked and key is not correct then 0 is returned
76 : // and write is discarded
77 : size_t write_locked(const uint8_t *buffer, size_t size, uint32_t key);
78 :
79 : // read buffer from a locked port. If port is locked and key is not correct then -1 is returned
80 : ssize_t read_locked(uint8_t *buf, size_t count, uint32_t key) WARN_IF_UNUSED;
81 :
82 : // get current parity for passthrough use
83 : uint8_t get_parity(void);
84 :
85 : // control optional features
86 23185 : virtual bool set_options(uint16_t options) { _last_options = options; return options==0; }
87 1 : virtual uint16_t get_options(void) const { return _last_options; }
88 :
89 : enum Option {
90 : OPTION_RXINV = (1U<<0), // invert RX line
91 : OPTION_TXINV = (1U<<1), // invert TX line
92 : OPTION_HDPLEX = (1U<<2), // half-duplex (one-wire) mode
93 : OPTION_SWAP = (1U<<3), // swap RX and TX pins
94 : OPTION_PULLDOWN_RX = (1U<<4), // apply pulldown to RX
95 : OPTION_PULLUP_RX = (1U<<5), // apply pullup to RX
96 : OPTION_PULLDOWN_TX = (1U<<6), // apply pulldown to TX
97 : OPTION_PULLUP_TX = (1U<<7), // apply pullup to TX
98 : OPTION_NODMA_RX = (1U<<8), // don't use DMA for RX
99 : OPTION_NODMA_TX = (1U<<9), // don't use DMA for TX
100 : OPTION_MAVLINK_NO_FORWARD_old = (1U<<10), // // moved to GCS_MAVLINK::Option
101 : OPTION_NOFIFO = (1U<<11), // disable hardware FIFO
102 : OPTION_NOSTREAMOVERRIDE_old = (1U<<12), // moved to GCS_MAVLINK::Option
103 : };
104 :
105 1838 : bool option_is_set(Option option) const {
106 1838 : return (_last_options & (uint16_t)option) != 0;
107 : }
108 :
109 :
110 : enum flow_control {
111 : FLOW_CONTROL_DISABLE=0,
112 : FLOW_CONTROL_ENABLE=1,
113 : FLOW_CONTROL_AUTO=2,
114 : FLOW_CONTROL_RTS_DE=3, // RTS pin is used as a driver enable (used in RS-485)
115 : };
116 24 : virtual void set_flow_control(enum flow_control flow_control_setting) {};
117 2 : virtual enum flow_control get_flow_control(void) { return FLOW_CONTROL_DISABLE; }
118 :
119 : // Return true if flow control is currently enabled
120 7704 : bool flow_control_enabled() { return flow_control_enabled(get_flow_control()); }
121 :
122 0 : virtual void configure_parity(uint8_t v){};
123 0 : virtual void set_stop_bits(int n){};
124 :
125 : /* unbuffered writes bypass the ringbuffer and go straight to the
126 : * file descriptor
127 : */
128 0 : virtual bool set_unbuffered_writes(bool on){ return false; };
129 :
130 : /*
131 : wait for at least n bytes of incoming data, with timeout in
132 : milliseconds. Return true if n bytes are available, false if
133 : timeout
134 : */
135 0 : virtual bool wait_timeout(uint16_t n, uint32_t timeout_ms) { return false; }
136 :
137 : /*
138 : * Optional method to control the update of the motors. Derived classes
139 : * can implement it if their HAL layer requires.
140 : */
141 0 : virtual void _timer_tick(void) { }
142 :
143 : /*
144 : return timestamp estimate in microseconds for when the start of
145 : a nbytes packet arrived on the uart. This should be treated as a
146 : time constraint, not an exact time. It is guaranteed that the
147 : packet did not start being received after this time, but it
148 : could have been in a system buffer before the returned time.
149 :
150 : This takes account of the baudrate of the link. For transports
151 : that have no baudrate (such as USB) the time estimate may be
152 : less accurate.
153 : */
154 : virtual uint64_t receive_time_constraint_us(uint16_t nbytes);
155 :
156 0 : virtual uint32_t bw_in_bytes_per_second() const {
157 0 : return 5760;
158 : }
159 :
160 0 : virtual uint32_t get_baud_rate() const { return 0; }
161 :
162 : /*
163 : return true if this UART has DMA enabled on both RX and TX
164 : */
165 0 : virtual bool is_dma_enabled() const { return false; }
166 :
167 : /*
168 : return true if this port carries its data over a network
169 : connection (e.g. a NET_Pn port) rather than over a physical
170 : serial port.
171 :
172 : If you are calling this you are probably doing something wrong;
173 : users of a port should be agnostic as to how the bytes reach the
174 : other end. It exists only for the rare device whose protocol
175 : itself cares - e.g. a gimbal which is told which of its own
176 : interfaces to send its replies out of.
177 : */
178 14642 : virtual bool is_network_port() const { return false; }
179 :
180 : #if HAL_UART_STATS_ENABLED
181 : // Helper to keep track of data usage since last call
182 : struct StatsTracker {
183 : class ByteTracker {
184 : public:
185 : // Take cumulative bytes and return the change since last call
186 : uint32_t update(uint32_t bytes);
187 : private:
188 : uint32_t last_bytes;
189 : };
190 : ByteTracker tx;
191 : ByteTracker rx;
192 : ByteTracker rx_dropped;
193 : };
194 :
195 : // request information on uart I/O for this uart, for @SYS/uarts.txt
196 0 : virtual void uart_info(ExpandingString &str, StatsTracker &stats, const uint32_t dt_ms) {}
197 :
198 : #if HAL_LOGGING_ENABLED
199 : // Log stats for this instance
200 : void log_stats(const uint8_t inst, StatsTracker &stats, const uint32_t dt_ms);
201 : #endif
202 : #endif // HAL_UART_STATS_ENABLED
203 :
204 : /*
205 : software control of the CTS/RTS pins if available. Return false if
206 : not available
207 : */
208 0 : virtual bool set_RTS_pin(bool high) { return false; };
209 0 : virtual bool set_CTS_pin(bool high) { return false; };
210 :
211 : // return true requested baud on USB port
212 0 : virtual uint32_t get_usb_baud(void) const { return 0; }
213 :
214 : // return requested parity on USB port
215 0 : virtual uint8_t get_usb_parity(void) const { return parity; }
216 :
217 : // disable TX/RX pins for unusued uart
218 6164 : virtual void disable_rxtx(void) const {}
219 :
220 : #if AP_UART_MONITOR_ENABLED
221 : // a way to monitor all reads from the UART, putting them in a
222 : // buffer. Used by AP_Periph for GPS debug
223 : bool set_monitor_read_buffer(ByteBuffer *buffer) {
224 : _monitor_read_buffer = buffer;
225 : return true;
226 : }
227 : #endif
228 :
229 : /*
230 : return true if the port is currently locked for writing
231 : */
232 0 : bool is_write_locked(void) const {
233 0 : return lock_write_key != 0;
234 : }
235 :
236 : // check that the current thread owns the uart making certain operations possible
237 0 : virtual bool is_owned_by_current_thread() const { return true; }
238 :
239 : protected:
240 : // key for a locked port
241 : uint32_t lock_write_key;
242 : uint32_t lock_read_key;
243 :
244 : uint8_t parity;
245 :
246 : /*
247 : backend begin method
248 : */
249 : virtual void _begin(uint32_t baud, uint16_t rxSpace, uint16_t txSpace) = 0;
250 :
251 : /*
252 : backend write method
253 : */
254 : virtual size_t _write(const uint8_t *buffer, size_t size) = 0;
255 :
256 : /*
257 : backend read method
258 : */
259 : virtual ssize_t _read(uint8_t *buffer, uint16_t count) WARN_IF_UNUSED = 0;
260 :
261 : /*
262 : end control of the port, freeing buffers
263 : */
264 : virtual void _end() = 0;
265 :
266 : /*
267 : flush any pending data
268 : */
269 : virtual void _flush() = 0;
270 :
271 : // check available data on the port
272 : virtual uint32_t _available() = 0;
273 :
274 : // discard incoming data on the port
275 : virtual bool _discard_input(void) = 0;
276 :
277 : // Helper to check if flow control is enabled given the passed setting
278 : bool flow_control_enabled(enum flow_control flow_control_setting) const;
279 :
280 : #if HAL_UART_STATS_ENABLED
281 : // Getters for cumulative tx and rx counts
282 6 : virtual uint32_t get_total_tx_bytes() const { return 0; }
283 6 : virtual uint32_t get_total_rx_bytes() const { return 0; }
284 314808 : virtual uint32_t get_total_dropped_rx_bytes() const { return 0; }
285 : #endif
286 :
287 : // option bits for port
288 : uint16_t _last_options;
289 :
290 : private:
291 :
292 : #if AP_UART_MONITOR_ENABLED
293 : ByteBuffer *_monitor_read_buffer;
294 : #endif
295 : };
|