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