japaric-archived / cu

Testing ground for the Copper book (http://japaric.github.io/copper/).
Apache License 2.0
58 stars 1 forks source link

Borrow/freeze registers when accessing its bitband view #33

Open japaric opened 8 years ago

japaric commented 8 years ago

Currently, register::GPIOA and bb::gpio::GPIOA appear to be unrelated but they actually alias the same physical memory. This should be reflected in the API: Accessing register::GPIOA using its bitband region bb::gpio::GPIOA should freeze the former struct.

Here's one way to do that:

mod bb {
    mod gpio {
        pub struct Block {
            pub crl: [u32; 32],
            // ...
        }
    }
}

mod gpio {
    pub struct Block {
        pub crl: u32,
    }

    // Just to have different types for GPIOA, GPIOB, etc
    pub struct A {
        block: gpio::Block,
        // ...
    }

    // NOTE: Fake subtyping -- with this we can use GPIOA as a gpio::Block
    // Do the same with DerefMut
    impl Deref for A {
        type Target = Block;

        fn deref(&self) -> &Block {
            &self.block
        }
    }
}

trait BitBand {
    type View;

    fn bb(&self) -> &Self::View;
}

impl BitBand for gpio::A {
    type View = bb::gpio::Block;

    fn bb(&self) -> &bb::gpio::Block {
        &__BB_GPIOA
    }
}

extern {
    static __GPIOA: gpio::A;
    static __BB_GPIOA: bb::gpio::Block;
}

The gpio::A newtype is to make GPIOA and GPIOB have different types so the .bb() method call can be performed without arithmetic by directly returning the start address of the bitband region.