1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #13855 from iosabi/qn908x_initial

cpu/qn908x: Initial minimal support for NXP QN908x CPUs.
This commit is contained in:
benpicco 2020-12-02 10:31:38 +01:00 committed by GitHub
commit 646e665a86
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 13540 additions and 0 deletions

View File

@ -0,0 +1,10 @@
# 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.
config BOARD_COMMON_QN908X
bool
depends on CPU_FAM_QN908X
# Add common board support here.

View File

@ -0,0 +1,3 @@
MODULE = boards_common_qn908x
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,3 @@
CPU ?= qn908x
# Put defined MCU peripherals here (in alphabetical order)

View File

@ -0,0 +1,26 @@
# Using dap or jlink depends on which firmware the OpenSDA debugger is running
#DEBUG_ADAPTER ?= dap
DEBUG_ADAPTER ?= jlink
# Use the shared OpenOCD configuration
OPENOCD_CONFIG ?= $(RIOTBOARD)/common/qn908x/dist/openocd.cfg
# Disable the watchdog when flashing. OpenOCD runs a CRC program in RAM to
# verify the image, which needs to have the WDT disabled but it is normally
# enabled after a 'reset halt' command.
OPENOCD_PRE_FLASH_CMDS += "-c qn908x disable_wdog"
# Set default port depending on operating system
PORT_LINUX ?= /dev/ttyACM0
PORT_DARWIN ?= $(firstword $(sort $(wildcard /dev/tty.usbmodem*)))
# OpenOCD is able to handle .elf files and is the preferred way.
FLASHFILE ?= $(ELFFILE)
# Setup serial terminal
include $(RIOTMAKE)/tools/serial.inc.mk
# This board uses OpenOCD. Note that support for QN908x in OpenOCD at the time
# of writing has not been merged in the tree and is only available at
# http://openocd.zylin.com/#/c/5584/ .
include $(RIOTMAKE)/tools/openocd.inc.mk

12
boards/common/qn908x/dist/openocd.cfg vendored Normal file
View File

@ -0,0 +1,12 @@
# Generic configuration for a qn908x-based board.
# QN908X only supports SWD
transport select swd
# NXP QN908x.
source [find target/qn908x.cfg]
$TARGETNAME configure -event gdb-attach {
halt
}
$TARGETNAME configure -rtos auto

21
boards/qn9080dk/Kconfig Normal file
View File

@ -0,0 +1,21 @@
# 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.
#
config BOARD
default "qn9080dk" if BOARD_QN9080DK
config BOARD_QN9080DK
bool
default y
select BOARD_COMMON_QN908X
select CPU_MODEL_QN9080XHN
# Put defined MCU peripherals here (in alphabetical order)
select BOARD_HAS_XTAL32K
select BOARD_HAS_XTAL_32M
source "$(RIOTBOARD)/common/qn908x/Kconfig"

6
boards/qn9080dk/Makefile Normal file
View File

@ -0,0 +1,6 @@
MODULE = board
# Use the common qn908x board.
DIRS += $(RIOTBOARD)/common/qn908x
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,3 @@
ifneq (,$(filter saul_default,$(USEMODULE)))
USEMODULE += saul_gpio
endif

View File

@ -0,0 +1,8 @@
CPU = qn908x
CPU_MODEL = qn9080xhn
# Put defined MCU peripherals here (in alphabetical order)
FEATURES_PROVIDED += periph_gpio periph_gpio_irq
# Include the common qn908x board features.
include $(RIOTBOARD)/common/qn908x/Makefile.features

View File

@ -0,0 +1,8 @@
CFLAGS += \
-DCONFIG_BOARD_HAS_XTAL \
-DCONFIG_BOARD_HAS_XTAL32K \
-DCONFIG_BOARD_HAS_XTAL_32M \
#
# Include default QN908x board config
include $(RIOTBOARD)/common/qn908x/Makefile.include

37
boards/qn9080dk/board.c Normal file
View File

@ -0,0 +1,37 @@
/*
* 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 boards_qn9080dk
* @{
*
* @file
* @brief Board specific implementations for the QN9080DK base board
*
* @author iosabi <iosabi@protonmail.com>
*
* @}
*/
#include "cpu.h"
#include "board.h"
#include "periph/gpio.h"
void board_init(void)
{
/* Initialize LEDs and Buttons. */
gpio_init(LED_RED_PIN, GPIO_OUT);
gpio_init(LED_GREEN_PIN, GPIO_OUT);
gpio_init(LED_BLUE_PIN, GPIO_OUT);
gpio_init(BTN1_PIN, BTN1_MODE);
gpio_init(BTN2_PIN, BTN2_MODE);
/* initialize the CPU */
cpu_init();
}

62
boards/qn9080dk/doc.txt Normal file
View File

@ -0,0 +1,62 @@
/**
@defgroup boards_qn9080dk QN9080DK base board
@ingroup boards
@brief Support for the QN9080DK base board.
### General information
The QN9080DK is the developer board reference from NXP for the QN908x CPUs.
The developer kit comes with two boards: a larger PCB with a QFN "module"
including a QN9080DHN soldered onto it, altogether referred as the "base
board"; and separately a much smaller USB dongle with another QN9080 cpu.
This board module supports the "base board" only, including the definitions
of the gpio, buttons and LEDs specific to this board.
This board packs a few peripherals and many GPIOs:
* MMA8652FC, a 12-bit accelerometer
*
The board also features a dedicated programmer hardware implemented using NXP's
LPC4322, with its dedicated USB port for connecting to a computer on one end
and the SWD port and one UART RX/TX pair connected to the QN9080 on the other
end. The LPC4322 also has a fast (50 ksps) ADC ADC122S021 connected to a
current sense amplifier to monitor the QN9080 current profile directly on
the board.
For more information visit NXP's product description page for the
[QN9080-DK](https://www.nxp.com/QN9080DK) where you can find the User's
Guide.
### User Interface
Buttons:
| Label | RIOT OS macro | MCU PIN | Function |
|:----- |:------------- |:-------- |:--------- |
| SW1 | BTN1_PIN | PA24 | User defined |
| SW2 | BTN2_PIN | PA19 | User defined |
| SW3 | | nRESET | QN9080 reset |
One RGB led, controlled by three GPIOs
| Label | RIOT OS macro | MCU PIN |
|:----- |:------------- |:-------- |
| red | LED_RED_PIN | PA31 |
| green | LED_GREEN_PIN | PA25 |
| blue | LED_BLUE_PIN | PA13 |
### Pinout
Button1:
### Flash the board
The board can be flashed using the internal LPC4322 JTAG/SWD debugger or an
external debugger connected to P1, selected using JP2.
OpenOCD support for the QN908x is experimental and available as pending
[patch](http://openocd.zylin.com/#/c/5584/).
*/

View File

@ -0,0 +1,69 @@
/*
* 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 boards_qn9080dk
* @{
*
* @file
* @brief Board specific definitions for the QN9080DK base board
*
* @author iosabi <iosabi@protonmail.com>
*/
#ifndef BOARD_H
#define BOARD_H
#include "cpu.h"
#include "periph_conf.h"
#include "periph_cpu.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name Clock configuration
* @{
*/
#ifndef CLOCK_CORECLOCK
/* Using 32MHz internal oscillator as default clock source */
#define CLOCK_CORECLOCK (32000000ul)
#endif
/** @} */
/**
* @name LED configuration
* @{
*/
#define LED_RED_PIN GPIO_PIN(PORT_A, 31)
#define LED_GREEN_PIN GPIO_PIN(PORT_A, 25)
#define LED_BLUE_PIN GPIO_PIN(PORT_A, 13)
/** @} */
/**
* @name User buttons
* @{
*/
#define BTN1_PIN GPIO_PIN(PORT_A, 24)
#define BTN1_MODE GPIO_IN_PU
#define BTN2_PIN GPIO_PIN(PORT_A, 19)
#define BTN2_MODE GPIO_IN_PU
/** @} */
/**
* @brief Initialize board specific hardware
*/
void board_init(void);
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H */
/** @} */

View File

@ -0,0 +1,71 @@
/*
* 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 boards_qn9080dk
* @{
*
* @file
* @brief Board specific configuration of direct mapped GPIOs
*
* @author iosabi <iosabi@protonmail.com>
*/
#ifndef GPIO_PARAMS_H
#define GPIO_PARAMS_H
#include "board.h"
#include "saul/periph.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief GPIO pin configuration
*/
static const saul_gpio_params_t saul_gpio_params[] =
{
{
.name = "LED red",
.pin = LED_RED_PIN,
.mode = GPIO_OUT,
.flags = SAUL_GPIO_INIT_CLEAR,
},
{
.name = "LED green",
.pin = LED_GREEN_PIN,
.mode = GPIO_OUT,
.flags = SAUL_GPIO_INIT_CLEAR,
},
{
.name = "LED blue",
.pin = LED_BLUE_PIN,
.mode = GPIO_OUT,
.flags = SAUL_GPIO_INIT_CLEAR,
},
{
.name = "Button(SW1)",
.pin = BTN1_PIN,
.mode = BTN1_MODE,
.flags = SAUL_GPIO_INVERTED,
},
{
.name = "Button(SW2)",
.pin = BTN2_PIN,
.mode = BTN2_MODE,
.flags = SAUL_GPIO_INVERTED,
},
};
#ifdef __cplusplus
}
#endif
#endif /* GPIO_PARAMS_H */
/** @} */

View File

@ -0,0 +1,49 @@
/*
* 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 boards_qn9080dk
* @{
*
* @file
* @brief Configuration of CPU peripherals for QN9080DK base board board
*
* @author iosabi <iosabi@protonmail.com>
*/
#ifndef PERIPH_CONF_H
#define PERIPH_CONF_H
#include <stdint.h>
#include "cpu.h"
#include "periph_cpu.h"
#ifdef __cplusplus
extern "C" {
#endif
/* put here the board peripherals definitions:
- Available clocks
- Timers
- UARTs
- PWMs
- SPIs
- I2C
- ADC
- RTC
- RTT
etc
*/
#ifdef __cplusplus
}
#endif
#endif /* PERIPH_CONF_H */
/** @} */

51
cpu/qn908x/Kconfig Normal file
View File

@ -0,0 +1,51 @@
# 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.
#
config CPU_FAM_QN908X
bool
select CPU_CORE_CORTEX_M4F
select HAS_CORTEXM_MPU
select HAS_CPU_QN908X
select HAS_PERIPH_CPUID
select HAS_PERIPH_GPIO
select HAS_PERIPH_GPIO_IRQ
select HAS_PERIPH_WDT
select HAS_PERIPH_WDT_CB
## CPU Models
# For cpus QN9080CHN (revision C) and QN9080DHN (revision D)
config CPU_MODEL_QN9080XHN
bool
select CPU_FAM_QN908X
# For the smaller package for the same die, with 28 GPIOs instead of 35.
# cpus QN9083CUK (revision C) and QN9083DUK (revision D)
config CPU_MODEL_QN9083XUK
bool
select CPU_FAM_QN908X
## CPU common symbols
config CPU_FAM
default "qn908x" if CPU_FAM_QN908X
config CPU_MODEL
default "qn9080xhn" if CPU_MODEL_QN9080XHN
default "qn9083xhk" if CPU_MODEL_QN9083XUK
config CPU
default "qn908x" if CPU_FAM_QN908X
## Definition of specific features
config HAS_CPU_QN908X
bool
help
Indicates that the current cpu is 'qn908x'.
# Other cpu configuration
rsource "Kconfig.clk"
source "$(RIOTCPU)/cortexm_common/Kconfig"

120
cpu/qn908x/Kconfig.clk Normal file
View File

@ -0,0 +1,120 @@
# 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.
#
menu "QN908x clock configuration"
depends on CPU_FAM_QN908X
config BOARD_HAS_XTAL32K
bool
help
Indicates that the board has an external low frequency 32.786 KHz
crystal oscillator connected to the XTAL32_IN / XTAL32_OUT pins.
This should only be set from board definition.
choice
prompt "32K low frequency clock selector"
default CPU_CLK_32K_XTAL if BOARD_HAS_XTAL32K
default CPU_CLK_32K_RCO
help
The "32K" clock bus runs at either 32 KHz from the internal RCO or
32.768 KHz from an external crystal oscillator. This clock can be used
to drive the "System clock" for a very low power operation, but it can
independently also be used for the watchdog timer (WDT) and other low
frequency system timers like a real time clock.
config CPU_CLK_32K_XTAL
bool "External 32.768 KHz crystal"
depends on BOARD_HAS_XTAL32K
config CPU_CLK_32K_RCO
bool "Internal 32 KHz oscillator"
endchoice
config BOARD_HAS_XTAL
bool
help
Indicates that the board has an external high frequency crystal
oscillator connected to the XTAL_IN / XTAL_OUT pins.
This should only be set from board definition.
config BOARD_HAS_XTAL_16M
bool
imply BOARD_HAS_XTAL
depends on !BOARD_HAS_XTAL_32M
help
Indicates that the external high frequency crystal oscillator is a
16 MHz crystal. This should only be set from board definition.
config BOARD_HAS_XTAL_32M
bool
imply BOARD_HAS_XTAL
help
Indicates that the external high frequency crystal oscillator is a
32 MHz crystal. This should only be set from board definition.
config CPU_CLK_OSC32M_DIV
bool "Internal OSC32M clock input /2 divider"
help
Selecting this option will set the high-speed internal oscillator
divider to /2, making it a 16 MHz clock source. See "System clock
configuration selector" for selecting this source.
config CPU_CLK_XTAL_DIV
bool "External XTAL 32 MHz clock input /2 divider"
depends on BOARD_HAS_XTAL_32M
help
Selecting this option will set the high-speed external crystal
oscillator divider to /2. This option is only available when the
external oscillator is a 32 MHz one. See "System clock
configuration selector" for selecting this source.
choice
prompt "System clock configuration selector"
default CPU_CLK_SYS_XTAL if BOARD_HAS_XTAL
default CPU_CLK_SYS_OSC32M
help
The System clock is used to derive the AHB clock, which drives the ARM
core and most peripherals.
config CPU_CLK_SYS_XTAL
bool "External 16/32 MHz crystal source (with optional divider)"
depends on BOARD_HAS_XTAL
config CPU_CLK_SYS_OSC32M
bool "Internal 32 MHz oscillator source (with optional divider)"
config CPU_CLK_SYS_32K
bool "Low frequency clock source (32 or 32.768 KHz)"
endchoice
config CPU_CLK_AHB_DIV
int "AHB clock divider"
default 1
range 1 8192
help
The AHB clock is derived from the System clock using this divider value,
between 1 and 8192, and serves as a clock source for ARM core, FSP, SCT,
Quad-SPI, Flexcomm (UART, SPI, I2C), GPIO, BLE_AHB and DMA.
Note: When BLE is enabled, the AHB clock must be at least the BLE clock
(either 8 or 16 MHz) limiting the range of allowed values for this
divider so that the AHB clock is 8, 16 or 32 MHz.
config CPU_CLK_APB_DIV
int "APB clock divider"
default 1
range 1 16
help
The APB clock is derived from the AHB clock using this divide value,
between 1 and 16, and serves as the clock source for several
peripherals, such as the RTC, ADC, DAC, Capacitive Sense (CS) and
optionally the WDT.
# TODO: Add USB PLL and BLE clock selectors.
endmenu

10
cpu/qn908x/Makefile Normal file
View File

@ -0,0 +1,10 @@
# define the module that is build
MODULE = cpu
# add a list of subdirectories that should also be built
DIRS = periph $(RIOTCPU)/cortexm_common vendor
# (file triggers compiler bug. see #5775)
SRC_NOLTO += vectors.c
include $(RIOTBASE)/Makefile.base

18
cpu/qn908x/Makefile.dep Normal file
View File

@ -0,0 +1,18 @@
# In some cases, peripheral modules use vendor provided driver modules such as
# the vendor_fsl_clock. This file defines the dependencies between these periph
# modules and the vendor modules.
USEMODULE += vendor
# The clock functionality is used by most modules, including cpu.c even when
# no peripheral module is being used.
USEMODULE += vendor_fsl_clock
# All peripherals use gpio_mux.h
USEMODULE += periph_gpio_mux
# This cpu modules doesn't support UART peripherals yet, so we need to include
# stdio_null.
# TODO: Remove stdio_null once periph_uart is implemented in this module.
USEMODULE += stdio_null
include $(RIOTCPU)/cortexm_common/Makefile.dep

View File

@ -0,0 +1,9 @@
CPU_CORE = cortex-m4f
CPU_FAM = qn908x
FEATURES_PROVIDED += cortexm_mpu
FEATURES_PROVIDED += periph_cpuid
FEATURES_PROVIDED += periph_gpio periph_gpio_irq
FEATURES_PROVIDED += periph_wdt periph_wdt_cb
include $(RIOTCPU)/cortexm_common/Makefile.features

View File

@ -0,0 +1,39 @@
# Add search path for linker scripts
LINKFLAGS += -L$(RIOTCPU)/$(CPU)/ldscripts
LINKER_SCRIPT = qn908x.ld
# Internal FLASH memory is located at address 0x0100000, aliased to address
# 0x2100000 and can also be aliased to address 0, which is done by the
# pre_startup() function in cpu/qn908x/isr_qn908x.c. The address 0 can be also
# be remapped to RAM instead, and the FLASH can be turned completely off to save
# power, thus linking all the code based on address 0 could make it easier in
# the future to provide a low-power mode where portions of the code execute
# from RAM only during this low-power mode. However, linking all the code at
# address 0 makes it more difficult to attach gdb after a 'reset halt' but
# before the FLASH is mapped to 0 by pre_startup() since it can't place a
# breakpoint at any function in the FLASH alias at 0 until it is mapped.
# This default value of 0x01000000 makes it possible to place breakpoints across
# reboots, but it can be override from the board if needed. When setting
# ROM_START_ADDR to 0 the IMAGE_OFFSET must be set to 0x01000000 to allow
# flashing at the right location.
ROM_START_ADDR ?= 0x01000000
# SRAM is actually at 0x04000000 but it is also aliased to 0x20000000.
RAM_BASE_ADDR = 0x20000000
RAM_START_ADDR = $(RAM_BASE_ADDR)
# The only QN908x chips available have 512K flash, although it seems possible to
# have 256K versions.
ROM_LEN ?= 512K
RAM_LEN ?= 128K
CFLAGS += \
-DQN908X_ROM_START_ADDR=$(ROM_START_ADDR)
#
# Vendor submodules are all bundled in the vendor module, and they include
# some files from the include/vendor directory directly so we need to add that
# include path here.
PSEUDOMODULES += vendor_%
INCLUDES += -I$(RIOTCPU)/$(CPU)/include/vendor
include $(RIOTMAKE)/arch/cortexm.inc.mk

