1 use crate::include::bindings::bindings::{io_in8, io_out8};
2 use core::{char, intrinsics::offset, str};
3 
4 const UART_SUCCESS: i32 = 0;
5 const E_UART_BITS_RATE_ERROR: i32 = 1;
6 const E_UART_SERIAL_FAULT: i32 = 2;
7 const UART_MAX_BITS_RATE: u32 = 115200;
8 
9 #[allow(dead_code)]
10 #[repr(u16)]
11 #[derive(Clone)]
12 pub enum UartPort {
13     COM1 = 0x3f8,
14     COM2 = 0x2f8,
15     COM3 = 0x3e8,
16     COM4 = 0x2e8,
17     COM5 = 0x5f8,
18     COM6 = 0x4f8,
19     COM7 = 0x5e8,
20     COM8 = 0x4e8,
21 }
22 
23 impl UartPort {
24     ///@brief 将u16转换为UartPort枚举类型
25     ///@param val 要转换的u16类型
26     ///@return 输入的端口地址正确,返回UartPort类型,错误,返回错误信息
27     #[allow(dead_code)]
from_u16(val: u16) -> Result<Self, &'static str>28     pub fn from_u16(val: u16) -> Result<Self, &'static str> {
29         match val {
30             0x3f8 => Ok(Self::COM1),
31             0x2f8 => Ok(Self::COM2),
32             0x3e8 => Ok(Self::COM3),
33             0x2e8 => Ok(Self::COM4),
34             0x5f8 => Ok(Self::COM5),
35             0x4f8 => Ok(Self::COM6),
36             0x5e8 => Ok(Self::COM7),
37             0x4e8 => Ok(Self::COM8),
38             _ => Err("port error!"),
39         }
40     }
41 
42     ///@brief 将UartPort枚举类型转换为u16类型
43     ///@param self 要转换的UartPort
44     ///@return 转换的u16值
45     #[allow(dead_code)]
to_u16(self: &Self) -> u1646     pub fn to_u16(self: &Self) -> u16 {
47         match self {
48             Self::COM1 => 0x3f8,
49             Self::COM2 => 0x2f8,
50             Self::COM3 => 0x3e8,
51             Self::COM4 => 0x2e8,
52             Self::COM5 => 0x5f8,
53             Self::COM6 => 0x4f8,
54             Self::COM7 => 0x5e8,
55             Self::COM8 => 0x4e8,
56         }
57     }
58 }
59 
60 #[allow(dead_code)]
61 #[repr(C)]
62 #[derive(Debug, Copy, Clone)]
63 struct UartRegister {
64     reg_data: u8,
65     reg_interrupt_enable: u8,
66     reg_ii_fifo: u8, // 	Interrupt Identification and FIFO control registers
67     reg_line_config: u8,
68     reg_modem_config: u8,
69     reg_line_status: u8,
70     reg_modem_statue: u8,
71     reg_scartch: u8,
72 }
73 
74 #[repr(C)]
75 pub struct UartDriver {
76     port: UartPort,
77     baud_rate: u32,
78 }
79 
80 impl Default for UartDriver {
default() -> Self81     fn default() -> Self {
82         Self {
83             port: UartPort::COM1,
84             baud_rate: 115200,
85         }
86     }
87 }
88 
89 impl UartDriver {
90     /// @brief 串口初始化
91     /// @param uart_port 端口号
92     /// @param baud_rate 波特率
93     /// @return 初始化成功,返回0,失败,返回错误信息
94     #[allow(dead_code)]
uart_init(uart_port: &UartPort, baud_rate: u32) -> Result<i32, &'static str>95     pub fn uart_init(uart_port: &UartPort, baud_rate: u32) -> Result<i32, &'static str> {
96         let message: &'static str = "uart init.";
97         let port = uart_port.to_u16();
98         // 错误的比特率
99         if baud_rate > UART_MAX_BITS_RATE || UART_MAX_BITS_RATE % baud_rate != 0 {
100             return Err("uart init error.");
101         }
102 
103         unsafe {
104             io_out8(port + 1, 0x00); // Disable all interrupts
105             io_out8(port + 3, 0x80); // Enable DLAB (set baud rate divisor)
106 
107             let divisor = UART_MAX_BITS_RATE / baud_rate;
108 
109             io_out8(port + 0, (divisor & 0xff) as u8); // Set divisor  (lo byte)
110             io_out8(port + 1, ((divisor >> 8) & 0xff) as u8); //                  (hi byte)
111             io_out8(port + 3, 0x03); // 8 bits, no parity, one stop bit
112             io_out8(port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
113             io_out8(port + 4, 0x08); // IRQs enabled, RTS/DSR clear (现代计算机上一般都不需要hardware flow control,因此不需要置位RTS/DSR)
114             io_out8(port + 4, 0x1E); // Set in loopback mode, test the serial chip
115             io_out8(port + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
116 
117             // Check if serial is faulty (i.e: not same byte as sent)
118             if io_in8(port + 0) != 0xAE {
119                 return Err("uart faulty");
120             }
121 
122             // If serial is not faulty set it in normal operation mode
123             // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
124             io_out8(port + 4, 0x08);
125         }
126         UartDriver::uart_send(uart_port, message);
127         Ok(0)
128         /*
129                 Notice that the initialization code above writes to [PORT + 1]
130             twice with different values. This is once to write to the Divisor
131             register along with [PORT + 0] and once to write to the Interrupt
132             register as detailed in the previous section.
133                 The second write to the Line Control register [PORT + 3]
134             clears the DLAB again as well as setting various other bits.
135         */
136     }
137 
serial_received(offset: u16) -> bool138     fn serial_received(offset: u16) -> bool {
139         if unsafe { io_in8(offset + 5) } & 1 != 0 {
140             true
141         } else {
142             false
143         }
144     }
145 
is_transmit_empty(offset: u16) -> bool146     fn is_transmit_empty(offset: u16) -> bool {
147         if unsafe { io_in8(offset + 5) } & 0x20 != 0 {
148             true
149         } else {
150             false
151         }
152     }
153 
154     /// @brief 串口发送
155     /// @param uart_port 端口号
156     /// @param str 发送字符切片
157     /// @return None
158     #[allow(dead_code)]
uart_send(uart_port: &UartPort, str: &str)159     fn uart_send(uart_port: &UartPort, str: &str) {
160         let port = uart_port.to_u16();
161         while UartDriver::is_transmit_empty(port) == false {
162             for c in str.bytes() {
163                 unsafe {
164                     io_out8(port, c);
165                 }
166             }
167         } //TODO:pause
168     }
169 
170     /// @brief 串口接收一个字节
171     /// @param uart_port 端口号
172     /// @return 接收的字节
173     #[allow(dead_code)]
uart_read_byte(uart_port: &UartPort) -> char174     fn uart_read_byte(uart_port: &UartPort) -> char {
175         let port = uart_port.to_u16();
176         while UartDriver::serial_received(port) == false {} //TODO:pause
177         unsafe { io_in8(port) as char }
178     }
179 }
180 
181 ///@brief 发送数据
182 ///@param port 端口号
183 ///@param c 要发送的数据
184 #[no_mangle]
c_uart_send(port: u16, c: u8)185 pub extern "C" fn c_uart_send(port: u16, c: u8) {
186     while UartDriver::is_transmit_empty(port) == false {} //TODO:pause
187     unsafe {
188         io_out8(port, c);
189     }
190 }
191 
192 ///@brief 从uart接收数据
193 ///@param port 端口号
194 ///@return u8 接收到的数据
195 #[no_mangle]
c_uart_read(port: u16) -> u8196 pub extern "C" fn c_uart_read(port: u16) -> u8 {
197     while UartDriver::serial_received(port) == false {} //TODO:pause
198     unsafe { io_in8(port) }
199 }
200 
201 ///@brief 通过串口发送整个字符串
202 ///@param port 串口端口
203 ///@param str 字符串S
204 #[no_mangle]
c_uart_send_str(port: u16, str: *const u8)205 pub extern "C" fn c_uart_send_str(port: u16, str: *const u8) {
206     unsafe {
207         let mut i = 0;
208         while *offset(str, i) != '\0' as u8 {
209             c_uart_send(port, *offset(str, i));
210             i = i + 1;
211         }
212     }
213 }
214 
215 /// @brief 串口初始化
216 /// @param u16 端口号
217 /// @param baud_rate 波特率
218 /// @return 初始化成功,返回0,失败,返回错误码
219 #[no_mangle]
c_uart_init(port: u16, baud_rate: u32) -> i32220 pub extern "C" fn c_uart_init(port: u16, baud_rate: u32) -> i32 {
221     let message: &'static str = "uart init\n";
222     // 错误的比特率
223     if baud_rate > UART_MAX_BITS_RATE || UART_MAX_BITS_RATE % baud_rate != 0 {
224         return -E_UART_BITS_RATE_ERROR;
225     }
226 
227     unsafe {
228         io_out8(port + 1, 0x00); // Disable all interrupts
229         io_out8(port + 3, 0x80); // Enable DLAB (set baud rate divisor)
230 
231         let divisor = UART_MAX_BITS_RATE / baud_rate;
232 
233         io_out8(port + 0, (divisor & 0xff) as u8); // Set divisor  (lo byte)
234         io_out8(port + 1, ((divisor >> 8) & 0xff) as u8); //                  (hi byte)
235         io_out8(port + 3, 0x03); // 8 bits, no parity, one stop bit
236         io_out8(port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
237         io_out8(port + 4, 0x08); // IRQs enabled, RTS/DSR clear (现代计算机上一般都不需要hardware flow control,因此不需要置位RTS/DSR)
238         io_out8(port + 4, 0x1E); // Set in loopback mode, test the serial chip
239         io_out8(port + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
240 
241         // Check if serial is faulty (i.e: not same byte as sent)
242         if io_in8(port + 0) != 0xAE {
243             return -E_UART_SERIAL_FAULT;
244         }
245 
246         // If serial is not faulty set it in normal operation mode
247         // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
248         io_out8(port + 4, 0x08);
249         let bytes = message.as_bytes();
250         for c in bytes {
251             c_uart_send(port, *c);
252         }
253     }
254     return UART_SUCCESS;
255     /*
256             Notice that the initialization code above writes to [PORT + 1]
257         twice with different values. This is once to write to the Divisor
258         register along with [PORT + 0] and once to write to the Interrupt
259         register as detailed in the previous section.
260             The second write to the Line Control register [PORT + 3]
261         clears the DLAB again as well as setting various other bits.
262     */
263 }
264