1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Email: opensource_embedded@phytium.com.cn
7  *
8  * Change Logs:
9  * Date        Author       Notes
10  * 2025-05-23  liyilun      first commit
11  */
12 
13 #include "rtconfig.h"
14 
15 #include <rtdevice.h>
16 #include "board.h"
17 #include <mmu.h>
18 #include "drv_usart_msg.h"
19 #include "interrupt.h"
20 #include "fio_mux.h"
21 #include "fparameters.h"
22 
23 #ifdef RT_USING_SMART
24     #include <ioremap.h>
25 #endif
26 
27 #define RING_BUFFER_WAIT_TIMEOUT              10000
28 #define RING_BUFFER_SIZE                      64
29 
30 struct rt_ringbuffer *recv_ringbuffer = NULL;
31 
32 
rt_ringbuffer_status(struct rt_ringbuffer * rb)33 rt_inline enum rt_ringbuffer_state rt_ringbuffer_status(struct rt_ringbuffer *rb)
34 {
35     if (rb->read_index == rb->write_index)
36     {
37         if (rb->read_mirror == rb->write_mirror)
38             return RT_RINGBUFFER_EMPTY;
39         else
40             return RT_RINGBUFFER_FULL;
41     }
42     return RT_RINGBUFFER_HALFFULL;
43 }
44 
45 static void Ft_Os_Uart_Msg_Callback(void *Args, u32 Event, u32 EventData);
46 
rt_hw_uart_msg_isr(int irqno,void * param)47 static void rt_hw_uart_msg_isr(int irqno, void *param)
48 {
49     FUartMsgInterruptHandler(irqno, param);
50 }
51 
uart_msg_configure(struct rt_serial_device * serial,struct serial_configure * cfg)52 static rt_err_t uart_msg_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
53 {
54     struct drv_usart_msg *uart_msg = RT_NULL;
55     FUartMsg *uart_msg_hw = RT_NULL;
56 
57     FUartMsgConfig config;
58 
59     RT_ASSERT(serial != RT_NULL);
60     RT_ASSERT(cfg != RT_NULL);
61     uart_msg = rt_container_of(serial, struct drv_usart_msg, serial);
62     uart_msg_hw = uart_msg->handle;
63     config = *(const FUartMsgConfig *)FUartMsgLookupConfig(uart_msg->config.uart_instance);
64 
65 #ifdef RT_USING_SMART
66     config.msg.regfile = (uintptr)rt_ioremap((void *)config.msg.regfile,  0x1000);
67     config.msg.shmem = (uintptr)rt_ioremap((void *)config.msg.shmem,  0x1000);
68 #endif
69 
70 
71     FIOPadSetUartMux(uart_msg->config.uart_instance);
72 
73     RT_ASSERT(FUartMsgCfgInitialize(uart_msg_hw, &config) == FT_SUCCESS);
74 
75     FUartMsgSetStartUp(uart_msg_hw);
76 
77     FUartMsgSetHandler(uart_msg_hw, Ft_Os_Uart_Msg_Callback, serial);
78 
79 
80     //<! 打开接收中断
81 
82     rt_hw_interrupt_set_priority(uart_msg_hw->config.irq_num, uart_msg->config.isr_priority);
83     rt_hw_interrupt_install(uart_msg_hw->config.irq_num, rt_hw_uart_msg_isr, uart_msg_hw, "uart");
84     rt_hw_interrupt_umask(uart_msg_hw->config.irq_num);
85     FUartMsgEnableInterrups(uart_msg_hw);
86 
87     return RT_EOK;
88 }
89 
uart_msg_control(struct rt_serial_device * serial,int cmd,void * arg)90 static rt_err_t uart_msg_control(struct rt_serial_device *serial, int cmd, void *arg)
91 {
92     struct drv_usart_msg *uart_msg = RT_NULL;
93     FUartMsg *uart_msg_ptr = RT_NULL;
94     RT_ASSERT(serial != RT_NULL);
95 
96     uart_msg = rt_container_of(serial, struct drv_usart_msg, serial);
97     uart_msg_ptr = uart_msg->handle;
98 
99     switch (cmd)
100     {
101         case RT_DEVICE_CTRL_CLR_INT:
102             /* disable rx irq */
103             rt_hw_interrupt_mask(uart_msg_ptr->config.irq_num);
104             break;
105 
106         case RT_DEVICE_CTRL_SET_INT:
107             /* enable rx irq */
108             rt_hw_interrupt_umask(uart_msg_ptr->config.irq_num);
109             break;
110     }
111 
112     return RT_EOK;
113 }
114 
uart_msg_putc(struct rt_serial_device * serial,char c)115 static int uart_msg_putc(struct rt_serial_device *serial, char c)
116 {
117     struct drv_usart_msg *uart_msg = RT_NULL;
118     FUartMsg *uart_msg_ptr = RT_NULL;
119     RT_ASSERT(serial != RT_NULL);
120 
121     uart_msg = rt_container_of(serial, struct drv_usart_msg, serial);
122     uart_msg_ptr = uart_msg->handle;
123 
124     while(-1 == FUartMsgTxChar(&(uart_msg_ptr->config.msg), (u8)c))
125     {
126     }
127 
128     return 1;
129 }
130 
FUartMsgRecvBufferNoBlocking(FUartMsg * uart_p)131 void FUartMsgRecvBufferNoBlocking(FUartMsg *uart_p)
132 {
133     u8 data[16] = {0};
134     rt_size_t write_length = 0;
135     u32 received_count = 0;
136 
137     while (!FUartMsgRxRingBufferIsEmpty(uart_p->config.msg.regfile))
138     {
139         received_count += FUartMsgRxChars(&(uart_p->config.msg), data, 16);
140     }
141 
142     if(received_count > 0)
143     {
144         write_length = rt_ringbuffer_put(recv_ringbuffer, data, received_count);
145         RT_ASSERT(write_length == received_count);
146     }
147 
148 }
149 
uart_msg_getc(struct rt_serial_device * serial)150 static int uart_msg_getc(struct rt_serial_device *serial)
151 {
152     int ch;
153     struct drv_usart_msg *uart_msg = RT_NULL;
154     FUartMsg *uart_msg_ptr = RT_NULL;
155     RT_ASSERT(serial != RT_NULL);
156 
157     uart_msg = rt_container_of(serial, struct drv_usart_msg, serial);
158     uart_msg_ptr = uart_msg->handle;
159 
160 
161     if(RT_RINGBUFFER_EMPTY == rt_ringbuffer_status(recv_ringbuffer))
162     {
163         FUartMsgRecvBufferNoBlocking(uart_msg_ptr);
164     }
165 
166     if(0 == rt_ringbuffer_getchar(recv_ringbuffer, (rt_uint8_t *)&ch))
167     {
168         return -1;
169     }
170 
171     if (ch == 0xffff)
172     {
173         ch = -1;
174     }
175     else
176     {
177         ch &= 0xff;
178     }
179 
180     return ch;
181 }
182 
Ft_Os_Uart_Msg_Callback(void * Args,u32 Event,u32 EventData)183 static void Ft_Os_Uart_Msg_Callback(void *Args, u32 Event, u32 EventData)
184 {
185 
186     struct rt_serial_device *serial = (struct rt_serial_device *)Args;
187     if(FUART_EVENT_RECV_DATA == Event)
188     {
189         if(serial->serial_rx)
190         {
191             rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
192         }
193     }
194     else if(FUART_EVENT_SENT_DATA == Event)
195     {
196 
197     }
198     else
199     {
200 
201     }
202 }
203 
204 
205 static const struct rt_uart_ops _uart_ops =
206 {
207     uart_msg_configure,
208     uart_msg_control,
209     uart_msg_putc,
210     uart_msg_getc,
211     NULL
212 };
213 
uart_msg_init(struct drv_usart_msg * uart_msg_dev)214 static int uart_msg_init(struct drv_usart_msg *uart_msg_dev)
215 {
216     struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
217 
218     config.bufsz = RT_SERIAL_RB_BUFSZ;
219     uart_msg_dev->serial.ops = &_uart_ops;
220     uart_msg_dev->serial.config = config;
221 
222     uart_msg_dev->config.isr_priority = 0xd0;
223     uart_msg_dev->config.isr_event_mask = RTOS_UART_MSG_RX_ISR_MASK | RTOS_UART_MSG_TX_ISR_MASK;
224     uart_msg_dev->config.uart_baudrate = BAUD_RATE_115200;
225 
226     recv_ringbuffer = rt_ringbuffer_create(RING_BUFFER_SIZE);
227 
228     RT_ASSERT(recv_ringbuffer != RT_NULL);
229 
230     rt_hw_serial_register(&uart_msg_dev->serial, uart_msg_dev->name,
231                           RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
232                           uart_msg_dev);
233 
234     return 0;
235 }
236 
237 #ifdef RT_USING_UART0_MSG
238     static FUartMsg Ft_Uart0_Msg;
239     static struct drv_usart_msg drv_uart0_msg;
240 #endif
241 #ifdef RT_USING_UART1_MSG
242     static FUartMsg Ft_Uart1_Msg;
243     static struct drv_usart_msg drv_uart1_msg;
244 #endif
245 #ifdef RT_USING_UART2_MSG
246     static FUartMsg Ft_Uart2_Msg;
247     static struct drv_usart_msg drv_uart2_msg;
248 #endif
249 
rt_hw_uart_init(void)250 int rt_hw_uart_init(void)
251 {
252 
253 #ifdef RT_USING_UART0_MSG
254     drv_uart0_msg.name = "uart0";
255     drv_uart0_msg.handle = &Ft_Uart0_Msg;
256     drv_uart0_msg.config.uart_instance = FUART0_MSG_ID;
257     uart_msg_init(&drv_uart0_msg);
258 #endif
259 #ifdef RT_USING_UART1_MSG
260     drv_uart1_msg.name = "uart1";
261     drv_uart1_msg.handle = &Ft_Uart1_Msg;
262     drv_uart1_msg.config.uart_instance = FUART1_MSG_ID;
263     uart_msg_init(&drv_uart1_msg);
264 #endif
265 #ifdef RT_USING_UART2_MSG
266     drv_uart2_msg.name = "uart2";
267     drv_uart2_msg.handle = &Ft_Uart2_Msg;
268     drv_uart2_msg.config.uart_instance = FUART2_MSG_ID;
269     uart_msg_init(&drv_uart2_msg);
270 #endif
271 
272     return 0;
273 }
274 INIT_BOARD_EXPORT(rt_hw_uart_init);
275