[KINETIS] Initial support for KL25 family

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@7110 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
utzig 2014-08-01 22:55:00 +00:00
parent ef7990a192
commit 800bd88d35
16 changed files with 4578 additions and 0 deletions

View File

@ -0,0 +1,156 @@
/*
ChibiOS/RT - Copyright (C) 2006-2014 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* KL25Z128 memory setup.
*/
__main_stack_size__ = 0x0400;
__process_stack_size__ = 0x0400;
MEMORY
{
flash0 : org = 0x00000000, len = 0xc0
flashcfg : org = 0x00000400, len = 0x10
flash : org = 0x00000410, len = 128k - 0x410
ram : org = 0x1FFFF000, len = 16k
}
__ram_start__ = ORIGIN(ram);
__ram_size__ = LENGTH(ram);
__ram_end__ = __ram_start__ + __ram_size__;
SECTIONS
{
. = 0;
.isr : ALIGN(4) SUBALIGN(4)
{
KEEP(*(vectors))
} > flash0
.cfmprotect : ALIGN(4) SUBALIGN(4)
{
KEEP(*(.cfmconfig))
} > flashcfg
_text = .;
constructors : ALIGN(4) SUBALIGN(4)
{
PROVIDE(__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE(__init_array_end = .);
} > flash
destructors : ALIGN(4) SUBALIGN(4)
{
PROVIDE(__fini_array_start = .);
KEEP(*(.fini_array))
KEEP(*(SORT(.fini_array.*)))
PROVIDE(__fini_array_end = .);
} > flash
.text : ALIGN(4) SUBALIGN(4)
{
*(.text)
*(.text.*)
*(.rodata)
*(.rodata.*)
*(.glue_7t)
*(.glue_7)
*(.gcc*)
} > flash
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > flash
.ARM.exidx : {
PROVIDE(__exidx_start = .);
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
PROVIDE(__exidx_end = .);
} > flash
.eh_frame_hdr :
{
*(.eh_frame_hdr)
} > flash
.eh_frame : ONLY_IF_RO
{
*(.eh_frame)
} > flash
.textalign : ONLY_IF_RO
{
. = ALIGN(8);
} > flash
_etext = .;
_textdata = _etext;
.stacks :
{
. = ALIGN(8);
__main_stack_base__ = .;
. += __main_stack_size__;
. = ALIGN(8);
__main_stack_end__ = .;
__process_stack_base__ = .;
__main_thread_stack_base__ = .;
. += __process_stack_size__;
. = ALIGN(8);
__process_stack_end__ = .;
__main_thread_stack_end__ = .;
} > ram
.data :
{
. = ALIGN(4);
PROVIDE(_data = .);
*(.data)
. = ALIGN(4);
*(.data.*)
. = ALIGN(4);
*(.ramtext)
. = ALIGN(4);
PROVIDE(_edata = .);
} > ram AT > flash
.bss :
{
. = ALIGN(4);
PROVIDE(_bss_start = .);
*(.bss)
. = ALIGN(4);
*(.bss.*)
. = ALIGN(4);
*(COMMON)
. = ALIGN(4);
PROVIDE(_bss_end = .);
} > ram
}
PROVIDE(end = .);
_end = .;
__heap_base__ = _end;
__heap_end__ = __ram_end__;

View File

@ -0,0 +1,87 @@
/*
ChibiOS/RT - Copyright (C) 2006-2014 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file GCC/ARMCMx/KL2x/cmparams.h
* @brief ARM Cortex-M0+ parameters for the Kinetis KL2x.
*
* @defgroup ARMCMx_KL2x Kinetis KL2x Specific Parameters
* @ingroup ARMCMx_SPECIFIC
* @details This file contains the Cortex-M0+ specific parameters for the
* Kinetis KL2x platform.
* @{
*/
#ifndef _CMPARAMS_H_
#define _CMPARAMS_H_
/**
* @brief Cortex core model.
*/
#define CORTEX_MODEL CORTEX_M0PLUS
/**
* @brief Systick unit presence.
*/
#define CORTEX_HAS_ST TRUE
/**
* @brief Memory Protection unit presence.
*/
#define CORTEX_HAS_MPU FALSE
/**
* @brief Floating Point unit presence.
*/
#define CORTEX_HAS_FPU FALSE
/**
* @brief Number of bits in priority masks.
*/
#define CORTEX_PRIORITY_BITS 2
/**
* @brief Number of interrupt vectors.
* @note This number does not include the 16 system vectors and must be
* rounded to a multiple of 8.
*/
#define CORTEX_NUM_VECTORS 32
/* The following code is not processed when the file is included from an
asm module.*/
#if !defined(_FROM_ASM_)
/* Including the device CMSIS header. Note, we are not using the definitions
from this header because we need this file to be usable also from
assembler source files. We verify that the info matches instead.*/
#include "kl25z.h"
#if !CORTEX_HAS_MPU != !__MPU_PRESENT
#error "CMSIS __MPU_PRESENT mismatch"
#endif
#if CORTEX_PRIORITY_BITS != __NVIC_PRIO_BITS
#error "CMSIS __NVIC_PRIO_BITS mismatch"
#endif
#endif /* !defined(_FROM_ASM_) */
#endif /* _CMPARAMS_H_ */
/** @} */

1147
os/ext/CMSIS/KINETIS/kl25z.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,128 @@
/*
ChibiOS/RT - Copyright (C) 2006-2014 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "ch.h"
#include "hal.h"
#if HAL_USE_PAL || defined(__DOXYGEN__)
/**
* @brief PAL setup.
* @details Digital I/O ports static configuration as defined in @p board.h.
* This variable is used by the HAL when initializing the PAL driver.
*/
const PALConfig pal_default_config =
{
.ports = {
{
.port = IOPORT1, // PORTA
.pads = {
/* PTA0*/ PAL_MODE_ALTERNATIVE_7, /* PTA1*/ PAL_MODE_ALTERNATIVE_2, /* PTA2*/ PAL_MODE_ALTERNATIVE_2,
/* PTA3*/ PAL_MODE_ALTERNATIVE_7, /* PTA4*/ PAL_MODE_INPUT_ANALOG, /* PTA5*/ PAL_MODE_INPUT_ANALOG,
/* PTA6*/ PAL_MODE_UNCONNECTED, /* PTA7*/ PAL_MODE_UNCONNECTED, /* PTA8*/ PAL_MODE_UNCONNECTED,
/* PTA9*/ PAL_MODE_UNCONNECTED, /*PTA10*/ PAL_MODE_UNCONNECTED, /*PTA11*/ PAL_MODE_UNCONNECTED,
/*PTA12*/ PAL_MODE_INPUT_ANALOG, /*PTA13*/ PAL_MODE_INPUT_ANALOG, /*PTA14*/ PAL_MODE_INPUT_ANALOG,
/*PTA15*/ PAL_MODE_INPUT_ANALOG, /*PTA16*/ PAL_MODE_INPUT_ANALOG, /*PTA17*/ PAL_MODE_INPUT_ANALOG,
/*PTA18*/ PAL_MODE_INPUT_ANALOG, /*PTA19*/ PAL_MODE_INPUT_ANALOG, /*PTA20*/ PAL_MODE_ALTERNATIVE_7,
/*PTA21*/ PAL_MODE_UNCONNECTED, /*PTA22*/ PAL_MODE_UNCONNECTED, /*PTA23*/ PAL_MODE_UNCONNECTED,
/*PTA24*/ PAL_MODE_UNCONNECTED, /*PTA25*/ PAL_MODE_UNCONNECTED, /*PTA26*/ PAL_MODE_UNCONNECTED,
/*PTA27*/ PAL_MODE_UNCONNECTED, /*PTA28*/ PAL_MODE_UNCONNECTED, /*PTA29*/ PAL_MODE_UNCONNECTED,
/*PTA30*/ PAL_MODE_UNCONNECTED, /*PTA31*/ PAL_MODE_UNCONNECTED,
},
},
{
.port = IOPORT2, // PORTB
.pads = {
/* PTB0*/ PAL_MODE_INPUT_ANALOG, /* PTB1*/ PAL_MODE_INPUT_ANALOG, /* PTB2*/ PAL_MODE_INPUT_ANALOG,
/* PTB3*/ PAL_MODE_INPUT_ANALOG, /* PTB4*/ PAL_MODE_UNCONNECTED, /* PTB5*/ PAL_MODE_UNCONNECTED,
/* PTB6*/ PAL_MODE_UNCONNECTED, /* PTB7*/ PAL_MODE_UNCONNECTED, /* PTB8*/ PAL_MODE_INPUT_ANALOG,
/* PTB9*/ PAL_MODE_INPUT_ANALOG, /*PTB10*/ PAL_MODE_INPUT_ANALOG, /*PTB11*/ PAL_MODE_INPUT_ANALOG,
/*PTB12*/ PAL_MODE_UNCONNECTED, /*PTB13*/ PAL_MODE_UNCONNECTED, /*PTB14*/ PAL_MODE_UNCONNECTED,
/*PTB15*/ PAL_MODE_UNCONNECTED, /*PTB16*/ PAL_MODE_INPUT_ANALOG, /*PTB17*/ PAL_MODE_INPUT_ANALOG,
/*PTB18*/ PAL_MODE_OUTPUT_PUSHPULL, /*PTB19*/ PAL_MODE_OUTPUT_PUSHPULL, /*PTB20*/ PAL_MODE_UNCONNECTED,
/*PTB21*/ PAL_MODE_UNCONNECTED, /*PTB22*/ PAL_MODE_UNCONNECTED, /*PTB23*/ PAL_MODE_UNCONNECTED,
/*PTB24*/ PAL_MODE_UNCONNECTED, /*PTB25*/ PAL_MODE_UNCONNECTED, /*PTB26*/ PAL_MODE_UNCONNECTED,
/*PTB27*/ PAL_MODE_UNCONNECTED, /*PTB28*/ PAL_MODE_UNCONNECTED, /*PTB29*/ PAL_MODE_UNCONNECTED,
/*PTB30*/ PAL_MODE_UNCONNECTED, /*PTB31*/ PAL_MODE_UNCONNECTED,
},
},
{
.port = IOPORT3, // PORTC
.pads = {
/* PTC0*/ PAL_MODE_INPUT_ANALOG, /* PTC1*/ PAL_MODE_INPUT_ANALOG, /* PTC2*/ PAL_MODE_INPUT_ANALOG,
/* PTC3*/ PAL_MODE_INPUT_ANALOG, /* PTC4*/ PAL_MODE_INPUT_ANALOG, /* PTC5*/ PAL_MODE_INPUT_ANALOG,
/* PTC6*/ PAL_MODE_INPUT_ANALOG, /* PTC7*/ PAL_MODE_INPUT_ANALOG, /* PTC8*/ PAL_MODE_INPUT_ANALOG,
/* PTC9*/ PAL_MODE_INPUT_ANALOG, /*PTC10*/ PAL_MODE_INPUT_ANALOG, /*PTC11*/ PAL_MODE_INPUT_ANALOG,
/*PTC12*/ PAL_MODE_INPUT_ANALOG, /*PTC13*/ PAL_MODE_INPUT_ANALOG, /*PTC14*/ PAL_MODE_INPUT_ANALOG,
/*PTC15*/ PAL_MODE_INPUT_ANALOG, /*PTC16*/ PAL_MODE_INPUT_ANALOG, /*PTC17*/ PAL_MODE_INPUT_ANALOG,
/*PTC18*/ PAL_MODE_UNCONNECTED, /*PTC19*/ PAL_MODE_UNCONNECTED, /*PTC20*/ PAL_MODE_UNCONNECTED,
/*PTC21*/ PAL_MODE_UNCONNECTED, /*PTC22*/ PAL_MODE_UNCONNECTED, /*PTC23*/ PAL_MODE_UNCONNECTED,
/*PTC24*/ PAL_MODE_UNCONNECTED, /*PTC25*/ PAL_MODE_UNCONNECTED, /*PTC26*/ PAL_MODE_UNCONNECTED,
/*PTC27*/ PAL_MODE_UNCONNECTED, /*PTC28*/ PAL_MODE_UNCONNECTED, /*PTC29*/ PAL_MODE_UNCONNECTED,
/*PTC30*/ PAL_MODE_UNCONNECTED, /*PTC31*/ PAL_MODE_UNCONNECTED,
},
},
{
.port = IOPORT4, // PORTD
.pads = {
/* PTD0*/ PAL_MODE_INPUT_ANALOG, /* PTD1*/ PAL_MODE_OUTPUT_PUSHPULL, /* PTD2*/ PAL_MODE_INPUT_ANALOG,
/* PTD3*/ PAL_MODE_INPUT_ANALOG, /* PTD4*/ PAL_MODE_INPUT_ANALOG, /* PTD5*/ PAL_MODE_INPUT_ANALOG,
/* PTD6*/ PAL_MODE_INPUT_ANALOG, /* PTD7*/ PAL_MODE_INPUT_ANALOG, /* PTD8*/ PAL_MODE_INPUT_ANALOG,
/* PTD9*/ PAL_MODE_UNCONNECTED, /*PTD10*/ PAL_MODE_UNCONNECTED, /*PTD11*/ PAL_MODE_UNCONNECTED,
/*PTD12*/ PAL_MODE_UNCONNECTED, /*PTD13*/ PAL_MODE_UNCONNECTED, /*PTD14*/ PAL_MODE_UNCONNECTED,
/*PTD15*/ PAL_MODE_UNCONNECTED, /*PTD16*/ PAL_MODE_UNCONNECTED, /*PTD17*/ PAL_MODE_UNCONNECTED,
/*PTD18*/ PAL_MODE_UNCONNECTED, /*PTD19*/ PAL_MODE_UNCONNECTED, /*PTD20*/ PAL_MODE_UNCONNECTED,
/*PTD21*/ PAL_MODE_UNCONNECTED, /*PTD22*/ PAL_MODE_UNCONNECTED, /*PTD23*/ PAL_MODE_UNCONNECTED,
/*PTD24*/ PAL_MODE_UNCONNECTED, /*PTD25*/ PAL_MODE_UNCONNECTED, /*PTD26*/ PAL_MODE_UNCONNECTED,
/*PTD27*/ PAL_MODE_UNCONNECTED, /*PTD28*/ PAL_MODE_UNCONNECTED, /*PTD29*/ PAL_MODE_UNCONNECTED,
/*PTD30*/ PAL_MODE_UNCONNECTED, /*PTD31*/ PAL_MODE_UNCONNECTED,
},
},
{
.port = IOPORT5, // PORTE
.pads = {
/* PTE0*/ PAL_MODE_INPUT_ANALOG, /* PTE1*/ PAL_MODE_INPUT_ANALOG, /* PTE2*/ PAL_MODE_INPUT_ANALOG,
/* PTE3*/ PAL_MODE_INPUT_ANALOG, /* PTE4*/ PAL_MODE_INPUT_ANALOG, /* PTE5*/ PAL_MODE_INPUT_ANALOG,
/* PTE6*/ PAL_MODE_UNCONNECTED, /* PTE7*/ PAL_MODE_UNCONNECTED, /* PTE8*/ PAL_MODE_UNCONNECTED,
/* PTE9*/ PAL_MODE_UNCONNECTED, /*PTE10*/ PAL_MODE_UNCONNECTED, /*PTE11*/ PAL_MODE_UNCONNECTED,
/*PTE12*/ PAL_MODE_UNCONNECTED, /*PTE13*/ PAL_MODE_UNCONNECTED, /*PTE14*/ PAL_MODE_UNCONNECTED,
/*PTE15*/ PAL_MODE_UNCONNECTED, /*PTE16*/ PAL_MODE_UNCONNECTED, /*PTE17*/ PAL_MODE_UNCONNECTED,
/*PTE18*/ PAL_MODE_UNCONNECTED, /*PTE19*/ PAL_MODE_UNCONNECTED, /*PTE20*/ PAL_MODE_INPUT_ANALOG,
/*PTE21*/ PAL_MODE_INPUT_ANALOG, /*PTE22*/ PAL_MODE_INPUT_ANALOG, /*PTE23*/ PAL_MODE_INPUT_ANALOG,
/*PTE24*/ PAL_MODE_ALTERNATIVE_5, /*PTE25*/ PAL_MODE_ALTERNATIVE_5, /*PTE26*/ PAL_MODE_UNCONNECTED,
/*PTE27*/ PAL_MODE_UNCONNECTED, /*PTE28*/ PAL_MODE_UNCONNECTED, /*PTE29*/ PAL_MODE_INPUT_ANALOG,
/*PTE30*/ PAL_MODE_INPUT_ANALOG, /*PTE31*/ PAL_MODE_INPUT_ANALOG,
},
},
},
};
#endif
/**
* @brief Early initialization code.
* @details This initialization must be performed just after stack setup
* and before any other initialization.
*/
void __early_init(void) {
kl2x_clock_init();
}
/**
* @brief Board-specific initialization code.
* @todo Add your board-specific code, if any.
*/
void boardInit(void) {
}

View File

@ -0,0 +1,44 @@
/*
ChibiOS/RT - Copyright (C) 2006-2014 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef _BOARD_H_
#define _BOARD_H_
/*
* Setup for Freescale Freedom KL25Z board.
*/
/*
* Board identifier.
*/
#define BOARD_FREESCALE_FREEDOM_KL25Z
#define BOARD_NAME "Freescale Freedom KL25Z"
/* External 8 MHz crystal with PLL for 48 MHz core/system clock. */
#define KINETIS_SYSCLK_FREQUENCY 48000000UL
#define KINETIS_MCG_MODE KINETIS_MCG_MODE_PEE
#if !defined(_FROM_ASM_)
#ifdef __cplusplus
extern "C" {
#endif
void boardInit(void);
#ifdef __cplusplus
}
#endif
#endif /* _FROM_ASM_ */
#endif /* _BOARD_H_ */

View File

@ -0,0 +1,5 @@
# List of all the board related files.
BOARDSRC = ${CHIBIOS}/os/hal/boards/FREESCALE_FREEDOM_KL25Z/board.c
# Required include directories
BOARDINC = ${CHIBIOS}/os/hal/boards/FREESCALE_FREEDOM_KL25Z

View File

@ -0,0 +1,282 @@
/*
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file KL2x/hal_lld.c
* @brief Kinetis KL2x HAL Driver subsystem low level driver source.
*
* @addtogroup HAL
* @{
*/
#include "osal.h"
#include "hal.h"
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level HAL driver initialization.
*
* @notapi
*/
void hal_lld_init(void) {
}
/**
* @brief KL2x clocks and PLL initialization.
* @note All the involved constants come from the file @p board.h.
* @note This function should be invoked just after the system reset.
*
* @special
*/
void kl2x_clock_init(void) {
#if !KINETIS_NO_INIT
/* Disable COP watchdog */
SIM->COPC = 0;
/* Enable PORTA */
SIM->SCGC5 |= SIM_SCGC5_PORTA;
/* --- MCG mode: FEI (default out of reset) ---
f_MCGOUTCLK = f_int * F
F is the FLL factor selected by C4[DRST_DRS] and C4[DMX32] bits.
Typical f_MCGOUTCLK = 21 MHz immediately after reset.
C4[DMX32]=0 and C4[DRST_DRS]=00 => FLL factor=640.
C3[SCTRIM] and C4[SCFTRIM] factory trim values apply to f_int. */
/* System oscillator drives 32 kHz clock (OSC32KSEL=0) */
SIM->SOPT1 &= ~SIM_SOPT1_OSC32KSEL_MASK;
#if KINETIS_MCG_MODE == KINETIS_MCG_MODE_FEI
/* This is the default mode at reset. */
/* The MCGOUTCLK is divided by OUTDIV1 and OUTDIV4:
* OUTDIV1 (divider for core/system and bus/flash clock)
* OUTDIV4 (additional divider for bus/flash clock) */
SIM->CLKDIV1 =
SIM_CLKDIV1_OUTDIV1(1) | /* OUTDIV1 = divide-by-2 => 24 MHz */
SIM_CLKDIV1_OUTDIV4(0); /* OUTDIV4 = divide-by-1 => 24 MHz */
#elif KINETIS_MCG_MODE == KINETIS_MCG_MODE_FEE
/*
* FLL Enabled External (FEE) MCG Mode
* 24 MHz core, 12 MHz bus - using 32.768 kHz crystal with FLL.
* f_MCGOUTCLK = (f_ext / FLL_R) * F
* = (32.768 kHz ) *
* FLL_R is the reference divider selected by C1[FRDIV]
* F is the FLL factor selected by C4[DRST_DRS] and C4[DMX32].
*
* Then the core/system and bus/flash clocks are divided:
* f_SYS = f_MCGOUTCLK / OUTDIV1 = 48 MHz / 1 = 48 MHz
* f_BUS = f_MCGOUTCLK / OUTDIV1 / OUTDIV4 = MHz / 4 = 24 MHz
*/
SIM->SOPT2 =
SIM_SOPT2_TPMSRC(1); /* MCGFLLCLK clock or MCGPLLCLK/2 */
/* PLLFLLSEL=0 -> MCGFLLCLK */
/* The MCGOUTCLK is divided by OUTDIV1 and OUTDIV4:
* OUTDIV1 (divider for core/system and bus/flash clock)
* OUTDIV4 (additional divider for bus/flash clock) */
SIM->CLKDIV1 =
SIM_CLKDIV1_OUTDIV1(KINETIS_MCG_FLL_OUTDIV1 - 1) |
SIM_CLKDIV1_OUTDIV4(KINETIS_MCG_FLL_OUTDIV4 - 1);
/* EXTAL0 and XTAL0 */
PORTA->PCR[18] &= ~0x01000700; /* Set PA18 to analog (default) */
PORTA->PCR[19] &= ~0x01000700; /* Set PA19 to analog (default) */
OSC0->CR = 0;
/* From KL25P80M48SF0RM section 24.5.1.1 "Initializing the MCG". */
/* To change from FEI mode to FEE mode: */
/* (1) Select the external clock source in C2 register.
Use low-power OSC mode (HGO0=0) which enables internal feedback
resistor, for 32.768 kHz crystal configuration. */
MCG->C2 =
MCG_C2_RANGE0(0) | /* low frequency range (<= 40 kHz) */
MCG_C2_EREFS0; /* external reference (using a crystal) */
/* (2) Write to C1 to select the clock mode. */
MCG->C1 = /* Clear the IREFS bit to switch to the external reference. */
MCG_C1_CLKS_FLLPLL | /* Use FLL for system clock, MCGCLKOUT. */
MCG_C1_FRDIV(0); /* Don't divide 32kHz ERCLK FLL reference. */
MCG->C6 = 0; /* PLLS=0: Select FLL as MCG source, not PLL */
/* Loop until S[OSCINIT0] is 1, indicating the
crystal selected by C2[EREFS0] has been initialized. */
while ((MCG->S & MCG_S_OSCINIT0) == 0)
;
/* Loop until S[IREFST] is 0, indicating the
external reference is the current reference clock source. */
while ((MCG->S & MCG_S_IREFST) != 0)
; /* Wait until external reference clock is FLL reference. */
/* (1)(e) Loop until S[CLKST] indicates FLL feeds MCGOUTCLK. */
while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST_FLL)
; /* Wait until FLL has been selected. */
/* --- MCG mode: FEE --- */
/* Set frequency range for DCO output (MCGFLLCLK). */
MCG->C4 = (KINETIS_MCG_FLL_DMX32 ? MCG_C4_DMX32 : 0) |
MCG_C4_DRST_DRS(KINETIS_MCG_FLL_DRS);
/* Wait for the FLL lock time; t[fll_acquire][max] = 1 ms */
/* TODO - not implemented - is it required? Freescale example code
seems to omit it. */
#elif KINETIS_MCG_MODE == KINETIS_MCG_MODE_PEE
/*
* PLL Enabled External (PEE) MCG Mode
* 48 MHz core, 24 MHz bus - using 8 MHz crystal with PLL.
* f_MCGOUTCLK = (OSCCLK / PLL_R) * M
* = 8 MHz / 2 * 24 = 96 MHz
* PLL_R is the reference divider selected by C5[PRDIV0]
* M is the multiplier selected by C6[VDIV0]
*
* Then the core/system and bus/flash clocks are divided:
* f_SYS = f_MCGOUTCLK / OUTDIV1 = 96 MHz / 2 = 48 MHz
* f_BUS = f_MCGOUTCLK / OUTDIV1 / OUTDIV4 = 96 MHz / 4 = 24 MHz
*/
/* The MCGOUTCLK is divided by OUTDIV1 and OUTDIV4:
* OUTDIV1 (divider for core/system and bus/flash clock)
* OUTDIV4 (additional divider for bus/flash clock) */
SIM->CLKDIV1 =
SIM_CLKDIV1_OUTDIV1(1) | /* OUTDIV1 = divide-by-2 => 48 MHz */
SIM_CLKDIV1_OUTDIV4(1); /* OUTDIV4 = divide-by-2 => 24 MHz */
SIM->SOPT2 =
SIM_SOPT2_TPMSRC(1) | /* MCGFLLCLK clock or MCGPLLCLK/2 */
SIM_SOPT2_PLLFLLSEL; /* PLLFLLSEL=MCGPLLCLK/2 */
/* EXTAL0 and XTAL0 */
PORTA->PCR[18] &= ~0x01000700; /* Set PA18 to analog (default) */
PORTA->PCR[19] &= ~0x01000700; /* Set PA19 to analog (default) */
OSC0->CR = 0;
/* From KL25P80M48SF0RM section 24.5.1.1 "Initializing the MCG". */
/* To change from FEI mode to FBE mode: */
/* (1) Select the external clock source in C2 register.
Use low-power OSC mode (HGO0=0) which enables internal feedback
resistor since FRDM-KL25Z has feedback resistor R25 unpopulated.
Use high-gain mode by setting C2[HGO0] instead if external
feedback resistor Rf is installed. */
MCG->C2 =
MCG_C2_RANGE0(2) | /* very high frequency range */
MCG_C2_EREFS0; /* external reference (using a crystal) */
/* (2) Write to C1 to select the clock mode. */
MCG->C1 = /* Clear the IREFS bit to switch to the external reference. */
MCG_C1_CLKS_ERCLK | /* Use ERCLK for system clock, MCGCLKOUT. */
MCG_C1_FRDIV(3); /* Divide ERCLK / 256 for FLL reference. */
/* Note: FLL reference frequency must be 31.25 kHz to 39.0625 kHz.
8 MHz / 256 = 31.25 kHz. */
MCG->C4 &= ~(MCG_C4_DMX32 | MCG_C4_DRST_DRS_MASK);
MCG->C6 = 0; /* PLLS=0: Select FLL as MCG source, not PLL */
/* (3) Once configuration is set, wait for MCG mode change. */
/* From KL25P80M48SF0RM section 24.5.31: */
/* (1)(c) Loop until S[OSCINIT0] is 1, indicating the
crystal selected by C2[EREFS0] has been initialized. */
while ((MCG->S & MCG_S_OSCINIT0) == 0)
;
/* (1)(d) Loop until S[IREFST] is 0, indicating the
external reference is the current reference clock source. */
while ((MCG->S & MCG_S_IREFST) != 0)
; /* Wait until external reference clock is FLL reference. */
/* (1)(e) Loop until S[CLKST] is 2'b10, indicating
the external reference clock is selected to feed MCGOUTCLK. */
while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST_ERCLK)
; /* Wait until external reference clock has been selected. */
/* --- MCG mode: FBE (FLL bypassed, external crystal) ---
Now the MCG is in FBE mode.
Although the FLL is bypassed, it is still on. */
/* (2) Then configure C5[PRDIV0] to generate the
correct PLL reference frequency. */
MCG->C5 = MCG_C5_PRDIV0(1); /* PLL External Reference Divide by 2 */
/* (3) Then from FBE transition to PBE mode. */
/* (3)(b) C6[PLLS]=1 to select PLL. */
/* (3)(b) C6[VDIV0]=5'b0000 (x24) 2 MHz * 24 = 48 MHz. */
MCG->C6 = MCG_C6_PLLS | MCG_C6_VDIV0(0);
/* (3)(d) Loop until S[PLLST], indicating PLL
is the PLLS clock source. */
while ((MCG->S & MCG_S_PLLST) == 0)
; /* wait until PLL is the PLLS clock source. */
/* (3)(e) Loop until S[LOCK0] is set, indicating the PLL has acquired lock. */
/* PLL selected as MCG source. VDIV0=00000 (Multiply=24). */
while ((MCG->S & MCG_S_LOCK0) == 0)
; /* wait until PLL locked */
/* --- MCG mode: PBE (PLL bypassed, external crystal) --- */
/* (4) Transition from PBE mode to PEE mode. */
/* (4)(a) C1[CLKS] = 2'b00 to select PLL output as system clock source. */
// Switch to PEE mode
// Select PLL output (CLKS=0)
// FLL external reference divider (FRDIV=3)
// External reference clock for FLL (IREFS=0)
MCG->C1 = MCG_C1_CLKS(0) |
MCG_C1_FRDIV(3);
/* (4)(b) Loop until S[CLKST] are 2'b11, indicating the PLL output is selected for MCGOUTCLK. */
while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST_PLL)
; /* wait until clock switched to PLL output */
/* --- MCG mode: PEE (PLL enabled, external crystal) --- */
#else /* KINETIS_MCG_MODE != KINETIS_MCG_MODE_PEE */
#error Unimplemented KINETIS_MCG_MODE
#endif /* KINETIS_MCG_MODE != KINETIS_MCG_MODE_PEE */
#endif /* !KINETIS_NO_INIT */
}
/**
* @brief Platform early initialization.
* @note All the involved constants come from the file @p board.h.
* @note This function is meant to be invoked early during the system
* initialization, it is usually invoked from the file
* @p board.c.
*
* @special
*/
void platform_early_init(void) {
}
/** @} */

