1 /*
2 
3 Copyright (c) 2009-2020 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_erratas.h"
30 #include "system_nrf52.h"
31 
32 /*lint ++flb "Enter library region" */
33 
34 #define __SYSTEM_CLOCK_64M      (64000000UL)
35 
36 
37 #if defined ( __CC_ARM )
38     uint32_t SystemCoreClock __attribute__((used)) = __SYSTEM_CLOCK_64M;
39 #elif defined ( __ICCARM__ )
40     __root uint32_t SystemCoreClock = __SYSTEM_CLOCK_64M;
41 #elif defined ( __GNUC__ )
42     uint32_t SystemCoreClock __attribute__((used)) = __SYSTEM_CLOCK_64M;
43 #endif
44 
SystemCoreClockUpdate(void)45 void SystemCoreClockUpdate(void)
46 {
47     SystemCoreClock = __SYSTEM_CLOCK_64M;
48 }
49 
SystemInit(void)50 void SystemInit(void)
51 {
52     /* Enable SWO trace functionality. If ENABLE_SWO is not defined, SWO pin will be used as GPIO (see Product
53        Specification to see which one). */
54     #if defined (ENABLE_SWO)
55         CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
56         NRF_CLOCK->TRACECONFIG |= CLOCK_TRACECONFIG_TRACEMUX_Serial << CLOCK_TRACECONFIG_TRACEMUX_Pos;
57         NRF_P0->PIN_CNF[18] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
58     #endif
59 
60     /* Enable Trace functionality. If ENABLE_TRACE is not defined, TRACE pins will be used as GPIOs (see Product
61        Specification to see which ones). */
62     #if defined (ENABLE_TRACE)
63         CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
64         NRF_CLOCK->TRACECONFIG |= CLOCK_TRACECONFIG_TRACEMUX_Parallel << CLOCK_TRACECONFIG_TRACEMUX_Pos;
65         NRF_P0->PIN_CNF[14] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
66         NRF_P0->PIN_CNF[15] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
67         NRF_P0->PIN_CNF[16] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
68         NRF_P0->PIN_CNF[18] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
69         NRF_P0->PIN_CNF[20] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
70     #endif
71 
72     /* Workaround for Errata 12 "COMP: Reference ladder not correctly calibrated" found at the Errata document
73        for your device located at https://infocenter.nordicsemi.com/index.jsp */
74     if (nrf52_errata_12()){
75         *(volatile uint32_t *)0x40013540 = (*(uint32_t *)0x10000324 & 0x00001F00) >> 8;
76     }
77 
78     /* Workaround for Errata 16 "System: RAM may be corrupt on wakeup from CPU IDLE" found at the Errata document
79        for your device located at https://infocenter.nordicsemi.com/index.jsp */
80     if (nrf52_errata_16()){
81         *(volatile uint32_t *)0x4007C074 = 3131961357ul;
82     }
83 
84     /* Workaround for Errata 31 "CLOCK: Calibration values are not correctly loaded from FICR at reset" found at the Errata document
85        for your device located at https://infocenter.nordicsemi.com/index.jsp */
86     if (nrf52_errata_31()){
87         *(volatile uint32_t *)0x4000053C = ((*(volatile uint32_t *)0x10000244) & 0x0000E000) >> 13;
88     }
89 
90     /* Workaround for Errata 32 "DIF: Debug session automatically enables TracePort pins" found at the Errata document
91        for your device located at https://infocenter.nordicsemi.com/index.jsp */
92     if (nrf52_errata_32()){
93         CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk;
94     }
95 
96     /* Workaround for Errata 36 "CLOCK: Some registers are not reset when expected" found at the Errata document
97        for your device located at https://infocenter.nordicsemi.com/index.jsp  */
98     if (nrf52_errata_36()){
99         NRF_CLOCK->EVENTS_DONE = 0;
100         NRF_CLOCK->EVENTS_CTTO = 0;
101         NRF_CLOCK->CTIV = 0;
102     }
103 
104     /* Workaround for Errata 37 "RADIO: Encryption engine is slow by default" found at the Errata document
105        for your device located at https://infocenter.nordicsemi.com/index.jsp  */
106     if (nrf52_errata_37()){
107         *(volatile uint32_t *)0x400005A0 = 0x3;
108     }
109 
110     /* Workaround for Errata 57 "NFCT: NFC Modulation amplitude" found at the Errata document
111        for your device located at https://infocenter.nordicsemi.com/index.jsp  */
112     if (nrf52_errata_57()){
113         *(volatile uint32_t *)0x40005610 = 0x00000005;
114         *(volatile uint32_t *)0x40005688 = 0x00000001;
115         *(volatile uint32_t *)0x40005618 = 0x00000000;
116         *(volatile uint32_t *)0x40005614 = 0x0000003F;
117     }
118 
119     /* Workaround for Errata 66 "TEMP: Linearity specification not met with default settings" found at the Errata document
120        for your device located at https://infocenter.nordicsemi.com/index.jsp  */
121     if (nrf52_errata_66()){
122         NRF_TEMP->A0 = NRF_FICR->TEMP.A0;
123         NRF_TEMP->A1 = NRF_FICR->TEMP.A1;
124         NRF_TEMP->A2 = NRF_FICR->TEMP.A2;
125         NRF_TEMP->A3 = NRF_FICR->TEMP.A3;
126         NRF_TEMP->A4 = NRF_FICR->TEMP.A4;
127         NRF_TEMP->A5 = NRF_FICR->TEMP.A5;
128         NRF_TEMP->B0 = NRF_FICR->TEMP.B0;
129         NRF_TEMP->B1 = NRF_FICR->TEMP.B1;
130         NRF_TEMP->B2 = NRF_FICR->TEMP.B2;
131         NRF_TEMP->B3 = NRF_FICR->TEMP.B3;
132         NRF_TEMP->B4 = NRF_FICR->TEMP.B4;
133         NRF_TEMP->B5 = NRF_FICR->TEMP.B5;
134         NRF_TEMP->T0 = NRF_FICR->TEMP.T0;
135         NRF_TEMP->T1 = NRF_FICR->TEMP.T1;
136         NRF_TEMP->T2 = NRF_FICR->TEMP.T2;
137         NRF_TEMP->T3 = NRF_FICR->TEMP.T3;
138         NRF_TEMP->T4 = NRF_FICR->TEMP.T4;
139     }
140 
141     /* 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
142        for your device located at https://infocenter.nordicsemi.com/index.jsp  */
143     if (nrf52_errata_108()){
144         *(volatile uint32_t *)0x40000EE4ul = *(volatile uint32_t *)0x10000258ul & 0x0000004Ful;
145     }
146 
147     /* Workaround for Errata 136 "System: Bits in RESETREAS are set when they should not be" found at the Errata document
148        for your device located at https://infocenter.nordicsemi.com/index.jsp  */
149     if (nrf52_errata_136()){
150         if (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk){
151             NRF_POWER->RESETREAS =  ~POWER_RESETREAS_RESETPIN_Msk;
152         }
153     }
154 
155     /* Workaround for Errata 182 "RADIO: Fixes for anomalies #102, #106, and #107 do not take effect" found at the Errata document
156        for your device located at https://infocenter.nordicsemi.com/index.jsp  */
157     if (nrf52_errata_182()){
158         *(volatile uint32_t *) 0x4000173C |= (0x1 << 10);
159     }
160 
161     /* Enable the FPU if the compiler used floating point unit instructions. __FPU_USED is a MACRO defined by the
162      * compiler. Since the FPU consumes energy, remember to disable FPU use in the compiler if floating point unit
163      * operations are not used in your code. */
164     #if (__FPU_USED == 1)
165         SCB->CPACR |= (3UL << 20) | (3UL << 22);
166         __DSB();
167         __ISB();
168     #endif
169 
170     /* Configure NFCT pins as GPIOs if NFCT is not to be used in your code. If CONFIG_NFCT_PINS_AS_GPIOS is not defined,
171        two GPIOs (see Product Specification to see which ones) will be reserved for NFC and will not be available as
172        normal GPIOs. */
173     #if defined (CONFIG_NFCT_PINS_AS_GPIOS)
174         if ((NRF_UICR->NFCPINS & UICR_NFCPINS_PROTECT_Msk) == (UICR_NFCPINS_PROTECT_NFC << UICR_NFCPINS_PROTECT_Pos)){
175             NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
176             while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
177             NRF_UICR->NFCPINS &= ~UICR_NFCPINS_PROTECT_Msk;
178             while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
179             NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
180             while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
181             NVIC_SystemReset();
182         }
183     #endif
184 
185     /* Configure GPIO pads as pPin Reset pin if Pin Reset capabilities desired. If CONFIG_GPIO_AS_PINRESET is not
186       defined, pin reset will not be available. One GPIO (see Product Specification to see which one) will then be
187       reserved for PinReset and not available as normal GPIO. */
188     #if defined (CONFIG_GPIO_AS_PINRESET)
189         if (((NRF_UICR->PSELRESET[0] & UICR_PSELRESET_CONNECT_Msk) != (UICR_PSELRESET_CONNECT_Connected << UICR_PSELRESET_CONNECT_Pos)) ||
190             ((NRF_UICR->PSELRESET[1] & UICR_PSELRESET_CONNECT_Msk) != (UICR_PSELRESET_CONNECT_Connected << UICR_PSELRESET_CONNECT_Pos))){
191             NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
192             while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
193             NRF_UICR->PSELRESET[0] = 21;
194             while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
195             NRF_UICR->PSELRESET[1] = 21;
196             while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
197             NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
198             while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
199             NVIC_SystemReset();
200         }
201     #endif
202 
203     SystemCoreClockUpdate();
204 }
205 
206 
207 /*lint --flb "Leave library region" */
208