125
cpu/qn908x/cpu.c Normal file
View File

@ -0,0 +1,125 @@
/*
* 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 "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 */
stdio_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);
}

68
cpu/qn908x/doc.txt Normal file
View File

@ -0,0 +1,68 @@
/* NXP QN908x specific information for the `periph` drivers */
/**
@defgroup cpu_qn908x NXP QN908x
@ingroup cpu
@brief NXP QN908x BLE-enabled Cortex-M4F MCU specific implementation
The NXP QN908x family of chips such as the QN9080 feature a Cortex-M4F,
Bluetooth Low Energy, USB 2.0 and in some SKUs like the QN9080SIP NFC as well.
The CPU is designed to be ultra-low-power and high-performance, allowing
applications with small battery capacity. It includes an optional DC-DC and LDO,
low power sleep timers, I2C, SPI, ADC, SPIFI and several other peripherals.
@defgroup cpu_qn908x_cpuid NXP QN908x CPUID
@ingroup cpu_qn908x
@brief NXP QN908x CPUID driver
No configuration is necessary. The CPUID value is based on the factory assigned
default Bluetooth address in the read-only flash section which may not be the
Bluetooth address used by the Bluetooth module if a different one was programmed
there.
@defgroup cpu_qn908x_gpio NXP QN908x GPIO
@ingroup cpu_qn908x
@brief NXP QN908x GPIO driver
The GPIO driver uses the @ref GPIO_PIN(port, pin) macro to declare pins.
No configuration is necessary.
@defgroup cpu_qn908x_wdt NXP QN908x Watchdog timer (WDT)
@ingroup cpu_qn908x
@brief NXP QN908x Watchdog timer (WDT)
The Watchdog timer in the NXP QN908x starts disabled on reset: the clock bit
`CLK_WDT_EN` is enabled in the `CLK_EN` register on reset so the timer is
running but the interrupt and reset functions are disabled. However, after the
read-only bootloader ROM in the QN908x transfer the control flow to the user
application (the RIOT kernel) the Watchdog is enabled with a timeout of 10
seconds.
If your board does not include the `periph_wdt` module, the Watchdog will be
disabled at `cpu_init()` time and there's no configuration necessary. However,
if your board or application does include it, the Watchdog will be left
configured with the 10 second timeout set by the Bootloader and you need to
call `wdt_setup_reboot()` or `wdt_setup_reboot_with_callback()` within the first
10 seconds.
The WDT block supports different clock sources which would be configured by the
board since they depend on whether the optional crystals are populated in your
board. Nevertheless, the millisecond values passed to `wdt_setup_reboot*` are
internally converted to clock ticks using the clock configured at the time the
function was called. `wdt_setup_reboot*()` can be called multiple times to
change the WDT parameters or after changing the WDT clock source, but in any
case `wdt_start()` must be called after it to start the WDT operation.
Once the WDT triggers, it is not possible to avoid the device reboot and calling
wdt_kick() from the WDT callback (if any) or after the callback was called will
not have any effect. Note that, however, if the WDT callback returns before the
configured CONFIG_WDT_WARNING_PERIOD the CPU will continue executing the code
before the WDT interrupt occurred. If this is not desired, an infinite loop at
the end of the WDT callback, after the safety operations have been performed is
advisable.
*/

View File

@ -0,0 +1,332 @@
/*
* 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 Implementation specific CPU configuration options
*
* @author iosabi <iosabi@protonmail.com>
*/
#ifndef CPU_CONF_H
#define CPU_CONF_H
#include "cpu_conf_common.h"
#include "vendor/QN908XC.h"
#include "vendor/QN908XC_features.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name ARM Cortex-M specific CPU configuration
* @{
*/
#define CPU_DEFAULT_IRQ_PRIO (1U)
/**
* NUMBER_OF_INT_VECTORS in the QN908XC.h is defined as including the standard
* ARM interrupt vectors and headers, however CPU_IRQ_NUMOF does not include
* the first 15 interrupt values and the stack pointer.
*/
#define CPU_IRQ_NUMOF (NUMBER_OF_INT_VECTORS - 16)
/**
* The flash is aliased at several addresses in the memory range. In particular,
* address 0 can be mapped to RAM or flash, so it is possible to run from
* address 0 from flash, or even turn off the flash altogether and run from RAM
* to save power. This setting uses the ROM_START_ADDR value set in the
* Makefile.
*/
#define CPU_FLASH_BASE (QN908X_ROM_START_ADDR)
/**
* @brief Bit-Band configuration
*/
#define CPU_HAS_BITBAND 1
/** @} */
/**
* @name Clocks configuration
* @{
* @brief External and internal clocks configuration.
*
* The QN908x has an internal 32 MHz RCO for the high frequency clock source and
* a 32 KHz RCO for the low frequency clock source, as well as external
* connections for a crystal oscillator (XTAL) of either 16 MHz or 32 MHz for
* the high frequency clock source and another connection for a 32.768 KHz XTAL
* for the low frequency clock normally used for accurate Bluetooth timing.
* Note that the "32 KHz" clock source is not exactly the same frequency whether
* you use the internal or external one.
*/
/**
* @brief Whether the board has a 32.768 KHz crystal in XTAL32_IN / XTAL32_OUT.
**/
#if !defined(CONFIG_BOARD_HAS_XTAL32K) || DOXYGEN
#define CONFIG_BOARD_HAS_XTAL32K 0
#endif
/**
* @name 32K low frequency clock selector
* @{
*/
#ifdef DOXYGEN
/**
* @brief Enabled when the 32K low frequency uses the external crystal.
**/
#define CONFIG_CPU_CLK_32K_XTAL
/**
* @brief Enabled when the 32K low frequency uses the internal oscillator.
**/
#define CONFIG_CPU_CLK_32K_RCO
#endif /* def DOXYGEN */
/** @} */
/* Default 32K clock selector config. */
#if !defined(CONFIG_CPU_CLK_32K_XTAL) && !defined(CONFIG_CPU_CLK_32K_RCO)
#if CONFIG_BOARD_HAS_XTAL32K
#define CONFIG_CPU_CLK_32K_XTAL 1
#else
#define CONFIG_CPU_CLK_32K_RCO 1
#endif
#endif
/**
* @brief Whether the board has a 16 or 32 MHz crystal in XTAL_IN / XTAL_OUT.
* @{
**/
#ifndef CONFIG_BOARD_HAS_XTAL
#define CONFIG_BOARD_HAS_XTAL 0
#endif
/**
* @name External high frequency "XTAL" crystal frequency
*/
#ifdef DOXYGEN
/**
* @brief Enabled when the external XTAL is a 16 MHz one.
**/
#define CONFIG_CPU_CLK_XTAL_16M
/**
* @brief Enabled when the external XTAL is a 32 MHz one.
**/
#define CONFIG_CPU_CLK_XTAL_32M
#endif /* def DOXYGEN */
/** @} */
/* Default XTAL setting. */
#if CONFIG_BOARD_HAS_XTAL && \
!defined(CONFIG_BOARD_HAS_XTAL_16M) && !defined(CONFIG_BOARD_HAS_XTAL_32M)
#define CONFIG_BOARD_HAS_XTAL_32M 1
#endif
/**
* @brief Internal OSC32M clock input /2 divider enabled
**/
#ifndef CONFIG_CPU_CLK_OSC32M_DIV
#define CONFIG_CPU_CLK_OSC32M_DIV 0
#endif
/**
* @brief External XTAL 32 MHz clock input /2 divider enabled
**/
#ifndef CONFIG_CPU_CLK_XTAL_DIV
#define CONFIG_CPU_CLK_XTAL_DIV 0
#endif
/**
* @name System clock configuration selector
* @{
*/
#ifdef DOXYGEN
/**
* @brief System clock is external crystal source (including divider).
**/
#define CONFIG_CPU_CLK_SYS_XTAL
/**
* @brief System clock is internal 32 MHz oscillator source (including divider).
**/
#define CONFIG_CPU_CLK_SYS_OSC32M
/**
* @brief System clock is the low frequency clock (32 or 32.768 KHz)
**/
#define CONFIG_CPU_CLK_SYS_32K
#endif /* def DOXYGEN */
/** @} */
/* Default system clock configuration selector */
#if !defined(CONFIG_CPU_CLK_SYS_XTAL) && !defined(CONFIG_CPU_CLK_SYS_OSC32M) && \
!defined(CONFIG_CPU_CLK_SYS_32K)
#if CONFIG_BOARD_HAS_XTAL
#define CONFIG_CPU_CLK_SYS_XTAL 1
#else
#define CONFIG_CPU_CLK_SYS_OSC32M 1
#endif
#endif
/**
* @brief AHB clock divider
*
* The AHB clock is derived from the System clock using this divider value,
* between 1 and 8192, and serves as a clock source for ARM core, FSP, SCT,
* Quad-SPI, Flexcomm (UART, SPI, I2C), GPIO, BLE_AHB and DMA.
* Note: When BLE is enabled, the AHB clock must be at least the BLE clock
* (either 8 or 16 MHz) limiting the range of allowed values for this
* divider so that the AHB clock is 8, 16 or 32 MHz.
**/
#ifndef CONFIG_CPU_CLK_AHB_DIV
#define CONFIG_CPU_CLK_AHB_DIV 1u
#endif
/**
* @brief APB clock divider
*
* The APB clock is derived from the AHB clock using this divide value,
* between 1 and 16, and serves as the clock source for several
* peripherals, such as the RTC, ADC, DAC, Capacitive Sense (CS) and
* optionally the WDT.
**/
#ifndef CONFIG_CPU_CLK_APB_DIV
#define CONFIG_CPU_CLK_APB_DIV 1u
#endif
/** @} */
/**
* @name Code Read Protection
* @{
* @brief Image "Code Read Protection" field definitions.
*
* The Code Read Protection (CRP) is a 32-bit field stored in one of the
* reserved fields in the Cortex-M interrupt vector and therefore part of the
* image. It allows to enable or disable access to the flash from the In-System
* Programming (ISP) interface to read, erase or write flash pages, as well as
* external SWD access for debugging or programming the flash. Not all the CRP
* values are valid and an invalid value may render the flash inaccessible and
* effectively brick the device.
*
* To select the access level define the @ref QN908X_CRP macro from the global
* compile options, otherwise the default value in this module will be used
* (allowing everything). The value of the uint32_t CRP field in the Image
* vector table should be the "or" of the following QN908X_CRP_* macros. Every
* field must be either enabled or disabled, otherwise it would result in an
* invalid CRP value.
*/
/**
* @brief Number of pages to protect (0 to 255).
*
* This defines the number of pages to protect starting from 0. A value of 0
* in this macro means that no page is protected. The maximum number allowed to
* be passed to this macro is 255, however there are 256 pages in the flash. The
* last page is protected if any other page is protected.
*
* Protected pages can't be erased or written to by the ISP.
*/
#define QN908X_CRP_PROTECT_PAGES(X) (255 - (X))
/**
* @brief Mass erase from ISP allowed.
*/
#define QN908X_CRP_MASS_ERASE_ALLOW (0x800)
/**
* @brief Mass erase from ISP not allowed.
*/
#define QN908X_CRP_MASS_ERASE_DISALLOW (0x400)
/**
* @brief Page erase/write from ISP (for unprotected pages) allowed.
*/
#define QN908X_CRP_PAGE_ERASE_WRITE_ALLOW (0x2000)
/**
* @brief Page erase/write from ISP (for unprotected pages) not allowed.
*/
#define QN908X_CRP_PAGE_ERASE_WRITE_DISALLOW (0x1000)
/**
* @brief Flash read (for unprotected pages) from ISP allowed or not.
*/
#define QN908X_CRP_FLASH_READ_ALLOW (0x8000)
/**
* @brief Flash read (for unprotected pages) from ISP not allowed.
*/
#define QN908X_CRP_FLASH_READ_DISALLOW (0x4000)
/**
* @brief ISP entry is allowed (via CHIP_MODE pin).
*/
#define QN908X_CRP_ISP_ENTRY_ALLOW (0x20000)
/**
* @brief ISP entry via CHIP_MODE pin is not allowed.
*/
#define QN908X_CRP_ISP_ENTRY_DISALLOW (0x10000)
/**
* @brief External access is allowed (including SWD interface).
*/
#define QN908X_CRP_EXTERNAL_ACCESS_ALLOW (0x80000)
/**
* @brief External access is not allowed (including SWD interface).
*/
#define QN908X_CRP_EXTERNAL_ACCESS_DISALLOW (0x40000)
/** @} */
/**
* @brief Default "Code Read Protection" allows everything.
*/
#ifndef QN908X_CRP
#define QN908X_CRP \
(QN908X_CRP_PROTECT_PAGES(0) \
| QN908X_CRP_MASS_ERASE_ALLOW \
| QN908X_CRP_PAGE_ERASE_WRITE_ALLOW \
| QN908X_CRP_FLASH_READ_ALLOW \
| QN908X_CRP_ISP_ENTRY_ALLOW \
| QN908X_CRP_EXTERNAL_ACCESS_ALLOW)
#endif /* QN908X_CRP */
/**
* @brief The "Code Read Protection" is stored at the offset 0x20.
*
* To modify the CRP field define the macro @ref QN908X_CRP.
*/
#define CORTEXM_VECTOR_RESERVED_0X20 QN908X_CRP
/* Safety checks that the QN908X_CRP value is valid. */
#if !(QN908X_CRP & QN908X_CRP_MASS_ERASE_ALLOW) == \
!(QN908X_CRP & QN908X_CRP_MASS_ERASE_DISALLOW)
#error "Must select exactly one of QN908X_CRP_MASS_ERASE_* in the QN908X_CRP"
#endif
#if !(QN908X_CRP & QN908X_CRP_PAGE_ERASE_WRITE_ALLOW) == \
!(QN908X_CRP & QN908X_CRP_PAGE_ERASE_WRITE_DISALLOW)
#error \
"Must select exactly one of QN908X_CRP_PAGE_ERASE_WRITE_* in the QN908X_CRP"
#endif
#if !(QN908X_CRP & QN908X_CRP_FLASH_READ_ALLOW) == \
!(QN908X_CRP & QN908X_CRP_FLASH_READ_DISALLOW)
#error "Must select exactly one of QN908X_CRP_FLASH_READ_* in the QN908X_CRP"
#endif
#if !(QN908X_CRP & QN908X_CRP_ISP_ENTRY_ALLOW) == \
!(QN908X_CRP & QN908X_CRP_ISP_ENTRY_DISALLOW)
#error "Must select exactly one of QN908X_CRP_ISP_ENTRY_* in the QN908X_CRP"
#endif
#if !(QN908X_CRP & QN908X_CRP_EXTERNAL_ACCESS_ALLOW) == \
!(QN908X_CRP & QN908X_CRP_EXTERNAL_ACCESS_DISALLOW)
#error \
"Must select exactly one of QN908X_CRP_EXTERNAL_ACCESS_* in the QN908X_CRP"
#endif
#ifdef __cplusplus
}
#endif
#endif /* CPU_CONF_H */
/** @} */

View File

@ -0,0 +1,71 @@
/*
* 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 Common Pin MUX functions.
*
* The pins in this CPU are multiplexed to several different function. This
* module allows to configure the pin multiplexer (MUX) from peripheral drivers.
*
* @author iosabi <iosabi@protonmail.com>
*/
#ifndef GPIO_MUX_H
#define GPIO_MUX_H
#include <stdint.h>
#include "periph_cpu.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Obtain the GPIO_BASE address from a GPIO_PIN(x, y) value.
*/
#define GPIO_T_ADDR_BASE(pin) (GPIOA_BASE + ((pin) & 0xf000u))
/**
* @brief Obtain the GPIO_BASE GPIO_Type* pointer from a GPIO_PIN(x, y) value.
*/
#define GPIO_T_ADDR(pin) ((GPIO_Type *)(GPIO_T_ADDR_BASE(pin)))
/**
* @brief Obtain the "x" port number (0 based) from a GPIO_PIN(x, y) value.
*
* This macro needs to be kept in sync with the definition of GPIO_PIN.
*/
#define GPIO_T_PORT(pin) ((gpio_t)(pin) >> 12u)
/**
* @brief Obtain the pin number "y" from a GPIO_PIN(x, y) value.
*/
#define GPIO_T_PIN(pin) ((pin) & 0x00ffu)
#if defined(GPIOB_BASE) && (GPIO_T_ADDR_BASE(GPIO_PIN(1, 1)) != GPIOB_BASE)
#error "GPIO_T_ADDR(GPIO_PIN(1, x)) must be the GPIOB address"
#endif
/**
* @brief Configure the pin mux to the given function.
*
* The meaning of the function value will depend on the gpio pin.
*/
void gpio_init_mux(gpio_t pin, uint32_t func);
#ifdef __cplusplus
}
#endif
#endif /* GPIO_MUX_H */
/** @} */

View File

