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