1 /*
2 * Copyright (c) 2006-2024 RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2022-06-29 Rbb666 first version
9 * 2025-04-21 hydevcode modify xmc7100d uart
10 * 2025-05-12 Passionate0424 update ifx_control
11 */
12
13 #include <rtthread.h>
14 #include "drv_uart.h"
15
16 #include "uart_config.h"
17 #include "cyhal_scb_common.h"
18
19 enum
20 {
21 #ifdef BSP_USING_UART0
22 UART0_INDEX,
23 #endif
24 #ifdef BSP_USING_UART1
25 UART1_INDEX,
26 #endif
27 #ifdef BSP_USING_UART2
28 UART2_INDEX,
29 #endif
30 #ifdef BSP_USING_UART3
31 UART3_INDEX,
32 #endif
33 #ifdef BSP_USING_UART4
34 UART4_INDEX,
35 #endif
36 #ifdef BSP_USING_UART5
37 UART5_INDEX,
38 #endif
39 #ifdef BSP_USING_UART6
40 UART6_INDEX,
41 #endif
42 };
43
44 static struct ifx_uart_config uart_config[] =
45 {
46 #ifdef BSP_USING_UART0
47 UART0_CONFIG,
48 #endif
49 #ifdef BSP_USING_UART1
50 UART1_CONFIG,
51 #endif
52 #ifdef BSP_USING_UART2
53 UART2_CONFIG,
54 #endif
55 #ifdef BSP_USING_UART3
56 UART3_CONFIG,
57 #endif
58 #ifdef BSP_USING_UART4
59 UART4_CONFIG,
60 #endif
61 #ifdef BSP_USING_UART5
62 UART5_CONFIG,
63 #endif
64 #ifdef BSP_USING_UART6
65 UART6_CONFIG,
66 #endif
67 };
68
69 static struct ifx_uart uart_obj[sizeof(uart_config) / sizeof(uart_config[0])] =
70 {0};
71
uart_isr(struct rt_serial_device * serial)72 static void uart_isr(struct rt_serial_device *serial)
73 {
74 RT_ASSERT(serial != RT_NULL);
75 struct ifx_uart *uart = (struct ifx_uart *) serial->parent.user_data;
76 RT_ASSERT(uart != RT_NULL);
77
78 if ((uart->config->usart_x->INTR_RX_MASKED & SCB_INTR_RX_MASKED_NOT_EMPTY_Msk) != 0)
79 {
80 /* Clear UART "RX fifo not empty interrupt" */
81 uart->config->usart_x->INTR_RX = uart->config->usart_x->INTR_RX & SCB_INTR_RX_NOT_EMPTY_Msk;
82
83 rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
84 }
85 }
86
87 #ifdef BSP_USING_UART0
88 /* UART0 Interrupt Hanlder */
uart0_isr_callback(void)89 void uart0_isr_callback(void)
90 {
91 /* enter interrupt */
92 rt_interrupt_enter();
93
94 uart_isr(&uart_obj[UART0_INDEX].serial);
95
96 /* leave interrupt */
97 rt_interrupt_leave();
98 }
99 #endif
100 #ifdef BSP_USING_UART1
101 /* UART1 Interrupt Hanlder */
uart1_isr_callback(void)102 void uart1_isr_callback(void)
103 {
104 /* enter interrupt */
105 rt_interrupt_enter();
106
107 uart_isr(&uart_obj[UART1_INDEX].serial);
108
109 /* leave interrupt */
110 rt_interrupt_leave();
111 }
112 #endif
113 #ifdef BSP_USING_UART2
114 /* UART2 Interrupt Hanlder */
uart2_isr_callback(void)115 void uart2_isr_callback(void)
116 {
117 /* enter interrupt */
118 rt_interrupt_enter();
119
120 uart_isr(&uart_obj[UART2_INDEX].serial);
121
122 /* leave interrupt */
123 rt_interrupt_leave();
124 }
125 #endif
126 #ifdef BSP_USING_UART3
127 /* UART3 Interrupt Hanlder */
uart3_isr_callback(void)128 void uart3_isr_callback(void)
129 {
130 /* enter interrupt */
131 rt_interrupt_enter();
132
133 uart_isr(&uart_obj[UART3_INDEX].serial);
134
135 /* leave interrupt */
136 rt_interrupt_leave();
137 }
138 #endif
139 #ifdef BSP_USING_UART4
140 /* UART4 Interrupt Hanlder */
uart4_isr_callback(void)141 void uart4_isr_callback(void)
142 {
143 /* enter interrupt */
144 rt_interrupt_enter();
145
146 uart_isr(&uart_obj[UART4_INDEX].serial);
147
148 /* leave interrupt */
149 rt_interrupt_leave();
150 }
151 #endif
152 #ifdef BSP_USING_UART5
153 /* UART5 Interrupt Hanlder */
uart5_isr_callback(void)154 void uart5_isr_callback(void)
155 {
156 /* enter interrupt */
157 rt_interrupt_enter();
158
159 uart_isr(&uart_obj[UART5_INDEX].serial);
160
161 /* leave interrupt */
162 rt_interrupt_leave();
163 }
164 #endif
165
166 #ifdef BSP_USING_UART6
167 /* UART5 Interrupt Hanlder */
uart6_isr_callback(void)168 void uart6_isr_callback(void)
169 {
170 /* enter interrupt */
171 rt_interrupt_enter();
172
173 uart_isr(&uart_obj[UART6_INDEX].serial);
174
175 /* leave interrupt */
176 rt_interrupt_leave();
177 }
178 #endif
179 /*
180 * UARTHS interface
181 */
ifx_configure(struct rt_serial_device * serial,struct serial_configure * cfg)182 static rt_err_t ifx_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
183 {
184 RT_ASSERT(serial != RT_NULL);
185 struct ifx_uart *uart = (struct ifx_uart *) serial->parent.user_data;
186 RT_ASSERT(uart != RT_NULL);
187
188 cy_en_scb_uart_status_t result;
189
190 const cyhal_uart_cfg_t uart_config =
191 {
192 .data_bits = 8,
193 .stop_bits = 1,
194 .parity = CYHAL_UART_PARITY_NONE,
195 .rx_buffer = NULL,
196 .rx_buffer_size = 0
197 };
198
199 /* Initialize retarget-io to use the debug UART port */
200 result = cyhal_uart_init(uart->config->uart_obj, uart->config->tx_pin, uart->config->rx_pin, NC, NC, NULL, &uart_config);
201
202 if (result == CY_RSLT_SUCCESS)
203 {
204 result = cyhal_uart_set_baud(uart->config->uart_obj, cfg->baud_rate, NULL);
205 }
206
207 RT_ASSERT(result == RT_EOK);
208
209 return RT_EOK;
210 }
211
ifx_control(struct rt_serial_device * serial,int cmd,void * arg)212 static rt_err_t ifx_control(struct rt_serial_device *serial, int cmd, void *arg)
213 {
214 RT_ASSERT(serial != RT_NULL);
215 struct ifx_uart *uart = (struct ifx_uart *) serial->parent.user_data;
216 RT_ASSERT(uart != RT_NULL);
217
218 switch (cmd)
219 {
220 case RT_DEVICE_CTRL_CLR_INT:
221 NVIC_DisableIRQ(uart->config->UART_SCB_IRQ_cfg->intrSrc);
222 break;
223
224 case RT_DEVICE_CTRL_SET_INT:
225 /* Unmasking only the RX fifo not empty interrupt bit */
226 uart->config->usart_x->INTR_RX_MASK = SCB_INTR_RX_MASK_NOT_EMPTY_Msk;
227
228 /* Interrupt Settings for UART */
229 Cy_SysInt_Init(uart->config->UART_SCB_IRQ_cfg, uart->config->userIsr);
230
231 /* Enable the interrupt */
232 #if defined(SOC_SERIES_IFX_XMC)
233 NVIC_DisableIRQ(UART_NvicMuxN_IRQn);
234 NVIC_EnableIRQ(UART_NvicMuxN_IRQn);
235 #else
236 NVIC_EnableIRQ(uart->config->UART_SCB_IRQ_cfg->intrSrc);
237 #endif
238 break;
239 }
240
241 return (RT_EOK);
242 }
243
ifx_uarths_putc(struct rt_serial_device * serial,char c)244 static int ifx_uarths_putc(struct rt_serial_device *serial, char c)
245 {
246 RT_ASSERT(serial != RT_NULL);
247
248 struct ifx_uart *uart = (struct ifx_uart *) serial->parent.user_data;
249
250 RT_ASSERT(uart != RT_NULL);
251
252 if (_cyhal_scb_pm_transition_pending())
253 return CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
254
255 uint32_t count = 0;
256
257 while (count == 0)
258 {
259 count = Cy_SCB_UART_Put(uart->config->usart_x, c);
260 }
261
262 return (1);
263 }
264
ifx_uarths_getc(struct rt_serial_device * serial)265 static int ifx_uarths_getc(struct rt_serial_device *serial)
266 {
267 int ch;
268 rt_uint8_t read_data;
269
270 RT_ASSERT(serial != RT_NULL);
271 struct ifx_uart *uart = (struct ifx_uart *) serial->parent.user_data;
272 RT_ASSERT(uart != RT_NULL);
273
274 ch = -1;
275
276 if (RT_EOK == cyhal_uart_getc(uart->config->uart_obj, (uint8_t *)&read_data, 10))
277 {
278 ch = read_data & 0xff;
279 }
280 else
281 {
282 ch = -1;
283 }
284
285 return ch;
286 }
287
288 const struct rt_uart_ops _uart_ops =
289 {
290 ifx_configure,
291 ifx_control,
292 ifx_uarths_putc,
293 ifx_uarths_getc,
294 RT_NULL
295 };
296
rt_hw_uart_init(void)297 void rt_hw_uart_init(void)
298 {
299 int index;
300
301 rt_size_t obj_num = sizeof(uart_obj) / sizeof(struct ifx_uart);
302 struct serial_configure serial_config = RT_SERIAL_CONFIG_DEFAULT;
303 rt_err_t result = 0;
304
305 for (index = 0; index < obj_num; index++)
306 {
307 uart_obj[index].config = &uart_config[index];
308 uart_obj[index].serial.ops = &_uart_ops;
309 uart_obj[index].serial.config = serial_config;
310
311 uart_obj[index].config->uart_obj = rt_malloc(sizeof(cyhal_uart_t));
312 RT_ASSERT(uart_obj[index].config->uart_obj != RT_NULL);
313 /* register uart device */
314 result = rt_hw_serial_register(&uart_obj[index].serial,
315 uart_obj[index].config->name,
316 RT_DEVICE_FLAG_RDWR |
317 RT_DEVICE_FLAG_INT_RX,
318 &uart_obj[index]);
319
320 RT_ASSERT(result == RT_EOK);
321 }
322 }
323