nrf52/uicr.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.
//! User information configuration registers
//!
//! Minimal implementation to support activation of the reset button on
//! nRF52-DK.
use crate::ficr;
use enum_primitive::cast::FromPrimitive;
use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
use kernel::utilities::registers::{register_bitfields, ReadWrite};
use kernel::utilities::StaticRef;
use crate::gpio::Pin;
const UICR_BASE: StaticRef<UicrRegisters> =
unsafe { StaticRef::new(0x10001200 as *const UicrRegisters) };
#[repr(C)]
struct UicrRegisters {
/// Mapping of the nRESET function (see POWER chapter for details)
/// - Address: 0x200 - 0x204
pselreset0: ReadWrite<u32, Pselreset::Register>,
/// Mapping of the nRESET function (see POWER chapter for details)
/// - Address: 0x204 - 0x208
pselreset1: ReadWrite<u32, Pselreset::Register>,
/// Access Port protection
/// - Address: 0x208 - 0x20c
approtect: ReadWrite<u32, ApProtect::Register>,
/// Setting of pins dedicated to NFC functionality: NFC antenna or GPIO
/// - Address: 0x20c - 0x210
nfcpins: ReadWrite<u32, NfcPins::Register>,
_reserved1: [u32; 60],
/// External circuitry to be supplied from VDD pin.
/// - Address: 0x300 - 0x304
extsupply: ReadWrite<u32, ExtSupply::Register>,
/// GPIO reference voltage
/// - Address: 0x304 - 0x308
regout0: ReadWrite<u32, RegOut::Register>,
}
register_bitfields! [u32,
/// Task register
Pselreset [
/// GPIO number Px.nn onto which Reset is exposed
PIN OFFSET(0) NUMBITS(5) [],
/// GPIO port number Pn.xx onto with Reset is exposed
PORT OFFSET(5) NUMBITS(1) [],
/// Connection
CONNECTION OFFSET(31) NUMBITS(1) [
DISCONNECTED = 1,
CONNECTED = 0
]
],
/// Access port protection
ApProtect [
/// Ready event
PALL OFFSET(0) NUMBITS(8) [
/// Enable
ENABLED = 0x00,
/// Disable for later nRF52 variants
HWDISABLE = 0x5a,
/// Disable
DISABLED = 0xff
]
],
/// Setting of pins dedicated to NFC functionality: NFC antenna or GPIO
NfcPins [
/// Setting pins dedicated to NFC functionality
PROTECT OFFSET(0) NUMBITS(1) [
/// Operation as GPIO pins. Same protection as normal GPIO pins
DISABLED = 0,
/// Operation as NFC antenna pins. Configures the protection for
/// NFC operation
NFC = 1
]
],
/// Enable external circuitry to be supplied from VDD pin
ExtSupply [
/// Enable external circuitry to be supplied from VDD pin
EXTSUPPLY OFFSET(0) NUMBITS(1) [
/// No current can be drawn from the VDD pin
DISABLED = 0,
/// It is allowed to supply external circuitry from the VDD pin
ENABLED = 1
]
],
/// GPIO reference voltage / external output supply voltage
RegOut [
/// Output voltage from REG0 regulator stage
VOUT OFFSET(0) NUMBITS(3) [
V1_8 = 0,
V2_1 = 1,
V2_4 = 2,
V2_7 = 3,
V3_0 = 4,
V3_3 = 5,
DEFAULT = 7
]
]
];
pub struct Uicr {
registers: StaticRef<UicrRegisters>,
}
#[derive(Copy, Clone, PartialEq)]
/// Output voltage from REG0 regulator stage.
///
/// The value is board dependent (e.g. the nRF52840dk board uses 1.8V
/// whereas the nRF52840-Dongle requires 3.0V to light its LEDs).
/// When a chip is out of the factory or fully erased, the default value (7)
/// will output 1.8V.
pub enum Regulator0Output {
V1_8 = 0,
V2_1 = 1,
V2_4 = 2,
V2_7 = 3,
V3_0 = 4,
V3_3 = 5,
DEFAULT = 7,
}
impl From<u32> for Regulator0Output {
fn from(val: u32) -> Self {
match val & 7 {
0 => Regulator0Output::V1_8,
1 => Regulator0Output::V2_1,
2 => Regulator0Output::V2_4,
3 => Regulator0Output::V2_7,
4 => Regulator0Output::V3_0,
5 => Regulator0Output::V3_3,
7 => Regulator0Output::DEFAULT,
_ => Regulator0Output::DEFAULT, // Invalid value, fall back to DEFAULT
}
}
}
impl Uicr {
pub const fn new() -> Uicr {
Uicr {
registers: UICR_BASE,
}
}
pub fn set_psel0_reset_pin(&self, pin: Pin) {
self.registers.pselreset0.set(pin as u32);
}
pub fn get_psel0_reset_pin(&self) -> Option<Pin> {
Pin::from_u32(self.registers.pselreset0.get())
}
pub fn set_psel1_reset_pin(&self, pin: Pin) {
self.registers.pselreset1.set(pin as u32);
}
pub fn get_psel1_reset_pin(&self) -> Option<Pin> {
Pin::from_u32(self.registers.pselreset1.get())
}
pub fn set_vout(&self, vout: Regulator0Output) {
self.registers.regout0.modify(RegOut::VOUT.val(vout as u32));
}
pub fn get_vout(&self) -> Regulator0Output {
Regulator0Output::from(self.registers.regout0.read(RegOut::VOUT))
}
pub fn set_nfc_pins_protection(&self, protected: bool) {
if protected {
self.registers.nfcpins.write(NfcPins::PROTECT::NFC);
} else {
self.registers.nfcpins.write(NfcPins::PROTECT::DISABLED);
}
}
pub fn is_nfc_pins_protection_enabled(&self) -> bool {
self.registers.nfcpins.matches_all(NfcPins::PROTECT::NFC)
}
pub fn is_ap_protect_enabled(&self) -> bool {
// We need to understand the variant of this nRF52 chip to correctly
// implement this function. Newer versions use a different value to
// indicate disabled.
let factory_config = ficr::Ficr::new();
let disabled_val = if factory_config.has_updated_approtect_logic() {
ApProtect::PALL::HWDISABLE
} else {
ApProtect::PALL::DISABLED
};
// Here we compare to the correct DISABLED value because any other value
// should enable the protection.
!self.registers.approtect.matches_all(disabled_val)
}
pub fn set_ap_protect(&self) {
self.registers.approtect.write(ApProtect::PALL::ENABLED);
}
/// Disable the access port protection in the UICR register. This is stored
/// in flash and is persistent. This behavior can also be accomplished
/// outside of tock by running `nrfjprog --recover`.
pub fn disable_ap_protect(&self) {
// We need to understand the variant of this nRF52 chip to correctly
// implement this function.
let factory_config = ficr::Ficr::new();
if factory_config.has_updated_approtect_logic() {
// Newer revisions of the chip require setting the APPROTECT
// register to `HwDisable`.
self.registers.approtect.write(ApProtect::PALL::HWDISABLE);
} else {
// All other revisions just use normal disable.
self.registers.approtect.write(ApProtect::PALL::DISABLED);
}
}
}