@ -0,0 +1,148 @@
/*
* 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 CPU specific definitions for internal peripheral handling
*
* @author iosabi <iosabi@protonmail.com>
*/
#ifndef PERIPH_CPU_H
#define PERIPH_CPU_H
#include <stdint.h>
#include <stdbool.h>
#include "cpu.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name CPU specific gpio_t type definition
* @{
*/
#define HAVE_GPIO_T
typedef uint16_t gpio_t;
/** @} */
/**
* @brief Definition of a fitting UNDEF value
*/
#define GPIO_UNDEF (0xffff)
/**
* @brief Define a CPU specific GPIO pin generator macro.
*
* This generates the GPIO port base address with a mask of the GPIO_PIN value
* to avoid a memory access. The value 12 here is selected as an optimization
* to be able to derive the GPIO port address with a simple mask of the GPIO_PIN
* value.
*/
#define GPIO_PIN(x, y) (((x) << 12u) | (y))
/* QN908x has a unique default Bluetooth address in the Flash Information Page
* descriptor. This value is set in the factory and cannot be modified by
* users. However, the actual Bluetooth address used by the stack may be
* different, this is just the default. */
/**
* @brief Starting offset of CPU_ID
*/
#define CPUID_ADDR (FSL_FEATURE_FLASH_ADDR_OF_VENDOR_BD_ADDR)
/**
* @brief Length of the CPU_ID in octets
*/
#define CPUID_LEN (6U)
/**
* @brief Watchdog clock can be stopped independently of other clocks.
*/
#define WDT_HAS_STOP (1)
/**
* @name WDT upper and lower bound times in ms
* @{
*/
/** The WDT clock can run up to 16MHz (via CLK_APB) and the WDT counter is
* 32-bit so the maximum value in ms we can wait is ((1 << 32) - 1) / 16000.
* TODO: A much larger limit (~1.5 days) can be set if the WDT runs from the
* 32 KHz clock. However, this is likely decided by the board and depends on the
* clocks installed on the board. Figure out a way to configure this limit based
* on the clock used.
*/
#define NWDT_TIME_LOWER_LIMIT (0)
#define NWDT_TIME_UPPER_LIMIT (268435U)
#define WWDT_TIME_LOWER_LIMIT (0)
#define WWDT_TIME_UPPER_LIMIT (268435U)
/** @} */
/**
* @brief Generate GPIO mode bitfields
*
* The GPIO_MODE has the following structure:
* - bit 0: open-drain: 1 for enabled (open-drain mode) and 0 for disabled.
* - bit 1: output-enabled: 1 output mode, 0 input mode.
* - bit 4-5: pull_mode: 0 for hi-z (no pull-up or down), 1 for pull-down and 2
* for pull-up. These correspond to the IOCON_MODE macros.
*/
#define GPIO_MODE(open_drain, out_enabled, pull_mode) \
((open_drain) | ((out_enabled) << 1) | ((pull_mode) << 4))
#ifndef DOXYGEN
/**
* @name GPIO pin modes
* @{
*/
#define HAVE_GPIO_MODE_T
typedef enum {
GPIO_IN = GPIO_MODE(0, 0, 0), /**< IN */
GPIO_IN_PD = GPIO_MODE(0, 0, 1), /**< IN with pull-down */
GPIO_IN_PU = GPIO_MODE(0, 0, 2), /**< IN with pull-up */
GPIO_OUT = GPIO_MODE(0, 1, 0), /**< OUT (push-pull) */
GPIO_OD = GPIO_MODE(1, 1, 0), /**< OD */
GPIO_OD_PU = GPIO_MODE(1, 1, 2), /**< OD with pull-up */
} gpio_mode_t;
/** @} */
#endif /* ndef DOXYGEN */
#ifndef DOXYGEN
/**
* @name GPIO flank configuration values
* @{
*/
#define HAVE_GPIO_FLANK_T
typedef enum {
GPIO_LOW = 0, /**< emit interrupt when the value is low */
GPIO_HIGH = 1, /**< emit interrupt when the value is high */
GPIO_RISING = 2, /**< emit interrupt on rising flank */
GPIO_FALLING = 3, /**< emit interrupt on falling flank */
} gpio_flank_t;
/** @} */
#endif /* ndef DOXYGEN */
/**
* @brief Available ports on the QN908x.
*/
enum {
PORT_A = 0, /**< port A */
PORT_B = 1, /**< port B */
GPIO_PORTS_NUMOF /**< overall number of available ports */
};
#ifdef __cplusplus
}
#endif
#endif /* PERIPH_CPU_H */
/** @} */

View File

@ -0,0 +1,118 @@
/*
* 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 Interrupt service routine declarations NXP QN908x MCUs
*
* @author iosabi <iosabi@protonmail.com>
*
* @}
*/
#ifndef VECTORS_QN908X_H
#define VECTORS_QN908X_H
#include <stdint.h>
#include "vectors_cortexm.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Dummy handler
*/
void dummy_handler(void);
/* Device specific interrupt vectors */
void isr_ext_gpio_wakeup(void); /**< Ext GPIO wakeup */
void isr_osc(void); /**< BLE wakeup */
void isr_acmp0(void); /**< Analog comparator0 */
void isr_acmp1(void); /**< Analog comparator1 */
void isr_rtc_sec(void); /**< RTC second */
void isr_rtc_fr(void); /**< RTC free running */
void isr_cs_wakeup(void); /**< Capacitive sense wakeup */
void isr_cs(void); /**< Capacitive sense */
void isr_gpioa(void); /**< GPIO group A */
void isr_gpiob(void); /**< GPIO group B */
void isr_dma0(void); /**< DMA controller */
void isr_pin_int0(void); /**< pin or pattern match engine slice 0 */
void isr_pin_int1(void); /**< pin or pattern match engine slice 1 */
void isr_pin_int2(void); /**< pin or pattern match engine slice 2 */
void isr_pin_int3(void); /**< pin or pattern match engine slice 3 */
void isr_osc_int_low(void); /**< Inverse of OSC */
void isr_usb0(void); /**< USB device */
void isr_flexcomm0(void); /**< Flexcomm Interface 0 (USART) */
void isr_flexcomm1(void); /**< Flexcomm Interface 1 (USART, I2C) */
void isr_flexcomm2(void); /**< Flexcomm Interface 2 (SPI, I2C) */
void isr_flexcomm3(void); /**< Flexcomm Interface 3 (SPI) */
void isr_ble(void); /**< BLE interrupts */
void isr_fsp(void); /**< FSP */
void isr_qdec0(void); /**< QDEC0 */
void isr_qdec1(void); /**< QDEC1 */
void isr_ctimer0(void); /**< Standard counter/timer CTIMER0 */
void isr_ctimer1(void); /**< Standard counter/timer CTIMER1 */
void isr_ctimer2(void); /**< Standard counter/timer CTIMER2 */
void isr_ctimer3(void); /**< Standard counter/timer CTIMER3 */
void isr_wdt(void); /**< Watch dog timer */
void isr_adc(void); /**< ADC */
void isr_dac(void); /**< DAC */
void isr_xtal_ready(void); /**< High frequency crystal ready */
void isr_flash(void); /**< Flash */
void isr_spifi0(void); /**< SPI flash interface */
void isr_sct0(void); /**< SCTimer/PWM */
void isr_rng(void); /**< Random number generator */
void isr_calib(void); /**< Calibration */
void isr_ble_tx(void); /**< ble tx flag */
void isr_ble_rx(void); /**< ble rx flag */
void isr_ble_freq_hop(void); /**< ble frequency hop */
void isr_bod(void); /**< Brown out detect */
/**
* @{
* @brief In-System Programming configuration field
*
* After the interrupt vectors, at address 0x110 there's a ISP
* (In-System Programming) configuration field. Define isp_configuration to
* any | combination of the following `QN908X_ISP_*` values to change the ISP
* allowed options.
*/
__attribute__((section(".vectors.100")))
extern const uint32_t isp_configuration;
/**
* @brief SMART write enabled to ISP
*/
#define QN908X_ISP_SMART_EN 0x80
/**
* @brief SMART USB disabled to ISP
*/
#define QN908X_ISP_USB_DIS 0x20
/**
* @brief SMART UART disabled to ISP
*/
#define QN908X_ISP_UART_DIS 0x08
/**
* @brief SMART SPI disabled to ISP
*/
#define QN908X_ISP_SPI_DIS 0x02
/** @} */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* VECTORS_QN908X_H */

