diff --git a/patches/tock/01-persistent-storage.patch b/patches/tock/01-persistent-storage.patch
index 1a356a337c350da5e6017731cacf8d34af458069..5aaec063d52d18dcb77d17af092a6500812a5828 100644
--- a/patches/tock/01-persistent-storage.patch
+++ b/patches/tock/01-persistent-storage.patch
@@ -1,8 +1,8 @@
 diff --git a/boards/nordic/nrf52dk_base/src/lib.rs b/boards/nordic/nrf52dk_base/src/lib.rs
-index ddac9dbd..7e2a3298 100644
+index fe493727..105f7120 100644
 --- a/boards/nordic/nrf52dk_base/src/lib.rs
 +++ b/boards/nordic/nrf52dk_base/src/lib.rs
-@@ -105,6 +105,7 @@ pub struct Platform {
+@@ -104,6 +104,7 @@ pub struct Platform {
      // The nRF52dk does not have the flash chip on it, so we make this optional.
      nonvolatile_storage:
          Option<&'static capsules::nonvolatile_storage_driver::NonvolatileStorage<'static>>,
@@ -18,9 +18,9 @@ index ddac9dbd..7e2a3298 100644
              kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
              _ => f(None),
          }
-@@ -408,6 +410,14 @@ pub unsafe fn setup_board<I: nrf52::interrupt_service::InterruptService>(
-         None
-     };
+@@ -405,6 +407,14 @@ pub unsafe fn setup_board<I: nrf52::interrupt_service::InterruptService>(
+     );
+     nrf52::acomp::ACOMP.set_client(analog_comparator);
  
 +    let nvmc = static_init!(
 +        nrf52::nvmc::SyscallDriver,
@@ -33,8 +33,8 @@ index ddac9dbd..7e2a3298 100644
      // Start all of the clocks. Low power operation will require a better
      // approach than this.
      nrf52::clock::CLOCK.low_stop();
-@@ -441,6 +451,7 @@ pub unsafe fn setup_board<I: nrf52::interrupt_service::InterruptService>(
-         alarm: alarm,
+@@ -439,6 +449,7 @@ pub unsafe fn setup_board<I: nrf52::interrupt_service::InterruptService>(
+         analog_comparator: analog_comparator,
          nonvolatile_storage: nonvolatile_storage,
          ipc: kernel::ipc::IPC::new(board_kernel, &memory_allocation_capability),
 +        nvmc: nvmc,
@@ -286,10 +286,10 @@ index 5abd2d84..5a726fdb 100644
 +    }
 +}
 diff --git a/kernel/src/callback.rs b/kernel/src/callback.rs
-index 95b25cc0..a7d8bc5c 100644
+index ece4a443..9a1afc84 100644
 --- a/kernel/src/callback.rs
 +++ b/kernel/src/callback.rs
-@@ -50,6 +50,31 @@ impl AppId {
+@@ -52,6 +52,31 @@ impl AppId {
              (start, end)
          })
      }
diff --git a/patches/tock/02-usb.patch b/patches/tock/02-usb.patch
index 0ba33d842726e5bc58776ce545fa7ed7cdd3bf04..a75a5b353492d9d67dca5ec2d606f5c64ea420a1 100644
--- a/patches/tock/02-usb.patch
+++ b/patches/tock/02-usb.patch
@@ -1,8 +1,8 @@
 diff --git a/boards/nordic/nrf52840_dongle/src/main.rs b/boards/nordic/nrf52840_dongle/src/main.rs
-index 5a9da538..75043d13 100644
+index 9a8dccfd..ad3e69b8 100644
 --- a/boards/nordic/nrf52840_dongle/src/main.rs
 +++ b/boards/nordic/nrf52840_dongle/src/main.rs
-@@ -140,6 +140,7 @@ pub unsafe fn reset_handler() {
+@@ -144,6 +144,7 @@ pub unsafe fn reset_handler() {
          FAULT_RESPONSE,
          nrf52840::uicr::Regulator0Output::V3_0,
          false,
@@ -11,10 +11,10 @@ index 5a9da538..75043d13 100644
      );
  }
 diff --git a/boards/nordic/nrf52840dk/src/main.rs b/boards/nordic/nrf52840dk/src/main.rs
-index 0b19ea3f..bd71dfbe 100644
+index 127c4f2f..a5847805 100644
 --- a/boards/nordic/nrf52840dk/src/main.rs
 +++ b/boards/nordic/nrf52840dk/src/main.rs
-@@ -252,6 +252,7 @@ pub unsafe fn reset_handler() {
+@@ -236,6 +236,7 @@ pub unsafe fn reset_handler() {
          FAULT_RESPONSE,
          nrf52840::uicr::Regulator0Output::DEFAULT,
          false,
@@ -23,10 +23,10 @@ index 0b19ea3f..bd71dfbe 100644
      );
  }
 diff --git a/boards/nordic/nrf52dk/src/main.rs b/boards/nordic/nrf52dk/src/main.rs
-index b49518ff..39f996c4 100644
+index d67ac695..b0bd8bf1 100644
 --- a/boards/nordic/nrf52dk/src/main.rs
 +++ b/boards/nordic/nrf52dk/src/main.rs
-@@ -209,6 +209,7 @@ pub unsafe fn reset_handler() {
+@@ -213,6 +213,7 @@ pub unsafe fn reset_handler() {
          FAULT_RESPONSE,
          nrf52832::uicr::Regulator0Output::DEFAULT,
          false,
@@ -35,10 +35,10 @@ index b49518ff..39f996c4 100644
      );
  }
 diff --git a/boards/nordic/nrf52dk_base/src/lib.rs b/boards/nordic/nrf52dk_base/src/lib.rs
-index 7e2a3298..d391e455 100644
+index 105f7120..535e5cd8 100644
 --- a/boards/nordic/nrf52dk_base/src/lib.rs
 +++ b/boards/nordic/nrf52dk_base/src/lib.rs
-@@ -102,6 +102,13 @@ pub struct Platform {
+@@ -101,6 +101,13 @@ pub struct Platform {
          'static,
          capsules::virtual_alarm::VirtualMuxAlarm<'static, nrf52::rtc::Rtc<'static>>,
      >,
@@ -70,7 +70,7 @@ index 7e2a3298..d391e455 100644
      chip: &'static nrf52::chip::NRF52<I>,
  ) {
      // Make non-volatile memory writable and activate the reset button
-@@ -418,6 +429,44 @@ pub unsafe fn setup_board<I: nrf52::interrupt_service::InterruptService>(
+@@ -415,6 +426,44 @@ pub unsafe fn setup_board<I: nrf52::interrupt_service::InterruptService>(
          )
      );
  
@@ -115,10 +115,10 @@ index 7e2a3298..d391e455 100644
      // Start all of the clocks. Low power operation will require a better
      // approach than this.
      nrf52::clock::CLOCK.low_stop();
-@@ -449,6 +498,7 @@ pub unsafe fn setup_board<I: nrf52::interrupt_service::InterruptService>(
-         rng: rng,
+@@ -447,6 +496,7 @@ pub unsafe fn setup_board<I: nrf52::interrupt_service::InterruptService>(
          temp: temp,
          alarm: alarm,
+         analog_comparator: analog_comparator,
 +        usb: usb_driver,
          nonvolatile_storage: nonvolatile_storage,
          ipc: kernel::ipc::IPC::new(board_kernel, &memory_allocation_capability),
@@ -967,15 +967,15 @@ index 8ddb5895..8c1992cc 100644
  
  fn status_epin(ep: usize) -> Field<u32, EndpointStatus::Register> {
 diff --git a/chips/nrf52840/src/lib.rs b/chips/nrf52840/src/lib.rs
-index 0c281276..7e9f7d1e 100644
+index 9d58a705..942d0288 100644
 --- a/chips/nrf52840/src/lib.rs
 +++ b/chips/nrf52840/src/lib.rs
 @@ -2,7 +2,7 @@
  
  pub use nrf52::{
-     adc, aes, ble_radio, clock, constants, crt1, ficr, i2c, ieee802154_radio, init, nvmc, pinmux,
--    ppi, pwm, rtc, spi, temperature, timer, trng, uart, uicr,
-+    ppi, pwm, rtc, spi, temperature, timer, trng, uart, uicr, usbd,
+     acomp, adc, aes, ble_radio, clock, constants, crt1, ficr, i2c, ieee802154_radio, init, nvmc,
+-    pinmux, ppi, pwm, rtc, spi, temperature, timer, trng, uart, uicr,
++    pinmux, ppi, pwm, rtc, spi, temperature, timer, trng, uart, uicr, usbd,
  };
  pub mod chip;
  pub mod gpio;
diff --git a/patches/tock/03-app-memory.patch b/patches/tock/03-app-memory.patch
deleted file mode 100644
index 355375c4b7654bef5b172dc1f25e5fd6b1013e54..0000000000000000000000000000000000000000
--- a/patches/tock/03-app-memory.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/boards/nordic/nrf52840dk/src/main.rs b/boards/nordic/nrf52840dk/src/main.rs
-index bd71dfbe..e8247905 100644
---- a/boards/nordic/nrf52840dk/src/main.rs
-+++ b/boards/nordic/nrf52840dk/src/main.rs
-@@ -113,7 +113,7 @@ const FAULT_RESPONSE: kernel::procs::FaultResponse = kernel::procs::FaultRespons
- const NUM_PROCS: usize = 8;
- 
- #[link_section = ".app_memory"]
--static mut APP_MEMORY: [u8; 245760] = [0; 245760];
-+static mut APP_MEMORY: [u8; 0x3A000] = [0; 0x3A000];
- 
- static mut PROCESSES: [Option<&'static dyn kernel::procs::ProcessType>; NUM_PROCS] =
-     [None, None, None, None, None, None, None, None];
diff --git a/patches/tock/03-usb-debugging.patch b/patches/tock/03-usb-debugging.patch
new file mode 100644
index 0000000000000000000000000000000000000000..892a0f94eb6db0e1739025b7efd3eeeda148f3fd
--- /dev/null
+++ b/patches/tock/03-usb-debugging.patch
@@ -0,0 +1,22 @@
+diff --git a/boards/nordic/nrf52840dk/src/main.rs b/boards/nordic/nrf52840dk/src/main.rs
+index a5847805..f0b303bf 100644
+--- a/boards/nordic/nrf52840dk/src/main.rs
++++ b/boards/nordic/nrf52840dk/src/main.rs
+@@ -102,7 +102,7 @@ pub mod io;
+ // Whether to use UART debugging or Segger RTT (USB) debugging.
+ // - Set to false to use UART.
+ // - Set to true to use Segger RTT over USB.
+-const USB_DEBUGGING: bool = false;
++const USB_DEBUGGING: bool = true;
+ 
+ // State for loading and holding applications.
+ // How should the kernel respond when a process faults.
+@@ -112,7 +112,7 @@ const FAULT_RESPONSE: kernel::procs::FaultResponse = kernel::procs::FaultRespons
+ const NUM_PROCS: usize = 8;
+ 
+ #[link_section = ".app_memory"]
+-static mut APP_MEMORY: [u8; 0x3C000] = [0; 0x3C000];
++static mut APP_MEMORY: [u8; 0x3A000] = [0; 0x3A000];
+ 
+ static mut PROCESSES: [Option<&'static dyn kernel::procs::ProcessType>; NUM_PROCS] =
+     [None, None, None, None, None, None, None, None];
diff --git a/patches/tock/04-rtt.patch b/patches/tock/04-rtt.patch
deleted file mode 100644
index 70bb3822cfa03db1935eabb14430d79b38fe7c19..0000000000000000000000000000000000000000
--- a/patches/tock/04-rtt.patch
+++ /dev/null
@@ -1,522 +0,0 @@
-diff --git a/boards/acd52832/src/main.rs b/boards/acd52832/src/main.rs
-index c844ccaf..d60bbc00 100644
---- a/boards/acd52832/src/main.rs
-+++ b/boards/acd52832/src/main.rs
-@@ -304,23 +304,26 @@ pub unsafe fn reset_handler() {
-     );
- 
-     // RTT communication channel
-+    let name = b"Terminal\0";
-+    let up_buffer_name = name;
-+    let down_buffer_name = name;
-+    let up_buffer = static_init!([u8; 1024], [0; 1024]);
-+    let down_buffer = static_init!([u8; 32], [0; 32]);
-+
-     let rtt_memory = static_init!(
-         capsules::segger_rtt::SeggerRttMemory,
--        capsules::segger_rtt::SeggerRttMemory::new(
--            b"Terminal\0",
--            &mut capsules::segger_rtt::UP_BUFFER,
--            b"Terminal\0",
--            &mut capsules::segger_rtt::DOWN_BUFFER
-+        capsules::segger_rtt::SeggerRttMemory::new_raw(
-+            up_buffer_name,
-+            up_buffer.as_ptr(),
-+            up_buffer.len(),
-+            down_buffer_name,
-+            down_buffer.as_ptr(),
-+            down_buffer.len()
-         )
-     );
-     let rtt = static_init!(
-         capsules::segger_rtt::SeggerRtt<VirtualMuxAlarm<'static, nrf52832::rtc::Rtc>>,
--        capsules::segger_rtt::SeggerRtt::new(
--            virtual_alarm_rtt,
--            rtt_memory,
--            &mut capsules::segger_rtt::UP_BUFFER,
--            &mut capsules::segger_rtt::DOWN_BUFFER
--        )
-+        capsules::segger_rtt::SeggerRtt::new(virtual_alarm_rtt, rtt_memory, up_buffer, down_buffer)
-     );
-     hil::time::Alarm::set_client(virtual_alarm_rtt, rtt);
- 
-diff --git a/boards/nordic/nrf52840_dongle/src/main.rs b/boards/nordic/nrf52840_dongle/src/main.rs
-index 31d0b392..5a9da538 100644
---- a/boards/nordic/nrf52840_dongle/src/main.rs
-+++ b/boards/nordic/nrf52840_dongle/src/main.rs
-@@ -11,7 +11,7 @@ use kernel::component::Component;
- #[allow(unused_imports)]
- use kernel::{debug, debug_gpio, debug_verbose, static_init};
- use nrf52840::gpio::Pin;
--use nrf52dk_base::{SpiPins, UartPins};
-+use nrf52dk_base::{SpiPins, UartChannel, UartPins};
- 
- // The nRF52840 Dongle LEDs
- const LED1_PIN: Pin = Pin::P0_06;
-@@ -130,7 +130,7 @@ pub unsafe fn reset_handler() {
-         LED2_G_PIN,
-         LED2_B_PIN,
-         led,
--        &UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD),
-+        UartChannel::Pins(UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD)),
-         &SpiPins::new(SPI_MOSI, SPI_MISO, SPI_CLK),
-         &None,
-         button,
-diff --git a/boards/nordic/nrf52840dk/Cargo.toml b/boards/nordic/nrf52840dk/Cargo.toml
-index 171c497f..9d16f679 100644
---- a/boards/nordic/nrf52840dk/Cargo.toml
-+++ b/boards/nordic/nrf52840dk/Cargo.toml
-@@ -17,6 +17,10 @@ lto = true
- opt-level = "z"
- debug = true
- 
-+[features]
-+usb_debugging = []
-+default = ["usb_debugging"]
-+
- [dependencies]
- components = { path = "../../components" }
- cortexm4 = { path = "../../../arch/cortex-m4" }
-diff --git a/boards/nordic/nrf52840dk/src/io.rs b/boards/nordic/nrf52840dk/src/io.rs
-index 4c4f3bf3..608fa9ca 100644
---- a/boards/nordic/nrf52840dk/src/io.rs
-+++ b/boards/nordic/nrf52840dk/src/io.rs
-@@ -1,19 +1,46 @@
- use core::fmt::Write;
- use core::panic::PanicInfo;
- use cortexm4;
-+#[cfg(feature = "usb_debugging")]
-+use kernel::common::cells::TakeCell;
- use kernel::debug;
- use kernel::debug::IoWrite;
- use kernel::hil::led;
-+#[cfg(not(feature = "usb_debugging"))]
- use kernel::hil::uart::{self, Configure};
- use nrf52840::gpio::Pin;
- 
- use crate::PROCESSES;
- 
- struct Writer {
-+    #[cfg(not(feature = "usb_debugging"))]
-     initialized: bool,
-+    #[cfg(feature = "usb_debugging")]
-+    rtt_memory: TakeCell<'static, capsules::segger_rtt::SeggerRttMemory<'static>>,
- }
- 
-+#[cfg(not(feature = "usb_debugging"))]
- static mut WRITER: Writer = Writer { initialized: false };
-+#[cfg(feature = "usb_debugging")]
-+static mut WRITER: Writer = Writer {
-+    rtt_memory: TakeCell::empty(),
-+};
-+
-+#[cfg(feature = "usb_debugging")]
-+fn wait() {
-+    let mut x = 0;
-+    for i in 0..5000 {
-+        unsafe { core::ptr::write_volatile(&mut x as *mut _, i) };
-+    }
-+}
-+
-+/// Set the RTT memory buffer used to output panic messages.
-+#[cfg(feature = "usb_debugging")]
-+pub unsafe fn set_rtt_memory(
-+    rtt_memory: &'static mut capsules::segger_rtt::SeggerRttMemory<'static>,
-+) {
-+    WRITER.rtt_memory.replace(rtt_memory);
-+}
- 
- impl Write for Writer {
-     fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
-@@ -23,6 +50,7 @@ impl Write for Writer {
- }
- 
- impl IoWrite for Writer {
-+    #[cfg(not(feature = "usb_debugging"))]
-     fn write(&mut self, buf: &[u8]) {
-         let uart = unsafe { &mut nrf52840::uart::UARTE0 };
-         if !self.initialized {
-@@ -42,6 +70,30 @@ impl IoWrite for Writer {
-             while !uart.tx_ready() {}
-         }
-     }
-+
-+    #[cfg(feature = "usb_debugging")]
-+    fn write(&mut self, buf: &[u8]) {
-+        // TODO: initialize if needed.
-+        self.rtt_memory.map(|rtt_memory| {
-+            let up_buffer = &mut rtt_memory.up_buffer;
-+            let buffer_len = up_buffer.length.get();
-+            let buffer = unsafe {
-+                core::slice::from_raw_parts_mut(
-+                    up_buffer.buffer.get() as *mut u8,
-+                    buffer_len as usize,
-+                )
-+            };
-+
-+            let mut write_position = up_buffer.write_position.get();
-+
-+            for &c in buf {
-+                buffer[write_position as usize] = c;
-+                write_position = (write_position + 1) % buffer_len;
-+                up_buffer.write_position.set(write_position);
-+                wait();
-+            }
-+        });
-+    }
- }
- 
- #[cfg(not(test))]
-diff --git a/boards/nordic/nrf52840dk/src/main.rs b/boards/nordic/nrf52840dk/src/main.rs
-index 57c42436..0b19ea3f 100644
---- a/boards/nordic/nrf52840dk/src/main.rs
-+++ b/boards/nordic/nrf52840dk/src/main.rs
-@@ -68,7 +68,9 @@ use kernel::component::Component;
- #[allow(unused_imports)]
- use kernel::{debug, debug_gpio, debug_verbose, static_init};
- use nrf52840::gpio::Pin;
--use nrf52dk_base::{SpiMX25R6435FPins, SpiPins, UartPins};
-+#[cfg(not(feature = "usb_debugging"))]
-+use nrf52dk_base::UartPins;
-+use nrf52dk_base::{SpiMX25R6435FPins, SpiPins, UartChannel};
- 
- // The nRF52840DK LEDs (see back of board)
- const LED1_PIN: Pin = Pin::P0_13;
-@@ -83,9 +85,13 @@ const BUTTON3_PIN: Pin = Pin::P0_24;
- const BUTTON4_PIN: Pin = Pin::P0_25;
- const BUTTON_RST_PIN: Pin = Pin::P0_18;
- 
-+#[cfg(not(feature = "usb_debugging"))]
- const UART_RTS: Pin = Pin::P0_05;
-+#[cfg(not(feature = "usb_debugging"))]
- const UART_TXD: Pin = Pin::P0_06;
-+#[cfg(not(feature = "usb_debugging"))]
- const UART_CTS: Pin = Pin::P0_07;
-+#[cfg(not(feature = "usb_debugging"))]
- const UART_RXD: Pin = Pin::P0_08;
- 
- const SPI_MOSI: Pin = Pin::P0_20;
-@@ -123,6 +129,37 @@ pub unsafe fn reset_handler() {
-     // Loads relocations and clears BSS
-     nrf52840::init();
- 
-+    // Initialize Segger RTT as early as possible so that any panic beyond this point can use the
-+    // RTT memory object.
-+    #[cfg(feature = "usb_debugging")]
-+    let (up_buffer, down_buffer, rtt_memory) = {
-+        let name = b"Terminal\0";
-+        let up_buffer_name = name;
-+        let down_buffer_name = name;
-+        let up_buffer = static_init!([u8; 1024], [0; 1024]);
-+        let down_buffer = static_init!([u8; 32], [0; 32]);
-+
-+        let rtt_memory = static_init!(
-+            capsules::segger_rtt::SeggerRttMemory,
-+            capsules::segger_rtt::SeggerRttMemory::new_raw(
-+                up_buffer_name,
-+                up_buffer.as_ptr(),
-+                up_buffer.len(),
-+                down_buffer_name,
-+                down_buffer.as_ptr(),
-+                down_buffer.len()
-+            )
-+        );
-+
-+        (up_buffer, down_buffer, rtt_memory)
-+    };
-+
-+    // XXX: This is inherently unsafe as it aliases the mutable reference to rtt_memory. This
-+    // aliases reference is only used inside a panic handler, which should be OK, but maybe we
-+    // should use a const reference to rtt_memory and leverage interior mutability instead.
-+    #[cfg(feature = "usb_debugging")]
-+    self::io::set_rtt_memory(&mut *(rtt_memory as *mut _));
-+
-     let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&PROCESSES));
-     let gpio = components::gpio::GpioComponent::new(board_kernel).finalize(
-         components::gpio_component_helper!(
-@@ -198,7 +235,10 @@ pub unsafe fn reset_handler() {
-         LED2_PIN,
-         LED3_PIN,
-         led,
--        &UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD),
-+        #[cfg(feature = "usb_debugging")]
-+        UartChannel::Rtt(up_buffer, down_buffer, rtt_memory),
-+        #[cfg(not(feature = "usb_debugging"))]
-+        UartChannel::Pins(UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD)),
-         &SpiPins::new(SPI_MOSI, SPI_MISO, SPI_CLK),
-         &Some(SpiMX25R6435FPins::new(
-             SPI_MX25R6435F_CHIP_SELECT,
-diff --git a/boards/nordic/nrf52dk/src/main.rs b/boards/nordic/nrf52dk/src/main.rs
-index 693f1e18..b49518ff 100644
---- a/boards/nordic/nrf52dk/src/main.rs
-+++ b/boards/nordic/nrf52dk/src/main.rs
-@@ -68,7 +68,7 @@ use kernel::component::Component;
- #[allow(unused_imports)]
- use kernel::{debug, debug_gpio, debug_verbose, static_init};
- use nrf52832::gpio::Pin;
--use nrf52dk_base::{SpiPins, UartPins};
-+use nrf52dk_base::{SpiPins, UartChannel, UartPins};
- 
- // The nRF52 DK LEDs (see back of board)
- const LED1_PIN: Pin = Pin::P0_17;
-@@ -199,7 +199,7 @@ pub unsafe fn reset_handler() {
-         LED2_PIN,
-         LED3_PIN,
-         led,
--        &UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD),
-+        UartChannel::Pins(UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD)),
-         &SpiPins::new(SPI_MOSI, SPI_MISO, SPI_CLK),
-         &None,
-         button,
-diff --git a/boards/nordic/nrf52dk_base/src/lib.rs b/boards/nordic/nrf52dk_base/src/lib.rs
-index 17be93a4..ddac9dbd 100644
---- a/boards/nordic/nrf52dk_base/src/lib.rs
-+++ b/boards/nordic/nrf52dk_base/src/lib.rs
-@@ -70,6 +70,15 @@ impl UartPins {
-     }
- }
- 
-+pub enum UartChannel<'a> {
-+    Pins(UartPins),
-+    Rtt(
-+        &'a mut [u8],
-+        &'a mut [u8],
-+        &'a mut capsules::segger_rtt::SeggerRttMemory<'a>,
-+    ),
-+}
-+
- /// Supported drivers by the platform
- pub struct Platform {
-     ble_radio: &'static capsules::ble_advertising_driver::BLE<
-@@ -136,7 +145,7 @@ pub unsafe fn setup_board<I: nrf52::interrupt_service::InterruptService>(
-     debug_pin2_index: Pin,
-     debug_pin3_index: Pin,
-     led: &'static capsules::led::LED<'static>,
--    uart_pins: &UartPins,
-+    uart_channel: UartChannel<'static>,
-     spi_pins: &SpiPins,
-     mx25r6435f: &Option<SpiMX25R6435FPins>,
-     button: &'static capsules::button::Button<'static>,
-@@ -232,6 +241,38 @@ pub unsafe fn setup_board<I: nrf52::interrupt_service::InterruptService>(
-     let alarm = components::alarm::AlarmDriverComponent::new(board_kernel, mux_alarm)
-         .finalize(components::alarm_component_helper!(nrf52::rtc::Rtc));
- 
-+    let channel: &dyn kernel::hil::uart::Uart = match uart_channel {
-+        UartChannel::Pins(uart_pins) => {
-+            nrf52::uart::UARTE0.initialize(
-+                nrf52::pinmux::Pinmux::new(uart_pins.txd as u32),
-+                nrf52::pinmux::Pinmux::new(uart_pins.rxd as u32),
-+                Some(nrf52::pinmux::Pinmux::new(uart_pins.cts as u32)),
-+                Some(nrf52::pinmux::Pinmux::new(uart_pins.rts as u32)),
-+            );
-+            &nrf52::uart::UARTE0
-+        }
-+        UartChannel::Rtt(up_buffer, down_buffer, rtt_memory) => {
-+            // Virtual alarm for the Segger RTT communication channel
-+            let virtual_alarm_rtt = static_init!(
-+                capsules::virtual_alarm::VirtualMuxAlarm<'static, nrf52::rtc::Rtc>,
-+                capsules::virtual_alarm::VirtualMuxAlarm::new(mux_alarm)
-+            );
-+
-+            // RTT communication channel
-+            let rtt = static_init!(
-+                capsules::segger_rtt::SeggerRtt<VirtualMuxAlarm<'static, nrf52::rtc::Rtc>>,
-+                capsules::segger_rtt::SeggerRtt::new(
-+                    virtual_alarm_rtt,
-+                    rtt_memory,
-+                    up_buffer,
-+                    down_buffer
-+                )
-+            );
-+            hil::time::Alarm::set_client(virtual_alarm_rtt, rtt);
-+            rtt
-+        }
-+    };
-+
-     let dynamic_deferred_call_clients =
-         static_init!([DynamicDeferredCallClientState; 2], Default::default());
-     let dynamic_deferred_caller = static_init!(
-@@ -241,19 +282,10 @@ pub unsafe fn setup_board<I: nrf52::interrupt_service::InterruptService>(
-     DynamicDeferredCall::set_global_instance(dynamic_deferred_caller);
- 
-     // Create a shared UART channel for the console and for kernel debug.
--    let uart_mux = components::console::UartMuxComponent::new(
--        &nrf52::uart::UARTE0,
--        115200,
--        dynamic_deferred_caller,
--    )
--    .finalize(());
--
--    nrf52::uart::UARTE0.initialize(
--        nrf52::pinmux::Pinmux::new(uart_pins.txd as u32),
--        nrf52::pinmux::Pinmux::new(uart_pins.rxd as u32),
--        Some(nrf52::pinmux::Pinmux::new(uart_pins.cts as u32)),
--        Some(nrf52::pinmux::Pinmux::new(uart_pins.rts as u32)),
--    );
-+    let uart_mux =
-+        components::console::UartMuxComponent::new(channel, 115200, dynamic_deferred_caller)
-+            .finalize(());
-+
-     let pconsole =
-         components::process_console::ProcessConsoleComponent::new(board_kernel, uart_mux)
-             .finalize(());
-diff --git a/capsules/src/segger_rtt.rs b/capsules/src/segger_rtt.rs
-index 1bf93fc1..33103c57 100644
---- a/capsules/src/segger_rtt.rs
-+++ b/capsules/src/segger_rtt.rs
-@@ -91,67 +91,69 @@
- //! ```
- 
- use core::cell::Cell;
--use kernel::common::cells::{OptionalCell, TakeCell};
-+use core::marker::PhantomData;
-+use kernel::common::cells::{OptionalCell, TakeCell, VolatileCell};
- use kernel::hil;
- use kernel::hil::time::Frequency;
- use kernel::hil::uart;
- use kernel::ReturnCode;
- 
--/// Buffer for transmitting to the host.
--pub static mut UP_BUFFER: [u8; 1024] = [0; 1024];
--
--/// Buffer for receiving messages from the host.
--pub static mut DOWN_BUFFER: [u8; 32] = [0; 32];
--
- /// This structure is defined by the segger RTT protocol. It must exist in
- /// memory in exactly this form so that the segger JTAG tool can find it in the
- /// chip's memory and read and write messages to the appropriate buffers.
- #[repr(C)]
--pub struct SeggerRttMemory {
--    id: [u8; 16],
--    number_up_buffers: u32,
--    number_down_buffers: u32,
--    up_buffer: SeggerRttBuffer,
--    down_buffer: SeggerRttBuffer,
-+pub struct SeggerRttMemory<'a> {
-+    id: VolatileCell<[u8; 16]>,
-+    number_up_buffers: VolatileCell<u32>,
-+    number_down_buffers: VolatileCell<u32>,
-+    pub up_buffer: SeggerRttBuffer<'a>,
-+    down_buffer: SeggerRttBuffer<'a>,
- }
- 
- #[repr(C)]
--pub struct SeggerRttBuffer {
--    name: *const u8, // Pointer to the name of this channel. Must be a 4 byte thin pointer.
--    buffer: *const u8, // Pointer to the buffer for this channel.
--    length: u32,
--    write_position: u32,
--    read_position: u32,
--    flags: u32,
-+pub struct SeggerRttBuffer<'a> {
-+    name: VolatileCell<*const u8>, // Pointer to the name of this channel. Must be a 4 byte thin pointer.
-+    pub buffer: VolatileCell<*const u8>, // Pointer to the buffer for this channel.
-+    pub length: VolatileCell<u32>,
-+    pub write_position: VolatileCell<u32>,
-+    read_position: VolatileCell<u32>,
-+    flags: VolatileCell<u32>,
-+    _lifetime: PhantomData<&'a [u8]>,
- }
- 
--impl SeggerRttMemory {
--    pub fn new(
-+impl SeggerRttMemory<'a> {
-+    pub fn new_raw(
-         up_buffer_name: &'a [u8],
--        up_buffer: &'static mut [u8],
--        down_buffer_name: &'static [u8],
--        down_buffer: &'static mut [u8],
--    ) -> SeggerRttMemory {
-+        up_buffer_ptr: *const u8,
-+        up_buffer_len: usize,
-+        down_buffer_name: &'a [u8],
-+        down_buffer_ptr: *const u8,
-+        down_buffer_len: usize,
-+    ) -> SeggerRttMemory<'a> {
-         SeggerRttMemory {
-+            // TODO: only write this ID when the object is fully initialized, to avoid having
-+            // these bytes elsewhere in (flash) memory.
-             // Must be "SEGGER RTT".
--            id: *b"SEGGER RTT\0\0\0\0\0\0",
--            number_up_buffers: 1,
--            number_down_buffers: 1,
-+            id: VolatileCell::new(*b"SEGGER RTT\0\0\0\0\0\0"),
-+            number_up_buffers: VolatileCell::new(1),
-+            number_down_buffers: VolatileCell::new(1),
-             up_buffer: SeggerRttBuffer {
--                name: up_buffer_name.as_ptr(),
--                buffer: up_buffer.as_ptr(),
--                length: 1024,
--                write_position: 0,
--                read_position: 0,
--                flags: 0,
-+                name: VolatileCell::new(up_buffer_name.as_ptr()),
-+                buffer: VolatileCell::new(up_buffer_ptr),
-+                length: VolatileCell::new(up_buffer_len as u32),
-+                write_position: VolatileCell::new(0),
-+                read_position: VolatileCell::new(0),
-+                flags: VolatileCell::new(0),
-+                _lifetime: PhantomData,
-             },
-             down_buffer: SeggerRttBuffer {
--                name: down_buffer_name.as_ptr(),
--                buffer: down_buffer.as_ptr(),
--                length: 32,
--                write_position: 0,
--                read_position: 0,
--                flags: 0,
-+                name: VolatileCell::new(down_buffer_name.as_ptr()),
-+                buffer: VolatileCell::new(down_buffer_ptr),
-+                length: VolatileCell::new(down_buffer_len as u32),
-+                write_position: VolatileCell::new(0),
-+                read_position: VolatileCell::new(0),
-+                flags: VolatileCell::new(0),
-+                _lifetime: PhantomData,
-             },
-         }
-     }
-@@ -159,9 +161,9 @@ impl SeggerRttMemory {
- 
- pub struct SeggerRtt<'a, A: hil::time::Alarm<'a>> {
-     alarm: &'a A, // Dummy alarm so we can get a callback.
--    config: TakeCell<'a, SeggerRttMemory>,
--    up_buffer: TakeCell<'static, [u8]>,
--    _down_buffer: TakeCell<'static, [u8]>,
-+    config: TakeCell<'a, SeggerRttMemory<'a>>,
-+    up_buffer: TakeCell<'a, [u8]>,
-+    _down_buffer: TakeCell<'a, [u8]>,
-     client: OptionalCell<&'a dyn uart::TransmitClient>,
-     client_buffer: TakeCell<'static, [u8]>,
-     tx_len: Cell<usize>,
-@@ -170,9 +172,9 @@ pub struct SeggerRtt<'a, A: hil::time::Alarm<'a>> {
- impl<'a, A: hil::time::Alarm<'a>> SeggerRtt<'a, A> {
-     pub fn new(
-         alarm: &'a A,
--        config: &'a mut SeggerRttMemory,
--        up_buffer: &'static mut [u8],
--        down_buffer: &'static mut [u8],
-+        config: &'a mut SeggerRttMemory<'a>,
-+        up_buffer: &'a mut [u8],
-+        down_buffer: &'a mut [u8],
-     ) -> SeggerRtt<'a, A> {
-         SeggerRtt {
-             alarm: alarm,
-@@ -205,15 +207,15 @@ impl<'a, A: hil::time::Alarm<'a>> uart::Transmit<'a> for SeggerRtt<'a, A> {
-                     // Copy the incoming data into the buffer. Once we increment
-                     // the `write_position` the RTT listener will go ahead and read
-                     // the message from us.
--                    let mut index = config.up_buffer.write_position as usize;
--                    let buffer_len = config.up_buffer.length as usize;
-+                    let mut index = config.up_buffer.write_position.get() as usize;
-+                    let buffer_len = config.up_buffer.length.get() as usize;
- 
-                     for i in 0..tx_len {
-                         buffer[(i + index) % buffer_len] = tx_data[i];
-                     }
- 
-                     index = (index + tx_len) % buffer_len;
--                    config.up_buffer.write_position = index as u32;
-+                    config.up_buffer.write_position.set(index as u32);
-                     self.tx_len.set(tx_len);
-                     // Save the client buffer so we can pass it back with the callback.
-                     self.client_buffer.replace(tx_data);
diff --git a/third_party/tock b/third_party/tock
index 862452b77ae0fc160231a2250de385dc7c358ef7..3a7d6b775d972798bfd731cba8365b58fab27175 160000
--- a/third_party/tock
+++ b/third_party/tock
@@ -1 +1 @@
-Subproject commit 862452b77ae0fc160231a2250de385dc7c358ef7
+Subproject commit 3a7d6b775d972798bfd731cba8365b58fab27175