Skip to content

fix docs+examples, work without reset, fixes #365

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

- `variant()` method for field reader and `Variant` enum for fields with reserved values

- Update documentation, add examples for register access methods

- Add `write_with_zero` method for registers without reset value

### Changed

- Field readers and writers use one enum where it is possible
- Field readers and writers use one enum where it is possible

- Replace register and its reader/writer by generic types

- Replace register and its reader/writer by generic types
- Restore `unsafe` marker on register writer `bits()` method

## [v0.15.2] - 2019-07-29

Expand Down
55 changes: 50 additions & 5 deletions src/generate/generic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,16 @@ where
{
///Reads the contents of `Readable` register
///
///See [reading](https://rust-embedded.github.io/book/start/registers.html#reading) in book.
///You can read the contents of a register in such way:
///```ignore
///let bits = periph.reg.read().bits();
///```
///or get the content of a particular field of a register.
///```ignore
///let reader = periph.reg.read();
///let bits = reader.field1().bits();
///let flag = reader.field2().bit_is_set();
///```
#[inline(always)]
pub fn read(&self) -> R<U, Self> {
R {bits: self.register.get(), _reg: marker::PhantomData}
Expand All @@ -55,6 +64,8 @@ where
U: Copy,
{
///Writes the reset value to `Writable` register
///
///Resets the register to its initial state
#[inline(always)]
pub fn reset(&self) {
self.register.set(Self::reset_value())
Expand All @@ -68,7 +79,19 @@ where
{
///Writes bits to `Writable` register
///
///See [writing](https://rust-embedded.github.io/book/start/registers.html#writing) in book.
///You can write raw bits into a register:
///```ignore
///periph.reg.write(|w| unsafe { w.bits(rawbits) });
///```
///or write only the fields you need:
///```ignore
///periph.reg.write(|w| w
/// .field1().bits(newfield1bits)
/// .field2().set_bit()
/// .field3().variant(VARIANT)
///);
///```
///Other fields will have reset value.
#[inline(always)]
pub fn write<F>(&self, f: F)
where
Expand All @@ -84,6 +107,8 @@ where
U: Copy + Default
{
///Writes Zero to `Writable` register
///
///Similar to `write`, but unused bits will contain 0.
#[inline(always)]
pub fn write_with_zero<F>(&self, f: F)
where
Expand All @@ -100,7 +125,21 @@ where
{
///Modifies the contents of the register
///
///See [modifying](https://rust-embedded.github.io/book/start/registers.html#modifying) in book.
///E.g. to do a read-modify-write sequence to change parts of a register:
///```ignore
///periph.reg.modify(|r, w| unsafe { w.bits(
/// r.bits() | 3
///) });
///```
///or
///```ignore
///periph.reg.modify(|_, w| w
/// .field1().bits(newfield1bits)
/// .field2().set_bit()
/// .field3().variant(VARIANT)
///);
///```
///Other fields will have value they had before call `modify`.
#[inline(always)]
pub fn modify<F>(&self, f: F)
where
Expand All @@ -112,6 +151,9 @@ where
}

///Register/field reader
///
///Result of the [`read`](Reg::read) method of a register.
///Also it can be used in the [`modify`](Reg::read) method
pub struct R<U, T> {
pub(crate) bits: U,
_reg: marker::PhantomData<T>,
Expand Down Expand Up @@ -141,6 +183,7 @@ where
U: PartialEq,
FI: ToBits<U>
{
#[inline(always)]
fn eq(&self, other: &FI) -> bool {
self.bits.eq(&other._bits())
}
Expand All @@ -165,16 +208,18 @@ impl<FI> R<bool, FI> {
}

///Register writer
///
///Used as an argument to the closures in the [`write`](Reg::write) and [`modify`](Reg::modify) methods of the register
pub struct W<U, REG> {
///Writable bits
pub bits: U,
pub(crate) bits: U,
_reg: marker::PhantomData<REG>,
}

impl<U, REG> W<U, REG> {
///Writes raw bits to the register
#[inline(always)]
pub fn bits(&mut self, bits: U) -> &mut Self {
pub unsafe fn bits(&mut self, bits: U) -> &mut Self {
self.bits = bits;
self
}
Expand Down
32 changes: 17 additions & 15 deletions src/generate/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,26 +54,28 @@ pub fn render(
}

if can_write {
let rv = register
.reset_value
.or(defs.reset_value)
.map(|v| util::hex(v as u64))
.ok_or_else(|| format!("Register {} has no reset value", register.name))?;

let desc = format!("Writer for register {}", register.name);
let doc = format!("Register {} `reset()`'s with value {}", register.name, &rv);
mod_items.push(quote! {
#[doc = #desc]
pub type W = crate::W<#rty, super::#name_pc>;
#[doc = #doc]
impl crate::ResetValue for super::#name_pc {
type Type = #rty;
#[inline(always)]
fn reset_value() -> Self::Type { #rv }
}
});
methods.push("reset");
methods.push("write");
let res_val = register
.reset_value
.or(defs.reset_value)
.map(|v| util::hex(v as u64));
if let Some(rv) = res_val {
let doc = format!("Register {} `reset()`'s with value {}", register.name, &rv);
mod_items.push(quote! {
#[doc = #doc]
impl crate::ResetValue for super::#name_pc {
type Type = #rty;
#[inline(always)]
fn reset_value() -> Self::Type { #rv }
}
});
methods.push("reset");
methods.push("write");
}
methods.push("write_with_zero");
}

Expand Down
52 changes: 32 additions & 20 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,14 @@
//! ..
//! }
//! }
//! impl crate::ResetValue for CR2 {
//! type Type = u32;
//! fn reset_value() -> Self::Type { 0 }
//! }
//! ```
//!
//! ## `read`
//!
//! The `read` method "reads" the register using a **single**, volatile `LDR` instruction and
//! returns a proxy `R` struct that allows access to only the readable bits (i.e. not to the
//! reserved or write-only bits) of the `CR2` register:
Expand All @@ -236,10 +242,10 @@
//! /// Value read from the register
//! impl R {
//! /// Bit 0 - Slave address bit 0 (master mode)
//! pub fn sadd0(&self) -> SADD0R { .. }
//! pub fn sadd0(&self) -> SADD0_R { .. }
//!
//! /// Bits 1:7 - Slave address bit 7:1 (master mode)
//! pub fn sadd1(&self) -> SADD1R { .. }
//! pub fn sadd1(&self) -> SADD1_R { .. }
//!
//! (..)
//! }
Expand All @@ -256,26 +262,30 @@
//! }
//! ```
//!
//! ## `reset`
//!
//! The `ResetValue` trait provides `reset_value` which returns the value of the `CR2`
//! register after a reset. This value can be used to modify the
//! writable bitfields of the `CR2` register or reset it to its initial state.
//! Usage looks like this:
//!
//! ```ignore
//! if i2c1.c2r.write().reset()
//! ```
//!
//! ## `write`
//!
//! On the other hand, the `write` method writes some value to the register using a **single**,
//! volatile `STR` instruction. This method involves a `W` struct that only allows constructing
//! valid states of the `CR2` register.
//!
//! The only constructor that `W` provides is `reset_value` which returns the value of the `CR2`
//! register after a reset. The rest of `W` methods are "builder-like" and can be used to modify the
//! writable bitfields of the `CR2` register.
//!
//! ```ignore
//! impl CR2W {
//! /// Reset value
//! pub fn reset_value() -> Self {
//! CR2W { bits: 0 }
//! }
//!
//! impl W {
//! /// Bits 1:7 - Slave address bit 7:1 (master mode)
//! pub fn sadd1(&mut self) -> _SADD1W { .. }
//! pub fn sadd1(&mut self) -> SADD1_W { .. }
//!
//! /// Bit 0 - Slave address bit 0 (master mode)
//! pub fn sadd0(&mut self) -> SADD0R { .. }
//! pub fn sadd0(&mut self) -> SADD0_W { .. }
//! }
//! ```
//!
Expand All @@ -300,6 +310,8 @@
//! // field; instead, `6 & 3` (i.e. `2`) will be written to the bitfield.
//! ```
//!
//! ## `modify`
//!
//! Finally, the `modify` method performs a **single** read-modify-write
//! operation that involves **one** read (`LDR`) to the register, modifying the
//! value and then a **single** write (`STR`) of the modified value to the
Expand Down Expand Up @@ -327,16 +339,16 @@
//! The new `read` API returns an enum that you can match:
//!
//! ```ignore
//! match gpioa.dir.read().pin0() {
//! gpioa::dir::PIN0R::Input => { .. },
//! gpioa::dir::PIN0R::Output => { .. },
//! match gpioa.dir.read().pin0().variant() {
//! gpioa::dir::PIN0_A::Input => { .. },
//! gpioa::dir::PIN0_A::Output => { .. },
//! }
//! ```
//!
//! or test for equality
//!
//! ```ignore
//! if gpioa.dir.read().pin0() == gpio::dir::PIN0R::Input {
//! if gpioa.dir.read().pin0().variant() == gpio::dir::PIN0_A::Input {
//! ..
//! }
//! ```
Expand Down Expand Up @@ -366,8 +378,8 @@
//! write from an `enum`eration of the possible ones:
//!
//! ```ignore
//! // enum DIRW { Input, Output }
//! gpioa.dir.write(|w| w.pin0().variant(gpio::dir::PIN0W::Output));
//! // enum PIN0_A { Input, Output }
//! gpioa.dir.write(|w| w.pin0().variant(gpio::dir::PIN0_A::Output));
//! ```
//!
//! There are convenience methods to pick one of the variants without having to
Expand Down