Skip to content

Commit 94358b5

Browse files
committed
bsp:k230:add pdma support for uart driver
Added pdma support for uart driver and a test file test_uart.c. The test uses pdma to improve uart send speed, to check if the driver works correctly. Signed-off-by: XU HU [email protected]
1 parent 3b93a78 commit 94358b5

File tree

7 files changed

+393
-38
lines changed

7 files changed

+393
-38
lines changed

bsp/k230/.config

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ CONFIG_RT_USING_DEVICE_OPS=y
192192
# CONFIG_RT_USING_THREADSAFE_PRINTF is not set
193193
CONFIG_RT_USING_CONSOLE=y
194194
CONFIG_RT_CONSOLEBUF_SIZE=256
195-
CONFIG_RT_CONSOLE_DEVICE_NAME="uart"
195+
CONFIG_RT_CONSOLE_DEVICE_NAME="uart0"
196196
CONFIG_RT_VER_NUM=0x50201
197197
CONFIG_RT_USING_STDC_ATOMIC=y
198198
CONFIG_RT_BACKTRACE_LEVEL_MAX_NR=32
@@ -1594,6 +1594,12 @@ CONFIG_PKG_ZLIB_VER="latest"
15941594
# CONFIG_BSP_USING_ADC is not set
15951595
# CONFIG_BSP_USING_TS is not set
15961596
# CONFIG_BSP_USING_PWM is not set
1597+
CONFIG_BSP_USING_UART=y
1598+
CONFIG_BSP_USING_UART0=y
1599+
# CONFIG_BSP_USING_UART1 is not set
1600+
# CONFIG_BSP_USING_UART2 is not set
1601+
# CONFIG_BSP_USING_UART3 is not set
1602+
# CONFIG_BSP_USING_UART4 is not set
15971603
CONFIG_BSP_USING_HARDLOCK=y
15981604
CONFIG_BSP_USING_SDIO=y
15991605
CONFIG_BSP_USING_SDIO0=y

bsp/k230/board/Kconfig

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,33 @@ menu "Drivers Configuration"
2525
default n
2626

2727
endif
28+
29+
menuconfig BSP_USING_UART
30+
bool "Enable UART"
31+
select RT_USING_UART
32+
default n
33+
34+
if BSP_USING_UART
35+
config BSP_USING_UART0
36+
bool "Enable UART0"
37+
default n
38+
39+
config BSP_USING_UART1
40+
bool "Enable UART1"
41+
default n
42+
43+
config BSP_USING_UART2
44+
bool "Enable UART2"
45+
default n
46+
47+
config BSP_USING_UART3
48+
bool "Enable UART3"
49+
default n
50+
51+
config BSP_USING_UART4
52+
bool "Enable UART4"
53+
default n
54+
endif
2855

2956
config BSP_USING_HARDLOCK
3057
bool "Enable Hard-Lock"

bsp/k230/drivers/interdrv/uart/drv_uart.c

Lines changed: 232 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,36 @@
99
#include <rtdevice.h>
1010
#include <lwp_user_mm.h>
1111
#include <ioremap.h>
12-
12+
#include <rtdbg.h>
1313
#include "board.h"
14+
#include "drv_pdma.h"
15+
#include <mmu.h>
1416
#include "drv_uart.h"
1517
#include "riscv_io.h"
1618

19+
typedef enum
20+
{
21+
TEST_PDMA_EVENT_NONE,
22+
TEST_PDMA_EVENT_COMPLETE,
23+
TEST_PDMA_EVENT_TIMEOUT
24+
} test_pdma_event_t;
25+
26+
static rt_event_t uart_pdma_event = RT_NULL;
27+
28+
void uart_pdma_call_back(rt_uint8_t ch, rt_bool_t is_done)
29+
{
30+
/* Send completion or timeout event based on callback status */
31+
test_pdma_event_t event_type = is_done ? TEST_PDMA_EVENT_COMPLETE : TEST_PDMA_EVENT_TIMEOUT;
32+
rt_event_send(uart_pdma_event, event_type);
33+
}
34+
1735
#define UART_DEFAULT_BAUDRATE 115200
1836
#define UART_CLK 50000000
19-
#define UART_ADDR UART0_BASE_ADDR
20-
#define UART_IRQ K230_IRQ_UART0
21-
37+
#define UART0_IRQ K230_IRQ_UART0
38+
#define UART1_IRQ K230_IRQ_UART1
39+
#define UART2_IRQ K230_IRQ_UART2
40+
#define UART3_IRQ K230_IRQ_UART3
41+
#define UART4_IRQ K230_IRQ_UART4
2242

