1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
//! # peripherals //! //! Define and access your microcontroller peripherals //! //! ## Features //! //! - A macro to generate code for peripherals, registers, and register fields //! - Zero-sized structs to represent peripherals and registers //! - Enums or newtype struct to represent fields values //! - Combine values to write to a regiser with `|` (binary or) //! - Read/write access at the regiser level //! - Strong typing ensure you don't mix up registers //! - Generic over the peripheral instance //! //! ## Usage //! //! Peripherals are defined with the [`periph!`] macro. Registers and fields can be defined in the //! same macro invocation or separately with the [`register!`] and [`field_type!`] macros. //! Microcontrollers / devices are then defined with the [`device!`] macro. //! //! These macros generate types to represent fields and their values, and marker types for //! registers and peripherals. These types can be seen in the [`example`] module. //! //! Registers are accessed with the [`Reg`] struct. [`Value`]s are used to read and write them. //! //! To use the generated device struct, create it from `()` as part of your initialisation routine. //! There sould be only one instance of the device (and the right one) in your whole program. //! //! ## Operators //! //! Most types implements the `|` (bit or), `&` (bit and) and `^` (xor) operators. Operations that //! returns that same type as their left operand can be written in the assign form, i.e. `|=`, `&=` //! and `^=`. The operands can be of the type written in the table below, or anything that converts //! to that type. //! //! Operation | Resulting type | Description //! ---------------------------------- | --------------- | ---------------------------------- //! [`Fields`] \| [`Fields`] | [`Fields`] | Fields in either or both operands //! [`Fields`] & [`Fields`] | [`Fields`] | Fields in both operands //! [`Fields`] ^ [`Fields`] | [`Fields`] | Fields in only one of the operands //! [`FieldValues`] \| [`FieldValues`] | [`FieldValues`] | Field values in either operand, with the value of the right operand if the field is specified in both //! [`FieldValues`] & [`Fields`] | [`FieldValues`] | Field values of fields in both operands //! [`FieldValues`] ^ [`Fields`] | [`FieldValues`] | Left operand with values of fields in both operands toggled (inverted) //! [`Value`] \| [`FieldValues`] | [`Value`] | Left operand with the values of the fields in the right operand //! [`Value`] & [`Fields`] | [`FieldValues`] | Values of fields in right operand //! [`Value`] ^ [`Fields`] | [`Value`] | Left operand with values of the fields in right operand toggled (inverted) //! //! ## Attribute in macros //! //! By default, attributes exand on generated types and fields, and not expand on generated impls. //! This can be changed by inserting `type:`, `field:`, `impl:` or `all:` to specify on what the //! attribute should be present. See the [`attributes`] module for examples. //! //! This allows to use e.g. `cfg` and `repr` attribute by writting `#[all: cfg(...)]` and `#[type: repr(...)]`. // Idealy `derive`, `non_exhaustive`, `must_use` and `repr` would expand only on types, `doc` on // types and fields, and any other attributes on everything. This however makes macros much more // complex #![no_std] #![warn(missing_docs)] #![warn(clippy::missing_inline_in_public_items)] #![warn(clippy::missing_const_for_fn)] #[doc(hidden)] pub use paste::paste; pub use utils::*; mod utils; mod macros; #[cfg(any(doc, test))] pub mod attributes; #[cfg(any(doc, test))] pub mod example;