blob: 28c225e3b07477122e5a4392659b05c9c94cf900 [file] [log] [blame]
/*
** ###################################################################
** Processors: JN5189HN
** JN5189THN
**
** Compilers: Keil ARM C/C++ Compiler
** GNU C Compiler
** IAR ANSI C/C++ Compiler for ARM
** MCUXpresso Compiler
**
** Reference manual: JN5189 User manual Rev0.1 27 July 2018
** Version: rev. 1.0, 2018-07-31
** Build: b180731
**
** Abstract:
** Provides a system configuration function and a global variable that
** contains the system frequency. It configures the device and initializes
** the oscillator (PLL) that is part of the microcontroller device.
**
** Copyright 2016 Freescale Semiconductor, Inc.
** Copyright 2016-2018 NXP
**
** SPDX-License-Identifier: BSD-3-Clause
**
** http: www.nxp.com
** mail: support@nxp.com
**
** Revisions:
** - rev. 1.0 (2018-07-31)
** Initial version.
**
** ###################################################################
*/
/*!
* @file JN5189
* @version 1.0
* @date 2018-07-31
* @brief Device specific configuration file for JN5189 (implementation file)
*
* Provides a system configuration function and a global variable that contains
* the system frequency. It configures the device and initializes the oscillator
* (PLL) that is part of the microcontroller device.
*/
#include <stdint.h>
#include "fsl_device_registers.h"
#include "rom_api.h"
/**
* Clock source selections for the Main Clock
*/
typedef enum _main_clock_src
{
kCLOCK_MainFro12M = 0,
kCLOCK_MainOsc32k = 1,
kCLOCK_MainXtal32M = 2,
kCLOCK_MainFro32M = 3,
kCLOCK_MainFro48M = 4,
kCLOCK_MainExtClk = 5,
kCLOCK_MainFro1M = 6,
} main_clock_src_t;
/**
* Clock source selections for CLKOUT
*/
typedef enum _clkout_clock_src
{
kCLOCK_ClkoutMainClk = 0,
kCLOCK_ClkoutXtal32k = 1,
kCLOCK_ClkoutFro32k = 2,
kCLOCK_ClkoutXtal32M = 3,
kCLOCK_ClkoutDcDcTest= 4,
kCLOCK_ClkoutFro48M = 5,
kCLOCK_ClkoutFro1M = 6,
kCLOCK_ClkoutNoClock = 7
} clkout_clock_src_t;
typedef enum
{
FRO12M_ENA = (1 << 0),
FRO32M_ENA = (1 << 1),
FRO48M_ENA = (1 << 2),
FRO64M_ENA = (1 << 3),
FRO96M_ENA = (1 << 4)
} Fro_ClkSel_t;
#define OSC32K_FREQ 32768UL
#define FRO32K_FREQ 32768UL
#define OSC32M_FREQ 32000000UL
#define XTAL32M_FREQ 32000000UL
#define FRO64M_FREQ 64000000UL
#define FRO1M_FREQ 1000000UL
#define FRO12M_FREQ 12000000UL
#define FRO32M_FREQ 32000000UL
#define FRO48M_FREQ 48000000UL
static const uint32_t g_Ext_Clk_Freq = 0U;
extern unsigned int __Vectors;
extern WEAK void SystemInit(void);
extern WEAK void WarmMain(void);
static uint32_t CLOCK_GetXtal32kFreq(void)
{
uint32_t freq = 0;
if (((PMC->PDRUNCFG & PMC_PDRUNCFG_ENA_XTAL32K_MASK)
>> PMC_PDRUNCFG_ENA_XTAL32K_SHIFT) != 0)
{
freq = OSC32K_FREQ;
}
return freq;
}
static uint32_t CLOCK_GetXtal32MFreq(void)
{
return XTAL32M_FREQ;
}
static uint32_t CLOCK_GetFro32kFreq(void)
{
uint32_t freq = 0;
if (((PMC->PDRUNCFG & PMC_PDRUNCFG_ENA_FRO32K_MASK)
>> PMC_PDRUNCFG_ENA_FRO32K_SHIFT) != 0)
{
freq = FRO32K_FREQ;
}
return freq;
}
static uint32_t CLOCK_GetFro1MFreq(void)
{
return FRO1M_FREQ;
}
static uint32_t CLOCK_GetFro12MFreq(void)
{
uint32_t freq = 0;
if (((PMC->FRO192M & PMC_FRO192M_DIVSEL_MASK) >>
PMC_FRO192M_DIVSEL_SHIFT) & FRO12M_ENA)
{
freq = FRO12M_FREQ;
}
return freq;
}
static uint32_t CLOCK_GetFro32MFreq(void)
{
uint32_t freq = 0;
if (((PMC->FRO192M & PMC_FRO192M_DIVSEL_MASK) >>
PMC_FRO192M_DIVSEL_SHIFT) & FRO32M_ENA)
{
freq = FRO32M_FREQ;
}
return freq;
}
static uint32_t CLOCK_GetFro48MFreq(void)
{
uint32_t freq = 0;
if (((PMC->FRO192M & PMC_FRO192M_DIVSEL_MASK) >>
PMC_FRO192M_DIVSEL_SHIFT) & FRO48M_ENA)
{
freq = FRO48M_FREQ;
}
return freq;
}
static uint32_t CLOCK_GetOsc32kFreq(void)
{
uint32_t freq = 0;
if ((SYSCON->OSC32CLKSEL & SYSCON_OSC32CLKSEL_SEL32KHZ_MASK) != 0)
{
freq = CLOCK_GetXtal32kFreq();
}
else
{
freq = CLOCK_GetFro32kFreq();
}
return freq;
}
/* Return main clock rate */
static uint32_t CLOCK_GetMainClockRate(void)
{
uint32_t freq = 0;
switch ((main_clock_src_t)((SYSCON->MAINCLKSEL & SYSCON_MAINCLKSEL_SEL_MASK)
>> SYSCON_MAINCLKSEL_SEL_SHIFT))
{
case kCLOCK_MainFro12M:
freq = CLOCK_GetFro12MFreq();
break;
case kCLOCK_MainOsc32k:
freq = CLOCK_GetOsc32kFreq();
break;
case kCLOCK_MainXtal32M:
freq = CLOCK_GetXtal32MFreq();
break;
case kCLOCK_MainFro32M:
freq = CLOCK_GetFro32MFreq();
break;
case kCLOCK_MainFro48M:
freq = CLOCK_GetFro48MFreq();
break;
case kCLOCK_MainExtClk:
freq = g_Ext_Clk_Freq;
break;
case kCLOCK_MainFro1M:
freq = CLOCK_GetFro1MFreq();
break;
}
return freq;
}
/* ----------------------------------------------------------------------------
-- Core clock
---------------------------------------------------------------------------- */
uint32_t SystemCoreClock = DEFAULT_SYSTEM_CLOCK;
#if defined(__ICCARM__)
//*****************************************************************************
// Reset entry point for your code.
// Sets up a simple runtime environment and initializes the C/C++
// library.
//*****************************************************************************
void ResetISR(void)
{
__asm volatile(
"LDR R0,=0x40000804\t\n" // load co-processor boot address (from CPBOOT)
"LDR R0,[R0]\t\n" // get address to branch to
"MOVS R0,R0\t\n" // Check if 0
"BEQ.N masterboot\t\n" // if zero in boot reg, we just branch to real reset
"LDR R1,=0x40000808\t\n" // load co-processor stack pointer (from CPSTACK)
"LDR R1,[R1]\t\n"
"MOV SP,R1\t\n"
"BX R0\t\n" // branch to boot address
"masterboot:\t\n"
"LDR R0, =ResetISR2\t\n" // jump to 'real' reset handler
"BX R0\t\n");
}
void ResetISR2(void)
{
if ((void (*)(void))WarmMain != NULL)
{
unsigned int warm_start;
uint32_t pmc_lpmode;
uint32_t pmc_resetcause;
uint32_t pwr_pdsleepcfg;
pmc_resetcause = PMC->RESETCAUSE;
pwr_pdsleepcfg = PMC->PDSLEEPCFG;
pmc_lpmode = BOOT_GetStartPowerMode();
warm_start = (pmc_lpmode == 0x02); /* coming from power down mode*/
// check if the reset cause is only a timer wakeup or io wakeup with all memory banks held
warm_start &= ( !(pmc_resetcause & (PMC_RESETCAUSE_POR_MASK
| PMC_RESETCAUSE_PADRESET_MASK
| PMC_RESETCAUSE_BODRESET_MASK
| PMC_RESETCAUSE_SYSTEMRESET_MASK
| PMC_RESETCAUSE_WDTRESET_MASK
| PMC_RESETCAUSE_WAKEUPIORESET_MASK ))
&& ( pmc_resetcause & PMC_RESETCAUSE_WAKEUPPWDNRESET_MASK )
&& ((pwr_pdsleepcfg & PMC_PDSLEEPCFG_PDEN_PD_MEM7_MASK) == 0x0 ) /* BANK7 memory bank held */
&& ( pwr_pdsleepcfg & PMC_PDSLEEPCFG_PDEN_LDO_MEM_MASK ) /* LDO MEM enabled */
);
if (warm_start)
{
if (SYSCON->CPSTACK)
{
/* if CPSTACK is not NULL, switch to CPSTACK value so we avoid to corrupt the stack used before power down
* Note: it looks like enough to switch to new SP now and not earlier */
__asm volatile(
"LDR R1,=0x40000808\t\n" // load co-processor stack pointer (from CPSTACK)
"LDR R1,[R1]\t\n"
"MOV SP,R1\t\n"
);
}
// Check to see if we are running the code from a non-zero
// address (eg RAM, external flash), in which case we need
// to modify the VTOR register to tell the CPU that the
// vector table is located at a non-0x0 address.
unsigned int *pSCB_VTOR = (unsigned int *)0xE000ED08;
if (((unsigned int)(&__Vectors) != 0))
{
// CMSIS : SCB->VTOR = <address of vector table>
*pSCB_VTOR = (unsigned int)(&__Vectors);
}
if ((void (*)(void))SystemInit != NULL)
{
SystemInit();
}
WarmMain();
//
// WarmMain() shouldn't return, but if it does, we'll just enter an infinite loop
//
while (1)
{
;
}
}
}
// Check to see if we are running the code from a non-zero
// address (eg RAM, external flash), in which case we need
// to modify the VTOR register to tell the CPU that the
// vector table is located at a non-0x0 address.
unsigned int *pSCB_VTOR = (unsigned int *)0xE000ED08;
if ((unsigned int)(&__Vectors) != 0)
{
// CMSIS : SCB->VTOR = <address of vector table>
*pSCB_VTOR = (unsigned int)(&__Vectors);
}
SystemInit();
#if defined(__cplusplus)
//
// Call C++ library initialisation
//
__libc_init_array();
#endif
}
#endif
/* ----------------------------------------------------------------------------
-- SystemInit()
---------------------------------------------------------------------------- */
void SystemInit (void) {
uint32_t trim;
/* Initialise SystemCoreClock value */
SystemCoreClockUpdate();
/* Initialise NVIC priority grouping value */
NVIC_SetPriorityGrouping(4);
/* Apply FRO1M trim value */
trim = *(uint32_t*)(0x9FCD0U);
if(trim & 0x1U)
{
PMC->FRO1M = (PMC->FRO1M & ~PMC_FRO1M_FREQSEL_MASK) | ((trim>>1) & PMC_FRO1M_FREQSEL_MASK);
}
}
/* ----------------------------------------------------------------------------
-- SystemCoreClockUpdate()
---------------------------------------------------------------------------- */
void SystemCoreClockUpdate (void) {
SystemCoreClock = (CLOCK_GetMainClockRate() / ((SYSCON->AHBCLKDIV & SYSCON_AHBCLKDIV_DIV_MASK) + 1U));
}