ESPHome 2026.6.0-dev
Loading...
Searching...
No Matches
uicr.cpp
Go to the documentation of this file.
2
3#ifdef USE_NRF52_REG0_VOUT
4#include <zephyr/init.h>
5#include <hal/nrf_power.h>
6#include <zephyr/sys/printk.h>
7
8extern "C" {
10void nvmc_wait();
12}
13
14// NOLINTBEGIN(clang-analyzer-core.FixedAddressDereference) -- NRF_UICR / NRF_TIMER2 are MMIO at fixed addresses
15namespace esphome::nrf52 {
16
17enum class StatusFlags : uint8_t {
18 OK = 0x00,
19 NEED_RESET = 0x01,
20 NEED_ERASE = 0x02,
21};
22
24 a = static_cast<StatusFlags>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
25 return a;
26}
27
28constexpr bool operator&(StatusFlags a, StatusFlags b) {
29 return (static_cast<uint8_t>(a) & static_cast<uint8_t>(b)) != 0;
30}
31
32static bool regout0_ok() {
33 return (NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) == (USE_NRF52_REG0_VOUT << UICR_REGOUT0_VOUT_Pos);
34}
35
36static StatusFlags set_regout0() {
37 /* If the board is powered from USB (high voltage mode),
38 * GPIO output voltage is set to 1.8 volts by default.
39 */
40 if (!regout0_ok()) {
41 nvmc_config(NVMC_CONFIG_WEN_Wen);
42 NRF_UICR->REGOUT0 =
43 (NRF_UICR->REGOUT0 & ~((uint32_t) UICR_REGOUT0_VOUT_Msk)) | (USE_NRF52_REG0_VOUT << UICR_REGOUT0_VOUT_Pos);
44 nvmc_wait();
45 nvmc_config(NVMC_CONFIG_WEN_Ren);
47 }
48 return StatusFlags::OK;
49}
50
51#ifndef USE_BOOTLOADER_MCUBOOT
52// https://github.com/adafruit/Adafruit_nRF52_Bootloader/blob/6a9a6a3e6d0f86918e9286188426a279976645bd/lib/sdk11/components/libraries/bootloader_dfu/dfu_types.h#L61
53constexpr uint32_t BOOTLOADER_REGION_START = 0x000F4000;
55
56static bool bootloader_ok() {
57 return NRF_UICR->NRFFW[0] == BOOTLOADER_REGION_START && NRF_UICR->NRFFW[1] == BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS;
58}
59
60static StatusFlags fix_bootloader() {
61 if (!bootloader_ok()) {
62 nvmc_config(NVMC_CONFIG_WEN_Wen);
63 NRF_UICR->NRFFW[0] = BOOTLOADER_REGION_START;
64 NRF_UICR->NRFFW[1] = BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS;
65 nvmc_wait();
66 nvmc_config(NVMC_CONFIG_WEN_Ren);
67 return bootloader_ok() ? StatusFlags::NEED_RESET : StatusFlags::NEED_ERASE;
68 }
69 return StatusFlags::OK;
70}
71#endif
72
73#define BOOTLOADER_VERSION_REGISTER NRF_TIMER2->CC[0]
74
75static StatusFlags set_uicr() {
77#ifndef USE_BOOTLOADER_MCUBOOT
78 if (BOOTLOADER_VERSION_REGISTER <= 0x902) {
79#ifdef CONFIG_PRINTK
80 printk("cannot control regout0 for %#x\n", BOOTLOADER_VERSION_REGISTER);
81#endif
82 } else
83#endif
84 {
85 status |= set_regout0();
86 }
87#ifndef USE_BOOTLOADER_MCUBOOT
88 status |= fix_bootloader();
89#endif
90 return status;
91}
92
93static int board_esphome_init() {
94 StatusFlags status = set_uicr();
95
96#ifdef USE_NRF52_UICR_ERASE
97 if (status & StatusFlags::NEED_ERASE) {
98 nrfx_err_t ret = nrfx_nvmc_uicr_erase();
99 if (ret != NRFX_SUCCESS) {
100#ifdef CONFIG_PRINTK
101 printk("nrfx_nvmc_uicr_erase failed %d\n", ret);
102#endif
103 } else {
104 status |= set_uicr();
105 }
106 }
107#endif
108
109 if (status & StatusFlags::NEED_RESET) {
110 /* a reset is required for changes to take effect */
111 NVIC_SystemReset();
112 }
113
114 return 0;
115}
116} // namespace esphome::nrf52
117// NOLINTEND(clang-analyzer-core.FixedAddressDereference)
118
119static int board_esphome_init() { return esphome::nrf52::board_esphome_init(); }
120
121SYS_INIT(board_esphome_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
122
123#endif
BedjetMode mode
BedJet operating mode.
uint8_t status
Definition bl0942.h:8
constexpr StatusFlags & operator|=(StatusFlags &a, StatusFlags b)
Definition uicr.cpp:23
constexpr bool operator&(StatusFlags a, StatusFlags b)
Definition uicr.cpp:28
constexpr uint32_t BOOTLOADER_MBR_PARAMS_PAGE_ADDRESS
Definition uicr.cpp:54
constexpr uint32_t BOOTLOADER_REGION_START
Definition uicr.cpp:53
static void uint32_t
void nvmc_config(uint32_t mode)
void nvmc_wait()
nrfx_err_t nrfx_nvmc_uicr_erase()
SYS_INIT(board_esphome_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT)