blob: 70e35ecfc32b32bdf68c19f79079991a157512c4 [file] [log] [blame]
/*
Copyright (c) 2009-2018 ARM Limited. All rights reserved.
SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the License); you may
not use this file except in compliance with the License.
You may obtain a copy of the License at
www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an AS IS BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
NOTICE: This file has been modified by Nordic Semiconductor ASA.
*/
/* NOTE: Template files (including this one) are application specific and therefore expected to
be copied into the application project folder prior to its use! */
#include <stdint.h>
#include <stdbool.h>
#include "nrf.h"
#include "system_nrf9160.h"
/*lint ++flb "Enter library region" */
#define __SYSTEM_CLOCK (64000000UL) /*!< nRF9160 Application core uses a fixed System Clock Frequency of 64MHz */
#if defined ( __CC_ARM )
uint32_t SystemCoreClock __attribute__((used)) = __SYSTEM_CLOCK;
#elif defined ( __ICCARM__ )
__root uint32_t SystemCoreClock = __SYSTEM_CLOCK;
#elif defined ( __GNUC__ )
uint32_t SystemCoreClock __attribute__((used)) = __SYSTEM_CLOCK;
#endif
/* Errata are only handled in secure mode since they usually need access to FICR. */
#if !defined(NRF_TRUSTZONE_NONSECURE)
static bool uicr_HFXOSRC_erased(void);
static bool uicr_HFXOCNT_erased(void);
static bool errata_6(void);
static bool errata_14(void);
static bool errata_15(void);
#endif
void SystemCoreClockUpdate(void)
{
SystemCoreClock = __SYSTEM_CLOCK;
}
void SystemInit(void)
{
#if !defined(NRF_TRUSTZONE_NONSECURE)
/* Perform Secure-mode initialization routines. */
/* Set all ARM SAU regions to NonSecure if TrustZone extensions are enabled.
* Nordic SPU should handle Secure Attribution tasks */
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
SAU->CTRL |= (1 << SAU_CTRL_ALLNS_Pos);
#endif
/* Trimming of the device. Copy all the trimming values from FICR into the target addresses. Trim
until one ADDR is not initialized. */
uint32_t index = 0;
for (index = 0; index < 256ul && NRF_FICR_S->TRIMCNF[index].ADDR != 0xFFFFFFFFul; index++){
#if defined ( __ICCARM__ )
#pragma diag_suppress=Pa082
#endif
*(volatile uint32_t *)NRF_FICR_S->TRIMCNF[index].ADDR = NRF_FICR_S->TRIMCNF[index].DATA;
#if defined ( __ICCARM__ )
#pragma diag_default=Pa082
#endif
}
/* Set UICR->HFXOSRC and UICR->HFXOCNT to working defaults if UICR was erased */
if (uicr_HFXOSRC_erased() || uicr_HFXOCNT_erased()) {
/* Wait for pending NVMC operations to finish */
while (NRF_NVMC_S->READY != NVMC_READY_READY_Ready);
/* Enable write mode in NVMC */
NRF_NVMC_S->CONFIG = NVMC_CONFIG_WEN_Wen;
while (NRF_NVMC_S->READY != NVMC_READY_READY_Ready);
if (uicr_HFXOSRC_erased()){
/* Write default value to UICR->HFXOSRC */
NRF_UICR_S->HFXOSRC = (NRF_UICR_S->HFXOSRC & ~UICR_HFXOSRC_HFXOSRC_Msk) | UICR_HFXOSRC_HFXOSRC_TCXO;
while (NRF_NVMC_S->READY != NVMC_READY_READY_Ready);
}
if (uicr_HFXOCNT_erased()){
/* Write default value to UICR->HFXOCNT */
NRF_UICR_S->HFXOCNT = (NRF_UICR_S->HFXOCNT & ~UICR_HFXOCNT_HFXOCNT_Msk) | 0x20;
while (NRF_NVMC_S->READY != NVMC_READY_READY_Ready);
}
/* Enable read mode in NVMC */
NRF_NVMC_S->CONFIG = NVMC_CONFIG_WEN_Ren;
while (NRF_NVMC_S->READY != NVMC_READY_READY_Ready);
/* Reset to apply clock select update */
NVIC_SystemReset();
}
/* Workaround for Errata 6 "POWER: SLEEPENTER and SLEEPEXIT events asserted after pin reset" found at the Errata document
for your device located at https://www.nordicsemi.com/DocLib */
if (errata_6()){
NRF_POWER_S->EVENTS_SLEEPENTER = (POWER_EVENTS_SLEEPENTER_EVENTS_SLEEPENTER_NotGenerated << POWER_EVENTS_SLEEPENTER_EVENTS_SLEEPENTER_Pos);
NRF_POWER_S->EVENTS_SLEEPEXIT = (POWER_EVENTS_SLEEPEXIT_EVENTS_SLEEPEXIT_NotGenerated << POWER_EVENTS_SLEEPEXIT_EVENTS_SLEEPEXIT_Pos);
}
/* Workaround for Errata 14 "REGULATORS: LDO mode at startup" found at the Errata document
for your device located at https://www.nordicsemi.com/DocLib */
if (errata_14()){
*(uint32_t *)0x50004A38 = 0x01ul;
NRF_REGULATORS_S->DCDCEN = REGULATORS_DCDCEN_DCDCEN_Enabled << REGULATORS_DCDCEN_DCDCEN_Pos;
}
/* Workaround for Errata 15 "REGULATORS: LDO mode at startup" found at the Errata document
for your device located at https://www.nordicsemi.com/DocLib */
if (errata_15()){
*(uint32_t *)0x50004A38 = 0x00ul;
NRF_REGULATORS_S->DCDCEN = REGULATORS_DCDCEN_DCDCEN_Enabled << REGULATORS_DCDCEN_DCDCEN_Pos;
}
/* Allow Non-Secure code to run FPU instructions.
* If only the secure code should control FPU power state these registers should be configured accordingly in the secure application code. */
SCB->NSACR |= (3UL << 10);
#endif
/* Enable the FPU if the compiler used floating point unit instructions. __FPU_USED is a MACRO defined by the
* compiler. Since the FPU consumes energy, remember to disable FPU use in the compiler if floating point unit
* operations are not used in your code. */
#if (__FPU_USED == 1)
SCB->CPACR |= (3UL << 20) | (3UL << 22);
__DSB();
__ISB();
#endif
SystemCoreClockUpdate();
}
#if !defined(NRF_TRUSTZONE_NONSECURE)
bool uicr_HFXOCNT_erased()
{
if (NRF_UICR_S->HFXOCNT == 0xFFFFFFFFul) {
return true;
}
return false;
}
bool uicr_HFXOSRC_erased()
{
if ((NRF_UICR_S->HFXOSRC & UICR_HFXOSRC_HFXOSRC_Msk) != UICR_HFXOSRC_HFXOSRC_TCXO) {
return true;
}
return false;
}
bool errata_6()
{
if (*(uint32_t *)0x00FF0130 == 0x9ul){
if (*(uint32_t *)0x00FF0134 == 0x01ul){
return true;
}
if (*(uint32_t *)0x00FF0134 == 0x02ul){
return true;
}
}
return false;
}
bool errata_14()
{
if (*(uint32_t *)0x00FF0130 == 0x9ul){
if (*(uint32_t *)0x00FF0134 == 0x01ul){
return true;
}
}
return false;
}
bool errata_15()
{
if (*(uint32_t *)0x00FF0130 == 0x9ul){
if (*(uint32_t *)0x00FF0134 == 0x02ul){
return true;
}
}
return false;
}
#endif
/*lint --flb "Leave library region" */