9491
cpu/qn908x/include/vendor/QN908XC.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,613 @@
/*
** ###################################################################
** Version: rev. 1.0, 2017-03-27
** Build: b170421
**
** Abstract:
** Chip specific module features.
**
** Copyright 2016 Freescale Semiconductor, Inc.
** Copyright 2016-2017 NXP
** All rights reserved.
**
** SPDX-License-Identifier: BSD-3-Clause
**
** http: www.nxp.com
** mail: support@nxp.com
**
** Revisions:
** - rev. 1.0 (2017-03-27)
** Initial version.
**
** ###################################################################
*/
#ifndef _QN908XC_FEATURES_H_
#define _QN908XC_FEATURES_H_
#ifdef __cplusplus
extern "C" {
#endif
/* SOC module features */
/* @brief ACMP availability on the SoC. */
#define FSL_FEATURE_SOC_ACMP_COUNT (2)
/* @brief ADC availability on the SoC. */
#define FSL_FEATURE_SOC_ADC_COUNT (1)
/* @brief ADC12 availability on the SoC. */
#define FSL_FEATURE_SOC_ADC12_COUNT (0)
/* @brief ADC16 availability on the SoC. */
#define FSL_FEATURE_SOC_ADC16_COUNT (0)
/* @brief ADC_5HC availability on the SoC. */
#define FSL_FEATURE_SOC_ADC_5HC_COUNT (0)
/* @brief AES availability on the SoC. */
#define FSL_FEATURE_SOC_AES_COUNT (0)
/* @brief HW AES availability on the SoC. */
#define FSL_FEATURE_SOC_AES_HW (1)
/* @brief AFE availability on the SoC. */
#define FSL_FEATURE_SOC_AFE_COUNT (0)
/* @brief AGC availability on the SoC. */
#define FSL_FEATURE_SOC_AGC_COUNT (1)
/* @brief AIPS availability on the SoC. */
#define FSL_FEATURE_SOC_AIPS_COUNT (0)
/* @brief AIPSTZ availability on the SoC. */
#define FSL_FEATURE_SOC_AIPSTZ_COUNT (0)
/* @brief ANATOP availability on the SoC. */
#define FSL_FEATURE_SOC_ANATOP_COUNT (0)
/* @brief AOI availability on the SoC. */
#define FSL_FEATURE_SOC_AOI_COUNT (0)
/* @brief APBH availability on the SoC. */
#define FSL_FEATURE_SOC_APBH_COUNT (0)
/* @brief ASMC availability on the SoC. */
#define FSL_FEATURE_SOC_ASMC_COUNT (0)
/* @brief ASRC availability on the SoC. */
#define FSL_FEATURE_SOC_ASRC_COUNT (0)
/* @brief ASYNC_SYSCON availability on the SoC. */
#define FSL_FEATURE_SOC_ASYNC_SYSCON_COUNT (0)
/* @brief ATX availability on the SoC. */
#define FSL_FEATURE_SOC_ATX_COUNT (0)
/* @brief AXBS availability on the SoC. */
#define FSL_FEATURE_SOC_AXBS_COUNT (0)
/* @brief BCH availability on the SoC. */
#define FSL_FEATURE_SOC_BCH_COUNT (0)
/* @brief BLEDP availability on the SoC. */
#define FSL_FEATURE_SOC_BLEDP_COUNT (1)
/* @brief BOD availability on the SoC. */
#define FSL_FEATURE_SOC_BOD_COUNT (1)
/* @brief CAAM availability on the SoC. */
#define FSL_FEATURE_SOC_CAAM_COUNT (0)
/* @brief CADC availability on the SoC. */
#define FSL_FEATURE_SOC_CADC_COUNT (0)
/* @brief CALIB availability on the SoC. */
#define FSL_FEATURE_SOC_CALIB_COUNT (1)
/* @brief CAN availability on the SoC. */
#define FSL_FEATURE_SOC_CAN_COUNT (0)
/* @brief CAU availability on the SoC. */
#define FSL_FEATURE_SOC_CAU_COUNT (0)
/* @brief CAU3 availability on the SoC. */
#define FSL_FEATURE_SOC_CAU3_COUNT (0)
/* @brief CCM availability on the SoC. */
#define FSL_FEATURE_SOC_CCM_COUNT (0)
/* @brief CCM_ANALOG availability on the SoC. */
#define FSL_FEATURE_SOC_CCM_ANALOG_COUNT (0)
/* @brief CHRG availability on the SoC. */
#define FSL_FEATURE_SOC_CHRG_COUNT (0)
/* @brief CMP availability on the SoC. */
#define FSL_FEATURE_SOC_CMP_COUNT (0)
/* @brief CMT availability on the SoC. */
#define FSL_FEATURE_SOC_CMT_COUNT (0)
/* @brief CNC availability on the SoC. */
#define FSL_FEATURE_SOC_CNC_COUNT (0)
/* @brief COP availability on the SoC. */
#define FSL_FEATURE_SOC_COP_COUNT (0)
/* @brief CRC availability on the SoC. */
#define FSL_FEATURE_SOC_CRC_COUNT (1)
/* @brief CS availability on the SoC. */
#define FSL_FEATURE_SOC_CS_COUNT (1)
/* @brief CSI availability on the SoC. */
#define FSL_FEATURE_SOC_CSI_COUNT (0)
/* @brief CT32B availability on the SoC. */
#define FSL_FEATURE_SOC_CT32B_COUNT (0)
/* @brief CTI availability on the SoC. */
#define FSL_FEATURE_SOC_CTI_COUNT (0)
/* @brief CTIMER availability on the SoC. */
#define FSL_FEATURE_SOC_CTIMER_COUNT (4)
/* @brief DAC availability on the SoC. */
#define FSL_FEATURE_SOC_DAC_COUNT (1)
/* @brief DAC32 availability on the SoC. */
#define FSL_FEATURE_SOC_DAC32_COUNT (0)
/* @brief DCDC availability on the SoC. */
#define FSL_FEATURE_SOC_DCDC_COUNT (0)
/* @brief DCP availability on the SoC. */
#define FSL_FEATURE_SOC_DCP_COUNT (0)
/* @brief DDR availability on the SoC. */
#define FSL_FEATURE_SOC_DDR_COUNT (0)
/* @brief DDRC availability on the SoC. */
#define FSL_FEATURE_SOC_DDRC_COUNT (0)
/* @brief DDRC_MP availability on the SoC. */
#define FSL_FEATURE_SOC_DDRC_MP_COUNT (0)
/* @brief DDR_PHY availability on the SoC. */
#define FSL_FEATURE_SOC_DDR_PHY_COUNT (0)
/* @brief DMA availability on the SoC. */
#define FSL_FEATURE_SOC_DMA_COUNT (1)
/* @brief DMAMUX availability on the SoC. */
#define FSL_FEATURE_SOC_DMAMUX_COUNT (1)
/* @brief DMIC availability on the SoC. */
#define FSL_FEATURE_SOC_DMIC_COUNT (0)
/* @brief DRY availability on the SoC. */
#define FSL_FEATURE_SOC_DRY_COUNT (0)
/* @brief DSPI availability on the SoC. */
#define FSL_FEATURE_SOC_DSPI_COUNT (0)
/* @brief ECSPI availability on the SoC. */
#define FSL_FEATURE_SOC_ECSPI_COUNT (0)
/* @brief EDMA availability on the SoC. */
#define FSL_FEATURE_SOC_EDMA_COUNT (0)
/* @brief EEPROM availability on the SoC. */
#define FSL_FEATURE_SOC_EEPROM_COUNT (0)
/* @brief EIM availability on the SoC. */
#define FSL_FEATURE_SOC_EIM_COUNT (0)
/* @brief EMC availability on the SoC. */
#define FSL_FEATURE_SOC_EMC_COUNT (0)
/* @brief EMVSIM availability on the SoC. */
#define FSL_FEATURE_SOC_EMVSIM_COUNT (0)
/* @brief ENC availability on the SoC. */
#define FSL_FEATURE_SOC_ENC_COUNT (0)
/* @brief ENET availability on the SoC. */
#define FSL_FEATURE_SOC_ENET_COUNT (0)
/* @brief EPDC availability on the SoC. */
#define FSL_FEATURE_SOC_EPDC_COUNT (0)
/* @brief EPIT availability on the SoC. */
#define FSL_FEATURE_SOC_EPIT_COUNT (0)
/* @brief ESAI availability on the SoC. */
#define FSL_FEATURE_SOC_ESAI_COUNT (0)
/* @brief EWM availability on the SoC. */
#define FSL_FEATURE_SOC_EWM_COUNT (0)
/* @brief FB availability on the SoC. */
#define FSL_FEATURE_SOC_FB_COUNT (0)
/* @brief FGPIO availability on the SoC. */
#define FSL_FEATURE_SOC_FGPIO_COUNT (0)
/* @brief FLASH availability on the SoC. */
#define FSL_FEATURE_SOC_FLASH_COUNT (1)
/* @brief FLEXCAN availability on the SoC. */
#define FSL_FEATURE_SOC_FLEXCAN_COUNT (0)
/* @brief FLEXCOMM availability on the SoC. */
#define FSL_FEATURE_SOC_FLEXCOMM_COUNT (4)
/* @brief FLEXIO availability on the SoC. */
#define FSL_FEATURE_SOC_FLEXIO_COUNT (0)
/* @brief FLEXRAM availability on the SoC. */
#define FSL_FEATURE_SOC_FLEXRAM_COUNT (0)
/* @brief FLEXSPI availability on the SoC. */
#define FSL_FEATURE_SOC_FLEXSPI_COUNT (0)
/* @brief FMC availability on the SoC. */
#define FSL_FEATURE_SOC_FMC_COUNT (0)
/* @brief FSKDT availability on the SoC. */
#define FSL_FEATURE_SOC_FSKDT_COUNT (0)
/* @brief FSP availability on the SoC. */
#define FSL_FEATURE_SOC_FSP_COUNT (1)
/* @brief FTFA availability on the SoC. */
#define FSL_FEATURE_SOC_FTFA_COUNT (0)
/* @brief FTFE availability on the SoC. */
#define FSL_FEATURE_SOC_FTFE_COUNT (0)
/* @brief FTFL availability on the SoC. */
#define FSL_FEATURE_SOC_FTFL_COUNT (0)
/* @brief FTM availability on the SoC. */
#define FSL_FEATURE_SOC_FTM_COUNT (0)
/* @brief FTMRA availability on the SoC. */
#define FSL_FEATURE_SOC_FTMRA_COUNT (0)
/* @brief FTMRE availability on the SoC. */
#define FSL_FEATURE_SOC_FTMRE_COUNT (0)
/* @brief FTMRH availability on the SoC. */
#define FSL_FEATURE_SOC_FTMRH_COUNT (0)
/* @brief GINT availability on the SoC. */
#define FSL_FEATURE_SOC_GINT_COUNT (0)
/* @brief GPC availability on the SoC. */
#define FSL_FEATURE_SOC_GPC_COUNT (0)
/* @brief GPC_PGC availability on the SoC. */
#define FSL_FEATURE_SOC_GPC_PGC_COUNT (0)
/* @brief GPIO availability on the SoC. */
#define FSL_FEATURE_SOC_GPIO_COUNT (2)
/* @brief GPMI availability on the SoC. */
#define FSL_FEATURE_SOC_GPMI_COUNT (0)
/* @brief GPT availability on the SoC. */
#define FSL_FEATURE_SOC_GPT_COUNT (0)
/* @brief HSADC availability on the SoC. */
#define FSL_FEATURE_SOC_HSADC_COUNT (0)
/* @brief I2C availability on the SoC. */
#define FSL_FEATURE_SOC_I2C_COUNT (2)
/* @brief I2S availability on the SoC. */
#define FSL_FEATURE_SOC_I2S_COUNT (0)
/* @brief ICS availability on the SoC. */
#define FSL_FEATURE_SOC_ICS_COUNT (0)
/* @brief IEE availability on the SoC. */
#define FSL_FEATURE_SOC_IEE_COUNT (0)
/* @brief IEER availability on the SoC. */
#define FSL_FEATURE_SOC_IEER_COUNT (0)
/* @brief IGPIO availability on the SoC. */
#define FSL_FEATURE_SOC_IGPIO_COUNT (0)
/* @brief II2C availability on the SoC. */
#define FSL_FEATURE_SOC_II2C_COUNT (0)
/* @brief INPUTMUX availability on the SoC. */
#define FSL_FEATURE_SOC_INPUTMUX_COUNT (0)
/* @brief INTMUX availability on the SoC. */
#define FSL_FEATURE_SOC_INTMUX_COUNT (0)
/* @brief IOCON availability on the SoC. */
#define FSL_FEATURE_SOC_IOCON_COUNT (0)
/* @brief IOMUXC availability on the SoC. */
#define FSL_FEATURE_SOC_IOMUXC_COUNT (0)
/* @brief IOMUXC_GPR availability on the SoC. */
#define FSL_FEATURE_SOC_IOMUXC_GPR_COUNT (0)
/* @brief IOMUXC_LPSR availability on the SoC. */
#define FSL_FEATURE_SOC_IOMUXC_LPSR_COUNT (0)
/* @brief IOMUXC_LPSR_GPR availability on the SoC. */
#define FSL_FEATURE_SOC_IOMUXC_LPSR_GPR_COUNT (0)
/* @brief IOMUXC_SNVS availability on the SoC. */
#define FSL_FEATURE_SOC_IOMUXC_SNVS_COUNT (0)
/* @brief IPWM availability on the SoC. */
#define FSL_FEATURE_SOC_IPWM_COUNT (0)
/* @brief IRQ availability on the SoC. */
#define FSL_FEATURE_SOC_IRQ_COUNT (0)
/* @brief IUART availability on the SoC. */
#define FSL_FEATURE_SOC_IUART_COUNT (0)
/* @brief KBI availability on the SoC. */
#define FSL_FEATURE_SOC_KBI_COUNT (0)
/* @brief KPP availability on the SoC. */
#define FSL_FEATURE_SOC_KPP_COUNT (0)
/* @brief L2CACHEC availability on the SoC. */
#define FSL_FEATURE_SOC_L2CACHEC_COUNT (0)
/* @brief LCD availability on the SoC. */
#define FSL_FEATURE_SOC_LCD_COUNT (0)
/* @brief LCDC availability on the SoC. */
#define FSL_FEATURE_SOC_LCDC_COUNT (0)
/* @brief LCDIF availability on the SoC. */
#define FSL_FEATURE_SOC_LCDIF_COUNT (0)
/* @brief LDO availability on the SoC. */
#define FSL_FEATURE_SOC_LDO_COUNT (0)
/* @brief LLWU availability on the SoC. */
#define FSL_FEATURE_SOC_LLWU_COUNT (0)
/* @brief LMEM availability on the SoC. */
#define FSL_FEATURE_SOC_LMEM_COUNT (0)
/* @brief LPADC availability on the SoC. */
#define FSL_FEATURE_SOC_LPADC_COUNT (0)
/* @brief LPCMP availability on the SoC. */
#define FSL_FEATURE_SOC_LPCMP_COUNT (0)
/* @brief LPDAC availability on the SoC. */
#define FSL_FEATURE_SOC_LPDAC_COUNT (0)
/* @brief LPI2C availability on the SoC. */
#define FSL_FEATURE_SOC_LPI2C_COUNT (0)
/* @brief LPIT availability on the SoC. */
#define FSL_FEATURE_SOC_LPIT_COUNT (0)
/* @brief LPSCI availability on the SoC. */
#define FSL_FEATURE_SOC_LPSCI_COUNT (0)
/* @brief LPSPI availability on the SoC. */
#define FSL_FEATURE_SOC_LPSPI_COUNT (0)
/* @brief LPTMR availability on the SoC. */
#define FSL_FEATURE_SOC_LPTMR_COUNT (0)
/* @brief LPTPM availability on the SoC. */
#define FSL_FEATURE_SOC_LPTPM_COUNT (0)
/* @brief LPUART availability on the SoC. */
#define FSL_FEATURE_SOC_LPUART_COUNT (0)
/* @brief LTC availability on the SoC. */
#define FSL_FEATURE_SOC_LTC_COUNT (0)
/* @brief MAILBOX availability on the SoC. */
#define FSL_FEATURE_SOC_MAILBOX_COUNT (0)
/* @brief MC availability on the SoC. */
#define FSL_FEATURE_SOC_MC_COUNT (0)
/* @brief MCG availability on the SoC. */
#define FSL_FEATURE_SOC_MCG_COUNT (0)
/* @brief MCGLITE availability on the SoC. */
#define FSL_FEATURE_SOC_MCGLITE_COUNT (0)
/* @brief MCM availability on the SoC. */
#define FSL_FEATURE_SOC_MCM_COUNT (0)
/* @brief MIPI_CSI2 availability on the SoC. */
#define FSL_FEATURE_SOC_MIPI_CSI2_COUNT (0)
/* @brief MIPI_DSI availability on the SoC. */
#define FSL_FEATURE_SOC_MIPI_DSI_COUNT (0)
/* @brief MIPI_DSI_HOST availability on the SoC. */
#define FSL_FEATURE_SOC_MIPI_DSI_HOST_COUNT (0)
/* @brief MMAU availability on the SoC. */
#define FSL_FEATURE_SOC_MMAU_COUNT (0)
/* @brief MMCAU availability on the SoC. */
#define FSL_FEATURE_SOC_MMCAU_COUNT (0)
/* @brief MMDC availability on the SoC. */
#define FSL_FEATURE_SOC_MMDC_COUNT (0)
/* @brief MMDVSQ availability on the SoC. */
#define FSL_FEATURE_SOC_MMDVSQ_COUNT (0)
/* @brief MPU availability on the SoC. */
#define FSL_FEATURE_SOC_MPU_COUNT (0)
/* @brief MRT availability on the SoC. */
#define FSL_FEATURE_SOC_MRT_COUNT (0)
/* @brief MSCAN availability on the SoC. */
#define FSL_FEATURE_SOC_MSCAN_COUNT (0)
/* @brief MSCM availability on the SoC. */
#define FSL_FEATURE_SOC_MSCM_COUNT (0)
/* @brief MTB availability on the SoC. */
#define FSL_FEATURE_SOC_MTB_COUNT (0)
/* @brief MTBDWT availability on the SoC. */
#define FSL_FEATURE_SOC_MTBDWT_COUNT (0)
/* @brief MU availability on the SoC. */
#define FSL_FEATURE_SOC_MU_COUNT (0)
/* @brief NFC availability on the SoC. */
#define FSL_FEATURE_SOC_NFC_COUNT (0)
/* @brief OCOTP availability on the SoC. */
#define FSL_FEATURE_SOC_OCOTP_COUNT (0)
/* @brief OPAMP availability on the SoC. */
#define FSL_FEATURE_SOC_OPAMP_COUNT (0)
/* @brief OSC availability on the SoC. */
#define FSL_FEATURE_SOC_OSC_COUNT (0)
/* @brief OSC32 availability on the SoC. */
#define FSL_FEATURE_SOC_OSC32_COUNT (0)
/* @brief OTFAD availability on the SoC. */
#define FSL_FEATURE_SOC_OTFAD_COUNT (0)
/* @brief PCC availability on the SoC. */
#define FSL_FEATURE_SOC_PCC_COUNT (0)
/* @brief PCIE_PHY_CMN availability on the SoC. */
#define FSL_FEATURE_SOC_PCIE_PHY_CMN_COUNT (0)
/* @brief PCIE_PHY_TRSV availability on the SoC. */
#define FSL_FEATURE_SOC_PCIE_PHY_TRSV_COUNT (0)
/* @brief PDB availability on the SoC. */
#define FSL_FEATURE_SOC_PDB_COUNT (0)
/* @brief PGA availability on the SoC. */
#define FSL_FEATURE_SOC_PGA_COUNT (0)
/* @brief PINT availability on the SoC. */
#define FSL_FEATURE_SOC_PINT_COUNT (1)
/* @brief PIT availability on the SoC. */
#define FSL_FEATURE_SOC_PIT_COUNT (0)
/* @brief PMC availability on the SoC. */
#define FSL_FEATURE_SOC_PMC_COUNT (0)
/* @brief PMU availability on the SoC. */
#define FSL_FEATURE_SOC_PMU_COUNT (0)
/* @brief PORT availability on the SoC. */
#define FSL_FEATURE_SOC_PORT_COUNT (0)
/* @brief PROP availability on the SoC. */
#define FSL_FEATURE_SOC_PROP_COUNT (1)
/* @brief PWM availability on the SoC. */
#define FSL_FEATURE_SOC_PWM_COUNT (0)
/* @brief PWT availability on the SoC. */
#define FSL_FEATURE_SOC_PWT_COUNT (0)
/* @brief PXP availability on the SoC. */
#define FSL_FEATURE_SOC_PXP_COUNT (0)
/* @brief QDEC availability on the SoC. */
#define FSL_FEATURE_SOC_QDEC_COUNT (2)
/* @brief QuadSPI availability on the SoC. */
#define FSL_FEATURE_SOC_QuadSPI_COUNT (0)
/* @brief RCM availability on the SoC. */
#define FSL_FEATURE_SOC_RCM_COUNT (0)
/* @brief RDC availability on the SoC. */
#define FSL_FEATURE_SOC_RDC_COUNT (0)
/* @brief RDC_SEMAPHORE availability on the SoC. */
#define FSL_FEATURE_SOC_RDC_SEMAPHORE_COUNT (0)
/* @brief RFSYS availability on the SoC. */
#define FSL_FEATURE_SOC_RFSYS_COUNT (0)
/* @brief RFVBAT availability on the SoC. */
#define FSL_FEATURE_SOC_RFVBAT_COUNT (0)
/* @brief RIT availability on the SoC. */
#define FSL_FEATURE_SOC_RIT_COUNT (0)
/* @brief RNG availability on the SoC. */
#define FSL_FEATURE_SOC_RNG_COUNT (1)
/* @brief RNGB availability on the SoC. */
#define FSL_FEATURE_SOC_RNGB_COUNT (0)
/* @brief ROM availability on the SoC. */
#define FSL_FEATURE_SOC_ROM_COUNT (0)
/* @brief ROMC availability on the SoC. */
#define FSL_FEATURE_SOC_ROMC_COUNT (0)
/* @brief RSIM availability on the SoC. */
#define FSL_FEATURE_SOC_RSIM_COUNT (0)
/* @brief RTC availability on the SoC. */
#define FSL_FEATURE_SOC_RTC_COUNT (1)
/* @brief SCG availability on the SoC. */
#define FSL_FEATURE_SOC_SCG_COUNT (0)
/* @brief SCI availability on the SoC. */
#define FSL_FEATURE_SOC_SCI_COUNT (0)
/* @brief SCT availability on the SoC. */
#define FSL_FEATURE_SOC_SCT_COUNT (1)
/* @brief SDHC availability on the SoC. */
#define FSL_FEATURE_SOC_SDHC_COUNT (0)
/* @brief SDIF availability on the SoC. */
#define FSL_FEATURE_SOC_SDIF_COUNT (0)
/* @brief SDIO availability on the SoC. */
#define FSL_FEATURE_SOC_SDIO_COUNT (0)
/* @brief SDMA availability on the SoC. */
#define FSL_FEATURE_SOC_SDMA_COUNT (0)
/* @brief SDMAARM availability on the SoC. */
#define FSL_FEATURE_SOC_SDMAARM_COUNT (0)
/* @brief SDMABP availability on the SoC. */
#define FSL_FEATURE_SOC_SDMABP_COUNT (0)
/* @brief SDMACORE availability on the SoC. */
#define FSL_FEATURE_SOC_SDMACORE_COUNT (0)
/* @brief SDMCORE availability on the SoC. */
#define FSL_FEATURE_SOC_SDMCORE_COUNT (0)
/* @brief SDRAM availability on the SoC. */
#define FSL_FEATURE_SOC_SDRAM_COUNT (0)
/* @brief SEMA4 availability on the SoC. */
#define FSL_FEATURE_SOC_SEMA4_COUNT (0)
/* @brief SEMA42 availability on the SoC. */
#define FSL_FEATURE_SOC_SEMA42_COUNT (0)
/* @brief SHA availability on the SoC. */
#define FSL_FEATURE_SOC_SHA_COUNT (0)
/* @brief SIM availability on the SoC. */
#define FSL_FEATURE_SOC_SIM_COUNT (0)
/* @brief SIMDGO availability on the SoC. */
#define FSL_FEATURE_SOC_SIMDGO_COUNT (0)
/* @brief SJC availability on the SoC. */
#define FSL_FEATURE_SOC_SJC_COUNT (0)
/* @brief SLCD availability on the SoC. */
#define FSL_FEATURE_SOC_SLCD_COUNT (0)
/* @brief SMARTCARD availability on the SoC. */
#define FSL_FEATURE_SOC_SMARTCARD_COUNT (0)
/* @brief SMC availability on the SoC. */
#define FSL_FEATURE_SOC_SMC_COUNT (0)
/* @brief SNVS availability on the SoC. */
#define FSL_FEATURE_SOC_SNVS_COUNT (0)
/* @brief SPBA availability on the SoC. */
#define FSL_FEATURE_SOC_SPBA_COUNT (0)
/* @brief SPDIF availability on the SoC. */
#define FSL_FEATURE_SOC_SPDIF_COUNT (0)
/* @brief SPI availability on the SoC. */
#define FSL_FEATURE_SOC_SPI_COUNT (2)
/* @brief SPIFI availability on the SoC. */
#define FSL_FEATURE_SOC_SPIFI_COUNT (1)
/* @brief SPM availability on the SoC. */
#define FSL_FEATURE_SOC_SPM_COUNT (0)
/* @brief SRC availability on the SoC. */
#define FSL_FEATURE_SOC_SRC_COUNT (0)
/* @brief SYSCON availability on the SoC. */
#define FSL_FEATURE_SOC_SYSCON_COUNT (1)
/* @brief TEMPMON availability on the SoC. */
#define FSL_FEATURE_SOC_TEMPMON_COUNT (0)
/* @brief TMR availability on the SoC. */
#define FSL_FEATURE_SOC_TMR_COUNT (0)
/* @brief TPM availability on the SoC. */
#define FSL_FEATURE_SOC_TPM_COUNT (0)
/* @brief TRGMUX availability on the SoC. */
#define FSL_FEATURE_SOC_TRGMUX_COUNT (0)
/* @brief TRIAMP availability on the SoC. */
#define FSL_FEATURE_SOC_TRIAMP_COUNT (0)
/* @brief TRNG availability on the SoC. */
#define FSL_FEATURE_SOC_TRNG_COUNT (0)
/* @brief TSC availability on the SoC. */
#define FSL_FEATURE_SOC_TSC_COUNT (0)
/* @brief TSI availability on the SoC. */
#define FSL_FEATURE_SOC_TSI_COUNT (0)
/* @brief TSTMR availability on the SoC. */
#define FSL_FEATURE_SOC_TSTMR_COUNT (0)
/* @brief UART availability on the SoC. */
#define FSL_FEATURE_SOC_UART_COUNT (0)
/* @brief USART availability on the SoC. */
#define FSL_FEATURE_SOC_USART_COUNT (2)
/* @brief USB availability on the SoC. */
#define FSL_FEATURE_SOC_USB_COUNT (1)
/* @brief USBHS availability on the SoC. */
#define FSL_FEATURE_SOC_USBHS_COUNT (0)
/* @brief USBDCD availability on the SoC. */
#define FSL_FEATURE_SOC_USBDCD_COUNT (0)
/* @brief USBFSH availability on the SoC. */
#define FSL_FEATURE_SOC_USBFSH_COUNT (0)
/* @brief USBHSD availability on the SoC. */
#define FSL_FEATURE_SOC_USBHSD_COUNT (0)
/* @brief USBHSDCD availability on the SoC. */
#define FSL_FEATURE_SOC_USBHSDCD_COUNT (0)
/* @brief USBHSH availability on the SoC. */
#define FSL_FEATURE_SOC_USBHSH_COUNT (0)
/* @brief USBNC availability on the SoC. */
#define FSL_FEATURE_SOC_USBNC_COUNT (0)
/* @brief USBPHY availability on the SoC. */
#define FSL_FEATURE_SOC_USBPHY_COUNT (0)
/* @brief USB_HSIC availability on the SoC. */
#define FSL_FEATURE_SOC_USB_HSIC_COUNT (0)
/* @brief USB_OTG availability on the SoC. */
#define FSL_FEATURE_SOC_USB_OTG_COUNT (0)
/* @brief USDHC availability on the SoC. */
#define FSL_FEATURE_SOC_USDHC_COUNT (0)
/* @brief UTICK availability on the SoC. */
#define FSL_FEATURE_SOC_UTICK_COUNT (0)
/* @brief VIU availability on the SoC. */
#define FSL_FEATURE_SOC_VIU_COUNT (0)
/* @brief VREF availability on the SoC. */
#define FSL_FEATURE_SOC_VREF_COUNT (0)
/* @brief VFIFO availability on the SoC. */
#define FSL_FEATURE_SOC_VFIFO_COUNT (0)
/* @brief WDOG availability on the SoC. */
#define FSL_FEATURE_SOC_WDOG_COUNT (1)
/* @brief WKPU availability on the SoC. */
#define FSL_FEATURE_SOC_WKPU_COUNT (0)
/* @brief WWDT availability on the SoC. */
#define FSL_FEATURE_SOC_WWDT_COUNT (0)
/* @brief XBAR availability on the SoC. */
#define FSL_FEATURE_SOC_XBAR_COUNT (0)
/* @brief XBARA availability on the SoC. */
#define FSL_FEATURE_SOC_XBARA_COUNT (0)
/* @brief XBARB availability on the SoC. */
#define FSL_FEATURE_SOC_XBARB_COUNT (0)
/* @brief XCVR availability on the SoC. */
#define FSL_FEATURE_SOC_XCVR_COUNT (0)
/* @brief XRDC availability on the SoC. */
#define FSL_FEATURE_SOC_XRDC_COUNT (0)
/* @brief XTALOSC availability on the SoC. */
#define FSL_FEATURE_SOC_XTALOSC_COUNT (0)
/* @brief XTALOSC24M availability on the SoC. */
#define FSL_FEATURE_SOC_XTALOSC24M_COUNT (0)
/* @brief ZLL availability on the SoC. */
#define FSL_FEATURE_SOC_ZLL_COUNT (0)
/* CRC module features */
/* @brief CRC for boot info */
#define FSL_FEATURE_CRC_BASE_ADDR (0x210B0700)
/* @brief Boot version */
#define FSL_FEATURE_CRC_READ_BASE_ADDR (0x31000000)
/* @brief Boot feature */
#define FSL_FEATURE_CRC_LOCK_BIT_STORE_ADDR (0x2107F800)
/* CTIMER module features */
/* @brief Has CTIMER IR_CR3INT (register bit IR[CR3INT]). */
#define FSL_FEATURE_CTIMER_HAS_IR_CR3INT (0)
/* @brief Has CTIMER CCR_CAP3 (register bits CCR[CAP3RE][CAP3FE][CAP3I]). */
#define FSL_FEATURE_CTIMER_HAS_CCR_CAP3 (0)
/* DMA module features */
/* @brief Number of channels */
#define FSL_FEATURE_DMA_NUMBER_OF_CHANNELS (20)
/* FLASH module features */
/* @brief Flash size in bytes */
#define FSL_FEATURE_FLASH_SIZE_BYTES (524288U)
/* @brief Flash page size in bytes */
#define FSL_FEATURE_FLASH_PAGE_SIZE_BYTES (2048U)
/* @brief Flash block write unit in bytes */
#define FSL_FEATURE_FLASH_PFLASH_BLOCK_WRITE_UNIT_SIZE (0x4U)
/* @brief P-Flash block count */
#define FSL_FEATURE_FLASH_PFLASH_BLOCK_COUNT (2)
/* @brief P-Flash block size */
#define FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE (0x40000U)
/* @brief Flash base address */
#define FSL_FEATURE_FLASH_BASE_ADDR (0x21000000U)
/* @brief Flash read base address */
#define FSL_FEATURE_FLASH_READ_BASE_ADDR (0x31000000U)
/* @brief Flash lock bit address */
#define FSL_FEATURE_FLASH_LOCK_BIT_STORE_ADDR (0x2107F800U)
/* @brief Flash information page address */
#define FSL_FEATURE_FLASH_INFO_BASE_ADDR (0x210B0000U)
/* @brief CRC for boot info (4 Bytes) */
#define FSL_FEATURE_FLASH_ADDR_OF_BOOT_CRC (0x210B0700U)
/* @brief Boot version (4 Bytes) */
#define FSL_FEATURE_FLASH_ADDR_OF_BOOT_VERSION (0x210B0704U)
/* @brief Boot feature (4 Bytes) */
#define FSL_FEATURE_FLASH_ADDR_OF_BOOT_FEATURE (0x210B0708U)
/* @brief Temperature sensor calibration value (4 Bytes) */
#define FSL_FEATURE_FLASH_ADDR_OF_TEMP_CAL (0x210B07F0U)
/* @brief Bandgap voltage for ADC reference calibration (4 Bytes) */
#define FSL_FEATURE_FLASH_ADDR_OF_BANDGAP_VOL (0x210B07F4U)
/* @brief Main Bandgap voltage calibration (4 Bytes) */
#define FSL_FEATURE_FLASH_ADDR_OF_MAINBANDGAP_VOL (0x210B070CU)
/* @brief Vendor bluetooth address(MAC) (6 Bytes) */
#define FSL_FEATURE_FLASH_ADDR_OF_VENDOR_BD_ADDR (0x210B07FAU)
/* PINT module features */
/* @brief Number of connected outputs */
#define FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS (4)
/* RTC module features */
/* @brief RTC has Free Running Counter */
#define FSL_FEATURE_RTC_HAS_FRC (1)
/* SCT module features */
/* @brief Number of events */
#define FSL_FEATURE_SCT_NUMBER_OF_EVENTS (10)
/* @brief Number of states */
#define FSL_FEATURE_SCT_NUMBER_OF_STATES (10)
/* @brief Number of match capture */
#define FSL_FEATURE_SCT_NUMBER_OF_MATCH_CAPTURE (10)
#ifdef __cplusplus
}
#endif
#endif /* _QN908XC_FEATURES_H_ */

