Skip to main content

some_serial/pl011/
control.rs

1use super::*;
2
3/// PL011 UART 驱动结构体
4pub struct Pl011 {
5    pub(super) base: Reg,
6    clock_freq: u32,
7    pub(super) saved_rx_status: Pl011RxStatus,
8}
9
10impl Pl011 {
11    /// 创建新的 PL011 实例(仅基地址,使用默认配置)
12    ///
13    /// # Arguments
14    /// * `base` - UART 寄存器基地址
15    pub fn new_no_clock(base: NonNull<u8>) -> Self {
16        // 自动检测时钟频率或使用合理的默认值
17        let clock_freq = Self::detect_clock_frequency(base.as_ptr() as usize);
18        Self::new(base, clock_freq)
19    }
20
21    pub fn new(base: NonNull<u8>, clock_freq: u32) -> Self {
22        let base = Reg(base.cast());
23
24        Self {
25            base,
26            clock_freq,
27            saved_rx_status: Pl011RxStatus::empty(),
28        }
29    }
30
31    pub(super) fn registers(&self) -> &Pl011Registers {
32        unsafe { &*self.base.0.as_ptr() }
33    }
34
35    pub(super) fn current_baudrate(&self) -> u32 {
36        let ibrd = self.registers().uartibrd.read(UARTIBRD::BAUD_DIVINT);
37        let fbrd = self.registers().uartfbrd.read(UARTFBRD::BAUD_DIVFRAC);
38        let divisor = ibrd * 64 + fbrd;
39        if divisor == 0 {
40            0
41        } else {
42            self.clock_freq * 64 / (16 * divisor)
43        }
44    }
45
46    /// 自动检测或确定合理的时钟频率
47    fn detect_clock_frequency(base: usize) -> u32 {
48        // 尝试读取当前波特率设置来反向推算时钟频率
49        let registers = unsafe { &*(base as *const Pl011Registers) };
50
51        use tock_registers::interfaces::Readable;
52        let ibrd = registers.uartibrd.read(UARTIBRD::BAUD_DIVINT);
53
54        // 如果有设置值,假设波特率为 115200 来估算时钟频率
55        if ibrd > 0 && ibrd <= 0xFFFF {
56            // 假设波特率为 115200,计算时钟频率
57            // FUARTCLK = 16 * BAUDDIV * Baud rate
58            let estimated_clock = 16 * ibrd * 115200;
59
60            // 合理的时钟频率范围:1MHz - 100MHz
61            if (1_000_000..=100_000_000).contains(&estimated_clock) {
62                return estimated_clock;
63            }
64        }
65
66        // 默认使用 24MHz(最常见)
67        24_000_000
68    }
69
70    // 内部私有方法,用于配置
71    pub(super) fn set_baudrate_internal(&self, baudrate: u32) -> Result<(), ConfigError> {
72        // PL011 波特率计算公式:
73        // BAUDDIV = (FUARTCLK / (16 * Baud rate))
74        // IBRD = integer(BAUDDIV)
75        // FBRD = integer((BAUDDIV - IBRD) * 64 + 0.5)
76
77        let scaled_baudrate = baudrate
78            .checked_mul(16)
79            .filter(|scaled| *scaled != 0)
80            .ok_or(ConfigError::InvalidBaudrate)?;
81        let bauddiv = self.clock_freq / scaled_baudrate;
82        let remainder = self.clock_freq % scaled_baudrate;
83        let fbrd = (remainder * 64 + (scaled_baudrate / 2)) / scaled_baudrate;
84
85        if bauddiv == 0 || bauddiv > 0xFFFF {
86            return Err(ConfigError::InvalidBaudrate);
87        }
88
89        self.registers()
90            .uartibrd
91            .write(UARTIBRD::BAUD_DIVINT.val(bauddiv));
92        self.registers()
93            .uartfbrd
94            .write(UARTFBRD::BAUD_DIVFRAC.val(fbrd));
95
96        Ok(())
97    }
98
99    pub(super) fn wait_until_not_busy(&self) -> Result<(), ConfigError> {
100        for _ in 0..BUSY_POLL_BUDGET {
101            if !self.registers().uartfr.is_set(UARTFR::BUSY) {
102                return Ok(());
103            }
104            core::hint::spin_loop();
105        }
106        Err(ConfigError::Timeout)
107    }
108
109    pub(super) fn set_data_bits_internal(&self, bits: DataBits) -> Result<(), ConfigError> {
110        let wlen = match bits {
111            DataBits::Five => UARTLCR_H::WLEN::FiveBit,
112            DataBits::Six => UARTLCR_H::WLEN::SixBit,
113            DataBits::Seven => UARTLCR_H::WLEN::SevenBit,
114            DataBits::Eight => UARTLCR_H::WLEN::EightBit,
115        };
116
117        self.registers().uartlcr_h.modify(wlen);
118        Ok(())
119    }
120
121    pub(super) fn set_stop_bits_internal(&self, bits: StopBits) -> Result<(), ConfigError> {
122        match bits {
123            StopBits::One => self.registers().uartlcr_h.modify(UARTLCR_H::STP2::CLEAR),
124            StopBits::Two => self.registers().uartlcr_h.modify(UARTLCR_H::STP2::SET),
125        }
126
127        Ok(())
128    }
129
130    pub(super) fn set_parity_internal(&self, parity: Parity) -> Result<(), ConfigError> {
131        match parity {
132            Parity::None => {
133                // PEN = 0, 无奇偶校验
134                self.registers().uartlcr_h.modify(UARTLCR_H::PEN::CLEAR);
135            }
136            Parity::Odd => {
137                // PEN = 1, EPS = 0 (奇校验), SPS = 0
138                self.registers()
139                    .uartlcr_h
140                    .modify(UARTLCR_H::PEN::SET + UARTLCR_H::EPS::CLEAR + UARTLCR_H::SPS::CLEAR);
141            }
142            Parity::Even => {
143                // PEN = 1, EPS = 1 (偶校验), SPS = 0
144                self.registers()
145                    .uartlcr_h
146                    .modify(UARTLCR_H::PEN::SET + UARTLCR_H::EPS::SET + UARTLCR_H::SPS::CLEAR);
147            }
148            Parity::Mark => {
149                // PEN = 1, SPS = 1, EPS = 0 (奇校验)
150                self.registers()
151                    .uartlcr_h
152                    .modify(UARTLCR_H::PEN::SET + UARTLCR_H::EPS::CLEAR + UARTLCR_H::SPS::SET);
153            }
154            Parity::Space => {
155                // PEN = 1, EPS = 1 (偶校验), SPS = 1
156                self.registers()
157                    .uartlcr_h
158                    .modify(UARTLCR_H::PEN::SET + UARTLCR_H::EPS::SET + UARTLCR_H::SPS::SET);
159            }
160        }
161
162        Ok(())
163    }
164
165    /// 初始化 PL011 UART
166    pub fn open(&mut self) -> Result<(), ConfigError> {
167        let original_cr = self.registers().uartcr.get();
168
169        // 禁用 UART
170        self.registers().uartcr.modify(UARTCR::UARTEN::CLEAR);
171
172        // 等待当前传输完成
173        if let Err(error) = self.wait_until_not_busy() {
174            self.registers().uartcr.set(original_cr);
175            return Err(error);
176        }
177
178        // 清除发送 FIFO
179        self.registers().uartlcr_h.modify(UARTLCR_H::FEN::CLEAR);
180
181        // 启用 FIFO
182        self.registers().uartlcr_h.modify(UARTLCR_H::FEN::SET);
183
184        // 调试信息:输出 FIFO 配置
185        #[cfg(debug_assertions)]
186        {
187            let ifls = self.registers().uartifls.get();
188            let lcr_h = self.registers().uartlcr_h.get();
189            log::debug!("UART IFLS: 0x{:02x}, LCR_H: 0x{:02x}", ifls, lcr_h);
190            log::debug!("  FIFO enabled: {}", lcr_h & (1 << 4) != 0);
191            log::debug!("  RX trigger level: 1/8");
192            log::debug!("  TX trigger level: 1/2");
193        }
194        self.registers().uartimsc.set(0); // 禁用所有中断
195        // 启用 UART
196        self.registers()
197            .uartcr
198            .modify(UARTCR::UARTEN::SET + UARTCR::TXE::SET + UARTCR::RXE::SET);
199        Ok(())
200    }
201
202    pub fn set_irq_mask(&mut self, events: SerialEventSet) {
203        self.registers().uartimsc.set(imsc_for_events(events));
204    }
205
206    pub fn get_irq_mask(&self) -> SerialEventSet {
207        let imsc = self.registers().uartimsc.extract();
208        let mut events = SerialEventSet::empty();
209
210        if imsc.is_set(UARTIS::RX)
211            || imsc.is_set(UARTIS::RT)
212            || imsc.is_set(UARTIS::FE)
213            || imsc.is_set(UARTIS::PE)
214            || imsc.is_set(UARTIS::BE)
215            || imsc.is_set(UARTIS::OE)
216        {
217            events |= SerialEventSet::RX;
218        }
219        if imsc.is_set(UARTIS::TX) {
220            events |= SerialEventSet::TX_SPACE;
221        }
222
223        events
224    }
225
226    pub fn pending(&mut self, direction: SerialDirection) -> bool {
227        match direction {
228            SerialDirection::Input => !self.registers().uartfr.is_set(UARTFR::RXFE),
229            SerialDirection::Output => !self.registers().uartfr.is_set(UARTFR::TXFF),
230        }
231    }
232
233    pub fn poll_status(&mut self) -> SerialEvent {
234        let mut event = SerialEvent::empty();
235        let fr = self.registers().uartfr.extract();
236        if !fr.is_set(UARTFR::RXFE) {
237            event |= SerialEvent::RX_READY;
238        }
239        if !fr.is_set(UARTFR::TXFF) {
240            event |= SerialEvent::TX_READY;
241        }
242
243        let status =
244            self.saved_rx_status | Pl011RxStatus::from_rsr(self.registers().uartrsr_ecr.extract());
245        if status.intersects(Pl011RxStatus::FRAMING | Pl011RxStatus::PARITY | Pl011RxStatus::BREAK)
246        {
247            event |= SerialEvent::RX_ERROR;
248        }
249        if status.contains(Pl011RxStatus::OVERRUN) {
250            event |= SerialEvent::RX_ERROR | SerialEvent::OVERRUN;
251        }
252
253        event
254    }
255
256    pub fn try_write(&mut self, bytes: &[u8]) -> usize {
257        let mut written = 0;
258        for &byte in bytes {
259            let status = self.poll_status();
260            if !status.tx_ready() {
261                break;
262            }
263            self.write_byte(byte);
264            written += 1;
265        }
266        written
267    }
268
269    pub fn try_read(&mut self, bytes: &mut [u8]) -> Result<usize, TransBytesError> {
270        let mut count = 0;
271        for byte in bytes.iter_mut() {
272            let status = self.poll_status();
273            if !status.rx_ready() && !status.rx_error() {
274                break;
275            }
276            match self.read_byte(status) {
277                Some(Ok(b)) => {
278                    *byte = b;
279                }
280                Some(Err(TransferError::Overrun(b))) => {
281                    *byte = b;
282                    count += 1;
283                    return Err(TransBytesError {
284                        bytes_transferred: count,
285                        kind: TransferError::Overrun(b),
286                    });
287                }
288                Some(Err(e)) => {
289                    return Err(TransBytesError {
290                        bytes_transferred: count,
291                        kind: e,
292                    });
293                }
294                None => break,
295            }
296            count += 1;
297        }
298        Ok(count)
299    }
300
301    pub fn write_byte(&mut self, byte: u8) {
302        self.registers().uartdr.set(byte as _);
303    }
304
305    pub fn read_byte(&mut self, status: SerialEvent) -> Option<Result<u8, TransferError>> {
306        if !status.rx_ready() && !status.rx_error() {
307            return None;
308        }
309
310        let sample = self.read_rx()?;
311        if sample.overrun {
312            return Some(Err(TransferError::Overrun(sample.byte.unwrap_or(0))));
313        }
314        match sample.flag {
315            RxFlag::Normal => sample.byte.map(Ok),
316            RxFlag::Break => Some(Err(TransferError::Break)),
317            RxFlag::Parity => Some(Err(TransferError::Parity)),
318            RxFlag::Framing => Some(Err(TransferError::Framing)),
319        }
320    }
321
322    pub fn read_rx(&mut self) -> Option<RxSample> {
323        let base = self.base;
324        // SAFETY: `base` is the mapped PL011 register block owned by this
325        // endpoint and remains valid for the endpoint lifetime.
326        let registers = unsafe { &*base.0.as_ptr() };
327        read_rx_sample(registers, &mut self.saved_rx_status)
328    }
329
330    /// 启用或禁用 FIFO
331    pub fn enable_fifo(&self, enable: bool) {
332        if enable {
333            self.registers().uartlcr_h.modify(UARTLCR_H::FEN::SET);
334        } else {
335            self.registers().uartlcr_h.modify(UARTLCR_H::FEN::CLEAR);
336        }
337    }
338
339    /// 设置 FIFO 触发级别
340    pub fn set_fifo_trigger_level(&self, rx_level: u8, tx_level: u8) {
341        // PL011 FIFO 触发级别:
342        // 0b000: 1/8 full
343        // 0b001: 1/4 full
344        // 0b010: 1/2 full
345        // 0b011: 3/4 full
346        // 0b100: 7/8 full
347
348        let rx_iflsel = match rx_level {
349            0..=2 => 0b000,  // 1/8
350            3..=4 => 0b001,  // 1/4
351            5..=8 => 0b010,  // 1/2
352            9..=12 => 0b011, // 3/4
353            _ => 0b100,      // 7/8
354        };
355
356        let tx_iflsel = match tx_level {
357            0..=2 => 0b000,  // 1/8
358            3..=4 => 0b001,  // 1/4
359            5..=8 => 0b010,  // 1/2
360            9..=12 => 0b011, // 3/4
361            _ => 0b100,      // 7/8
362        };
363
364        self.registers()
365            .uartifls
366            .write(UARTIFLS::RXIFLSEL.val(rx_iflsel) + UARTIFLS::TXIFLSEL.val(tx_iflsel));
367    }
368}