Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[serial_v2] support half duplex. #9480

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 42 additions & 32 deletions components/drivers/include/drivers/dev_serial_v2.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,52 +12,53 @@
#define __DEV_SERIAL_V2_H__

#include <rtthread.h>
#include <drivers/dev_pin.h>


/**
* @addtogroup Drivers RTTHREAD Driver
* @defgroup Serial_v2 Serial v2
*
* @brief Serial v2 driver api
*
*
* <b>Example</b>
* @code {.c}
*
*
* #include <rtthread.h>
* #include <rtdevice.h>
*
* #define SAMPLE_UART_NAME "uart1"
*
*
* #define SAMPLE_UART_NAME "uart1"
*
* struct rx_msg
* {
* rt_device_t dev;
* rt_size_t size;
* };
* static rt_device_t serial;
* static struct rt_messagequeue rx_mq;
*
*
* static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
* {
* struct rx_msg msg;
* rt_err_t result;
* msg.dev = dev;
* msg.size = size;
*
*
* result = rt_mq_send(&rx_mq, &msg, sizeof(msg));
* if (result == -RT_EFULL)
* {
* rt_kprintf("message queue full!\n");
* }
* return result;
* }
*
*
* static void serial_thread_entry(void *parameter)
* {
* struct rx_msg msg;
* rt_err_t result;
* rt_uint32_t rx_length;
* static char rx_buffer[BSP_UART1_RX_BUFSIZE + 1];
*
*
* while (1)
* {
* rt_memset(&msg, 0, sizeof(msg));
Expand All @@ -71,14 +72,14 @@
* }
* }
* }
*
*
* static int uart_dma_sample(int argc, char *argv[])
* {
* rt_err_t ret = RT_EOK;
* char uart_name[RT_NAME_MAX];
* static char msg_pool[256];
* char str[] = "hello RT-Thread!\r\n";
*
*
* if (argc == 2)
* {
* rt_strncpy(uart_name, argv[1], RT_NAME_MAX);
Expand All @@ -87,39 +88,39 @@
* {
* rt_strncpy(uart_name, SAMPLE_UART_NAME, RT_NAME_MAX);
* }
*
*
* serial = rt_device_find(uart_name);
* if (!serial)
* {
* rt_kprintf("find %s failed!\n", uart_name);
* return RT_ERROR;
* return -RT_ERROR;
* }
*
*
* rt_mq_init(&rx_mq, "rx_mq",
* msg_pool,
* sizeof(struct rx_msg),
* sizeof(msg_pool),
* RT_IPC_FLAG_FIFO);
*
* msg_pool,
* sizeof(struct rx_msg),
* sizeof(msg_pool),
* RT_IPC_FLAG_FIFO);
*
* rt_device_open(serial, RT_DEVICE_FLAG_RX_NON_BLOCKING | RT_DEVICE_FLAG_TX_BLOCKING);
* rt_device_set_rx_indicate(serial, uart_input);
* rt_device_write(serial, 0, str, (sizeof(str) - 1));
*
*
* rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10);
* if (thread != RT_NULL)
* {
* rt_thread_startup(thread);
* }
* else
* {
* ret = RT_ERROR;
* ret = -RT_ERROR;
* }
*
*
* return ret;
* }
* MSH_CMD_EXPORT(uart_dma_sample, uart device dma sample);
* @endcode
*
*
* @ingroup Drivers
*/

Expand Down Expand Up @@ -204,6 +205,10 @@
#define RT_SERIAL_FLOWCONTROL_CTSRTS 1
#define RT_SERIAL_FLOWCONTROL_NONE 0

#define RT_SERIAL_FULL_DUPLEX 0
#define RT_SERIAL_HALF_DUPLEX_TX_HIGH 1
#define RT_SERIAL_HALF_DUPLEX_TX_LOW 2