View File

@ -0,0 +1,268 @@
/*
ChibiOS/RT - Copyright (C) 2006-2014 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file KL2x/hal_lld.h
* @brief Kinetis KL2x HAL subsystem low level driver header.
*
* @addtogroup HAL
* @{
*/
#ifndef _HAL_LLD_H_
#define _HAL_LLD_H_
#include "kl25z.h"
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/**
* @brief Defines the support for realtime counters in the HAL.
*/
#define HAL_IMPLEMENTS_COUNTERS FALSE
/**
* @name Platform identification
* @{
*/
#define PLATFORM_NAME "Kinetis"
/** @} */
/**
* @brief Maximum system and core clock (f_SYS) frequency.
*/
#define KINETIS_SYSCLK_MAX 48000000
/**
* @brief Maximum bus clock (f_BUS) frequency.
*/
#define KINETIS_BUSCLK_MAX 24000000
/**
* @name Internal clock sources
* @{
*/
#define KINETIS_IRCLK_F 4000000 /**< Fast internal reference clock, factory trimmed. */
#define KINETIS_IRCLK_S 32768 /**< Slow internal reference clock, factory trimmed. */
/** @} */
#define KINETIS_MCG_MODE_FEI 1 /**< FLL Engaged Internal. */
#define KINETIS_MCG_MODE_FEE 2 /**< FLL Engaged External. */
#define KINETIS_MCG_MODE_FBI 3 /**< FLL Bypassed Internal. */
#define KINETIS_MCG_MODE_FBE 4 /**< FLL Bypassed External. */
#define KINETIS_MCG_MODE_PEE 5 /**< PLL Engaged External. */
#define KINETIS_MCG_MODE_PBE 6 /**< PLL Bypassed External. */
#define KINETIS_MCG_MODE_BLPI 7 /**< Bypassed Low Power Internal. */
#define KINETIS_MCG_MODE_BLPE 8 /**< Bypassed Low Power External. */
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name Configuration options
* @{
*/
/**
* @brief Disables the MCG/system clock initialization in the HAL.
*/
#if !defined(KINETIS_NO_INIT) || defined(__DOXYGEN__)
#define KINETIS_NO_INIT FALSE
#endif
/**
* @brief MCG mode selection.
*/
#if !defined(KINETIS_MCG_MODE) || defined(__DOXYGEN__)
#define KINETIS_MCG_MODE KINETIS_MCG_MODE_PEE
#endif
/**
* @brief Clock divider for core/system and bus/flash clocks (OUTDIV1).
* @note The allowed range is 1...16.
* @note The default value is calculated for a 48 MHz system clock
* from a 96 MHz PLL output.
*/
#if !defined(KINETIS_MCG_FLL_OUTDIV1) || defined(__DOXYGEN__)
#define KINETIS_MCG_FLL_OUTDIV1 2
#endif
/**
* @brief Additional clock divider bus/flash clocks (OUTDIV4).
* @note The allowed range is 1...8.
* @note This divider is on top of the OUTDIV1 divider.
* @note The default value is calculated for 24 MHz bus/flash clocks
* from a 96 MHz PLL output and 48 MHz core/system clock.
*/
#if !defined(KINETIS_MCG_FLL_OUTDIV4) || defined(__DOXYGEN__)
#define KINETIS_MCG_FLL_OUTDIV4 2
#endif
/**
* @brief FLL DCO tuning enable for 32.768 kHz reference.
* @note Set to 1 for fine-tuning DCO for maximum frequency with
* a 32.768 kHz reference.
* @note The default value is for a 32.768 kHz external crystal.
*/
#if !defined(KINETIS_MCG_FLL_DMX32) || defined(__DOXYGEN__)
#define KINETIS_MCG_FLL_DMX32 1
#endif
/**
* @brief FLL DCO range selection.
* @note The allowed range is 0...3.
* @note The default value is calculated for 48 MHz FLL output
* from a 32.768 kHz external crystal.
* (DMX32 && DRST_DRS=1 => F=1464; 32.768 kHz * F ~= 48 MHz.)
*
*/
#if !defined(KINETIS_MCG_FLL_DRS) || defined(__DOXYGEN__)
#define KINETIS_MCG_FLL_DRS 2
#endif
/**
* @brief MCU system/core clock frequency.
*/
#if !defined(KINETIS_SYSCLK_FREQUENCY) || defined(__DOXYGEN__)
#define KINETIS_SYSCLK_FREQUENCY 48000000UL
#endif
/**
* @brief MCU bus/flash clock frequency.
*/
#if !defined(KINETIS_BUSCLK_FREQUENCY) || defined(__DOXYGEN__)
#define KINETIS_BUSCLK_FREQUENCY (KINETIS_SYSCLK_FREQUENCY / KINETIS_MCG_FLL_OUTDIV4)
#endif
/**
* @brief UART0 clock frequency.
* @note The default value is based on 96 MHz PLL/2 source.
* If you use a different source, such as the FLL,
* you must set this properly.
*/
#if !defined(KINETIS_UART0_CLOCK_FREQ) || defined(__DOXYGEN__)
#define KINETIS_UART0_CLOCK_FREQ KINETIS_SYSCLK_FREQUENCY
#endif
/**
* @brief UART0 clock source.
* @note The default value is to use PLL/2 or FLL source.
*/
#if !defined(KINETIS_UART0_CLOCK_SRC) || defined(__DOXYGEN__)
#define KINETIS_UART0_CLOCK_SRC 1
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if !defined(KINETIS_SYSCLK_FREQUENCY)
#error KINETIS_SYSCLK_FREQUENCY must be defined
#endif
#if KINETIS_SYSCLK_FREQUENCY <= 0 || KINETIS_SYSCLK_FREQUENCY > KINETIS_SYSCLK_MAX
#error KINETIS_SYSCLK_FREQUENCY out of range
#endif
#if !defined(KINETIS_BUSCLK_FREQUENCY)
#error KINETIS_BUSCLK_FREQUENCY must be defined
#endif
#if KINETIS_BUSCLK_FREQUENCY <= 0 || KINETIS_BUSCLK_FREQUENCY > KINETIS_BUSCLK_MAX
#error KINETIS_BUSCLK_FREQUENCY out of range
#endif
#if !(defined(KINETIS_MCG_FLL_OUTDIV1) && \
KINETIS_MCG_FLL_OUTDIV1 >= 1 && KINETIS_MCG_FLL_OUTDIV1 <= 16)
#error KINETIS_MCG_FLL_OUTDIV1 must be 1 through 16
#endif
#if !(defined(KINETIS_MCG_FLL_OUTDIV4) && \
KINETIS_MCG_FLL_OUTDIV4 >= 1 && KINETIS_MCG_FLL_OUTDIV4 <= 8)
#error KINETIS_MCG_FLL_OUTDIV4 must be 1 through 8
#endif
#if !(KINETIS_MCG_FLL_DMX32 == 0 || KINETIS_MCG_FLL_DMX32 == 1)
#error Invalid KINETIS_MCG_FLL_DMX32 value, must be 0 or 1
#endif
#if !(0 <= KINETIS_MCG_FLL_DRS && KINETIS_MCG_FLL_DRS <= 3)
#error Invalid KINETIS_MCG_FLL_DRS value, must be 0...3
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Type representing a system clock frequency.
*/
typedef uint32_t halclock_t;
/**
* @brief Type of the realtime free counter value.
*/
typedef uint32_t halrtcnt_t;
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/**
* @brief Returns the current value of the system free running counter.
* @note This service is implemented by returning the content of the
* DWT_CYCCNT register.
*
* @return The value of the system free running counter of
* type halrtcnt_t.
*
* @notapi
*/
#define hal_lld_get_counter_value() 0
/**
* @brief Realtime counter frequency.
* @note The DWT_CYCCNT register is incremented directly by the system
* clock so this function returns STM32_HCLK.
*
* @return The realtime counter frequency of type halclock_t.
*
* @notapi
*/
#define hal_lld_get_counter_frequency() 0
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#include "nvic.h"
#ifdef __cplusplus
extern "C" {
#endif
void hal_lld_init(void);
void kl2x_clock_init(void);
#ifdef __cplusplus
}
#endif
#endif /* _HAL_LLD_H_ */
/** @} */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,225 @@
/*
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file KL2x/pal_lld.c
* @brief Kinetis KL2x PAL subsystem low level driver.
*
* @addtogroup PAL
* @{
*/
#include "osal.h"
#include "hal.h"
#if HAL_USE_PAL || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief STM32 I/O ports configuration.
* @details Ports A-D(E, F, G, H) clocks enabled.
*
* @param[in] config the STM32 ports configuration
*
* @notapi
*/
void _pal_lld_init(const PALConfig *config) {
int i, j;
/* Enable clocking of all Ports */
SIM->SCGC5 |= SIM_SCGC5_PORTA |
SIM_SCGC5_PORTB |
SIM_SCGC5_PORTC |
SIM_SCGC5_PORTD |
SIM_SCGC5_PORTE;
for (i = 0; i < TOTAL_PORTS; i++) {
for (j = 0; j < PADS_PER_PORT; j++) {
pal_lld_setpadmode(config->ports[i].port,
j,
config->ports[i].pads[j]);
}
}
}
/**
* @brief Pads mode setup.
* @details This function programs a pads group belonging to the same port
* with the specified mode.
*
* @param[in] port the port identifier
* @param[in] mask the group mask
* @param[in] mode the mode
*
* @notapi
*/
void _pal_lld_setgroupmode(ioportid_t port,
ioportmask_t mask,
iomode_t mode) {
(void)port;
(void)mask;
(void)mode;
}
/**
* @brief Reads a logical state from an I/O pad.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*
* @param[in] port port identifier
* @param[in] pad pad number within the port
* @return The logical state.
* @retval PAL_LOW low logical state.
* @retval PAL_HIGH high logical state.
*
* @notapi
*/
uint8_t pal_lld_readpad(ioportid_t port, uint8_t pad)
{
return (port->PDIR & ((uint32_t) 1 << pad)) ? PAL_HIGH : PAL_LOW;
}
/**
* @brief Writes a logical state on an output pad.
* @note This function is not meant to be invoked directly by the
* application code.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*
* @param[in] port port identifier
* @param[in] pad pad number within the port
* @param[in] bit logical value, the value must be @p PAL_LOW or
* @p PAL_HIGH
*
* @notapi
*/
void pal_lld_writepad(ioportid_t port, uint8_t pad, uint8_t bit)
{
if (bit == PAL_HIGH)
port->PDOR |= ((uint32_t) 1 << pad);
else
port->PDOR &= ~((uint32_t) 1 << pad);
}
/**
* @brief Pad mode setup.
* @details This function programs a pad with the specified mode.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
* @note Programming an unknown or unsupported mode is silently ignored.
*
* @param[in] port port identifier
* @param[in] pad pad number within the port
* @param[in] mode pad mode
*
* @notapi
*/
void pal_lld_setpadmode(ioportid_t port, uint8_t pad, iomode_t mode)
{
PORT_TypeDef *portcfg = NULL;
osalDbgAssert(pad <= 31, "pal_lld_setpadmode() - invalid pad");
if (mode == PAL_MODE_OUTPUT_PUSHPULL)
port->PDDR |= ((uint32_t) 1 << pad);
else
port->PDDR &= ~((uint32_t) 1 << pad);
if (port == IOPORT1)
portcfg = PORTA;
else if (port == IOPORT2)
portcfg = PORTB;
else if (port == IOPORT3)
portcfg = PORTC;
else if (port == IOPORT4)
portcfg = PORTD;
else if (port == IOPORT5)
portcfg = PORTE;
osalDbgAssert(portcfg != NULL, "pal_lld_setpadmode() - invalid port");
switch (mode) {
case PAL_MODE_RESET:
case PAL_MODE_INPUT:
case PAL_MODE_OUTPUT_PUSHPULL:
portcfg->PCR[pad] = PORTx_PCRn_MUX(1);
break;
case PAL_MODE_INPUT_PULLUP:
portcfg->PCR[pad] = PORTx_PCRn_MUX(1) | PORTx_PCRn_PE | PORTx_PCRn_PS;
break;
case PAL_MODE_INPUT_PULLDOWN:
portcfg->PCR[pad] = PORTx_PCRn_MUX(1) | PORTx_PCRn_PE;
break;
case PAL_MODE_UNCONNECTED:
case PAL_MODE_INPUT_ANALOG:
portcfg->PCR[pad] = PORTx_PCRn_MUX(0);
break;
case PAL_MODE_ALTERNATIVE_1:
portcfg->PCR[pad] = PORTx_PCRn_MUX(1);
break;
case PAL_MODE_ALTERNATIVE_2:
portcfg->PCR[pad] = PORTx_PCRn_MUX(2);
break;
case PAL_MODE_ALTERNATIVE_3:
portcfg->PCR[pad] = PORTx_PCRn_MUX(3);
break;
case PAL_MODE_ALTERNATIVE_4:
portcfg->PCR[pad] = PORTx_PCRn_MUX(4);
break;
case PAL_MODE_ALTERNATIVE_5:
portcfg->PCR[pad] = PORTx_PCRn_MUX(5);
break;
case PAL_MODE_ALTERNATIVE_6:
portcfg->PCR[pad] = PORTx_PCRn_MUX(6);
break;
case PAL_MODE_ALTERNATIVE_7:
portcfg->PCR[pad] = PORTx_PCRn_MUX(7);
break;
}
}
#endif /* HAL_USE_PAL */
/** @} */