2343
#define UART_RBR (0x00) /* receive buffer register */
2444
#define UART_THR (0x00) /* transmit holding register */
@@ -95,25 +115,81 @@ struct device_uart
95115
rt_ubase_t hw_base;
96116
void* pa_base;
97117
rt_uint32_t irqno;
118+
98119
};
99120

100121
static rt_err_t rt_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg);
101122
static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg);
102123
static int drv_uart_putc(struct rt_serial_device *serial, char c);
103124
static int drv_uart_getc(struct rt_serial_device *serial);
125+
static rt_ssize_t uart_dma_tran(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction);
104126

105-
const struct rt_uart_ops _uart_ops =
127+
const struct rt_uart_ops _uart_ops =
106128
{
107-
rt_uart_configure,
108-
uart_control,
109-
drv_uart_putc,
110-
drv_uart_getc,
111-
//TODO: add DMA support
112-
RT_NULL
129+
.configure = rt_uart_configure,
130+
.control = uart_control,
131+
.putc = drv_uart_putc,
132+
.getc = drv_uart_getc,
133+
.dma_transmit = uart_dma_tran
113134
};
114135

115-
struct rt_serial_device serial1;
116-
struct device_uart uart1;
136+
struct k230_uart_dev
137+
{
138+
struct rt_serial_device serial;
139+
struct device_uart uart;
140+
const char *name;
141+
rt_uint32_t pa_base;
142+
rt_uint32_t uart_to_size;
143+
rt_uint32_t irqno;
144+
};
145+
146+
/* 支持的 UART 设备列表 */
147+
static struct k230_uart_dev uart_devs[] =
148+
{
149+
#ifdef BSP_USING_UART0
150+
{
151+
.name = "uart0",
152+
.pa_base = UART0_BASE_ADDR,
153+
.uart_to_size = UART0_IO_SIZE,
154+
.irqno = UART0_IRQ,
155+
},
156+
#endif
157+
#ifdef BSP_USING_UART1
158+
{
159+
.name = "uart1",
160+
.pa_base = UART1_BASE_ADDR,
161+
.uart_to_size = UART1_IO_SIZE,
162+
.irqno = UART1_IRQ,
163+
},
164+
#endif
165+
#ifdef BSP_USING_UART2
166+
{
167+
.name = "uart2",
168+
.pa_base = UART2_BASE_ADDR,
169+
.uart_to_size = UART2_IO_SIZE,
170+
.irqno = UART2_IRQ,
171+
},
172+
#endif
173+
#ifdef BSP_USING_UART3
174+
{
175+
.name = "uart3",
176+
.pa_base = UART3_BASE_ADDR,
177+
.uart_to_size = UART3_IO_SIZE,
178+
.irqno = UART3_IRQ,
179+
},
180+
#endif
181+
#ifdef BSP_USING_UART4
182+
{
183+
.name = "uart4",
184+
.pa_base = UART4_BASE_ADDR,
185+
.uart_to_size = UART4_IO_SIZE,
186+
.irqno = UART4_IRQ,
187+
},
188+
#endif
189+
#if !defined(BSP_USING_UART0) && !defined(BSP_USING_UART1) && !defined(BSP_USING_UART2) && !defined(BSP_USING_UART3) && !defined(BSP_USING_UART4)
190+
#error "No UART device defined!"
191+
#endif
192+
};
117193

