mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-11-09 20:45:41 +08:00
add serial DMA transmit function(beta)
git-svn-id: https://rt-thread.googlecode.com/svn/trunk@2382 bbd45198-f89e-11dd-88c7-29a3b14d5316
This commit is contained in:
1 parent
6773015c4a
commit
db58e3350b
4 files changed
+281
-196
No files matched your search
@@ -57,18 +57,21 @@
|
||||
#define RT_SERIAL_ERR_OVERRUN 0x01
|
||||
#define RT_SERIAL_ERR_FRAMING 0x02
|
||||
#define RT_SERIAL_ERR_PARITY 0x03
|
||||
|
||||
#define RT_SERIAL_TX_DATAQUEUE_SIZE 40
|
||||
#define RT_SERIAL_TX_DATAQUEUE_LWM 30
|
||||
|
||||
/* Default config for serial_configure structure */
|
||||
#define RT_SERIAL_CONFIG_DEFAULT \
|
||||
{ \
|
||||
BAUD_RATE_115200, /* 115200 bits/s */ \
|
||||
DATA_BITS_8, /* 8 databits */ \
|
||||
STOP_BITS_1, /* 1 stopbit */ \
|
||||
PARITY_NONE, /* No parity */ \
|
||||
BIT_ORDER_LSB, /* LSB first sent */ \
|
||||
NRZ_NORMAL, /* Normal mode */ \
|
||||
0 \
|
||||
}
|
||||
STOP_BITS_1, /* 1 stopbit */ \
|
||||
PARITY_NONE, /* No parity */ \
|
||||
BIT_ORDER_LSB, /* LSB first sent */ \
|
||||
NRZ_NORMAL, /* Normal mode */ \
|
||||
0 \
|
||||
}
|
||||
|
||||
struct serial_ringbuffer
|
||||
{
|
||||
@@ -98,6 +101,10 @@ struct rt_serial_device
|
||||
struct serial_ringbuffer *int_rx;
|
||||
/* tx structure */
|
||||
struct serial_ringbuffer *int_tx;
|
||||
|
||||
struct rt_data_queue tx_dq; /* tx dataqueue */
|
||||
|
||||
volatile rt_bool_t dma_flag; /* dma transfer flag */
|
||||
};
|
||||
typedef struct rt_serial_device rt_serial_t;
|
||||
|
||||
@@ -111,9 +118,12 @@ struct rt_uart_ops
|
||||
|
||||
int (*putc)(struct rt_serial_device *serial, char c);
|
||||
int (*getc)(struct rt_serial_device *serial);
|
||||
|
||||
rt_size_t (*dma_transmit)(struct rt_serial_device *serial, const char *buf, rt_size_t size);
|
||||
};
|
||||
|
||||
void rt_hw_serial_isr(struct rt_serial_device *serial);
|
||||
void rt_hw_serial_dma_tx_isr(struct rt_serial_device *serial);
|
||||
rt_err_t rt_hw_serial_register(struct rt_serial_device *serial,
|
||||
const char *name,
|
||||
rt_uint32_t flag,
|
||||
|
||||
@@ -125,15 +125,15 @@ rt_err_t rt_data_queue_init(struct rt_data_queue *queue,
|
||||
rt_uint16_t lwm,
|
||||
void (*evt_notify)(struct rt_data_queue *queue, rt_uint32_t event));
|
||||
rt_err_t rt_data_queue_push(struct rt_data_queue *queue,
|
||||
void *data_ptr,
|
||||
const void *data_ptr,
|
||||
rt_size_t data_size,
|
||||
rt_int32_t timeout);
|
||||
rt_err_t rt_data_queue_pop(struct rt_data_queue *queue,
|
||||
void **data_ptr,
|
||||
const void **data_ptr,
|
||||
rt_size_t *size,
|
||||
rt_int32_t timeout);
|
||||
rt_err_t rt_data_queue_peak(struct rt_data_queue *queue,
|
||||
void **data_ptr,
|
||||
const void **data_ptr,
|
||||
rt_size_t *size);
|
||||
void rt_data_queue_reset(struct rt_data_queue *queue);
|
||||
|
||||
|
||||
@@ -132,7 +132,16 @@ static rt_err_t rt_serial_init(struct rt_device *dev)
|
||||
serial_ringbuffer_init(serial->int_rx);
|
||||
|
||||
if (dev->flag & RT_DEVICE_FLAG_INT_TX)
|
||||
serial_ringbuffer_init(serial->int_tx);
|
||||
serial_ringbuffer_init(serial->int_tx);
|
||||
|
||||
if (dev->flag & RT_DEVICE_FLAG_DMA_TX)
|
||||
{
|
||||
serial->dma_flag = RT_FALSE;
|
||||
|
||||
/* init data queue */
|
||||
rt_data_queue_init(&(serial->tx_dq), RT_SERIAL_TX_DATAQUEUE_SIZE,
|
||||
RT_SERIAL_TX_DATAQUEUE_LWM, RT_NULL);
|
||||
}
|
||||
|
||||
/* set activated */
|
||||
dev->flag |= RT_DEVICE_FLAG_ACTIVATED;
|
||||
@@ -261,6 +270,41 @@ static rt_size_t rt_serial_write(struct rt_device *dev,
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (dev->flag & RT_DEVICE_FLAG_DMA_TX)
|
||||
{
|
||||
const void *data_ptr = RT_NULL;
|
||||
rt_size_t data_size = 0;
|
||||
rt_base_t level;
|
||||
rt_err_t result;
|
||||
|
||||
RT_ASSERT(0 == (dev->flag & RT_DEVICE_FLAG_STREAM));
|
||||
|
||||
result = rt_data_queue_push(&(serial->tx_dq), buffer, size, 20);
|
||||
if (result == RT_EOK)
|
||||
{
|
||||
level = rt_hw_interrupt_disable();
|
||||
if (serial->dma_flag == RT_FALSE)
|
||||
{
|
||||
serial->dma_flag = RT_TRUE;
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
||||
if (RT_EOK == rt_data_queue_pop(&(serial->tx_dq), &data_ptr, &data_size, 0))
|
||||
{
|
||||
serial->ops->dma_transmit(serial, data_ptr, data_size);
|
||||
}
|
||||
}
|
||||
else
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
||||
return size;
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_set_errno(result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* polling mode */
|
||||
@@ -377,3 +421,22 @@ void rt_hw_serial_isr(struct rt_serial_device *serial)
|
||||
serial->parent.rx_indicate(&serial->parent, rx_length);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ISR for DMA mode Tx
|
||||
*/
|
||||
void rt_hw_serial_dma_tx_isr(struct rt_serial_device *serial)
|
||||
{
|
||||
void *data_ptr;
|
||||
rt_size_t data_size;
|
||||
|
||||
if (RT_EOK == rt_data_queue_pop(&(serial->tx_dq), &data_ptr, &data_size, 0))
|
||||
{
|
||||
/* transmit next data node */
|
||||
serial->ops->dma_transmit(serial, data_ptr, data_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
serial->dma_flag = RT_FALSE;
|
||||
}
|
||||
}
|
||||
+198
-186
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user