1 /* 2 3 Copyright (c) 2009-2024 ARM Limited. All rights reserved. 4 5 SPDX-License-Identifier: Apache-2.0 6 7 Licensed under the Apache License, Version 2.0 (the License); you may 8 not use this file except in compliance with the License. 9 You may obtain a copy of the License at 10 11 www.apache.org/licenses/LICENSE-2.0 12 13 Unless required by applicable law or agreed to in writing, software 14 distributed under the License is distributed on an AS IS BASIS, WITHOUT 15 WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 See the License for the specific language governing permissions and 17 limitations under the License. 18 19 NOTICE: This file has been modified by Nordic Semiconductor ASA. 20 21 */ 22 23 /* NOTE: Template files (including this one) are application specific and therefore expected to 24 be copied into the application project folder prior to its use! */ 25 26 #include <stdint.h> 27 #include <stdbool.h> 28 #include "nrf.h" 29 #include "nrf_peripherals.h" 30 #include "nrf91_erratas.h" 31 #include "system_nrf91.h" 32 #include "system_nrf91_approtect.h" 33 34 /*lint ++flb "Enter library region" */ 35 36 void SystemStoreFICRNS(void); 37 void SystemLockFICRNS(void); 38 39 #define __SYSTEM_CLOCK_DEFAULT (64000000UL) /*!< nRF91 Application core uses a fixed System Clock Frequency of 64MHz */ 40 41 #define TRACE_PIN_CNF_VALUE ( (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos) | \ 42 (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | \ 43 (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) | \ 44 (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | \ 45 (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) ) 46 #define TRACE_TRACECLK_PIN (21ul) 47 #define TRACE_TRACEDATA0_PIN (22ul) 48 #define TRACE_TRACEDATA1_PIN (23ul) 49 #define TRACE_TRACEDATA2_PIN (24ul) 50 #define TRACE_TRACEDATA3_PIN (25ul) 51 52 #if defined ( __CC_ARM ) 53 uint32_t SystemCoreClock __attribute__((used)) = __SYSTEM_CLOCK_DEFAULT; 54 #elif defined ( __ICCARM__ ) 55 __root uint32_t SystemCoreClock = __SYSTEM_CLOCK_DEFAULT; 56 #elif defined ( __GNUC__ ) 57 uint32_t SystemCoreClock __attribute__((used)) = __SYSTEM_CLOCK_DEFAULT; 58 #endif 59 60 /* Errata are only handled in secure mode since they usually need access to FICR. */ 61 #if !defined(NRF_TRUSTZONE_NONSECURE) 62 #if !defined(NRF_SKIP_UICR_HFXO_WORKAROUND) 63 static bool uicr_HFXOSRC_erased(void); 64 static bool uicr_HFXOCNT_erased(void); 65 #endif 66 static bool is_empty_word(uint32_t const volatile * word); 67 #endif 68 SystemCoreClockUpdate(void)69void SystemCoreClockUpdate(void) 70 { 71 SystemCoreClock = __SYSTEM_CLOCK_DEFAULT; 72 } 73 SystemInit(void)74void SystemInit(void) 75 { 76 #if !defined(NRF_TRUSTZONE_NONSECURE) 77 /* Perform Secure-mode initialization routines. */ 78 79 /* Set all ARM SAU regions to NonSecure if TrustZone extensions are enabled. 80 * Nordic SPU should handle Secure Attribution tasks */ 81 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) 82 SAU->CTRL |= (1ul << SAU_CTRL_ALLNS_Pos); 83 #endif 84 85 /* Workaround for Errata 6 "POWER: SLEEPENTER and SLEEPEXIT events asserted after pin reset" found at the Errata document 86 for your device located at https://infocenter.nordicsemi.com/index.jsp */ 87 if (nrf91_errata_6()){ 88 NRF_POWER_S->EVENTS_SLEEPENTER = (POWER_EVENTS_SLEEPENTER_EVENTS_SLEEPENTER_NotGenerated << POWER_EVENTS_SLEEPENTER_EVENTS_SLEEPENTER_Pos); 89 NRF_POWER_S->EVENTS_SLEEPEXIT = (POWER_EVENTS_SLEEPEXIT_EVENTS_SLEEPEXIT_NotGenerated << POWER_EVENTS_SLEEPEXIT_EVENTS_SLEEPEXIT_Pos); 90 } 91 92 /* Workaround for Errata 14 "REGULATORS: LDO mode at startup" found at the Errata document 93 for your device located at https://infocenter.nordicsemi.com/index.jsp */ 94 if (nrf91_errata_14()){ 95 *((volatile uint32_t *)0x50004A38ul) = 0x01ul; 96 NRF_REGULATORS_S->DCDCEN = REGULATORS_DCDCEN_DCDCEN_Enabled << REGULATORS_DCDCEN_DCDCEN_Pos; 97 } 98 99 /* Workaround for Errata 15 "REGULATORS: LDO mode at startup" found at the Errata document 100 for your device located at https://infocenter.nordicsemi.com/index.jsp */ 101 if (nrf91_errata_15()){ 102 NRF_REGULATORS_S->DCDCEN = REGULATORS_DCDCEN_DCDCEN_Enabled << REGULATORS_DCDCEN_DCDCEN_Pos; 103 } 104 105 /* Workaround for Errata 20 "RAM content cannot be trusted upon waking up from System ON Idle or System OFF mode" found at the Errata document 106 for your device located at https://infocenter.nordicsemi.com/index.jsp */ 107 if (nrf91_errata_20()){ 108 *((volatile uint32_t *)0x5003AEE4ul) = 0xEul; 109 } 110 111 /* Workaround for Errata 31 "XOSC32k Startup Failure" found at the Errata document 112 for your device located at https://infocenter.nordicsemi.com/index.jsp */ 113 if (nrf91_errata_31()){ 114 *((volatile uint32_t *)0x5000470Cul) = 0x0ul; 115 *((volatile uint32_t *)0x50004710ul) = 0x1ul; 116 } 117 118 #if !defined(NRF_SKIP_FICR_NS_COPY_TO_RAM) 119 SystemStoreFICRNS(); 120 #endif 121 122 /* Trimming of the device. Copy all the trimming values from FICR into the target addresses. Trim 123 until one ADDR is not initialized. */ 124 125 for (uint32_t index = 0ul; index < 256ul && !is_empty_word(&NRF_FICR_S->TRIMCNF[index].ADDR); index++){ 126 #if defined ( __ICCARM__ ) 127 #pragma diag_suppress=Pa082 128 #endif 129 *(volatile uint32_t *)NRF_FICR_S->TRIMCNF[index].ADDR = NRF_FICR_S->TRIMCNF[index].DATA; 130 #if defined ( __ICCARM__ ) 131 #pragma diag_default=Pa082 132 #endif 133 } 134 135 #if !defined(NRF_SKIP_UICR_HFXO_WORKAROUND) 136 bool irq_disabled = __get_PRIMASK() == 1; 137 uint32_t uicr_erased_value; 138 uint32_t uicr_new_value; 139 /* Set UICR->HFXOSRC and UICR->HFXOCNT to working defaults if UICR was erased */ 140 if (uicr_HFXOSRC_erased() || uicr_HFXOCNT_erased()) { 141 __DSB(); 142 /* Wait for pending NVMC operations to finish */ 143 while (NRF_NVMC_S->READY != NVMC_READY_READY_Ready); 144 145 /* Enable write mode in NVMC */ 146 NRF_NVMC_S->CONFIG = NVMC_CONFIG_WEN_Wen; 147 while (NRF_NVMC_S->READY != NVMC_READY_READY_Ready); 148 149 if (!irq_disabled && nrf91_errata_7()){ 150 __disable_irq(); 151 } 152 153 if (uicr_HFXOSRC_erased()){ 154 /* Write default value to UICR->HFXOSRC */ 155 uicr_erased_value = NRF_UICR_S->HFXOSRC; 156 uicr_new_value = (uicr_erased_value & ~UICR_HFXOSRC_HFXOSRC_Msk) | UICR_HFXOSRC_HFXOSRC_TCXO; 157 NRF_UICR_S->HFXOSRC = uicr_new_value; 158 __DSB(); 159 while (NRF_NVMC_S->READY != NVMC_READY_READY_Ready); 160 } 161 162 if (uicr_HFXOCNT_erased()){ 163 /* Write default value to UICR->HFXOCNT */ 164 uicr_erased_value = NRF_UICR_S->HFXOCNT; 165 uicr_new_value = (uicr_erased_value & ~UICR_HFXOCNT_HFXOCNT_Msk) | 0x20; 166 NRF_UICR_S->HFXOCNT = uicr_new_value; 167 __DSB(); 168 while (NRF_NVMC_S->READY != NVMC_READY_READY_Ready); 169 } 170 171 if(!irq_disabled && nrf91_errata_7()){ 172 __enable_irq(); 173 } 174 175 /* Enable read mode in NVMC */ 176 NRF_NVMC_S->CONFIG = NVMC_CONFIG_WEN_Ren; 177 while (NRF_NVMC_S->READY != NVMC_READY_READY_Ready); 178 179 /* Reset to apply clock select update */ 180 NVIC_SystemReset(); 181 } 182 #endif 183 184 /* Enable Trace functionality. If ENABLE_TRACE is not defined, TRACE pins will be used as GPIOs (see Product 185 Specification to see which ones). */ 186 #if defined (ENABLE_TRACE) 187 // Enable Trace And Debug peripheral 188 NRF_TAD_S->ENABLE = TAD_ENABLE_ENABLE_Msk; 189 NRF_TAD_S->TASKS_CLOCKSTART = TAD_TASKS_CLOCKSTART_TASKS_CLOCKSTART_Msk; 190 191 // Set up Trace pads SPU firewall 192 NRF_SPU_S->GPIOPORT[0].PERM &= ~(1ul << TRACE_TRACECLK_PIN); 193 NRF_SPU_S->GPIOPORT[0].PERM &= ~(1ul << TRACE_TRACEDATA0_PIN); 194 NRF_SPU_S->GPIOPORT[0].PERM &= ~(1ul << TRACE_TRACEDATA1_PIN); 195 NRF_SPU_S->GPIOPORT[0].PERM &= ~(1ul << TRACE_TRACEDATA2_PIN); 196 NRF_SPU_S->GPIOPORT[0].PERM &= ~(1ul << TRACE_TRACEDATA3_PIN); 197 198 // Configure trace port pads 199 NRF_P0_S->PIN_CNF[TRACE_TRACECLK_PIN] = TRACE_PIN_CNF_VALUE; 200 NRF_P0_S->PIN_CNF[TRACE_TRACEDATA0_PIN] = TRACE_PIN_CNF_VALUE; 201 NRF_P0_S->PIN_CNF[TRACE_TRACEDATA1_PIN] = TRACE_PIN_CNF_VALUE; 202 NRF_P0_S->PIN_CNF[TRACE_TRACEDATA2_PIN] = TRACE_PIN_CNF_VALUE; 203 NRF_P0_S->PIN_CNF[TRACE_TRACEDATA3_PIN] = TRACE_PIN_CNF_VALUE; 204 205 // Select trace pins 206 NRF_TAD_S->PSEL.TRACECLK = TRACE_TRACECLK_PIN; 207 NRF_TAD_S->PSEL.TRACEDATA0 = TRACE_TRACEDATA0_PIN; 208 NRF_TAD_S->PSEL.TRACEDATA1 = TRACE_TRACEDATA1_PIN; 209 NRF_TAD_S->PSEL.TRACEDATA2 = TRACE_TRACEDATA2_PIN; 210 NRF_TAD_S->PSEL.TRACEDATA3 = TRACE_TRACEDATA3_PIN; 211 212 // Set trace port speed to 32 MHz 213 NRF_TAD_S->TRACEPORTSPEED = TAD_TRACEPORTSPEED_TRACEPORTSPEED_32MHz; 214 215 *((volatile uint32_t *)(0xE0053000ul)) = 0x00000001ul; 216 217 *((volatile uint32_t *)(0xE005AFB0ul)) = 0xC5ACCE55ul; 218 *((volatile uint32_t *)(0xE005A000ul)) &= 0xFFFFFF00ul; 219 *((volatile uint32_t *)(0xE005A004ul)) = 0x00000009ul; 220 *((volatile uint32_t *)(0xE005A000ul)) = 0x00000303ul; 221 *((volatile uint32_t *)(0xE005AFB0ul)) = 0x00000000ul; 222 223 *((volatile uint32_t *)(0xE005BFB0ul)) = 0xC5ACCE55ul; 224 *((volatile uint32_t *)(0xE005B000ul)) &= 0xFFFFFF00ul; 225 *((volatile uint32_t *)(0xE005B004ul)) = 0x00003000ul; 226 *((volatile uint32_t *)(0xE005B000ul)) = 0x00000308ul; 227 *((volatile uint32_t *)(0xE005BFB0ul)) = 0x00000000ul; 228 229 *((volatile uint32_t *)(0xE0058FB0ul)) = 0xC5ACCE55ul; 230 *((volatile uint32_t *)(0xE0058000ul)) = 0x00000000ul; 231 *((volatile uint32_t *)(0xE0058004ul)) = 0x00000000ul; 232 *((volatile uint32_t *)(0xE0058FB0ul)) = 0x00000000ul; 233 234 /* Rom table does not list ETB, or TPIU base addresses. 235 * Some debug probes may require manual configuration of these peripherals to enable tracing. 236 * ETB_BASE = 0xE0051000 237 * TPIU_BASE = 0xE0054000 238 */ 239 #endif 240 241 /* Allow Non-Secure code to run FPU instructions. 242 * If only the secure code should control FPU power state these registers should be configured accordingly in the secure application code. */ 243 SCB->NSACR |= (3UL << 10ul); 244 245 nrf91_handle_approtect(); 246 #endif 247 248 /* Enable the FPU if the compiler used floating point unit instructions. __FPU_USED is a MACRO defined by the 249 * compiler. Since the FPU consumes energy, remember to disable FPU use in the compiler if floating point unit 250 * operations are not used in your code. */ 251 #if (__FPU_USED == 1) 252 SCB->CPACR |= (3UL << 20ul) | (3UL << 22ul); 253 __DSB(); 254 __ISB(); 255 #endif 256 } 257 258 259 #if !defined(NRF_TRUSTZONE_NONSECURE) 260 261 #if !defined(NRF_SKIP_UICR_HFXO_WORKAROUND) uicr_HFXOCNT_erased()262 bool uicr_HFXOCNT_erased() 263 { 264 bool irq_disabled = __get_PRIMASK() == 1; 265 if (!irq_disabled && nrf91_errata_7()){ 266 __disable_irq(); 267 } 268 bool is_empty = is_empty_word(&NRF_UICR_S->HFXOCNT); 269 if (!irq_disabled && nrf91_errata_7()){ 270 __enable_irq(); 271 } 272 return is_empty; 273 } 274 275 uicr_HFXOSRC_erased()276 bool uicr_HFXOSRC_erased() 277 { 278 bool irq_disabled = __get_PRIMASK() == 1; 279 if (!irq_disabled && nrf91_errata_7()){ 280 __disable_irq(); 281 } 282 uint32_t HFXOSRC_readout = NRF_UICR_S->HFXOSRC; 283 __DSB(); 284 bool erased = (HFXOSRC_readout & UICR_HFXOSRC_HFXOSRC_Msk) != UICR_HFXOSRC_HFXOSRC_TCXO; 285 if (!irq_disabled && nrf91_errata_7()){ 286 __enable_irq(); 287 } 288 return erased; 289 } 290 #endif 291 is_empty_word(uint32_t const volatile * word)292 bool is_empty_word(uint32_t const volatile * word) 293 { 294 uint32_t val = *word; 295 __DSB(); 296 return val == 0xFFFFFFFFul; 297 } 298 #endif 299 300 301 /* Workaround to allow NS code to access FICR. Override NRF_FICR_NS to move FICR_NS buffer. */ 302 #define FICR_SIZE 0x1000ul 303 #define RAM_BASE 0x20000000ul 304 #define RAM_END 0x2FFFFFFFul 305 306 /* Copy FICR_S to FICR_NS RAM region */ SystemStoreFICRNS()307void SystemStoreFICRNS() 308 { 309 if ((uint32_t)NRF_FICR_NS < RAM_BASE || (uint32_t)NRF_FICR_NS + FICR_SIZE > RAM_END) 310 { 311 /* FICR_NS is not in RAM. */ 312 return; 313 } 314 /* Copy FICR to NS-accessible RAM block. */ 315 volatile uint32_t * from = (volatile uint32_t *)((uint32_t)NRF_FICR_S + (FICR_SIZE - sizeof(uint32_t))); 316 volatile uint32_t * to = (volatile uint32_t *)((uint32_t)NRF_FICR_NS + (FICR_SIZE - sizeof(uint32_t))); 317 volatile uint32_t * copy_from_end = (volatile uint32_t *)NRF_FICR_S; 318 while (from >= copy_from_end) 319 { 320 *(to--) = *(from--); 321 } 322 323 /* Make RAM region NS. */ 324 uint32_t ram_region = ((uint32_t)NRF_FICR_NS - (uint32_t)RAM_BASE) / SPU_RAMREGION_SIZE; 325 __DSB(); 326 NRF_SPU_S->RAMREGION[ram_region].PERM &= ~(1ul << SPU_RAMREGION_PERM_SECATTR_Pos); 327 } 328 329 /* Block write and execute access to FICR RAM region */ SystemLockFICRNS()330void SystemLockFICRNS() 331 { 332 if ((uint32_t)NRF_FICR_NS < RAM_BASE || (uint32_t)NRF_FICR_NS + FICR_SIZE > RAM_END) 333 { 334 /* FICR_NS is not in RAM. */ 335 return; 336 } 337 338 uint32_t ram_region = ((uint32_t)NRF_FICR_NS - (uint32_t)RAM_BASE) / SPU_RAMREGION_SIZE; 339 __DSB(); 340 NRF_SPU_S->RAMREGION[ram_region].PERM &= 341 ~( 342 (1ul << SPU_RAMREGION_PERM_WRITE_Pos) | 343 (1ul << SPU_RAMREGION_PERM_EXECUTE_Pos) 344 ); 345 NRF_SPU_S->RAMREGION[ram_region].PERM |= 1ul << SPU_RAMREGION_PERM_LOCK_Pos; 346 } 347 348 /*lint --flb "Leave library region" */ 349