/* Default config for serial_configure structure */
#define RT_SERIAL_CONFIG_DEFAULT \
{ \
Expand All @@ -216,12 +221,14 @@
RT_SERIAL_RX_MINBUFSZ, /* rxBuf size */ \
RT_SERIAL_TX_MINBUFSZ, /* txBuf size */ \
RT_SERIAL_FLOWCONTROL_NONE, /* Off flowcontrol */ \
0 \
RT_SERIAL_FULL_DUPLEX, /* Full duplex */ \
0, \
PIN_NONE, \
}

/**
* @brief Serial receive indicate hook function type
*
*
*/
typedef void (*rt_hw_serial_rxind_hookproto_t)(rt_device_t dev, rt_size_t size);
RT_OBJECT_HOOKLIST_DECLARE(rt_hw_serial_rxind_hookproto_t, rt_hw_serial_rxind);
Expand All @@ -238,7 +245,10 @@ struct serial_configure
rt_uint32_t rx_bufsz :16;
rt_uint32_t tx_bufsz :16;
rt_uint32_t flowcontrol :1;
rt_uint32_t reserved :5;
rt_uint32_t duplex :2;
rt_uint32_t reserved :3;

rt_base_t duplex_pin;
};

/**
Expand All @@ -258,7 +268,7 @@ struct rt_serial_rx_fifo

/**
* @brief Serial Transmit FIFO mode
*
*
*/
struct rt_serial_tx_fifo
{
Expand All @@ -276,7 +286,7 @@ struct rt_serial_tx_fifo

/**
* @brief serial device structure
*
*
*/
struct rt_serial_device
{
Expand All @@ -293,7 +303,7 @@ struct rt_serial_device

/**
* @brief uart device operations
*
*
*/
struct rt_uart_ops
{
Expand Down Expand Up @@ -324,7 +334,7 @@ void rt_hw_serial_isr(struct rt_serial_device *serial, int event);

/**
* @brief Register a serial device to device list
*
*
* @param serial serial device
* @param name device name
* @param flag device flag
Expand All @@ -341,10 +351,10 @@ rt_err_t rt_hw_serial_register(struct rt_serial_device *serial,

/**
* @brief register a serial device to system device list and add a device object to system object list
*
*
* @param serial serial device
* @return rt_err_t error code
*
*
* @ingroup Serial_v2
*/
rt_err_t rt_hw_serial_register_tty(struct rt_serial_device *serial);
Expand Down
61 changes: 61 additions & 0 deletions components/drivers/serial/dev_serial_v2.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,33 @@ static rt_ssize_t rt_serial_update_write_index(struct rt_ringbuffer *rb,
return write_size;
}

#ifdef RT_SERIAL_USING_HALF_DUPLEX
static void _serial_half_duplex_tx_on(struct rt_serial_device *serial)
{
RT_ASSERT(serial != RT_NULL);

if (serial->config.duplex_pin != PIN_NONE)
{
if (serial->config.duplex == RT_SERIAL_HALF_DUPLEX_TX_HIGH)
rt_pin_write(serial->config.duplex_pin, PIN_HIGH);
else
rt_pin_write(serial->config.duplex_pin, PIN_LOW);
}
}

static void _serial_half_duplex_tx_off(struct rt_serial_device *serial)
{
RT_ASSERT(serial != RT_NULL);

if (serial->config.duplex_pin != PIN_NONE)
{
if (serial->config.duplex == RT_SERIAL_HALF_DUPLEX_TX_HIGH)
rt_pin_write(serial->config.duplex_pin, PIN_LOW);
else
rt_pin_write(serial->config.duplex_pin, PIN_HIGH);
}
}
#endif

/**
* @brief Serial polling receive data routine, This function will receive data
Expand Down Expand Up @@ -368,6 +395,9 @@ rt_ssize_t _serial_poll_tx(struct rt_device *dev,
putc_buffer = (rt_uint8_t *)buffer;
putc_size = size;

#ifdef RT_SERIAL_USING_HALF_DUPLEX
_serial_half_duplex_tx_on(serial);
#endif
while (size)
{
if (serial->parent.open_flag & RT_DEVICE_FLAG_STREAM)
Expand All @@ -382,6 +412,9 @@ rt_ssize_t _serial_poll_tx(struct rt_device *dev,
++ putc_buffer;
-- size;
}
#ifdef RT_SERIAL_USING_HALF_DUPLEX
_serial_half_duplex_tx_off(serial);
#endif

return putc_size - size;
}
Expand Down Expand Up @@ -485,13 +518,19 @@ static rt_ssize_t _serial_fifo_tx_blocking_nbuf(struct rt_device *dev,
if (tx_fifo->activated == RT_TRUE) return 0;

tx_fifo->activated = RT_TRUE;
#ifdef RT_SERIAL_USING_HALF_DUPLEX
_serial_half_duplex_tx_on(serial);
#endif
/* Call the transmit interface for transmission */
rst = serial->ops->transmit(serial,
(rt_uint8_t *)buffer,
size,
RT_SERIAL_TX_BLOCKING);
/* Waiting for the transmission to complete */
rt_completion_wait(&(tx_fifo->tx_cpt), RT_WAITING_FOREVER);
#ifdef RT_SERIAL_USING_HALF_DUPLEX
_serial_half_duplex_tx_off(serial);
#endif
/* Inactive tx mode flag */
tx_fifo->activated = RT_FALSE;
return rst;
Expand Down Expand Up @@ -535,6 +574,9 @@ static rt_ssize_t _serial_fifo_tx_blocking_buf(struct rt_device *dev,
if (tx_fifo->activated == RT_TRUE) return 0;
tx_fifo->activated = RT_TRUE;

#ifdef RT_SERIAL_USING_HALF_DUPLEX
_serial_half_duplex_tx_on(serial);
#endif
while (size)
{
/* Copy one piece of data into the ringbuffer at a time
Expand All @@ -554,6 +596,9 @@ static rt_ssize_t _serial_fifo_tx_blocking_buf(struct rt_device *dev,
/* Waiting for the transmission to complete */
rt_completion_wait(&(tx_fifo->tx_cpt), RT_WAITING_FOREVER);
}
#ifdef RT_SERIAL_USING_HALF_DUPLEX
_serial_half_duplex_tx_off(serial);
#endif
/* Finally Inactivate the tx->fifo */
tx_fifo->activated = RT_FALSE;

Expand Down Expand Up @@ -601,6 +646,9 @@ static rt_ssize_t _serial_fifo_tx_nonblocking(struct rt_device *dev,
rt_uint8_t *put_ptr = RT_NULL;
/* Get the linear length buffer from rinbuffer */
tx_fifo->put_size = rt_serial_get_linear_buffer(&(tx_fifo->rb), &put_ptr);
#ifdef RT_SERIAL_USING_HALF_DUPLEX
_serial_half_duplex_tx_on(serial);
#endif
/* Call the transmit interface for transmission */
serial->ops->transmit(serial,
put_ptr,
Expand Down Expand Up @@ -1158,6 +1206,13 @@ static rt_err_t rt_serial_control(struct rt_device *dev,
/* set serial configure */
serial->config = *pconfig;
serial->ops->configure(serial, (struct serial_configure *) args);
if (serial->config.duplex_pin != PIN_NONE)
{
rt_pin_mode(serial->config.duplex_pin, PIN_MODE_OUTPUT);
}
#ifdef RT_SERIAL_USING_HALF_DUPLEX
_serial_half_duplex_tx_off(serial);
#endif
}
break;
case RT_DEVICE_CTRL_NOTIFY_SET:
Expand Down Expand Up @@ -1632,6 +1687,12 @@ void rt_hw_serial_isr(struct rt_serial_device *serial, int event)
tx_fifo->put_size,
RT_SERIAL_TX_NON_BLOCKING);
}
else
{
#ifdef RT_SERIAL_USING_HALF_DUPLEX
_serial_half_duplex_tx_off(serial);
#endif
}

break;
}
Expand Down
Loading