Repostiory containing DAPLink source code with Reset Pin workaround for HANI_IOT board.
Upstream: https://github.com/ARMmbed/DAPLink
source/hic_hal/freescale/k26f/hic_init.c@0:01f31e923fe2, 2020-04-07 (annotated)
- Committer:
- Pawel Zarembski
- Date:
- Tue Apr 07 12:55:42 2020 +0200
- Revision:
- 0:01f31e923fe2
hani: DAPLink with reset workaround
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Pawel Zarembski |
0:01f31e923fe2 | 1 | /** |
Pawel Zarembski |
0:01f31e923fe2 | 2 | * @file hic_init.c |
Pawel Zarembski |
0:01f31e923fe2 | 3 | * @brief |
Pawel Zarembski |
0:01f31e923fe2 | 4 | * |
Pawel Zarembski |
0:01f31e923fe2 | 5 | * DAPLink Interface Firmware |
Pawel Zarembski |
0:01f31e923fe2 | 6 | * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved |
Pawel Zarembski |
0:01f31e923fe2 | 7 | * Copyright (c) 2016-2017 NXP |
Pawel Zarembski |
0:01f31e923fe2 | 8 | * SPDX-License-Identifier: Apache-2.0 |
Pawel Zarembski |
0:01f31e923fe2 | 9 | * |
Pawel Zarembski |
0:01f31e923fe2 | 10 | * Licensed under the Apache License, Version 2.0 (the "License"); you may |
Pawel Zarembski |
0:01f31e923fe2 | 11 | * not use this file except in compliance with the License. |
Pawel Zarembski |
0:01f31e923fe2 | 12 | * You may obtain a copy of the License at |
Pawel Zarembski |
0:01f31e923fe2 | 13 | * |
Pawel Zarembski |
0:01f31e923fe2 | 14 | * http://www.apache.org/licenses/LICENSE-2.0 |
Pawel Zarembski |
0:01f31e923fe2 | 15 | * |
Pawel Zarembski |
0:01f31e923fe2 | 16 | * Unless required by applicable law or agreed to in writing, software |
Pawel Zarembski |
0:01f31e923fe2 | 17 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
Pawel Zarembski |
0:01f31e923fe2 | 18 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
Pawel Zarembski |
0:01f31e923fe2 | 19 | * See the License for the specific language governing permissions and |
Pawel Zarembski |
0:01f31e923fe2 | 20 | * limitations under the License. |
Pawel Zarembski |
0:01f31e923fe2 | 21 | */ |
Pawel Zarembski |
0:01f31e923fe2 | 22 | |
Pawel Zarembski |
0:01f31e923fe2 | 23 | #include "hic_init.h" |
Pawel Zarembski |
0:01f31e923fe2 | 24 | #include "gpio.h" |
Pawel Zarembski |
0:01f31e923fe2 | 25 | #include "fsl_clock.h" |
Pawel Zarembski |
0:01f31e923fe2 | 26 | #include "usb_phy.h" |
Pawel Zarembski |
0:01f31e923fe2 | 27 | #include "util.h" |
Pawel Zarembski |
0:01f31e923fe2 | 28 | |
Pawel Zarembski |
0:01f31e923fe2 | 29 | static void busy_wait(uint32_t cycles) |
Pawel Zarembski |
0:01f31e923fe2 | 30 | { |
Pawel Zarembski |
0:01f31e923fe2 | 31 | volatile uint32_t i; |
Pawel Zarembski |
0:01f31e923fe2 | 32 | i = cycles; |
Pawel Zarembski |
0:01f31e923fe2 | 33 | |
Pawel Zarembski |
0:01f31e923fe2 | 34 | while (i > 0) { |
Pawel Zarembski |
0:01f31e923fe2 | 35 | i--; |
Pawel Zarembski |
0:01f31e923fe2 | 36 | } |
Pawel Zarembski |
0:01f31e923fe2 | 37 | } |
Pawel Zarembski |
0:01f31e923fe2 | 38 | |
Pawel Zarembski |
0:01f31e923fe2 | 39 | static void fll_delay(void) |
Pawel Zarembski |
0:01f31e923fe2 | 40 | { |
Pawel Zarembski |
0:01f31e923fe2 | 41 | // ~2.5ms at 16MHz core clock |
Pawel Zarembski |
0:01f31e923fe2 | 42 | busy_wait(10000); |
Pawel Zarembski |
0:01f31e923fe2 | 43 | } |
Pawel Zarembski |
0:01f31e923fe2 | 44 | |
Pawel Zarembski |
0:01f31e923fe2 | 45 | // This IRQ handler will be invoked if VDD falls below the trip point. |
Pawel Zarembski |
0:01f31e923fe2 | 46 | void LVD_LVW_IRQHandler(void) |
Pawel Zarembski |
0:01f31e923fe2 | 47 | { |
Pawel Zarembski |
0:01f31e923fe2 | 48 | if (PMC->LVDSC1 & PMC_LVDSC1_LVDF_MASK) |
Pawel Zarembski |
0:01f31e923fe2 | 49 | { |
Pawel Zarembski |
0:01f31e923fe2 | 50 | util_assert(false && "low voltage detect tripped"); |
Pawel Zarembski |
0:01f31e923fe2 | 51 | PMC->LVDSC1 |= PMC_LVDSC1_LVDACK_MASK; |
Pawel Zarembski |
0:01f31e923fe2 | 52 | } |
Pawel Zarembski |
0:01f31e923fe2 | 53 | if (PMC->LVDSC2 & PMC_LVDSC2_LVWF_MASK) |
Pawel Zarembski |
0:01f31e923fe2 | 54 | { |
Pawel Zarembski |
0:01f31e923fe2 | 55 | util_assert(false && "low voltage warning tripped"); |
Pawel Zarembski |
0:01f31e923fe2 | 56 | PMC->LVDSC2 |= PMC_LVDSC2_LVWACK_MASK; |
Pawel Zarembski |
0:01f31e923fe2 | 57 | } |
Pawel Zarembski |
0:01f31e923fe2 | 58 | } |
Pawel Zarembski |
0:01f31e923fe2 | 59 | |
Pawel Zarembski |
0:01f31e923fe2 | 60 | //! - MPU is disabled and gated. |
Pawel Zarembski |
0:01f31e923fe2 | 61 | //! - 8kB cache is enabled. SRAM is not cached, so no flushing is required for normal operation. |
Pawel Zarembski |
0:01f31e923fe2 | 62 | //! - Enable low voltage warning interrupt. |
Pawel Zarembski |
0:01f31e923fe2 | 63 | //! - Disable USB current limiter so the voltage doesn't drop as we enable high speed clocks. |
Pawel Zarembski |
0:01f31e923fe2 | 64 | void sdk_init(void) |
Pawel Zarembski |
0:01f31e923fe2 | 65 | { |
Pawel Zarembski |
0:01f31e923fe2 | 66 | CLOCK_SetXtal0Freq(16000000U); // 16 MHz crystal |
Pawel Zarembski |
0:01f31e923fe2 | 67 | CLOCK_SetXtal32Freq(0); |
Pawel Zarembski |
0:01f31e923fe2 | 68 | |
Pawel Zarembski |
0:01f31e923fe2 | 69 | // Disable the MPU if it's enabled. |
Pawel Zarembski |
0:01f31e923fe2 | 70 | if (SIM->SCGC7 & SIM_SCGC7_MPU_MASK) |
Pawel Zarembski |
0:01f31e923fe2 | 71 | { |
Pawel Zarembski |
0:01f31e923fe2 | 72 | SYSMPU->CESR = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 73 | SIM->SCGC7 &= ~SIM_SCGC7_MPU_MASK; |
Pawel Zarembski |
0:01f31e923fe2 | 74 | } |
Pawel Zarembski |
0:01f31e923fe2 | 75 | |
Pawel Zarembski |
0:01f31e923fe2 | 76 | // Invalidate and enable code cache. |
Pawel Zarembski |
0:01f31e923fe2 | 77 | LMEM->PCCCR = LMEM_PCCCR_GO_MASK | LMEM_PCCCR_INVW1_MASK | LMEM_PCCCR_INVW0_MASK | LMEM_PCCCR_ENCACHE_MASK; |
Pawel Zarembski |
0:01f31e923fe2 | 78 | |
Pawel Zarembski |
0:01f31e923fe2 | 79 | // Enable LVD/LVW IRQ. |
Pawel Zarembski |
0:01f31e923fe2 | 80 | PMC->LVDSC1 |= PMC_LVDSC1_LVDACK_MASK; |
Pawel Zarembski |
0:01f31e923fe2 | 81 | PMC->LVDSC1 = PMC_LVDSC1_LVDIE_MASK | PMC_LVDSC1_LVDV(0); // low trip point |
Pawel Zarembski |
0:01f31e923fe2 | 82 | PMC->LVDSC2 |= PMC_LVDSC2_LVWACK_MASK; |
Pawel Zarembski |
0:01f31e923fe2 | 83 | PMC->LVDSC2 = PMC_LVDSC2_LVWIE_MASK | PMC_LVDSC2_LVWV(0); // low trip point |
Pawel Zarembski |
0:01f31e923fe2 | 84 | // NVIC_EnableIRQ(LVD_LVW_IRQn); |
Pawel Zarembski |
0:01f31e923fe2 | 85 | |
Pawel Zarembski |
0:01f31e923fe2 | 86 | // Disable USB inrush current limiter. |
Pawel Zarembski |
0:01f31e923fe2 | 87 | SIM->USBPHYCTL |= SIM_USBPHYCTL_USBDISILIM_MASK; |
Pawel Zarembski |
0:01f31e923fe2 | 88 | } |
Pawel Zarembski |
0:01f31e923fe2 | 89 | |
Pawel Zarembski |
0:01f31e923fe2 | 90 | //! - Turn on 16MHz crystal oscillator. |
Pawel Zarembski |
0:01f31e923fe2 | 91 | //! - Turn on 32kHz IRC. |
Pawel Zarembski |
0:01f31e923fe2 | 92 | //! - Switch core clock to System PLL at 120 MHz, bus clock at 60 MHz, flash clock at 24 MHz. |
Pawel Zarembski |
0:01f31e923fe2 | 93 | //! - Enable the 480MHz USB PHY PLL. |
Pawel Zarembski |
0:01f31e923fe2 | 94 | //! - Ungate USBPHY and USBHS. |
Pawel Zarembski |
0:01f31e923fe2 | 95 | //! - Configure the USB PHY. |
Pawel Zarembski |
0:01f31e923fe2 | 96 | void hic_enable_usb_clocks(void) |
Pawel Zarembski |
0:01f31e923fe2 | 97 | { |
Pawel Zarembski |
0:01f31e923fe2 | 98 | // Enable external oscillator and 32kHz IRC. |
Pawel Zarembski |
0:01f31e923fe2 | 99 | MCG->C1 |= MCG_C1_IRCLKEN_MASK; // Select 32k IR. |
Pawel Zarembski |
0:01f31e923fe2 | 100 | // Delay at least 100µs for 32kHz IRQ to stabilize. |
Pawel Zarembski |
0:01f31e923fe2 | 101 | fll_delay(); |
Pawel Zarembski |
0:01f31e923fe2 | 102 | // Configure OSC for very high freq, low power mode. |
Pawel Zarembski |
0:01f31e923fe2 | 103 | MCG->C2 = (MCG->C2 & ~(MCG_C2_RANGE_MASK | MCG_C2_HGO_MASK)) | MCG_C2_RANGE(2); |
Pawel Zarembski |
0:01f31e923fe2 | 104 | OSC0->CR |= OSC_CR_ERCLKEN_MASK; // Enable OSC. |
Pawel Zarembski |
0:01f31e923fe2 | 105 | MCG->C2 |= MCG_C2_EREFS_MASK; // Select OSC as ext ref. |
Pawel Zarembski |
0:01f31e923fe2 | 106 | |
Pawel Zarembski |
0:01f31e923fe2 | 107 | // Wait for the oscillator to stabilize. |
Pawel Zarembski |
0:01f31e923fe2 | 108 | while (!(MCG->S & MCG_S_OSCINIT0_MASK)) |
Pawel Zarembski |
0:01f31e923fe2 | 109 | { |
Pawel Zarembski |
0:01f31e923fe2 | 110 | } |
Pawel Zarembski |
0:01f31e923fe2 | 111 | |
Pawel Zarembski |
0:01f31e923fe2 | 112 | // Divide 16MHz xtal by 512 = 31.25kHz |
Pawel Zarembski |
0:01f31e923fe2 | 113 | CLOCK_SetFbeMode(4, kMCG_Dmx32Default, kMCG_DrsMid, fll_delay); |
Pawel Zarembski |
0:01f31e923fe2 | 114 | |
Pawel Zarembski |
0:01f31e923fe2 | 115 | // Set dividers before switching to SYSPLL. |
Pawel Zarembski |
0:01f31e923fe2 | 116 | SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) // System/core /1 = 120MHz |
Pawel Zarembski |
0:01f31e923fe2 | 117 | | SIM_CLKDIV1_OUTDIV2(1) // Bus /2 = 60Mhz |
Pawel Zarembski |
0:01f31e923fe2 | 118 | | SIM_CLKDIV1_OUTDIV3(4) // FlexBus /5 = 24Mhz |
Pawel Zarembski |
0:01f31e923fe2 | 119 | | SIM_CLKDIV1_OUTDIV4(4); // Flash /5 = 24MHz |
Pawel Zarembski |
0:01f31e923fe2 | 120 | |
Pawel Zarembski |
0:01f31e923fe2 | 121 | // 120MHz SYSPLL |
Pawel Zarembski |
0:01f31e923fe2 | 122 | mcg_pll_config_t pllConfig; |
Pawel Zarembski |
0:01f31e923fe2 | 123 | pllConfig.enableMode = 0; |
Pawel Zarembski |
0:01f31e923fe2 | 124 | pllConfig.prdiv = 2 - 1; |
Pawel Zarembski |
0:01f31e923fe2 | 125 | pllConfig.vdiv = 30 - 16; |
Pawel Zarembski |
0:01f31e923fe2 | 126 | CLOCK_SetPbeMode(kMCG_PllClkSelPll0, &pllConfig); |
Pawel Zarembski |
0:01f31e923fe2 | 127 | CLOCK_SetPeeMode(); |
Pawel Zarembski |
0:01f31e923fe2 | 128 | |
Pawel Zarembski |
0:01f31e923fe2 | 129 | // Enable USB clock source and init phy. This turns on the 480MHz PLL. |
Pawel Zarembski |
0:01f31e923fe2 | 130 | CLOCK_EnableUsbhs0Clock(kCLOCK_UsbSrcPll0, CLOCK_GetFreq(kCLOCK_PllFllSelClk)); |
Pawel Zarembski |
0:01f31e923fe2 | 131 | USB_EhciPhyInit(0, CPU_XTAL_CLK_HZ); |
Pawel Zarembski |
0:01f31e923fe2 | 132 | |
Pawel Zarembski |
0:01f31e923fe2 | 133 | SystemCoreClockUpdate(); |
Pawel Zarembski |
0:01f31e923fe2 | 134 | } |
Pawel Zarembski |
0:01f31e923fe2 | 135 | |
Pawel Zarembski |
0:01f31e923fe2 | 136 | void hic_power_target(void) |
Pawel Zarembski |
0:01f31e923fe2 | 137 | { |
Pawel Zarembski |
0:01f31e923fe2 | 138 | // Keep powered off in bootloader mode |
Pawel Zarembski |
0:01f31e923fe2 | 139 | // to prevent the target from effecting the state |
Pawel Zarembski |
0:01f31e923fe2 | 140 | // of the reset line / reset button |
Pawel Zarembski |
0:01f31e923fe2 | 141 | if (!daplink_is_bootloader()) { |
Pawel Zarembski |
0:01f31e923fe2 | 142 | // configure pin as GPIO |
Pawel Zarembski |
0:01f31e923fe2 | 143 | PIN_POWER_EN_PORT->PCR[PIN_POWER_EN_BIT] = PORT_PCR_MUX(1); |
Pawel Zarembski |
0:01f31e923fe2 | 144 | // force always on logic 1 |
Pawel Zarembski |
0:01f31e923fe2 | 145 | PIN_POWER_EN_GPIO->PSOR = 1UL << PIN_POWER_EN_BIT; |
Pawel Zarembski |
0:01f31e923fe2 | 146 | PIN_POWER_EN_GPIO->PDDR |= 1UL << PIN_POWER_EN_BIT; |
Pawel Zarembski |
0:01f31e923fe2 | 147 | |
Pawel Zarembski |
0:01f31e923fe2 | 148 | // Let the voltage rails stabilize. This is especailly important |
Pawel Zarembski |
0:01f31e923fe2 | 149 | // during software resets, since the target's 3.3v rail can take |
Pawel Zarembski |
0:01f31e923fe2 | 150 | // 20-50ms to drain. During this time the target could be driving |
Pawel Zarembski |
0:01f31e923fe2 | 151 | // the reset pin low, causing the bootloader to think the reset |
Pawel Zarembski |
0:01f31e923fe2 | 152 | // button is pressed. |
Pawel Zarembski |
0:01f31e923fe2 | 153 | // Note: With optimization set to -O2 the value 5115 delays for ~1ms @ 20.9Mhz core |
Pawel Zarembski |
0:01f31e923fe2 | 154 | busy_wait(5115 * 50); |
Pawel Zarembski |
0:01f31e923fe2 | 155 | } |
Pawel Zarembski |
0:01f31e923fe2 | 156 | } |