va416xx_hal/can/
ll.rs

1use arbitrary_int::{prelude::*, u11, u15, u3, u4};
2use embedded_can::Frame;
3
4use super::{
5    regs::{
6        self, BaseId, BufStatusAndControl, BufferState, ExtendedId, MmioCanMessageBuffer,
7        TwoBytesData,
8    },
9    CanFrame, CanFrameNormal, CanFrameRtr, CanId, InvalidBufferIndexError,
10};
11
12pub struct CanChannelLowLevel {
13    id: CanId,
14    /// Message buffer index.
15    idx: usize,
16    msg_buf: MmioCanMessageBuffer<'static>,
17}
18
19impl core::fmt::Debug for CanChannelLowLevel {
20    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
21        f.debug_struct("CanChannel")
22            .field("can_id", &self.id)
23            .field("idx", &self.idx)
24            .finish()
25    }
26}
27
28impl CanChannelLowLevel {
29    /// Steal a low level instance of a CAN channel.
30    ///
31    /// # Safety
32    ///
33    /// Circumvents ownership and safety guarantees of the HAL.
34    #[inline]
35    pub unsafe fn steal(can: CanId, idx: usize) -> Result<Self, InvalidBufferIndexError> {
36        if idx > 14 {
37            return Err(InvalidBufferIndexError(idx));
38        }
39        let msg_buf = unsafe { can.steal_regs().steal_cmbs_unchecked(idx) };
40        Ok(Self {
41            id: can,
42            idx,
43            msg_buf,
44        })
45    }
46
47    /// Steal a low level instance of a CAN channel without and index checks.
48    ///
49    /// # Safety
50    ///
51    /// Does not perform any bound checks. Passing an invalid index of 15 or higher leads to
52    /// undefined behaviour.
53    #[inline]
54    pub const unsafe fn steal_unchecked(can: CanId, idx: usize) -> Self {
55        if idx > 14 {
56            panic!("invalid buffer index for CAN low level channel");
57        }
58        let msg_buf = unsafe { can.steal_regs().steal_cmbs_unchecked(idx) };
59        Self {
60            id: can,
61            idx,
62            msg_buf,
63        }
64    }
65
66    /// # Safety
67    ///
68    /// Allows to create an aribtrary amoutn of driver handles to the same message block, which
69    /// might lead to data races on invalid usage.
70    #[inline]
71    pub const unsafe fn clone(&self) -> Self {
72        Self {
73            id: self.id,
74            idx: self.idx,
75            msg_buf: unsafe { self.msg_buf.clone() },
76        }
77    }
78
79    pub fn reset(&mut self) {
80        self.msg_buf.reset();
81    }
82
83    #[inline]
84    pub fn read_state(&self) -> Result<BufferState, u8> {
85        self.msg_buf.read_stat_ctrl().state()
86    }
87
88    #[inline]
89    pub fn write_state(&mut self, buffer_state: BufferState) {
90        self.msg_buf.modify_stat_ctrl(|mut val| {
91            val.set_state(buffer_state);
92            val
93        });
94    }
95
96    pub fn configure_for_transmission(&mut self, tx_priority: Option<u4>) {
97        self.msg_buf.modify_stat_ctrl(|mut val| {
98            val.set_dlc(u4::new(0));
99            if let Some(tx_priority) = tx_priority {
100                val.set_priority(tx_priority);
101            }
102            val.set_state(BufferState::TxNotActive);
103            val
104        });
105    }
106
107    pub fn set_standard_id(&mut self, standard_id: embedded_can::StandardId, set_rtr: bool) {
108        let mut id1_reg = standard_id.as_raw() << 5;
109        if set_rtr {
110            id1_reg |= 1 << 4;
111        }
112        self.msg_buf
113            .write_id1(BaseId::new_with_raw_value(id1_reg as u32));
114    }
115
116    pub fn set_extended_id(&mut self, extended_id: embedded_can::ExtendedId, set_rtr: bool) {
117        let id_raw = extended_id.as_raw();
118        let id1_reg = (((id_raw >> 18) & 0x7FF) << 4) as u16 | ((id_raw >> 15) & 0b111) as u16;
119        self.msg_buf
120            .write_id1(BaseId::new_with_raw_value(id1_reg as u32));
121        let id0_reg = ((id_raw & 0x7FFF) << 1) as u16 | set_rtr as u16;
122        self.msg_buf
123            .write_id0(ExtendedId::new_with_raw_value(id0_reg as u32));
124    }
125
126    pub fn configure_for_reception(&mut self) {
127        self.msg_buf.write_stat_ctrl(
128            BufStatusAndControl::builder()
129                .with_dlc(u4::new(0))
130                .with_priority(u4::new(0))
131                .with_state(BufferState::RxReady)
132                .build(),
133        );
134    }
135
136    pub fn transmit_frame_unchecked(&mut self, frame: CanFrame) {
137        let is_remote = frame.is_remote_frame();
138        self.write_id(frame.id(), is_remote);
139        let dlc = frame.dlc();
140        self.msg_buf.modify_stat_ctrl(|mut ctrl| {
141            ctrl.set_dlc(u4::new(dlc as u8));
142            ctrl
143        });
144        if !is_remote {
145            self.msg_buf
146                .write_data0(TwoBytesData::new_with_raw_value(0));
147            self.msg_buf
148                .write_data1(TwoBytesData::new_with_raw_value(0));
149            self.msg_buf
150                .write_data2(TwoBytesData::new_with_raw_value(0));
151            self.msg_buf
152                .write_data3(TwoBytesData::new_with_raw_value(0));
153            for idx in 0..dlc {
154                match idx {
155                    0 => self.msg_buf.modify_data0(|mut val| {
156                        val.set_data_upper_byte(frame.data()[idx]);
157                        val
158                    }),
159                    1 => self.msg_buf.modify_data0(|mut val| {
160                        val.set_data_lower_byte(frame.data()[idx]);
161                        val
162                    }),
163                    2 => self.msg_buf.modify_data1(|mut val| {
164                        val.set_data_upper_byte(frame.data()[idx]);
165                        val
166                    }),
167                    3 => self.msg_buf.modify_data1(|mut val| {
168                        val.set_data_lower_byte(frame.data()[idx]);
169                        val
170                    }),
171                    4 => self.msg_buf.modify_data2(|mut val| {
172                        val.set_data_upper_byte(frame.data()[idx]);
173                        val
174                    }),
175                    5 => self.msg_buf.modify_data2(|mut val| {
176                        val.set_data_lower_byte(frame.data()[idx]);
177                        val
178                    }),
179                    6 => self.msg_buf.modify_data3(|mut val| {
180                        val.set_data_upper_byte(frame.data()[idx]);
181                        val
182                    }),
183                    7 => self.msg_buf.modify_data3(|mut val| {
184                        val.set_data_lower_byte(frame.data()[idx]);
185                        val
186                    }),
187                    _ => unreachable!(),
188                }
189            }
190        }
191        self.write_state(BufferState::TxOnce);
192    }
193
194    #[inline]
195    pub fn clear_interrupt(&mut self) {
196        let mut regs = unsafe { self.id.steal_regs() };
197        let mut clear = regs::InterruptClear::new_with_raw_value(0);
198        clear.set_buffer(self.idx, true);
199        regs.write_iclr(clear);
200    }
201
202    pub fn enable_error_interrupt(&mut self, enable_translation: bool) {
203        let mut regs = unsafe { self.id.steal_regs() };
204        if enable_translation {
205            regs.modify_icen(|mut val| {
206                val.set_error(true);
207                val
208            });
209        }
210        regs.modify_ien(|mut val| {
211            val.set_error(true);
212            val
213        });
214    }
215
216    pub fn enable_interrupt(&mut self, enable_translation: bool) {
217        let mut regs = unsafe { self.id.steal_regs() };
218        if enable_translation {
219            regs.modify_icen(|mut val| {
220                val.set_buffer(self.idx, true);
221                val
222            });
223        }
224        regs.modify_ien(|mut val| {
225            val.set_buffer(self.idx, true);
226            val
227        });
228    }
229
230    fn write_id(&mut self, id: embedded_can::Id, is_remote: bool) {
231        match id {
232            embedded_can::Id::Standard(standard_id) => {
233                self.msg_buf.write_id1(
234                    BaseId::builder()
235                        .with_mask_28_18(u11::new(standard_id.as_raw()))
236                        .with_rtr_or_srr(is_remote)
237                        .with_ide(false)
238                        .with_mask_17_15(u3::new(0))
239                        .build(),
240                );
241                self.msg_buf.write_id0(ExtendedId::new_with_raw_value(0));
242            }
243            embedded_can::Id::Extended(extended_id) => {
244                let id_raw = extended_id.as_raw();
245                self.msg_buf.write_id1(
246                    BaseId::builder()
247                        .with_mask_28_18(u11::new(((id_raw >> 18) & 0x7FF) as u16))
248                        .with_rtr_or_srr(true)
249                        .with_ide(true)
250                        .with_mask_17_15(u3::new(((id_raw >> 15) & 0b111) as u8))
251                        .build(),
252                );
253                self.msg_buf.write_id0(
254                    ExtendedId::builder()
255                        .with_mask_14_0(u15::new((id_raw & 0x7FFF) as u16))
256                        .with_xrtr(is_remote)
257                        .build(),
258                );
259            }
260        }
261    }
262
263    /// Reads a received CAN frame from the message buffer.
264    ///
265    /// This function does not check whether the pre-requisites for reading a CAN frame were
266    /// met and assumes this was already checked by the user.
267    pub fn read_frame_unchecked(&self) -> CanFrame {
268        let id0 = self.msg_buf.read_id0();
269        let id1 = self.msg_buf.read_id1();
270        let data0 = self.msg_buf.read_data0();
271        let data1 = self.msg_buf.read_data1();
272        let data2 = self.msg_buf.read_data2();
273        let data3 = self.msg_buf.read_data3();
274        let mut data: [u8; 8] = [0; 8];
275        let mut read_data = |dlc: u4| {
276            (0..dlc.as_usize()).for_each(|i| match i {
277                0 => data[i] = data0.data_upper_byte().as_u8(),
278                1 => data[i] = data0.data_lower_byte().as_u8(),
279                2 => data[i] = data1.data_upper_byte().as_u8(),
280                3 => data[i] = data1.data_lower_byte().as_u8(),
281                4 => data[i] = data2.data_upper_byte().as_u8(),
282                5 => data[i] = data2.data_lower_byte().as_u8(),
283                6 => data[i] = data3.data_upper_byte().as_u8(),
284                7 => data[i] = data3.data_lower_byte().as_u8(),
285                _ => unreachable!(),
286            });
287        };
288        let (id, rtr) = if !id1.ide() {
289            let id = embedded_can::Id::Standard(
290                embedded_can::StandardId::new(id1.mask_28_18().as_u16()).unwrap(),
291            );
292            if id1.rtr_or_srr() {
293                (id, true)
294            } else {
295                (id, false)
296            }
297        } else {
298            let id_raw = (id1.mask_28_18().as_u32() << 18)
299                | (id1.mask_17_15().as_u32() << 15)
300                | id0.mask_14_0().as_u32();
301            let id = embedded_can::Id::Extended(embedded_can::ExtendedId::new(id_raw).unwrap());
302            if id0.xrtr() {
303                (id, true)
304            } else {
305                (id, false)
306            }
307        };
308        if rtr {
309            CanFrameRtr::new(id, self.msg_buf.read_stat_ctrl().dlc().as_usize()).into()
310        } else {
311            let dlc = self.msg_buf.read_stat_ctrl().dlc();
312            read_data(dlc);
313            CanFrameNormal::new(id, &data[0..dlc.as_usize()])
314                .unwrap()
315                .into()
316        }
317    }
318}