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