/*
* Copyright (C) 2017 AltOS-Rust Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//! Volatile memory operations.
//!
//! This library contains wrappers around raw pointers to perform volatile memory operations. This
//! is mainly useful for memory mapped I/O. Writing to the peripheral memory addresses will
//! normally be optimized out by the compiler. The `Volatile` type wraps a memory address to
//! perform volatile operations in order to force the compiler to keep these memory accesses and
//! stores.
//!
//! The creation of a `Volatile` pointer is generally unsafe, but the actual operations that you
//! can perform on it are considered safe by Rust's standards. This is because the actual memory
//! operations are performed through the `Deref` and `DerefMut` traits, which are defined as safe
//! methods. It is important to remember that a `Volatile` pointer is nearly identical to a
//! primitive pointer, and so all dereferencing operations on one should be considered unsafe (even
//! if not enforced by the compiler).
//!
//! # Examples
//!
//! ```rust,no_run
//! use volatile::Volatile;
//!
//! const IO_ADDR: *const u32 = 0x4000_4400 as *const _;
//!
//! unsafe {
//! let mut io_ptr = Volatile::new(IO_ADDR);
//! // Some bit that we need to set for an IO operation
//! *io_ptr |= 0b1 << 5;
//! }
//! ```
//!
//! On some embedded devices you may want to do something like wait for a certain amount of time to
//! pass measured by some amount of ticks.
//!
//! ```rust,no_run
//! // Some tick counter that may be updated by a hardware interrupt
//! static mut TICKS: usize = 0;
//!
//! while unsafe { TICKS < 10 } {/* wait for ticks to change */}
//! ```
//!
//! Normally, the Rust compilier would optimize this kind of operation into just an infinite
//! `loop`, since the value of `TICKS` can't change in a single threaded environment, but `TICKS`
//! could be updated by some hardware interrupt, so we want to keep reloading the value in order to
//! check it. So to get around this we can use a `Volatile` pointer to force the compiler to reload
//! the value every time through the loop.
//!
//! ```rust,no_run
//! use volatile::Volatile;
//!
//! static mut TICKS: usize = 0;
//!
//! unsafe {
//! let ticks_ptr = Volatile::new(&TICKS);
//! while *ticks_ptr < 10 {/* wait for ticks to change */}
//! }
//! ```
//!
//! Now the value of `TICKS` will be reloaded every time through the loop.
//!
//! Oftentimes when working with memory mapped peripherals, you will have a block of memory that
//! you want to be working on that contains control, status, and data registers for some hardware
//! peripheral. These are often best represented as structs with each of their registers as fields,
//! but without volatile operations, loads and stores to these memory addresses often get optimized
//! out by the compiler. To get around this you can use a `Volatile` pointer to point at the mapped
//! address and have it be represented as a struct of the correct type.
//!
//! ```rust,no_run
//! use volatile::Volatile;
//!
//! const USART_ADDR: *const Usart = 0x4000_4400 as *const _;
//! // For transmitting and receiving data over serial
//! #[repr(C)]
//! struct Usart {
//! control_reg: u32,
//! status_reg: u32,
//! tx_data_reg: u32,
//! rx_data_reg: u32,
//! }
//!
//! let recieved = unsafe {
//! let mut usart_block = Volatile::new(USART_ADDR);
//! // Set some bits, these will be hardware specific
//! usart_block.control_reg |= 0b11 << 5;
//!
//! while usart_block.status_reg & 0b1 << 7 == 0 {/*wait for hardware to set a bit*/}
//!
//! // Transmit some data
//! usart_block.tx_data_reg = 100;
//!
//! while usart_block.status_reg & 0b1 << 6 == 0 {/*wait for hardware to set some other bit*/}
//!
//! // Receive some data
//! usart_block.rx_data_reg
//! };
//! ```
//!
//! Every field access to a pointed at struct will be considered volatile and so will not be
//! optimized out by the compiler.
//!
//! Just as with primitive pointers, `Volatile` pointers can be created from valid references
//! safely, though their use should still be considered unsafe.
//!
//! ```rust
//! # #![allow(dead_code)]
//! use volatile::Volatile;
//!
//! let x: u32 = 0;
//! let ptr = Volatile::from(&x);
//! ```
use fmt;
use hash;
use *;
use Unsize;
use ;
/// A volatile pointer.
///
/// This type acts as a pointer that only uses volatile operations. Pointer arithmetic can be
/// performed on it, and it can be dereferenced to its raw type in order to perform volatile memory
/// operations. This is especially useful for I/O operations where writing and reading from memory
/// mapped I/O registers would normally be optimized out by the compiler.
///
/// The `Volatile` type has the same syntax as a primitive pointer, so all functions that you can
/// expect to use with a primitive pointer like `*const` or `*mut` can also be used with a
/// `Volatile` pointer.
///
/// # Examples
///
/// ```rust
/// use volatile::Volatile;
///
/// let value: i32 = 0;
/// unsafe {
/// let mut ptr = Volatile::new(&value);
/// let mask = 0x0F0F;
/// *ptr |= mask;
/// }
/// assert_eq!(value, 0x0F0F);
/// ```
///
/// `Volatile` pointers can also be used to point at whole structs, and any memory accesses into
/// that struct will also be considered volatile
///
/// ```rust
/// use volatile::Volatile;
/// use std::mem;
///
/// struct IODevice {
/// reg1: u32,
/// reg2: u32,
/// reg3: u32,
/// }
///
/// let io_device: IODevice = unsafe { mem::uninitialized() };
///
/// unsafe {
/// let mut ptr = Volatile::new(&io_device);
/// ptr.reg1 = 1;
/// ptr.reg2 = 2;
/// ptr.reg3 = 3;
/// assert_eq!(ptr.reg1, 1);
/// assert_eq!(ptr.reg2, 2);
/// assert_eq!(ptr.reg3, 3);
/// }
/// ```
///
/// # Safety
///
/// Because `Volatile` pointers are often used for memory mapped peripherals, the compiler can not
/// guarantee that the address pointed at is valid, so the creation of a `Volatile` pointer is
/// unsafe. If you have a valid reference to some object, you can safely create a `Volatile`
/// pointer to that object through the `From` trait implemented for references.
///
/// ```rust
/// use volatile::Volatile;
///
/// let x: u32 = 0;
/// let ptr = Volatile::from(&x);
/// ```
///
/// Be wary however that a `Volatile` pointer provides interior mutability, so creating a pointer
/// from a shared reference may break immutability guarantees if used improperly.
;