View File

@ -0,0 +1,309 @@
/*
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file KL2x/pal_lld.h
* @brief Kinetis KL2x PAL subsystem low level driver header.
*
* @addtogroup PAL
* @{
*/
#ifndef _PAL_LLD_H_
#define _PAL_LLD_H_
#if HAL_USE_PAL || defined(__DOXYGEN__)
/*===========================================================================*/
/* Unsupported modes and specific modes */
/*===========================================================================*/
#undef PAL_MODE_OUTPUT_OPENDRAIN
#define PAL_MODE_ALTERNATIVE_1 0x10
#define PAL_MODE_ALTERNATIVE_2 0x11
#define PAL_MODE_ALTERNATIVE_3 0x12
#define PAL_MODE_ALTERNATIVE_4 0x13
#define PAL_MODE_ALTERNATIVE_5 0x14
#define PAL_MODE_ALTERNATIVE_6 0x15
#define PAL_MODE_ALTERNATIVE_7 0x16
/*===========================================================================*/
/* I/O Ports Types and constants. */
/*===========================================================================*/
#define TOTAL_PORTS 5
#define PADS_PER_PORT 32
/**
* @brief Digital I/O port sized unsigned type.
*/
typedef uint32_t ioportmask_t;
/**
* @brief Digital I/O modes.
*/
typedef uint8_t iomode_t;
/**
* @brief Port Identifier.
* @details This type can be a scalar or some kind of pointer, do not make
* any assumption about it, use the provided macros when populating
* variables of this type.
*/
typedef GPIO_TypeDef * ioportid_t;
typedef struct {
ioportid_t port;
iomode_t pads[PADS_PER_PORT];
} PortConfig;
/**
* @brief Generic I/O ports static initializer.
* @details An instance of this structure must be passed to @p palInit() at
* system startup time in order to initialized the digital I/O
* subsystem. This represents only the initial setup, specific pads
* or whole ports can be reprogrammed at later time.
* @note Implementations may extend this structure to contain more,
* architecture dependent, fields.
*/
typedef struct
{
PortConfig ports[TOTAL_PORTS];
} PALConfig;
/**
* @brief Width, in bits, of an I/O port.
*/
#define PAL_IOPORTS_WIDTH 32
/**
* @brief Whole port mask.
* @brief This macro specifies all the valid bits into a port.
*/
#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFFFFFF)
/*===========================================================================*/
/* I/O Ports Identifiers. */
/*===========================================================================*/
/**
* @brief First I/O port identifier.
* @details Low level drivers can define multiple ports, it is suggested to
* use this naming convention.
*/
#define IOPORT1 GPIOA
#define IOPORT2 GPIOB
#define IOPORT3 GPIOC
#define IOPORT4 GPIOD
#define IOPORT5 GPIOE
/*===========================================================================*/
/* Implementation, some of the following macros could be implemented as */
/* functions, if so please put them in pal_lld.c. */
/*===========================================================================*/
/**
* @brief Low level PAL subsystem initialization.
*
* @param[in] config architecture-dependent ports configuration
*
* @notapi
*/
#define pal_lld_init(config) _pal_lld_init(config)
/**
* @brief Reads the physical I/O port states.
*
* @param[in] port port identifier
* @return The port bits.
*
* @notapi
*/
#define pal_lld_readport(port) \
(port)->PDIR
/**
* @brief Reads the output latch.
* @details The purpose of this function is to read back the latched output
* value.
*
* @param[in] port port identifier
* @return The latched logical states.
*
* @notapi
*/
#define pal_lld_readlatch(port) 0
/**
* @brief Writes a bits mask on a I/O port.
*
* @param[in] port port identifier
* @param[in] bits bits to be written on the specified port
*
* @notapi
*/
#define pal_lld_writeport(port, bits)
/**
* @brief Sets a bits mask on a I/O port.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*
* @param[in] port port identifier
* @param[in] bits bits to be ORed on the specified port
*
* @notapi
*/
#define pal_lld_setport(port, bits)
/**
* @brief Clears a bits mask on a I/O port.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*
* @param[in] port port identifier
* @param[in] bits bits to be cleared on the specified port
*
* @notapi
*/
#define pal_lld_clearport(port, bits)
/**
* @brief Toggles a bits mask on a I/O port.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*
* @param[in] port port identifier
* @param[in] bits bits to be XORed on the specified port
*
* @notapi
*/
#define pal_lld_toggleport(port, bits)
/**
* @brief Reads a group of bits.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*
* @param[in] port port identifier
* @param[in] mask group mask
* @param[in] offset group bit offset within the port
* @return The group logical states.
*
* @notapi
*/
#define pal_lld_readgroup(port, mask, offset) 0
/**
* @brief Writes a group of bits.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*
* @param[in] port port identifier
* @param[in] mask group mask
* @param[in] offset group bit offset within the port
* @param[in] bits bits to be written. Values exceeding the group width
* are masked.
*
* @notapi
*/
#define pal_lld_writegroup(port, mask, offset, bits) (void)bits
/**
* @brief Pads group mode setup.
* @details This function programs a pads group belonging to the same port
* with the specified mode.
* @note Programming an unknown or unsupported mode is silently ignored.
*
* @param[in] port port identifier
* @param[in] mask group mask
* @param[in] offset group bit offset within the port
* @param[in] mode group mode
*
* @notapi
*/
#define pal_lld_setgroupmode(port, mask, offset, mode) \
_pal_lld_setgroupmode(port, mask << offset, mode)
/**
* @brief Sets a pad logical state to @p PAL_HIGH.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*
* @param[in] port port identifier
* @param[in] pad pad number within the port
*
* @notapi
*/
#define pal_lld_setpad(port, pad) (port)->PSOR |= ((uint32_t) 1 << (pad))
/**
* @brief Clears a pad logical state to @p PAL_LOW.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*
* @param[in] port port identifier
* @param[in] pad pad number within the port
*
* @notapi
*/
#define pal_lld_clearpad(port, pad) (port)->PCOR |= ((uint32_t) 1 << (pad))
/**
* @brief Toggles a pad logical state.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*
* @param[in] port port identifier
* @param[in] pad pad number within the port
*
* @notapi
*/
#define pal_lld_togglepad(port, pad) (port)->PTOR |= ((uint32_t) 1 << (pad))
#if !defined(__DOXYGEN__)
extern const PALConfig pal_default_config;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void _pal_lld_init(const PALConfig *config);
void _pal_lld_setgroupmode(ioportid_t port,
ioportmask_t mask,
iomode_t mode);
void pal_lld_setpadmode(ioportid_t port,
uint8_t pad,
iomode_t mode);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_PAL */
#endif /* _PAL_LLD_H_ */
/** @} */