View File

@ -0,0 +1,356 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright (c) 2016 - 2017 , NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_CLOCK_H_
#define _FSL_CLOCK_H_
#include "fsl_common.h"
/*! @addtogroup clock */
/*! @{ */
/*! @file */
/*******************************************************************************
* Definitions
*****************************************************************************/
/* To calculate flexcomm clock for baud rate correction */
#define FLEXCOMM_CLK(srcClock_Hz, baudrate_Bps) ((((srcClock_Hz) / 8) / baudrate_Bps) * baudrate_Bps * 8)
/*! @brief Configure whether driver controls clock
*
* When set to 0, peripheral drivers will enable clock in initialize function
* and disable clock in de-initialize function. When set to 1, peripheral
* driver will not control the clock, application could contol the clock out of
* the driver.
*
* @note All drivers share this feature switcher. If it is set to 1, application
* should handle clock enable and disable for all drivers.
*/
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL))
#define FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL 0
#endif
/*! @brief Clock ip name array for LPUART. */
#define LPUART_CLOCKS \
{ \
kCLOCK_Flexcomm0, kCLOCK_Flexcomm1 \
}
/*! @brief Clock ip name array for BI2C. */
#define BI2C_CLOCKS \
{ \
kCLOCK_Flexcomm1, kCLOCK_Flexcomm2 \
}
/*! @brief Clock ip name array for FLEXCOMM. */
#define FLEXCOMM_CLOCKS \
{ \
kCLOCK_Flexcomm0, kCLOCK_Flexcomm1, kCLOCK_Flexcomm2, kCLOCK_Flexcomm3 \
}
/*! @brief Clock ip name array for CRC. */
#define CRC_CLOCKS \
{ \
kCLOCK_Crc \
}
/*! @brief Clock ip name array for CTIMER. */
#define CTIMER_CLOCKS \
{ \
kCLOCK_Ctimer0, kCLOCK_Ctimer1, kCLOCK_Ctimer2, kCLOCK_Ctimer3 \
}
/*! @brief Clock ip name array for SCTimer. */
#define SCT_CLOCKS \
{ \
kCLOCK_Sct0 \
}
/*! @brief Clock ip name array for GPIO. */
#define GPIO_CLOCKS \
{ \
kCLOCK_Gpio \
}
/*! @brief Clock ip name array for Calibration. */
#define CAL_CLOCKS \
{ \
kCLOCK_Cal \
}
/*! @brief Clock ip name array for USBD. */
#define USBD_CLOCKS \
{ \
kCLOCK_Usbd0 \
}
/*! @brief Clock ip name array for WDT. */
#define WDT_CLOCKS \
{ \
kCLOCK_Wdt \
}
/*! @brief Clock ip name array for BIV(including RTC and SYSCON clock). Enabled as default */
#define BIV_CLOCKS \
{ \
kCLOCK_Biv \
}
/*! @brief Clock ip name array for ADC. */
#define ADC_CLOCKS \
{ \
kCLOCK_Adc \
}
/*! @brief Clock ip name array for DAC. */
#define DAC_CLOCKS \
{ \
kCLOCK_Dac \
}
/*! @brief Clock ip name array for CS. */
#define CS_CLOCKS \
{ \
kCLOCK_Cs \
}
/*! @brief Clock ip name array for FSP. */
#define FSP_CLOCKS \
{ \
kCLOCK_Fsp \
}
/*! @brief Clock ip name array for DMA. */
#define DMA_CLOCKS \
{ \
kCLOCK_Dma \
}
/*! @brief Clock ip name array for QDEC. */
#define QDEC_CLOCKS \
{ \
kCLOCK_Qdec0, kCLOCK_Qdec1 \
}
/*! @brief Clock ip name array for DP. */
#define DP_CLOCKS \
{ \
kCLOCK_Dp \
}
/*! @brief Clock ip name array for SPIFI. */
#define SPIFI_CLOCKS \
{ \
kCLOCK_Spifi \
}
/*! @brief Clock ip name array for BLE. */
#define BLE_CLOCKS \
{ \
kCLOCK_Ble \
}
/*! @brief Clock ip name array for PROP. */
#define PROP_CLOCKS \
{ \
kCLOCK_Prop \
}
/*! @brief Clock gate name used for CLOCK_EnableClock/CLOCK_DisableClock. */
/*------------------------------------------------------------------------------
clock_ip_name_t definition:
------------------------------------------------------------------------------*/
/*! @brief Clock gate name used for CLOCK_EnableClock/CLOCK_DisableClock. */
typedef enum _clock_ip_name
{
kCLOCK_IpInvalid = 33U,
kCLOCK_Flexcomm0 = 0U,
kCLOCK_Flexcomm1 = 1U,
kCLOCK_Flexcomm2 = 2U,
kCLOCK_Flexcomm3 = 3U,
kCLOCK_Ctimer0 = 4U,
kCLOCK_Ctimer1 = 5U,
kCLOCK_Ctimer2 = 6U,
kCLOCK_Ctimer3 = 7U,
kCLOCK_Sct0 = 8U,
kCLOCK_Wdt = 9U,
kCLOCK_Usbd0 = 10U,
kCLOCK_Gpio = 11U,
kCLOCK_Biv = 12U,
kCLOCK_Adc = 13U,
kCLOCK_Dac = 14U,
kCLOCK_Cs = 15U,
kCLOCK_Crc = 16U,
kCLOCK_Fsp = 16U,
kCLOCK_Dma = 17U,
kCLOCK_Pint = 17U,
kCLOCK_InputMux = 17U,
kCLOCK_Qdec0 = 19U,
kCLOCK_Qdec1 = 20U,
kCLOCK_Dp = 21U,
kCLOCK_Spifi = 22U,
kCLOCK_Cal = 25U,
kCLOCK_Ble = 27U,
kCLOCK_Prop = 29U,
} clock_ip_name_t;
/*! @brief Clock name used to get clock frequency. */
typedef enum _clock_name
{
kCLOCK_CoreSysClk, /*!< Core/system clock (aka MAIN_CLK) */
kCLOCK_BusClk, /*!< Bus clock (AHB clock) */
kCLOCK_ApbClk, /*!< Apb clock */
kCLOCK_WdtClk, /*!< Wdt clock*/
kCLOCK_FroHf, /*!< FRO */
kCLOCK_Xin, /*!< 16/32 MHz XIN */
kCLOCK_32KClk /*!< 32K clock */
} clock_name_t;
/*! @brief Clock Mux Switches
*
* [4 bits for choice] [8 bits mux ID]
*/
#define MUX_A(m, choice) (((m) << 0) | ((choice + 1) << 8))
#define CM_32KCLKSEL 0
#define CM_SYSCLKSEL 1
#define CM_WDTCLKSEL 2
#define CM_BLECLKSEL 3
#define CM_XTALCLKSEL 4
typedef enum _clock_attach_id
{
kXTAL32K_to_32K_CLK = MUX_A(CM_32KCLKSEL, 0), /*!< XTAL 32K clock */
kRCO32K_to_32K_CLK = MUX_A(CM_32KCLKSEL, 1), /*!< RCO 32KHz clock */
kOSC32M_to_SYS_CLK = MUX_A(CM_SYSCLKSEL, 0), /*!< OSC 32MHz clock */
kXTAL_to_SYS_CLK = MUX_A(CM_SYSCLKSEL, 1), /*!< XTAL 16MHz/32MHz clock */
k32K_to_SYS_CLK = MUX_A(CM_SYSCLKSEL, 2), /*!< 32KHz clock */
k32K_to_WDT_CLK = MUX_A(CM_WDTCLKSEL, 0), /*!< 32KHz clock */
kAPB_to_WDT_CLK = MUX_A(CM_WDTCLKSEL, 1), /*!< APB clock */
k8M_to_BLE_CLK = MUX_A(CM_BLECLKSEL, 0), /*!< 8M CLOCK */
k16M_to_BLE_CLK = MUX_A(CM_BLECLKSEL, 1), /*!< 16M CLOCK */
k16M_to_XTAL_CLK = MUX_A(CM_XTALCLKSEL, 0), /*!< 16M XTAL */
k32M_to_XTAL_CLK = MUX_A(CM_XTALCLKSEL, 1), /*!< 32M XTAL */
kNONE_to_NONE = 0x80000000U,
} clock_attach_id_t;
/* Clock dividers */
typedef enum _clock_div_name
{
kCLOCK_DivXtalClk,
kCLOCK_DivOsc32mClk,
kCLOCK_DivAhbClk,
kCLOCK_DivApbClk,
kCLOCK_DivFrg0,
kCLOCK_DivFrg1,
kCLOCK_DivClkOut
} clock_div_name_t;
/*! @brief USB clock source definition. */
typedef enum _clock_usb_src
{
kCLOCK_UsbSrcFro =
(uint32_t)kCLOCK_FroHf, /*!< Fake USB src clock, temporary fix until USB clock control is done properly */
} clock_usb_src_t;
/* Clock clock out source */
typedef enum _clock_clkout_src
{
kCLOCK_Clkout_32K = SYSCON_CLK_CTRL_CLK_32K_OE_MASK, /*!< 32KHz clock out */
kCLOCK_Clkout_XTAL = SYSCON_CLK_CTRL_CLK_XTAL_OE_MASK /*!< XTAL clock out */
} clock_clkout_src_t;
/* Clock clock out pin */
typedef enum _clock_clkout_pin
{
kCLOCK_Clkout_PA04_32K = SYSCON_PIO_WAKEUP_EN1_PA04_32K_OE_MASK,
kCLOCK_Clkout_PA05_XTAL = SYSCON_PIO_WAKEUP_EN1_PA05_XTAL_OE_MASK,
kCLOCK_Clkout_PA10_32K = SYSCON_PIO_WAKEUP_EN1_PA10_32K_OE_MASK,
kCLOCK_Clkout_PA11_XTAL = SYSCON_PIO_WAKEUP_EN1_PA11_XTAL_OE_MASK,
kCLOCK_Clkout_PA18_32K = SYSCON_PIO_WAKEUP_EN1_PA18_32K_OE_MASK,
kCLOCK_Clkout_PA19_XTAL = SYSCON_PIO_WAKEUP_EN1_PA19_XTAL_OE_MASK,
kCLOCK_Clkout_PA24_32K = SYSCON_PIO_WAKEUP_EN1_PA24_32K_OE_MASK,
kCLOCK_Clkout_PA25_XTAL = SYSCON_PIO_WAKEUP_EN1_PA25_XTAL_OE_MASK
} clock_clkout_pin_t;
/*******************************************************************************
* API
******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/*!
* @brief Enable the specified peripheral clock
*/
void CLOCK_EnableClock(clock_ip_name_t clk);
/*!
* @brief Disable the specified peripheral clock
*/
void CLOCK_DisableClock(clock_ip_name_t clk);
/*!
* @brief Configure the clock selection muxes.
*
* @param connection: Clock to be configured.
*/
void CLOCK_AttachClk(clock_attach_id_t connection);
/*!
* @brief Setup peripheral clock dividers.
*
* @param div_name: Clock divider name
* @param divided_by_value: Value to be divided
*/
void CLOCK_SetClkDiv(clock_div_name_t div_name, uint32_t divided_by_value);
/*!
* @brief Get frequency of selected clock
*
* @return Frequency of selected clock
*/
uint32_t CLOCK_GetFreq(clock_name_t clk);
/*!
* @brief Disable USB FS clock.
*
* Disable USB FS clock.
*/
static inline void CLOCK_DisableUsbfs0Clock(void)
{
CLOCK_DisableClock(kCLOCK_Usbd0);
}
bool CLOCK_EnableUsbfs0DeviceClock(clock_usb_src_t src, uint32_t freq);
/*!
* @brief Enable/Disable clock out source.
*
* @param mask Mask value for the clock source, See "clock_clkout_src_t".
* @param enable Enable/Disable the clock out source.
*/
void CLOCK_EnableClkoutSource(uint32_t mask, bool enable);
/*!
* @brief Enable/Disable clock out pin.
*
* @param mask Mask value for the clock source, See "clock_clkout_pin_t".
* @param enable Enable/Disable the clock out pin.
*/
void CLOCK_EnableClkoutPin(uint32_t mask, bool enable);
/*! @brief Return Input frequency for the Fractional baud rate generator
* @return Input Frequency for FRG
*/
uint32_t CLOCK_GetFRGInputClock(void);
/*!
* @brief Set output of the Fractional baud rate generator
*
* @param div_name: Clock divider name: kCLOCK_DivFrg0 and kCLOCK_DivFrg1
* @param freq: Desired output frequency
* @return Error Code 0 - fail 1 - success
*/
uint32_t CLOCK_SetFRGClock(clock_div_name_t div_name, uint32_t freq);
#ifdef __cplusplus
}
#endif /* __cplusplus */
/*! @} */
#endif /* _FSL_CLOCK_H_ */

View File

