From b0a75810674d430ca104edda24800ff11073fdcb Mon Sep 17 00:00:00 2001 From: Michael Walker Date: Mon, 30 Apr 2018 16:34:26 -0700 Subject: Attempt at Teensy 3.6 support --- os/hal/boards/PJRC_TEENSY_3_6/board.c | 209 +++++++++ os/hal/boards/PJRC_TEENSY_3_6/board.h | 345 +++++++++++++++ os/hal/boards/PJRC_TEENSY_3_6/board.mk | 5 + os/hal/ports/KINETIS/LLD/hal_serial_lld.c | 12 + os/hal/ports/KINETIS/LLD/hal_serial_lld.h | 69 ++- os/hal/ports/KINETIS/MK66F18/hal_lld.c | 238 +++++++++++ os/hal/ports/KINETIS/MK66F18/hal_lld.h | 319 ++++++++++++++ os/hal/ports/KINETIS/MK66F18/hal_pwm_lld.c | 390 +++++++++++++++++ os/hal/ports/KINETIS/MK66F18/hal_pwm_lld.h | 270 ++++++++++++ os/hal/ports/KINETIS/MK66F18/hal_spi_lld.c | 539 ++++++++++++++++++++++++ os/hal/ports/KINETIS/MK66F18/hal_spi_lld.h | 261 ++++++++++++ os/hal/ports/KINETIS/MK66F18/kinetis_registry.h | 165 ++++++++ os/hal/ports/KINETIS/MK66F18/platform.dox | 365 ++++++++++++++++ os/hal/ports/KINETIS/MK66F18/platform.mk | 18 + 14 files changed, 3204 insertions(+), 1 deletion(-) create mode 100644 os/hal/boards/PJRC_TEENSY_3_6/board.c create mode 100644 os/hal/boards/PJRC_TEENSY_3_6/board.h create mode 100644 os/hal/boards/PJRC_TEENSY_3_6/board.mk create mode 100644 os/hal/ports/KINETIS/MK66F18/hal_lld.c create mode 100644 os/hal/ports/KINETIS/MK66F18/hal_lld.h create mode 100644 os/hal/ports/KINETIS/MK66F18/hal_pwm_lld.c create mode 100644 os/hal/ports/KINETIS/MK66F18/hal_pwm_lld.h create mode 100644 os/hal/ports/KINETIS/MK66F18/hal_spi_lld.c create mode 100644 os/hal/ports/KINETIS/MK66F18/hal_spi_lld.h create mode 100644 os/hal/ports/KINETIS/MK66F18/kinetis_registry.h create mode 100644 os/hal/ports/KINETIS/MK66F18/platform.dox create mode 100644 os/hal/ports/KINETIS/MK66F18/platform.mk (limited to 'os/hal') diff --git a/os/hal/boards/PJRC_TEENSY_3_6/board.c b/os/hal/boards/PJRC_TEENSY_3_6/board.c new file mode 100644 index 0000000..3e2f022 --- /dev/null +++ b/os/hal/boards/PJRC_TEENSY_3_6/board.c @@ -0,0 +1,209 @@ +/* + ChibiOS - Copyright (C) 2015 RedoX https://github.com/RedoXyde + + 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 "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 = { + { + /* + * PORTA setup. + * + * PTA0 - SWD + * PTA3 - SWD + * PTA5 - PIN25 + * PTA12 - PIN3 + * PTA13 - PIN4 + * PTA14 - PIN26 + * PTA15 - PIN27 + * PTA16 - PIN28 + * PTA17 - PIN39 + * PTA18 - Crystal + * PTA19 - Crystal + * PTA26 - PIN42 + * PTA28 - PIN40 + * PTA29 - PIN41 + * + */ + .port = IOPORT1, + .pads = { + PAL_MODE_ALTERNATIVE_7, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_ALTERNATIVE_7, PAL_MODE_UNCONNECTED, PAL_MODE_OUTPUT_PUSHPULL, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, + PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, + PAL_MODE_INPUT_ANALOG, PAL_MODE_INPUT_ANALOG, PAL_MODE_UNCONNECTED, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_OUTPUT_PUSHPULL, + PAL_MODE_UNCONNECTED, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + }, + }, + { + /* + * PORTB setup. + * + * PTB0 - PIN16 + * PTB1 - PIN17 + * PTB2 - PIN19 + * PTB3 - PIN18 + * PTB4 - PIN49 + * PTB5 - PIN50 + * PTB10 - PIN31 + * PTB11 - PIN32 + * PTB16 - PIN0 - UART0_RX + * PTB17 - PIN1 - UART0_TX + * PTB18 - PIN29 + * PTB19 - PIN30 + * PTB20 - PIN43 + * PTB21 - PIN46 + * PTB22 - PIN44 + * PTB23 - PIN45 + */ + .port = IOPORT2, + .pads = { + PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, + PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_UNCONNECTED, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_UNCONNECTED, PAL_MODE_ALTERNATIVE_3, PAL_MODE_ALTERNATIVE_3, + PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, + PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + }, + }, + { + /* + * PORTC setup. + * PTC0 - PIN15 + * PTC1 - PIN22 + * PTC2 - PIN23 + * PTC3 - PIN9 + * PTC4 - PIN10 + * PTC5 - PIN13 + * PTC6 - PIN11 + * PTC7 - PIN12 + * PTC8 - PIN35 + * PTC9 - PIN36 + * PTC10 - PIN37 + * PTC11 - PIN38 + * + */ + .port = IOPORT3, + .pads = { + PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, + PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, + PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, + PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + }, + }, + { + /* + * PORTD setup. + * + * PTD0 - PIN2 + * PTD1 - PIN14 + * PTD2 - PIN7 + * PTD3 - PIN8 + * PTD4 - PIN6 + * PTD5 - PIN20 + * PTD6 - PIN21 + * PTD7 - PIN5 + * PTD8 - PIN47 + * PTD9 - PIN48 + * PTD11 - PIN55 + * PTD12 - PIN53 + * PTD13 - PIN52 + * PTD14 - PIN51 + * PTD15 - PIN54 + */ + .port = IOPORT4, + .pads = { + PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, + PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, + PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, + PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_UNCONNECTED, PAL_MODE_OUTPUT_PUSHPULL, + PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, + PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + }, + }, + { + /* + * PORTE setup. + * + * PTE10 - PIN56 + * PTE11 - PIN57 + * PTE24 - PIN33 + * PTE25 - PIN34 + * PTE26 - PIN24 + */ + .port = IOPORT5, + .pads = { + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_UNCONNECTED, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, PAL_MODE_OUTPUT_PUSHPULL, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + PAL_MODE_UNCONNECTED, PAL_MODE_UNCONNECTED, + }, + }, + }, +}; +#endif + +/** + * @brief Early initialization code. + * @details This initialization must be performed just after stack setup + * and before any other initialization. + */ +void __early_init(void) { + + MK66F18_clock_init(); +} + +/** + * @brief Board-specific initialization code. + * @todo Add your board-specific code, if any. + */ +void boardInit(void) { +} diff --git a/os/hal/boards/PJRC_TEENSY_3_6/board.h b/os/hal/boards/PJRC_TEENSY_3_6/board.h new file mode 100644 index 0000000..9b0a8ad --- /dev/null +++ b/os/hal/boards/PJRC_TEENSY_3_6/board.h @@ -0,0 +1,345 @@ +/* + ChibiOS - Copyright (C) 2015 RedoX https://github.com/RedoXyde + + 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 the PJRC Teensy 3.6 board. + */ + +/* + * Board identifier. + */ +#define BOARD_PJRC_TEENSY_3_6 +#define BOARD_NAME "PJRC Teensy 3.6" + +/* External 16 MHz crystal */ +#define KINETIS_XTAL_FREQUENCY 16000000UL + +/* Use internal capacitors for the crystal */ +#define KINETIS_BOARD_OSCILLATOR_SETTING OSC_CR_SC8P|OSC_CR_SC2P + +/* + * MCU type + */ +#define MK66F18 + +/* + * IO pins assignments. + */ +#define PORTA_PIN0 0 +#define PORTA_PIN1 1 +#define PORTA_PIN2 2 +#define PORTA_PIN3 3 +#define PORTA_PIN4 4 +#define TEENSY_PIN25 5 +#define PORTA_PIN6 6 +#define PORTA_PIN7 7 +#define PORTA_PIN8 8 +#define PORTA_PIN9 9 +#define PORTA_PIN10 10 +#define PORTA_PIN11 11 +#define TEENSY_PIN3 12 +#define TEENSY_PIN4 13 +#define TEENSY_PIN26 14 +#define TEENSY_PIN27 15 +#define TEENSY_PIN28 16 +#define TEENSY_PIN39 17 +#define PORTA_PIN18 18 +#define PORTA_PIN19 19 +#define PORTA_PIN20 20 +#define PORTA_PIN21 21 +#define PORTA_PIN22 22 +#define PORTA_PIN23 23 +#define PORTA_PIN24 24 +#define PORTA_PIN25 25 +#define TEENSY_PIN42 26 +#define PORTA_PIN27 27 +#define TEENSY_PIN40 28 +#define TEENSY_PIN41 29 +#define PORTA_PIN30 30 +#define PORTA_PIN31 31 + +#define TEENSY_PIN40_IOPORT IOPORT1 +#define TEENSY_PIN41_IOPORT IOPORT1 +#define TEENSY_PIN42_IOPORT IOPORT1 +#define TEENSY_PIN3_IOPORT IOPORT1 +#define TEENSY_PIN4_IOPORT IOPORT1 +#define TEENSY_PIN25_IOPORT IOPORT1 +#define TEENSY_PIN26_IOPORT IOPORT1 +#define TEENSY_PIN27_IOPORT IOPORT1 +#define TEENSY_PIN28_IOPORT IOPORT1 +#define TEENSY_PIN39_IOPORT IOPORT1 + +#define TEENSY_PIN16 0 +#define TEENSY_PIN17 1 +#define TEENSY_PIN19 2 +#define TEENSY_PIN18 3 +#define TEENSY_PIN49 4 +#define TEENSY_PIN50 5 +#define PORTB_PIN6 6 +#define PORTB_PIN7 7 +#define PORTB_PIN8 8 +#define PORTB_PIN9 9 +#define TEENSY_PIN31 10 +#define TEENSY_PIN32 11 +#define PORTB_PIN12 12 +#define PORTB_PIN13 13 +#define PORTB_PIN14 14 +#define PORTB_PIN15 15 +#define TEENSY_PIN0 16 +#define TEENSY_PIN1 17 +#define TEENSY_PIN29 18 +#define TEENSY_PIN30 19 +#define TEENSY_PIN43 20 +#define TEENSY_PIN46 21 +#define TEENSY_PIN44 22 +#define TEENSY_PIN45 23 +#define PORTB_PIN24 24 +#define PORTB_PIN25 25 +#define PORTB_PIN26 26 +#define PORTB_PIN27 27 +#define PORTB_PIN28 28 +#define PORTB_PIN29 29 +#define PORTB_PIN30 30 +#define PORTB_PIN31 31 + +#define TEENSY_PIN49_IOPORT IOPORT2 +#define TEENSY_PIN50_IOPORT IOPORT2 +#define TEENSY_PIN43_IOPORT IOPORT2 +#define TEENSY_PIN44_IOPORT IOPORT2 +#define TEENSY_PIN45_IOPORT IOPORT2 +#define TEENSY_PIN46_IOPORT IOPORT2 +#define TEENSY_PIN0_IOPORT IOPORT2 +#define TEENSY_PIN1_IOPORT IOPORT2 +#define TEENSY_PIN29_IOPORT IOPORT2 +#define TEENSY_PIN30_IOPORT IOPORT2 +#define TEENSY_PIN31_IOPORT IOPORT2 +#define TEENSY_PIN32_IOPORT IOPORT2 +#define TEENSY_PIN16_IOPORT IOPORT2 +#define TEENSY_PIN17_IOPORT IOPORT2 +#define TEENSY_PIN19_IOPORT IOPORT2 +#define TEENSY_PIN18_IOPORT IOPORT2 + +#define TEENSY_PIN15 0 +#define TEENSY_PIN22 1 +#define TEENSY_PIN23 2 +#define TEENSY_PIN9 3 +#define TEENSY_PIN10 4 +#define TEENSY_PIN13 5 +#define TEENSY_PIN11 6 +#define TEENSY_PIN12 7 +#define TEENSY_PIN35 8 +#define TEENSY_PIN36 9 +#define TEENSY_PIN37 10 +#define TEENSY_PIN38 11 +#define PORTC_PIN12 12 +#define PORTC_PIN13 13 +#define PORTC_PIN14 14 +#define PORTC_PIN15 15 +#define PORTC_PIN16 16 +#define PORTC_PIN17 17 +#define PORTC_PIN18 18 +#define PORTC_PIN19 19 +#define PORTC_PIN20 20 +#define PORTC_PIN21 21 +#define PORTC_PIN22 22 +#define PORTC_PIN23 23 +#define PORTC_PIN24 24 +#define PORTC_PIN25 25 +#define PORTC_PIN26 26 +#define PORTC_PIN27 27 +#define PORTC_PIN28 28 +#define PORTC_PIN29 29 +#define PORTC_PIN30 30 +#define PORTC_PIN31 31 + +#define TEENSY_PIN9_IOPORT IOPORT3 +#define TEENSY_PIN10_IOPORT IOPORT3 +#define TEENSY_PIN11_IOPORT IOPORT3 +#define TEENSY_PIN12_IOPORT IOPORT3 +#define TEENSY_PIN35_IOPORT IOPORT3 +#define TEENSY_PIN36_IOPORT IOPORT3 +#define TEENSY_PIN37_IOPORT IOPORT3 +#define TEENSY_PIN38_IOPORT IOPORT3 +#define TEENSY_PIN13_IOPORT IOPORT3 +#define TEENSY_PIN15_IOPORT IOPORT3 +#define TEENSY_PIN22_IOPORT IOPORT3 +#define TEENSY_PIN23_IOPORT IOPORT3 + +#define TEENSY_PIN2 0 +#define TEENSY_PIN14 1 +#define TEENSY_PIN7 2 +#define TEENSY_PIN8 3 +#define TEENSY_PIN6 4 +#define TEENSY_PIN20 5 +#define TEENSY_PIN21 6 +#define TEENSY_PIN5 7 +#define TEENSY_PIN47 8 +#define TEENSY_PIN48 9 +#define PORTD_PIN10 10 +#define TEENSY_PIN55 11 +#define TEENSY_PIN53 12 +#define TEENSY_PIN52 13 +#define TEENSY_PIN51 14 +#define TEENSY_PIN54 15 +#define PORTD_PIN16 16 +#define PORTD_PIN17 17 +#define PORTD_PIN18 18 +#define PORTD_PIN19 19 +#define PORTD_PIN20 20 +#define PORTD_PIN21 21 +#define PORTD_PIN22 22 +#define PORTD_PIN23 23 +#define PORTD_PIN24 24 +#define PORTD_PIN25 25 +#define PORTD_PIN26 26 +#define PORTD_PIN27 27 +#define PORTD_PIN28 28 +#define PORTD_PIN29 29 +#define PORTD_PIN30 30 +#define PORTD_PIN31 31 + +#define TEENSY_PIN51_IOPORT IOPORT4 +#define TEENSY_PIN52_IOPORT IOPORT4 +#define TEENSY_PIN53_IOPORT IOPORT4 +#define TEENSY_PIN54_IOPORT IOPORT4 +#define TEENSY_PIN55_IOPORT IOPORT4 +#define TEENSY_PIN47_IOPORT IOPORT4 +#define TEENSY_PIN48_IOPORT IOPORT4 +#define TEENSY_PIN2_IOPORT IOPORT4 +#define TEENSY_PIN5_IOPORT IOPORT4 +#define TEENSY_PIN6_IOPORT IOPORT4 +#define TEENSY_PIN7_IOPORT IOPORT4 +#define TEENSY_PIN8_IOPORT IOPORT4 +#define TEENSY_PIN14_IOPORT IOPORT4 +#define TEENSY_PIN20_IOPORT IOPORT4 +#define TEENSY_PIN21_IOPORT IOPORT4 + +#define PORTE_PIN0 0 +#define PORTE_PIN1 1 +#define PORTE_PIN2 2 +#define PORTE_PIN3 3 +#define PORTE_PIN4 4 +#define PORTE_PIN5 5 +#define PORTE_PIN6 6 +#define PORTE_PIN7 7 +#define PORTE_PIN8 8 +#define PORTE_PIN9 9 +#define TEENSY_PIN56 10 +#define TEENSY_PIN57 11 +#define PORTE_PIN12 12 +#define PORTE_PIN13 13 +#define PORTE_PIN14 14 +#define PORTE_PIN15 15 +#define PORTE_PIN16 16 +#define PORTE_PIN17 17 +#define PORTE_PIN18 18 +#define PORTE_PIN19 19 +#define PORTE_PIN20 20 +#define PORTE_PIN21 21 +#define PORTE_PIN22 22 +#define PORTE_PIN23 23 +#define TEENSY_PIN33 24 +#define TEENSY_PIN34 25 +#define TEENSY_PIN24 26 +#define PORTE_PIN27 27 +#define PORTE_PIN28 28 +#define PORTE_PIN29 29 +#define PORTE_PIN30 30 +#define PORTE_PIN31 31 + +#define TEENSY_PIN56_IOPORT IOPORT5 +#define TEENSY_PIN57_IOPORT IOPORT5 +#define TEENSY_PIN24_IOPORT IOPORT5 +#define TEENSY_PIN33_IOPORT IOPORT5 +#define TEENSY_PIN34_IOPORT IOPORT5 + + +#define LINE_PIN0 PAL_LINE(TEENSY_PIN0_IOPORT, TEENSY_PIN0) +#define LINE_PIN1 PAL_LINE(TEENSY_PIN1_IOPORT, TEENSY_PIN1) +#define LINE_PIN2 PAL_LINE(TEENSY_PIN2_IOPORT, TEENSY_PIN2) +#define LINE_PIN3 PAL_LINE(TEENSY_PIN3_IOPORT, TEENSY_PIN3) +#define LINE_PIN4 PAL_LINE(TEENSY_PIN4_IOPORT, TEENSY_PIN4) +#define LINE_PIN5 PAL_LINE(TEENSY_PIN5_IOPORT, TEENSY_PIN5) +#define LINE_PIN6 PAL_LINE(TEENSY_PIN6_IOPORT, TEENSY_PIN6) +#define LINE_PIN7 PAL_LINE(TEENSY_PIN7_IOPORT, TEENSY_PIN7) +#define LINE_PIN8 PAL_LINE(TEENSY_PIN8_IOPORT, TEENSY_PIN8) +#define LINE_PIN9 PAL_LINE(TEENSY_PIN9_IOPORT, TEENSY_PIN9) +#define LINE_PIN10 PAL_LINE(TEENSY_PIN10_IOPORT, TEENSY_PIN10) +#define LINE_PIN11 PAL_LINE(TEENSY_PIN11_IOPORT, TEENSY_PIN11) +#define LINE_PIN12 PAL_LINE(TEENSY_PIN12_IOPORT, TEENSY_PIN12) +#define LINE_PIN13 PAL_LINE(TEENSY_PIN13_IOPORT, TEENSY_PIN13) +#define LINE_PIN14 PAL_LINE(TEENSY_PIN14_IOPORT, TEENSY_PIN14) +#define LINE_PIN15 PAL_LINE(TEENSY_PIN15_IOPORT, TEENSY_PIN15) +#define LINE_PIN16 PAL_LINE(TEENSY_PIN16_IOPORT, TEENSY_PIN16) +#define LINE_PIN17 PAL_LINE(TEENSY_PIN17_IOPORT, TEENSY_PIN17) +#define LINE_PIN18 PAL_LINE(TEENSY_PIN18_IOPORT, TEENSY_PIN18) +#define LINE_PIN19 PAL_LINE(TEENSY_PIN19_IOPORT, TEENSY_PIN19) +#define LINE_PIN20 PAL_LINE(TEENSY_PIN20_IOPORT, TEENSY_PIN20) +#define LINE_PIN21 PAL_LINE(TEENSY_PIN21_IOPORT, TEENSY_PIN21) +#define LINE_PIN22 PAL_LINE(TEENSY_PIN22_IOPORT, TEENSY_PIN22) +#define LINE_PIN23 PAL_LINE(TEENSY_PIN23_IOPORT, TEENSY_PIN23) +#define LINE_PIN24 PAL_LINE(TEENSY_PIN24_IOPORT, TEENSY_PIN24) +#define LINE_PIN25 PAL_LINE(TEENSY_PIN25_IOPORT, TEENSY_PIN25) +#define LINE_PIN25 PAL_LINE(TEENSY_PIN25_IOPORT, TEENSY_PIN25) +#define LINE_PIN26 PAL_LINE(TEENSY_PIN26_IOPORT, TEENSY_PIN26) +#define LINE_PIN27 PAL_LINE(TEENSY_PIN27_IOPORT, TEENSY_PIN27) +#define LINE_PIN28 PAL_LINE(TEENSY_PIN28_IOPORT, TEENSY_PIN28) +#define LINE_PIN29 PAL_LINE(TEENSY_PIN29_IOPORT, TEENSY_PIN29) +#define LINE_PIN30 PAL_LINE(TEENSY_PIN30_IOPORT, TEENSY_PIN30) +#define LINE_PIN31 PAL_LINE(TEENSY_PIN31_IOPORT, TEENSY_PIN31) +#define LINE_PIN32 PAL_LINE(TEENSY_PIN32_IOPORT, TEENSY_PIN32) +#define LINE_PIN33 PAL_LINE(TEENSY_PIN33_IOPORT, TEENSY_PIN33) +#define LINE_PIN34 PAL_LINE(TEENSY_PIN34_IOPORT, TEENSY_PIN34) +#define LINE_PIN35 PAL_LINE(TEENSY_PIN35_IOPORT, TEENSY_PIN35) +#define LINE_PIN36 PAL_LINE(TEENSY_PIN36_IOPORT, TEENSY_PIN36) +#define LINE_PIN37 PAL_LINE(TEENSY_PIN37_IOPORT, TEENSY_PIN37) +#define LINE_PIN38 PAL_LINE(TEENSY_PIN38_IOPORT, TEENSY_PIN38) +#define LINE_PIN39 PAL_LINE(TEENSY_PIN39_IOPORT, TEENSY_PIN39) +#define LINE_PIN40 PAL_LINE(TEENSY_PIN40_IOPORT, TEENSY_PIN40) +#define LINE_PIN41 PAL_LINE(TEENSY_PIN41_IOPORT, TEENSY_PIN41) +#define LINE_PIN42 PAL_LINE(TEENSY_PIN42_IOPORT, TEENSY_PIN42) +#define LINE_PIN43 PAL_LINE(TEENSY_PIN43_IOPORT, TEENSY_PIN43) +#define LINE_PIN44 PAL_LINE(TEENSY_PIN44_IOPORT, TEENSY_PIN44) +#define LINE_PIN45 PAL_LINE(TEENSY_PIN45_IOPORT, TEENSY_PIN45) +#define LINE_PIN46 PAL_LINE(TEENSY_PIN46_IOPORT, TEENSY_PIN46) +#define LINE_PIN47 PAL_LINE(TEENSY_PIN47_IOPORT, TEENSY_PIN47) +#define LINE_PIN48 PAL_LINE(TEENSY_PIN48_IOPORT, TEENSY_PIN48) +#define LINE_PIN49 PAL_LINE(TEENSY_PIN49_IOPORT, TEENSY_PIN49) +#define LINE_PIN50 PAL_LINE(TEENSY_PIN50_IOPORT, TEENSY_PIN50) +#define LINE_PIN51 PAL_LINE(TEENSY_PIN51_IOPORT, TEENSY_PIN50) +#define LINE_PIN52 PAL_LINE(TEENSY_PIN52_IOPORT, TEENSY_PIN52) +#define LINE_PIN53 PAL_LINE(TEENSY_PIN53_IOPORT, TEENSY_PIN53) +#define LINE_PIN54 PAL_LINE(TEENSY_PIN54_IOPORT, TEENSY_PIN54) +#define LINE_PIN55 PAL_LINE(TEENSY_PIN55_IOPORT, TEENSY_PIN55) +#define LINE_PIN56 PAL_LINE(TEENSY_PIN56_IOPORT, TEENSY_PIN56) +#define LINE_PIN57 PAL_LINE(TEENSY_PIN57_IOPORT, TEENSY_PIN57) + +#define LINE_LED LINE_PIN13 + +#if !defined(_FROM_ASM_) +#ifdef __cplusplus +extern "C" { +#endif + void boardInit(void); +#ifdef __cplusplus +} +#endif +#endif /* _FROM_ASM_ */ + +#endif /* _BOARD_H_ */ diff --git a/os/hal/boards/PJRC_TEENSY_3_6/board.mk b/os/hal/boards/PJRC_TEENSY_3_6/board.mk new file mode 100644 index 0000000..6e2695c --- /dev/null +++ b/os/hal/boards/PJRC_TEENSY_3_6/board.mk @@ -0,0 +1,5 @@ +# List of all the board related files. +BOARDSRC = ${CHIBIOS_CONTRIB}/os/hal/boards/PJRC_TEENSY_3_6/board.c + +# Required include directories +BOARDINC = ${CHIBIOS_CONTRIB}/os/hal/boards/PJRC_TEENSY_3_6 diff --git a/os/hal/ports/KINETIS/LLD/hal_serial_lld.c b/os/hal/ports/KINETIS/LLD/hal_serial_lld.c index c80cf22..c75d41a 100644 --- a/os/hal/ports/KINETIS/LLD/hal_serial_lld.c +++ b/os/hal/ports/KINETIS/LLD/hal_serial_lld.c @@ -50,6 +50,18 @@ SerialDriver SD2; SerialDriver SD3; #endif +#if KINETIS_SERIAL_USE_UART3 || defined(__DOXYGEN__) +SerialDriver SD4; +#endif + +#if KINETIS_SERIAL_USE_UART4 || defined(__DOXYGEN__) +SerialDriver SD5; +#endif + +#if KINETIS_SERIAL_USE_UART5 || defined(__DOXYGEN__) +SerialDriver SD6; +#endif + /*===========================================================================*/ /* Driver local variables and types. */ /*===========================================================================*/ diff --git a/os/hal/ports/KINETIS/LLD/hal_serial_lld.h b/os/hal/ports/KINETIS/LLD/hal_serial_lld.h index f11c063..3cb6d2b 100644 --- a/os/hal/ports/KINETIS/LLD/hal_serial_lld.h +++ b/os/hal/ports/KINETIS/LLD/hal_serial_lld.h @@ -60,6 +60,27 @@ #if !defined(KINETIS_SERIAL_USE_UART2) || defined(__DOXYGEN__) #define KINETIS_SERIAL_USE_UART2 FALSE #endif +/** + * @brief SD4 driver enable switch. + * @details If set to @p TRUE the support for SD4 is included. + */ +#if !defined(KINETIS_SERIAL_USE_UART3) || defined(__DOXYGEN__) +#define KINETIS_SERIAL_USE_UART3 FALSE +#endif +/** + * @brief SD5 driver enable switch. + * @details If set to @p TRUE the support for SD5 is included. + */ +#if !defined(KINETIS_SERIAL_USE_UART4) || defined(__DOXYGEN__) +#define KINETIS_SERIAL_USE_UART4 FALSE +#endif +/** + * @brief SD6 driver enable switch. + * @details If set to @p TRUE the support for SD6 is included. + */ +#if !defined(KINETIS_SERIAL_USE_UART5) || defined(__DOXYGEN__) +#define KINETIS_SERIAL_USE_UART5 FALSE +#endif /** * @brief UART0 interrupt priority level setting. @@ -82,6 +103,27 @@ #define KINETIS_SERIAL_UART2_PRIORITY 12 #endif +/** + * @brief UART3 interrupt priority level setting. + */ +#if !defined(KINETIS_SERIAL_UART3_PRIORITY) || defined(__DOXYGEN__) +#define KINETIS_SERIAL_UART3_PRIORITY 12 +#endif + +/** + * @brief UART4 interrupt priority level setting. + */ +#if !defined(KINETIS_SERIAL_UART4_PRIORITY) || defined(__DOXYGEN__) +#define KINETIS_SERIAL_UART4_PRIORITY 12 +#endif + +/** + * @brief UART5 interrupt priority level setting. + */ +#if !defined(KINETIS_SERIAL_UART5_PRIORITY) || defined(__DOXYGEN__) +#define KINETIS_SERIAL_UART5_PRIORITY 12 +#endif + /** * @brief UART0 clock source. */ @@ -115,8 +157,21 @@ #error "UART2 not present in the selected device" #endif +#if KINETIS_SERIAL_USE_UART3 && !KINETIS_HAS_SERIAL3 +#error "UART3 not present in the selected device" +#endif + +#if KINETIS_SERIAL_USE_UART4 && !KINETIS_HAS_SERIAL4 +#error "UART4 not present in the selected device" +#endif + +#if KINETIS_SERIAL_USE_UART5 && !KINETIS_HAS_SERIAL5 +#error "UART5 not present in the selected device" +#endif + #if !(KINETIS_SERIAL_USE_UART0 || KINETIS_SERIAL_USE_UART1 || \ - KINETIS_SERIAL_USE_UART2) + KINETIS_SERIAL_USE_UART2 || KINETIS_SERIAL_USE_UART3 || \ + KINETIS_SERIAL_USE_UART4 || KINETIS_SERIAL_USE_UART5) #error "Serial driver activated but no UART peripheral assigned" #endif @@ -203,6 +258,18 @@ extern SerialDriver SD2; extern SerialDriver SD3; #endif +#if KINETIS_SERIAL_USE_UART3 && !defined(__DOXYGEN__) +extern SerialDriver SD4; +#endif + +#if KINETIS_SERIAL_USE_UART4 && !defined(__DOXYGEN__) +extern SerialDriver SD5; +#endif + +#if KINETIS_SERIAL_USE_UART5 && !defined(__DOXYGEN__) +extern SerialDriver SD6; +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/os/hal/ports/KINETIS/MK66F18/hal_lld.c b/os/hal/ports/KINETIS/MK66F18/hal_lld.c new file mode 100644 index 0000000..857f384 --- /dev/null +++ b/os/hal/ports/KINETIS/MK66F18/hal_lld.c @@ -0,0 +1,238 @@ +/* + ChibiOS - Copyright (C) 2014-2015 Fabio Utzig + + 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 templates/hal_lld.c + * @brief HAL Driver subsystem low level driver source template. + * + * @addtogroup HAL + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +#ifdef __CC_ARM +__attribute__ ((section(".ARM.__at_0x400"))) +#else +__attribute__ ((used,section(".cfmconfig"))) +#endif +const uint8_t _cfm[0x10] = { + 0xFF, /* NV_BACKKEY3: KEY=0xFF */ + 0xFF, /* NV_BACKKEY2: KEY=0xFF */ + 0xFF, /* NV_BACKKEY1: KEY=0xFF */ + 0xFF, /* NV_BACKKEY0: KEY=0xFF */ + 0xFF, /* NV_BACKKEY7: KEY=0xFF */ + 0xFF, /* NV_BACKKEY6: KEY=0xFF */ + 0xFF, /* NV_BACKKEY5: KEY=0xFF */ + 0xFF, /* NV_BACKKEY4: KEY=0xFF */ + 0xFF, /* NV_FPROT3: PROT=0xFF */ + 0xFF, /* NV_FPROT2: PROT=0xFF */ + 0xFF, /* NV_FPROT1: PROT=0xFF */ + 0xFF, /* NV_FPROT0: PROT=0xFF */ + 0x7E, /* NV_FSEC: KEYEN=1,MEEN=3,FSLACC=3,SEC=2 */ + 0xFF, /* NV_FOPT: ??=1,??=1,FAST_INIT=1,LPBOOT1=1,RESET_PIN_CFG=1, + NMI_DIS=1,EZPORT_DIS=1,LPBOOT0=1 */ + 0xFF, + 0xFF +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level HAL driver initialization. + * @todo Use a macro to define the system clock frequency. + * + * @notapi + */ +void hal_lld_init(void) { + +} + +/** + * @brief MK66F18 clock 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. + * @todo This function needs to be more generic. + * + * @special + */ +void MK66F18_clock_init(void) { +#if !KINETIS_NO_INIT + + /* Disable the watchdog */ + WDOG->UNLOCK = 0xC520; + WDOG->UNLOCK = 0xD928; + WDOG->STCTRLH &= ~WDOG_STCTRLH_WDOGEN; + + SIM->SCGC5 |= SIM_SCGC5_PORTA | + SIM_SCGC5_PORTB | + SIM_SCGC5_PORTC | + SIM_SCGC5_PORTD | + SIM_SCGC5_PORTE; + +#if KINETIS_MCG_MODE == KINETIS_MCG_MODE_FEI + /* This is the default mode at reset. */ + + /* Configure FEI mode */ + MCG->C4 = MCG_C4_DRST_DRS(KINETIS_MCG_FLL_DRS) | + (KINETIS_MCG_FLL_DMX32 ? MCG_C4_DMX32 : 0); + + /* Set clock dividers */ + SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(KINETIS_CLKDIV1_OUTDIV1-1) | + SIM_CLKDIV1_OUTDIV2(KINETIS_CLKDIV1_OUTDIV2-1) | +#if defined(MK66F18) + SIM_CLKDIV1_OUTDIV3(KINETIS_CLKDIV1_OUTDIV3-1) | +#endif + SIM_CLKDIV1_OUTDIV4(KINETIS_CLKDIV1_OUTDIV4-1); + SIM->CLKDIV2 = SIM_CLKDIV2_USBDIV(0); /* not strictly necessary since usb_lld will set this */ + +#elif KINETIS_MCG_MODE == KINETIS_MCG_MODE_PEE + + uint32_t ratio, frdiv; + uint32_t ratios[] = { 32, 64, 128, 256, 512, 1024, 1280, 1536 }; + uint8_t ratio_quantity = sizeof(ratios) / sizeof(ratios[0]); + uint8_t i; + + /* EXTAL0 and XTAL0 */ + PORTA->PCR[18] = 0; + PORTA->PCR[19] = 0; + + /* + * Start in FEI mode + */ + + /* Internal capacitors for crystal */ +#if defined(KINETIS_BOARD_OSCILLATOR_SETTING) + OSC0->CR = KINETIS_BOARD_OSCILLATOR_SETTING; +#else /* KINETIS_BOARD_OSCILLATOR_SETTING */ + /* Disable the internal capacitors */ + OSC0->CR = 0; +#endif /* KINETIS_BOARD_OSCILLATOR_SETTING */ + + /* TODO: need to add more flexible calculation, specially regarding + * divisors which may not be available depending on the XTAL + * frequency, which would required other registers to be modified. + */ + /* Enable OSC, low power mode */ + if (KINETIS_XTAL_FREQUENCY > 8000000UL) + MCG->C2 = MCG_C2_LOCRE0 | MCG_C2_EREFS0 | MCG_C2_RANGE0(2); + else + MCG->C2 = MCG_C2_LOCRE0 | MCG_C2_EREFS0 | MCG_C2_RANGE0(1); + + frdiv = 7; + ratio = KINETIS_XTAL_FREQUENCY / 31250UL; + for (i = 0; i < ratio_quantity; ++i) { + if (ratio == ratios[i]) { + frdiv = i; + break; + } + } + + /* Switch to crystal as clock source, FLL input of 31.25 KHz */ + MCG->C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(frdiv); + + /* Wait for crystal oscillator to begin */ + while (!(MCG->S & MCG_S_OSCINIT0)); + + /* Wait for the FLL to use the oscillator */ + while (MCG->S & MCG_S_IREFST); + + /* Wait for the MCGOUTCLK to use the oscillator */ + while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST(2)); + + /* + * Now in FBE mode + */ + #define KINETIS_PLLIN_FREQUENCY 2000000UL + /* + * Config PLL input for 2 MHz + * TODO: Make sure KINETIS_XTAL_FREQUENCY >= 2Mhz && <= 50Mhz + */ + MCG->C5 = MCG_C5_PRDIV0((KINETIS_XTAL_FREQUENCY/KINETIS_PLLIN_FREQUENCY) - 1); + + /* + * Config PLL output to match KINETIS_SYSCLK_FREQUENCY + * TODO: make sure KINETIS_SYSCLK_FREQUENCY is a match + */ + for(i = 24; i < 56; i++) + { + if(i == (KINETIS_PLLCLK_FREQUENCY/KINETIS_PLLIN_FREQUENCY)) + { + /* Config PLL to match KINETIS_PLLCLK_FREQUENCY */ + MCG->C6 = MCG_C6_PLLS | MCG_C6_VDIV0(i-24); + break; + } + } + + if(i>=56) /* Config PLL for 96 MHz output as default setting */ + MCG->C6 = MCG_C6_PLLS | MCG_C6_VDIV0(0); + + /* Wait for PLL to start using crystal as its input, and to lock */ + while ((MCG->S & (MCG_S_PLLST|MCG_S_LOCK0))!=(MCG_S_PLLST|MCG_S_LOCK0)); + + /* + * Now in PBE mode + */ + /* Set the PLL dividers for the different clocks */ + SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(KINETIS_CLKDIV1_OUTDIV1-1) | + SIM_CLKDIV1_OUTDIV2(KINETIS_CLKDIV1_OUTDIV2-1) | + SIM_CLKDIV1_OUTDIV4(KINETIS_CLKDIV1_OUTDIV4-1); + SIM->CLKDIV2 = SIM_CLKDIV2_USBDIV(0); + + /* Configure peripherals to use MCGPLLCLK */ + SIM->SOPT2 = SIM_SOPT2_PLLFLLSEL; + + /* Switch to PLL as clock source */ + MCG->C1 = MCG_C1_CLKS(0); + + /* Wait for PLL clock to be used */ + while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST_PLL); + + /* + * Now in PEE mode + */ +#else /* KINETIS_MCG_MODE == KINETIS_MCG_MODE_PEE */ +#error Unimplemented KINETIS_MCG_MODE +#endif /* KINETIS_MCG_MODE == ... */ + +#endif /* !KINETIS_NO_INIT */ +} + +/** @} */ diff --git a/os/hal/ports/KINETIS/MK66F18/hal_lld.h b/os/hal/ports/KINETIS/MK66F18/hal_lld.h new file mode 100644 index 0000000..832955e --- /dev/null +++ b/os/hal/ports/KINETIS/MK66F18/hal_lld.h @@ -0,0 +1,319 @@ +/* + ChibiOS - Copyright (C) 2014-2015 Fabio Utzig + + 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 MK66F18/hal_lld.h + * @brief Kinetis MK66F18 HAL subsystem low level driver header. + * + * @addtogroup HAL + * @{ + */ + +#ifndef HAL_LLD_H_ +#define HAL_LLD_H_ + +#include "kinetis_registry.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" +/** @} */ + +/** + * @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 MCU PLL clock frequency. + */ +#if !defined(KINETIS_PLLCLK_FREQUENCY) || defined(__DOXYGEN__) +#define KINETIS_PLLCLK_FREQUENCY 96000000UL +#endif + +/** + * @brief Clock divider for core/system 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_CLKDIV1_OUTDIV1) || defined(__DOXYGEN__) + #if defined(KINETIS_SYSCLK_FREQUENCY) && KINETIS_SYSCLK_FREQUENCY > 0 + #define KINETIS_CLKDIV1_OUTDIV1 (KINETIS_PLLCLK_FREQUENCY/KINETIS_SYSCLK_FREQUENCY) + #else + #define KINETIS_CLKDIV1_OUTDIV1 2 + #endif +#endif + +/** + * @brief Clock divider for bus clock (OUTDIV2). + * @note The allowed range is 1..16 + * @note The default value is calculated for a 48 MHz bus clock + * from a 96 MHz PLL output. + */ +#if !defined(KINETIS_CLKDIV1_OUTDIV2) || defined(__DOXYGEN__) + #if defined(KINETIS_BUSCLK_FREQUENCY) && KINETIS_BUSCLK_FREQUENCY > 0 + #define KINETIS_CLKDIV1_OUTDIV2 (KINETIS_PLLCLK_FREQUENCY/KINETIS_BUSCLK_FREQUENCY) + #elif defined(KINETIS_SYSCLK_FREQUENCY) && KINETIS_SYSCLK_FREQUENCY > 0 + #define KINETIS_CLKDIV1_OUTDIV2 KINETIS_CLKDIV1_OUTDIV1 + #else + #define KINETIS_CLKDIV1_OUTDIV2 2 + #endif +#endif + +/** + * @brief Clock divider for FlexBus clock (OUTDIV3). + * @note The allowed range is 1..16 + * @note The default value is calculated for a 48 MHz clock + * from a 96 MHz PLL output. + */ +#if !defined(KINETIS_CLKDIV1_OUTDIV3) || defined(__DOXYGEN__) + #if defined(KINETIS_FLEXBUSCLK_FREQUENCY) && KINETIS_FLEXBUSCLK_FREQUENCY > 0 + #define KINETIS_CLKDIV1_OUTDIV3 (KINETIS_PLLCLK_FREQUENCY/KINETIS_FLEXBUSCLK_FREQUENCY) + #endif +#endif + +/** + * @brief Clock divider for flash clock (OUTDIV4). + * @note The allowed range is 1..16 + * @note The default value is calculated for a 24 MHz flash clock + * from a 96 MHz PLL output + */ +#if !defined(KINETIS_CLKDIV1_OUTDIV4) || defined(__DOXYGEN__) + #if defined(KINETIS_FLASHCLK_FREQUENCY) && KINETIS_FLASHCLK_FREQUENCY > 0 + #define KINETIS_CLKDIV1_OUTDIV4 (KINETIS_PLLCLK_FREQUENCY/KINETIS_FLASHCLK_FREQUENCY) + #elif defined(KINETIS_SYSCLK_FREQUENCY) && KINETIS_SYSCLK_FREQUENCY > 0 + #define KINETIS_CLKDIV1_OUTDIV4 (KINETIS_CLKDIV1_OUTDIV1*2) + #else + #define KINETIS_CLKDIV1_OUTDIV4 4 + #endif +#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 (KINETIS_PLLCLK_FREQUENCY / KINETIS_CLKDIV1_OUTDIV1) +#endif + +/** + * @brief MCU bus clock frequency. + */ +#if !defined(KINETIS_BUSCLK_FREQUENCY) || defined(__DOXYGEN__) +#define KINETIS_BUSCLK_FREQUENCY (KINETIS_PLLCLK_FREQUENCY / KINETIS_CLKDIV1_OUTDIV2) +#endif + +/** + * @brief MCU flash clock frequency. + */ +#if !defined(KINETIS_FLASHCLK_FREQUENCY) || defined(__DOXYGEN__) +#define KINETIS_FLASHCLK_FREQUENCY (KINETIS_PLLCLK_FREQUENCY / KINETIS_CLKDIV1_OUTDIV4) +#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 KINETIS_BUSCLK_FREQUENCY > KINETIS_SYSCLK_FREQUENCY + #error KINETIS_BUSCLK_FREQUENCY must be an integer divide of\ + KINETIS_SYSCLK_FREQUENCY +#endif + +#if !defined(KINETIS_FLASHCLK_FREQUENCY) + #error KINETIS_FLASHCLK_FREQUENCY must be defined +#endif + +#if KINETIS_FLASHCLK_FREQUENCY <= 0 || KINETIS_FLASHCLK_FREQUENCY > KINETIS_FLASHCLK_MAX + #error KINETIS_FLASHCLK_FREQUENCY out of range +#endif + +#if KINETIS_FLASHCLK_FREQUENCY > KINETIS_SYSCLK_FREQUENCY + #error KINETIS_FLASHCLK_FREQUENCY must be an integer divide of\ + KINETIS_SYSCLK_FREQUENCY +#endif + +#if !(defined(KINETIS_CLKDIV1_OUTDIV1) && \ + KINETIS_CLKDIV1_OUTDIV1 >= 1 && KINETIS_CLKDIV1_OUTDIV1 <= 16) + #error KINETIS_CLKDIV1_OUTDIV1 must be 1 through 16 +#endif + +#if !(defined(KINETIS_CLKDIV1_OUTDIV2) && \ + KINETIS_CLKDIV1_OUTDIV2 >= 1 && KINETIS_CLKDIV1_OUTDIV2 <= 16) +#error KINETIS_CLKDIV1_OUTDIV2 must be 1 through 16 +#endif + +#if !(defined(KINETIS_CLKDIV1_OUTDIV3) && \ + KINETIS_CLKDIV1_OUTDIV3 >= 1 && KINETIS_CLKDIV1_OUTDIV3 <= 16) +#error KINETIS_CLKDIV1_OUTDIV3 must be 1 through 16 +#endif + +#if !(defined(KINETIS_CLKDIV1_OUTDIV4) && \ + KINETIS_CLKDIV1_OUTDIV4 >= 1 && KINETIS_CLKDIV1_OUTDIV4 <= 16) +#error KINETIS_CLKDIV1_OUTDIV4 must be 1 through 16 +#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 MK66F18_clock_init(void); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/KINETIS/MK66F18/hal_pwm_lld.c b/os/hal/ports/KINETIS/MK66F18/hal_pwm_lld.c new file mode 100644 index 0000000..f39823d --- /dev/null +++ b/os/hal/ports/KINETIS/MK66F18/hal_pwm_lld.c @@ -0,0 +1,390 @@ +/* + ChibiOS/HAL - Copyright (C) 2014 Adam J. Porter + + 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 MK66F18/pwm_lld.c + * @brief KINETIS PWM subsystem low level driver source. + * + * @addtogroup PWM + * @{ + */ + +#include "hal.h" + +#if HAL_USE_PWM || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief PWMD1 driver identifier. + * @note The driver PWMD1 allocates the timer FTM0 when enabled. + */ +#if KINETIS_PWM_USE_FTM0 || defined(__DOXYGEN__) +PWMDriver PWMD1; +#endif + +/** + * @brief PWMD2 driver identifier. + * @note The driver PWMD2 allocates the timer FTM1 when enabled. + */ +#if KINETIS_PWM_USE_FTM1 || defined(__DOXYGEN__) +PWMDriver PWMD2; +#endif + +/** + * @brief PWMD3 driver identifier. + * @note The driver PWMD3 allocates the timer FTM2 when enabled. + */ +#if KINETIS_PWM_USE_FTM2 || defined(__DOXYGEN__) +PWMDriver PWMD3; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static void pwm_lld_serve_interrupt(PWMDriver *pwmp) { + uint32_t sr; + + sr = pwmp->ftm->SC; + pwmp->ftm->SC = sr&(~FTM_SC_TOF); + + if (((sr & FTM_SC_TOF) != 0) && /* Timer Overflow */ + ((sr & FTM_SC_TOIE) != 0) && + (pwmp->config->callback != NULL)) { + pwmp->config->callback(pwmp); + } + + uint8_t n=0; + for(n=0;nchannels;n++) { + sr = pwmp->ftm->CHANNEL[n].CnSC; + pwmp->ftm->CHANNEL[n].CnSC = sr&(~FTM_CnSC_CHF); + if (((sr & FTM_CnSC_CHF) != 0) && + ((sr & FTM_CnSC_CHIE) != 0) && + (pwmp->config->channels[n].callback != NULL)) { + pwmp->config->channels[n].callback(pwmp); + } + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if KINETIS_PWM_USE_FTM0 +/** + * @brief FTM0 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(KINETIS_FTM0_IRQ_VECTOR) { + OSAL_IRQ_PROLOGUE(); + pwm_lld_serve_interrupt(&PWMD1); + OSAL_IRQ_EPILOGUE(); +} +#endif /* KINETIS_PWM_USE_FTM0 */ + +#if KINETIS_PWM_USE_FTM1 +/** + * @brief FTM1 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(KINETIS_FTM1_IRQ_VECTOR) { + + OSAL_IRQ_PROLOGUE(); + pwm_lld_serve_interrupt(&PWMD2); + OSAL_IRQ_EPILOGUE(); +} +#endif /* KINETIS_PWM_USE_FTM1 */ + +#if KINETIS_PWM_USE_FTM2 +/** + * @brief FTM2 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(KINETIS_FTM2_IRQ_VECTOR) { + + OSAL_IRQ_PROLOGUE(); + pwm_lld_serve_interrupt(&PWMD3); + OSAL_IRQ_EPILOGUE(); +} +#endif /* KINETIS_PWM_USE_FTM2 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level PWM driver initialization. + * + * @notapi + */ +void pwm_lld_init(void) { + +#if KINETIS_PWM_USE_FTM0 + pwmObjectInit(&PWMD1); + PWMD1.channels = KINETIS_FTM0_CHANNELS; + PWMD1.ftm = FTM0; +#endif + +#if KINETIS_PWM_USE_FTM1 + pwmObjectInit(&PWMD2); + PWMD2.channels = KINETIS_FTM1_CHANNELS; + PWMD2.ftm = FTM1; +#endif + +#if KINETIS_PWM_USE_FTM2 + pwmObjectInit(&PWMD3); + PWMD3.channels = KINETIS_FTM2_CHANNELS; + PWMD3.ftm = FTM2; +#endif +} + +/** + * @brief Configures and activates the PWM peripheral. + * @note Starting a driver that is already in the @p PWM_READY state + * disables all the active channels. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @notapi + */ +void pwm_lld_start(PWMDriver *pwmp) { + uint16_t psc; + uint8_t i=0; + + if (pwmp->state == PWM_STOP) { + /* Clock activation and timer reset.*/ +#if KINETIS_PWM_USE_FTM0 + if (&PWMD1 == pwmp) { + SIM->SCGC6 |= SIM_SCGC6_FTM0; + nvicEnableVector(FTM0_IRQn, KINETIS_PWM_FTM0_PRIORITY); + } +#endif + +#if KINETIS_PWM_USE_FTM1 + if (&PWMD2 == pwmp) { + SIM->SCGC6 |= SIM_SCGC6_FTM1; + nvicEnableVector(FTM1_IRQn, KINETIS_PWM_FTM1_PRIORITY); + } +#endif + +#if KINETIS_PWM_USE_FTM2 + if (&PWMD3 == pwmp) { + SIM->SCGC3 |= SIM_SCGC3_FTM2; + nvicEnableVector(FTM2_IRQn, KINETIS_PWM_FTM2_PRIORITY); + } +#endif + } + pwmp->ftm->MODE = FTM_MODE_FTMEN_MASK|FTM_MODE_PWMSYNC_MASK; + pwmp->ftm->SYNC = FTM_SYNC_CNTMIN_MASK|FTM_SYNC_CNTMAX_MASK + |FTM_SYNC_SWSYNC_MASK; + pwmp->ftm->COMBINE = FTM_COMBINE_SYNCEN3_MASK | FTM_COMBINE_SYNCEN2_MASK + | FTM_COMBINE_SYNCEN1_MASK | FTM_COMBINE_SYNCEN0_MASK; + pwmp->ftm->SYNCONF = FTM_SYNCONF_SYNCMODE_MASK; + + pwmp->ftm->CNTIN = 0x0000; + //~ pwmp->ftm->SC = 0; /* Disable FTM counter.*/ + pwmp->ftm->CNT = 0x0000; /* Clear count register.*/ + + /* Prescaler value calculation.*/ + psc = (KINETIS_SYSCLK_FREQUENCY / pwmp->config->frequency); + //~ /* Prescaler must be power of two between 1 and 128.*/ + osalDbgAssert(psc <= 128 && !(psc & (psc - 1)), "invalid frequency"); + //~ /* Prescaler register value determination. + //~ Prescaler register value conveniently corresponds to bit position, + //~ i.e., register value for prescaler CLK/64 is 6 ((1 << 6) == 64).*/ + for (i = 0; i < 8; i++) { + if (psc == (unsigned)(1 << i)) { + break; + } + } + + /* Set prescaler and clock mode. + This also sets the following: + CPWMS up-counting mode + Timer overflow interrupt disabled + DMA disabled.*/ + pwmp->ftm->SC = FTM_SC_CLKS(1) | FTM_SC_PS(i); + /* Configure period */ + pwmp->ftm->MOD = pwmp->period-1; + pwmp->ftm->PWMLOAD = FTM_PWMLOAD_LDOK_MASK; +} + +/** + * @brief Deactivates the PWM peripheral. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @notapi + */ +void pwm_lld_stop(PWMDriver *pwmp) { + + /* If in ready state then disables the PWM clock.*/ + if (pwmp->state == PWM_READY) { +#if KINETIS_PWM_USE_FTM0 + if (&PWMD1 == pwmp) { + SIM->SCGC6 &= ~SIM_SCGC6_FTM0; + nvicDisableVector(FTM0_IRQn); + } +#endif + +#if KINETIS_PWM_USE_FTM1 + if (&PWMD2 == pwmp) { + SIM->SCGC6 &= ~SIM_SCGC6_FTM1; + nvicDisableVector(FTM1_IRQn); + } +#endif + +#if KINETIS_PWM_USE_FTM2 + if (&PWMD3 == pwmp) { + SIM->SCGC3 &= ~SIM_SCGC3_FTM2; + nvicDisableVector(FTM2_IRQn); + } +#endif + /* Disable FTM counter.*/ + pwmp->ftm->SC = 0; + pwmp->ftm->MOD = 0; + } +} + +/** + * @brief Enables a PWM channel. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The channel is active using the specified configuration. + * @note The function has effect at the next cycle start. + * @note Channel notification is not enabled. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...channels-1) + * @param[in] width PWM pulse width as clock pulses number + * + * @notapi + */ +void pwm_lld_enable_channel(PWMDriver *pwmp, + pwmchannel_t channel, + pwmcnt_t width) { + uint32_t mode = FTM_CnSC_MSB; /* Edge-aligned PWM mode.*/ + + switch (pwmp->config->channels[channel].mode & PWM_OUTPUT_MASK) { + case PWM_OUTPUT_ACTIVE_HIGH: + mode |= FTM_CnSC_ELSB; + break; + case PWM_OUTPUT_ACTIVE_LOW: + mode |= FTM_CnSC_ELSA; + break; + } + + if (pwmp->ftm->CHANNEL[channel].CnSC & FTM_CnSC_CHIE) + mode |= FTM_CnSC_CHIE; + + pwmp->ftm->CHANNEL[channel].CnSC = mode; + pwmp->ftm->CHANNEL[channel].CnV = width; + pwmp->ftm->PWMLOAD = FTM_PWMLOAD_LDOK_MASK; +} + +/** + * @brief Disables a PWM channel and its notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The channel is disabled and its output line returned to the + * idle state. + * @note The function has effect at the next cycle start. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...channels-1) + * + * @notapi + */ +void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) { + + pwmp->ftm->CHANNEL[channel].CnSC = 0; + pwmp->ftm->CHANNEL[channel].CnV = 0; +} + +/** + * @brief Enables the periodic activation edge notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @note If the notification is already enabled then the call has no effect. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @notapi + */ +void pwm_lld_enable_periodic_notification(PWMDriver *pwmp) { + pwmp->ftm->SC |= FTM_SC_TOIE; +} + +/** + * @brief Disables the periodic activation edge notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @note If the notification is already disabled then the call has no effect. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @notapi + */ +void pwm_lld_disable_periodic_notification(PWMDriver *pwmp) { + pwmp->ftm->SC &= ~FTM_SC_TOIE; +} + +/** + * @brief Enables a channel de-activation edge notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @pre The channel must have been activated using @p pwmEnableChannel(). + * @note If the notification is already enabled then the call has no effect. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...channels-1) + * + * @notapi + */ +void pwm_lld_enable_channel_notification(PWMDriver *pwmp, + pwmchannel_t channel) { + pwmp->ftm->CHANNEL[channel].CnSC |= FTM_CnSC_CHIE; +} + +/** + * @brief Disables a channel de-activation edge notification. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @pre The channel must have been activated using @p pwmEnableChannel(). + * @note If the notification is already disabled then the call has no effect. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...channels-1) + * + * @notapi + */ +void pwm_lld_disable_channel_notification(PWMDriver *pwmp, + pwmchannel_t channel) { + pwmp->ftm->CHANNEL[channel].CnSC &= ~FTM_CnSC_CHIE; +} + +#endif /* HAL_USE_PWM */ + +/** @} */ diff --git a/os/hal/ports/KINETIS/MK66F18/hal_pwm_lld.h b/os/hal/ports/KINETIS/MK66F18/hal_pwm_lld.h new file mode 100644 index 0000000..9332e34 --- /dev/null +++ b/os/hal/ports/KINETIS/MK66F18/hal_pwm_lld.h @@ -0,0 +1,270 @@ +/* + ChibiOS/HAL - Copyright (C) 2014 Adam J. Porter + + 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 MK66F18/pwm_lld.h + * @brief KINETIS PWM subsystem low level driver header. + * + * @addtogroup PWM + * @{ + */ + +#ifndef HAL_PWM_LLD_H_ +#define HAL_PWM_LLD_H_ + +#if HAL_USE_PWM || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Number of PWM channels per PWM driver. + */ +#define PWM_CHANNELS 8 + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +#if !defined(KINETIS_PWM_USE_FTM0) + #define KINETIS_PWM_USE_FTM0 FALSE +#endif + +#if !defined(KINETIS_PWM_USE_FTM1) + #define KINETIS_PWM_USE_FTM1 FALSE +#endif + +#if !defined(KINETIS_PWM_USE_FTM2) + #define KINETIS_PWM_USE_FTM2 FALSE +#endif + +/** + * @brief FTM0 interrupt priority level setting. + */ +#if !defined(KINETIS_PWM_FTM0_PRIORITY) || defined(__DOXYGEN__) +#define KINETIS_PWM_FTM0_PRIORITY 12 +#endif + +/** + * @brief FTM1 interrupt priority level setting. + */ +#if !defined(KINETIS_PWM_FTM1_PRIORITY) || defined(__DOXYGEN__) +#define KINETIS_PWM_FTM1_PRIORITY 12 +#endif + +/** + * @brief FTM2 interrupt priority level setting. + */ +#if !defined(KINETIS_PWM_FTM2_PRIORITY) || defined(__DOXYGEN__) +#define KINETIS_PWM_FTM2_PRIORITY 12 +#endif + +/** @} */ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief If advanced timer features switch. + * @details If set to @p TRUE the advanced features for TIM1 and TIM8 are + * enabled. + * @note The default is @p TRUE. + */ +#if !defined(KINETIS_PWM_USE_ADVANCED) || defined(__DOXYGEN__) +#define KINETIS_PWM_USE_ADVANCED FALSE +#endif +/** @} */ + +/*===========================================================================*/ +/* Configuration checks. */ +/*===========================================================================*/ + +#if !KINETIS_PWM_USE_FTM0 && !KINETIS_PWM_USE_FTM1 && !KINETIS_PWM_USE_FTM2 +#error "PWM driver activated but no FTM peripheral assigned" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a PWM mode. + */ +typedef uint32_t pwmmode_t; + +/** + * @brief Type of a PWM channel. + */ +typedef uint8_t pwmchannel_t; + +/** + * @brief Type of a channels mask. + */ +typedef uint32_t pwmchnmsk_t; + +/** + * @brief Type of a PWM counter. + */ +typedef uint16_t pwmcnt_t; + +/** + * @brief Type of a PWM driver channel configuration structure. + */ +typedef struct { + /** + * @brief Channel active logic level. + */ + pwmmode_t mode; + + /** + * @brief Channel callback pointer. + * @note This callback is invoked on the channel compare event. If set to + * @p NULL then the callback is disabled. + */ + pwmcallback_t callback; + /* End of the mandatory fields.*/ +} PWMChannelConfig; + +/** + * @brief Type of a PWM driver configuration structure. + */ +typedef struct { + /** + * @brief Timer clock in Hz. + * @note The low level can use assertions in order to catch invalid + * frequency specifications. + */ + uint32_t frequency; + /** + * @brief PWM period in ticks. + * @note The low level can use assertions in order to catch invalid + * period specifications. + */ + pwmcnt_t period; + /** + * @brief Periodic callback pointer. + * @note This callback is invoked on PWM counter reset. If set to + * @p NULL then the callback is disabled. + */ + pwmcallback_t callback; + /** + * @brief Channels configurations. + */ + PWMChannelConfig channels[PWM_CHANNELS]; + /* End of the mandatory fields.*/ +} PWMConfig; + +/** + * @brief Structure representing a PWM driver. + */ +struct PWMDriver { + /** + * @brief Driver state. + */ + pwmstate_t state; + /** + * @brief Current driver configuration data. + */ + const PWMConfig *config; + /** + * @brief Current PWM period in ticks. + */ + pwmcnt_t period; + /** + * @brief Mask of the enabled channels. + */ + pwmchnmsk_t enabled; + /** + * @brief Number of channels in this instance. + */ + pwmchannel_t channels; +#if defined(PWM_DRIVER_EXT_FIELDS) + PWM_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the FTM registers block. + */ + FTM_TypeDef *ftm; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Changes the period the PWM peripheral. + * @details This function changes the period of a PWM unit that has already + * been activated using @p pwmStart(). + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The PWM unit period is changed to the new value. + * @note The function has effect at the next cycle start. + * @note If a period is specified that is shorter than the pulse width + * programmed in one of the channels then the behavior is not + * guaranteed. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] period new cycle time in ticks + * + * @notapi + */ +#define pwm_lld_change_period(pwmp, period) \ + do { \ + (pwmp)->ftm->MOD = ((period) - 1); \ + pwmp->ftm->PWMLOAD = FTM_PWMLOAD_LDOK_MASK;\ + } while(0) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if KINETIS_PWM_USE_FTM0 || defined(__DOXYGEN__) +extern PWMDriver PWMD1; +#endif +#if KINETIS_PWM_USE_FTM1 || defined(__DOXYGEN__) +extern PWMDriver PWMD2; +#endif +#if KINETIS_PWM_USE_FTM2 || defined(__DOXYGEN__) +extern PWMDriver PWMD3; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void pwm_lld_init(void); + void pwm_lld_start(PWMDriver *pwmp); + void pwm_lld_stop(PWMDriver *pwmp); + void pwm_lld_enable_channel(PWMDriver *pwmp, + pwmchannel_t channel, + pwmcnt_t width); + void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel); + void pwm_lld_enable_periodic_notification(PWMDriver *pwmp); + void pwm_lld_disable_periodic_notification(PWMDriver *pwmp); + void pwm_lld_enable_channel_notification(PWMDriver *pwmp, + pwmchannel_t channel); + void pwm_lld_disable_channel_notification(PWMDriver *pwmp, + pwmchannel_t channel); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_PWM */ + +#endif /* HAL_PWM_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/KINETIS/MK66F18/hal_spi_lld.c b/os/hal/ports/KINETIS/MK66F18/hal_spi_lld.c new file mode 100644 index 0000000..29ab4e8 --- /dev/null +++ b/os/hal/ports/KINETIS/MK66F18/hal_spi_lld.c @@ -0,0 +1,539 @@ +/* + ChibiOS - Copyright (C) 2014-2015 Fabio Utzig + + 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/spi_lld.c + * @brief KINETIS SPI subsystem low level driver source. + * + * @addtogroup SPI + * @{ + */ + +#include "hal.h" + +#if HAL_USE_SPI || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#if !defined(KINETIS_SPI0_RX_DMA_IRQ_PRIORITY) +#define KINETIS_SPI0_RX_DMA_IRQ_PRIORITY 8 +#endif + +#if !defined(KINETIS_SPI0_RX_DMAMUX_CHANNEL) +#define KINETIS_SPI0_RX_DMAMUX_CHANNEL 0 +#endif + +#if !defined(KINETIS_SPI0_RX_DMA_CHANNEL) +#define KINETIS_SPI0_RX_DMA_CHANNEL 0 +#endif + +#if !defined(KINETIS_SPI0_TX_DMAMUX_CHANNEL) +#define KINETIS_SPI0_TX_DMAMUX_CHANNEL 1 +#endif + +#if !defined(KINETIS_SPI0_TX_DMA_CHANNEL) +#define KINETIS_SPI0_TX_DMA_CHANNEL 1 +#endif + +#if !defined(KINETIS_SPI1_RX_DMA_IRQ_PRIORITY) +#define KINETIS_SPI1_RX_DMA_IRQ_PRIORITY 8 +#endif + +#if !defined(KINETIS_SPI1_RX_DMAMUX_CHANNEL) +#define KINETIS_SPI1_RX_DMAMUX_CHANNEL 0 +#endif + +#if !defined(KINETIS_SPI1_RX_DMA_CHANNEL) +#define KINETIS_SPI1_RX_DMA_CHANNEL 0 +#endif + +#if !defined(KINETIS_SPI1_TX_DMAMUX_CHANNEL) +#define KINETIS_SPI1_TX_DMAMUX_CHANNEL 1 +#endif + +#if !defined(KINETIS_SPI1_TX_DMA_CHANNEL) +#define KINETIS_SPI1_TX_DMA_CHANNEL 1 +#endif + +#if KINETIS_SPI_USE_SPI0 +#define DMAMUX_SPI_RX_SOURCE 16 +#define DMAMUX_SPI_TX_SOURCE 17 +#endif + +#if KINETIS_SPI_USE_SPI1 +#define DMAMUX_SPI_RX_SOURCE 18 +#define DMAMUX_SPI_TX_SOURCE 19 +#endif + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief SPI0 driver identifier.*/ +#if KINETIS_SPI_USE_SPI0 || defined(__DOXYGEN__) +SPIDriver SPID1; +#endif + +/** @brief SPI1 driver identifier.*/ +#if KINETIS_SPI_USE_SPI1 || defined(__DOXYGEN__) +SPIDriver SPID2; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/* Use a dummy byte as the source/destination when a buffer is not provided */ +/* Note: The MMC driver relies on 0xFF being sent for dummy bytes. */ +static volatile uint16_t dmaRxDummy; +static uint16_t dmaTxDummy = 0xFFFF; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static void spi_start_xfer(SPIDriver *spip, bool polling) +{ + /* + * Enable the DSPI peripheral in master mode. + * Clear the TX and RX FIFOs. + * */ + spip->spi->MCR = SPIx_MCR_MSTR | SPIx_MCR_CLR_TXF | SPIx_MCR_CLR_RXF; + + /* If we are not polling then enable DMA */ + if (!polling) { + + /* Enable receive dma and transmit dma */ + spip->spi->RSER = SPIx_RSER_RFDF_DIRS | SPIx_RSER_RFDF_RE | + SPIx_RSER_TFFF_RE | SPIx_RSER_TFFF_DIRS; + + /* Configure RX DMA */ + if (spip->rxbuf) { + DMA->TCD[KINETIS_SPI0_RX_DMA_CHANNEL].DADDR = (uint32_t)spip->rxbuf; + DMA->TCD[KINETIS_SPI0_RX_DMA_CHANNEL].DOFF = spip->word_size; + } else { + DMA->TCD[KINETIS_SPI0_RX_DMA_CHANNEL].DADDR = (uint32_t)&dmaRxDummy; + DMA->TCD[KINETIS_SPI0_RX_DMA_CHANNEL].DOFF = 0; + } + DMA->TCD[KINETIS_SPI0_RX_DMA_CHANNEL].BITER_ELINKNO = spip->count; + DMA->TCD[KINETIS_SPI0_RX_DMA_CHANNEL].CITER_ELINKNO = spip->count; + + /* Enable Request Register (ERQ) for RX by writing 0 to SERQ */ + DMA->SERQ = KINETIS_SPI0_RX_DMA_CHANNEL; + + /* Configure TX DMA */ + if (spip->txbuf) { + DMA->TCD[KINETIS_SPI0_TX_DMA_CHANNEL].SADDR = (uint32_t)spip->txbuf; + DMA->TCD[KINETIS_SPI0_TX_DMA_CHANNEL].SOFF = spip->word_size; + } else { + DMA->TCD[KINETIS_SPI0_TX_DMA_CHANNEL].SADDR = (uint32_t)&dmaTxDummy; + DMA->TCD[KINETIS_SPI0_TX_DMA_CHANNEL].SOFF = 0; + } + DMA->TCD[KINETIS_SPI0_TX_DMA_CHANNEL].BITER_ELINKNO = spip->count; + DMA->TCD[KINETIS_SPI0_TX_DMA_CHANNEL].CITER_ELINKNO = spip->count; + + /* Enable Request Register (ERQ) for TX by writing 1 to SERQ */ + DMA->SERQ = KINETIS_SPI0_TX_DMA_CHANNEL; + } +} + +static void spi_stop_xfer(SPIDriver *spip) +{ + /* Halt the DSPI peripheral */ + spip->spi->MCR = SPIx_MCR_MSTR | SPIx_MCR_HALT; + + /* Clear all the flags which are currently set. */ + spip->spi->SR |= spip->spi->SR; +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if KINETIS_SPI_USE_SPI0 || defined(__DOXYGEN__) + +OSAL_IRQ_HANDLER(KINETIS_DMA0_IRQ_VECTOR) { + OSAL_IRQ_PROLOGUE(); + + /* Clear bit 0 in Interrupt Request Register (INT) by writing 0 to CINT */ + DMA->CINT = KINETIS_SPI0_RX_DMA_CHANNEL; + + spi_stop_xfer(&SPID1); + + _spi_isr_code(&SPID1); + + OSAL_IRQ_EPILOGUE(); +} + +#endif + +#if KINETIS_SPI_USE_SPI1 || defined(__DOXYGEN__) + +OSAL_IRQ_HANDLER(KINETIS_DMA0_IRQ_VECTOR) { + OSAL_IRQ_PROLOGUE(); + + /* Clear bit 0 in Interrupt Request Register (INT) by writing 0 to CINT */ + DMA->CINT = KINETIS_SPI1_RX_DMA_CHANNEL; + + spi_stop_xfer(&SPID2); + + _spi_isr_code(&SPID2); + + OSAL_IRQ_EPILOGUE(); +} + +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level SPI driver initialization. + * + * @notapi + */ +void spi_lld_init(void) { +#if KINETIS_SPI_USE_SPI0 + spiObjectInit(&SPID1); +#endif +#if KINETIS_SPI_USE_SPI1 + spiObjectInit(&SPID2); +#endif +} + +/** + * @brief Configures and activates the SPI peripheral. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_start(SPIDriver *spip) { + + /* If in stopped state then enables the SPI and DMA clocks.*/ + if (spip->state == SPI_STOP) { + +#if KINETIS_SPI_USE_SPI0 + if (&SPID1 == spip) { + + /* Enable the clock for SPI0 */ + SIM->SCGC6 |= SIM_SCGC6_SPI0; + + SPID1.spi = SPI0; + + if (spip->config->tar0) { + spip->spi->CTAR[0] = spip->config->tar0; + } else { + spip->spi->CTAR[0] = KINETIS_SPI_TAR0_DEFAULT; + } + } +#endif + +#if KINETIS_SPI_USE_SPI1 + if (&SPID2 == spip) { + + /* Enable the clock for SPI0 */ + SIM->SCGC6 |= SIM_SCGC6_SPI1; + + SPID2.spi = SPI1; + + if (spip->config->tar0) { + spip->spi->CTAR[0] = spip->config->tar0; + } else { + spip->spi->CTAR[0] = KINETIS_SPI_TAR0_DEFAULT; + } + } +#endif + + nvicEnableVector(DMA0_IRQn, KINETIS_SPI0_RX_DMA_IRQ_PRIORITY); + + SIM->SCGC6 |= SIM_SCGC6_DMAMUX; + SIM->SCGC7 |= SIM_SCGC7_DMA; + + /* Clear DMA error flags */ + DMA->ERR = 0x0F; + +#if KINETIS_SPI_USE_SPI0 + /* Rx, select SPI Rx FIFO */ + DMAMUX->CHCFG[KINETIS_SPI0_RX_DMAMUX_CHANNEL] = DMAMUX_CHCFGn_ENBL | + DMAMUX_CHCFGn_SOURCE(DMAMUX_SPI_RX_SOURCE); + + /* Tx, select SPI Tx FIFO */ + DMAMUX->CHCFG[KINETIS_SPI0_TX_DMAMUX_CHANNEL] = DMAMUX_CHCFGn_ENBL | + DMAMUX_CHCFGn_SOURCE(DMAMUX_SPI_TX_SOURCE); + + /* Extract the frame size from the TAR */ + uint16_t frame_size = ((spip->spi->CTAR[0] >> SPIx_CTARn_FMSZ_SHIFT) & + SPIx_CTARn_FMSZ_MASK) + 1; + + /* DMA transfer size is 16 bits for a frame size > 8 bits */ + uint16_t dma_size = frame_size > 8 ? 1 : 0; + + /* DMA word size is 2 for a 16 bit frame size */ + spip->word_size = frame_size > 8 ? 2 : 1; + + /* configure DMA RX fixed values */ + DMA->TCD[KINETIS_SPI0_RX_DMA_CHANNEL].SADDR = (uint32_t)&SPI0->POPR; + DMA->TCD[KINETIS_SPI0_RX_DMA_CHANNEL].SOFF = 0; + DMA->TCD[KINETIS_SPI0_RX_DMA_CHANNEL].SLAST = 0; + DMA->TCD[KINETIS_SPI0_RX_DMA_CHANNEL].DLASTSGA = 0; + DMA->TCD[KINETIS_SPI0_RX_DMA_CHANNEL].ATTR = DMA_ATTR_SSIZE(dma_size) | + DMA_ATTR_DSIZE(dma_size); + DMA->TCD[KINETIS_SPI0_RX_DMA_CHANNEL].NBYTES_MLNO = spip->word_size; + DMA->TCD[KINETIS_SPI0_RX_DMA_CHANNEL].CSR = DMA_CSR_DREQ_MASK | + DMA_CSR_INTMAJOR_MASK; + + /* configure DMA TX fixed values */ + DMA->TCD[KINETIS_SPI0_TX_DMA_CHANNEL].SLAST = 0; + DMA->TCD[KINETIS_SPI0_TX_DMA_CHANNEL].DADDR = (uint32_t)&SPI0->PUSHR; + DMA->TCD[KINETIS_SPI0_TX_DMA_CHANNEL].DOFF = 0; + DMA->TCD[KINETIS_SPI0_TX_DMA_CHANNEL].DLASTSGA = 0; + DMA->TCD[KINETIS_SPI0_TX_DMA_CHANNEL].ATTR = DMA_ATTR_SSIZE(dma_size) | + DMA_ATTR_DSIZE(dma_size); + DMA->TCD[KINETIS_SPI0_TX_DMA_CHANNEL].NBYTES_MLNO = spip->word_size; + DMA->TCD[KINETIS_SPI0_TX_DMA_CHANNEL].CSR = DMA_CSR_DREQ_MASK; +#endif + +#if KINETIS_SPI_USE_SPI1 + /* Rx, select SPI Rx FIFO */ + DMAMUX->CHCFG[KINETIS_SPI1_RX_DMAMUX_CHANNEL] = DMAMUX_CHCFGn_ENBL | + DMAMUX_CHCFGn_SOURCE(DMAMUX_SPI_RX_SOURCE); + + /* Tx, select SPI Tx FIFO */ + DMAMUX->CHCFG[KINETIS_SPI1_TX_DMAMUX_CHANNEL] = DMAMUX_CHCFGn_ENBL | + DMAMUX_CHCFGn_SOURCE(DMAMUX_SPI_TX_SOURCE); + + /* Extract the frame size from the TAR */ + uint16_t frame_size = ((spip->spi->CTAR[0] >> SPIx_CTARn_FMSZ_SHIFT) & + SPIx_CTARn_FMSZ_MASK) + 1; + + /* DMA transfer size is 16 bits for a frame size > 8 bits */ + uint16_t dma_size = frame_size > 8 ? 1 : 0; + + /* DMA word size is 2 for a 16 bit frame size */ + spip->word_size = frame_size > 8 ? 2 : 1; + + /* configure DMA RX fixed values */ + DMA->TCD[KINETIS_SPI1_RX_DMA_CHANNEL].SADDR = (uint32_t)&SPI1->POPR; + DMA->TCD[KINETIS_SPI1_RX_DMA_CHANNEL].SOFF = 0; + DMA->TCD[KINETIS_SPI1_RX_DMA_CHANNEL].SLAST = 0; + DMA->TCD[KINETIS_SPI1_RX_DMA_CHANNEL].DLASTSGA = 0; + DMA->TCD[KINETIS_SPI1_RX_DMA_CHANNEL].ATTR = DMA_ATTR_SSIZE(dma_size) | + DMA_ATTR_DSIZE(dma_size); + DMA->TCD[KINETIS_SPI1_RX_DMA_CHANNEL].NBYTES_MLNO = spip->word_size; + DMA->TCD[KINETIS_SPI1_RX_DMA_CHANNEL].CSR = DMA_CSR_DREQ_MASK | + DMA_CSR_INTMAJOR_MASK; + + /* configure DMA TX fixed values */ + DMA->TCD[KINETIS_SPI1_TX_DMA_CHANNEL].SLAST = 0; + DMA->TCD[KINETIS_SPI1_TX_DMA_CHANNEL].DADDR = (uint32_t)&SPI1->PUSHR; + DMA->TCD[KINETIS_SPI1_TX_DMA_CHANNEL].DOFF = 0; + DMA->TCD[KINETIS_SPI1_TX_DMA_CHANNEL].DLASTSGA = 0; + DMA->TCD[KINETIS_SPI1_TX_DMA_CHANNEL].ATTR = DMA_ATTR_SSIZE(dma_size) | + DMA_ATTR_DSIZE(dma_size); + DMA->TCD[KINETIS_SPI1_TX_DMA_CHANNEL].NBYTES_MLNO = spip->word_size; + DMA->TCD[KINETIS_SPI1_TX_DMA_CHANNEL].CSR = DMA_CSR_DREQ_MASK; +#endif + } +} + +/** + * @brief Deactivates the SPI peripheral. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_stop(SPIDriver *spip) { + + /* If in ready state then disables the SPI clock.*/ + if (spip->state == SPI_READY) { + + nvicDisableVector(DMA0_IRQn); + + SIM->SCGC7 &= ~SIM_SCGC7_DMA; + SIM->SCGC6 &= ~SIM_SCGC6_DMAMUX; + +#if KINETIS_SPI_USE_SPI0 + if (&SPID1 == spip) { + /* SPI halt.*/ + spip->spi->MCR |= SPIx_MCR_HALT; + } + + /* Disable the clock for SPI0 */ + SIM->SCGC6 &= ~SIM_SCGC6_SPI0; +#endif + +#if KINETIS_SPI_USE_SPI1 + if (&SPID2 == spip) { + /* SPI halt.*/ + spip->spi->MCR |= SPIx_MCR_HALT; + } + + /* Disable the clock for SPI1 */ + SIM->SCGC6 &= ~SIM_SCGC6_SPI1; +#endif + } +} + +/** + * @brief Asserts the slave select signal and prepares for transfers. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_select(SPIDriver *spip) { + + palClearPad(spip->config->ssport, spip->config->sspad); +} + +/** + * @brief Deasserts the slave select signal. + * @details The previously selected peripheral is unselected. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_unselect(SPIDriver *spip) { + + palSetPad(spip->config->ssport, spip->config->sspad); +} + +/** + * @brief Ignores data on the SPI bus. + * @details This asynchronous function starts the transmission of a series of + * idle words on the SPI bus and ignores the received data. + * @post At the end of the operation the configured callback is invoked. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to be ignored + * + * @notapi + */ +void spi_lld_ignore(SPIDriver *spip, size_t n) { + + spip->count = n; + spip->rxbuf = NULL; + spip->txbuf = NULL; + + spi_start_xfer(spip, false); +} + +/** + * @brief Exchanges data on the SPI bus. + * @details This asynchronous function starts a simultaneous transmit/receive + * operation. + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below or + * equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to be exchanged + * @param[in] txbuf the pointer to the transmit buffer + * @param[out] rxbuf the pointer to the receive buffer + * + * @notapi + */ +void spi_lld_exchange(SPIDriver *spip, size_t n, + const void *txbuf, void *rxbuf) { + + spip->count = n; + spip->rxbuf = rxbuf; + spip->txbuf = txbuf; + + spi_start_xfer(spip, false); +} + +/** + * @brief Sends data over the SPI bus. + * @details This asynchronous function starts a transmit operation. + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below or + * equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @notapi + */ +void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) { + + spip->count = n; + spip->rxbuf = NULL; + spip->txbuf = (void *)txbuf; + + spi_start_xfer(spip, false); +} + +/** + * @brief Receives data from the SPI bus. + * @details This asynchronous function starts a receive operation. + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below or + * equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to receive + * @param[out] rxbuf the pointer to the receive buffer + * + * @notapi + */ +void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) { + + spip->count = n; + spip->rxbuf = rxbuf; + spip->txbuf = NULL; + + spi_start_xfer(spip, false); +} + +/** + * @brief Exchanges one frame using a polled wait. + * @details This synchronous function exchanges one frame using a polled + * synchronization method. This function is useful when exchanging + * small amount of data on high speed channels, usually in this + * situation is much more efficient just wait for completion using + * polling than suspending the thread waiting for an interrupt. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] frame the data frame to send over the SPI bus + * @return The received data frame from the SPI bus. + */ +uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame) { + + spi_start_xfer(spip, true); + + spip->spi->PUSHR = SPIx_PUSHR_TXDATA(frame); + + while ((spip->spi->SR & SPIx_SR_RFDF) == 0) + ; + + frame = spip->spi->POPR; + + spi_stop_xfer(spip); + + return frame; +} + +#endif /* HAL_USE_SPI */ + +/** @} */ diff --git a/os/hal/ports/KINETIS/MK66F18/hal_spi_lld.h b/os/hal/ports/KINETIS/MK66F18/hal_spi_lld.h new file mode 100644 index 0000000..0cf108e --- /dev/null +++ b/os/hal/ports/KINETIS/MK66F18/hal_spi_lld.h @@ -0,0 +1,261 @@ +/* + ChibiOS - Copyright (C) 2014-2015 Fabio Utzig + + 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/spi_lld.h + * @brief KINETIS SPI subsystem low level driver header. + * + * @addtogroup SPI + * @{ + */ + +#ifndef HAL_SPI_LLD_H_ +#define HAL_SPI_LLD_H_ + +#if HAL_USE_SPI || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief SPI0 driver enable switch. + * @details If set to @p TRUE the support for SPI0 is included. + * @note The default is @p FALSE. + */ +#if !defined(KINETIS_SPI_USE_SPI0) || defined(__DOXYGEN__) +#define KINETIS_SPI_USE_SPI0 FALSE +#endif + +/** + * @brief SPI0 interrupt priority level setting. + */ +#if !defined(KINETIS_SPI_SPI0_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define KINETIS_SPI_SPI0_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI1 driver enable switch. + * @details If set to @p TRUE the support for SPI0 is included. + * @note The default is @p FALSE. + */ +#if !defined(KINETIS_SPI_USE_SPI1) || defined(__DOXYGEN__) +#define KINETIS_SPI_USE_SPI1 FALSE +#endif + +/** + * @brief SPI1 interrupt priority level setting. + */ +#if !defined(KINETIS_SPI_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define KINETIS_SPI_SPI1_IRQ_PRIORITY 10 +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if KINETIS_SPI_USE_SPI0 && !KINETIS_HAS_SPI0 +#error "SPI0 not present in the selected device" +#endif + +#if KINETIS_SPI_USE_SPI1 && !KINETIS_HAS_SPI1 +#error "SPI1 not present in the selected device" +#endif + +#if KINETIS_SPI_USE_SPI0 && KINETIS_SPI_USE_SPI1 +#error "Only one SPI peripheral can be enabled" +#endif + +#if !(KINETIS_SPI_USE_SPI0 || KINETIS_SPI_USE_SPI1) +#error "SPI driver activated but no SPI peripheral assigned" +#endif + +#if KINETIS_SPI_USE_SPI0 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(KINETIS_SPI_SPI0_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI0" +#endif + +#if KINETIS_SPI_USE_SPI1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(KINETIS_SPI_SPI1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI1" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a structure representing an SPI driver. + */ +typedef struct SPIDriver SPIDriver; + +/** + * @brief SPI notification callback type. + * + * @param[in] spip pointer to the @p SPIDriver object triggering the + * callback + */ +typedef void (*spicallback_t)(SPIDriver *spip); + +/** + * @brief Driver configuration structure. + */ +typedef struct { + /** + * @brief Operation complete callback or @p NULL. + */ + spicallback_t end_cb; + /* End of the mandatory fields.*/ + /** + * @brief The chip select line port - when not using pcs. + */ + ioportid_t ssport; + /** + * @brief The chip select line pad number - when not using pcs. + */ + uint16_t sspad; + /** + * @brief SPI initialization data. + */ + uint32_t tar0; +} SPIConfig; + +/** + * @brief Structure representing a SPI driver. + */ +struct SPIDriver { + /** + * @brief Driver state. + */ + spistate_t state; + /** + * @brief Current configuration data. + */ + const SPIConfig *config; +#if SPI_USE_WAIT || defined(__DOXYGEN__) + /** + * @brief Waiting thread. + */ + thread_reference_t thread; +#endif /* SPI_USE_WAIT */ +#if SPI_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) + /** + * @brief Mutex protecting the bus. + */ + mutex_t mutex; +#endif /* SPI_USE_MUTUAL_EXCLUSION */ +#if defined(SPI_DRIVER_EXT_FIELDS) + SPI_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the SPIx registers block. + */ + SPI_TypeDef *spi; + /** + * @brief Number of bytes/words of data to transfer. + */ + size_t count; + /** + * @brief Word size in bytes. + */ + size_t word_size; + /** + * @brief Pointer to the buffer with data to send. + */ + const uint8_t *txbuf; + /** + * @brief Pointer to the buffer to put received data. + */ + uint8_t *rxbuf; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/* TAR settings for n bits at SYSCLK / 2 */ +#define KINETIS_SPI_TAR_SYSCLK_DIV_2(n)\ + SPIx_CTARn_FMSZ((n) - 1) | \ + SPIx_CTARn_CPOL | \ + SPIx_CTARn_CPHA | \ + SPIx_CTARn_DBR | \ + SPIx_CTARn_PBR(0) | \ + SPIx_CTARn_BR(0) | \ + SPIx_CTARn_CSSCK(0) | \ + SPIx_CTARn_ASC(0) | \ + SPIx_CTARn_DT(0) + +/* TAR settings for n bits at SYSCLK / 4096 for debugging */ +#define KINETIS_SPI_TAR_SYSCLK_DIV_4096(n) \ + SPIx_CTARn_FMSZ(((n) - 1)) | \ + SPIx_CTARn_CPOL | \ + SPIx_CTARn_CPHA | \ + SPIx_CTARn_PBR(0) | \ + SPIx_CTARn_BR(0xB) | \ + SPIx_CTARn_CSSCK(0xB) | \ + SPIx_CTARn_ASC(0x7) | \ + SPIx_CTARn_DT(0xB) + +#define KINETIS_SPI_TAR_8BIT_FAST KINETIS_SPI_TAR_SYSCLK_DIV_2(8) +#define KINETIS_SPI_TAR_8BIT_SLOW KINETIS_SPI_TAR_SYSCLK_DIV_4096(8) + +#define KINETIS_SPI_TAR0_DEFAULT KINETIS_SPI_TAR_SYSCLK_DIV_2(8) +#define KINETIS_SPI_TAR1_DEFAULT KINETIS_SPI_TAR_SYSCLK_DIV_2(8) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if KINETIS_SPI_USE_SPI0 && !defined(__DOXYGEN__) +extern SPIDriver SPID1; +#endif + +#if KINETIS_SPI_USE_SPI1 && !defined(__DOXYGEN__) +extern SPIDriver SPID2; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void spi_lld_init(void); + void spi_lld_start(SPIDriver *spip); + void spi_lld_stop(SPIDriver *spip); + void spi_lld_select(SPIDriver *spip); + void spi_lld_unselect(SPIDriver *spip); + void spi_lld_ignore(SPIDriver *spip, size_t n); + void spi_lld_exchange(SPIDriver *spip, size_t n, + const void *txbuf, void *rxbuf); + void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf); + void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf); + uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SPI */ + +#endif /* HAL_SPI_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/KINETIS/MK66F18/kinetis_registry.h b/os/hal/ports/KINETIS/MK66F18/kinetis_registry.h new file mode 100644 index 0000000..f733244 --- /dev/null +++ b/os/hal/ports/KINETIS/MK66F18/kinetis_registry.h @@ -0,0 +1,165 @@ +/* + ChibiOS - Copyright (C) 2014 Derek Mulcahy + (C) 2016 flabbergast + + 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 MK66F18/kinetis_registry.h + * @brief MK66F18 capabilities registry. + * + * @addtogroup HAL + * @{ + */ + +#ifndef KINETIS_REGISTRY_H_ +#define KINETIS_REGISTRY_H_ + +#if !defined(MK66F18) || defined(__DOXYGEN__) +#define MK66F18 +#endif + +/*===========================================================================*/ +/* Platform capabilities. */ +/*===========================================================================*/ + +/** + * @brief Maximum system and core clock (f_SYS) frequency. + */ +#define KINETIS_SYSCLK_MAX 180000000L + +/** + * @brief Maximum bus clock (f_BUS) frequency. + */ +#define KINETIS_BUSCLK_MAX 60000000L + +/** + * @brief Maximum flash clock (f_FLASH) frequency. + */ +#define KINETIS_FLASHCLK_MAX 28000000L + +/* ADC attributes.*/ +#define KINETIS_HAS_ADC0 TRUE +#define KINETIS_ADC0_IRQ_VECTOR VectorDC +#define KINETIS_HAS_ADC1 TRUE +#define KINETIS_ADC1_IRQ_VECTOR Vector164 + +/* DAC attributes.*/ +#define KINETIS_HAS_DAC0 TRUE +#define KINETIS_DAC0_IRQ_VECTOR Vector120 +#define KINETIS_HAS_DAC1 TRUE +#define KINETIS_DAC1_IRQ_VECTOR Vector160 + +/* DMA attributes.*/ +#define KINETIS_DMA0_IRQ_VECTOR Vector40 +#define KINETIS_DMA1_IRQ_VECTOR Vector44 +#define KINETIS_DMA2_IRQ_VECTOR Vector48 +#define KINETIS_DMA3_IRQ_VECTOR Vector4C +#define KINETIS_DMA4_IRQ_VECTOR Vector50 +#define KINETIS_DMA5_IRQ_VECTOR Vector54 +#define KINETIS_DMA6_IRQ_VECTOR Vector58 +#define KINETIS_DMA7_IRQ_VECTOR Vector5C +#define KINETIS_DMA8_IRQ_VECTOR Vector60 +#define KINETIS_DMA9_IRQ_VECTOR Vector64 +#define KINETIS_DMA10_IRQ_VECTOR Vector68 +#define KINETIS_DMA11_IRQ_VECTOR Vector6C +#define KINETIS_DMA12_IRQ_VECTOR Vector70 +#define KINETIS_DMA13_IRQ_VECTOR Vector74 +#define KINETIS_DMA14_IRQ_VECTOR Vector78 +#define KINETIS_DMA15_IRQ_VECTOR Vector7C +#define KINETIS_HAS_DMA_ERROR_IRQ TRUE +#define KINETIS_DMA_ERROR_IRQ_VECTOR Vector80 + +/* EXT attributes.*/ +#define KINETIS_PORTA_IRQ_VECTOR Vector12C +#define KINETIS_PORTB_IRQ_VECTOR Vector130 +#define KINETIS_PORTC_IRQ_VECTOR Vector134 +#define KINETIS_PORTD_IRQ_VECTOR Vector138 +#define KINETIS_PORTE_IRQ_VECTOR Vector13C +#define KINETIS_EXT_HAS_COMMON_CD_IRQ FALSE +#define KINETIS_EXT_HAS_COMMON_BCDE_IRQ FALSE +#define KINETIS_GPIO_HAS_OPENDRAIN TRUE + +/* I2C attributes.*/ +#define KINETIS_HAS_I2C0 TRUE +#define KINETIS_I2C0_IRQ_VECTOR VectorA0 +#define KINETIS_HAS_I2C1 TRUE +#define KINETIS_I2C1_IRQ_VECTOR VectorA4 + +/* Serial attributes.*/ +#define KINETIS_HAS_SERIAL0 TRUE +#define KINETIS_SERIAL0_IRQ_VECTOR VectorBC +#define KINETIS_HAS_SERIAL1 TRUE +#define KINETIS_SERIAL1_IRQ_VECTOR VectorC4 +#define KINETIS_HAS_SERIAL2 TRUE +#define KINETIS_SERIAL2_IRQ_VECTOR VectorCC +#define KINETIS_HAS_SERIAL3 TRUE +#define KINETIS_SERIAL3_IRQ_VECTOR VectorD4 +#define KINETIS_HAS_SERIAL_ERROR_IRQ TRUE +#define KINETIS_SERIAL0_ERROR_IRQ_VECTOR VectorC0 +#define KINETIS_SERIAL1_ERROR_IRQ_VECTOR VectorC8 +#define KINETIS_SERIAL2_ERROR_IRQ_VECTOR VectorD0 +#define KINETIS_SERIAL3_ERROR_IRQ_VECTOR VectorD8 +#define KINETIS_SERIAL0_IS_LPUART FALSE +#define KINETIS_SERIAL0_IS_UARTLP FALSE +#define KINETIS_SERIAL1_IS_LPUART FALSE +#define KINETIS_SERIAL1_IS_UARTLP FALSE +#define KINETIS_SERIAL2_IS_LPUART FALSE +#define KINETIS_SERIAL2_IS_UARTLP FALSE +#define KINETIS_SERIAL3_IS_LPUART FALSE +#define KINETIS_SERIAL3_IS_UARTLP FALSE + +/* SPI attributes.*/ +#define KINETIS_HAS_SPI0 TRUE +#define KINETIS_SPI0_IRQ_VECTOR VectorA8 +#define KINETIS_HAS_SPI1 TRUE +#define KINETIS_SPI1_IRQ_VECTOR VectorAC + +/* FlexTimer attributes.*/ +#define KINETIS_FTM0_CHANNELS 8 +#define KINETIS_FTM1_CHANNELS 2 +#define KINETIS_FTM2_CHANNELS 2 +#define KINETIS_FTM3_CHANNELS 8 + +#define KINETIS_HAS_FTM0 TRUE +#define KINETIS_FTM0_IRQ_VECTOR VectorE8 +#define KINETIS_HAS_FTM1 TRUE +#define KINETIS_FTM1_IRQ_VECTOR VectorEC +#define KINETIS_HAS_FTM2 TRUE +#define KINETIS_FTM2_IRQ_VECTOR VectorF0 +#define KINETIS_HAS_FTM3 TRUE +#define KINETIS_FTM3_IRQ_VECTOR Vector15C + +/* GPT attributes.*/ +#define KINETIS_HAS_PIT0 TRUE +#define KINETIS_PIT0_IRQ_VECTOR Vector100 +#define KINETIS_HAS_PIT1 TRUE +#define KINETIS_PIT1_IRQ_VECTOR Vector104 +#define KINETIS_HAS_PIT2 TRUE +#define KINETIS_PIT2_IRQ_VECTOR Vector108 +#define KINETIS_HAS_PIT3 TRUE +#define KINETIS_PIT3_IRQ_VECTOR Vector10C +#define KINETIS_HAS_PIT_COMMON_IRQ FALSE + +/* USB attributes.*/ +#define KINETIS_HAS_USB TRUE +#define KINETIS_USB_IRQ_VECTOR Vector114 +#define KINETIS_USB0_IS_USBOTG TRUE +#define KINETIS_HAS_USB_CLOCK_RECOVERY TRUE + +/** @} */ + +#endif /* KINETIS_REGISTRY_H_ */ + +/** @} */ diff --git a/os/hal/ports/KINETIS/MK66F18/platform.dox b/os/hal/ports/KINETIS/MK66F18/platform.dox new file mode 100644 index 0000000..beb8f61 --- /dev/null +++ b/os/hal/ports/KINETIS/MK66F18/platform.dox @@ -0,0 +1,365 @@ +/* + ChibiOS - Copyright (C) 2014-2015 Fabio Utzig + + 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. +*/ + +/* TODO Still need to edit this entire file */ + +/** + * @defgroup MK66FX1M0_DRIVERS MK66FX1M0 Drivers + * @details This section describes all the supported drivers on the MK66FX1M0 + * platform and the implementation details of the single drivers. + * + * @ingroup platforms + */ + +/** + * @defgroup MK66FX1M0_HAL MK66FX1M0 Initialization Support + * @details The MK66FX1M0 HAL support is responsible for system initialization. + * + * @section mk66fx1m0_hal_1 Supported HW resources + * - PLL1. + * - PLL2. + * - RCC. + * - Flash. + * . + * @section mk66fx1m0_hal_2 MK66FX1M0 HAL driver implementation features + * - PLL startup and stabilization. + * - Clock tree initialization. + * - Clock source selection. + * - Flash wait states initialization based on the selected clock options. + * - SYSTICK initialization based on current clock and kernel required rate. + * - DMA support initialization. + * . + * @ingroup MK66FX1M0_DRIVERS + */ + +/** + * @defgroup MK66FX1M0_ADC MK66FX1M0 ADC Support + * @details The MK66FX1M0 ADC driver supports the ADC peripherals using DMA + * channels for maximum performance. + * + * @section mk66fx1m0_adc_1 Supported HW resources + * - ADC1. + * - ADC2. + * - ADC3. + * - DMA2. + * . + * @section mk66fx1m0_adc_2 MK66FX1M0 ADC driver implementation features + * - Clock stop for reduced power usage when the driver is in stop state. + * - Streaming conversion using DMA for maximum performance. + * - Programmable ADC interrupt priority level. + * - Programmable DMA bus priority for each DMA channel. + * - Programmable DMA interrupt priority for each DMA channel. + * - DMA and ADC errors detection. + * . + * @ingroup MK66FX1M0_DRIVERS + */ + +/** + * @defgroup MK66FX1M0_CAN MK66FX1M0 CAN Support + * @details The MK66FX1M0 CAN driver uses the CAN peripherals. + * + * @section mk66fx1m0_can_1 Supported HW resources + * - bxCAN1. + * . + * @section mk66fx1m0_can_2 MK66FX1M0 CAN driver implementation features + * - Clock stop for reduced power usage when the driver is in stop state. + * - Support for bxCAN sleep mode. + * - Programmable bxCAN interrupts priority level. + * . + * @ingroup MK66FX1M0_DRIVERS + */ + +/** + * @defgroup MK66FX1M0_EXT MK66FX1M0 EXT Support + * @details The MK66FX1M0 EXT driver uses the EXTI peripheral. + * + * @section mk66fx1m0_ext_1 Supported HW resources + * - EXTI. + * . + * @section mk66fx1m0_ext_2 MK66FX1M0 EXT driver implementation features + * - Each EXTI channel can be independently enabled and programmed. + * - Programmable EXTI interrupts priority level. + * - Capability to work as event sources (WFE) rather than interrupt sources. + * . + * @ingroup MK66FX1M0_DRIVERS + */ + +/** + * @defgroup MK66FX1M0_GPT MK66FX1M0 GPT Support + * @details The MK66FX1M0 GPT driver uses the TIMx peripherals. + * + * @section mk66fx1m0_gpt_1 Supported HW resources + * - TIM1. + * - TIM2. + * - TIM3. + * - TIM4. + * - TIM5. + * - TIM8. + * . + * @section mk66fx1m0_gpt_2 MK66FX1M0 GPT driver implementation features + * - Each timer can be independently enabled and programmed. Unused + * peripherals are left in low power mode. + * - Programmable TIMx interrupts priority level. + * . + * @ingroup MK66FX1M0_DRIVERS + */ + +/** + * @defgroup MK66FX1M0_ICU MK66FX1M0 ICU Support + * @details The MK66FX1M0 ICU driver uses the TIMx peripherals. + * + * @section mk66fx1m0_icu_1 Supported HW resources + * - TIM1. + * - TIM2. + * - TIM3. + * - TIM4. + * - TIM5. + * - TIM8. + * . + * @section mk66fx1m0_icu_2 MK66FX1M0 ICU driver implementation features + * - Each timer can be independently enabled and programmed. Unused + * peripherals are left in low power mode. + * - Programmable TIMx interrupts priority level. + * . + * @ingroup MK66FX1M0_DRIVERS + */ + +/** + * @defgroup MK66FX1M0_MAC MK66FX1M0 MAC Support + * @details The MK66FX1M0 MAC driver supports the ETH peripheral. + * + * @section mk66fx1m0_mac_1 Supported HW resources + * - ETH. + * - PHY (external). + * . + * @section mk66fx1m0_mac_2 MK66FX1M0 MAC driver implementation features + * - Dedicated DMA operations. + * - Support for checksum off-loading. + * . + * @ingroup MK66FX1M0_DRIVERS + */ + +/** + * @defgroup MK66FX1M0_PAL MK66FX1M0 PAL Support + * @details The MK66FX1M0 PAL driver uses the GPIO peripherals. + * + * @section mk66fx1m0_pal_1 Supported HW resources + * - GPIOA. + * - GPIOB. + * - GPIOC. + * - GPIOD. + * - GPIOE. + * - GPIOF. + * - GPIOG. + * - GPIOH. + * - GPIOI. + * . + * @section mk66fx1m0_pal_2 MK66FX1M0 PAL driver implementation features + * The PAL driver implementation fully supports the following hardware + * capabilities: + * - 16 bits wide ports. + * - Atomic set/reset functions. + * - Atomic set+reset function (atomic bus operations). + * - Output latched regardless of the pad setting. + * - Direct read of input pads regardless of the pad setting. + * . + * @section mk66fx1m0_pal_3 Supported PAL setup modes + * The MK66FX1M0 PAL driver supports the following I/O modes: + * - @p PAL_MODE_RESET. + * - @p PAL_MODE_UNCONNECTED. + * - @p PAL_MODE_INPUT. + * - @p PAL_MODE_INPUT_PULLUP. + * - @p PAL_MODE_INPUT_PULLDOWN. + * - @p PAL_MODE_INPUT_ANALOG. + * - @p PAL_MODE_OUTPUT_PUSHPULL. + * - @p PAL_MODE_OUTPUT_OPENDRAIN. + * - @p PAL_MODE_ALTERNATE (non standard). + * . + * Any attempt to setup an invalid mode is ignored. + * + * @section mk66fx1m0_pal_4 Suboptimal behavior + * The MK66FX1M0 GPIO is less than optimal in several areas, the limitations + * should be taken in account while using the PAL driver: + * - Pad/port toggling operations are not atomic. + * - Pad/group mode setup is not atomic. + * . + * @ingroup MK66FX1M0_DRIVERS + */ + +/** + * @defgroup MK66FX1M0_PWM MK66FX1M0 PWM Support + * @details The MK66FX1M0 PWM driver uses the TIMx peripherals. + * + * @section mk66fx1m0_pwm_1 Supported HW resources + * - TIM1. + * - TIM2. + * - TIM3. + * - TIM4. + * - TIM5. + * - TIM8. + * . + * @section mk66fx1m0_pwm_2 MK66FX1M0 PWM driver implementation features + * - Each timer can be independently enabled and programmed. Unused + * peripherals are left in low power mode. + * - Four independent PWM channels per timer. + * - Programmable TIMx interrupts priority level. + * . + * @ingroup MK66FX1M0_DRIVERS + */ + +/** + * @defgroup MK66FX1M0_SDC MK66FX1M0 SDC Support + * @details The MK66FX1M0 SDC driver uses the SDIO peripheral. + * + * @section mk66fx1m0_sdc_1 Supported HW resources + * - SDIO. + * - DMA2. + * . + * @section mk66fx1m0_sdc_2 MK66FX1M0 SDC driver implementation features + * - Clock stop for reduced power usage when the driver is in stop state. + * - Programmable interrupt priority. + * - DMA is used for receiving and transmitting. + * - Programmable DMA bus priority for each DMA channel. + * . + * @ingroup MK66FX1M0_DRIVERS + */ + +/** + * @defgroup MK66FX1M0_SERIAL MK66FX1M0 Serial Support + * @details The MK66FX1M0 Serial driver uses the USART/UART peripherals in a + * buffered, interrupt driven, implementation. + * + * @section mk66fx1m0_serial_1 Supported HW resources + * The serial driver can support any of the following hardware resources: + * - USART1. + * - USART2. + * - USART3. + * - UART4. + * - UART5. + * - USART6. + * . + * @section mk66fx1m0_serial_2 MK66FX1M0 Serial driver implementation features + * - Clock stop for reduced power usage when the driver is in stop state. + * - Each UART/USART can be independently enabled and programmed. Unused + * peripherals are left in low power mode. + * - Fully interrupt driven. + * - Programmable priority levels for each UART/USART. + * . + * @ingroup MK66FX1M0_DRIVERS + */ + +/** + * @defgroup MK66FX1M0_SPI MK66FX1M0 SPI Support + * @details The SPI driver supports the MK66FX1M0 SPI peripherals using DMA + * channels for maximum performance. + * + * @section mk66fx1m0_spi_1 Supported HW resources + * - SPI1. + * - SPI2. + * - SPI3. + * - DMA1. + * - DMA2. + * . + * @section mk66fx1m0_spi_2 MK66FX1M0 SPI driver implementation features + * - Clock stop for reduced power usage when the driver is in stop state. + * - Each SPI can be independently enabled and programmed. Unused + * peripherals are left in low power mode. + * - Programmable interrupt priority levels for each SPI. + * - DMA is used for receiving and transmitting. + * - Programmable DMA bus priority for each DMA channel. + * - Programmable DMA interrupt priority for each DMA channel. + * - Programmable DMA error hook. + * . + * @ingroup MK66FX1M0_DRIVERS + */ + +/** + * @defgroup MK66FX1M0_UART MK66FX1M0 UART Support + * @details The UART driver supports the MK66FX1M0 USART peripherals using DMA + * channels for maximum performance. + * + * @section mk66fx1m0_uart_1 Supported HW resources + * The UART driver can support any of the following hardware resources: + * - USART1. + * - USART2. + * - USART3. + * - DMA1. + * - DMA2. + * . + * @section mk66fx1m0_uart_2 MK66FX1M0 UART driver implementation features + * - Clock stop for reduced power usage when the driver is in stop state. + * - Each UART/USART can be independently enabled and programmed. Unused + * peripherals are left in low power mode. + * - Programmable interrupt priority levels for each UART/USART. + * - DMA is used for receiving and transmitting. + * - Programmable DMA bus priority for each DMA channel. + * - Programmable DMA interrupt priority for each DMA channel. + * - Programmable DMA error hook. + * . + * @ingroup MK66FX1M0_DRIVERS + */ + +/** + * @defgroup MK66FX1M0_PLATFORM_DRIVERS MK66FX1M0 Platform Drivers + * @details Platform support drivers. Platform drivers do not implement HAL + * standard driver templates, their role is to support platform + * specific functionalities. + * + * @ingroup MK66FX1M0_DRIVERS + */ + +/** + * @defgroup MK66FX1M0_DMA MK66FX1M0 DMA Support + * @details This DMA helper driver is used by the other drivers in order to + * access the shared DMA resources in a consistent way. + * + * @section mk66fx1m0_dma_1 Supported HW resources + * The DMA driver can support any of the following hardware resources: + * - DMA1. + * - DMA2. + * . + * @section mk66fx1m0_dma_2 MK66FX1M0 DMA driver implementation features + * - Exports helper functions/macros to the other drivers that share the + * DMA resource. + * - Automatic DMA clock stop when not in use by any driver. + * - DMA streams and interrupt vectors sharing among multiple drivers. + * . + * @ingroup MK66FX1M0_PLATFORM_DRIVERS + */ + +/** + * @defgroup MK66FX1M0_ISR MK66FX1M0 ISR Support + * @details This ISR helper driver is used by the other drivers in order to + * map ISR names to physical vector names. + * + * @ingroup MK66FX1M0_PLATFORM_DRIVERS + */ + +/** + * @defgroup MK66FX1M0_RCC MK66FX1M0 RCC Support + * @details This RCC helper driver is used by the other drivers in order to + * access the shared RCC resources in a consistent way. + * + * @section mk66fx1m0_rcc_1 Supported HW resources + * - RCC. + * . + * @section mk66fx1m0_rcc_2 MK66FX1M0 RCC driver implementation features + * - Peripherals reset. + * - Peripherals clock enable. + * - Peripherals clock disable. + * . + * @ingroup MK66FX1M0_PLATFORM_DRIVERS + */ diff --git a/os/hal/ports/KINETIS/MK66F18/platform.mk b/os/hal/ports/KINETIS/MK66F18/platform.mk new file mode 100644 index 0000000..d66a31d --- /dev/null +++ b/os/hal/ports/KINETIS/MK66F18/platform.mk @@ -0,0 +1,18 @@ +# List of all platform files. +PLATFORMSRC = ${CHIBIOS}/os/hal/ports/common/ARMCMx/nvic.c \ + ${CHIBIOS_CONTRIB}/os/hal/ports/KINETIS/MK66F18/hal_lld.c \ + ${CHIBIOS_CONTRIB}/os/hal/ports/KINETIS/LLD/hal_pal_lld.c \ + ${CHIBIOS_CONTRIB}/os/hal/ports/KINETIS/LLD/hal_serial_lld.c \ + ${CHIBIOS_CONTRIB}/os/hal/ports/KINETIS/MK66F18/hal_spi_lld.c \ + ${CHIBIOS_CONTRIB}/os/hal/ports/KINETIS/LLD/hal_i2c_lld.c \ + ${CHIBIOS_CONTRIB}/os/hal/ports/KINETIS/LLD/hal_ext_lld.c \ + ${CHIBIOS_CONTRIB}/os/hal/ports/KINETIS/LLD/hal_adc_lld.c \ + ${CHIBIOS_CONTRIB}/os/hal/ports/KINETIS/LLD/hal_gpt_lld.c \ + ${CHIBIOS_CONTRIB}/os/hal/ports/KINETIS/MK66F18/hal_pwm_lld.c \ + ${CHIBIOS_CONTRIB}/os/hal/ports/KINETIS/LLD/hal_st_lld.c \ + ${CHIBIOS_CONTRIB}/os/hal/ports/KINETIS/LLD/hal_usb_lld.c + +# Required include directories +PLATFORMINC = ${CHIBIOS}/os/hal/ports/common/ARMCMx \ + ${CHIBIOS_CONTRIB}/os/hal/ports/KINETIS/MK66F18 \ + ${CHIBIOS_CONTRIB}/os/hal/ports/KINETIS/LLD -- cgit v1.2.3