nrf52/
approtect.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2023.
4
5//! Access port protection
6//!
7//! <https://infocenter.nordicsemi.com/index.jsp?topic=%2Fps_nrf52840%2Fdif.html&cp=5_0_0_3_7_1&anchor=register.DISABLE>
8//!
9//! The logic around APPROTECT was changed in newer revisions of the nRF52
10//! series chips (Oct 2021) and later which requires more careful disabling of
11//! the access port (JTAG), both in the UICR register and in a software written
12//! register. This module enables the kernel to disable the protection on boot.
13//!
14//! Example code to disable the APPROTECT protection in software:
15//!
16//! ```rust,ignore
17//! let approtect = nrf52::approtect::Approtect::new();
18//! approtect.sw_disable_approtect();
19//! ```
20
21use crate::ficr;
22use kernel::utilities::registers::interfaces::Writeable;
23use kernel::utilities::registers::{register_bitfields, register_structs, ReadWrite};
24use kernel::utilities::StaticRef;
25
26const APPROTECT_BASE: StaticRef<ApprotectRegisters> =
27    unsafe { StaticRef::new(0x40000000 as *const ApprotectRegisters) };
28
29register_structs! {
30    ApprotectRegisters {
31        (0x000 => _reserved0),
32        (0x550 => forceprotect: ReadWrite<u32, Forceprotect::Register>),
33        (0x554 => _reserved1),
34        (0x558 => disable: ReadWrite<u32, Disable::Register>),
35        (0x55c => @END),
36    }
37}
38
39register_bitfields! [u32,
40    Forceprotect [
41        FORCEPROTECT OFFSET(0) NUMBITS(8) [
42            FORCE = 0
43        ]
44    ],
45    /// Access port protection
46    Disable [
47        DISABLE OFFSET(0) NUMBITS(8) [
48            SWDISABLE = 0x5a
49        ]
50    ]
51];
52
53pub struct Approtect {
54    registers: StaticRef<ApprotectRegisters>,
55}
56
57impl Approtect {
58    pub const fn new() -> Approtect {
59        Approtect {
60            registers: APPROTECT_BASE,
61        }
62    }
63
64    /// Software disable the Access Port Protection mechanism.
65    ///
66    /// On newer variants of the nRF52, to enable JTAG, APPROTECT must be
67    /// disabled both in the UICR register (hardware) and in this register
68    /// (software). For older variants this is just a no-op.
69    ///
70    /// - <https://devzone.nordicsemi.com/f/nordic-q-a/96590/how-to-disable-approtect-permanently-dfu-is-needed>
71    /// - <https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/working-with-the-nrf52-series-improved-approtect>
72    pub fn sw_disable_approtect(&self) {
73        let factory_config = ficr::Ficr::new();
74        match factory_config.variant() {
75            ficr::Variant::AAF0 | ficr::Variant::Unspecified => {
76                // Newer revisions of the chip require setting the APPROTECT
77                // software register to `SwDisable`. We assume that an unspecified
78                // version means that it is new and the FICR module hasn't been
79                // updated to recognize it.
80                self.registers.disable.write(Disable::DISABLE::SWDISABLE);
81            }
82
83            // Exhaustively list variants here to produce compiler error on
84            // adding a new variant, which would otherwise not match the above
85            // condition.
86            ficr::Variant::AAA0
87            | ficr::Variant::AAAA
88            | ficr::Variant::AAAB
89            | ficr::Variant::AAB0
90            | ficr::Variant::AABA
91            | ficr::Variant::AABB
92            | ficr::Variant::AAC0
93            | ficr::Variant::AACA
94            | ficr::Variant::AACB
95            | ficr::Variant::AAD0
96            | ficr::Variant::AAD1
97            | ficr::Variant::AADA
98            | ficr::Variant::AAE0
99            | ficr::Variant::AAEA
100            | ficr::Variant::ABBA
101            | ficr::Variant::BAAA
102            | ficr::Variant::CAAA => {
103                // All other revisions don't need this.
104            }
105        }
106    }
107}