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
This commit is contained in:
Michael Stapelberg 2020-06-10 22:07:24 +02:00
parent 334fe4f499
commit 22b4ec3b6b
10 changed files with 876 additions and 435 deletions

View File

@ -0,0 +1,158 @@
/*
* Copyright (C) 2013-2016 Fabio Utzig, http://fabioutzig.com
* (C) 2016 flabbergast <s3+flabbergast@sdfeu.org>
*
* 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

View File

@ -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();
}
/**

View File

@ -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
};

View File

@ -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);

View File

@ -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
/* 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);
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);
#if KINETIS_MCG_MODE == KINETIS_MCG_MODE_FEI
/* This is the default mode at reset. */
BOARD_InitBootClocks();
//SystemCoreClockUpdate();
/* Configure FEI mode */
MCG->C4 = MCG_C4_DRST_DRS(KINETIS_MCG_FLL_DRS) |
(KINETIS_MCG_FLL_DMX32 ? MCG_C4_DMX32 : 0);
// TODO: is the following covered by NXP startup code somewhere?
/* 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 */
// 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;
#elif KINETIS_MCG_MODE == KINETIS_MCG_MODE_PEE
// 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);
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;
printf_debug_init();
printf_debug("\n***********IMXRT Chibi Startup**********\n");
printf_debug("test %d %d %d\n", 1, -1234567, 3);
/* 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 */
}
/** @} */

View File

@ -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

View File

@ -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;
}
/** @} */

View File

@ -1,10 +1,14 @@
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)
@ -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}

View File

@ -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 <stdarg.h>
#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

View File

@ -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, ...);