1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2013-05-18 Bernard The first version for LPC40xx
9 * 2014-07-18 ArdaFu Port to TM4C129X
10 */
11
12 #include <rthw.h>
13 #include <rtthread.h>
14 #include <rtdevice.h>
15
16 #include "board.h"
17
18 #include "inc/hw_memmap.h"
19 #include "driverlib/sysctl.h"
20 #include "driverlib/gpio.h"
21 #include "driverlib/uart.h"
22 #include "driverlib/pin_map.h"
23 #include "driverlib/interrupt.h"
24 #include "driverlib/rom_map.h"
25 typedef struct hw_uart_device
26 {
27 uint32_t hw_base; // base address
28 }hw_uart_t;
29
30 #define mUartGetHwPtr(serial) ((hw_uart_t*)(serial->parent.user_data))
31
hw_configure(struct rt_serial_device * serial,struct serial_configure * cfg)32 static rt_err_t hw_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
33 {
34 uint32_t config = 0;
35 hw_uart_t* uart;
36 RT_ASSERT(serial != RT_NULL);
37 uart = mUartGetHwPtr(serial);
38
39 MAP_UARTDisable(uart->hw_base);
40 // build UART Configuration parameter structure
41 switch(cfg->data_bits)
42 {
43 case DATA_BITS_9:
44 // enable 9bit address mode and set DATA_BIT_8
45 MAP_UART9BitEnable(uart->hw_base);
46 case DATA_BITS_8:
47 config |= UART_CONFIG_WLEN_8;
48 break;
49 case DATA_BITS_7:
50 config |= UART_CONFIG_WLEN_7;
51 break;
52 case DATA_BITS_6:
53 config |= UART_CONFIG_WLEN_6;
54 break;
55 case DATA_BITS_5:
56 config |= UART_CONFIG_WLEN_5;
57 break;
58 default:
59 RT_ASSERT(0);
60 break;
61 }
62 switch(cfg->parity)
63 {
64 case PARITY_ODD:
65 config |= UART_CONFIG_PAR_ODD;
66 break;
67 case PARITY_EVEN:
68 config |= UART_CONFIG_PAR_EVEN;
69 break;
70 case PARITY_NONE:
71 config |= UART_CONFIG_PAR_NONE;
72 break;
73 default:
74 RT_ASSERT(0);
75 break;
76 }
77 switch(cfg->stop_bits)
78 {
79 case STOP_BITS_1:
80 config |= UART_CONFIG_STOP_ONE;
81 break;
82 case STOP_BITS_2:
83 config |= UART_CONFIG_STOP_TWO;
84 break;
85 default:
86 RT_ASSERT(0);
87 break;
88 }
89
90 // Initialize UART0 peripheral with given to corresponding parameter
91 MAP_UARTConfigSetExpClk(uart->hw_base, SystemCoreClock, cfg->baud_rate, config);
92 MAP_UARTFIFOEnable(uart->hw_base);
93
94 // Enable the UART.
95 MAP_UARTEnable(uart->hw_base);
96 return RT_EOK;
97 }
98
hw_control(struct rt_serial_device * serial,int cmd,void * arg)99 static rt_err_t hw_control(struct rt_serial_device *serial, int cmd, void *arg)
100 {
101 hw_uart_t* uart;
102 RT_ASSERT(serial != RT_NULL);
103 uart = mUartGetHwPtr(serial);
104
105 switch (cmd)
106 {
107 case RT_DEVICE_CTRL_CLR_INT:
108 /* disable rx irq */
109 MAP_UARTIntDisable(uart->hw_base, UART_INT_RX | UART_INT_RT);
110 break;
111 case RT_DEVICE_CTRL_SET_INT:
112 /* enable rx irq */
113 MAP_UARTIntEnable(uart->hw_base, UART_INT_RX | UART_INT_RT);
114 break;
115 }
116
117 return RT_EOK;
118 }
119
hw_putc(struct rt_serial_device * serial,char c)120 static int hw_putc(struct rt_serial_device *serial, char c)
121 {
122 hw_uart_t* uart;
123 RT_ASSERT(serial != RT_NULL);
124 uart = mUartGetHwPtr(serial);
125
126 MAP_UARTCharPut(uart->hw_base, *((uint8_t *)&c));
127 return 1;
128 }
129
hw_getc(struct rt_serial_device * serial)130 static int hw_getc(struct rt_serial_device *serial)
131 {
132 hw_uart_t* uart;
133 RT_ASSERT(serial != RT_NULL);
134 uart = mUartGetHwPtr(serial);
135
136 return MAP_UARTCharGetNonBlocking(uart->hw_base);
137 }
138
139 static const struct rt_uart_ops hw_uart_ops =
140 {
141 hw_configure,
142 hw_control,
143 hw_putc,
144 hw_getc,
145 };
146
147 #if defined(RT_USING_UART0)
148 /* UART0 device driver structure */
149 struct rt_serial_device serial0;
150 hw_uart_t uart0 =
151 {
152 UART0_BASE,
153 };
154
UART0_IRQHandler(void)155 void UART0_IRQHandler(void)
156 {
157 uint32_t intsrc;
158 hw_uart_t *uart = &uart0;
159
160 /* enter interrupt */
161 rt_interrupt_enter();
162
163 /* Determine the interrupt source */
164 intsrc = MAP_UARTIntStatus(uart->hw_base, true);
165
166 // Receive Data Available or Character time-out
167 if (intsrc & (UART_INT_RX | UART_INT_RT))
168 {
169 MAP_UARTIntClear(uart->hw_base, intsrc);
170 rt_hw_serial_isr(&serial0, RT_SERIAL_EVENT_RX_IND);
171 }
172
173 /* leave interrupt */
174 rt_interrupt_leave();
175 }
176 #endif
177
rt_hw_uart_init(void)178 int rt_hw_uart_init(void)
179 {
180 hw_uart_t* uart;
181 struct serial_configure config;
182
183 config.baud_rate = BAUD_RATE_115200;
184 config.bit_order = BIT_ORDER_LSB;
185 config.data_bits = DATA_BITS_8;
186 config.parity = PARITY_NONE;
187 config.stop_bits = STOP_BITS_1;
188 config.invert = NRZ_NORMAL;
189 config.bufsz = RT_SERIAL_RB_BUFSZ;
190
191 #ifdef RT_USING_UART0
192 uart = &uart0;
193 serial0.ops = &hw_uart_ops;
194 serial0.config = config;
195
196 MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
197 MAP_GPIOPinConfigure(GPIO_PA0_U0RX);
198 MAP_GPIOPinConfigure(GPIO_PA1_U0TX);
199
200 MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
201 MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
202
203 /* preemption = 1, sub-priority = 1 */
204 //IntPrioritySet(INT_UART0, ((0x01 << 5) | 0x01));
205
206 /* Enable Interrupt for UART channel */
207 UARTIntRegister(uart->hw_base, UART0_IRQHandler);
208 MAP_IntEnable(INT_UART0);
209 MAP_UARTEnable(uart->hw_base);
210
211 /* register UART0 device */
212 rt_hw_serial_register(&serial0, "uart0",
213 RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
214 uart);
215 #endif
216 return 0;
217 }
218 INIT_BOARD_EXPORT(rt_hw_uart_init);
219