1 use crate::include::bindings::bindings::{io_in8, io_out8};
2 use core::{str, char, intrinsics::offset};
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 {port: UartPort::COM1, baud_rate: 115200}
83     }
84 }
85 
86 impl UartDriver {
87     /// @brief 串口初始化
88     /// @param uart_port 端口号
89     /// @param baud_rate 波特率
90     /// @return 初始化成功,返回0,失败,返回错误信息
91     #[allow(dead_code)]
uart_init(uart_port: &UartPort, baud_rate: u32) -> Result<i32, &'static str>92     pub fn uart_init(uart_port: &UartPort, baud_rate: u32) -> Result<i32, &'static str> {
93         let message: &'static str = "uart init.";
94         let port = uart_port.to_u16();
95         // 错误的比特率
96         if baud_rate > UART_MAX_BITS_RATE || UART_MAX_BITS_RATE % baud_rate != 0 {
97             return Err("uart init error.");
98         }
99 
100         unsafe {
101             io_out8(port + 1, 0x00); // Disable all interrupts
102             io_out8(port + 3, 0x80); // Enable DLAB (set baud rate divisor)
103 
104             let divisor = UART_MAX_BITS_RATE / baud_rate;
105 
106             io_out8(port + 0, (divisor & 0xff) as u8);        // Set divisor  (lo byte)
107             io_out8(port + 1, ((divisor >> 8) & 0xff) as u8); //                  (hi byte)
108             io_out8(port + 3, 0x03);                  // 8 bits, no parity, one stop bit
109             io_out8(port + 2, 0xC7);                  // Enable FIFO, clear them, with 14-byte threshold
110             io_out8(port + 4, 0x08); // IRQs enabled, RTS/DSR clear (现代计算机上一般都不需要hardware flow control,因此不需要置位RTS/DSR)
111             io_out8(port + 4, 0x1E); // Set in loopback mode, test the serial chip
112             io_out8(port + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
113 
114             // Check if serial is faulty (i.e: not same byte as sent)
115             if io_in8(port + 0) != 0xAE {
116                 return Err("uart faulty");
117             }
118 
119             // If serial is not faulty set it in normal operation mode
120             // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
121             io_out8(port + 4, 0x08);
122         }
123         UartDriver::uart_send(uart_port, message);
124         Ok(0)
125         /*
126                 Notice that the initialization code above writes to [PORT + 1]
127             twice with different values. This is once to write to the Divisor
128             register along with [PORT + 0] and once to write to the Interrupt
129             register as detailed in the previous section.
130                 The second write to the Line Control register [PORT + 3]
131             clears the DLAB again as well as setting various other bits.
132         */
133     }
134 
serial_received(offset: u16) -> bool135     fn serial_received(offset: u16) -> bool {
136         if unsafe{ io_in8(offset + 5) } & 1 != 0 {
137             true
138         } else {
139             false
140         }
141     }
142 
is_transmit_empty(offset: u16) -> bool143     fn is_transmit_empty(offset: u16) -> bool {
144         if unsafe{ io_in8(offset + 5) } & 0x20 != 0 {
145             true
146         } else {
147             false
148         }
149     }
150 
151     /// @brief 串口发送
152     /// @param uart_port 端口号
153     /// @param str 发送字符切片
154     /// @return None
155     #[allow(dead_code)]
uart_send(uart_port: &UartPort, str: &str)156     fn uart_send(uart_port: &UartPort, str: &str) {
157         let port = uart_port.to_u16();
158         while UartDriver::is_transmit_empty(port) == false {
159             for c in str.bytes() {
160                 unsafe { io_out8(port, c); }
161             }
162         } //TODO:pause
163     }
164 
165     /// @brief 串口接收一个字节
166     /// @param uart_port 端口号
167     /// @return 接收的字节
168     #[allow(dead_code)]
uart_read_byte(uart_port: &UartPort) -> char169     fn uart_read_byte(uart_port: &UartPort) -> char {
170         let port = uart_port.to_u16();
171         while UartDriver::serial_received(port) == false {} //TODO:pause
172         unsafe { io_in8(port) as char }
173     }
174 
175 }
176 
177 ///@brief 发送数据
178 ///@param port 端口号
179 ///@param c 要发送的数据
180 #[no_mangle]
c_uart_send(port: u16, c: u8)181 pub extern "C" fn c_uart_send(port: u16, c: u8) {
182     while UartDriver::is_transmit_empty(port) == false {} //TODO:pause
183     unsafe { io_out8(port, c); }
184 }
185 
186 ///@brief 从uart接收数据
187 ///@param port 端口号
188 ///@return u8 接收到的数据
189 #[no_mangle]
c_uart_read(port: u16) -> u8190 pub extern "C" fn c_uart_read(port: u16) -> u8 {
191     while UartDriver::serial_received(port) == false {} //TODO:pause
192     unsafe { io_in8(port) }
193 }
194 
195 ///@brief 通过串口发送整个字符串
196 ///@param port 串口端口
197 ///@param str 字符串S
198 #[no_mangle]
c_uart_send_str(port: u16, str: *const u8)199 pub extern "C" fn c_uart_send_str(port: u16, str: *const u8)
200 {
201     unsafe {
202         let mut i = 0;
203         while *offset(str, i) != '\0' as u8 {
204             c_uart_send(port, *offset(str, i));
205             i = i + 1;
206         }
207     }
208 }
209 
210 /// @brief 串口初始化
211 /// @param u16 端口号
212 /// @param baud_rate 波特率
213 /// @return 初始化成功,返回0,失败,返回错误码
214 #[no_mangle]
c_uart_init(port: u16, baud_rate: u32) -> i32215 pub extern "C" fn c_uart_init(port: u16, baud_rate: u32) -> i32 {
216     let message: &'static str = "uart init\n";
217     // 错误的比特率
218     if baud_rate > UART_MAX_BITS_RATE || UART_MAX_BITS_RATE % baud_rate != 0 {
219         return -E_UART_BITS_RATE_ERROR;
220     }
221 
222     unsafe {
223         io_out8(port + 1, 0x00); // Disable all interrupts
224         io_out8(port + 3, 0x80); // Enable DLAB (set baud rate divisor)
225 
226         let divisor = UART_MAX_BITS_RATE / baud_rate;
227 
228         io_out8(port + 0, (divisor & 0xff) as u8);        // Set divisor  (lo byte)
229         io_out8(port + 1, ((divisor >> 8) & 0xff) as u8); //                  (hi byte)
230         io_out8(port + 3, 0x03);                  // 8 bits, no parity, one stop bit
231         io_out8(port + 2, 0xC7);                  // Enable FIFO, clear them, with 14-byte threshold
232         io_out8(port + 4, 0x08); // IRQs enabled, RTS/DSR clear (现代计算机上一般都不需要hardware flow control,因此不需要置位RTS/DSR)
233         io_out8(port + 4, 0x1E); // Set in loopback mode, test the serial chip
234         io_out8(port + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
235 
236         // Check if serial is faulty (i.e: not same byte as sent)
237         if io_in8(port + 0) != 0xAE {
238             return -E_UART_SERIAL_FAULT;
239         }
240 
241         // If serial is not faulty set it in normal operation mode
242         // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
243         io_out8(port + 4, 0x08);
244         let bytes = message.as_bytes();
245         for c in bytes {
246             c_uart_send(port, *c);
247         }
248     }
249     return UART_SUCCESS;
250     /*
251             Notice that the initialization code above writes to [PORT + 1]
252         twice with different values. This is once to write to the Divisor
253         register along with [PORT + 0] and once to write to the Interrupt
254         register as detailed in the previous section.
255             The second write to the Line Control register [PORT + 3]
256         clears the DLAB again as well as setting various other bits.
257     */
258 }
259