118194
#define write32(addr, val) writel(val, (void*)(addr))
119195
#define read32(addr) readl((void*)(addr))
@@ -150,7 +226,8 @@ static void _uart_init(void *uart_base)
150226
write32(uart_base + UART_IER, 0x00);
151227
/* Enable DLAB */
152228
write32(uart_base + UART_LCR, 0x80);
153-
if (bdiv) {
229+
if (bdiv)
230+
{
154231
/* Set divisor low byte */
155232
write32(uart_base + UART_DLL, dll);
156233
/* Set divisor high byte */
@@ -301,6 +378,109 @@ static int drv_uart_getc(struct rt_serial_device *serial)
301378
return (int)*rbr;
302379
}
303380

381+
static rt_ssize_t uart_dma_write(struct rt_serial_device *serial, const void *buffer, rt_size_t size)
382+
{
383+
rt_uint8_t ch;
384+
rt_err_t err;
385+
rt_uint32_t recv_event;
386+
387+
struct k230_uart_dev *uart_dev = rt_container_of(serial, struct k230_uart_dev, serial);
388+
uint32_t len = RT_ALIGN(size, 64);
389+
uint8_t *buf = rt_malloc_align(len, 64);
390+
rt_memcpy(buf, buffer, size);
391+
rt_hw_cpu_dcache_clean((void*)buf, len);
392+
void *buf_pa = rt_kmem_v2p(buf);
393+
rt_event_control(uart_pdma_event, RT_IPC_CMD_RESET, NULL);
394+
395+
/* Configure DMA transfer */
396+
err = k230_pdma_request_channel(&ch);
397+
398+
usr_pdma_cfg_t pdma_cfg;
399+
/* Configure DMA parameters */
400+
if (!strcmp(uart_dev->name, "uart0"))
401+
{
402+
pdma_cfg.device = UART0_TX;
403+
}
404+
else if (!strcmp(uart_dev->name, "uart1"))
405+
{
406+
pdma_cfg.device = UART1_TX;
407+
}
408+
else if (!strcmp(uart_dev->name, "uart2"))
409+
{
410+
pdma_cfg.device = UART2_TX;
411+
}
412+
else if (!strcmp(uart_dev->name, "uart3"))
413+
{
414+
pdma_cfg.device = UART3_TX;
415+
}
416+
else if (!strcmp(uart_dev->name, "uart4"))
417+
{
418+
pdma_cfg.device = UART4_TX;
419+
}
420+
421+
pdma_cfg.src_addr = buf_pa;
422+
pdma_cfg.dst_addr = (rt_uint8_t *)uart_dev->pa_base;
423+
pdma_cfg.line_size = len;
424+
425+
/* Set channel configuration */
426+
pdma_cfg.pdma_ch_cfg.ch_src_type = CONTINUE;
427+
pdma_cfg.pdma_ch_cfg.ch_dev_hsize = PSBYTE1;
428+
pdma_cfg.pdma_ch_cfg.ch_dat_endian = PDEFAULT;
429+
pdma_cfg.pdma_ch_cfg.ch_dev_blen = PBURST_LEN_16;
430+
pdma_cfg.pdma_ch_cfg.ch_priority = 7;
431+
pdma_cfg.pdma_ch_cfg.ch_dev_tout = 0xFFF;
432+
433+
err = k230_pdma_set_callback(ch, uart_pdma_call_back);
434+
if(err != RT_EOK)
435+
{
436+
LOG_E("pdma_set_callback failed, err=%d\n", err);
437+
}
438+
err = k230_pdma_config(ch, &pdma_cfg);
439+
if(err != RT_EOK)
440+
{
441+
LOG_E("pdma_config failed, err=%d\n", err);
442+
}
443+
/* Start transfer and wait for completion */
444+
err = k230_pdma_start(ch);
445+
if(err != RT_EOK)
446+
{
447+
LOG_E("pdma_start failed, err=%d\n", err);
448+
}
449+
err = rt_event_recv(uart_pdma_event,
450+
TEST_PDMA_EVENT_COMPLETE | TEST_PDMA_EVENT_TIMEOUT,
451+
RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
452+
RT_WAITING_FOREVER,
453+
&recv_event);
454+
/* Cleanup */
455+
if(err != RT_EOK)
456+
{
457+
LOG_E("event_recv failed, err=%d\n", err);
458+
}
459+
err = k230_pdma_stop(ch);
460+
if(err != RT_EOK)
461+
{
462+
LOG_E("pdma_stop failed, err=%d\n", err);
463+
}
464+
err = k230_pdma_release_channel(ch);
465+
if(err != RT_EOK)
466+
{
467+
LOG_E("pdma_release_channel failed, err=%d\n", err);
468+
}
469+
rt_free_align(buf);
470+
return size;
471+
}
472+
473+
static rt_ssize_t uart_dma_tran(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction)
474+
{
475+
rt_ssize_t len;
476+
if (RT_SERIAL_DMA_TX == direction)
477+
{
478+
len = uart_dma_write(serial, (void*)buf, size);
479+
}
480+
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_TX_DMADONE);
481+
return len;
482+
}
483+
304484
static void rt_hw_uart_isr(int irq, void *param)
305485
{
306486
struct rt_serial_device *serial = (struct rt_serial_device*)param;
@@ -331,7 +511,7 @@ static void rt_hw_uart_isr(int irq, void *param)
331511
}
332512
#ifdef RT_USING_SERIAL_V2
333513
uint8_t data;
334-
514+
335515
do {
336516
data = readb((void*)(uart_base + UART_RBR));
337517
rt_ringbuffer_putchar(&(rx_fifo->rb), data);
@@ -354,32 +534,49 @@ static void rt_hw_uart_isr(int irq, void *param)
354534
*/
355535
int rt_hw_uart_init(void)
356536
{
357-
struct rt_serial_device *serial;
358-
struct device_uart *uart;
359537
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
538+
rt_err_t ret;
360539

540+
uart_pdma_event = (rt_event_t)rt_malloc(sizeof(struct rt_event));
541+
if (uart_pdma_event == RT_NULL)
361542
{
362-
serial = &serial1;
363-
uart = &uart1;
543+
LOG_E("Failed to allocate memory for pdma_event!");
544+
return -RT_ENOMEM;
545+
}
364546

365-
serial->ops = &_uart_ops;
366-
serial->config = config;
367-
serial->config.baud_rate = UART_DEFAULT_BAUDRATE;
547+
if (rt_event_init(uart_pdma_event, "pdma_event", RT_IPC_FLAG_FIFO) != RT_EOK)
548+
{
549+
LOG_E("Failed to init pdma_event!");
550+
rt_free(uart_pdma_event);
551+
return -RT_ERROR;
552+
}
368553

369-
uart->pa_base = (void *)UART_ADDR;
370-
uart->hw_base = (rt_base_t)rt_ioremap(uart->pa_base, 0x1000);
371-
uart->irqno = UART_IRQ;
554+
for (int i = 0; i < sizeof(uart_devs)/sizeof(uart_devs[0]); i++)
555+
{
556+
struct k230_uart_dev *dev = &uart_devs[i];
372557

373-
_uart_init((void*)(uart->hw_base));
558+
dev->serial.ops = &_uart_ops;
559+
dev->serial.config = config;
560+
dev->serial.config.baud_rate = UART_DEFAULT_BAUDRATE;
374561

375-
rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, serial, "uart1");
376-
rt_hw_interrupt_umask(uart->irqno);
562+
dev->uart.pa_base = (void *)dev->pa_base;
563+
dev->uart.hw_base = (rt_base_t)rt_ioremap(dev->uart.pa_base, dev->uart_to_size);
564+
dev->uart.irqno = dev->irqno;
377565

378-
rt_hw_serial_register(serial,
379-
RT_CONSOLE_DEVICE_NAME,
380-
RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
381-
uart);
382-
}
566+
_uart_init((void*)(dev->uart.hw_base));
383567

384-
return 0;
385-
}
568+
rt_hw_interrupt_install(dev->uart.irqno, rt_hw_uart_isr, &dev->serial, dev->name);
569+
rt_hw_interrupt_umask(dev->uart.irqno);
570+
571+
ret = rt_hw_serial_register(&dev->serial,
572+
dev->name,
573+
RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_DMA_TX,
574+
&dev->uart);
575+
if (ret != RT_EOK)
576+
{
577+
LOG_E("Failed to register %s, ret=%d\n", dev->name, ret);
578+
return ret;
579+
}
580+
}
581+
return RT_EOK;
582+
}

bsp/k230/drivers/utest/SConscript

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ if GetDepend('RT_UTEST_USING_ALL_CASES') or GetDepend('BSP_UTEST_DRIVERS'):
2424
if GetDepend('BSP_USING_TS'):
2525
src += ['test_ts.c']
2626

27+
if GetDepend('BSP_USING_UART'):
28+
src += ['test_uart.c']
29+
2730
group = DefineGroup('utestcases', src, depend = [''])
2831

2932
Return('group')

0 commit comments

Comments
 (0)