/* mbed Microcontroller Library * Copyright (c) 2006-2020 ARM Limited * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "pinmap.h" #include "clock_config.h" #include "fsl_clock.h" #include "fsl_xbara.h" #include "fsl_iomuxc.h" #include "fsl_gpio.h" #include "lpm.h" #include "usb_phy.h" #include "usb_device_config.h" #define LPSPI_CLOCK_SOURCE_DIVIDER (7U) #define LPI2C_CLOCK_SOURCE_DIVIDER (5U) /* USB PHY condfiguration */ #define BOARD_USB_PHY_D_CAL (0x0CU) #define BOARD_USB_PHY_TXCAL45DP (0x06U) #define BOARD_USB_PHY_TXCAL45DM (0x06U) uint8_t mbed_otp_mac_address(char *mac); void mbed_default_mac_address(char *mac); /* MPU configuration. */ void BOARD_ConfigMPU(void) { /* Disable I cache and D cache */ if (SCB_CCR_IC_Msk == (SCB_CCR_IC_Msk & SCB->CCR)) { SCB_DisableICache(); } if (SCB_CCR_DC_Msk == (SCB_CCR_DC_Msk & SCB->CCR)) { SCB_DisableDCache(); } /* Disable MPU */ ARM_MPU_Disable(); /* MPU configure: * Use ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) * API in mpu_armv7.h. * param DisableExec Instruction access (XN) disable bit,0=instruction fetches enabled, 1=instruction fetches disabled. * param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. * Use MACROS defined in mpu_armv7.h: ARM_MPU_AP_NONE/ARM_MPU_AP_PRIV/ARM_MPU_AP_URO/ARM_MPU_AP_FULL/ARM_MPU_AP_PRO/ARM_MPU_AP_RO * Combine TypeExtField/IsShareable/IsCacheable/IsBufferable to configure MPU memory access attributes. * TypeExtField IsShareable IsCacheable IsBufferable Memory Attribtue Shareability Cache * 0 x 0 0 Strongly Ordered shareable * 0 x 0 1 Device shareable * 0 0 1 0 Normal not shareable Outer and inner write through no write allocate * 0 0 1 1 Normal not shareable Outer and inner write back no write allocate * 0 1 1 0 Normal shareable Outer and inner write through no write allocate * 0 1 1 1 Normal shareable Outer and inner write back no write allocate * 1 0 0 0 Normal not shareable outer and inner noncache * 1 1 0 0 Normal shareable outer and inner noncache * 1 0 1 1 Normal not shareable outer and inner write back write/read acllocate * 1 1 1 1 Normal shareable outer and inner write back write/read acllocate * 2 x 0 0 Device not shareable * Above are normal use settings, if your want to see more details or want to config different inner/outter cache policy. * please refer to Table 4-55 /4-56 in arm cortex-M7 generic user guide <dui0646b_cortex_m7_dgug.pdf> * param SubRegionDisable Sub-region disable field. 0=sub-region is enabled, 1=sub-region is disabled. * param Size Region size of the region to be configured. use ARM_MPU_REGION_SIZE_xxx MACRO in mpu_armv7.h. */ /* Region 0 setting: Memory with Device type, not shareable, non-cacheable. */ MPU->RBAR = ARM_MPU_RBAR(0, 0x80000000U); MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_512MB); /* Region 1 setting: Memory with Device type, not shareable, non-cacheable. */ MPU->RBAR = ARM_MPU_RBAR(1, 0x60000000U); MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_512MB); /* Region 2 setting */ #if defined(XIP_EXTERNAL_FLASH) && (XIP_EXTERNAL_FLASH == 1) /* Setting Memory with Normal type, not shareable, outer/inner write back. */ MPU->RBAR = ARM_MPU_RBAR(2, 0x60000000U); MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_RO, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_64MB); #endif /* Region 3 setting: Memory with Device type, not shareable, non-cacheable. */ MPU->RBAR = ARM_MPU_RBAR(3, 0x00000000U); MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_1GB); /* Region 4 setting: Memory with Normal type, not shareable, outer/inner write back */ MPU->RBAR = ARM_MPU_RBAR(4, 0x00000000U); MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_128KB); /* Region 5 setting: Memory with Normal type, not shareable, not cacheable */ /* DTCM is set to non-cacheable so that we can use it for things like Ethernet and * USB DMA buffers which will not work if they are cached. */ MPU->RBAR = ARM_MPU_RBAR(5, 0x20000000U); MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_128KB); /* Region 6 setting: Memory with Normal type, not shareable, outer/inner write back */ MPU->RBAR = ARM_MPU_RBAR(6, 0x20200000U); MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_256KB); /* The define sets the cacheable memory to shareable, * this suggestion is referred from chapter 2.2.1 Memory regions, * types and attributes in Cortex-M7 Devices, Generic User Guide */ #if defined(SDRAM_IS_SHAREABLE) /* Region 7 setting: Memory with Normal type, shareable, outer/inner write back, write/read allocate */ MPU->RBAR = ARM_MPU_RBAR(7, 0x80000000U); MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, 1, 1, 1, 0, ARM_MPU_REGION_SIZE_32MB); #else /* Region 7 setting: Memory with Normal type, not shareable, outer/inner write back, write/read allocate */ MPU->RBAR = ARM_MPU_RBAR(7, 0x80000000U); MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_32MB); #endif /* Enable MPU */ ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk); /* Enable I cache and D cache */ SCB_EnableDCache(); SCB_EnableICache(); } void BOARD_Init_PMIC_STBY_REQ(void) { CLOCK_EnableClock(kCLOCK_IomuxcSnvs); /* iomuxc_snvs clock (iomuxc_snvs_clk_enable): 0x03U */ /* GPIO configuration of PERI_PWREN on PMIC_STBY_REQ (pin L7) */ gpio_pin_config_t PERI_PWREN_config = { .direction = kGPIO_DigitalOutput, .outputLogic = 0U, .interruptMode = kGPIO_NoIntmode }; /* Initialize GPIO functionality on PMIC_STBY_REQ (pin L7) */ GPIO_PinInit(GPIO5, 2U, &PERI_PWREN_config); IOMUXC_SetPinMux( IOMUXC_SNVS_PMIC_STBY_REQ_GPIO5_IO02, /* PMIC_STBY_REQ is configured as GPIO5_IO02 */ 0U); /* Software Input On Field: Input Path is determined by functionality */ IOMUXC_SetPinConfig( IOMUXC_SNVS_PMIC_STBY_REQ_GPIO5_IO02, /* PMIC_STBY_REQ PAD functional properties : */ 0x10B0U); /* Slew Rate Field: Slow Slew Rate Drive Strength Field: R0/6 Speed Field: medium(100MHz) Open Drain Enable Field: Open Drain Disabled Pull / Keep Enable Field: Pull/Keeper Enabled Pull / Keep Select Field: Keeper Pull Up / Down Config. Field: 100K Ohm Pull Down Hyst. Enable Field: Hysteresis Disabled */ } // called before main void mbed_sdk_init() { BOARD_ConfigMPU(); #if MBED_CONF_TARGET_ENABLE_OVERDRIVE_MODE BOARD_ClockOverdrive(); #else BOARD_ClockFullSpeed(); #endif #if TARGET_EVK /* Since SNVS_PMIC_STBY_REQ_GPIO5_IO02 will output a high-level signal under Stop Mode(Suspend Mode) and this pin is * connected to LCD power switch circuit. So it needs to be configured as a low-level output GPIO to reduce the * current. */ BOARD_Init_PMIC_STBY_REQ(); #endif LPM_Init(); } void spi_setup_clock() { /*Set clock source for LPSPI*/ CLOCK_SetMux(kCLOCK_LpspiMux, 1U); CLOCK_SetDiv(kCLOCK_LpspiDiv, LPSPI_CLOCK_SOURCE_DIVIDER); } uint32_t spi_get_clock(void) { return (CLOCK_GetFreq(kCLOCK_Usb1PllPfd0Clk) / (LPSPI_CLOCK_SOURCE_DIVIDER + 1U)); } void us_ticker_setup_clock() { /* Set PERCLK_CLK source to OSC_CLK*/ CLOCK_SetMux(kCLOCK_PerclkMux, 1U); /* Set PERCLK_CLK divider to 1 */ CLOCK_SetDiv(kCLOCK_PerclkDiv, 0U); } uint32_t us_ticker_get_clock() { return CLOCK_GetFreq(kCLOCK_OscClk); } void serial_setup_clock(void) { /* Configure UART divider to default */ CLOCK_SetMux(kCLOCK_UartMux, 1); /* Set UART source to OSC 24M */ CLOCK_SetDiv(kCLOCK_UartDiv, 0); /* Set UART divider to 1 */ } uint32_t serial_get_clock(void) { uint32_t clock_freq; if (CLOCK_GetMux(kCLOCK_UartMux) == 0) /* PLL3 div6 80M */ { clock_freq = (CLOCK_GetPllFreq(kCLOCK_PllUsb1) / 6U) / (CLOCK_GetDiv(kCLOCK_UartDiv) + 1U); } else { clock_freq = CLOCK_GetOscFreq() / (CLOCK_GetDiv(kCLOCK_UartDiv) + 1U); } return clock_freq; } void i2c_setup_clock() { /* Select USB1 PLL (480 MHz) as master lpi2c clock source */ CLOCK_SetMux(kCLOCK_Lpi2cMux, 0U); CLOCK_SetDiv(kCLOCK_Lpi2cDiv, LPI2C_CLOCK_SOURCE_DIVIDER); } uint32_t i2c_get_clock() { return ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / 8) / (LPI2C_CLOCK_SOURCE_DIVIDER + 1U)); } void pwm_setup(uint32_t instance) { /* Use default clock settings */ /* Set the PWM Fault inputs to a low value */ XBARA_Init(XBARA1); XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1234Fault2); XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1234Fault3); switch (instance) { case 1: XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1Fault0); XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm1Fault1); break; case 2: XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm2Fault0); XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm2Fault1); break; case 3: XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm3Fault0); XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm3Fault1); break; case 4: XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm4Fault0); XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm4Fault1); break; default: break; } } uint32_t pwm_get_clock() { return CLOCK_GetFreq(kCLOCK_IpgClk); } // Change the NMI pin to an input. This allows NMI pin to // be used as a low power mode wakeup. The application will // need to change the pin back to NMI_b or wakeup only occurs once! void NMI_Handler(void) { pin_function(WAKEUP, 7); pin_mode(WAKEUP, PullDefault); } void mbed_mac_address(char *mac) { if (mbed_otp_mac_address(mac)) { return; } else { mbed_default_mac_address(mac); } return; } uint8_t mbed_otp_mac_address(char *mac) { #if TARGET_MIMXRT1050_EVK /* Check if a valid MAC address is programmed to the fuse bank */ if ((OCOTP->MAC0 != 0) && (OCOTP->MAC1 != 0) && (OCOTP->GP3 != 0)) { uint16_t MAC[3]; // 3 16 bits words for the MAC // Read the MAC address from the OCOTP MAC registers MAC[0] = (uint16_t)OCOTP->MAC0; // most significant half-word MAC[1] = (uint16_t)OCOTP->MAC1; MAC[2] = (uint16_t)OCOTP->GP3; // least significant half word // The network stack expects an array of 6 bytes // so we copy, and shift and copy from the half-word array to the byte array mac[0] = MAC[0] >> 8; mac[1] = MAC[0]; mac[2] = MAC[1] >> 8; mac[3] = MAC[1]; mac[4] = MAC[2] >> 8; mac[5] = MAC[2]; return 1; } #endif #if TARGET_TEENSY_4X if(OCOTP->MAC0 != 0 || OCOTP->MAC1 != 0) { mac[0] = OCOTP->MAC1 >> 8; mac[1] = OCOTP->MAC1 >> 0; mac[2] = OCOTP->MAC0 >> 24; mac[3] = OCOTP->MAC0 >> 16; mac[4] = OCOTP->MAC0 >> 8; mac[5] = OCOTP->MAC0 >> 0; return 1; } #endif return 0; } void mbed_default_mac_address(char *mac) { mac[0] = 0x00; mac[1] = 0x02; mac[2] = 0xF7; mac[3] = 0xF0; mac[4] = 0x00; mac[5] = 0x00; return; } void USB_DeviceClockInit(void) { usb_phy_config_struct_t phyConfig = { BOARD_USB_PHY_D_CAL, BOARD_USB_PHY_TXCAL45DP, BOARD_USB_PHY_TXCAL45DM, }; CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usbphy480M, 480000000U); CLOCK_EnableUsbhs0Clock(kCLOCK_Usb480M, 480000000U); USB_EhciPhyInit(CONTROLLER_ID, BOARD_XTAL0_CLK_HZ, &phyConfig); } uint32_t USB_DeviceGetIrqNumber(void) { uint8_t irqNumber; uint8_t usbDeviceEhciIrq[] = USBHS_IRQS; irqNumber = usbDeviceEhciIrq[CONTROLLER_ID - kUSB_ControllerEhci0]; return irqNumber; } #if MBED_CONF_TARGET_ENABLE_OVERDRIVE_MODE #define LPM_POWER_MODE LPM_PowerModeOverRun #else #define LPM_POWER_MODE LPM_PowerModeFullRun #endif void vPortPRE_SLEEP_PROCESSING(clock_mode_t powermode) { LPM_EnableWakeupSource(GPT2_IRQn); LPM_EnterLowPowerIdle(LPM_POWER_MODE); } void vPortPOST_SLEEP_PROCESSING(clock_mode_t powermode) { LPM_ExitLowPowerIdle(LPM_POWER_MODE); LPM_DisableWakeupSource(GPT2_IRQn); }