@ -0,0 +1,259 @@
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_IOCON_H_
#define _FSL_IOCON_H_
#include "fsl_common.h"
/*!
* @addtogroup qn_iocon
* @{
*/
/*! @file */
/*******************************************************************************
* Definitions
******************************************************************************/
#define IOCON SYSCON
/*! @name Driver version */
/*@{*/
/*! @brief IOCON driver version 2.0.0. */
#define LPC_IOCON_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
/*@}*/
/**
* @brief Array of IOCON pin definitions passed to IOCON_SetPinMuxing() must be in this format
*/
typedef struct _iocon_group
{
uint32_t port : 8; /* Pin port */
uint32_t pin : 8; /* Pin number */
uint32_t modefunc : 16; /* Function and mode */
} iocon_group_t;
/**
* @brief IOCON function, mode and drive selection definitions
* @note See the User Manual for specific drive levels, modes and functions supported by the various pins.
*/
#define IOCON_FUNC0 0x0U /*!< Selects pin function 0 */
#define IOCON_FUNC1 0x1U /*!< Selects pin function 1 */
#define IOCON_FUNC2 0x2U /*!< Selects pin function 2 */
#define IOCON_FUNC3 0x3U /*!< Selects pin function 3 */
#define IOCON_FUNC4 0x4U /*!< Selects pin function 4 */
#define IOCON_FUNC5 0x5U /*!< Selects pin function 5 */
#define IOCON_FUNC6 0x6U /*!< Selects pin function 6 */
#define IOCON_FUNC7 0x7U /*!< Selects pin function 7 */
#define IOCON_MODE_HIGHZ (0x0U << 4U) /*!< Selects High-Z function */
#define IOCON_MODE_PULLDOWN (0x1U << 4U) /*!< Selects pull-down function */
#define IOCON_MODE_PULLUP (0x2U << 4U) /*!< Selects pull-up function */
#define IOCON_DRIVE_LOW (0x0U << 6U) /*!< Enable low drive strength */
#define IOCON_DRIVE_HIGH (0x1U << 6U) /*!< Enable high drive strength */
#define IOCON_DRIVE_EXTRA (0x1U << 7U) /*!< Enable extra drive, only valid for PA06/PA11/PA19/PA26/PA27 */
/**
* @brief Pull mode
*/
typedef enum _iocon_pull_mode
{
kIOCON_HighZ = 0U, /*!< High Z */
kIOCON_PullDown, /*!< Pull down */
kIOCON_PullUp /*!< Pull up */
} iocon_pull_mode_t;
/**
* @brief Drive strength
*/
typedef enum _iocon_drive_strength
{
kIOCON_LowDriveStrength = 0U, /*!< Low-drive */
kIOCON_HighDriveStrength, /*!< High-drive */
kIOCON_LowDriveWithExtraStrength, /*!< Low-drive with extra */
kIOCON_HighDriveWithExtraStrength, /*!< High-drive with extra */
} iocon_drive_strength_t;
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Sets I/O control pin mux
* @param base The base of SYSCON peripheral on the chip
* @param port GPIO port to mux (value from 0 ~ 1)
* @param pin GPIO pin to mux (value from 0 ~ 31)
* @param modeFunc OR'ed values of type IOCON_*
* @return Nothing
*/
__STATIC_INLINE void IOCON_PinMuxSet(SYSCON_Type *base, uint8_t port, uint8_t pin, uint32_t modeFunc)
{
assert(((port == 0U) && (pin <= 31U)) || ((port == 1U) && (pin <= 2U)));
uint8_t pinMuxIndex = (pin >> 3U);
uint8_t pinMuxLocation = ((pin & 0x7U) << 2U);
uint8_t pinPullIndex = (pin >> 4U);
uint8_t pinPullLocation = ((pin & 0xFU) << 1U);
if (port == 0U)
{
base->PIO_FUNC_CFG[pinMuxIndex] &= ~(0x07U << pinMuxLocation);
base->PIO_FUNC_CFG[pinMuxIndex] |= (modeFunc & 0x07U) << pinMuxLocation;
pinPullIndex = (pin >> 4U);
}
else if (port == 1U)
{
pinPullIndex = 2U;
if ((pin == 0U) || (pin == 1U))
{
base->PIO_CFG_MISC &= ~(1U << pin);
base->PIO_CFG_MISC |= (modeFunc & 0x01U) << pin;
}
else if (pin == 2U)
{
base->PIO_CFG_MISC &= ~(1U << 16U);
base->PIO_CFG_MISC |= (modeFunc & 0x01U) << 16U;
}
else
{
return;
}
}
else
{
return;
}
base->PIO_PULL_CFG[pinPullIndex] &= ~(0x03U << pinPullLocation);
base->PIO_PULL_CFG[pinPullIndex] |= ((modeFunc >> 4U) & 0x03U) << pinPullLocation;
base->PIO_DRV_CFG[port] &= ~(1U << pin);
base->PIO_DRV_CFG[port] |= (((modeFunc >> 6U) & 0x01U)) << pin;
if ((port == 0U) && ((pin == 6U) || (pin == 11U) || (pin == 19U) || (pin == 26U) || (pin == 27U)))
{
base->PIO_DRV_CFG[2U] &= ~(1U << pin);
base->PIO_DRV_CFG[2U] |= (((modeFunc >> 7U) & 0x01U)) << pin;
}
}
/**
* @brief Set all I/O control pin muxing
* @param base The base of SYSCON peripheral on the chip
* @param pinArray Pointer to array of pin mux selections
* @param arrayLength Number of entries in pinArray
* @return Nothing
*/
__STATIC_INLINE void IOCON_SetPinMuxing(SYSCON_Type *base, const iocon_group_t *pinArray, uint32_t arrayLength)
{
uint32_t i;
for (i = 0U; i < arrayLength; i++)
{
IOCON_PinMuxSet(base, pinArray[i].port, pinArray[i].pin, pinArray[i].modefunc);
}
}
/**
* @brief Sets I/O control pin function
* @param base The base of SYSCON peripheral on the chip
* @param port GPIO port (value from 0 ~ 1)
* @param pin GPIO pin (value from 0 ~ 31)
* @param func Pin fucntion (value from 0 ~ 7)
* @return Nothing
*/
__STATIC_INLINE void IOCON_FuncSet(SYSCON_Type *base, uint8_t port, uint8_t pin, uint8_t func)
{
assert(((port == 0U) && (pin <= 31U)) || ((port == 1U) && (pin <= 2U)));
uint8_t index = (pin >> 3);
uint8_t pinLocation = ((pin & 0x7U) << 2U);
if (port == 0U)
{
base->PIO_FUNC_CFG[index] &= ~(0x07U << pinLocation);
base->PIO_FUNC_CFG[index] |= (func & 0x07U) << pinLocation;
}
else if (port == 1U)
{
if ((pin == 0U) || (pin == 1U))
{
base->PIO_CFG_MISC &= ~(1U << pin);
base->PIO_CFG_MISC |= (func & 0x01U) << pin;
}
else if (pin == 2U)
{
base->PIO_CFG_MISC &= ~(1U << 16U);
base->PIO_CFG_MISC |= (func & 0x01U) << 16U;
}
else
{
return;
}
}
else
{
return;
}
}
/**
* @brief Sets I/O control drive capability
* @param base The base of SYSCON peripheral on the chip
* @param port GPIO port (value from 0 ~ 1)
* @param pin GPIO pin (value from 0 ~ 31)
* @param strength Drive strength (Extra option is only valid for PA06/PA11/PA19/PA26/PA27)
* - kIOCON_LowDriveStrength = 0U - Low-drive strength is configured.
* - kIOCON_HighDriveStrength = 1U - High-drive strength is configured
* - kIOCON_LowDriveWithExtraStrength = 2U - Low-drive with extra strength is configured
* - kIOCON_HighDriveWithExtraStrength = 3U - High-drive with extra strength is configured
* @return Nothing
*/
__STATIC_INLINE void IOCON_DriveSet(SYSCON_Type *base, uint8_t port, uint8_t pin, uint8_t strength)
{
assert(((port == 0U) && (pin <= 31U)) || ((port == 1U) && (pin <= 2U)));
base->PIO_DRV_CFG[port] &= ~(1U << pin);
base->PIO_DRV_CFG[port] |= (strength & 0x01U) << pin;
if ((port == 0U) && ((pin == 6U) || (pin == 11U) || (pin == 19U) || (pin == 26U) || (pin == 27U)))
{
base->PIO_DRV_CFG[2U] &= ~(1U << pin);
base->PIO_DRV_CFG[2U] |= (((strength >> 1U) & 0x01U)) << pin;
}
}
/**
* @brief Sets I/O control pull configuration
* @param base The base of SYSCON peripheral on the chip
* @param port GPIO port (value from 0 ~ 1)
* @param pin GPIO pin (value from 0 ~ 31)
* @param pullMode Pull mode
* - kIOCON_HighZ = 0U - High Z is configured.
* - kIOCON_PullDown = 1U - Pull-down is configured
* - kIOCON_PullUp = 2U - Pull-up is configured
* @return Nothing
*/
__STATIC_INLINE void IOCON_PullSet(SYSCON_Type *base, uint8_t port, uint8_t pin, uint8_t pullMode)
{
assert(((port == 0U) && (pin <= 31U)) || ((port == 1U) && (pin <= 2U)));
uint8_t index = (port == 1U) ? 2U : (pin >> 4U);
uint8_t pinLocation = ((pin & 0xFU) << 1U);
base->PIO_PULL_CFG[index] &= ~(0x03U << pinLocation);
base->PIO_PULL_CFG[index] |= (uint32_t)pullMode << pinLocation;
}
/* @} */
#ifdef __cplusplus
}
#endif
#endif /* _FSL_IOCON_H_ */

52
cpu/qn908x/include/vendor/fsl_common.h vendored Normal file
View File

@ -0,0 +1,52 @@
/*
* 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 Wrapper header for SDK drivers.
*
* Vendor SDK drivers include "fsl_common.h" with many definitions and extra
* dependencies on more headers that are not used in the RIOT-OS port. This
* header is a wrapper intended to keep the SDK headers unchanged and provide
* the essential definitions needed by other SDK modules.
*
* @author iosabi <iosabi@protonmail.com>
*/
#ifndef FSL_COMMON_H
#define FSL_COMMON_H
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#include "irq.h"
#include "vectors_cortexm.h"
#include "QN908XC.h"
#include "QN908XC_features.h"
#ifdef __cplusplus
extern "C" {
#endif
/* RIOT-OS equivalent functions. */
#define DisableGlobalIRQ irq_disable
#define EnableGlobalIRQ irq_restore
#define __Vectors cortex_vector_base
#ifdef __cplusplus
}
#endif
#endif /* FSL_COMMON_H */
/** @} */

View File

@ -0,0 +1,97 @@
/*
** ###################################################################
** Processors: QN9080C
** QN9083C
**
** Compilers: Keil ARM C/C++ Compiler
** GNU C Compiler
** IAR ANSI C/C++ Compiler for ARM
** MCUXpresso Compiler
**
** Reference manual: QN908X User manual Rev.1.0 21 Mar 2017
** Version: rev. 1.0, 2017-03-27
** Build: b170328
**
** 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-2017 NXP
** All rights reserved.
**
** SPDX-License-Identifier: BSD-3-Clause
**
** http: www.nxp.com
** mail: support@nxp.com
**
** Revisions:
** - rev. 1.0 (2017-03-27)
** Initial version.
**
** ###################################################################
*/
/*!
* @file QN908XC
* @version 1.0
* @date 2017-03-27
* @brief Device specific configuration file for QN908XC (header 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.
*/
#ifndef _SYSTEM_QN908XC_H_
#define _SYSTEM_QN908XC_H_ /**< Symbol preventing repeated inclusion */
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#define CLK_XTAL_16MHZ 16000000u /* 16 MHz XTAL clock */
#define CLK_XTAL_32MHZ 32000000u /* 32 MHz XTAL clock */
#define CLK_OSC_32MHZ 32000000u /* OSC 32 MHz */
#define CLK_XTAL_32KHZ 32768u /* XTAL 32 kHz */
#define CLK_RCO_32KHZ 32000u /* RCO 32 kHz */
#define DEFAULT_SYSTEM_CLOCK 16000000u /* Default System clock value */
/**
* @brief System clock frequency (core clock)
*
* The system clock frequency supplied to the SysTick timer and the processor
* core clock. This variable can be used by the user application to setup the
* SysTick timer or configure other parameters. It may also be used by debugger to
* query the frequency of the debug timer or configure the trace clock speed
* SystemCoreClock is initialized with a correct predefined value.
*/
extern uint32_t SystemCoreClock;
/**
* @brief Setup the microcontroller system.
*
* Typically this function configures the oscillator (PLL) that is part of the
* microcontroller device. For systems with variable clock speed it also updates
* the variable SystemCoreClock. SystemInit is called from startup_device file.
*/
void SystemInit (void);
/**
* @brief Updates the SystemCoreClock variable.
*
* It must be called whenever the core clock is changed during program
* execution. SystemCoreClockUpdate() evaluates the clock register settings and calculates
* the current core clock.
*/
void SystemCoreClockUpdate (void);
#ifdef __cplusplus
}
#endif
#endif /* _SYSTEM_QN908XC_H_ */

129
cpu/qn908x/isr_qn908x.c Normal file
View File

@ -0,0 +1,129 @@
/*
* 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 Default interrupt service routine definitions for NXP QN908x
*
* These weak default definitions act as a fallback definition if no driver
* defines a ISR for the specific interrupt.
*
* @author iosabi <iosabi@protonmail.com>
*
* @}
*/
#include "cpu.h"
#include "vectors_cortexm.h"
#include "vectors_qn908x.h"
/* These are defined in vectors_cortexm.c. */
extern void reset_handler_default(void);
extern uint32_t _estack; /* Exception stack pointer. */
/**
* @brief Jump to the reset_handle_default handler with the exception stack.
*/
__attribute__((noreturn)) static inline void cpu_restart(void)
{
/* Reset the stack pointer to the beginning again and jump to the reset
* handler at the expected address.
*/
__asm volatile ("msr msp, %[estack]\n"
"mov pc, %[entry]\n"
:
: [ estack ] "r" (&_estack),
[ entry ] "r" (reset_handler_default)
: "memory");
/* This function doesn't return anyway. */
while (1) {}
}
/**
* @brief Remap the flash to address 0 on start.
*
* The bootloader will jump to the flash at address 0x21000000 which is aliased
* to the flash on this CPU. However, our program is linked to run as if the
* flash is mapped at address 0 which is the common case. The range starting at
* address 0 can be mapped to flash, RAM or ROM via the SYS_MODE_CTRL register,
* but on reset the default value (0x0) means that it is mapped to ROM.
* We need to remap the flash and change the program counter to be running from
* the right address range (0).
*/
void pre_startup(void)
{
register unsigned int pc;
/* Disable interrupts */
__disable_irq();
/* Check whether we are running from the 0x21000000 range. If that's the
* case we need to remap the flash to the address 0 in SYS_MODE_CTRL and
* jump back to the reset_handler_default so everything starts as running
* from the address 0x0 instead.
*/
__asm volatile ("mov %0, pc" : "=r" (pc));
if ((pc & 0x21000000) == 0x21000000) {
SYSCON->SYS_MODE_CTRL |= 1;
cpu_restart();
}
}
/* QN908x interrupt service routines */
WEAK_DEFAULT void isr_ext_gpio_wakeup(void);
WEAK_DEFAULT void isr_osc(void);
WEAK_DEFAULT void isr_acmp0(void);
WEAK_DEFAULT void isr_acmp1(void);
WEAK_DEFAULT void isr_rtc_sec(void);
WEAK_DEFAULT void isr_rtc_fr(void);
WEAK_DEFAULT void isr_cs_wakeup(void);
WEAK_DEFAULT void isr_cs(void);
WEAK_DEFAULT void isr_gpioa(void);
WEAK_DEFAULT void isr_gpiob(void);
WEAK_DEFAULT void isr_dma0(void);
WEAK_DEFAULT void isr_pin_int0(void);
WEAK_DEFAULT void isr_pin_int1(void);
WEAK_DEFAULT void isr_pin_int2(void);
WEAK_DEFAULT void isr_pin_int3(void);
WEAK_DEFAULT void isr_osc_int_low(void);
WEAK_DEFAULT void isr_usb0(void);
WEAK_DEFAULT void isr_flexcomm0(void);
WEAK_DEFAULT void isr_flexcomm1(void);
WEAK_DEFAULT void isr_flexcomm2(void);
WEAK_DEFAULT void isr_flexcomm3(void);
WEAK_DEFAULT void isr_ble(void);
WEAK_DEFAULT void isr_fsp(void);
WEAK_DEFAULT void isr_qdec0(void);
WEAK_DEFAULT void isr_qdec1(void);
WEAK_DEFAULT void isr_ctimer0(void);
WEAK_DEFAULT void isr_ctimer1(void);
WEAK_DEFAULT void isr_ctimer2(void);
WEAK_DEFAULT void isr_ctimer3(void);
WEAK_DEFAULT void isr_wdt(void);
WEAK_DEFAULT void isr_adc(void);
WEAK_DEFAULT void isr_dac(void);
WEAK_DEFAULT void isr_xtal_ready(void);
WEAK_DEFAULT void isr_flash(void);
WEAK_DEFAULT void isr_spifi0(void);
WEAK_DEFAULT void isr_sct0(void);
WEAK_DEFAULT void isr_rng(void);
WEAK_DEFAULT void isr_calib(void);
WEAK_DEFAULT void isr_ble_tx(void);
WEAK_DEFAULT void isr_ble_rx(void);
WEAK_DEFAULT void isr_ble_freq_hop(void);
WEAK_DEFAULT void isr_bod(void);
void dummy_handler(void)
{
dummy_handler_default();
}

View File

