summaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
authorryancw <[email protected]>2024-09-04 10:39:10 +0800
committerRbb666 <[email protected]>2025-05-16 09:42:11 +0800
commitac8fba0129f98b5c6a7c6caaa55538a53b370db2 (patch)
treeff4cfe35207900dba802b879da2f244a3adf5f5b /components
parentbf96f99d6bc3dfa3c7c9230d1b8e4415c02f19f0 (diff)
[drivers][serial_v2]允许阻塞接收超过rx缓冲区大小的数据、增加超时时间、flush、获取缓冲区数据长度命令、数据溢出逻辑修复、稳定性细节优化、添加更多serial_v2测试用例
[components][serial_v2] 优化txflush逻辑、对tx的activated做中断保护 [components][at] at_client适配新版serial_v2 [components][at] at_server适配新版serial_v2 [components][serial_v2] 测试用例增加循环调用,format测试用例 [components][serial_v2] poll模式判断逻辑错误 [components][serial_v2] 测试用例去掉一些非必要延时 [components][serial_v2] 测试例程使用menuconfig进行配置,更新readme [components][at_client] at_client_getchar返回值错误、at_client解析线程优先级错误设置 [components][at] 错误码应该返回负值 [components][serial_v2] TCFLSH和FIONREAD完善、control函数增加错误返回值 [components][serial_v2] RT_SERIAL_CTRL_GET_RX_DATA_LEN更改为RT_SERIAL_CTRL_GET_UNREAD_BYTES_COUNT [utest][serial_v2] TC_UART_SEND_TIMES替换为RT_SERIAL_TC_SEND_ITERATIONS [components][serial_v2] FIONREAD参数应该是无符号类型 [utest][serial_v2] 完善测试用例 [components][serial_v2] 避免使用三目运算符 [components][serial_v2] 使用clang-format格式化代码 [components][serial_v2] 添加get超时时间命令 [components][serial_v2] 完善posix接口 [components][serial_v2] 阻塞接口添加阻塞时间为0时的处理逻辑、优化RX阻塞接收逻辑 [components][serial_v2] 设置超时时间命令的参数改为指针形式 [components][serial_v2] nbuf发送添加超时时间为0时的逻辑 [components][serial_v2] 完善添加测试用例 [utest][serial_v2] 修复依赖关系 [components][serial_v2] 非阻塞模式下tx_flush错误修复 [components][serial_v2] activated使用原子API [components][serial_v2] 优化DMA逻辑、没使能DMA时屏蔽DMA逻辑节约资源 [components][serial_v2] 提供写满时丢弃新数据和覆盖旧数据策略,写满丢弃策略效率更高 [components][serial_v2] 部分平台适配写满时两种策略功能 [components][serial_v2] DMA模式暂不支持丢弃新数据策略 [utest][serial_v2] 优化测试代码 [components][serial_v2] DMA模式下使用乒乓缓冲、DMA模式支持丢弃新数据策略 [utest][serial_v2] 适配DMA乒乓缓冲 [bsp][serial_v2] 部分bsp适配DMA下乒乓缓冲 [components][serial_v2] 使用spinlock替换中断,对部分结构体变量使用原子操作 [utest][serial_v2] 更新测试用例 [components][at] 适配new serialv2不再判断RTT版本号 [components][at] 删除多余的中文注释 [utest][serial_v2] 添加交叉echo示例,qemu环境下专用 [bsp][qemu] 适配串口v2并开启fifo [components][at] 修复合并导致的错误 [bsp][n32] 适配serial_v2,没有经过测试 [components][serial_v2] 格式化代码 [utest][serial_v2] 删除无意义的打印
Diffstat (limited to 'components')
-rw-r--r--components/drivers/include/drivers/dev_serial_v2.h65
-rw-r--r--components/drivers/serial/Kconfig11
-rw-r--r--components/drivers/serial/dev_serial_v2.c1874
-rw-r--r--components/net/at/include/at.h9
-rw-r--r--components/net/at/src/at_client.c59
-rw-r--r--components/net/at/src/at_server.c42
6 files changed, 1338 insertions, 722 deletions
diff --git a/components/drivers/include/drivers/dev_serial_v2.h b/components/drivers/include/drivers/dev_serial_v2.h
index ef163dff0c..d1b116ab1c 100644
--- a/components/drivers/include/drivers/dev_serial_v2.h
+++ b/components/drivers/include/drivers/dev_serial_v2.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2023, RT-Thread Development Team
+ * Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -12,8 +12,7 @@
#define __DEV_SERIAL_V2_H__
#include <rtthread.h>
-
-
+#include <rtdevice.h>
/**
* @addtogroup group_Drivers RTTHREAD Driver
* @defgroup group_Serial_v2 Serial v2
@@ -169,6 +168,9 @@
#define NRZ_NORMAL 0 /* Non Return to Zero : normal mode */
#define NRZ_INVERTED 1 /* Non Return to Zero : inverted mode */
+/**
+ * device flag
+ */
#define RT_DEVICE_FLAG_RX_BLOCKING 0x1000
#define RT_DEVICE_FLAG_RX_NON_BLOCKING 0x2000
@@ -180,21 +182,42 @@
#define RT_SERIAL_TX_BLOCKING RT_DEVICE_FLAG_TX_BLOCKING
#define RT_SERIAL_TX_NON_BLOCKING RT_DEVICE_FLAG_TX_NON_BLOCKING
+/**
+ * hw device control commands
+ */
#define RT_DEVICE_CHECK_OPTMODE 0x20
+/**
+ * hw serial control commands
+ */
+#define RT_HW_SERIAL_CTRL_GETC 0x01 /* Tx irq get char */
+#define RT_HW_SERIAL_CTRL_PUTC 0x02 /* Rx irq put char */
+#define RT_HW_SERIAL_CTRL_GET_DMA_PING_BUF 0x03 /* Get DMA ping-pong buffer */
+
+/**
+ * hw isr event
+ */
#define RT_SERIAL_EVENT_RX_IND 0x01 /* Rx indication */
#define RT_SERIAL_EVENT_TX_DONE 0x02 /* Tx complete */
#define RT_SERIAL_EVENT_RX_DMADONE 0x03 /* Rx DMA transfer done */
#define RT_SERIAL_EVENT_TX_DMADONE 0x04 /* Tx DMA transfer done */
-#define RT_SERIAL_EVENT_RX_TIMEOUT 0x05 /* Rx timeout */
+
+/**
+ * device commands
+ * 0x40 - special device control commands
+ */
+#define RT_SERIAL_CTRL_SET_RX_TIMEOUT 0x41 /* set Rx timeout. Call before rt_device_read. not supported in poll mode */
+#define RT_SERIAL_CTRL_SET_TX_TIMEOUT 0x42 /* set Tx timeout. Call before rt_device_write. not supported in poll mode */
+#define RT_SERIAL_CTRL_GET_RX_TIMEOUT 0x43 /* get Rx timeout. not supported in poll mode */
+#define RT_SERIAL_CTRL_GET_TX_TIMEOUT 0x44 /* get Tx timeout. not supported in poll mode */
+#define RT_SERIAL_CTRL_RX_FLUSH 0x45 /* clear rx buffer. Discard all data */
+#define RT_SERIAL_CTRL_TX_FLUSH 0x46 /* clear tx buffer. Blocking and wait for the send buffer data to be sent. not supported in poll mode */
+#define RT_SERIAL_CTRL_GET_UNREAD_BYTES_COUNT 0x47 /* get unread bytes count. not supported in poll mode */
#define RT_SERIAL_ERR_OVERRUN 0x01
#define RT_SERIAL_ERR_FRAMING 0x02
#define RT_SERIAL_ERR_PARITY 0x03
-#define RT_SERIAL_TX_DATAQUEUE_SIZE 2048
-#define RT_SERIAL_TX_DATAQUEUE_LWM 30
-
#define RT_SERIAL_RX_MINBUFSZ 64
#define RT_SERIAL_TX_MINBUFSZ 64
@@ -216,7 +239,8 @@
RT_SERIAL_RX_MINBUFSZ, /* rxBuf size */ \
RT_SERIAL_TX_MINBUFSZ, /* txBuf size */ \
RT_SERIAL_FLOWCONTROL_NONE, /* Off flowcontrol */ \
- 0 \
+ 0, /* reserved */ \
+ 0, /* dma_ping_bufsz */ \
}
/**
@@ -239,6 +263,10 @@ struct serial_configure
rt_uint32_t tx_bufsz :16;
rt_uint32_t flowcontrol :1;
rt_uint32_t reserved :5;
+
+#ifdef RT_SERIAL_USING_DMA
+ rt_uint32_t dma_ping_bufsz :16;
+#endif
};
/**
@@ -248,12 +276,15 @@ struct rt_serial_rx_fifo
{
struct rt_ringbuffer rb;
+#ifdef RT_SERIAL_USING_DMA
+ struct rt_ringbuffer dma_ping_rb;
+#endif
+
struct rt_completion rx_cpt;
- rt_uint16_t rx_cpt_index;
+ rt_size_t rx_cpt_index;
- /* software fifo */
- rt_uint8_t buffer[];
+ rt_atomic_t rx_timeout;
};
/**
@@ -264,14 +295,13 @@ struct rt_serial_tx_fifo
{
struct rt_ringbuffer rb;
- rt_size_t put_size;
+ struct rt_completion tx_cpt;
- rt_bool_t activated;
+ rt_size_t put_size;
- struct rt_completion tx_cpt;
+ rt_atomic_t tx_timeout;
- /* software fifo */
- rt_uint8_t buffer[];
+ rt_atomic_t activated;
};
/**
@@ -288,6 +318,8 @@ struct rt_serial_device
void *serial_rx;
void *serial_tx;
+ struct rt_spinlock spinlock;
+
struct rt_device_notify rx_notify;
};
@@ -321,6 +353,7 @@ struct rt_uart_ops
*/
void rt_hw_serial_isr(struct rt_serial_device *serial, int event);
+rt_err_t rt_hw_serial_control_isr(struct rt_serial_device *serial, int cmd, void *args);
/**
* @brief Register a serial device to device list
diff --git a/components/drivers/serial/Kconfig b/components/drivers/serial/Kconfig
index 349aaeab2f..cd6cf3f359 100644
--- a/components/drivers/serial/Kconfig
+++ b/components/drivers/serial/Kconfig
@@ -13,6 +13,17 @@ menuconfig RT_USING_SERIAL
config RT_USING_SERIAL_V2
bool "RT_USING_SERIAL_V2"
endchoice
+
+ choice
+ prompt "Choice Serial version"
+ depends on RT_USING_SERIAL_V2
+ default RT_SERIAL_BUF_STRATEGY_OVERWRITE
+ config RT_SERIAL_BUF_STRATEGY_DROP
+ bool "drop new incoming data when the buffer is full"
+ config RT_SERIAL_BUF_STRATEGY_OVERWRITE
+ bool "overwrite old data when the buffer is full"
+ endchoice
+
config RT_SERIAL_USING_DMA
bool "Enable serial DMA mode"
default y
diff --git a/components/drivers/serial/dev_serial_v2.c b/components/drivers/serial/dev_serial_v2.c
index 18f9c8970e..bf51d3fb4f 100644
--- a/components/drivers/serial/dev_serial_v2.c
+++ b/components/drivers/serial/dev_serial_v2.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2023, RT-Thread Development Team
+ * Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -12,10 +12,22 @@
#include <rtthread.h>
#include <rtdevice.h>
-#define DBG_TAG "Serial"
-#define DBG_LVL DBG_INFO
+#define DBG_TAG "Serial"
+#define DBG_LVL DBG_INFO
#include <rtdbg.h>
+#ifdef RT_SERIAL_BUF_STRATEGY_DROP
+#define RT_SERIAL_FIFO_LOCK(spinlock) ((rt_base_t)0)
+#define RT_SERIAL_FIFO_UNLOCK(spinlock, level) \
+ do { \
+ RT_UNUSED(spinlock); \
+ RT_UNUSED(level); \
+ } while (0)
+#else
+#define RT_SERIAL_FIFO_LOCK(spinlock) rt_spin_lock_irqsave(spinlock)
+#define RT_SERIAL_FIFO_UNLOCK(spinlock, level) rt_spin_unlock_irqrestore(spinlock, level)
+#endif /* RT_SERIAL_BUF_STRATEGY_DROP */
+
#ifdef RT_USING_POSIX_STDIO
#include <unistd.h>
#include <fcntl.h>
@@ -39,7 +51,7 @@ RT_OBJECT_HOOKLIST_DEFINE(rt_hw_serial_rxind);
static rt_err_t serial_fops_rx_ind(rt_device_t dev, rt_size_t size)
{
- rt_wqueue_wakeup(&(dev->wait_queue), (void*)POLLIN);
+ rt_wqueue_wakeup(&dev->wait_queue, (void *)POLLIN);
RT_OBJECT_HOOKLIST_CALL(rt_hw_serial_rxind, (dev, size));
@@ -49,7 +61,7 @@ static rt_err_t serial_fops_rx_ind(rt_device_t dev, rt_size_t size)
/* fops for serial */
static int serial_fops_open(struct dfs_file *fd)
{
- rt_err_t ret = 0;
+ rt_err_t ret = 0;
rt_uint16_t flags = 0;
rt_device_t device;
@@ -77,7 +89,7 @@ static int serial_fops_open(struct dfs_file *fd)
if ((fd->flags & O_ACCMODE) != O_WRONLY)
rt_device_set_rx_indicate(device, serial_fops_rx_ind);
- ret = rt_device_open(device, flags);
+ ret = rt_device_open(device, flags | RT_SERIAL_RX_BLOCKING | RT_SERIAL_TX_BLOCKING);
if (ret == RT_EOK) return 0;
return ret;
@@ -98,8 +110,8 @@ static int serial_fops_close(struct dfs_file *fd)
static int serial_fops_ioctl(struct dfs_file *fd, int cmd, void *args)
{
rt_device_t device;
- int flags = (int)(rt_base_t)args;
- int mask = O_NONBLOCK | O_APPEND;
+ int flags = (int)(rt_base_t)args;
+ int mask = O_NONBLOCK | O_APPEND;
device = (rt_device_t)fd->vnode->data;
switch (cmd)
@@ -109,7 +121,7 @@ static int serial_fops_ioctl(struct dfs_file *fd, int cmd, void *args)
case FIONWRITE:
break;
case F_SETFL:
- flags &= mask;
+ flags &= mask;
fd->flags &= ~mask;
fd->flags |= flags;
break;
@@ -124,25 +136,35 @@ static ssize_t serial_fops_read(struct dfs_file *fd, void *buf, size_t count, of
static ssize_t serial_fops_read(struct dfs_file *fd, void *buf, size_t count)
#endif
{
- int size = 0;
+ ssize_t size = 0;
rt_device_t device;
+ rt_int32_t rx_timout;
+
+ if (count == 0) return 0;
+ RT_ASSERT(fd != RT_NULL && buf != RT_NULL);
device = (rt_device_t)fd->vnode->data;
+ RT_ASSERT(device != RT_NULL);
- do
+ /* nonblock mode */
+ if (fd->flags & O_NONBLOCK)
{
- size = rt_device_read(device, -1, buf, count);
+ rx_timout = RT_WAITING_NO;
+ rt_device_control(device, RT_SERIAL_CTRL_SET_RX_TIMEOUT, (void *)&rx_timout);
+ size = rt_device_read(device, -1, buf, count);
if (size <= 0)
{
- if (fd->flags & O_NONBLOCK)
- {
- size = -EAGAIN;
- break;
- }
-
- rt_wqueue_wait(&(device->wait_queue), 0, RT_WAITING_FOREVER);
+ size = -1;
+ rt_set_errno(EAGAIN);
}
- }while (size <= 0);
+ }
+ else
+ {
+ rx_timout = RT_WAITING_FOREVER;
+ rt_device_control(device, RT_SERIAL_CTRL_SET_RX_TIMEOUT, (void *)&rx_timout);
+ size = rt_device_read(device, -1, buf, count);
+ }
+
return size;
}
@@ -153,17 +175,53 @@ static ssize_t serial_fops_write(struct dfs_file *fd, const void *buf, size_t co
static ssize_t serial_fops_write(struct dfs_file *fd, const void *buf, size_t count)
#endif
{
+ ssize_t size = 0;
rt_device_t device;
+ rt_int32_t tx_timeout;
+
+ device = (rt_device_t)fd->vnode->data;
+
+ if (fd->flags & O_NONBLOCK)
+ {
+ tx_timeout = RT_WAITING_NO;
+ rt_device_control(device, RT_SERIAL_CTRL_SET_TX_TIMEOUT, (void *)&tx_timeout);
+ size = rt_device_write(device, -1, buf, count);
+ if (size <= 0)
+ {
+ size = -1;
+ rt_set_errno(EAGAIN);
+ }
+ }
+ else
+ {
+ tx_timeout = RT_WAITING_FOREVER;
+ rt_device_control(device, RT_SERIAL_CTRL_SET_TX_TIMEOUT, (void *)&tx_timeout);
+ size = rt_device_write(device, -1, buf, count);
+ }
+
+ return size;
+}
+
+static int serial_fops_flush(struct dfs_file *fd)
+{
+ rt_device_t device;
+ struct rt_serial_device *serial;
device = (rt_device_t)fd->vnode->data;
- return rt_device_write(device, -1, buf, count);
+ RT_ASSERT(device != RT_NULL);
+
+ serial = (struct rt_serial_device *)device;
+ rt_device_control(device, RT_SERIAL_CTRL_TX_FLUSH, (void *)RT_NULL);
+ rt_device_control(device, RT_SERIAL_CTRL_RX_FLUSH, (void *)RT_NULL);
+
+ return 0;
}
static int serial_fops_poll(struct dfs_file *fd, struct rt_pollreq *req)
{
- int mask = 0;
- int flags = 0;
- rt_device_t device;
+ int mask = 0;
+ int flags = 0;
+ rt_device_t device;
struct rt_serial_device *serial;
device = (rt_device_t)fd->vnode->data;
@@ -175,43 +233,41 @@ static int serial_fops_poll(struct dfs_file *fd, struct rt_pollreq *req)
flags = fd->flags & O_ACCMODE;
if (flags == O_RDONLY || flags == O_RDWR)
{
- rt_base_t level;
- struct rt_serial_rx_fifo* rx_fifo;
-
- rt_poll_add(&(device->wait_queue), req);
+ rt_base_t level;
+ struct rt_serial_rx_fifo *rx_fifo;
- rx_fifo = (struct rt_serial_rx_fifo*) serial->serial_rx;
+ rt_poll_add(&device->wait_queue, req);
- level = rt_hw_interrupt_disable();
+ rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx;
+ level = RT_SERIAL_FIFO_LOCK(&serial->spinlock);
if (rt_ringbuffer_data_len(&rx_fifo->rb))
mask |= POLLIN;
- rt_hw_interrupt_enable(level);
+ RT_SERIAL_FIFO_UNLOCK(&serial->spinlock, level);
}
- // mask|=POLLOUT;
- return mask;
+ /* mask|=POLLOUT; */
+ return mask;
}
const static struct dfs_file_ops _serial_fops =
-{
- .open = serial_fops_open,
- .close = serial_fops_close,
- .ioctl = serial_fops_ioctl,
- .read = serial_fops_read,
- .write = serial_fops_write,
- .poll = serial_fops_poll,
+ {
+ .open = serial_fops_open,
+ .close = serial_fops_close,
+ .ioctl = serial_fops_ioctl,
+ .read = serial_fops_read,
+ .write = serial_fops_write,
+ .flush = serial_fops_flush,
+ .poll = serial_fops_poll,
};
#endif /* RT_USING_POSIX_STDIO */
-static rt_ssize_t rt_serial_get_linear_buffer(struct rt_ringbuffer *rb,
- rt_uint8_t **ptr)
+static rt_ssize_t rt_serial_get_linear_buffer(struct rt_ringbuffer *rb,
+ rt_uint8_t **ptr)
{
rt_size_t size;
RT_ASSERT(rb != RT_NULL);
- *ptr = RT_NULL;
-
/* whether has enough data */
size = rt_ringbuffer_data_len(rb);
@@ -221,7 +277,7 @@ static rt_ssize_t rt_serial_get_linear_buffer(struct rt_ringbuffer *rb,
*ptr = &rb->buffer_ptr[rb->read_index];
- if(rb->buffer_size - rb->read_index > size)
+ if (rb->buffer_size - rb->read_index > size)
{
return size;
}
@@ -229,8 +285,9 @@ static rt_ssize_t rt_serial_get_linear_buffer(struct rt_ringbuffer *rb,
return rb->buffer_size - rb->read_index;
}
-static rt_ssize_t rt_serial_update_read_index(struct rt_ringbuffer *rb,
- rt_uint16_t read_index)
+#ifdef RT_SERIAL_USING_DMA
+static void rt_serial_update_read_index(struct rt_ringbuffer *rb,
+ rt_uint16_t length)
{
rt_size_t size;
@@ -241,60 +298,98 @@ static rt_ssize_t rt_serial_update_read_index(struct rt_ringbuffer *rb,
/* no data */
if (size == 0)
- return 0;
+ return;
/* less data */
- if(size < read_index)
- read_index = size;
+ if (size < length)
+ length = size;
- if(rb->buffer_size - rb->read_index > read_index)
+ if (rb->buffer_size - rb->read_index > length)
{
- rb->read_index += read_index;
- return read_index;
+ rb->read_index += length;
+ return;
}
- read_index = rb->buffer_size - rb->read_index;
-
/* we are going into the other side of the mirror */
rb->read_mirror = ~rb->read_mirror;
- rb->read_index = 0;
+ rb->read_index = length - (rb->buffer_size - rb->read_index);
- return read_index;
+ return;
}
-static rt_ssize_t rt_serial_update_write_index(struct rt_ringbuffer *rb,
- rt_uint16_t write_size)
+static void rt_serial_update_write_index(struct rt_ringbuffer *rb,
+ rt_uint16_t length)
{
- rt_uint16_t size;
+#ifdef RT_SERIAL_BUF_STRATEGY_DROP
+ rt_uint16_t space_length;
+
RT_ASSERT(rb != RT_NULL);
/* whether has enough space */
- size = rt_ringbuffer_space_len(rb);
+ space_length = rt_ringbuffer_space_len(rb);
+
+ /* no space */
+ if (space_length == 0)
+ return;
+
+ /* drop some data */
+ if (space_length < length)
+ length = space_length;
- /* no space, drop some data */
- if (size < write_size)
+ if (rb->buffer_size - rb->write_index > length)
{
- write_size = size;
+ /* this should not cause overflow because there is enough space for
+ * length of data in current mirror */
+ rb->write_index += length;
+ return;
+ }
+
+ /* we are going into the other side of the mirror */
+ rb->write_mirror = ~rb->write_mirror;
+ rb->write_index = length - (rb->buffer_size - rb->write_index);
+ return;
+
+#else
+ rt_uint16_t space_length;
+ RT_ASSERT(rb != RT_NULL);
+
+ /* whether has enough space */
+ space_length = rt_ringbuffer_space_len(rb);
+
+ if (length > rb->buffer_size)
+ {
+ length = rb->buffer_size;
#if !defined(RT_USING_ULOG) || defined(ULOG_USING_ISR_LOG)
LOG_W("The serial buffer (len %d) is overflow.", rb->buffer_size);
#endif
}
- if (rb->buffer_size - rb->write_index > write_size)
+ if (rb->buffer_size - rb->write_index > length)
{
/* this should not cause overflow because there is enough space for
* length of data in current mirror */
- rb->write_index += write_size;
- return write_size;
+ rb->write_index += length;
+
+ if (length > space_length)
+ rb->read_index = rb->write_index;
+
+ return;
}
/* we are going into the other side of the mirror */
rb->write_mirror = ~rb->write_mirror;
- rb->write_index = write_size - (rb->buffer_size - rb->write_index);
+ rb->write_index = length - (rb->buffer_size - rb->write_index);
- return write_size;
+ if (length > space_length)
+ {
+ if (rb->write_index <= rb->read_index)
+ rb->read_mirror = ~rb->read_mirror;
+ rb->read_index = rb->write_index;
+ }
+ return;
+#endif /* RT_SERIAL_BUF_STRATEGY_DROP */
}
-
+#endif /* RT_SERIAL_USING_DMA */
/**
* @brief Serial polling receive data routine, This function will receive data
@@ -305,32 +400,32 @@ static rt_ssize_t rt_serial_update_write_index(struct rt_ringbuffer *rb,
* @param size Receive data buffer length.
* @return Return the final length of data received.
*/
-rt_ssize_t _serial_poll_rx(struct rt_device *dev,
- rt_off_t pos,
- void *buffer,
- rt_size_t size)
+rt_ssize_t _serial_poll_rx(struct rt_device *dev,
+ rt_off_t pos,
+ void *buffer,
+ rt_size_t size)
{
struct rt_serial_device *serial;
- rt_size_t getc_size;
- int getc_element; /* Gets one byte of data received */
- rt_uint8_t *getc_buffer; /* Pointer to the receive data buffer */
+ rt_size_t getc_size;
+ int getc_element; /* Gets one byte of data received */
+ rt_uint8_t *getc_buffer; /* Pointer to the receive data buffer */
- RT_ASSERT(dev != RT_NULL);
+ if (size == 0) return 0;
+ RT_ASSERT(dev != RT_NULL && buffer != RT_NULL);
- serial = (struct rt_serial_device *)dev;
- RT_ASSERT(serial != RT_NULL);
+ serial = (struct rt_serial_device *)dev;
getc_buffer = (rt_uint8_t *)buffer;
- getc_size = size;
+ getc_size = size;
- while(size)
+ while (size)
{
getc_element = serial->ops->getc(serial);
if (getc_element == -1) break;
*getc_buffer = getc_element;
- ++ getc_buffer;
- -- size;
+ ++getc_buffer;
+ --size;
if (serial->parent.open_flag & RT_DEVICE_FLAG_STREAM)
{
@@ -340,7 +435,7 @@ rt_ssize_t _serial_poll_rx(struct rt_device *dev,
}
}
- return getc_size - size;
+ return getc_size - size;
}
/**
@@ -350,23 +445,23 @@ rt_ssize_t _serial_poll_rx(struct rt_device *dev,
* @param pos Empty parameter.
* @param buffer Transmit data buffer.
* @param size Transmit data buffer length.
- * @return Return the final length of data received.
+ * @return Return the final length of data transmit.
*/
-rt_ssize_t _serial_poll_tx(struct rt_device *dev,
- rt_off_t pos,
- const void *buffer,
- rt_size_t size)
+rt_ssize_t _serial_poll_tx(struct rt_device *dev,
+ rt_off_t pos,
+ const void *buffer,
+ rt_size_t size)
{
struct rt_serial_device *serial;
- rt_size_t putc_size;
- rt_uint8_t *putc_buffer; /* Pointer to the transmit data buffer */
- RT_ASSERT(dev != RT_NULL);
+ rt_size_t putc_size;
+ rt_uint8_t *putc_buffer; /* Pointer to the transmit data buffer */
- serial = (struct rt_serial_device *)dev;
- RT_ASSERT(serial != RT_NULL);
+ if (size == 0) return 0;
+ RT_ASSERT(dev != RT_NULL && buffer != RT_NULL);
+ serial = (struct rt_serial_device *)dev;
putc_buffer = (rt_uint8_t *)buffer;
- putc_size = size;
+ putc_size = size;
while (size)
{
@@ -379,73 +474,109 @@ rt_ssize_t _serial_poll_tx(struct rt_device *dev,
}
serial->ops->putc(serial, *putc_buffer);
- ++ putc_buffer;
- -- size;
+ ++putc_buffer;
+ --size;
}
- return putc_size - size;
+ return putc_size - size;
}
/**
* @brief Serial receive data routines, This function will receive
* data by using fifo
+ *
+ * @note In blocking mode, the function will wait until the specified amount of data is received or until a timeout occurs.
+ * In non-blocking mode, the function will immediately attempt to retrieve as much data as possible from the ring buffer and return.
+ *
* @param dev The pointer of device driver structure
* @param pos Empty parameter.
* @param buffer Receive data buffer.
* @param size Receive data buffer length.
- * @return Return the final length of data received.
+ * @return Returns the actual length of data received. If a timeout occurs in blocking mode, it returns -RT_ETIMEOUT.
*/
-static rt_ssize_t _serial_fifo_rx(struct rt_device *dev,
- rt_off_t pos,
- void *buffer,
- rt_size_t size)
+static rt_ssize_t _serial_fifo_rx(struct rt_device *dev,
+ rt_off_t pos,
+ void *buffer,
+ rt_size_t size)
{
- struct rt_serial_device *serial;
+ struct rt_serial_device *serial;
struct rt_serial_rx_fifo *rx_fifo;
- rt_base_t level;
- rt_size_t recv_len; /* The length of data from the ringbuffer */
+ rt_base_t level;
+ rt_size_t recv_size = 0;
- RT_ASSERT(dev != RT_NULL);
if (size == 0) return 0;
+ RT_ASSERT(dev != RT_NULL && buffer != RT_NULL);
- serial = (struct rt_serial_device *)dev;
-
- RT_ASSERT((serial != RT_NULL) && (buffer != RT_NULL));
-
- rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx;
+ serial = (struct rt_serial_device *)dev;
+ rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx;
if (dev->open_flag & RT_SERIAL_RX_BLOCKING)
{
- if (size > serial->config.rx_bufsz)
- {
- LOG_W("(%s) serial device received data:[%d] larger than "
- "rx_bufsz:[%d], please increase the BSP_UARTx_RX_BUFSIZE option",
- dev->parent.name, size, serial->config.rx_bufsz);
+ rt_size_t data_len = 0;
+ rt_size_t rx_bufsz_third = serial->config.rx_bufsz / 2;
+ rt_int32_t base_rx_timeout = rt_atomic_load(&rx_fifo->rx_timeout);
+ rt_int32_t rx_timeout = base_rx_timeout;
+ rt_tick_t now_tick = 0;
+ rt_tick_t begin_tick = rt_tick_get();
- return 0;
- }
- /* Get the length of the data from the ringbuffer */
- recv_len = rt_ringbuffer_data_len(&(rx_fifo->rb));
-
- if (recv_len < size)
+ while (1)
{
- /* When recv_len is less than size, rx_cpt_index is updated to the size
- * and rt_current_thread is suspend until rx_cpt_index is equal to 0 */
- rx_fifo->rx_cpt_index = size;
- rt_completion_wait(&(rx_fifo->rx_cpt), RT_WAITING_FOREVER);
- }
- }
+ if (rx_timeout != RT_WAITING_NO)
+ {
+ level = rt_spin_lock_irqsave(&serial->spinlock);
+ data_len = rt_ringbuffer_data_len(&rx_fifo->rb);
+ if (data_len < size - recv_size)
+ {
+ if (size - (recv_size + data_len) >= rx_bufsz_third)
+ {
+ rx_fifo->rx_cpt_index = rx_bufsz_third;
+ }
+ else
+ {
+ rx_fifo->rx_cpt_index = size - (recv_size + data_len);
+ }
+ rt_completion_wait(&rx_fifo->rx_cpt, 0);
+ }
+ rt_spin_unlock_irqrestore(&serial->spinlock, level);
+ }
- /* This part of the code is open_flag as RT_SERIAL_RX_NON_BLOCKING */
+ level = RT_SERIAL_FIFO_LOCK(&serial->spinlock);
+ recv_size += rt_ringbuffer_get(&rx_fifo->rb, (rt_uint8_t *)buffer + recv_size, size - recv_size);
+ RT_SERIAL_FIFO_UNLOCK(&serial->spinlock, level);
+ if (recv_size == size || rx_timeout == RT_WAITING_NO)
+ {
+ break;
+ }
- level = rt_hw_interrupt_disable();
- /* When open_flag is RT_SERIAL_RX_NON_BLOCKING,
- * the data is retrieved directly from the ringbuffer and returned */
- recv_len = rt_ringbuffer_get(&(rx_fifo->rb), buffer, size);
- rt_hw_interrupt_enable(level);
+ rt_completion_wait(&rx_fifo->rx_cpt, rx_timeout);
+ if (rx_timeout != RT_WAITING_FOREVER)
+ {
+ now_tick = rt_tick_get();
+ if (now_tick - begin_tick >= base_rx_timeout)
+ {
+ return -RT_ETIMEOUT;
+ }
+ else
+ {
+ if (now_tick > begin_tick)
+ rx_timeout = base_rx_timeout - (now_tick - begin_tick);
+ else
+ rx_timeout = begin_tick + base_rx_timeout - now_tick + 1;
+ }
+ }
+ }
+ }
+ else if (dev->open_flag & RT_SERIAL_RX_NON_BLOCKING)
+ {
+ /* When open_flag is RT_SERIAL_RX_NON_BLOCKING,
+ * the data is retrieved directly from the ringbuffer and returned */
+ level = RT_SERIAL_FIFO_LOCK(&serial->spinlock);
+ recv_size = rt_ringbuffer_get(&rx_fifo->rb, buffer, size);
+ RT_SERIAL_FIFO_UNLOCK(&serial->spinlock, level);
+ }
- return recv_len;
+ return recv_size;
}
/**
@@ -455,23 +586,23 @@ static rt_ssize_t _serial_fifo_rx(struct rt_device *dev,
* @param pos Empty parameter.
* @param buffer Transmit data buffer.
* @param size Transmit data buffer length.
- * @return Return the final length of data transmit.
+ * @return Returns the actual length of data transmitted. If a timeout occurs, it returns -RT_ETIMEOUT.
*/
-static rt_ssize_t _serial_fifo_tx_blocking_nbuf(struct rt_device *dev,
- rt_off_t pos,
- const void *buffer,
- rt_size_t size)
+static rt_ssize_t _serial_fifo_tx_blocking_nbuf(struct rt_device *dev,
+ rt_off_t pos,
+ const void *buffer,
+ rt_size_t size)
{
- struct rt_serial_device *serial;
- struct rt_serial_tx_fifo *tx_fifo = RT_NULL;
- rt_ssize_t rst;
+ struct rt_serial_device *serial;
+ struct rt_serial_tx_fifo *tx_fifo;
+ rt_ssize_t send_size;
+ rt_err_t ret;
- RT_ASSERT(dev != RT_NULL);
if (size == 0) return 0;
+ RT_ASSERT(dev != RT_NULL && buffer != RT_NULL);
- serial = (struct rt_serial_device *)dev;
- RT_ASSERT((serial != RT_NULL) && (buffer != RT_NULL));
- tx_fifo = (struct rt_serial_tx_fifo *) serial->serial_tx;
+ serial = (struct rt_serial_device *)dev;
+ tx_fifo = (struct rt_serial_tx_fifo *)serial->serial_tx;
RT_ASSERT(tx_fifo != RT_NULL);
if (rt_thread_self() == RT_NULL || (serial->parent.open_flag & RT_DEVICE_FLAG_STREAM))
@@ -482,19 +613,42 @@ static rt_ssize_t _serial_fifo_tx_blocking_nbuf(struct rt_device *dev,
/* When serial transmit in tx_blocking mode,
* if the activated mode is RT_TRUE, it will return directly */
- if (tx_fifo->activated == RT_TRUE) return 0;
+ if (rt_atomic_flag_test_and_set(&tx_fifo->activated))
+ {
+ return 0;
+ }
+
+ /* clear tx_cpt flag */
+ rt_completion_wait(&tx_fifo->tx_cpt, 0);
- tx_fifo->activated = RT_TRUE;
/* Call the transmit interface for transmission */
- rst = serial->ops->transmit(serial,
- (rt_uint8_t *)buffer,
- size,
- RT_SERIAL_TX_BLOCKING);
+ send_size = serial->ops->transmit(serial,
+ (rt_uint8_t *)buffer,
+ size,
+ RT_SERIAL_TX_BLOCKING);
+
+ if (rt_atomic_load(&tx_fifo->tx_timeout) == RT_WAITING_NO)
+ {
+ return send_size;
+ }
+
/* Waiting for the transmission to complete */
- rt_completion_wait(&(tx_fifo->tx_cpt), RT_WAITING_FOREVER);
+ ret = rt_completion_wait(&tx_fifo->tx_cpt, rt_atomic_load(&tx_fifo->tx_timeout));
+ if (ret != RT_EOK)
+ {
+ if (ret == -RT_ETIMEOUT)
+ {
+ return ret;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
/* Inactive tx mode flag */
- tx_fifo->activated = RT_FALSE;
- return rst;
+ rt_atomic_flag_clear(&tx_fifo->activated);
+ return send_size;
}
/**
@@ -504,25 +658,23 @@ static rt_ssize_t _serial_fifo_tx_blocking_nbuf(struct rt_device *dev,
* @param pos Empty parameter.
* @param buffer Transmit data buffer.
* @param size Transmit data buffer length.
- * @return Return the final length of data transmit.
+ * @return Returns the final length of data transmitted. If not all data can be sent within the timeout period, returns -RT_ETIMEOUT.
*/
-static rt_ssize_t _serial_fifo_tx_blocking_buf(struct rt_device *dev,
- rt_off_t pos,
- const void *buffer,
- rt_size_t size)
+static rt_ssize_t _serial_fifo_tx_blocking_buf(struct rt_device *dev,
+ rt_off_t pos,
+ const void *buffer,
+ rt_size_t size)
{
- struct rt_serial_device *serial;
- struct rt_serial_tx_fifo *tx_fifo = RT_NULL;
- rt_size_t length = size;
- rt_size_t offset = 0;
+ struct rt_serial_device *serial;
+ struct rt_serial_tx_fifo *tx_fifo;
+ rt_base_t level;
+ rt_size_t send_size = 0;
if (size == 0) return 0;
+ RT_ASSERT(dev != RT_NULL && buffer != RT_NULL);
- RT_ASSERT(dev != RT_NULL);
- serial = (struct rt_serial_device *)dev;
- RT_ASSERT((serial != RT_NULL) && (buffer != RT_NULL));
-
- tx_fifo = (struct rt_serial_tx_fifo *) serial->serial_tx;
+ serial = (struct rt_serial_device *)dev;
+ tx_fifo = (struct rt_serial_tx_fifo *)serial->serial_tx;
RT_ASSERT(tx_fifo != RT_NULL);
if (rt_thread_self() == RT_NULL || (serial->parent.open_flag & RT_DEVICE_FLAG_STREAM))
@@ -530,34 +682,70 @@ static rt_ssize_t _serial_fifo_tx_blocking_buf(struct rt_device *dev,
/* using poll tx when the scheduler not startup or in stream mode */
return _serial_poll_tx(dev, pos, buffer, size);
}
+
/* When serial transmit in tx_blocking mode,
* if the activated mode is RT_TRUE, it will return directly */
- if (tx_fifo->activated == RT_TRUE) return 0;
- tx_fifo->activated = RT_TRUE;
+ if (rt_atomic_flag_test_and_set(&tx_fifo->activated))
+ {
+ return 0;
+ }
- while (size)
+ rt_int32_t base_tx_timeout = rt_atomic_load(&tx_fifo->tx_timeout);
+ rt_int32_t tx_timeout = base_tx_timeout;
+ rt_tick_t now_tick = 0;
+ rt_tick_t begin_tick = rt_tick_get();
+
+ while (send_size != size)
{
/* Copy one piece of data into the ringbuffer at a time
* until the length of the data is equal to size */
- tx_fifo->put_size = rt_ringbuffer_put(&(tx_fifo->rb),
- (rt_uint8_t *)buffer + offset,
- size);
+ level = RT_SERIAL_FIFO_LOCK(&serial->spinlock);
+ tx_fifo->put_size = rt_ringbuffer_put(&tx_fifo->rb,
+ (rt_uint8_t *)buffer + send_size,
+ size - send_size);
+ RT_SERIAL_FIFO_UNLOCK(&serial->spinlock, level);
+
+ /* clear tx_cpt flag */
+ rt_completion_wait(&tx_fifo->tx_cpt, 0);
- /* Call the transmit interface for transmission */
+ /* Call the transmit interface for transmission again */
+ /* Note that in interrupt mode, buffer and tx_fifo->put_size
+ * are inactive parameters */
serial->ops->transmit(serial,
- (rt_uint8_t *)buffer + offset,
- tx_fifo->put_size,
- RT_SERIAL_TX_BLOCKING);
+ (rt_uint8_t *)buffer + send_size,
+ tx_fifo->put_size,
+ RT_SERIAL_TX_BLOCKING);
+
+ send_size += tx_fifo->put_size;
+
+ if (tx_timeout == RT_WAITING_NO)
+ {
+ break;
+ }
- offset += tx_fifo->put_size;
- size -= tx_fifo->put_size;
/* Waiting for the transmission to complete */
- rt_completion_wait(&(tx_fifo->tx_cpt), RT_WAITING_FOREVER);
+ rt_completion_wait(&tx_fifo->tx_cpt, tx_timeout);
+ if (tx_timeout != RT_WAITING_FOREVER)
+ {
+ now_tick = rt_tick_get();
+ if (now_tick - begin_tick >= base_tx_timeout)
+ {
+ return -RT_ETIMEOUT;
+ }
+ else
+ {
+ if (now_tick > begin_tick)
+ tx_timeout = base_tx_timeout - (now_tick - begin_tick);
+ else
+ tx_timeout = begin_tick + base_tx_timeout - now_tick + 1;
+ }
+ }
}
+
/* Finally Inactivate the tx->fifo */
- tx_fifo->activated = RT_FALSE;
+ rt_atomic_flag_clear(&tx_fifo->activated);
- return length;
+ return send_size;
}
/**
@@ -569,46 +757,49 @@ static rt_ssize_t _serial_fifo_tx_blocking_buf(struct rt_device *dev,
* @param size Transmit data buffer length.
* @return Return the final length of data transmit.
*/
-static rt_ssize_t _serial_fifo_tx_nonblocking(struct rt_device *dev,
- rt_off_t pos,
- const void *buffer,
- rt_size_t size)
+static rt_ssize_t _serial_fifo_tx_nonblocking(struct rt_device *dev,
+ rt_off_t pos,
+ const void *buffer,
+ rt_size_t size)
{
- struct rt_serial_device *serial;
+ struct rt_serial_device *serial;
struct rt_serial_tx_fifo *tx_fifo;
- rt_base_t level;
- rt_size_t length;
+ rt_uint8_t *put_ptr;
+ rt_base_t level;
+ rt_size_t send_size = 0;
- RT_ASSERT(dev != RT_NULL);
if (size == 0) return 0;
+ RT_ASSERT(dev != RT_NULL && buffer != RT_NULL);
- serial = (struct rt_serial_device *)dev;
- RT_ASSERT((serial != RT_NULL) && (buffer != RT_NULL));
- tx_fifo = (struct rt_serial_tx_fifo *) serial->serial_tx;
-
- level = rt_hw_interrupt_disable();
+ serial = (struct rt_serial_device *)dev;
+ tx_fifo = (struct rt_serial_tx_fifo *)serial->serial_tx;
+ RT_ASSERT(tx_fifo != RT_NULL);
- if (tx_fifo->activated == RT_FALSE)
- {
- /* When serial transmit in tx_non_blocking mode, if the activated mode is RT_FALSE,
+ /* When serial transmit in tx_non_blocking mode, if the activated mode is RT_FALSE,
* start copying data into the ringbuffer */
- tx_fifo->activated = RT_TRUE;
+ if (!rt_atomic_flag_test_and_set(&tx_fifo->activated))
+ {
+ level = RT_SERIAL_FIFO_LOCK(&serial->spinlock);
/* Copying data into the ringbuffer */
- length = rt_ringbuffer_put(&(tx_fifo->rb), buffer, size);
+ send_size = rt_ringbuffer_put(&tx_fifo->rb, buffer, size);
- rt_hw_interrupt_enable(level);
-
- rt_uint8_t *put_ptr = RT_NULL;
/* Get the linear length buffer from ringbuffer */
- tx_fifo->put_size = rt_serial_get_linear_buffer(&(tx_fifo->rb), &put_ptr);
- /* Call the transmit interface for transmission */
+ tx_fifo->put_size = rt_serial_get_linear_buffer(&tx_fifo->rb, &put_ptr);
+ RT_SERIAL_FIFO_UNLOCK(&serial->spinlock, level);
+
+ /* clear tx_cpt flag */
+ rt_completion_wait(&tx_fifo->tx_cpt, 0);
+
+ /* Call the transmit interface for transmission again */
+ /* Note that in interrupt mode, put_ptr and tx_fifo->put_size
+ * are inactive parameters */
serial->ops->transmit(serial,
put_ptr,
tx_fifo->put_size,
RT_SERIAL_TX_NON_BLOCKING);
/* In tx_nonblocking mode, there is no need to call rt_completion_wait() APIs to wait
* for the rt_current_thread to resume */
- return length;
+ return send_size;
}
/* If the activated mode is RT_TRUE, it means that serial device is transmitting,
@@ -616,12 +807,12 @@ static rt_ssize_t _serial_fifo_tx_nonblocking(struct rt_device *dev,
* Note that this part of the code requires disable interrupts
* to prevent multi thread reentrant */
+ level = RT_SERIAL_FIFO_LOCK(&serial->spinlock);
/* Copying data into the ringbuffer */
- length = rt_ringbuffer_put(&(tx_fifo->rb), buffer, size);
-
- rt_hw_interrupt_enable(level);
+ send_size = rt_ringbuffer_put(&tx_fifo->rb, buffer, size);
+ RT_SERIAL_FIFO_UNLOCK(&serial->spinlock, level);
- return length;
+ return send_size;
}
@@ -631,10 +822,10 @@ static rt_ssize_t _serial_fifo_tx_nonblocking(struct rt_device *dev,
* @param rx_oflag The flag of that the serial port opens.
* @return Return the status of the operation.
*/
-static rt_err_t rt_serial_tx_enable(struct rt_device *dev,
- rt_uint16_t tx_oflag)
+static rt_err_t rt_serial_tx_enable(struct rt_device *dev,
+ rt_uint16_t tx_oflag)
{
- struct rt_serial_device *serial;
+ struct rt_serial_device *serial;
struct rt_serial_tx_fifo *tx_fifo = RT_NULL;
RT_ASSERT(dev != RT_NULL);
@@ -646,7 +837,7 @@ static rt_err_t rt_serial_tx_enable(struct rt_device *dev,
if (tx_oflag == RT_SERIAL_TX_NON_BLOCKING)
{
LOG_E("(%s) serial device with misconfigure: tx_bufsz = 0",
- dev->parent.name);
+ dev->parent.name);
return -RT_EINVAL;
}
@@ -665,7 +856,7 @@ static rt_err_t rt_serial_tx_enable(struct rt_device *dev,
{
/* When using RT_SERIAL_TX_BLOCKING, it is necessary to determine
* whether serial device needs to use buffer */
- rt_err_t optmode; /* The operating mode used by serial device */
+ rt_err_t optmode; /* The operating mode used by serial device */
/* Call the Control() API to get the operating mode */
optmode = serial->ops->control(serial,
RT_DEVICE_CHECK_OPTMODE,
@@ -673,13 +864,12 @@ static rt_err_t rt_serial_tx_enable(struct rt_device *dev,
if (optmode == RT_SERIAL_TX_BLOCKING_BUFFER)
{
/* If use RT_SERIAL_TX_BLOCKING_BUFFER, the ringbuffer is initialized */
- tx_fifo = (struct rt_serial_tx_fifo *) rt_malloc
- (sizeof(struct rt_serial_tx_fifo) + serial->config.tx_bufsz);
+ tx_fifo = (struct rt_serial_tx_fifo *)rt_malloc(sizeof(struct rt_serial_tx_fifo) + serial->config.tx_bufsz);
RT_ASSERT(tx_fifo != RT_NULL);
-
- rt_ringbuffer_init(&(tx_fifo->rb),
- tx_fifo->buffer,
- serial->config.tx_bufsz);
+ rt_memset(tx_fifo, RT_NULL, sizeof(struct rt_serial_tx_fifo) + serial->config.tx_bufsz);
+ rt_ringbuffer_init(&tx_fifo->rb,
+ (rt_uint8_t *)tx_fifo + sizeof(struct rt_serial_tx_fifo),
+ serial->config.tx_bufsz);
serial->serial_tx = tx_fifo;
#ifndef RT_USING_DEVICE_OPS
@@ -690,13 +880,11 @@ static rt_err_t rt_serial_tx_enable(struct rt_device *dev,
{
/* If not use RT_SERIAL_TX_BLOCKING_BUFFER,
* the control() API is called to configure the serial device */
- tx_fifo = (struct rt_serial_tx_fifo*) rt_malloc
- (sizeof(struct rt_serial_tx_fifo));
+ tx_fifo = (struct rt_serial_tx_fifo *)rt_malloc(sizeof(struct rt_serial_tx_fifo));
RT_ASSERT(tx_fifo != RT_NULL);
-
+ rt_memset(tx_fifo, RT_NULL, sizeof(struct rt_serial_tx_fifo));
/* Init rb.buffer_ptr to RT_NULL, in rt_serial_write() need check it
* otherwise buffer_ptr maybe a random value, as rt_malloc not init memory */
- tx_fifo->rb.buffer_ptr = RT_NULL;
serial->serial_tx = tx_fifo;
#ifndef RT_USING_DEVICE_OPS
@@ -705,41 +893,45 @@ static rt_err_t rt_serial_tx_enable(struct rt_device *dev,
/* Call the control() API to configure the serial device by RT_SERIAL_TX_BLOCKING*/
serial->ops->control(serial,
- RT_DEVICE_CTRL_CONFIG,
- (void *)RT_SERIAL_TX_BLOCKING);
- rt_memset(&tx_fifo->rb, RT_NULL, sizeof(tx_fifo->rb));
+ RT_DEVICE_CTRL_CONFIG,
+ (void *)RT_SERIAL_TX_BLOCKING);
}
-
- tx_fifo->activated = RT_FALSE;
+ rt_atomic_flag_clear(&tx_fifo->activated);
tx_fifo->put_size = 0;
- rt_completion_init(&(tx_fifo->tx_cpt));
+ rt_atomic_store(&tx_fifo->tx_timeout, RT_WAITING_FOREVER);
+
+ rt_completion_init(&tx_fifo->tx_cpt);
dev->open_flag |= RT_SERIAL_TX_BLOCKING;
return RT_EOK;
}
+
/* When using RT_SERIAL_TX_NON_BLOCKING, ringbuffer needs to be initialized,
* and initialize the tx_fifo->activated value is RT_FALSE.
*/
- tx_fifo = (struct rt_serial_tx_fifo *) rt_malloc
- (sizeof(struct rt_serial_tx_fifo) + serial->config.tx_bufsz);
+ tx_fifo = (struct rt_serial_tx_fifo *)rt_malloc(sizeof(struct rt_serial_tx_fifo) + serial->config.tx_bufsz);
RT_ASSERT(tx_fifo != RT_NULL);
+ rt_memset(tx_fifo, RT_NULL, sizeof(struct rt_serial_tx_fifo) + serial->config.tx_bufsz);
- tx_fifo->activated = RT_FALSE;
- tx_fifo->put_size = 0;
- rt_ringbuffer_init(&(tx_fifo->rb),
- tx_fifo->buffer,
- serial->config.tx_bufsz);
+ rt_ringbuffer_init(&tx_fifo->rb,
+ (rt_uint8_t *)tx_fifo + sizeof(struct rt_serial_tx_fifo),
+ serial->config.tx_bufsz);
serial->serial_tx = tx_fifo;
+ rt_atomic_flag_clear(&tx_fifo->activated);
+ tx_fifo->put_size = 0;
+
#ifndef RT_USING_DEVICE_OPS
dev->write = _serial_fifo_tx_nonblocking;
#endif
+ rt_completion_init(&tx_fifo->tx_cpt);
dev->open_flag |= RT_SERIAL_TX_NON_BLOCKING;
+
/* Call the control() API to configure the serial device by RT_SERIAL_TX_NON_BLOCKING*/
serial->ops->control(serial,
- RT_DEVICE_CTRL_CONFIG,
- (void *)RT_SERIAL_TX_NON_BLOCKING);
+ RT_DEVICE_CTRL_CONFIG,
+ (void *)RT_SERIAL_TX_NON_BLOCKING);
return RT_EOK;
}
@@ -751,11 +943,12 @@ static rt_err_t rt_serial_tx_enable(struct rt_device *dev,
* @param rx_oflag The flag of that the serial port opens.
* @return Return the status of the operation.
*/
-static rt_err_t rt_serial_rx_enable(struct rt_device *dev,
- rt_uint16_t rx_oflag)
+static rt_err_t rt_serial_rx_enable(struct rt_device *dev,
+ rt_uint16_t rx_oflag)
{
- struct rt_serial_device *serial;
- struct rt_serial_rx_fifo *rx_fifo = RT_NULL;
+ struct rt_serial_device *serial;
+ struct rt_serial_rx_fifo *rx_fifo = RT_NULL;
+ rt_size_t rx_fifo_size = 0;
RT_ASSERT(dev != RT_NULL);
serial = (struct rt_serial_device *)dev;
@@ -766,7 +959,7 @@ static rt_err_t rt_serial_rx_enable(struct rt_device *dev,
if (rx_oflag == RT_SERIAL_RX_NON_BLOCKING)
{
LOG_E("(%s) serial device with misconfigure: rx_bufsz = 0",
- dev->parent.name);
+ dev->parent.name);
return -RT_EINVAL;
}
@@ -781,11 +974,30 @@ static rt_err_t rt_serial_rx_enable(struct rt_device *dev,
if (serial->config.rx_bufsz < RT_SERIAL_RX_MINBUFSZ)
serial->config.rx_bufsz = RT_SERIAL_RX_MINBUFSZ;
- rx_fifo = (struct rt_serial_rx_fifo *) rt_malloc
- (sizeof(struct rt_serial_rx_fifo) + serial->config.rx_bufsz);
+#ifdef RT_SERIAL_USING_DMA
+ if (serial->config.dma_ping_bufsz > 0 && serial->config.dma_ping_bufsz < RT_SERIAL_RX_MINBUFSZ / 2)
+ serial->config.dma_ping_bufsz = RT_SERIAL_RX_MINBUFSZ / 2;
+ rx_fifo_size = sizeof(struct rt_serial_rx_fifo) + serial->config.rx_bufsz + serial->config.dma_ping_bufsz;
+#else
+ rx_fifo_size = sizeof(struct rt_serial_rx_fifo) + serial->config.rx_bufsz;
+#endif
+ rx_fifo = (struct rt_serial_rx_fifo *)rt_malloc(rx_fifo_size);
RT_ASSERT(rx_fifo != RT_NULL);
- rt_ringbuffer_init(&(rx_fifo->rb), rx_fifo->buffer, serial->config.rx_bufsz);
+ rt_memset(rx_fifo, RT_NULL, rx_fifo_size);
+
+ rt_ringbuffer_init(&rx_fifo->rb,
+ (rt_uint8_t *)rx_fifo + sizeof(struct rt_serial_rx_fifo),
+ serial->config.rx_bufsz);
+
+#ifdef RT_SERIAL_USING_DMA
+ if (serial->config.dma_ping_bufsz > 0)
+ {
+ rt_ringbuffer_init(&rx_fifo->dma_ping_rb,
+ (rt_uint8_t *)rx_fifo + sizeof(struct rt_serial_rx_fifo) + serial->config.rx_bufsz,
+ serial->config.dma_ping_bufsz);
+ }
+#endif
serial->serial_rx = rx_fifo;
@@ -798,19 +1010,22 @@ static rt_err_t rt_serial_rx_enable(struct rt_device *dev,
dev->open_flag |= RT_SERIAL_RX_NON_BLOCKING;
/* Call the control() API to configure the serial device by RT_SERIAL_RX_NON_BLOCKING*/
serial->ops->control(serial,
- RT_DEVICE_CTRL_CONFIG,
- (void *) RT_SERIAL_RX_NON_BLOCKING);
+ RT_DEVICE_CTRL_CONFIG,
+ (void *)RT_SERIAL_RX_NON_BLOCKING);
return RT_EOK;
}
+
/* When using RT_SERIAL_RX_BLOCKING, rt_completion_init() and rx_cpt_index are initialized */
rx_fifo->rx_cpt_index = 0;
- rt_completion_init(&(rx_fifo->rx_cpt));
+ rt_atomic_store(&rx_fifo->rx_timeout, RT_WAITING_FOREVER);
+
+ rt_completion_init(&rx_fifo->rx_cpt);
dev->open_flag |= RT_SERIAL_RX_BLOCKING;
/* Call the control() API to configure the serial device by RT_SERIAL_RX_BLOCKING*/
serial->ops->control(serial,
- RT_DEVICE_CTRL_CONFIG,
- (void *) RT_SERIAL_RX_BLOCKING);
+ RT_DEVICE_CTRL_CONFIG,
+ (void *)RT_SERIAL_RX_BLOCKING);
return RT_EOK;
}
@@ -821,10 +1036,10 @@ static rt_err_t rt_serial_rx_enable(struct rt_device *dev,
* @param rx_oflag The flag of that the serial port opens.
* @return Return the status of the operation.
*/
-static rt_err_t rt_serial_rx_disable(struct rt_device *dev,
- rt_uint16_t rx_oflag)
+static rt_err_t rt_serial_rx_disable(struct rt_device *dev,
+ rt_uint16_t rx_oflag)
{
- struct rt_serial_device *serial;
+ struct rt_serial_device *serial;
struct rt_serial_rx_fifo *rx_fifo;
RT_ASSERT(dev != RT_NULL);
@@ -836,22 +1051,20 @@ static rt_err_t rt_serial_rx_disable(struct rt_device *dev,
if (serial->serial_rx == RT_NULL) return RT_EOK;
- do
+ if (rx_oflag == RT_SERIAL_RX_NON_BLOCKING)
{
- if (rx_oflag == RT_SERIAL_RX_NON_BLOCKING)
- {
- dev->open_flag &= ~ RT_SERIAL_RX_NON_BLOCKING;
- serial->ops->control(serial,
- RT_DEVICE_CTRL_CLR_INT,
- (void *)RT_SERIAL_RX_NON_BLOCKING);
- break;
- }
-
- dev->open_flag &= ~ RT_SERIAL_RX_BLOCKING;
+ dev->open_flag &= ~RT_SERIAL_RX_NON_BLOCKING;
serial->ops->control(serial,
- RT_DEVICE_CTRL_CLR_INT,
- (void *)RT_SERIAL_RX_BLOCKING);
- } while (0);
+ RT_DEVICE_CTRL_CLR_INT,
+ (void *)RT_SERIAL_RX_NON_BLOCKING);
+ }
+ else
+ {
+ dev->open_flag &= ~RT_SERIAL_RX_BLOCKING;
+ serial->ops->control(serial,
+ RT_DEVICE_CTRL_CLR_INT,
+ (void *)RT_SERIAL_RX_BLOCKING);
+ }
rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx;
RT_ASSERT(rx_fifo != RT_NULL);
@@ -867,10 +1080,10 @@ static rt_err_t rt_serial_rx_disable(struct rt_device *dev,
* @param rx_oflag The flag of that the serial port opens.
* @return Return the status of the operation.
*/
-static rt_err_t rt_serial_tx_disable(struct rt_device *dev,
- rt_uint16_t tx_oflag)
+static rt_err_t rt_serial_tx_disable(struct rt_device *dev,
+ rt_uint16_t tx_oflag)
{
- struct rt_serial_device *serial;
+ struct rt_serial_device *serial;
struct rt_serial_tx_fifo *tx_fifo;
RT_ASSERT(dev != RT_NULL);
@@ -885,30 +1098,26 @@ static rt_err_t rt_serial_tx_disable(struct rt_device *dev,
tx_fifo = (struct rt_serial_tx_fifo *)serial->serial_tx;
RT_ASSERT(tx_fifo != RT_NULL);
- do
+ if (tx_oflag == RT_SERIAL_TX_NON_BLOCKING)
{
- if (tx_oflag == RT_SERIAL_TX_NON_BLOCKING)
- {
- dev->open_flag &= ~ RT_SERIAL_TX_NON_BLOCKING;
-
- serial->ops->control(serial,
- RT_DEVICE_CTRL_CLR_INT,
- (void *)RT_SERIAL_TX_NON_BLOCKING);
- break;
- }
+ dev->open_flag &= ~RT_SERIAL_TX_NON_BLOCKING;
- rt_completion_done(&(tx_fifo->tx_cpt));
- dev->open_flag &= ~ RT_SERIAL_TX_BLOCKING;
serial->ops->control(serial,
- RT_DEVICE_CTRL_CLR_INT,
- (void *)RT_SERIAL_TX_BLOCKING);
- } while (0);
+ RT_DEVICE_CTRL_CLR_INT,
+ (void *)RT_SERIAL_TX_NON_BLOCKING);
+ }
+ else
+ {
+ rt_completion_done(&tx_fifo->tx_cpt);
+ dev->open_flag &= ~RT_SERIAL_TX_BLOCKING;
+ serial->ops->control(serial,
+ RT_DEVICE_CTRL_CLR_INT,
+ (void *)RT_SERIAL_TX_BLOCKING);
+ }
+
rt_free(tx_fifo);
serial->serial_tx = RT_NULL;
-
- rt_memset(&serial->rx_notify, 0, sizeof(struct rt_device_notify));
-
return RT_EOK;
}
@@ -919,7 +1128,7 @@ static rt_err_t rt_serial_tx_disable(struct rt_device *dev,
*/
static rt_err_t rt_serial_init(struct rt_device *dev)
{
- rt_err_t result = RT_EOK;
+ rt_err_t result = RT_EOK;
struct rt_serial_device *serial;
RT_ASSERT(dev != RT_NULL);
@@ -958,7 +1167,7 @@ static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag)
}
LOG_D("open serial device: 0x%08x with open flag: 0x%04x",
- dev, oflag);
+ dev, oflag);
/* By default, the receive mode of a serial devide is RT_SERIAL_RX_NON_BLOCKING */
if ((oflag & RT_SERIAL_RX_BLOCKING) == RT_SERIAL_RX_BLOCKING)
@@ -973,19 +1182,16 @@ static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag)
dev->open_flag |= RT_SERIAL_TX_BLOCKING;
/* set steam flag */
- if ((oflag & RT_DEVICE_FLAG_STREAM) ||
- (dev->open_flag & RT_DEVICE_FLAG_STREAM))
+ if ((oflag & RT_DEVICE_FLAG_STREAM) || (dev->open_flag & RT_DEVICE_FLAG_STREAM))
dev->open_flag |= RT_DEVICE_FLAG_STREAM;
/* initialize the Rx structure according to open flag */
if (serial->serial_rx == RT_NULL)
- rt_serial_rx_enable(dev, dev->open_flag &
- (RT_SERIAL_RX_BLOCKING | RT_SERIAL_RX_NON_BLOCKING));
+ rt_serial_rx_enable(dev, dev->open_flag & (RT_SERIAL_RX_BLOCKING | RT_SERIAL_RX_NON_BLOCKING));
/* initialize the Tx structure according to open flag */
if (serial->serial_tx == RT_NULL)
- rt_serial_tx_enable(dev, dev->open_flag &
- (RT_SERIAL_TX_BLOCKING | RT_SERIAL_TX_NON_BLOCKING));
+ rt_serial_tx_enable(dev, dev->open_flag & (RT_SERIAL_TX_BLOCKING | RT_SERIAL_TX_NON_BLOCKING));
return RT_EOK;
}
@@ -1006,16 +1212,16 @@ static rt_err_t rt_serial_close(struct rt_device *dev)
/* this device has more reference count */
if (dev->ref_count > 1) return -RT_ERROR;
/* Disable serial receive mode. */
- rt_serial_rx_disable(dev, dev->open_flag &
- (RT_SERIAL_RX_BLOCKING | RT_SERIAL_RX_NON_BLOCKING));
+ rt_serial_rx_disable(dev, dev->open_flag & (RT_SERIAL_RX_BLOCKING | RT_SERIAL_RX_NON_BLOCKING));
/* Disable serial tranmit mode. */
- rt_serial_tx_disable(dev, dev->open_flag &
- (RT_SERIAL_TX_BLOCKING | RT_SERIAL_TX_NON_BLOCKING));
+ rt_serial_tx_disable(dev, dev->open_flag & (RT_SERIAL_TX_BLOCKING | RT_SERIAL_TX_NON_BLOCKING));
/* Clear the callback function */
serial->parent.rx_indicate = RT_NULL;
serial->parent.tx_complete = RT_NULL;
+ rt_memset(&serial->rx_notify, RT_NULL, sizeof(struct rt_device_notify));
+
/* Call the control() API to close the serial device */
serial->ops->control(serial, RT_DEVICE_CTRL_CLOSE, RT_NULL);
dev->flag &= ~RT_DEVICE_FLAG_ACTIVATED;
@@ -1023,35 +1229,108 @@ static rt_err_t rt_serial_close(struct rt_device *dev)
return RT_EOK;
}
+static void _serial_rx_flush(struct rt_serial_device *serial)
+{
+ rt_base_t level;
+ struct rt_serial_rx_fifo *rx_fifo;
+ RT_ASSERT(serial != RT_NULL);
+
+ if (serial->config.rx_bufsz == 0)
+ {
+ while (serial->ops->getc(serial) != -1)
+ {
+ }
+ }
+ else
+ {
+ rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx;
+ RT_ASSERT(rx_fifo != RT_NULL);
+
+ level = rt_spin_lock_irqsave(&serial->spinlock);
+ rt_completion_wait(&rx_fifo->rx_cpt, 0);
+ rt_ringbuffer_reset(&rx_fifo->rb);
+ rx_fifo->rx_cpt_index = 0;
+#ifdef RT_SERIAL_USING_DMA
+ if (serial->config.dma_ping_bufsz > 0)
+ {
+ rt_ringbuffer_reset(&rx_fifo->dma_ping_rb);
+ }
+#endif
+ rt_spin_unlock_irqrestore(&serial->spinlock, level);
+ }
+}
+
+static void _serial_tx_flush(struct rt_serial_device *serial)
+{
+ struct rt_serial_tx_fifo *tx_fifo;
+ RT_ASSERT(serial != RT_NULL);
+
+ if (serial->config.tx_bufsz != 0)
+ {
+ tx_fifo = (struct rt_serial_tx_fifo *)serial->serial_tx;
+ RT_ASSERT(tx_fifo != RT_NULL);
+
+ if (rt_atomic_load(&tx_fifo->activated))
+ {
+ rt_completion_wait(&tx_fifo->tx_cpt, RT_WAITING_FOREVER);
+ return;
+ }
+ }
+}
+
+static rt_err_t _serial_get_unread_bytes_count(struct rt_serial_device *serial, rt_ssize_t *unread_bytes)
+{
+ rt_base_t level;
+ struct rt_serial_rx_fifo *rx_fifo;
+ RT_ASSERT(serial != RT_NULL);
+
+ if (serial->config.rx_bufsz == 0)
+ {
+ LOG_W("get unread bytes count not support in poll mode.");
+ *unread_bytes = -1;
+ return -RT_EPERM;
+ }
+ else
+ {
+ rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx;
+ RT_ASSERT(rx_fifo != RT_NULL);
+
+ level = RT_SERIAL_FIFO_LOCK(&serial->spinlock);
+ *unread_bytes = rt_ringbuffer_data_len(&rx_fifo->rb);
+ RT_SERIAL_FIFO_UNLOCK(&serial->spinlock, level);
+ }
+ return RT_EOK;
+}
+
#ifdef RT_USING_POSIX_TERMIOS
struct speed_baudrate_item
{
speed_t speed;
- int baudrate;
+ int baudrate;
};
const static struct speed_baudrate_item _tbl[] =
-{
- {B2400, BAUD_RATE_2400},
- {B4800, BAUD_RATE_4800},
- {B9600, BAUD_RATE_9600},
- {B19200, BAUD_RATE_19200},
- {B38400, BAUD_RATE_38400},
- {B57600, BAUD_RATE_57600},
- {B115200, BAUD_RATE_115200},
- {B230400, BAUD_RATE_230400},
- {B460800, BAUD_RATE_460800},
- {B500000, BAUD_RATE_500000},
- {B921600, BAUD_RATE_921600},
- {B2000000, BAUD_RATE_2000000},
- {B3000000, BAUD_RATE_3000000},
+ {
+ { B2400, BAUD_RATE_2400},
+ { B4800, BAUD_RATE_4800},
+ { B9600, BAUD_RATE_9600},
+ { B19200, BAUD_RATE_19200},
+ { B38400, BAUD_RATE_38400},
+ { B57600, BAUD_RATE_57600},
+ { B115200, BAUD_RATE_115200},
+ { B230400, BAUD_RATE_230400},
+ { B460800, BAUD_RATE_460800},
+ { B500000, BAUD_RATE_500000},
+ { B921600, BAUD_RATE_921600},
+ {B2000000, BAUD_RATE_2000000},
+ {B3000000, BAUD_RATE_3000000},
};
static speed_t _get_speed(int baudrate)
{
int index;
- for (index = 0; index < sizeof(_tbl)/sizeof(_tbl[0]); index ++)
+ for (index = 0; index < sizeof(_tbl) / sizeof(_tbl[0]); index++)
{
if (_tbl[index].baudrate == baudrate)
return _tbl[index].speed;
@@ -1064,7 +1343,7 @@ static int _get_baudrate(speed_t speed)
{
int index;
- for (index = 0; index < sizeof(_tbl)/sizeof(_tbl[0]); index ++)
+ for (index = 0; index < sizeof(_tbl) / sizeof(_tbl[0]); index++)
{
if (_tbl[index].speed == speed)
return _tbl[index].baudrate;
@@ -1075,44 +1354,17 @@ static int _get_baudrate(speed_t speed)
static void _tc_flush(struct rt_serial_device *serial, int queue)
{
- rt_base_t level;
- int ch = -1;
- struct rt_serial_rx_fifo *rx_fifo = RT_NULL;
- struct rt_device *device = RT_NULL;
-
RT_ASSERT(serial != RT_NULL);
- device = &(serial->parent);
- rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx;
-
- switch(queue)
+ if (queue == TCIFLUSH || queue == TCIOFLUSH)
{
- case TCIFLUSH:
- case TCIOFLUSH:
- RT_ASSERT(rx_fifo != RT_NULL);
-
- if((device->open_flag & RT_DEVICE_FLAG_INT_RX) || (device->open_flag & RT_DEVICE_FLAG_DMA_RX))
- {
- RT_ASSERT(RT_NULL != rx_fifo);
- level = rt_hw_interrupt_disable();
- rx_fifo->rx_cpt_index = 0;
- rt_hw_interrupt_enable(level);
- }
- else
- {
- while (1)
- {
- ch = serial->ops->getc(serial);
- if (ch == -1) break;
- }
- }
-
- break;
-
- case TCOFLUSH:
- break;
+ _serial_rx_flush(serial);
}
+ if (queue == TCOFLUSH || queue == TCIOFLUSH)
+ {
+ _serial_tx_flush(serial);
+ }
}
#endif /* RT_USING_POSIX_TERMIOS */
@@ -1127,7 +1379,7 @@ static rt_err_t rt_serial_control(struct rt_device *dev,
int cmd,
void *args)
{
- rt_err_t ret = RT_EOK;
+ rt_err_t ret = RT_EOK;
struct rt_serial_device *serial;
RT_ASSERT(dev != RT_NULL);
@@ -1135,254 +1387,381 @@ static rt_err_t rt_serial_control(struct rt_device *dev,
switch (cmd)
{
- case RT_DEVICE_CTRL_SUSPEND:
- /* suspend device */
- dev->flag |= RT_DEVICE_FLAG_SUSPENDED;
- break;
+ case RT_DEVICE_CTRL_SUSPEND:
+ /* suspend device */
+ dev->flag |= RT_DEVICE_FLAG_SUSPENDED;
+ break;
- case RT_DEVICE_CTRL_RESUME:
- /* resume device */
- dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED;
- break;
+ case RT_DEVICE_CTRL_RESUME:
+ /* resume device */
+ dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED;
+ break;
+
+ case RT_DEVICE_CTRL_CONFIG:
+ if (args == RT_NULL)
+ {
+ ret = -RT_EINVAL;
+ }
+ else
+ {
+ struct serial_configure *pconfig = (struct serial_configure *)args;
+ 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
+ )
+ && serial->parent.ref_count != 0)
+ {
+ /*can not change buffer size*/
+ ret = -RT_EBUSY;
+ break;
+ }
+ /* set serial configure */
+ serial->config = *pconfig;
+ serial->ops->configure(serial, (struct serial_configure *)args);
+ }
+ break;
+ case RT_DEVICE_CTRL_NOTIFY_SET:
+ if (args == RT_NULL)
+ {
+ ret = -RT_EINVAL;
+ }
+ else
+ {
+ rt_memcpy(&serial->rx_notify, args, sizeof(struct rt_device_notify));
+ }
+ break;
+
+ case RT_DEVICE_CTRL_CONSOLE_OFLAG:
+ if (args == RT_NULL)
+ {
+ ret = -RT_EINVAL;
+ }
+ else
+ {
+ *(rt_uint16_t *)args = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM;
+ }
+ break;
- case RT_DEVICE_CTRL_CONFIG:
- if (args != RT_NULL)
+ /* Call before rt_device_read */
+ case RT_SERIAL_CTRL_SET_RX_TIMEOUT:
+ if (args == RT_NULL)
+ {
+ ret = -RT_EINVAL;
+ }
+ else
+ {
+ if (serial->config.rx_bufsz == 0)
{
- struct serial_configure *pconfig = (struct serial_configure *) args;
- if (((pconfig->rx_bufsz != serial->config.rx_bufsz) || (pconfig->tx_bufsz != serial->config.tx_bufsz))
- && serial->parent.ref_count)
- {
- /*can not change buffer size*/
- return -RT_EBUSY;
- }
- /* set serial configure */
- serial->config = *pconfig;
- serial->ops->configure(serial, (struct serial_configure *) args);
+ ret = -RT_EPERM;
}
- break;
- case RT_DEVICE_CTRL_NOTIFY_SET:
- if (args)
+
+ struct rt_serial_rx_fifo *rx_fifo = RT_NULL;
+ rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx;
+ RT_ASSERT(rx_fifo != RT_NULL);
+
+ rt_atomic_store(&rx_fifo->rx_timeout, *(rt_int32_t *)args);
+ }
+ break;
+
+ /* Call before rt_device_write */
+ case RT_SERIAL_CTRL_SET_TX_TIMEOUT:
+ if (args == RT_NULL)
+ {
+ ret = -RT_EINVAL;
+ }
+ else
+ {
+ if (serial->config.tx_bufsz == 0)
{
- rt_memcpy(&serial->rx_notify, args, sizeof(struct rt_device_notify));
+ ret = -RT_EPERM;
}
- break;
- case RT_DEVICE_CTRL_CONSOLE_OFLAG:
- if (args)
+ struct rt_serial_tx_fifo *tx_fifo = RT_NULL;
+ tx_fifo = (struct rt_serial_tx_fifo *)serial->serial_tx;
+ RT_ASSERT(tx_fifo != RT_NULL);
+
+ rt_atomic_store(&tx_fifo->tx_timeout, *(rt_int32_t *)args);
+ }
+ break;
+
+ case RT_SERIAL_CTRL_GET_RX_TIMEOUT:
+ if (args == RT_NULL)
+ {
+ ret = -RT_EINVAL;
+ }
+ else
+ {
+ if (serial->config.rx_bufsz == 0)
{
- *(rt_uint16_t*)args = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM;
+ ret = -RT_EPERM;
}
- break;
-#ifdef RT_USING_POSIX_STDIO
-#ifdef RT_USING_POSIX_TERMIOS
- case TCGETA:
+
+ struct rt_serial_rx_fifo *rx_fifo = RT_NULL;
+ rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx;
+ RT_ASSERT(rx_fifo != RT_NULL);
+
+ *(rt_int32_t *)args = rt_atomic_load(&rx_fifo->rx_timeout);
+ }
+ break;
+
+ case RT_SERIAL_CTRL_GET_TX_TIMEOUT:
+ if (args == RT_NULL)
+ {
+ ret = -RT_EINVAL;
+ }
+ else
+ {
+ if (serial->config.tx_bufsz == 0)
{
- struct termios *tio = (struct termios*)args;
- if (tio == RT_NULL) return -RT_EINVAL;
+ ret = -RT_EPERM;
+ }
- tio->c_iflag = 0;
- tio->c_oflag = 0;
- tio->c_lflag = 0;
+ struct rt_serial_tx_fifo *tx_fifo = RT_NULL;
+ tx_fifo = (struct rt_serial_tx_fifo *)serial->serial_tx;
+ RT_ASSERT(tx_fifo != RT_NULL);
- /* update oflag for console device */
- if (rt_console_get_device() == dev)
- tio->c_oflag = OPOST | ONLCR;
+ *(rt_int32_t *)args = rt_atomic_load(&tx_fifo->tx_timeout);
+ }
+ break;
- /* set cflag */
- tio->c_cflag = 0;
- if (serial->config.data_bits == DATA_BITS_5)
- tio->c_cflag = CS5;
- else if (serial->config.data_bits == DATA_BITS_6)
- tio->c_cflag = CS6;
- else if (serial->config.data_bits == DATA_BITS_7)
- tio->c_cflag = CS7;
- else if (serial->config.data_bits == DATA_BITS_8)
- tio->c_cflag = CS8;
+ /* Discard all data */
+ case RT_SERIAL_CTRL_RX_FLUSH:
+ _serial_rx_flush(serial);
+ break;
- if (serial->config.stop_bits == STOP_BITS_2)
- tio->c_cflag |= CSTOPB;
+ /* Blocking and wait for the send buffer data to be sent. */
+ case RT_SERIAL_CTRL_TX_FLUSH:
+ _serial_tx_flush(serial);
+ break;
- if (serial->config.parity == PARITY_EVEN)
- tio->c_cflag |= PARENB;
- else if (serial->config.parity == PARITY_ODD)
- tio->c_cflag |= (PARODD | PARENB);
+ /* get unread bytes count. */
+ case RT_SERIAL_CTRL_GET_UNREAD_BYTES_COUNT:
+ if (args == RT_NULL)
+ {
+ ret = -RT_EINVAL;
+ }
+ else
+ {
+ ret = _serial_get_unread_bytes_count(serial, (rt_ssize_t *)args);
+ }
+ break;
- if (serial->config.flowcontrol == RT_SERIAL_FLOWCONTROL_CTSRTS)
- tio->c_cflag |= CRTSCTS;
+#ifdef RT_USING_POSIX_STDIO
+#ifdef RT_USING_POSIX_TERMIOS
+ case TCGETA: {
+ struct termios *tio = (struct termios *)args;
+ if (tio == RT_NULL) return -RT_EINVAL;
- cfsetospeed(tio, _get_speed(serial->config.baud_rate));
- }
- break;
+ tio->c_iflag = 0;
+ tio->c_oflag = 0;
+ tio->c_lflag = 0;
- case TCSETAW:
- case TCSETAF:
- case TCSETA:
- {
- int baudrate;
- struct serial_configure config;
+ /* update oflag for console device */
+ if (rt_console_get_device() == dev)
+ tio->c_oflag = OPOST | ONLCR;
- struct termios *tio = (struct termios*)args;
- if (tio == RT_NULL) return -RT_EINVAL;
+ /* set cflag */
+ tio->c_cflag = 0;
+ if (serial->config.data_bits == DATA_BITS_5)
+ tio->c_cflag = CS5;
+ else if (serial->config.data_bits == DATA_BITS_6)
+ tio->c_cflag = CS6;
+ else if (serial->config.data_bits == DATA_BITS_7)
+ tio->c_cflag = CS7;
+ else if (serial->config.data_bits == DATA_BITS_8)
+ tio->c_cflag = CS8;
- config = serial->config;
+ if (serial->config.stop_bits == STOP_BITS_2)
+ tio->c_cflag |= CSTOPB;
- baudrate = _get_baudrate(cfgetospeed(tio));
- config.baud_rate = baudrate;
+ if (serial->config.parity == PARITY_EVEN)
+ tio->c_cflag |= PARENB;
+ else if (serial->config.parity == PARITY_ODD)
+ tio->c_cflag |= (PARODD | PARENB);
- switch (tio->c_cflag & CSIZE)
- {
- case CS5:
- config.data_bits = DATA_BITS_5;
- break;
- case CS6:
- config.data_bits = DATA_BITS_6;
- break;
- case CS7:
- config.data_bits = DATA_BITS_7;
- break;
- default:
- config.data_bits = DATA_BITS_8;
- break;
- }
+ if (serial->config.flowcontrol == RT_SERIAL_FLOWCONTROL_CTSRTS)
+ tio->c_cflag |= CRTSCTS;
- if (tio->c_cflag & CSTOPB) config.stop_bits = STOP_BITS_2;
- else config.stop_bits = STOP_BITS_1;
+ cfsetospeed(tio, _get_speed(serial->config.baud_rate));
+ }
+ break;
- if (tio->c_cflag & PARENB)
- {
- if (tio->c_cflag & PARODD) config.parity = PARITY_ODD;
- else config.parity = PARITY_EVEN;
- }
- else config.parity = PARITY_NONE;
+ case TCSETAW:
+ case TCSETAF:
+ case TCSETA: {
+ int baudrate;
+ struct serial_configure config;
- if (tio->c_cflag & CRTSCTS) config.flowcontrol = RT_SERIAL_FLOWCONTROL_CTSRTS;
- else config.flowcontrol = RT_SERIAL_FLOWCONTROL_NONE;
+ struct termios *tio = (struct termios *)args;
+ if (tio == RT_NULL) return -RT_EINVAL;
- /* set serial configure */
- serial->config = config;
- serial->ops->configure(serial, &config);
- }
- break;
- case TCFLSH:
- {
- int queue = (int)args;
+ config = serial->config;
- _tc_flush(serial, queue);
- }
+ baudrate = _get_baudrate(cfgetospeed(tio));
+ config.baud_rate = baudrate;
+ switch (tio->c_cflag & CSIZE)
+ {
+ case CS5:
+ config.data_bits = DATA_BITS_5;
break;
- case TCXONC:
+ case CS6:
+ config.data_bits = DATA_BITS_6;
break;
-#endif /*RT_USING_POSIX_TERMIOS*/
- case TIOCSWINSZ:
- {
- struct winsize* p_winsize;
-
- p_winsize = (struct winsize*)args;
- rt_kprintf("\x1b[8;%d;%dt", p_winsize->ws_col, p_winsize->ws_row);
- }
+ case CS7:
+ config.data_bits = DATA_BITS_7;
break;
- case TIOCGWINSZ:
- {
- struct winsize* p_winsize;
- p_winsize = (struct winsize*)args;
+ default:
+ config.data_bits = DATA_BITS_8;
+ break;
+ }
- if(rt_thread_self() != rt_thread_find(FINSH_THREAD_NAME))
- {
- /* only can be used in tshell thread; otherwise, return default size */
- p_winsize->ws_col = 80;
- p_winsize->ws_row = 24;
- }
- else
- {
- #include <shell.h>
- #define _TIO_BUFLEN 20
- char _tio_buf[_TIO_BUFLEN];
- unsigned char cnt1, cnt2, cnt3, i;
- char row_s[4], col_s[4];
- char *p;
+ if (tio->c_cflag & CSTOPB)
+ config.stop_bits = STOP_BITS_2;
+ else
+ config.stop_bits = STOP_BITS_1;
- rt_memset(_tio_buf, 0, _TIO_BUFLEN);
+ if (tio->c_cflag & PARENB)
+ {
+ if (tio->c_cflag & PARODD)
+ config.parity = PARITY_ODD;
+ else
+ config.parity = PARITY_EVEN;
+ }
+ else
+ config.parity = PARITY_NONE;
- /* send the command to terminal for getting the window size of the terminal */
- rt_kprintf("\033[18t");
+ if (tio->c_cflag & CRTSCTS)
+ config.flowcontrol = RT_SERIAL_FLOWCONTROL_CTSRTS;
+ else
+ config.flowcontrol = RT_SERIAL_FLOWCONTROL_NONE;
- /* waiting for the response from the terminal */
- i = 0;
- while(i < _TIO_BUFLEN)
- {
- _tio_buf[i] = finsh_getchar();
- if(_tio_buf[i] != 't')
- {
- i ++;
- }
- else
- {
- break;
- }
- }
- if(i == _TIO_BUFLEN)
- {
- /* buffer overloaded, and return default size */
- p_winsize->ws_col = 80;
- p_winsize->ws_row = 24;
- break;
- }
+ /* set serial configure */
+ serial->config = config;
+ serial->ops->configure(serial, &config);
+ }
+ break;
+ case TCFLSH: {
+ int queue = (int)args;
- /* interpreting data eg: "\033[8;1;15t" which means row is 1 and col is 15 (unit: size of ONE character) */
- rt_memset(row_s,0,4);
- rt_memset(col_s,0,4);
- cnt1 = 0;
- while(cnt1 < _TIO_BUFLEN && _tio_buf[cnt1] != ';')
- {
- cnt1++;
- }
- cnt2 = ++cnt1;
- while(cnt2 < _TIO_BUFLEN && _tio_buf[cnt2] != ';')
- {
- cnt2++;
- }
- p = row_s;
- while(cnt1 < cnt2)
- {
- *p++ = _tio_buf[cnt1++];
- }
- p = col_s;
- cnt2++;
- cnt3 = rt_strlen(_tio_buf) - 1;
- while(cnt2 < cnt3)
- {
- *p++ = _tio_buf[cnt2++];
- }
+ _tc_flush(serial, queue);
+ }
+
+ break;
+ case TCXONC:
+ break;
+#endif /*RT_USING_POSIX_TERMIOS*/
+ case TIOCSWINSZ: {
+ struct winsize *p_winsize;
- /* load the window size date */
- p_winsize->ws_col = atoi(col_s);
- p_winsize->ws_row = atoi(row_s);
- #undef _TIO_BUFLEN
+ p_winsize = (struct winsize *)args;
+ rt_kprintf("\x1b[8;%d;%dt", p_winsize->ws_col, p_winsize->ws_row);
+ }
+ break;
+ case TIOCGWINSZ: {
+ struct winsize *p_winsize;
+ p_winsize = (struct winsize *)args;
+
+ if (rt_thread_self() != rt_thread_find(FINSH_THREAD_NAME))
+ {
+ /* only can be used in tshell thread; otherwise, return default size */
+ p_winsize->ws_col = 80;
+ p_winsize->ws_row = 24;
+ }
+ else
+ {
+#include <shell.h>
+#define _TIO_BUFLEN 20
+ char _tio_buf[_TIO_BUFLEN];
+ unsigned char cnt1, cnt2, cnt3, i;
+ char row_s[4], col_s[4];
+ char *p;
+
+ rt_memset(_tio_buf, 0, _TIO_BUFLEN);
+
+ /* send the command to terminal for getting the window size of the terminal */
+ rt_kprintf("\033[18t");
+
+ /* waiting for the response from the terminal */
+ i = 0;
+ while (i < _TIO_BUFLEN)
+ {
+ _tio_buf[i] = finsh_getchar();
+ if (_tio_buf[i] != 't')
+ {
+ i++;
+ }
+ else
+ {
+ break;
}
+ }
+ if (i == _TIO_BUFLEN)
+ {
+ /* buffer overloaded, and return default size */
+ p_winsize->ws_col = 80;
+ p_winsize->ws_row = 24;
+ break;
+ }
- p_winsize->ws_xpixel = 0;/* unused */
- p_winsize->ws_ypixel = 0;/* unused */
+ /* interpreting data eg: "\033[8;1;15t" which means row is 1 and col is 15 (unit: size of ONE character) */
+ rt_memset(row_s, 0, 4);
+ rt_memset(col_s, 0, 4);
+ cnt1 = 0;
+ while (cnt1 < _TIO_BUFLEN && _tio_buf[cnt1] != ';')
+ {
+ cnt1++;
}
- break;
- case FIONREAD:
+ cnt2 = ++cnt1;
+ while (cnt2 < _TIO_BUFLEN && _tio_buf[cnt2] != ';')
+ {
+ cnt2++;
+ }
+ p = row_s;
+ while (cnt1 < cnt2)
+ {
+ *p++ = _tio_buf[cnt1++];
+ }
+ p = col_s;
+ cnt2++;
+ cnt3 = rt_strlen(_tio_buf) - 1;
+ while (cnt2 < cnt3)
{
- rt_size_t recved = 0;
- rt_base_t level;
- struct rt_serial_rx_fifo * rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx;
+ *p++ = _tio_buf[cnt2++];
+ }
- level = rt_hw_interrupt_disable();
- recved = rt_ringbuffer_data_len(&(rx_fifo->rb));
- rt_hw_interrupt_enable(level);
+ /* load the window size date */
+ p_winsize->ws_col = atoi(col_s);
+ p_winsize->ws_row = atoi(row_s);
+#undef _TIO_BUFLEN
+ }
- *(rt_size_t *)args = recved;
- }
- break;
+ p_winsize->ws_xpixel = 0; /* unused */
+ p_winsize->ws_ypixel = 0; /* unused */
+ }
+ break;
+ case FIONREAD:
+ if (args == RT_NULL)
+ {
+ ret = -RT_EINVAL;
+ }
+ else
+ {
+ rt_ssize_t unread_bytes = 0;
+ ret = _serial_get_unread_bytes_count(serial, &unread_bytes);
+ if (ret == RT_EOK)
+ *(rt_size_t *)args = (rt_size_t)unread_bytes;
+ else
+ *(rt_size_t *)args = 0;
+ }
+ break;
#endif /* RT_USING_POSIX_STDIO */
- default :
- /* control device */
- ret = serial->ops->control(serial, cmd, args);
- break;
+ default:
+ /* control device */
+ ret = serial->ops->control(serial, cmd, args);
+ break;
}
return ret;
@@ -1390,9 +1769,9 @@ static rt_err_t rt_serial_control(struct rt_device *dev,
#ifdef RT_USING_DEVICE_OPS
static rt_ssize_t rt_serial_read(struct rt_device *dev,
- rt_off_t pos,
- void *buffer,
- rt_size_t size)
+ rt_off_t pos,
+ void *buffer,
+ rt_size_t size)
{
struct rt_serial_device *serial;
@@ -1411,11 +1790,11 @@ static rt_ssize_t rt_serial_read(struct rt_device *dev,
static rt_ssize_t rt_serial_write(struct rt_device *dev,
- rt_off_t pos,
- const void *buffer,
- rt_size_t size)
+ rt_off_t pos,
+ const void *buffer,
+ rt_size_t size)
{
- struct rt_serial_device *serial;
+ struct rt_serial_device *serial;
struct rt_serial_tx_fifo *tx_fifo;
RT_ASSERT(dev != RT_NULL);
@@ -1423,7 +1802,7 @@ static rt_ssize_t rt_serial_write(struct rt_device *dev,
serial = (struct rt_serial_device *)dev;
RT_ASSERT((serial != RT_NULL) && (buffer != RT_NULL));
- tx_fifo = (struct rt_serial_tx_fifo *) serial->serial_tx;
+ tx_fifo = (struct rt_serial_tx_fifo *)serial->serial_tx;
if (serial->config.tx_bufsz == 0)
{
@@ -1432,6 +1811,7 @@ static rt_ssize_t rt_serial_write(struct rt_device *dev,
if (dev->open_flag & RT_SERIAL_TX_BLOCKING)
{
+ RT_ASSERT(tx_fifo != RT_NULL);
if ((tx_fifo->rb.buffer_ptr) == RT_NULL)
{
return _serial_fifo_tx_blocking_nbuf(dev, pos, buffer, size);
@@ -1444,14 +1824,13 @@ static rt_ssize_t rt_serial_write(struct rt_device *dev,
}
const static struct rt_device_ops serial_ops =
-{
- rt_serial_init,
- rt_serial_open,
- rt_serial_close,
- rt_serial_read,
- rt_serial_write,
- rt_serial_control
-};
+ {
+ rt_serial_init,
+ rt_serial_open,
+ rt_serial_close,
+ rt_serial_read,
+ rt_serial_write,
+ rt_serial_control};
#endif
/**
@@ -1467,34 +1846,36 @@ rt_err_t rt_hw_serial_register(struct rt_serial_device *serial,
rt_uint32_t flag,
void *data)
{
- rt_err_t ret;
+ rt_err_t ret;
struct rt_device *device;
RT_ASSERT(serial != RT_NULL);
- device = &(serial->parent);
+ rt_spin_lock_init(&serial->spinlock);
+
+ device = &serial->parent;
device->type = RT_Device_Class_Char;
device->rx_indicate = RT_NULL;
device->tx_complete = RT_NULL;
#ifdef RT_USING_DEVICE_OPS
- device->ops = &serial_ops;
+ device->ops = &serial_ops;
#else
- device->init = rt_serial_init;
- device->open = rt_serial_open;
- device->close = rt_serial_close;
- device->read = RT_NULL;
- device->write = RT_NULL;
- device->control = rt_serial_control;
+ device->init = rt_serial_init;
+ device->open = rt_serial_open;
+ device->close = rt_serial_close;
+ device->read = RT_NULL;
+ device->write = RT_NULL;
+ device->control = rt_serial_control;
#endif
- device->user_data = data;
+ device->user_data = data;
/* register a character device */
ret = rt_device_register(device, name, flag);
#ifdef RT_USING_POSIX_STDIO
/* set fops */
- device->fops = &_serial_fops;
+ device->fops = &_serial_fops;
#endif
return ret;
}
@@ -1504,139 +1885,266 @@ rt_err_t rt_hw_serial_register(struct rt_serial_device *serial,
* @param serial RT-thread serial device.
* @param event ISR event type.
*/
-void rt_hw_serial_isr(struct rt_serial_device *serial, int event)
+rt_err_t rt_hw_serial_control_isr(struct rt_serial_device *serial, int cmd, void *args)
{
RT_ASSERT(serial != RT_NULL);
+ rt_err_t ret = RT_EOK;
- switch (event & 0xff)
+ switch (cmd)
{
- /* Interrupt receive event */
- case RT_SERIAL_EVENT_RX_IND:
- case RT_SERIAL_EVENT_RX_DMADONE:
+ case RT_HW_SERIAL_CTRL_PUTC:
+ if (args == RT_NULL)
{
- struct rt_serial_rx_fifo *rx_fifo;
- rt_size_t rx_length = 0;
- rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx;
- rt_base_t level;
+ ret = -RT_EINVAL;
+ }
+ else
+ {
+ struct rt_serial_rx_fifo *rx_fifo = RT_NULL;
+ rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx;
RT_ASSERT(rx_fifo != RT_NULL);
- /* If the event is RT_SERIAL_EVENT_RX_IND, rx_length is equal to 0 */
- rx_length = (event & (~0xff)) >> 8;
+#ifdef RT_SERIAL_BUF_STRATEGY_DROP
+ rt_ringbuffer_putchar(&rx_fifo->rb, *(rt_uint8_t *)args);
+#else
+ rt_ringbuffer_putchar_force(&rx_fifo->rb, *(rt_uint8_t *)args);
+#endif /* RT_SERIAL_BUF_STRATEGY_DROP */
+ }
+ break;
- if (rx_length)
- { /* RT_SERIAL_EVENT_RX_DMADONE MODE */
- level = rt_hw_interrupt_disable();
- rt_serial_update_write_index(&(rx_fifo->rb), rx_length);
- rt_hw_interrupt_enable(level);
+ case RT_HW_SERIAL_CTRL_GETC:
+ if (args == RT_NULL)
+ {
+ ret = -RT_EINVAL;
+ }
+ else
+ {
+ struct rt_serial_tx_fifo *tx_fifo = RT_NULL;
+ tx_fifo = (struct rt_serial_tx_fifo *)serial->serial_tx;
+ RT_ASSERT(tx_fifo != RT_NULL);
+ if (rt_ringbuffer_getchar(&tx_fifo->rb, (rt_uint8_t *)args) == 0)
+ {
+ ret = -RT_EEMPTY;
}
+ }
+ break;
- /* Get the length of the data from the ringbuffer */
- rx_length = rt_ringbuffer_data_len(&rx_fifo->rb);
- if (rx_length == 0) break;
+#ifdef RT_SERIAL_USING_DMA
+ case RT_HW_SERIAL_CTRL_GET_DMA_PING_BUF:
+ if (args == RT_NULL)
+ {
+ ret = -RT_EINVAL;
+ }
+ else
+ {
+ struct rt_serial_rx_fifo *rx_fifo = RT_NULL;
+ rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx;
+ RT_ASSERT(rx_fifo != RT_NULL);
+ *(rt_uint8_t **)args = rx_fifo->dma_ping_rb.buffer_ptr;
+ }
+ break;
+#endif
+
+ default:
+ ret = -RT_EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * @brief ISR for serial interrupt
+ * @param serial RT-thread serial device.
+ * @param event ISR event type.
+ */
+void rt_hw_serial_isr(struct rt_serial_device *serial, int event)
+{
+ RT_ASSERT(serial != RT_NULL);
+
+ switch (event & 0xff)
+ {
+ /* Interrupt receive event */
+ case RT_SERIAL_EVENT_RX_IND:
+ case RT_SERIAL_EVENT_RX_DMADONE: {
+ struct rt_serial_rx_fifo *rx_fifo;
+ rt_size_t rx_length = 0;
+ rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx;
+ RT_ASSERT(rx_fifo != RT_NULL);
- if (serial->parent.open_flag & RT_SERIAL_RX_BLOCKING)
+#ifdef RT_SERIAL_USING_DMA
+ rt_base_t level;
+ /* If the event is RT_SERIAL_EVENT_RX_IND, rx_length is equal to 0 */
+ rx_length = event >> 8;
+
+ /* RT_SERIAL_EVENT_RX_DMADONE MODE */
+ if (rx_length != 0)
+ {
+#ifdef RT_SERIAL_BUF_STRATEGY_DROP
+ rt_uint8_t *ptr;
+ rt_size_t size;
+ rt_size_t space_len;
+ /* UART_IT_IDLE and dma isr */
+ level = rt_spin_lock_irqsave(&serial->spinlock);
+ rt_serial_update_write_index(&rx_fifo->dma_ping_rb, rx_length);
+ do
{
- if (rx_fifo->rx_cpt_index && rx_length >= rx_fifo->rx_cpt_index )
- {
- rx_fifo->rx_cpt_index = 0;
- rt_completion_done(&(rx_fifo->rx_cpt));
- }
- }
- /* Trigger the receiving completion callback */
- if (serial->parent.rx_indicate != RT_NULL)
- serial->parent.rx_indicate(&(serial->parent), rx_length);
+ space_len = rt_ringbuffer_space_len(&rx_fifo->rb);
+ if (space_len == 0)
+ break;
- if (serial->rx_notify.notify)
+ size = rt_ringbuffer_peek(&rx_fifo->dma_ping_rb, &ptr);
+ if (size == 0)
+ break;
+
+ space_len -= rt_ringbuffer_put(&rx_fifo->rb, ptr, size);
+ if (space_len == 0)
+ break;
+
+ size = rt_ringbuffer_peek(&rx_fifo->dma_ping_rb, &ptr);
+ if (size == 0)
+ break;
+
+ rt_ringbuffer_put(&rx_fifo->rb, ptr, size);
+ } while (0);
+ if (space_len == 0)
+ rt_serial_update_read_index(&rx_fifo->dma_ping_rb, rt_ringbuffer_get_size(&rx_fifo->dma_ping_rb));
+ rt_spin_unlock_irqrestore(&serial->spinlock, level);
+#else
+ rt_uint8_t *ptr;
+ rt_size_t size;
+ /* UART_IT_IDLE and dma isr */
+ level = rt_spin_lock_irqsave(&serial->spinlock);
+ rt_serial_update_write_index(&rx_fifo->dma_ping_rb, rx_length);
+ do
{
- serial->rx_notify.notify(serial->rx_notify.dev);
- }
- break;
+ size = rt_ringbuffer_peek(&rx_fifo->dma_ping_rb, &ptr);
+ if (size == 0)
+ break;
+
+ rt_ringbuffer_put_force(&rx_fifo->rb, ptr, size);
+
+ size = rt_ringbuffer_peek(&rx_fifo->dma_ping_rb, &ptr);
+ if (size == 0)
+ break;
+
+ rt_ringbuffer_put_force(&rx_fifo->rb, ptr, size);
+ } while (0);
+ rt_spin_unlock_irqrestore(&serial->spinlock, level);
+#endif /* RT_SERIAL_BUF_STRATEGY_DROP */
}
+#endif /* RT_SERIAL_USING_DMA */
- /* Interrupt transmit event */
- case RT_SERIAL_EVENT_TX_DONE:
+ rx_length = rt_ringbuffer_data_len(&rx_fifo->rb);
+ if (rx_length == 0)
{
- struct rt_serial_tx_fifo *tx_fifo;
- rt_size_t tx_length = 0;
- tx_fifo = (struct rt_serial_tx_fifo *)serial->serial_tx;
- RT_ASSERT(tx_fifo != RT_NULL);
+ break;
+ }
- /* Get the length of the data from the ringbuffer */
- tx_length = rt_ringbuffer_data_len(&tx_fifo->rb);
- /* If there is no data in tx_ringbuffer,
- * then the transmit completion callback is triggered*/
- if (tx_length == 0)
+ if (serial->parent.open_flag & RT_SERIAL_RX_BLOCKING)
+ {
+ if (rx_fifo->rx_cpt_index && rx_length >= rx_fifo->rx_cpt_index)
{
- /* Trigger the transmit completion callback */
- if (serial->parent.tx_complete != RT_NULL)
- serial->parent.tx_complete(&serial->parent, RT_NULL);
-
- /* Maybe some datas left in the buffer still need to be sent in block mode,
- * so tx_fifo->activated should be RT_TRUE */
- if (serial->parent.open_flag & RT_SERIAL_TX_BLOCKING)
- {
- rt_completion_done(&(tx_fifo->tx_cpt));
- }
- else
- {
- tx_fifo->activated = RT_FALSE;
- }
-
- break;
+ rx_fifo->rx_cpt_index = 0;
+ rt_completion_done(&rx_fifo->rx_cpt);
}
+ }
- /* Call the transmit interface for transmission again */
- /* Note that in interrupt mode, tx_fifo->buffer and tx_length
- * are inactive parameters */
- serial->ops->transmit(serial,
- tx_fifo->buffer,
- tx_length,
- serial->parent.open_flag & ( \
- RT_SERIAL_TX_BLOCKING | \
- RT_SERIAL_TX_NON_BLOCKING));
- break;
+ /* Trigger the receiving completion callback */
+ if (serial->parent.rx_indicate != RT_NULL)
+ {
+ serial->parent.rx_indicate(&serial->parent, rx_length);
}
- case RT_SERIAL_EVENT_TX_DMADONE:
+ if (serial->rx_notify.notify != RT_NULL)
{
- struct rt_serial_tx_fifo *tx_fifo;
- tx_fifo = (struct rt_serial_tx_fifo *)serial->serial_tx;
- RT_ASSERT(tx_fifo != RT_NULL);
+ serial->rx_notify.notify(serial->rx_notify.dev);
+ }
+ break;
+ }
- tx_fifo->activated = RT_FALSE;
+ /* Interrupt transmit event */
+ case RT_SERIAL_EVENT_TX_DONE: {
+ struct rt_serial_tx_fifo *tx_fifo;
+ rt_size_t tx_length = 0;
+ tx_fifo = (struct rt_serial_tx_fifo *)serial->serial_tx;
+ RT_ASSERT(tx_fifo != RT_NULL);
+
+ /* Get the length of the data from the ringbuffer */
+ tx_length = rt_ringbuffer_data_len(&tx_fifo->rb);
+
+ /* If there is no data in tx_ringbuffer,
+ * then the transmit completion callback is triggered*/
+ if (tx_length == 0)
+ {
+ rt_completion_done(&tx_fifo->tx_cpt);
/* Trigger the transmit completion callback */
if (serial->parent.tx_complete != RT_NULL)
- serial->parent.tx_complete(&serial->parent, RT_NULL);
-
- if (serial->parent.open_flag & RT_SERIAL_TX_BLOCKING)
{
- rt_completion_done(&(tx_fifo->tx_cpt));
- break;
+ serial->parent.tx_complete(&serial->parent, RT_NULL);
}
+ rt_atomic_flag_clear(&tx_fifo->activated);
+ break;
+ }
+
+ rt_atomic_flag_test_and_set(&tx_fifo->activated);
+ /* Call the transmit interface for transmission again */
+ /* Note that in interrupt mode, tx_fifo->buffer and tx_length
+ * are inactive parameters */
+ serial->ops->transmit(serial,
+ tx_fifo->rb.buffer_ptr,
+ tx_length,
+ serial->parent.open_flag & (RT_SERIAL_TX_BLOCKING | RT_SERIAL_TX_NON_BLOCKING));
+ break;
+ }
+
+#ifdef RT_SERIAL_USING_DMA
+ case RT_SERIAL_EVENT_TX_DMADONE: {
+ struct rt_serial_tx_fifo *tx_fifo;
+ rt_size_t tx_length = 0;
+ tx_fifo = (struct rt_serial_tx_fifo *)serial->serial_tx;
+ RT_ASSERT(tx_fifo != RT_NULL);
+ if ((serial->parent.open_flag & RT_SERIAL_TX_BLOCKING) != RT_SERIAL_TX_BLOCKING || rt_ringbuffer_get_size(&tx_fifo->rb) != 0)
+ {
+ // 每次进来中断就说明之前的put_size已经被发送完毕了
rt_serial_update_read_index(&tx_fifo->rb, tx_fifo->put_size);
- /* Get the length of the data from the ringbuffer.
- * If there is some data in tx_ringbuffer,
- * then call the transmit interface for transmission again */
- if (rt_ringbuffer_data_len(&tx_fifo->rb))
+
+ /* Get the length of the data from the ringbuffer */
+ tx_length = rt_ringbuffer_data_len(&tx_fifo->rb);
+
+ if (tx_length != 0)
{
- tx_fifo->activated = RT_TRUE;
+ /* If there is some data in tx_ringbuffer,
+ * then call the transmit interface for transmission again */
+ rt_atomic_flag_test_and_set(&tx_fifo->activated);
- rt_uint8_t *put_ptr = RT_NULL;
+ rt_uint8_t *put_ptr = RT_NULL;
/* Get the linear length buffer from ringbuffer */
- tx_fifo->put_size = rt_serial_get_linear_buffer(&(tx_fifo->rb), &put_ptr);
+ tx_fifo->put_size = rt_serial_get_linear_buffer(&tx_fifo->rb, &put_ptr);
+
/* Call the transmit interface for transmission again */
serial->ops->transmit(serial,
- put_ptr,
- tx_fifo->put_size,
- RT_SERIAL_TX_NON_BLOCKING);
+ put_ptr,
+ tx_fifo->put_size,
+ RT_SERIAL_TX_NON_BLOCKING);
+ break;
}
+ }
- break;
+ rt_completion_done(&tx_fifo->tx_cpt);
+
+ /* Trigger the transmit completion callback */
+ if (serial->parent.tx_complete != RT_NULL)
+ {
+ serial->parent.tx_complete(&serial->parent, RT_NULL);
}
- default:
- break;
+ rt_atomic_flag_clear(&tx_fifo->activated);
+ break;
+ }
+#endif /* RT_SERIAL_USING_DMA */
+ default:
+ break;
}
}
diff --git a/components/net/at/include/at.h b/components/net/at/include/at.h
index 6af944168a..b94c0448cc 100644
--- a/components/net/at/include/at.h
+++ b/components/net/at/include/at.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2025 RT-Thread Development Team
+ * Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -90,7 +90,10 @@ struct at_server
char send_buffer[AT_SERVER_SEND_BUFF_LEN];
char recv_buffer[AT_SERVER_RECV_BUFF_LEN];
rt_size_t cur_recv_len;
+
+#if (!defined(RT_USING_SERIAL_V2))
rt_sem_t rx_notice;
+#endif
rt_thread_t parser;
void (*parser_entry)(struct at_server *server);
@@ -165,7 +168,11 @@ struct at_client
rt_size_t recv_line_len;
/* The maximum supported receive data length */
rt_size_t recv_bufsz;
+
+#if (!defined(RT_USING_SERIAL_V2))
rt_sem_t rx_notice;
+#endif
+
rt_mutex_t lock;
at_response_t resp;
diff --git a/components/net/at/src/at_client.c b/components/net/at/src/at_client.c
index 900f2b1b96..ed183f1eac 100644
--- a/components/net/at/src/at_client.c
+++ b/components/net/at/src/at_client.c
@@ -11,6 +11,7 @@
* 2021-03-17 Meco Man fix a buf of leaking memory
* 2021-07-14 Sszl fix a buf of leaking memory
* 2025-01-02 dongly support SERIAL_V2
+ * 2025-04-18 RyanCw support New SERIAL_V2
*/
#include <at.h>
@@ -225,7 +226,8 @@ int at_resp_parse_line_args(at_response_t resp, rt_size_t resp_line, const char
RT_ASSERT(resp);
RT_ASSERT(resp_expr);
- if ((resp_line_buf = at_resp_get_line(resp, resp_line)) == RT_NULL)
+ resp_line_buf = at_resp_get_line(resp, resp_line);
+ if (resp_line_buf == RT_NULL)
{
return -1;
}
@@ -259,7 +261,8 @@ int at_resp_parse_line_args_by_kw(at_response_t resp, const char *keyword, const
RT_ASSERT(resp);
RT_ASSERT(resp_expr);
- if ((resp_line_buf = at_resp_get_line_by_kw(resp, keyword)) == RT_NULL)
+ resp_line_buf = at_resp_get_line_by_kw(resp, keyword);
+ if (resp_line_buf == RT_NULL)
{
return -1;
}
@@ -541,6 +544,7 @@ static rt_err_t at_client_getchar(at_client_t client, char *ch, rt_int32_t timeo
{
rt_err_t result = RT_EOK;
+#if (!defined(RT_USING_SERIAL_V2))
while (rt_device_read(client->device, 0, ch, 1) == 0)
{
result = rt_sem_take(client->rx_notice, rt_tick_from_millisecond(timeout));
@@ -551,8 +555,19 @@ static rt_err_t at_client_getchar(at_client_t client, char *ch, rt_int32_t timeo
rt_sem_control(client->rx_notice, RT_IPC_CMD_RESET, RT_NULL);
}
+#else
+ rt_int32_t rx_timeout = rt_tick_from_millisecond(timeout);
+ rt_device_control(client->device, RT_SERIAL_CTRL_SET_RX_TIMEOUT, (void *)&rx_timeout);
+ result = rt_device_read(client->device, 0, ch, 1);
+ if(result <= 0)
+ {
+ result = -RT_ERROR;
+ }
+ rx_timeout = RT_WAITING_FOREVER;
+ rt_device_control(client->device, RT_SERIAL_CTRL_SET_RX_TIMEOUT, (void*)&rx_timeout);
+#endif
- return RT_EOK;
+ return result;
}
/**
@@ -570,7 +585,7 @@ static rt_err_t at_client_getchar(at_client_t client, char *ch, rt_int32_t timeo
*/
rt_size_t at_client_obj_recv(at_client_t client, char *buf, rt_size_t size, rt_int32_t timeout)
{
- rt_size_t len = 0;
+ rt_size_t read_idx = 0;
RT_ASSERT(buf);
@@ -580,16 +595,17 @@ rt_size_t at_client_obj_recv(at_client_t client, char *buf, rt_size_t size, rt_i
return 0;
}
+#if (!defined(RT_USING_SERIAL_V2))
while (size)
{
rt_size_t read_len;
rt_sem_control(client->rx_notice, RT_IPC_CMD_RESET, RT_NULL);
- read_len = rt_device_read(client->device, 0, buf + len, size);
+ read_len = rt_device_read(client->device, 0, buf + read_idx, size);
if (read_len > 0)
{
- len += read_len;
+ read_idx += read_len;
size -= read_len;
}
else
@@ -598,12 +614,19 @@ rt_size_t at_client_obj_recv(at_client_t client, char *buf, rt_size_t size, rt_i
break;
}
}
+#else
+ rt_int32_t rx_timeout = rt_tick_from_millisecond(timeout);
+ rt_device_control(client->device, RT_SERIAL_CTRL_SET_RX_TIMEOUT, (void *)&rx_timeout);
+ read_idx = rt_device_read(client->device, 0, buf, size);
+ rx_timeout = RT_WAITING_FOREVER;
+ rt_device_control(client->device, RT_SERIAL_CTRL_SET_RX_TIMEOUT, (void*)&rx_timeout);
+#endif
#ifdef AT_PRINT_RAW_CMD
- at_print_raw_cmd("urc_recv", buf, len);
+ at_print_raw_cmd("urc_recv", buf, read_idx);
#endif
- return len;
+ return read_idx;
}
/**
@@ -780,7 +803,8 @@ static int at_recv_readline(at_client_t client)
}
/* is newline or URC data */
- if ((client->urc = get_urc_obj(client)) != RT_NULL || (ch == '\n' && last_ch == '\r')
+ client->urc = get_urc_obj(client);
+ if (client->urc != RT_NULL || (ch == '\n' && last_ch == '\r')
|| (client->end_sign != 0 && ch == client->end_sign))
{
if (is_full)
@@ -877,6 +901,7 @@ static void client_parser(at_client_t client)
}
}
+#if (!defined(RT_USING_SERIAL_V2))
static rt_err_t at_client_rx_ind(rt_device_t dev, rt_size_t size)
{
int idx = 0;
@@ -891,6 +916,7 @@ static rt_err_t at_client_rx_ind(rt_device_t dev, rt_size_t size)
return RT_EOK;
}
+#endif
/* initialize the client object parameters */
static int at_client_para_init(at_client_t client)
@@ -933,6 +959,7 @@ static int at_client_para_init(at_client_t client)
goto __exit;
}
+#if (!defined(RT_USING_SERIAL_V2))
rt_snprintf(name, RT_NAME_MAX, "%s%d", AT_CLIENT_SEM_NAME, at_client_num);
client->rx_notice = rt_sem_create(name, 0, RT_IPC_FLAG_FIFO);
if (client->rx_notice == RT_NULL)
@@ -941,6 +968,7 @@ static int at_client_para_init(at_client_t client)
result = -RT_ENOMEM;
goto __exit;
}
+#endif
rt_snprintf(name, RT_NAME_MAX, "%s%d", AT_CLIENT_RESP_NAME, at_client_num);
client->resp_notice = rt_sem_create(name, 0, RT_IPC_FLAG_FIFO);
@@ -974,10 +1002,12 @@ __exit:
rt_mutex_delete(client->lock);
}
+#if (!defined(RT_USING_SERIAL_V2))
if (client->rx_notice)
{
rt_sem_delete(client->rx_notice);
}
+#endif
if (client->resp_notice)
{
@@ -1055,12 +1085,8 @@ int at_client_init(const char *dev_name, rt_size_t recv_bufsz, rt_size_t send_bu
if (client->device)
{
RT_ASSERT(client->device->type == RT_Device_Class_Char);
-
+#if (!defined(RT_USING_SERIAL_V2))
rt_device_set_rx_indicate(client->device, at_client_rx_ind);
-
-#ifdef RT_USING_SERIAL_V2
- open_result = rt_device_open(client->device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_RX_NON_BLOCKING);
-#else
/* using DMA mode first */
open_result = rt_device_open(client->device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_DMA_RX);
/* using interrupt mode when DMA mode not supported */
@@ -1068,8 +1094,11 @@ int at_client_init(const char *dev_name, rt_size_t recv_bufsz, rt_size_t send_bu
{
open_result = rt_device_open(client->device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
}
-#endif /* RT_USING_SERIAL_V2 */
RT_ASSERT(open_result == RT_EOK);
+#else
+ open_result = rt_device_open(client->device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING);
+ RT_ASSERT(open_result == RT_EOK);
+#endif
}
else
{
diff --git a/components/net/at/src/at_server.c b/components/net/at/src/at_server.c
index 7817372948..fd54923258 100644
--- a/components/net/at/src/at_server.c
+++ b/components/net/at/src/at_server.c
@@ -8,6 +8,7 @@
* 2018-03-30 chenyong first version
* 2018-04-14 chenyong modify parse arguments
* 2025-01-02 dongly support SERIAL_V2
+ * 2025-04-18 RyanCw support New SERIAL_V2
*/
#include <at.h>
@@ -223,6 +224,7 @@ rt_size_t at_server_recv(at_server_t server, char *buf, rt_size_t size, rt_int32
return 0;
}
+#if (!defined(RT_USING_SERIAL_V2))
while (1)
{
if (read_idx < size)
@@ -242,6 +244,13 @@ rt_size_t at_server_recv(at_server_t server, char *buf, rt_size_t size, rt_int32
break;
}
}
+#else
+ rt_int32_t rx_timout = rt_tick_from_millisecond(timeout);
+ rt_device_control(server->device, RT_SERIAL_CTRL_SET_RX_TIMEOUT, (void*)&rx_timout);
+ read_idx = rt_device_read(server->device, 0, buf, size);
+ rx_timeout = RT_WAITING_FOREVER;
+ rt_device_control(server->device, RT_SERIAL_CTRL_SET_RX_TIMEOUT, (void*)&rx_timeout);
+#endif
return read_idx;
}
@@ -411,15 +420,27 @@ static rt_err_t at_server_getchar(at_server_t server, char *ch, rt_int32_t timeo
{
rt_err_t result = RT_EOK;
+#if (!defined(RT_USING_SERIAL_V2))
while (rt_device_read(at_server_local->device, 0, ch, 1) == 0)
{
- rt_sem_control(at_server_local->rx_notice, RT_IPC_CMD_RESET, RT_NULL);
result = rt_sem_take(at_server_local->rx_notice, rt_tick_from_millisecond(timeout));
if (result != RT_EOK)
{
return result;
}
+ rt_sem_control(at_server_local->rx_notice, RT_IPC_CMD_RESET, RT_NULL);
+ }
+#else
+ rt_int32_t rx_timout = rt_tick_from_millisecond(timeout);
+ rt_device_control(server->device, RT_SERIAL_CTRL_SET_RX_TIMEOUT, (void*)&rx_timout);
+ result = rt_device_read(server->device, 0, ch, 1);
+ if(result <= 0)
+ {
+ result = -RT_ERROR;
}
+ rx_timeout = RT_WAITING_FOREVER;
+ rt_device_control(server->device, RT_SERIAL_CTRL_SET_RX_TIMEOUT, (void*)&rx_timeout);
+#endif
return result;
}
@@ -497,6 +518,7 @@ static void server_parser(at_server_t server)
}
}
+#if (!defined(RT_USING_SERIAL_V2))
static rt_err_t at_rx_ind(rt_device_t dev, rt_size_t size)
{
if (size > 0)
@@ -506,6 +528,7 @@ static rt_err_t at_rx_ind(rt_device_t dev, rt_size_t size)
return RT_EOK;
}
+#endif
#if defined(__ICCARM__) || defined(__ICCRX__) /* for IAR compiler */
#pragma section="RtAtCmdTab"
@@ -551,6 +574,7 @@ int at_server_init(void)
rt_memset(at_server_local->recv_buffer, 0x00, AT_SERVER_RECV_BUFF_LEN);
at_server_local->cur_recv_len = 0;
+#if (!defined(RT_USING_SERIAL_V2))
at_server_local->rx_notice = rt_sem_create("at_svr", 0, RT_IPC_FLAG_FIFO);
if (!at_server_local->rx_notice)
{
@@ -558,18 +582,15 @@ int at_server_init(void)
result = -RT_ENOMEM;
goto __exit;
}
+#endif
/* Find and open command device */
at_server_local->device = rt_device_find(AT_SERVER_DEVICE);
if (at_server_local->device)
{
RT_ASSERT(at_server_local->device->type == RT_Device_Class_Char);
-
+#if (!defined(RT_USING_SERIAL_V2))
rt_device_set_rx_indicate(at_server_local->device, at_rx_ind);
-
-#ifdef RT_USING_SERIAL_V2
- open_result = rt_device_open(client->device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_RX_NON_BLOCKING);
-#else
/* using DMA mode first */
open_result = rt_device_open(at_server_local->device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_DMA_RX);
/* using interrupt mode when DMA mode not supported */
@@ -577,8 +598,11 @@ int at_server_init(void)
{
open_result = rt_device_open(at_server_local->device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
}
-#endif /* RT_USING_SERIAL_V2 */
RT_ASSERT(open_result == RT_EOK);
+#else
+ open_result = rt_device_open(at_server_local->device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING);
+ RT_ASSERT(open_result == RT_EOK);
+#endif
}
else
{
@@ -614,10 +638,14 @@ __exit:
{
if (at_server_local)
{
+
+#if (!defined(RT_USING_SERIAL_V2))
if (at_server_local->rx_notice)
{
rt_sem_delete(at_server_local->rx_notice);
}
+#endif
+
if (at_server_local->device)
{
rt_device_close(at_server_local->device);