From 22b4ec3b6bb3256a9be8474d0452d14ffb34001a Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 10 Jun 2020 22:07:24 +0200 Subject: [PATCH] MIMXRT1062: hal: port Arduino Teensy 4 Core startup code and linker script The one oddity of this platform is that it requires using XIP (eXecute In Place), which for us largely means setting up a few special sections at special flash locations. References: https://www.nxp.com/docs/en/application-note/AN12107.pdf https://github.com/PaulStoffregen/cores/blob/master/teensy4/imxrt1062_t41.ld https://www.pjrc.com/store/teensy40.html#memory_layout --- .../ARMCMx/compilers/GCC/ld/MIMXRT1062.ld | 158 ++++++++ os/hal/boards/PJRC_TEENSY_4_1/board.c | 3 + .../MIMXRT1062/MIMXRT1062/bootable_image.c | 346 ++++++++++++++++++ .../MIMXRT1062/MIMXRT1062/clock_config.c | 4 + os/hal/ports/MIMXRT1062/MIMXRT1062/hal_lld.c | 257 +++---------- os/hal/ports/MIMXRT1062/MIMXRT1062/hal_lld.h | 215 +---------- os/hal/ports/MIMXRT1062/MIMXRT1062/mpu.c | 175 +++++++++ .../ports/MIMXRT1062/MIMXRT1062/platform.mk | 25 +- .../MIMXRT1062/MIMXRT1062/printf_debug.c | 115 ++++++ .../MIMXRT1062/MIMXRT1062/printf_debug.h | 13 + 10 files changed, 876 insertions(+), 435 deletions(-) create mode 100644 os/common/startup/ARMCMx/compilers/GCC/ld/MIMXRT1062.ld create mode 100644 os/hal/ports/MIMXRT1062/MIMXRT1062/bootable_image.c create mode 100644 os/hal/ports/MIMXRT1062/MIMXRT1062/mpu.c create mode 100644 os/hal/ports/MIMXRT1062/MIMXRT1062/printf_debug.c create mode 100644 os/hal/ports/MIMXRT1062/MIMXRT1062/printf_debug.h diff --git a/os/common/startup/ARMCMx/compilers/GCC/ld/MIMXRT1062.ld b/os/common/startup/ARMCMx/compilers/GCC/ld/MIMXRT1062.ld new file mode 100644 index 00000000..0ae1a5ee --- /dev/null +++ b/os/common/startup/ARMCMx/compilers/GCC/ld/MIMXRT1062.ld @@ -0,0 +1,158 @@ +/* + * 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. + */ + +/* + * MIMXRT1062 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 + * + * See also https://www.pjrc.com/store/teensy40.html#memory_layout + */ + flash0 : org = 0x60000000, len = 1984K /* 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 teensy 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.*/ +/* .data in teensy-arduino-core/imxrt1062.ld */ +REGION_ALIAS("DATA_RAM", ram0); +REGION_ALIAS("DATA_RAM_LMA", flash0); + +/* RAM region to be used for BSS segment.*/ +/* .bss in imxrt1062.ld */ +REGION_ALIAS("BSS_RAM", ram0); + +/* RAM region to be used for the default heap.*/ +/* _heap_start in imxrt1062.ld */ +REGION_ALIAS("HEAP_RAM", ram0); + +/* Generic rules inclusion.*/ +INCLUDE rules.ld diff --git a/os/hal/boards/PJRC_TEENSY_4_1/board.c b/os/hal/boards/PJRC_TEENSY_4_1/board.c index a3a31114..d2e393b9 100644 --- a/os/hal/boards/PJRC_TEENSY_4_1/board.c +++ b/os/hal/boards/PJRC_TEENSY_4_1/board.c @@ -204,8 +204,11 @@ const PALConfig pal_default_config = * and before any other initialization. */ void __early_init(void) { +} +void __late_init(void) { MIMXRT1062_clock_init(); + MIMXRT1062_MPU_init(); } /** diff --git a/os/hal/ports/MIMXRT1062/MIMXRT1062/bootable_image.c b/os/hal/ports/MIMXRT1062/MIMXRT1062/bootable_image.c new file mode 100644 index 00000000..c135e132 --- /dev/null +++ b/os/hal/ports/MIMXRT1062/MIMXRT1062/bootable_image.c @@ -0,0 +1,346 @@ +/* + 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 MIMXRT1062/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 + 0x60000000, // 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: + 1984*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 + // TODO: +#define ARDUINO_TEENSY41 1 + +#if defined(ARDUINO_TEENSY40) + 0x00200000, // sflashA1Size 0x50 +#elif defined(ARDUINO_TEENSY41) + 0x00800000, // sflashA1Size 0x50 +#else +#error "Unknow flash chip size"; +#endif + 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/MIMXRT1062/MIMXRT1062/clock_config.c b/os/hal/ports/MIMXRT1062/MIMXRT1062/clock_config.c index 18e4f9eb..5c3bb05a 100644 --- a/os/hal/ports/MIMXRT1062/MIMXRT1062/clock_config.c +++ b/os/hal/ports/MIMXRT1062/MIMXRT1062/clock_config.c @@ -256,6 +256,9 @@ void BOARD_BootClockRUN(void) /* Set Flexspi clock source. */ CLOCK_SetMux(kCLOCK_FlexspiMux, 3); #endif + // The following code results in a fault and seems incorrect: why set clock + // detail settings after disabling the clock? +#if 0 /* Disable Flexspi2 clock gate. */ CLOCK_DisableClock(kCLOCK_FlexSpi2); /* Set FLEXSPI2_PODF. */ @@ -268,6 +271,7 @@ void BOARD_BootClockRUN(void) CLOCK_SetDiv(kCLOCK_CsiDiv, 1); /* Set Csi clock source. */ CLOCK_SetMux(kCLOCK_CsiMux, 0); +#endif /* Disable LPSPI clock gate. */ CLOCK_DisableClock(kCLOCK_Lpspi1); CLOCK_DisableClock(kCLOCK_Lpspi2); diff --git a/os/hal/ports/MIMXRT1062/MIMXRT1062/hal_lld.c b/os/hal/ports/MIMXRT1062/MIMXRT1062/hal_lld.c index 9782cc4f..8e4d3164 100644 --- a/os/hal/ports/MIMXRT1062/MIMXRT1062/hal_lld.c +++ b/os/hal/ports/MIMXRT1062/MIMXRT1062/hal_lld.c @@ -43,8 +43,8 @@ */ /** - * @file MK66F18/hal_lld.c - * @brief Kinetis MK66F18 HAL Driver subsystem low level driver source template. + * @file MIMXRT1062/hal_lld.c + * @brief MIMXRT1062 HAL Driver subsystem low level driver source template. * * @addtogroup HAL * @{ @@ -52,6 +52,10 @@ #include "hal.h" +#include "printf_debug.h" + +#include "clock_config.h" + /*===========================================================================*/ /* Driver local definitions. */ /*===========================================================================*/ @@ -108,227 +112,54 @@ const uint8_t _cfm[0x10] = { * @notapi */ void hal_lld_init(void) { - -#if defined(MK66F18) - /* Disable the MPU by default */ - SYSMPU->CESR &= ~SYSMPU_CESR_VLD_MASK; -#endif - } -/** - * @brief MK66F18 clock initialization. - * @note All the involved constants come from the file @p board.h. - * @note This function is meant to be invoked early during the system - * initialization, it is usually invoked from the file - * @p board.c. - * @todo This function needs to be more generic. - * - * @special - */ -void MK66F18_clock_init(void) { -#if !KINETIS_NO_INIT - /* Disable the watchdog */ - WDOG->UNLOCK = 0xC520; - WDOG->UNLOCK = 0xD928; - WDOG->STCTRLH &= ~WDOG_STCTRLH_WDOGEN; +#define NVIC_NUM_INTERRUPTS 160 +extern uint32_t _vectors[NVIC_NUM_INTERRUPTS]; - SIM->SCGC5 |= SIM_SCGC5_PORTA | - SIM_SCGC5_PORTB | - SIM_SCGC5_PORTC | - SIM_SCGC5_PORTD | - SIM_SCGC5_PORTE; +uint32_t SystemCoreClock = 528000000UL; // default system clock + +void MIMXRT1062_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); - /* Ported from the Teensyduino Core Library at - https://github.com/PaulStoffregen/cores/blob/master/teensy3/mk20dx128.c - */ - /* Allow the MCU to enter High Speed Run mode (HSRUN) */ - SMC->PMPROT = SMC_PMPROT_AHSRUN_SET(1) | SMC_PMPROT_AVLP_SET(1) | SMC_PMPROT_ALLS_SET(1) | SMC_PMPROT_AVLLS_SET(1); + BOARD_InitBootClocks(); + //SystemCoreClockUpdate(); -#if KINETIS_MCG_MODE == KINETIS_MCG_MODE_FEI - /* This is the default mode at reset. */ + // TODO: is the following covered by NXP startup code somewhere? - /* Configure FEI mode */ - MCG->C4 = MCG_C4_DRST_DRS(KINETIS_MCG_FLL_DRS) | - (KINETIS_MCG_FLL_DMX32 ? MCG_C4_DMX32 : 0); + // 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); - /* Set clock dividers */ - SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(KINETIS_CLKDIV1_OUTDIV1-1) | - SIM_CLKDIV1_OUTDIV2(KINETIS_CLKDIV1_OUTDIV2-1) | -#if defined(MK66F18) - SIM_CLKDIV1_OUTDIV3(KINETIS_CLKDIV1_OUTDIV3-1) | -#endif - SIM_CLKDIV1_OUTDIV4(KINETIS_CLKDIV1_OUTDIV4-1); - SIM->CLKDIV2 = SIM_CLKDIV2_USBDIV(0); /* not strictly necessary since usb_lld will set this */ - -#elif KINETIS_MCG_MODE == KINETIS_MCG_MODE_PEE - - uint32_t ratio, frdiv; - uint32_t ratios[] = { 32, 64, 128, 256, 512, 1024, 1280, 1536 }; - uint8_t ratio_quantity = sizeof(ratios) / sizeof(ratios[0]); - uint8_t i; - - /* EXTAL0 and XTAL0 */ - PORTA->PCR[18] = 0; - PORTA->PCR[19] = 0; - - /* - * Start in FEI mode - */ - - /* Internal capacitors for crystal */ -#if defined(KINETIS_BOARD_OSCILLATOR_SETTING) - OSC0->CR = KINETIS_BOARD_OSCILLATOR_SETTING; -#else /* KINETIS_BOARD_OSCILLATOR_SETTING */ - /* Disable the internal capacitors */ - OSC0->CR = 0; -#endif /* KINETIS_BOARD_OSCILLATOR_SETTING */ - - /* TODO: need to add more flexible calculation, specially regarding - * divisors which may not be available depending on the XTAL - * frequency, which would required other registers to be modified. - */ - /* Enable OSC, low power mode */ - if (KINETIS_XTAL_FREQUENCY > 8000000UL) - MCG->C2 = MCG_C2_LOCRE0 | MCG_C2_EREFS0 | MCG_C2_RANGE0_SET(2); - else - MCG->C2 = MCG_C2_LOCRE0 | MCG_C2_EREFS0 | MCG_C2_RANGE0_SET(1); - - frdiv = 7; - ratio = KINETIS_XTAL_FREQUENCY / 31250UL; - for (i = 0; i < ratio_quantity; ++i) { - if (ratio == ratios[i]) { - frdiv = i; - break; - } + // 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); } - - /* Switch to crystal as clock source, FLL input of 31.25 KHz */ - MCG->C1 = MCG_C1_CLKS_SET(2) | MCG_C1_FRDIV_SET(frdiv); - - /* Wait for crystal oscillator to begin */ - while (!(MCG->S & MCG_S_OSCINIT0)); - - /* Wait for the FLL to use the oscillator */ - while (MCG->S & MCG_S_IREFST); - - /* Wait for the MCGOUTCLK to use the oscillator */ - while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST_SET(2)); - - /* Ported from the Teensyduino Core Library at - https://github.com/PaulStoffregen/cores/blob/master/teensy3/mk20dx128.c - */ -#define F_CPU KINETIS_SYSCLK_FREQUENCY -#define MCG_C5 MCG->C5 -#undef MCG_C5_PRDIV0 -#define MCG_C5_PRDIV0 MCG_C5_PRDIV0_SET -#define MCG_C6 MCG->C6 -#undef MCG_C6_VDIV0 -#define MCG_C6_VDIV0 MCG_C6_VDIV0_SET -#if 1 /* PJRC_HSRUN */ - // if we need faster than the crystal, turn on the PLL - - SMC->PMCTRL = SMC_PMCTRL_RUNM_SET(3); // enter HSRUN mode - #define SMC_PMSTAT_HSRUN ((uint8_t)0x80) - while (SMC->PMSTAT != SMC_PMSTAT_HSRUN) - ; // wait for HSRUN - - #if F_CPU == 256000000 - //See table in 27.4.6 MCG Control 6 Register (MCG_C6) - //16 -> Multiply factor 32. 32*8MHz =256MHz - MCG_C5 = MCG_C5_PRDIV0(0); - MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(16); - #elif F_CPU == 240000000 - MCG_C5 = MCG_C5_PRDIV0(0); - MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(14); - #elif F_CPU == 216000000 - MCG_C5 = MCG_C5_PRDIV0(0); - MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(11); - #elif F_CPU == 192000000 - MCG_C5 = MCG_C5_PRDIV0(0); - MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(8); - #elif F_CPU == 180000000 - MCG_C5 = MCG_C5_PRDIV0(1); - MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(29); - #elif F_CPU == 168000000 - MCG_C5 = MCG_C5_PRDIV0(0); - MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(5); - #elif F_CPU == 144000000 - MCG_C5 = MCG_C5_PRDIV0(0); - MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(2); - #elif F_CPU == 120000000 - MCG_C5 = MCG_C5_PRDIV0(1); - MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(14); - #elif F_CPU == 96000000 || F_CPU == 48000000 || F_CPU == 24000000 - MCG_C5 = MCG_C5_PRDIV0(1); - MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(8); - #elif F_CPU == 72000000 - MCG_C5 = MCG_C5_PRDIV0(1); - MCG_C6 = MCG_C6_PLLS | MCG_C6_VDIV0(2); - #elif F_CPU > 16000000 - #error "MK66FX1M0 does not support this clock speed yet...." - #endif - -#else /* PJRC_HSRUN */ - - /* - * Now in FBE mode - */ - #define KINETIS_PLLIN_FREQUENCY 2000000UL - /* - * Config PLL input for 2 MHz - * TODO: Make sure KINETIS_XTAL_FREQUENCY >= 2Mhz && <= 50Mhz - */ - MCG->C5 = MCG_C5_PRDIV0_SET((KINETIS_XTAL_FREQUENCY/KINETIS_PLLIN_FREQUENCY) - 1); - - /* - * Config PLL output to match KINETIS_SYSCLK_FREQUENCY - * TODO: make sure KINETIS_SYSCLK_FREQUENCY is a match - */ - for(i = 24; i < 56; i++) - { - if(i == (KINETIS_PLLCLK_FREQUENCY/KINETIS_PLLIN_FREQUENCY)) - { - /* Config PLL to match KINETIS_PLLCLK_FREQUENCY */ - MCG->C6 = MCG_C6_PLLS | MCG_C6_VDIV0_SET(i-24); - break; - } + 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); } - - if(i>=56) /* Config PLL for 96 MHz output as default setting */ - MCG->C6 = MCG_C6_PLLS | MCG_C6_VDIV0_SET(0); -#endif /* PJRC_HSRUN */ - - /* Wait for PLL to start using crystal as its input, and to lock */ - while ((MCG->S & (MCG_S_PLLST|MCG_S_LOCK0))!=(MCG_S_PLLST|MCG_S_LOCK0)); - - /* - * Now in PBE mode - */ - /* Set the PLL dividers for the different clocks */ - SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(KINETIS_CLKDIV1_OUTDIV1-1) | - SIM_CLKDIV1_OUTDIV2(KINETIS_CLKDIV1_OUTDIV2-1) | - SIM_CLKDIV1_OUTDIV4(KINETIS_CLKDIV1_OUTDIV4-1); - SIM->CLKDIV2 = SIM_CLKDIV2_USBDIV(0); - - /* Configure peripherals to use MCGPLLCLK */ - SIM->SOPT2 = SIM_SOPT2_PLLFLLSEL; - - /* Switch to PLL as clock source */ - MCG->C1 = MCG_C1_CLKS_SET(0); - - /* Wait for PLL clock to be used */ - while ((MCG->S & MCG_S_CLKST_MASK) != MCG_S_CLKST_PLL); - - /* - * Now in PEE mode - */ -#else /* KINETIS_MCG_MODE == KINETIS_MCG_MODE_PEE */ -#error Unimplemented KINETIS_MCG_MODE -#endif /* KINETIS_MCG_MODE == ... */ - -#endif /* !KINETIS_NO_INIT */ } /** @} */ diff --git a/os/hal/ports/MIMXRT1062/MIMXRT1062/hal_lld.h b/os/hal/ports/MIMXRT1062/MIMXRT1062/hal_lld.h index 4faf575e..d5322f0c 100644 --- a/os/hal/ports/MIMXRT1062/MIMXRT1062/hal_lld.h +++ b/os/hal/ports/MIMXRT1062/MIMXRT1062/hal_lld.h @@ -40,227 +40,17 @@ * @name Platform identification * @{ */ -#define PLATFORM_NAME "Kinetis" +#define PLATFORM_NAME "MIMXRT1062" /** @} */ -/** - * @name Internal clock sources - * @{ - */ -#define KINETIS_IRCLK_F 4000000 /**< Fast internal reference clock, factory trimmed. */ -#define KINETIS_IRCLK_S 32768 /**< Slow internal reference clock, factory trimmed. */ -/** @} */ - -#define KINETIS_MCG_MODE_FEI 1 /**< FLL Engaged Internal. */ -#define KINETIS_MCG_MODE_FEE 2 /**< FLL Engaged External. */ -#define KINETIS_MCG_MODE_FBI 3 /**< FLL Bypassed Internal. */ -#define KINETIS_MCG_MODE_FBE 4 /**< FLL Bypassed External. */ -#define KINETIS_MCG_MODE_PEE 5 /**< PLL Engaged External. */ -#define KINETIS_MCG_MODE_PBE 6 /**< PLL Bypassed External. */ -#define KINETIS_MCG_MODE_BLPI 7 /**< Bypassed Low Power Internal. */ -#define KINETIS_MCG_MODE_BLPE 8 /**< Bypassed Low Power External. */ - /*===========================================================================*/ /* Driver pre-compile time settings. */ /*===========================================================================*/ -/** - * @name Configuration options - * @{ - */ -/** - * @brief Disables the MCG/system clock initialization in the HAL. - */ -#if !defined(KINETIS_NO_INIT) || defined(__DOXYGEN__) -#define KINETIS_NO_INIT FALSE -#endif - -/** - * @brief MCG mode selection. - */ -#if !defined(KINETIS_MCG_MODE) || defined(__DOXYGEN__) -#define KINETIS_MCG_MODE KINETIS_MCG_MODE_PEE -#endif - -/** - * @brief MCU PLL clock frequency. - */ -#if !defined(KINETIS_PLLCLK_FREQUENCY) || defined(__DOXYGEN__) -#define KINETIS_PLLCLK_FREQUENCY 96000000UL -#endif - -/** - * @brief Clock divider for core/system clocks (OUTDIV1). - * @note The allowed range is 1..16 - * @note The default value is calculated for a 48 MHz system clock - * from a 96 MHz PLL output. - */ -#if !defined(KINETIS_CLKDIV1_OUTDIV1) || defined(__DOXYGEN__) - #if defined(KINETIS_SYSCLK_FREQUENCY) && KINETIS_SYSCLK_FREQUENCY > 0 - #define KINETIS_CLKDIV1_OUTDIV1 (KINETIS_PLLCLK_FREQUENCY/KINETIS_SYSCLK_FREQUENCY) - #else - #define KINETIS_CLKDIV1_OUTDIV1 2 - #endif -#endif - -/** - * @brief Clock divider for bus clock (OUTDIV2). - * @note The allowed range is 1..16 - * @note The default value is calculated for a 48 MHz bus clock - * from a 96 MHz PLL output. - */ -#if !defined(KINETIS_CLKDIV1_OUTDIV2) || defined(__DOXYGEN__) - #if defined(KINETIS_BUSCLK_FREQUENCY) && KINETIS_BUSCLK_FREQUENCY > 0 - #define KINETIS_CLKDIV1_OUTDIV2 (KINETIS_PLLCLK_FREQUENCY/KINETIS_BUSCLK_FREQUENCY) - #elif defined(KINETIS_SYSCLK_FREQUENCY) && KINETIS_SYSCLK_FREQUENCY > 0 - #define KINETIS_CLKDIV1_OUTDIV2 KINETIS_CLKDIV1_OUTDIV1 - #else - #define KINETIS_CLKDIV1_OUTDIV2 2 - #endif -#endif - -/** - * @brief Clock divider for FlexBus clock (OUTDIV3). - * @note The allowed range is 1..16 - * @note The default value is calculated for a 48 MHz clock - * from a 96 MHz PLL output. - */ -#if !defined(KINETIS_CLKDIV1_OUTDIV3) || defined(__DOXYGEN__) - #if defined(KINETIS_FLEXBUSCLK_FREQUENCY) && KINETIS_FLEXBUSCLK_FREQUENCY > 0 - #define KINETIS_CLKDIV1_OUTDIV3 (KINETIS_PLLCLK_FREQUENCY/KINETIS_FLEXBUSCLK_FREQUENCY) - #else - /* If no FlexBus frequency provided, use bus speed divider */ - #define KINETIS_CLKDIV1_OUTDIV3 KINETIS_CLKDIV1_OUTDIV2 - #endif -#endif - -/** - * @brief Clock divider for flash clock (OUTDIV4). - * @note The allowed range is 1..16 - * @note The default value is calculated for a 24 MHz flash clock - * from a 96 MHz PLL output - */ -#if !defined(KINETIS_CLKDIV1_OUTDIV4) || defined(__DOXYGEN__) - #if defined(KINETIS_FLASHCLK_FREQUENCY) && KINETIS_FLASHCLK_FREQUENCY > 0 - #define KINETIS_CLKDIV1_OUTDIV4 (KINETIS_PLLCLK_FREQUENCY/KINETIS_FLASHCLK_FREQUENCY) - #elif defined(KINETIS_SYSCLK_FREQUENCY) && KINETIS_SYSCLK_FREQUENCY > 0 - #define KINETIS_CLKDIV1_OUTDIV4 (KINETIS_CLKDIV1_OUTDIV1*2) - #else - #define KINETIS_CLKDIV1_OUTDIV4 4 - #endif -#endif - -/** - * @brief FLL DCO tuning enable for 32.768 kHz reference. - * @note Set to 1 for fine-tuning DCO for maximum frequency with - * a 32.768 kHz reference. - * @note The default value is for a 32.768 kHz external crystal. - */ -#if !defined(KINETIS_MCG_FLL_DMX32) || defined(__DOXYGEN__) -#define KINETIS_MCG_FLL_DMX32 1 -#endif - -/** - * @brief FLL DCO range selection. - * @note The allowed range is 0...3. - * @note The default value is calculated for 48 MHz FLL output - * from a 32.768 kHz external crystal. - * (DMX32 && DRST_DRS=1 => F=1464; 32.768 kHz * F ~= 48 MHz.) - * - */ -#if !defined(KINETIS_MCG_FLL_DRS) || defined(__DOXYGEN__) -#define KINETIS_MCG_FLL_DRS 2 -#endif - -/** - * @brief MCU system/core clock frequency. - */ -#if !defined(KINETIS_SYSCLK_FREQUENCY) || defined(__DOXYGEN__) -#define KINETIS_SYSCLK_FREQUENCY (KINETIS_PLLCLK_FREQUENCY / KINETIS_CLKDIV1_OUTDIV1) -#endif - -/** - * @brief MCU bus clock frequency. - */ -#if !defined(KINETIS_BUSCLK_FREQUENCY) || defined(__DOXYGEN__) -#define KINETIS_BUSCLK_FREQUENCY (KINETIS_PLLCLK_FREQUENCY / KINETIS_CLKDIV1_OUTDIV2) -#endif - -/** - * @brief MCU flash clock frequency. - */ -#if !defined(KINETIS_FLASHCLK_FREQUENCY) || defined(__DOXYGEN__) -#define KINETIS_FLASHCLK_FREQUENCY (KINETIS_PLLCLK_FREQUENCY / KINETIS_CLKDIV1_OUTDIV4) -#endif - -/** @} */ - /*===========================================================================*/ /* Derived constants and error checks. */ /*===========================================================================*/ -#if !defined(KINETIS_SYSCLK_FREQUENCY) - #error KINETIS_SYSCLK_FREQUENCY must be defined -#endif - -#if KINETIS_SYSCLK_FREQUENCY <= 0 || KINETIS_SYSCLK_FREQUENCY > KINETIS_SYSCLK_MAX - #error KINETIS_SYSCLK_FREQUENCY out of range -#endif - -#if !defined(KINETIS_BUSCLK_FREQUENCY) - #error KINETIS_BUSCLK_FREQUENCY must be defined -#endif - -#if KINETIS_BUSCLK_FREQUENCY <= 0 || KINETIS_BUSCLK_FREQUENCY > KINETIS_BUSCLK_MAX - #error KINETIS_BUSCLK_FREQUENCY out of range -#endif - -#if KINETIS_BUSCLK_FREQUENCY > KINETIS_SYSCLK_FREQUENCY - #error KINETIS_BUSCLK_FREQUENCY must be an integer divide of\ - KINETIS_SYSCLK_FREQUENCY -#endif - -#if !defined(KINETIS_FLASHCLK_FREQUENCY) - #error KINETIS_FLASHCLK_FREQUENCY must be defined -#endif - -#if KINETIS_FLASHCLK_FREQUENCY <= 0 || KINETIS_FLASHCLK_FREQUENCY > KINETIS_FLASHCLK_MAX - #error KINETIS_FLASHCLK_FREQUENCY out of range -#endif - -#if KINETIS_FLASHCLK_FREQUENCY > KINETIS_SYSCLK_FREQUENCY - #error KINETIS_FLASHCLK_FREQUENCY must be an integer divide of\ - KINETIS_SYSCLK_FREQUENCY -#endif - -#if !(defined(KINETIS_CLKDIV1_OUTDIV1) && \ - KINETIS_CLKDIV1_OUTDIV1 >= 1 && KINETIS_CLKDIV1_OUTDIV1 <= 16) - #error KINETIS_CLKDIV1_OUTDIV1 must be 1 through 16 -#endif - -#if !(defined(KINETIS_CLKDIV1_OUTDIV2) && \ - KINETIS_CLKDIV1_OUTDIV2 >= 1 && KINETIS_CLKDIV1_OUTDIV2 <= 16) -#error KINETIS_CLKDIV1_OUTDIV2 must be 1 through 16 -#endif - -#if !(defined(KINETIS_CLKDIV1_OUTDIV3) && \ - KINETIS_CLKDIV1_OUTDIV3 >= 1 && KINETIS_CLKDIV1_OUTDIV3 <= 16) -#error KINETIS_CLKDIV1_OUTDIV3 must be 1 through 16 -#endif - -#if !(defined(KINETIS_CLKDIV1_OUTDIV4) && \ - KINETIS_CLKDIV1_OUTDIV4 >= 1 && KINETIS_CLKDIV1_OUTDIV4 <= 16) -#error KINETIS_CLKDIV1_OUTDIV4 must be 1 through 16 -#endif - -#if !(KINETIS_MCG_FLL_DMX32 == 0 || KINETIS_MCG_FLL_DMX32 == 1) -#error Invalid KINETIS_MCG_FLL_DMX32 value, must be 0 or 1 -#endif - -#if !(0 <= KINETIS_MCG_FLL_DRS && KINETIS_MCG_FLL_DRS <= 3) -#error Invalid KINETIS_MCG_FLL_DRS value, must be 0...3 -#endif - /*===========================================================================*/ /* Driver data structures and types. */ /*===========================================================================*/ @@ -312,7 +102,8 @@ typedef uint32_t halrtcnt_t; extern "C" { #endif void hal_lld_init(void); - void MK66F18_clock_init(void); + void MIMXRT1062_clock_init(void); + void MIMXRT1062_MPU_init(void); #ifdef __cplusplus } #endif diff --git a/os/hal/ports/MIMXRT1062/MIMXRT1062/mpu.c b/os/hal/ports/MIMXRT1062/MIMXRT1062/mpu.c new file mode 100644 index 00000000..3e289585 --- /dev/null +++ b/os/hal/ports/MIMXRT1062/MIMXRT1062/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 MIMXRT1062/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 MIMXRT1062_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 = 0x60000000 | REGION(i++); // QSPI Flash + MPU->RASR = MEM_CACHE_WBWA | READONLY | SIZE_16M; + + MPU->RBAR = 0x70000000 | 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/MIMXRT1062/MIMXRT1062/platform.mk b/os/hal/ports/MIMXRT1062/MIMXRT1062/platform.mk index 68bd2214..9cdfc2f3 100644 --- a/os/hal/ports/MIMXRT1062/MIMXRT1062/platform.mk +++ b/os/hal/ports/MIMXRT1062/MIMXRT1062/platform.mk @@ -1,11 +1,15 @@ PLATFORMSRC_CONTRIB := ${CHIBIOS}/os/hal/ports/common/ARMCMx/nvic.c \ ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1062/MIMXRT1062/hal_lld.c \ - ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1062/LLD/PITv1/hal_st_lld.c - + ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1062/MIMXRT1062/clock_config.c \ + ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1062/MIMXRT1062/printf_debug.c \ + ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1062/MIMXRT1062/bootable_image.c \ + ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1062/MIMXRT1062/mpu.c + PLATFORMINC_CONTRIB := ${CHIBIOS}/os/hal/ports/common/ARMCMx \ ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1062/LLD \ - ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1062/MIMXRT1062 - + ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1062/MIMXRT1062 \ + ${CHIBIOS_CONTRIB}/ext/mcux-sdk/devices/MIMXRT1062/drivers + ifeq ($(USE_SMART_BUILD),yes) # Configuration files directory @@ -19,15 +23,16 @@ endif include ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1062/LLD/GPIOv1/driver.mk include ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1062/LLD/UARTv1/driver.mk -include ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1062/LLD/SPIv1/driver.mk -include ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1062/LLD/I2Cv1/driver.mk -include ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1062/LLD/PORTv1/driver.mk -include ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1062/LLD/ADCv1/driver.mk include ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1062/LLD/PITv1/driver.mk -include ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1062/LLD/SDHCv1/driver.mk -include ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1062/LLD/FTMv1/driver.mk include ${CHIBIOS_CONTRIB}/os/hal/ports/MIMXRT1062/LLD/USBHSv1/driver.mk # Shared variables ALLCSRC += $(PLATFORMSRC_CONTRIB) ALLINC += $(PLATFORMINC_CONTRIB) + +MIMXRT1062_DEFS = -DCPU_MIMXRT1062DVL6A -DXIP_EXTERNAL_FLASH=1 + +# The ChibiOS build system uses DDEFS: +DDEFS += ${MIMXRT1062_DEFS} +# The QMK ChibiOS build rules use OPT_DEFS: +OPT_DEFS += ${MIMXRT1062_DEFS} diff --git a/os/hal/ports/MIMXRT1062/MIMXRT1062/printf_debug.c b/os/hal/ports/MIMXRT1062/MIMXRT1062/printf_debug.c new file mode 100644 index 00000000..2f6d78b1 --- /dev/null +++ b/os/hal/ports/MIMXRT1062/MIMXRT1062/printf_debug.c @@ -0,0 +1,115 @@ +/* + 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), +// i.e. pin 17 on the Teensy 4.1: +#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/MIMXRT1062/MIMXRT1062/printf_debug.h b/os/hal/ports/MIMXRT1062/MIMXRT1062/printf_debug.h new file mode 100644 index 00000000..f1b807f0 --- /dev/null +++ b/os/hal/ports/MIMXRT1062/MIMXRT1062/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/MIMXRT1062/MIMXRT1062/printf_debug.c: +// +// #include "chprintf.h" +// #undef printf_debug +// extern void printf_debug(const char *format, ...);