diff --git a/src/device/nxp/clock_mimxrt1062.go b/src/device/nxp/mimxrt1062_clock.go similarity index 70% rename from src/device/nxp/clock_mimxrt1062.go rename to src/device/nxp/mimxrt1062_clock.go index a41e3f93..38e6e533 100644 --- a/src/device/nxp/clock_mimxrt1062.go +++ b/src/device/nxp/mimxrt1062_clock.go @@ -11,75 +11,42 @@ import ( "unsafe" ) +// Clock represents an individual peripheral clock that may be enabled/disabled +// at runtime. Clocks also have a method `Mux` for selecting the clock source +// and a method `Div` for selecting the hardware divisor. Note that many +// peripherals have an independent prescalar configuration applied to the output +// of this divisor. type ( Clock uint32 - Gate uint8 ClockMode uint8 - - // PLL configuration for ARM - ClockConfigArmPll struct { - LoopDivider uint32 // PLL loop divider. Valid range for divider value: 54-108. Fout=Fin*LoopDivider/2. - Src uint8 // Pll clock source, reference _clock_pll_clk_src - } - - // PLL configuration for System - ClockConfigSysPll struct { - LoopDivider uint8 // PLL loop divider. Intended to be 1 (528M): 0 - Fout=Fref*20, 1 - Fout=Fref*22 - Numerator uint32 // 30 bit Numerator of fractional loop divider. - Denominator uint32 // 30 bit Denominator of fractional loop divider - Src uint8 // Pll clock source, reference _clock_pll_clk_src - SsStop uint16 // Stop value to get frequency change. - SsEnable uint8 // Enable spread spectrum modulation - SsStep uint16 // Step value to get frequency change step. - } - - // PLL configuration for USB - ClockConfigUsbPll struct { - Instance uint8 // USB PLL number (1 or 2) - LoopDivider uint8 // PLL loop divider: 0 - Fout=Fref*20, 1 - Fout=Fref*22 - Src uint8 // Pll clock source, reference _clock_pll_clk_src - } - - // PLL configuration for AUDIO - ClockConfigAudioPll struct { - LoopDivider uint8 // PLL loop divider. Valid range for DIV_SELECT divider value: 27~54. - PostDivider uint8 // Divider after the PLL, should only be 1, 2, 4, 8, 16. - Numerator uint32 // 30 bit Numerator of fractional loop divider. - Denominator uint32 // 30 bit Denominator of fractional loop divider - Src uint8 // Pll clock source, reference _clock_pll_clk_src - } - - // PLL configuration for VIDEO - ClockConfigVideoPll struct { - LoopDivider uint8 // PLL loop divider. Valid range for DIV_SELECT divider value: 27~54. - PostDivider uint8 // Divider after the PLL, should only be 1, 2, 4, 8, 16. - Numerator uint32 // 30 bit Numerator of fractional loop divider. - Denominator uint32 // 30 bit Denominator of fractional loop divider - Src uint8 // Pll clock source, reference _clock_pll_clk_src - } - - // PLL configuration for ENET - ClockConfigEnetPll struct { - EnableClkOutput bool // Power on and enable PLL clock output for ENET0. - EnableClkOutput25M bool // Power on and enable PLL clock output for ENET2. - LoopDivider uint8 // Controls the frequency of the ENET0 reference clock: b00=25MHz, b01=50MHz, b10=100MHz (not 50% duty cycle), b11=125MHz - Src uint8 // Pll clock source, reference _clock_pll_clk_src - EnableClkOutput1 bool // Power on and enable PLL clock output for ENET1. - LoopDivider1 uint8 // Controls the frequency of the ENET1 reference clock: b00 25MHz, b01 50MHz, b10 100MHz (not 50% duty cycle), b11 125MHz - } ) +// Enable activates or deactivates the clock gate of receiver Clock c. +func (c Clock) Enable(enable bool) { + if enable { + c.setGate(clockNeededRunWait) + } else { + c.setGate(clockNotNeeded) + } +} + +// Mux selects a clock source for the mux of the receiver Clock c. +func (c Clock) Mux(mux uint32) { c.setCcm(mux) } + +// Div configures the prescalar divisor of the receiver Clock c. +func (c Clock) Div(div uint32) { c.setCcm(div) } + const ( - ModeClkRun ClockMode = 0 // Remain in run mode - ModeClkWait ClockMode = 1 // Transfer to wait mode - ModeClkStop ClockMode = 2 // Transfer to stop mode + ClockModeRun ClockMode = 0 // Remain in run mode + ClockModeWait ClockMode = 1 // Transfer to wait mode + ClockModeStop ClockMode = 2 // Transfer to stop mode ) -const ( - GateClkNotNeeded Gate = 0 // Clock is off during all modes - GateClkNeededRun Gate = 1 // Clock is on in run mode, but off in WAIT and STOP modes - GateClkNeededRunWait Gate = 3 // Clock is on during all modes, except STOP mode -) +// Set configures the run mode of the MCU. +func (m ClockMode) Set() { + CCM.CLPCR.Set((CCM.CLPCR.Get() & ^uint32(CCM_CLPCR_LPM_Msk)) | + ((uint32(m) << CCM_CLPCR_LPM_Pos) & CCM_CLPCR_LPM_Msk)) +} // Named oscillators const ( @@ -259,6 +226,7 @@ const ( ClockPfd3 Clock = 3 // PLL PFD3 ) +// Named clock muxes of integrated peripherals const ( MuxIpPll3Sw Clock = (offCCSR & 0xFF) | (CCM_CCSR_PLL3_SW_CLK_SEL_Pos << 8) | (((CCM_CCSR_PLL3_SW_CLK_SEL_Msk >> CCM_CCSR_PLL3_SW_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // pll3_sw_clk mux name MuxIpPeriph Clock = (offCBCDR & 0xFF) | (CCM_CBCDR_PERIPH_CLK_SEL_Pos << 8) | (((CCM_CBCDR_PERIPH_CLK_SEL_Msk >> CCM_CBCDR_PERIPH_CLK_SEL_Pos) & 0x1FFF) << 13) | (CCM_CDHIPR_PERIPH_CLK_SEL_BUSY_Pos << 26) // periph mux name @@ -286,6 +254,7 @@ const ( MuxIpCsi Clock = (offCSCDR3 & 0xFF) | (CCM_CSCDR3_CSI_CLK_SEL_Pos << 8) | (((CCM_CSCDR3_CSI_CLK_SEL_Msk >> CCM_CSCDR3_CSI_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // csi mux name ) +// Named hardware clock divisors of integrated peripherals const ( DivIpArm Clock = (offCACRR & 0xFF) | (CCM_CACRR_ARM_PODF_Pos << 8) | (((CCM_CACRR_ARM_PODF_Msk >> CCM_CACRR_ARM_PODF_Pos) & 0x1FFF) << 13) | (CCM_CDHIPR_ARM_PODF_BUSY_Pos << 26) // core div name DivIpPeriphClk2 Clock = (offCBCDR & 0xFF) | (CCM_CBCDR_PERIPH_CLK2_PODF_Pos << 8) | (((CCM_CBCDR_PERIPH_CLK2_PODF_Msk >> CCM_CBCDR_PERIPH_CLK2_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // periph clock2 div name @@ -345,7 +314,7 @@ const ( noBusyWait = 0x20 ) -// analog pll definition +// analog PLL definition const ( pllBypassPos = 16 pllBypassClkSrcMsk = 0xC000 @@ -358,29 +327,14 @@ const ( pllSrcClkPN = 1 // Pll clock source CLK1_P and CLK1_N ) -// Set configures the run mode of the MCU. -func (m ClockMode) Set() { - CCM.CLPCR.Set((CCM.CLPCR.Get() & ^uint32(CCM_CLPCR_LPM_Msk)) | - ((uint32(m) << CCM_CLPCR_LPM_Pos) & CCM_CLPCR_LPM_Msk)) -} +const ( + clockNotNeeded uint32 = 0 // Clock is off during all modes + clockNeededRun uint32 = 1 // Clock is on in run mode, but off in WAIT and STOP modes + clockNeededRunWait uint32 = 3 // Clock is on during all modes, except STOP mode +) -// Enable activates or deactivates the clock gate of receiver Clock clk. -func (clk Clock) Enable(enable bool) { - if enable { - clk.control(GateClkNeededRunWait) - } else { - clk.control(GateClkNotNeeded) - } -} - -// Mux selects a clock source for the mux of the receiver Clock clk. -func (clk Clock) Mux(mux uint32) { clk.ccm(mux) } - -// Div configures the prescalar divisor of the receiver Clock clk. -func (clk Clock) Div(div uint32) { clk.ccm(div) } - -// getCCGR returns the CCM clock gating register for the receiver clk. -func (clk Clock) getCCGR() *volatile.Register32 { +// getGate returns the CCM clock gating register for the receiver clk. +func (clk Clock) getGate() *volatile.Register32 { switch clk >> 8 { case 0: return &CCM.CCGR0 @@ -403,14 +357,14 @@ func (clk Clock) getCCGR() *volatile.Register32 { } } -// control enables or disables the receiver clk using its gating register. -func (clk Clock) control(value Gate) { - reg := clk.getCCGR() +// setGate enables or disables the receiver clk using its gating register. +func (clk Clock) setGate(value uint32) { + reg := clk.getGate() shift := clk & 0x1F - reg.Set((reg.Get() & ^(3 << shift)) | (uint32(value) << shift)) + reg.Set((reg.Get() & ^(3 << shift)) | (value << shift)) } -func (clk Clock) ccm(value uint32) { +func (clk Clock) setCcm(value uint32) { const ccmBase = 0x400fc000 reg := (*volatile.Register32)(unsafe.Pointer(uintptr(ccmBase + (uint32(clk) & 0xFF)))) msk := ((uint32(clk) >> 13) & 0x1FFF) << ((uint32(clk) >> 8) & 0x1F) @@ -423,260 +377,6 @@ func (clk Clock) ccm(value uint32) { } } -// GetFreq returns the calculated frequency of the receiver clock clk. -func (clk Clock) GetFreq() uint32 { - switch clk { - case ClockCpu, ClockAhb: - return getAhbFreq() - case ClockSemc: - return getSemcFreq() - case ClockIpg: - return getIpgFreq() - case ClockPer: - return getPerClkFreq() - case ClockOsc: - return getOscFreq() - case ClockRtc: - return getRtcFreq() - case ClockArmPll: - return ClockPllArm.getPllFreq() - case ClockUsb1Pll: - return ClockPllUsb1.getPllFreq() - case ClockUsb1PllPfd0: - return ClockPfd0.getUsb1PfdFreq() - case ClockUsb1PllPfd1: - return ClockPfd1.getUsb1PfdFreq() - case ClockUsb1PllPfd2: - return ClockPfd2.getUsb1PfdFreq() - case ClockUsb1PllPfd3: - return ClockPfd3.getUsb1PfdFreq() - case ClockUsb2Pll: - return ClockPllUsb2.getPllFreq() - case ClockSysPll: - return ClockPllSys.getPllFreq() - case ClockSysPllPfd0: - return ClockPfd0.getSysPfdFreq() - case ClockSysPllPfd1: - return ClockPfd1.getSysPfdFreq() - case ClockSysPllPfd2: - return ClockPfd2.getSysPfdFreq() - case ClockSysPllPfd3: - return ClockPfd3.getSysPfdFreq() - case ClockEnetPll0: - return ClockPllEnet.getPllFreq() - case ClockEnetPll1: - return ClockPllEnet2.getPllFreq() - case ClockEnetPll2: - return ClockPllEnet25M.getPllFreq() - case ClockAudioPll: - return ClockPllAudio.getPllFreq() - case ClockVideoPll: - return ClockPllVideo.getPllFreq() - default: - panic("nxp: invalid clock") - } -} - -// getOscFreq returns the XTAL OSC clock frequency -func getOscFreq() uint32 { - return 24000000 // 24 MHz -} - -// getRtcFreq returns the RTC clock frequency -func getRtcFreq() uint32 { - return 32768 // 32.768 kHz -} - -func ccmCbcmrPeriphClk2Sel(n uint32) uint32 { - return (n << CCM_CBCMR_PERIPH_CLK2_SEL_Pos) & CCM_CBCMR_PERIPH_CLK2_SEL_Msk -} - -func ccmCbcmrPrePeriphClkSel(n uint32) uint32 { - return (n << CCM_CBCMR_PRE_PERIPH_CLK_SEL_Pos) & CCM_CBCMR_PRE_PERIPH_CLK_SEL_Msk -} - -// getPeriphClkFreq returns the PERIPH clock frequency -func getPeriphClkFreq() uint32 { - freq := uint32(0) - if CCM.CBCDR.HasBits(CCM_CBCDR_PERIPH_CLK_SEL_Msk) { - // Periph_clk2_clk -> Periph_clk - switch CCM.CBCMR.Get() & CCM_CBCMR_PERIPH_CLK2_SEL_Msk { - case ccmCbcmrPeriphClk2Sel(0): - // Pll3_sw_clk -> Periph_clk2_clk -> Periph_clk - freq = ClockPllUsb1.getPllFreq() - case ccmCbcmrPeriphClk2Sel(1): - // Osc_clk -> Periph_clk2_clk -> Periph_clk - freq = getOscFreq() - case ccmCbcmrPeriphClk2Sel(2): - freq = ClockPllSys.getPllFreq() - case ccmCbcmrPeriphClk2Sel(3): - freq = 0 - } - freq /= ((CCM.CBCDR.Get() & CCM_CBCDR_PERIPH_CLK2_PODF_Msk) >> CCM_CBCDR_PERIPH_CLK2_PODF_Pos) + 1 - } else { - // Pre_Periph_clk -> Periph_clk - switch CCM.CBCMR.Get() & CCM_CBCMR_PRE_PERIPH_CLK_SEL_Msk { - case ccmCbcmrPrePeriphClkSel(0): - // PLL2 -> Pre_Periph_clk -> Periph_clk - freq = ClockPllSys.getPllFreq() - case ccmCbcmrPrePeriphClkSel(1): - // PLL2 PFD2 -> Pre_Periph_clk -> Periph_clk - freq = ClockPfd2.getSysPfdFreq() - case ccmCbcmrPrePeriphClkSel(2): - // PLL2 PFD0 -> Pre_Periph_clk -> Periph_clk - freq = ClockPfd0.getSysPfdFreq() - case ccmCbcmrPrePeriphClkSel(3): - // PLL1 divided(/2) -> Pre_Periph_clk -> Periph_clk - freq = ClockPllArm.getPllFreq() / (((CCM.CACRR.Get() & CCM_CACRR_ARM_PODF_Msk) >> CCM_CACRR_ARM_PODF_Pos) + 1) - } - } - return freq -} - -// getAhbFreq returns the AHB clock frequency -func getAhbFreq() uint32 { - return getPeriphClkFreq() / (((CCM.CBCDR.Get() & CCM_CBCDR_AHB_PODF_Msk) >> CCM_CBCDR_AHB_PODF_Pos) + 1) -} - -// getSemcFreq returns the SEMC clock frequency -func getSemcFreq() uint32 { - - freq := uint32(0) - - if CCM.CBCDR.HasBits(CCM_CBCDR_SEMC_CLK_SEL_Msk) { - // SEMC alternative clock -> SEMC Clock - - if CCM.CBCDR.HasBits(CCM_CBCDR_SEMC_ALT_CLK_SEL_Msk) { - // PLL3 PFD1 -> SEMC alternative clock -> SEMC Clock - freq = ClockPfd1.getUsb1PfdFreq() - } else { - // PLL2 PFD2 -> SEMC alternative clock -> SEMC Clock - freq = ClockPfd2.getSysPfdFreq() - } - } else { - // Periph_clk -> SEMC Clock - freq = getPeriphClkFreq() - } - - freq /= ((CCM.CBCDR.Get() & CCM_CBCDR_SEMC_PODF_Msk) >> CCM_CBCDR_SEMC_PODF_Pos) + 1 - - return freq -} - -// getIpgFreq returns the IPG clock frequency -func getIpgFreq() uint32 { - return getAhbFreq() / (((CCM.CBCDR.Get() & CCM_CBCDR_IPG_PODF_Msk) >> CCM_CBCDR_IPG_PODF_Pos) + 1) -} - -// getPerClkFreq returns the PER clock frequency -func getPerClkFreq() uint32 { - freq := uint32(0) - if CCM.CSCMR1.HasBits(CCM_CSCMR1_PERCLK_CLK_SEL_Msk) { - // Osc_clk -> PER Cloc - freq = getOscFreq() - } else { - // Periph_clk -> AHB Clock -> IPG Clock -> PER Clock - freq = getIpgFreq() - } - return freq/((CCM.CSCMR1.Get()&CCM_CSCMR1_PERCLK_PODF_Msk)>> - CCM_CSCMR1_PERCLK_PODF_Pos) + 1 -} - -// getPllFreq returns the clock frequency of the receiver (PLL) clock clk -func (clk Clock) getPllFreq() uint32 { - enetRefClkFreq := []uint32{ - 25000000, // 25 MHz - 50000000, // 50 MHz - 100000000, // 100 MHz - 125000000, // 125 MHz - } - // check if PLL is enabled - if !clk.isPllEnabled() { - return 0 - } - // get pll reference clock - freq := clk.getBypassFreq() - // check if pll is bypassed - if clk.isPllBypassed() { - return freq - } - switch clk { - case ClockPllArm: - freq *= (CCM_ANALOG.PLL_ARM.Get() & CCM_ANALOG_PLL_ARM_DIV_SELECT_Msk) >> CCM_ANALOG_PLL_ARM_DIV_SELECT_Pos - freq >>= 1 - case ClockPllSys: - // PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM). - fFreq := float64(freq) * float64(CCM_ANALOG.PLL_SYS_NUM.Get()) - fFreq /= float64(CCM_ANALOG.PLL_SYS_DENOM.Get()) - if CCM_ANALOG.PLL_SYS.HasBits(CCM_ANALOG_PLL_SYS_DIV_SELECT_Msk) { - freq *= 22 - } else { - freq *= 20 - } - freq += uint32(fFreq) - case ClockPllUsb1: - if CCM_ANALOG.PLL_USB1.HasBits(CCM_ANALOG_PLL_USB1_DIV_SELECT_Msk) { - freq *= 22 - } else { - freq *= 20 - } - case ClockPllEnet: - divSelect := (CCM_ANALOG.PLL_ENET.Get() & CCM_ANALOG_PLL_ENET_DIV_SELECT_Msk) >> CCM_ANALOG_PLL_ENET_DIV_SELECT_Pos - freq = enetRefClkFreq[divSelect] - case ClockPllEnet2: - divSelect := (CCM_ANALOG.PLL_ENET.Get() & CCM_ANALOG_PLL_ENET_ENET2_DIV_SELECT_Msk) >> CCM_ANALOG_PLL_ENET_ENET2_DIV_SELECT_Pos - freq = enetRefClkFreq[divSelect] - case ClockPllEnet25M: - // ref_enetpll1 if fixed at 25MHz. - freq = 25000000 - case ClockPllUsb2: - if CCM_ANALOG.PLL_USB2.HasBits(CCM_ANALOG_PLL_USB2_DIV_SELECT_Msk) { - freq *= 22 - } else { - freq *= 20 - } - default: - freq = 0 - } - return freq -} - -// getSysPfdFreq returns current system PLL PFD output frequency -func (clk Clock) getSysPfdFreq() uint32 { - freq := ClockPllSys.getPllFreq() - switch clk { - case ClockPfd0: - freq /= (CCM_ANALOG.PFD_528.Get() & CCM_ANALOG_PFD_528_PFD0_FRAC_Msk) >> CCM_ANALOG_PFD_528_PFD0_FRAC_Pos - case ClockPfd1: - freq /= (CCM_ANALOG.PFD_528.Get() & CCM_ANALOG_PFD_528_PFD1_FRAC_Msk) >> CCM_ANALOG_PFD_528_PFD1_FRAC_Pos - case ClockPfd2: - freq /= (CCM_ANALOG.PFD_528.Get() & CCM_ANALOG_PFD_528_PFD2_FRAC_Msk) >> CCM_ANALOG_PFD_528_PFD2_FRAC_Pos - case ClockPfd3: - freq /= (CCM_ANALOG.PFD_528.Get() & CCM_ANALOG_PFD_528_PFD3_FRAC_Msk) >> CCM_ANALOG_PFD_528_PFD3_FRAC_Pos - default: - freq = 0 - } - return freq * 18 -} - -// getUsb1PfdFreq returns current USB1 PLL PFD output frequency -func (clk Clock) getUsb1PfdFreq() uint32 { - freq := ClockPllUsb1.getPllFreq() - switch clk { - case ClockPfd0: - freq /= (CCM_ANALOG.PFD_480.Get() & CCM_ANALOG_PFD_480_PFD0_FRAC_Msk) >> CCM_ANALOG_PFD_480_PFD0_FRAC_Pos - case ClockPfd1: - freq /= (CCM_ANALOG.PFD_480.Get() & CCM_ANALOG_PFD_480_PFD1_FRAC_Msk) >> CCM_ANALOG_PFD_480_PFD1_FRAC_Pos - case ClockPfd2: - freq /= (CCM_ANALOG.PFD_480.Get() & CCM_ANALOG_PFD_480_PFD2_FRAC_Msk) >> CCM_ANALOG_PFD_480_PFD2_FRAC_Pos - case ClockPfd3: - freq /= (CCM_ANALOG.PFD_480.Get() & CCM_ANALOG_PFD_480_PFD3_FRAC_Msk) >> CCM_ANALOG_PFD_480_PFD3_FRAC_Pos - default: - freq = 0 - } - return freq * 18 -} - func setSysPfd(value ...uint32) { for i, val := range value { pfd528 := CCM_ANALOG.PFD_528.Get() & @@ -701,40 +401,10 @@ func setUsb1Pfd(value ...uint32) { } } -func (clk Clock) isPllEnabled() bool { - const ccmAnalogBase = 0x400d8000 - addr := ccmAnalogBase + ((uint32(clk) >> 16) & 0xFFF) - pos := uint32(1 << (uint32(clk) & 0x1F)) - return ((*volatile.Register32)(unsafe.Pointer(uintptr(addr)))).HasBits(pos) -} - -func (clk Clock) isPllBypassed() bool { - const ccmAnalogBase = 0x400d8000 - addr := ccmAnalogBase + ((uint32(clk) >> 16) & 0xFFF) - pos := uint32(1 << pllBypassPos) - return ((*volatile.Register32)(unsafe.Pointer(uintptr(addr)))).HasBits(pos) -} - -func (clk Clock) getBypassFreq() uint32 { - const ccmAnalogBase = 0x400d8000 - addr := ccmAnalogBase + ((uint32(clk) >> 16) & 0xFFF) - src := (((*volatile.Register32)(unsafe.Pointer(uintptr(addr)))).Get() & - pllBypassClkSrcMsk) >> pllBypassClkSrcPos - if src == uint32(pllSrc24M) { - return getOscFreq() - } - return 0 -} - -func (clk Clock) bypass(bypass bool) { - const ccmAnalogBase = 0x400d8000 - if bypass { - addr := ccmAnalogBase + ((uint32(clk) >> 16) & 0xFFF) + 4 - ((*volatile.Register32)(unsafe.Pointer(uintptr(addr)))).Set(1 << pllBypassPos) - } else { - addr := ccmAnalogBase + ((uint32(clk) >> 16) & 0xFFF) + 8 - ((*volatile.Register32)(unsafe.Pointer(uintptr(addr)))).Set(1 << pllBypassPos) - } +// PLL configuration for ARM +type ClockConfigArmPll struct { + LoopDivider uint32 // PLL loop divider. Valid range for divider value: 54-108. Fout=Fin*LoopDivider/2. + Src uint8 // Pll clock source, reference _clock_pll_clk_src } func (cfg ClockConfigArmPll) Configure() { @@ -757,6 +427,17 @@ func (cfg ClockConfigArmPll) Configure() { CCM_ANALOG.PLL_ARM.ClearBits(CCM_ANALOG_PLL_ARM_BYPASS_Msk) } +// PLL configuration for System +type ClockConfigSysPll struct { + LoopDivider uint8 // PLL loop divider. Intended to be 1 (528M): 0 - Fout=Fref*20, 1 - Fout=Fref*22 + Numerator uint32 // 30 bit Numerator of fractional loop divider. + Denominator uint32 // 30 bit Denominator of fractional loop divider + Src uint8 // Pll clock source, reference _clock_pll_clk_src + SsStop uint16 // Stop value to get frequency change. + SsEnable uint8 // Enable spread spectrum modulation + SsStep uint16 // Step value to get frequency change step. +} + func (cfg ClockConfigSysPll) Configure(pfd ...uint32) { // bypass PLL first @@ -790,6 +471,13 @@ func (cfg ClockConfigSysPll) Configure(pfd ...uint32) { setSysPfd(pfd...) } +// PLL configuration for USB +type ClockConfigUsbPll struct { + Instance uint8 // USB PLL number (1 or 2) + LoopDivider uint8 // PLL loop divider: 0 - Fout=Fref*20, 1 - Fout=Fref*22 + Src uint8 // Pll clock source, reference _clock_pll_clk_src +} + func (cfg ClockConfigUsbPll) Configure(pfd ...uint32) { switch cfg.Instance { diff --git a/src/device/nxp/hardfault_mimxrt1062.go b/src/device/nxp/mimxrt1062_hardfault.go similarity index 100% rename from src/device/nxp/hardfault_mimxrt1062.go rename to src/device/nxp/mimxrt1062_hardfault.go diff --git a/src/device/nxp/mpu_mimxrt1062.go b/src/device/nxp/mimxrt1062_mpu.go similarity index 92% rename from src/device/nxp/mpu_mimxrt1062.go rename to src/device/nxp/mimxrt1062_mpu.go index d5b0f8a7..8483b756 100644 --- a/src/device/nxp/mpu_mimxrt1062.go +++ b/src/device/nxp/mimxrt1062_mpu.go @@ -34,16 +34,6 @@ type ( Extension uint32 ) -// MPU Type Register Definitions -const ( - MPU_TYPE_IREGION_Pos = 16 // MPU TYPE: IREGION Position - MPU_TYPE_IREGION_Msk = 0xFF << MPU_TYPE_IREGION_Pos // MPU TYPE: IREGION Mask - MPU_TYPE_DREGION_Pos = 8 // MPU TYPE: DREGION Position - MPU_TYPE_DREGION_Msk = 0xFF << MPU_TYPE_DREGION_Pos // MPU TYPE: DREGION Mask - MPU_TYPE_SEPARATE_Pos = 0 // MPU TYPE: SEPARATE Position - MPU_TYPE_SEPARATE_Msk = 1 // MPU TYPE: SEPARATE Mask -) - // MPU Control Register Definitions const ( MPU_CTRL_PRIVDEFENA_Pos = 2 // MPU CTRL: PRIVDEFENA Position @@ -54,12 +44,6 @@ const ( MPU_CTRL_ENABLE_Msk = 1 // MPU CTRL: ENABLE Mask ) -// MPU Region Number Register Definitions -const ( - MPU_RNR_REGION_Pos = 0 // MPU RNR: REGION Position - MPU_RNR_REGION_Msk = 0xFF // MPU RNR: REGION Mask -) - // MPU Region Base Address Register Definitions const ( MPU_RBAR_ADDR_Pos = 5 // MPU RBAR: ADDR Position @@ -161,11 +145,11 @@ func (mpu *MPU_Type) Enable(enable bool) { dsb 0xF isb 0xF `, nil) - EnableDcache(true) - EnableIcache(true) + enableDcache(true) + enableIcache(true) } else { - EnableIcache(false) - EnableDcache(false) + enableIcache(false) + enableDcache(false) arm.AsmFull(` dmb 0xF `, nil) @@ -200,7 +184,7 @@ func (mpu *MPU_Type) SetRASR(size RegionSize, access AccessPerms, ext Extension, MPU_RASR_ENABLE_Msk) } -func EnableIcache(enable bool) { +func enableIcache(enable bool) { if enable != SystemControl.CCR.HasBits(SCB_CCR_IC_Msk) { if enable { arm.AsmFull(` @@ -232,7 +216,7 @@ func EnableIcache(enable bool) { } } -func EnableDcache(enable bool) { +func enableDcache(enable bool) { if enable != SystemControl.CCR.HasBits(SCB_CCR_DC_Msk) { if enable { SystemControl.CSSELR.Set(0) diff --git a/src/machine/board_teensy40.go b/src/machine/board_teensy40.go index 558a09bc..ffda21ab 100644 --- a/src/machine/board_teensy40.go +++ b/src/machine/board_teensy40.go @@ -2,11 +2,6 @@ package machine -const ( - NUM_DIGITAL_IO_PINS = 40 - NUM_ANALOG_IO_PINS = 14 -) - // Digital pins const ( // = Pin // [Pad]: Alt Func 0 Alt Func 1 Alt Func 2 Alt Func 3 Alt Func 4 Alt Func 5 Alt Func 6 Alt Func 7 Alt Func 8 Alt Func 9 @@ -55,57 +50,53 @@ const ( // Analog pins const ( - // = Pin // Dig | [Pad] {Ch} - A0 = PA18 // D14 | [AD_B1_02] {7} - A1 = PA19 // D15 | [AD_B1_03] {8} - A2 = PA23 // D16 | [AD_B1_07] {12} - A3 = PA22 // D17 | [AD_B1_06] {11} - A4 = PA17 // D18 | [AD_B1_01] {6} - A5 = PA16 // D19 | [AD_B1_00] {5} - A6 = PA26 // D20 | [AD_B1_10] {15} - A7 = PA27 // D21 | [AD_B1_11] {0} - A8 = PA24 // D22 | [AD_B1_08] {13} - A9 = PA25 // D23 | [AD_B1_09] {14} - A10 = PA12 // D24 | [AD_B0_12] {1} - A11 = PA13 // D25 | [AD_B0_13] {2} - A12 = PA30 // D26 | [AD_B1_14] {128+3} - A13 = PA31 // D27 | [AD_B1_15] {128+4} + // = Pin // Dig | [Pad] {ADC1/ADC2} + A0 = PA18 // D14 | [AD_B1_02] { 7 / 7 } + A1 = PA19 // D15 | [AD_B1_03] { 8 / 8 } + A2 = PA23 // D16 | [AD_B1_07] { 12 / 12 } + A3 = PA22 // D17 | [AD_B1_06] { 11 / 11 } + A4 = PA17 // D18 | [AD_B1_01] { 6 / 6 } + A5 = PA16 // D19 | [AD_B1_00] { 5 / 5 } + A6 = PA26 // D20 | [AD_B1_10] { 15 / 15 } + A7 = PA27 // D21 | [AD_B1_11] { 0 / 0 } + A8 = PA24 // D22 | [AD_B1_08] { 13 / 13 } + A9 = PA25 // D23 | [AD_B1_09] { 14 / 14 } + A10 = PA12 // D24 | [AD_B0_12] { 1 / - } + A11 = PA13 // D25 | [AD_B0_13] { 2 / - } + A12 = PA30 // D26 | [AD_B1_14] { - / 3 } + A13 = PA31 // D27 | [AD_B1_15] { - / 4 } ) -func init() { - initLED() - initUART() - initSPI() - initI2C() -} - -// -- LEDs --------------------------------------------------------------------- - +// Default peripheral pins const ( - NUM_BOARD_LED = 1 + LED = D13 - LED_BUILTIN = D13 - LED = LED_BUILTIN + UART_RX_PIN = UART1_RX_PIN // D0 + UART_TX_PIN = UART1_TX_PIN // D1 + + SPI_SDI_PIN = SPI1_SDI_PIN // D12 + SPI_SDO_PIN = SPI1_SDO_PIN // D11 + SPI_SCK_PIN = SPI1_SCK_PIN // D13 + SPI_CS_PIN = SPI1_CS_PIN // D10 + + I2C_SDA_PIN = I2C1_SDA_PIN // D18/A4 + I2C_SCL_PIN = I2C1_SCL_PIN // D19/A5 ) -func initLED() {} - -// -- UART --------------------------------------------------------------------- - +// #=====================================================# +// | UART | +// #===========#===========#=============#===============# +// | Interface | Hardware | Clock(Freq) | RX/TX : Alt | +// #===========#===========#=============#=========-=====# +// | UART1 | LPUART6 | OSC(24 MHz) | D0/D1 : 2/2 | +// | UART2 | LPUART4 | OSC(24 MHz) | D7/D8 : 2/2 | +// | UART3 | LPUART2 | OSC(24 MHz) | D15/D14 : 2/2 | +// | UART4 | LPUART3 | OSC(24 MHz) | D16/D17 : 2/2 | +// | UART5 | LPUART8 | OSC(24 MHz) | D21/D20 : 2/2 | +// | UART6 | LPUART1 | OSC(24 MHz) | D25/D24 : 2/2 | +// | UART7 | LPUART7 | OSC(24 MHz) | D28/D29 : 2/2 | +// #===========#===========#=============#=========-=====# const ( - // #===========#===========#=============#===========#=============# - // | Interface | Hardware | Clock(Freq) | RX/TX Pin | RX/TX AltFn | - // #===========#===========#=============#===========#=============# - // | UART1 | LPUART6 | OSC(24 MHz) | D0/D1 | 2/2 | - // | UART2 | LPUART4 | OSC(24 MHz) | D7/D8 | 2/2 | - // | UART3 | LPUART2 | OSC(24 MHz) | D15/D14 | 2/2 | - // | UART4 | LPUART3 | OSC(24 MHz) | D16/D17 | 2/2 | - // | UART5 | LPUART8 | OSC(24 MHz) | D21/D20 | 2/2 | - // | UART6 | LPUART1 | OSC(24 MHz) | D25/D24 | 2/2 | - // | UART7 | LPUART7 | OSC(24 MHz) | D28/D29 | 2/2 | - // #===========#===========#=============#===========#=============# - NUM_UART_INTERFACES = 7 - UART1_RX_PIN = D0 UART1_TX_PIN = D1 @@ -126,25 +117,18 @@ const ( UART7_RX_PIN = D28 UART7_TX_PIN = D29 - - UART_RX_PIN = UART1_RX_PIN - UART_TX_PIN = UART1_TX_PIN ) -func initUART() {} - -// -- SPI ---------------------------------------------------------------------- - +// #==================================================================# +// | SPI | +// #===========#==========#===============#===========================# +// | Interface | Hardware | Clock(Freq) | SDI/SDO/SCK/CS : Alt | +// #===========#==========#===============#=================-=========# +// | SPI1 | LPSPI4 | PLL2(132 MHz) | D12/D11/D13/D10 : 3/3/3/3 | +// | SPI2 | LPSPI3 | PLL2(132 MHz) | D1/D26/D27/D0 : 7/2/2/7 | +// | SPI3 | LPSPI1 | PLL2(132 MHz) | D34/D35/D37/D36 : 4/4/4/4 | +// #===========#==========#===============#=================-=========# const ( - // #===========#==========#===================#===========================# - // | Interface | Hardware | Clock(Freq) | SDI/SDO/SCK/CS : Alt | - // #===========#==========#===================#=================-=========# - // | SPI1 | LPSPI4 | PLL3PFD1(130 MHz) | D12/D11/D13/D10 : 3/3/3/3 | - // | SPI2 | LPSPI3 | PLL3PFD1(130 MHz) | D1/D26/D27/D0 : 7/2/2/7 | - // | SPI3 | LPSPI1 | PLL3PFD1(130 MHz) | D34/D35/D37/D36 : 4/4/4/4 | - // #===========#==========#===================#=================-=========# - NUM_SPI_INTERFACES = 3 - SPI1_SDI_PIN = D12 SPI1_SDO_PIN = D11 SPI1_SCK_PIN = D13 @@ -159,19 +143,24 @@ const ( SPI3_SDO_PIN = D35 SPI3_SCK_PIN = D37 SPI3_CS_PIN = D36 - - SPI_SDI_PIN = SPI1_SDI_PIN - SPI_SDO_PIN = SPI1_SDO_PIN - SPI_SCK_PIN = SPI1_SCK_PIN - SPI_CS_PIN = SPI1_CS_PIN ) -func initSPI() {} - -// -- I2C ---------------------------------------------------------------------- - +// #====================================================# +// | I2C | +// #===========#==========#=============#===============# +// | Interface | Hardware | Clock(Freq) | SDA/SCL : Alt | +// #===========#==========#=============#=========-=====# +// | I2C1 | LPI2C1 | OSC(24 MHz) | D18/D19 : 3/3 | +// | I2C2 | LPI2C3 | OSC(24 MHz) | D17/D16 : 1/1 | +// | I2C3 | LPI2C4 | OSC(24 MHz) | D25/D24 : 0/0 | +// #===========#==========#=============#=========-=====# const ( - NUM_I2C_INTERFACES = 3 -) + I2C1_SDA_PIN = D18 + I2C1_SCL_PIN = D19 -func initI2C() {} + I2C2_SDA_PIN = D17 + I2C2_SCL_PIN = D16 + + I2C3_SDA_PIN = D25 + I2C3_SCL_PIN = D24 +) diff --git a/src/machine/machine_mimxrt1062.go b/src/machine/machine_mimxrt1062.go index 6fe0639f..ec316683 100644 --- a/src/machine/machine_mimxrt1062.go +++ b/src/machine/machine_mimxrt1062.go @@ -15,28 +15,6 @@ func CPUFrequency() uint32 { type PinMode uint8 -// muxSelect is yet another level of indirection required to connect pins in an -// alternate function state to a desired peripheral (since more than one pin can -// provide a given alternate function). -// -// Once a pin is configured with a given alternate function mode, the IOMUXC -// device must then be configured to select which alternate function pin to -// route to the desired peripheral. -// -// The reference manual refers to this functionality as a "Daisy Chain". The -// associated docs are found in the i.MX RT1060 Processor Reference Manual: -// "Chapter 11.3.3 Daisy chain - multi pads driving same module input pin" -type muxSelect struct { - mux uint8 // AF mux selection (NOT a Pin type) - sel *volatile.Register32 // AF selection register -} - -// connect configures the IOMUXC controller to route a given pin with alternate -// function to a desired peripheral (see godoc comments on type muxSelect). -func (s muxSelect) connect() { - s.sel.Set(uint32(s.mux)) -} - const ( // GPIO PinInput PinMode = iota @@ -45,93 +23,25 @@ const ( PinOutput PinOutputOpenDrain PinDisable + + // ADC + PinInputAnalog + + // UART + PinModeUARTTX + PinModeUARTRX + + // SPI + PinModeSPISDI + PinModeSPISDO + PinModeSPICLK + PinModeSPICS + + // I2C + PinModeI2CSDA + PinModeI2CSCL ) -// Configure sets the GPIO pad and pin properties, and selects the appropriate -// alternate function, for a given Pin and PinConfig. -func (p Pin) Configure(config PinConfig) { - var ( - // padSRE = uint32(0x01 << 0) - padDSE = func(n uint32) uint32 { return (n & 0x07) << 3 } - // padSPD = func(n uint32) uint32 { return (n & 0x03) << 6 } - padODE = uint32(0x01 << 11) - padPKE = uint32(0x01 << 12) - padPUE = uint32(0x01 << 13) - padPUP = func(n uint32) uint32 { return (n & 0x03) << 14 } - padHYS = uint32(0x01 << 16) - ) - - _, gpio := p.getGPIO() // use fast GPIO for all pins - pad, mux := p.getPad() - - // first configure the pad characteristics - switch config.Mode { - case PinInput: - gpio.GDIR.ClearBits(p.getMask()) - pad.Set(padDSE(7)) - - case PinInputPullUp: - gpio.GDIR.ClearBits(p.getMask()) - pad.Set(padDSE(7) | padPKE | padPUE | padPUP(3) | padHYS) - - case PinInputPullDown: - gpio.GDIR.ClearBits(p.getMask()) - pad.Set(padDSE(7) | padPKE | padPUE | padHYS) - - case PinOutput: - gpio.GDIR.SetBits(p.getMask()) - pad.Set(padDSE(7)) - - case PinOutputOpenDrain: - gpio.GDIR.SetBits(p.getMask()) - pad.Set(padDSE(7) | padODE) - - case PinDisable: - gpio.GDIR.ClearBits(p.getMask()) - pad.Set(padDSE(7) | padHYS) - } - - // then configure the alternate function mux - mux.Set(p.getMuxMode(config)) -} - -// getMuxMode acts as a callback from the `(Pin).Configure(PinMode)` routine to -// determine the alternate function setting for a given Pin and PinConfig. -// This value is used in the IOMUXC device's SW_MUX_CTL_PAD_GPIO_* registers. -func (p Pin) getMuxMode(config PinConfig) uint32 { - const forcePath = true // TODO: should be input parameter? - switch config.Mode { - - // GPIO - case PinInput, PinInputPullUp, PinInputPullDown, - PinOutput, PinOutputOpenDrain, PinDisable: - mode := uint32(0x5) // GPIO is always alternate function 5 - if forcePath { - mode |= 0x10 // SION bit - } - return mode - - default: - panic("machine: invalid pin mode") - } -} - -// Set changes the value of the GPIO pin. The pin must be configured as output. -func (p Pin) Set(value bool) { - _, gpio := p.getGPIO() // use fast GPIO for all pins - if value { - gpio.DR_SET.Set(p.getMask()) - } else { - gpio.DR_CLEAR.Set(p.getMask()) - } -} - -// Get returns the current value of a GPIO pin. -func (p Pin) Get() bool { - _, gpio := p.getGPIO() // use fast GPIO for all pins - return gpio.PSR.HasBits(p.getMask()) -} - // From the i.MXRT1062 Processor Reference Manual (Chapter 12 - GPIO): // // | High-speed GPIOs exist in this device: @@ -149,17 +59,13 @@ func (p Pin) Get() bool { // We cannot declare 32 pins for all available ports (GPIO1-9) anyway, since Pin // is only uint8, and 9*32=288 > 256, so something has to be sacrificed. -const numPorts, pinsPerPort = 4, 32 - const ( - portA Pin = iota * pinsPerPort // GPIO1(6) - portB // GPIO2(7) - portC // GPIO3(8) - portD // GPIO4(9) + portA Pin = iota * 32 // GPIO1(6) + portB // GPIO2(7) + portC // GPIO3(8) + portD // GPIO4(9) ) -const numPins = numPorts * pinsPerPort - const ( // [Pad]: Alt Func 0 Alt Func 1 Alt Func 2 Alt Func 3 Alt Func 4 Alt Func 5 Alt Func 6 Alt Func 7 Alt Func 8 Alt Func 9 // ---------- --------------- --------------- ------------------- -------------------- -------------------- ----------- -------------------- -------------------- --------------------- ---------------- @@ -296,9 +202,104 @@ const ( PD31 = portD + 31 // [EMC_31]: SEMC_DATA09 FLEXPWM3_PWMA01 LPUART7_TX LPSPI1_PCS1 CSI_DATA22 GPIO4_IO31 ENET2_TDATA01 ~ ~ ~ ) -func (p Pin) getPos() uint8 { return uint8(p % pinsPerPort) } +func (p Pin) getPos() uint8 { return uint8(p % 32) } func (p Pin) getMask() uint32 { return uint32(1) << p.getPos() } -func (p Pin) getPort() Pin { return Pin(p/pinsPerPort) * pinsPerPort } +func (p Pin) getPort() Pin { return Pin(p/32) * 32 } + +// Configure sets the GPIO pad and pin properties, and selects the appropriate +// alternate function, for a given Pin and PinConfig. +func (p Pin) Configure(config PinConfig) { + var ( + sre = uint32(0x01 << 0) + dse = func(n uint32) uint32 { return (n & 0x07) << 3 } + spd = func(n uint32) uint32 { return (n & 0x03) << 6 } + ode = uint32(0x01 << 11) + pke = uint32(0x01 << 12) + pue = uint32(0x01 << 13) + pup = func(n uint32) uint32 { return (n & 0x03) << 14 } + hys = uint32(0x01 << 16) + ) + + _, gpio := p.getGPIO() // use fast GPIO for all pins + pad, mux := p.getPad() + + // first configure the pad characteristics + switch config.Mode { + case PinInput: + gpio.GDIR.ClearBits(p.getMask()) + pad.Set(dse(7)) + + case PinInputPullUp: + gpio.GDIR.ClearBits(p.getMask()) + pad.Set(dse(7) | pke | pue | pup(3) | hys) + + case PinInputPullDown: + gpio.GDIR.ClearBits(p.getMask()) + pad.Set(dse(7) | pke | pue | hys) + + case PinOutput: + gpio.GDIR.SetBits(p.getMask()) + pad.Set(dse(7)) + + case PinOutputOpenDrain: + gpio.GDIR.SetBits(p.getMask()) + pad.Set(dse(7) | ode) + + case PinDisable: + gpio.GDIR.ClearBits(p.getMask()) + pad.Set(dse(7) | hys) + + case PinInputAnalog: + gpio.GDIR.ClearBits(p.getMask()) + pad.Set(dse(7)) + + case PinModeUARTTX: + pad.Set(sre | dse(3) | spd(3)) + + case PinModeUARTRX: + pad.Set(dse(7) | pke | pue | pup(3) | hys) + + case PinModeSPISDI: + pad.Set(dse(7) | spd(2)) + + case PinModeSPISDO: + pad.Set(dse(7) | spd(2)) + + case PinModeSPICLK: + pad.Set(dse(7) | spd(2)) + + case PinModeSPICS: + pad.Set(dse(7)) + + case PinModeI2CSDA, PinModeI2CSCL: + pad.Set(ode | sre | dse(4) | spd(1) | pke | pue | pup(3)) + } + + // then configure the alternate function mux + mux.Set(p.getMuxMode(config)) +} + +// Get returns the current value of a GPIO pin. +func (p Pin) Get() bool { + _, gpio := p.getGPIO() // use fast GPIO for all pins + return gpio.PSR.HasBits(p.getMask()) +} + +// Set changes the value of the GPIO pin. The pin must be configured as output. +func (p Pin) Set(value bool) { + _, gpio := p.getGPIO() // use fast GPIO for all pins + if value { + gpio.DR_SET.Set(p.getMask()) + } else { + gpio.DR_CLEAR.Set(p.getMask()) + } +} + +// Toggle switches an output pin from low to high or from high to low. +func (p Pin) Toggle() { + _, gpio := p.getGPIO() // use fast GPIO for all pins + gpio.DR_TOGGLE.Set(p.getMask()) +} // getGPIO returns both the normal (IPG_CLK_ROOT) and high-speed (AHB_CLK_ROOT) // GPIO peripherals to which a given Pin is connected. @@ -589,3 +590,168 @@ func (p Pin) getPad() (pad *volatile.Register32, mux *volatile.Register32) { } panic("machine: invalid pin") } + +// muxSelect is yet another level of indirection required to connect pins in an +// alternate function state to a desired peripheral (since more than one pin can +// provide a given alternate function). +// +// Once a pin is configured with a given alternate function mode, the IOMUXC +// device must then be configured to select which alternate function pin to +// route to the desired peripheral. +// +// The reference manual refers to this functionality as a "Daisy Chain". The +// associated docs are found in the i.MX RT1060 Processor Reference Manual: +// "Chapter 11.3.3 Daisy chain - multi pads driving same module input pin" +type muxSelect struct { + mux uint8 // AF mux selection (NOT a Pin type) + sel *volatile.Register32 // AF selection register +} + +// connect configures the IOMUXC controller to route a given pin with alternate +// function to a desired peripheral (see godoc comments on type muxSelect). +func (s muxSelect) connect() { + s.sel.Set(uint32(s.mux)) +} + +// getMuxMode acts as a callback from the `(Pin).Configure(PinMode)` routine to +// determine the alternate function setting for a given Pin and PinConfig. +// This value is used in the IOMUXC device's SW_MUX_CTL_PAD_GPIO_* registers. +func (p Pin) getMuxMode(config PinConfig) uint32 { + const forcePath = true // TODO: should be input parameter? + switch config.Mode { + + // GPIO + case PinInput, PinInputPullUp, PinInputPullDown, + PinOutput, PinOutputOpenDrain, PinDisable: + mode := uint32(0x5) // GPIO is always alternate function 5 + if forcePath { + mode |= 0x10 // SION bit + } + return mode + + // ADC + case PinInputAnalog: + mode := uint32(0x5) // use alternate function 5 (GPIO) + if forcePath { + mode |= 0x10 // SION bit + } + return mode + + // UART RX/TX + case PinModeUARTRX, PinModeUARTTX: + mode := uint32(0x2) // UART is always alternate function 2 on Teensy 4.0 + // TODO: Teensy 4.1 has a UART (LPUART5) with alternate function 1 + return mode + + // SPI SDI + case PinModeSPISDI: + var mode uint32 + switch p { + case PC15: // LPSPI1 SDI on PC15 alternate function 4 + mode = uint32(0x4) + case PA2: // LPSPI3 SDI on PA2 alternate function 7 + mode = uint32(0x7) + case PB1: // LPSPI4 SDI on PB1 alternate function 3 + mode = uint32(0x3) + default: + panic("machine: invalid SPI SDI pin") + } + if forcePath { + mode |= 0x10 // SION bit + } + return mode + + // SPI SDO + case PinModeSPISDO: + var mode uint32 + switch p { + case PC14: // LPSPI1 SDO on PC14 alternate function 4 + mode = uint32(0x4) + case PA30: // LPSPI3 SDO on PA30 alternate function 2 + mode = uint32(0x2) + case PB2: // LPSPI4 SDO on PB2 alternate function 3 + mode = uint32(0x3) + default: + panic("machine: invalid SPI SDO pin") + } + if forcePath { + mode |= 0x10 // SION bit + } + return mode + + // SPI SCK + case PinModeSPICLK: + var mode uint32 + switch p { + case PC12: // LPSPI1 SCK on PC12 alternate function 4 + mode = uint32(0x4) + case PA31: // LPSPI3 SCK on PA31 alternate function 2 + mode = uint32(0x2) + case PB3: // LPSPI4 SCK on PB3 alternate function 3 + mode = uint32(0x3) + default: + panic("machine: invalid SPI CLK pin") + } + if forcePath { + mode |= 0x10 // SION bit + } + return mode + + // SPI CS + case PinModeSPICS: + var mode uint32 + switch p { + case PC13: // LPSPI1 CS on PC13 alternate function 4 + mode = uint32(0x4) + case PA3: // LPSPI3 CS on PA3 alternate function 7 + mode = uint32(0x7) + case PB0: // LPSPI4 CS on PB0 alternate function 3 + mode = uint32(0x3) + default: // use alternate function 5 (GPIO) if non-CS pin selected + mode = uint32(0x5) + } + if forcePath { + mode |= 0x10 // SION bit + } + return mode + + // I2C SDA + case PinModeI2CSDA: + var mode uint32 + switch p { + case PA13: // LPI2C4 SDA on PA13 alternate function 0 + mode = uint32(0) + case PA17: // LPI2C1 SDA on PA17 alternate function 3 + mode = uint32(3) + case PA22: // LPI2C3 SDA on PA22 alternate function 1 + mode = uint32(1) + default: + panic("machine: invalid I2C SDA pin") + } + if forcePath { + mode |= 0x10 // SION bit + } + return mode + + // I2C SCL + case PinModeI2CSCL: + var mode uint32 + switch p { + case PA12: // LPI2C4 SCL on PA12 alternate function 0 + mode = uint32(0) + case PA16: // LPI2C1 SCL on PA16 alternate function 3 + mode = uint32(3) + case PA23: // LPI2C3 SCL on PA23 alternate function 1 + mode = uint32(1) + default: + panic("machine: invalid I2C SCL pin") + } + if forcePath { + mode |= 0x10 // SION bit + } + return mode + + default: + panic("machine: invalid pin mode") + } +} diff --git a/src/runtime/runtime_mimxrt1062_clock.go b/src/runtime/runtime_mimxrt1062_clock.go index a262fe2c..3a576198 100644 --- a/src/runtime/runtime_mimxrt1062_clock.go +++ b/src/runtime/runtime_mimxrt1062_clock.go @@ -6,66 +6,13 @@ import ( "device/nxp" ) -// Core, bus, and peripheral clock frequencies (Hz) +// Core clock frequencies (Hz) const ( - CORE_FREQ = 600000000 // 600 MHz - SYSTICK_FREQ = 100000 // 100 kHz (see note below) - _ // ----------- - AHB_FREQ = 600000000 // 600 MHz - CAN_FREQ = 40000000 // 40 MHz - CKIL_SYNC_FREQ = 32768 // 32.768 kHz - CSI_FREQ = 12000000 // 12 MHz - FLEXIO1_FREQ = 30000000 // 30 MHz - FLEXIO2_FREQ = 30000000 // 30 MHz - FLEXSPI2_FREQ = 327724137 // 327.7 MHz - FLEXSPI_FREQ = 327724137 // 327.7 MHz - IPG_FREQ = 150000000 // 150 MHz - LCDIF_FREQ = 39272727 // 39.3 MHz - LPI2C_FREQ = 60000000 // 60 MHz - LPSPI_FREQ = 132000000 // 132 MHz - PERCLK_FREQ = 24000000 // 24 MHz - SAI1_FREQ = 63529411 // 63.5 MHz - SAI2_FREQ = 63529411 // 63.5 MHz - SAI3_FREQ = 63529411 // 63.5 MHz - SEMC_FREQ = 163862068 // 163.9 MHz - SPDIF0_FREQ = 30000000 // 30 MHz - TRACE_FREQ = 132000000 // 132 MHz - UART_FREQ = 24000000 // 24 MHz - USDHC1_FREQ = 198000000 // 198 MHz - USDHC2_FREQ = 198000000 // 198 MHz + CORE_FREQ = 600000000 // 600 MHz + OSC_FREQ = 24000000 // 24 MHz ) -var ( - ArmPllConfig = nxp.ClockConfigArmPll{ - LoopDivider: 100, // PLL loop divider, Fout = Fin * 50 - Src: 0, // Bypass clock source, 0 - OSC 24M, 1 - CLK1_P and CLK1_N - } - SysPllConfig = nxp.ClockConfigSysPll{ - LoopDivider: 1, // PLL loop divider, Fout = Fin * ( 20 + LoopDivider*2 + Numerator / Denominator ) - Numerator: 0, // 30 bit Numerator of fractional loop divider - Denominator: 1, // 30 bit Denominator of fractional loop divider - Src: 0, // Bypass clock source, 0 - OSC 24M, 1 - CLK1_P and CLK1_N - } - Usb1PllConfig = nxp.ClockConfigUsbPll{ - Instance: 1, // USB PLL Instance - LoopDivider: 0, // PLL loop divider, Fout = Fin * 20 - Src: 0, // Bypass clock source, 0 - OSC 24M, 1 - CLK1_P and CLK1_N - } - Usb2PllConfig = nxp.ClockConfigUsbPll{ - Instance: 2, // USB PLL Instance - LoopDivider: 0, // PLL loop divider, Fout = Fin * 20 - Src: 0, // Bypass clock source, 0 - OSC 24M, 1 - CLK1_P and CLK1_N - } - VideoPllConfig = nxp.ClockConfigVideoPll{ - LoopDivider: 31, // PLL loop divider, Fout = Fin * ( LoopDivider + Numerator / Denominator ) - PostDivider: 8, // Divider after PLL - Numerator: 0, // 30 bit Numerator of fractional loop divider, Fout = Fin * ( LoopDivider + Numerator / Denominator ) - Denominator: 1, // 30 bit Denominator of fractional loop divider, Fout = Fin * ( LoopDivider + Numerator / Denominator ) - Src: 0, // Bypass clock source, 0 - OSC 24M, 1 - CLK1_P and CLK1_N - } -) - -// Note about SYSTICK_FREQ from Teensyduino (cores/teensy4/startup.c): +// Note from Teensyduino (cores/teensy4/startup.c): // // | ARM SysTick is used for most Ardiuno timing functions, delay(), millis(), // | micros(). SysTick can run from either the ARM core clock, or from an @@ -75,6 +22,30 @@ var ( // | the external clock is really 100 kHz. We use this clock rather than the // | ARM clock, to allow SysTick to maintain correct timing even when we change // | the ARM clock to run at different speeds. +const SYSTICK_FREQ = 100000 // 100 kHz + +var ( + ArmPllConfig = nxp.ClockConfigArmPll{ + LoopDivider: 100, // PLL loop divider, Fout=Fin*50 + Src: 0, // bypass clock source, 0=OSC24M, 1=CLK1_P & CLK1_N + } + SysPllConfig = nxp.ClockConfigSysPll{ + LoopDivider: 1, // PLL loop divider, Fout=Fin*(20+LOOP*2+NUMER/DENOM) + Numerator: 0, // 30-bit NUMER of fractional loop divider + Denominator: 1, // 30-bit DENOM of fractional loop divider + Src: 0, // bypass clock source, 0=OSC24M, 1=CLK1_P & CLK1_N + } + Usb1PllConfig = nxp.ClockConfigUsbPll{ + Instance: 1, // USB PLL instance + LoopDivider: 0, // PLL loop divider, Fout=Fin*20 + Src: 0, // bypass clock source, 0=OSC24M, 1=CLK1_P & CLK1_N + } + Usb2PllConfig = nxp.ClockConfigUsbPll{ + Instance: 2, // USB PLL instance + LoopDivider: 0, // PLL loop divider, Fout=Fin*20 + Src: 0, // bypass clock source, 0=OSC24M, 1=CLK1_P & CLK1_N + } +) // initClocks configures the core, buses, and all peripherals' clock source mux // and dividers for runtime. The clock gates for individual peripherals are all @@ -85,11 +56,10 @@ func initClocks() { // disable low-power mode so that __WFI doesn't lock up at runtime. // see: Using the MIMXRT1060/4-EVK with MCUXpresso IDE v10.3.x (v1.0.2, // 2019MAR01), chapter 14 - nxp.ModeClkRun.Set() + nxp.ClockModeRun.Set() - // enable 1MHz clock output + // enable and use 1MHz clock output nxp.XTALOSC24M.OSC_CONFIG2.SetBits(nxp.XTALOSC24M_OSC_CONFIG2_ENABLE_1M_Msk) - // use free 1MHz clock output nxp.XTALOSC24M.OSC_CONFIG2.ClearBits(nxp.XTALOSC24M_OSC_CONFIG2_MUX_1M_Msk) // initialize external 24 MHz clock @@ -101,10 +71,8 @@ func initClocks() { } nxp.CCM_ANALOG.MISC0_CLR.Set(nxp.CCM_ANALOG_MISC0_OSC_XTALOK_EN_Msk) - // initialize internal RC oscillator 24 MHz clock + // initialize internal RC OSC 24 MHz, and switch clock source to external OSC nxp.XTALOSC24M.LOWPWR_CTRL.SetBits(nxp.XTALOSC24M_LOWPWR_CTRL_RC_OSC_EN_Msk) - - // switch clock source to external oscillator nxp.XTALOSC24M.LOWPWR_CTRL_CLR.Set(nxp.XTALOSC24M_LOWPWR_CTRL_CLR_OSC_SEL_Msk) // set oscillator ready counter value @@ -123,142 +91,122 @@ func initClocks() { for !nxp.DCDC.REG0.HasBits(nxp.DCDC_REG0_STS_DC_OK_Msk) { } - // -------------------------------------------------------------------- AHB -- nxp.DivIpAhb.Div(0) // divide AHB_PODF (DIV1) - // -------------------------------------------------------------------- ADC -- - nxp.ClockIpAdc1.Enable(false) // disable ADC clock gates - nxp.ClockIpAdc2.Enable(false) // ~ + nxp.ClockIpAdc1.Enable(false) // disable ADC + nxp.ClockIpAdc2.Enable(false) // - // ------------------------------------------------------------------- XBAR -- - nxp.ClockIpXbar1.Enable(false) // disable XBAR clock gates - nxp.ClockIpXbar2.Enable(false) // ~ - nxp.ClockIpXbar3.Enable(false) // ~ + nxp.ClockIpXbar1.Enable(false) // disable XBAR + nxp.ClockIpXbar2.Enable(false) // + nxp.ClockIpXbar3.Enable(false) // - // ---------------------------------------------------------------- ARM/IPG -- nxp.DivIpIpg.Div(3) // divide IPG_PODF (DIV4) nxp.DivIpArm.Div(1) // divide ARM_PODF (DIV2) nxp.DivIpPeriphClk2.Div(0) // divide PERIPH_CLK2_PODF (DIV1) - // ---------------------------------------------------------------- GPT/PIT -- - nxp.ClockIpGpt1.Enable(false) // disable GPT/PIT clock gates - nxp.ClockIpGpt1S.Enable(false) // ~ - nxp.ClockIpGpt2.Enable(false) // ~ - nxp.ClockIpGpt2S.Enable(false) // ~ - nxp.ClockIpPit.Enable(false) // ~ + nxp.ClockIpGpt1.Enable(false) // disable GPT/PIT + nxp.ClockIpGpt1S.Enable(false) // + nxp.ClockIpGpt2.Enable(false) // + nxp.ClockIpGpt2S.Enable(false) // + nxp.ClockIpPit.Enable(false) // - // -------------------------------------------------------------------- PER -- nxp.DivIpPerclk.Div(0) // divide PERCLK_PODF (DIV1) - // ------------------------------------------------------------------ USDHC -- - nxp.ClockIpUsdhc1.Enable(false) // disable USDHC1 clock gate + nxp.ClockIpUsdhc1.Enable(false) // disable USDHC1 nxp.DivIpUsdhc1.Div(1) // divide USDHC1_PODF (DIV2) nxp.MuxIpUsdhc1.Mux(1) // USDHC1 select PLL2_PFD0 - nxp.ClockIpUsdhc2.Enable(false) // disable USDHC2 clock gate + nxp.ClockIpUsdhc2.Enable(false) // disable USDHC2 nxp.DivIpUsdhc2.Div(1) // divide USDHC2_PODF (DIV2) nxp.MuxIpUsdhc2.Mux(1) // USDHC2 select PLL2_PFD0 - // ------------------------------------------------------------------- SEMC -- - nxp.ClockIpSemc.Enable(false) // disable SEMC clock gate + nxp.ClockIpSemc.Enable(false) // disable SEMC nxp.DivIpSemc.Div(1) // divide SEMC_PODF (DIV2) nxp.MuxIpSemcAlt.Mux(0) // SEMC_ALT select PLL2_PFD2 nxp.MuxIpSemc.Mux(1) // SEMC select SEMC_ALT - // ---------------------------------------------------------------- FLEXSPI -- if false { // TODO: external flash is on this bus, configured via DCD block - nxp.ClockIpFlexSpi.Enable(false) // disable FLEXSPI clock gate + nxp.ClockIpFlexSpi.Enable(false) // disable FLEXSPI nxp.DivIpFlexSpi.Div(0) // divide FLEXSPI_PODF (DIV1) nxp.MuxIpFlexSpi.Mux(2) // FLEXSPI select PLL2_PFD2 } - nxp.ClockIpFlexSpi2.Enable(false) // disable FLEXSPI2 clock gate + nxp.ClockIpFlexSpi2.Enable(false) // disable FLEXSPI2 nxp.DivIpFlexSpi2.Div(0) // divide FLEXSPI2_PODF (DIV1) nxp.MuxIpFlexSpi2.Mux(0) // FLEXSPI2 select PLL2_PFD2 - // -------------------------------------------------------------------- CSI -- - nxp.ClockIpCsi.Enable(false) // disable CSI clock gate + nxp.ClockIpCsi.Enable(false) // disable CSI nxp.DivIpCsi.Div(1) // divide CSI_PODF (DIV2) nxp.MuxIpCsi.Mux(0) // CSI select OSC24M - // ------------------------------------------------------------------ LPSPI -- - nxp.ClockIpLpspi1.Enable(false) // disable LPSPI clock gate - nxp.ClockIpLpspi2.Enable(false) // ~ - nxp.ClockIpLpspi3.Enable(false) // ~ - nxp.ClockIpLpspi4.Enable(false) // ~ + nxp.ClockIpLpspi1.Enable(false) // disable LPSPI + nxp.ClockIpLpspi2.Enable(false) // + nxp.ClockIpLpspi3.Enable(false) // + nxp.ClockIpLpspi4.Enable(false) // nxp.DivIpLpspi.Div(3) // divide LPSPI_PODF (DIV4) nxp.MuxIpLpspi.Mux(2) // LPSPI select PLL2 - // ------------------------------------------------------------------ TRACE -- - nxp.ClockIpTrace.Enable(false) // disable TRACE clock gate + nxp.ClockIpTrace.Enable(false) // disable TRACE nxp.DivIpTrace.Div(3) // divide TRACE_PODF (DIV4) nxp.MuxIpTrace.Mux(0) // TRACE select PLL2_MAIN - // -------------------------------------------------------------------- SAI -- - nxp.ClockIpSai1.Enable(false) // disable SAI1 clock gate + nxp.ClockIpSai1.Enable(false) // disable SAI1 nxp.DivIpSai1Pre.Div(3) // divide SAI1_CLK_PRED (DIV4) nxp.DivIpSai1.Div(1) // divide SAI1_CLK_PODF (DIV2) nxp.MuxIpSai1.Mux(0) // SAI1 select PLL3_PFD2 - nxp.ClockIpSai2.Enable(false) // disable SAI2 clock gate + nxp.ClockIpSai2.Enable(false) // disable SAI2 nxp.DivIpSai2Pre.Div(3) // divide SAI2_CLK_PRED (DIV4) nxp.DivIpSai2.Div(1) // divide SAI2_CLK_PODF (DIV2) nxp.MuxIpSai2.Mux(0) // SAI2 select PLL3_PFD2 - nxp.ClockIpSai3.Enable(false) // disable SAI3 clock gate + nxp.ClockIpSai3.Enable(false) // disable SAI3 nxp.DivIpSai3Pre.Div(3) // divide SAI3_CLK_PRED (DIV4) nxp.DivIpSai3.Div(1) // divide SAI3_CLK_PODF (DIV2) nxp.MuxIpSai3.Mux(0) // SAI3 select PLL3_PFD2 - // ------------------------------------------------------------------ LPI2C -- - nxp.ClockIpLpi2c1.Enable(false) // disable LPI2C clock gate - nxp.ClockIpLpi2c2.Enable(false) // ~ - nxp.ClockIpLpi2c3.Enable(false) // ~ + nxp.ClockIpLpi2c1.Enable(false) // disable LPI2C + nxp.ClockIpLpi2c2.Enable(false) // + nxp.ClockIpLpi2c3.Enable(false) // nxp.DivIpLpi2c.Div(0) // divide LPI2C_CLK_PODF (DIV1) nxp.MuxIpLpi2c.Mux(0) // LPI2C select PLL3_SW_60M - // -------------------------------------------------------------------- CAN -- - nxp.ClockIpCan1.Enable(false) // disable CAN clock gate - nxp.ClockIpCan2.Enable(false) // ~ - nxp.ClockIpCan3.Enable(false) // ~ - nxp.ClockIpCan1S.Enable(false) // ~ - nxp.ClockIpCan2S.Enable(false) // ~ - nxp.ClockIpCan3S.Enable(false) // ~ + nxp.ClockIpCan1.Enable(false) // disable CAN + nxp.ClockIpCan2.Enable(false) // + nxp.ClockIpCan3.Enable(false) // + nxp.ClockIpCan1S.Enable(false) // + nxp.ClockIpCan2S.Enable(false) // + nxp.ClockIpCan3S.Enable(false) // nxp.DivIpCan.Div(1) // divide CAN_CLK_PODF (DIV2) nxp.MuxIpCan.Mux(2) // CAN select PLL3_SW_80M - // ------------------------------------------------------------------- UART -- - nxp.ClockIpLpuart1.Enable(false) // disable UART clock gate - nxp.ClockIpLpuart2.Enable(false) // ~ - nxp.ClockIpLpuart3.Enable(false) // ~ - nxp.ClockIpLpuart4.Enable(false) // ~ - nxp.ClockIpLpuart5.Enable(false) // ~ - nxp.ClockIpLpuart6.Enable(false) // ~ - nxp.ClockIpLpuart7.Enable(false) // ~ - nxp.ClockIpLpuart8.Enable(false) // ~ + nxp.ClockIpLpuart1.Enable(false) // disable UART + nxp.ClockIpLpuart2.Enable(false) // + nxp.ClockIpLpuart3.Enable(false) // + nxp.ClockIpLpuart4.Enable(false) // + nxp.ClockIpLpuart5.Enable(false) // + nxp.ClockIpLpuart6.Enable(false) // + nxp.ClockIpLpuart7.Enable(false) // + nxp.ClockIpLpuart8.Enable(false) // nxp.DivIpUart.Div(0) // divide UART_CLK_PODF (DIV1) nxp.MuxIpUart.Mux(1) // UART select OSC - // -------------------------------------------------------------------- LCD -- - nxp.ClockIpLcdPixel.Enable(false) // disable LCDIF clock gate + nxp.ClockIpLcdPixel.Enable(false) // disable LCDIF nxp.DivIpLcdifPre.Div(1) // divide LCDIF_PRED (DIV2) nxp.DivIpLcdif.Div(3) // divide LCDIF_CLK_PODF (DIV4) nxp.MuxIpLcdifPre.Mux(5) // LCDIF_PRE select PLL3_PFD1 - // ------------------------------------------------------------------ SPDIF -- - nxp.ClockIpSpdif.Enable(false) // disable SPDIF clock gate + nxp.ClockIpSpdif.Enable(false) // disable SPDIF nxp.DivIpSpdif0Pre.Div(1) // divide SPDIF0_CLK_PRED (DIV2) nxp.DivIpSpdif0.Div(7) // divide SPDIF0_CLK_PODF (DIV8) nxp.MuxIpSpdif.Mux(3) // SPDIF select PLL3_SW - // ----------------------------------------------------------------- FLEXIO -- - nxp.ClockIpFlexio1.Enable(false) // disable FLEXIO1 clock gate + nxp.ClockIpFlexio1.Enable(false) // disable FLEXIO1 nxp.DivIpFlexio1Pre.Div(1) // divide FLEXIO1_CLK_PRED (DIV2) nxp.DivIpFlexio1.Div(7) // divide FLEXIO1_CLK_PODF (DIV8) nxp.MuxIpFlexio1.Mux(3) // FLEXIO1 select PLL3_SW - nxp.ClockIpFlexio2.Enable(false) // enable FLEXIO2 clock gate + nxp.ClockIpFlexio2.Enable(false) // disable FLEXIO2 nxp.DivIpFlexio2Pre.Div(1) // divide FLEXIO2_CLK_PRED (DIV2) nxp.DivIpFlexio2.Div(7) // divide FLEXIO2_CLK_PODF (DIV8) nxp.MuxIpFlexio2.Mux(3) // FLEXIO2 select PLL3_SW - // ---------------------------------------------------------------- PLL/PFD -- nxp.MuxIpPll3Sw.Mux(0) // PLL3_SW select PLL3_MAIN ArmPllConfig.Configure() // init ARM PLL @@ -277,18 +225,15 @@ func initClocks() { Usb1PllConfig.Configure() // init USB1 PLL and PFDs Usb2PllConfig.Configure() // init USB2 PLL - // --------------------------------------------------------------- ARM CORE -- nxp.MuxIpPrePeriph.Mux(3) // PRE_PERIPH select ARM_PLL nxp.MuxIpPeriph.Mux(0) // PERIPH select PRE_PERIPH nxp.MuxIpPeriphClk2.Mux(1) // PERIPH_CLK2 select OSC nxp.MuxIpPerclk.Mux(1) // PERCLK select OSC - // ------------------------------------------------------------------- LVDS -- // set LVDS1 clock source nxp.CCM_ANALOG.MISC1.Set((nxp.CCM_ANALOG.MISC1.Get() & ^uint32(nxp.CCM_ANALOG_MISC1_LVDS1_CLK_SEL_Msk)) | ((0 << nxp.CCM_ANALOG_MISC1_LVDS1_CLK_SEL_Pos) & nxp.CCM_ANALOG_MISC1_LVDS1_CLK_SEL_Msk)) - // ----------------------------------------------------------------- CLKOUT -- // set CLOCK_OUT1 divider nxp.CCM.CCOSR.Set((nxp.CCM.CCOSR.Get() & ^uint32(nxp.CCM_CCOSR_CLKO1_DIV_Msk)) | ((0 << nxp.CCM_CCOSR_CLKO1_DIV_Pos) & nxp.CCM_CCOSR_CLKO1_DIV_Msk)) @@ -306,95 +251,80 @@ func initClocks() { nxp.CCM.CCOSR.SetBits(nxp.CCM_CCOSR_CLKO1_EN_Msk) // enable CLK_OUT1 nxp.CCM.CCOSR.SetBits(nxp.CCM_CCOSR_CLKO2_EN_Msk) // enable CLK_OUT2 - // ----------------------------------------------------------------- IOMUXC -- - nxp.ClockIpIomuxcGpr.Enable(false) // disable IOMUXC_GPR clock gate - nxp.ClockIpIomuxc.Enable(false) // disable IOMUXC clock gate + nxp.ClockIpIomuxcGpr.Enable(false) // disable IOMUXC_GPR + nxp.ClockIpIomuxc.Enable(false) // disable IOMUXC // set GPT1 High frequency reference clock source nxp.IOMUXC_GPR.GPR5.ClearBits(nxp.IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT1_Msk) // set GPT2 High frequency reference clock source nxp.IOMUXC_GPR.GPR5.ClearBits(nxp.IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT2_Msk) - // ------------------------------------------------------------------- GPIO -- - nxp.ClockIpGpio1.Enable(false) // disable GPIO clock gates - nxp.ClockIpGpio2.Enable(false) // ~ - nxp.ClockIpGpio3.Enable(false) // ~ - nxp.ClockIpGpio4.Enable(false) // ~ + nxp.ClockIpGpio1.Enable(false) // disable GPIO + nxp.ClockIpGpio2.Enable(false) // + nxp.ClockIpGpio3.Enable(false) // + nxp.ClockIpGpio4.Enable(false) // } func enableTimerClocks() { - // ---------------------------------------------------------------- GPT/PIT -- - nxp.ClockIpGpt1.Enable(true) // enable GPT/PIT clock gates - nxp.ClockIpGpt1S.Enable(true) // ~ - nxp.ClockIpGpt2.Enable(true) // ~ - nxp.ClockIpGpt2S.Enable(true) // ~ - nxp.ClockIpPit.Enable(true) // ~ + nxp.ClockIpGpt1.Enable(true) // enable GPT/PIT + nxp.ClockIpGpt1S.Enable(true) // + nxp.ClockIpGpt2.Enable(true) // + nxp.ClockIpGpt2S.Enable(true) // + nxp.ClockIpPit.Enable(true) // } func enablePinClocks() { - // ----------------------------------------------------------------- IOMUXC -- - nxp.ClockIpIomuxcGpr.Enable(true) // enable IOMUXC clock gates - nxp.ClockIpIomuxc.Enable(true) // ~ + nxp.ClockIpIomuxcGpr.Enable(true) // enable IOMUXC + nxp.ClockIpIomuxc.Enable(true) // - // ------------------------------------------------------------------- GPIO -- - nxp.ClockIpGpio1.Enable(true) // enable GPIO clock gates - nxp.ClockIpGpio2.Enable(true) // ~ - nxp.ClockIpGpio3.Enable(true) // ~ - nxp.ClockIpGpio4.Enable(true) // ~ + nxp.ClockIpGpio1.Enable(true) // enable GPIO + nxp.ClockIpGpio2.Enable(true) // + nxp.ClockIpGpio3.Enable(true) // + nxp.ClockIpGpio4.Enable(true) // } func enablePeripheralClocks() { - // -------------------------------------------------------------------- ADC -- - nxp.ClockIpAdc1.Enable(true) // enable ADC clock gates - nxp.ClockIpAdc2.Enable(true) // ~ + nxp.ClockIpAdc1.Enable(true) // enable ADC + nxp.ClockIpAdc2.Enable(true) // - // ------------------------------------------------------------------- XBAR -- - nxp.ClockIpXbar1.Enable(true) // enable XBAR clock gates - nxp.ClockIpXbar2.Enable(true) // ~ - nxp.ClockIpXbar3.Enable(true) // ~ + nxp.ClockIpXbar1.Enable(true) // enable XBAR + nxp.ClockIpXbar2.Enable(true) // + nxp.ClockIpXbar3.Enable(true) // - // ------------------------------------------------------------------ USDHC -- - nxp.ClockIpUsdhc1.Enable(true) // enable USDHC clock gates - nxp.ClockIpUsdhc2.Enable(true) // ~ + nxp.ClockIpUsdhc1.Enable(true) // enable USDHC + nxp.ClockIpUsdhc2.Enable(true) // - // ------------------------------------------------------------------- SEMC -- - nxp.ClockIpSemc.Enable(true) // enable SEMC clock gate + nxp.ClockIpSemc.Enable(true) // enable SEMC - // ---------------------------------------------------------------- FLEXSPI -- - nxp.ClockIpFlexSpi2.Enable(true) // enable FLEXSPI2 clock gate + nxp.ClockIpFlexSpi2.Enable(true) // enable FLEXSPI2 - // ------------------------------------------------------------------ LPSPI -- - nxp.ClockIpLpspi1.Enable(true) // enable LPSPI clock gate - nxp.ClockIpLpspi2.Enable(true) // ~ - nxp.ClockIpLpspi3.Enable(true) // ~ - nxp.ClockIpLpspi4.Enable(true) // ~ + nxp.ClockIpLpspi1.Enable(true) // enable LPSPI + nxp.ClockIpLpspi2.Enable(true) // + nxp.ClockIpLpspi3.Enable(true) // + nxp.ClockIpLpspi4.Enable(true) // - // ------------------------------------------------------------------ LPI2C -- - nxp.ClockIpLpi2c1.Enable(true) // enable LPI2C clock gate - nxp.ClockIpLpi2c2.Enable(true) // ~ - nxp.ClockIpLpi2c3.Enable(true) // ~ + nxp.ClockIpLpi2c1.Enable(true) // enable LPI2C + nxp.ClockIpLpi2c2.Enable(true) // + nxp.ClockIpLpi2c3.Enable(true) // - // -------------------------------------------------------------------- CAN -- - nxp.ClockIpCan1.Enable(true) // enable CAN clock gate - nxp.ClockIpCan2.Enable(true) // ~ - nxp.ClockIpCan3.Enable(true) // ~ - nxp.ClockIpCan1S.Enable(true) // ~ - nxp.ClockIpCan2S.Enable(true) // ~ - nxp.ClockIpCan3S.Enable(true) // ~ + nxp.ClockIpCan1.Enable(true) // enable CAN + nxp.ClockIpCan2.Enable(true) // + nxp.ClockIpCan3.Enable(true) // + nxp.ClockIpCan1S.Enable(true) // + nxp.ClockIpCan2S.Enable(true) // + nxp.ClockIpCan3S.Enable(true) // - // ------------------------------------------------------------------- UART -- - nxp.ClockIpLpuart1.Enable(true) // enable UART clock gate - nxp.ClockIpLpuart2.Enable(true) // ~ - nxp.ClockIpLpuart3.Enable(true) // ~ - nxp.ClockIpLpuart4.Enable(true) // ~ - nxp.ClockIpLpuart5.Enable(true) // ~ - nxp.ClockIpLpuart6.Enable(true) // ~ - nxp.ClockIpLpuart7.Enable(true) // ~ - nxp.ClockIpLpuart8.Enable(true) // ~ + nxp.ClockIpLpuart1.Enable(true) // enable UART + nxp.ClockIpLpuart2.Enable(true) // + nxp.ClockIpLpuart3.Enable(true) // + nxp.ClockIpLpuart4.Enable(true) // + nxp.ClockIpLpuart5.Enable(true) // + nxp.ClockIpLpuart6.Enable(true) // + nxp.ClockIpLpuart7.Enable(true) // + nxp.ClockIpLpuart8.Enable(true) // - // ----------------------------------------------------------------- FLEXIO -- - nxp.ClockIpFlexio1.Enable(true) // enable FLEXIO clock gates - nxp.ClockIpFlexio2.Enable(true) // ~ + nxp.ClockIpFlexio1.Enable(true) // enable FLEXIO + nxp.ClockIpFlexio2.Enable(true) // } diff --git a/src/runtime/runtime_mimxrt1062_mpu.go b/src/runtime/runtime_mimxrt1062_mpu.go index 58297047..cd71dd84 100644 --- a/src/runtime/runtime_mimxrt1062_mpu.go +++ b/src/runtime/runtime_mimxrt1062_mpu.go @@ -10,50 +10,38 @@ func initCache() { nxp.MPU.Enable(false) - // -------------------------------------------------------- OVERLAY REGIONS -- - // add Default [0] region to deny access to whole address space to workaround // speculative prefetch. Refer to Arm errata 1013783-B for more details. - // [0] Default {OVERLAY}: - // 4 GiB, -access, @device, -exec, -share, -cache, -buffer, -subregion + // [0] Default {OVERLAY}: 4 GiB, -access, @device, -exec, -share, -cache, -buffer, -subregion nxp.MPU.SetRBAR(0, 0x00000000) nxp.MPU.SetRASR(nxp.RGNSZ_4GB, nxp.PERM_NONE, nxp.EXTN_DEVICE, false, false, false, false, false) - // [1] Peripherals {OVERLAY}: - // 64 MiB, +ACCESS, @device, +EXEC, -share, -cache, -buffer, -subregion + // [1] Peripherals {OVERLAY}: 64 MiB, +ACCESS, @device, +EXEC, -share, -cache, -buffer, -subregion nxp.MPU.SetRBAR(1, 0x40000000) nxp.MPU.SetRASR(nxp.RGNSZ_64MB, nxp.PERM_FULL, nxp.EXTN_DEVICE, true, false, false, false, false) - // [2] RAM {OVERLAY}: - // 1 GiB, +ACCESS, @device, +EXEC, -share, -cache, -buffer, -subregion + // [2] RAM {OVERLAY}: 1 GiB, +ACCESS, @device, +EXEC, -share, -cache, -buffer, -subregion nxp.MPU.SetRBAR(2, 0x00000000) nxp.MPU.SetRASR(nxp.RGNSZ_1GB, nxp.PERM_FULL, nxp.EXTN_DEVICE, true, false, false, false, false) - // ----------------------------------------------------- PERIPHERAL REGIONS -- - - // [3] ITCM: - // 512 KiB, +ACCESS, #NORMAL, +EXEC, -share, -cache, -buffer, -subregion + // [3] ITCM: 512 KiB, +ACCESS, #NORMAL, +EXEC, -share, -cache, -buffer, -subregion nxp.MPU.SetRBAR(3, 0x00000000) nxp.MPU.SetRASR(nxp.RGNSZ_512KB, nxp.PERM_FULL, nxp.EXTN_NORMAL, true, false, false, false, false) - // [4] DTCM: - // 512 KiB, +ACCESS, #NORMAL, +EXEC, -share, -cache, -buffer, -subregion + // [4] DTCM: 512 KiB, +ACCESS, #NORMAL, +EXEC, -share, -cache, -buffer, -subregion nxp.MPU.SetRBAR(4, 0x20000000) nxp.MPU.SetRASR(nxp.RGNSZ_512KB, nxp.PERM_FULL, nxp.EXTN_NORMAL, true, false, false, false, false) - // [5] RAM (AXI): - // 512 KiB, +ACCESS, #NORMAL, +EXEC, -share, +CACHE, +BUFFER, -subregion + // [5] RAM (AXI): 512 KiB, +ACCESS, #NORMAL, +EXEC, -share, +CACHE, +BUFFER, -subregion nxp.MPU.SetRBAR(5, 0x20200000) nxp.MPU.SetRASR(nxp.RGNSZ_512KB, nxp.PERM_FULL, nxp.EXTN_NORMAL, true, false, true, true, false) - // [6] FlexSPI: - // 512 MiB, +ACCESS, #NORMAL, +EXEC, -share, +CACHE, +BUFFER, -subregion + // [6] FlexSPI: 512 MiB, +ACCESS, #NORMAL, +EXEC, -share, +CACHE, +BUFFER, -subregion nxp.MPU.SetRBAR(6, 0x70000000) nxp.MPU.SetRASR(nxp.RGNSZ_512MB, nxp.PERM_FULL, nxp.EXTN_NORMAL, true, false, true, true, false) - // [7] QSPI flash: - // 2 MiB, +ACCESS, #NORMAL, +EXEC, -share, +CACHE, +BUFFER, -subregion + // [7] QSPI flash: 2 MiB, +ACCESS, #NORMAL, +EXEC, -share, +CACHE, +BUFFER, -subregion nxp.MPU.SetRBAR(7, 0x60000000) nxp.MPU.SetRASR(nxp.RGNSZ_2MB, nxp.PERM_FULL, nxp.EXTN_NORMAL, true, false, true, true, false) diff --git a/src/runtime/runtime_mimxrt1062_time.go b/src/runtime/runtime_mimxrt1062_time.go index 08433440..22f29d17 100644 --- a/src/runtime/runtime_mimxrt1062_time.go +++ b/src/runtime/runtime_mimxrt1062_time.go @@ -12,14 +12,14 @@ import ( type timeUnit int64 -const ( // HW divides 24 MHz XTALOSC down to 100 kHz +const ( lastCycle = SYSTICK_FREQ/1000 - 1 cyclesPerMicro = CORE_FREQ / 1000000 ) const ( - PIT_FREQ = PERCLK_FREQ - pitCyclesPerMicro = PIT_FREQ / 1000000 + pitFreq = OSC_FREQ // PIT/GPT are muxed to 24 MHz OSC + pitCyclesPerMicro = pitFreq / 1000000 pitSleepTimer = 0 // x4 32-bit PIT timers [0..3] ) @@ -32,16 +32,11 @@ var ( var ( // debug exception and monitor control - DEMCR = (*volatile.Register32)(unsafe.Pointer(uintptr(0xe000edfc))) - DWT_CTRL = (*volatile.Register32)(unsafe.Pointer(uintptr(0xe0001000))) + DEM_CR = (*volatile.Register32)(unsafe.Pointer(uintptr(0xe000edfc))) + DWT_CR = (*volatile.Register32)(unsafe.Pointer(uintptr(0xe0001000))) DWT_CYCCNT = (*volatile.Register32)(unsafe.Pointer(uintptr(0xe0001004))) ) -const ( - DEMCR_TRCENA = 0x01000000 // enable debugging & monitoring blocks - DWT_CTRL_CYCCNTENA = 0x00000001 // cycle count register -) - func ticksToNanoseconds(ticks timeUnit) int64 { return int64(ticks) * 1000 } @@ -51,22 +46,30 @@ func nanosecondsToTicks(ns int64) timeUnit { } func initSysTick() { - // disable if already running + + const ( + traceEnable = 0x01000000 // enable debugging & monitoring blocks + cycleCountEnable = 0x00000001 // cycle count register + ) + + // disable SysTick if already running if arm.SYST.SYST_CSR.HasBits(arm.SYST_CSR_ENABLE_Msk) { arm.SYST.SYST_CSR.ClearBits(arm.SYST_CSR_ENABLE_Msk) } + // zeroize the counter tickCount.Set(0) arm.SYST.SYST_RVR.Set(lastCycle) arm.SYST.SYST_CVR.Set(0) arm.SYST.SYST_CSR.Set(arm.SYST_CSR_TICKINT | arm.SYST_CSR_ENABLE) + // set SysTick and PendSV priority to 32 nxp.SystemControl.SHPR3.Set((0x20 << nxp.SCB_SHPR3_PRI_15_Pos) | (0x20 << nxp.SCB_SHPR3_PRI_14_Pos)) // turn on cycle counter - DEMCR.SetBits(DEMCR_TRCENA) - DWT_CTRL.SetBits(DWT_CTRL_CYCCNTENA) + DEM_CR.SetBits(traceEnable) + DWT_CR.SetBits(cycleCountEnable) cycleCount.Set(DWT_CYCCNT.Get()) // enable PIT, disable counters @@ -74,6 +77,7 @@ func initSysTick() { for i := range nxp.PIT.TIMER { nxp.PIT.TIMER[i].TCTRL.Set(0) } + // register sleep timer interrupt pitTimeout = interrupt.New(nxp.IRQ_PIT, timerWake) pitTimeout.SetPriority(0x21) @@ -101,7 +105,13 @@ func ticks() timeUnit { cycs := cycleCount.Get() curr := DWT_CYCCNT.Get() arm.EnableInterrupts(mask) - frac := uint64((curr-cycs)*0xFFFFFFFF/cyclesPerMicro) >> 32 + var diff uint32 + if curr < cycs { // cycle counter overflow/rollover occurred + diff = (0xFFFFFFFF - cycs) + curr + } else { + diff = curr - cycs + } + frac := uint64(diff*0xFFFFFFFF/cyclesPerMicro) >> 32 if frac > 1000 { frac = 1000 } @@ -111,15 +121,14 @@ func ticks() timeUnit { func sleepTicks(duration timeUnit) { if duration >= 0 { curr := ticks() - last := curr + duration + last := curr + duration // 64-bit overflow unlikely for curr < last { cycles := timeUnit((last - curr) / pitCyclesPerMicro) if cycles > 0xFFFFFFFF { cycles = 0xFFFFFFFF } if !timerSleep(uint32(cycles)) { - // return early due to interrupt - return + return // return early due to interrupt } curr = ticks() } diff --git a/targets/teensy40.json b/targets/teensy40.json index fe9994e5..6ccfdf54 100644 --- a/targets/teensy40.json +++ b/targets/teensy40.json @@ -4,17 +4,13 @@ "cpu": "cortex-m7", "build-tags": ["teensy40", "teensy", "mimxrt1062", "nxp"], "automatic-stack-size": false, - "default-stack-size": 131072, + "default-stack-size": 4096, "cflags": [ "--target=armv7em-none-eabi", "-Qunused-arguments", - "-mfloat-abi=hard", + "-mfloat-abi=soft", "-mfpu=fpv5-d16" ], - "ldflags": [ - "--emit-relocs", - "--gc-sections" - ], "linkerscript": "targets/mimxrt1062-teensy40.ld", "extra-files": [ "src/device/nxp/mimxrt1062.s",