use crate::clocks::{phclk, Stm32f4Clocks};
use core::cell::Cell;
use kernel::deferred_call::{DeferredCall, DeferredCallClient};
use kernel::hil::can::{self, StandardBitTiming};
use kernel::platform::chip::ClockInterface;
use kernel::utilities::cells::{OptionalCell, TakeCell};
use kernel::utilities::registers::interfaces::{ReadWriteable, Readable};
use kernel::utilities::registers::{register_bitfields, register_structs, ReadWrite};
use kernel::utilities::StaticRef;
pub const BRP_MIN_STM32: u32 = 0;
pub const BRP_MAX_STM32: u32 = 1023;
pub const TX_MAILBOX_COUNT: usize = 3;
pub const RX_MAILBOX_COUNT: usize = 2;
pub const FILTER_COUNT: usize = 56;
register_structs! {
pub Registers {
(0x000 => can_mcr: ReadWrite<u32, CAN_MCR::Register>),
(0x004 => can_msr: ReadWrite<u32, CAN_MSR::Register>),
(0x008 => can_tsr: ReadWrite<u32, CAN_TSR::Register>),
(0x00c => can_rf0r: ReadWrite<u32, CAN_RF0R::Register>),
(0x010 => can_rf1r: ReadWrite<u32, CAN_RF1R::Register>),
(0x014 => can_ier: ReadWrite<u32, CAN_IER::Register>),
(0x018 => can_esr: ReadWrite<u32, CAN_ESR::Register>),
(0x01c => can_btr: ReadWrite<u32, CAN_BTR::Register>),
(0x020 => _reserved0),
(0x180 => can_tx_mailbox: [TransmitMailBox; TX_MAILBOX_COUNT]),
(0x1b0 => can_rx_mailbox: [ReceiveMailBox; RX_MAILBOX_COUNT]),
(0x1d0 => _reserved1),
(0x200 => can_fmr: ReadWrite<u32, CAN_FMR::Register>),
(0x204 => can_fm1r: ReadWrite<u32, CAN_FM1R::Register>),
(0x208 => _reserved2),
(0x20c => can_fs1r: ReadWrite<u32, CAN_FS1R::Register>),
(0x210 => _reserved3),
(0x214 => can_ffa1r: ReadWrite<u32, CAN_FFA1R::Register>),
(0x218 => _reserved4),
(0x21c => can_fa1r: ReadWrite<u32, CAN_FA1R::Register>),
(0x220 => _reserved5),
(0x240 => can_firx: [ReadWrite<u32, CAN_FiRx::Register>; FILTER_COUNT]),
(0x320 => @END),
},
TransmitMailBox {
(0x00 => can_tir: ReadWrite<u32, CAN_TIxR::Register>),
(0x04 => can_tdtr: ReadWrite<u32, CAN_TDTxR::Register>),
(0x08 => can_tdlr: ReadWrite<u32, CAN_TDLxR::Register>),
(0x0c => can_tdhr: ReadWrite<u32, CAN_TDHxR::Register>),
(0x010 => @END),
},
ReceiveMailBox {
(0x00 => can_rir: ReadWrite<u32, CAN_RIxR::Register>),
(0x04 => can_rdtr: ReadWrite<u32, CAN_RDTxR::Register>),
(0x08 => can_rdlr: ReadWrite<u32, CAN_RDLxR::Register>),
(0x0c => can_rdhr: ReadWrite<u32, CAN_RDHxR::Register>),
(0x010 => @END),
}
}
register_bitfields![u32,
CAN_MCR [
DBF OFFSET(16) NUMBITS(1) [],
RESET OFFSET(15) NUMBITS(1) [],
TTCM OFFSET(7) NUMBITS(1) [],
ABOM OFFSET(6) NUMBITS(1) [],
AWUM OFFSET(5) NUMBITS(1) [],
NART OFFSET(4) NUMBITS(1) [],
RFLM OFFSET(3) NUMBITS(1) [],
TXFP OFFSET(2) NUMBITS(1) [],
SLEEP OFFSET(1) NUMBITS(1) [],
INRQ OFFSET(0) NUMBITS(1) []
],
CAN_MSR [
RX OFFSET(11) NUMBITS(1) [],
SAMP OFFSET(10) NUMBITS(1) [],
RXM OFFSET(9) NUMBITS(1) [],
TXM OFFSET(8) NUMBITS(1) [],
SLAKI OFFSET(4) NUMBITS(1) [],
WKUI OFFSET(3) NUMBITS(1) [],
ERRI OFFSET(2) NUMBITS(1) [],
SLAK OFFSET(1) NUMBITS(1) [],
INAK OFFSET(0) NUMBITS(1) []
],
CAN_TSR [
LOW2 OFFSET(31) NUMBITS(1) [],
LOW1 OFFSET(30) NUMBITS(1) [],
LOW0 OFFSET(29) NUMBITS(1) [],
TME2 OFFSET(28) NUMBITS(1) [],
TME1 OFFSET(27) NUMBITS(1) [],
TME0 OFFSET(26) NUMBITS(1) [],
CODE OFFSET(24) NUMBITS(2) [],
ABRQ2 OFFSET(23) NUMBITS(1) [],
TERR2 OFFSET(19) NUMBITS(1) [],
ALST2 OFFSET(18) NUMBITS(1) [],
TXOK2 OFFSET(17) NUMBITS(1) [],
RQCP2 OFFSET(16) NUMBITS(1) [],
ABRQ1 OFFSET(15) NUMBITS(1) [],
TERR1 OFFSET(11) NUMBITS(1) [],
ALST1 OFFSET(10) NUMBITS(1) [],
TXOK1 OFFSET(9) NUMBITS(1) [],
RQCP1 OFFSET(8) NUMBITS(1) [],
ABRQ0 OFFSET(7) NUMBITS(1) [],
TERR0 OFFSET(3) NUMBITS(1) [],
ALST0 OFFSET(2) NUMBITS(1) [],
TXOK0 OFFSET(1) NUMBITS(1) [],
RQCP0 OFFSET(0) NUMBITS(1) []
],
CAN_RF0R [
RFOM0 OFFSET(5) NUMBITS(1) [],
FOVR0 OFFSET(4) NUMBITS(1) [],
FULL0 OFFSET(3) NUMBITS(1) [],
FMP0 OFFSET(0) NUMBITS(2) []
],
CAN_RF1R [
RFOM1 OFFSET(5) NUMBITS(1) [],
FOVR1 OFFSET(4) NUMBITS(1) [],
FULL1 OFFSET(3) NUMBITS(1) [],
FMP1 OFFSET(0) NUMBITS(2) []
],
CAN_IER [
SLKIE OFFSET(17) NUMBITS(1) [],
WKUIE OFFSET(16) NUMBITS(1) [],
ERRIE OFFSET(15) NUMBITS(1) [],
LECIE OFFSET(11) NUMBITS(1) [],
BOFIE OFFSET(10) NUMBITS(1) [],
EPVIE OFFSET(9) NUMBITS(1) [],
EWGIE OFFSET(8) NUMBITS(1) [],
FOVIE1 OFFSET(6) NUMBITS(1) [],
FFIE1 OFFSET(5) NUMBITS(1) [],
FMPIE1 OFFSET(4) NUMBITS(1) [],
FOVIE0 OFFSET(3) NUMBITS(1) [],
FFIE0 OFFSET(2) NUMBITS(1) [],
FMPIE0 OFFSET(1) NUMBITS(1) [],
TMEIE OFFSET(0) NUMBITS(1) []
],
CAN_ESR [
REC OFFSET(24) NUMBITS(8) [],
TEC OFFSET(16) NUMBITS(8) [],
LEC OFFSET(4) NUMBITS(3) [
NoError = 0,
StuffError = 1,
FormError = 2,
AcknowledgmentError = 3,
BitRecessiveError = 4,
BitDominantError = 5,
CrcError = 6,
SetBySoftware = 7
],
BOFF OFFSET(2) NUMBITS(1) [],
EPVF OFFSET(1) NUMBITS(1) [],
EWGF OFFSET(0) NUMBITS(1) []
],
CAN_BTR [
SILM OFFSET(31) NUMBITS(1) [],
LBKM OFFSET(30) NUMBITS(1) [],
SJW OFFSET(24) NUMBITS(2) [],
TS2 OFFSET(20) NUMBITS(3) [],
TS1 OFFSET(16) NUMBITS(4) [],
BRP OFFSET(0) NUMBITS(10) []
],
CAN_TIxR [
STID OFFSET(21) NUMBITS(11) [],
EXID OFFSET(3) NUMBITS(18) [],
IDE OFFSET(2) NUMBITS(1) [],
RTR OFFSET(1) NUMBITS(1) [],
TXRQ OFFSET(0) NUMBITS(1) []
],
CAN_TDTxR [
TIME OFFSET(16) NUMBITS(16) [],
TGT OFFSET(8) NUMBITS(1) [],
DLC OFFSET(0) NUMBITS(4) []
],
CAN_TDLxR [
DATA3 OFFSET(24) NUMBITS(8) [],
DATA2 OFFSET(16) NUMBITS(8) [],
DATA1 OFFSET(8) NUMBITS(8) [],
DATA0 OFFSET(0) NUMBITS(8) []
],
CAN_TDHxR [
DATA7 OFFSET(24) NUMBITS(8) [],
DATA6 OFFSET(16) NUMBITS(8) [],
DATA5 OFFSET(8) NUMBITS(8) [],
DATA4 OFFSET(0) NUMBITS(8) []
],
CAN_RIxR [
STID OFFSET(21) NUMBITS(11) [],
EXID OFFSET(3) NUMBITS(18) [],
IDE OFFSET(2) NUMBITS(1) [],
RTR OFFSET(1) NUMBITS(1) []
],
CAN_RDTxR [
TIME OFFSET(16) NUMBITS(16) [],
FMI OFFSET(8) NUMBITS(8) [],
DLC OFFSET(0) NUMBITS(4) []
],
CAN_RDLxR [
DATA3 OFFSET(24) NUMBITS(8) [],
DATA2 OFFSET(16) NUMBITS(8) [],
DATA1 OFFSET(8) NUMBITS(8) [],
DATA0 OFFSET(0) NUMBITS(8) []
],
CAN_RDHxR [
DATA7 OFFSET(24) NUMBITS(8) [],
DATA6 OFFSET(16) NUMBITS(8) [],
DATA5 OFFSET(8) NUMBITS(8) [],
DATA4 OFFSET(0) NUMBITS(8) []
],
CAN_FMR [
CANSB OFFSET(8) NUMBITS(6) [],
FINIT OFFSET(0) NUMBITS(1) []
],
CAN_FM1R [
FBM OFFSET(0) NUMBITS(28) []
],
CAN_FS1R [
FSC OFFSET(0) NUMBITS(28) []
],
CAN_FFA1R [
FFA OFFSET(0) NUMBITS(28) []
],
CAN_FA1R [
FACT OFFSET(0) NUMBITS(28) []
],
CAN_FiRx [
FB OFFSET(0) NUMBITS(32) []
]
];
#[derive(Copy, Clone, PartialEq)]
enum CanState {
Initialization,
Normal,
Sleep,
RunningError(can::Error),
}
#[derive(Copy, Clone, PartialEq)]
enum AsyncAction {
Enable,
AbortReceive,
Disabled,
EnableError(kernel::ErrorCode),
}
#[repr(u32)]
enum BitSegment1 {
CanBtrTs1Min = 0b0000,
CanBtrTs1Max = 0b1111,
}
#[repr(u32)]
enum BitSegment2 {
CanBtrTs2Min = 0b0000,
CanBtrTs2Max = 0b0111,
}
#[repr(u32)]
enum SynchronizationJumpWidth {
CanBtrSjwMin = 0b00,
CanBtrSjwMax = 0b11,
}
#[derive(Copy, Clone, PartialEq)]
pub enum CanInterruptMode {
TransmitInterrupt,
Fifo0Interrupt,
Fifo1Interrupt,
ErrorAndStatusChangeInterrupt,
}
impl From<CanState> for can::State {
fn from(state: CanState) -> Self {
match state {
CanState::Initialization | CanState::Sleep => can::State::Disabled,
CanState::Normal => can::State::Running,
CanState::RunningError(err) => can::State::Error(err),
}
}
}
pub struct Can<'a> {
registers: StaticRef<Registers>,
clock: CanClock<'a>,
can_state: Cell<CanState>,
error_interrupt_counter: Cell<u32>,
fifo0_interrupt_counter: Cell<u32>,
fifo1_interrupt_counter: Cell<u32>,
failed_messages: Cell<u32>,
automatic_retransmission: Cell<bool>,
automatic_wake_up: Cell<bool>,
operating_mode: OptionalCell<can::OperationMode>,
bit_timing: OptionalCell<can::BitTiming>,
controller_client: OptionalCell<&'static dyn can::ControllerClient>,
receive_client:
OptionalCell<&'static dyn can::ReceiveClient<{ can::STANDARD_CAN_PACKET_SIZE }>>,
transmit_client:
OptionalCell<&'static dyn can::TransmitClient<{ can::STANDARD_CAN_PACKET_SIZE }>>,
rx_buffer: TakeCell<'static, [u8; can::STANDARD_CAN_PACKET_SIZE]>,
tx_buffer: TakeCell<'static, [u8; can::STANDARD_CAN_PACKET_SIZE]>,
deferred_call: DeferredCall,
deferred_action: OptionalCell<AsyncAction>,
}
impl<'a> Can<'a> {
pub fn new(clocks: &'a dyn Stm32f4Clocks, registers: StaticRef<Registers>) -> Can<'a> {
Can {
registers,
clock: CanClock(phclk::PeripheralClock::new(
phclk::PeripheralClockType::APB1(phclk::PCLK1::CAN1),
clocks,
)),
can_state: Cell::new(CanState::Sleep),
error_interrupt_counter: Cell::new(0),
fifo0_interrupt_counter: Cell::new(0),
fifo1_interrupt_counter: Cell::new(0),
failed_messages: Cell::new(0),
automatic_retransmission: Cell::new(false),
automatic_wake_up: Cell::new(false),
operating_mode: OptionalCell::empty(),
bit_timing: OptionalCell::empty(),
controller_client: OptionalCell::empty(),
receive_client: OptionalCell::empty(),
transmit_client: OptionalCell::empty(),
rx_buffer: TakeCell::empty(),
tx_buffer: TakeCell::empty(),
deferred_call: DeferredCall::new(),
deferred_action: OptionalCell::empty(),
}
}
fn wait_for(times: usize, f: impl Fn() -> bool) -> bool {
for _ in 0..times {
if f() {
return true;
}
}
false
}
pub fn enable(&self) -> Result<(), kernel::ErrorCode> {
self.registers.can_mcr.modify(CAN_MCR::SLEEP::CLEAR);
self.registers.can_mcr.modify(CAN_MCR::INRQ::SET);
if !Can::wait_for(20000, || self.registers.can_msr.is_set(CAN_MSR::INAK)) {
return Err(kernel::ErrorCode::FAIL);
}
self.can_state.set(CanState::Initialization);
if !Can::wait_for(20000, || !self.registers.can_msr.is_set(CAN_MSR::SLAK)) {
return Err(kernel::ErrorCode::FAIL);
}
self.registers.can_mcr.modify(CAN_MCR::TTCM::CLEAR);
self.registers.can_mcr.modify(CAN_MCR::ABOM::CLEAR);
self.registers.can_mcr.modify(CAN_MCR::RFLM::CLEAR);
self.registers.can_mcr.modify(CAN_MCR::TXFP::CLEAR);
match self.automatic_retransmission.get() {
true => self.registers.can_mcr.modify(CAN_MCR::AWUM::SET),
false => self.registers.can_mcr.modify(CAN_MCR::AWUM::CLEAR),
}
match self.automatic_wake_up.get() {
true => self.registers.can_mcr.modify(CAN_MCR::NART::CLEAR),
false => self.registers.can_mcr.modify(CAN_MCR::NART::SET),
}
if let Some(operating_mode_settings) = self.operating_mode.get() {
match operating_mode_settings {
can::OperationMode::Loopback => self.registers.can_btr.modify(CAN_BTR::LBKM::SET),
can::OperationMode::Monitoring => self.registers.can_btr.modify(CAN_BTR::SILM::SET),
can::OperationMode::Freeze => return Err(kernel::ErrorCode::INVAL),
_ => {}
}
}
if let Some(bit_timing_settings) = self.bit_timing.get() {
self.registers
.can_btr
.modify(CAN_BTR::TS1.val(bit_timing_settings.segment1 as u32));
self.registers
.can_btr
.modify(CAN_BTR::TS2.val(bit_timing_settings.segment2 as u32));
self.registers
.can_btr
.modify(CAN_BTR::SJW.val(bit_timing_settings.sync_jump_width));
self.registers
.can_btr
.modify(CAN_BTR::BRP.val(bit_timing_settings.baud_rate_prescaler));
} else {
self.enter_sleep_mode();
return Err(kernel::ErrorCode::INVAL);
}
Ok(())
}
pub fn config_filter(&self, filter_info: can::FilterParameters, enable: bool) {
let filter_number = 1 << filter_info.number;
self.registers.can_fmr.modify(CAN_FMR::FINIT::SET);
self.registers.can_fa1r.modify(
CAN_FA1R::FACT.val(self.registers.can_fa1r.read(CAN_FA1R::FACT) & !filter_number),
);
match filter_info.scale_bits {
can::ScaleBits::Bits16 => {
self.registers.can_fs1r.modify(
CAN_FS1R::FSC.val(self.registers.can_fs1r.read(CAN_FS1R::FSC) | filter_number),
);
}
can::ScaleBits::Bits32 => {
self.registers.can_fs1r.modify(
CAN_FS1R::FSC.val(self.registers.can_fs1r.read(CAN_FS1R::FSC) & !filter_number),
);
}
}
self.registers.can_firx[(filter_info.number as usize) * 2].modify(CAN_FiRx::FB.val(0));
self.registers.can_firx[(filter_info.number as usize) * 2 + 1].modify(CAN_FiRx::FB.val(0));
match filter_info.identifier_mode {
can::IdentifierMode::List => {
self.registers.can_fm1r.modify(
CAN_FM1R::FBM.val(self.registers.can_fm1r.read(CAN_FM1R::FBM) | filter_number),
);
}
can::IdentifierMode::Mask => {
self.registers.can_fm1r.modify(
CAN_FM1R::FBM.val(self.registers.can_fm1r.read(CAN_FM1R::FBM) & !filter_number),
);
}
}
if filter_info.fifo_number == 0 {
self.registers.can_ffa1r.modify(
CAN_FFA1R::FFA.val(self.registers.can_ffa1r.read(CAN_FFA1R::FFA) & !filter_number),
);
} else {
self.registers.can_ffa1r.modify(
CAN_FFA1R::FFA.val(self.registers.can_ffa1r.read(CAN_FFA1R::FFA) | filter_number),
);
}
if enable {
self.registers.can_fa1r.modify(
CAN_FA1R::FACT.val(self.registers.can_fa1r.read(CAN_FA1R::FACT) | filter_number),
);
} else {
self.registers.can_fa1r.modify(
CAN_FA1R::FACT.val(self.registers.can_fa1r.read(CAN_FA1R::FACT) & !filter_number),
);
}
}
pub fn enable_filter_config(&self) {
self.registers.can_fmr.modify(CAN_FMR::FINIT::CLEAR);
}
pub fn enter_normal_mode(&self) -> Result<(), kernel::ErrorCode> {
self.registers.can_mcr.modify(CAN_MCR::INRQ::CLEAR);
if !Can::wait_for(20000, || !self.registers.can_msr.is_set(CAN_MSR::INAK)) {
return Err(kernel::ErrorCode::FAIL);
}
self.can_state.set(CanState::Normal);
Ok(())
}
pub fn enter_sleep_mode(&self) {
self.disable_irqs();
self.registers.can_mcr.modify(CAN_MCR::SLEEP::SET);
self.can_state.set(CanState::Sleep);
}
pub fn send_8byte_message(
&self,
id: can::Id,
dlc: usize,
rtr: u8,
) -> Result<(), kernel::ErrorCode> {
self.enable_irq(CanInterruptMode::ErrorAndStatusChangeInterrupt);
if self.can_state.get() == CanState::Normal {
if let Some(tx_mailbox) = self.find_empty_mailbox() {
match id {
can::Id::Standard(id) => {
self.registers.can_tx_mailbox[tx_mailbox]
.can_tir
.modify(CAN_TIxR::IDE::CLEAR);
self.registers.can_tx_mailbox[tx_mailbox]
.can_tir
.modify(CAN_TIxR::STID.val(id as u32 & 0xeff));
self.registers.can_tx_mailbox[tx_mailbox]
.can_tir
.modify(CAN_TIxR::EXID.val(0));
}
can::Id::Extended(id) => {
self.registers.can_tx_mailbox[tx_mailbox]
.can_tir
.modify(CAN_TIxR::IDE::SET);
self.registers.can_tx_mailbox[tx_mailbox]
.can_tir
.modify(CAN_TIxR::STID.val((id & 0xffc0000) >> 18));
self.registers.can_tx_mailbox[tx_mailbox]
.can_tir
.modify(CAN_TIxR::EXID.val(id & 0x003fffff));
}
}
self.registers.can_tx_mailbox[tx_mailbox]
.can_tir
.modify(CAN_TIxR::RTR.val(rtr.into()));
self.registers.can_tx_mailbox[tx_mailbox]
.can_tdtr
.modify(CAN_TDTxR::DLC.val(dlc as u32));
match self.tx_buffer.map(|tx| {
self.registers.can_tx_mailbox[tx_mailbox]
.can_tdlr
.modify(CAN_TDLxR::DATA0.val(tx[0].into()));
self.registers.can_tx_mailbox[tx_mailbox]
.can_tdlr
.modify(CAN_TDLxR::DATA1.val(tx[1].into()));
self.registers.can_tx_mailbox[tx_mailbox]
.can_tdlr
.modify(CAN_TDLxR::DATA2.val(tx[2].into()));
self.registers.can_tx_mailbox[tx_mailbox]
.can_tdlr
.modify(CAN_TDLxR::DATA3.val(tx[3].into()));
self.registers.can_tx_mailbox[tx_mailbox]
.can_tdhr
.modify(CAN_TDHxR::DATA4.val(tx[4].into()));
self.registers.can_tx_mailbox[tx_mailbox]
.can_tdhr
.modify(CAN_TDHxR::DATA5.val(tx[5].into()));
self.registers.can_tx_mailbox[tx_mailbox]
.can_tdhr
.modify(CAN_TDHxR::DATA6.val(tx[6].into()));
self.registers.can_tx_mailbox[tx_mailbox]
.can_tdhr
.modify(CAN_TDHxR::DATA7.val(tx[7].into()));
self.registers.can_tx_mailbox[tx_mailbox]
.can_tir
.modify(CAN_TIxR::TXRQ::SET);
}) {
Some(()) => Ok(()),
None => Err(kernel::ErrorCode::FAIL),
}
} else {
self.failed_messages.replace(self.failed_messages.get() + 1);
Err(kernel::ErrorCode::BUSY)
}
} else {
Err(kernel::ErrorCode::OFF)
}
}
pub fn find_empty_mailbox(&self) -> Option<usize> {
if self.registers.can_tsr.read(CAN_TSR::TME0) == 1 {
Some(0)
} else if self.registers.can_tsr.read(CAN_TSR::TME1) == 1 {
Some(1)
} else if self.registers.can_tsr.read(CAN_TSR::TME2) == 1 {
Some(2)
} else {
None
}
}
pub fn is_enabled_clock(&self) -> bool {
self.clock.is_enabled()
}
pub fn enable_clock(&self) {
self.clock.enable();
}
pub fn disable_clock(&self) {
self.clock.disable();
}
pub fn handle_transmit_interrupt(&self) {
let mut state = Ok(());
if self.registers.can_esr.read(CAN_ESR::BOFF) == 1 {
state = Err(can::Error::BusOff)
} else {
if self.registers.can_tsr.read(CAN_TSR::RQCP0) == 1 {
state = if self.registers.can_tsr.read(CAN_TSR::TXOK0) == 1 {
Ok(())
} else if self.registers.can_tsr.read(CAN_TSR::TERR0) == 1 {
Err(can::Error::Transmission)
} else if self.registers.can_tsr.read(CAN_TSR::ALST0) == 1 {
Err(can::Error::ArbitrationLost)
} else {
Ok(())
};
self.registers.can_tsr.modify(CAN_TSR::RQCP0::SET);
}
if self.registers.can_tsr.read(CAN_TSR::RQCP1) == 1 {
state = if self.registers.can_tsr.read(CAN_TSR::TXOK1) == 1 {
Ok(())
} else if self.registers.can_tsr.read(CAN_TSR::TERR1) == 1 {
Err(can::Error::Transmission)
} else if self.registers.can_tsr.read(CAN_TSR::ALST1) == 1 {
Err(can::Error::ArbitrationLost)
} else {
Ok(())
};
self.registers.can_tsr.modify(CAN_TSR::RQCP1::SET);
}
if self.registers.can_tsr.read(CAN_TSR::RQCP2) == 1 {
state = if self.registers.can_tsr.read(CAN_TSR::TXOK2) == 1 {
Ok(())
} else if self.registers.can_tsr.read(CAN_TSR::TERR2) == 1 {
Err(can::Error::Transmission)
} else if self.registers.can_tsr.read(CAN_TSR::ALST2) == 1 {
Err(can::Error::ArbitrationLost)
} else {
Ok(())
};
self.registers.can_tsr.modify(CAN_TSR::RQCP2::SET);
}
}
match state {
Err(err) => self.can_state.set(CanState::RunningError(err)),
_ => {}
}
self.transmit_client
.map(|transmit_client| match self.tx_buffer.take() {
Some(buf) => transmit_client.transmit_complete(state, buf),
None => {}
});
}
pub fn process_received_message(
&self,
rx_mailbox: usize,
) -> (can::Id, usize, [u8; can::STANDARD_CAN_PACKET_SIZE]) {
let message_id = if self.registers.can_rx_mailbox[rx_mailbox]
.can_rir
.read(CAN_RIxR::IDE)
== 0
{
can::Id::Standard(
self.registers.can_rx_mailbox[rx_mailbox]
.can_rir
.read(CAN_RIxR::STID) as u16,
)
} else {
can::Id::Extended(
(self.registers.can_rx_mailbox[rx_mailbox]
.can_rir
.read(CAN_RIxR::STID)
<< 18)
| (self.registers.can_rx_mailbox[rx_mailbox]
.can_rir
.read(CAN_RIxR::EXID)),
)
};
let message_length = self.registers.can_rx_mailbox[rx_mailbox]
.can_rdtr
.read(CAN_RDTxR::DLC) as usize;
let recv: u64 = ((self.registers.can_rx_mailbox[0].can_rdhr.get() as u64) << 32)
| (self.registers.can_rx_mailbox[0].can_rdlr.get() as u64);
let rx_buf = recv.to_le_bytes();
self.rx_buffer.map(|rx| {
rx[..8].copy_from_slice(&rx_buf[..8]);
});
(message_id, message_length, rx_buf)
}
pub fn handle_fifo0_interrupt(&self) {
if self.registers.can_rf0r.read(CAN_RF0R::FULL0) == 1 {
self.registers.can_rf0r.modify(CAN_RF0R::FULL0::SET);
}
if self.registers.can_rf0r.read(CAN_RF0R::FOVR0) == 1 {
self.registers.can_rf0r.modify(CAN_RF0R::FOVR0::SET);
}
if self.registers.can_rf0r.read(CAN_RF0R::FMP0) != 0 {
let (message_id, message_length, mut rx_buf) = self.process_received_message(0);
self.receive_client.map(|receive_client| {
receive_client.message_received(message_id, &mut rx_buf, message_length, Ok(()))
});
self.fifo0_interrupt_counter
.replace(self.fifo0_interrupt_counter.get() + 1);
self.registers.can_rf0r.modify(CAN_RF0R::RFOM0::SET);
}
}
pub fn handle_fifo1_interrupt(&self) {
if self.registers.can_rf1r.read(CAN_RF1R::FULL1) == 1 {
self.registers.can_rf1r.modify(CAN_RF1R::FULL1::SET);
}
if self.registers.can_rf1r.read(CAN_RF1R::FOVR1) == 1 {
self.registers.can_rf1r.modify(CAN_RF1R::FOVR1::SET);
}
if self.registers.can_rf1r.read(CAN_RF1R::FMP1) != 0 {
self.fifo1_interrupt_counter
.replace(self.fifo1_interrupt_counter.get() + 1);
let (message_id, message_length, mut rx_buf) = self.process_received_message(1);
self.receive_client.map(|receive_client| {
receive_client.message_received(message_id, &mut rx_buf, message_length, Ok(()))
});
self.registers.can_rf1r.modify(CAN_RF1R::RFOM1::SET);
}
}
pub fn handle_error_status_interrupt(&self) {
if self.registers.can_msr.read(CAN_MSR::WKUI) == 1 {
self.registers.can_msr.modify(CAN_MSR::WKUI::SET);
}
if self.registers.can_msr.read(CAN_MSR::SLAKI) == 1 {
self.registers.can_msr.modify(CAN_MSR::SLAKI::SET);
}
if self.registers.can_esr.read(CAN_ESR::EWGF) == 1 {
self.can_state
.set(CanState::RunningError(can::Error::Warning));
}
if self.registers.can_esr.read(CAN_ESR::EPVF) == 1 {
self.can_state
.set(CanState::RunningError(can::Error::Passive));
}
if self.registers.can_esr.read(CAN_ESR::BOFF) == 1 {
self.can_state
.set(CanState::RunningError(can::Error::BusOff));
}
match self.registers.can_esr.read(CAN_ESR::LEC) {
0x001 => self
.can_state
.set(CanState::RunningError(can::Error::Stuff)),
0x010 => self.can_state.set(CanState::RunningError(can::Error::Form)),
0x011 => self.can_state.set(CanState::RunningError(can::Error::Ack)),
0x100 => self
.can_state
.set(CanState::RunningError(can::Error::BitRecessive)),
0x101 => self
.can_state
.set(CanState::RunningError(can::Error::BitDominant)),
0x110 => self.can_state.set(CanState::RunningError(can::Error::Crc)),
0x111 => self
.can_state
.set(CanState::RunningError(can::Error::SetBySoftware)),
_ => {}
}
self.error_interrupt_counter
.replace(self.error_interrupt_counter.get() + 1);
match self.can_state.get() {
CanState::RunningError(err) => {
self.controller_client.map(|controller_client| {
controller_client.state_changed(kernel::hil::can::State::Error(err));
});
}
_ => {}
}
}
pub fn enable_irq(&self, interrupt: CanInterruptMode) {
match interrupt {
CanInterruptMode::TransmitInterrupt => {
self.registers.can_ier.modify(CAN_IER::TMEIE::SET);
}
CanInterruptMode::Fifo0Interrupt => {
self.registers.can_ier.modify(CAN_IER::FMPIE0::SET);
self.registers.can_ier.modify(CAN_IER::FFIE0::SET);
self.registers.can_ier.modify(CAN_IER::FOVIE0::SET);
}
CanInterruptMode::Fifo1Interrupt => {
self.registers.can_ier.modify(CAN_IER::FMPIE1::SET);
self.registers.can_ier.modify(CAN_IER::FFIE1::SET);
self.registers.can_ier.modify(CAN_IER::FOVIE1::SET);
}
CanInterruptMode::ErrorAndStatusChangeInterrupt => {
self.registers.can_ier.modify(CAN_IER::ERRIE::SET);
self.registers.can_ier.modify(CAN_IER::EWGIE::SET);
self.registers.can_ier.modify(CAN_IER::EPVIE::SET);
self.registers.can_ier.modify(CAN_IER::BOFIE::SET);
self.registers.can_ier.modify(CAN_IER::LECIE::SET);
self.registers.can_ier.modify(CAN_IER::WKUIE::SET);
self.registers.can_ier.modify(CAN_IER::SLKIE::SET);
}
}
}
pub fn disable_irq(&self, interrupt: CanInterruptMode) {
match interrupt {
CanInterruptMode::TransmitInterrupt => {
self.registers.can_ier.modify(CAN_IER::TMEIE::CLEAR);
}
CanInterruptMode::Fifo0Interrupt => {
self.registers.can_ier.modify(CAN_IER::FMPIE0::CLEAR);
self.registers.can_ier.modify(CAN_IER::FFIE0::CLEAR);
self.registers.can_ier.modify(CAN_IER::FOVIE0::CLEAR);
}
CanInterruptMode::Fifo1Interrupt => {
self.registers.can_ier.modify(CAN_IER::FMPIE1::CLEAR);
self.registers.can_ier.modify(CAN_IER::FFIE1::CLEAR);
self.registers.can_ier.modify(CAN_IER::FOVIE1::CLEAR);
}
CanInterruptMode::ErrorAndStatusChangeInterrupt => {
self.registers.can_ier.modify(CAN_IER::ERRIE::CLEAR);
self.registers.can_ier.modify(CAN_IER::EWGIE::CLEAR);
self.registers.can_ier.modify(CAN_IER::EPVIE::CLEAR);
self.registers.can_ier.modify(CAN_IER::BOFIE::CLEAR);
self.registers.can_ier.modify(CAN_IER::LECIE::CLEAR);
self.registers.can_ier.modify(CAN_IER::WKUIE::CLEAR);
self.registers.can_ier.modify(CAN_IER::SLKIE::CLEAR);
}
}
}
pub fn enable_irqs(&self) {
self.enable_irq(CanInterruptMode::TransmitInterrupt);
self.enable_irq(CanInterruptMode::Fifo0Interrupt);
self.enable_irq(CanInterruptMode::Fifo1Interrupt);
self.enable_irq(CanInterruptMode::ErrorAndStatusChangeInterrupt);
}
pub fn disable_irqs(&self) {
self.disable_irq(CanInterruptMode::TransmitInterrupt);
self.disable_irq(CanInterruptMode::Fifo0Interrupt);
self.disable_irq(CanInterruptMode::Fifo1Interrupt);
self.disable_irq(CanInterruptMode::ErrorAndStatusChangeInterrupt);
}
}
impl DeferredCallClient for Can<'_> {
fn register(&'static self) {
self.deferred_call.register(self)
}
fn handle_deferred_call(&self) {
match self.deferred_action.take() {
Some(action) => match action {
AsyncAction::Enable => {
if let Err(enable_err) = self.enter_normal_mode() {
self.controller_client.map(|controller_client| {
controller_client.state_changed(self.can_state.get().into());
controller_client.enabled(Err(enable_err));
});
}
self.controller_client.map(|controller_client| {
controller_client.state_changed(can::State::Running);
controller_client.enabled(Ok(()));
});
}
AsyncAction::AbortReceive => {
if let Some(rx) = self.rx_buffer.take() {
self.receive_client
.map(|receive_client| receive_client.stopped(rx));
}
}
AsyncAction::Disabled => {
self.controller_client.map(|controller_client| {
controller_client.state_changed(self.can_state.get().into());
controller_client.disabled(Ok(()));
});
}
AsyncAction::EnableError(err) => {
self.controller_client.map(|controller_client| {
controller_client.state_changed(self.can_state.get().into());
controller_client.enabled(Err(err));
});
}
},
None => todo!(),
}
}
}
struct CanClock<'a>(phclk::PeripheralClock<'a>);
impl ClockInterface for CanClock<'_> {
fn is_enabled(&self) -> bool {
self.0.is_enabled()
}
fn enable(&self) {
self.0.enable();
}
fn disable(&self) {
self.0.disable();
}
}
impl can::Configure for Can<'_> {
const MIN_BIT_TIMINGS: can::BitTiming = can::BitTiming {
segment1: BitSegment1::CanBtrTs1Min as u8,
segment2: BitSegment2::CanBtrTs2Min as u8,
propagation: 0,
sync_jump_width: SynchronizationJumpWidth::CanBtrSjwMin as u32,
baud_rate_prescaler: BRP_MIN_STM32,
};
const MAX_BIT_TIMINGS: can::BitTiming = can::BitTiming {
segment1: BitSegment1::CanBtrTs1Max as u8,
segment2: BitSegment2::CanBtrTs2Max as u8,
propagation: 0,
sync_jump_width: SynchronizationJumpWidth::CanBtrSjwMax as u32,
baud_rate_prescaler: BRP_MAX_STM32,
};
const SYNC_SEG: u8 = 1;
fn set_bitrate(&self, bitrate: u32) -> Result<(), kernel::ErrorCode> {
let bit_timing = Self::bit_timing_for_bitrate(16_000_000, bitrate)?;
self.set_bit_timing(bit_timing)
}
fn set_bit_timing(&self, bit_timing: can::BitTiming) -> Result<(), kernel::ErrorCode> {
match self.can_state.get() {
CanState::Sleep => {
self.bit_timing.set(bit_timing);
Ok(())
}
CanState::Normal | CanState::Initialization | CanState::RunningError(_) => {
Err(kernel::ErrorCode::BUSY)
}
}
}
fn set_operation_mode(&self, mode: can::OperationMode) -> Result<(), kernel::ErrorCode> {
match self.can_state.get() {
CanState::Sleep => {
self.operating_mode.set(mode);
Ok(())
}
CanState::Normal | CanState::Initialization | CanState::RunningError(_) => {
Err(kernel::ErrorCode::BUSY)
}
}
}
fn get_bit_timing(&self) -> Result<can::BitTiming, kernel::ErrorCode> {
if let Some(bit_timing) = self.bit_timing.get() {
Ok(bit_timing)
} else {
Err(kernel::ErrorCode::INVAL)
}
}
fn get_operation_mode(&self) -> Result<can::OperationMode, kernel::ErrorCode> {
if let Some(operation_mode) = self.operating_mode.get() {
Ok(operation_mode)
} else {
Err(kernel::ErrorCode::INVAL)
}
}
fn set_automatic_retransmission(&self, automatic: bool) -> Result<(), kernel::ErrorCode> {
match self.can_state.get() {
CanState::Sleep => {
self.automatic_retransmission.replace(automatic);
Ok(())
}
CanState::Normal | CanState::Initialization | CanState::RunningError(_) => {
Err(kernel::ErrorCode::BUSY)
}
}
}
fn set_wake_up(&self, wake_up: bool) -> Result<(), kernel::ErrorCode> {
match self.can_state.get() {
CanState::Sleep => {
self.automatic_wake_up.replace(wake_up);
Ok(())
}
CanState::Normal | CanState::Initialization | CanState::RunningError(_) => {
Err(kernel::ErrorCode::BUSY)
}
}
}
fn get_automatic_retransmission(&self) -> Result<bool, kernel::ErrorCode> {
Ok(self.automatic_retransmission.get())
}
fn get_wake_up(&self) -> Result<bool, kernel::ErrorCode> {
Ok(self.automatic_wake_up.get())
}
fn receive_fifo_count(&self) -> usize {
2
}
}
impl can::Controller for Can<'_> {
fn set_client(&self, client: Option<&'static dyn can::ControllerClient>) {
if let Some(client) = client {
self.controller_client.replace(client);
} else {
self.controller_client.clear();
}
}
fn enable(&self) -> Result<(), kernel::ErrorCode> {
match self.can_state.get() {
CanState::Sleep => {
if self.bit_timing.is_none() || self.operating_mode.is_none() {
Err(kernel::ErrorCode::INVAL)
} else {
let r = self.enable();
if self.deferred_action.is_some() {
Err(kernel::ErrorCode::BUSY)
} else {
match r {
Ok(()) => {
self.deferred_action.set(AsyncAction::Enable);
}
Err(err) => {
self.deferred_action.set(AsyncAction::EnableError(err));
}
}
self.deferred_call.set();
r
}
}
}
CanState::Normal | CanState::Initialization => Err(kernel::ErrorCode::ALREADY),
CanState::RunningError(_) => Err(kernel::ErrorCode::FAIL),
}
}
fn disable(&self) -> Result<(), kernel::ErrorCode> {
match self.can_state.get() {
CanState::Normal | CanState::RunningError(_) => {
self.enter_sleep_mode();
if self.deferred_action.is_some() {
return Err(kernel::ErrorCode::BUSY);
} else {
self.deferred_action.set(AsyncAction::Disabled);
self.deferred_call.set();
}
Ok(())
}
CanState::Sleep | CanState::Initialization => Err(kernel::ErrorCode::OFF),
}
}
fn get_state(&self) -> Result<can::State, kernel::ErrorCode> {
Ok(self.can_state.get().into())
}
}
impl can::Transmit<{ can::STANDARD_CAN_PACKET_SIZE }> for Can<'_> {
fn set_client(
&self,
client: Option<&'static dyn can::TransmitClient<{ can::STANDARD_CAN_PACKET_SIZE }>>,
) {
if let Some(client) = client {
self.transmit_client.set(client);
} else {
self.transmit_client.clear();
}
}
fn send(
&self,
id: can::Id,
buffer: &'static mut [u8; can::STANDARD_CAN_PACKET_SIZE],
len: usize,
) -> Result<
(),
(
kernel::ErrorCode,
&'static mut [u8; can::STANDARD_CAN_PACKET_SIZE],
),
> {
match self.can_state.get() {
CanState::Normal | CanState::RunningError(_) => {
self.tx_buffer.replace(buffer);
self.enable_irq(CanInterruptMode::TransmitInterrupt);
self.can_state.set(CanState::Normal);
match self.send_8byte_message(id, len, 0) {
Ok(()) => Ok(()),
Err(err) => Err((err, self.tx_buffer.take().unwrap())),
}
}
CanState::Sleep | CanState::Initialization => Err((kernel::ErrorCode::OFF, buffer)),
}
}
}
impl can::Receive<{ can::STANDARD_CAN_PACKET_SIZE }> for Can<'_> {
fn set_client(
&self,
client: Option<&'static dyn can::ReceiveClient<{ can::STANDARD_CAN_PACKET_SIZE }>>,
) {
if let Some(client) = client {
self.receive_client.set(client);
} else {
self.receive_client.clear();
}
}
fn start_receive_process(
&self,
buffer: &'static mut [u8; can::STANDARD_CAN_PACKET_SIZE],
) -> Result<
(),
(
kernel::ErrorCode,
&'static mut [u8; can::STANDARD_CAN_PACKET_SIZE],
),
> {
match self.can_state.get() {
CanState::Normal | CanState::RunningError(_) => {
self.can_state.set(CanState::Normal);
self.config_filter(
can::FilterParameters {
number: 0,
scale_bits: can::ScaleBits::Bits32,
identifier_mode: can::IdentifierMode::Mask,
fifo_number: 0,
},
true,
);
self.config_filter(
can::FilterParameters {
number: 1,
scale_bits: can::ScaleBits::Bits32,
identifier_mode: can::IdentifierMode::Mask,
fifo_number: 1,
},
true,
);
self.enable_filter_config();
self.enable_irq(CanInterruptMode::Fifo0Interrupt);
self.enable_irq(CanInterruptMode::Fifo1Interrupt);
self.rx_buffer.put(Some(buffer));
Ok(())
}
CanState::Sleep | CanState::Initialization => Err((kernel::ErrorCode::OFF, buffer)),
}
}
fn stop_receive(&self) -> Result<(), kernel::ErrorCode> {
match self.can_state.get() {
CanState::Normal | CanState::RunningError(_) => {
self.can_state.set(CanState::Normal);
self.config_filter(
can::FilterParameters {
number: 0,
scale_bits: can::ScaleBits::Bits32,
identifier_mode: can::IdentifierMode::Mask,
fifo_number: 0,
},
false,
);
self.config_filter(
can::FilterParameters {
number: 1,
scale_bits: can::ScaleBits::Bits32,
identifier_mode: can::IdentifierMode::Mask,
fifo_number: 1,
},
false,
);
self.enable_filter_config();
self.disable_irq(CanInterruptMode::Fifo0Interrupt);
self.disable_irq(CanInterruptMode::Fifo1Interrupt);
if self.deferred_action.is_some() {
Err(kernel::ErrorCode::BUSY)
} else if self.rx_buffer.is_none() {
Err(kernel::ErrorCode::SIZE)
} else {
self.deferred_action.set(AsyncAction::AbortReceive);
self.deferred_call.set();
Ok(())
}
}
CanState::Sleep | CanState::Initialization => Err(kernel::ErrorCode::OFF),
}
}
}