diff --git a/CHANGELOG.md b/CHANGELOG.md
index c4225fe26b8027b089335f13657d60b5f1d1e837..6b99f5ca116d17cad9a470c0dab556686247f242 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
 
 ## [Unreleased]
 
+## [v0.4.0] - 2018-01-15
+
+### Added
+
+- Formatter and Flush Control register (FFCR) accessor to the TPIU register block.
+
+- A `singleton!` macro that creates mutable reference to a statically allocated variable.
+
+- A Cargo feature, `cm7-r0p1`, to work around a silicon erratum that affects writes to BASEPRI on
+  Cortex-M7 r0p1 devices.
+
+### Changed
+
+- [breaking-change] All peripherals are now exposed as scoped singletons and they need to be `take`n
+  into scope to become accessible.
+
+- [breaking-change] The signatures of methods exposed by peripheral proxies have changed to
+  better match the new scoped singletons semantics.
+
+- All the thin wrappers around assembly instructions now panic when executed on non-ARM devices.
+
+### Removed
+
+- [breaking-change] APIs specific to ARMv7-M (`peripheral::{cbp, fpb, fpu, itm, tpiu}`, `itm`) when
+  compiling for `thumb6m-none-eabi`.
+
 ## [v0.3.1] - 2017-07-20
 
 ### Changed
diff --git a/Cargo.toml b/Cargo.toml
index 8a6c0e247d5f893cbcd027aade2ed12a0671fe41..da25ca46a95fdbeea029170e7235dd00e9c1d704 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,7 +7,7 @@ keywords = ["arm", "cortex-m", "register", "peripheral"]
 license = "MIT OR Apache-2.0"
 name = "cortex-m"
 repository = "https://github.com/japaric/cortex-m"
-version = "0.3.1"
+version = "0.4.0"
 
 [dependencies]
 aligned = "0.1.1"
diff --git a/src/peripheral/mod.rs b/src/peripheral/mod.rs
index 2abe79f62c3606d129ef4998d85906900a72b577..dad12a59bb841da81e60562f080bb0a8722ba1b2 100644
--- a/src/peripheral/mod.rs
+++ b/src/peripheral/mod.rs
@@ -3,9 +3,9 @@
 //! # API
 //!
 //! To use (most of) the peripheral API first you must get an *instance* of the peripheral. All the
-//! core peripherals are modeled as singletons (there can only ever be, at most, one instance of
-//! them at any given point in time) and the only way to get an instance of them is through the
-//! [`Peripherals::take`](struct.Peripherals.html#method.take) method.
+//! core peripherals are modeled as singletons (there can only ever be, at most, one instance of any
+//! one of them at any given point in time) and the only way to get an instance of them is through
+//! the [`Peripherals::take`](struct.Peripherals.html#method.take) method.
 //!
 //! ``` no_run
 //! extern crate cortex_m;
@@ -21,9 +21,19 @@
 //! This method can only be successfully called *once* -- this is why the method returns an
 //! `Option`. Subsequent calls to the method will result in a `None` value being returned.
 //!
+//! ``` no_run
+//! extern crate cortex_m;
+//!
+//! use cortex_m::peripheral::Peripherals;
+//!
+//! fn main() {
+//!     let ok = Peripherals::take().unwrap();
+//!     let panics = Peripherals::take().unwrap();
+//! }
+//! ```
 //! A part of the peripheral API doesn't require access to a peripheral instance. This part of the
 //! API is provided as static methods on the peripheral types. One example is the
-//! [`DWT::cyccnt`](struct.DWT.html#method.cyccnt) method.
+//! [`DWT::get_cycle_count`](struct.DWT.html#method.get_cycle_count) method.
 //!
 //! ``` no_run
 //! extern crate cortex_m;
@@ -43,7 +53,7 @@
 //!
 //! The singleton property can be *unsafely* bypassed using the `ptr` static method which is
 //! available on all the peripheral types. This method is a useful building block for implementing
-//! higher level and safe abstractions.
+//! safe higher level abstractions.
 //!
 //! ``` no_run
 //! extern crate cortex_m;