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 "nrf52_erratas.h"
31 #include "system_nrf52.h"
32 #include "system_nrf52_approtect.h"
33
34 #define __SYSTEM_CLOCK_DEFAULT (64000000UL)
35
36
37 #if defined ( __CC_ARM ) || defined ( __GNUC__ )
38 uint32_t SystemCoreClock __attribute__((used)) = __SYSTEM_CLOCK_DEFAULT;
39 #elif defined ( __ICCARM__ )
40 __root uint32_t SystemCoreClock = __SYSTEM_CLOCK_DEFAULT;
41 #endif
42
43 /* Simplify later device detection macros. Check DEVELOP_IN first, as they take precedence. */
44 #if defined (DEVELOP_IN_NRF52805)
45 #define IS_NRF52805 1ul
46 #elif defined (DEVELOP_IN_NRF52810)
47 #define IS_NRF52810 1ul
48 #elif defined (DEVELOP_IN_NRF52811)
49 #define IS_NRF52811 1ul
50 #elif defined (DEVELOP_IN_NRF52820)
51 #define IS_NRF52820 1ul
52 #elif defined (DEVELOP_IN_NRF52832)
53 #define IS_NRF52832 1
54 #elif defined (DEVELOP_IN_NRF52833)
55 #define IS_NRF52833 1
56 #elif defined (DEVELOP_IN_NRF52840)
57 #define IS_NRF52840 1ul
58 #elif defined (NRF52805_XXAA)
59 #define IS_NRF52805 1ul
60 #elif defined (NRF52810_XXAA)
61 #define IS_NRF52810 1ul
62 #elif defined (NRF52811_XXAA)
63 #define IS_NRF52811 1ul
64 #elif defined (NRF52820_XXAA)
65 #define IS_NRF52820 1ul
66 #elif defined (NRF52832_XXAA) || defined (NRF52832_XXAB)
67 #define IS_NRF52832 1ul
68 #elif defined (NRF52833_XXAA)
69 #define IS_NRF52833 1ul
70 #elif defined (NRF52840_XXAA)
71 #define IS_NRF52840 1ul
72 #else
73 #error "A supported device macro must be defined."
74 #endif
75
76 /* Trace configuration */
77 #define TRACE_PIN_CONFIG ((GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) \
78 | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) \
79 | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos))
80
81 #if defined (IS_NRF52832) && IS_NRF52832
82 #define TRACECLK_PIN_CNF NRF_P0->PIN_CNF[20]
83 #define TRACEDATA0_PIN_CNF NRF_P0->PIN_CNF[18]
84 #define TRACEDATA1_PIN_CNF NRF_P0->PIN_CNF[16]
85 #define TRACEDATA2_PIN_CNF NRF_P0->PIN_CNF[15]
86 #define TRACEDATA3_PIN_CNF NRF_P0->PIN_CNF[14]
87 #elif (defined (IS_NRF52833) && IS_NRF52833) || (defined (IS_NRF52840) && IS_NRF52840)
88 #define TRACECLK_PIN_CNF NRF_P0->PIN_CNF[7]
89 #define TRACEDATA0_PIN_CNF NRF_P1->PIN_CNF[0]
90 #define TRACEDATA1_PIN_CNF NRF_P0->PIN_CNF[12]
91 #define TRACEDATA2_PIN_CNF NRF_P0->PIN_CNF[11]
92 #define TRACEDATA3_PIN_CNF NRF_P1->PIN_CNF[9]
93 #else
94 /* No trace supported */
95 #endif
96
97 /* Select correct reset pin */
98 /* Handle DEVELOP_IN-targets first as they take precedence over the later macros */
99 #if (defined(IS_NRF52805) && IS_NRF52805) || \
100 (defined(IS_NRF52810) && IS_NRF52810) || \
101 (defined(IS_NRF52811) && IS_NRF52811) || \
102 (defined(IS_NRF52832) && IS_NRF52832)
103 #define RESET_PIN 21ul
104 #elif (defined(IS_NRF52820) && IS_NRF52820) || \
105 (defined(IS_NRF52833) && IS_NRF52833) || \
106 (defined(IS_NRF52840) && IS_NRF52840)
107 #define RESET_PIN 18ul
108 #else
109 #error "A supported device macro must be defined."
110 #endif
111
112 /* -- NVMC utility functions -- */
113 /* Waits until NVMC is done with the current pending action */
nvmc_wait(void)114 void nvmc_wait(void)
115 {
116 while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
117 }
118
119 /* Configure the NVMC to "mode".
120 Mode must be an enumerator of field NVMC_CONFIG_WEN */
nvmc_config(uint32_t mode)121 void nvmc_config(uint32_t mode)
122 {
123 NRF_NVMC->CONFIG = mode << NVMC_CONFIG_WEN_Pos;
124 nvmc_wait();
125 }
126
SystemCoreClockUpdate(void)127 void SystemCoreClockUpdate(void)
128 {
129 SystemCoreClock = __SYSTEM_CLOCK_DEFAULT;
130 }
131
SystemInit(void)132 void SystemInit(void)
133 {
134 /* Enable SWO trace functionality. If ENABLE_SWO is not defined, SWO pin will be used as GPIO (see Product
135 Specification to see which one). */
136 #if defined (ENABLE_SWO) && defined(CLOCK_TRACECONFIG_TRACEMUX_Pos)
137 CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
138 NRF_CLOCK->TRACECONFIG |= CLOCK_TRACECONFIG_TRACEMUX_Serial << CLOCK_TRACECONFIG_TRACEMUX_Pos;
139 TRACEDATA0_PIN_CNF = TRACE_PIN_CONFIG;
140 #endif
141
142 /* Enable Trace functionality. If ENABLE_TRACE is not defined, TRACE pins will be used as GPIOs (see Product
143 Specification to see which ones). */
144 #if defined (ENABLE_TRACE) && defined(CLOCK_TRACECONFIG_TRACEMUX_Pos)
145 CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
146 NRF_CLOCK->TRACECONFIG |= CLOCK_TRACECONFIG_TRACEMUX_Parallel << CLOCK_TRACECONFIG_TRACEMUX_Pos;
147 TRACECLK_PIN_CNF = TRACE_PIN_CONFIG;
148 TRACEDATA0_PIN_CNF = TRACE_PIN_CONFIG;
149 TRACEDATA1_PIN_CNF = TRACE_PIN_CONFIG;
150 TRACEDATA2_PIN_CNF = TRACE_PIN_CONFIG;
151 TRACEDATA3_PIN_CNF = TRACE_PIN_CONFIG;
152 #endif
153
154 #if NRF52_ERRATA_12_ENABLE_WORKAROUND
155 /* Workaround for Errata 12 "COMP: Reference ladder not correctly calibrated" found at the Errata document
156 for your device located at https://infocenter.nordicsemi.com/index.jsp */
157 if (nrf52_errata_12()){
158 *(volatile uint32_t *)0x40013540 = (*(uint32_t *)0x10000324 & 0x00001F00) >> 8;
159 }
160 #endif
161
162 #if NRF52_ERRATA_16_ENABLE_WORKAROUND
163 /* Workaround for Errata 16 "System: RAM may be corrupt on wakeup from CPU IDLE" found at the Errata document
164 for your device located at https://infocenter.nordicsemi.com/index.jsp */
165 if (nrf52_errata_16()){
166 *(volatile uint32_t *)0x4007C074 = 3131961357ul;
167 }
168 #endif
169
170 #if NRF52_ERRATA_31_ENABLE_WORKAROUND
171 /* Workaround for Errata 31 "CLOCK: Calibration values are not correctly loaded from FICR at reset" found at the Errata document
172 for your device located at https://infocenter.nordicsemi.com/index.jsp */
173 if (nrf52_errata_31()){
174 *(volatile uint32_t *)0x4000053C = ((*(volatile uint32_t *)0x10000244) & 0x0000E000) >> 13;
175 }
176 #endif
177
178 #if NRF52_ERRATA_32_ENABLE_WORKAROUND
179 /* Workaround for Errata 32 "DIF: Debug session automatically enables TracePort pins" found at the Errata document
180 for your device located at https://infocenter.nordicsemi.com/index.jsp */
181 if (nrf52_errata_32()){
182 CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk;
183 }
184 #endif
185
186 #if NRF52_ERRATA_36_ENABLE_WORKAROUND
187 /* Workaround for Errata 36 "CLOCK: Some registers are not reset when expected" found at the Errata document
188 for your device located at https://infocenter.nordicsemi.com/index.jsp */
189 if (nrf52_errata_36()){
190 NRF_CLOCK->EVENTS_DONE = 0ul;
191 NRF_CLOCK->EVENTS_CTTO = 0ul;
192 NRF_CLOCK->CTIV = 0ul;
193 }
194 #endif
195
196 #if NRF52_ERRATA_37_ENABLE_WORKAROUND
197 /* Workaround for Errata 37 "RADIO: Encryption engine is slow by default" found at the Errata document
198 for your device located at https://infocenter.nordicsemi.com/index.jsp */
199 if (nrf52_errata_37()){
200 *(volatile uint32_t *)0x400005A0 = 0x3;
201 }
202 #endif
203
204 #if NRF52_ERRATA_57_ENABLE_WORKAROUND
205 /* Workaround for Errata 57 "NFCT: NFC Modulation amplitude" found at the Errata document
206 for your device located at https://infocenter.nordicsemi.com/index.jsp */
207 if (nrf52_errata_57()){
208 *(volatile uint32_t *)0x40005610 = 0x00000005;
209 *(volatile uint32_t *)0x40005688 = 0x00000001;
210 *(volatile uint32_t *)0x40005618 = 0x00000000;
211 *(volatile uint32_t *)0x40005614 = 0x0000003F;
212 }
213 #endif
214
215 #if NRF52_ERRATA_66_ENABLE_WORKAROUND
216 /* Workaround for Errata 66 "TEMP: Linearity specification not met with default settings" found at the Errata document
217 for your device located at https://infocenter.nordicsemi.com/index.jsp */
218 if (nrf52_errata_66()){
219 NRF_TEMP->A0 = NRF_FICR->TEMP.A0;
220 NRF_TEMP->A1 = NRF_FICR->TEMP.A1;
221 NRF_TEMP->A2 = NRF_FICR->TEMP.A2;
222 NRF_TEMP->A3 = NRF_FICR->TEMP.A3;
223 NRF_TEMP->A4 = NRF_FICR->TEMP.A4;
224 NRF_TEMP->A5 = NRF_FICR->TEMP.A5;
225 NRF_TEMP->B0 = NRF_FICR->TEMP.B0;
226 NRF_TEMP->B1 = NRF_FICR->TEMP.B1;
227 NRF_TEMP->B2 = NRF_FICR->TEMP.B2;
228 NRF_TEMP->B3 = NRF_FICR->TEMP.B3;
229 NRF_TEMP->B4 = NRF_FICR->TEMP.B4;
230 NRF_TEMP->B5 = NRF_FICR->TEMP.B5;
231 NRF_TEMP->T0 = NRF_FICR->TEMP.T0;
232 NRF_TEMP->T1 = NRF_FICR->TEMP.T1;
233 NRF_TEMP->T2 = NRF_FICR->TEMP.T2;
234 NRF_TEMP->T3 = NRF_FICR->TEMP.T3;
235 NRF_TEMP->T4 = NRF_FICR->TEMP.T4;
236 }
237 #endif
238
239 #if NRF52_ERRATA_98_ENABLE_WORKAROUND
240 /* Workaround for Errata 98 "NFCT: Not able to communicate with the peer" found at the Errata document
241 for your device located at https://infocenter.nordicsemi.com/index.jsp */
242 if (nrf52_errata_98()){
243 *(volatile uint32_t *)0x4000568Cul = 0x00038148ul;
244 }
245 #endif
246
247 #if NRF52_ERRATA_103_ENABLE_WORKAROUND && defined(CCM_MAXPACKETSIZE_MAXPACKETSIZE_Pos)
248 /* Workaround for Errata 103 "CCM: Wrong reset value of CCM MAXPACKETSIZE" found at the Errata document
249 for your device located at https://infocenter.nordicsemi.com/index.jsp */
250 if (nrf52_errata_103()){
251 NRF_CCM->MAXPACKETSIZE = 0xFBul;
252 }
253 #endif
254
255 #if NRF52_ERRATA_108_ENABLE_WORKAROUND
256 /* Workaround for Errata 108 "RAM: RAM content cannot be trusted upon waking up from System ON Idle or System OFF mode" found at the Errata document
257 for your device located at https://infocenter.nordicsemi.com/index.jsp */
258 if (nrf52_errata_108()){
259 *(volatile uint32_t *)0x40000EE4ul = *(volatile uint32_t *)0x10000258ul & 0x0000004Ful;
260 }
261 #endif
262
263 #if NRF52_ERRATA_115_ENABLE_WORKAROUND
264 /* Workaround for Errata 115 "RAM: RAM content cannot be trusted upon waking up from System ON Idle or System OFF mode" found at the Errata document
265 for your device located at https://infocenter.nordicsemi.com/index.jsp */
266 if (nrf52_errata_115()){
267 *(volatile uint32_t *)0x40000EE4ul = (*(volatile uint32_t *)0x40000EE4ul & 0xFFFFFFF0ul) | (*(uint32_t *)0x10000258ul & 0x0000000Ful);
268 }
269 #endif
270
271 #if NRF52_ERRATA_120_ENABLE_WORKAROUND
272 /* Workaround for Errata 120 "QSPI: Data read or written is corrupted" found at the Errata document
273 for your device located at https://infocenter.nordicsemi.com/index.jsp */
274 if (nrf52_errata_120()){
275 *(volatile uint32_t *)0x40029640ul = 0x200ul;
276 }
277 #endif
278
279 #if NRF52_ERRATA_136_ENABLE_WORKAROUND
280 /* Workaround for Errata 136 "System: Bits in RESETREAS are set when they should not be" found at the Errata document
281 for your device located at https://infocenter.nordicsemi.com/index.jsp */
282 if (nrf52_errata_136()){
283 if (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk){
284 NRF_POWER->RESETREAS = ~POWER_RESETREAS_RESETPIN_Msk;
285 }
286 }
287 #endif
288
289 #if NRF52_ERRATA_182_ENABLE_WORKAROUND
290 /* Workaround for Errata 182 "RADIO: Fixes for anomalies #102, #106, and #107 do not take effect" found at the Errata document
291 for your device located at https://infocenter.nordicsemi.com/index.jsp */
292 if (nrf52_errata_182()){
293 *(volatile uint32_t *) 0x4000173Cul |= (0x1ul << 10ul);
294 }
295 #endif
296
297 #if NRF52_ERRATA_217_ENABLE_WORKAROUND
298 /* Workaround for Errata 217 "RAM: RAM content cannot be trusted upon waking up from System ON Idle or System OFF mode" found at the Errata document
299 for your device located at https://infocenter.nordicsemi.com/index.jsp */
300 if (nrf52_errata_217()){
301 *(volatile uint32_t *)0x40000EE4ul |= 0x0000000Ful;
302 }
303 #endif
304
305 /* Enable the FPU if the compiler used floating point unit instructions. __FPU_USED is a MACRO defined by the
306 * compiler. Since the FPU consumes energy, remember to disable FPU use in the compiler if floating point unit
307 * operations are not used in your code. */
308 #if (__FPU_USED == 1)
309 SCB->CPACR |= (3UL << 20ul) | (3UL << 22ul);
310 __DSB();
311 __ISB();
312 #endif
313
314 nrf52_handle_approtect();
315
316 #if NRF52_CONFIGURATION_249_ENABLE && (defined(NRF52805_XXAA) || defined(NRF52810_XXAA) || defined(NRF52811_XXAA))
317 if (nrf52_configuration_249() && (NRF_UICR->NRFMDK[0] == 0xFFFFFFFFul || NRF_UICR->NRFMDK[1] == 0xFFFFFFFFul))
318 {
319 nvmc_config(NVMC_CONFIG_WEN_Wen);
320 NRF_UICR->NRFMDK[0] = 0ul;
321 nvmc_wait();
322 NRF_UICR->NRFMDK[1] = 0ul;
323 nvmc_wait();
324 nvmc_config(NVMC_CONFIG_WEN_Ren);
325 }
326 #endif
327
328 /* Configure NFCT pins as GPIOs if NFCT is not to be used in your code. If CONFIG_NFCT_PINS_AS_GPIOS is not defined,
329 two GPIOs (see Product Specification to see which ones) will be reserved for NFC and will not be available as
330 normal GPIOs. */
331 #if defined (CONFIG_NFCT_PINS_AS_GPIOS) && defined(NFCT_PRESENT)
332 if ((NRF_UICR->NFCPINS & UICR_NFCPINS_PROTECT_Msk) == (UICR_NFCPINS_PROTECT_NFC << UICR_NFCPINS_PROTECT_Pos)){
333 nvmc_config(NVMC_CONFIG_WEN_Wen);
334 NRF_UICR->NFCPINS &= ~UICR_NFCPINS_PROTECT_Msk;
335 nvmc_wait();
336 nvmc_config(NVMC_CONFIG_WEN_Ren);
337 NVIC_SystemReset();
338 }
339 #endif
340
341 /* Configure GPIO pads as pPin Reset pin if Pin Reset capabilities desired. If CONFIG_GPIO_AS_PINRESET is not
342 defined, pin reset will not be available. One GPIO (see Product Specification to see which one) will then be
343 reserved for PinReset and not available as normal GPIO. */
344 #if defined (CONFIG_GPIO_AS_PINRESET)
345 if (((NRF_UICR->PSELRESET[0] & UICR_PSELRESET_CONNECT_Msk) != (UICR_PSELRESET_CONNECT_Connected << UICR_PSELRESET_CONNECT_Pos)) ||
346 ((NRF_UICR->PSELRESET[1] & UICR_PSELRESET_CONNECT_Msk) != (UICR_PSELRESET_CONNECT_Connected << UICR_PSELRESET_CONNECT_Pos))){
347 nvmc_config(NVMC_CONFIG_WEN_Wen);
348 NRF_UICR->PSELRESET[0] = RESET_PIN;
349 nvmc_wait();
350 NRF_UICR->PSELRESET[1] = RESET_PIN;
351 nvmc_wait();
352 nvmc_config(NVMC_CONFIG_WEN_Ren);
353 NVIC_SystemReset();
354 }
355 #endif
356
357 /* When developing for nRF52810 on an nRF52832, or nRF52811 on an nRF52840,
358 make sure NFC pins are mapped as GPIO. */
359 #if defined (DEVELOP_IN_NRF52832) && defined(NRF52810_XXAA) \
360 || defined (DEVELOP_IN_NRF52840) && defined(NRF52811_XXAA)
361 if ((*((uint32_t *)0x1000120Cul) & (1ul << 0ul)) != 0ul){
362 nvmc_config(NVMC_CONFIG_WEN_Wen);
363 *((uint32_t *)0x1000120Cul) = 0ul;
364 nvmc_wait();
365 nvmc_config(NVMC_CONFIG_WEN_Ren);
366 NVIC_SystemReset();
367 }
368 #endif
369 }
370