LCOV - code coverage report
Current view: top level - AP_HAL - UARTDriver.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 61 97 62.9 %
Date: 2026-09-09 11:02:08 Functions: 15 22 68.2 %

          Line data    Source code
       1             : /*
       2             :   implement generic UARTDriver code, including port locking
       3             :  */
       4             : #include "AP_HAL.h"
       5             : #include <AP_Logger/AP_Logger.h>
       6             : 
       7      542808 : void AP_HAL::UARTDriver::begin(uint32_t baud, uint16_t rxSpace, uint16_t txSpace)
       8             : {
       9      542808 :     if (lock_write_key != 0) {
      10             :         // silently fail
      11           0 :         return;
      12             :     }
      13      542808 :     return _begin(baud, rxSpace, txSpace);
      14             : }
      15             : 
      16      521764 : void AP_HAL::UARTDriver::begin(uint32_t baud)
      17             : {
      18      521764 :     return begin(baud, 0, 0);
      19             : }
      20             : 
      21             : /*
      22             :   lock the uart for exclusive use by write_locked() and read_locked() with the right key
      23             :  */
      24           0 : bool AP_HAL::UARTDriver::lock_port(uint32_t write_key, uint32_t read_key)
      25             : {
      26           0 :     if (lock_write_key != 0 && write_key != lock_write_key && write_key != 0) {
      27             :         // someone else is using it
      28           0 :         return false;
      29             :     }
      30           0 :     if (lock_read_key != 0 && read_key != lock_read_key && read_key != 0) {
      31             :         // someone else is using it
      32           0 :         return false;
      33             :     }
      34           0 :     lock_write_key = write_key;
      35           0 :     lock_read_key = read_key;
      36           0 :     return true;
      37             : }
      38             : 
      39           0 : void AP_HAL::UARTDriver::begin_locked(uint32_t baud, uint16_t rxSpace, uint16_t txSpace, uint32_t key)
      40             : {
      41           0 :     if (lock_write_key != 0 && key != lock_write_key) {
      42             :         // silently fail
      43           0 :         return;
      44             :     }
      45           0 :     return _begin(baud, rxSpace, txSpace);
      46             : }
      47             : 
      48             : /*
      49             :    write to a locked port. If port is locked and key is not correct then 0 is returned
      50             :    and write is discarded. All writes are non-blocking
      51             : */
      52           0 : size_t AP_HAL::UARTDriver::write_locked(const uint8_t *buffer, size_t size, uint32_t key)
      53             : {
      54           0 :     if (lock_write_key != 0 && key != lock_write_key) {
      55           0 :         return 0;
      56             :     }
      57           0 :     return _write(buffer, size);
      58             : }
      59             : 
      60             : /*
      61             :    read from a locked port. If port is locked and key is not correct then -1 is returned
      62             : */
      63   444374012 : ssize_t AP_HAL::UARTDriver::read_locked(uint8_t *buf, size_t count, uint32_t key)
      64             : {
      65   444374012 :     if (lock_read_key != 0 && key != lock_read_key) {
      66           0 :         return 0;
      67             :     }
      68   444374012 :     ssize_t ret = _read(buf, count);
      69             : #if AP_UART_MONITOR_ENABLED
      70   444372662 :     auto monitor = _monitor_read_buffer;
      71   444372662 :     if (monitor != nullptr && ret > 0) {
      72           0 :         monitor->write(buf, ret);
      73             :     }
      74             : #endif
      75   444372735 :     return ret;
      76             : }
      77             : 
      78           0 : uint32_t AP_HAL::UARTDriver::available_locked(uint32_t key)
      79             : {
      80           0 :     if (lock_read_key != 0 && lock_read_key != key) {
      81           0 :         return 0;
      82             :     }
      83           0 :     return _available();
      84             : }
      85             : 
      86   117474477 : size_t AP_HAL::UARTDriver::write(const uint8_t *buffer, size_t size)
      87             : {
      88   117474477 :     if (lock_write_key != 0) {
      89           0 :         return 0;
      90             :     }
      91   117474477 :     return _write(buffer, size);
      92             : }
      93             : 
      94      303159 : size_t AP_HAL::UARTDriver::write(uint8_t c)
      95             : {
      96      303159 :     return write(&c, 1);
      97             : }
      98             : 
      99         155 : size_t AP_HAL::UARTDriver::write(const char *str)
     100             : {
     101         155 :     return write((const uint8_t *)str, strlen(str));
     102             : }
     103             : 
     104   444374096 : ssize_t AP_HAL::UARTDriver::read(uint8_t *buffer, uint16_t count)
     105             : {
     106   444374096 :     return read_locked(buffer, count, 0);
     107             : }
     108             : 
     109   443774815 : bool AP_HAL::UARTDriver::read(uint8_t &b)
     110             : {
     111   443774815 :     ssize_t n = read(&b, 1);
     112   443773613 :     return n > 0;
     113             : }
     114             : 
     115   142781192 : int16_t AP_HAL::UARTDriver::read(void)
     116             : {
     117             :     uint8_t b;
     118   142781192 :     if (!read(b)) {
     119           0 :         return -1;
     120             :     }
     121   142781192 :     return b;
     122             : }
     123             : 
     124             : 
     125   136305479 : uint32_t AP_HAL::UARTDriver::available()
     126             : {
     127   136305479 :     if (lock_read_key != 0) {
     128           0 :         return 0;
     129             :     }
     130   136305479 :     return _available();
     131             : }
     132             : 
     133           0 : void AP_HAL::UARTDriver::end()
     134             : {
     135           0 :     if (lock_read_key != 0 || lock_write_key != 0) {
     136           0 :         return;
     137             :     }
     138           0 :     _end();
     139             : }
     140             : 
     141        1639 : void AP_HAL::UARTDriver::flush()
     142             : {
     143        1639 :     if (lock_read_key != 0 || lock_write_key != 0) {
     144           0 :         return;
     145             :     }
     146        1639 :     _flush();
     147             : }
     148             : 
     149      191581 : bool AP_HAL::UARTDriver::discard_input()
     150             : {
     151      191581 :     if (lock_read_key != 0) {
     152           0 :         return false;
     153             :     }
     154      191581 :     return _discard_input();
     155             : }
     156             : 
     157             : /*
     158             :   default implementation of receive_time_constraint_us() will be used
     159             :   for subclasses that don't implement the call (eg. network
     160             :   sockets). Best we can do is to use the current timestamp as we don't
     161             :   know the transport delay
     162             :  */
     163           0 : uint64_t AP_HAL::UARTDriver::receive_time_constraint_us(uint16_t nbytes)
     164             : {
     165           0 :     return AP_HAL::micros64();
     166             : }
     167             : 
     168             : // Helper to check if flow control is enabled given the passed setting
     169        7704 : bool AP_HAL::UARTDriver::flow_control_enabled(enum flow_control flow_control_setting) const
     170             : {
     171        7704 :     switch(flow_control_setting) {
     172        7012 :         case FLOW_CONTROL_ENABLE:
     173             :         case FLOW_CONTROL_AUTO:
     174        7012 :             return true;
     175         692 :         case FLOW_CONTROL_DISABLE:
     176             :         case FLOW_CONTROL_RTS_DE:
     177         692 :             break;
     178             :     }
     179         692 :     return false;
     180             : }
     181             : 
     182           0 : uint8_t AP_HAL::UARTDriver::get_parity(void)
     183             : {
     184           0 :     return AP_HAL::UARTDriver::parity;
     185             : }
     186             : 
     187             : #if HAL_UART_STATS_ENABLED
     188             : // Take cumulative bytes and return the change since last call
     189      967590 : uint32_t AP_HAL::UARTDriver::StatsTracker::ByteTracker::update(uint32_t bytes)
     190             : {
     191      967590 :     const uint32_t change = bytes - last_bytes;
     192      967590 :     last_bytes = bytes;
     193      967590 :     return change;
     194             : }
     195             : 
     196             : #if HAL_LOGGING_ENABLED
     197             : // Write UART log message
     198     1492499 : void AP_HAL::UARTDriver::log_stats(const uint8_t inst, StatsTracker &stats, const uint32_t dt_ms)
     199             : {
     200             :     // get totals
     201     1492499 :     const uint32_t total_tx_bytes = get_total_tx_bytes();
     202     1492499 :     const uint32_t total_rx_bytes = get_total_rx_bytes();
     203             : 
     204             :     // Don't log if we have never seen data
     205     1492499 :     if ((total_tx_bytes == 0) && (total_rx_bytes == 0)) {
     206             :         // This could be wrong if we happen to wrap both tx and rx to zero at exactly the same time
     207             :         // In that very unlikely case one log will be missed
     208     1177625 :         return;
     209             :     }
     210             : 
     211             :     // Update tracking
     212      314874 :     const uint32_t tx_bytes = stats.tx.update(total_tx_bytes);
     213      314874 :     const uint32_t rx_bytes = stats.rx.update(total_rx_bytes);
     214      314874 :     const uint32_t rx_dropped_bytes = stats.rx_dropped.update(get_total_dropped_rx_bytes());
     215             : 
     216             :     // Assemble struct and log
     217      314874 :     struct log_UART pkt {
     218             :         LOG_PACKET_HEADER_INIT(LOG_UART_MSG),
     219      314874 :         time_us  : AP_HAL::micros64(),
     220             :         instance : inst,
     221      314874 :         tx_rate  : float((tx_bytes * 1000) / dt_ms),
     222      314874 :         rx_rate  : float((rx_bytes * 1000) / dt_ms),
     223      314874 :         rx_drop_rate : float((rx_dropped_bytes * 1000) / dt_ms),
     224      314874 :     };
     225      314874 :     AP::logger().WriteBlock(&pkt, sizeof(pkt));
     226             : }
     227             : #endif // HAL_LOGGING_ENABLED
     228             : #endif // HAL_UART_STATS_ENABLED

Generated by: LCOV version 1.14