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