avr_mcu/
model.rs

1/// A microcontroller with one or more variants.
2#[derive(Clone, Debug, PartialOrd, PartialEq)]
3pub struct Mcu {
4    /// Information about the microcontroller itself.
5    pub device: Device,
6    /// The different variants the mcu can come in.
7    pub variants: Vec<Variant>,
8    /// The modules built into the mcu package.
9    pub modules: Vec<Module>,
10    /// The family that the mcu belongs to.
11    pub architecture: Architecture,
12    /// The C preprocessor name.
13    pub c_preprocessor_name: String,
14}
15
16/// Information fore a specific device.
17#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Hash)]
18pub struct Device {
19    /// The name of the device.
20    pub name: String,
21    /// A list of all address spaces the device has.
22    pub address_spaces: Vec<AddressSpace>,
23    /// A list of supported peripherals.
24    pub peripherals: Vec<Peripheral>,
25    /// A list of supported interrupts
26    pub interrupts: Vec<Interrupt>,
27}
28
29/// A variation of a specific microcontroller.
30#[derive(Clone, Debug, PartialOrd, PartialEq)]
31pub struct Variant {
32    /// The name of the variant.
33    pub name: String,
34    /// What pinout is used.
35    pub pinout: Option<String>,
36    /// The package format.
37    pub package: String,
38    /// The minimum temperate in celsius.
39    pub temperature_min: i32,
40    /// The maximum temperature in celsius.
41    pub temperature_max: i32,
42    /// The minimum voltage.
43    pub voltage_min: f32,
44    /// The maximum voltate.
45    pub voltage_max: f32,
46    /// The max clock speed in Hz.
47    pub speed_max_hz: u64,
48}
49
50/// An address space.
51#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Hash)]
52pub struct AddressSpace {
53    /// The identifier.
54    pub id: String,
55    /// The name.
56    pub name: String,
57    /// The starting memory address of the address space.
58    pub start_address: u32,
59    /// The number of bytes in the address space.
60    pub size: u32,
61    /// What segments are in the address space.
62    pub segments: Vec<MemorySegment>,
63}
64
65/// A segment of memory in a particular address space.
66#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Hash)]
67pub struct MemorySegment {
68    /// The name of the segment.
69    pub name: String,
70    /// A pointer to the first byte in the segment.
71    pub start_address: u32,
72    /// The number of bytes in the segment.
73    pub size: u32,
74    /// The segment type.
75    pub ty: String,
76    /// Whether the segment can be read from.
77    pub readable: bool,
78    /// Whether the segment can be written to.
79    pub writable: bool,
80    /// Whether the segment can be executed.
81    pub executable: bool,
82    /// How large pages are in this segment.
83    pub page_size: Option<u32>,
84}
85
86/// An on-board peripheral, such as an IO port.
87#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Hash)]
88pub struct Peripheral {
89    /// The name of the peripheral, for example, `PORT`.
90    pub name: String,
91    /// A list of instances where the peripheral is used.
92    ///
93    /// As an example, if the peripheral is an IO port, then the
94    /// instance list would list all PORT instances, such as `PORTA`
95    /// and `PORTB`.
96    pub instances: Vec<Instance>,
97}
98
99/// An interrupt supported by a device.
100#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Hash)]
101pub struct Interrupt {
102    /// The name of the interrupt, for example `TIMER1_COMPA`.
103    pub name: String,
104    /// A brief description of the interrupt
105    pub caption: String,
106    /// The interrupt vector table index
107    pub index: u32,
108}
109
110/// A module built into the silicon.
111#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Hash)]
112pub struct Module {
113    /// The name of the module, for example, `PORT`.
114    pub name: String,
115    /// Registers associated with the module.
116    pub register_groups: Vec<RegisterGroup>,
117    /// Value groups associated with the module.
118    pub value_groups: Vec<ValueGroup>,
119}
120
121/// An instance of a peripheral.
122#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Hash)]
123pub struct Instance {
124    /// The name of the peripheral instance, for example, `PORTB`.
125    pub name: String,
126    /// What signals are used in the peripheral.
127    pub signals: Vec<Signal>,
128}
129
130/// A group of registers.
131#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Hash)]
132pub struct RegisterGroup {
133    /// The name of the group.
134    pub name: String,
135    pub caption: String,
136    /// The registers that make up the group.
137    pub registers: Vec<Register>,
138}
139
140/// A group of values.
141#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Hash)]
142pub struct ValueGroup {
143    pub name: String,
144    pub caption: String,
145    pub values: Vec<Value>,
146}
147
148/// A values for a register/mask.
149#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Hash)]
150pub struct Value {
151    pub name: String,
152    pub caption: String,
153    pub value: u32,
154}
155
156/// Specifies the mutability of a register.
157#[derive(Copy, Clone, Debug, PartialOrd, PartialEq, Eq, Hash)]
158pub enum ReadWrite {
159    /// The register is readable and writable.
160    ReadAndWrite,
161    /// The register is read-only.
162    ReadOnly,
163    /// The register is write-only.
164    WriteOnly,
165}
166
167/// An CPU or IO register.
168#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Hash)]
169pub struct Register {
170    /// The name of the register, such as `TCCR0A`.
171    pub name: String,
172    /// The register description.
173    pub caption: String,
174    /// The offset of the register in IO space.
175    pub offset: u32,
176    /// The number of bytes that make up the bitfield.
177    pub size: u32,
178    pub mask: Option<u32>,
179    /// The mutability of the register.
180    pub rw: ReadWrite,
181    /// The bitfields supported by the register.
182    pub bitfields: Vec<Bitfield>,
183}
184
185/// A bitfield within a register.
186#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Hash)]
187pub struct Bitfield {
188    /// The name of the bitfield, such as `U2X0` for the USART register `UCSR0A`.
189    pub name: String,
190    /// A description of the bitfield.
191    pub caption: String,
192    /// The mask that makes up the bitfield.
193    ///
194    /// This will always match up to the parent register. A 16-bit register has
195    /// 16-but masks.
196    pub mask: u32,
197    /// The number of bytes that make up the bitfield.
198    pub size: u32,
199    /// reference into value_groups on the container
200    pub values: Option<String>,
201}
202
203/// A signal that is exposed on the outside of the package.
204#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Hash)]
205pub struct Signal {
206    /// The external pin name that exposes the signal.
207    pub pad: String,
208    pub group: Option<String>,
209    pub index: Option<u8>,
210}
211
212/// An AVR architecture (mcu family) name.
213///
214/// Architecture is a misnomer - 'mcu family' would make sense.
215/// Cores with the same instruction sets share an architecture name.
216#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
217pub enum Architecture {
218    Unknown,
219
220    Avr0,
221    Avr1,
222    Avr2,
223    Avr25,
224    Avr3,
225    Avr31,
226    Avr35,
227    Avr4,
228    Avr5,
229    Avr51,
230    Avr6,
231    Xmega2,
232    Xmega3,
233    Xmega4,
234    Xmega5,
235    Xmega6,
236    Xmega7,
237    Tiny,
238}
239
240/// A port, such as `PORTB`.
241#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Hash)]
242pub struct Port<'a> {
243    /// The port peripheral instance.
244    instance: &'a Instance,
245    /// The register group associated with the port.
246    register_group: &'a RegisterGroup,
247}
248
249impl Mcu {
250    /// Gets a peripheral module by name.
251    pub fn peripheral(&self, name: &str) -> Option<&Peripheral> {
252        self.device.peripherals.iter().find(|p| p.name == name)
253    }
254
255    /// Gets a module by name.
256    pub fn module(&self, name: &str) -> Option<&Module> {
257        self.modules.iter().find(|p| p.name == name)
258    }
259
260    /// Gets an iterator over all register groups.
261    pub fn register_groups<'a>(&'a self) -> impl Iterator<Item = &'a RegisterGroup> {
262        self.modules.iter().flat_map(|m| m.register_groups.iter())
263    }
264
265    /// Gets an iterator over all registers.
266    pub fn registers<'a>(&'a self) -> impl Iterator<Item = &'a Register> {
267        self.register_groups().flat_map(|rg| rg.registers.iter())
268    }
269
270    /// Gets a port by letter.
271    pub fn port(&self, letter: char) -> Port {
272        let port_name = format!("PORT{}", letter);
273        let instance = self
274            .port_peripheral()
275            .instance(&port_name)
276            .expect("no port instance with that letter found");
277        let register_group = self
278            .port_module()
279            .register_group(&port_name)
280            .expect("no port register group with that letter found");
281        Port { instance, register_group }
282    }
283
284    /// Gets the port peripheral.
285    pub fn port_peripheral(&self) -> &Peripheral {
286        self.peripheral("PORT").expect("mcu does not have a port peripheral")
287    }
288
289    /// Gets the port module.
290    pub fn port_module(&self) -> &Module {
291        self.module("PORT").expect("mcu does not have a port module")
292    }
293}
294
295impl Peripheral {
296    /// Gets an instance by name.
297    pub fn instance(&self, name: &str) -> Option<&Instance> {
298        self.instances.iter().find(|i| i.name == name)
299    }
300
301    /// Gets an iterator over all signals that the peripheral uses.
302    pub fn signals<'a>(&'a self) -> impl Iterator<Item = &'a Signal> {
303        self.instances.iter().flat_map(|i| i.signals.iter())
304    }
305
306    pub fn instance_signal_with_pad(&self, pad: &str) -> Option<(&Instance, &Signal)> {
307        self.instance_signals_on_pad(pad).next()
308    }
309
310    /// Gets a tuple of `(instance, signal)` pairs that use a pad by its name.
311    fn instance_signals_on_pad<'a>(
312        &'a self,
313        pad: &str,
314    ) -> impl Iterator<Item = (&'a Instance, &'a Signal)> {
315        let mut instance_signals = Vec::new();
316
317        for instance in self.instances.iter() {
318            for signal in instance.signals.iter() {
319                if signal.pad == pad {
320                    instance_signals.push((instance, signal));
321                }
322            }
323        }
324        instance_signals.into_iter()
325    }
326}
327
328impl Module {
329    /// Gets a register group by name.
330    pub fn register_group(&self, name: &str) -> Option<&RegisterGroup> {
331        self.register_groups.iter().find(|rg| rg.name == name)
332    }
333
334    /// Gets an iterator over all registers in the module.
335    pub fn registers<'a>(&'a self) -> impl Iterator<Item = &'a Register> {
336        self.register_groups.iter().flat_map(|rg| rg.registers.iter())
337    }
338}
339
340impl Register {
341    /// Get the union between two descriptions of the same register.
342    pub fn union(&self, with: &Self) -> Self {
343        assert_eq!(
344            self.name, with.name,
345            "can only take the union between different descriptions of the same register"
346        );
347
348        let mut result = self.clone();
349
350        match (result.mask, with.mask) {
351            (None, Some(v)) => result.mask = Some(v), // rhs is more specific
352            _ => (),
353        }
354
355        result
356    }
357}
358
359impl<'a> Port<'a> {
360    /// Gets all associated registers.
361    pub fn registers(&'a self) -> impl Iterator<Item = &'a Register> {
362        self.register_group.registers.iter()
363    }
364
365    /// Gets all associated signals.
366    pub fn signals(&'a self) -> impl Iterator<Item = &'a Signal> {
367        self.instance.signals.iter()
368    }
369
370    /// Gets the signal associated with a pad.
371    pub fn signal_with_pad(&'a self, pad: &str) -> Option<&'a Signal> {
372        self.signals().find(|s| s.pad == pad)
373    }
374
375    /// Gets the data direction register.
376    pub fn ddr_register(&self) -> &Register {
377        self.registers()
378            .find(|r| r.name.starts_with("DDR"))
379            .expect("port does not have ddr register")
380    }
381
382    /// Gets the port register.
383    pub fn port_register(&self) -> &Register {
384        self.registers()
385            .find(|r| r.name.starts_with("PORT"))
386            .expect("port does not have port register")
387    }
388
389    /// Gets the pin register.
390    pub fn pin_register(&self) -> &Register {
391        self.registers()
392            .find(|r| r.name.starts_with("PIN"))
393            .expect("port does not have pin register")
394    }
395}
396
397impl Architecture {
398    pub fn name(&self) -> &'static str {
399        use Architecture::*;
400
401        match self {
402            Unknown => "<unknown architecture>",
403            Avr0 => "avr0",
404            Avr1 => "avr1",
405            Avr2 => "avr2",
406            Avr25 => "avr25",
407            Avr3 => "avr3",
408            Avr31 => "avr31",
409            Avr35 => "avr35",
410            Avr4 => "avr4",
411            Avr5 => "avr5",
412            Avr51 => "avr51",
413            Avr6 => "avr6",
414            Xmega2 => "xmega2",
415            Xmega3 => "xmega3",
416            Xmega4 => "xmega4",
417            Xmega5 => "xmega5",
418            Xmega6 => "xmega6",
419            Xmega7 => "xmega7",
420            Tiny => "tiny",
421        }
422    }
423}