forked from M-Labs/zynq-rs
uart: add baud_rate_gen
This commit is contained in:
parent
43b6d3acd0
commit
b296fc1d7f
43
src/uart/baud_rate_gen.rs
Normal file
43
src/uart/baud_rate_gen.rs
Normal file
@ -0,0 +1,43 @@
|
||||
use crate::regs::*;
|
||||
use super::regs::{RegisterBlock, BaudRateGen, BaudRateDiv};
|
||||
|
||||
const BDIV_MIN: u8 = 4;
|
||||
const BDIV_MAX: u8 = 255;
|
||||
const CD_MAX: u16 = 65535;
|
||||
|
||||
/// Algorithm as in the Linux 5.1 driver
|
||||
pub fn configure(regs: &RegisterBlock, mut clk: u32, baud: u32) {
|
||||
if regs.mode.read().clks() {
|
||||
clk /= 8;
|
||||
}
|
||||
|
||||
let mut best = None;
|
||||
for bdiv in BDIV_MIN..=BDIV_MAX {
|
||||
let bdiv: u32 = bdiv.into();
|
||||
let cd = clk / (baud * (bdiv + 1));
|
||||
if cd < 1 || cd > CD_MAX.into() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let actual_baud = clk / (cd * (bdiv + 1));
|
||||
let error = if baud > actual_baud {
|
||||
baud - actual_baud
|
||||
} else {
|
||||
actual_baud - baud
|
||||
};
|
||||
let better = best
|
||||
.map(|(_cd, _bdiv, best_error)| error < best_error)
|
||||
.unwrap_or(true);
|
||||
if better {
|
||||
best = Some((cd as u16, bdiv as u8, error));
|
||||
}
|
||||
}
|
||||
|
||||
match best {
|
||||
Some((cd, bdiv, error)) => {
|
||||
regs.baud_rate_gen.write(BaudRateGen::zeroed().cd(cd));
|
||||
regs.baud_rate_divider.write(BaudRateDiv::zeroed().bdiv(bdiv));
|
||||
}
|
||||
None => panic!("Cannot configure baud rate")
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ use volatile_register::RW;
|
||||
use crate::regs::*;
|
||||
|
||||
mod regs;
|
||||
mod baud_rate_gen;
|
||||
|
||||
pub struct Uart {
|
||||
regs: &'static mut regs::RegisterBlock,
|
||||
@ -49,12 +50,12 @@ impl Uart {
|
||||
}
|
||||
|
||||
pub fn configure(&self) {
|
||||
// Confiugre UART character frame
|
||||
// Configure UART character frame
|
||||
// * Disable clock-divider
|
||||
// * 8-bit
|
||||
// * 1 stop bit
|
||||
// * Normal channel mode
|
||||
// * no parity
|
||||
// * No parity
|
||||
let parity_mode = regs::ParityMode::None;
|
||||
self.regs.mode.write(
|
||||
regs::Mode::zeroed()
|
||||
@ -66,12 +67,7 @@ impl Uart {
|
||||
self.disable_rx();
|
||||
self.disable_tx();
|
||||
|
||||
// 9,600 baud
|
||||
self.regs.baud_rate_gen.write(regs::BaudRateGen::zeroed().cd(651));
|
||||
self.regs.baud_rate_divider.write(regs::BaudRateDiv::zeroed().bdiv(7));
|
||||
// // 115,200 baud
|
||||
// self.regs.baud_rate_gen.write(regs::BaudRateGen::zeroed().cd(62));
|
||||
// self.regs.baud_rate_divider.write(regs::BaudRateDiv::zeroed().bdiv(6));
|
||||
baud_rate_gen::configure(&self.regs, 50_000_000, 9_600);
|
||||
|
||||
// Enable controller
|
||||
self.reset_rx();
|
||||
|
Loading…
Reference in New Issue
Block a user