@ -0,0 +1,69 @@
/*
* 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.
*/
/**
* @addtogroup cpu_qn908x
* @{
*
* @file
* @brief Sections definitions for the NXP QN908x MCUs
*
* @author iosabi <iosabi@protonmail.com>
*
* This linker script organizes the flash headers to generate a "Legacy" image
* as described in the "Boot Process" section of the QN908x user manual. A
* legacy image contains an "Image vector table" which is the standard ARM
* vector table with some special values in the reserved fields. In particular,
* this needs a to have a valid checksum at address 0x1c to be considered a
* valid image by the bootloader, which is not set by the build process.
*
* @}
*/
OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
_vectors_length = 0x114;
/* The Flash lock and protect descriptor occupies the last flash page of 0x800
* bytes. See "Flash lock and protection" protection section. */
_flash_lock_length = 0x800;
INCLUDE cortexm_rom_offset.ld
MEMORY
{
/* Note: What we call "rom" here is the flash region for consistency with
* the rest of the RIOT build system naming. There is a 256 kB ROM memory in
* the QN908x holding the bootloader and Bluetooth stack that can't be
* modified by the user.
*/
vectors : ORIGIN = _rom_start_addr + _rom_offset, LENGTH = _vectors_length
rom (rx) : ORIGIN = _rom_start_addr + _rom_offset + _vectors_length, LENGTH = _fw_rom_length - _vectors_length - _flash_lock_length
ram (!rx) : ORIGIN = _ram_start_addr, LENGTH = _ram_length
}
SECTIONS
{
/* "Image vector table" 0x000-0x114, defined in the "Boot process" section,
* must have exactly this size, otherwise we configured something wrong.
*/
.vectors :
{
PROVIDE(_isr_vectors = .);
KEEP(*(SORT(.vector*)))
} > vectors
ASSERT (SIZEOF(.vectors) == _vectors_length,
"Image vector table size mismatch.")
ASSERT (ADDR(.vectors) == _rom_start_addr + _rom_offset,
"Image vector table must start at the beginning of the flash")
ASSERT (LOADADDR(.vectors) == _rom_start_addr + _rom_offset,
"Image vector table must start at the beginning of the flash")
}
INCLUDE cortexm_base.ld

View File

@ -0,0 +1 @@
include $(RIOTMAKE)/periph.mk

276
cpu/qn908x/periph/gpio.c Normal file
View File

@ -0,0 +1,276 @@
/*
* 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
* @ingroup drivers_periph_gpio
*
* @{
*
* @file
* @brief Low-level GPIO driver implementation
*
* @author iosabi <iosabi@protonmail.com>
*
* @}
*/
#include <stddef.h>
#include <stdint.h>
#include "cpu.h"
#include "bitarithm.h"
#include "periph/gpio.h"
#include "vectors_qn908x.h"
#include "gpio_mux.h"
#include "vendor/drivers/fsl_clock.h"
#include "vendor/drivers/fsl_iocon.h"
/* The pull-up / pull-down / high-z mode in the gpio_mode_t enum matches the
* values in the IOCON_PinMuxSet() function.
*/
#if (GPIO_MODE(0, 0, 0) & 0x30) != IOCON_MODE_HIGHZ
#error "GPIO_MODE(x, y, 0) must be High-Z mode"
#endif
#if (GPIO_MODE(0, 0, 1) & 0x30) != IOCON_MODE_PULLDOWN
#error "GPIO_MODE(x, y, 0) must be pull-down mode"
#endif
#if (GPIO_MODE(0, 0, 2) & 0x30) != IOCON_MODE_PULLUP
#error "GPIO_MODE(x, y, 0) must be pull-up mode"
#endif
/* Bit mask indicating if a GPIO is set to open_drain. */
static uint32_t gpio_open_drain[GPIO_PORTS_NUMOF] = {};
int gpio_init(gpio_t pin, gpio_mode_t mode)
{
GPIO_Type *const base = GPIO_T_ADDR(pin);
const uint32_t mask = 1u << GPIO_T_PIN(pin);
/* We need to enable the GPIO clock before we set any register in the GPIO
* blocks. */
CLOCK_EnableClock(kCLOCK_Gpio);
/* Disable the interrupts just in case this was already configured as an
* interrupt pin. Note: this only disables the pin(s) that you write a 1
* to. */
base->INTENCLR = mask;
/* pin_mode is the "or" of the three parts: function, mode and drive
* strength. The mode is just the bits 4 and 5 of the gpio_mode_t and
* corresponds to the IOCON_MODE_* values */
uint32_t pin_mode =
IOCON_FUNC0 | /* FUNC0 is digital GPIO on all pins. */
(mode & 0x30) | IOCON_DRIVE_HIGH;
gpio_init_mux(pin, pin_mode);
if (mode & 2) {
/* output mode */
/* Configure the open-drain variable for allowing setting the values
* later. */
if (mode & 1) {
/* open-drain enabled. */
gpio_open_drain[GPIO_T_PORT(pin)] |= mask;
/* Starts with the pin set to "high" (open) in open-drain mode.
* The DATAOUT value doesn't do anything if the output is not
* enabled but we keep track of the current value in DATAOUT
* anyway to allow gpio_toggle. */
base->OUTENCLR = mask;
base->DATAOUT |= mask;
}
else {
gpio_open_drain[GPIO_T_PORT(pin)] &= ~mask;
/* Starts with the pin set to low on push-pull mode. */
base->DATAOUT &= ~mask;
base->OUTENSET = mask;
}
}
else {
/* input mode */
gpio_open_drain[GPIO_T_PORT(pin)] &= ~mask;
base->OUTENCLR = mask;
}
return 0;
}
#ifdef MODULE_PERIPH_GPIO_IRQ
typedef struct {
gpio_cb_t cb;
void *arg;
} gpio_isr_cb_state_t;
/**
* @brief The number of GPIO pins per port.
*/
#define PINS_PER_PORT (32)
/**
* @brief The total number of GPIO pins in the chip.
*/
#define TOTAL_GPIO_PINS (35)
static gpio_isr_cb_state_t gpio_isr_state[TOTAL_GPIO_PINS] = {};
int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank,
gpio_cb_t cb, void *arg)
{
uint8_t gpio_num = GPIO_T_PORT(pin) * PINS_PER_PORT + GPIO_T_PIN(pin);
if (gpio_num >= TOTAL_GPIO_PINS) {
return -1;
}
gpio_isr_state[gpio_num].cb = cb;
gpio_isr_state[gpio_num].arg = arg;
if (gpio_init(pin, mode) != 0) {
return -1;
}
GPIO_Type *const base = GPIO_T_ADDR(pin);
const uint32_t mask = 1u << GPIO_T_PIN(pin);
switch (flank) {
case GPIO_LOW:
base->INTTYPECLR = mask; /* CLR = level */
base->INTPOLCLR = mask; /* CLR = low */
break;
case GPIO_HIGH:
base->INTTYPECLR = mask; /* CLR = level */
base->INTPOLSET = mask; /* SET = high */
break;
case GPIO_FALLING:
base->INTTYPESET = mask; /* SET = edge */
base->INTPOLCLR = mask; /* CLR = falling */
break;
case GPIO_RISING:
base->INTTYPESET = mask; /* SET = edge */
base->INTPOLSET = mask; /* SET = rising */
break;
}
gpio_irq_enable(pin);
return 0;
}
void gpio_irq_enable(gpio_t pin)
{
GPIO_T_ADDR(pin)->INTENSET = 1u << GPIO_T_PIN(pin);
}
void gpio_irq_disable(gpio_t pin)
{
GPIO_T_ADDR(pin)->INTENCLR = 1u << GPIO_T_PIN(pin);
}
#endif /* defined(MODULE_PERIPH_GPIO_IRQ) */
int gpio_read(gpio_t pin)
{
return ((GPIO_T_ADDR(pin)->DATA) >> GPIO_T_PIN(pin)) & 1u;
}
void gpio_set(gpio_t pin)
{
GPIO_Type *const base = GPIO_T_ADDR(pin);
const uint32_t mask = 1u << GPIO_T_PIN(pin);
/* out_clr has only the pin bit set if this is an open-drain pin, which
* means we need to disable the output. This needs to happen before changing
* DATAOUT. */
const uint32_t out_clr = mask & gpio_open_drain[GPIO_T_PORT(pin)];
base->OUTENCLR = out_clr;
base->DATAOUT |= mask;
}
void gpio_clear(gpio_t pin)
{
GPIO_Type *const base = GPIO_T_ADDR(pin);
const uint32_t mask = 1u << GPIO_T_PIN(pin);
base->DATAOUT &= ~mask;
/* out_clr has only the pin bit set if this is an open-drain pin, which
* means we need to enable the output. This needs to happen after changing
* DATAOUT. */
const uint32_t out_clr = mask & gpio_open_drain[GPIO_T_PORT(pin)];
base->OUTENSET = out_clr;
}
void gpio_toggle(gpio_t pin)
{
GPIO_Type *const base = GPIO_T_ADDR(pin);
const uint32_t mask = 1u << GPIO_T_PIN(pin);
const uint32_t out_clr = mask & gpio_open_drain[GPIO_T_PORT(pin)];
const uint32_t dataout = base->DATAOUT;
/* The output is disabled if the pin is an open-drain pin and DATAOUT is
* not set for that pin. This avoids having if conditions. */
base->OUTENCLR = out_clr & ~dataout;
base->DATAOUT ^= mask;
/* The output is disabled if the pin is an open-drain and DATAOUT at the
* beginning of the function was set. */
base->OUTENSET = out_clr & dataout;
}
void gpio_write(gpio_t pin, int value)
{
if (value) {
gpio_set(pin);
}
else {
gpio_clear(pin);
}
}
#ifdef MODULE_PERIPH_GPIO_IRQ
static inline void irq_handler(GPIO_Type *base, uint32_t port_num)
{
uint32_t status = base->INTSTATUS;
while (status) {
/* Clear all the flags immediately and process them in order. This gives
* a chance to execute every pin's interrupt handler even if another pin
* is always on.
* Note: to *clear* the interrupt flag you write a 1 to that bit.
*/
base->INTSTATUS = status;
while (status) {
uint8_t pin;
status = bitarithm_test_and_clear(status, &pin);
uint32_t gpio_num = port_num * PINS_PER_PORT + pin;
gpio_cb_t cb = gpio_isr_state[gpio_num].cb;
if (cb) {
cb(gpio_isr_state[gpio_num].arg);
}
}
status = base->INTSTATUS;
}
}
#ifdef GPIOA_BASE
void isr_gpioa(void)
{
irq_handler(GPIOA, 0);
cortexm_isr_end();
}
#endif /* GPIOA_BASE */
#ifdef GPIOB_BASE
void isr_gpiob(void)
{
irq_handler(GPIOB, 1);
cortexm_isr_end();
}
#endif /* GPIOB_BASE */
#endif /* MODULE_PERIPH_GPIO_IRQ */

View File

@ -0,0 +1,32 @@
/*
* 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 Common Pin MUX functions.
*
* @author iosabi <iosabi@protonmail.com>
*
* @}
*/
#include "gpio_mux.h"
#include "vendor/drivers/fsl_iocon.h"
void gpio_init_mux(gpio_t pin, uint32_t func)
{
if (pin == GPIO_UNDEF) {
return;
}
IOCON_PinMuxSet(IOCON, GPIO_T_PORT(pin), GPIO_T_PIN(pin), func);
}

191
cpu/qn908x/periph/wdt.c Normal file
View File

@ -0,0 +1,191 @@
/*
* 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
* @ingroup cpu_qn908x_wdt
*
* @{
*
* @file
* @brief Low-level WDOG driver implementation
*
* @author iosabi <iosabi@protonmail.com>
*
* @}
*/
#include "periph/wdt.h"
#include <stdint.h>
#include <stdbool.h>
#include "vendor/drivers/fsl_clock.h"
#include "debug.h"
/* The number of cycles to refresh the WDT with when kicked. */
static uint32_t wdt_load_value = 0xffffffff;
/* The maximum value the WDT counter could have when kicked. The WDT counter
* always decrements starting from wdt_load_value, so when used in WINDOW mode
* a counter value larger than this means that WDT was kicked before the lower
* bound of the window.
*/
static uint32_t wdt_load_window_value = 0xffffffff;
/* The value that will be loaded in the WDT counter after the first interrupt
* triggers. The WDT doesn't not reset the device automatically once the WDT
* counter reaches 0, instead it first triggers an interrupt and restarts the
* count again. This value will be loaded by the ISR after it triggers. A value
* of 0 means to reset immediately after the ISR triggers, which is used if no
* callback is provided. */
static uint32_t wdt_load_after_isr = 0;
#ifdef MODULE_PERIPH_WDT_CB
static wdt_cb_t wdt_cb;
static void *wdt_arg;
static bool wdt_kick_disabled = false;
#endif /* MODULE_PERIPH_WDT_CB */
/**
* Before making any change to the WDT it is required to "unlock" it by writing
* this value to the LOCK register. Call @ref _wdt_lock() to lock it again.
*/
static void _wdt_unlock(void)
{
WDT->LOCK = 0x1acce551;
}
/**
* @brief Lock the WDT block to prevent accidental changes.
*/
static void _wdt_lock(void)
{
WDT->LOCK = 0x10c1ced; /* Any other value is as good. */
}
void wdt_start(void)
{
CLOCK_EnableClock(kCLOCK_Wdt);
}
void wdt_stop(void)
{
/* This only stops the clock of the watchdog and therefore the counter
* stops, but leaves it otherwise configured. */
CLOCK_DisableClock(kCLOCK_Wdt);
}
void wdt_kick(void)
{
#ifdef MODULE_PERIPH_WDT_CB
if (wdt_kick_disabled) {
return;
}
#endif /* MODULE_PERIPH_WDT_CB */
if (WDT->VALUE > wdt_load_window_value) {
DEBUG("wdt_kick() called before the minimum window time.");
/* In this condition we simulate the WDT triggering immediately by
* setting its LOAD value to 0. This will cause the ISR (and the
* callback if there is one) if it wasn't called yet, which will update
* the LOAD value with the time derived from CONFIG_WDT_WARNING_PERIOD
* if needed and reset the device afterwards. */
_wdt_unlock();
WDT->LOAD = 0;
_wdt_lock();
while (true) {}
}
_wdt_unlock();
WDT->LOAD = wdt_load_value;
_wdt_lock();
}
static void wdt_setup(uint32_t min_time, uint32_t max_time, uint32_t isr_time)
{
/* Check reset time limit */
assert((max_time > NWDT_TIME_LOWER_LIMIT)
&& (max_time < NWDT_TIME_UPPER_LIMIT));
assert(min_time <= max_time);
/* The clock is stopped after setup and calling wdt_start() is required. */
wdt_stop();
const uint32_t tick_per_ms = CLOCK_GetFreq(kCLOCK_WdtClk) / 1000;
wdt_load_value = tick_per_ms * max_time;
wdt_load_window_value = tick_per_ms * (max_time - min_time);
wdt_load_after_isr = tick_per_ms * isr_time;
/* The ISR is always called as it is needed to trigger the reset after the
* appropriate delay even in the no callback case. */
_wdt_unlock();
WDT->LOAD = wdt_load_value;
WDT->CTRL = WDT_CTRL_RESEN_MASK | WDT_CTRL_INTEN_MASK;
_wdt_lock();
NVIC_EnableIRQ(WDT_IRQn);
}
void wdt_setup_reboot(uint32_t min_time, uint32_t max_time)
{
#ifdef MODULE_PERIPH_WDT_CB
wdt_cb = NULL;
wdt_arg = NULL;
#endif /* MODULE_PERIPH_WDT_CB */
wdt_setup(min_time, max_time, 0);
}
#ifdef MODULE_PERIPH_WDT_CB
void wdt_setup_reboot_with_callback(uint32_t min_time, uint32_t max_time,
wdt_cb_t cb, void *arg)
{
wdt_cb = cb;
wdt_arg = arg;
assert(max_time >= CONFIG_WDT_WARNING_PERIOD);
/* We don't support having a min_time that falls within the
* CONFIG_WDT_WARNING_PERIOD since that would mean that you can't call
* wdt_kick() until some time after the callback is called which is pretty
* useless considering that the purpose of the callback is to perform
* "specific safety operations of data logging before the actual reboot."
* before the reboot happens. After the callback is called the reboot is
* inevitable and calling wdt_kick() has no effect. This code moves the
* min_time back to at least the point where the callback is called which is
* a similar behavior. */
if (max_time - CONFIG_WDT_WARNING_PERIOD < min_time) {
min_time = max_time - CONFIG_WDT_WARNING_PERIOD;
}
wdt_setup(min_time, max_time - CONFIG_WDT_WARNING_PERIOD,
CONFIG_WDT_WARNING_PERIOD);
}
#endif /* MODULE_PERIPH_WDT_CB */
void isr_wdt(void)
{
DEBUG("[wdt] isr_wdt with LOAD=%" PRIu32 "\n", WDT->LOAD);
/* Set the timer to reset the device after CONFIG_WDT_WARNING_PERIOD but not
* clear the interrupt bit in the WDT->INT_CLR register. This will cause the
* WDT to reset the device the next time the counter reaches 0, which now
* will happen again in CONFIG_WDT_WARNING_PERIOD ms.
* Since the wdt_cb may return before the new WDT counter triggers, which is
* the normal case if we expect the callback to do some short safety
* operations, we would exit the ISR without clearing the interrupt bit in
* WDT->INT_CLR which would cause the interrupt to be called again. To avoid
* this situation, we disable the IRQ source in the NVIC.
* After this ISR triggers, further wdt_kicks() are ignored to prevent the
* software from kicking the WDT during the CONFIG_WDT_WARNING_PERIOD. */
NVIC_DisableIRQ(WDT_IRQn);
_wdt_unlock();
WDT->LOAD = wdt_load_after_isr;
_wdt_lock();
#ifdef MODULE_PERIPH_WDT_CB
wdt_kick_disabled = true;
if (wdt_cb) {
wdt_cb(wdt_arg);
}
#endif /* MODULE_PERIPH_WDT_CB */
cortexm_isr_end();
}

52
cpu/qn908x/system.c Normal file
View File

@ -0,0 +1,52 @@
/*
* 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 CMSIS system setup wrapper functions for NXP QN908x
*
* The system_QN908XC.h header is used by several vendor headers (including
* QN908XC.h which defines all the registers and some drivers). The
* system_QN908XC.c file in the vendor SDK implements the system initialization
* via the SystemInit() function and provides the current system clock
* frequency, however part of the system initialization is more appropriate in
* the board module (in `board_init`) or in the cpu module (in `cpu_init`) and
* some values like the XTAL or BUCK configuration depend on the actual board
* used while in the SDK code they are set to the QN9080DK developer module.
* Because of this we can't include that source file here.
*
* This file implements the minimum required to make some of the drivers in the
* vendor code work by providing the global SystemCoreClock variable and a
* function to update its value with the current clock configuration.
*
* @author iosabi <iosabi@protonmail.com>
*
* @}
*/
#include <stdint.h>
#include "cpu.h"
#include "vendor/drivers/fsl_clock.h"
uint32_t SystemCoreClock = DEFAULT_SYSTEM_CLOCK;
void SystemInit(void)
{
/* Do nothing here. The system initialization is done in board_init() and
* cpu_init() as needed. This function shouldn't be called anyway.
*/
}
void SystemCoreClockUpdate(void)
{
SystemCoreClock = CLOCK_GetFreq(kCLOCK_CoreSysClk);
}