View File

@ -0,0 +1,10 @@
# List of all platform files.
PLATFORMSRC = ${CHIBIOS}/os/hal/ports/common/ARMCMx/nvic.c \
${CHIBIOS}/os/hal/ports/KINETIS/KL2x/hal_lld.c \
${CHIBIOS}/os/hal/ports/KINETIS/KL2x/pal_lld.c \
${CHIBIOS}/os/hal/ports/KINETIS/KL2x/serial_lld.c \
${CHIBIOS}/os/hal/ports/KINETIS/KL2x/st_lld.c
# Required include directories
PLATFORMINC = ${CHIBIOS}/os/hal/ports/common/ARMCMx \
${CHIBIOS}/os/hal/ports/KINETIS/KL2x

View File

@ -0,0 +1,353 @@
/*
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file KL2x/serial_lld.c
* @brief Kinetis KL2x Serial Driver subsystem low level driver source.
*
* @addtogroup SERIAL
* @{
*/
#include "ch.h"
#include "hal.h"
#if HAL_USE_SERIAL || defined(__DOXYGEN__)
#include "kl25z.h"
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/**
* @brief SD1 driver identifier.
*/
#if KINETIS_SERIAL_USE_UART0 || defined(__DOXYGEN__)
SerialDriver SD1;
#endif
#if KINETIS_SERIAL_USE_UART1 || defined(__DOXYGEN__)
SerialDriver SD2;
#endif
#if KINETIS_SERIAL_USE_UART2 || defined(__DOXYGEN__)
SerialDriver SD3;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/**
* @brief Driver default configuration.
*/
static const SerialConfig default_config = {
38400
};
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/**
* @brief Common IRQ handler.
* @note Tries hard to clear all the pending interrupt sources, we don't
* want to go through the whole ISR and have another interrupt soon
* after.
*
* @param[in] u pointer to an UART I/O block
* @param[in] sdp communication channel associated to the UART
*/
static void serve_interrupt(SerialDriver *sdp) {
UARTLP_TypeDef *u = sdp->uart;
if (u->S1 & UARTx_S1_RDRF) {
osalSysLockFromISR();
if (chIQIsEmptyI(&sdp->iqueue))
chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE);
if (chIQPutI(&sdp->iqueue, u->D) < Q_OK)
chnAddFlagsI(sdp, SD_OVERRUN_ERROR);
osalSysUnlockFromISR();
}
if (u->S1 & UARTx_S1_TDRE) {
msg_t b;
osalSysLockFromISR();
b = chOQGetI(&sdp->oqueue);
osalSysUnlockFromISR();
if (b < Q_OK) {
osalSysLockFromISR();
chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
osalSysUnlockFromISR();
u->C2 &= ~UARTx_C2_TIE;
} else {
u->D = b;
}
}
if (u->S1 & UARTx_S1_IDLE)
u->S1 = UARTx_S1_IDLE; // Clear IDLE (S1 bits are write-1-to-clear).
if (u->S1 & (UARTx_S1_OR | UARTx_S1_NF | UARTx_S1_FE | UARTx_S1_PF)) {
// FIXME: need to add set_error()
// Clear flags (S1 bits are write-1-to-clear).
u->S1 = UARTx_S1_OR | UARTx_S1_NF | UARTx_S1_FE | UARTx_S1_PF;
}
}
/**
* @brief Attempts a TX preload
*/
static void preload(SerialDriver *sdp) {
UARTLP_TypeDef *u = sdp->uart;
if (u->S1 & UARTx_S1_TDRE) {
msg_t b = chOQGetI(&sdp->oqueue);
if (b < Q_OK) {
chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
return;
}
u->D = b;
u->C2 |= UARTx_C2_TIE;
}
}
/**
* @brief Driver output notification.
*/
#if KINETIS_SERIAL_USE_UART0 || defined(__DOXYGEN__)
static void notify1(GenericQueue *qp)
{
(void)qp;
preload(&SD1);
}
#endif
#if KINETIS_SERIAL_USE_UART1 || defined(__DOXYGEN__)
static void notify2(GenericQueue *qp)
{
(void)qp;
preload(&SD2);
}
#endif
#if KINETIS_SERIAL_USE_UART2 || defined(__DOXYGEN__)
static void notify3(GenericQueue *qp)
{
(void)qp;
preload(&SD3);
}
#endif
/**
* @brief Common UART configuration.
*
*/
static void configure_uart(UARTLP_TypeDef *uart, const SerialConfig *config)
{
uint32_t uart_clock;
uart->C1 = 0;
uart->C3 = UARTx_C3_ORIE | UARTx_C3_NEIE | UARTx_C3_FEIE | UARTx_C3_PEIE;
uart->S1 = UARTx_S1_IDLE | UARTx_S1_OR | UARTx_S1_NF | UARTx_S1_FE | UARTx_S1_PF;
while (uart->S1 & UARTx_S1_RDRF) {
(void)uart->D;
}
#if KINETIS_SERIAL_USE_UART0
if (uart == UART0) {
/* UART0 can be clocked from several sources. */
uart_clock = KINETIS_UART0_CLOCK_FREQ;
}
#endif
#if KINETIS_SERIAL_USE_UART1
if (uart == UART1) {
uart_clock = KINETIS_BUSCLK_FREQUENCY;
}
#endif
#if KINETIS_SERIAL_USE_UART2
if (uart == UART2) {
uart_clock = KINETIS_BUSCLK_FREQUENCY;
}
#endif
/* FIXME: change fixed OSR = 16 to dynamic value based on baud */
uint16_t divisor = (uart_clock / 16) / config->sc_speed;
uart->C4 = UARTx_C4_OSR & (16 - 1);
uart->BDH = (divisor >> 8) & UARTx_BDH_SBR;
uart->BDL = (divisor & UARTx_BDL_SBR);
uart->C2 = UARTx_C2_RE | UARTx_C2_RIE | UARTx_C2_TE;
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if KINETIS_SERIAL_USE_UART0 || defined(__DOXYGEN__)
CH_IRQ_HANDLER(Vector70) {
CH_IRQ_PROLOGUE();
serve_interrupt(&SD1);
CH_IRQ_EPILOGUE();
}
#endif
#if KINETIS_SERIAL_USE_UART1 || defined(__DOXYGEN__)
CH_IRQ_HANDLER(Vector74) {
CH_IRQ_PROLOGUE();
serve_interrupt(&SD2);
CH_IRQ_EPILOGUE();
}
#endif
#if KINETIS_SERIAL_USE_UART2 || defined(__DOXYGEN__)
CH_IRQ_HANDLER(Vector78) {
CH_IRQ_PROLOGUE();
serve_interrupt(&SD3);
CH_IRQ_EPILOGUE();
}
#endif
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level serial driver initialization.
*
* @notapi
*/
void sd_lld_init(void) {
#if KINETIS_SERIAL_USE_UART0
/* Driver initialization.*/
sdObjectInit(&SD1, NULL, notify1);
SD1.uart = UART0;
#endif
#if KINETIS_SERIAL_USE_UART1
/* Driver initialization.*/
sdObjectInit(&SD2, NULL, notify2);
SD2.uart = UART1;
#endif
#if KINETIS_SERIAL_USE_UART2
/* Driver initialization.*/
sdObjectInit(&SD3, NULL, notify3);
SD3.uart = UART2;
#endif
}
/**
* @brief Low level serial driver configuration and (re)start.
*
* @param[in] sdp pointer to a @p SerialDriver object
* @param[in] config the architecture-dependent serial driver configuration.
* If this parameter is set to @p NULL then a default
* configuration is used.
*
* @notapi
*/
void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {
if (config == NULL)
config = &default_config;
if (sdp->state == SD_STOP) {
/* Enables the peripheral.*/
#if KINETIS_SERIAL_USE_UART0
if (sdp == &SD1) {
SIM->SCGC4 |= SIM_SCGC4_UART0;
SIM->SOPT2 =
(SIM->SOPT2 & ~SIM_SOPT2_UART0SRC_MASK) |
SIM_SOPT2_UART0SRC(KINETIS_UART0_CLOCK_SRC);
configure_uart(sdp->uart, config);
nvicEnableVector(UART0_IRQn, KINETIS_SERIAL_UART0_PRIORITY);
}
#endif /* KINETIS_SERIAL_USE_UART0 */
#if KINETIS_SERIAL_USE_UART1
if (sdp == &SD2) {
SIM->SCGC4 |= SIM_SCGC4_UART1;
configure_uart(sdp->uart, config);
nvicEnableVector(UART1_IRQn, KINETIS_SERIAL_UART1_PRIORITY);
}
#endif /* KINETIS_SERIAL_USE_UART1 */
#if KINETIS_SERIAL_USE_UART2
if (sdp == &SD3) {
SIM->SCGC4 |= SIM_SCGC4_UART2;
configure_uart(sdp->uart, config);
nvicEnableVector(UART2_IRQn, KINETIS_SERIAL_UART2_PRIORITY);
}
#endif /* KINETIS_SERIAL_USE_UART2 */
}
/* Configures the peripheral.*/
}
/**
* @brief Low level serial driver stop.
* @details De-initializes the USART, stops the associated clock, resets the
* interrupt vector.
*
* @param[in] sdp pointer to a @p SerialDriver object
*
* @notapi
*/
void sd_lld_stop(SerialDriver *sdp) {
if (sdp->state == SD_READY) {
/* TODO: Resets the peripheral.*/
#if KINETIS_SERIAL_USE_UART0
if (sdp == &SD1) {
nvicDisableVector(UART0_IRQn);
SIM->SCGC4 &= ~SIM_SCGC4_UART0;
}
#endif
#if KINETIS_SERIAL_USE_UART1
if (sdp == &SD2) {
nvicDisableVector(UART1_IRQn);
SIM->SCGC4 &= ~SIM_SCGC4_UART1;
}
#endif
#if KINETIS_SERIAL_USE_UART2
if (sdp == &SD3) {
nvicDisableVector(UART2_IRQn);
SIM->SCGC4 &= ~SIM_SCGC4_UART2;
}
#endif
}
}
#endif /* HAL_USE_SERIAL */
/** @} */

View File

@ -0,0 +1,163 @@
/*
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file KL2x/serial_lld.h
* @brief Kinetis KL2x Serial Driver subsystem low level driver header.
*
* @addtogroup SERIAL
* @{
*/
#ifndef _SERIAL_LLD_H_
#define _SERIAL_LLD_H_
#if HAL_USE_SERIAL || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name Configuration options
* @{
*/
/**
* @brief SD1 driver enable switch.
* @details If set to @p TRUE the support for SD1 is included.
*/
#if !defined(KINETIS_SERIAL_USE_UART0) || defined(__DOXYGEN__)
#define KINETIS_SERIAL_USE_UART0 FALSE
#endif
/**
* @brief SD2 driver enable switch.
* @details If set to @p TRUE the support for SD2 is included.
*/
#if !defined(KINETIS_SERIAL_USE_UART1) || defined(__DOXYGEN__)
#define KINETIS_SERIAL_USE_UART1 FALSE
#endif
/**
* @brief SD3 driver enable switch.
* @details If set to @p TRUE the support for SD3 is included.
*/
#if !defined(KINETIS_SERIAL_USE_UART2) || defined(__DOXYGEN__)
#define KINETIS_SERIAL_USE_UART2 FALSE
#endif
/**
* @brief UART0 interrupt priority level setting.
*/
#if !defined(KINETIS_SERIAL_UART0_PRIORITY) || defined(__DOXYGEN__)
#define KINETIS_SERIAL_UART0_PRIORITY 12
#endif
/**
* @brief UART1 interrupt priority level setting.
*/
#if !defined(KINETIS_SERIAL_UART1_PRIORITY) || defined(__DOXYGEN__)
#define KINETIS_SERIAL_UART1_PRIORITY 12
#endif
/**
* @brief UART2 interrupt priority level setting.
*/
#if !defined(KINETIS_SERIAL_UART2_PRIORITY) || defined(__DOXYGEN__)
#define KINETIS_SERIAL_UART2_PRIORITY 12
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Generic Serial Driver configuration structure.
* @details An instance of this structure must be passed to @p sdStart()
* in order to configure and start a serial driver operations.
* @note Implementations may extend this structure to contain more,
* architecture dependent, fields.
*/
typedef struct {
/**
* @brief Bit rate.
*/
uint32_t sc_speed;
/* End of the mandatory fields.*/
} SerialConfig;
/**
* @brief @p SerialDriver specific data.
*/
#define _serial_driver_data \
_base_asynchronous_channel_data \
/* Driver state.*/ \
sdstate_t state; \
/* Input queue.*/ \
InputQueue iqueue; \
/* Output queue.*/ \
OutputQueue oqueue; \
/* Input circular buffer.*/ \
uint8_t ib[SERIAL_BUFFERS_SIZE]; \
/* Output circular buffer.*/ \
uint8_t ob[SERIAL_BUFFERS_SIZE]; \
/* End of the mandatory fields.*/ \
/* Pointer to the UART registers block.*/ \
UARTLP_TypeDef *uart;
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if KINETIS_SERIAL_USE_UART0 && !defined(__DOXYGEN__)
extern SerialDriver SD1;
#endif
#if KINETIS_SERIAL_USE_UART1 && !defined(__DOXYGEN__)
extern SerialDriver SD2;
#endif
#if KINETIS_SERIAL_USE_UART2 && !defined(__DOXYGEN__)
extern SerialDriver SD3;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void sd_lld_init(void);
void sd_lld_start(SerialDriver *sdp, const SerialConfig *config);
void sd_lld_stop(SerialDriver *sdp);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_SERIAL */
#endif /* _SERIAL_LLD_H_ */
/** @} */

View File

@ -0,0 +1,98 @@
/*
ChibiOS/RT - Copyright (C) 2006-2014 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file KINETIS/KL2x/st_lld.c
* @brief ST Driver subsystem low level driver code.
*
* @addtogroup ST
* @{
*/
#include "hal.h"
#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if (OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC) || defined(__DOXYGEN__)
/**
* @brief System Timer vector.
* @details This interrupt is used for system tick in periodic mode.
*
* @isr
*/
OSAL_IRQ_HANDLER(SysTick_Handler) {
OSAL_IRQ_PROLOGUE();
osalSysLockFromISR();
osalOsTimerHandlerI();
osalSysUnlockFromISR();
OSAL_IRQ_EPILOGUE();
}
#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level ST driver initialization.
*
* @notapi
*/
void st_lld_init(void) {
#if OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC
/* Periodic systick mode, the Cortex-Mx internal systick timer is used
in this mode.*/
SysTick->LOAD = (KINETIS_SYSCLK_FREQUENCY / OSAL_ST_FREQUENCY) - 1;
SysTick->VAL = 0;
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_ENABLE_Msk |
SysTick_CTRL_TICKINT_Msk;
/* IRQ enabled.*/
nvicSetSystemHandlerPriority(HANDLER_SYSTICK, KINETIS_ST_IRQ_PRIORITY);
#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */
}
#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */
/** @} */

View File

@ -0,0 +1,156 @@
/*
ChibiOS/RT - Copyright (C) 2006-2014 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file KINETIS/st_lld.h
* @brief ST Driver subsystem low level driver header.
* @details This header is designed to be include-able without having to
* include other files from the HAL.
*
* @addtogroup ST
* @{
*/
#ifndef _ST_LLD_H_
#define _ST_LLD_H_
#include "mcuconf.h"
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name Configuration options
* @{
*/
/**
* @brief SysTick timer IRQ priority.
*/
#if !defined(KINETIS_ST_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define KINETIS_ST_IRQ_PRIORITY 8
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void st_lld_init(void);
#ifdef __cplusplus
}
#endif
/*===========================================================================*/
/* Driver inline functions. */
/*===========================================================================*/
/**
* @brief Returns the time counter value.
*
* @return The counter value.
*
* @notapi
*/
static inline systime_t st_lld_get_counter(void) {
return (systime_t)0;
}
/**
* @brief Starts the alarm.
* @note Makes sure that no spurious alarms are triggered after
* this call.
*
* @param[in] time the time to be set for the first alarm
*
* @notapi
*/
static inline void st_lld_start_alarm(systime_t time) {
(void)time;
}
/**
* @brief Stops the alarm interrupt.
*
* @notapi
*/
static inline void st_lld_stop_alarm(void) {
}
/**
* @brief Sets the alarm time.
*
* @param[in] time the time to be set for the next alarm
*
* @notapi
*/
static inline void st_lld_set_alarm(systime_t time) {
(void)time;
}
/**
* @brief Returns the current alarm time.
*
* @return The currently set alarm time.
*
* @notapi
*/
static inline systime_t st_lld_get_alarm(void) {
return (systime_t)0;
}
/**
* @brief Determines if the alarm is active.
*
* @return The alarm status.
* @retval false if the alarm is not active.
* @retval true is the alarm is active
*
* @notapi
*/
static inline bool st_lld_is_alarm_active(void) {
return false;
}
#endif /* _ST_LLD_H_ */
/** @} */