1use arbitrary_int::{prelude::*, u11, u15, u2, u3, u4, u6, u7};
5
6pub const CAN_0_BASE: usize = 0x4001_4000;
7pub const CAN_1_BASE: usize = 0x4001_4400;
8
9#[derive(Debug, PartialEq, Eq)]
10#[bitbybit::bitenum(u4)]
11#[cfg_attr(feature = "defmt", derive(defmt::Format))]
12pub enum BufferState {
13 RxNotActive = 0b0000,
15 RxBusy = 0b0001,
18 RxReady = 0b0010,
19 RxBusy0 = 0b0011,
21 RxFull = 0b0100,
22 RxBusy1 = 0b0101,
24 RxOverrun = 0b0110,
25 RxBusy2 = 0b0111,
26 TxNotActive = 0b1000,
27 TxRtr = 0b1010,
29 TxOnce = 0b1100,
31 TxBusy0 = 0b1101,
32 TxOnceRtr = 0b1110,
36 TxBusy2 = 0b1111,
37}
38
39#[bitbybit::bitfield(u32, default = 0x0, debug, defmt_fields(feature = "defmt"))]
41pub struct BufStatusAndControl {
42 #[bits(12..=15, rw)]
44 dlc: u4,
45 #[bits(4..=7, rw)]
46 priority: u4,
47 #[bits(0..=3, rw)]
48 state: Option<BufferState>,
49}
50
51#[derive(Debug)]
52pub struct Timestamp(arbitrary_int::UInt<u32, 16>);
53
54impl Timestamp {
55 pub fn new(value: u16) -> Self {
56 Self(value.into())
57 }
58 pub fn value(&self) -> u16 {
59 self.0.value() as u16
60 }
61
62 pub fn write(&mut self, value: u16) {
63 self.0 = value.into();
64 }
65}
66
67#[bitbybit::bitfield(u32, default = 0x0, debug, defmt_bitfields(feature = "defmt"))]
68pub struct TwoBytesData {
69 #[bits(0..=7, rw)]
70 data_lower_byte: u8,
71 #[bits(8..=15, rw)]
72 data_upper_byte: u8,
73}
74
75#[derive(derive_mmio::Mmio)]
76#[repr(C)]
77pub struct CanMessageBuffer {
78 stat_ctrl: BufStatusAndControl,
79 timestamp: Timestamp,
80 data3: TwoBytesData,
81 data2: TwoBytesData,
82 data1: TwoBytesData,
83 data0: TwoBytesData,
84 id0: ExtendedId,
85 id1: BaseId,
86}
87
88static_assertions::const_assert_eq!(core::mem::size_of::<CanMessageBuffer>(), 0x20);
89
90impl MmioCanMessageBuffer<'_> {
91 pub fn reset(&mut self) {
92 self.write_stat_ctrl(BufStatusAndControl::new_with_raw_value(0));
93 self.write_timestamp(Timestamp::new(0));
94 self.write_data0(TwoBytesData::new_with_raw_value(0));
95 self.write_data1(TwoBytesData::new_with_raw_value(0));
96 self.write_data2(TwoBytesData::new_with_raw_value(0));
97 self.write_data3(TwoBytesData::new_with_raw_value(0));
98 self.write_id1(BaseId::new_with_raw_value(0));
99 self.write_id0(ExtendedId::new_with_raw_value(0));
100 }
101}
102
103#[bitbybit::bitenum(u1, exhaustive = true)]
104#[derive(Debug)]
105#[cfg_attr(feature = "defmt", derive(defmt::Format))]
106pub enum PinLogicLevel {
107 DominantIsZero = 0b0,
108 DominantIsOne = 0b1,
109}
110
111#[bitbybit::bitenum(u1, exhaustive = true)]
112#[derive(Debug)]
113#[cfg_attr(feature = "defmt", derive(defmt::Format))]
114pub enum ErrorInterruptType {
115 EveryError = 0b0,
117 ErrorOnRxTxCounterChange = 0b1,
120}
121
122#[bitbybit::bitenum(u1, exhaustive = true)]
123#[derive(Debug)]
124#[cfg_attr(feature = "defmt", derive(defmt::Format))]
125pub enum DataDirection {
126 FirstByteAtHighestAddr = 0b0,
127 LastByteAtHighestAddr = 0b1,
128}
129
130#[bitbybit::bitfield(u32, debug, defmt_fields(feature = "defmt"))]
131pub struct Control {
132 #[bit(11, rw)]
133 error_interrupt_type: ErrorInterruptType,
134 #[bit(10, rw)]
136 diag_enable: bool,
137 #[bit(9, rw)]
139 internal: bool,
140 #[bit(8, rw)]
143 loopback: bool,
144 #[bit(7, rw)]
146 ignore_ack: bool,
147 #[bit(6, rw)]
149 listen_only: bool,
150 #[bit(5, rw)]
151 data_dir: DataDirection,
152 #[bit(4, rw)]
153 timestamp_enable: bool,
154 #[bit(3, rw)]
155 bufflock: bool,
156 #[bit(2, rw)]
157 tx_logic_level: PinLogicLevel,
158 #[bit(1, rw)]
159 rx_logic_level: PinLogicLevel,
160 #[bit(0, rw)]
161 enable: bool,
162}
163
164#[bitbybit::bitfield(u32, default = 0x0, debug, defmt_bitfields(feature = "defmt"))]
165pub struct TimingConfig {
166 #[bits(0..=2, rw)]
167 tseg2: u3,
168 #[bits(3..=6, rw)]
169 tseg1: u4,
170 #[bits(7..=8, rw)]
171 sync_jump_width: u2,
172 #[bits(9..=15, rw)]
173 prescaler: u7,
174}
175
176#[bitbybit::bitfield(u32)]
177#[derive(Debug)]
178pub struct InterruptEnable {
179 #[bit(15, rw)]
180 error: bool,
181 #[bit(0, rw)]
182 buffer: [bool; 15],
183}
184
185#[bitbybit::bitfield(u32)]
186#[derive(Debug)]
187pub struct InterruptClear {
188 #[bit(15, w)]
189 error: bool,
190 #[bit(0, w)]
191 buffer: [bool; 15],
192}
193
194#[bitbybit::bitfield(u32)]
195#[derive(Debug)]
196pub struct InterruptPending {
197 #[bit(15, r)]
198 error: bool,
199 #[bit(0, r)]
200 buffer: [bool; 15],
201}
202
203#[derive(Debug)]
204#[repr(usize)]
205#[cfg_attr(feature = "defmt", derive(defmt::Format))]
206pub enum CanInterruptId {
207 None = 0b00000,
208 Error = 0b10000,
209 Buffer(usize),
210}
211
212#[bitbybit::bitfield(u32, debug, defmt_bitfields(feature = "defmt"))]
213pub struct StatusPending {
214 #[bits(5..=7, r)]
215 ns: u3,
216 #[bit(4, r)]
217 irq: bool,
218 #[bits(0..=3, r)]
219 ist: u4,
220}
221
222impl StatusPending {
223 pub fn interrupt_id(&self) -> Option<CanInterruptId> {
224 if !self.irq() && self.ist().value() == 0 {
225 return Some(CanInterruptId::None);
226 }
227
228 if self.irq() && self.ist().value() == 0 {
229 return Some(CanInterruptId::Error);
230 }
231 if !self.irq() {
232 return None;
233 }
234 Some(CanInterruptId::Buffer(self.ist().as_usize() - 1))
235 }
236}
237
238#[bitbybit::bitfield(u32, debug, defmt_bitfields(feature = "defmt"))]
239pub struct ErrorCounter {
240 #[bits(0..=7, r)]
241 transmit: u8,
242 #[bits(8..=15, r)]
243 receive: u8,
244}
245
246#[bitbybit::bitfield(u32, default = 0x0, debug, defmt_bitfields(feature = "defmt"))]
248pub struct ExtendedId {
249 #[bits(1..=15, rw)]
251 mask_14_0: u15,
252 #[bit(0, rw)]
254 xrtr: bool,
255}
256
257#[bitbybit::bitfield(u32, default = 0x0, debug, defmt_bitfields(feature = "defmt"))]
258pub struct BaseId {
259 #[bits(5..=15, rw)]
261 mask_28_18: u11,
262 #[bit(4, rw)]
264 rtr_or_srr: bool,
265 #[bit(3, rw)]
267 ide: bool,
268 #[bits(0..=2, rw)]
270 mask_17_15: u3,
271}
272
273#[derive(Debug, PartialEq, Eq)]
274#[bitbybit::bitenum(u4, exhaustive = true)]
275#[cfg_attr(feature = "defmt", derive(defmt::Format))]
276pub enum ErrorFieldId {
277 Error = 0b0000,
278 ErrorDel = 0b0001,
279 ErrorEcho = 0b0010,
280 BusIdle = 0b0011,
281 Ack = 0b0100,
282 Eof = 0b0101,
283 Intermission = 0b0110,
284 SuspendTransmission = 0b0111,
285 Sof = 0b1000,
286 Arbitration = 0b1001,
287 Ide = 0b1010,
288 ExtendedArbitration = 0b1011,
289 R1R0 = 0b1100,
290 Dlc = 0b1101,
291 Data = 0b1110,
292 Crc = 0b1111,
293}
294
295#[bitbybit::bitfield(u32, debug, defmt_bitfields(feature = "defmt"))]
296pub struct DiagnosticRegister {
297 #[bit(14, r)]
299 drive: bool,
300 #[bit(13, r)]
303 mon: bool,
304 #[bit(12, r)]
307 crc: bool,
308 #[bit(11, r)]
310 stuff: bool,
311 #[bit(10, r)]
313 txe: bool,
314 #[bits(4..=9, r)]
315 ebid: u6,
316 #[bits(0..=3, r)]
317 efid: ErrorFieldId,
318}
319
320#[derive(derive_mmio::Mmio)]
321#[mmio(const_inner)]
322#[repr(C)]
323pub struct Can {
324 #[mmio(Inner)]
325 cmbs: [CanMessageBuffer; 15],
326 #[mmio(Inner)]
328 _hcmb: CanMessageBuffer,
329 control: Control,
330 timing: TimingConfig,
331 gmskx: ExtendedId,
333 gmskb: BaseId,
335 bmskx: ExtendedId,
337 bmskb: BaseId,
339 ien: InterruptEnable,
340 #[mmio(PureRead)]
341 ipnd: InterruptPending,
342 #[mmio(Write)]
343 iclr: InterruptClear,
344 icen: InterruptEnable,
346 #[mmio(PureRead)]
347 status_pending: StatusPending,
348 #[mmio(PureRead)]
349 error_counter: ErrorCounter,
350 #[mmio(PureRead)]
351 diag: DiagnosticRegister,
352 #[mmio(PureRead)]
353 timer: u32,
354}
355
356static_assertions::const_assert_eq!(core::mem::size_of::<Can>(), 0x238);
357
358impl Can {
359 pub const unsafe fn new_mmio_fixed_0() -> MmioCan<'static> {
367 Self::new_mmio_at(CAN_0_BASE)
368 }
369
370 pub const unsafe fn new_mmio_fixed_1() -> MmioCan<'static> {
378 Self::new_mmio_at(CAN_1_BASE)
379 }
380}