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