1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/cpu/qn908x/cpu.c
2023-01-08 22:26:12 +01:00

126 lines
3.7 KiB
C

/*
* Copyright (C) 2020 iosabi
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @ingroup cpu_qn908x
* @{
*
* @file
* @brief QN908x CPU initialization
*
* @author iosabi <iosabi@protonmail.com>
* @}
*/
#include "cpu.h"
#include "kernel_init.h"
#include "periph/init.h"
#include "stdio_base.h"
#include "vendor/drivers/fsl_clock.h"
static void cpu_clock_init(void);
/**
* @brief Initialize the CPU
*/
void cpu_init(void)
{
/* initialize the Cortex-M core */
cortexm_init();
#ifndef MODULE_PERIPH_WDT
/* If the `periph_wdt` is *not* being used (because the user does not care
* about that feature) we need to disable the Watchdog and continue running
* without it. Otherwise the CPU will reboot after about 10 seconds.
*/
CLOCK_DisableClock(kCLOCK_Wdt);
#endif /* ndef MODULE_PERIPH_WDT */
/* TODO: It would be good to move the VTOR to SRAM to allow execution from
* RAM with the FLASH memory off to allow for ultra low power operation on
* sleep mode. This needs to be done after cortexm_init() since it sets the
* VTOR to _isr_vectors which is the address on FLASH.
*/
/* initialize the clocks */
cpu_clock_init();
/* initialize stdio prior to periph_init() to allow use of DEBUG() there */
early_init();
/* trigger static peripheral initialization */
periph_init();
}
/* Set up clock speed configuration. See cpu_conf.h for details about the
* different clock options. */
void cpu_clock_init(void)
{
/* Set up external clock frequency. */
#if CONFIG_BOARD_HAS_XTAL
#if CONFIG_BOARD_HAS_XTAL_32M
CLOCK_AttachClk(k32M_to_XTAL_CLK); /* Switch XTAL_CLK to 32M */
#elif CONFIG_BOARD_HAS_XTAL_16M
CLOCK_AttachClk(k16M_to_XTAL_CLK); /* Switch XTAL_CLK to 16M */
#else
#error "One of the CONFIG_BOARD_XTAL_* must be set."
#endif
#endif /* CONFIG_BOARD_HAS_XTAL */
/* Set up 32K clock source. */
#if CONFIG_CPU_CLK_32K_XTAL
CLOCK_AttachClk(kXTAL32K_to_32K_CLK); /* Switch 32K_CLK to XTAL32K */
#elif CONFIG_CPU_CLK_32K_RCO
CLOCK_AttachClk(kRCO32K_to_32K_CLK); /* Switch 32K_CLK to RCO32K */
#else
#error "One of the CONFIG_CPU_CLK_32K_* must be set."
#endif
/* Set up System clock source. */
#if CONFIG_CPU_CLK_SYS_XTAL
CLOCK_AttachClk(kXTAL_to_SYS_CLK); /* Switch SYS_CLK to XTAL */
#elif CONFIG_CPU_CLK_SYS_OSC32M
CLOCK_AttachClk(kOSC32M_to_SYS_CLK); /* Switch SYS_CLK to OSM32M */
#elif CONFIG_CPU_CLK_SYS_32K
CLOCK_AttachClk(k32K_to_SYS_CLK); /* Switch SYS_CLK to 32K source */
#else
#error "One of the CONFIG_CPU_CLK_SYS_* must be set."
#endif
/* Run the WDT from the APB always. */
CLOCK_AttachClk(kAPB_to_WDT_CLK);
/* Set up dividers */
/* Set OSC32M_DIV divider */
#if CONFIG_CPU_CLK_OSC32M_DIV != 0 && CONFIG_CPU_CLK_OSC32M_DIV != 1
#error "Invalid CONFIG_CPU_CLK_OSC32M_DIV value"
#endif
/* Note: The denominator is set to (CONFIG_CPU_CLK_OSC32M_DIV + 1), so /2
* when the macro is enabled. */
CLOCK_SetClkDiv(kCLOCK_DivOsc32mClk, CONFIG_CPU_CLK_OSC32M_DIV);
/* Set XTAL_DIV divider */
#if CONFIG_CPU_CLK_XTAL_DIV != 0 && CONFIG_CPU_CLK_XTAL_DIV != 1
#error "Invalid CONFIG_CPU_CLK_XTAL_DIV value"
#endif
CLOCK_SetClkDiv(kCLOCK_DivXtalClk, CONFIG_CPU_CLK_XTAL_DIV);
/* Set AHB_DIV divider. */
#if CONFIG_CPU_CLK_AHB_DIV < 1 || CONFIG_CPU_CLK_AHB_DIV > 8192
#error "Invalid CONFIG_CPU_CLK_AHB_DIV"
#endif
CLOCK_SetClkDiv(kCLOCK_DivAhbClk, CONFIG_CPU_CLK_AHB_DIV - 1u);
/* Set APB_DIV divider. */
#if CONFIG_CPU_CLK_APB_DIV < 1 || CONFIG_CPU_CLK_APB_DIV > 16
#error "Invalid CONFIG_CPU_CLK_APB_DIV"
#endif
CLOCK_SetClkDiv(kCLOCK_DivApbClk, CONFIG_CPU_CLK_APB_DIV - 1u);
}