summaryrefslogtreecommitdiff
path: root/components/drivers
diff options
context:
space:
mode:
authorwdfk-prog <[email protected]>2026-06-15 14:31:59 +0800
committerRbb666 <[email protected]>2026-06-27 11:39:10 +0800
commit1f9146897be1d898bea2a3ed0492c2d0a0507320 (patch)
tree403e514c1afc015fa9112a7c18fdc42b4636ac6c /components/drivers
parent187dc3fddfe45202f4c1000a724f38cdc742dd2e (diff)
feat[serial][v2]: add RX DMA event mode control
add serial v2 RX DMA event mode configuration for DMA-enabled builds support STM32 UART RX DMA half/full transfer interrupt policy selection validate RX DMA event mode before applying serial configuration restore serial configuration when backend configure fails
Diffstat (limited to 'components/drivers')
-rw-r--r--components/drivers/include/drivers/dev_serial_v2.h47
-rw-r--r--components/drivers/serial/dev_serial_v2.c39
2 files changed, 67 insertions, 19 deletions
diff --git a/components/drivers/include/drivers/dev_serial_v2.h b/components/drivers/include/drivers/dev_serial_v2.h
index b987bc4543..2a8d9145e6 100644
--- a/components/drivers/include/drivers/dev_serial_v2.h
+++ b/components/drivers/include/drivers/dev_serial_v2.h
@@ -225,21 +225,37 @@
#define RT_SERIAL_FLOWCONTROL_CTSRTS 1
#define RT_SERIAL_FLOWCONTROL_NONE 0
+#ifdef RT_SERIAL_USING_DMA
+/**
+ * @brief Serial RX DMA data event mode.
+ * @note This mode controls only DMA half/full transfer data events.
+ * UART IDLE interrupt remains enabled in RX DMA mode.
+ */
+enum rt_serial_rx_dma_event_mode
+{
+ RT_SERIAL_RX_DMA_EVENT_AUTO = 0, /**< Use the default RX DMA event mode. */
+ RT_SERIAL_RX_DMA_EVENT_NONE, /**< Disable DMA half/full data events; UART IDLE still reports received data. */
+ RT_SERIAL_RX_DMA_EVENT_FULL_ONLY, /**< Report only DMA transfer-complete data events plus UART IDLE. */
+ RT_SERIAL_RX_DMA_EVENT_HALF_FULL /**< Report both DMA half-transfer and transfer-complete data events plus UART IDLE. */
+};
+#endif /* RT_SERIAL_USING_DMA */
+
/* Default config for serial_configure structure */
#ifdef RT_SERIAL_USING_DMA
-#define RT_SERIAL_CONFIG_DEFAULT \
-{ \
- BAUD_RATE_115200, /* 115200 bits/s */ \
- DATA_BITS_8, /* 8 databits */ \
- STOP_BITS_1, /* 1 stopbit */ \
- PARITY_NONE, /* No parity */ \
- BIT_ORDER_LSB, /* LSB first sent */ \
- NRZ_NORMAL, /* Normal mode */ \
- RT_SERIAL_RX_MINBUFSZ, /* rxBuf size */ \
- RT_SERIAL_TX_MINBUFSZ, /* txBuf size */ \
- RT_SERIAL_FLOWCONTROL_NONE, /* Off flowcontrol */ \
- 0, /* reserved */ \
- RT_SERIAL_RX_MINBUFSZ / 2, /* dma_ping_bufsz */ \
+#define RT_SERIAL_CONFIG_DEFAULT \
+{ \
+ BAUD_RATE_115200, /* 115200 bits/s */ \
+ DATA_BITS_8, /* 8 databits */ \
+ STOP_BITS_1, /* 1 stopbit */ \
+ PARITY_NONE, /* No parity */ \
+ BIT_ORDER_LSB, /* LSB first sent */ \
+ NRZ_NORMAL, /* Normal mode */ \
+ RT_SERIAL_RX_MINBUFSZ, /* rxBuf size */ \
+ RT_SERIAL_TX_MINBUFSZ, /* txBuf size */ \
+ RT_SERIAL_FLOWCONTROL_NONE, /* Off flowcontrol */ \
+ 0, /* reserved */ \
+ RT_SERIAL_RX_MINBUFSZ / 2, /* dma_ping_bufsz */ \
+ RT_SERIAL_RX_DMA_EVENT_AUTO, /* rx dma event mode */ \
}
#else
#define RT_SERIAL_CONFIG_DEFAULT \
@@ -255,7 +271,7 @@
RT_SERIAL_FLOWCONTROL_NONE, /* Off flowcontrol */ \
0, /* reserved */ \
}
-#endif
+#endif /* RT_SERIAL_USING_DMA */
/**
* @brief Serial receive indicate hook function type
@@ -280,7 +296,8 @@ struct serial_configure
#ifdef RT_SERIAL_USING_DMA
rt_uint32_t dma_ping_bufsz :16;
-#endif
+ enum rt_serial_rx_dma_event_mode rx_dma_event_mode; /**< RX DMA half/full data event mode. */
+#endif /* RT_SERIAL_USING_DMA */
};
/**
diff --git a/components/drivers/serial/dev_serial_v2.c b/components/drivers/serial/dev_serial_v2.c
index d8cc2e0cb5..e7851f07ea 100644
--- a/components/drivers/serial/dev_serial_v2.c
+++ b/components/drivers/serial/dev_serial_v2.c
@@ -102,7 +102,7 @@ static int serial_fops_open(struct dfs_file *fd)
rt_device_close(device);
ret = rt_device_open(device, flags);
-
+
if (ret == RT_EOK)
{
serial = (struct rt_serial_device *)device;
@@ -1388,6 +1388,21 @@ static void _tc_flush(struct rt_serial_device *serial, int queue)
}
#endif /* RT_USING_POSIX_TERMIOS */
+#ifdef RT_SERIAL_USING_DMA
+/**
+ * @brief Check whether one serial RX DMA event mode value is valid.
+ * @param mode RX DMA event mode value.
+ * @return RT_TRUE if the mode value is valid.
+ */
+static rt_bool_t rt_serial_rx_dma_event_mode_valid(enum rt_serial_rx_dma_event_mode mode)
+{
+ return ((mode == RT_SERIAL_RX_DMA_EVENT_AUTO) ||
+ (mode == RT_SERIAL_RX_DMA_EVENT_NONE) ||
+ (mode == RT_SERIAL_RX_DMA_EVENT_FULL_ONLY) ||
+ (mode == RT_SERIAL_RX_DMA_EVENT_HALF_FULL)) ? RT_TRUE : RT_FALSE;
+}
+#endif /* RT_SERIAL_USING_DMA */
+
/**
* @brief Control the serial device.
* @param dev The pointer of device driver structure
@@ -1425,20 +1440,36 @@ static rt_err_t rt_serial_control(struct rt_device *dev,
else
{
struct serial_configure *pconfig = (struct serial_configure *)args;
+ struct serial_configure old_config = serial->config;
+
+#ifdef RT_SERIAL_USING_DMA
+ if (rt_serial_rx_dma_event_mode_valid(pconfig->rx_dma_event_mode) != RT_TRUE)
+ {
+ ret = -RT_EINVAL;
+ break;
+ }
+#endif /* RT_SERIAL_USING_DMA */
+
if (((pconfig->rx_bufsz != serial->config.rx_bufsz) || (pconfig->tx_bufsz != serial->config.tx_bufsz)
#ifdef RT_SERIAL_USING_DMA
|| (pconfig->dma_ping_bufsz != serial->config.dma_ping_bufsz)
-#endif
+ || (pconfig->rx_dma_event_mode != serial->config.rx_dma_event_mode)
+#endif /* RT_SERIAL_USING_DMA */
) &&
serial->parent.ref_count != 0)
{
- /*can not change buffer size*/
+ /* can not change buffer or DMA event configuration while opened */
ret = -RT_EBUSY;
break;
}
+
/* set serial configure */
serial->config = *pconfig;
- serial->ops->configure(serial, (struct serial_configure *)args);
+ ret = serial->ops->configure(serial, (struct serial_configure *)args);
+ if (ret != RT_EOK)
+ {
+ serial->config = old_config;
+ }
}
break;
case RT_SERIAL_CTRL_GET_CONFIG: