mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-18 12:52:44 +01:00
Merge pull request #6995 from gebart/pr/frdm-kw41z
cpu+board: Add support for NXP Kinetis KW41Z and FRDM-KW41Z development board
This commit is contained in:
commit
ab0a2f7033
24
boards/common/frdm/dist/openocd-klx.cfg
vendored
Normal file
24
boards/common/frdm/dist/openocd-klx.cfg
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
#
|
||||
# NXP Kinetis Freedom developer board
|
||||
#
|
||||
# OpenSDA is the on-board debugger, some boards have a CMSIS-DAP compatible
|
||||
# interface, other boards comes pre-flashed with a Segger J-Link compatible
|
||||
# firmware. The OpenSDA controller can be re-flashed to provide either of the two.
|
||||
# Both interfaces work with OpenOCD, but we need to tell which one we have on
|
||||
# our debugger.
|
||||
|
||||
# CMSIS-DAP (DAPLink) compatible OpenSDA firmware binary images can be found at:
|
||||
# http://www.nxp.com/opensda
|
||||
|
||||
# Kinetis L only supports SWD
|
||||
transport select swd
|
||||
|
||||
# Kinetis L series CPUs
|
||||
source [find target/klx.cfg]
|
||||
|
||||
reset_config srst_only
|
||||
|
||||
$_TARGETNAME configure -event gdb-attach {
|
||||
halt
|
||||
}
|
||||
$_TARGETNAME configure -rtos auto
|
3
boards/frdm-kw41z/Makefile
Normal file
3
boards/frdm-kw41z/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE = board
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
6
boards/frdm-kw41z/Makefile.dep
Normal file
6
boards/frdm-kw41z/Makefile.dep
Normal file
@ -0,0 +1,6 @@
|
||||
ifneq (,$(filter saul_default,$(USEMODULE)))
|
||||
USEMODULE += saul_gpio
|
||||
USEMODULE += saul_adc
|
||||
endif
|
||||
|
||||
include $(RIOTCPU)/kinetis/Makefile.dep
|
15
boards/frdm-kw41z/Makefile.features
Normal file
15
boards/frdm-kw41z/Makefile.features
Normal file
@ -0,0 +1,15 @@
|
||||
# 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))
|
13
boards/frdm-kw41z/Makefile.include
Normal file
13
boards/frdm-kw41z/Makefile.include
Normal file
@ -0,0 +1,13 @@
|
||||
# define the cpu used by the board
|
||||
export CPU = kinetis
|
||||
export CPU_MODEL = mkw41z512vht4
|
||||
|
||||
# OpenOCD v0.10.0-dev (current development version) or later is required for
|
||||
# flashing KW41Z devices
|
||||
# See http://openocd.zylin.com/#/c/4104/ for the upstreaming process
|
||||
export USE_OLD_OPENOCD ?= 0
|
||||
# This board comes with OpenSDA configured for JLink compatibility
|
||||
export DEBUG_ADAPTER ?= jlink
|
||||
|
||||
# Include default FRDM board config
|
||||
include $(RIOTBOARD)/common/frdm/Makefile.include
|
44
boards/frdm-kw41z/board.c
Normal file
44
boards/frdm-kw41z/board.c
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Eistec AB
|
||||
*
|
||||
* 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_frdm-kw41z
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Board specific initialization for the FRDM-KW41Z
|
||||
*
|
||||
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "board.h"
|
||||
#include "periph/gpio.h"
|
||||
#include "periph/rtt.h"
|
||||
|
||||
void board_init(void)
|
||||
{
|
||||
/* initialize the CPU core */
|
||||
cpu_init();
|
||||
|
||||
#if MODULE_XTIMER && !(KINETIS_XTIMER_SOURCE_PIT)
|
||||
/* Start the RTT, used as time base for xtimer when using LPTMR backend */
|
||||
rtt_init();
|
||||
#endif
|
||||
|
||||
/* initialize and turn off LEDs */
|
||||
gpio_init(LED0_PIN, GPIO_OUT);
|
||||
gpio_set(LED0_PIN);
|
||||
gpio_init(LED1_PIN, GPIO_OUT);
|
||||
gpio_set(LED1_PIN);
|
||||
gpio_init(LED2_PIN, GPIO_OUT);
|
||||
gpio_set(LED2_PIN);
|
||||
gpio_init(LED3_PIN, GPIO_OUT);
|
||||
gpio_set(LED3_PIN);
|
||||
}
|
81
boards/frdm-kw41z/include/adc_params.h
Normal file
81
boards/frdm-kw41z/include/adc_params.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Eistec AB
|
||||
*
|
||||
* 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_frdm_kw41z
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Board specific configuration of direct mapped ADC
|
||||
*
|
||||
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
|
||||
*/
|
||||
|
||||
#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 = "corevrefh",
|
||||
.line = ADC_LINE(2),
|
||||
.res = ADC_RES_16BIT,
|
||||
},
|
||||
{
|
||||
.name = "corevrefl",
|
||||
.line = ADC_LINE(3),
|
||||
.res = ADC_RES_16BIT,
|
||||
},
|
||||
{
|
||||
.name = "dcdcvbat",
|
||||
.line = ADC_LINE(4),
|
||||
.res = ADC_RES_16BIT,
|
||||
},
|
||||
{
|
||||
.name = "ADC0_DP-DM",
|
||||
.line = ADC_LINE(5),
|
||||
.res = ADC_RES_16BIT,
|
||||
},
|
||||
{
|
||||
.name = "ADC0_SE2",
|
||||
.line = ADC_LINE(6),
|
||||
.res = ADC_RES_16BIT,
|
||||
},
|
||||
{
|
||||
.name = "ADC0_SE3",
|
||||
.line = ADC_LINE(7),
|
||||
.res = ADC_RES_16BIT,
|
||||
},
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ADC_PARAMS_H */
|
||||
/** @} */
|
99
boards/frdm-kw41z/include/board.h
Normal file
99
boards/frdm-kw41z/include/board.h
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Eistec AB
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup boards_frdm-kw41z Freescale FRDM-KW41Z Board
|
||||
* @ingroup boards
|
||||
* @brief Board specific implementations for the FRDM-KW41Z
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Board specific definitions for the FRDM-KW41Z
|
||||
*
|
||||
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
|
||||
*/
|
||||
|
||||
#ifndef BOARD_H
|
||||
#define BOARD_H
|
||||
|
||||
#include "cpu.h"
|
||||
#include "periph_conf.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name LED pin definitions and handlers
|
||||
* @{
|
||||
*/
|
||||
#define LED0_PIN GPIO_PIN(PORT_B, 0)
|
||||
#define LED0_MASK (1 << 0)
|
||||
#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_C, 1)
|
||||
#define LED1_MASK (1 << 1)
|
||||
#define LED1_ON (GPIOC->PCOR = LED1_MASK)
|
||||
#define LED1_OFF (GPIOC->PSOR = LED1_MASK)
|
||||
#define LED1_TOGGLE (GPIOC->PTOR = LED1_MASK)
|
||||
#define LED2_PIN GPIO_PIN(PORT_A, 19)
|
||||
#define LED2_MASK (1 << 19)
|
||||
#define LED2_ON (GPIOA->PCOR = LED2_MASK)
|
||||
#define LED2_OFF (GPIOA->PSOR = LED2_MASK)
|
||||
#define LED2_TOGGLE (GPIOA->PTOR = LED2_MASK)
|
||||
#define LED3_PIN GPIO_PIN(PORT_A, 18)
|
||||
#define LED3_MASK (1 << 18)
|
||||
#define LED3_ON (GPIOA->PCOR = LED3_MASK)
|
||||
#define LED3_OFF (GPIOA->PSOR = LED3_MASK)
|
||||
#define LED3_TOGGLE (GPIOA->PTOR = LED3_MASK)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @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
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name NOR flash hardware configuration
|
||||
* @{
|
||||
*/
|
||||
#define FRDM_NOR_SPI_DEV SPI_DEV(0)
|
||||
#define FRDM_NOR_SPI_CLK SPI_CLK_5MHZ
|
||||
#define FRDM_NOR_SPI_CS SPI_HWCS(0) /**< Flash CS pin */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Initialize board specific hardware, including clock, LEDs and standard I/O
|
||||
*/
|
||||
void board_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BOARD_H */
|
||||
/** @} */
|
80
boards/frdm-kw41z/include/gpio_params.h
Normal file
80
boards/frdm-kw41z/include/gpio_params.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2017 SKF AB
|
||||
*
|
||||
* 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_frdm_kw41z
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Board specific configuration of direct mapped GPIOs
|
||||
*
|
||||
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
|
||||
*/
|
||||
|
||||
#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[] =
|
||||
{
|
||||
/* These LEDs are marked on the board silkscreen with "LED3" for the red LED,
|
||||
* and "LED4" for the RGB LED, hence the names for the SAUL actuators don't
|
||||
* match the LEDx_PIN macros in board.h */
|
||||
/* LED1 and LED2 on the board are wired to the target CPU reset pin, and the
|
||||
* power supply line and are not software controllable */
|
||||
{
|
||||
.name = "LED3",
|
||||
.pin = LED0_PIN,
|
||||
.mode = GPIO_OUT,
|
||||
.flags = (SAUL_GPIO_INVERTED | SAUL_GPIO_INIT_CLEAR),
|
||||
},
|
||||
{
|
||||
.name = "LED4_R",
|
||||
.pin = LED1_PIN,
|
||||
.mode = GPIO_OUT,
|
||||
.flags = (SAUL_GPIO_INVERTED | SAUL_GPIO_INIT_CLEAR),
|
||||
},
|
||||
{
|
||||
.name = "LED4_G",
|
||||
.pin = LED2_PIN,
|
||||
.mode = GPIO_OUT,
|
||||
.flags = (SAUL_GPIO_INVERTED | SAUL_GPIO_INIT_CLEAR),
|
||||
},
|
||||
{
|
||||
.name = "LED4_B",
|
||||
.pin = LED3_PIN,
|
||||
.mode = GPIO_OUT,
|
||||
.flags = (SAUL_GPIO_INVERTED | SAUL_GPIO_INIT_CLEAR),
|
||||
},
|
||||
{
|
||||
.name = "SW3",
|
||||
.pin = GPIO_PIN(PORT_C, 4),
|
||||
.mode = GPIO_IN_PU
|
||||
},
|
||||
{
|
||||
.name = "SW4",
|
||||
.pin = GPIO_PIN(PORT_C, 5),
|
||||
.mode = GPIO_IN_PU
|
||||
},
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GPIO_PARAMS_H */
|
||||
/** @} */
|
306
boards/frdm-kw41z/include/periph_conf.h
Normal file
306
boards/frdm-kw41z/include/periph_conf.h
Normal file
@ -0,0 +1,306 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Eistec AB
|
||||
*
|
||||
* 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_frdm-kw41z
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @name Peripheral MCU configuration for the FRDM-KW41Z
|
||||
*
|
||||
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
|
||||
*/
|
||||
|
||||
#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: 48 MHz
|
||||
* Bus: 24 MHz
|
||||
* Flash: 24 MHz
|
||||
*/
|
||||
.clkdiv1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV4(1),
|
||||
/* 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,
|
||||
.fcrdiv = 0, /* Fast IRC divide by 1 => 4 MHz */
|
||||
.oscsel = 0, /* Use RSIM for external clock */
|
||||
.clc = 0, /* no load cap configuration */
|
||||
.fll_frdiv = 0b101, /* Divide by 1024 */
|
||||
.fll_factor_fei = KINETIS_MCG_FLL_FACTOR_1464, /* FEI FLL freq = 48 MHz */
|
||||
.fll_factor_fee = KINETIS_MCG_FLL_FACTOR_1280, /* FEE FLL freq = 40 MHz */
|
||||
.enable_oscillator = true, /* Use RF module oscillator */
|
||||
.select_fast_irc = true,
|
||||
.enable_mcgirclk = true, /* Used for LPUART clocking */
|
||||
};
|
||||
/* Radio xtal frequency, either 32 MHz or 26 MHz */
|
||||
#define CLOCK_RADIOXTAL (32000000ul)
|
||||
/* CPU core clock, the MCG clock output frequency */
|
||||
#define CLOCK_CORECLOCK (48000000ul)
|
||||
#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, \
|
||||
} \
|
||||
}
|
||||
#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 */
|
||||
[ 0] = { ADC0, GPIO_UNDEF, 26 }, /* internal: temperature sensor */
|
||||
/* 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 */
|
||||
[ 1] = { ADC0, GPIO_UNDEF, 27 }, /* internal: band gap */
|
||||
[ 2] = { ADC0, GPIO_UNDEF, 29 }, /* internal: V_REFH */
|
||||
[ 3] = { ADC0, GPIO_UNDEF, 30 }, /* internal: V_REFL */
|
||||
[ 4] = { ADC0, GPIO_UNDEF, 23 }, /* internal: DCDC divided battery level */
|
||||
[ 5] = { ADC0, GPIO_UNDEF, 0 | ADC_SC1_DIFF_MASK }, /* ADC0_DP-ADC0_DM differential reading */
|
||||
[ 6] = { ADC0, GPIO_PIN(PORT_B, 3), 2 }, /* ADC0_SE2 */
|
||||
[ 7] = { ADC0, GPIO_PIN(PORT_B, 2), 3 }, /* ADC0_SE3 */
|
||||
};
|
||||
#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 only connected to a 100 nF
|
||||
* capacitor on the FRDM-KW41Z board. So use VDDA by default on this board
|
||||
* unless the application enables the VREF module.
|
||||
*/
|
||||
#define ADC_REF_SETTING 1
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name SPI configuration
|
||||
*
|
||||
* Clock configuration values based on the configured 16Mhz 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(2) | SPI_CTAR_BR(5) | /* -> 100000Hz */
|
||||
SPI_CTAR_PCSSCK(2) | SPI_CTAR_CSSCK(4) |
|
||||
SPI_CTAR_PASC(2) | SPI_CTAR_ASC(4) |
|
||||
SPI_CTAR_PDT(2) | SPI_CTAR_DT(4)
|
||||
),
|
||||
(
|
||||
SPI_CTAR_PBR(2) | SPI_CTAR_BR(3) | /* -> 400000Hz */
|
||||
SPI_CTAR_PCSSCK(2) | SPI_CTAR_CSSCK(2) |
|
||||
SPI_CTAR_PASC(2) | SPI_CTAR_ASC(2) |
|
||||
SPI_CTAR_PDT(2) | SPI_CTAR_DT(2)
|
||||
),
|
||||
(
|
||||
SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | /* -> 1000000Hz */
|
||||
SPI_CTAR_PCSSCK(0) | SPI_CTAR_CSSCK(3) |
|
||||
SPI_CTAR_PASC(0) | SPI_CTAR_ASC(3) |
|
||||
SPI_CTAR_PDT(0) | SPI_CTAR_DT(3)
|
||||
),
|
||||
(
|
||||
SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | /* -> 4000000Hz */
|
||||
SPI_CTAR_PCSSCK(0) | SPI_CTAR_CSSCK(1) |
|
||||
SPI_CTAR_PASC(0) | SPI_CTAR_ASC(1) |
|
||||
SPI_CTAR_PDT(0) | SPI_CTAR_DT(1)
|
||||
),
|
||||
(
|
||||
SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | /* -> 4000000Hz */
|
||||
SPI_CTAR_PCSSCK(0) | SPI_CTAR_CSSCK(0) |
|
||||
SPI_CTAR_PASC(0) | SPI_CTAR_ASC(0) |
|
||||
SPI_CTAR_PDT(0) | SPI_CTAR_DT(0)
|
||||
)
|
||||
};
|
||||
|
||||
static const spi_conf_t spi_config[] = {
|
||||
{
|
||||
.dev = SPI0,
|
||||
.pin_miso = GPIO_PIN(PORT_C, 18),
|
||||
.pin_mosi = GPIO_PIN(PORT_C, 17),
|
||||
.pin_clk = GPIO_PIN(PORT_C, 16),
|
||||
.pin_cs = {
|
||||
GPIO_PIN(PORT_C, 19),
|
||||
GPIO_UNDEF,
|
||||
GPIO_UNDEF,
|
||||
GPIO_UNDEF,
|
||||
GPIO_UNDEF
|
||||
},
|
||||
.pcr = GPIO_AF_2,
|
||||
.simmask = SIM_SCGC6_SPI0_MASK
|
||||
},
|
||||
{
|
||||
.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
|
||||
* @{
|
||||
*/
|
||||
/* This CPU has I2C0 clocked by the bus clock and I2C1 clocked by the system
|
||||
* clock. This causes trouble with the current implementation in kinetis
|
||||
* which only supports one set of frequency dividers at a time */
|
||||
/* The current configuration sets the dividers so that the I2C0 bus will run at
|
||||
* half the requested speed, to avoid exceeding the requested speed on I2C1 with
|
||||
* the same configuration */
|
||||
#define I2C_NUMOF (2U)
|
||||
#define I2C_0_EN 1
|
||||
/* Disabled while waiting for a rewritten i2c driver which supports different
|
||||
* clock sources for each i2c module */
|
||||
#define I2C_1_EN 1
|
||||
/* Low (10 kHz): MUL = 2, SCL divider = 1792, total: 3584 */
|
||||
#define KINETIS_I2C_F_ICR_LOW (0x3A)
|
||||
#define KINETIS_I2C_F_MULT_LOW (1)
|
||||
/* Normal (100 kHz): MUL = 1, SCL divider = 320, total: 320 */
|
||||
#define KINETIS_I2C_F_ICR_NORMAL (0x25)
|
||||
#define KINETIS_I2C_F_MULT_NORMAL (0)
|
||||
/* Fast (400 kHz): MUL = 1, SCL divider = 80, total: 80 */
|
||||
#define KINETIS_I2C_F_ICR_FAST (0x14)
|
||||
#define KINETIS_I2C_F_MULT_FAST (0)
|
||||
/* Fast plus (1000 kHz): MUL = 1, SCL divider = 32, total: 32 */
|
||||
#define KINETIS_I2C_F_ICR_FAST_PLUS (0x09)
|
||||
#define KINETIS_I2C_F_MULT_FAST_PLUS (0)
|
||||
|
||||
/* I2C 0 device configuration */
|
||||
#define I2C_0_DEV I2C0
|
||||
#define I2C_0_CLKEN() (bit_set32(&SIM->SCGC4, SIM_SCGC4_I2C0_SHIFT))
|
||||
#define I2C_0_CLKDIS() (bit_clear32(&SIM->SCGC4, SIM_SCGC4_I2C0_SHIFT))
|
||||
#define I2C_0_IRQ I2C0_IRQn
|
||||
#define I2C_0_IRQ_HANDLER isr_i2c0
|
||||
/* I2C 0 pin configuration */
|
||||
#define I2C_0_PORT PORTB
|
||||
#define I2C_0_PORT_CLKEN() (bit_set32(&SIM->SCGC5, SIM_SCGC5_PORTB_SHIFT))
|
||||
#define I2C_0_PIN_AF 3
|
||||
#define I2C_0_SDA_PIN 1
|
||||
#define I2C_0_SCL_PIN 0
|
||||
#define I2C_0_PORT_CFG (PORT_PCR_MUX(I2C_0_PIN_AF))
|
||||
/* I2C 1 device configuration */
|
||||
#define I2C_1_DEV I2C1
|
||||
#define I2C_1_CLKEN() (bit_set32(&SIM->SCGC4, SIM_SCGC4_I2C1_SHIFT))
|
||||
#define I2C_1_CLKDIS() (bit_clear32(&SIM->SCGC4, SIM_SCGC4_I2C1_SHIFT))
|
||||
#define I2C_1_IRQ I2C1_IRQn
|
||||
#define I2C_1_IRQ_HANDLER isr_i2c1
|
||||
/* I2C 1 pin configuration */
|
||||
#define I2C_1_PORT PORTC
|
||||
#define I2C_1_PORT_CLKEN() (bit_set32(&SIM->SCGC5, SIM_SCGC5_PORTC_SHIFT))
|
||||
#define I2C_1_PIN_AF 3
|
||||
#define I2C_1_SDA_PIN 3
|
||||
#define I2C_1_SCL_PIN 2
|
||||
#define I2C_1_PORT_CFG (PORT_PCR_MUX(I2C_0_PIN_AF))
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name RTT and RTC configuration
|
||||
* @{
|
||||
*/
|
||||
#define RTT_NUMOF (1U)
|
||||
#define RTC_NUMOF (1U)
|
||||
#define RTT_DEV RTC
|
||||
#define RTT_IRQ RTC_IRQn
|
||||
#define RTT_IRQ_PRIO 10
|
||||
#define RTT_UNLOCK() (bit_set32(&SIM->SCGC6, SIM_SCGC6_RTC_SHIFT))
|
||||
#define RTT_ISR isr_rtc
|
||||
#define RTT_FREQUENCY (1)
|
||||
#define RTT_MAX_VALUE (0xffffffff)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Random Number Generator configuration
|
||||
* @{
|
||||
*/
|
||||
#define KINETIS_TRNG TRNG
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PERIPH_CONF_H */
|
||||
/** @} */
|
256
cpu/kinetis/include/bme.h
Normal file
256
cpu/kinetis/include/bme.h
Normal file
@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Eistec AB
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup cpu_kinetis_bme Kinetis Bit Manipulation Engine (BME)
|
||||
* @ingroup cpu_kinetis
|
||||
* @brief Macros for using decorated memory accesses with the Bit
|
||||
* Manipulation Engine available in Kinetis Cortex-M0+ devices
|
||||
*
|
||||
* @{
|
||||
* @file
|
||||
* @brief Macro definitions for the Kinetis Bit Manipulation Engine (BME)
|
||||
*
|
||||
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
|
||||
*/
|
||||
|
||||
#ifndef BME_H
|
||||
#define BME_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Tell bit.h that we provide CPU specific bit manipulation functions
|
||||
*/
|
||||
#define BITBAND_FUNCTIONS_PROVIDED 1
|
||||
|
||||
#define BME_AND_MASK (1 << 26) /**< AND decoration bitmask */
|
||||
#define BME_OR_MASK (1 << 27) /**< OR decoration bitmask */
|
||||
#define BME_XOR_MASK (3 << 26) /**< XOR decoration bitmask */
|
||||
#define BME_LAC1_MASK(BIT) ((1 << 27) | ((BIT) << 21)) /**< Load-and-clear 1 bit */
|
||||
#define BME_LAS1_MASK(BIT) ((3 << 26) | ((BIT) << 21)) /**< Load-and-set 1 bit */
|
||||
|
||||
/**
|
||||
* @brief Bit field extraction bitmask
|
||||
*
|
||||
* @param bit LSB of the bitfield within the word/halfword/byte
|
||||
* @param width Number of bits to extract
|
||||
*/
|
||||
#define BME_BF_MASK(bit, width) ((1 << 28) | ((bit) << 23) | (((width) - 1 ) << 19))
|
||||
|
||||
/**
|
||||
* @brief Bit field address macro
|
||||
*
|
||||
* @pre The target address must lie within a part of the peripheral address
|
||||
* space 0x40000000 - 0x40070000
|
||||
*
|
||||
* @param[in] ptr Pointer to target register
|
||||
* @param[in] bit Location of the LSB of the bitfield within the register
|
||||
* @param[in] width Width of the the bitfield, in bits
|
||||
*
|
||||
* @return bitfield address as an uintptr_t
|
||||
*/
|
||||
static inline volatile void *bme_bf_addr(volatile void *ptr, uintptr_t bit, uintptr_t width)
|
||||
{
|
||||
return (volatile void *)(((uintptr_t)ptr) | BME_BF_MASK(bit, width));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Access a bitfield (32 bit load/store)
|
||||
*
|
||||
* This macro can be used both for store `(*bme_bitfield32(xxx) = y)` and
|
||||
* load `(y = *bme_bitfield32(ptr, bit))`
|
||||
*
|
||||
* @pre The target address must lie within a part of the peripheral address
|
||||
* space 0x40000000 - 0x40070000
|
||||
*
|
||||
* @param[in] ptr Pointer to target register
|
||||
* @param[in] bit Location of the LSB of the bitfield within the register
|
||||
* @param[in] width Width of the the bitfield, in bits
|
||||
*
|
||||
* @return bitfield extracted as a (modifiable) lvalue
|
||||
*/
|
||||
static inline volatile uint32_t *bme_bitfield32(volatile uint32_t *ptr, uint8_t bit, uint8_t width)
|
||||
{
|
||||
return (volatile uint32_t *)(bme_bf_addr(ptr, bit, width));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Access a bitfield (16 bit load/store)
|
||||
*
|
||||
* This macro can be used both for store `(*bme_bitfield16(xxx) = y)` and
|
||||
* load `(y = *bme_bitfield16(ptr, bit))`
|
||||
*
|
||||
* @pre The target address must lie within a part of the peripheral address
|
||||
* space 0x40000000 - 0x40070000
|
||||
*
|
||||
* @param[in] ptr Pointer to target register
|
||||
* @param[in] bit Location of the LSB of the bitfield within the register
|
||||
* @param[in] width Width of the the bitfield, in bits
|
||||
*
|
||||
* @return bitfield extracted as a (modifiable) lvalue
|
||||
*/
|
||||
static inline volatile uint16_t *bme_bitfield16(volatile uint16_t *ptr, uint8_t bit, uint8_t width)
|
||||
{
|
||||
return (volatile uint16_t *)(bme_bf_addr(ptr, bit, width));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Access a bitfield (8 bit load/store)
|
||||
*
|
||||
* This macro can be used both for store `(*bme_bitfield8(xxx) = y)` and
|
||||
* load `(y = *bme_bitfield8(ptr, bit))`
|
||||
*
|
||||
* @pre The target address must lie within a part of the peripheral address
|
||||
* space 0x40000000 - 0x40070000
|
||||
*
|
||||
* @param[in] ptr Pointer to target register
|
||||
* @param[in] bit Location of the LSB of the bitfield within the register
|
||||
* @param[in] width Width of the the bitfield, in bits
|
||||
*
|
||||
* @return bitfield extracted as a (modifiable) lvalue
|
||||
*/
|
||||
static inline volatile uint8_t *bme_bitfield8(volatile uint8_t *ptr, uint8_t bit, uint8_t width)
|
||||
{
|
||||
return (volatile uint8_t *)(bme_bf_addr(ptr, bit, width));
|
||||
}
|
||||
|
||||
/* For compatibility with the M3/M4 bitbanding macros: */
|
||||
|
||||
/**
|
||||
* @brief Set a single bit in the 32 bit word pointed to by @p ptr
|
||||
*
|
||||
* The effect is the same as for the following snippet:
|
||||
*
|
||||
* @code{c}
|
||||
* *ptr |= (1 << bit);
|
||||
* @endcode
|
||||
*
|
||||
* There is a read-modify-write cycle occurring within the core, but this cycle
|
||||
* is atomic and can not be disrupted by IRQs
|
||||
*
|
||||
* @param[in] ptr pointer to target word
|
||||
* @param[in] bit bit number within the word
|
||||
*/
|
||||
static inline void bit_set32(volatile uint32_t *ptr, uint8_t bit)
|
||||
{
|
||||
*((volatile uint32_t *)(((uintptr_t)ptr) | BME_OR_MASK)) = (uint32_t)((1ul << bit));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set a single bit in the 16 bit word pointed to by @p ptr
|
||||
*
|
||||
* The effect is the same as for the following snippet:
|
||||
*
|
||||
* @code{c}
|
||||
* *ptr |= (1 << bit);
|
||||
* @endcode
|
||||
*
|
||||
* There is a read-modify-write cycle occurring within the core, but this cycle
|
||||
* is atomic and can not be disrupted by IRQs
|
||||
*
|
||||
* @param[in] ptr pointer to target word
|
||||
* @param[in] bit bit number within the word
|
||||
*/
|
||||
static inline void bit_set16(volatile uint16_t *ptr, uint8_t bit)
|
||||
{
|
||||
*((volatile uint16_t *)(((uintptr_t)ptr) | BME_OR_MASK)) = (uint16_t)((1ul << bit));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set a single bit in the 8 bit byte pointed to by @p ptr
|
||||
*
|
||||
* The effect is the same as for the following snippet:
|
||||
*
|
||||
* @code{c}
|
||||
* *ptr |= (1 << bit);
|
||||
* @endcode
|
||||
*
|
||||
* There is a read-modify-write cycle occurring within the core, but this cycle
|
||||
* is atomic and can not be disrupted by IRQs
|
||||
*
|
||||
* @param[in] ptr pointer to target byte
|
||||
* @param[in] bit bit number within the byte
|
||||
*/
|
||||
static inline void bit_set8(volatile uint8_t *ptr, uint8_t bit)
|
||||
{
|
||||
*((volatile uint8_t *)(((uintptr_t)ptr) | BME_OR_MASK)) = (uint8_t)((1ul << bit));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear a single bit in the 32 bit word pointed to by @p ptr
|
||||
*
|
||||
* The effect is the same as for the following snippet:
|
||||
*
|
||||
* @code{c}
|
||||
* *ptr &= ~(1 << bit);
|
||||
* @endcode
|
||||
*
|
||||
* There is a read-modify-write cycle occurring within the core, but this cycle
|
||||
* is atomic and can not be disrupted by IRQs
|
||||
*
|
||||
* @param[in] ptr pointer to target word
|
||||
* @param[in] bit bit number within the word
|
||||
*/
|
||||
static inline void bit_clear32(volatile uint32_t *ptr, uint8_t bit)
|
||||
{
|
||||
*((volatile uint32_t *)(((uintptr_t)ptr) | BME_AND_MASK)) = (uint32_t)(~(1ul << bit));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear a single bit in the 16 bit word pointed to by @p ptr
|
||||
*
|
||||
* The effect is the same as for the following snippet:
|
||||
*
|
||||
* @code{c}
|
||||
* *ptr &= ~(1 << bit);
|
||||
* @endcode
|
||||
*
|
||||
* There is a read-modify-write cycle occurring within the core, but this cycle
|
||||
* is atomic and can not be disrupted by IRQs
|
||||
*
|
||||
* @param[in] ptr pointer to target word
|
||||
* @param[in] bit bit number within the word
|
||||
*/
|
||||
static inline void bit_clear16(volatile uint16_t *ptr, uint8_t bit)
|
||||
{
|
||||
*((volatile uint16_t *)(((uintptr_t)ptr) | BME_AND_MASK)) = (uint16_t)(~(1ul << bit));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear a single bit in the 8 bit byte pointed to by @p ptr
|
||||
*
|
||||
* The effect is the same as for the following snippet:
|
||||
*
|
||||
* @code{c}
|
||||
* *ptr &= ~(1 << bit);
|
||||
* @endcode
|
||||
*
|
||||
* There is a read-modify-write cycle occurring within the core, but this cycle
|
||||
* is atomic and can not be disrupted by IRQs
|
||||
*
|
||||
* @param[in] ptr pointer to target byte
|
||||
* @param[in] bit bit number within the byte
|
||||
*/
|
||||
static inline void bit_clear8(volatile uint8_t *ptr, uint8_t bit)
|
||||
{
|
||||
*((volatile uint8_t *)(((uintptr_t)ptr) | BME_AND_MASK)) = (uint8_t)(~(1ul << bit));
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BME_H */
|
||||
|
||||
/** @} */
|
@ -21,6 +21,15 @@
|
||||
|
||||
#include "cpu_conf_common.h"
|
||||
|
||||
#if (__CORTEX_M < 3)
|
||||
/*
|
||||
* Kinetis Cortex-M0+ devices have bit manipulation engine (BME) which provides
|
||||
* the same functionality (and some more) as the bitband aliased memory found in
|
||||
* Cortex-M3 and up
|
||||
*/
|
||||
#include "bme.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
|
@ -63,7 +63,18 @@
|
||||
|
||||
#elif defined(KINETIS_CORE_Z)
|
||||
/* Kinetis KWxxZ */
|
||||
/* TODO */
|
||||
#if defined(CPU_MODEL_MKW21Z256VHT4) || \
|
||||
defined(CPU_MODEL_MKW21Z512VHT4)
|
||||
#include "vendor/MKW21Z4.h"
|
||||
#elif defined(CPU_MODEL_MKW31Z256VHT4) || \
|
||||
defined(CPU_MODEL_MKW31Z512CAT4) || \
|
||||
defined(CPU_MODEL_MKW31Z512VHT4)
|
||||
#include "vendor/MKW31Z4.h"
|
||||
#elif defined(CPU_MODEL_MKW41Z256VHT4) || \
|
||||
defined(CPU_MODEL_MKW41Z512CAT4) || \
|
||||
defined(CPU_MODEL_MKW41Z512VHT4)
|
||||
#include "vendor/MKW41Z4.h"
|
||||
#endif
|
||||
#endif /* KINETIS_CORE_x */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -46,6 +46,8 @@ typedef uint16_t gpio_t;
|
||||
*/
|
||||
#define GPIO_PIN(x, y) (((x + 1) << 12) | (x << 6) | y)
|
||||
|
||||
#ifdef SIM_UIDH_UID_MASK
|
||||
/* Kinetis Cortex-M4 has a 128 bit SIM UID */
|
||||
/**
|
||||
* @brief Starting offset of CPU_ID
|
||||
*/
|
||||
@ -55,6 +57,17 @@ typedef uint16_t gpio_t;
|
||||
* @brief Length of the CPU_ID in octets
|
||||
*/
|
||||
#define CPUID_LEN (16U)
|
||||
#else /* defined(SIM_UIDH_UID_MASK) */
|
||||
/* Kinetis Cortex-M0+ has a 96 bit SIM UID */
|
||||
/**
|
||||
* @brief Starting offset of CPU_ID
|
||||
*/
|
||||
#define CPUID_ADDR (&SIM->UIDMH)
|
||||
/**
|
||||
* @brief Length of the CPU_ID in octets
|
||||
*/
|
||||
#define CPUID_LEN (12U)
|
||||
#endif /* defined(SIM_UIDH_UID_MASK) */
|
||||
|
||||
/**
|
||||
* @brief Generate GPIO mode bitfields
|
||||
@ -67,11 +80,6 @@ typedef uint16_t gpio_t;
|
||||
*/
|
||||
#define GPIO_MODE(pu, pe, od, out) (pu | (pe << 1) | (od << 5) | (out << 7))
|
||||
|
||||
/**
|
||||
* @brief Define the maximum number of PWM channels that can be configured
|
||||
*/
|
||||
#define PWM_CHAN_MAX (4U)
|
||||
|
||||
/**
|
||||
* @brief Define a CPU specific SPI hardware chip select line macro
|
||||
*
|
||||
@ -135,7 +143,9 @@ typedef enum {
|
||||
GPIO_AF_5 = PORT_PCR_MUX(5), /**< use alternate function 5 */
|
||||
GPIO_AF_6 = PORT_PCR_MUX(6), /**< use alternate function 6 */
|
||||
GPIO_AF_7 = PORT_PCR_MUX(7), /**< use alternate function 7 */
|
||||
#ifdef PORT_PCR_ODE_MASK
|
||||
GPIO_PCR_OD = (PORT_PCR_ODE_MASK), /**< open-drain mode */
|
||||
#endif
|
||||
GPIO_PCR_PD = (PORT_PCR_PE_MASK), /**< enable pull-down */
|
||||
GPIO_PCR_PU = (PORT_PCR_PE_MASK | PORT_PCR_PS_MASK) /**< enable PU */
|
||||
} gpio_pcr_t;
|
||||
@ -186,8 +196,14 @@ typedef enum {
|
||||
} adc_res_t;
|
||||
/** @} */
|
||||
|
||||
#if defined(FTM_CnSC_MSB_MASK)
|
||||
/**
|
||||
* @name PWM mode configuration bits
|
||||
* @brief Define the maximum number of PWM channels that can be configured
|
||||
*/
|
||||
#define PWM_CHAN_MAX (4U)
|
||||
|
||||
/**
|
||||
* @name PWM mode configuration
|
||||
* @{
|
||||
*/
|
||||
#define HAVE_PWM_MODE_T
|
||||
@ -196,7 +212,7 @@ typedef enum {
|
||||
PWM_RIGHT = (FTM_CnSC_MSB_MASK | FTM_CnSC_ELSA_MASK), /**< right aligned */
|
||||
PWM_CENTER = (FTM_CnSC_MSB_MASK) /**< center aligned */
|
||||
} pwm_mode_t;
|
||||
/** @} */
|
||||
#endif /* defined(FTM_CnSC_MSB_MASK) */
|
||||
#endif /* ndef DOXYGEN */
|
||||
|
||||
/**
|
||||
@ -279,6 +295,7 @@ typedef struct {
|
||||
uint8_t irqn;
|
||||
} lptmr_conf_t;
|
||||
|
||||
#ifdef FTM_CnSC_MSB_MASK
|
||||
/**
|
||||
* @brief PWM configuration structure
|
||||
*/
|
||||
@ -292,6 +309,7 @@ typedef struct {
|
||||
uint8_t chan_numof; /**< number of actually configured channels */
|
||||
uint8_t ftm_num; /**< FTM number used */
|
||||
} pwm_conf_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SPI module configuration options
|
||||
|
@ -121,6 +121,7 @@ void isr_lvd_lvw(void); /**< PMC controller low-voltage detect, low-voltage
|
||||
void isr_mcg(void); /**< MCG interrupt handler */
|
||||
void isr_mcm(void); /**< MCM normal interrupt handler */
|
||||
void isr_pdb0(void); /**< PDB0 interrupt handler */
|
||||
void isr_pit(void); /**< PIT any channel interrupt handler */
|
||||
void isr_pit0(void); /**< PIT timer channel 0 interrupt handler */
|
||||
void isr_pit1(void); /**< PIT timer channel 1 interrupt handler */
|
||||
void isr_pit2(void); /**< PIT timer channel 2 interrupt handler */
|
||||
@ -130,6 +131,9 @@ void isr_portb(void); /**< Port B pin detect interrupt handler */
|
||||
void isr_portc(void); /**< Port C pin detect interrupt handler */
|
||||
void isr_portd(void); /**< Port D pin detect interrupt handler */
|
||||
void isr_porte(void); /**< Port E pin detect interrupt handler */
|
||||
void isr_portb_portc(void); /**< Port B, C combined pin detect interrupt handler */
|
||||
void isr_radio_0(void); /**< Radio transceiver INT0 interrupt handler */
|
||||
void isr_radio_1(void); /**< Radio transceiver INT1 interrupt handler */
|
||||
void isr_rng(void); /**< RNG interrupt handler */
|
||||
void isr_rtc(void); /**< RTC interrupt handler */
|
||||
void isr_rtc_seconds(void); /**< RTC seconds interrupt handler */
|
||||
@ -141,6 +145,7 @@ void isr_swi(void); /**< Software interrupt handler */
|
||||
void isr_tpm0(void); /**< TPM0 interrupt handler */
|
||||
void isr_tpm1(void); /**< TPM1 interrupt handler */
|
||||
void isr_tpm2(void); /**< TPM2 interrupt handler */
|
||||
void isr_trng0(void); /**< TRNG0 interrupt handler */
|
||||
void isr_tsi0(void); /**< TSI0 interrupt handler */
|
||||
void isr_uart0_err(void); /**< UART0 error interrupt handler */
|
||||
void isr_uart0_lon(void); /**< UART0 LON interrupt handler */
|
||||
|
12944
cpu/kinetis/include/vendor/MKW21Z4.h
vendored
Normal file
12944
cpu/kinetis/include/vendor/MKW21Z4.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
12312
cpu/kinetis/include/vendor/MKW31Z4.h
vendored
Normal file
12312
cpu/kinetis/include/vendor/MKW31Z4.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
13015
cpu/kinetis/include/vendor/MKW41Z4.h
vendored
Normal file
13015
cpu/kinetis/include/vendor/MKW41Z4.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -169,6 +169,7 @@ WEAK_DEFAULT void isr_lvd_lvw(void);
|
||||
WEAK_DEFAULT void isr_mcg(void);
|
||||
WEAK_DEFAULT void isr_mcm(void);
|
||||
WEAK_DEFAULT void isr_pdb0(void);
|
||||
WEAK_DEFAULT void isr_pit(void);
|
||||
WEAK_DEFAULT void isr_pit0(void);
|
||||
WEAK_DEFAULT void isr_pit1(void);
|
||||
WEAK_DEFAULT void isr_pit2(void);
|
||||
@ -178,6 +179,9 @@ WEAK_DEFAULT void isr_portb(void);
|
||||
WEAK_DEFAULT void isr_portc(void);
|
||||
WEAK_DEFAULT void isr_portd(void);
|
||||
WEAK_DEFAULT void isr_porte(void);
|
||||
WEAK_DEFAULT void isr_portb_portc(void);
|
||||
WEAK_DEFAULT void isr_radio_0(void);
|
||||
WEAK_DEFAULT void isr_radio_1(void);
|
||||
WEAK_DEFAULT void isr_rng(void);
|
||||
WEAK_DEFAULT void isr_rtc(void);
|
||||
WEAK_DEFAULT void isr_rtc_seconds(void);
|
||||
@ -190,6 +194,7 @@ WEAK_DEFAULT void isr_tpm0(void);
|
||||
WEAK_DEFAULT void isr_tpm1(void);
|
||||
WEAK_DEFAULT void isr_tpm2(void);
|
||||
WEAK_DEFAULT void isr_tsi0(void);
|
||||
WEAK_DEFAULT void isr_trng0(void);
|
||||
WEAK_DEFAULT void isr_uart0_err(void);
|
||||
WEAK_DEFAULT void isr_uart0_lon(void);
|
||||
WEAK_DEFAULT void isr_uart0_rx_tx(void);
|
||||
|
@ -31,6 +31,11 @@
|
||||
#include "bit.h"
|
||||
#include "periph/gpio.h"
|
||||
|
||||
#ifndef PORT_PCR_ODE_MASK
|
||||
/* For compatibility with Kinetis CPUs without open drain GPIOs (e.g. KW41Z) */
|
||||
#define PORT_PCR_ODE_MASK 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Get the OCR reg value from the gpio_mode_t value
|
||||
*/
|
||||
@ -347,3 +352,12 @@ void isr_portg(void)
|
||||
irq_handler(PORTG, 6);
|
||||
}
|
||||
#endif /* ISR_PORT_G */
|
||||
|
||||
#if defined(PORTB_BASE) && defined(PORTC_BASE)
|
||||
/* Combined ISR used in certain KL devices */
|
||||
void isr_portb_portc(void)
|
||||
{
|
||||
irq_handler(PORTB, 1);
|
||||
irq_handler(PORTC, 2);
|
||||
}
|
||||
#endif
|
||||
|
@ -29,6 +29,12 @@
|
||||
#include "assert.h"
|
||||
#include "periph/pwm.h"
|
||||
|
||||
/* This driver uses the FlexTimer module (FTM) for generating PWM signals, but
|
||||
* not all Kinetis CPUs have such a module. This preprocessor condition prevents
|
||||
* compilation errors when the CPU header lacks the register definitions for the
|
||||
* FTM */
|
||||
#ifdef FTM0
|
||||
|
||||
#define PRESCALER_MAX (7U)
|
||||
|
||||
static inline FTM_Type *ftm(pwm_t pwm)
|
||||
@ -150,3 +156,5 @@ void pwm_poweroff(pwm_t pwm)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* defined(FTM0) */
|
||||
|
@ -32,6 +32,16 @@
|
||||
#include "periph_conf.h"
|
||||
#include "periph/timer.h"
|
||||
|
||||
#ifdef PIT_LTMR64H_LTH_MASK
|
||||
/* The KW41Z PIT module provides only one IRQ for all PIT channels combined. */
|
||||
/* TODO: find a better way to distinguish which Kinetis CPUs have separate PIT
|
||||
* channel interrupts */
|
||||
#define KINETIS_PIT_COMBINED_IRQ 1
|
||||
#else
|
||||
/* K60, K64F etc have a separate IRQ number for each PIT channel */
|
||||
#define KINETIS_PIT_COMBINED_IRQ 0
|
||||
#endif
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
@ -189,10 +199,15 @@ static inline int pit_init(uint8_t dev, uint32_t freq, timer_cb_t cb, void *arg)
|
||||
|
||||
/* Clear IRQ flag */
|
||||
PIT->CHANNEL[pit_config[dev].count_ch].TFLG = PIT_TFLG_TIF_MASK;
|
||||
#if KINETIS_PIT_COMBINED_IRQ
|
||||
/* One IRQ for all channels */
|
||||
/* NVIC_ClearPendingIRQ(PIT_IRQn); */ /* does it make sense to clear this IRQ flag? */
|
||||
NVIC_EnableIRQ(PIT_IRQn);
|
||||
#else
|
||||
/* Refactor the below lines if there are any CPUs where the PIT IRQs are not sequential */
|
||||
NVIC_ClearPendingIRQ(PIT0_IRQn + pit_config[dev].count_ch);
|
||||
NVIC_EnableIRQ(PIT0_IRQn + pit_config[dev].count_ch);
|
||||
|
||||
#endif
|
||||
/* Reset up-counter */
|
||||
pit[dev].count = PIT_MAX_VALUE;
|
||||
pit[dev].ldval = PIT_MAX_VALUE;
|
||||
@ -711,6 +726,22 @@ void timer_stop(tim_t dev)
|
||||
|
||||
/* ****** ISR instances ****** */
|
||||
|
||||
void isr_pit(void)
|
||||
{
|
||||
/* Some of the lower end Kinetis CPUs combine the individual PIT interrupt
|
||||
* flags into a single NVIC IRQ signal. This means that software needs to
|
||||
* test which timer(s) went off when an IRQ occurs. */
|
||||
for (size_t i = 0; i < PIT_NUMOF; ++i) {
|
||||
if (PIT->CHANNEL[pit_config[i].count_ch].TCTRL & PIT_TCTRL_TIE_MASK) {
|
||||
/* Interrupt is enabled */
|
||||
if (PIT->CHANNEL[pit_config[i].count_ch].TFLG) {
|
||||
/* Timer interrupt flag is set */
|
||||
pit_irq_handler(_pit_tim_t(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PIT_ISR_0
|
||||
void PIT_ISR_0(void)
|
||||
{
|
||||
|
@ -38,6 +38,7 @@
|
||||
#define FTFL_Collision_IRQn Read_Collision_IRQn
|
||||
#define PMC_IRQn LVD_LVW_IRQn
|
||||
#define Watchdog_IRQn WDOG_EWM_IRQn
|
||||
#define LVD_LVW_DCDC_IRQn LVD_LVW_IRQn
|
||||
|
||||
#include "vectors_kinetis.h"
|
||||
|
||||
@ -125,21 +126,29 @@ ISR_VECTOR(1) const isr_t vector_cpu[CPU_IRQ_NUMOF] = {
|
||||
#elif defined(DMA_INT_INT15_MASK)
|
||||
[DMA15_IRQn ] = isr_dma15, /* DMA Channel 15 Transfer Complete */
|
||||
#endif
|
||||
#ifndef KINETIS_CORE_Z
|
||||
[DMA_Error_IRQn ] = isr_dma_error, /* DMA Error Interrupt */
|
||||
#endif
|
||||
#endif /* defined(DMA0) */
|
||||
#ifdef MCM
|
||||
#if defined(MCM) && !defined(KINETIS_CORE_Z)
|
||||
[MCM_IRQn ] = isr_mcm, /* Normal Interrupt */
|
||||
#endif
|
||||
#if defined(FTFA)
|
||||
[FTFA_IRQn ] = isr_ftfa, /* FTFA command complete */
|
||||
#ifndef KINETIS_CORE_Z
|
||||
[FTFA_Collision_IRQn] = isr_ftfa_collision, /* FTFA read collision */
|
||||
#endif
|
||||
#elif defined(FTFE)
|
||||
[FTFE_IRQn ] = isr_ftfe, /* FTFE command complete */
|
||||
#ifndef KINETIS_CORE_Z
|
||||
[FTFE_Collision_IRQn] = isr_ftfe_collision, /* FTFE read collision */
|
||||
#endif
|
||||
#elif defined(FTFL)
|
||||
[FTFL_IRQn ] = isr_ftfl, /* FTFL command complete */
|
||||
#ifndef KINETIS_CORE_Z
|
||||
[FTFL_Collision_IRQn] = isr_ftfl_collision, /* FTFL read collision */
|
||||
#endif
|
||||
#endif
|
||||
#ifdef PMC
|
||||
[LVD_LVW_IRQn ] = isr_lvd_lvw, /* Low Voltage Detect, Low Voltage Warning */
|
||||
#endif
|
||||
@ -245,11 +254,15 @@ ISR_VECTOR(1) const isr_t vector_cpu[CPU_IRQ_NUMOF] = {
|
||||
[RTC_Seconds_IRQn] = isr_rtc_seconds, /* RTC seconds interrupt */
|
||||
#endif
|
||||
#ifdef PIT
|
||||
#ifdef KINETIS_CORE_Z
|
||||
[PIT_IRQn ] = isr_pit, /* PIT any channel interrupt */
|
||||
#else
|
||||
[PIT0_IRQn ] = isr_pit0, /* PIT timer channel 0 interrupt */
|
||||
[PIT1_IRQn ] = isr_pit1, /* PIT timer channel 1 interrupt */
|
||||
[PIT2_IRQn ] = isr_pit2, /* PIT timer channel 2 interrupt */
|
||||
[PIT3_IRQn ] = isr_pit3, /* PIT timer channel 3 interrupt */
|
||||
#endif
|
||||
#endif /* defined(PIT) */
|
||||
#ifdef PDB0
|
||||
[PDB0_IRQn ] = isr_pdb0, /* PDB0 Interrupt */
|
||||
#endif
|
||||
@ -274,6 +287,11 @@ ISR_VECTOR(1) const isr_t vector_cpu[CPU_IRQ_NUMOF] = {
|
||||
#ifdef PORTA
|
||||
[PORTA_IRQn ] = isr_porta, /* Port A interrupt */
|
||||
#endif
|
||||
#ifdef KINETIS_CORE_Z
|
||||
#if defined(PORTB) && defined(PORTC)
|
||||
[PORTB_PORTC_IRQn] = isr_portb_portc, /* Port B, C combined interrupt */
|
||||
#endif
|
||||
#else
|
||||
#ifdef PORTB
|
||||
[PORTB_IRQn ] = isr_portb, /* Port B interrupt */
|
||||
#endif
|
||||
@ -286,6 +304,7 @@ ISR_VECTOR(1) const isr_t vector_cpu[CPU_IRQ_NUMOF] = {
|
||||
#ifdef PORTE
|
||||
[PORTE_IRQn ] = isr_porte, /* Port E interrupt */
|
||||
#endif
|
||||
#endif
|
||||
#if __CORTEX_M >= 3
|
||||
[SWI_IRQn ] = isr_swi, /* Software interrupt */
|
||||
#endif
|
||||
@ -350,6 +369,12 @@ ISR_VECTOR(1) const isr_t vector_cpu[CPU_IRQ_NUMOF] = {
|
||||
#ifdef USBHS
|
||||
[USBHS_IRQn ] = isr_usbhs, /* USB high speed OTG interrupt */
|
||||
#endif
|
||||
#ifdef BTLE_RF
|
||||
[Radio_0_IRQn ] = isr_radio_0, /* Radio INT0 interrupt */
|
||||
#endif
|
||||
#ifdef ZLL
|
||||
[Radio_1_IRQn ] = isr_radio_1, /* Radio INT1 interrupt */
|
||||
#endif
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
@ -99,6 +99,7 @@ ARM_CORTEX_M_BOARDS := airfy-beacon \
|
||||
fox \
|
||||
frdm-k22f \
|
||||
frdm-k64f \
|
||||
frdm-kw41z \
|
||||
iotlab-a8-m3 \
|
||||
iotlab-m3 \
|
||||
limifrog-v1 \
|
||||
|
Loading…
Reference in New Issue
Block a user