diff options
| author | wdfk-prog <[email protected]> | 2026-06-15 14:31:59 +0800 |
|---|---|---|
| committer | Rbb666 <[email protected]> | 2026-06-27 11:39:10 +0800 |
| commit | 1f9146897be1d898bea2a3ed0492c2d0a0507320 (patch) | |
| tree | 403e514c1afc015fa9112a7c18fdc42b4636ac6c /components/drivers | |
| parent | 187dc3fddfe45202f4c1000a724f38cdc742dd2e (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.h | 47 | ||||
| -rw-r--r-- | components/drivers/serial/dev_serial_v2.c | 39 |
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: |
