summaryrefslogtreecommitdiff
path: root/components/drivers/include
diff options
context:
space:
mode:
Diffstat (limited to 'components/drivers/include')
-rw-r--r--components/drivers/include/drivers/adc_v2.h622
-rw-r--r--components/drivers/include/drivers/adc_v2_trigger.h171
-rw-r--r--components/drivers/include/drivers/clock_time.h34
-rw-r--r--components/drivers/include/rtdevice.h6
4 files changed, 830 insertions, 3 deletions
diff --git a/components/drivers/include/drivers/adc_v2.h b/components/drivers/include/drivers/adc_v2.h
new file mode 100644
index 0000000000..bf369e3a50
--- /dev/null
+++ b/components/drivers/include/drivers/adc_v2.h
@@ -0,0 +1,622 @@
+/*
+ * Copyright (c) 2006-2026, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-04-21 wdfk-prog add standalone adc v2 framework interface
+ */
+
+/**
+ * @file adc_v2.h
+ * @brief Standalone ADC V2 framework declarations.
+ */
+
+#ifndef __ADC_V2_H__
+#define __ADC_V2_H__
+
+#include <rtconfig.h>
+#include "misc.h"
+#if !defined(RT_USING_ADC_V2)
+#error "ADC V2 interface requires RT_USING_ADC_V2."
+#endif /* !defined(RT_USING_ADC_V2) */
+
+#include <rtatomic.h>
+#include <rtdevice.h>
+#include <rtthread.h>
+
+#if defined(RT_ADC_USING_TRIGGER)
+#include <drivers/adc_v2_trigger.h>
+#endif /* defined(RT_ADC_USING_TRIGGER) */
+
+#if defined(RT_ADC_USING_STREAM) && defined(RT_ADC_STREAM_USING_FIFO)
+#include <ipc/completion.h>
+#include <ipc/ringbuffer.h>
+#endif /* defined(RT_ADC_USING_STREAM) && defined(RT_ADC_STREAM_USING_FIFO) */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @brief ADC control command identifiers.
+ */
+enum rt_adc_control_cmd
+{
+ RT_ADC_CMD_GET_RESOLUTION = RT_DEVICE_CTRL_BASE(ADC) + 1, /**< Get resolution in bits. */
+ RT_ADC_CMD_CALIBRATE, /**< Run ADC calibration. */
+ RT_ADC_CMD_SET_VREF, /**< Set fallback VREF from rt_uint32_t mV. */
+ RT_ADC_CMD_CALC_VREF, /**< Calculate VDDA from a raw VREF sample. */
+ RT_ADC_CMD_GET_VREF_CHANNEL, /**< Get the backend VREF sample channel as rt_uint8_t. */
+ RT_ADC_CMD_SET_SESSION, /**< Configure and cache conversion channels from rt_uint32_t mask. */
+ RT_ADC_CMD_SET_CONFIG, /**< Set backend private device configuration. */
+ RT_ADC_CMD_GET_CONFIG, /**< Get backend private device configuration. */
+ RT_ADC_CMD_CLEAR_CHANNEL_CONFIG /**< Clear backend channel/rank configuration explicitly. */
+};
+
+/**
+ * @brief ADC input mode request flags.
+ */
+enum rt_adc_input_mode
+{
+ RT_ADC_INPUT_MODE_SINGLE_ENDED = 0x01U, /**< Single-ended ADC input mode. */
+ RT_ADC_INPUT_MODE_DIFFERENTIAL = 0x02U /**< Differential ADC input mode. */
+};
+
+/**
+ * @brief Build an ADC channel mask from one logical channel index.
+ * @param _channel Logical ADC channel index.
+ */
+#define RT_ADC_CHANNEL_MASK(_channel) (1UL << (rt_uint32_t)(_channel))
+
+/**
+ * @brief ADC framework runtime state.
+ */
+enum rt_adc_state
+{
+ RT_ADC_STATE_IDLE = 0, /**< The ADC device is idle. */
+ RT_ADC_STATE_LOCKED, /**< The ADC device is temporarily locked by a framework operation. */
+ RT_ADC_STATE_STREAM /**< The ADC device is owned by an active stream session. */
+};
+
+struct rt_adc_device;
+typedef struct rt_adc_device *rt_adc_device_t;
+
+struct rt_adc_sequence_cfg;
+struct rt_adc_stream_cfg;
+
+/**
+ * @brief ADC core driver operation table.
+ */
+struct rt_adc_core_ops
+{
+ /**
+ * @brief Open and initialize the ADC hardware.
+ * @param device Pointer to the ADC device object.
+ * @return Operation status.
+ */
+ rt_err_t (*open)(struct rt_adc_device *device);
+
+ /**
+ * @brief Close and deinitialize the ADC hardware.
+ * @param device Pointer to the ADC device object.
+ * @return Operation status.
+ */
+ rt_err_t (*close)(struct rt_adc_device *device);
+
+
+ /**
+ * @brief Configure one ADC conversion session before data transfer.
+ * @param device Pointer to the ADC device object.
+ * @param channels ADC channel selection mask.
+ * @return Operation status.
+ */
+ rt_err_t (*session_config)(struct rt_adc_device *device, rt_uint32_t channels);
+
+#if defined(RT_ADC_USING_TRIGGER)
+ /**
+ * @brief Preconfigure the ADC backend trigger state for the next hardware configuration pass.
+ * @param device Pointer to the ADC device object.
+ * @param cfg Pointer to the active ADC trigger configuration object.
+ * @return Operation status.
+ * @note The implementation may only validate @p cfg, update pending driver
+ * state, or fill HAL initialization fields. It must not start the
+ * trigger source or arm ADC conversions.
+ */
+ rt_err_t (*trigger_prepare)(struct rt_adc_device *device, const struct rt_adc_trigger_cfg *cfg);
+#endif /* defined(RT_ADC_USING_TRIGGER) */
+
+ /**
+ * @brief Handle ADC control commands.
+ * @param device Pointer to the ADC device object.
+ * @param cmd Control command.
+ * @param args Pointer to the control argument buffer.
+ * @return Operation status.
+ */
+ rt_err_t (*control)(struct rt_adc_device *device, int cmd, void *args);
+};
+
+/**
+ * @brief ADC finite-sequence operation table.
+ */
+struct rt_adc_sequence_ops
+{
+ /**
+ * @brief Start one active finite transfer session.
+ * @param device Pointer to the ADC device object.
+ * @param channels ADC channel selection mask.
+ * @param cfg Pointer to the sequence request object.
+ * @return Operation status.
+ */
+ rt_err_t (*start)(struct rt_adc_device *device, rt_uint32_t channels, const struct rt_adc_sequence_cfg *cfg);
+
+ /**
+ * @brief Read one converted sample from an active finite transfer session.
+ * @param device Pointer to the ADC device object.
+ * @param value Pointer to the output sample value.
+ * @param timeout_ms Read timeout in milliseconds; negative means wait forever.
+ * @return Operation status.
+ */
+ rt_err_t (*read)(struct rt_adc_device *device, rt_uint32_t *value, rt_int32_t timeout_ms);
+
+ /**
+ * @brief Stop one active finite transfer session.
+ * @param device Pointer to the ADC device object.
+ * @return Operation status.
+ */
+ rt_err_t (*stop)(struct rt_adc_device *device);
+};
+
+#ifdef RT_ADC_USING_STREAM
+/**
+ * @brief ADC stream operation table.
+ */
+struct rt_adc_stream_ops
+{
+ /**
+ * @brief Start one active stream session.
+ * @param device Pointer to the ADC device object.
+ * @param channels ADC channel selection mask.
+ * @param cfg Pointer to the stream configuration object.
+ * @return Operation status.
+ */
+ rt_err_t (*start)(struct rt_adc_device *device, rt_uint32_t channels, const struct rt_adc_stream_cfg *cfg);
+
+ /**
+ * @brief Synchronize a backend DMA sample range before CPU access.
+ * @param device Pointer to the ADC device object.
+ * @param sample_buffer Pointer to the DMA sample buffer.
+ * @param sample_count Number of samples to synchronize.
+ * @return Operation status.
+ */
+ rt_err_t (*sync)(struct rt_adc_device *device, const rt_uint32_t *sample_buffer, rt_size_t sample_count);
+
+ /**
+ * @brief Stop one active stream session.
+ * @param device Pointer to the ADC device object.
+ * @param hardware_stopped Pointer to the hardware-stop state output.
+ * @return Operation status.
+ *
+ * The backend sets @p hardware_stopped to RT_TRUE after the ADC hardware
+ * conversion path has stopped. When this callback returns an error with
+ * @p hardware_stopped set to RT_TRUE, the framework treats it as a
+ * post-stop cleanup failure and moves the stream to IDLE.
+ */
+ rt_err_t (*stop)(struct rt_adc_device *device, rt_bool_t *hardware_stopped);
+};
+#endif /* RT_ADC_USING_STREAM */
+
+
+/**
+ * @brief ADC driver operation table.
+ */
+struct rt_adc_ops
+{
+ const struct rt_adc_core_ops *core; /**< Core operation table. */
+ const struct rt_adc_sequence_ops *sequence; /**< Sequence-session operations. */
+#ifdef RT_ADC_USING_STREAM
+ const struct rt_adc_stream_ops *stream; /**< Stream-session operations. */
+#endif /* RT_ADC_USING_STREAM */
+};
+
+/**
+ * @brief ADC synchronous one-frame sequence request.
+ */
+struct rt_adc_sequence_cfg
+{
+ rt_uint32_t *buffer; /**< Destination sample buffer. */
+ rt_size_t buffer_length; /**< Destination buffer length in samples. */
+ rt_int32_t timeout_ms; /**< Per-sample timeout; negative means wait forever. */
+};
+
+#ifdef RT_ADC_USING_STREAM
+/**
+ * @brief ADC stream backend event.
+ */
+enum rt_adc_stream_event
+{
+ RT_ADC_STREAM_EVENT_DMA_HALF = 0x01U, /**< ADC stream DMA half-transfer event. */
+ RT_ADC_STREAM_EVENT_DMA_DONE = 0x02U, /**< ADC stream DMA transfer-complete event. */
+ RT_ADC_STREAM_EVENT_ERROR = 0x03U /**< ADC stream backend error event. */
+};
+
+/**
+ * @brief ADC stream buffering policy.
+ */
+enum rt_adc_stream_policy
+{
+#ifdef RT_ADC_STREAM_USING_LATEST
+ /**
+ * @brief Keep only the latest ADC rank values.
+ *
+ * This policy is intended for slow-changing ADC values such as battery
+ * voltage, temperature, potentiometer input, resistor-divider voltage, or
+ * board status monitoring. Old values may be overwritten.
+ *
+ * In this policy, @ref rt_adc_stream_cfg::dma_buffer_length must be exactly
+ * equal to the active ADC frame length, namely the number of enabled ADC
+ * ranks. The backend must expose the DMA buffer as a single latest-frame
+ * layout:
+ *
+ * - dma_buffer[0] stores the latest value of ADC rank 1.
+ * - dma_buffer[1] stores the latest value of ADC rank 2.
+ * - dma_buffer[n] stores the latest value of ADC rank n + 1.
+ *
+ * STM32 regular scan conversion with circular DMA naturally satisfies this
+ * layout when the DMA length equals the ADC rank count. Backends for other
+ * platforms may also support this policy if their DMA engine writes samples
+ * in scan-rank order. If a backend produces packed, interleaved,
+ * descriptor-based, hardware-FIFO, or otherwise non-rank-ordered data, it
+ * must either convert the data into this latest-frame layout internally or
+ * reject the configuration with -RT_ENOSYS.
+ *
+ * @note Latest mode is a low-overhead lockless DMA-buffer view. CPU-side
+ * atomic operations, spin locks, mutexes, or read-write locks cannot
+ * prevent the DMA engine from updating memory concurrently, because
+ * DMA does not participate in CPU locking protocols. This mode only
+ * guarantees that each buffer index maps to the corresponding ADC rank
+ * latest value; it does not guarantee that the copied frame is a
+ * single hardware scan-cycle snapshot. Use RT_ADC_STREAM_POLICY_FIFO
+ * when ordered and frame-accurate samples are required.
+ */
+ RT_ADC_STREAM_POLICY_LATEST = 0,
+#endif /* RT_ADC_STREAM_USING_LATEST */
+#ifdef RT_ADC_STREAM_USING_FIFO
+ /**
+ * @brief Preserve ADC samples in FIFO order.
+ *
+ * This policy is intended for continuous and loss-sensitive sampling such
+ * as waveform, current, vibration, audio-like, motor-control, or
+ * control-loop data where each sample matters.
+ *
+ * The backend reports completed DMA blocks to the ADC framework. The
+ * framework copies those blocks into a ringbuffer and wakes blocking readers
+ * through a completion object.
+ */
+ RT_ADC_STREAM_POLICY_FIFO,
+#endif /* RT_ADC_STREAM_USING_FIFO */
+};
+
+/**
+ * @brief ADC stream DMA data event mode.
+ */
+enum rt_adc_stream_dma_event_mode
+{
+ RT_ADC_STREAM_DMA_EVENT_AUTO = 0, /**< Use the default event mode for the selected stream policy. */
+ RT_ADC_STREAM_DMA_EVENT_NONE, /**< Disable DMA half/full data events; DMA error events remain enabled. */
+ RT_ADC_STREAM_DMA_EVENT_FULL_ONLY, /**< Report only DMA transfer-complete data events to reduce interrupt rate. */
+ RT_ADC_STREAM_DMA_EVENT_HALF_FULL /**< Report both DMA half-transfer and transfer-complete data events. */
+};
+
+/**
+ * @brief ADC stream FIFO data callback type.
+ * @param device Pointer to the ADC device object.
+ * @param sample_count Number of newly accepted samples.
+ * @param user_data Pointer to the user context.
+ * @note This callback is invoked from ADC stream ISR context. It must not
+ * block, sleep, or call APIs that may suspend the current context.
+ */
+typedef void (*rt_adc_stream_callback_t)(struct rt_adc_device *device, rt_size_t sample_count, void *user_data);
+
+/**
+ * @brief ADC stream configuration.
+ * @note The DMA buffer belongs to the caller and must remain valid until
+ * rt_adc_stream_stop() returns. The stream configuration object only
+ * needs to remain valid for the duration of rt_adc_stream_start(). A
+ * backend may use an internal cache-aligned DMA buffer when the caller
+ * buffer is not safe for platform cache maintenance. Backend drivers must
+ * copy scalar configuration fields they need after rt_adc_stream_start()
+ * returns.
+ */
+struct rt_adc_stream_cfg
+{
+ enum rt_adc_stream_policy policy; /**< Stream buffering policy. */
+ enum rt_adc_stream_dma_event_mode dma_event_mode; /**< DMA half/full data event mode. */
+
+ /**
+ * @brief DMA circular staging buffer.
+ *
+ * For RT_ADC_STREAM_POLICY_LATEST, this buffer stores exactly one latest
+ * ADC scan frame. dma_buffer_length must equal the active frame length.
+ * Each element maps to one configured ADC rank.
+ *
+ * For RT_ADC_STREAM_POLICY_FIFO, this buffer is a DMA staging buffer. The
+ * default rt_adc_stream_start() entry validates only basic buffer presence
+ * and capacity. It does not require each DMA data-event block to end on an
+ * ADC scan-frame boundary.
+ *
+ * Use rt_adc_stream_start_frame_aligned_fifo() when continuous FIFO sampling
+ * requires a strict frame-aligned DMA/FIFO layout before the stream starts.
+ */
+ rt_uint32_t *dma_buffer;
+
+ /**
+ * @brief DMA buffer length in samples.
+ */
+ rt_size_t dma_buffer_length;
+#ifdef RT_ADC_STREAM_USING_FIFO
+ rt_uint32_t *fifo_buffer; /**< FIFO storage for FIFO policy. */
+ rt_size_t fifo_buffer_length; /**< FIFO buffer length in samples. */
+ rt_size_t watermark; /**< FIFO wakeup or callback threshold in samples. */
+ rt_adc_stream_callback_t callback; /**< Optional ISR-context FIFO data callback. */
+ void *user_data; /**< User data passed to the FIFO data callback. */
+#endif /* RT_ADC_STREAM_USING_FIFO */
+};
+
+/**
+ * @brief ADC stream runtime control block owned by the ADC framework.
+ */
+struct rt_adc_stream_ctrl
+{
+ rt_bool_t active; /**< Whether a stream backend session is active. */
+ enum rt_adc_stream_policy policy; /**< Active stream buffering policy. */
+ enum rt_adc_stream_dma_event_mode dma_event_mode; /**< Active DMA data event mode. */
+ rt_uint32_t *dma_buffer; /**< DMA circular staging buffer. */
+ rt_size_t dma_buffer_length; /**< DMA buffer length in samples. */
+ rt_size_t frame_length; /**< Samples in one ADC scan frame. */
+#ifdef RT_ADC_STREAM_USING_FIFO
+ struct rt_ringbuffer fifo; /**< FIFO storage for FIFO policy. */
+ rt_bool_t fifo_enabled; /**< FIFO initialized flag. */
+ /**
+ * @brief Reader wake completion for FIFO stream.
+ *
+ * The FIFO ringbuffer is the source of truth for available data. This
+ * completion object is only a wakeup edge for blocking reads.
+ */
+ struct rt_completion rx_cpt;
+ rt_size_t overflow_count; /**< FIFO overrun count. */
+ rt_size_t watermark; /**< FIFO wakeup or callback threshold. */
+ rt_adc_stream_callback_t callback; /**< Optional FIFO data callback. */
+ void *user_data; /**< Callback private data. */
+#endif /* RT_ADC_STREAM_USING_FIFO */
+ rt_atomic_t last_error; /**< Atomic last stream backend error. */
+};
+#endif /* RT_ADC_USING_STREAM */
+
+/**
+ * @brief ADC active session runtime control block.
+ */
+struct rt_adc_session_ctrl
+{
+ rt_uint32_t channels; /**< Cached active ADC channel selection mask. */
+ rt_size_t channel_count; /**< Cached active session channel count. */
+ rt_bool_t configured; /**< Whether the cached session configuration is valid. */
+};
+
+/**
+ * @brief ADC device object.
+ */
+struct rt_adc_device
+{
+ struct rt_device parent; /**< RT-Thread device object. */
+ const struct rt_adc_ops *ops; /**< ADC driver operation table. */
+ rt_atomic_t state; /**< Atomic ADC runtime state. */
+ struct rt_spinlock spinlock; /**< Protects ADC stream FIFO shared by thread context and ISR. */
+ rt_uint32_t default_vref_mv; /**< Default reference voltage in millivolts. */
+ struct rt_adc_session_ctrl session_ctrl; /**< ADC active session control block. */
+#if defined(RT_ADC_USING_TRIGGER)
+ struct rt_adc_trigger_ctrl trigger_ctrl; /**< ADC trigger runtime control block. */
+#endif /* defined(RT_ADC_USING_TRIGGER) */
+#ifdef RT_ADC_USING_STREAM
+ struct rt_adc_stream_ctrl stream_ctrl; /**< ADC stream runtime control block. */
+#endif /* RT_ADC_USING_STREAM */
+};
+
+/**
+ * @brief Count selected ADC channels in one channel mask.
+ * @param channels ADC channel selection mask.
+ * @return Number of selected channels.
+ */
+rt_inline rt_size_t rt_adc_channel_mask_count(rt_uint32_t channels)
+{
+#if defined(__GNUC__) || defined(__clang__)
+ return (rt_size_t)__builtin_popcount((unsigned int)channels);
+#else
+ rt_size_t count;
+
+ count = 0U;
+ while (channels != 0U)
+ {
+ channels &= channels - 1U;
+ count++;
+ }
+
+ return count;
+#endif /* defined(__GNUC__) || defined(__clang__) */
+}
+
+/**
+ * @brief Take the lowest selected ADC channel from one channel mask.
+ * @param channels Pointer to the ADC channel selection mask.
+ * @return Selected channel index, or 0xff if the mask is empty.
+ */
+rt_inline rt_uint8_t rt_adc_channel_mask_take_lsb(rt_uint32_t *channels)
+{
+ rt_uint8_t bit;
+
+ if ((channels == RT_NULL) || (*channels == 0U))
+ {
+ return 0xffU;
+ }
+
+#if defined(__GNUC__) || defined(__clang__)
+ bit = (rt_uint8_t)__builtin_ctz((unsigned int)*channels);
+#else
+ for (bit = 0U; bit < 32U; bit++)
+ {
+ if ((*channels & RT_ADC_CHANNEL_MASK(bit)) != 0U)
+ {
+ break;
+ }
+ }
+#endif /* defined(__GNUC__) || defined(__clang__) */
+
+ *channels &= ~RT_ADC_CHANNEL_MASK(bit);
+ return bit;
+}
+
+/**
+ * @brief Register an ADC device with the RT-Thread device framework.
+ * @param device Pointer to the ADC device object.
+ * @param name Pointer to the ADC device name string.
+ * @param ops Pointer to the ADC driver operation table.
+ * @param user_data Pointer to driver private data.
+ * @return Operation status.
+ */
+rt_err_t rt_hw_adc_register(rt_adc_device_t device, const char *name, const struct rt_adc_ops *ops, const void *user_data);
+
+/**
+ * @brief Get the raw sample index of one channel in an ADC session mask.
+ * @param session_channels Configured ADC session channel mask.
+ * @param channel Single-channel mask to locate.
+ * @param index Pointer to the output raw sample index.
+ * @return Operation status.
+ */
+rt_err_t rt_adc_session_channel_index(rt_uint32_t session_channels, rt_uint32_t channel, rt_size_t *index);
+
+
+/**
+ * @brief Read one ADC conversion sequence frame.
+ * @param device Pointer to the ADC device object.
+ * @param channels ADC channel selection mask.
+ * @param cfg Pointer to the ADC sequence request object.
+ * @param read_count Pointer to the stored sample count.
+ * @return Operation status.
+ */
+rt_err_t rt_adc_read_sequence(rt_adc_device_t device, rt_uint32_t channels,
+ const struct rt_adc_sequence_cfg *cfg, rt_size_t *read_count);
+
+#ifdef RT_ADC_USING_STREAM
+/**
+ * @brief Start one ADC stream session.
+ * @param device Pointer to the ADC device object.
+ * @param channels ADC channel selection mask.
+ * @param cfg Pointer to the ADC stream configuration object.
+ * @return Operation status.
+ */
+rt_err_t rt_adc_stream_start(rt_adc_device_t device, rt_uint32_t channels, const struct rt_adc_stream_cfg *cfg);
+
+#ifdef RT_ADC_STREAM_USING_FIFO
+/**
+ * @brief Start one FIFO ADC stream with strict frame-aligned buffer layout.
+ * @param device Pointer to the ADC device object.
+ * @param channels ADC channel selection mask.
+ * @param cfg Pointer to the ADC stream configuration object.
+ * @return Operation status.
+ */
+rt_err_t rt_adc_stream_start_frame_aligned_fifo(rt_adc_device_t device, rt_uint32_t channels, const struct rt_adc_stream_cfg *cfg);
+#endif /* RT_ADC_STREAM_USING_FIFO */
+
+/**
+ * @brief Read converted samples from an active ADC stream session.
+ * @param device Pointer to the ADC device object.
+ * @param buffer Pointer to the destination sample buffer.
+ * @param sample_count Number of samples to read.
+ * @param timeout_ms Read timeout in milliseconds; negative means wait forever.
+ * @return Number of samples read, or a negative RT-Thread error code.
+ */
+rt_ssize_t rt_adc_stream_read(rt_adc_device_t device, rt_uint32_t *buffer, rt_size_t sample_count, rt_int32_t timeout_ms);
+
+/**
+ * @brief Cancel a blocked ADC stream reader before stream shutdown.
+ * @param device Pointer to the ADC device object.
+ * @return Operation status.
+ */
+rt_err_t rt_adc_stream_cancel(rt_adc_device_t device);
+
+/**
+ * @brief Stop one ADC stream session.
+ * @param device Pointer to the ADC device object.
+ * @return Operation status.
+ */
+rt_err_t rt_adc_stream_stop(rt_adc_device_t device);
+
+/**
+ * @brief Notify the ADC framework of one stream backend event.
+ * @param device Pointer to the ADC device object.
+ * @param event ADC stream event reported by the backend or ISR.
+ * @param sample_buffer Pointer to the completed sample buffer block.
+ * @param sample_count Number of samples in @p sample_buffer.
+ * @return Operation status.
+ */
+rt_err_t rt_hw_adc_stream_isr(rt_adc_device_t device, enum rt_adc_stream_event event,
+ const rt_uint32_t *sample_buffer, rt_size_t sample_count);
+#endif /* RT_ADC_USING_STREAM */
+
+/**
+ * @brief Convert one raw ADC sample to millivolts.
+ * @param raw_value Raw ADC sample value.
+ * @param vref_mv ADC reference voltage in millivolts.
+ * @param resolution_bits ADC resolution in bits.
+ * @param voltage_mv Pointer to the output voltage in millivolts.
+ * @return Operation status.
+ */
+rt_err_t rt_adc_raw_to_voltage_mv(rt_uint32_t raw_value, rt_uint32_t vref_mv, rt_uint8_t resolution_bits, rt_uint32_t *voltage_mv);
+
+/**
+ * @brief Convert one ADC raw sample to a scaled voltage in millivolts.
+ * @param raw_value Raw ADC sample code.
+ * @param vref_mv ADC reference voltage in millivolts.
+ * @param resolution_bits ADC resolution in bits.
+ * @param scale_num Voltage scaling numerator.
+ * @param scale_den Voltage scaling denominator.
+ * @param voltage_mv Pointer to the output scaled voltage in millivolts.
+ * @return Operation status.
+ *
+ * The scaled voltage is calculated as:
+ *
+ * raw_to_voltage_mv(raw_value) * scale_num / scale_den
+ *
+ * @note @p scale_num and @p scale_den may describe any positive rational
+ * scaling ratio that does not overflow the internal calculation. The
+ * final scaled millivolt value must fit in rt_uint32_t.
+ *
+ * @retval RT_EOK The conversion completed successfully.
+ * @retval -RT_EINVAL A pointer is null, a scale argument is zero, the ADC
+ * conversion arguments are invalid, or the scaled result overflows
+ * rt_uint32_t.
+ */
+rt_err_t rt_adc_raw_to_scaled_voltage_mv(rt_uint32_t raw_value, rt_uint32_t vref_mv, rt_uint8_t resolution_bits, rt_uint32_t scale_num, rt_uint32_t scale_den, rt_uint32_t *voltage_mv);
+
+/**
+ * @brief Read ADC samples and convert them to millivolts.
+ * @param device Pointer to the ADC device object.
+ * @param voltages_mv Pointer to the output voltage buffer in millivolts.
+ * @param size Output voltage buffer length.
+ * @param timeout_ms Per-sample timeout in milliseconds; negative means wait forever.
+ * @return Operation status.
+ *
+ * @note This API reads the currently configured ADC session and does not modify
+ * the active channel mask. If default_vref_mv is zero, callers that need
+ * backend-calculated VDDA must include the backend VREF channel in the
+ * configured session. The VREF sample is used only as the reference for
+ * conversion and is not auto-inserted by this API.
+ */
+rt_err_t rt_adc_voltage(rt_adc_device_t device, rt_uint32_t *voltages_mv, rt_size_t size, rt_int32_t timeout_ms);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ADC_V2_H__ */
diff --git a/components/drivers/include/drivers/adc_v2_trigger.h b/components/drivers/include/drivers/adc_v2_trigger.h
new file mode 100644
index 0000000000..bb328b8dba
--- /dev/null
+++ b/components/drivers/include/drivers/adc_v2_trigger.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2006-2026, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2026-05-20 wdfk-prog add ADC V2 trigger declarations
+ */
+
+/**
+ * @file adc_v2_trigger.h
+ * @brief ADC V2 trigger framework declarations.
+ */
+
+#ifndef __ADC_V2_TRIGGER_H__
+#define __ADC_V2_TRIGGER_H__
+
+#include <rtconfig.h>
+#include <rtthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#if defined(RT_ADC_USING_TRIGGER)
+struct rt_adc_device;
+struct rt_device;
+
+/**
+ * @brief ADC hardware trigger event type.
+ *
+ * @note A platform backend may support only part of these trigger types.
+ * Unsupported trigger types shall be rejected by the framework or backend
+ * with an error such as -RT_ENOSYS.
+ */
+enum rt_adc_trigger_type
+{
+ RT_ADC_TRIGGER_TIMER_UPDATE = 0, /**< Use a timer update/TRGO event. */
+ RT_ADC_TRIGGER_TIMER_COMPARE, /**< Use a timer compare event. */
+ RT_ADC_TRIGGER_PWM_EDGE, /**< Use a PWM edge event. */
+ RT_ADC_TRIGGER_EXTI_EDGE, /**< Use an external interrupt edge event. */
+ RT_ADC_TRIGGER_ANALOG_COMPARE, /**< Use an analog comparator event. */
+ RT_ADC_TRIGGER_BACKEND, /**< Use a backend-specific trigger event. */
+};
+
+/**
+ * @brief ADC trigger edge selector.
+ */
+enum rt_adc_trigger_edge
+{
+ RT_ADC_TRIGGER_EDGE_NONE = 0, /**< No edge selection is required. */
+ RT_ADC_TRIGGER_EDGE_RISING, /**< Use the rising edge. */
+ RT_ADC_TRIGGER_EDGE_FALLING, /**< Use the falling edge. */
+ RT_ADC_TRIGGER_EDGE_BOTH, /**< Use both rising and falling edges. */
+};
+
+/**
+ * @brief Timer-based ADC trigger event.
+ */
+struct rt_adc_trigger_timer_event
+{
+ struct rt_device *timer; /**< Timer device used as trigger source. */
+ rt_uint32_t freq_hz; /**< Timer trigger output frequency in hertz. */
+ rt_uint16_t channel; /**< Timer channel, or 0 for update/TRGO event. */
+ rt_uint16_t reserved; /**< Reserved for future extension. */
+};
+
+/**
+ * @brief PWM-based ADC trigger event.
+ */
+struct rt_adc_trigger_pwm_event
+{
+ struct rt_device *pwm; /**< PWM device used as trigger source. */
+ rt_uint16_t channel; /**< PWM channel. */
+ enum rt_adc_trigger_edge edge; /**< PWM edge used as trigger event. */
+};
+
+/**
+ * @brief External interrupt ADC trigger event.
+ */
+struct rt_adc_trigger_exti_event
+{
+ struct rt_device *pin; /**< Pin or GPIO controller device. */
+ rt_uint16_t line; /**< External interrupt line or pin number. */
+ enum rt_adc_trigger_edge edge; /**< Interrupt edge used as trigger event. */
+};
+
+/**
+ * @brief Analog comparator ADC trigger event.
+ */
+struct rt_adc_trigger_compare_event
+{
+ struct rt_device *comparator; /**< Optional comparator device used as trigger source. */
+ rt_uint16_t channel; /**< Comparator channel or instance index. */
+ enum rt_adc_trigger_edge edge; /**< Comparator output edge used as trigger event. */
+};
+
+/**
+ * @brief Backend-specific ADC trigger event.
+ */
+struct rt_adc_trigger_backend_event
+{
+ rt_uint32_t selector; /**< Backend-specific trigger selector. */
+ rt_uint32_t edge; /**< Backend-specific edge selector. */
+ const void *data; /**< Optional backend-specific configuration. */
+ rt_size_t data_size; /**< Size of backend-specific configuration. */
+};
+
+/**
+ * @brief ADC trigger configuration.
+ */
+struct rt_adc_trigger_cfg
+{
+ enum rt_adc_trigger_type type; /**< Trigger event type. */
+ rt_uint32_t flags; /**< Common trigger flags, reserved for future extension. */
+
+ union
+ {
+ struct rt_adc_trigger_timer_event timer; /**< Timer trigger event. */
+ struct rt_adc_trigger_pwm_event pwm; /**< PWM trigger event. */
+ struct rt_adc_trigger_exti_event exti; /**< External interrupt trigger event. */
+ struct rt_adc_trigger_compare_event compare; /**< Comparator trigger event. */
+ struct rt_adc_trigger_backend_event backend; /**< Backend-specific trigger event. */
+ } event; /**< Trigger event payload. */
+};
+
+/**
+ * @brief ADC trigger runtime control block.
+ */
+struct rt_adc_trigger_ctrl
+{
+ struct rt_adc_trigger_cfg cfg; /**< Cached device-level hardware trigger configuration. */
+ rt_bool_t configured; /**< Whether cfg contains a cached hardware trigger request. */
+};
+
+/**
+ * @brief Set one device-level ADC hardware trigger request.
+ * @param device Pointer to the ADC device object.
+ * @param cfg Pointer to the ADC trigger configuration object.
+ * @return Operation status.
+ * @note This function only checks the framework-level trigger structure and
+ * caches the request. It does not write ADC trigger registers immediately.
+ * Backend compatibility is reported when the cached trigger is
+ * preconfigured before a conversion hardware configuration.
+ */
+rt_err_t rt_adc_trigger_set(struct rt_adc_device *device, const struct rt_adc_trigger_cfg *cfg);
+
+/**
+ * @brief Clear the cached device-level ADC hardware trigger request.
+ * @param device Pointer to the ADC device object.
+ * @return Operation status.
+ * @note This function does not write ADC trigger registers immediately. The
+ * next conversion hardware configuration preconfigures the backend
+ * software/default trigger state.
+ */
+rt_err_t rt_adc_trigger_clear(struct rt_adc_device *device);
+
+/**
+ * @brief Check whether one ADC device has a cached hardware trigger request.
+ * @param device Pointer to the ADC device object.
+ * @return RT_TRUE if a hardware trigger request is set, otherwise RT_FALSE.
+ */
+rt_bool_t rt_adc_trigger_is_set(struct rt_adc_device *device);
+#endif /* defined(RT_ADC_USING_TRIGGER) */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __ADC_V2_TRIGGER_H__ */
diff --git a/components/drivers/include/drivers/clock_time.h b/components/drivers/include/drivers/clock_time.h
index 7374b97d00..c43c079eb0 100644
--- a/components/drivers/include/drivers/clock_time.h
+++ b/components/drivers/include/drivers/clock_time.h
@@ -47,9 +47,41 @@ typedef enum
CLOCK_TIMER_CTRL_FREQ_SET = RT_DEVICE_CTRL_BASE(Timer) + 0x01,
CLOCK_TIMER_CTRL_STOP = RT_DEVICE_CTRL_BASE(Timer) + 0x02,
CLOCK_TIMER_CTRL_INFO_GET = RT_DEVICE_CTRL_BASE(Timer) + 0x03,
- CLOCK_TIMER_CTRL_MODE_SET = RT_DEVICE_CTRL_BASE(Timer) + 0x04
+ CLOCK_TIMER_CTRL_MODE_SET = RT_DEVICE_CTRL_BASE(Timer) + 0x04,
+#if defined(RT_USING_CLOCK_TIMER_TRIGGER)
+ CLOCK_TIMER_CTRL_TRIGGER_CONFIG = RT_DEVICE_CTRL_BASE(Timer) + 0x05,
+ CLOCK_TIMER_CTRL_TRIGGER_START = RT_DEVICE_CTRL_BASE(Timer) + 0x06,
+ CLOCK_TIMER_CTRL_TRIGGER_STOP = RT_DEVICE_CTRL_BASE(Timer) + 0x07,
+ CLOCK_TIMER_CTRL_TRIGGER_RELEASE = RT_DEVICE_CTRL_BASE(Timer) + 0x08
+#endif /* defined(RT_USING_CLOCK_TIMER_TRIGGER) */
} rt_clock_timer_ctrl_t;
+#if defined(RT_USING_CLOCK_TIMER_TRIGGER)
+/**
+ * @brief Hardware timer trigger output event type.
+ */
+enum rt_clock_timer_trigger_event
+{
+ CLOCK_TIMER_TRIGGER_EVENT_UPDATE = 0, /**< Generate trigger on timer update/overflow event. */
+ CLOCK_TIMER_TRIGGER_EVENT_COMPARE, /**< Generate trigger on timer compare match event. */
+ CLOCK_TIMER_TRIGGER_EVENT_PWM_EDGE, /**< Generate trigger on timer PWM output reference edge. */
+ CLOCK_TIMER_TRIGGER_EVENT_BACKEND /**< Generate trigger from a backend-specific timer event. */
+};
+
+/**
+ * @brief Hardware trigger output configuration.
+ * @note This interface does not arbitrate timer ownership. Callers must
+ * provide a timer dedicated to hardware trigger output.
+ */
+struct rt_clock_timer_trigger_cfg
+{
+ rt_uint32_t freq_hz; /**< Trigger output frequency in hertz. */
+ enum rt_clock_timer_trigger_event event; /**< Timer event used as trigger output. */
+ rt_uint16_t channel; /**< Timer compare channel, or 0 for update event. */
+ rt_uint16_t reserved; /**< Reserved for future extension. */
+};
+#endif /* defined(RT_USING_CLOCK_TIMER_TRIGGER) */
+
typedef enum
{
CLOCK_TIMER_MODE_ONESHOT = 0x01,
diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h
index e6eb43bc57..a9da14d322 100644
--- a/components/drivers/include/rtdevice.h
+++ b/components/drivers/include/rtdevice.h
@@ -272,9 +272,11 @@ extern "C" {
#include "drivers/dev_audio.h"
#endif /* RT_USING_AUDIO */
-#ifdef RT_USING_ADC
+#ifdef RT_USING_ADC_V2
+#include "drivers/adc_v2.h"
+#elif defined(RT_USING_ADC)
#include "drivers/adc.h"
-#endif /* RT_USING_ADC */
+#endif /* RT_USING_ADC_V2 */
#ifdef RT_USING_DAC
#include "drivers/dac.h"