nrf52/approtect.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
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2023.
//! Access port protection
//!
//! <https://infocenter.nordicsemi.com/index.jsp?topic=%2Fps_nrf52840%2Fdif.html&cp=5_0_0_3_7_1&anchor=register.DISABLE>
//!
//! The logic around APPROTECT was changed in newer revisions of the nRF52
//! series chips (Oct 2021) and later which requires more careful disabling of
//! the access port (JTAG), both in the UICR register and in a software written
//! register. This module enables the kernel to disable the protection on boot.
//!
//! Example code to disable the APPROTECT protection in software:
//!
//! ```rust,ignore
//! let approtect = nrf52::approtect::Approtect::new();
//! approtect.sw_disable_approtect();
//! ```
use crate::ficr;
use kernel::utilities::registers::interfaces::Writeable;
use kernel::utilities::registers::{register_bitfields, register_structs, ReadWrite};
use kernel::utilities::StaticRef;
const APPROTECT_BASE: StaticRef<ApprotectRegisters> =
unsafe { StaticRef::new(0x40000000 as *const ApprotectRegisters) };
register_structs! {
ApprotectRegisters {
(0x000 => _reserved0),
(0x550 => forceprotect: ReadWrite<u32, Forceprotect::Register>),
(0x554 => _reserved1),
(0x558 => disable: ReadWrite<u32, Disable::Register>),
(0x55c => @END),
}
}
register_bitfields! [u32,
Forceprotect [
FORCEPROTECT OFFSET(0) NUMBITS(8) [
FORCE = 0
]
],
/// Access port protection
Disable [
DISABLE OFFSET(0) NUMBITS(8) [
SWDISABLE = 0x5a
]
]
];
pub struct Approtect {
registers: StaticRef<ApprotectRegisters>,
}
impl Approtect {
pub const fn new() -> Approtect {
Approtect {
registers: APPROTECT_BASE,
}
}
/// Software disable the Access Port Protection mechanism.
///
/// On newer variants of the nRF52, to enable JTAG, APPROTECT must be
/// disabled both in the UICR register (hardware) and in this register
/// (software). For older variants this is just a no-op.
///
/// - <https://devzone.nordicsemi.com/f/nordic-q-a/96590/how-to-disable-approtect-permanently-dfu-is-needed>
/// - <https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/working-with-the-nrf52-series-improved-approtect>
pub fn sw_disable_approtect(&self) {
let factory_config = ficr::Ficr::new();
match factory_config.variant() {
ficr::Variant::AAF0 | ficr::Variant::Unspecified => {
// Newer revisions of the chip require setting the APPROTECT
// software register to `SwDisable`. We assume that an unspecified
// version means that it is new and the FICR module hasn't been
// updated to recognize it.
self.registers.disable.write(Disable::DISABLE::SWDISABLE);
}
// Exhaustively list variants here to produce compiler error on
// adding a new variant, which would otherwise not match the above
// condition.
ficr::Variant::AAA0
| ficr::Variant::AAAA
| ficr::Variant::AAAB
| ficr::Variant::AAB0
| ficr::Variant::AABA
| ficr::Variant::AABB
| ficr::Variant::AAC0
| ficr::Variant::AACA
| ficr::Variant::AACB
| ficr::Variant::AAD0
| ficr::Variant::AAD1
| ficr::Variant::AADA
| ficr::Variant::AAE0
| ficr::Variant::AAEA
| ficr::Variant::ABBA
| ficr::Variant::BAAA
| ficr::Variant::CAAA => {
// All other revisions don't need this.
}
}
}
}