mirror of
https://github.com/PX4/PX4-Autopilot.git
synced 2026-09-22 11:32:05 +08:00
feat(drivers): implemented serial passthrough (#27605)
* feat: implemented serial passthrough * fix: used make format * fix: changed function order to match other drivers * fix: moved passthrough from systemcmds to drivers * fix: renamed BITBANG_TIMER to UART_BITBANG_TIMER * fix: used make format * feat: added PASSTHRU_EN guard to start of dshot&pwm_out * fix: made changing ESC channels more stable * fix: adjusted naming of guards * fix: changed include guard of bitbang * fix: removed unused variable SER_PASS_BAUD * fix: adjusted comments * fix: adjusted print_usage() to match other drivers * fix: remove bitbang_write_byte from public API and some buffer guard * fix: added Serialpassthrough&Bitbang to exclude list of allyesconfig.py * fix: added missing flag to print_usage()
This commit is contained in:
@@ -539,8 +539,13 @@ else
|
||||
else
|
||||
commander start
|
||||
|
||||
dshot start
|
||||
pwm_out start
|
||||
if param compare -s PASSTHRU_EN 0
|
||||
then
|
||||
dshot start
|
||||
pwm_out start
|
||||
else
|
||||
param set PASSTHRU_EN 0
|
||||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
|
||||
@@ -54,6 +54,8 @@ exception_list = [
|
||||
'MODULES_MUORB_APPS', # Weird QURT/Posix package doesn't work on x86 px4 sitl
|
||||
'MODULES_SIMULATION_SIMULATOR_SIH', # Causes compile errors
|
||||
'MODULES_SPACECRAFT', # Clashes with Control Allocation (mom's spaghetti code)
|
||||
'DRIVERS_SERIALPASSTHROUGH', # Requires board-specific UART config and NuttX
|
||||
'SERIALPASSTHROUGH_BITBANG', # Requires STM32 timer and GPIO config
|
||||
]
|
||||
|
||||
exception_list_sitl = [
|
||||
@@ -110,6 +112,7 @@ exception_list_sitl = [
|
||||
'SYSTEMCMDS_USB_CONNECTED', # Not supported in SITL
|
||||
'SYSTEMCMDS_MFT_CFG', # Not supported in SITL
|
||||
'MODULES_SPACECRAFT', # Clashes with Control Allocation (mom's spaghetti code)
|
||||
'DRIVERS_SERIALPASSTHROUGH', # Not supported in SITL
|
||||
]
|
||||
|
||||
def main():
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
CONFIG_BOARD_TOOLCHAIN="arm-none-eabi"
|
||||
CONFIG_BOARD_ARCHITECTURE="cortex-m7"
|
||||
CONFIG_ARCH_CHIP_STM32H7=y
|
||||
CONFIG_BOARD_ETHERNET=y
|
||||
CONFIG_BOARD_SERIAL_GPS1="/dev/ttyS6"
|
||||
CONFIG_BOARD_SERIAL_TEL1="/dev/ttyS0"
|
||||
@@ -95,4 +96,6 @@ CONFIG_SYSTEMCMDS_TOPIC_LISTENER=y
|
||||
CONFIG_SYSTEMCMDS_UORB=y
|
||||
CONFIG_SYSTEMCMDS_VER=y
|
||||
CONFIG_SYSTEMCMDS_WORK_QUEUE=y
|
||||
CONFIG_DRIVERS_SERIALPASSTHROUGH=y
|
||||
CONFIG_SERIALPASSTHROUGH_BITBANG=y
|
||||
CONFIG_WQ_TTY_STACKSIZE=2500
|
||||
|
||||
@@ -244,6 +244,7 @@ CONFIG_STM32H7_TIM3=y
|
||||
CONFIG_STM32H7_TIM4=y
|
||||
CONFIG_STM32H7_TIM5=y
|
||||
CONFIG_STM32H7_TIM8=y
|
||||
CONFIG_STM32H7_TIM13=y
|
||||
CONFIG_STM32H7_UART4=y
|
||||
CONFIG_STM32H7_UART5=y
|
||||
CONFIG_STM32H7_UART7=y
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
CONFIG_BOARD_TOOLCHAIN="arm-none-eabi"
|
||||
CONFIG_BOARD_ARCHITECTURE="cortex-m7"
|
||||
CONFIG_ARCH_CHIP_STM32H7=y
|
||||
CONFIG_BOARD_ETHERNET=y
|
||||
CONFIG_BOARD_SERIAL_GPS1="/dev/ttyS0"
|
||||
CONFIG_BOARD_SERIAL_GPS2="/dev/ttyS7"
|
||||
@@ -99,3 +100,5 @@ CONFIG_SYSTEMCMDS_TUNE_CONTROL=y
|
||||
CONFIG_SYSTEMCMDS_UORB=y
|
||||
CONFIG_SYSTEMCMDS_VER=y
|
||||
CONFIG_SYSTEMCMDS_WORK_QUEUE=y
|
||||
CONFIG_DRIVERS_SERIALPASSTHROUGH=y
|
||||
CONFIG_SERIALPASSTHROUGH_BITBANG=y
|
||||
|
||||
@@ -257,6 +257,7 @@ CONFIG_STM32H7_TIM12=y
|
||||
CONFIG_STM32H7_TIM1=y
|
||||
CONFIG_STM32H7_TIM4=y
|
||||
CONFIG_STM32H7_TIM5=y
|
||||
CONFIG_STM32H7_TIM13=y
|
||||
CONFIG_STM32H7_UART4=y
|
||||
CONFIG_STM32H7_UART5=y
|
||||
CONFIG_STM32H7_UART7=y
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (c) 2026 PX4 Development Team. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name PX4 nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
px4_add_library(arch_bitbang_uart
|
||||
bitbang_uart.cpp
|
||||
)
|
||||
target_compile_options(arch_bitbang_uart PRIVATE ${MAX_CUSTOM_OPT_LEVEL})
|
||||
File diff suppressed because it is too large
Load Diff
@@ -44,5 +44,9 @@ add_subdirectory(../stm32_common/spi spi)
|
||||
add_subdirectory(../stm32_common/tone_alarm tone_alarm)
|
||||
add_subdirectory(../stm32_common/version version)
|
||||
|
||||
if(CONFIG_SERIALPASSTHROUGH_BITBANG)
|
||||
add_subdirectory(../stm32_common/bitbang_uart bitbang_uart)
|
||||
endif()
|
||||
|
||||
add_subdirectory(px4io_serial)
|
||||
add_subdirectory(watchdog)
|
||||
|
||||
@@ -45,4 +45,8 @@ add_subdirectory(../stm32_common/spi spi)
|
||||
add_subdirectory(../stm32_common/tone_alarm tone_alarm)
|
||||
add_subdirectory(../stm32_common/version version)
|
||||
|
||||
if(CONFIG_SERIALPASSTHROUGH_BITBANG)
|
||||
add_subdirectory(../stm32_common/bitbang_uart bitbang_uart)
|
||||
endif()
|
||||
|
||||
add_subdirectory(px4io_serial)
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2026 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file drv_bitbang_uart.h
|
||||
*
|
||||
* Architecture-agnostic interface for bit-bang UART.
|
||||
*
|
||||
* Currently implemented for STM32F7/H7 in:
|
||||
* platforms/nuttx/src/px4/stm/stm32_common/bitbang_uart/
|
||||
*
|
||||
* NOTE: Currently only single-wire (half-duplex) operation is implemented.
|
||||
* The single_wire flag is provided in the API to make this explicit and to
|
||||
* allow future extension to dual-wire (full-duplex) operation.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <px4_platform_common/defines.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* Initialize bit-bang UART
|
||||
*
|
||||
* @param baudrate Baudrate (typically 19200)
|
||||
* @param single_wire True for single-wire half-duplex (TX and RX share one GPIO).
|
||||
* False for dual-wire full-duplex (separate TX/RX GPIOs) — not yet implemented.
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
int bitbang_uart_init(uint32_t baudrate, bool single_wire);
|
||||
|
||||
/**
|
||||
* Deinitialize bit-bang UART
|
||||
*
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
int bitbang_uart_deinit(void);
|
||||
|
||||
/**
|
||||
* Transmit multiple bytes
|
||||
*
|
||||
* @param channel Timer/GPIO channel
|
||||
* @param data Pointer to data buffer
|
||||
* @param length Number of bytes to transmit
|
||||
* @return Number of bytes transmitted, or negative error code on failure
|
||||
*/
|
||||
int bitbang_uart_write(uint8_t channel, const uint8_t *data, size_t length);
|
||||
|
||||
/**
|
||||
* Read received bytes (blocking with timeout)
|
||||
*
|
||||
* @param channel Timer/GPIO channel
|
||||
* @param data Pointer to buffer for received data
|
||||
* @param length Number of bytes to read
|
||||
* @param timeout_us Timeout in microseconds (0 = block until length bytes received)
|
||||
* @return Number of bytes actually read
|
||||
*/
|
||||
int bitbang_uart_read(uint8_t channel, uint8_t *data, size_t length, uint32_t timeout_us);
|
||||
|
||||
__END_DECLS
|
||||
@@ -0,0 +1,47 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (c) 2025 PX4 Development Team. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name PX4 nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
px4_add_module(
|
||||
MODULE drivers__serialpassthrough
|
||||
MAIN serialpassthrough
|
||||
SRCS
|
||||
serialpassthrough.cpp
|
||||
DEPENDS
|
||||
px4_platform
|
||||
MODULE_CONFIG
|
||||
module.yaml
|
||||
)
|
||||
|
||||
if(CONFIG_SERIALPASSTHROUGH_BITBANG)
|
||||
target_link_libraries(drivers__serialpassthrough PRIVATE arch_bitbang_uart)
|
||||
endif()
|
||||
@@ -0,0 +1,30 @@
|
||||
menuconfig DRIVERS_SERIALPASSTHROUGH
|
||||
bool "serialpassthrough"
|
||||
default n
|
||||
---help---
|
||||
Enable the serialpassthrough module.
|
||||
Forwards data between a UART and a MAVLink via
|
||||
SERIAL_CONTROL messages.
|
||||
|
||||
if DRIVERS_SERIALPASSTHROUGH
|
||||
|
||||
config SERIALPASSTHROUGH_BITBANG
|
||||
bool "Enable bit-bang UART support (ESC channel mode)"
|
||||
default n
|
||||
depends on PLATFORM_NUTTX
|
||||
---help---
|
||||
Enable bit-bang UART.
|
||||
|
||||
if SERIALPASSTHROUGH_BITBANG
|
||||
|
||||
config UART_BITBANG_TIMER
|
||||
int "Timer instance for bit-bang UART"
|
||||
default 13
|
||||
range 1 17
|
||||
---help---
|
||||
Timer instance to use for bit-bang UART timing mode.
|
||||
Default TIM13.
|
||||
|
||||
endif # SERIALPASSTHROUGH_BITBANG
|
||||
|
||||
endif # DRIVERS_SERIALPASSTHROUGH
|
||||
@@ -0,0 +1,15 @@
|
||||
module_name: Serial Passthrough (MAVLink)
|
||||
|
||||
parameters:
|
||||
- group: Serial Passthrough
|
||||
definitions:
|
||||
PASSTHRU_EN:
|
||||
description:
|
||||
short: Serial passthrough enable
|
||||
long: |
|
||||
When enabled, the serial passthrough mode is active and the
|
||||
normal motor output drivers (dshot, pwm_out) are not started
|
||||
at boot.
|
||||
type: boolean
|
||||
default: 0
|
||||
reboot_required: true
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,164 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2026 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file serialpassthrough.hpp
|
||||
*
|
||||
* Serial passthrough driven by MAVLink SERIAL_CONTROL messages.
|
||||
*
|
||||
* Exposes a thread-safe push/pop interface so MavlinkReceiver can push
|
||||
* incoming payload bytes to the UART, and the Mavlink main loop can drain
|
||||
* UART-received bytes back as SERIAL_CONTROL replies.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <px4_platform_common/px4_config.h>
|
||||
#include <px4_platform_common/atomic.h>
|
||||
#include <px4_platform_common/Serial.hpp>
|
||||
#ifdef CONFIG_SERIALPASSTHROUGH_BITBANG
|
||||
#include <drivers/drv_bitbang_uart.h>
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static constexpr size_t SP_BUF_SIZE = 1024;
|
||||
static constexpr int SP_MAX_INSTANCES = 8;
|
||||
|
||||
class SerialPassthrough
|
||||
{
|
||||
public:
|
||||
SerialPassthrough(const char *device_path, unsigned baudrate, bool swap_rxtx, bool single_wire, int esc_channel = -1);
|
||||
~SerialPassthrough();
|
||||
|
||||
static int task_spawn(int argc, char *argv[]);
|
||||
static int run_trampoline(int argc, char *argv[]);
|
||||
static SerialPassthrough *instantiate(int argc, char *argv[]);
|
||||
static int print_usage(const char *reason = nullptr);
|
||||
|
||||
void run();
|
||||
|
||||
/**
|
||||
* Print status of all running instances.
|
||||
*/
|
||||
static int print_status_all();
|
||||
|
||||
/**
|
||||
* Get instance by slot index (0..SP_MAX_INSTANCES-1). Returns nullptr if slot empty.
|
||||
* Used by Mavlink main loop to iterate all instances.
|
||||
*/
|
||||
static SerialPassthrough *get_instance_by_index(int index);
|
||||
|
||||
/**
|
||||
* Get the running instance for a specific device_id. Returns nullptr if not running.
|
||||
*/
|
||||
static SerialPassthrough *get_instance_for_device(uint8_t device_id);
|
||||
|
||||
/**
|
||||
* Start an instance for a given device ID (from SERIAL_CONTROL device field).
|
||||
* Maps device IDs to board-specific UART paths using CONFIG_BOARD_SERIAL_*.
|
||||
* If already running on the same device, does nothing.
|
||||
* Device IDs: 0=TEL1, 1=TEL2, 2=GPS1, 3=GPS2, 4=TEL3, 5=TEL4, 20-27=ESC bitbang ch0-7
|
||||
* Returns 0 on success, -1 if device ID is not supported on this board.
|
||||
*/
|
||||
static int startForDevice(uint8_t device_id, uint32_t baudrate);
|
||||
|
||||
/**
|
||||
* Stop the instance for a specific device_id.
|
||||
*/
|
||||
static void stop_for_device(uint8_t device_id);
|
||||
|
||||
/**
|
||||
* Stop all running instances.
|
||||
*/
|
||||
static void stop_all();
|
||||
|
||||
/**
|
||||
* Push data received via MAVLink SERIAL_CONTROL to the UART.
|
||||
* Thread-safe; called from MavlinkReceiver thread.
|
||||
* channel: the MAVLink channel index (0-based) this arrived on.
|
||||
*/
|
||||
void pushFromMavlink(const uint8_t *data, size_t len,
|
||||
uint8_t sysid, uint8_t compid, uint8_t device,
|
||||
uint8_t channel);
|
||||
|
||||
/**
|
||||
* Pop up to max_len bytes of UART-received data for sending back as
|
||||
* SERIAL_CONTROL reply. Thread-safe; called from Mavlink main loop.
|
||||
* Only returns data if channel matches the channel that sent the request.
|
||||
*/
|
||||
size_t popToMavlink(uint8_t *buf, size_t max_len,
|
||||
uint8_t *out_sysid, uint8_t *out_compid, uint8_t *out_device,
|
||||
uint8_t channel);
|
||||
|
||||
bool should_exit() const { return _should_exit.load(); }
|
||||
void request_stop() { _should_exit.store(true); }
|
||||
|
||||
private:
|
||||
// --- Static instance registry ---
|
||||
static SerialPassthrough *_instances[SP_MAX_INSTANCES];
|
||||
static pthread_mutex_t _instances_mutex;
|
||||
|
||||
bool register_instance(uint8_t device_id);
|
||||
void unregister_instance();
|
||||
|
||||
device::Serial _serial_port;
|
||||
char _dev_path[20] {};
|
||||
unsigned _baudrate{115200};
|
||||
bool _swap_rxtx{false};
|
||||
bool _single_wire{false};
|
||||
int _esc_channel{-1}; // if >= 0, use bitbang_uart on this motor channel instead of _serial_port
|
||||
uint8_t _registered_device_id{255};
|
||||
|
||||
px4::atomic_bool _should_exit{false};
|
||||
|
||||
// MAVLink → UART buffer (written by pushFromMavlink, drained by run())
|
||||
uint8_t _rx_buf[SP_BUF_SIZE] {};
|
||||
size_t _rx_len{0};
|
||||
pthread_mutex_t _rx_mutex;
|
||||
|
||||
// UART → MAVLink buffer (written by run(), drained by popToMavlink)
|
||||
uint8_t _tx_buf[SP_BUF_SIZE] {};
|
||||
size_t _tx_len{0};
|
||||
pthread_mutex_t _tx_mutex;
|
||||
|
||||
// Reply metadata (sysid/compid/device/channel of last received message)
|
||||
uint8_t _target_sysid{0};
|
||||
uint8_t _target_compid{0};
|
||||
uint8_t _device_id{0};
|
||||
uint8_t _tx_channel{255}; // MAVLink channel index to reply on (255 = not set)
|
||||
pthread_mutex_t _meta_mutex;
|
||||
|
||||
uint8_t _ser_read_buf[256] {};
|
||||
};
|
||||
@@ -147,6 +147,10 @@ px4_add_module(
|
||||
UNITY_BUILD
|
||||
)
|
||||
|
||||
if(CONFIG_DRIVERS_SERIALPASSTHROUGH)
|
||||
target_link_libraries(modules__mavlink PRIVATE drivers__serialpassthrough)
|
||||
endif()
|
||||
|
||||
px4_add_unit_gtest(SRC MavlinkStatustextHandlerTest.cpp
|
||||
INCLUDES
|
||||
${MAVLINK_LIBRARY_DIR}
|
||||
|
||||
@@ -61,6 +61,10 @@
|
||||
#include "mavlink_receiver.h"
|
||||
#include "mavlink_main.h"
|
||||
|
||||
#ifdef CONFIG_DRIVERS_SERIALPASSTHROUGH
|
||||
#include <drivers/serialpassthrough/serialpassthrough.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef MAVLINK_UDP
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
@@ -2519,6 +2523,7 @@ Mavlink::task_main(int argc, char *argv[])
|
||||
handleCommands();
|
||||
handleAndGetCurrentCommandAck();
|
||||
handleMavlinkShellOutput();
|
||||
handleSerialPassthroughOutput();
|
||||
|
||||
check_requested_subscriptions();
|
||||
|
||||
@@ -2694,6 +2699,39 @@ void Mavlink::handleStatus()
|
||||
}
|
||||
}
|
||||
|
||||
void Mavlink::handleSerialPassthroughOutput()
|
||||
{
|
||||
#ifdef CONFIG_DRIVERS_SERIALPASSTHROUGH
|
||||
// Drain all pending UART->MAVLink data from every active instance,
|
||||
// one SERIAL_CONTROL message at a time.
|
||||
mavlink_serial_control_t msg{};
|
||||
msg.baudrate = 0;
|
||||
msg.timeout = 0;
|
||||
msg.flags = SERIAL_CONTROL_FLAG_REPLY;
|
||||
|
||||
uint8_t sysid, compid, device;
|
||||
|
||||
for (int i = 0; i < SP_MAX_INSTANCES; i++) {
|
||||
SerialPassthrough *sp = SerialPassthrough::get_instance_by_index(i);
|
||||
|
||||
if (!sp) { continue; }
|
||||
|
||||
while (get_free_tx_buf() >= MAVLINK_MSG_ID_SERIAL_CONTROL_LEN + MAVLINK_NUM_NON_PAYLOAD_BYTES) {
|
||||
size_t n = sp->popToMavlink(msg.data, sizeof(msg.data), &sysid, &compid, &device,
|
||||
(uint8_t)get_channel());
|
||||
|
||||
if (n == 0) { break; }
|
||||
|
||||
PX4_DEBUG("handleSerialPassthroughOutput: sending %zu bytes", n);
|
||||
msg.count = n;
|
||||
msg.device = device;
|
||||
mavlink_msg_serial_control_send_struct(get_channel(), &msg);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void Mavlink::handleMavlinkShellOutput()
|
||||
{
|
||||
if (_mavlink_shell) { // First do a fast check before taking the lock
|
||||
|
||||
@@ -694,6 +694,8 @@ private:
|
||||
|
||||
void handleMavlinkShellOutput();
|
||||
|
||||
void handleSerialPassthroughOutput();
|
||||
|
||||
/**
|
||||
* Reconfigure a SiK radio if requested by MAV_SIK_RADIO_ID
|
||||
*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2012-2021 PX4 Development Team. All rights reserved.
|
||||
* Copyright (c) 2012-2026 PX4 Development Team. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -61,6 +61,10 @@
|
||||
#include "mavlink_main.h"
|
||||
#include "mavlink_receiver.h"
|
||||
|
||||
#ifdef CONFIG_DRIVERS_SERIALPASSTHROUGH
|
||||
#include <drivers/serialpassthrough/serialpassthrough.hpp>
|
||||
#endif
|
||||
|
||||
#include <lib/drivers/device/Device.hpp> // For DeviceId union
|
||||
#include <containers/LockGuard.hpp>
|
||||
|
||||
@@ -1996,13 +2000,36 @@ MavlinkReceiver::handle_message_serial_control(mavlink_message_t *msg)
|
||||
if ((serial_control_mavlink.target_system != 0 &&
|
||||
mavlink_system.sysid != serial_control_mavlink.target_system) ||
|
||||
(serial_control_mavlink.target_component != 0 &&
|
||||
mavlink_system.compid != serial_control_mavlink.target_component)) {
|
||||
mavlink_system.compid != serial_control_mavlink.target_component) ||
|
||||
(serial_control_mavlink.flags & SERIAL_CONTROL_FLAG_REPLY)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// (0=TEL1, 1=TEL2, 2=GPS1, 3=GPS2, 4=TEL3, 5=TEL4)
|
||||
// (20-27: ESC0 - ESC7)
|
||||
#ifdef CONFIG_DRIVERS_SERIALPASSTHROUGH
|
||||
|
||||
if (serial_control_mavlink.device <= 5 ||
|
||||
(serial_control_mavlink.device >= 20 && serial_control_mavlink.device <= 27)) {
|
||||
|
||||
SerialPassthrough::startForDevice(serial_control_mavlink.device, serial_control_mavlink.baudrate);
|
||||
SerialPassthrough *sp = SerialPassthrough::get_instance_for_device(serial_control_mavlink.device);
|
||||
|
||||
if (sp && serial_control_mavlink.count > 0) {
|
||||
sp->pushFromMavlink(serial_control_mavlink.data,
|
||||
serial_control_mavlink.count,
|
||||
msg->sysid, msg->compid,
|
||||
serial_control_mavlink.device,
|
||||
(uint8_t)_mavlink.get_channel());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endif // CONFIG_DRIVERS_SERIALPASSTHROUGH
|
||||
|
||||
// we only support shell commands
|
||||
if (serial_control_mavlink.device != SERIAL_CONTROL_DEV_SHELL
|
||||
|| (serial_control_mavlink.flags & SERIAL_CONTROL_FLAG_REPLY)) {
|
||||
if (serial_control_mavlink.device != SERIAL_CONTROL_DEV_SHELL) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user