77
cpu/qn908x/vectors.c Normal file
View File

@ -0,0 +1,77 @@
/*
* 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 Interrupt vector for NXP QN908x MCUs
*
* @author iosabi <iosabi@protonmail.com>
*/
/**
* @name Interrupt vector definition
* @{
*/
#include "board.h"
#include "vectors_cortexm.h"
#include "vectors_qn908x.h"
/* CPU specific interrupt vector table */
ISR_VECTOR(1) const isr_t vector_cpu[CPU_IRQ_NUMOF] = {
[EXT_GPIO_WAKEUP_IRQn] = isr_ext_gpio_wakeup, /* Ext GPIO wakeup */
[OSC_IRQn ] = isr_osc, /* BLE wakeup */
[ACMP0_IRQn ] = isr_acmp0, /* Analog comparator0 */
[ACMP1_IRQn ] = isr_acmp1, /* Analog comparator1 */
[RTC_SEC_IRQn ] = isr_rtc_sec, /* RTC second */
[RTC_FR_IRQn ] = isr_rtc_fr, /* RTC free running */
[CS_WAKEUP_IRQn ] = isr_cs_wakeup, /* Capacitive sense wakeup */
[CS_IRQn ] = isr_cs, /* Capacitive sense */
[GPIOA_IRQn ] = isr_gpioa, /* GPIO group A */
[GPIOB_IRQn ] = isr_gpiob, /* GPIO group B */
[DMA0_IRQn ] = isr_dma0, /* DMA controller */
[PIN_INT0_IRQn ] = isr_pin_int0, /* pin or pattern match engine slice 0 */
[PIN_INT1_IRQn ] = isr_pin_int1, /* pin or pattern match engine slice 1 */
[PIN_INT2_IRQn ] = isr_pin_int2, /* pin or pattern match engine slice 2 */
[PIN_INT3_IRQn ] = isr_pin_int3, /* pin or pattern match engine slice 3 */
[OSC_INT_LOW_IRQn ] = isr_osc_int_low, /* Inverse of OSC */
[USB0_IRQn ] = isr_usb0, /* USB device */
[FLEXCOMM0_IRQn ] = isr_flexcomm0, /* Flexcomm Interface 0 (USART) */
[FLEXCOMM1_IRQn ] = isr_flexcomm1, /* Flexcomm Interface 1 (USART, I2C) */
[FLEXCOMM2_IRQn ] = isr_flexcomm2, /* Flexcomm Interface 2 (SPI, I2C) */
[FLEXCOMM3_IRQn ] = isr_flexcomm3, /* Flexcomm Interface 3 (SPI) */
[BLE_IRQn ] = isr_ble, /* BLE interrupts */
[FSP_IRQn ] = isr_fsp, /* FSP */
[QDEC0_IRQn ] = isr_qdec0, /* QDEC0 */
[QDEC1_IRQn ] = isr_qdec1, /* QDEC1 */
[CTIMER0_IRQn ] = isr_ctimer0, /* Standard counter/timer CTIMER0 */
[CTIMER1_IRQn ] = isr_ctimer1, /* Standard counter/timer CTIMER1 */
[CTIMER2_IRQn ] = isr_ctimer2, /* Standard counter/timer CTIMER2 */
[CTIMER3_IRQn ] = isr_ctimer3, /* Standard counter/timer CTIMER3 */
[WDT_IRQn ] = isr_wdt, /* Watch dog timer */
[ADC_IRQn ] = isr_adc, /* ADC */
[DAC_IRQn ] = isr_dac, /* DAC */
[XTAL_READY_IRQn ] = isr_xtal_ready, /* High frequency crystal ready */
[FLASH_IRQn ] = isr_flash, /* Flash */
[SPIFI0_IRQn ] = isr_spifi0, /* SPI flash interface */
[SCT0_IRQn ] = isr_sct0, /* SCTimer/PWM */
[RNG_IRQn ] = isr_rng, /* Random number generator */
[CALIB_IRQn ] = isr_calib, /* Calibration */
[BLE_TX_IRQn ] = isr_ble_tx, /* ble tx flag */
[BLE_RX_IRQn ] = isr_ble_rx, /* ble rx flag */
[BLE_FREQ_HOP_IRQn] = isr_ble_freq_hop, /* ble frequency hop */
[BOD_IRQn ] = isr_bod, /* Brown out detect */
};
__attribute__((weak)) const uint32_t isp_configuration = 0;
/** @} */

14
cpu/qn908x/vendor/Makefile vendored Normal file
View File

@ -0,0 +1,14 @@
MODULE := vendor
# Enable submodules, although these are all compiled into the same "vendor.a"
# library since vendor_% is marked as a pseudomodule.
SUBMODULES := 1
SUBMODULES_NOFORCE := 1
CFLAGS += -Wno-unused-parameter -Wno-sign-compare
INCLUDES += \
-I$(RIOTCPU)/$(CPU)/include/vendor/ \
-I$(RIOTCPU)/$(CPU)/include/vendor/drivers/ \
#
include $(RIOTBASE)/Makefile.base

334
cpu/qn908x/vendor/fsl_clock.c vendored Normal file
View File

@ -0,0 +1,334 @@
/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright (c) 2016 - 2017 , NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_clock.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define getSysconClkMux() ((SYSCON->CLK_CTRL & SYSCON_CLK_CTRL_SYS_CLK_SEL_MASK) >> SYSCON_CLK_CTRL_SYS_CLK_SEL_SHIFT)
/*******************************************************************************
* Variables
******************************************************************************/
typedef union
{
struct
{
uint8_t crcClkRefCnt;
uint8_t dmaClkRefCnt;
} ref_cnt_t;
uint8_t clkRefCnt[2];
} clock_ref_cnt_t;
/** Clock reference count */
static clock_ref_cnt_t clk_ref_cnt;
/*******************************************************************************
* Code
******************************************************************************/
static void Clk32KConfig(uint8_t choice)
{
SYSCON->CLK_CTRL = (SYSCON->CLK_CTRL & ~SYSCON_CLK_CTRL_CLK_32K_SEL_MASK) | SYSCON_CLK_CTRL_CLK_32K_SEL(choice);
}
static void ClkSysConfig(uint8_t choice)
{
if (choice == 0)
{
/* RCO 32MHz ,wait for ready */
while (!(SYSCON->SYS_MODE_CTRL & SYSCON_SYS_MODE_CTRL_OSC32M_RDY_MASK))
{
}
}
/* Switch to the clock source */
SYSCON->CLK_CTRL = (SYSCON->CLK_CTRL & ~SYSCON_CLK_CTRL_SYS_CLK_SEL_MASK) | SYSCON_CLK_CTRL_SYS_CLK_SEL(choice);
}
static void ClkWdtConfig(uint8_t choice)
{
SYSCON->CLK_CTRL = (SYSCON->CLK_CTRL & ~SYSCON_CLK_CTRL_CLK_WDT_SEL_MASK) | SYSCON_CLK_CTRL_CLK_WDT_SEL(choice);
}
static void ClkBleConfig(uint8_t choice)
{
SYSCON->CLK_CTRL = (SYSCON->CLK_CTRL & ~SYSCON_CLK_CTRL_CLK_BLE_SEL_MASK) | SYSCON_CLK_CTRL_CLK_BLE_SEL(choice);
}
static void ClkXTALConfig(uint8_t choice)
{
switch (choice)
{
/* 16M XTAL */
case 0:
SYSCON->CLK_CTRL &= ~SYSCON_CLK_CTRL_CLK_XTAL_SEL_MASK;
break;
/* 32M XTAL */
case 1:
SYSCON->CLK_CTRL |= SYSCON_CLK_CTRL_CLK_XTAL_SEL_MASK;
break;
default:
break;
}
/* wait for ready */
while (!(SYSCON->SYS_MODE_CTRL & SYSCON_SYS_MODE_CTRL_XTAL_RDY_MASK))
{
}
}
void CLOCK_EnableClock(clock_ip_name_t clk)
{
uint32_t regPrimask = 0U;
if ((clk == kCLOCK_Crc) || (clk == kCLOCK_Dma))
{
regPrimask = DisableGlobalIRQ();
clk_ref_cnt.clkRefCnt[clk - kCLOCK_Crc] += 1U;
EnableGlobalIRQ(regPrimask);
}
SYSCON->CLK_EN = (1U << clk);
}
void CLOCK_DisableClock(clock_ip_name_t clk)
{
uint32_t regPrimask = 0U;
if (((clk == kCLOCK_Crc) || (clk == kCLOCK_Dma)) && (clk_ref_cnt.clkRefCnt[clk - kCLOCK_Crc] > 0))
{
regPrimask = DisableGlobalIRQ();
clk_ref_cnt.clkRefCnt[clk - kCLOCK_Crc] -= 1U;
EnableGlobalIRQ(regPrimask);
if (clk_ref_cnt.clkRefCnt[clk - kCLOCK_Crc] > 0)
{
return;
}
}
SYSCON->CLK_DIS = (1U << clk);
}
void CLOCK_AttachClk(clock_attach_id_t connection)
{
uint8_t mux, choice;
mux = (uint8_t)connection;
choice = (uint8_t)(((connection & 0xf00) >> 8) - 1);
switch (mux)
{
case CM_32KCLKSEL:
Clk32KConfig(choice);
break;
case CM_SYSCLKSEL:
ClkSysConfig(choice);
break;
case CM_WDTCLKSEL:
ClkWdtConfig(choice);
break;
case CM_BLECLKSEL:
ClkBleConfig(choice);
break;
case CM_XTALCLKSEL:
ClkXTALConfig(choice);
break;
default:
break;
}
}
void CLOCK_SetClkDiv(clock_div_name_t div_name, uint32_t divided_by_value)
{
switch (div_name)
{
case kCLOCK_DivXtalClk:
/* F(XTAL) = F(XTAL) / (divided_by_value + 1), occupy 1 bit, take effect only when k32M_to_XTAL_CLK attached */
SYSCON->XTAL_CTRL =
(SYSCON->XTAL_CTRL & ~SYSCON_XTAL_CTRL_XTAL_DIV_MASK) | SYSCON_XTAL_CTRL_XTAL_DIV(divided_by_value);
break;
case kCLOCK_DivOsc32mClk:
/* F(OSC32M) = F(OSC32M) / (divided_by_value + 1), occupy 1 bit */
SYSCON->CLK_CTRL = (SYSCON->CLK_CTRL & ~SYSCON_CLK_CTRL_CLK_OSC32M_DIV_MASK) |
SYSCON_CLK_CTRL_CLK_OSC32M_DIV(divided_by_value);
break;
case kCLOCK_DivAhbClk:
/* F(AHB) = F(SYS) / (divided_by_value + 1), occupy 13 bits
* Note: If ble core's clock is enabled by setting SYSCON_CLK_EN_CLK_BLE_EN to 1, ahb clock can only be 8M,
* 16M or 32M.
*/
SYSCON->CLK_CTRL =
(SYSCON->CLK_CTRL & ~SYSCON_CLK_CTRL_AHB_DIV_MASK) | SYSCON_CLK_CTRL_AHB_DIV(divided_by_value);
break;
case kCLOCK_DivApbClk:
/* F(APB) = F(AHB) / (divided_by_value + 1), occupy 4 bits */
SYSCON->CLK_CTRL =
(SYSCON->CLK_CTRL & ~SYSCON_CLK_CTRL_APB_DIV_MASK) | SYSCON_CLK_CTRL_APB_DIV(divided_by_value);
break;
case kCLOCK_DivFrg0:
/* F(Flexcomm0) = F(AHB) / (1 + MULT/DIV), DIV = 0xFF */
SYSCON->FC_FRG = (SYSCON->FC_FRG & ~SYSCON_FC_FRG_FRG_MULT0_MASK) |
SYSCON_FC_FRG_FRG_MULT0(divided_by_value) | SYSCON_FC_FRG_FRG_DIV0_MASK;
break;
case kCLOCK_DivFrg1:
/* F(Flexcomm1) = F(AHB) / (1 + MULT/DIV), DIV = 0xFF */
SYSCON->FC_FRG = (SYSCON->FC_FRG & ~SYSCON_FC_FRG_FRG_MULT1_MASK) |
SYSCON_FC_FRG_FRG_MULT1(divided_by_value) | SYSCON_FC_FRG_FRG_DIV1_MASK;
break;
case kCLOCK_DivClkOut:
/* F(ClkOut) = F(XTAL) / (2 * divided_by_value), occupy 4bits, take effect only when clock out source is
* XTAL */
SYSCON->CLK_CTRL = (SYSCON->CLK_CTRL & ~SYSCON_CLK_CTRL_XTAL_OUT_DIV_MASK) |
SYSCON_CLK_CTRL_XTAL_OUT_DIV(divided_by_value);
break;
default:
break;
}
}
static uint32_t CLOCK_GetRco32MFreq(void)
{
return (SYSCON->CLK_CTRL & SYSCON_CLK_CTRL_CLK_OSC32M_DIV_MASK) ? CLK_OSC_32MHZ / 2 : CLK_OSC_32MHZ;
}
static uint32_t CLOCK_GetXinFreq(void)
{
return ((SYSCON->CLK_CTRL & SYSCON_CLK_CTRL_CLK_XTAL_SEL_MASK) &&
(!(SYSCON->XTAL_CTRL & SYSCON_XTAL_CTRL_XTAL_DIV_MASK))) ?
CLK_XTAL_32MHZ :
CLK_XTAL_16MHZ;
}
static uint32_t CLOCK_Get32KFreq(void)
{
return (SYSCON->CLK_CTRL & SYSCON_CLK_CTRL_CLK_32K_SEL_MASK) ? CLK_RCO_32KHZ : CLK_XTAL_32KHZ;
}
static uint32_t CLOCK_GetCoreSysClkFreq(void)
{
return (getSysconClkMux() == 0) ? CLOCK_GetRco32MFreq() : (getSysconClkMux() == 1) ?
CLOCK_GetXinFreq() :
(getSysconClkMux() == 2) ? CLOCK_Get32KFreq() : 0;
}
static uint32_t CLOCK_GetAhbClkFreq(void)
{
return CLOCK_GetCoreSysClkFreq() /
(((SYSCON->CLK_CTRL & SYSCON_CLK_CTRL_AHB_DIV_MASK) >> SYSCON_CLK_CTRL_AHB_DIV_SHIFT) + 1);
}
static uint32_t CLOCK_GetApbClkFreq(void)
{
return CLOCK_GetAhbClkFreq() /
(((SYSCON->CLK_CTRL & SYSCON_CLK_CTRL_APB_DIV_MASK) >> SYSCON_CLK_CTRL_APB_DIV_SHIFT) + 1);
}
static uint32_t CLOCK_GetWdtFreq(void)
{
return (SYSCON->CLK_CTRL & SYSCON_CLK_CTRL_CLK_WDT_SEL_MASK) ? CLOCK_GetApbClkFreq() : CLOCK_Get32KFreq();
}
uint32_t CLOCK_GetFreq(clock_name_t clk)
{
uint32_t freq;
switch (clk)
{
case kCLOCK_CoreSysClk:
freq = CLOCK_GetCoreSysClkFreq();
break;
case kCLOCK_BusClk:
freq = CLOCK_GetAhbClkFreq();
break;
case kCLOCK_ApbClk:
freq = CLOCK_GetApbClkFreq();
break;
case kCLOCK_WdtClk:
freq = CLOCK_GetWdtFreq();
break;
case kCLOCK_FroHf:
freq = CLOCK_GetRco32MFreq();
break;
case kCLOCK_Xin:
freq = CLOCK_GetXinFreq();
break;
case kCLOCK_32KClk:
freq = CLOCK_Get32KFreq();
break;
default:
freq = 0;
break;
}
return freq;
}
bool CLOCK_EnableUsbfs0DeviceClock(clock_usb_src_t src, uint32_t freq)
{
CLOCK_EnableClock(kCLOCK_Usbd0);
return true;
}
void CLOCK_EnableClkoutSource(uint32_t mask, bool enable)
{
if (enable)
{
SYSCON->CLK_CTRL |= mask;
}
else
{
SYSCON->CLK_CTRL &= ~mask;
}
}
void CLOCK_EnableClkoutPin(uint32_t mask, bool enable)
{
if (enable)
{
SYSCON->PIO_WAKEUP_EN1 |= mask;
}
else
{
SYSCON->PIO_WAKEUP_EN1 &= ~mask;
}
}
uint32_t CLOCK_GetFRGInputClock(void)
{
return CLOCK_GetFreq(kCLOCK_BusClk);
}
uint32_t CLOCK_SetFRGClock(clock_div_name_t div_name, uint32_t freq)
{
uint32_t input = CLOCK_GetFRGInputClock();
uint32_t mul;
if ((freq > 32000000) || (freq > input) || (input / freq >= 2))
{
/* FRG output frequency should be less than equal to 32MHz */
return 0;
}
else
{
mul = ((uint64_t)(input - freq) * 256) / ((uint64_t)freq);
if (div_name == kCLOCK_DivFrg0)
{
SYSCON->FC_FRG = (SYSCON->FC_FRG & ~SYSCON_FC_FRG_FRG_MULT0_MASK) | SYSCON_FC_FRG_FRG_MULT0(mul) |
SYSCON_FC_FRG_FRG_DIV0_MASK;
}
else if (div_name == kCLOCK_DivFrg1)
{
SYSCON->FC_FRG = (SYSCON->FC_FRG & ~SYSCON_FC_FRG_FRG_MULT1_MASK) | SYSCON_FC_FRG_FRG_MULT1(mul) |
SYSCON_FC_FRG_FRG_DIV1_MASK;
}
else
{
/* Add for avoid the misra 2004 rule 14.10 */
}
return 1;
}
}