use cfg_if::cfg_if;
use crate::{
error::{Error, Result},
pac::RCC,
util::{bounded_loop, rcc_en_reset},
};
cfg_if! {
if #[cfg(feature = "f3")] {
use bxcan;
use crate::pac::{can, CAN};
} else if #[cfg(any(feature = "f4", feature = "l4"))] {
use bxcan;
use crate::pac::{CAN1 as CAN};
} else { use fdcan;
use crate::pac::{FDCAN1 as CAN};
}
}
cfg_if! {
if #[cfg(feature = "g4")] {
pub mod g4;
pub use g4::*;
} else {
pub struct Can {
pub regs: CAN,
}
impl Can {
pub fn new(regs: CAN) -> Self {
let rcc = unsafe { &*RCC::ptr() };
cfg_if! {
if #[cfg(feature = "f3")] {
rcc_en_reset!(apb1, can, rcc);
} else if #[cfg(any(feature = "f4", feature = "l4"))] {
rcc_en_reset!(apb1, can1, rcc);
} else if #[cfg(feature = "h7")]{
rcc.apb1henr().modify(|_, w| w.fdcanen().bit(true));
rcc.apb1hrstr().modify(|_, w| w.fdcanrst().bit(true));
rcc.apb1hrstr().modify(|_, w| w.fdcanrst().clear_bit());
} else {
rcc_en_reset!(apb1, fdcan, rcc);
}
}
Self { regs }
}
pub fn read_status(&self) -> u32 {
cfg_if! {
if #[cfg(any(feature = "h7", feature = "l5"))] {
unsafe { self.regs.psr().read().bits() }
} else {
unsafe { self.regs.msr.read().bits() }
}
}
}
}
#[cfg(feature = "h7")]
pub fn set_message_ram_layout() -> Result<()> {
let regs = unsafe { &(*CAN::ptr()) };
regs.cccr().modify(|_, w| w.init().bit(true));
bounded_loop!(regs.cccr.read().init().bit_is_clear(), Error::RegisterUnchanged);
regs.cccr().modify(|_, w| w.cce().bit(true));
bounded_loop!(regs.cccr.read().cce().bit_is_clear(), Error::RegisterUnchanged);
let mut word_addr = 0x000;
use fdcan::message_ram::*;
regs.sidfc()
.modify(|_, w| unsafe { w.flssa().bits(word_addr) });
word_addr += STANDARD_FILTER_MAX as u16;
regs.xidfc()
.modify(|_, w| unsafe { w.flesa().bits(word_addr) });
word_addr += 2 * EXTENDED_FILTER_MAX as u16;
regs.rxf0c().modify(|_, w| unsafe {
w.f0sa()
.bits(word_addr)
.f0s()
.bits(RX_FIFO_MAX)
.f0wm()
.bits(RX_FIFO_MAX)
});
word_addr += 18 * RX_FIFO_MAX as u16;
regs.rxf1c().modify(|_, w| unsafe {
w.f1sa()
.bits(word_addr)
.f1s()
.bits(RX_FIFO_MAX)
.f1wm()
.bits(RX_FIFO_MAX)
});
word_addr += 18 * RX_FIFO_MAX as u16;
regs.txefc().modify(|_, w| unsafe {
w.efsa()
.bits(word_addr)
.efs()
.bits(TX_EVENT_MAX)
.efwm()
.bits(TX_EVENT_MAX)
});
word_addr += 2 * TX_EVENT_MAX as u16;
regs.txbc()
.modify(|_, w| unsafe { w.tbsa().bits(word_addr).tfqs().bits(TX_FIFO_MAX) });
word_addr += 18 * TX_FIFO_MAX as u16;
regs.rxbc().modify(|_, w| unsafe { w.rbsa().bits(word_addr) });
regs.rxesc()
.modify(|_, w| unsafe { w.rbds().bits(0b111).f1ds().bits(0b111).f0ds().bits(0b111) });
regs.txesc().modify(|_, w| unsafe { w.tbds().bits(0b111) });
}
cfg_if! {
if #[cfg(feature = "can_bx")] {
unsafe impl bxcan::Instance for Can {
const REGISTERS: *mut bxcan::RegisterBlock = CAN::ptr() as *mut _;
}
unsafe impl bxcan::FilterOwner for Can {
#[cfg(any(feature = "f3", feature = "f4"))]
const NUM_FILTER_BANKS: u8 = 28;
#[cfg(any(feature = "l4"))]
const NUM_FILTER_BANKS: u8 = 14;
}
unsafe impl bxcan::MasterInstance for Can {}
} else {
unsafe impl fdcan::Instance for Can {
const REGISTERS: *mut fdcan::RegisterBlock = CAN::ptr() as *mut _;
}
unsafe impl fdcan::message_ram::Instance for Can {
#[cfg(feature = "h7")]
const MSG_RAM: *mut fdcan::message_ram::RegisterBlock = (0x4000_ac00 as *mut _);
}
}
}
}
}