blob: c3311410a206ca340a8611a779f26973a100adce [file] [log] [blame]
/*
* Copyright (c) 2016 Nordic Semiconductor ASA
*
* 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
*
* http://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.
*/
/**
* @file
* @brief System/hardware module for Nordic Semiconductor nRF52 family processor
*
* This module provides routines to initialize and support board-level hardware
* for the Nordic Semiconductor nRF52 family processor.
*/
#include <nanokernel.h>
#include <device.h>
#include <init.h>
#include <soc.h>
#ifdef CONFIG_RUNTIME_NMI
extern void _NmiInit(void);
#define NMI_INIT() _NmiInit()
#else
#define NMI_INIT()
#endif
#include "system_nrf52.h"
#define __SYSTEM_CLOCK_64M (64000000UL)
static bool ftpan_32(void);
static bool ftpan_37(void);
static bool ftpan_36(void);
uint32_t SystemCoreClock __used = __SYSTEM_CLOCK_64M;
static void clock_init(void)
{
SystemCoreClock = __SYSTEM_CLOCK_64M;
}
static int nordicsemi_nrf52_init(struct device *arg)
{
uint32_t key;
ARG_UNUSED(arg);
/* Note:
* Magic numbers below are obtained by reading the registers
* when the SoC was running the SAM-BA bootloader
* (with reserved bits set to 0).
*/
key = irq_lock();
/* Setup the vector table offset register (VTOR),
* which is located at the beginning of flash area.
*/
_scs_relocate_vector_table((void *)CONFIG_FLASH_BASE_ADDRESS);
/* Workaround for FTPAN-32 "DIF: Debug session automatically
* enables TracePort pins" found at Product Anomaly document
* for your device located at https://www.nordicsemi.com/
*/
if (ftpan_32()) {
CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk;
}
/* Workaround for FTPAN-37 "AMLI: EasyDMA is slow with Radio,
* ECB, AAR and CCM." found at Product Anomaly document
* for your device located at https://www.nordicsemi.com/
*/
if (ftpan_37()) {
*(volatile uint32_t *)0x400005A0 = 0x3;
}
/* Workaround for FTPAN-36 "CLOCK: Some registers are not
* reset when expected." found at Product Anomaly document
* for your device located at https://www.nordicsemi.com/
*/
if (ftpan_36()) {
NRF_CLOCK->EVENTS_DONE = 0;
NRF_CLOCK->EVENTS_CTTO = 0;
}
/* 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
/* Configure NFCT pins as GPIOs if NFCT is not to be used in
* your code. If CONFIG_NFCT_PINS_AS_GPIOS is not defined,
* two GPIOs (see Product Specification to see which ones)
* will be reserved for NFC and will not be available as
* normal GPIOs.
*/
#if defined(CONFIG_NFCT_PINS_AS_GPIOS)
if ((NRF_UICR->NFCPINS & UICR_NFCPINS_PROTECT_Msk) ==
(UICR_NFCPINS_PROTECT_NFC << UICR_NFCPINS_PROTECT_Pos)) {
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {
;
}
NRF_UICR->NFCPINS &= ~UICR_NFCPINS_PROTECT_Msk;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {
;
}
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {
;
}
NVIC_SystemReset();
}
#endif
/* Configure GPIO pads as pPin Reset pin if Pin Reset
* capabilities desired. If CONFIG_GPIO_AS_PINRESET is not
* defined, pin reset will not be available. One GPIO (see
* Product Specification to see which one) will then be
* reserved for PinReset and not available as normal GPIO.
*/
#if defined(CONFIG_GPIO_AS_PINRESET)
if (((NRF_UICR->PSELRESET[0] & UICR_PSELRESET_CONNECT_Msk) !=
(UICR_PSELRESET_CONNECT_Connected << UICR_PSELRESET_CONNECT_Pos)) ||
((NRF_UICR->PSELRESET[0] & UICR_PSELRESET_CONNECT_Msk) !=
(UICR_PSELRESET_CONNECT_Connected << UICR_PSELRESET_CONNECT_Pos))) {
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {
;
}
NRF_UICR->PSELRESET[0] = 21;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {
;
}
NRF_UICR->PSELRESET[1] = 21;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {
;
}
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {
;
}
NVIC_SystemReset();
}
#endif
/* Enable SWO trace functionality. If ENABLE_SWO is not
* defined, SWO pin will be used as GPIO (see Product
* Specification to see which one).
*/
#if defined(ENABLE_SWO)
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
NRF_CLOCK->TRACECONFIG |= CLOCK_TRACECONFIG_TRACEMUX_Serial <<
CLOCK_TRACECONFIG_TRACEMUX_Pos;
#endif
/* Enable Trace functionality. If ENABLE_TRACE is not
* defined, TRACE pins will be used as GPIOs (see Product
* Specification to see which ones).
*/
#if defined(ENABLE_TRACE)
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
NRF_CLOCK->TRACECONFIG |= CLOCK_TRACECONFIG_TRACEMUX_Parallel <<
CLOCK_TRACECONFIG_TRACEMUX_Pos;
#endif
/* Clear all faults */
_ScbMemFaultAllFaultsReset();
_ScbBusFaultAllFaultsReset();
_ScbUsageFaultAllFaultsReset();
_ScbHardFaultAllFaultsReset();
/* Setup master clock */
clock_init();
/* Install default handler that simply resets the CPU
* if configured in the kernel, NOP otherwise
*/
NMI_INIT();
irq_unlock(key);
return 0;
}
static bool ftpan_32(void)
{
if ((((*(uint32_t *)0xF0000FE0) & 0x000000FF) == 0x6) &&
(((*(uint32_t *)0xF0000FE4) & 0x0000000F) == 0x0)) {
if ((((*(uint32_t *)0xF0000FE8) & 0x000000F0) == 0x30) &&
(((*(uint32_t *)0xF0000FEC) & 0x000000F0) == 0x0)) {
return true;
}
}
return false;
}
static bool ftpan_37(void)
{
if ((((*(uint32_t *)0xF0000FE0) & 0x000000FF) == 0x6) &&
(((*(uint32_t *)0xF0000FE4) & 0x0000000F) == 0x0)) {
if ((((*(uint32_t *)0xF0000FE8) & 0x000000F0) == 0x30) &&
(((*(uint32_t *)0xF0000FEC) & 0x000000F0) == 0x0)) {
return true;
}
}
return false;
}
static bool ftpan_36(void)
{
if ((((*(uint32_t *)0xF0000FE0) & 0x000000FF) == 0x6) &&
(((*(uint32_t *)0xF0000FE4) & 0x0000000F) == 0x0)) {
if ((((*(uint32_t *)0xF0000FE8) & 0x000000F0) == 0x30) &&
(((*(uint32_t *)0xF0000FEC) & 0x000000F0) == 0x0)) {
return true;
}
}
return false;
}
SYS_INIT(nordicsemi_nrf52_init, PRIMARY, 0);