some_serial/
pl011.rs

1use core::ptr::NonNull;
2
3use crate::Register;
4use rdif_serial::{Serial, TransferError};
5use tock_registers::{interfaces::*, register_bitfields, register_structs, registers::*};
6
7use crate::{Config, ConfigError, DataBits, InterruptMask, LineStatus, Parity, StopBits};
8
9register_bitfields! [
10    u32,
11
12    /// Data Register
13    UARTDR [
14        DATA OFFSET(0) NUMBITS(8) [],
15        FE OFFSET(8) NUMBITS(1) [],
16        PE OFFSET(9) NUMBITS(1) [],
17        BE OFFSET(10) NUMBITS(1) [],
18        OE OFFSET(11) NUMBITS(1) []
19    ],
20
21    /// Receive Status Register / Error Clear Register
22    UARTRSR_ECR [
23        FE OFFSET(0) NUMBITS(1) [],
24        PE OFFSET(1) NUMBITS(1) [],
25        BE OFFSET(2) NUMBITS(1) [],
26        OE OFFSET(3) NUMBITS(1) []
27    ],
28
29    /// Flag Register
30    UARTFR [
31        CTS OFFSET(0) NUMBITS(1) [],
32        DSR OFFSET(1) NUMBITS(1) [],
33        DCD OFFSET(2) NUMBITS(1) [],
34        BUSY OFFSET(3) NUMBITS(1) [],
35        RXFE OFFSET(4) NUMBITS(1) [],
36        TXFF OFFSET(5) NUMBITS(1) [],
37        RXFF OFFSET(6) NUMBITS(1) [],
38        TXFE OFFSET(7) NUMBITS(1) [],
39        RI OFFSET(8) NUMBITS(1) []
40    ],
41
42    /// Integer Baud Rate Register
43    UARTIBRD [
44        BAUD_DIVINT OFFSET(0) NUMBITS(16) []
45    ],
46
47    /// Fractional Baud Rate Register
48    UARTFBRD [
49        BAUD_DIVFRAC OFFSET(0) NUMBITS(6) []
50    ],
51
52    /// Line Control Register
53    UARTLCR_H [
54        BRK OFFSET(0) NUMBITS(1) [],
55        PEN OFFSET(1) NUMBITS(1) [],
56        EPS OFFSET(2) NUMBITS(1) [],
57        STP2 OFFSET(3) NUMBITS(1) [],
58        FEN OFFSET(4) NUMBITS(1) [],
59        WLEN OFFSET(5) NUMBITS(2) [
60            FiveBit = 0,
61            SixBit = 1,
62            SevenBit = 2,
63            EightBit = 3
64        ],
65        SPS OFFSET(7) NUMBITS(1) []
66    ],
67
68    /// Control Register
69    UARTCR [
70        UARTEN OFFSET(0) NUMBITS(1) [],
71        SIREN OFFSET(1) NUMBITS(1) [],
72        SIRLP OFFSET(2) NUMBITS(1) [],
73        LBE OFFSET(7) NUMBITS(1) [],
74        TXE OFFSET(8) NUMBITS(1) [],
75        RXE OFFSET(9) NUMBITS(1) [],
76        DTR OFFSET(10) NUMBITS(1) [],
77        RTS OFFSET(11) NUMBITS(1) [],
78        OUT1 OFFSET(12) NUMBITS(1) [],
79        OUT2 OFFSET(13) NUMBITS(1) [],
80        RTSEN OFFSET(14) NUMBITS(1) [],
81        CTSEN OFFSET(15) NUMBITS(1) []
82    ],
83
84    /// Interrupt FIFO Level Select Register
85    UARTIFLS [
86        TXIFLSEL OFFSET(0) NUMBITS(3) [],
87        RXIFLSEL OFFSET(3) NUMBITS(3) []
88    ],
89
90    /// Interrupt Mask Set/Clear Register
91    UARTIS [
92        RIM OFFSET(0) NUMBITS(1) [],
93        CTSM OFFSET(1) NUMBITS(1) [],
94        DCDM OFFSET(2) NUMBITS(1) [],
95        DSRM OFFSET(3) NUMBITS(1) [],
96        RX OFFSET(4) NUMBITS(1) [],
97        TX OFFSET(5) NUMBITS(1) [],
98        RT OFFSET(6) NUMBITS(1) [],
99        FE OFFSET(7) NUMBITS(1) [],
100        PE OFFSET(8) NUMBITS(1) [],
101        BE OFFSET(9) NUMBITS(1) [],
102        OE OFFSET(10) NUMBITS(1) []
103    ],
104
105    /// DMA Control Register
106    UARTDMACR [
107        RXDMAE OFFSET(0) NUMBITS(1) [],
108        TXDMAE OFFSET(1) NUMBITS(1) [],
109        DMAONERR OFFSET(2) NUMBITS(1) []
110    ]
111];
112
113register_structs! {
114    pub Pl011Registers {
115        (0x000 => uartdr: ReadWrite<u32, UARTDR::Register>),        // 数据寄存器(收发数据/错误标志)
116        (0x004 => uartrsr_ecr: ReadWrite<u32, UARTRSR_ECR::Register>), // 接收状态/错误清除寄存器
117        (0x008 => _reserved1),                                      // 保留
118        (0x018 => uartfr: ReadOnly<u32, UARTFR::Register>),         // 标志寄存器(状态标志,如忙/空/满等)
119        (0x01c => _reserved2),                                      // 保留
120        (0x020 => uartilpr: ReadWrite<u32>),                        // 红外低功耗波特率寄存器(很少用)
121        (0x024 => uartibrd: ReadWrite<u32, UARTIBRD::Register>),    // 整数波特率分频寄存器
122        (0x028 => uartfbrd: ReadWrite<u32, UARTFBRD::Register>),    // 小数波特率分频寄存器
123        (0x02c => uartlcr_h: ReadWrite<u32, UARTLCR_H::Register>),  // 线路控制寄存器(数据位、停止位、校验等)
124        (0x030 => uartcr: ReadWrite<u32, UARTCR::Register>),        // 控制寄存器(UART使能、收发使能等)
125        (0x034 => uartifls: ReadWrite<u32, UARTIFLS::Register>),    // FIFO中断触发级别选择寄存器
126        (0x038 => uartimsc: ReadWrite<u32, UARTIS::Register>),      // 中断屏蔽设置/清除寄存器
127        (0x03c => uartris: ReadOnly<u32, UARTIS::Register>),        // 原始中断状态寄存器
128        (0x040 => uartmis: ReadOnly<u32, UARTIS::Register>),        // 屏蔽后的中断状态寄存器
129        (0x044 => uarticr: WriteOnly<u32, UARTIS::Register>),       // 中断清除寄存器
130        (0x048 => uartdmacr: ReadWrite<u32, UARTDMACR::Register>),  // DMA控制寄存器
131        (0x04c => _reserved3),                                      // 保留
132        (0x1000 => @END),
133    }
134}
135
136// SAFETY: PL011 寄存器访问是原子的,硬件保证了内存映射寄存器的线程安全
137unsafe impl Sync for Pl011Registers {}
138
139/// PL011 UART 驱动结构体
140#[derive(Clone)]
141pub struct Pl011 {
142    base: NonNull<Pl011Registers>,
143    clock_freq: u32,
144}
145
146unsafe impl Send for Pl011 {}
147unsafe impl Sync for Pl011 {}
148
149impl Pl011 {
150    /// 创建新的 PL011 实例(仅基地址,使用默认配置)
151    ///
152    /// # Arguments
153    /// * `base` - UART 寄存器基地址
154    pub fn new_no_clock(base: NonNull<u8>) -> Serial<Self> {
155        // 自动检测时钟频率或使用合理的默认值
156        let clock_freq = Self::detect_clock_frequency(base.as_ptr() as usize);
157        Self::new(base, clock_freq)
158    }
159
160    pub fn new(base: NonNull<u8>, clock_freq: u32) -> Serial<Self> {
161        Serial::new(Self {
162            base: base.cast(),
163            clock_freq,
164        })
165    }
166
167    fn registers(&self) -> &Pl011Registers {
168        unsafe { self.base.as_ref() }
169    }
170
171    /// 自动检测或确定合理的时钟频率
172    fn detect_clock_frequency(base: usize) -> u32 {
173        // 尝试读取当前波特率设置来反向推算时钟频率
174        let registers = unsafe { &*(base as *const Pl011Registers) };
175
176        use tock_registers::interfaces::Readable;
177        let ibrd = registers.uartibrd.read(UARTIBRD::BAUD_DIVINT);
178
179        // 如果有设置值,假设波特率为 115200 来估算时钟频率
180        if ibrd > 0 && ibrd <= 0xFFFF {
181            // 假设波特率为 115200,计算时钟频率
182            // FUARTCLK = 16 * BAUDDIV * Baud rate
183            let estimated_clock = 16 * ibrd * 115200;
184
185            // 合理的时钟频率范围:1MHz - 100MHz
186            if (1_000_000..=100_000_000).contains(&estimated_clock) {
187                return estimated_clock;
188            }
189        }
190
191        // 默认使用 24MHz(最常见)
192        24_000_000
193    }
194
195    // 内部私有方法,用于配置
196    fn set_baudrate_internal(&self, baudrate: u32) -> Result<(), ConfigError> {
197        // PL011 波特率计算公式:
198        // BAUDDIV = (FUARTCLK / (16 * Baud rate))
199        // IBRD = integer(BAUDDIV)
200        // FBRD = integer((BAUDDIV - IBRD) * 64 + 0.5)
201
202        let bauddiv = self.clock_freq / (16 * baudrate);
203        let remainder = self.clock_freq % (16 * baudrate);
204        let fbrd = (remainder * 64 + (16 * baudrate / 2)) / (16 * baudrate);
205
206        if bauddiv == 0 || bauddiv > 0xFFFF {
207            return Err(ConfigError::InvalidBaudrate);
208        }
209
210        self.registers()
211            .uartibrd
212            .write(UARTIBRD::BAUD_DIVINT.val(bauddiv));
213        self.registers()
214            .uartfbrd
215            .write(UARTFBRD::BAUD_DIVFRAC.val(fbrd));
216
217        Ok(())
218    }
219
220    fn set_data_bits_internal(&self, bits: DataBits) -> Result<(), ConfigError> {
221        let wlen = match bits {
222            DataBits::Five => UARTLCR_H::WLEN::FiveBit,
223            DataBits::Six => UARTLCR_H::WLEN::SixBit,
224            DataBits::Seven => UARTLCR_H::WLEN::SevenBit,
225            DataBits::Eight => UARTLCR_H::WLEN::EightBit,
226        };
227
228        self.registers().uartlcr_h.modify(wlen);
229        Ok(())
230    }
231
232    fn set_stop_bits_internal(&self, bits: StopBits) -> Result<(), ConfigError> {
233        match bits {
234            StopBits::One => self.registers().uartlcr_h.modify(UARTLCR_H::STP2::CLEAR),
235            StopBits::Two => self.registers().uartlcr_h.modify(UARTLCR_H::STP2::SET),
236        }
237
238        Ok(())
239    }
240
241    fn set_parity_internal(&self, parity: Parity) -> Result<(), ConfigError> {
242        match parity {
243            Parity::None => {
244                // PEN = 0, 无奇偶校验
245                self.registers().uartlcr_h.modify(UARTLCR_H::PEN::CLEAR);
246            }
247            Parity::Odd => {
248                // PEN = 1, EPS = 0 (奇校验), SPS = 0
249                self.registers()
250                    .uartlcr_h
251                    .modify(UARTLCR_H::PEN::SET + UARTLCR_H::EPS::CLEAR + UARTLCR_H::SPS::CLEAR);
252            }
253            Parity::Even => {
254                // PEN = 1, EPS = 1 (偶校验), SPS = 0
255                self.registers()
256                    .uartlcr_h
257                    .modify(UARTLCR_H::PEN::SET + UARTLCR_H::EPS::SET + UARTLCR_H::SPS::CLEAR);
258            }
259            Parity::Mark => {
260                // PEN = 1, SPS = 1, EPS = 0 (奇校验)
261                self.registers()
262                    .uartlcr_h
263                    .modify(UARTLCR_H::PEN::SET + UARTLCR_H::EPS::CLEAR + UARTLCR_H::SPS::SET);
264            }
265            Parity::Space => {
266                // PEN = 1, EPS = 1 (偶校验), SPS = 1
267                self.registers()
268                    .uartlcr_h
269                    .modify(UARTLCR_H::PEN::SET + UARTLCR_H::EPS::SET + UARTLCR_H::SPS::SET);
270            }
271        }
272
273        Ok(())
274    }
275
276    /// 初始化 PL011 UART
277    fn init(&self) {
278        // 禁用 UART
279        self.registers().uartcr.modify(UARTCR::UARTEN::CLEAR);
280
281        // 等待当前传输完成
282        while self.registers().uartfr.is_set(UARTFR::BUSY) {
283            core::hint::spin_loop();
284        }
285
286        // 清除发送 FIFO
287        self.registers().uartlcr_h.modify(UARTLCR_H::FEN::CLEAR);
288
289        // 启用 FIFO
290        self.registers().uartlcr_h.modify(UARTLCR_H::FEN::SET);
291
292        // 调试信息:输出 FIFO 配置
293        #[cfg(debug_assertions)]
294        {
295            let ifls = self.registers().uartifls.get();
296            let lcr_h = self.registers().uartlcr_h.get();
297            log::debug!("UART IFLS: 0x{:02x}, LCR_H: 0x{:02x}", ifls, lcr_h);
298            log::debug!("  FIFO enabled: {}", lcr_h & (1 << 4) != 0);
299            log::debug!("  RX trigger level: 1/8");
300            log::debug!("  TX trigger level: 1/2");
301        }
302        self.registers().uartimsc.set(0); // 禁用所有中断
303                                          // 启用 UART
304        self.registers()
305            .uartcr
306            .modify(UARTCR::UARTEN::SET + UARTCR::TXE::SET + UARTCR::RXE::SET);
307    }
308}
309
310impl Register for Pl011 {
311    fn write_byte(&mut self, byte: u8) {
312        self.registers().uartdr.write(UARTDR::DATA.val(byte as u32));
313    }
314
315    fn read_byte(&mut self) -> Result<u8, TransferError> {
316        let dr = self.registers().uartdr.extract();
317        let data = dr.read(UARTDR::DATA) as u8;
318
319        if dr.is_set(UARTDR::FE) {
320            return Err(TransferError::Framing);
321        }
322
323        if dr.is_set(UARTDR::PE) {
324            return Err(TransferError::Parity);
325        }
326
327        if dr.is_set(UARTDR::OE) {
328            return Err(TransferError::Overrun(data));
329        }
330
331        if dr.is_set(UARTDR::BE) {
332            return Err(TransferError::Break);
333        }
334
335        Ok(data)
336    }
337
338    fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
339        use tock_registers::interfaces::Readable;
340
341        // 根据ARM文档的建议配置流程:
342        // 1. 禁用UART
343        let original_enable = self.registers().uartcr.is_set(UARTCR::UARTEN); // 保存原始使能状态
344        self.registers().uartcr.modify(UARTCR::UARTEN::CLEAR); // 禁用UART
345
346        // 2. 等待当前字符传输完成
347        while self.registers().uartfr.is_set(UARTFR::BUSY) {
348            core::hint::spin_loop();
349        }
350
351        // 3. 刷新发送FIFO(通过设置FEN=0)
352        self.registers().uartlcr_h.modify(UARTLCR_H::FEN::CLEAR);
353
354        // 4. 配置各项参数
355        if let Some(baudrate) = config.baudrate {
356            self.set_baudrate_internal(baudrate)?;
357        }
358        if let Some(data_bits) = config.data_bits {
359            self.set_data_bits_internal(data_bits)?;
360        }
361        if let Some(stop_bits) = config.stop_bits {
362            self.set_stop_bits_internal(stop_bits)?;
363        }
364        if let Some(parity) = config.parity {
365            self.set_parity_internal(parity)?;
366        }
367
368        // 5. 重新启用FIFO
369        self.registers().uartlcr_h.modify(UARTLCR_H::FEN::SET);
370
371        // 6. 恢复UART使能状态
372        if original_enable {
373            self.registers().uartcr.modify(UARTCR::UARTEN::SET); // 重新启用UART
374        }
375
376        Ok(())
377    }
378
379    fn baudrate(&self) -> u32 {
380        let ibrd = self.registers().uartibrd.read(UARTIBRD::BAUD_DIVINT);
381        let fbrd = self.registers().uartfbrd.read(UARTFBRD::BAUD_DIVFRAC);
382
383        // 反向计算波特率
384        // Baud rate = FUARTCLK / (16 * (IBRD + FBRD/64))
385        let divisor = ibrd * 64 + fbrd;
386        if divisor == 0 {
387            return 0;
388        }
389
390        self.clock_freq * 64 / (16 * divisor)
391    }
392
393    fn data_bits(&self) -> DataBits {
394        let wlen = self.registers().uartlcr_h.read(UARTLCR_H::WLEN);
395
396        match wlen {
397            0 => DataBits::Five,
398            1 => DataBits::Six,
399            2 => DataBits::Seven,
400            3 => DataBits::Eight,
401            _ => DataBits::Eight, // 默认值
402        }
403    }
404
405    fn stop_bits(&self) -> StopBits {
406        if self.registers().uartlcr_h.is_set(UARTLCR_H::STP2) {
407            StopBits::Two
408        } else {
409            StopBits::One
410        }
411    }
412
413    fn parity(&self) -> Parity {
414        if !self.registers().uartlcr_h.is_set(UARTLCR_H::PEN) {
415            Parity::None
416        } else if self.registers().uartlcr_h.is_set(UARTLCR_H::SPS) {
417            // Stick parity
418            if self.registers().uartlcr_h.is_set(UARTLCR_H::EPS) {
419                Parity::Space
420            } else {
421                Parity::Mark
422            }
423        } else {
424            // Normal parity
425            if self.registers().uartlcr_h.is_set(UARTLCR_H::EPS) {
426                Parity::Even
427            } else {
428                Parity::Odd
429            }
430        }
431    }
432
433    fn open(&mut self) {
434        self.init()
435    }
436
437    fn close(&mut self) {
438        // 禁用 UART
439        self.registers().uartcr.modify(UARTCR::UARTEN::CLEAR);
440    }
441
442    fn clean_interrupt_status(&mut self) -> InterruptMask {
443        let mis = self.registers().uartmis.extract();
444        let mut mask = InterruptMask::empty();
445
446        if mis.is_set(UARTIS::RX) {
447            mask |= InterruptMask::RX_AVAILABLE;
448        }
449        if mis.is_set(UARTIS::TX) {
450            mask |= InterruptMask::TX_EMPTY;
451        }
452
453        self.registers().uarticr.set(mis.get());
454
455        mask
456    }
457
458    fn line_status(&mut self) -> LineStatus {
459        let mut status = LineStatus::empty();
460
461        let fr = self.registers().uartfr.extract();
462
463        if !fr.is_set(UARTFR::RXFE) {
464            status |= LineStatus::DATA_READY;
465        }
466
467        if !fr.is_set(UARTFR::TXFF) {
468            status |= LineStatus::TX_HOLDING_EMPTY;
469        }
470
471        status
472    }
473
474    fn read_reg(&self, offset: usize) -> u32 {
475        let addr = unsafe { self.base.cast::<u8>().add(offset) };
476        unsafe { addr.cast().read_volatile() }
477    }
478
479    fn write_reg(&mut self, offset: usize, value: u32) {
480        let addr = unsafe { self.base.cast::<u8>().add(offset) };
481        unsafe { addr.cast().write_volatile(value) };
482    }
483
484    fn get_base(&self) -> usize {
485        self.base.as_ptr() as usize
486    }
487
488    fn set_base(&mut self, base: usize) {
489        self.base = NonNull::new(base as *mut Pl011Registers).unwrap();
490    }
491
492    fn clock_freq(&self) -> u32 {
493        self.clock_freq
494    }
495
496    fn enable_loopback(&mut self) {
497        self.registers().uartcr.modify(UARTCR::LBE::SET);
498    }
499
500    fn disable_loopback(&mut self) {
501        self.registers().uartcr.modify(UARTCR::LBE::CLEAR);
502    }
503
504    fn is_loopback_enabled(&self) -> bool {
505        self.registers().uartcr.is_set(UARTCR::LBE)
506    }
507
508    fn set_irq_mask(&mut self, mask: InterruptMask) {
509        let mut imsc = 0;
510        if mask.contains(InterruptMask::RX_AVAILABLE) {
511            imsc += UARTIS::RX::SET.value;
512        }
513        if mask.contains(InterruptMask::TX_EMPTY) {
514            imsc += UARTIS::TX::SET.value;
515        }
516
517        self.registers().uartimsc.set(imsc);
518    }
519
520    fn get_irq_mask(&self) -> InterruptMask {
521        let imsc = self.registers().uartimsc.extract();
522        let mut mask = InterruptMask::empty();
523
524        if imsc.is_set(UARTIS::RX) {
525            mask |= InterruptMask::RX_AVAILABLE;
526        }
527        if imsc.is_set(UARTIS::TX) {
528            mask |= InterruptMask::TX_EMPTY;
529        }
530
531        mask
532    }
533}
534
535// 额外的便利方法,用于 FIFO 和流控制
536impl Pl011 {
537    /// 启用或禁用 FIFO
538    pub fn enable_fifo(&self, enable: bool) {
539        if enable {
540            self.registers().uartlcr_h.modify(UARTLCR_H::FEN::SET);
541        } else {
542            self.registers().uartlcr_h.modify(UARTLCR_H::FEN::CLEAR);
543        }
544    }
545
546    /// 设置 FIFO 触发级别
547    pub fn set_fifo_trigger_level(&self, rx_level: u8, tx_level: u8) {
548        // PL011 FIFO 触发级别:
549        // 0b000: 1/8 full
550        // 0b001: 1/4 full
551        // 0b010: 1/2 full
552        // 0b011: 3/4 full
553        // 0b100: 7/8 full
554
555        let rx_iflsel = match rx_level {
556            0..=2 => 0b000,  // 1/8
557            3..=4 => 0b001,  // 1/4
558            5..=8 => 0b010,  // 1/2
559            9..=12 => 0b011, // 3/4
560            _ => 0b100,      // 7/8
561        };
562
563        let tx_iflsel = match tx_level {
564            0..=2 => 0b000,  // 1/8
565            3..=4 => 0b001,  // 1/4
566            5..=8 => 0b010,  // 1/2
567            9..=12 => 0b011, // 3/4
568            _ => 0b100,      // 7/8
569        };
570
571        self.registers()
572            .uartifls
573            .write(UARTIFLS::RXIFLSEL.val(rx_iflsel) + UARTIFLS::TXIFLSEL.val(tx_iflsel));
574    }
575}
576
577// ModemStatus 现在在 lib.rs 中定义,这里只是导出