From 50c7b5c11a3ca796fbfa37446296178efc4b49e9 Mon Sep 17 00:00:00 2001 From: Jose Alamos Date: Wed, 12 Dec 2018 15:28:48 +0100 Subject: [PATCH] boards/phynode-kw41z: add initial support --- boards/phynode-kw41z/Makefile | 3 + boards/phynode-kw41z/Makefile.dep | 6 + boards/phynode-kw41z/Makefile.features | 16 ++ boards/phynode-kw41z/Makefile.include | 17 ++ boards/phynode-kw41z/board.c | 48 ++++ boards/phynode-kw41z/include/adc_params.h | 58 +++++ boards/phynode-kw41z/include/board.h | 108 +++++++++ boards/phynode-kw41z/include/gpio_params.h | 83 +++++++ boards/phynode-kw41z/include/periph_conf.h | 254 +++++++++++++++++++++ 9 files changed, 593 insertions(+) create mode 100644 boards/phynode-kw41z/Makefile create mode 100644 boards/phynode-kw41z/Makefile.dep create mode 100644 boards/phynode-kw41z/Makefile.features create mode 100644 boards/phynode-kw41z/Makefile.include create mode 100644 boards/phynode-kw41z/board.c create mode 100644 boards/phynode-kw41z/include/adc_params.h create mode 100644 boards/phynode-kw41z/include/board.h create mode 100644 boards/phynode-kw41z/include/gpio_params.h create mode 100644 boards/phynode-kw41z/include/periph_conf.h diff --git a/boards/phynode-kw41z/Makefile b/boards/phynode-kw41z/Makefile new file mode 100644 index 0000000000..f8fcbb53a0 --- /dev/null +++ b/boards/phynode-kw41z/Makefile @@ -0,0 +1,3 @@ +MODULE = board + +include $(RIOTBASE)/Makefile.base diff --git a/boards/phynode-kw41z/Makefile.dep b/boards/phynode-kw41z/Makefile.dep new file mode 100644 index 0000000000..a73981801a --- /dev/null +++ b/boards/phynode-kw41z/Makefile.dep @@ -0,0 +1,6 @@ +ifneq (,$(filter saul_default,$(USEMODULE))) + USEMODULE += saul_gpio + USEMODULE += saul_adc +endif + +include $(RIOTCPU)/kinetis/Makefile.dep diff --git a/boards/phynode-kw41z/Makefile.features b/boards/phynode-kw41z/Makefile.features new file mode 100644 index 0000000000..3463bf7b1c --- /dev/null +++ b/boards/phynode-kw41z/Makefile.features @@ -0,0 +1,16 @@ +# Put defined MCU peripherals here (in alphabetical order) +FEATURES_PROVIDED += periph_adc +FEATURES_PROVIDED += periph_i2c +FEATURES_PROVIDED += periph_rtc +FEATURES_PROVIDED += periph_rtt +FEATURES_PROVIDED += periph_spi +FEATURES_PROVIDED += periph_timer +FEATURES_PROVIDED += periph_uart + +# The board MPU family (used for grouping by the CI system) +FEATURES_MCU_GROUP = cortex_m0_2 + +include $(RIOTCPU)/kinetis/Makefile.features +# +# Remove this line after TRNG driver is implemented +FEATURES_PROVIDED := $(filter-out periph_hwrng,$(FEATURES_PROVIDED)) diff --git a/boards/phynode-kw41z/Makefile.include b/boards/phynode-kw41z/Makefile.include new file mode 100644 index 0000000000..bdd30ee32d --- /dev/null +++ b/boards/phynode-kw41z/Makefile.include @@ -0,0 +1,17 @@ +# define the cpu used by the board +export CPU = kinetis +export CPU_MODEL = mkw41z512vht4 + +# use openocd by default to program this board +PROGRAMMER ?= openocd + +# dap debug adapter is required for openocd +ifeq (openocd,$(PROGRAMMER)) +DEBUG_ADAPTER = dap +endif + +# Enable direct write to FCF (required for setting FOPT byte). +export OPENOCD_PRE_FLASH_CMDS += "-c kinetis fcf_source write" + +# Include default FRDM board config +include $(RIOTBOARD)/common/frdm/Makefile.include diff --git a/boards/phynode-kw41z/board.c b/boards/phynode-kw41z/board.c new file mode 100644 index 0000000000..61cdf78795 --- /dev/null +++ b/boards/phynode-kw41z/board.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2018 Eistec AB + * Copyright (C) HAW Hamburg + * + * 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_phynode-kw41z + * @{ + * + * @file + * @brief Board specific initialization for the PhyNODE KW41Z + * + * @author Joakim Nohlgård + * @author José Alamos + * + * @} + */ + +#include "board.h" +#include "periph/gpio.h" + +void board_init(void) +{ + /* initialize the CPU core */ + cpu_init(); + + /* initialize and turn off LEDs */ +#ifdef LED0_PIN + gpio_init(LED0_PIN, GPIO_OUT); + gpio_set(LED0_PIN); +#endif +#ifdef LED1_PIN + gpio_init(LED1_PIN, GPIO_OUT); + gpio_set(LED1_PIN); +#endif +#ifdef LED2_PIN + gpio_init(LED2_PIN, GPIO_OUT); + gpio_set(LED2_PIN); +#endif +#ifdef LED3_PIN + gpio_init(LED3_PIN, GPIO_OUT); + gpio_set(LED3_PIN); +#endif +} diff --git a/boards/phynode-kw41z/include/adc_params.h b/boards/phynode-kw41z/include/adc_params.h new file mode 100644 index 0000000000..925e38bb73 --- /dev/null +++ b/boards/phynode-kw41z/include/adc_params.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2017 Eistec AB + * Copyright (C) 2018 HAW Hamburg + * + * 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_phynode-kw41z + * @{ + * + * @file + * @brief Board specific configuration of direct mapped ADC + * + * @author Joakim Nohlgård + * @author José Alamos + */ + +#ifndef ADC_PARAMS_H +#define ADC_PARAMS_H + +#include "board.h" +#include "saul/periph.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief ADC configuration + */ +static const saul_adc_params_t saul_adc_params[] = +{ + { + .name = "coretemp", + .line = ADC_LINE(0), + .res = ADC_RES_16BIT, + }, + { + .name = "corebandgap", + .line = ADC_LINE(1), + .res = ADC_RES_16BIT, + }, + { + .name = "dcdcvbat", + .line = ADC_LINE(2), + .res = ADC_RES_16BIT, + }, +}; + +#ifdef __cplusplus +} +#endif + +#endif /* ADC_PARAMS_H */ +/** @} */ diff --git a/boards/phynode-kw41z/include/board.h b/boards/phynode-kw41z/include/board.h new file mode 100644 index 0000000000..2fc4cb13ed --- /dev/null +++ b/boards/phynode-kw41z/include/board.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2018 Eistec AB + * Copyright (C) 2018 HAW Hamburg + * + * 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_phynode-kw41z + * @{ + * + * @file + * @brief Board specific definitions for the USB-KW41Z + * + * @author Joakim Nohlgård + * @author José Alamos + */ + +#ifndef BOARD_H +#define BOARD_H + +#include "cpu.h" +#include "periph_conf.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Set the FOPT bit to disable NMI so that we can use it as a GPIO pin for + * the LED (PTB18) */ +#define KINETIS_FOPT (0xff & ~(NV_FOPT_NMI_DIS_MASK)) + +/** + * @name LED pin definitions and handlers + * @{ + */ +#define LED0_PIN GPIO_PIN(PORT_B, 3) +#define LED0_MASK (1 << 3) +#define LED0_ON (GPIOB->PCOR = LED0_MASK) +#define LED0_OFF (GPIOB->PSOR = LED0_MASK) +#define LED0_TOGGLE (GPIOB->PTOR = LED0_MASK) + + +#define LED1_PIN GPIO_PIN(PORT_B, 1) +#define LED1_MASK (1 << 1) +#define LED1_ON (GPIOB->PCOR = LED1_MASK) +#define LED1_OFF (GPIOB->PSOR = LED1_MASK) +#define LED1_TOGGLE (GPIOB->PTOR = LED1_MASK) + +#define LED2_PIN GPIO_PIN(PORT_B, 0) +#define LED2_MASK (1 << 0) +#define LED2_ON (GPIOB->PCOR = LED2_MASK) +#define LED2_OFF (GPIOB->PSOR = LED2_MASK) +#define LED2_TOGGLE (GPIOB->PTOR = LED2_MASK) + +#define LED3_PIN GPIO_PIN(PORT_B, 18) +#define LED3_MASK (1 << 18) +#define LED3_ON (GPIOB->PCOR = LED3_MASK) +#define LED3_OFF (GPIOB->PSOR = LED3_MASK) +#define LED3_TOGGLE (GPIOB->PTOR = LED3_MASK) + +/** + * @name Button pin definitions + * @{ + */ +/* Pressing SW1 will short this pin to ground but there are no external pull + * resistors, use internal pull-up on the pin */ +/* BTN0 is mapped to SW1 */ +#define BTN0_PIN GPIO_PIN(PORT_C, 5) +#define BTN0_MODE GPIO_IN_PU +/** @} */ + +/** + * @name xtimer configuration + * @{ + */ +#if KINETIS_XTIMER_SOURCE_PIT +/* PIT xtimer configuration */ +#define XTIMER_DEV (TIMER_PIT_DEV(0)) +#define XTIMER_CHAN (0) +/* Default xtimer settings should work on the PIT */ +#else +/* LPTMR xtimer configuration */ +#define XTIMER_DEV (TIMER_LPTMR_DEV(0)) +#define XTIMER_CHAN (0) +/* LPTMR is 16 bits wide and runs at 32768 Hz (clocked by the RTC) */ +#define XTIMER_WIDTH (16) +#define XTIMER_BACKOFF (5) +#define XTIMER_ISR_BACKOFF (5) +#define XTIMER_OVERHEAD (4) +#define XTIMER_HZ (32768ul) +#endif +/** @} */ + +/** + * @brief Initialize board specific hardware, including clock, LEDs and standard I/O + */ +void board_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* BOARD_H */ +/** @} */ diff --git a/boards/phynode-kw41z/include/gpio_params.h b/boards/phynode-kw41z/include/gpio_params.h new file mode 100644 index 0000000000..6fd7e38d08 --- /dev/null +++ b/boards/phynode-kw41z/include/gpio_params.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2018 Eistec AB + * Copyright (C) 2018 HAW Hamburg + * + * 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_phynode-kw41z + * @{ + * + * @file + * @brief Board specific configuration of direct mapped GPIOs + * + * @author Joakim Nohlgård + * @author José Alamos + */ + +#ifndef GPIO_PARAMS_H +#define GPIO_PARAMS_H + +#include "board.h" +#include "saul/periph.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief LED configuration + */ +static const saul_gpio_params_t saul_gpio_params[] = +{ + /* There are 2 user controlled LEDs on board. An orange LED (D2) and an + * RGB LED (D10). The RGB LED is configured with 3 LEDx macros. */ +#ifdef LED0_PIN + { + .name = "D2 (Orange)", + .pin = LED0_PIN, + .mode = GPIO_OUT, + .flags = (SAUL_GPIO_INVERTED | SAUL_GPIO_INIT_CLEAR), + }, +#endif /* LED0_PIN */ +#ifdef LED1_PIN + { + .name = "D10 RGB (Red)", + .pin = LED1_PIN, + .mode = GPIO_OUT, + .flags = (SAUL_GPIO_INVERTED | SAUL_GPIO_INIT_CLEAR), + }, +#endif /* LED1_PIN */ +#ifdef LED2_PIN + { + .name = "D10 RGB (Green)", + .pin = LED2_PIN, + .mode = GPIO_OUT, + .flags = (SAUL_GPIO_INVERTED | SAUL_GPIO_INIT_CLEAR), + }, +#endif /* LED1_PIN */ +#ifdef LED3_PIN + { + .name = "D10 RGB (Blue)", + .pin = LED3_PIN, + .mode = GPIO_OUT, + .flags = (SAUL_GPIO_INVERTED | SAUL_GPIO_INIT_CLEAR), + }, +#endif /* LED1_PIN */ + { + .name = "S2 (Button)", + .pin = BTN0_PIN, + .mode = BTN0_MODE, + .flags = (SAUL_GPIO_INVERTED), + }, +}; + +#ifdef __cplusplus +} +#endif + +#endif /* GPIO_PARAMS_H */ +/** @} */ diff --git a/boards/phynode-kw41z/include/periph_conf.h b/boards/phynode-kw41z/include/periph_conf.h new file mode 100644 index 0000000000..7754cf873c --- /dev/null +++ b/boards/phynode-kw41z/include/periph_conf.h @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2018 Eistec AB + * Copyright (C) 2018 HAW Hamburg + * + * 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_phynode-kw41z + * @{ + * + * @file + * @name Peripheral MCU configuration for the PhyNODE KW41Z + * + * @author Joakim Nohlgård + * @author José Alamos + */ + +#ifndef PERIPH_CONF_H +#define PERIPH_CONF_H + +#include "periph_cpu.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @name Clock system configuration + * @{ + */ +static const clock_config_t clock_config = { + /* + * This configuration results in the system running with the internal clock + * with the following clock frequencies: + * Core: 41.94 MHz + * Bus: 20.97 MHz + * Flash: 20.97 MHz + */ + .clkdiv1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV4(1), + /* unsure if this RTC load cap configuration is correct, but it matches the + * settings used by the example code in the NXP provided SDK */ + .rtc_clc = 0, + /* Use the 32 kHz oscillator as ERCLK32K. Note that the values here have a + * different mapping for the KW41Z than the values used in the Kinetis K series */ + .osc32ksel = SIM_SOPT1_OSC32KSEL(0), + .clock_flags = + KINETIS_CLOCK_OSC0_EN | /* Enable RSIM oscillator */ + KINETIS_CLOCK_RTCOSC_EN | + KINETIS_CLOCK_USE_FAST_IRC | + KINETIS_CLOCK_MCGIRCLK_EN | /* Used for LPUART clocking */ + KINETIS_CLOCK_MCGIRCLK_STOP_EN | + 0, + /* Using FEI mode by default, the external crystal settings below are only + * used if mode is changed to an external mode (PEE, FBE, or FEE) */ + .default_mode = KINETIS_MCG_MODE_FEI, + /* The crystal connected to RSIM OSC is 32 MHz */ + .erc_range = KINETIS_MCG_ERC_RANGE_VERY_HIGH, + .osc_clc = 0, /* no load cap configuration */ + .oscsel = MCG_C7_OSCSEL(0), /* Use RSIM for external clock */ + .fcrdiv = MCG_SC_FCRDIV(0), /* Fast IRC divide by 1 => 4 MHz */ + .fll_frdiv = MCG_C1_FRDIV(0b101), /* Divide by 1024 */ + .fll_factor_fei = KINETIS_MCG_FLL_FACTOR_1280, /* FEI FLL freq = 41.94 MHz */ + .fll_factor_fee = KINETIS_MCG_FLL_FACTOR_1280, /* FEE FLL freq = 40 MHz */ +}; +/* Radio xtal frequency, either 32 MHz or 26 MHz */ +#define CLOCK_RADIOXTAL (32000000ul) +/* CPU core clock, the MCG clock output frequency */ +#define CLOCK_CORECLOCK (32768 * 1280) +#define CLOCK_BUSCLOCK (CLOCK_CORECLOCK / 2) +#define CLOCK_MCGIRCLK (4000000ul) +/** @} */ + +/** + * @name Timer configuration + * @{ + */ +#define PIT_NUMOF (1U) +#define PIT_CONFIG { \ + { \ + .prescaler_ch = 0, \ + .count_ch = 1, \ + }, \ + } +#define LPTMR_NUMOF (1U) +#define LPTMR_CONFIG { \ + { \ + .dev = LPTMR0, \ + .irqn = LPTMR0_IRQn, \ + .src = 2, \ + .base_freq = 32768u, \ + } \ + } +#define TIMER_NUMOF ((PIT_NUMOF) + (LPTMR_NUMOF)) +#define PIT_BASECLOCK (CLOCK_BUSCLOCK) +#define LPTMR_ISR_0 isr_lptmr0 +/** @} */ + +/** + * @name UART configuration + * @{ + */ +static const uart_conf_t uart_config[] = { + { + .dev = LPUART0, + .freq = CLOCK_MCGIRCLK, + .pin_rx = GPIO_PIN(PORT_C, 6), + .pin_tx = GPIO_PIN(PORT_C, 7), + .pcr_rx = PORT_PCR_MUX(4), + .pcr_tx = PORT_PCR_MUX(4), + .irqn = LPUART0_IRQn, + .scgc_addr = &SIM->SCGC5, + .scgc_bit = SIM_SCGC5_LPUART0_SHIFT, + .mode = UART_MODE_8N1, + .type = KINETIS_LPUART, + }, +}; +#define UART_NUMOF (sizeof(uart_config) / sizeof(uart_config[0])) +#define LPUART_0_ISR isr_lpuart0 +/* Use MCGIRCLK (internal reference 4 MHz clock) */ +#define LPUART_0_SRC 3 +/** @} */ + +/** + * @name ADC configuration + * @{ + */ +static const adc_conf_t adc_config[] = { + /* dev, pin, channel */ + /* internal: temperature sensor */ + /* The temperature sensor has a very high output impedance, it must not be + * sampled using hardware averaging, or the sampled values will be garbage */ + [ 0] = { .dev = ADC0, .pin = GPIO_UNDEF, .chan = 26, .avg = ADC_AVG_NONE }, + /* Note: the band gap buffer uses a bit of current and is turned off by default, + * Set PMC->REGSC |= PMC_REGSC_BGBE_MASK before reading or the input will be floating */ + /* internal: band gap */ + [ 1] = { .dev = ADC0, .pin = GPIO_UNDEF, .chan = 27, .avg = ADC_AVG_MAX }, + /* internal: DCDC divided battery level */ + [ 2] = { .dev = ADC0, .pin = GPIO_UNDEF, .chan = 23, .avg = ADC_AVG_MAX }, +}; +#define ADC_NUMOF (sizeof(adc_config) / sizeof(adc_config[0])) +/* + * KW41Z ADC reference settings: + * 0: VREFH external pin or VREF_OUT 1.2 V signal (if VREF module is enabled) + * 1: VDDA (analog supply input voltage) + * 2-3: reserved + * + * VREF_OUT and VREFH shares the pin on KW41Z and is tied to VDDA on the + * USB-KW41Z board, so it does not matter which setting is chosen here for this + * board. + */ +#define ADC_REF_SETTING 1 +/** @} */ + +/** + * @name SPI configuration + * + * Clock configuration values based on the configured 20.97 MHz module clock. + * + * Auto-generated by: + * cpu/kinetis/dist/calc_spi_scalers/calc_spi_scalers.c + * +* @{ +*/ +static const uint32_t spi_clk_config[] = { + ( + SPI_CTAR_PBR(3) | SPI_CTAR_BR(5) | /* -> 93622Hz */ + SPI_CTAR_PCSSCK(3) | SPI_CTAR_CSSCK(4) | + SPI_CTAR_PASC(3) | SPI_CTAR_ASC(4) | + SPI_CTAR_PDT(3) | SPI_CTAR_DT(4) + ), + ( + SPI_CTAR_PBR(3) | SPI_CTAR_BR(3) | /* -> 374491Hz */ + SPI_CTAR_PCSSCK(3) | SPI_CTAR_CSSCK(2) | + SPI_CTAR_PASC(3) | SPI_CTAR_ASC(2) | + SPI_CTAR_PDT(3) | SPI_CTAR_DT(2) + ), + ( + SPI_CTAR_PBR(1) | SPI_CTAR_BR(3) | /* -> 873813Hz */ + SPI_CTAR_PCSSCK(1) | SPI_CTAR_CSSCK(2) | + SPI_CTAR_PASC(1) | SPI_CTAR_ASC(2) | + SPI_CTAR_PDT(1) | SPI_CTAR_DT(2) + ), + ( + SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | /* -> 3495253Hz */ + SPI_CTAR_PCSSCK(1) | SPI_CTAR_CSSCK(0) | + SPI_CTAR_PASC(1) | SPI_CTAR_ASC(0) | + SPI_CTAR_PDT(1) | SPI_CTAR_DT(0) + ), + ( + SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | /* -> 5242880Hz */ + SPI_CTAR_PCSSCK(0) | SPI_CTAR_CSSCK(1) | + SPI_CTAR_PASC(0) | SPI_CTAR_ASC(1) | + SPI_CTAR_PDT(0) | SPI_CTAR_DT(1) + ) +}; + +static const spi_conf_t spi_config[] = { + { + .dev = SPI1, + .pin_miso = GPIO_PIN(PORT_A, 17), + .pin_mosi = GPIO_PIN(PORT_A, 16), + .pin_clk = GPIO_PIN(PORT_A, 18), + .pin_cs = { + GPIO_PIN(PORT_A, 19), + GPIO_UNDEF, + GPIO_UNDEF, + GPIO_UNDEF, + GPIO_UNDEF + }, + .pcr = GPIO_AF_2, + .simmask = SIM_SCGC6_SPI1_MASK + } +}; +#define SPI_NUMOF (sizeof(spi_config) / sizeof(spi_config[0])) +/** @} */ + + +/** +* @name I2C configuration +* @{ +*/ +static const i2c_conf_t i2c_config[] = { + { + .i2c = I2C1, + .scl_pin = GPIO_PIN(PORT_C, 2), + .sda_pin = GPIO_PIN(PORT_C, 3), + .freq = CLOCK_CORECLOCK, + .speed = I2C_SPEED_FAST, + .irqn = I2C1_IRQn, + .scl_pcr = (PORT_PCR_MUX(3)), + .sda_pcr = (PORT_PCR_MUX(3)), + }, +}; +#define I2C_NUMOF (sizeof(i2c_config) / sizeof(i2c_config[0])) +#define I2C_0_ISR (isr_i2c1) +/** @} */ + +/** + * @name Random Number Generator configuration + * @{ + */ +#define KINETIS_TRNG TRNG +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* PERIPH_CONF_H */ +/** @} */