From 1bf1d2fe8ff006df57f737ddc4273c6f74b96257 Mon Sep 17 00:00:00 2001 From: jturnsek Date: Sun, 12 Feb 2023 10:29:46 +0100 Subject: [PATCH] Adding new board called EdgePro1 based on MIMXRT1064 --- .../ARMCMx/compilers/GCC/ld/MIMXRT1064.ld | 154 ++++ .../compilers/GCC/mk/startup_MIMXRT1064.mk | 19 + .../ARMCMx/devices/MIMXRT1064/cmparams.h | 80 ++ os/hal/boards/EDGEPRO1/board.c | 47 ++ os/hal/boards/EDGEPRO1/board.h | 172 ++++ os/hal/boards/EDGEPRO1/board.mk | 9 + os/hal/ports/MIMXRT1064/LLD/GPIOv1/driver.mk | 9 + .../ports/MIMXRT1064/LLD/GPIOv1/hal_pal_lld.c | 297 +++++++ .../ports/MIMXRT1064/LLD/GPIOv1/hal_pal_lld.h | 316 +++++++ os/hal/ports/MIMXRT1064/LLD/I2Cv1/driver.mk | 16 + .../ports/MIMXRT1064/LLD/I2Cv1/hal_i2c_lld.c | 228 +++++ .../ports/MIMXRT1064/LLD/I2Cv1/hal_i2c_lld.h | 203 +++++ os/hal/ports/MIMXRT1064/LLD/PITv1/driver.mk | 3 + .../ports/MIMXRT1064/LLD/PITv1/hal_gpt_lld.c | 391 +++++++++ .../ports/MIMXRT1064/LLD/PITv1/hal_gpt_lld.h | 333 ++++++++ .../ports/MIMXRT1064/LLD/PITv1/hal_st_lld.c | 109 +++ .../ports/MIMXRT1064/LLD/PITv1/hal_st_lld.h | 156 ++++ os/hal/ports/MIMXRT1064/LLD/UARTv1/driver.mk | 16 + .../MIMXRT1064/LLD/UARTv1/hal_serial_lld.c | 444 ++++++++++ .../MIMXRT1064/LLD/UARTv1/hal_serial_lld.h | 274 ++++++ os/hal/ports/MIMXRT1064/LLD/USBHSv1/driver.mk | 22 + .../MIMXRT1064/LLD/USBHSv1/hal_usb_lld.c | 787 ++++++++++++++++++ .../MIMXRT1064/LLD/USBHSv1/hal_usb_lld.h | 451 ++++++++++ .../LLD/USBHSv1/usb_device_config.h | 178 ++++ .../MIMXRT1064/MIMXRT1064/bootable_image.c | 339 ++++++++ .../MIMXRT1064/MIMXRT1064/clock_config.c | 516 ++++++++++++ .../MIMXRT1064/MIMXRT1064/clock_config.h | 126 +++ os/hal/ports/MIMXRT1064/MIMXRT1064/hal_lld.c | 165 ++++ os/hal/ports/MIMXRT1064/MIMXRT1064/hal_lld.h | 113 +++ .../MIMXRT1064/mimxrt1064_registry.h | 160 ++++ os/hal/ports/MIMXRT1064/MIMXRT1064/mpu.c | 175 ++++ .../ports/MIMXRT1064/MIMXRT1064/platform.dox | 365 ++++++++ .../ports/MIMXRT1064/MIMXRT1064/platform.mk | 39 + .../MIMXRT1064/MIMXRT1064/printf_debug.c | 114 +++ .../MIMXRT1064/MIMXRT1064/printf_debug.h | 13 + 35 files changed, 6839 insertions(+) create mode 100644 os/common/startup/ARMCMx/compilers/GCC/ld/MIMXRT1064.ld create mode 100644 os/common/startup/ARMCMx/compilers/GCC/mk/startup_MIMXRT1064.mk create mode 100644 os/common/startup/ARMCMx/devices/MIMXRT1064/cmparams.h create mode 100644 os/hal/boards/EDGEPRO1/board.c create mode 100644 os/hal/boards/EDGEPRO1/board.h create mode 100644 os/hal/boards/EDGEPRO1/board.mk create mode 100644 os/hal/ports/MIMXRT1064/LLD/GPIOv1/driver.mk create mode 100644 os/hal/ports/MIMXRT1064/LLD/GPIOv1/hal_pal_lld.c create mode 100644 os/hal/ports/MIMXRT1064/LLD/GPIOv1/hal_pal_lld.h create mode 100644 os/hal/ports/MIMXRT1064/LLD/I2Cv1/driver.mk create mode 100644 os/hal/ports/MIMXRT1064/LLD/I2Cv1/hal_i2c_lld.c create mode 100644 os/hal/ports/MIMXRT1064/LLD/I2Cv1/hal_i2c_lld.h create mode 100644 os/hal/ports/MIMXRT1064/LLD/PITv1/driver.mk create mode 100644 os/hal/ports/MIMXRT1064/LLD/PITv1/hal_gpt_lld.c create mode 100644 os/hal/ports/MIMXRT1064/LLD/PITv1/hal_gpt_lld.h create mode 100644 os/hal/ports/MIMXRT1064/LLD/PITv1/hal_st_lld.c create mode 100644 os/hal/ports/MIMXRT1064/LLD/PITv1/hal_st_lld.h create mode 100644 os/hal/ports/MIMXRT1064/LLD/UARTv1/driver.mk create mode 100644 os/hal/ports/MIMXRT1064/LLD/UARTv1/hal_serial_lld.c create mode 100644 os/hal/ports/MIMXRT1064/LLD/UARTv1/hal_serial_lld.h create mode 100644 os/hal/ports/MIMXRT1064/LLD/USBHSv1/driver.mk create mode 100644 os/hal/ports/MIMXRT1064/LLD/USBHSv1/hal_usb_lld.c create mode 100644 os/hal/ports/MIMXRT1064/LLD/USBHSv1/hal_usb_lld.h create mode 100644 os/hal/ports/MIMXRT1064/LLD/USBHSv1/usb_device_config.h create mode 100644 os/hal/ports/MIMXRT1064/MIMXRT1064/bootable_image.c create mode 100644 os/hal/ports/MIMXRT1064/MIMXRT1064/clock_config.c create mode 100644 os/hal/ports/MIMXRT1064/MIMXRT1064/clock_config.h create mode 100644 os/hal/ports/MIMXRT1064/MIMXRT1064/hal_lld.c create mode 100644 os/hal/ports/MIMXRT1064/MIMXRT1064/hal_lld.h create mode 100644 os/hal/ports/MIMXRT1064/MIMXRT1064/mimxrt1064_registry.h create mode 100644 os/hal/ports/MIMXRT1064/MIMXRT1064/mpu.c create mode 100644 os/hal/ports/MIMXRT1064/MIMXRT1064/platform.dox create mode 100644 os/hal/ports/MIMXRT1064/MIMXRT1064/platform.mk create mode 100644 os/hal/ports/MIMXRT1064/MIMXRT1064/printf_debug.c create mode 100644 os/hal/ports/MIMXRT1064/MIMXRT1064/printf_debug.h diff --git a/os/common/startup/ARMCMx/compilers/GCC/ld/MIMXRT1064.ld b/os/common/startup/ARMCMx/compilers/GCC/ld/MIMXRT1064.ld new file mode 100644 index 0000000000..e327bba80d --- /dev/null +++ b/os/common/startup/ARMCMx/compilers/GCC/ld/MIMXRT1064.ld @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2013-2016 Fabio Utzig, http://fabioutzig.com + * (C) 2016 flabbergast + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* + * MIMXRT1064 memory setup. + */ +MEMORY +{ + /* + * The top 64K of flash are unavailable: + * + * 60K are reserved for EEPROM emulation, + * 4K are special read-only memory containing a known-good blink program + * + */ + flash0 : org = 0x70000000, len = 4096K /* FLASH */ + flash1 : org = 0x00000000, len = 0 + flash2 : org = 0x00000000, len = 0 + flash3 : org = 0x00000000, len = 0 + flash4 : org = 0x00000000, len = 0 + flash5 : org = 0x00000000, len = 0 + flash6 : org = 0x00000000, len = 0 + flash7 : org = 0x00000000, len = 0 + + /* NOTE: ram0, ram1 and ram2 can be configured to use various + * percentages of the available 512K of FlexRAM. + * + * The linker script defines each with a 512k size. + * + * That is not safe to do with ChibiOS, where the full size + * of an individual entry (e.g. 512K for ram1) will be used + * in full, e.g. for the heap. + * + * We get around this limitation by allocating all 512K of + * FlexRAM as DTCM (ram1), and not using ram0 and ram2 at all. + * + * See also: + * IMXRT1060RM: Page 36 Table 3-1 System memory map (CM7) + */ + + /* Our startup code configures all of the flexram as DTCM. */ + /* ram0: DTCM, general purpose only + 2000_0000, up to 512KB */ + ram0 : org = 0x20000000, len = 512k + + /* Our startup code does not configure any ram1. */ + /* Possible optimization: copy .text code into ram0 */ + /* ram1: ITCM, can be TCM or general purpose + 0000_0000, up to 512KB */ + /* ram1 : org = 0x00000000, len = 512k */ + ram1 : org = 0x00000000, len = 0 + + /* Our startup code does not configure any ram2. */ + /* ram2: OCRAM (On-Chip RAM), general purpose but not TCM (slower) + 2020_0000 Size: 512KB OCRAM2 */ + /* ram2 : org = 0x20200000, len = 512k */ + ram2 : org = 0x00000000, len = 0 + + ram3 : org = 0x00000000, len = 0 + ram4 : org = 0x00000000, len = 0 + ram5 : org = 0x00000000, len = 0 + ram6 : org = 0x00000000, len = 0 + ram7 : org = 0x00000000, len = 0 +} + +/* Flash region for the configuration bytes.*/ +SECTIONS +{ + .text.progmem : ALIGN(4) + { + . = 0; + KEEP(*(.flashconfig)) + FILL(0xFF) + /* IVT offset is 0x1000 from the bootable image as per section 2.5 + of https://www.nxp.com/docs/en/application-note/AN12107.pdf */ + . = ORIGIN(flash0) + 0x1000; + KEEP(*(.ivt)) + KEEP(*(.bootdata)) + + /* .vectors get placed in rules_code.ld */ + } > flash0 + + .cfmprotect : ALIGN(4) SUBALIGN(4) + { + KEEP(*(.cfmconfig)) + } > flash0 +} + +/* For each data/text section two region are defined, a virtual region + and a load region (_LMA suffix).*/ + +/* Flash region to be used for exception vectors.*/ +REGION_ALIAS("VECTORS_FLASH", flash0); +REGION_ALIAS("VECTORS_FLASH_LMA", flash0); + +/* Flash region to be used for constructors and destructors.*/ +REGION_ALIAS("XTORS_FLASH", flash0); +REGION_ALIAS("XTORS_FLASH_LMA", flash0); + +/* Flash region to be used for code text.*/ +REGION_ALIAS("TEXT_FLASH", flash0); +REGION_ALIAS("TEXT_FLASH_LMA", flash0); + +/* Flash region to be used for read only data.*/ +REGION_ALIAS("RODATA_FLASH", flash0); +REGION_ALIAS("RODATA_FLASH_LMA", flash0); + +/* Flash region to be used for various.*/ +REGION_ALIAS("VARIOUS_FLASH", flash0); +REGION_ALIAS("VARIOUS_FLASH_LMA", flash0); + +/* Flash region to be used for RAM(n) initialization data.*/ +REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0); + +/* RAM region to be used for Main stack. This stack accommodates the processing + of all exceptions and interrupts.*/ +REGION_ALIAS("MAIN_STACK_RAM", ram0); + +/* RAM region to be used for the process stack. This is the stack used by + the main() function.*/ +REGION_ALIAS("PROCESS_STACK_RAM", ram0); + +/* RAM region to be used for data segment.*/ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash0); + +/* RAM region to be used for BSS segment.*/ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Generic rules inclusion.*/ +INCLUDE rules.ld diff --git a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_MIMXRT1064.mk b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_MIMXRT1064.mk new file mode 100644 index 0000000000..97d2f084ee --- /dev/null +++ b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_MIMXRT1064.mk @@ -0,0 +1,19 @@ +# List of the ChibiOS generic MIMXRT1064 startup and CMSIS files. +STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c + +STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.S \ + $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.S + +STARTUPINC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld \ + $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/devices/MIMXRT1064 \ + $(CHIBIOS)/os/common/ext/CMSIS/include \ + $(CHIBIOS)/os/common/ext/ARM/CMSIS/Core/Include \ + $(CHIBIOS_CONTRIB)/os/common/ext/CMSIS/MIMXRT1064 + +STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld +STARTUPLD_CONTRIB = $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/compilers/GCC/ld + +# Shared variables +ALLXASMSRC += $(STARTUPASM) +ALLCSRC += $(STARTUPSRC) +ALLINC += $(STARTUPINC) diff --git a/os/common/startup/ARMCMx/devices/MIMXRT1064/cmparams.h b/os/common/startup/ARMCMx/devices/MIMXRT1064/cmparams.h new file mode 100644 index 0000000000..e29a7fe96e --- /dev/null +++ b/os/common/startup/ARMCMx/devices/MIMXRT1064/cmparams.h @@ -0,0 +1,80 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2014 Giovanni Di Sirio. + (C) 2015 RedoX https://github.com/RedoXyde + (C) 2016 flabbergast + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file GCC/ARMCMx/MK66F18/cmparams.h + * @brief ARM Cortex-M4 parameters for the Kinetis MK66F18. + * + * @defgroup ARMCMx_MK66F18 Kinetis MK66F18 Specific Parameters + * @ingroup ARMCMx_SPECIFIC + * @details This file contains the Cortex-M4 specific parameters for the + * Kinetis MK66F18 platform. + * @{ + */ + +#ifndef _CMPARAMS_H_ +#define _CMPARAMS_H_ + +/** + * @brief Cortex core model. + */ +#define CORTEX_MODEL 7 + +/** + * @brief Systick unit presence. + */ +#define CORTEX_HAS_ST TRUE + +/** + * @brief Floating Point unit presence. + */ +#define CORTEX_HAS_FPU TRUE + +/** + * @brief Number of bits in priority masks. + */ +#define CORTEX_PRIORITY_BITS 4 + +/** + * @brief Number of interrupt vectors. + * @note This number does not include the 16 system vectors and must be + * rounded to a multiple of 8. + */ +#define CORTEX_NUM_VECTORS 160 + +/* The following code is not processed when the file is included from an + asm module.*/ +#if !defined(_FROM_ASM_) + +/* Including the device CMSIS header. Note, we are not using the definitions + from this header because we need this file to be usable also from + assembler source files. We verify that the info matches instead.*/ +#include "MIMXRT1064.h" + +#if CORTEX_PRIORITY_BITS != __NVIC_PRIO_BITS +#error "CMSIS __NVIC_PRIO_BITS mismatch" +#endif + +#endif /* !defined(_FROM_ASM_) */ + +#endif /* _CMPARAMS_H_ */ + +/** @} */ diff --git a/os/hal/boards/EDGEPRO1/board.c b/os/hal/boards/EDGEPRO1/board.c new file mode 100644 index 0000000000..15423d21f6 --- /dev/null +++ b/os/hal/boards/EDGEPRO1/board.c @@ -0,0 +1,47 @@ +/* + 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 = +{ +}; +#endif + +/** + * @brief Early initialization code. + * @details This initialization must be performed just after stack setup + * and before any other initialization. + */ +void __early_init(void) { +} + +void __late_init(void) { + MIMXRT1064_clock_init(); + MIMXRT1064_MPU_init(); +} + +/** + * @brief Board-specific initialization code. + * @todo Add your board-specific code, if any. + */ +void boardInit(void) { +} diff --git a/os/hal/boards/EDGEPRO1/board.h b/os/hal/boards/EDGEPRO1/board.h new file mode 100644 index 0000000000..8f01ff5cb0 --- /dev/null +++ b/os/hal/boards/EDGEPRO1/board.h @@ -0,0 +1,172 @@ +/* + 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 EdgePro1 board. + */ + +/* + * Board identifier. + */ +#define BOARD_EDGEPRO1 +#define BOARD_NAME "EdgePro1" + +/* + * MCU type + */ +#define MIMXRT1064 + +/* + * IO pins assignments. + * + * These come from (with light string replacement from CORE_ to EDGEPRO1_ for + * consistency with the EDGEPRO1 3.6 port): + * https://github.com/PaulStoffregen/cores/blob/master/EDGEPRO14/core_pins.h + * + */ + +// We expose EDGEPRO1 pin numbers +#define EDGEPRO1_PIN0 0 +#define EDGEPRO1_PIN1 1 +#define EDGEPRO1_PIN2 2 +#define EDGEPRO1_PIN3 3 +#define EDGEPRO1_PIN4 4 +#define EDGEPRO1_PIN5 5 +#define EDGEPRO1_PIN6 6 +#define EDGEPRO1_PIN7 7 +#define EDGEPRO1_PIN8 8 +#define EDGEPRO1_PIN9 9 +#define EDGEPRO1_PIN10 10 +#define EDGEPRO1_PIN11 11 +#define EDGEPRO1_PIN12 12 +#define EDGEPRO1_PIN13 13 +#define EDGEPRO1_PIN14 14 +#define EDGEPRO1_PIN15 15 +#define EDGEPRO1_PIN16 16 + + +#define EDGEPRO1_PIN0_BIT 2 +#define EDGEPRO1_PIN1_BIT 3 +#define EDGEPRO1_PIN2_BIT 0 +#define EDGEPRO1_PIN3_BIT 1 +#define EDGEPRO1_PIN4_BIT 13 +#define EDGEPRO1_PIN5_BIT 14 +#define EDGEPRO1_PIN6_BIT 16 +#define EDGEPRO1_PIN7_BIT 15 +#define EDGEPRO1_PIN8_BIT 7 +#define EDGEPRO1_PIN9_BIT 6 +#define EDGEPRO1_PIN10_BIT 10 +#define EDGEPRO1_PIN11_BIT 5 +#define EDGEPRO1_PIN12_BIT 8 +#define EDGEPRO1_PIN13_BIT 9 +#define EDGEPRO1_PIN14_BIT 6 +#define EDGEPRO1_PIN15_BIT 7 +#define EDGEPRO1_PIN16_BIT 4 + + +#define EDGEPRO1_PIN0_IOPORT GPIO7 +#define EDGEPRO1_PIN1_IOPORT GPIO7 +#define EDGEPRO1_PIN2_IOPORT GPIO7 +#define EDGEPRO1_PIN3_IOPORT GPIO7 +#define EDGEPRO1_PIN4_IOPORT GPIO9 +#define EDGEPRO1_PIN5_IOPORT GPIO9 +#define EDGEPRO1_PIN6_IOPORT GPIO9 +#define EDGEPRO1_PIN7_IOPORT GPIO9 +#define EDGEPRO1_PIN8_IOPORT GPIO6 +#define EDGEPRO1_PIN9_IOPORT GPIO6 +#define EDGEPRO1_PIN10_IOPORT GPIO6 +#define EDGEPRO1_PIN11_IOPORT GPIO6 +#define EDGEPRO1_PIN12_IOPORT GPIO6 +#define EDGEPRO1_PIN13_IOPORT GPIO6 +#define EDGEPRO1_PIN14_IOPORT GPIO6 +#define EDGEPRO1_PIN15_IOPORT GPIO6 +#define EDGEPRO1_PIN16_IOPORT GPIO6 + + +// mux config registers control which peripheral uses the pin +#define EDGEPRO1_PIN0_MUX kIOMUXC_SW_MUX_CTL_PAD_GPIO_B0_02 +#define EDGEPRO1_PIN1_MUX kIOMUXC_SW_MUX_CTL_PAD_GPIO_B0_03 +#define EDGEPRO1_PIN2_MUX kIOMUXC_SW_MUX_CTL_PAD_GPIO_B0_00 +#define EDGEPRO1_PIN3_MUX kIOMUXC_SW_MUX_CTL_PAD_GPIO_B0_01 +#define EDGEPRO1_PIN4_MUX kIOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_13 +#define EDGEPRO1_PIN5_MUX kIOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_14 +#define EDGEPRO1_PIN6_MUX kIOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_16 +#define EDGEPRO1_PIN7_MUX kIOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_15 +#define EDGEPRO1_PIN8_MUX kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_07 +#define EDGEPRO1_PIN9_MUX kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_06 +#define EDGEPRO1_PIN10_MUX kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_10 +#define EDGEPRO1_PIN11_MUX kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_05 +#define EDGEPRO1_PIN12_MUX kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_08 +#define EDGEPRO1_PIN13_MUX kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_09 +#define EDGEPRO1_PIN14_MUX kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_06 +#define EDGEPRO1_PIN15_MUX kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_07 +#define EDGEPRO1_PIN16_MUX kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_04 + +// pad config registers control pullup/pulldown/keeper, drive strength, etc +#define EDGEPRO1_PIN0_PAD kIOMUXC_SW_PAD_CTL_PAD_GPIO_B0_02 +#define EDGEPRO1_PIN1_PAD kIOMUXC_SW_PAD_CTL_PAD_GPIO_B0_03 +#define EDGEPRO1_PIN2_PAD kIOMUXC_SW_PAD_CTL_PAD_GPIO_B0_00 +#define EDGEPRO1_PIN3_PAD kIOMUXC_SW_PAD_CTL_PAD_GPIO_B0_01 +#define EDGEPRO1_PIN4_PAD kIOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_13 +#define EDGEPRO1_PIN5_PAD kIOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_14 +#define EDGEPRO1_PIN6_PAD kIOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_16 +#define EDGEPRO1_PIN7_PAD kIOMUXC_SW_PAD_CTL_PAD_GPIO_EMC_15 +#define EDGEPRO1_PIN8_PAD kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_07 +#define EDGEPRO1_PIN9_PAD kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_06 +#define EDGEPRO1_PIN10_PAD kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_10 +#define EDGEPRO1_PIN11_PAD kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_05 +#define EDGEPRO1_PIN12_PAD kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_08 +#define EDGEPRO1_PIN13_PAD kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_09 +#define EDGEPRO1_PIN14_PAD kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_06 +#define EDGEPRO1_PIN15_PAD kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_07 +#define EDGEPRO1_PIN16_PAD kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B0_04 + + +#define LINE_PIN0 PAL_LINE(EDGEPRO1_PIN0_IOPORT, EDGEPRO1_PIN0) +#define LINE_PIN1 PAL_LINE(EDGEPRO1_PIN1_IOPORT, EDGEPRO1_PIN1) +#define LINE_PIN2 PAL_LINE(EDGEPRO1_PIN2_IOPORT, EDGEPRO1_PIN2) +#define LINE_PIN3 PAL_LINE(EDGEPRO1_PIN3_IOPORT, EDGEPRO1_PIN3) +#define LINE_PIN4 PAL_LINE(EDGEPRO1_PIN4_IOPORT, EDGEPRO1_PIN4) +#define LINE_PIN5 PAL_LINE(EDGEPRO1_PIN5_IOPORT, EDGEPRO1_PIN5) +#define LINE_PIN6 PAL_LINE(EDGEPRO1_PIN6_IOPORT, EDGEPRO1_PIN6) +#define LINE_PIN7 PAL_LINE(EDGEPRO1_PIN7_IOPORT, EDGEPRO1_PIN7) +#define LINE_PIN8 PAL_LINE(EDGEPRO1_PIN8_IOPORT, EDGEPRO1_PIN8) +#define LINE_PIN9 PAL_LINE(EDGEPRO1_PIN9_IOPORT, EDGEPRO1_PIN9) +#define LINE_PIN10 PAL_LINE(EDGEPRO1_PIN10_IOPORT, EDGEPRO1_PIN10) +#define LINE_PIN11 PAL_LINE(EDGEPRO1_PIN11_IOPORT, EDGEPRO1_PIN11) +#define LINE_PIN12 PAL_LINE(EDGEPRO1_PIN12_IOPORT, EDGEPRO1_PIN12) +#define LINE_PIN13 PAL_LINE(EDGEPRO1_PIN13_IOPORT, EDGEPRO1_PIN13) +#define LINE_PIN14 PAL_LINE(EDGEPRO1_PIN14_IOPORT, EDGEPRO1_PIN14) +#define LINE_PIN15 PAL_LINE(EDGEPRO1_PIN15_IOPORT, EDGEPRO1_PIN15) +#define LINE_PIN16 PAL_LINE(EDGEPRO1_PIN16_IOPORT, EDGEPRO1_PIN16) + + +#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/EDGEPRO1/board.mk b/os/hal/boards/EDGEPRO1/board.mk new file mode 100644 index 0000000000..22d4392e53 --- /dev/null +++ b/os/hal/boards/EDGEPRO1/board.mk @@ -0,0 +1,9 @@ +# List of all the board related files. +BOARDSRC = ${CHIBIOS_CONTRIB}/os/hal/boards/EDGEPRO1/board.c + +# Required include directories +BOARDINC = ${CHIBIOS_CONTRIB}/os/hal/boards/EDGEPRO1 + +# Shared variables +ALLCSRC += $(BOARDSRC) +ALLINC += $(BOARDINC) diff --git a/os/hal/ports/MIMXRT1064/LLD/GPIOv1/driver.mk b/os/hal/ports/MIMXRT1064/LLD/GPIOv1/driver.mk new file mode 100644 index 0000000000..716a918432 --- /dev/null +++ b/os/hal/ports/MIMXRT1064/LLD/GPIOv1/driver.mk @@ -0,0 +1,9 @@ +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_PAL TRUE,$(HALCONF)),) +PLATFORMSRC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1064/LLD/GPIOv1/hal_pal_lld.c +endif +else +PLATFORMSRC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1064/LLD/GPIOv1/hal_pal_lld.c +endif + +PLATFORMINC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1064/LLD/GPIOv1 diff --git a/os/hal/ports/MIMXRT1064/LLD/GPIOv1/hal_pal_lld.c b/os/hal/ports/MIMXRT1064/LLD/GPIOv1/hal_pal_lld.c new file mode 100644 index 0000000000..28e9e2bfe2 --- /dev/null +++ b/os/hal/ports/MIMXRT1064/LLD/GPIOv1/hal_pal_lld.c @@ -0,0 +1,297 @@ +/* + 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 GPIOv1/hal_pal_lld.c + * @brief PAL subsystem low level driver. + * + * @addtogroup PAL + * @{ + */ + +#include "osal.h" +#include "hal.h" + +#if HAL_USE_PAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +uint8_t bit_by_index[] = + { + EDGEPRO1_PIN0_BIT, + EDGEPRO1_PIN1_BIT, + EDGEPRO1_PIN2_BIT, + EDGEPRO1_PIN3_BIT, + EDGEPRO1_PIN4_BIT, + EDGEPRO1_PIN5_BIT, + EDGEPRO1_PIN6_BIT, + EDGEPRO1_PIN7_BIT, + EDGEPRO1_PIN8_BIT, + EDGEPRO1_PIN9_BIT, + EDGEPRO1_PIN10_BIT, + EDGEPRO1_PIN11_BIT, + EDGEPRO1_PIN12_BIT, + EDGEPRO1_PIN13_BIT, + EDGEPRO1_PIN14_BIT, + EDGEPRO1_PIN15_BIT, + EDGEPRO1_PIN16_BIT, + }; + +uint8_t SW_MUX_CTL_PAD_by_index[] = + { + EDGEPRO1_PIN0_MUX, + EDGEPRO1_PIN1_MUX, + EDGEPRO1_PIN2_MUX, + EDGEPRO1_PIN3_MUX, + EDGEPRO1_PIN4_MUX, + EDGEPRO1_PIN5_MUX, + EDGEPRO1_PIN6_MUX, + EDGEPRO1_PIN7_MUX, + EDGEPRO1_PIN8_MUX, + EDGEPRO1_PIN9_MUX, + EDGEPRO1_PIN10_MUX, + EDGEPRO1_PIN11_MUX, + EDGEPRO1_PIN12_MUX, + EDGEPRO1_PIN13_MUX, + EDGEPRO1_PIN14_MUX, + EDGEPRO1_PIN15_MUX, + EDGEPRO1_PIN16_MUX, + }; + +uint8_t SW_PAD_CTL_PAD_by_index[] = + { + EDGEPRO1_PIN0_PAD, + EDGEPRO1_PIN1_PAD, + EDGEPRO1_PIN2_PAD, + EDGEPRO1_PIN3_PAD, + EDGEPRO1_PIN4_PAD, + EDGEPRO1_PIN5_PAD, + EDGEPRO1_PIN6_PAD, + EDGEPRO1_PIN7_PAD, + EDGEPRO1_PIN8_PAD, + EDGEPRO1_PIN9_PAD, + EDGEPRO1_PIN10_PAD, + EDGEPRO1_PIN11_PAD, + EDGEPRO1_PIN12_PAD, + EDGEPRO1_PIN13_PAD, + EDGEPRO1_PIN14_PAD, + EDGEPRO1_PIN15_PAD, + EDGEPRO1_PIN16_PAD, + }; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Reads a logical state from an I/O pad. + * @note The @ref PAL provides a default software implementation of this + * functionality, implement this function if can optimize it by using + * special hardware functionalities or special coding. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * @return The logical state. + * @retval PAL_LOW low logical state. + * @retval PAL_HIGH high logical state. + * + * @notapi + */ +uint8_t _pal_lld_readpad(ioportid_t port, + uint8_t pad) { + return (port->DR & ((uint32_t) 1 << bit_by_index[pad])) ? PAL_HIGH : PAL_LOW; +} + +/** + * @brief Writes a logical state on an output pad. + * @note This function is not meant to be invoked directly by the + * application code. + * @note The @ref PAL provides a default software implementation of this + * functionality, implement this function if can optimize it by using + * special hardware functionalities or special coding. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * @param[in] bit logical value, the value must be @p PAL_LOW or + * @p PAL_HIGH + * + * @notapi + */ +void _pal_lld_writepad(ioportid_t port, + uint8_t pad, + uint8_t bit) { + if (bit == PAL_HIGH) + port->DR_SET = ((uint32_t) 1 << bit_by_index[pad]); + else + port->DR_CLEAR = ((uint32_t) 1 << bit_by_index[pad]); +} + +void _pal_lld_togglepad(ioportid_t port, + uint8_t pad) { + port->DR_TOGGLE = ((uint32_t) 1 << bit_by_index[pad]); +} + +/** + * @brief Pad mode setup. + * @details This function programs a pad with the specified mode. + * @note The @ref PAL provides a default software implementation of this + * functionality, implement this function if can optimize it by using + * special hardware functionalities or special coding. + * @note Programming an unknown or unsupported mode is silently ignored. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * @param[in] mode pad mode + * + * @notapi + */ +void _pal_lld_setpadmode(ioportid_t port, + uint8_t pad, + iomode_t mode) { + osalDbgAssert(pad < PADS_PER_PORT, "pal_lld_setpadmode() #1, invalid pad"); + + // see IMXRT1060RM Section 12.4.3 GPIO programming + + // Interrupt Mask Register (IMR) + port->IMR &= ~((uint32_t) 1 << bit_by_index[pad]); + + // All GPIOs are on mode ALT5 as per Chapter 10, External Signals and Pin Multiplexing, Table 10-1 + const int altMode = 5; + + switch (mode) { + case PAL_MODE_RESET: + case PAL_MODE_INPUT: + case PAL_MODE_OUTPUT_PUSHPULL: + IOMUXC->SW_MUX_CTL_PAD[SW_MUX_CTL_PAD_by_index[pad]] = + PIN_MUX_ALTERNATIVE(altMode); + // need to always set PAD_CTL in case the pin was configured as input before + IOMUXC->SW_PAD_CTL_PAD[SW_PAD_CTL_PAD_by_index[pad]] = + IOMUXC_SW_PAD_CTL_PAD_DSE(6); + //IOMUXC->SW_PAD_CTL_PAD[SW_PAD_CTL_PAD_by_index[pad]] = 0; + break; + + case PAL_MODE_OUTPUT_OPENDRAIN: + IOMUXC->SW_MUX_CTL_PAD[SW_MUX_CTL_PAD_by_index[pad]] = + PIN_MUX_ALTERNATIVE(altMode); + IOMUXC->SW_PAD_CTL_PAD[SW_PAD_CTL_PAD_by_index[pad]] = + IOMUXC_SW_PAD_CTL_PAD_ODE(1); /* Open Drain Enable */ + break; + + case PAL_MODE_INPUT_PULLUP: + IOMUXC->SW_MUX_CTL_PAD[SW_MUX_CTL_PAD_by_index[pad]] = + PIN_MUX_ALTERNATIVE(altMode); + + IOMUXC->SW_PAD_CTL_PAD[SW_PAD_CTL_PAD_by_index[pad]] = + IOMUXC_SW_PAD_CTL_PAD_PKE(1) | /* Pull/Keep Enable */ + IOMUXC_SW_PAD_CTL_PAD_PUS(1) | /* Pull Up/Down Config: 47k pull up */ + IOMUXC_SW_PAD_CTL_PAD_PUE(1); /* Pull/Keep Select: pull */ + + break; + + case PAL_MODE_INPUT_PULLDOWN: + IOMUXC->SW_MUX_CTL_PAD[SW_MUX_CTL_PAD_by_index[pad]] = + PIN_MUX_ALTERNATIVE(altMode); + + IOMUXC->SW_PAD_CTL_PAD[SW_PAD_CTL_PAD_by_index[pad]] = + IOMUXC_SW_PAD_CTL_PAD_PKE(1) | /* Pull/Keep Enable */ + IOMUXC_SW_PAD_CTL_PAD_PUS(0) | /* Pull Up/Down Config: 100k pull dn */ + IOMUXC_SW_PAD_CTL_PAD_PUE(1); /* Pull/Keep Select: pull */ + break; + + case PAL_MODE_UNCONNECTED: + case PAL_MODE_INPUT_ANALOG: + IOMUXC->SW_MUX_CTL_PAD[SW_MUX_CTL_PAD_by_index[pad]] = + PIN_MUX_ALTERNATIVE(altMode); + break; + + case PAL_MODE_ALTERNATIVE_1: + IOMUXC->SW_MUX_CTL_PAD[SW_MUX_CTL_PAD_by_index[pad]] = + PIN_MUX_ALTERNATIVE(1); + break; + + case PAL_MODE_ALTERNATIVE_2: + IOMUXC->SW_MUX_CTL_PAD[SW_MUX_CTL_PAD_by_index[pad]] = + PIN_MUX_ALTERNATIVE(2); + break; + + case PAL_MODE_ALTERNATIVE_3: + IOMUXC->SW_MUX_CTL_PAD[SW_MUX_CTL_PAD_by_index[pad]] = + PIN_MUX_ALTERNATIVE(3); + break; + + case PAL_MODE_ALTERNATIVE_4: + IOMUXC->SW_MUX_CTL_PAD[SW_MUX_CTL_PAD_by_index[pad]] = + PIN_MUX_ALTERNATIVE(4); + break; + + case PAL_MODE_ALTERNATIVE_5: + IOMUXC->SW_MUX_CTL_PAD[SW_MUX_CTL_PAD_by_index[pad]] = + PIN_MUX_ALTERNATIVE(5); + break; + + case PAL_MODE_ALTERNATIVE_6: + IOMUXC->SW_MUX_CTL_PAD[SW_MUX_CTL_PAD_by_index[pad]] = + PIN_MUX_ALTERNATIVE(6); + break; + + case PAL_MODE_ALTERNATIVE_7: + IOMUXC->SW_MUX_CTL_PAD[SW_MUX_CTL_PAD_by_index[pad]] = + PIN_MUX_ALTERNATIVE(7); + break; + } + + // GPIO direction register (GDIR) + if (mode == PAL_MODE_OUTPUT_PUSHPULL) { + port->GDIR |= ((uint32_t) 1 << bit_by_index[pad]); + } else { + port->GDIR &= ~((uint32_t) 1 << bit_by_index[pad]); + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief MIMXRT1064 I/O ports configuration. + * + * @param[in] config the MIMXRT1064 ports configuration + * + * @notapi + */ +void _pal_lld_init(const PALConfig *config) { + (void)config; + /* Clocks are already enabled because MIMXRT1064_clock_init() enables GPIO + earlier in the boot. */ +} + +#endif /* HAL_USE_PAL */ + +/** @} */ diff --git a/os/hal/ports/MIMXRT1064/LLD/GPIOv1/hal_pal_lld.h b/os/hal/ports/MIMXRT1064/LLD/GPIOv1/hal_pal_lld.h new file mode 100644 index 0000000000..bdecaed4af --- /dev/null +++ b/os/hal/ports/MIMXRT1064/LLD/GPIOv1/hal_pal_lld.h @@ -0,0 +1,316 @@ +/* + 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 GPIOv1/hal_pal_lld.h + * @brief PAL subsystem low level driver header. + * + * @addtogroup PAL + * @{ + */ + +#ifndef HAL_PAL_LLD_H_ +#define HAL_PAL_LLD_H_ + +#if HAL_USE_PAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Unsupported modes and specific modes */ +/*===========================================================================*/ + +#define PAL_MODE_ALTERNATIVE_1 0x10 +#define PAL_MODE_ALTERNATIVE_2 0x11 +#define PAL_MODE_ALTERNATIVE_3 0x12 +#define PAL_MODE_ALTERNATIVE_4 0x13 +#define PAL_MODE_ALTERNATIVE_5 0x14 +#define PAL_MODE_ALTERNATIVE_6 0x15 +#define PAL_MODE_ALTERNATIVE_7 0x16 + +#define PIN_MUX_ALTERNATIVE(x) IOMUXC_SW_MUX_CTL_PAD_MUX_MODE(x) + +/*===========================================================================*/ +/* I/O Ports Types and constants. */ +/*===========================================================================*/ + +#define TOTAL_PORTS 9 +#define PADS_PER_PORT 32 + +/** + * @brief Width, in bits, of an I/O port. + */ +#define PAL_IOPORTS_WIDTH 32 + +/** + * @brief Whole port mask. + * @brief This macro specifies all the valid bits into a port. + */ +#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFFFFFF) + +/** + * @brief Digital I/O port sized unsigned type. + */ +typedef uint32_t ioportmask_t; + +/** + * @brief Digital I/O modes. + */ +typedef uint32_t iomode_t; + +/** + * @brief Type of an I/O line. + */ +typedef uint32_t ioline_t; + +/** + * @brief Port Identifier. + * @details This type can be a scalar or some kind of pointer, do not make + * any assumption about it, use the provided macros when populating + * variables of this type. + */ +typedef GPIO_Type *ioportid_t; + +/** + * @brief Type of an pad identifier. + */ +typedef uint32_t iopadid_t; + +/** + * @brief Generic I/O ports static initializer. + * @details An instance of this structure must be passed to @p palInit() at + * system startup time in order to initialized the digital I/O + * subsystem. This represents only the initial setup, specific pads + * or whole ports can be reprogrammed at later time. + * @note Implementations may extend this structure to contain more, + * architecture dependent, fields. + */ +typedef struct { +} PALConfig; + +/*===========================================================================*/ +/* I/O Ports Identifiers. */ +/*===========================================================================*/ + +/** + * @brief GPIO1 identifier. + */ +#define IOPORT1 GPIO1 + +/** + * @brief GPIO2 identifier. + */ +#define IOPORT2 GPIO2 + +/** + * @brief GPIO3 identifier. + */ +#define IOPORT3 GPIO3 + +/** + * @brief GPIO4 identifier. + */ +#define IOPORT4 GPIO4 + +/** + * @brief GPIO5 identifier. + */ +#define IOPORT5 GPIO5 + +/** + * @brief GPIO6 identifier. + */ +#define IOPORT6 GPIO6 + +/** + * @brief GPIO7 identifier. + */ +#define IOPORT7 GPIO7 + +/** + * @brief GPIO8 identifier. + */ +#define IOPORT8 GPIO8 + +/** + * @brief GPIO9 identifier. + */ +#define IOPORT9 GPIO9 + +/** + * @name Line handling macros + * @{ + */ +/** + * @brief Forms a line identifier. + * @details A port/pad pair are encoded into an @p ioline_t type. The encoding + * of this type is platform-dependent. + * @note In this driver the pad number is encoded in the byte of the GPIO + * address that's zero on all Kinetis devices. + */ +#define PAL_LINE(port, pad) \ + ((ioline_t)((uint32_t)(port) | ((uint32_t)(pad)))) + +/** + * @brief Decodes a port identifier from a line identifier. + * @note The GPIOn base addresses follow the division of port/pad + * and must match the division used in PAL_PORT and PAL_PAD. + */ +#define PAL_PORT(line) \ + ((GPIO_Type *)(((uint32_t)(line)) & 0xFFFFF000U)) + +/** + * @brief Decodes a pad identifier from a line identifier. + * @note The GPIOn base addresses follow the division of port/pad + * and must match the division used in PAL_PORT and PAL_PAD. + */ +#define PAL_PAD(line) \ + ((uint32_t)((uint32_t)(line) & 0x00000FFFU)) + +/** + * @brief Value identifying an invalid line. + */ +#define PAL_NOLINE 0U +/** @} */ + +/*===========================================================================*/ +/* Implementation, some of the following macros could be implemented as */ +/* functions, if so please put them in pal_lld.c. */ +/*===========================================================================*/ + +/** + * @brief Low level PAL subsystem initialization. + * + * @param[in] config architecture-dependent ports configuration + * + * @notapi + */ +#define pal_lld_init(config) _pal_lld_init(config) + +/** + * @brief Reads a logical state from an I/O pad. + * @note The @ref PAL provides a default software implementation of this + * functionality, implement this function if can optimize it by using + * special hardware functionalities or special coding. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * @return The logical state. + * @retval PAL_LOW low logical state. + * @retval PAL_HIGH high logical state. + * + * @notapi + */ +#define pal_lld_readpad(port, pad) _pal_lld_readpad(port, pad) + +/** + * @brief Writes a logical state on an output pad. + * @note This function is not meant to be invoked directly by the + * application code. + * @note The @ref PAL provides a default software implementation of this + * functionality, implement this function if can optimize it by using + * special hardware functionalities or special coding. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * @param[in] bit logical value, the value must be @p PAL_LOW or + * @p PAL_HIGH + * + * @notapi + */ +#define pal_lld_writepad(port, pad, bit) _pal_lld_writepad(port, pad, bit) + +/** + * @brief Sets a pad logical state to @p PAL_HIGH. + * @note The @ref PAL provides a default software implementation of this + * functionality, implement this function if can optimize it by using + * special hardware functionalities or special coding. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * + * @notapi + */ +#define pal_lld_setpad(port, pad) _pal_lld_writepad(port, pad, PAL_HIGH) + +/** + * @brief Clears a pad logical state to @p PAL_LOW. + * @note The @ref PAL provides a default software implementation of this + * functionality, implement this function if can optimize it by using + * special hardware functionalities or special coding. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * + * @notapi + */ +#define pal_lld_clearpad(port, pad) _pal_lld_writepad(port, pad, PAL_LOW) + +/** + * @brief Toggles a pad logical state. + * @note The @ref PAL provides a default software implementation of this + * functionality, implement this function if can optimize it by using + * special hardware functionalities or special coding. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * + * @notapi + */ +#define pal_lld_togglepad(port, pad) _pal_lld_togglepad(port, pad) + +/** + * @brief Pad mode setup. + * @details This function programs a pad with the specified mode. + * @note The @ref PAL provides a default software implementation of this + * functionality, implement this function if can optimize it by using + * special hardware functionalities or special coding. + * @note Programming an unknown or unsupported mode is silently ignored. + * + * @param[in] port port identifier + * @param[in] pad pad number within the port + * @param[in] mode pad mode + * + * @notapi + */ +#define pal_lld_setpadmode(port, pad, mode) \ + _pal_lld_setpadmode(port, pad, mode) + +#if !defined(__DOXYGEN__) +extern const PALConfig pal_default_config; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void _pal_lld_init(const PALConfig *config); + void _pal_lld_setpadmode(ioportid_t port, + uint8_t pad, + iomode_t mode); + uint8_t _pal_lld_readpad(ioportid_t port, + uint8_t pad); + void _pal_lld_writepad(ioportid_t port, + uint8_t pad, + uint8_t bit); + void _pal_lld_togglepad(ioportid_t port, + uint8_t pad); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_PAL */ + +#endif /* HAL_PAL_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/MIMXRT1064/LLD/I2Cv1/driver.mk b/os/hal/ports/MIMXRT1064/LLD/I2Cv1/driver.mk new file mode 100644 index 0000000000..d5b60fab0d --- /dev/null +++ b/os/hal/ports/MIMXRT1064/LLD/I2Cv1/driver.mk @@ -0,0 +1,16 @@ +I2CSRC = ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1064/LLD/I2Cv1/hal_i2c_lld.c \ + ${CHIBIOS_CONTRIB}/ext/mcux-sdk/drivers/lpi2c/fsl_lpi2c.c \ + ${CHIBIOS_CONTRIB}/ext/mcux-sdk/devices/MIMXRT1064/drivers/fsl_clock.c + +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) +PLATFORMSRC_CONTRIB += $(I2CSRC) +endif +else +PLATFORMSRC_CONTRIB += $(I2CSRC) +endif + +PLATFORMINC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1064/LLD/I2Cv1 \ + ${CHIBIOS_CONTRIB}/ext/mcux-sdk/drivers/common \ + ${CHIBIOS_CONTRIB}/ext/mcux-sdk/drivers/lpi2c \ + ${CHIBIOS_CONTRIB}/ext/mcux-sdk/devices/MIMXRT1064 diff --git a/os/hal/ports/MIMXRT1064/LLD/I2Cv1/hal_i2c_lld.c b/os/hal/ports/MIMXRT1064/LLD/I2Cv1/hal_i2c_lld.c new file mode 100644 index 0000000000..0be7649bfb --- /dev/null +++ b/os/hal/ports/MIMXRT1064/LLD/I2Cv1/hal_i2c_lld.c @@ -0,0 +1,228 @@ +/* + 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 I2Cv1/hal_i2c_lld.c + * @brief LPI2C subsystem low level driver source. + * + * @addtogroup I2C + * @{ + */ + +#include "osal.h" +#include "hal.h" + +#include "fsl_lpi2c.h" + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief I2C3 driver identifier. + */ +#if MIMXRT1064_I2C_USE_I2C3 || defined(__DOXYGEN__) +I2CDriver I2CD1; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level I2C driver initialization. + * + * @notapi + */ +void i2c_lld_init(void) { + +#if MIMXRT1064_I2C_USE_I2C3 + i2cObjectInit(&I2CD1); + I2CD1.thread = NULL; + I2CD1.i2c.lpi2c_p = LPI2C3; +#endif + +} + +/** + * @brief Configures and activates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +void i2c_lld_start(I2CDriver *i2cp) { + + if (i2cp->state == I2C_STOP) { + +#if MIMXRT1064_I2C_USE_I2C3 + if (&I2CD1 == i2cp) { + lpi2c_master_config_t masterConfig = {0}; + + IOMUXC->SW_MUX_CTL_PAD[kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_06] = IOMUXC_SW_MUX_CTL_PAD_SION(1) | PIN_MUX_ALTERNATIVE(1); + IOMUXC->SW_MUX_CTL_PAD[kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_07] = IOMUXC_SW_MUX_CTL_PAD_SION(1) | PIN_MUX_ALTERNATIVE(1); + + IOMUXC->SW_PAD_CTL_PAD[kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_06] = IOMUXC_SW_PAD_CTL_PAD_ODE(1) | IOMUXC_SW_PAD_CTL_PAD_SPEED(1) | IOMUXC_SW_PAD_CTL_PAD_DSE(7); + IOMUXC->SW_PAD_CTL_PAD[kIOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_07] = IOMUXC_SW_PAD_CTL_PAD_ODE(1) | IOMUXC_SW_PAD_CTL_PAD_SPEED(1) | IOMUXC_SW_PAD_CTL_PAD_DSE(7); + + IOMUXC->SELECT_INPUT[kIOMUXC_LPI2C3_SCL_SELECT_INPUT] = IOMUXC_SELECT_INPUT_DAISY(2); + IOMUXC->SELECT_INPUT[kIOMUXC_LPI2C3_SDA_SELECT_INPUT] = IOMUXC_SELECT_INPUT_DAISY(2); + + + /* + * lpi2cConfig.debugEnable = false; + * lpi2cConfig.ignoreAck = false; + * lpi2cConfig.pinConfig = kLPI2C_2PinOpenDrain; + * lpi2cConfig.baudRate_Hz = 100000U; + * lpi2cConfig.busIdleTimeout_ns = 0; + * lpi2cConfig.pinLowTimeout_ns = 0; + * lpi2cConfig.sdaGlitchFilterWidth_ns = 0; + * lpi2cConfig.sclGlitchFilterWidth_ns = 0; + */ + LPI2C_MasterGetDefaultConfig(&masterConfig); + //masterConfig.baudRate_Hz = 400000U; + LPI2C_MasterInit(i2cp->i2c.lpi2c_p, &masterConfig, 60000000U); + + } +#endif + + } + +} + +/** + * @brief Deactivates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +void i2c_lld_stop(I2CDriver *i2cp) { + + if (i2cp->state != I2C_STOP) { + +#if MIMXRT1064_I2C_USE_I2C3 + if (&I2CD1 == i2cp) { + LPI2C_MasterDeinit(i2cp->i2c.lpi2c_p); + } +#endif + + } +} + +/** + * @brief Receives data via the I2C bus as master. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address + * @param[out] rxbuf pointer to the receive buffer + * @param[in] rxbytes number of bytes to be received + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a + * timeout the driver must be stopped and restarted + * because the bus is in an uncertain state. + * + * @notapi + */ +msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout) { + lpi2c_master_transfer_t xfer; + status_t ret; + + xfer.flags = kLPI2C_TransferDefaultFlag; + xfer.slaveAddress = addr; + xfer.direction = kLPI2C_Read; + xfer.subaddress = 0; + xfer.subaddressSize = 0; + xfer.data = rxbuf; + xfer.dataSize = rxbytes; + + ret = LPI2C_MasterTransferBlocking(i2cp->i2c.lpi2c_p, &xfer); + if (ret != kStatus_Success) { + return MSG_RESET; + } + + return MSG_OK; +} + +/** + * @brief Transmits data via the I2C bus as master. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address + * @param[in] txbuf pointer to the transmit buffer + * @param[in] txbytes number of bytes to be transmitted + * @param[out] rxbuf pointer to the receive buffer + * @param[in] rxbytes number of bytes to be received + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a + * timeout the driver must be stopped and restarted + * because the bus is in an uncertain state. + * + * @notapi + */ +msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, + const uint8_t *txbuf, size_t txbytes, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout) { + lpi2c_master_transfer_t xfer; + status_t ret; + + xfer.flags = kLPI2C_TransferDefaultFlag; + xfer.slaveAddress = addr; + xfer.direction = kLPI2C_Write; + xfer.subaddress = 0; + xfer.subaddressSize = 0; + xfer.data = (void *)txbuf; + xfer.dataSize = txbytes; + + ret = LPI2C_MasterTransferBlocking(i2cp->i2c.lpi2c_p, &xfer); + if (ret != kStatus_Success) { + return MSG_RESET; + } + + return MSG_OK; +} + +#endif /* HAL_USE_I2C */ + +/** @} */ diff --git a/os/hal/ports/MIMXRT1064/LLD/I2Cv1/hal_i2c_lld.h b/os/hal/ports/MIMXRT1064/LLD/I2Cv1/hal_i2c_lld.h new file mode 100644 index 0000000000..eb43834d7b --- /dev/null +++ b/os/hal/ports/MIMXRT1064/LLD/I2Cv1/hal_i2c_lld.h @@ -0,0 +1,203 @@ +/* + 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 I2Cv1/hal_i2c_lld.h + * @brief LPI2C subsystem low level driver header. + * + * @addtogroup I2C + * @{ + */ + +#ifndef HAL_I2C_LLD_H_ +#define HAL_I2C_LLD_H_ + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +#include "fsl_lpi2c.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief I2C3 driver enable switch. + * @details If set to @p TRUE the support for I2C3 is included. + * @note The default is @p FALSE. + */ +#if !defined(MIMXRT1064_I2C_USE_I2C3) || defined(__DOXYGEN__) +#define MIMXRT1064_I2C_USE_I2C3 FALSE +#endif + +/** @} */ + +/** + * @brief I2C3 interrupt priority level setting. + */ +#if !defined(MIMXRT1064_I2C_I2C3_PRIORITY) || defined(__DOXYGEN__) +#define MIMXRT1064_I2C_I2C3_PRIORITY 12 +#endif + +/** + * @brief Timeout for external clearing BUSY bus (in ms). + */ +#if !defined(MIMXRT1064_I2C_BUSY_TIMEOUT) || defined(__DOXYGEN__) +#define MIMXRT1064_I2C_BUSY_TIMEOUT 50 +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/** @brief error checks */ +#if MIMXRT1064_I2C_USE_I2C3 && !MIMXRT1064_HAS_I2C3 +#error "I2C3 not present in the selected device" +#endif + +#if !(MIMXRT1064_I2C_USE_I2C3) +#error "I2C driver activated but no I2C peripheral assigned" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/* @brief Type representing I2C address. */ +typedef uint8_t i2caddr_t; + +/* @brief Type of I2C Driver condition flags. */ +typedef uint32_t i2cflags_t; + +/** + * @brief Driver configuration structure. + */ +typedef struct { + + /* @brief Clock to be used for the I2C bus. */ + uint32_t clock; + +} I2CConfig; + +/** + * @brief Driver configuration structure. + * @note Implementations may extend this structure to contain more, + * architecture dependent, fields. + */ + +/** + * @brief Generic LPI2C register structure. + * @note Individual LPI2C register blocks (even within the same chip) can differ. + */ + +typedef struct { + LPI2C_Type *lpi2c_p; + lpi2c_master_handle_t handle; +} LPI2C_w_TypeDef; + +/** + * @brief Type of a structure representing an I2C driver. + */ +typedef struct I2CDriver I2CDriver; + +/** + * @brief Structure representing an I2C driver. + */ +struct I2CDriver { + /** + * @brief Driver state. + */ + i2cstate_t state; + + /** + * @brief Current configuration data. + */ + const I2CConfig *config; + + /** + * @brief Error flags. + */ + i2cflags_t errors; +#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) + /** + * @brief Mutex protecting the bus. + */ + mutex_t mutex; +#endif /* I2C_USE_MUTUAL_EXCLUSION */ +#if defined(I2C_DRIVER_EXT_FIELDS) + I2C_DRIVER_EXT_FIELDS +#endif + /* @brief Thread waiting for I/O completion. */ + thread_reference_t thread; + + /* @brief Low-level register access. */ + LPI2C_w_TypeDef i2c; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Get errors from I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_get_errors(i2cp) ((i2cp)->errors) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) + +#if MIMXRT1064_I2C_USE_I2C3 +extern I2CDriver I2CD1; +#endif + +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void i2c_lld_init(void); + void i2c_lld_start(I2CDriver *i2cp); + void i2c_lld_stop(I2CDriver *i2cp); + msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, + const uint8_t *txbuf, size_t txbytes, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout); + msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_I2C */ + +#endif /* HAL_I2C_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/MIMXRT1064/LLD/PITv1/driver.mk b/os/hal/ports/MIMXRT1064/LLD/PITv1/driver.mk new file mode 100644 index 0000000000..64661fdd81 --- /dev/null +++ b/os/hal/ports/MIMXRT1064/LLD/PITv1/driver.mk @@ -0,0 +1,3 @@ +PLATFORMSRC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1064/LLD/PITv1/hal_st_lld.c + +PLATFORMINC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1064/LLD/PITv1 diff --git a/os/hal/ports/MIMXRT1064/LLD/PITv1/hal_gpt_lld.c b/os/hal/ports/MIMXRT1064/LLD/PITv1/hal_gpt_lld.c new file mode 100644 index 0000000000..36699371f3 --- /dev/null +++ b/os/hal/ports/MIMXRT1064/LLD/PITv1/hal_gpt_lld.c @@ -0,0 +1,391 @@ +/* + ChibiOS - Copyright (C) 2014 Derek Mulcahy + + 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 PITv1/hal_gpt_lld.c + * @brief KINETIS GPT subsystem low level driver source. + * + * @addtogroup GPT + * @{ + */ + +#include "hal.h" + +#if HAL_USE_GPT || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief GPTD1 driver identifier. + * @note The driver GPTD1 allocates the complex timer PIT0 when enabled. + */ +#if KINETIS_GPT_USE_PIT0 || defined(__DOXYGEN__) +GPTDriver GPTD1; +#endif + +/** + * @brief GPTD2 driver identifier. + * @note The driver GPTD2 allocates the timer PIT1 when enabled. + */ +#if KINETIS_GPT_USE_PIT1 || defined(__DOXYGEN__) +GPTDriver GPTD2; +#endif + +/** + * @brief GPTD3 driver identifier. + * @note The driver GPTD3 allocates the timer PIT2 when enabled. + */ +#if KINETIS_GPT_USE_PIT2 || defined(__DOXYGEN__) +GPTDriver GPTD3; +#endif + +/** + * @brief GPTD4 driver identifier. + * @note The driver GPTD4 allocates the timer PIT3 when enabled. + */ +#if KINETIS_GPT_USE_PIT3 || defined(__DOXYGEN__) +GPTDriver GPTD4; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +#if KINETIS_HAS_PIT_COMMON_IRQ +static uint8_t active_channels = 0; +#endif /* KINETIS_HAS_PIT_COMMON_IRQ */ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Shared IRQ handler. + * + * @param[in] gptp pointer to a @p GPTDriver object + */ +static void gpt_lld_serve_interrupt(GPTDriver *gptp) { + + /* Clear the interrupt */ + gptp->channel->TFLG |= PIT_TFLGn_TIF; + + if (gptp->state == GPT_ONESHOT) { + gptp->state = GPT_READY; /* Back in GPT_READY state. */ + gpt_lld_stop_timer(gptp); /* Timer automatically stopped. */ + } + gptp->config->callback(gptp); +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if !KINETIS_HAS_PIT_COMMON_IRQ + +#if KINETIS_GPT_USE_PIT0 +/** + * @brief PIT1 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(KINETIS_PIT0_IRQ_VECTOR) { + OSAL_IRQ_PROLOGUE(); + gpt_lld_serve_interrupt(&GPTD1); + OSAL_IRQ_EPILOGUE(); +} +#endif /* KINETIS_GPT_USE_PIT0 */ + +#if KINETIS_GPT_USE_PIT1 +/** + * @brief PIT1 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(KINETIS_PIT1_IRQ_VECTOR) { + OSAL_IRQ_PROLOGUE(); + gpt_lld_serve_interrupt(&GPTD2); + OSAL_IRQ_EPILOGUE(); +} +#endif /* KINETIS_GPT_USE_PIT1 */ + +#if KINETIS_GPT_USE_PIT2 +/** + * @brief PIT2 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(KINETIS_PIT2_IRQ_VECTOR) { + OSAL_IRQ_PROLOGUE(); + gpt_lld_serve_interrupt(&GPTD3); + OSAL_IRQ_EPILOGUE(); +} +#endif /* KINETIS_GPT_USE_PIT2 */ + +#if KINETIS_GPT_USE_PIT3 +/** + * @brief PIT3 interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(KINETIS_PIT3_IRQ_VECTOR) { + OSAL_IRQ_PROLOGUE(); + gpt_lld_serve_interrupt(&GPTD4); + OSAL_IRQ_EPILOGUE(); +} +#endif /* KINETIS_GPT_USE_PIT3 */ + +#else /* !KINETIS_HAS_PIT_COMMON_IRQ */ +/** + * @brief Common PIT interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(KINETIS_PIT_IRQ_VECTOR) { + OSAL_IRQ_PROLOGUE(); +#if KINETIS_GPT_USE_PIT0 + if(GPTD1.channel->TFLG & PIT_TFLGn_TIF) + gpt_lld_serve_interrupt(&GPTD1); +#endif /* KINETIS_GPT_USE_PIT0 */ +#if KINETIS_GPT_USE_PIT1 + if(GPTD2.channel->TFLG & PIT_TFLGn_TIF) + gpt_lld_serve_interrupt(&GPTD2); +#endif /* KINETIS_GPT_USE_PIT1 */ +#if KINETIS_GPT_USE_PIT2 + if(GPTD3.channel->TFLG & PIT_TFLGn_TIF) + gpt_lld_serve_interrupt(&GPTD3); +#endif /* KINETIS_GPT_USE_PIT2 */ +#if KINETIS_GPT_USE_PIT3 + if(GPTD4.channel->TFLG & PIT_TFLGn_TIF) + gpt_lld_serve_interrupt(&GPTD4); +#endif /* KINETIS_GPT_USE_PIT3 */ + OSAL_IRQ_EPILOGUE(); +} + +#endif /* !KINETIS_HAS_PIT_COMMON_IRQ */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level GPT driver initialization. + * + * @notapi + */ +void gpt_lld_init(void) { + +#if KINETIS_GPT_USE_PIT0 + /* Driver initialization.*/ + GPTD1.channel = &PIT->CHANNEL[0]; + gptObjectInit(&GPTD1); +#endif + +#if KINETIS_GPT_USE_PIT1 + /* Driver initialization.*/ + GPTD2.channel = &PIT->CHANNEL[1]; + gptObjectInit(&GPTD2); +#endif + +#if KINETIS_GPT_USE_PIT2 + /* Driver initialization.*/ + GPTD3.channel = &PIT->CHANNEL[2]; + gptObjectInit(&GPTD3); +#endif + +#if KINETIS_GPT_USE_PIT3 + /* Driver initialization.*/ + GPTD4.channel = &PIT->CHANNEL[3]; + gptObjectInit(&GPTD4); +#endif +} + +/** + * @brief Configures and activates the GPT peripheral. + * + * @param[in] gptp pointer to the @p GPTDriver object + * + * @notapi + */ +void gpt_lld_start(GPTDriver *gptp) { + uint16_t psc; + + if (gptp->state == GPT_STOP) { + /* Clock activation.*/ + SIM->SCGC6 |= SIM_SCGC6_PIT; + gptp->clock = KINETIS_SYSCLK_FREQUENCY; + +#if !KINETIS_HAS_PIT_COMMON_IRQ + +#if KINETIS_GPT_USE_PIT0 + if (&GPTD1 == gptp) { + nvicEnableVector(PITChannel0_IRQn, KINETIS_GPT_PIT0_IRQ_PRIORITY); + } +#endif +#if KINETIS_GPT_USE_PIT1 + if (&GPTD2 == gptp) { + nvicEnableVector(PITChannel1_IRQn, KINETIS_GPT_PIT1_IRQ_PRIORITY); + } +#endif +#if KINETIS_GPT_USE_PIT2 + if (&GPTD3 == gptp) { + nvicEnableVector(PITChannel2_IRQn, KINETIS_GPT_PIT2_IRQ_PRIORITY); + } +#endif +#if KINETIS_GPT_USE_PIT3 + if (&GPTD4 == gptp) { + nvicEnableVector(PITChannel3_IRQn, KINETIS_GPT_PIT3_IRQ_PRIORITY); + } +#endif + +#else /* !KINETIS_HAS_PIT_COMMON_IRQ */ + nvicEnableVector(PIT_IRQn, KINETIS_GPT_PIT_IRQ_PRIORITY); + active_channels++; +#endif /* !KINETIS_HAS_PIT_COMMON_IRQ */ + } + + /* Prescaler value calculation.*/ + psc = (uint16_t)((gptp->clock / gptp->config->frequency) - 1); + osalDbgAssert(((uint32_t)(psc + 1) * gptp->config->frequency) == gptp->clock, + "invalid frequency"); + + /* Enable the PIT */ + PIT->MCR = 0; +} + +/** + * @brief Deactivates the GPT peripheral. + * + * @param[in] gptp pointer to the @p GPTDriver object + * + * @notapi + */ +void gpt_lld_stop(GPTDriver *gptp) { + + if (gptp->state == GPT_READY) { + SIM->SCGC6 &= ~SIM_SCGC6_PIT; + + /* Disable the channel */ + gptp->channel->TCTRL = 0; + + /* Clear pending interrupts */ + gptp->channel->TFLG |= PIT_TFLGn_TIF; + +#if !KINETIS_HAS_PIT_COMMON_IRQ + +#if KINETIS_GPT_USE_PIT0 + if (&GPTD1 == gptp) { + nvicDisableVector(PITChannel0_IRQn); + } +#endif +#if KINETIS_GPT_USE_PIT1 + if (&GPTD2 == gptp) { + nvicDisableVector(PITChannel1_IRQn); + } +#endif +#if KINETIS_GPT_USE_PIT2 + if (&GPTD3 == gptp) { + nvicDisableVector(PITChannel2_IRQn); + } +#endif +#if KINETIS_GPT_USE_PIT3 + if (&GPTD4 == gptp) { + nvicDisableVector(PITChannel3_IRQn); + } +#endif + +#else /* !KINETIS_HAS_PIT_COMMON_IRQ */ + if(--active_channels == 0) + nvicDisableVector(PIT_IRQn); +#endif /* !KINETIS_HAS_PIT_COMMON_IRQ */ + } +} + +/** + * @brief Starts the timer in continuous mode. + * + * @param[in] gptp pointer to the @p GPTDriver object + * @param[in] interval period in ticks + * + * @notapi + */ +void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t interval) { + + /* Clear pending interrupts */ + gptp->channel->TFLG |= PIT_TFLGn_TIF; + + /* Set the interval */ + gpt_lld_change_interval(gptp, interval); + + /* Start the timer */ + gptp->channel->TCTRL |= PIT_TCTRLn_TIE | PIT_TCTRLn_TEN; +} + +/** + * @brief Stops the timer. + * + * @param[in] gptp pointer to the @p GPTDriver object + * + * @notapi + */ +void gpt_lld_stop_timer(GPTDriver *gptp) { + + /* Stop the timer */ + gptp->channel->TCTRL = 0; +} + +/** + * @brief Starts the timer in one shot mode and waits for completion. + * @details This function specifically polls the timer waiting for completion + * in order to not have extra delays caused by interrupt servicing, + * this function is only recommended for short delays. + * + * @param[in] gptp pointer to the @p GPTDriver object + * @param[in] interval time interval in ticks + * + * @notapi + */ +void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval) { + struct PIT_CHANNEL *channel = gptp->channel; + + /* Disable timer and disable interrupts */ + channel->TCTRL = 0; + + /* Clear the interrupt flag */ + channel->TFLG |= PIT_TFLGn_TIF; + + /* Set the interval */ + channel->LDVAL = (gptp->clock / gptp->config->frequency) * interval; + + /* Enable Timer but keep interrupts disabled */ + channel->TCTRL = PIT_TCTRLn_TEN; + + /* Wait for the interrupt flag to be set */ + while (!(channel->TFLG & PIT_TFLGn_TIF)) + ; + + /* Disable timer and disable interrupts */ + channel->TCTRL = 0; +} + +#endif /* HAL_USE_GPT */ + +/** @} */ diff --git a/os/hal/ports/MIMXRT1064/LLD/PITv1/hal_gpt_lld.h b/os/hal/ports/MIMXRT1064/LLD/PITv1/hal_gpt_lld.h new file mode 100644 index 0000000000..96c4c70e1a --- /dev/null +++ b/os/hal/ports/MIMXRT1064/LLD/PITv1/hal_gpt_lld.h @@ -0,0 +1,333 @@ +/* + ChibiOS - Copyright (C) 2014 Derek Mulcahy + + 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 PITv1/hal_gpt_lld.h + * @brief KINETIS GPT subsystem low level driver header. + * + * @addtogroup GPT + * @{ + */ + +#ifndef HAL_GPT_LLD_H_ +#define HAL_GPT_LLD_H_ + +#if HAL_USE_GPT || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief GPTD1 driver enable switch. + * @details If set to @p TRUE the support for GPTD1 is included. + * @note The default is @p TRUE. + */ +#if !defined(KINETIS_GPT_USE_PIT0) || defined(__DOXYGEN__) +#define KINETIS_GPT_USE_PIT0 FALSE +#endif + +/** + * @brief GPTD2 driver enable switch. + * @details If set to @p TRUE the support for GPTD2 is included. + * @note The default is @p TRUE. + */ +#if !defined(KINETIS_GPT_USE_PIT1) || defined(__DOXYGEN__) +#define KINETIS_GPT_USE_PIT1 FALSE +#endif + +/** + * @brief GPTD3 driver enable switch. + * @details If set to @p TRUE the support for GPTD3 is included. + * @note The default is @p TRUE. + */ +#if !defined(KINETIS_GPT_USE_PIT2) || defined(__DOXYGEN__) +#define KINETIS_GPT_USE_PIT2 FALSE +#endif + +/** + * @brief GPTD4 driver enable switch. + * @details If set to @p TRUE the support for GPTD4 is included. + * @note The default is @p TRUE. + */ +#if !defined(KINETIS_GPT_USE_PIT3) || defined(__DOXYGEN__) +#define KINETIS_GPT_USE_PIT3 FALSE +#endif + +/** + * @brief GPTD1 interrupt priority level setting. + */ +#if !defined(KINETIS_GPT_PIT0_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define KINETIS_GPT_PIT0_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD2 interrupt priority level setting. + */ +#if !defined(KINETIS_GPT_PIT1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define KINETIS_GPT_PIT1_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD3 interrupt priority level setting. + */ +#if !defined(KINETIS_GPT_PIT2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define KINETIS_GPT_PIT2_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD4 interrupt priority level setting. + */ +#if !defined(KINETIS_GPT_PIT3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define KINETIS_GPT_PIT3_IRQ_PRIORITY 7 +#endif + +/** + * @brief GPTD* common interrupt priority level setting. + */ +#if (KINETIS_HAS_PIT_COMMON_IRQ && !defined(KINETIS_GPT_PIT_IRQ_PRIORITY)) \ + || defined(__DOXYGEN__) +#define KINETIS_GPT_PIT_IRQ_PRIORITY 2 +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if KINETIS_GPT_USE_PIT0 && !KINETIS_HAS_PIT0 +#error "PIT0 not present in the selected device" +#endif + +#if KINETIS_GPT_USE_PIT1 && !KINETIS_HAS_PIT1 +#error "PIT1 not present in the selected device" +#endif + +#if KINETIS_GPT_USE_PIT2 && !KINETIS_HAS_PIT2 +#error "PIT2 not present in the selected device" +#endif + +#if KINETIS_GPT_USE_PIT3 && !KINETIS_HAS_PIT3 +#error "PIT3 not present in the selected device" +#endif + +#if !KINETIS_GPT_USE_PIT0 && !KINETIS_GPT_USE_PIT1 && \ + !KINETIS_GPT_USE_PIT2 && !KINETIS_GPT_USE_PIT3 +#error "GPT driver activated but no PIT peripheral assigned" +#endif + +#if KINETIS_GPT_USE_PIT0 && !KINETIS_HAS_PIT_COMMON_IRQ && \ + !OSAL_IRQ_IS_VALID_PRIORITY(KINETIS_GPT_PIT0_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to PIT0" +#endif + +#if KINETIS_GPT_USE_PIT1 && !KINETIS_HAS_PIT_COMMON_IRQ && \ + !OSAL_IRQ_IS_VALID_PRIORITY(KINETIS_GPT_PIT1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to PIT1" +#endif + +#if KINETIS_GPT_USE_PIT2 && !KINETIS_HAS_PIT_COMMON_IRQ && \ + !OSAL_IRQ_IS_VALID_PRIORITY(KINETIS_GPT_PIT2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to PIT2" +#endif + +#if KINETIS_GPT_USE_PIT3 && !KINETIS_HAS_PIT_COMMON_IRQ && \ + !OSAL_IRQ_IS_VALID_PRIORITY(KINETIS_GPT_PIT3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to PIT3" +#endif + +#if KINETIS_HAS_PIT_COMMON_IRQ && \ + !OSAL_IRQ_IS_VALID_PRIORITY(KINETIS_GPT_PIT_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to PIT" +#endif + +#if KINETIS_GPT_USE_PIT0 && !defined(KINETIS_PIT0_IRQ_VECTOR) && \ + !KINETIS_HAS_PIT_COMMON_IRQ +#error "KINETIS_PIT0_IRQ_VECTOR not defined" +#endif + +#if KINETIS_GPT_USE_PIT1 && !defined(KINETIS_PIT1_IRQ_VECTOR) && \ + !KINETIS_HAS_PIT_COMMON_IRQ +#error "KINETIS_PIT1_IRQ_VECTOR not defined" +#endif + +#if KINETIS_GPT_USE_PIT2 && !defined(KINETIS_PIT2_IRQ_VECTOR) && \ + !KINETIS_HAS_PIT_COMMON_IRQ +#error "KINETIS_PIT2_IRQ_VECTOR not defined" +#endif + +#if KINETIS_GPT_USE_PIT3 && !defined(KINETIS_PIT3_IRQ_VECTOR) && \ + !KINETIS_HAS_PIT_COMMON_IRQ +#error "KINETIS_PIT3_IRQ_VECTOR not defined" +#endif + +#if KINETIS_HAS_PIT_COMMON_IRQ && !defined(KINETIS_PIT_IRQ_VECTOR) +#error "KINETIS_PIT_IRQ_VECTOR not defined" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief GPT frequency type. + */ +typedef uint32_t gptfreq_t; + +/** + * @brief GPT counter type. + */ +typedef uint32_t gptcnt_t; + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + /** + * @brief Timer clock in Hz. + * @note The low level can use assertions in order to catch invalid + * frequency specifications. + */ + gptfreq_t frequency; + /** + * @brief Timer callback pointer. + * @note This callback is invoked on GPT counter events. + * @note This callback can be set to @p NULL but in that case the + * one-shot mode cannot be used. + */ + gptcallback_t callback; + /* End of the mandatory fields.*/ +} GPTConfig; + +/** + * @brief Structure representing a GPT driver. + */ +struct GPTDriver { + /** + * @brief Driver state. + */ + gptstate_t state; + /** + * @brief Current configuration data. + */ + const GPTConfig *config; +#if defined(GPT_DRIVER_EXT_FIELDS) + GPT_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Timer base clock. + */ + uint32_t clock; + /** + * @brief Channel structure in PIT registers block. + */ + struct PIT_CHANNEL *channel; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Changes the interval of GPT peripheral. + * @details This function changes the interval of a running GPT unit. + * @pre The GPT unit must be running in continuous mode. + * @post The GPT unit interval is changed to the new value. + * @note The function has effect at the next cycle start. + * + * @param[in] gptp pointer to a @p GPTDriver object + * @param[in] interval new cycle time in timer ticks + * + * @notapi + */ +#define gpt_lld_change_interval(gptp, interval) \ + ((gptp)->channel->LDVAL = (uint32_t)( \ + ( (gptp)->clock / (gptp)->config->frequency ) * \ + ( interval ) )) + +/** + * @brief Returns the interval of GPT peripheral. + * @pre The GPT unit must be running in continuous mode. + * + * @param[in] gptp pointer to a @p GPTDriver object + * @return The current interval. + * + * @notapi + */ +#define gpt_lld_get_interval(gptp) \ + ((uint32_t)( ( (uint64_t)(gptp)->channel->LDVAL * (gptp)->config->frequency ) / \ + ( (uint32_t)(gptp)->clock ) )) + +/** + * @brief Returns the counter value of GPT peripheral. + * @pre The GPT unit must be running in continuous mode. + * @note The nature of the counter is not defined, it may count upward + * or downward, it could be continuously running or not. + * + * @param[in] gptp pointer to a @p GPTDriver object + * @return The current counter value. + * + * @notapi + */ +#define gpt_lld_get_counter(gptp) ((gptcnt_t)(gptp)->pit->CHANNEL[gptp->channel].CVAL) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if KINETIS_GPT_USE_PIT0 && !defined(__DOXYGEN__) +extern GPTDriver GPTD1; +#endif + +#if KINETIS_GPT_USE_PIT1 && !defined(__DOXYGEN__) +extern GPTDriver GPTD2; +#endif + +#if KINETIS_GPT_USE_PIT2 && !defined(__DOXYGEN__) +extern GPTDriver GPTD3; +#endif + +#if KINETIS_GPT_USE_PIT3 && !defined(__DOXYGEN__) +extern GPTDriver GPTD4; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void gpt_lld_init(void); + void gpt_lld_start(GPTDriver *gptp); + void gpt_lld_stop(GPTDriver *gptp); + void gpt_lld_start_timer(GPTDriver *gptp, gptcnt_t period); + void gpt_lld_stop_timer(GPTDriver *gptp); + void gpt_lld_polled_delay(GPTDriver *gptp, gptcnt_t interval); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_GPT */ + +#endif /* HAL_GPT_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/MIMXRT1064/LLD/PITv1/hal_st_lld.c b/os/hal/ports/MIMXRT1064/LLD/PITv1/hal_st_lld.c new file mode 100644 index 0000000000..4b17c2feaf --- /dev/null +++ b/os/hal/ports/MIMXRT1064/LLD/PITv1/hal_st_lld.c @@ -0,0 +1,109 @@ +/* + 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 PITv1/hal_st_lld.c + * @brief ST Driver subsystem low level driver code. + * + * @addtogroup ST + * @{ + */ + +#include "hal.h" + +#include "clock_config.h" + +#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if (OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC) || defined(__DOXYGEN__) +/** + * @brief System Timer vector. + * @details This interrupt is used for system tick in periodic mode. + * + * @isr + */ +OSAL_IRQ_HANDLER(SysTick_Handler) { + + OSAL_IRQ_PROLOGUE(); + + osalSysLockFromISR(); + osalOsTimerHandlerI(); + osalSysUnlockFromISR(); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level ST driver initialization. + * + * @notapi + */ +void st_lld_init(void) { +#if OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC + + /* Periodic systick mode, the Cortex-M7 internal systick timer is used in this + mode. + + Contrary to the Teensy 4 Arduino startup code, we use the internal 600 MHz + ARM clock instead of the external 100 kHz clock. They use the external + clock to make switching CPU frequencies easier, but this ChibiOS port does + not support switching CPU frequencies at all. When we want to add support, + we will just need to adjust the SysTick configuration accordingly. + + Using the faster clock allows users to increase the CH_CFG_ST_FREQUENCY for + finer grained tick duration and thereby minimum sleep duration when using + chThdSleep: 10μs instead of 100μs. */ + SysTick->LOAD = (BOARD_BOOTCLOCKRUN_CORE_CLOCK / OSAL_ST_FREQUENCY) - 1; + SysTick->VAL = 0; + SysTick->CTRL = SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk; + + /* IRQ enabled.*/ + nvicSetSystemHandlerPriority(HANDLER_SYSTICK, MIMXRT1064_ST_IRQ_PRIORITY); +#endif /* OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC */ +} + +#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */ + +/** @} */ diff --git a/os/hal/ports/MIMXRT1064/LLD/PITv1/hal_st_lld.h b/os/hal/ports/MIMXRT1064/LLD/PITv1/hal_st_lld.h new file mode 100644 index 0000000000..07b3b31550 --- /dev/null +++ b/os/hal/ports/MIMXRT1064/LLD/PITv1/hal_st_lld.h @@ -0,0 +1,156 @@ +/* + 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 PITv1/hal_st_lld.h + * @brief ST Driver subsystem low level driver header. + * @details This header is designed to be include-able without having to + * include other files from the HAL. + * + * @addtogroup ST + * @{ + */ + +#ifndef HAL_ST_LLD_H_ +#define HAL_ST_LLD_H_ + +#include "mcuconf.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief SysTick timer IRQ priority. + */ +#if !defined(MIMXRT1064_ST_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define MIMXRT1064_ST_IRQ_PRIORITY 8 +#endif + +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void st_lld_init(void); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Driver inline functions. */ +/*===========================================================================*/ + +/** + * @brief Returns the time counter value. + * + * @return The counter value. + * + * @notapi + */ +static inline systime_t st_lld_get_counter(void) { + + return (systime_t)0; +} + +/** + * @brief Starts the alarm. + * @note Makes sure that no spurious alarms are triggered after + * this call. + * + * @param[in] time the time to be set for the first alarm + * + * @notapi + */ +static inline void st_lld_start_alarm(systime_t time) { + + (void)time; +} + +/** + * @brief Stops the alarm interrupt. + * + * @notapi + */ +static inline void st_lld_stop_alarm(void) { + +} + +/** + * @brief Sets the alarm time. + * + * @param[in] time the time to be set for the next alarm + * + * @notapi + */ +static inline void st_lld_set_alarm(systime_t time) { + + (void)time; +} + +/** + * @brief Returns the current alarm time. + * + * @return The currently set alarm time. + * + * @notapi + */ +static inline systime_t st_lld_get_alarm(void) { + + return (systime_t)0; +} + +/** + * @brief Determines if the alarm is active. + * + * @return The alarm status. + * @retval false if the alarm is not active. + * @retval true is the alarm is active + * + * @notapi + */ +static inline bool st_lld_is_alarm_active(void) { + + return false; +} + +#endif /* HAL_ST_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/MIMXRT1064/LLD/UARTv1/driver.mk b/os/hal/ports/MIMXRT1064/LLD/UARTv1/driver.mk new file mode 100644 index 0000000000..04a654caf3 --- /dev/null +++ b/os/hal/ports/MIMXRT1064/LLD/UARTv1/driver.mk @@ -0,0 +1,16 @@ +UARTSRC = ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1064/LLD/UARTv1/hal_serial_lld.c \ + ${CHIBIOS_CONTRIB}/ext/mcux-sdk/drivers/lpuart/fsl_lpuart.c \ + ${CHIBIOS_CONTRIB}/ext/mcux-sdk/devices/MIMXRT1064/drivers/fsl_clock.c + +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_SERIAL TRUE,$(HALCONF)),) +PLATFORMSRC_CONTRIB += $(UARTSRC) +endif +else +PLATFORMSRC_CONTRIB += $(UARTSRC) +endif + +PLATFORMINC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1064/LLD/UARTv1 \ + ${CHIBIOS_CONTRIB}/ext/mcux-sdk/drivers/common \ + ${CHIBIOS_CONTRIB}/ext/mcux-sdk/drivers/lpuart \ + ${CHIBIOS_CONTRIB}/ext/mcux-sdk/devices/MIMXRT1064 diff --git a/os/hal/ports/MIMXRT1064/LLD/UARTv1/hal_serial_lld.c b/os/hal/ports/MIMXRT1064/LLD/UARTv1/hal_serial_lld.c new file mode 100644 index 0000000000..b37d861ad6 --- /dev/null +++ b/os/hal/ports/MIMXRT1064/LLD/UARTv1/hal_serial_lld.c @@ -0,0 +1,444 @@ +/* + ChibiOS - Copyright (C) 2013-2015 Fabio Utzig + Copyright (C) 2017 Wim Lewis + + 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 UARTv1/hal_serial_lld.c + * @brief Kinetis KL2x Serial Driver subsystem low level driver source. + * + * @addtogroup SERIAL + * @{ + */ + +#include "osal.h" +#include "hal.h" + +#include "fsl_lpuart.h" + +#define printf_init() +#define printf(...) +#define printf_debug_init() +#define printf_debug(...) + +#if HAL_USE_SERIAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief SD1 driver identifier. + */ +#if MIMXRT1064_SERIAL_USE_UART0 || defined(__DOXYGEN__) +SerialDriver SD1; +#endif + +#if MIMXRT1064_SERIAL_USE_UART1 || defined(__DOXYGEN__) +SerialDriver SD2; +#endif + +#if MIMXRT1064_SERIAL_USE_UART2 || defined(__DOXYGEN__) +SerialDriver SD3; +#endif + +#if MIMXRT1064_SERIAL_USE_UART3 || defined(__DOXYGEN__) +SerialDriver SD4; +#endif + +#if MIMXRT1064_SERIAL_USE_UART4 || defined(__DOXYGEN__) +SerialDriver SD5; +#endif + +#if MIMXRT1064_SERIAL_USE_UART5 || defined(__DOXYGEN__) +SerialDriver SD6; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief Driver default configuration. + */ +static const SerialConfig default_config = { + SERIAL_DEFAULT_BITRATE +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ +/** + * @brief Error handling routine. + * + * @param[in] sdp pointer to a @p SerialDriver object + * @param[in] isr UART s1 register value + */ +static void set_error(SerialDriver *sdp, uint32_t flags) { + eventflags_t sts = 0; + + if (flags & kLPUART_RxOverrunFlag) { + sts |= SD_OVERRUN_ERROR; + } + if (flags & kLPUART_ParityErrorFlag) { + sts |= SD_PARITY_ERROR; + } + if (flags & kLPUART_FramingErrorFlag) { + sts |= SD_FRAMING_ERROR; + } + if (flags & kLPUART_NoiseErrorFlag) { + sts |= SD_NOISE_ERROR; + } + osalSysLockFromISR(); + chnAddFlagsI(sdp, sts); + osalSysUnlockFromISR(); +} + +/** + * @brief Common error IRQ handler. + * + * @param[in] sdp communication channel associated to the UART + */ +static void serve_error_interrupt(SerialDriver *sdp) { + UART_w_TypeDef *u = &(sdp->uart); + const uint32_t flags = LPUART_GetStatusFlags(u->lpuart_p); + + if (flags & kLPUART_IdleLineFlag) { + } + + if (flags & (kLPUART_RxOverrunFlag | kLPUART_NoiseErrorFlag | kLPUART_FramingErrorFlag | kLPUART_ParityErrorFlag)) { + set_error(sdp, flags); + } +} + +/** + * @brief Common IRQ handler. + * @note Tries hard to clear all the pending interrupt sources, we don't + * want to go through the whole ISR and have another interrupt soon + * after. + * + * @param[in] sdp communication channel associated to the UART + */ +static void serve_interrupt(SerialDriver *sdp) { + UART_w_TypeDef *u = &(sdp->uart); + + const uint32_t flags = LPUART_GetStatusFlags(u->lpuart_p); + + if (flags & kLPUART_RxDataRegFullFlag) { + osalSysLockFromISR(); + if (iqIsEmptyI(&sdp->iqueue)) + chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE); + uint8_t b; + LPUART_ReadBlocking(u->lpuart_p, &b, 1); + if (iqPutI(&sdp->iqueue, b) < Q_OK) + chnAddFlagsI(sdp, SD_OVERRUN_ERROR); + osalSysUnlockFromISR(); + } + + if (flags & kLPUART_TxDataRegEmptyFlag) { + msg_t b; + + osalSysLockFromISR(); + b = oqGetI(&sdp->oqueue); + osalSysUnlockFromISR(); + + if (b < Q_OK) { + osalSysLockFromISR(); + chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY); + osalSysUnlockFromISR(); + // Disable Transfer Interrupt + LPUART_DisableInterrupts(u->lpuart_p, kLPUART_TxDataRegEmptyInterruptEnable); + } else { + LPUART_WriteBlocking(u->lpuart_p, (const uint8_t*)&b, 1); + } + } + + serve_error_interrupt(sdp); + LPUART_ClearStatusFlags(u->lpuart_p, flags); +} + +/** + * @brief Attempts a TX preload + */ +static void preload(SerialDriver *sdp) { + UART_w_TypeDef *u = &(sdp->uart); + uint32_t flags = LPUART_GetStatusFlags(u->lpuart_p); + + if (flags & kLPUART_TxDataRegEmptyFlag) { + msg_t b = oqGetI(&sdp->oqueue); + if (b < Q_OK) { + chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY); + return; + } + LPUART_WriteBlocking(u->lpuart_p, (const uint8_t*)&b, 1); + LPUART_EnableInterrupts(u->lpuart_p, kLPUART_TxDataRegEmptyInterruptEnable); + } +} + +/** + * @brief Driver output notification. + */ +static void notify(io_queue_t *qp) +{ + preload(qp->q_link); +} + +/** + * @brief Common driver initialization, except LP. + */ +static void sd_lld_init_driver(SerialDriver *SDn, LPUART_Type *UARTn) { + /* Driver initialization.*/ + sdObjectInit(SDn, NULL, notify); + SDn->uart.lpuart_p = UARTn; +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if MIMXRT1064_SERIAL_USE_UART0 || defined(__DOXYGEN__) +OSAL_IRQ_HANDLER(MIMXRT1064_SERIAL0_IRQ_VECTOR) { + OSAL_IRQ_PROLOGUE(); + serve_interrupt(&SD1); + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if MIMXRT1064_SERIAL_USE_UART1 || defined(__DOXYGEN__) +OSAL_IRQ_HANDLER(MIMXRT1064_SERIAL1_IRQ_VECTOR) { + OSAL_IRQ_PROLOGUE(); + serve_interrupt(&SD2); + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if MIMXRT1064_SERIAL_USE_UART2 || defined(__DOXYGEN__) +OSAL_IRQ_HANDLER(MIMXRT1064_SERIAL2_IRQ_VECTOR) { + OSAL_IRQ_PROLOGUE(); + serve_interrupt(&SD3); + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if MIMXRT1064_SERIAL_USE_UART3 || defined(__DOXYGEN__) +OSAL_IRQ_HANDLER(MIMXRT1064_SERIAL3_IRQ_VECTOR) { + OSAL_IRQ_PROLOGUE(); + serve_interrupt(&SD4); + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if MIMXRT1064_SERIAL_USE_UART4 || defined(__DOXYGEN__) +OSAL_IRQ_HANDLER(MIMXRT1064_SERIAL4_IRQ_VECTOR) { + OSAL_IRQ_PROLOGUE(); + serve_interrupt(&SD5); + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if MIMXRT1064_SERIAL_USE_UART5 || defined(__DOXYGEN__) +OSAL_IRQ_HANDLER(MIMXRT1064_SERIAL5_IRQ_VECTOR) { + OSAL_IRQ_PROLOGUE(); + serve_interrupt(&SD6); + OSAL_IRQ_EPILOGUE(); +} +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level serial driver initialization. + * + * @notapi + */ +void sd_lld_init(void) { + +#if MIMXRT1064_SERIAL_USE_UART0 + /* Driver initialization.*/ + sd_lld_init_driver(&SD1, LPUART1); +#endif /* MIMXRT1064_SERIAL_USE_UART0 */ + +#if MIMXRT1064_SERIAL_USE_UART1 + sd_lld_init_driver(&SD2, LPUART2); +#endif /* MIMXRT1064_SERIAL_USE_UART1 */ + +#if MIMXRT1064_SERIAL_USE_UART2 + sd_lld_init_driver(&SD3, LPUART3); +#endif /* MIMXRT1064_SERIAL_USE_UART2 */ + +#if MIMXRT1064_SERIAL_USE_UART3 + sd_lld_init_driver(&SD4, LPUART4); +#endif /* MIMXRT1064_SERIAL_USE_UART3 */ + +#if MIMXRT1064_SERIAL_USE_UART4 + sd_lld_init_driver(&SD5, LPUART5); +#endif /* MIMXRT1064_SERIAL_USE_UART4 */ + +#if MIMXRT1064_SERIAL_USE_UART5 + sd_lld_init_driver(&SD6, LPUART6); +#endif /* MIMXRT1064_SERIAL_USE_UART5 */ +} + +// See also: +// https://github.com/adafruit/circuitpython/blob/main/ports/mimxrt10xx/supervisor/serial.c +static uint32_t UartSrcFreq(void) { + uint32_t freq; + + /* To make it simple, we assume default PLL and divider settings, and the only variable + from application is use PLL3 source or OSC source */ + /* PLL3 div6 80M */ + if (CLOCK_GetMux(kCLOCK_UartMux) == 0) { + freq = (CLOCK_GetPllFreq(kCLOCK_PllUsb1) / 6U) / (CLOCK_GetDiv(kCLOCK_UartDiv) + 1U); + } else { + freq = CLOCK_GetOscFreq() / (CLOCK_GetDiv(kCLOCK_UartDiv) + 1U); + } + + return freq; +} + +/** + * @brief Low level serial driver configuration and (re)start. + * + * @param[in] sdp pointer to a @p SerialDriver object + * @param[in] config the architecture-dependent serial driver configuration. + * If this parameter is set to @p NULL then a default + * configuration is used. + * + * @notapi + */ +void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) { + + if (config == NULL) + config = &default_config; + + if (sdp->state == SD_STOP) { + /* Enables the peripheral.*/ + + lpuart_config_t uconfig; + + LPUART_GetDefaultConfig(&uconfig); + uconfig.baudRate_Bps = config->sc_speed; + uconfig.enableTx = true; + uconfig.enableRx = true; + +#if MIMXRT1064_SERIAL_USE_UART0 + if (sdp == &SD1) { + LPUART_Init(LPUART1, &uconfig, UartSrcFreq()); + IOMUXC->SW_MUX_CTL_PAD[kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_12] = 2; // Arduino pin 24 + IOMUXC->SW_MUX_CTL_PAD[kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_13] = 2; // Arduino pin 25 + + nvicEnableVector(LPUART1_IRQn, MIMXRT1064_SERIAL_UART0_PRIORITY); + + LPUART_EnableInterrupts(LPUART1, kLPUART_RxDataRegFullInterruptEnable); + } +#endif /* MIMXRT1064_SERIAL_USE_UART0 */ + +#if MIMXRT1064_SERIAL_USE_UART1 + if (sdp == &SD2) { + LPUART_Init(LPUART2, &uconfig, UartSrcFreq()); + } +#endif /* MIMXRT1064_SERIAL_USE_UART1 */ + +#if MIMXRT1064_SERIAL_USE_UART2 + if (sdp == &SD3) { + LPUART_Init(LPUART3, &uconfig, UartSrcFreq()); + IOMUXC->SW_MUX_CTL_PAD[kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_06] = 2; // Arduino pin 17 + } +#endif /* MIMXRT1064_SERIAL_USE_UART2 */ + +#if MIMXRT1064_SERIAL_USE_UART3 + if (sdp == &SD4) { + LPUART_Init(LPUART4, &uconfig, UartSrcFreq()); + } +#endif /* MIMXRT1064_SERIAL_USE_UART3 */ + +#if MIMXRT1064_SERIAL_USE_UART4 + if (sdp == &SD5) { + LPUART_Init(LPUART4, &uconfig, UartSrcFreq()); + } +#endif /* MIMXRT1064_SERIAL_USE_UART4 */ + +#if MIMXRT1064_SERIAL_USE_UART5 + if (sdp == &SD6) { + LPUART_Init(LPUART5, &uconfig, UartSrcFreq()); + } +#endif /* MIMXRT1064_SERIAL_USE_UART5 */ + + } + /* Configures the peripheral.*/ + +} + +/** + * @brief Low level serial driver stop. + * @details De-initializes the USART, stops the associated clock, resets the + * interrupt vector. + * + * @param[in] sdp pointer to a @p SerialDriver object + * + * @notapi + */ +void sd_lld_stop(SerialDriver *sdp) { + + if (sdp->state == SD_READY) { + +#if MIMXRT1064_SERIAL_USE_UART0 + if (sdp == &SD1) { + nvicDisableVector(LPUART1_IRQn); + LPUART_Deinit(LPUART1); + } +#endif + +#if MIMXRT1064_SERIAL_USE_UART1 + if (sdp == &SD2) { + LPUART_Deinit(LPUART2); + } +#endif + +#if MIMXRT1064_SERIAL_USE_UART2 + if (sdp == &SD3) { + LPUART_Deinit(LPUART3); + } +#endif + +#if MIMXRT1064_SERIAL_USE_UART3 + if (sdp == &SD4) { + LPUART_Deinit(LPUART4); + } +#endif + +#if MIMXRT1064_SERIAL_USE_UART4 + if (sdp == &SD5) { + LPUART_Deinit(LPUART5); + } +#endif + +#if MIMXRT1064_SERIAL_USE_UART5 + if (sdp == &SD6) { + LPUART_Deinit(LPUART6); + } +#endif + } +} + +#endif /* HAL_USE_SERIAL */ + +/** @} */ diff --git a/os/hal/ports/MIMXRT1064/LLD/UARTv1/hal_serial_lld.h b/os/hal/ports/MIMXRT1064/LLD/UARTv1/hal_serial_lld.h new file mode 100644 index 0000000000..bdae85ed66 --- /dev/null +++ b/os/hal/ports/MIMXRT1064/LLD/UARTv1/hal_serial_lld.h @@ -0,0 +1,274 @@ +/* + ChibiOS - Copyright (C) 2013-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 UARTv1/hal_serial_lld.h + * @brief Kinetis KL2x Serial Driver subsystem low level driver header. + * + * @addtogroup SERIAL + * @{ + */ + +#ifndef HAL_SERIAL_LLD_H_ +#define HAL_SERIAL_LLD_H_ + +#if HAL_USE_SERIAL || defined(__DOXYGEN__) + +#include "fsl_lpuart.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief SD1 driver enable switch. + * @details If set to @p TRUE the support for SD1 is included. + */ +#if !defined(MIMXRT1064_SERIAL_USE_UART0) || defined(__DOXYGEN__) +#define MIMXRT1064_SERIAL_USE_UART0 FALSE +#endif +/** + * @brief SD2 driver enable switch. + * @details If set to @p TRUE the support for SD2 is included. + */ +#if !defined(MIMXRT1064_SERIAL_USE_UART1) || defined(__DOXYGEN__) +#define MIMXRT1064_SERIAL_USE_UART1 FALSE +#endif +/** + * @brief SD3 driver enable switch. + * @details If set to @p TRUE the support for SD3 is included. + */ +#if !defined(MIMXRT1064_SERIAL_USE_UART2) || defined(__DOXYGEN__) +#define MIMXRT1064_SERIAL_USE_UART2 FALSE +#endif +/** + * @brief SD4 driver enable switch. + * @details If set to @p TRUE the support for SD4 is included. + */ +#if !defined(MIMXRT1064_SERIAL_USE_UART3) || defined(__DOXYGEN__) +#define MIMXRT1064_SERIAL_USE_UART3 FALSE +#endif +/** + * @brief SD5 driver enable switch. + * @details If set to @p TRUE the support for SD5 is included. + */ +#if !defined(MIMXRT1064_SERIAL_USE_UART4) || defined(__DOXYGEN__) +#define MIMXRT1064_SERIAL_USE_UART4 FALSE +#endif +/** + * @brief SD6 driver enable switch. + * @details If set to @p TRUE the support for SD6 is included. + */ +#if !defined(MIMXRT1064_SERIAL_USE_UART5) || defined(__DOXYGEN__) +#define MIMXRT1064_SERIAL_USE_UART5 FALSE +#endif + +/** + * @brief UART0 interrupt priority level setting. + */ +#if !defined(MIMXRT1064_SERIAL_UART0_PRIORITY) || defined(__DOXYGEN__) +#define MIMXRT1064_SERIAL_UART0_PRIORITY 12 +#endif + +/** + * @brief UART1 interrupt priority level setting. + */ +#if !defined(MIMXRT1064_SERIAL_UART1_PRIORITY) || defined(__DOXYGEN__) +#define MIMXRT1064_SERIAL_UART1_PRIORITY 12 +#endif + +/** + * @brief UART2 interrupt priority level setting. + */ +#if !defined(MIMXRT1064_SERIAL_UART2_PRIORITY) || defined(__DOXYGEN__) +#define MIMXRT1064_SERIAL_UART2_PRIORITY 12 +#endif + +/** + * @brief UART3 interrupt priority level setting. + */ +#if !defined(MIMXRT1064_SERIAL_UART3_PRIORITY) || defined(__DOXYGEN__) +#define MIMXRT1064_SERIAL_UART3_PRIORITY 12 +#endif + +/** + * @brief UART4 interrupt priority level setting. + */ +#if !defined(MIMXRT1064_SERIAL_UART4_PRIORITY) || defined(__DOXYGEN__) +#define MIMXRT1064_SERIAL_UART4_PRIORITY 12 +#endif + +/** + * @brief UART5 interrupt priority level setting. + */ +#if !defined(MIMXRT1064_SERIAL_UART5_PRIORITY) || defined(__DOXYGEN__) +#define MIMXRT1064_SERIAL_UART5_PRIORITY 12 +#endif + +/** + * @brief UART0 clock source. + */ +#if !defined(MIMXRT1064_UART0_CLOCK_SRC) || defined(__DOXYGEN__) +#define MIMXRT1064_UART0_CLOCK_SRC 1 /* MCGFLLCLK clock, or MCGPLLCLK/2; or IRC48M */ +#endif + +/** + * @brief UART1 clock source. + */ +#if !defined(MIMXRT1064_UART1_CLOCK_SRC) || defined(__DOXYGEN__) +#define MIMXRT1064_UART1_CLOCK_SRC 1 /* IRC48M */ +#endif + +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/** @brief error checks */ +#if MIMXRT1064_SERIAL_USE_UART0 && !MIMXRT1064_HAS_SERIAL0 +#error "UART0 not present in the selected device" +#endif + +#if MIMXRT1064_SERIAL_USE_UART1 && !MIMXRT1064_HAS_SERIAL1 +#error "UART1 not present in the selected device" +#endif + +#if MIMXRT1064_SERIAL_USE_UART2 && !MIMXRT1064_HAS_SERIAL2 +#error "UART2 not present in the selected device" +#endif + +#if MIMXRT1064_SERIAL_USE_UART3 && !MIMXRT1064_HAS_SERIAL3 +#error "UART3 not present in the selected device" +#endif + +#if MIMXRT1064_SERIAL_USE_UART4 && !MIMXRT1064_HAS_SERIAL4 +#error "UART4 not present in the selected device" +#endif + +#if MIMXRT1064_SERIAL_USE_UART5 && !MIMXRT1064_HAS_SERIAL5 +#error "UART5 not present in the selected device" +#endif + +#if !(MIMXRT1064_SERIAL_USE_UART0 || MIMXRT1064_SERIAL_USE_UART1 || \ + MIMXRT1064_SERIAL_USE_UART2 || MIMXRT1064_SERIAL_USE_UART3 || \ + MIMXRT1064_SERIAL_USE_UART4 || MIMXRT1064_SERIAL_USE_UART5) +#error "Serial driver activated but no UART peripheral assigned" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Generic Serial Driver configuration structure. + * @details An instance of this structure must be passed to @p sdStart() + * in order to configure and start a serial driver operations. + * @note Implementations may extend this structure to contain more, + * architecture dependent, fields. + */ +typedef struct { + /** + * @brief Bit rate. + */ + uint32_t sc_speed; + /* End of the mandatory fields.*/ +} SerialConfig; + +/** + * @brief Generic UART register structure. + * @note Individual UART register blocks (even within the same chip) can differ. + */ + +typedef struct { + LPUART_Type *lpuart_p; + lpuart_handle_t handle; +} UART_w_TypeDef; + +/** + * @brief @p SerialDriver specific data. + */ +#define _serial_driver_data \ + _base_asynchronous_channel_data \ + /* Driver state.*/ \ + sdstate_t state; \ + /* Input queue.*/ \ + input_queue_t iqueue; \ + /* Output queue.*/ \ + output_queue_t oqueue; \ + /* Input circular buffer.*/ \ + uint8_t ib[SERIAL_BUFFERS_SIZE]; \ + /* Output circular buffer.*/ \ + uint8_t ob[SERIAL_BUFFERS_SIZE]; \ + /* End of the mandatory fields.*/ \ + /* Pointer to the UART registers block.*/ \ + UART_w_TypeDef uart; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if MIMXRT1064_SERIAL_USE_UART0 && !defined(__DOXYGEN__) +extern SerialDriver SD1; +#endif + +#if MIMXRT1064_SERIAL_USE_UART1 && !defined(__DOXYGEN__) +extern SerialDriver SD2; +#endif + +#if MIMXRT1064_SERIAL_USE_UART2 && !defined(__DOXYGEN__) +extern SerialDriver SD3; +#endif + +#if MIMXRT1064_SERIAL_USE_UART3 && !defined(__DOXYGEN__) +extern SerialDriver SD4; +#endif + +#if MIMXRT1064_SERIAL_USE_UART4 && !defined(__DOXYGEN__) +extern SerialDriver SD5; +#endif + +#if MIMXRT1064_SERIAL_USE_UART5 && !defined(__DOXYGEN__) +extern SerialDriver SD6; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void sd_lld_init(void); + void sd_lld_start(SerialDriver *sdp, const SerialConfig *config); + void sd_lld_stop(SerialDriver *sdp); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SERIAL */ + +#endif /* HAL_SERIAL_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/MIMXRT1064/LLD/USBHSv1/driver.mk b/os/hal/ports/MIMXRT1064/LLD/USBHSv1/driver.mk new file mode 100644 index 0000000000..3bab14f760 --- /dev/null +++ b/os/hal/ports/MIMXRT1064/LLD/USBHSv1/driver.mk @@ -0,0 +1,22 @@ + +HAL_USB_SRC = ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1064/LLD/USBHSv1/hal_usb_lld.c \ + ${CHIBIOS_CONTRIB}/ext/nxp-middleware-usb/device/usb_device_dci.c \ + ${CHIBIOS_CONTRIB}/ext/nxp-middleware-usb/device/usb_device_ehci.c \ + ${CHIBIOS_CONTRIB}/ext/nxp-middleware-usb/phy/usb_phy.c \ + ${CHIBIOS_CONTRIB}/ext/mcux-sdk/components/osa/fsl_os_abstraction_bm.c \ + ${CHIBIOS_CONTRIB}/ext/mcux-sdk/components/lists/fsl_component_generic_list.c + +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_USB TRUE,$(HALCONF)),) +PLATFORMSRC_CONTRIB += ${HAL_USB_SRC} +endif +else +PLATFORMSRC_CONTRIB += ${HAL_USB_SRC} +endif + +PLATFORMINC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1064/LLD/USBHSv1 \ + ${CHIBIOS_CONTRIB}/ext/nxp-middleware-usb/include \ + ${CHIBIOS_CONTRIB}/ext/nxp-middleware-usb/device \ + ${CHIBIOS_CONTRIB}/ext/nxp-middleware-usb/phy \ + ${CHIBIOS_CONTRIB}/ext/mcux-sdk/components/osa \ + ${CHIBIOS_CONTRIB}/ext/mcux-sdk/components/lists diff --git a/os/hal/ports/MIMXRT1064/LLD/USBHSv1/hal_usb_lld.c b/os/hal/ports/MIMXRT1064/LLD/USBHSv1/hal_usb_lld.c new file mode 100644 index 0000000000..08b8639470 --- /dev/null +++ b/os/hal/ports/MIMXRT1064/LLD/USBHSv1/hal_usb_lld.c @@ -0,0 +1,787 @@ +/* + ChibiOS - Copyright (C) 2015 RedoX https://github.com/RedoXyde/ + (C) 2015-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 USBHSv1/hal_usb_lld.c + * @brief MIMXRT1064 USB subsystem low level driver source. + * @note page 2211 in https://www.pjrc.com/teensy/IMXRT1060RM_rev2.pdf + * @note page 2203: chapter 42 USB + * @note https://github.com/kylemanna/kinetis-sdk2/blob/master/docs/usb/MCUXpresso%20SDK%20USB%20Stack%20Device%20Reference%20Manual.pdf + * + * @addtogroup USB + * @{ + */ + +#include + +#include "hal.h" + +#include "usb_device_config.h" +#include "usb.h" +#include "usb_device.h" +#include "usb_device_dci.h" +#include "usb_device_ehci.h" +#include "usb_phy.h" + +usb_device_handle handle; + +#include "printf_debug.h" + +#include "fsl_clock.h" + + +#if HAL_USE_USB || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief USB1 driver identifier.*/ +#if MIMXRT1064_USB_USE_USB1 || defined(__DOXYGEN__) +USBDriver USBD1; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief IN EP0 state. + */ +USBInEndpointState ep0in; + +/** + * @brief OUT EP0 state. + */ +USBOutEndpointState ep0out; + +/** + * @brief Buffer for the EP0 setup packets. + */ +static uint8_t ep0setup_buffer[8]; + +/** + * @brief EP0 initialization structure. + */ +static const USBEndpointConfig ep0config = { + USB_EP_MODE_TYPE_CTRL, + _usb_ep0setup, + _usb_ep0in, + _usb_ep0out, + 64, + 64, + &ep0in, + &ep0out, + 1, + ep0setup_buffer +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static uint8_t epaddr(usbep_t ep, uint8_t direction) { + return ep | (direction << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT); +} + +static usb_status_t usb_device_callback(usb_device_handle handle, uint32_t callbackEvent, void *eventParam) { + (void)handle; + (void)eventParam; + + USBDriver *usbp = &USBD1; + printf_debug("usb_device_callback(event=%d)", callbackEvent); + + switch (callbackEvent) { + case kUSB_DeviceEventBusReset: + printf_debug(" bus reset"); + _usb_reset(usbp); + break; + + case kUSB_DeviceEventSuspend: + printf_debug(" suspend"); + _usb_suspend(usbp); + break; + + case kUSB_DeviceEventResume: + printf_debug(" resume"); + _usb_wakeup(usbp); + break; + } + + return kStatus_USB_Success; +} + + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*============================================================================*/ + +#if MIMXRT1064_USB_USE_USB1 || defined(__DOXYGEN__) + +/** + * @brief USB interrupt handler. + + * @note → page 2210, “Interrupts” + * + * @isr + */ +OSAL_IRQ_HANDLER(MIMXRT1064_USB_OTG1_IRQ_VECTOR) { + USBDriver *usbp = &USBD1; + OSAL_IRQ_PROLOGUE(); + + // Do not print as long as SOF interrupt is enabled to avoid slowing down the + // application due to serial print latency: + //printf_debug("ISR\n"); + + // inlined from USB_DeviceEhciIsrFunction(handle) so that we can dispatch the + // SOF (start of frame) interrupt: + usb_device_struct_t *dev_handle = (usb_device_struct_t *)handle; + usb_device_ehci_state_struct_t *ehciState; + uint32_t status; + + ehciState = (usb_device_ehci_state_struct_t *)(dev_handle->controllerHandle); + + status = ehciState->registerBase->USBSTS; + status &= ehciState->registerBase->USBINTR; + + USB_DeviceEhciIsrFunction(handle); + + // Some ChibiOS components require the SOF interrupt, such as the USB serial. + if ((status & USBHS_USBSTS_SRI_MASK)) { + _usb_isr_invoke_sof_cb(usbp); + } + + OSAL_IRQ_EPILOGUE(); +} +#endif /* MIMXRT1064_USB_USE_USB1 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level USB driver initialization. + * + * @notapi + */ +void usb_lld_init(void) { + USBDriver *usbp = &USBD1; + + /* Driver initialization.*/ + usbObjectInit(usbp); + +#if MIMXRT1064_USB_USE_USB1 + /* USB PHY configuration */ +#ifndef BOARD_USB_PHY_D_CAL +#define BOARD_USB_PHY_D_CAL (0x0CU) +#endif +#ifndef BOARD_USB_PHY_TXCAL45DP +#define BOARD_USB_PHY_TXCAL45DP (0x06U) +#endif +#ifndef BOARD_USB_PHY_TXCAL45DM +#define BOARD_USB_PHY_TXCAL45DM (0x06U) +#endif + usb_phy_config_struct_t phyConfig = { + BOARD_USB_PHY_D_CAL, BOARD_USB_PHY_TXCAL45DP, BOARD_USB_PHY_TXCAL45DM, + }; + uint32_t notUsed = 0; + + CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usbphy480M, 480000000U); + CLOCK_EnableUsbhs0Clock(kCLOCK_Usb480M, 480000000U); + + USB_EhciPhyInit(kUSB_ControllerEhci0, notUsed, &phyConfig); + + if (USB_DeviceInit(kUSB_ControllerEhci0, usb_device_callback, &handle) != kStatus_USB_Success) { + printf_debug("allocating handle failed"); + return; + } + printf_debug("handle allocated"); + +#endif /* MIMXRT1064_USB_USE_USB1 */ +} + +/** + * @brief Configures and activates the USB peripheral. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_start(USBDriver *usbp) { + if (usbp->state != USB_STOP) { + printf_debug("already started!"); + return; // already started + } + +#if MIMXRT1064_USB_USE_USB1 + if (usbp != &USBD1) { + return; // unknown usbp + } + + printf_debug(" usb_lld_start() enter"); + + USB_DeviceRun(handle); + printf_debug("device running"); + + nvicEnableVector(USB_OTG1_IRQn, MIMXRT1064_USB_USB1_IRQ_PRIORITY); + printf_debug("interrupt enabled"); +#endif /* MIMXRT1064_USB_USE_USB1 */ +} + +/** + * @brief Deactivates the USB peripheral. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_stop(USBDriver *usbp) { + if (usbp->state == USB_STOP) { +#if MIMXRT1064_USB_USE_USB1 + if (&USBD1 == usbp) { + printf_debug("usb_lld_stop()"); + USB_DeviceStop(handle); + nvicDisableVector(USB_OTG1_IRQn); + } +#endif /* MIMXRT1064_USB_USE_USB1 */ + } +} + +/** + * Called when the USB transfer completed + * + */ +static usb_status_t device_ep0_control_callback(usb_device_handle handle, + usb_device_endpoint_callback_message_struct_t *message, + void *callbackParam, + uint8_t direction) { + (void)handle; + (void)callbackParam; + + USBDriver *usbp = &USBD1; + printf_debug("device_ep0_control_callback"); + const uint8_t ep = 0; + const USBEndpointConfig *epc = usbp->epc[ep]; + if (message->isSetup) { + printf_debug("setup message for endpoint 0"); + + /* Clear receiving in the chibios state machine */ + (usbp)->receiving &= ~(1 << ep); + (usbp)->transmitting &= ~(1 << ep); + + memcpy(usbp->setup, message->buffer, message->length); + + /* Call SETUP function (ChibiOS core), which prepares + * for send or receive and releases the buffer + */ + if (epc->setup_cb != NULL) { + _usb_isr_invoke_setup_cb(usbp, ep); + // -> will call usb_lld_read_setup + // -> will call e.g. usb_lld_start_in + } + return kStatus_USB_Success; + } + printf_debug("transfer done: buffer %x, len=%d!", message->buffer, message->length); + + if (message->length == USB_CANCELLED_TRANSFER_LENGTH) { + printf_debug("USB transfer cancelled"); + return kStatus_USB_InvalidRequest; + } + + if (direction == USB_OUT) { + printf_debug(" complete, OUT ep=%d (OUT), rxbuf=%x", ep, epc->out_state->rxbuf); + + USBOutEndpointState *osp = epc->out_state; + osp->rxcnt = message->length; + + printf_debug(" received %d bytes", osp->rxcnt); + + /* Endpoint Receive Complete Event */ + /* Transfer Direction OUT */ + printf_debug(" invoking out_cb for ep %d", ep); + _usb_isr_invoke_out_cb(usbp, ep); + } else if (direction == USB_IN) { + printf_debug(" complete, IN ep=%d (IN), txbuf=%x", ep, epc->in_state->txbuf); + /* Endpoint Transmit Complete Event */ + /* Transfer Direction IN */ + printf_debug(" invoking in_cb for ep %d", ep); + _usb_isr_invoke_in_cb(usbp, ep); + } + + return kStatus_USB_Success; +} + +static usb_status_t device_ep0_control_callback_in(usb_device_handle handle, + usb_device_endpoint_callback_message_struct_t *message, + void *callbackParam) { + return device_ep0_control_callback(handle, message, callbackParam, USB_IN); +} + +static usb_status_t device_ep0_control_callback_out(usb_device_handle handle, + usb_device_endpoint_callback_message_struct_t *message, + void *callbackParam) { + return device_ep0_control_callback(handle, message, callbackParam, USB_OUT); +} + +/** + * @brief USB low level reset routine. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_reset(USBDriver *usbp) { + usbp->epc[0] = &ep0config; + + usb_device_endpoint_init_struct_t epInitStruct; + usb_device_endpoint_callback_struct_t epCallback; + usb_status_t status; + + epCallback.callbackFn = device_ep0_control_callback_in; + epCallback.callbackParam = NULL; + + /* ChibiOS handles zero-length transmissions (ZLT) in software, so disable the + * hardware functionality for it: + * https://github.com/ChibiOS/ChibiOS/blob/525f89f0e322bb410e0674e4945bf8196d92df65/os/hal/src/hal_usb.c#L891-L901 + * + * See also: + * https://community.nxp.com/t5/MQX-Software-Solutions/MQX-USBHS-Control-Endpoint-Zero-Length-Termination/m-p/375730 + */ + epInitStruct.zlt = 0; + epInitStruct.transferType = USB_ENDPOINT_CONTROL; + epInitStruct.interval = 0; + epInitStruct.endpointAddress = epaddr(USB_CONTROL_ENDPOINT, USB_IN); + epInitStruct.maxPacketSize = USB_CONTROL_MAX_PACKET_SIZE; + /* Initialize the control IN pipe */ + status = USB_DeviceInitEndpoint(handle, &epInitStruct, &epCallback); + + if (kStatus_USB_Success != status) { + printf_debug("USB_DeviceInitEndpoint() failed: %d", status); + return; + } + + epCallback.callbackFn = device_ep0_control_callback_out; + epCallback.callbackParam = NULL; + epInitStruct.endpointAddress = epaddr(USB_CONTROL_ENDPOINT, USB_OUT); + /* Initialize the control OUT pipe */ + status = USB_DeviceInitEndpoint(handle, &epInitStruct, &epCallback); + + if (kStatus_USB_Success != status) { + (void)USB_DeviceDeinitEndpoint(handle, epInitStruct.endpointAddress); + printf_debug("USB_DeviceInitEndpoint() failed: %d", status); + return; + } +} + +/** + * @brief Sets the USB address. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_set_address(USBDriver *usbp) { + +#if MIMXRT1064_USB_USE_USB1 + printf_debug("usb_lld_set_address(%d)", usbp->address); + + usb_status_t error = kStatus_USB_InvalidRequest; + uint8_t state = 0U; + + USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state); + + printf_debug(" DeviceStatusDeviceState=%x", state); + + if (((uint8_t)kUSB_DeviceStateAddressing != state) && ((uint8_t)kUSB_DeviceStateAddress != state) && + ((uint8_t)kUSB_DeviceStateDefault != state) && ((uint8_t)kUSB_DeviceStateConfigured != state)) { + printf_debug(" invalid state!"); + return; + } + + if ((uint8_t)kUSB_DeviceStateAddressing != state) { + /* If the device address is not setting, pass the address and the device state will change to + * kUSB_DeviceStateAddressing internally. */ + state = (uint8_t)(usbp->address & 0xFF); + error = USB_DeviceSetStatus(handle, kUSB_DeviceStatusAddress, &state); + } else { + /* If the device address is setting, set device address and the address will be write into the controller + * internally. */ + error = USB_DeviceSetStatus(handle, kUSB_DeviceStatusAddress, NULL); + /* And then change the device state to kUSB_DeviceStateAddress. */ + if (kStatus_USB_Success == error) { + state = (uint8_t)kUSB_DeviceStateAddress; + error = USB_DeviceSetStatus(handle, kUSB_DeviceStatusDeviceState, &state); + } + } +#endif /* MIMXRT1064_USB_USE_USB1 */ +} + +/** + * Called when the USB transfer completed + * + */ +static usb_status_t device_epN_control_callback(usb_device_handle handle, + usb_device_endpoint_callback_message_struct_t *message, + void *callbackParam, + uint8_t direction) { + (void)handle; + USBDriver *usbp = &USBD1; + uint8_t ep = (uint8_t)((uint32_t)callbackParam & 0xFF); + printf_debug("device_epN_control_callback"); + if (message->isSetup) { + printf_debug("discarding unexpected setup message for endpoint ep=%d", ep); + return kStatus_USB_Error; + } + + if (message->length == USB_CANCELLED_TRANSFER_LENGTH) { + printf_debug("USB transfer cancelled"); + return kStatus_USB_InvalidRequest; + } + + printf_debug("transfer done: buffer %x, len=%d!", message->buffer, message->length); + + const USBEndpointConfig *epc = usbp->epc[ep]; + + if (direction == USB_OUT) { + printf_debug(" complete, OUT ep=%d (OUT), rxbuf=%x", ep, epc->out_state->rxbuf); + + USBOutEndpointState *osp = epc->out_state; + osp->rxcnt = message->length; + printf_debug(" received %d bytes", osp->rxcnt); + + /* Endpoint Receive Complete Event */ + /* Transfer Direction OUT */ + printf_debug(" invoking out_cb for ep %d", ep); + _usb_isr_invoke_out_cb(usbp, ep); + } else if (direction == USB_IN) { + printf_debug(" complete, IN ep=%d (IN), txbuf=%x", ep, epc->in_state->txbuf); + /* Endpoint Transmit Complete Event */ + /* Transfer Direction IN */ + printf_debug(" invoking in_cb for ep %d", ep); + _usb_isr_invoke_in_cb(usbp, ep); + } + return kStatus_USB_Success; +} + +static usb_status_t device_epN_control_callback_out(usb_device_handle handle, + usb_device_endpoint_callback_message_struct_t *message, + void *callbackParam) { + return device_epN_control_callback(handle, message, callbackParam, USB_OUT); +} + +static usb_status_t device_epN_control_callback_in(usb_device_handle handle, + usb_device_endpoint_callback_message_struct_t *message, + void *callbackParam) { + return device_epN_control_callback(handle, message, callbackParam, USB_IN); +} + +/** + * @brief Enables an endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) { + + if(ep > MIMXRT1064_USB_ENDPOINTS) + return; + + printf_debug("usb_lld_init_endpoint(ep=%d)", ep); + + const USBEndpointConfig *epc = usbp->epc[ep]; + + if (epc->out_state == NULL && epc->in_state == NULL) { + printf_debug(" BUG: unknown endpoint type?!"); + return; + } + + usb_device_endpoint_init_struct_t epInitStruct; + usb_device_endpoint_callback_struct_t epCallback; + usb_status_t status; + + epCallback.callbackFn = device_epN_control_callback_in; + epCallback.callbackParam = (void*)((uint32_t)ep); + + epInitStruct.transferType = epc->ep_mode; + epInitStruct.zlt = 0; + epInitStruct.interval = 0; + + if (epc->in_state != NULL) { + epInitStruct.endpointAddress = epaddr(ep, USB_IN); + epInitStruct.maxPacketSize = epc->in_maxsize; + /* Initialize the endpoint IN pipe */ + if ((status = USB_DeviceInitEndpoint(handle, &epInitStruct, &epCallback)) != kStatus_USB_Success) { + printf_debug("USB_DeviceInitEndpoint() failed: %d", status); + return; + } + } + + if (epc->out_state != NULL) { + epCallback.callbackFn = device_epN_control_callback_out; + + epInitStruct.endpointAddress = epaddr(ep, USB_OUT); + epInitStruct.maxPacketSize = epc->out_maxsize; + /* Initialize the endpoint OUT pipe */ + if ((status = USB_DeviceInitEndpoint(handle, &epInitStruct, &epCallback)) != kStatus_USB_Success) { + USB_DeviceDeinitEndpoint(handle, USB_CONTROL_ENDPOINT | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT)); + printf_debug("USB_DeviceInitEndpoint() failed: %d", status); + return; + } + } + + return; + +#if MIMXRT1064_USB_USE_USB1 +#endif /* MIMXRT1064_USB_USE_USB1 */ +} + +/** + * @brief Disables all the active endpoints except the endpoint zero. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void usb_lld_disable_endpoints(USBDriver *usbp) { + (void)usbp; + printf_debug("TODO: usb_lld_disable_endpoints()"); +#if MIMXRT1064_USB_USE_USB1 + // TODO: find active endpoints and disable + // USB_DeviceDeinitEndpoint(usb_device_handle handle, uint8_t endpointAddress); +#endif /* MIMXRT1064_USB_USE_USB1 */ +} + +static usbepstatus_t usb_lld_get_status(USBDriver *usbp, usbep_t ep, uint8_t direction) { + (void)usbp; + /* The NXP USB middleware does not expose any API to query whether an endpoint + * was initialized, so we just always assume an endpoint is active: */ + // TODO: maybe check if epCallback[].callbackFn != NULL? + usbepstatus_t epstatus = EP_STATUS_ACTIVE; + usb_status_t status; + usb_device_endpoint_status_struct_t endpointStatus; + endpointStatus.endpointAddress = epaddr(ep, direction); + if ((status = USB_DeviceGetStatus(handle, kUSB_DeviceStatusEndpoint, &endpointStatus)) != kStatus_USB_Success) { + printf_debug("USB_DeviceGetStatus() = %d", status); + return epstatus; + } + if (endpointStatus.endpointStatus == kUSB_DeviceEndpointStateStalled) { + return EP_STATUS_STALLED; + } + return epstatus; +} + +/** + * @brief Returns the status of an OUT endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @return The endpoint status. + * @retval EP_STATUS_DISABLED The endpoint is not active. + * @retval EP_STATUS_STALLED The endpoint is stalled. + * @retval EP_STATUS_ACTIVE The endpoint is active. + * + * @notapi + */ +usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep) { + (void)usbp; + if(ep > USB_MAX_ENDPOINTS) + return EP_STATUS_DISABLED; +#if MIMXRT1064_USB_USE_USB1 + printf_debug("usb_lld_get_status_out(ep=%d)", ep); + return usb_lld_get_status(usbp, ep, USB_OUT); +#endif /* MIMXRT1064_USB_USE_USB1 */ +} + +/** + * @brief Returns the status of an IN endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @return The endpoint status. + * @retval EP_STATUS_DISABLED The endpoint is not active. + * @retval EP_STATUS_STALLED The endpoint is stalled. + * @retval EP_STATUS_ACTIVE The endpoint is active. + * + * @notapi + */ +usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep) { + (void)usbp; + + if(ep > USB_MAX_ENDPOINTS) + return EP_STATUS_DISABLED; +#if MIMXRT1064_USB_USE_USB1 + printf_debug("usb_lld_get_status_in(ep=%d)", ep); + return usb_lld_get_status(usbp, ep, USB_IN); +#endif /* MIMXRT1064_USB_USE_USB1 */ +} + +/** + * @brief Reads a setup packet from the dedicated packet buffer. + * @details This function must be invoked in the context of the @p setup_cb + * callback in order to read the received setup packet. + * @pre In order to use this function the endpoint must have been + * initialized as a control endpoint. + * @post The endpoint is ready to accept another packet. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @param[out] buf buffer where to copy the packet data + * + * @notapi + */ +void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) { + (void)usbp; + (void)ep; + (void)buf; + + // We already populated usbp->setup in device_ep0_control_callback(), so no + // extra steps are required in this function. +} + +/** + * @brief Starts a receive operation on an OUT endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_start_out(USBDriver *usbp, usbep_t ep) { + const USBEndpointConfig *epc = usbp->epc[ep]; + USBOutEndpointState *osp = epc->out_state; + + printf_debug(" usb_lld_start_out(ep=%d) (receive)", ep); + + if (osp->rxsize > epc->out_maxsize) { + osp->rxsize = epc->out_maxsize; + } + + USB_DeviceRecvRequest(handle, epaddr(ep, USB_OUT), osp->rxbuf, osp->rxsize); +} + +/** + * @brief Starts a transmit operation on an IN endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @note Called from ISR and locked zone. + * @notapi + */ +void usb_lld_start_in(USBDriver *usbp, usbep_t ep) { + const USBEndpointConfig *epc = usbp->epc[ep]; + USBInEndpointState *isp = epc->in_state; + printf_debug(" usb_lld_start_in(ep=%d, txbuf=%x) (transmit)", ep, isp->txbuf); + + // Notably, at least with Linux, isp->txsize may exceed epc->in_maxsize, and + // capping it makes device enumeration fail. + + // Silence a warning about a mismatch in const-correctness between ChibiOS and + // the NXP SDK: ChibiOS uses const for isp->txbuf (but not for rxbuf, of + // course), but the NXP SDK APIs do not use const at all. + uint32_t p = (uint32_t)isp->txbuf; + uint8_t *buf = (uint8_t*)p; + + USB_DeviceSendRequest(handle, epaddr(ep, USB_IN), buf, isp->txsize); +} + +/** + * @brief Brings an OUT endpoint in the stalled state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) { + (void)usbp; + printf_debug("usb_lld_stall_out(ep=%d)", ep); +#if MIMXRT1064_USB_USE_USB1 + usb_status_t status; + if ((status = USB_DeviceStallEndpoint(handle, epaddr(ep, USB_OUT))) != kStatus_USB_Success) { + printf_debug(" stalling failed: %d", status); + } +#endif /* MIMXRT1064_USB_USE_USB1 */ +} + +/** + * @brief Brings an IN endpoint in the stalled state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_stall_in(USBDriver *usbp, usbep_t ep) { + (void)usbp; + printf_debug("usb_lld_stall_in(ep=%d)", ep); + +#if MIMXRT1064_USB_USE_USB1 + usb_status_t status; + if ((status = USB_DeviceStallEndpoint(handle, epaddr(ep, USB_IN))) != kStatus_USB_Success) { + printf_debug(" stalling failed: %d", status); + } +#endif /* MIMXRT1064_USB_USE_USB1 */ +} + +/** + * @brief Brings an OUT endpoint in the active state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_clear_out(USBDriver *usbp, usbep_t ep) { + (void)usbp; + printf_debug("usb_lld_clear_out(ep=%d)", ep); +#if MIMXRT1064_USB_USE_USB1 + usb_status_t status; + if ((status = USB_DeviceUnstallEndpoint(handle, epaddr(ep, USB_OUT))) != kStatus_USB_Success) { + printf_debug(" unstalling failed: %d", status); + } +#endif /* MIMXRT1064_USB_USE_USB1 */ +} + +/** + * @brief Brings an IN endpoint in the active state. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_clear_in(USBDriver *usbp, usbep_t ep) { + (void)usbp; + printf_debug("usb_lld_clear_in(ep=%d)", ep); +#if MIMXRT1064_USB_USE_USB1 + usb_status_t status; + if ((status = USB_DeviceUnstallEndpoint(handle, epaddr(ep, USB_IN))) != kStatus_USB_Success) { + printf_debug(" unstalling failed: %d", status); + } +#endif /* MIMXRT1064_USB_USE_USB1 */ +} + +#endif /* HAL_USE_USB */ + +/** @} */ diff --git a/os/hal/ports/MIMXRT1064/LLD/USBHSv1/hal_usb_lld.h b/os/hal/ports/MIMXRT1064/LLD/USBHSv1/hal_usb_lld.h new file mode 100644 index 0000000000..f9c89128ed --- /dev/null +++ b/os/hal/ports/MIMXRT1064/LLD/USBHSv1/hal_usb_lld.h @@ -0,0 +1,451 @@ +/* + ChibiOS - Copyright (C) 2015 RedoX https://github.com/RedoXyde/ + (C) 2015-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 USBHSv1/hal_usb_lld.h + * @brief MIMXRT1064 USB subsystem low level driver header. + * + * @addtogroup USB + * @{ + */ + +#ifndef HAL_USB_LLD_H_ +#define HAL_USB_LLD_H_ + +#if HAL_USE_USB || defined(__DOXYGEN__) + +#include "usb_device_config.h" +#include "usb.h" +#include "usb_device.h" +#include "usb_device_dci.h" +#include "usb_device_ehci.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Maximum endpoint address. + */ +#define USB_MAX_ENDPOINTS 7 + +#if USB_DEVICE_CONFIG_ENDPOINTS != USB_MAX_ENDPOINTS +#error "Mismatch: USB_DEVICE_CONFIG_ENDPOINTS != USB_MAX_ENDPOINTS" +#endif + +/** + * @brief Status stage handling method. + */ +#define USB_EP0_STATUS_STAGE USB_EP0_STATUS_STAGE_SW + +/** + * @brief Address ack handling + */ +#define USB_SET_ADDRESS_ACK_HANDLING USB_SET_ADDRESS_ACK_SW + +/** + * @brief This device requires the address change after the status packet. + */ +#define USB_SET_ADDRESS_MODE USB_EARLY_SET_ADDRESS + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief USB1 driver enable switch. + * @details If set to @p TRUE the support for USB1 is included. + * @note The default is @p TRUE. + */ +#if !defined(MIMXRT1064_USB_USE_USB1) || defined(__DOXYGEN__) +#define MIMXRT1064_USB_USE_USB1 TRUE +#endif + +#if !defined(MIMXRT1064_USB1_IS_USBOTG) +#define MIMXRT1064_USB1_IS_USBOTG TRUE +#endif + +/** + * @brief USB1 interrupt priority level setting. + */ +#if !defined(MIMXRT1064_USB_USB1_IRQ_PRIORITY)|| defined(__DOXYGEN__) +#define MIMXRT1064_USB_USB1_IRQ_PRIORITY 3 +#endif + +#if !defined(MIMXRT1064_USB_ENDPOINTS) || defined(__DOXYGEN__) +#define MIMXRT1064_USB_ENDPOINTS (USB_MAX_ENDPOINTS+1) +#endif + +/** + * @brief Host wake-up procedure duration. + */ +#if !defined(USB_HOST_WAKEUP_DURATION) || defined(__DOXYGEN__) +#define USB_HOST_WAKEUP_DURATION 2 +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if MIMXRT1064_USB_USE_USB1 && !MIMXRT1064_HAS_USB +#error "USB not present in the selected device" +#endif + +#if !MIMXRT1064_USB_USE_USB1 +#error "USB driver activated but no USB peripheral assigned" +#endif + +#if MIMXRT1064_USB_USE_USB1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(MIMXRT1064_USB_USB1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to MIMXRT1064_USB_USB1_IRQ_PRIORITY" +#endif + +#if !defined(MIMXRT1064_USB_OTG1_IRQ_VECTOR) +#error "MIMXRT1064_USB_OTG1_IRQ_VECTOR not defined" +#endif + +#if (USB_HOST_WAKEUP_DURATION < 2) || (USB_HOST_WAKEUP_DURATION > 15) +#error "invalid USB_HOST_WAKEUP_DURATION setting, it must be between 2 and 15" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of an IN endpoint state structure. + */ +typedef struct { + /** + * @brief Requested transmit transfer size. + */ + size_t txsize; + /** + * @brief Transmitted bytes so far. + */ + size_t txcnt; + /** + * @brief Pointer to the transmission linear buffer. + */ + const uint8_t *txbuf; +#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__) + /** + * @brief Waiting thread. + */ + thread_reference_t thread; +#endif +} USBInEndpointState; + +/** + * @brief Type of an OUT endpoint state structure. + */ +typedef struct { + /** + * @brief Requested receive transfer size. + */ + size_t rxsize; + /** + * @brief Received bytes so far. + */ + size_t rxcnt; + /** + * @brief Pointer to the receive linear buffer. + */ + uint8_t *rxbuf; +#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__) + /** + * @brief Waiting thread. + */ + thread_reference_t thread; +#endif + /* End of the mandatory fields.*/ +} USBOutEndpointState; + +/** + * @brief Type of an USB endpoint configuration structure. + * @note Platform specific restrictions may apply to endpoints. + */ +typedef struct { + /** + * @brief Type and mode of the endpoint. + */ + uint32_t ep_mode; + /** + * @brief Setup packet notification callback. + * @details This callback is invoked when a setup packet has been + * received. + * @post The application must immediately call @p usbReadPacket() in + * order to access the received packet. + * @note This field is only valid for @p USB_EP_MODE_TYPE_CTRL + * endpoints, it should be set to @p NULL for other endpoint + * types. + */ + usbepcallback_t setup_cb; + /** + * @brief IN endpoint notification callback. + * @details This field must be set to @p NULL if callback is not required. + */ + usbepcallback_t in_cb; + /** + * @brief OUT endpoint notification callback. + * @details This field must be set to @p NULL if callback is not required. + */ + usbepcallback_t out_cb; + /** + * @brief IN endpoint maximum packet size. + * @details This field must be set to zero if the IN endpoint is not used. + */ + uint16_t in_maxsize; + /** + * @brief OUT endpoint maximum packet size. + * @details This field must be set to zero if the OUT endpoint is not used. + */ + uint16_t out_maxsize; + /** + * @brief @p USBEndpointState associated to the IN endpoint. + * @details This field must be set to @p NULL if the IN endpoint is not + * used. + */ + USBInEndpointState *in_state; + /** + * @brief @p USBEndpointState associated to the OUT endpoint. + * @details This field must be set to @p NULL if the OUT endpoint is not + * used. + */ + USBOutEndpointState *out_state; + /* End of the mandatory fields.*/ + /** + * @brief Reserved field, not currently used. + * @note Initialize this field to 1 in order to be forward compatible. + */ + uint16_t ep_buffers; + /** + * @brief Pointer to a buffer for setup packets. + * @details Setup packets require a dedicated 8-bytes buffer, set this + * field to @p NULL for non-control endpoints. + */ + uint8_t *setup_buf; +} USBEndpointConfig; + +/** + * @brief Type of an USB driver configuration structure. + */ +typedef struct { + /** + * @brief USB events callback. + * @details This callback is invoked when an USB driver event is registered. + */ + usbeventcb_t event_cb; + /** + * @brief Device GET_DESCRIPTOR request callback. + * @note This callback is mandatory and cannot be set to @p NULL. + */ + usbgetdescriptor_t get_descriptor_cb; + /** + * @brief Requests hook callback. + * @details This hook allows to be notified of standard requests or to + * handle non standard requests. + */ + usbreqhandler_t requests_hook_cb; + /** + * @brief Start Of Frame callback. + */ + usbcallback_t sof_cb; + /* End of the mandatory fields.*/ +} USBConfig; + +/** + * @brief Structure representing an USB driver. + */ +struct USBDriver { + /** + * @brief Driver state. + */ + usbstate_t state; + /** + * @brief Current configuration data. + */ + const USBConfig *config; + /** + * @brief Bit map of the transmitting IN endpoints. + */ + uint16_t transmitting; + /** + * @brief Bit map of the receiving OUT endpoints. + */ + uint16_t receiving; + /** + * @brief Active endpoints configurations. + */ + const USBEndpointConfig *epc[USB_MAX_ENDPOINTS + 1]; + /** + * @brief Fields available to user, it can be used to associate an + * application-defined handler to an IN endpoint. + * @note The base index is one, the endpoint zero does not have a + * reserved element in this array. + */ + void *in_params[USB_MAX_ENDPOINTS]; + /** + * @brief Fields available to user, it can be used to associate an + * application-defined handler to an OUT endpoint. + * @note The base index is one, the endpoint zero does not have a + * reserved element in this array. + */ + void *out_params[USB_MAX_ENDPOINTS]; + /** + * @brief Endpoint 0 state. + */ + usbep0state_t ep0state; + /** + * @brief Next position in the buffer to be transferred through endpoint 0. + */ + uint8_t *ep0next; + /** + * @brief Number of bytes yet to be transferred through endpoint 0. + */ + size_t ep0n; + /** + * @brief Endpoint 0 end transaction callback. + */ + usbcallback_t ep0endcb; + /** + * @brief Setup packet buffer. + */ + uint8_t setup[8]; + /** + * @brief Current USB device status. + */ + uint16_t status; + /** + * @brief Assigned USB address. + */ + uint8_t address; + /** + * @brief Current USB device configuration. + */ + uint8_t configuration; + /** + * @brief State of the driver when a suspend happened. + */ + usbstate_t saved_state; +#if defined(USB_DRIVER_EXT_FIELDS) + USB_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the next address in the packet memory. + */ + uint32_t pmnext; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Returns the current frame number. + * + * @param[in] usbp pointer to the @p USBDriver object + * @return The current frame number. + * + * @notapi + */ +#define usb_lld_get_frame_number(usbp) ((USB1->FRMNUMH<<8)|USB1->FRMNUML) + +/** + * @brief Returns the exact size of a receive transaction. + * @details The received size can be different from the size specified in + * @p usbStartReceiveI() because the last packet could have a size + * different from the expected one. + * @pre The OUT endpoint must have been configured in transaction mode + * in order to use this function. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @return Received data size. + * + * @notapi + */ +#define usb_lld_get_transaction_size(usbp, ep) \ + ((usbp)->epc[ep]->out_state->rxcnt) + +/** + * @brief Connects the USB device. + * + * @api + */ +#if !defined(usb_lld_connect_bus) +#define usb_lld_connect_bus(usbp) do { usb_device_struct_t *dev_handle = (usb_device_struct_t *)handle; (void)USB_DeviceEhciControl((usb_device_ehci_state_struct_t *)(dev_handle->controllerHandle), kUSB_DeviceControlRun, NULL); } while (0) +#endif + +/** + * @brief Disconnect the USB device. + * + * @api + */ +#if !defined(usb_lld_disconnect_bus) +#define usb_lld_disconnect_bus(usbp) do { usb_device_struct_t *dev_handle = (usb_device_struct_t *)handle; (void)USB_DeviceEhciControl((usb_device_ehci_state_struct_t *)(dev_handle->controllerHandle), kUSB_DeviceControlStop, NULL); } while (0) +#endif + +/** + * @brief Start of host wake-up procedure. + * @todo Test and wire up, if supported. + * + * @notapi + */ +#define usb_lld_wakeup_host(usbp) \ + do{ \ + } while (false) + + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if MIMXRT1064_USB_USE_USB1 && !defined(__DOXYGEN__) +extern USBDriver USBD1; +extern usb_device_handle handle; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void usb_lld_init(void); + void usb_lld_start(USBDriver *usbp); + void usb_lld_stop(USBDriver *usbp); + void usb_lld_reset(USBDriver *usbp); + void usb_lld_set_address(USBDriver *usbp); + void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep); + void usb_lld_disable_endpoints(USBDriver *usbp); + usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep); + usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep); + void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf); + void usb_lld_start_out(USBDriver *usbp, usbep_t ep); + void usb_lld_start_in(USBDriver *usbp, usbep_t ep); + void usb_lld_stall_out(USBDriver *usbp, usbep_t ep); + void usb_lld_stall_in(USBDriver *usbp, usbep_t ep); + void usb_lld_clear_out(USBDriver *usbp, usbep_t ep); + void usb_lld_clear_in(USBDriver *usbp, usbep_t ep); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_USB */ + +#endif /* HAL_USB_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/MIMXRT1064/LLD/USBHSv1/usb_device_config.h b/os/hal/ports/MIMXRT1064/LLD/USBHSv1/usb_device_config.h new file mode 100644 index 0000000000..c00e7bff5a --- /dev/null +++ b/os/hal/ports/MIMXRT1064/LLD/USBHSv1/usb_device_config.h @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016 - 2017 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _USB_DEVICE_CONFIG_H_ +#define _USB_DEVICE_CONFIG_H_ + +/******************************************************************************* + * Definitions + ******************************************************************************/ +/*! + * @addtogroup usb_device_configuration + * @{ + */ + +/*! + * @name Hardware instance define + * @{ + */ + +/*! @brief KHCI instance count */ +#define USB_DEVICE_CONFIG_KHCI (0U) + +/*! @brief EHCI instance count */ +#define USB_DEVICE_CONFIG_EHCI (1U) + +/*! @brief LPC USB IP3511 FS instance count */ +#define USB_DEVICE_CONFIG_LPCIP3511FS (0U) + +/*! @brief LPC USB IP3511 HS instance count */ +#define USB_DEVICE_CONFIG_LPCIP3511HS (0U) + +/*! @brief Device instance count, the sum of KHCI and EHCI instance counts*/ +#define USB_DEVICE_CONFIG_NUM \ + (USB_DEVICE_CONFIG_KHCI + USB_DEVICE_CONFIG_EHCI + USB_DEVICE_CONFIG_LPCIP3511FS + USB_DEVICE_CONFIG_LPCIP3511HS) + +/* @} */ + +/*! + * @name class instance define + * @{ + */ + +/*! @brief HID instance count */ +#ifndef USB_DEVICE_CONFIG_HID +#define USB_DEVICE_CONFIG_HID (0U) +#endif + +/*! @brief CDC ACM instance count */ +#ifndef USB_DEVICE_CONFIG_CDC_ACM +#define USB_DEVICE_CONFIG_CDC_ACM (0U) +#endif +#ifndef USB_DEVICE_CONFIG_CDC_RNDIS +#define USB_DEVICE_CONFIG_CDC_RNDIS (0U) +#endif + +/*! @brief MSC instance count */ +#ifndef USB_DEVICE_CONFIG_MSC +#define USB_DEVICE_CONFIG_MSC (0U) +#endif + +/*! @brief Audio instance count */ +#ifndef USB_DEVICE_CONFIG_AUDIO +#define USB_DEVICE_CONFIG_AUDIO (0U) +#endif + +/*! @brief PHDC instance count */ +#ifndef USB_DEVICE_CONFIG_PHDC +#define USB_DEVICE_CONFIG_PHDC (0U) +#endif + +/*! @brief Video instance count */ +#ifndef USB_DEVICE_CONFIG_VIDEO +#define USB_DEVICE_CONFIG_VIDEO (0U) +#endif + +/*! @brief CCID instance count */ +#ifndef USB_DEVICE_CONFIG_CCID +#define USB_DEVICE_CONFIG_CCID (0U) +#endif + +/*! @brief Printer instance count */ +#ifndef USB_DEVICE_CONFIG_PRINTER +#define USB_DEVICE_CONFIG_PRINTER (0U) +#endif + +/*! @brief DFU instance count */ +#ifndef USB_DEVICE_CONFIG_DFU +#define USB_DEVICE_CONFIG_DFU (0U) +#endif + +/* @} */ + +/*! @brief Whether device is self power. 1U supported, 0U not supported */ +#define USB_DEVICE_CONFIG_SELF_POWER (1U) + +/*! @brief How many endpoints are supported in the stack. */ +#define USB_DEVICE_CONFIG_ENDPOINTS (7U) + +/*! @brief Whether the device task is enabled. */ +#define USB_DEVICE_CONFIG_USE_TASK (0U) + +/*! @brief How many the notification message are supported when the device task is enabled. */ +#define USB_DEVICE_CONFIG_MAX_MESSAGES (8U) + +/*! @brief Whether test mode enabled. */ +#define USB_DEVICE_CONFIG_USB20_TEST_MODE (0U) + +/*! @brief Whether device CV test is enabled. */ +#define USB_DEVICE_CONFIG_CV_TEST (0U) + +/*! @brief Whether device compliance test is enabled. If the macro is enabled, + the test mode and CV test macroes will be set.*/ +#define USB_DEVICE_CONFIG_COMPLIANCE_TEST (0U) + +#if ((defined(USB_DEVICE_CONFIG_COMPLIANCE_TEST)) && (USB_DEVICE_CONFIG_COMPLIANCE_TEST > 0U)) + +/*! @brief Undefine the macro USB_DEVICE_CONFIG_USB20_TEST_MODE. */ +#undef USB_DEVICE_CONFIG_USB20_TEST_MODE +/*! @brief Undefine the macro USB_DEVICE_CONFIG_CV_TEST. */ +#undef USB_DEVICE_CONFIG_CV_TEST + +/*! @brief enable the test mode. */ +#define USB_DEVICE_CONFIG_USB20_TEST_MODE (1U) + +/*! @brief enable the CV test */ +#define USB_DEVICE_CONFIG_CV_TEST (1U) + +#endif + +#if ((defined(USB_DEVICE_CONFIG_KHCI)) && (USB_DEVICE_CONFIG_KHCI > 0U)) + +/*! @brief The MAX buffer length for the KHCI DMA workaround.*/ +#define USB_DEVICE_CONFIG_KHCI_DMA_ALIGN_BUFFER_LENGTH (64U) +#endif + +#if ((defined(USB_DEVICE_CONFIG_EHCI)) && (USB_DEVICE_CONFIG_EHCI > 0U)) +/*! @brief How many the DTD are supported. */ +#define USB_DEVICE_CONFIG_EHCI_MAX_DTD (16U) + +/*! @brief Whether the EHCI ID pin detect feature enabled. */ +#define USB_DEVICE_CONFIG_EHCI_ID_PIN_DETECT (0U) +#endif + +/*! @brief Whether the keep alive feature enabled. */ +#define USB_DEVICE_CONFIG_KEEP_ALIVE_MODE (0U) + +/*! @brief Whether the transfer buffer is cache-enabled or not. */ +#ifndef USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE +#define USB_DEVICE_CONFIG_BUFFER_PROPERTY_CACHEABLE (0U) +#endif +/*! @brief Whether the low power mode is enabled or not. */ +#define USB_DEVICE_CONFIG_LOW_POWER_MODE (0U) + +#if ((defined(USB_DEVICE_CONFIG_LOW_POWER_MODE)) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U)) +/*! @brief Whether device remote wakeup supported. 1U supported, 0U not supported */ +#define USB_DEVICE_CONFIG_REMOTE_WAKEUP (0U) + +/*! @brief Whether LPM is supported. 1U supported, 0U not supported */ +#define USB_DEVICE_CONFIG_LPM_L1 (0U) +#else +/*! @brief The device remote wakeup is unsupported. */ +#define USB_DEVICE_CONFIG_REMOTE_WAKEUP (0U) +#endif + +/*! @brief Whether the device detached feature is enabled or not. */ +#define USB_DEVICE_CONFIG_DETACH_ENABLE (0U) + +/*! @brief Whether handle the USB bus error. */ +#define USB_DEVICE_CONFIG_ERROR_HANDLING (0U) + +/* @} */ + +#endif /* _USB_DEVICE_CONFIG_H_ */ diff --git a/os/hal/ports/MIMXRT1064/MIMXRT1064/bootable_image.c b/os/hal/ports/MIMXRT1064/MIMXRT1064/bootable_image.c new file mode 100644 index 0000000000..4943c2fa66 --- /dev/null +++ b/os/hal/ports/MIMXRT1064/MIMXRT1064/bootable_image.c @@ -0,0 +1,339 @@ +/* + 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. + + Portions Copyright (C) 2017 PJRC.COM, LLC. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + 1. The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 2. If the Software is incorporated into a build system that allows + selection among a list of target devices, then similar target + devices manufactured by PJRC.COM must be included in the list of + target devices and selectable in the same manner. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + +*/ + +/** + * @file MIMXRT1064/bootable_image.c + * @brief Additional information for the NXP BootROM. + * With these extra sections, we define a bootable image, + * allowing the BootROM to start our code from flash. + * @note https://www.nxp.com/docs/en/nxp/application-notes/AN12238.pdf + * @note https://www.nxp.com/docs/en/application-note/AN12107.pdf + * + * @addtogroup HAL + * @{ + */ + +#include "hal.h" + +#include "printf_debug.h" + +#include "clock_config.h" + +#define NVIC_NUM_INTERRUPTS 160 +extern uint32_t _vectors[NVIC_NUM_INTERRUPTS]; + +extern void Reset_Handler(void); + +// trampoline_reset_handler initializes FlexRAM, then jumps to the ChibiOS +// Reset_Handler. This is required because the ChibiOS crt0 does not provide a +// hook in a suitable place to integrate FlexRAM configuration. +// +// Note that when loading an image into the debugger, the ELF entry point +// (specified by ENTRY(Reset_Handler) in rules_code.ld) is used directly, and +// our trampoline_reset_handler that we configure in the Image Vector Table +// (IVT) is not called. Instead, the debugger Connect Script +// (e.g. rt1060_connect.scp) is responsible for setting up FlexRAM. Instead of +// modifying the Connect Script accordingly, it might be easier to change +// ENTRY(Reset_Handler) to ENTRY(trampoline_reset_handler) for debugging. +__attribute__((target("thumb"), aligned(2))) +void trampoline_reset_handler(void) { + __disable_irq(); + + // Switch to final VTOR as quickly as possible to have fault handlers set up + // (e.g. HardFault) for easier debugging. When encountering a fault without a + // usable VTOR table, the MCU will raise another fault and end up in lockup. + SCB->VTOR = (uint32_t)&_vectors; + + IOMUXC_GPR->GPR17 = 0xaaaaaaaa; + __DSB(); + __ISB(); + IOMUXC_GPR->GPR16 &= ~IOMUXC_GPR_GPR16_INIT_ITCM_EN_MASK; + IOMUXC_GPR->GPR16 |= + IOMUXC_GPR_GPR16_FLEXRAM_BANK_CFG_SEL(1) | + IOMUXC_GPR_GPR16_INIT_DTCM_EN(1) | + IOMUXC_GPR_GPR16_INIT_ITCM_EN(0); + + __DSB(); + __ISB(); + + uint32_t current_gpr14 = IOMUXC_GPR->GPR14; + current_gpr14 &= ~IOMUXC_GPR_GPR14_CM7_CFGDTCMSZ_MASK; + current_gpr14 |= IOMUXC_GPR_GPR14_CM7_CFGDTCMSZ(10); + current_gpr14 &= ~IOMUXC_GPR_GPR14_CM7_CFGITCMSZ_MASK; + current_gpr14 |= IOMUXC_GPR_GPR14_CM7_CFGITCMSZ(0); + IOMUXC_GPR->GPR14 = current_gpr14; + + __DSB(); + __ISB(); + + Reset_Handler(); +} + +// IMXRT1060RM: 9.5.5 Exception handling +// A minimal vector table with only the first 2 elements, i.e. initial SP (stack +// pointer) and PC (program count) values. +__attribute__ ((section(".vectors"), used, aligned(1024))) +const uint32_t vector_table[] = { + // Initial SP (stack pointer) value when booting. + // Will be updated to point to DTCM FlexRAM by ChibiOS crt0_v7m.S. + 0x20201000, // OCRAM, always available regardless of FlexRAM setting. + + // Initial PC (program count) value when booting. + (uint32_t)&trampoline_reset_handler, // jumps to Reset_Handler +}; + +/* See section 2.5.2 in https://www.nxp.com/docs/en/application-note/AN12107.pdf */ +__attribute__ ((section(".bootdata"), used)) +const uint32_t BootData[3] = { + // destination address is equal to the external flash address, so the i.MX + // BootROM will skip any remaining memory copies and start up the application + // binary directly in the flash address space. + // See section 3.2.2 in https://www.nxp.com/docs/en/nxp/application-notes/AN12238.pdf + 0x70000000, // absolute address of the bootable image + // The following size normally determines how many bytes are copied from + // flash to RAM, but because the destination address is equal to the + // flash address, no copying is taking place. + // + // So, logically, we would set this field to 0, but 32 is the minimum + // size that works in practice. My guess is that 32 is the size of the + // IVT, and perhaps the BootROM code needs the IVT to be present and + // accounted for. The NXP examples just set this to the size of the + // flash, so we do the same: + 4096*1024, + 0, // plugin flag, 0 = normal boot image +}; + + +/* See section 2.5.1 in https://www.nxp.com/docs/en/application-note/AN12107.pdf */ +__attribute__ ((section(".ivt"), used)) +const uint32_t ImageVectorTable[8] = { + 0x402000D1, // header + (uint32_t)vector_table, // docs are wrong, needs to be vec table, not start addr + 0, // reserved + + // DCD (Device Configuration Data), e.g. for SDRAM during boot. Note + // that the BootROM of the i.MX RT 1060 does not actually support DCD, + // so this field must always be set to 0: + // + // IMXRT1060RM: NOTE: The DCD is not supported in the BootROM, in this + // device. It must be set to 0x00. + 0, + + (uint32_t)BootData, // abs address of boot data + (uint32_t)ImageVectorTable, // self + 0, // command sequence file + 0 // reserved +}; + +__attribute__ ((section(".flashconfig"), used)) +uint32_t FlexSPI_NOR_Config[128] = { + // 448 byte common FlexSPI configuration block, 8.6.3.1 page 223 (RT1060 rev 0) + // MCU_Flashloader_Reference_Manual.pdf, 8.2.1, Table 8-2, page 72-75 + 0x42464346, // Tag 0x00 + 0x56010000, // Version + 0, // reserved + 0x00030301, // columnAdressWidth,dataSetupTime,dataHoldTime,readSampleClkSrc + + 0x00000000, // waitTimeCfgCommands,-,deviceModeCfgEnable + 0, // deviceModeSeq + 0, // deviceModeArg + 0x00000000, // -,-,-,configCmdEnable + + 0, // configCmdSeqs 0x20 + 0, + 0, + 0, + + 0, // cfgCmdArgs 0x30 + 0, + 0, + 0, + + 0x00000000, // controllerMiscOption 0x40 + // The Teensy 4 config used to run the FlexSPI Serial Clock at 60 MHz: + // https://github.com/PaulStoffregen/cores/commit/c346fc36ed97dcaed2fa1d70626fbd80cf35586d + // whereas NXP is running it with 100 MHz. With the old default of 60 + // MHz, I occasionally get hard faults when reading data from flash. + 0x00080401, // lutCustomSeqEnable,serialClkFreq,sflashPadType,deviceType + 0, // reserved + 0, // reserved + + 0x00400000, // sflashA1Size 0x50 + + 0, // sflashA2Size + 0, // sflashB1Size + 0, // sflashB2Size + + 0, // csPadSettingOverride 0x60 + 0, // sclkPadSettingOverride + 0, // dataPadSettingOverride + 0, // dqsPadSettingOverride + + 0, // timeoutInMs 0x70 + 0, // commandInterval + 0, // dataValidTime + 0x00000000, // busyBitPolarity,busyOffset + + 0x0A1804EB, // lookupTable[0] 0x80 + 0x26043206, // lookupTable[1] + 0, // lookupTable[2] + 0, // lookupTable[3] + + 0x24040405, // lookupTable[4] 0x90 + 0, // lookupTable[5] + 0, // lookupTable[6] + 0, // lookupTable[7] + + 0, // lookupTable[8] 0xA0 + 0, // lookupTable[9] + 0, // lookupTable[10] + 0, // lookupTable[11] + + 0x00000406, // lookupTable[12] 0xB0 + 0, // lookupTable[13] + 0, // lookupTable[14] + 0, // lookupTable[15] + + 0, // lookupTable[16] 0xC0 + 0, // lookupTable[17] + 0, // lookupTable[18] + 0, // lookupTable[19] + + 0x08180420, // lookupTable[20] 0xD0 + 0, // lookupTable[21] + 0, // lookupTable[22] + 0, // lookupTable[23] + + 0, // lookupTable[24] 0xE0 + 0, // lookupTable[25] + 0, // lookupTable[26] + 0, // lookupTable[27] + + 0, // lookupTable[28] 0xF0 + 0, // lookupTable[29] + 0, // lookupTable[30] + 0, // lookupTable[31] + + 0x081804D8, // lookupTable[32] 0x100 + 0, // lookupTable[33] + 0, // lookupTable[34] + 0, // lookupTable[35] + + 0x08180402, // lookupTable[36] 0x110 + 0x00002004, // lookupTable[37] + 0, // lookupTable[38] + 0, // lookupTable[39] + + 0, // lookupTable[40] 0x120 + 0, // lookupTable[41] + 0, // lookupTable[42] + 0, // lookupTable[43] + + 0x00000460, // lookupTable[44] 0x130 + 0, // lookupTable[45] + 0, // lookupTable[46] + 0, // lookupTable[47] + + 0, // lookupTable[48] 0x140 + 0, // lookupTable[49] + 0, // lookupTable[50] + 0, // lookupTable[51] + + 0, // lookupTable[52] 0x150 + 0, // lookupTable[53] + 0, // lookupTable[54] + 0, // lookupTable[55] + + 0, // lookupTable[56] 0x160 + 0, // lookupTable[57] + 0, // lookupTable[58] + 0, // lookupTable[59] + + 0, // lookupTable[60] 0x170 + 0, // lookupTable[61] + 0, // lookupTable[62] + 0, // lookupTable[63] + + 0, // LUT 0: Read 0x180 + 0, // LUT 1: ReadStatus + 0, // LUT 3: WriteEnable + 0, // LUT 5: EraseSector + + 0, // LUT 9: PageProgram 0x190 + 0, // LUT 11: ChipErase + 0, // LUT 15: Dummy + 0, // LUT unused? + + 0, // LUT unused? 0x1A0 + 0, // LUT unused? + 0, // LUT unused? + 0, // LUT unused? + + 0, // reserved 0x1B0 + 0, // reserved + 0, // reserved + 0, // reserved + + // 64 byte Serial NOR configuration block, 8.6.3.2, page 346 + + 256, // pageSize 0x1C0 + 4096, // sectorSize + 1, // ipCmdSerialClkFreq + 0, // reserved + + 0x00010000, // block size 0x1D0 + 0, // reserved + 0, // reserved + 0, // reserved + + 0, // reserved 0x1E0 + 0, // reserved + 0, // reserved + 0, // reserved + + 0, // reserved 0x1F0 + 0, // reserved + 0, // reserved + 0 // reserved +}; diff --git a/os/hal/ports/MIMXRT1064/MIMXRT1064/clock_config.c b/os/hal/ports/MIMXRT1064/MIMXRT1064/clock_config.c new file mode 100644 index 0000000000..0a709a2d4c --- /dev/null +++ b/os/hal/ports/MIMXRT1064/MIMXRT1064/clock_config.c @@ -0,0 +1,516 @@ +/* + * Copyright 2018-2020 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * How to setup clock using clock driver functions: + * + * 1. Call CLOCK_InitXXXPLL() to configure corresponding PLL clock. + * + * 2. Call CLOCK_InitXXXpfd() to configure corresponding PLL pfd clock. + * + * 3. Call CLOCK_SetMux() to configure corresponding clock source for target clock out. + * + * 4. Call CLOCK_SetDiv() to configure corresponding clock divider for target clock out. + * + * 5. Call CLOCK_SetXtalFreq() to set XTAL frequency based on board settings. + * + */ + +/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +!!GlobalInfo +product: Clocks v7.0 +processor: MIMXRT1064xxxxA +package_id: MIMXRT1064DVL6A +mcu_data: ksdk2_0 +processor_version: 0.7.9 +board: MIMXRT1064-EVK + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ + +#include "clock_config.h" +#include "fsl_iomuxc.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/******************************************************************************* + * Variables + ******************************************************************************/ +/* System clock frequency. */ +extern uint32_t SystemCoreClock; + +/******************************************************************************* + ************************ BOARD_InitBootClocks function ************************ + ******************************************************************************/ +void BOARD_InitBootClocks(void) +{ + BOARD_BootClockRUN(); +} + +/******************************************************************************* + ********************** Configuration BOARD_BootClockRUN *********************** + ******************************************************************************/ +/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +!!Configuration +name: BOARD_BootClockRUN +called_from_default_init: true +outputs: +- {id: AHB_CLK_ROOT.outFreq, value: 600 MHz} +- {id: CAN_CLK_ROOT.outFreq, value: 40 MHz} +- {id: CKIL_SYNC_CLK_ROOT.outFreq, value: 32.768 kHz} +- {id: CLK_1M.outFreq, value: 1 MHz} +- {id: CLK_24M.outFreq, value: 24 MHz} +- {id: CSI_CLK_ROOT.outFreq, value: 12 MHz} +- {id: ENET1_TX_CLK.outFreq, value: 2.4 MHz} +- {id: ENET2_125M_CLK.outFreq, value: 1.2 MHz} +- {id: ENET2_TX_CLK.outFreq, value: 1.2 MHz} +- {id: ENET_125M_CLK.outFreq, value: 2.4 MHz} +- {id: ENET_25M_REF_CLK.outFreq, value: 1.2 MHz} +- {id: FLEXIO1_CLK_ROOT.outFreq, value: 30 MHz} +- {id: FLEXIO2_CLK_ROOT.outFreq, value: 30 MHz} +- {id: FLEXSPI2_CLK_ROOT.outFreq, value: 1440/11 MHz} +- {id: FLEXSPI_CLK_ROOT.outFreq, value: 1440/11 MHz} +- {id: GPT1_ipg_clk_highfreq.outFreq, value: 75 MHz} +- {id: GPT2_ipg_clk_highfreq.outFreq, value: 75 MHz} +- {id: IPG_CLK_ROOT.outFreq, value: 150 MHz} +- {id: LCDIF_CLK_ROOT.outFreq, value: 67.5 MHz} +- {id: LPI2C_CLK_ROOT.outFreq, value: 60 MHz} +- {id: LPSPI_CLK_ROOT.outFreq, value: 105.6 MHz} +- {id: LVDS1_CLK.outFreq, value: 1.2 GHz} +- {id: MQS_MCLK.outFreq, value: 1080/17 MHz} +- {id: PERCLK_CLK_ROOT.outFreq, value: 75 MHz} +- {id: PLL7_MAIN_CLK.outFreq, value: 24 MHz} +- {id: SAI1_CLK_ROOT.outFreq, value: 1080/17 MHz} +- {id: SAI1_MCLK1.outFreq, value: 1080/17 MHz} +- {id: SAI1_MCLK2.outFreq, value: 1080/17 MHz} +- {id: SAI1_MCLK3.outFreq, value: 30 MHz} +- {id: SAI2_CLK_ROOT.outFreq, value: 1080/17 MHz} +- {id: SAI2_MCLK1.outFreq, value: 1080/17 MHz} +- {id: SAI2_MCLK3.outFreq, value: 30 MHz} +- {id: SAI3_CLK_ROOT.outFreq, value: 1080/17 MHz} +- {id: SAI3_MCLK1.outFreq, value: 1080/17 MHz} +- {id: SAI3_MCLK3.outFreq, value: 30 MHz} +- {id: SEMC_CLK_ROOT.outFreq, value: 75 MHz} +- {id: SPDIF0_CLK_ROOT.outFreq, value: 30 MHz} +- {id: TRACE_CLK_ROOT.outFreq, value: 132 MHz} +- {id: UART_CLK_ROOT.outFreq, value: 80 MHz} +- {id: USDHC1_CLK_ROOT.outFreq, value: 198 MHz} +- {id: USDHC2_CLK_ROOT.outFreq, value: 198 MHz} +settings: +- {id: CCM.AHB_PODF.scale, value: '1', locked: true} +- {id: CCM.ARM_PODF.scale, value: '2', locked: true} +- {id: CCM.FLEXSPI2_PODF.scale, value: '2', locked: true} +- {id: CCM.FLEXSPI2_SEL.sel, value: CCM_ANALOG.PLL3_PFD0_CLK} +- {id: CCM.FLEXSPI_PODF.scale, value: '2', locked: true} +- {id: CCM.FLEXSPI_SEL.sel, value: CCM_ANALOG.PLL3_PFD0_CLK} +- {id: CCM.LPSPI_PODF.scale, value: '5', locked: true} +- {id: CCM.PERCLK_PODF.scale, value: '2', locked: true} +- {id: CCM.SEMC_PODF.scale, value: '8'} +- {id: CCM.TRACE_CLK_SEL.sel, value: CCM_ANALOG.PLL2_MAIN_CLK} +- {id: CCM.TRACE_PODF.scale, value: '4', locked: true} +- {id: CCM_ANALOG.PLL1_BYPASS.sel, value: CCM_ANALOG.PLL1} +- {id: CCM_ANALOG.PLL1_PREDIV.scale, value: '1', locked: true} +- {id: CCM_ANALOG.PLL1_VDIV.scale, value: '50', locked: true} +- {id: CCM_ANALOG.PLL2.denom, value: '1', locked: true} +- {id: CCM_ANALOG.PLL2.num, value: '0', locked: true} +- {id: CCM_ANALOG.PLL2_BYPASS.sel, value: CCM_ANALOG.PLL2_OUT_CLK} +- {id: CCM_ANALOG.PLL2_PFD0_BYPASS.sel, value: CCM_ANALOG.PLL2_PFD0} +- {id: CCM_ANALOG.PLL2_PFD1_BYPASS.sel, value: CCM_ANALOG.PLL2_PFD1} +- {id: CCM_ANALOG.PLL2_PFD2_BYPASS.sel, value: CCM_ANALOG.PLL2_PFD2} +- {id: CCM_ANALOG.PLL2_PFD3_BYPASS.sel, value: CCM_ANALOG.PLL2_PFD3} +- {id: CCM_ANALOG.PLL3_BYPASS.sel, value: CCM_ANALOG.PLL3} +- {id: CCM_ANALOG.PLL3_PFD0_BYPASS.sel, value: CCM_ANALOG.PLL3_PFD0} +- {id: CCM_ANALOG.PLL3_PFD0_DIV.scale, value: '33', locked: true} +- {id: CCM_ANALOG.PLL3_PFD0_MUL.scale, value: '18', locked: true} +- {id: CCM_ANALOG.PLL3_PFD1_BYPASS.sel, value: CCM_ANALOG.PLL3_PFD1} +- {id: CCM_ANALOG.PLL3_PFD2_BYPASS.sel, value: CCM_ANALOG.PLL3_PFD2} +- {id: CCM_ANALOG.PLL3_PFD3_BYPASS.sel, value: CCM_ANALOG.PLL3_PFD3} +- {id: CCM_ANALOG.PLL4.denom, value: '50'} +- {id: CCM_ANALOG.PLL4.div, value: '47'} +- {id: CCM_ANALOG.PLL5.denom, value: '1'} +- {id: CCM_ANALOG.PLL5.div, value: '31', locked: true} +- {id: CCM_ANALOG.PLL5.num, value: '0'} +- {id: CCM_ANALOG.PLL5_BYPASS.sel, value: CCM_ANALOG.PLL5_POST_DIV} +- {id: CCM_ANALOG.PLL5_POST_DIV.scale, value: '2', locked: true} +- {id: CCM_ANALOG.VIDEO_DIV.scale, value: '4', locked: true} +- {id: CCM_ANALOG_PLL_ENET_POWERDOWN_CFG, value: 'Yes'} +- {id: CCM_ANALOG_PLL_USB1_POWER_CFG, value: 'Yes'} +- {id: CCM_ANALOG_PLL_VIDEO_POWERDOWN_CFG, value: 'No'} +sources: +- {id: XTALOSC24M.RTC_OSC.outFreq, value: 32.768 kHz, enabled: true} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ + +/******************************************************************************* + * Variables for BOARD_BootClockRUN configuration + ******************************************************************************/ +const clock_arm_pll_config_t armPllConfig_BOARD_BootClockRUN = + { + .loopDivider = 100, /* PLL loop divider, Fout = Fin * 50 */ + .src = 0, /* Bypass clock source, 0 - OSC 24M, 1 - CLK1_P and CLK1_N */ + }; +const clock_sys_pll_config_t sysPllConfig_BOARD_BootClockRUN = + { + .loopDivider = 1, /* PLL loop divider, Fout = Fin * ( 20 + loopDivider*2 + numerator / denominator ) */ + .numerator = 0, /* 30 bit numerator of fractional loop divider */ + .denominator = 1, /* 30 bit denominator of fractional loop divider */ + .src = 0, /* Bypass clock source, 0 - OSC 24M, 1 - CLK1_P and CLK1_N */ + }; +const clock_usb_pll_config_t usb1PllConfig_BOARD_BootClockRUN = + { + .loopDivider = 0, /* PLL loop divider, Fout = Fin * 20 */ + .src = 0, /* Bypass clock source, 0 - OSC 24M, 1 - CLK1_P and CLK1_N */ + }; +const clock_video_pll_config_t videoPllConfig_BOARD_BootClockRUN = + { + .loopDivider = 31, /* PLL loop divider, Fout = Fin * ( loopDivider + numerator / denominator ) */ + .postDivider = 8, /* Divider after PLL */ + .numerator = 0, /* 30 bit numerator of fractional loop divider, Fout = Fin * ( loopDivider + numerator / denominator ) */ + .denominator = 1, /* 30 bit denominator of fractional loop divider, Fout = Fin * ( loopDivider + numerator / denominator ) */ + .src = 0, /* Bypass clock source, 0 - OSC 24M, 1 - CLK1_P and CLK1_N */ + }; +/******************************************************************************* + * Code for BOARD_BootClockRUN configuration + ******************************************************************************/ +void BOARD_BootClockRUN(void) +{ + /* Init RTC OSC clock frequency. */ + CLOCK_SetRtcXtalFreq(32768U); + /* Enable 1MHz clock output. */ + XTALOSC24M->OSC_CONFIG2 |= XTALOSC24M_OSC_CONFIG2_ENABLE_1M_MASK; + /* Use free 1MHz clock output. */ + XTALOSC24M->OSC_CONFIG2 &= ~XTALOSC24M_OSC_CONFIG2_MUX_1M_MASK; + /* Set XTAL 24MHz clock frequency. */ + CLOCK_SetXtalFreq(24000000U); + /* Enable XTAL 24MHz clock source. */ + CLOCK_InitExternalClk(0); + /* Enable internal RC. */ + CLOCK_InitRcOsc24M(); + /* Switch clock source to external OSC. */ + CLOCK_SwitchOsc(kCLOCK_XtalOsc); + /* Set Oscillator ready counter value. */ + CCM->CCR = (CCM->CCR & (~CCM_CCR_OSCNT_MASK)) | CCM_CCR_OSCNT(127); + /* Setting PeriphClk2Mux and PeriphMux to provide stable clock before PLLs are initialed */ + CLOCK_SetMux(kCLOCK_PeriphClk2Mux, 1); /* Set PERIPH_CLK2 MUX to OSC */ + CLOCK_SetMux(kCLOCK_PeriphMux, 1); /* Set PERIPH_CLK MUX to PERIPH_CLK2 */ + /* Setting the VDD_SOC to 1.275V. It is necessary to config AHB to 600Mhz. */ + DCDC->REG3 = (DCDC->REG3 & (~DCDC_REG3_TRG_MASK)) | DCDC_REG3_TRG(0x13); + /* Waiting for DCDC_STS_DC_OK bit is asserted */ + while (DCDC_REG0_STS_DC_OK_MASK != (DCDC_REG0_STS_DC_OK_MASK & DCDC->REG0)) + { + } + /* Set AHB_PODF. */ + CLOCK_SetDiv(kCLOCK_AhbDiv, 0); + /* Disable IPG clock gate. */ + CLOCK_DisableClock(kCLOCK_Adc1); + CLOCK_DisableClock(kCLOCK_Adc2); + CLOCK_DisableClock(kCLOCK_Xbar1); + CLOCK_DisableClock(kCLOCK_Xbar2); + CLOCK_DisableClock(kCLOCK_Xbar3); + /* Set IPG_PODF. */ + CLOCK_SetDiv(kCLOCK_IpgDiv, 3); + /* Set ARM_PODF. */ + CLOCK_SetDiv(kCLOCK_ArmDiv, 1); + /* Set PERIPH_CLK2_PODF. */ + CLOCK_SetDiv(kCLOCK_PeriphClk2Div, 0); + /* Disable PERCLK clock gate. */ + CLOCK_DisableClock(kCLOCK_Gpt1); + CLOCK_DisableClock(kCLOCK_Gpt1S); + CLOCK_DisableClock(kCLOCK_Gpt2); + CLOCK_DisableClock(kCLOCK_Gpt2S); + CLOCK_DisableClock(kCLOCK_Pit); + /* Set PERCLK_PODF. */ + CLOCK_SetDiv(kCLOCK_PerclkDiv, 1); + /* Disable USDHC1 clock gate. */ + CLOCK_DisableClock(kCLOCK_Usdhc1); + /* Set USDHC1_PODF. */ + CLOCK_SetDiv(kCLOCK_Usdhc1Div, 1); + /* Set Usdhc1 clock source. */ + CLOCK_SetMux(kCLOCK_Usdhc1Mux, 0); + /* Disable USDHC2 clock gate. */ + CLOCK_DisableClock(kCLOCK_Usdhc2); + /* Set USDHC2_PODF. */ + CLOCK_SetDiv(kCLOCK_Usdhc2Div, 1); + /* Set Usdhc2 clock source. */ + CLOCK_SetMux(kCLOCK_Usdhc2Mux, 0); + /* In SDK projects, SDRAM (configured by SEMC) will be initialized in either debug script or dcd. + * With this macro SKIP_SYSCLK_INIT, system pll (selected to be SEMC source clock in SDK projects) will be left unchanged. + * Note: If another clock source is selected for SEMC, user may want to avoid changing that clock as well.*/ +#ifndef SKIP_SYSCLK_INIT + /* Disable Semc clock gate. */ + CLOCK_DisableClock(kCLOCK_Semc); + /* Set SEMC_PODF. */ + CLOCK_SetDiv(kCLOCK_SemcDiv, 7); + /* Set Semc alt clock source. */ + CLOCK_SetMux(kCLOCK_SemcAltMux, 0); + /* Set Semc clock source. */ + CLOCK_SetMux(kCLOCK_SemcMux, 0); +#endif + /* Disable Flexspi clock gate. */ + CLOCK_DisableClock(kCLOCK_FlexSpi); + /* Set FLEXSPI_PODF. */ + CLOCK_SetDiv(kCLOCK_FlexspiDiv, 1); + /* Set Flexspi clock source. */ + CLOCK_SetMux(kCLOCK_FlexspiMux, 3); + /* In SDK projects, external flash (configured by FLEXSPI2) will be initialized by dcd. + * With this macro XIP_EXTERNAL_FLASH, usb1 pll (selected to be FLEXSPI2 clock source in SDK projects) will be left unchanged. + * Note: If another clock source is selected for FLEXSPI2, user may want to avoid changing that clock as well.*/ +#if !(defined(XIP_EXTERNAL_FLASH) && (XIP_EXTERNAL_FLASH == 1)) + /* Disable Flexspi2 clock gate. */ + CLOCK_DisableClock(kCLOCK_FlexSpi2); + /* Set FLEXSPI2_PODF. */ + CLOCK_SetDiv(kCLOCK_Flexspi2Div, 1); + /* Set Flexspi2 clock source. */ + CLOCK_SetMux(kCLOCK_Flexspi2Mux, 3); +#endif + /* Disable CSI clock gate. */ + CLOCK_DisableClock(kCLOCK_Csi); + /* Set CSI_PODF. */ + CLOCK_SetDiv(kCLOCK_CsiDiv, 1); + /* Set Csi clock source. */ + CLOCK_SetMux(kCLOCK_CsiMux, 0); + /* Disable LPSPI clock gate. */ + CLOCK_DisableClock(kCLOCK_Lpspi1); + CLOCK_DisableClock(kCLOCK_Lpspi2); + CLOCK_DisableClock(kCLOCK_Lpspi3); + CLOCK_DisableClock(kCLOCK_Lpspi4); + /* Set LPSPI_PODF. */ + CLOCK_SetDiv(kCLOCK_LpspiDiv, 4); + /* Set Lpspi clock source. */ + CLOCK_SetMux(kCLOCK_LpspiMux, 2); + /* Disable TRACE clock gate. */ + CLOCK_DisableClock(kCLOCK_Trace); + /* Set TRACE_PODF. */ + CLOCK_SetDiv(kCLOCK_TraceDiv, 3); + /* Set Trace clock source. */ + CLOCK_SetMux(kCLOCK_TraceMux, 0); + /* Disable SAI1 clock gate. */ + CLOCK_DisableClock(kCLOCK_Sai1); + /* Set SAI1_CLK_PRED. */ + CLOCK_SetDiv(kCLOCK_Sai1PreDiv, 3); + /* Set SAI1_CLK_PODF. */ + CLOCK_SetDiv(kCLOCK_Sai1Div, 1); + /* Set Sai1 clock source. */ + CLOCK_SetMux(kCLOCK_Sai1Mux, 0); + /* Disable SAI2 clock gate. */ + CLOCK_DisableClock(kCLOCK_Sai2); + /* Set SAI2_CLK_PRED. */ + CLOCK_SetDiv(kCLOCK_Sai2PreDiv, 3); + /* Set SAI2_CLK_PODF. */ + CLOCK_SetDiv(kCLOCK_Sai2Div, 1); + /* Set Sai2 clock source. */ + CLOCK_SetMux(kCLOCK_Sai2Mux, 0); + /* Disable SAI3 clock gate. */ + CLOCK_DisableClock(kCLOCK_Sai3); + /* Set SAI3_CLK_PRED. */ + CLOCK_SetDiv(kCLOCK_Sai3PreDiv, 3); + /* Set SAI3_CLK_PODF. */ + CLOCK_SetDiv(kCLOCK_Sai3Div, 1); + /* Set Sai3 clock source. */ + CLOCK_SetMux(kCLOCK_Sai3Mux, 0); + /* Disable Lpi2c clock gate. */ + CLOCK_DisableClock(kCLOCK_Lpi2c1); + CLOCK_DisableClock(kCLOCK_Lpi2c2); + CLOCK_DisableClock(kCLOCK_Lpi2c3); + /* Set LPI2C_CLK_PODF. */ + CLOCK_SetDiv(kCLOCK_Lpi2cDiv, 0); + /* Set Lpi2c clock source. */ + CLOCK_SetMux(kCLOCK_Lpi2cMux, 0); + /* Disable CAN clock gate. */ + CLOCK_DisableClock(kCLOCK_Can1); + CLOCK_DisableClock(kCLOCK_Can2); + CLOCK_DisableClock(kCLOCK_Can3); + CLOCK_DisableClock(kCLOCK_Can1S); + CLOCK_DisableClock(kCLOCK_Can2S); + CLOCK_DisableClock(kCLOCK_Can3S); + /* Set CAN_CLK_PODF. */ + CLOCK_SetDiv(kCLOCK_CanDiv, 1); + /* Set Can clock source. */ + CLOCK_SetMux(kCLOCK_CanMux, 2); + /* Disable UART clock gate. */ + CLOCK_DisableClock(kCLOCK_Lpuart1); + CLOCK_DisableClock(kCLOCK_Lpuart2); + CLOCK_DisableClock(kCLOCK_Lpuart3); + CLOCK_DisableClock(kCLOCK_Lpuart4); + CLOCK_DisableClock(kCLOCK_Lpuart5); + CLOCK_DisableClock(kCLOCK_Lpuart6); + CLOCK_DisableClock(kCLOCK_Lpuart7); + CLOCK_DisableClock(kCLOCK_Lpuart8); + /* Set UART_CLK_PODF. */ + CLOCK_SetDiv(kCLOCK_UartDiv, 0); + /* Set Uart clock source. */ + CLOCK_SetMux(kCLOCK_UartMux, 0); + /* Disable LCDIF clock gate. */ + CLOCK_DisableClock(kCLOCK_LcdPixel); + /* Set LCDIF_PRED. */ + CLOCK_SetDiv(kCLOCK_LcdifPreDiv, 1); + /* Set LCDIF_CLK_PODF. */ + CLOCK_SetDiv(kCLOCK_LcdifDiv, 3); + /* Set Lcdif pre clock source. */ + CLOCK_SetMux(kCLOCK_LcdifPreMux, 5); + /* Disable SPDIF clock gate. */ + CLOCK_DisableClock(kCLOCK_Spdif); + /* Set SPDIF0_CLK_PRED. */ + CLOCK_SetDiv(kCLOCK_Spdif0PreDiv, 1); + /* Set SPDIF0_CLK_PODF. */ + CLOCK_SetDiv(kCLOCK_Spdif0Div, 7); + /* Set Spdif clock source. */ + CLOCK_SetMux(kCLOCK_SpdifMux, 3); + /* Disable Flexio1 clock gate. */ + CLOCK_DisableClock(kCLOCK_Flexio1); + /* Set FLEXIO1_CLK_PRED. */ + CLOCK_SetDiv(kCLOCK_Flexio1PreDiv, 1); + /* Set FLEXIO1_CLK_PODF. */ + CLOCK_SetDiv(kCLOCK_Flexio1Div, 7); + /* Set Flexio1 clock source. */ + CLOCK_SetMux(kCLOCK_Flexio1Mux, 3); + /* Disable Flexio2 clock gate. */ + CLOCK_DisableClock(kCLOCK_Flexio2); + /* Set FLEXIO2_CLK_PRED. */ + CLOCK_SetDiv(kCLOCK_Flexio2PreDiv, 1); + /* Set FLEXIO2_CLK_PODF. */ + CLOCK_SetDiv(kCLOCK_Flexio2Div, 7); + /* Set Flexio2 clock source. */ + CLOCK_SetMux(kCLOCK_Flexio2Mux, 3); + /* Set Pll3 sw clock source. */ + CLOCK_SetMux(kCLOCK_Pll3SwMux, 0); + /* Init ARM PLL. */ + CLOCK_InitArmPll(&armPllConfig_BOARD_BootClockRUN); + /* In SDK projects, SDRAM (configured by SEMC) will be initialized in either debug script or dcd. + * With this macro SKIP_SYSCLK_INIT, system pll (selected to be SEMC source clock in SDK projects) will be left unchanged. + * Note: If another clock source is selected for SEMC, user may want to avoid changing that clock as well.*/ +#ifndef SKIP_SYSCLK_INIT +#if defined(XIP_BOOT_HEADER_DCD_ENABLE) && (XIP_BOOT_HEADER_DCD_ENABLE == 1) + #warning "SKIP_SYSCLK_INIT should be defined to keep system pll (selected to be SEMC source clock in SDK projects) unchanged." +#endif + /* Init System PLL. */ + CLOCK_InitSysPll(&sysPllConfig_BOARD_BootClockRUN); + /* Init System pfd0. */ + CLOCK_InitSysPfd(kCLOCK_Pfd0, 27); + /* Init System pfd1. */ + CLOCK_InitSysPfd(kCLOCK_Pfd1, 16); + /* Init System pfd2. */ + CLOCK_InitSysPfd(kCLOCK_Pfd2, 24); + /* Init System pfd3. */ + CLOCK_InitSysPfd(kCLOCK_Pfd3, 16); +#endif + /* In SDK projects, external flash (configured by FLEXSPI2) will be initialized by dcd. + * With this macro XIP_EXTERNAL_FLASH, usb1 pll (selected to be FLEXSPI2 clock source in SDK projects) will be left unchanged. + * Note: If another clock source is selected for FLEXSPI2, user may want to avoid changing that clock as well.*/ +#if !(defined(XIP_EXTERNAL_FLASH) && (XIP_EXTERNAL_FLASH == 1)) + /* Init Usb1 PLL. */ + CLOCK_InitUsb1Pll(&usb1PllConfig_BOARD_BootClockRUN); + /* Init Usb1 pfd0. */ + CLOCK_InitUsb1Pfd(kCLOCK_Pfd0, 33); + /* Init Usb1 pfd1. */ + CLOCK_InitUsb1Pfd(kCLOCK_Pfd1, 16); + /* Init Usb1 pfd2. */ + CLOCK_InitUsb1Pfd(kCLOCK_Pfd2, 17); + /* Init Usb1 pfd3. */ + CLOCK_InitUsb1Pfd(kCLOCK_Pfd3, 19); + /* Disable Usb1 PLL output for USBPHY1. */ + CCM_ANALOG->PLL_USB1 &= ~CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK; +#endif + /* DeInit Audio PLL. */ + CLOCK_DeinitAudioPll(); + /* Bypass Audio PLL. */ + CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_PllAudio, 1); + /* Set divider for Audio PLL. */ + CCM_ANALOG->MISC2 &= ~CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK; + CCM_ANALOG->MISC2 &= ~CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK; + /* Enable Audio PLL output. */ + CCM_ANALOG->PLL_AUDIO |= CCM_ANALOG_PLL_AUDIO_ENABLE_MASK; + /* Init Video PLL. */ + uint32_t pllVideo; + /* Disable Video PLL output before initial Video PLL. */ + CCM_ANALOG->PLL_VIDEO &= ~CCM_ANALOG_PLL_VIDEO_ENABLE_MASK; + /* Bypass PLL first */ + CCM_ANALOG->PLL_VIDEO = (CCM_ANALOG->PLL_VIDEO & (~CCM_ANALOG_PLL_VIDEO_BYPASS_CLK_SRC_MASK)) | + CCM_ANALOG_PLL_VIDEO_BYPASS_MASK | CCM_ANALOG_PLL_VIDEO_BYPASS_CLK_SRC(0); + CCM_ANALOG->PLL_VIDEO_NUM = CCM_ANALOG_PLL_VIDEO_NUM_A(0); + CCM_ANALOG->PLL_VIDEO_DENOM = CCM_ANALOG_PLL_VIDEO_DENOM_B(1); + pllVideo = (CCM_ANALOG->PLL_VIDEO & (~(CCM_ANALOG_PLL_VIDEO_DIV_SELECT_MASK | CCM_ANALOG_PLL_VIDEO_POWERDOWN_MASK))) | + CCM_ANALOG_PLL_VIDEO_ENABLE_MASK |CCM_ANALOG_PLL_VIDEO_DIV_SELECT(31); + pllVideo |= CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(1); + CCM_ANALOG->MISC2 = (CCM_ANALOG->MISC2 & (~CCM_ANALOG_MISC2_VIDEO_DIV_MASK)) | CCM_ANALOG_MISC2_VIDEO_DIV(3); + CCM_ANALOG->PLL_VIDEO = pllVideo; + while ((CCM_ANALOG->PLL_VIDEO & CCM_ANALOG_PLL_VIDEO_LOCK_MASK) == 0) + { + } + /* Disable bypass for Video PLL. */ + CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_PllVideo, 0); + /* DeInit Enet PLL. */ + CLOCK_DeinitEnetPll(); + /* Bypass Enet PLL. */ + CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_PllEnet, 1); + /* Set Enet output divider. */ + CCM_ANALOG->PLL_ENET = (CCM_ANALOG->PLL_ENET & (~CCM_ANALOG_PLL_ENET_DIV_SELECT_MASK)) | CCM_ANALOG_PLL_ENET_DIV_SELECT(1); + /* Enable Enet output. */ + CCM_ANALOG->PLL_ENET |= CCM_ANALOG_PLL_ENET_ENABLE_MASK; + /* Set Enet2 output divider. */ + CCM_ANALOG->PLL_ENET = (CCM_ANALOG->PLL_ENET & (~CCM_ANALOG_PLL_ENET_ENET2_DIV_SELECT_MASK)) | CCM_ANALOG_PLL_ENET_ENET2_DIV_SELECT(0); + /* Enable Enet2 output. */ + CCM_ANALOG->PLL_ENET |= CCM_ANALOG_PLL_ENET_ENET2_REF_EN_MASK; + /* Enable Enet25M output. */ + CCM_ANALOG->PLL_ENET |= CCM_ANALOG_PLL_ENET_ENET_25M_REF_EN_MASK; + /* DeInit Usb2 PLL. */ + CLOCK_DeinitUsb2Pll(); + /* Bypass Usb2 PLL. */ + CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_PllUsb2, 1); + /* Enable Usb2 PLL output. */ + CCM_ANALOG->PLL_USB2 |= CCM_ANALOG_PLL_USB2_ENABLE_MASK; + /* Set preperiph clock source. */ + CLOCK_SetMux(kCLOCK_PrePeriphMux, 3); + /* Set periph clock source. */ + CLOCK_SetMux(kCLOCK_PeriphMux, 0); + /* Set periph clock2 clock source. */ + CLOCK_SetMux(kCLOCK_PeriphClk2Mux, 0); + /* Set per clock source. */ + CLOCK_SetMux(kCLOCK_PerclkMux, 0); + /* Set lvds1 clock source. */ + CCM_ANALOG->MISC1 = (CCM_ANALOG->MISC1 & (~CCM_ANALOG_MISC1_LVDS1_CLK_SEL_MASK)) | CCM_ANALOG_MISC1_LVDS1_CLK_SEL(0); + /* Set clock out1 divider. */ + CCM->CCOSR = (CCM->CCOSR & (~CCM_CCOSR_CLKO1_DIV_MASK)) | CCM_CCOSR_CLKO1_DIV(0); + /* Set clock out1 source. */ + CCM->CCOSR = (CCM->CCOSR & (~CCM_CCOSR_CLKO1_SEL_MASK)) | CCM_CCOSR_CLKO1_SEL(1); + /* Set clock out2 divider. */ + CCM->CCOSR = (CCM->CCOSR & (~CCM_CCOSR_CLKO2_DIV_MASK)) | CCM_CCOSR_CLKO2_DIV(0); + /* Set clock out2 source. */ + CCM->CCOSR = (CCM->CCOSR & (~CCM_CCOSR_CLKO2_SEL_MASK)) | CCM_CCOSR_CLKO2_SEL(18); + /* Set clock out1 drives clock out1. */ + CCM->CCOSR &= ~CCM_CCOSR_CLK_OUT_SEL_MASK; + /* Disable clock out1. */ + CCM->CCOSR &= ~CCM_CCOSR_CLKO1_EN_MASK; + /* Disable clock out2. */ + CCM->CCOSR &= ~CCM_CCOSR_CLKO2_EN_MASK; + /* Set SAI1 MCLK1 clock source. */ + IOMUXC_SetSaiMClkClockSource(IOMUXC_GPR, kIOMUXC_GPR_SAI1MClk1Sel, 0); + /* Set SAI1 MCLK2 clock source. */ + IOMUXC_SetSaiMClkClockSource(IOMUXC_GPR, kIOMUXC_GPR_SAI1MClk2Sel, 0); + /* Set SAI1 MCLK3 clock source. */ + IOMUXC_SetSaiMClkClockSource(IOMUXC_GPR, kIOMUXC_GPR_SAI1MClk3Sel, 0); + /* Set SAI2 MCLK3 clock source. */ + IOMUXC_SetSaiMClkClockSource(IOMUXC_GPR, kIOMUXC_GPR_SAI2MClk3Sel, 0); + /* Set SAI3 MCLK3 clock source. */ + IOMUXC_SetSaiMClkClockSource(IOMUXC_GPR, kIOMUXC_GPR_SAI3MClk3Sel, 0); + /* Set MQS configuration. */ + IOMUXC_MQSConfig(IOMUXC_GPR,kIOMUXC_MqsPwmOverSampleRate32, 0); + /* Set ENET1 Tx clock source. */ + IOMUXC_EnableMode(IOMUXC_GPR, kIOMUXC_GPR_ENET1RefClkMode, false); + /* Set ENET2 Tx clock source. */ +#if defined(FSL_IOMUXC_DRIVER_VERSION) && (FSL_IOMUXC_DRIVER_VERSION != (MAKE_VERSION(2, 0, 0))) + IOMUXC_EnableMode(IOMUXC_GPR, kIOMUXC_GPR_ENET2RefClkMode, false); +#else + IOMUXC_EnableMode(IOMUXC_GPR, IOMUXC_GPR_GPR1_ENET2_CLK_SEL_MASK, false); +#endif + /* Set GPT1 High frequency reference clock source. */ + IOMUXC_GPR->GPR5 &= ~IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT1_MASK; + /* Set GPT2 High frequency reference clock source. */ + IOMUXC_GPR->GPR5 &= ~IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT2_MASK; + /* Set SystemCoreClock variable. */ + SystemCoreClock = BOARD_BOOTCLOCKRUN_CORE_CLOCK; +} + diff --git a/os/hal/ports/MIMXRT1064/MIMXRT1064/clock_config.h b/os/hal/ports/MIMXRT1064/MIMXRT1064/clock_config.h new file mode 100644 index 0000000000..a03f3199eb --- /dev/null +++ b/os/hal/ports/MIMXRT1064/MIMXRT1064/clock_config.h @@ -0,0 +1,126 @@ +/* + * Copyright 2018-2020 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _CLOCK_CONFIG_H_ +#define _CLOCK_CONFIG_H_ + +#include "fsl_common.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ +#define BOARD_XTAL0_CLK_HZ 24000000U /*!< Board xtal0 frequency in Hz */ + +#define BOARD_XTAL32K_CLK_HZ 32768U /*!< Board xtal32k frequency in Hz */ +/******************************************************************************* + ************************ BOARD_InitBootClocks function ************************ + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes default configuration of clocks. + * + */ +void BOARD_InitBootClocks(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +/******************************************************************************* + ********************** Configuration BOARD_BootClockRUN *********************** + ******************************************************************************/ +/******************************************************************************* + * Definitions for BOARD_BootClockRUN configuration + ******************************************************************************/ +#define BOARD_BOOTCLOCKRUN_CORE_CLOCK 600000000U /*!< Core clock frequency: 600000000Hz */ + +/* Clock outputs (values are in Hz): */ +#define BOARD_BOOTCLOCKRUN_AHB_CLK_ROOT 600000000UL +#define BOARD_BOOTCLOCKRUN_CAN_CLK_ROOT 40000000UL +#define BOARD_BOOTCLOCKRUN_CKIL_SYNC_CLK_ROOT 32768UL +#define BOARD_BOOTCLOCKRUN_CLKO1_CLK 0UL +#define BOARD_BOOTCLOCKRUN_CLKO2_CLK 0UL +#define BOARD_BOOTCLOCKRUN_CLK_1M 1000000UL +#define BOARD_BOOTCLOCKRUN_CLK_24M 24000000UL +#define BOARD_BOOTCLOCKRUN_CSI_CLK_ROOT 12000000UL +#define BOARD_BOOTCLOCKRUN_ENET1_TX_CLK 2400000UL +#define BOARD_BOOTCLOCKRUN_ENET2_125M_CLK 1200000UL +#define BOARD_BOOTCLOCKRUN_ENET2_TX_CLK 1200000UL +#define BOARD_BOOTCLOCKRUN_ENET_125M_CLK 2400000UL +#define BOARD_BOOTCLOCKRUN_ENET_25M_REF_CLK 1200000UL +#define BOARD_BOOTCLOCKRUN_FLEXIO1_CLK_ROOT 30000000UL +#define BOARD_BOOTCLOCKRUN_FLEXIO2_CLK_ROOT 30000000UL +#define BOARD_BOOTCLOCKRUN_FLEXSPI2_CLK_ROOT 130909090UL +#define BOARD_BOOTCLOCKRUN_FLEXSPI_CLK_ROOT 130909090UL +#define BOARD_BOOTCLOCKRUN_GPT1_IPG_CLK_HIGHFREQ 75000000UL +#define BOARD_BOOTCLOCKRUN_GPT2_IPG_CLK_HIGHFREQ 75000000UL +#define BOARD_BOOTCLOCKRUN_IPG_CLK_ROOT 150000000UL +#define BOARD_BOOTCLOCKRUN_LCDIF_CLK_ROOT 67500000UL +#define BOARD_BOOTCLOCKRUN_LPI2C_CLK_ROOT 60000000UL +#define BOARD_BOOTCLOCKRUN_LPSPI_CLK_ROOT 105600000UL +#define BOARD_BOOTCLOCKRUN_LVDS1_CLK 1200000000UL +#define BOARD_BOOTCLOCKRUN_MQS_MCLK 63529411UL +#define BOARD_BOOTCLOCKRUN_PERCLK_CLK_ROOT 75000000UL +#define BOARD_BOOTCLOCKRUN_PLL7_MAIN_CLK 24000000UL +#define BOARD_BOOTCLOCKRUN_SAI1_CLK_ROOT 63529411UL +#define BOARD_BOOTCLOCKRUN_SAI1_MCLK1 63529411UL +#define BOARD_BOOTCLOCKRUN_SAI1_MCLK2 63529411UL +#define BOARD_BOOTCLOCKRUN_SAI1_MCLK3 30000000UL +#define BOARD_BOOTCLOCKRUN_SAI2_CLK_ROOT 63529411UL +#define BOARD_BOOTCLOCKRUN_SAI2_MCLK1 63529411UL +#define BOARD_BOOTCLOCKRUN_SAI2_MCLK2 0UL +#define BOARD_BOOTCLOCKRUN_SAI2_MCLK3 30000000UL +#define BOARD_BOOTCLOCKRUN_SAI3_CLK_ROOT 63529411UL +#define BOARD_BOOTCLOCKRUN_SAI3_MCLK1 63529411UL +#define BOARD_BOOTCLOCKRUN_SAI3_MCLK2 0UL +#define BOARD_BOOTCLOCKRUN_SAI3_MCLK3 30000000UL +#define BOARD_BOOTCLOCKRUN_SEMC_CLK_ROOT 75000000UL +#define BOARD_BOOTCLOCKRUN_SPDIF0_CLK_ROOT 30000000UL +#define BOARD_BOOTCLOCKRUN_SPDIF0_EXTCLK_OUT 0UL +#define BOARD_BOOTCLOCKRUN_TRACE_CLK_ROOT 132000000UL +#define BOARD_BOOTCLOCKRUN_UART_CLK_ROOT 80000000UL +#define BOARD_BOOTCLOCKRUN_USBPHY1_CLK 0UL +#define BOARD_BOOTCLOCKRUN_USBPHY2_CLK 0UL +#define BOARD_BOOTCLOCKRUN_USDHC1_CLK_ROOT 198000000UL +#define BOARD_BOOTCLOCKRUN_USDHC2_CLK_ROOT 198000000UL + +/*! @brief Arm PLL set for BOARD_BootClockRUN configuration. + */ +extern const clock_arm_pll_config_t armPllConfig_BOARD_BootClockRUN; +/*! @brief Usb1 PLL set for BOARD_BootClockRUN configuration. + */ +extern const clock_usb_pll_config_t usb1PllConfig_BOARD_BootClockRUN; +/*! @brief Sys PLL for BOARD_BootClockRUN configuration. + */ +extern const clock_sys_pll_config_t sysPllConfig_BOARD_BootClockRUN; +/*! @brief Video PLL set for BOARD_BootClockRUN configuration. + */ +extern const clock_video_pll_config_t videoPllConfig_BOARD_BootClockRUN; + +/******************************************************************************* + * API for BOARD_BootClockRUN configuration + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes configuration of clocks. + * + */ +void BOARD_BootClockRUN(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +#endif /* _CLOCK_CONFIG_H_ */ + diff --git a/os/hal/ports/MIMXRT1064/MIMXRT1064/hal_lld.c b/os/hal/ports/MIMXRT1064/MIMXRT1064/hal_lld.c new file mode 100644 index 0000000000..a933b6790a --- /dev/null +++ b/os/hal/ports/MIMXRT1064/MIMXRT1064/hal_lld.c @@ -0,0 +1,165 @@ +/* + 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. + + Portions Copyright (C) 2017 PJRC.COM, LLC. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + 1. The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 2. If the Software is incorporated into a build system that allows + selection among a list of target devices, then similar target + devices manufactured by PJRC.COM must be included in the list of + target devices and selectable in the same manner. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + +*/ + +/** + * @file MIMXRT1064/hal_lld.c + * @brief MIMXRT1064 HAL Driver subsystem low level driver source template. + * + * @addtogroup HAL + * @{ + */ + +#include "hal.h" + +#include "printf_debug.h" + +#include "clock_config.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) { +} + + +#define NVIC_NUM_INTERRUPTS 160 +extern uint32_t _vectors[NVIC_NUM_INTERRUPTS]; + +uint32_t SystemCoreClock = 528000000UL; // default system clock + +void MIMXRT1064_clock_init(void) { + // We need the IOMUXC for GPIO to work. We do not need BOARD_InitPins() from + // the NXP SDK, we use the ChibiOS PAL HAL instead. + CLOCK_EnableClock(kCLOCK_Iomuxc); + + BOARD_InitBootClocks(); + //SystemCoreClockUpdate(); + + // TODO: is the following covered by NXP startup code somewhere? + + // Configure the GPIO pins from the standard-speed GPIOs onto the high-speed + // GPIOs GPIO6, GPIO7, GPIO8, and GPIO9: + // + // See also IMXRT1060RM, page 949, 12.1 Chip-specific GPIO information. + IOMUXC_GPR->GPR26 = 0xFFFFFFFF; + IOMUXC_GPR->GPR27 = 0xFFFFFFFF; + IOMUXC_GPR->GPR28 = 0xFFFFFFFF; + IOMUXC_GPR->GPR29 = 0xFFFFFFFF; + + // Turn on the Teensy power LED on pin 13, which users generally expect: + // IOMUXC->SW_MUX_CTL_PAD[kIOMUXC_SW_MUX_CTL_PAD_GPIO_B0_03] = + // PIN_MUX_ALTERNATIVE(5); + // GPIO7->GDIR |= ((uint32_t) 1 << 3); + // GPIO7->DR_SET = ((uint32_t) 1 << 3); + + printf_debug_init(); + printf_debug("\n***********IMXRT Chibi Startup**********\n"); + printf_debug("test %d %d %d\n", 1, -1234567, 3); + + // Explicitly warn for a few issues I ran into, to catch possible + // problems automatically when working on startup code: + if (SCB->VTOR != (uint32_t)&_vectors) { + printf_debug("WARNING: unexpected SCB->VTOR value %x, expected &_vectors = %x\n", SCB->VTOR, (uint32_t)&_vectors); + } + if ((uint32_t)&_vectors % 4 != 0) { + printf_debug("WARNING: &_vectors = %x is unexpectedly not aligned by 4\n", (uint32_t)&_vectors); + } + if (CORTEX_NUM_VECTORS != 160) { + printf_debug("WARNING: unexpected CORTEX_NUM_VECTORS = %d, want %d", CORTEX_NUM_VECTORS, 160); + } +} + +/** @} */ diff --git a/os/hal/ports/MIMXRT1064/MIMXRT1064/hal_lld.h b/os/hal/ports/MIMXRT1064/MIMXRT1064/hal_lld.h new file mode 100644 index 0000000000..439995a068 --- /dev/null +++ b/os/hal/ports/MIMXRT1064/MIMXRT1064/hal_lld.h @@ -0,0 +1,113 @@ +/* + 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 "mimxrt1064_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 "MIMXRT1064" +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* 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 MIMXRT1064_clock_init(void); + void MIMXRT1064_MPU_init(void); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_LLD_H_ */ + +/** @} */ diff --git a/os/hal/ports/MIMXRT1064/MIMXRT1064/mimxrt1064_registry.h b/os/hal/ports/MIMXRT1064/MIMXRT1064/mimxrt1064_registry.h new file mode 100644 index 0000000000..015a35418c --- /dev/null +++ b/os/hal/ports/MIMXRT1064/MIMXRT1064/mimxrt1064_registry.h @@ -0,0 +1,160 @@ +/* + 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 MIMXRT1064_REGISTRY_H_ +#define MIMXRT1064_REGISTRY_H_ + +#if !defined(MIMXRT1064) || defined(__DOXYGEN__) +#define MIMXRT1064 +#endif + +/*===========================================================================*/ +/* Platform capabilities. */ +/*===========================================================================*/ + +/* See IMXRT1060RM, page 44, table 4-2: CM7 domain interrupt summary */ + +/* ADC attributes.*/ +#define MIMXRT1064_HAS_ADC0 TRUE +#define MIMXRT1064_ADC0_IRQ_VECTOR Vector14C +#define MIMXRT1064_HAS_ADC1 TRUE +#define MIMXRT1064_ADC1_IRQ_VECTOR Vector150 + +/* DAC attributes.*/ +/* IMXRT1060RM, page 3324, 65.11 DAC interrupts: This module has no interrupts. */ +#define MIMXRT1064_HAS_DAC0 TRUE +#define MIMXRT1064_HAS_DAC1 TRUE +#define MIMXRT1064_HAS_DAC2 TRUE +#define MIMXRT1064_HAS_DAC3 TRUE + +/* DMA attributes.*/ +#define MIMXRT1064_DMA0_IRQ_VECTOR Vector40 +#define MIMXRT1064_DMA1_IRQ_VECTOR Vector44 +#define MIMXRT1064_DMA2_IRQ_VECTOR Vector48 +#define MIMXRT1064_DMA3_IRQ_VECTOR Vector4C +#define MIMXRT1064_DMA4_IRQ_VECTOR Vector50 +#define MIMXRT1064_DMA5_IRQ_VECTOR Vector54 +#define MIMXRT1064_DMA6_IRQ_VECTOR Vector58 +#define MIMXRT1064_DMA7_IRQ_VECTOR Vector5C +#define MIMXRT1064_DMA8_IRQ_VECTOR Vector60 +#define MIMXRT1064_DMA9_IRQ_VECTOR Vector64 +#define MIMXRT1064_DMA10_IRQ_VECTOR Vector68 +#define MIMXRT1064_DMA11_IRQ_VECTOR Vector6C +#define MIMXRT1064_DMA12_IRQ_VECTOR Vector70 +#define MIMXRT1064_DMA13_IRQ_VECTOR Vector74 +#define MIMXRT1064_DMA14_IRQ_VECTOR Vector78 +#define MIMXRT1064_DMA15_IRQ_VECTOR Vector7C +#define MIMXRT1064_HAS_DMA_ERROR_IRQ TRUE +#define MIMXRT1064_DMA_ERROR_IRQ_VECTOR Vector80 + +/* I2C attributes.*/ +#define MIMXRT1064_HAS_I2C0 TRUE +#define MIMXRT1064_I2C0_IRQ_VECTOR VectorB0 +#define MIMXRT1064_I2C0_IS_LPI2C TRUE +#define MIMXRT1064_HAS_I2C1 TRUE +#define MIMXRT1064_I2C1_IRQ_VECTOR VectorB4 +#define MIMXRT1064_I2C1_IS_LPI2C TRUE +#define MIMXRT1064_HAS_I2C2 TRUE +#define MIMXRT1064_I2C2_IRQ_VECTOR VectorB8 +#define MIMXRT1064_I2C2_IS_LPI2C TRUE +#define MIMXRT1064_HAS_I2C3 TRUE +#define MIMXRT1064_I2C3_IRQ_VECTOR VectorBC +#define MIMXRT1064_I2C3_IS_LPI2C TRUE + +/* Serial attributes.*/ +#define MIMXRT1064_HAS_SERIAL0 TRUE +#define MIMXRT1064_SERIAL0_IRQ_VECTOR Vector90 +#define MIMXRT1064_HAS_SERIAL1 TRUE +#define MIMXRT1064_SERIAL1_IRQ_VECTOR Vector94 +#define MIMXRT1064_HAS_SERIAL2 TRUE +#define MIMXRT1064_SERIAL2_IRQ_VECTOR Vector98 +#define MIMXRT1064_HAS_SERIAL3 TRUE +#define MIMXRT1064_SERIAL3_IRQ_VECTOR Vector9C +#define MIMXRT1064_HAS_SERIAL4 TRUE +#define MIMXRT1064_SERIAL4_IRQ_VECTOR VectorA0 +#define MIMXRT1064_HAS_SERIAL5 TRUE +#define MIMXRT1064_SERIAL5_IRQ_VECTOR VectorA4 +#define MIMXRT1064_HAS_SERIAL6 TRUE +#define MIMXRT1064_SERIAL6_IRQ_VECTOR VectorA8 +#define MIMXRT1064_HAS_SERIAL7 TRUE +#define MIMXRT1064_SERIAL7_IRQ_VECTOR VectorAC +#define MIMXRT1064_HAS_SERIAL_ERROR_IRQ FALSE +#define MIMXRT1064_SERIAL0_IS_LPUART TRUE +#define MIMXRT1064_SERIAL0_IS_UARTLP FALSE +#define MIMXRT1064_SERIAL1_IS_LPUART TRUE +#define MIMXRT1064_SERIAL1_IS_UARTLP FALSE +#define MIMXRT1064_SERIAL2_IS_LPUART TRUE +#define MIMXRT1064_SERIAL2_IS_UARTLP FALSE +#define MIMXRT1064_SERIAL3_IS_LPUART TRUE +#define MIMXRT1064_SERIAL3_IS_UARTLP FALSE +#define MIMXRT1064_SERIAL4_IS_LPUART TRUE +#define MIMXRT1064_SERIAL4_IS_UARTLP FALSE +#define MIMXRT1064_SERIAL5_IS_LPUART TRUE +#define MIMXRT1064_SERIAL5_IS_UARTLP FALSE +#define MIMXRT1064_SERIAL6_IS_LPUART TRUE +#define MIMXRT1064_SERIAL6_IS_UARTLP FALSE +#define MIMXRT1064_SERIAL7_IS_LPUART TRUE +#define MIMXRT1064_SERIAL7_IS_UARTLP FALSE + +/* SPI attributes.*/ +#define MIMXRT1064_HAS_SPI0 TRUE +#define MIMXRT1064_SPI0_IRQ_VECTOR VectorC0 +#define MIMXRT1064_SPI0_IS_LPSPI TRUE +#define MIMXRT1064_HAS_SPI1 TRUE +#define MIMXRT1064_SPI1_IRQ_VECTOR VectorC4 +#define MIMXRT1064_SPI1_IS_LPSPI TRUE +#define MIMXRT1064_HAS_SPI2 TRUE +#define MIMXRT1064_SPI2_IRQ_VECTOR VectorC8 +#define MIMXRT1064_SPI2_IS_LPSPI TRUE +#define MIMXRT1064_HAS_SPI3 TRUE +#define MIMXRT1064_SPI3_IRQ_VECTOR VectorCC +#define MIMXRT1064_SPI3_IS_LPSPI TRUE + +/* GPT attributes.*/ +#define MIMXRT1064_HAS_PIT0 TRUE +#define MIMXRT1064_HAS_PIT1 TRUE +#define MIMXRT1064_HAS_PIT2 TRUE +#define MIMXRT1064_HAS_PIT3 TRUE +#define MIMXRT1064_HAS_PIT_COMMON_IRQ TRUE +#define MIMXRT1064_PIT_IRQ_VECTOR Vector228 + +/* USB attributes.*/ +#define MIMXRT1064_HAS_USB TRUE +#define MIMXRT1064_USB_OTG1_IRQ_VECTOR Vector204 +#define MIMXRT1064_USB_OTG2_IRQ_VECTOR Vector200 +#define MIMXRT1064_USB0_IS_USBOTG TRUE +#define MIMXRT1064_HAS_USB_CLOCK_RECOVERY TRUE + +/* SDHC (SDC, MMC, SDIO) attributes */ +#define MIMXRT1064_HAS_SDHC0 TRUE +#define MIMXRT1064_SDHC0_IRQ_VECTOR Vector1F8 +#define MIMXRT1064_HAS_SDHC1 TRUE +#define MIMXRT1064_SDHC1_IRQ_VECTOR Vector1FC + +/** @} */ + +#endif /* MIMXRT1064_REGISTRY_H_ */ + +/** @} */ diff --git a/os/hal/ports/MIMXRT1064/MIMXRT1064/mpu.c b/os/hal/ports/MIMXRT1064/MIMXRT1064/mpu.c new file mode 100644 index 0000000000..744358520d --- /dev/null +++ b/os/hal/ports/MIMXRT1064/MIMXRT1064/mpu.c @@ -0,0 +1,175 @@ +/* + 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. + + Portions Copyright (C) 2017 PJRC.COM, LLC. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + 1. The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 2. If the Software is incorporated into a build system that allows + selection among a list of target devices, then similar target + devices manufactured by PJRC.COM must be included in the list of + target devices and selectable in the same manner. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + +*/ + +/** + * @file MIMXRT1064/mpu.c + * @brief Memory Protection Unit (MPU) configuration. + * @note Be careful when changing the linker script or FlexRAM config: + * do not configure MPU regions for memory regions that are + * not currently available, otherwise the device may hang. + * + * @addtogroup HAL + * @{ + */ + +#include "hal.h" + +#include "printf_debug.h" + +#include "clock_config.h" + +// TODO: port this to CMSIS style headers +#define SCB_MPU_TYPE (*(volatile uint32_t *)0xE000ED90) // +#define SCB_MPU_CTRL (*(volatile uint32_t *)0xE000ED94) // +#define SCB_MPU_CTRL_PRIVDEFENA ((uint32_t)(1<<2)) // Enables default memory map +#define SCB_MPU_CTRL_HFNMIENA ((uint32_t)(1<<1)) // Use MPU for HardFault & NMI +#define SCB_MPU_CTRL_ENABLE ((uint32_t)(1<<0)) // Enables MPU +#define SCB_MPU_RNR (*(volatile uint32_t *)0xE000ED98) // +#define SCB_MPU_RBAR (*(volatile uint32_t *)0xE000ED9C) // +#define SCB_MPU_RBAR_ADDR_MASK ((uint32_t)(0xFFFFFFE0)) +#define SCB_MPU_RBAR_VALID ((uint32_t)(1<<4)) +#define SCB_MPU_RBAR_REGION(n) ((uint32_t)((n) & 15)) +#define SCB_MPU_RASR (*(volatile uint32_t *)0xE000EDA0) // ARM DDI0403E, pg 696 +#define SCB_MPU_RASR_XN ((uint32_t)(1<<28)) +#define SCB_MPU_RASR_AP(n) ((uint32_t)(((n) & 7) << 24)) +#define SCB_MPU_RASR_TEX(n) ((uint32_t)(((n) & 7) << 19)) +#define SCB_MPU_RASR_S ((uint32_t)(1<<18)) +#define SCB_MPU_RASR_C ((uint32_t)(1<<17)) +#define SCB_MPU_RASR_B ((uint32_t)(1<<16)) +#define SCB_MPU_RASR_SRD(n) ((uint32_t)(((n) & 255) << 8)) +#define SCB_MPU_RASR_SIZE(n) ((uint32_t)(((n) & 31) << 1)) +#define SCB_MPU_RASR_ENABLE ((uint32_t)(1<<0)) +#define SCB_MPU_RBAR_A1 (*(volatile uint32_t *)0xE000EDA4) // +#define SCB_MPU_RASR_A1 (*(volatile uint32_t *)0xE000EDA8) // +#define SCB_MPU_RBAR_A2 (*(volatile uint32_t *)0xE000EDAC) // +#define SCB_MPU_RASR_A2 (*(volatile uint32_t *)0xE000EDB0) // +#define SCB_MPU_RBAR_A3 (*(volatile uint32_t *)0xE000EDB4) // +#define SCB_MPU_RASR_A3 (*(volatile uint32_t *)0xE000EDB8) // + + +// concise defines for SCB_MPU_RASR and SCB_MPU_RBAR, ARM DDI0403E, pg 696 +#define NOEXEC SCB_MPU_RASR_XN +#define READONLY SCB_MPU_RASR_AP(7) +#define READWRITE SCB_MPU_RASR_AP(3) +#define NOACCESS SCB_MPU_RASR_AP(0) +#define MEM_CACHE_WT SCB_MPU_RASR_TEX(0) | SCB_MPU_RASR_C +#define MEM_CACHE_WB SCB_MPU_RASR_TEX(0) | SCB_MPU_RASR_C | SCB_MPU_RASR_B +#define MEM_CACHE_WBWA SCB_MPU_RASR_TEX(1) | SCB_MPU_RASR_C | SCB_MPU_RASR_B +#define MEM_NOCACHE SCB_MPU_RASR_TEX(1) +#define DEV_NOCACHE SCB_MPU_RASR_TEX(2) +#define SIZE_32B (SCB_MPU_RASR_SIZE(4) | SCB_MPU_RASR_ENABLE) +#define SIZE_64B (SCB_MPU_RASR_SIZE(5) | SCB_MPU_RASR_ENABLE) +#define SIZE_128B (SCB_MPU_RASR_SIZE(6) | SCB_MPU_RASR_ENABLE) +#define SIZE_256B (SCB_MPU_RASR_SIZE(7) | SCB_MPU_RASR_ENABLE) +#define SIZE_512B (SCB_MPU_RASR_SIZE(8) | SCB_MPU_RASR_ENABLE) +#define SIZE_1K (SCB_MPU_RASR_SIZE(9) | SCB_MPU_RASR_ENABLE) +#define SIZE_2K (SCB_MPU_RASR_SIZE(10) | SCB_MPU_RASR_ENABLE) +#define SIZE_4K (SCB_MPU_RASR_SIZE(11) | SCB_MPU_RASR_ENABLE) +#define SIZE_8K (SCB_MPU_RASR_SIZE(12) | SCB_MPU_RASR_ENABLE) +#define SIZE_16K (SCB_MPU_RASR_SIZE(13) | SCB_MPU_RASR_ENABLE) +#define SIZE_32K (SCB_MPU_RASR_SIZE(14) | SCB_MPU_RASR_ENABLE) +#define SIZE_64K (SCB_MPU_RASR_SIZE(15) | SCB_MPU_RASR_ENABLE) +#define SIZE_128K (SCB_MPU_RASR_SIZE(16) | SCB_MPU_RASR_ENABLE) +#define SIZE_256K (SCB_MPU_RASR_SIZE(17) | SCB_MPU_RASR_ENABLE) +#define SIZE_512K (SCB_MPU_RASR_SIZE(18) | SCB_MPU_RASR_ENABLE) +#define SIZE_1M (SCB_MPU_RASR_SIZE(19) | SCB_MPU_RASR_ENABLE) +#define SIZE_2M (SCB_MPU_RASR_SIZE(20) | SCB_MPU_RASR_ENABLE) +#define SIZE_4M (SCB_MPU_RASR_SIZE(21) | SCB_MPU_RASR_ENABLE) +#define SIZE_8M (SCB_MPU_RASR_SIZE(22) | SCB_MPU_RASR_ENABLE) +#define SIZE_16M (SCB_MPU_RASR_SIZE(23) | SCB_MPU_RASR_ENABLE) +#define SIZE_32M (SCB_MPU_RASR_SIZE(24) | SCB_MPU_RASR_ENABLE) +#define SIZE_64M (SCB_MPU_RASR_SIZE(25) | SCB_MPU_RASR_ENABLE) +#define SIZE_128M (SCB_MPU_RASR_SIZE(26) | SCB_MPU_RASR_ENABLE) +#define SIZE_256M (SCB_MPU_RASR_SIZE(27) | SCB_MPU_RASR_ENABLE) +#define SIZE_512M (SCB_MPU_RASR_SIZE(28) | SCB_MPU_RASR_ENABLE) +#define SIZE_1G (SCB_MPU_RASR_SIZE(29) | SCB_MPU_RASR_ENABLE) +#define SIZE_2G (SCB_MPU_RASR_SIZE(30) | SCB_MPU_RASR_ENABLE) +#define SIZE_4G (SCB_MPU_RASR_SIZE(31) | SCB_MPU_RASR_ENABLE) +#define REGION(n) (SCB_MPU_RBAR_REGION(n) | SCB_MPU_RBAR_VALID) + +void MIMXRT1064_MPU_init(void) +{ + MPU->CTRL = 0; // turn off MPU + + uint32_t i = 0; + MPU->RBAR = 0x00000000 | REGION(i++); //https://developer.arm.com/docs/146793866/10/why-does-the-cortex-m7-initiate-axim-read-accesses-to-memory-addresses-that-do-not-fall-under-a-defined-mpu-region + MPU->RASR = SCB_MPU_RASR_TEX(0) | NOACCESS | NOEXEC | SIZE_4G; + + /* MPU->RBAR = 0x00000000 | REGION(i++); // ITCM */ + /* MPU->RASR = MEM_NOCACHE | READWRITE | SIZE_512K; */ + + // TODO: trap regions should be created last, because the hardware gives + // priority to the higher number ones. + MPU->RBAR = 0x00000000 | REGION(i++); // trap NULL pointer deref + MPU->RASR = DEV_NOCACHE | NOACCESS | SIZE_32B; + + MPU->RBAR = 0x00200000 | REGION(i++); // Boot ROM + MPU->RASR = MEM_CACHE_WT | READONLY | SIZE_128K; + + MPU->RBAR = 0x20000000 | REGION(i++); // DTCM + MPU->RASR = MEM_NOCACHE | READWRITE | NOEXEC | SIZE_512K; + + // teensy4/startup.c sets up a region on the stack to detect stack overflow. + // ChibiOS, at the time of writing, does not. + // MPU->RBAR = ((uint32_t)&_ebss) | REGION(i++); // trap stack overflow + // MPU->RASR = SCB_MPU_RASR_TEX(0) | NOACCESS | NOEXEC | SIZE_32B; + + MPU->RBAR = 0x20200000 | REGION(i++); // RAM (AXI bus) + MPU->RASR = MEM_CACHE_WBWA | READWRITE | NOEXEC | SIZE_1M; + + MPU->RBAR = 0x40000000 | REGION(i++); // Peripherals + MPU->RASR = DEV_NOCACHE | READWRITE | NOEXEC | SIZE_64M; + + MPU->RBAR = 0x70000000 | REGION(i++); // QSPI Flash + MPU->RASR = MEM_CACHE_WBWA | READONLY | SIZE_16M; + + MPU->RBAR = 0x60000000 | REGION(i++); // FlexSPI2 + MPU->RASR = MEM_CACHE_WBWA | READWRITE | NOEXEC | SIZE_16M; + + // TODO: protect access to power supply config + + MPU->CTRL = SCB_MPU_CTRL_ENABLE; +} + +/** @} */ diff --git a/os/hal/ports/MIMXRT1064/MIMXRT1064/platform.dox b/os/hal/ports/MIMXRT1064/MIMXRT1064/platform.dox new file mode 100644 index 0000000000..beb8f61192 --- /dev/null +++ b/os/hal/ports/MIMXRT1064/MIMXRT1064/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/MIMXRT1064/MIMXRT1064/platform.mk b/os/hal/ports/MIMXRT1064/MIMXRT1064/platform.mk new file mode 100644 index 0000000000..b92a7d6d84 --- /dev/null +++ b/os/hal/ports/MIMXRT1064/MIMXRT1064/platform.mk @@ -0,0 +1,39 @@ +PLATFORMSRC_CONTRIB := ${CHIBIOS}/os/hal/ports/common/ARMCMx/nvic.c \ + ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1064/MIMXRT1064/hal_lld.c \ + ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1064/MIMXRT1064/clock_config.c \ + ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1064/MIMXRT1064/printf_debug.c \ + ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1064/MIMXRT1064/bootable_image.c \ + ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1064/MIMXRT1064/mpu.c + +PLATFORMINC_CONTRIB := ${CHIBIOS}/os/hal/ports/common/ARMCMx \ + ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1064/LLD \ + ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1064/MIMXRT1064 \ + ${CHIBIOS_CONTRIB}/ext/mcux-sdk/devices/MIMXRT1064/drivers + +ifeq ($(USE_SMART_BUILD),yes) + +# Configuration files directory +ifeq ($(CONFDIR),) + CONFDIR = . +endif + +HALCONF := $(strip $(shell cat $(CONFDIR)/halconf.h $(CONFDIR)/halconf_community.h | egrep -e "\#define")) + +endif + +include ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1064/LLD/GPIOv1/driver.mk +include ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1064/LLD/UARTv1/driver.mk +include ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1064/LLD/I2Cv1/driver.mk +include ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1064/LLD/PITv1/driver.mk +include ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1064/LLD/USBHSv1/driver.mk + +# Shared variables +ALLCSRC += $(PLATFORMSRC_CONTRIB) +ALLINC += $(PLATFORMINC_CONTRIB) + +MIMXRT1064_DEFS = -DCPU_MIMXRT1064DVL6A -DXIP_EXTERNAL_FLASH=1 + +# The ChibiOS build system uses DDEFS: +DDEFS += ${MIMXRT1064_DEFS} +# The QMK ChibiOS build rules use OPT_DEFS: +OPT_DEFS += ${MIMXRT1064_DEFS} diff --git a/os/hal/ports/MIMXRT1064/MIMXRT1064/printf_debug.c b/os/hal/ports/MIMXRT1064/MIMXRT1064/printf_debug.c new file mode 100644 index 0000000000..7b030a44b7 --- /dev/null +++ b/os/hal/ports/MIMXRT1064/MIMXRT1064/printf_debug.c @@ -0,0 +1,114 @@ +/* + Copyright (C) 2017 PJRC.COM, LLC. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + 1. The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + 2. If the Software is incorporated into a build system that allows + selection among a list of target devices, then similar target + devices manufactured by PJRC.COM must be included in the list of + target devices and selectable in the same manner. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +// Enable to get startup debug on ChibiOS LPUART3 (== NXP peripheral LPUART4) +#if 0 /* PRINT_DEBUG_STUFF */ + +#include +#include "fsl_lpuart.h" + +void putchar_debug(char c); +static void puint_debug(unsigned int num); + + + void printf_debug(const char *format, ...) +{ + va_list args; + unsigned int val; + int n; + + va_start(args, format); + for (; *format != 0; format++) { // no-frills stand-alone printf + if (*format == '%') { + ++format; + if (*format == '%') goto out; + if (*format == '-') format++; // ignore size + while (*format >= '0' && *format <= '9') format++; // ignore size + if (*format == 'l') format++; // ignore long + if (*format == '\0') break; + if (*format == 's') { + printf_debug((char *)va_arg(args, int)); + } else if (*format == 'd') { + n = va_arg(args, int); + if (n < 0) { + n = -n; + putchar_debug('-'); + } + puint_debug(n); + } else if (*format == 'u') { + puint_debug(va_arg(args, unsigned int)); + } else if (*format == 'x' || *format == 'X') { + val = va_arg(args, unsigned int); + for (n=0; n < 8; n++) { + unsigned int d = (val >> 28) & 15; + putchar_debug((d < 10) ? d + '0' : d - 10 + 'A'); + val <<= 4; + } + } else if (*format == 'c' ) { + putchar_debug((char)va_arg(args, int)); + } + } else { + out: + if (*format == '\n') putchar_debug('\r'); + putchar_debug(*format); + } + } + va_end(args); +} + +static void puint_debug(unsigned int num) +{ + char buf[12]; + unsigned int i = sizeof(buf)-2; + + buf[sizeof(buf)-1] = 0; + while (1) { + buf[i] = (num % 10) + '0'; + num /= 10; + if (num == 0) break; + i--; + } + printf_debug(buf + i); +} + +void putchar_debug(char c) +{ + while (!(LPUART3->STAT & LPUART_STAT_TDRE(1))) ; // wait + LPUART3->DATA = c; +} + +void printf_debug_init(void) +{ + CCM->CCGR0 |= CCM_CCGR0_CG6(1); // turn on Serial4 + IOMUXC->SW_MUX_CTL_PAD[kIOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_06] = 2; // Arduino pin 17 + LPUART3->BAUD = LPUART_BAUD_OSR(25) | LPUART_BAUD_SBR(8); // ~115200 baud + LPUART3->CTRL = LPUART_CTRL_TE(1); +} + +#endif diff --git a/os/hal/ports/MIMXRT1064/MIMXRT1064/printf_debug.h b/os/hal/ports/MIMXRT1064/MIMXRT1064/printf_debug.h new file mode 100644 index 0000000000..ceebc58478 --- /dev/null +++ b/os/hal/ports/MIMXRT1064/MIMXRT1064/printf_debug.h @@ -0,0 +1,13 @@ +#pragma once + +#define printf_init() +#define printf(...) +#define printf_debug_init() +#define printf_debug(...) + +// Comment out to enable debug messages by a printf_debug implementation of your +// choice, e.g. os/hal/ports/MIMXRT1064/MIMXRT1064/printf_debug.c: +// +// #include "chprintf.h" +// #undef printf_debug +// extern void printf_debug(const char *format, ...);