teensy40: refactor to remove unnecessary code and constants
Этот коммит содержится в:
родитель
47410a4b54
коммит
19a0270303
9 изменённых файлов: 581 добавлений и 831 удалений
|
@ -11,75 +11,42 @@ import (
|
||||||
"unsafe"
|
"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 (
|
type (
|
||||||
Clock uint32
|
Clock uint32
|
||||||
Gate uint8
|
|
||||||
ClockMode 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 (
|
const (
|
||||||
ModeClkRun ClockMode = 0 // Remain in run mode
|
ClockModeRun ClockMode = 0 // Remain in run mode
|
||||||
ModeClkWait ClockMode = 1 // Transfer to wait mode
|
ClockModeWait ClockMode = 1 // Transfer to wait mode
|
||||||
ModeClkStop ClockMode = 2 // Transfer to stop mode
|
ClockModeStop ClockMode = 2 // Transfer to stop mode
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
// Set configures the run mode of the MCU.
|
||||||
GateClkNotNeeded Gate = 0 // Clock is off during all modes
|
func (m ClockMode) Set() {
|
||||||
GateClkNeededRun Gate = 1 // Clock is on in run mode, but off in WAIT and STOP modes
|
CCM.CLPCR.Set((CCM.CLPCR.Get() & ^uint32(CCM_CLPCR_LPM_Msk)) |
|
||||||
GateClkNeededRunWait Gate = 3 // Clock is on during all modes, except STOP mode
|
((uint32(m) << CCM_CLPCR_LPM_Pos) & CCM_CLPCR_LPM_Msk))
|
||||||
)
|
}
|
||||||
|
|
||||||
// Named oscillators
|
// Named oscillators
|
||||||
const (
|
const (
|
||||||
|
@ -259,6 +226,7 @@ const (
|
||||||
ClockPfd3 Clock = 3 // PLL PFD3
|
ClockPfd3 Clock = 3 // PLL PFD3
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Named clock muxes of integrated peripherals
|
||||||
const (
|
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
|
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
|
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
|
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 (
|
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
|
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
|
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
|
noBusyWait = 0x20
|
||||||
)
|
)
|
||||||
|
|
||||||
// analog pll definition
|
// analog PLL definition
|
||||||
const (
|
const (
|
||||||
pllBypassPos = 16
|
pllBypassPos = 16
|
||||||
pllBypassClkSrcMsk = 0xC000
|
pllBypassClkSrcMsk = 0xC000
|
||||||
|
@ -358,29 +327,14 @@ const (
|
||||||
pllSrcClkPN = 1 // Pll clock source CLK1_P and CLK1_N
|
pllSrcClkPN = 1 // Pll clock source CLK1_P and CLK1_N
|
||||||
)
|
)
|
||||||
|
|
||||||
// Set configures the run mode of the MCU.
|
const (
|
||||||
func (m ClockMode) Set() {
|
clockNotNeeded uint32 = 0 // Clock is off during all modes
|
||||||
CCM.CLPCR.Set((CCM.CLPCR.Get() & ^uint32(CCM_CLPCR_LPM_Msk)) |
|
clockNeededRun uint32 = 1 // Clock is on in run mode, but off in WAIT and STOP modes
|
||||||
((uint32(m) << CCM_CLPCR_LPM_Pos) & CCM_CLPCR_LPM_Msk))
|
clockNeededRunWait uint32 = 3 // Clock is on during all modes, except STOP mode
|
||||||
}
|
)
|
||||||
|
|
||||||
// Enable activates or deactivates the clock gate of receiver Clock clk.
|
// getGate returns the CCM clock gating register for the receiver clk.
|
||||||
func (clk Clock) Enable(enable bool) {
|
func (clk Clock) getGate() *volatile.Register32 {
|
||||||
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 {
|
|
||||||
switch clk >> 8 {
|
switch clk >> 8 {
|
||||||
case 0:
|
case 0:
|
||||||
return &CCM.CCGR0
|
return &CCM.CCGR0
|
||||||
|
@ -403,14 +357,14 @@ func (clk Clock) getCCGR() *volatile.Register32 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// control enables or disables the receiver clk using its gating register.
|
// setGate enables or disables the receiver clk using its gating register.
|
||||||
func (clk Clock) control(value Gate) {
|
func (clk Clock) setGate(value uint32) {
|
||||||
reg := clk.getCCGR()
|
reg := clk.getGate()
|
||||||
shift := clk & 0x1F
|
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
|
const ccmBase = 0x400fc000
|
||||||
reg := (*volatile.Register32)(unsafe.Pointer(uintptr(ccmBase + (uint32(clk) & 0xFF))))
|
reg := (*volatile.Register32)(unsafe.Pointer(uintptr(ccmBase + (uint32(clk) & 0xFF))))
|
||||||
msk := ((uint32(clk) >> 13) & 0x1FFF) << ((uint32(clk) >> 8) & 0x1F)
|
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) {
|
func setSysPfd(value ...uint32) {
|
||||||
for i, val := range value {
|
for i, val := range value {
|
||||||
pfd528 := CCM_ANALOG.PFD_528.Get() &
|
pfd528 := CCM_ANALOG.PFD_528.Get() &
|
||||||
|
@ -701,40 +401,10 @@ func setUsb1Pfd(value ...uint32) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (clk Clock) isPllEnabled() bool {
|
// PLL configuration for ARM
|
||||||
const ccmAnalogBase = 0x400d8000
|
type ClockConfigArmPll struct {
|
||||||
addr := ccmAnalogBase + ((uint32(clk) >> 16) & 0xFFF)
|
LoopDivider uint32 // PLL loop divider. Valid range for divider value: 54-108. Fout=Fin*LoopDivider/2.
|
||||||
pos := uint32(1 << (uint32(clk) & 0x1F))
|
Src uint8 // Pll clock source, reference _clock_pll_clk_src
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg ClockConfigArmPll) Configure() {
|
func (cfg ClockConfigArmPll) Configure() {
|
||||||
|
@ -757,6 +427,17 @@ func (cfg ClockConfigArmPll) Configure() {
|
||||||
CCM_ANALOG.PLL_ARM.ClearBits(CCM_ANALOG_PLL_ARM_BYPASS_Msk)
|
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) {
|
func (cfg ClockConfigSysPll) Configure(pfd ...uint32) {
|
||||||
|
|
||||||
// bypass PLL first
|
// bypass PLL first
|
||||||
|
@ -790,6 +471,13 @@ func (cfg ClockConfigSysPll) Configure(pfd ...uint32) {
|
||||||
setSysPfd(pfd...)
|
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) {
|
func (cfg ClockConfigUsbPll) Configure(pfd ...uint32) {
|
||||||
|
|
||||||
switch cfg.Instance {
|
switch cfg.Instance {
|
|
@ -34,16 +34,6 @@ type (
|
||||||
Extension uint32
|
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
|
// MPU Control Register Definitions
|
||||||
const (
|
const (
|
||||||
MPU_CTRL_PRIVDEFENA_Pos = 2 // MPU CTRL: PRIVDEFENA Position
|
MPU_CTRL_PRIVDEFENA_Pos = 2 // MPU CTRL: PRIVDEFENA Position
|
||||||
|
@ -54,12 +44,6 @@ const (
|
||||||
MPU_CTRL_ENABLE_Msk = 1 // MPU CTRL: ENABLE Mask
|
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
|
// MPU Region Base Address Register Definitions
|
||||||
const (
|
const (
|
||||||
MPU_RBAR_ADDR_Pos = 5 // MPU RBAR: ADDR Position
|
MPU_RBAR_ADDR_Pos = 5 // MPU RBAR: ADDR Position
|
||||||
|
@ -161,11 +145,11 @@ func (mpu *MPU_Type) Enable(enable bool) {
|
||||||
dsb 0xF
|
dsb 0xF
|
||||||
isb 0xF
|
isb 0xF
|
||||||
`, nil)
|
`, nil)
|
||||||
EnableDcache(true)
|
enableDcache(true)
|
||||||
EnableIcache(true)
|
enableIcache(true)
|
||||||
} else {
|
} else {
|
||||||
EnableIcache(false)
|
enableIcache(false)
|
||||||
EnableDcache(false)
|
enableDcache(false)
|
||||||
arm.AsmFull(`
|
arm.AsmFull(`
|
||||||
dmb 0xF
|
dmb 0xF
|
||||||
`, nil)
|
`, nil)
|
||||||
|
@ -200,7 +184,7 @@ func (mpu *MPU_Type) SetRASR(size RegionSize, access AccessPerms, ext Extension,
|
||||||
MPU_RASR_ENABLE_Msk)
|
MPU_RASR_ENABLE_Msk)
|
||||||
}
|
}
|
||||||
|
|
||||||
func EnableIcache(enable bool) {
|
func enableIcache(enable bool) {
|
||||||
if enable != SystemControl.CCR.HasBits(SCB_CCR_IC_Msk) {
|
if enable != SystemControl.CCR.HasBits(SCB_CCR_IC_Msk) {
|
||||||
if enable {
|
if enable {
|
||||||
arm.AsmFull(`
|
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.CCR.HasBits(SCB_CCR_DC_Msk) {
|
||||||
if enable {
|
if enable {
|
||||||
SystemControl.CSSELR.Set(0)
|
SystemControl.CSSELR.Set(0)
|
|
@ -2,11 +2,6 @@
|
||||||
|
|
||||||
package machine
|
package machine
|
||||||
|
|
||||||
const (
|
|
||||||
NUM_DIGITAL_IO_PINS = 40
|
|
||||||
NUM_ANALOG_IO_PINS = 14
|
|
||||||
)
|
|
||||||
|
|
||||||
// Digital pins
|
// Digital pins
|
||||||
const (
|
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
|
// = 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
|
// Analog pins
|
||||||
const (
|
const (
|
||||||
// = Pin // Dig | [Pad] {Ch}
|
// = Pin // Dig | [Pad] {ADC1/ADC2}
|
||||||
A0 = PA18 // D14 | [AD_B1_02] {7}
|
A0 = PA18 // D14 | [AD_B1_02] { 7 / 7 }
|
||||||
A1 = PA19 // D15 | [AD_B1_03] {8}
|
A1 = PA19 // D15 | [AD_B1_03] { 8 / 8 }
|
||||||
A2 = PA23 // D16 | [AD_B1_07] {12}
|
A2 = PA23 // D16 | [AD_B1_07] { 12 / 12 }
|
||||||
A3 = PA22 // D17 | [AD_B1_06] {11}
|
A3 = PA22 // D17 | [AD_B1_06] { 11 / 11 }
|
||||||
A4 = PA17 // D18 | [AD_B1_01] {6}
|
A4 = PA17 // D18 | [AD_B1_01] { 6 / 6 }
|
||||||
A5 = PA16 // D19 | [AD_B1_00] {5}
|
A5 = PA16 // D19 | [AD_B1_00] { 5 / 5 }
|
||||||
A6 = PA26 // D20 | [AD_B1_10] {15}
|
A6 = PA26 // D20 | [AD_B1_10] { 15 / 15 }
|
||||||
A7 = PA27 // D21 | [AD_B1_11] {0}
|
A7 = PA27 // D21 | [AD_B1_11] { 0 / 0 }
|
||||||
A8 = PA24 // D22 | [AD_B1_08] {13}
|
A8 = PA24 // D22 | [AD_B1_08] { 13 / 13 }
|
||||||
A9 = PA25 // D23 | [AD_B1_09] {14}
|
A9 = PA25 // D23 | [AD_B1_09] { 14 / 14 }
|
||||||
A10 = PA12 // D24 | [AD_B0_12] {1}
|
A10 = PA12 // D24 | [AD_B0_12] { 1 / - }
|
||||||
A11 = PA13 // D25 | [AD_B0_13] {2}
|
A11 = PA13 // D25 | [AD_B0_13] { 2 / - }
|
||||||
A12 = PA30 // D26 | [AD_B1_14] {128+3}
|
A12 = PA30 // D26 | [AD_B1_14] { - / 3 }
|
||||||
A13 = PA31 // D27 | [AD_B1_15] {128+4}
|
A13 = PA31 // D27 | [AD_B1_15] { - / 4 }
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
// Default peripheral pins
|
||||||
initLED()
|
|
||||||
initUART()
|
|
||||||
initSPI()
|
|
||||||
initI2C()
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- LEDs ---------------------------------------------------------------------
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
NUM_BOARD_LED = 1
|
LED = D13
|
||||||
|
|
||||||
LED_BUILTIN = D13
|
UART_RX_PIN = UART1_RX_PIN // D0
|
||||||
LED = LED_BUILTIN
|
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 (
|
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_RX_PIN = D0
|
||||||
UART1_TX_PIN = D1
|
UART1_TX_PIN = D1
|
||||||
|
|
||||||
|
@ -126,25 +117,18 @@ const (
|
||||||
|
|
||||||
UART7_RX_PIN = D28
|
UART7_RX_PIN = D28
|
||||||
UART7_TX_PIN = D29
|
UART7_TX_PIN = D29
|
||||||
|
|
||||||
UART_RX_PIN = UART1_RX_PIN
|
|
||||||
UART_TX_PIN = UART1_TX_PIN
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func initUART() {}
|
// #==================================================================#
|
||||||
|
// | SPI |
|
||||||
// -- SPI ----------------------------------------------------------------------
|
// #===========#==========#===============#===========================#
|
||||||
|
|
||||||
const (
|
|
||||||
// #===========#==========#===================#===========================#
|
|
||||||
// | Interface | Hardware | Clock(Freq) | SDI/SDO/SCK/CS : Alt |
|
// | Interface | Hardware | Clock(Freq) | SDI/SDO/SCK/CS : Alt |
|
||||||
// #===========#==========#===================#=================-=========#
|
// #===========#==========#===============#=================-=========#
|
||||||
// | SPI1 | LPSPI4 | PLL3PFD1(130 MHz) | D12/D11/D13/D10 : 3/3/3/3 |
|
// | SPI1 | LPSPI4 | PLL2(132 MHz) | D12/D11/D13/D10 : 3/3/3/3 |
|
||||||
// | SPI2 | LPSPI3 | PLL3PFD1(130 MHz) | D1/D26/D27/D0 : 7/2/2/7 |
|
// | SPI2 | LPSPI3 | PLL2(132 MHz) | D1/D26/D27/D0 : 7/2/2/7 |
|
||||||
// | SPI3 | LPSPI1 | PLL3PFD1(130 MHz) | D34/D35/D37/D36 : 4/4/4/4 |
|
// | SPI3 | LPSPI1 | PLL2(132 MHz) | D34/D35/D37/D36 : 4/4/4/4 |
|
||||||
// #===========#==========#===================#=================-=========#
|
// #===========#==========#===============#=================-=========#
|
||||||
NUM_SPI_INTERFACES = 3
|
const (
|
||||||
|
|
||||||
SPI1_SDI_PIN = D12
|
SPI1_SDI_PIN = D12
|
||||||
SPI1_SDO_PIN = D11
|
SPI1_SDO_PIN = D11
|
||||||
SPI1_SCK_PIN = D13
|
SPI1_SCK_PIN = D13
|
||||||
|
@ -159,19 +143,24 @@ const (
|
||||||
SPI3_SDO_PIN = D35
|
SPI3_SDO_PIN = D35
|
||||||
SPI3_SCK_PIN = D37
|
SPI3_SCK_PIN = D37
|
||||||
SPI3_CS_PIN = D36
|
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 (
|
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
|
||||||
|
)
|
||||||
|
|
|
@ -15,28 +15,6 @@ func CPUFrequency() uint32 {
|
||||||
|
|
||||||
type PinMode uint8
|
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 (
|
const (
|
||||||
// GPIO
|
// GPIO
|
||||||
PinInput PinMode = iota
|
PinInput PinMode = iota
|
||||||
|
@ -45,93 +23,25 @@ const (
|
||||||
PinOutput
|
PinOutput
|
||||||
PinOutputOpenDrain
|
PinOutputOpenDrain
|
||||||
PinDisable
|
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):
|
// From the i.MXRT1062 Processor Reference Manual (Chapter 12 - GPIO):
|
||||||
//
|
//
|
||||||
// | High-speed GPIOs exist in this device:
|
// | 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
|
// 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.
|
// is only uint8, and 9*32=288 > 256, so something has to be sacrificed.
|
||||||
|
|
||||||
const numPorts, pinsPerPort = 4, 32
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
portA Pin = iota * pinsPerPort // GPIO1(6)
|
portA Pin = iota * 32 // GPIO1(6)
|
||||||
portB // GPIO2(7)
|
portB // GPIO2(7)
|
||||||
portC // GPIO3(8)
|
portC // GPIO3(8)
|
||||||
portD // GPIO4(9)
|
portD // GPIO4(9)
|
||||||
)
|
)
|
||||||
|
|
||||||
const numPins = numPorts * pinsPerPort
|
|
||||||
|
|
||||||
const (
|
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
|
// [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 ~ ~ ~
|
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) 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)
|
// getGPIO returns both the normal (IPG_CLK_ROOT) and high-speed (AHB_CLK_ROOT)
|
||||||
// GPIO peripherals to which a given Pin is connected.
|
// 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")
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -6,66 +6,13 @@ import (
|
||||||
"device/nxp"
|
"device/nxp"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Core, bus, and peripheral clock frequencies (Hz)
|
// Core clock frequencies (Hz)
|
||||||
const (
|
const (
|
||||||
CORE_FREQ = 600000000 // 600 MHz
|
CORE_FREQ = 600000000 // 600 MHz
|
||||||
SYSTICK_FREQ = 100000 // 100 kHz (see note below)
|
OSC_FREQ = 24000000 // 24 MHz
|
||||||
_ // -----------
|
|
||||||
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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
// Note from Teensyduino (cores/teensy4/startup.c):
|
||||||
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):
|
|
||||||
//
|
//
|
||||||
// | ARM SysTick is used for most Ardiuno timing functions, delay(), millis(),
|
// | ARM SysTick is used for most Ardiuno timing functions, delay(), millis(),
|
||||||
// | micros(). SysTick can run from either the ARM core clock, or from an
|
// | 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
|
// | 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
|
// | ARM clock, to allow SysTick to maintain correct timing even when we change
|
||||||
// | the ARM clock to run at different speeds.
|
// | 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
|
// initClocks configures the core, buses, and all peripherals' clock source mux
|
||||||
// and dividers for runtime. The clock gates for individual peripherals are all
|
// 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.
|
// 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,
|
// see: Using the MIMXRT1060/4-EVK with MCUXpresso IDE v10.3.x (v1.0.2,
|
||||||
// 2019MAR01), chapter 14
|
// 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)
|
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)
|
nxp.XTALOSC24M.OSC_CONFIG2.ClearBits(nxp.XTALOSC24M_OSC_CONFIG2_MUX_1M_Msk)
|
||||||
|
|
||||||
// initialize external 24 MHz clock
|
// 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)
|
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)
|
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)
|
nxp.XTALOSC24M.LOWPWR_CTRL_CLR.Set(nxp.XTALOSC24M_LOWPWR_CTRL_CLR_OSC_SEL_Msk)
|
||||||
|
|
||||||
// set oscillator ready counter value
|
// set oscillator ready counter value
|
||||||
|
@ -123,142 +91,122 @@ func initClocks() {
|
||||||
for !nxp.DCDC.REG0.HasBits(nxp.DCDC_REG0_STS_DC_OK_Msk) {
|
for !nxp.DCDC.REG0.HasBits(nxp.DCDC_REG0_STS_DC_OK_Msk) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------- AHB --
|
|
||||||
nxp.DivIpAhb.Div(0) // divide AHB_PODF (DIV1)
|
nxp.DivIpAhb.Div(0) // divide AHB_PODF (DIV1)
|
||||||
|
|
||||||
// -------------------------------------------------------------------- ADC --
|
nxp.ClockIpAdc1.Enable(false) // disable ADC
|
||||||
nxp.ClockIpAdc1.Enable(false) // disable ADC clock gates
|
nxp.ClockIpAdc2.Enable(false) //
|
||||||
nxp.ClockIpAdc2.Enable(false) // ~
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------- XBAR --
|
nxp.ClockIpXbar1.Enable(false) // disable XBAR
|
||||||
nxp.ClockIpXbar1.Enable(false) // disable XBAR clock gates
|
nxp.ClockIpXbar2.Enable(false) //
|
||||||
nxp.ClockIpXbar2.Enable(false) // ~
|
nxp.ClockIpXbar3.Enable(false) //
|
||||||
nxp.ClockIpXbar3.Enable(false) // ~
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------- ARM/IPG --
|
|
||||||
nxp.DivIpIpg.Div(3) // divide IPG_PODF (DIV4)
|
nxp.DivIpIpg.Div(3) // divide IPG_PODF (DIV4)
|
||||||
nxp.DivIpArm.Div(1) // divide ARM_PODF (DIV2)
|
nxp.DivIpArm.Div(1) // divide ARM_PODF (DIV2)
|
||||||
nxp.DivIpPeriphClk2.Div(0) // divide PERIPH_CLK2_PODF (DIV1)
|
nxp.DivIpPeriphClk2.Div(0) // divide PERIPH_CLK2_PODF (DIV1)
|
||||||
|
|
||||||
// ---------------------------------------------------------------- GPT/PIT --
|
nxp.ClockIpGpt1.Enable(false) // disable GPT/PIT
|
||||||
nxp.ClockIpGpt1.Enable(false) // disable GPT/PIT clock gates
|
nxp.ClockIpGpt1S.Enable(false) //
|
||||||
nxp.ClockIpGpt1S.Enable(false) // ~
|
nxp.ClockIpGpt2.Enable(false) //
|
||||||
nxp.ClockIpGpt2.Enable(false) // ~
|
nxp.ClockIpGpt2S.Enable(false) //
|
||||||
nxp.ClockIpGpt2S.Enable(false) // ~
|
nxp.ClockIpPit.Enable(false) //
|
||||||
nxp.ClockIpPit.Enable(false) // ~
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------- PER --
|
|
||||||
nxp.DivIpPerclk.Div(0) // divide PERCLK_PODF (DIV1)
|
nxp.DivIpPerclk.Div(0) // divide PERCLK_PODF (DIV1)
|
||||||
|
|
||||||
// ------------------------------------------------------------------ USDHC --
|
nxp.ClockIpUsdhc1.Enable(false) // disable USDHC1
|
||||||
nxp.ClockIpUsdhc1.Enable(false) // disable USDHC1 clock gate
|
|
||||||
nxp.DivIpUsdhc1.Div(1) // divide USDHC1_PODF (DIV2)
|
nxp.DivIpUsdhc1.Div(1) // divide USDHC1_PODF (DIV2)
|
||||||
nxp.MuxIpUsdhc1.Mux(1) // USDHC1 select PLL2_PFD0
|
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.DivIpUsdhc2.Div(1) // divide USDHC2_PODF (DIV2)
|
||||||
nxp.MuxIpUsdhc2.Mux(1) // USDHC2 select PLL2_PFD0
|
nxp.MuxIpUsdhc2.Mux(1) // USDHC2 select PLL2_PFD0
|
||||||
|
|
||||||
// ------------------------------------------------------------------- SEMC --
|
nxp.ClockIpSemc.Enable(false) // disable SEMC
|
||||||
nxp.ClockIpSemc.Enable(false) // disable SEMC clock gate
|
|
||||||
nxp.DivIpSemc.Div(1) // divide SEMC_PODF (DIV2)
|
nxp.DivIpSemc.Div(1) // divide SEMC_PODF (DIV2)
|
||||||
nxp.MuxIpSemcAlt.Mux(0) // SEMC_ALT select PLL2_PFD2
|
nxp.MuxIpSemcAlt.Mux(0) // SEMC_ALT select PLL2_PFD2
|
||||||
nxp.MuxIpSemc.Mux(1) // SEMC select SEMC_ALT
|
nxp.MuxIpSemc.Mux(1) // SEMC select SEMC_ALT
|
||||||
|
|
||||||
// ---------------------------------------------------------------- FLEXSPI --
|
|
||||||
if false {
|
if false {
|
||||||
// TODO: external flash is on this bus, configured via DCD block
|
// 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.DivIpFlexSpi.Div(0) // divide FLEXSPI_PODF (DIV1)
|
||||||
nxp.MuxIpFlexSpi.Mux(2) // FLEXSPI select PLL2_PFD2
|
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.DivIpFlexSpi2.Div(0) // divide FLEXSPI2_PODF (DIV1)
|
||||||
nxp.MuxIpFlexSpi2.Mux(0) // FLEXSPI2 select PLL2_PFD2
|
nxp.MuxIpFlexSpi2.Mux(0) // FLEXSPI2 select PLL2_PFD2
|
||||||
|
|
||||||
// -------------------------------------------------------------------- CSI --
|
nxp.ClockIpCsi.Enable(false) // disable CSI
|
||||||
nxp.ClockIpCsi.Enable(false) // disable CSI clock gate
|
|
||||||
nxp.DivIpCsi.Div(1) // divide CSI_PODF (DIV2)
|
nxp.DivIpCsi.Div(1) // divide CSI_PODF (DIV2)
|
||||||
nxp.MuxIpCsi.Mux(0) // CSI select OSC24M
|
nxp.MuxIpCsi.Mux(0) // CSI select OSC24M
|
||||||
|
|
||||||
// ------------------------------------------------------------------ LPSPI --
|
nxp.ClockIpLpspi1.Enable(false) // disable LPSPI
|
||||||
nxp.ClockIpLpspi1.Enable(false) // disable LPSPI clock gate
|
nxp.ClockIpLpspi2.Enable(false) //
|
||||||
nxp.ClockIpLpspi2.Enable(false) // ~
|
nxp.ClockIpLpspi3.Enable(false) //
|
||||||
nxp.ClockIpLpspi3.Enable(false) // ~
|
nxp.ClockIpLpspi4.Enable(false) //
|
||||||
nxp.ClockIpLpspi4.Enable(false) // ~
|
|
||||||
nxp.DivIpLpspi.Div(3) // divide LPSPI_PODF (DIV4)
|
nxp.DivIpLpspi.Div(3) // divide LPSPI_PODF (DIV4)
|
||||||
nxp.MuxIpLpspi.Mux(2) // LPSPI select PLL2
|
nxp.MuxIpLpspi.Mux(2) // LPSPI select PLL2
|
||||||
|
|
||||||
// ------------------------------------------------------------------ TRACE --
|
nxp.ClockIpTrace.Enable(false) // disable TRACE
|
||||||
nxp.ClockIpTrace.Enable(false) // disable TRACE clock gate
|
|
||||||
nxp.DivIpTrace.Div(3) // divide TRACE_PODF (DIV4)
|
nxp.DivIpTrace.Div(3) // divide TRACE_PODF (DIV4)
|
||||||
nxp.MuxIpTrace.Mux(0) // TRACE select PLL2_MAIN
|
nxp.MuxIpTrace.Mux(0) // TRACE select PLL2_MAIN
|
||||||
|
|
||||||
// -------------------------------------------------------------------- SAI --
|
nxp.ClockIpSai1.Enable(false) // disable SAI1
|
||||||
nxp.ClockIpSai1.Enable(false) // disable SAI1 clock gate
|
|
||||||
nxp.DivIpSai1Pre.Div(3) // divide SAI1_CLK_PRED (DIV4)
|
nxp.DivIpSai1Pre.Div(3) // divide SAI1_CLK_PRED (DIV4)
|
||||||
nxp.DivIpSai1.Div(1) // divide SAI1_CLK_PODF (DIV2)
|
nxp.DivIpSai1.Div(1) // divide SAI1_CLK_PODF (DIV2)
|
||||||
nxp.MuxIpSai1.Mux(0) // SAI1 select PLL3_PFD2
|
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.DivIpSai2Pre.Div(3) // divide SAI2_CLK_PRED (DIV4)
|
||||||
nxp.DivIpSai2.Div(1) // divide SAI2_CLK_PODF (DIV2)
|
nxp.DivIpSai2.Div(1) // divide SAI2_CLK_PODF (DIV2)
|
||||||
nxp.MuxIpSai2.Mux(0) // SAI2 select PLL3_PFD2
|
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.DivIpSai3Pre.Div(3) // divide SAI3_CLK_PRED (DIV4)
|
||||||
nxp.DivIpSai3.Div(1) // divide SAI3_CLK_PODF (DIV2)
|
nxp.DivIpSai3.Div(1) // divide SAI3_CLK_PODF (DIV2)
|
||||||
nxp.MuxIpSai3.Mux(0) // SAI3 select PLL3_PFD2
|
nxp.MuxIpSai3.Mux(0) // SAI3 select PLL3_PFD2
|
||||||
|
|
||||||
// ------------------------------------------------------------------ LPI2C --
|
nxp.ClockIpLpi2c1.Enable(false) // disable LPI2C
|
||||||
nxp.ClockIpLpi2c1.Enable(false) // disable LPI2C clock gate
|
nxp.ClockIpLpi2c2.Enable(false) //
|
||||||
nxp.ClockIpLpi2c2.Enable(false) // ~
|
nxp.ClockIpLpi2c3.Enable(false) //
|
||||||
nxp.ClockIpLpi2c3.Enable(false) // ~
|
|
||||||
nxp.DivIpLpi2c.Div(0) // divide LPI2C_CLK_PODF (DIV1)
|
nxp.DivIpLpi2c.Div(0) // divide LPI2C_CLK_PODF (DIV1)
|
||||||
nxp.MuxIpLpi2c.Mux(0) // LPI2C select PLL3_SW_60M
|
nxp.MuxIpLpi2c.Mux(0) // LPI2C select PLL3_SW_60M
|
||||||
|
|
||||||
// -------------------------------------------------------------------- CAN --
|
nxp.ClockIpCan1.Enable(false) // disable CAN
|
||||||
nxp.ClockIpCan1.Enable(false) // disable CAN clock gate
|
nxp.ClockIpCan2.Enable(false) //
|
||||||
nxp.ClockIpCan2.Enable(false) // ~
|
nxp.ClockIpCan3.Enable(false) //
|
||||||
nxp.ClockIpCan3.Enable(false) // ~
|
nxp.ClockIpCan1S.Enable(false) //
|
||||||
nxp.ClockIpCan1S.Enable(false) // ~
|
nxp.ClockIpCan2S.Enable(false) //
|
||||||
nxp.ClockIpCan2S.Enable(false) // ~
|
nxp.ClockIpCan3S.Enable(false) //
|
||||||
nxp.ClockIpCan3S.Enable(false) // ~
|
|
||||||
nxp.DivIpCan.Div(1) // divide CAN_CLK_PODF (DIV2)
|
nxp.DivIpCan.Div(1) // divide CAN_CLK_PODF (DIV2)
|
||||||
nxp.MuxIpCan.Mux(2) // CAN select PLL3_SW_80M
|
nxp.MuxIpCan.Mux(2) // CAN select PLL3_SW_80M
|
||||||
|
|
||||||
// ------------------------------------------------------------------- UART --
|
nxp.ClockIpLpuart1.Enable(false) // disable UART
|
||||||
nxp.ClockIpLpuart1.Enable(false) // disable UART clock gate
|
nxp.ClockIpLpuart2.Enable(false) //
|
||||||
nxp.ClockIpLpuart2.Enable(false) // ~
|
nxp.ClockIpLpuart3.Enable(false) //
|
||||||
nxp.ClockIpLpuart3.Enable(false) // ~
|
nxp.ClockIpLpuart4.Enable(false) //
|
||||||
nxp.ClockIpLpuart4.Enable(false) // ~
|
nxp.ClockIpLpuart5.Enable(false) //
|
||||||
nxp.ClockIpLpuart5.Enable(false) // ~
|
nxp.ClockIpLpuart6.Enable(false) //
|
||||||
nxp.ClockIpLpuart6.Enable(false) // ~
|
nxp.ClockIpLpuart7.Enable(false) //
|
||||||
nxp.ClockIpLpuart7.Enable(false) // ~
|
nxp.ClockIpLpuart8.Enable(false) //
|
||||||
nxp.ClockIpLpuart8.Enable(false) // ~
|
|
||||||
nxp.DivIpUart.Div(0) // divide UART_CLK_PODF (DIV1)
|
nxp.DivIpUart.Div(0) // divide UART_CLK_PODF (DIV1)
|
||||||
nxp.MuxIpUart.Mux(1) // UART select OSC
|
nxp.MuxIpUart.Mux(1) // UART select OSC
|
||||||
|
|
||||||
// -------------------------------------------------------------------- LCD --
|
nxp.ClockIpLcdPixel.Enable(false) // disable LCDIF
|
||||||
nxp.ClockIpLcdPixel.Enable(false) // disable LCDIF clock gate
|
|
||||||
nxp.DivIpLcdifPre.Div(1) // divide LCDIF_PRED (DIV2)
|
nxp.DivIpLcdifPre.Div(1) // divide LCDIF_PRED (DIV2)
|
||||||
nxp.DivIpLcdif.Div(3) // divide LCDIF_CLK_PODF (DIV4)
|
nxp.DivIpLcdif.Div(3) // divide LCDIF_CLK_PODF (DIV4)
|
||||||
nxp.MuxIpLcdifPre.Mux(5) // LCDIF_PRE select PLL3_PFD1
|
nxp.MuxIpLcdifPre.Mux(5) // LCDIF_PRE select PLL3_PFD1
|
||||||
|
|
||||||
// ------------------------------------------------------------------ SPDIF --
|
nxp.ClockIpSpdif.Enable(false) // disable SPDIF
|
||||||
nxp.ClockIpSpdif.Enable(false) // disable SPDIF clock gate
|
|
||||||
nxp.DivIpSpdif0Pre.Div(1) // divide SPDIF0_CLK_PRED (DIV2)
|
nxp.DivIpSpdif0Pre.Div(1) // divide SPDIF0_CLK_PRED (DIV2)
|
||||||
nxp.DivIpSpdif0.Div(7) // divide SPDIF0_CLK_PODF (DIV8)
|
nxp.DivIpSpdif0.Div(7) // divide SPDIF0_CLK_PODF (DIV8)
|
||||||
nxp.MuxIpSpdif.Mux(3) // SPDIF select PLL3_SW
|
nxp.MuxIpSpdif.Mux(3) // SPDIF select PLL3_SW
|
||||||
|
|
||||||
// ----------------------------------------------------------------- FLEXIO --
|
nxp.ClockIpFlexio1.Enable(false) // disable FLEXIO1
|
||||||
nxp.ClockIpFlexio1.Enable(false) // disable FLEXIO1 clock gate
|
|
||||||
nxp.DivIpFlexio1Pre.Div(1) // divide FLEXIO1_CLK_PRED (DIV2)
|
nxp.DivIpFlexio1Pre.Div(1) // divide FLEXIO1_CLK_PRED (DIV2)
|
||||||
nxp.DivIpFlexio1.Div(7) // divide FLEXIO1_CLK_PODF (DIV8)
|
nxp.DivIpFlexio1.Div(7) // divide FLEXIO1_CLK_PODF (DIV8)
|
||||||
nxp.MuxIpFlexio1.Mux(3) // FLEXIO1 select PLL3_SW
|
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.DivIpFlexio2Pre.Div(1) // divide FLEXIO2_CLK_PRED (DIV2)
|
||||||
nxp.DivIpFlexio2.Div(7) // divide FLEXIO2_CLK_PODF (DIV8)
|
nxp.DivIpFlexio2.Div(7) // divide FLEXIO2_CLK_PODF (DIV8)
|
||||||
nxp.MuxIpFlexio2.Mux(3) // FLEXIO2 select PLL3_SW
|
nxp.MuxIpFlexio2.Mux(3) // FLEXIO2 select PLL3_SW
|
||||||
|
|
||||||
// ---------------------------------------------------------------- PLL/PFD --
|
|
||||||
nxp.MuxIpPll3Sw.Mux(0) // PLL3_SW select PLL3_MAIN
|
nxp.MuxIpPll3Sw.Mux(0) // PLL3_SW select PLL3_MAIN
|
||||||
|
|
||||||
ArmPllConfig.Configure() // init ARM PLL
|
ArmPllConfig.Configure() // init ARM PLL
|
||||||
|
@ -277,18 +225,15 @@ func initClocks() {
|
||||||
Usb1PllConfig.Configure() // init USB1 PLL and PFDs
|
Usb1PllConfig.Configure() // init USB1 PLL and PFDs
|
||||||
Usb2PllConfig.Configure() // init USB2 PLL
|
Usb2PllConfig.Configure() // init USB2 PLL
|
||||||
|
|
||||||
// --------------------------------------------------------------- ARM CORE --
|
|
||||||
nxp.MuxIpPrePeriph.Mux(3) // PRE_PERIPH select ARM_PLL
|
nxp.MuxIpPrePeriph.Mux(3) // PRE_PERIPH select ARM_PLL
|
||||||
nxp.MuxIpPeriph.Mux(0) // PERIPH select PRE_PERIPH
|
nxp.MuxIpPeriph.Mux(0) // PERIPH select PRE_PERIPH
|
||||||
nxp.MuxIpPeriphClk2.Mux(1) // PERIPH_CLK2 select OSC
|
nxp.MuxIpPeriphClk2.Mux(1) // PERIPH_CLK2 select OSC
|
||||||
nxp.MuxIpPerclk.Mux(1) // PERCLK select OSC
|
nxp.MuxIpPerclk.Mux(1) // PERCLK select OSC
|
||||||
|
|
||||||
// ------------------------------------------------------------------- LVDS --
|
|
||||||
// set LVDS1 clock source
|
// set LVDS1 clock source
|
||||||
nxp.CCM_ANALOG.MISC1.Set((nxp.CCM_ANALOG.MISC1.Get() & ^uint32(nxp.CCM_ANALOG_MISC1_LVDS1_CLK_SEL_Msk)) |
|
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))
|
((0 << nxp.CCM_ANALOG_MISC1_LVDS1_CLK_SEL_Pos) & nxp.CCM_ANALOG_MISC1_LVDS1_CLK_SEL_Msk))
|
||||||
|
|
||||||
// ----------------------------------------------------------------- CLKOUT --
|
|
||||||
// set CLOCK_OUT1 divider
|
// set CLOCK_OUT1 divider
|
||||||
nxp.CCM.CCOSR.Set((nxp.CCM.CCOSR.Get() & ^uint32(nxp.CCM_CCOSR_CLKO1_DIV_Msk)) |
|
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))
|
((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_CLKO1_EN_Msk) // enable CLK_OUT1
|
||||||
nxp.CCM.CCOSR.SetBits(nxp.CCM_CCOSR_CLKO2_EN_Msk) // enable CLK_OUT2
|
nxp.CCM.CCOSR.SetBits(nxp.CCM_CCOSR_CLKO2_EN_Msk) // enable CLK_OUT2
|
||||||
|
|
||||||
// ----------------------------------------------------------------- IOMUXC --
|
nxp.ClockIpIomuxcGpr.Enable(false) // disable IOMUXC_GPR
|
||||||
nxp.ClockIpIomuxcGpr.Enable(false) // disable IOMUXC_GPR clock gate
|
nxp.ClockIpIomuxc.Enable(false) // disable IOMUXC
|
||||||
nxp.ClockIpIomuxc.Enable(false) // disable IOMUXC clock gate
|
|
||||||
// set GPT1 High frequency reference clock source
|
// set GPT1 High frequency reference clock source
|
||||||
nxp.IOMUXC_GPR.GPR5.ClearBits(nxp.IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT1_Msk)
|
nxp.IOMUXC_GPR.GPR5.ClearBits(nxp.IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT1_Msk)
|
||||||
// set GPT2 High frequency reference clock source
|
// set GPT2 High frequency reference clock source
|
||||||
nxp.IOMUXC_GPR.GPR5.ClearBits(nxp.IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT2_Msk)
|
nxp.IOMUXC_GPR.GPR5.ClearBits(nxp.IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT2_Msk)
|
||||||
|
|
||||||
// ------------------------------------------------------------------- GPIO --
|
nxp.ClockIpGpio1.Enable(false) // disable GPIO
|
||||||
nxp.ClockIpGpio1.Enable(false) // disable GPIO clock gates
|
nxp.ClockIpGpio2.Enable(false) //
|
||||||
nxp.ClockIpGpio2.Enable(false) // ~
|
nxp.ClockIpGpio3.Enable(false) //
|
||||||
nxp.ClockIpGpio3.Enable(false) // ~
|
nxp.ClockIpGpio4.Enable(false) //
|
||||||
nxp.ClockIpGpio4.Enable(false) // ~
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func enableTimerClocks() {
|
func enableTimerClocks() {
|
||||||
|
|
||||||
// ---------------------------------------------------------------- GPT/PIT --
|
nxp.ClockIpGpt1.Enable(true) // enable GPT/PIT
|
||||||
nxp.ClockIpGpt1.Enable(true) // enable GPT/PIT clock gates
|
nxp.ClockIpGpt1S.Enable(true) //
|
||||||
nxp.ClockIpGpt1S.Enable(true) // ~
|
nxp.ClockIpGpt2.Enable(true) //
|
||||||
nxp.ClockIpGpt2.Enable(true) // ~
|
nxp.ClockIpGpt2S.Enable(true) //
|
||||||
nxp.ClockIpGpt2S.Enable(true) // ~
|
nxp.ClockIpPit.Enable(true) //
|
||||||
nxp.ClockIpPit.Enable(true) // ~
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func enablePinClocks() {
|
func enablePinClocks() {
|
||||||
|
|
||||||
// ----------------------------------------------------------------- IOMUXC --
|
nxp.ClockIpIomuxcGpr.Enable(true) // enable IOMUXC
|
||||||
nxp.ClockIpIomuxcGpr.Enable(true) // enable IOMUXC clock gates
|
nxp.ClockIpIomuxc.Enable(true) //
|
||||||
nxp.ClockIpIomuxc.Enable(true) // ~
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------- GPIO --
|
nxp.ClockIpGpio1.Enable(true) // enable GPIO
|
||||||
nxp.ClockIpGpio1.Enable(true) // enable GPIO clock gates
|
nxp.ClockIpGpio2.Enable(true) //
|
||||||
nxp.ClockIpGpio2.Enable(true) // ~
|
nxp.ClockIpGpio3.Enable(true) //
|
||||||
nxp.ClockIpGpio3.Enable(true) // ~
|
nxp.ClockIpGpio4.Enable(true) //
|
||||||
nxp.ClockIpGpio4.Enable(true) // ~
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func enablePeripheralClocks() {
|
func enablePeripheralClocks() {
|
||||||
|
|
||||||
// -------------------------------------------------------------------- ADC --
|
nxp.ClockIpAdc1.Enable(true) // enable ADC
|
||||||
nxp.ClockIpAdc1.Enable(true) // enable ADC clock gates
|
nxp.ClockIpAdc2.Enable(true) //
|
||||||
nxp.ClockIpAdc2.Enable(true) // ~
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------- XBAR --
|
nxp.ClockIpXbar1.Enable(true) // enable XBAR
|
||||||
nxp.ClockIpXbar1.Enable(true) // enable XBAR clock gates
|
nxp.ClockIpXbar2.Enable(true) //
|
||||||
nxp.ClockIpXbar2.Enable(true) // ~
|
nxp.ClockIpXbar3.Enable(true) //
|
||||||
nxp.ClockIpXbar3.Enable(true) // ~
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------ USDHC --
|
nxp.ClockIpUsdhc1.Enable(true) // enable USDHC
|
||||||
nxp.ClockIpUsdhc1.Enable(true) // enable USDHC clock gates
|
nxp.ClockIpUsdhc2.Enable(true) //
|
||||||
nxp.ClockIpUsdhc2.Enable(true) // ~
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------- SEMC --
|
nxp.ClockIpSemc.Enable(true) // enable SEMC
|
||||||
nxp.ClockIpSemc.Enable(true) // enable SEMC clock gate
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------- FLEXSPI --
|
nxp.ClockIpFlexSpi2.Enable(true) // enable FLEXSPI2
|
||||||
nxp.ClockIpFlexSpi2.Enable(true) // enable FLEXSPI2 clock gate
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------ LPSPI --
|
nxp.ClockIpLpspi1.Enable(true) // enable LPSPI
|
||||||
nxp.ClockIpLpspi1.Enable(true) // enable LPSPI clock gate
|
nxp.ClockIpLpspi2.Enable(true) //
|
||||||
nxp.ClockIpLpspi2.Enable(true) // ~
|
nxp.ClockIpLpspi3.Enable(true) //
|
||||||
nxp.ClockIpLpspi3.Enable(true) // ~
|
nxp.ClockIpLpspi4.Enable(true) //
|
||||||
nxp.ClockIpLpspi4.Enable(true) // ~
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------ LPI2C --
|
nxp.ClockIpLpi2c1.Enable(true) // enable LPI2C
|
||||||
nxp.ClockIpLpi2c1.Enable(true) // enable LPI2C clock gate
|
nxp.ClockIpLpi2c2.Enable(true) //
|
||||||
nxp.ClockIpLpi2c2.Enable(true) // ~
|
nxp.ClockIpLpi2c3.Enable(true) //
|
||||||
nxp.ClockIpLpi2c3.Enable(true) // ~
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------- CAN --
|
nxp.ClockIpCan1.Enable(true) // enable CAN
|
||||||
nxp.ClockIpCan1.Enable(true) // enable CAN clock gate
|
nxp.ClockIpCan2.Enable(true) //
|
||||||
nxp.ClockIpCan2.Enable(true) // ~
|
nxp.ClockIpCan3.Enable(true) //
|
||||||
nxp.ClockIpCan3.Enable(true) // ~
|
nxp.ClockIpCan1S.Enable(true) //
|
||||||
nxp.ClockIpCan1S.Enable(true) // ~
|
nxp.ClockIpCan2S.Enable(true) //
|
||||||
nxp.ClockIpCan2S.Enable(true) // ~
|
nxp.ClockIpCan3S.Enable(true) //
|
||||||
nxp.ClockIpCan3S.Enable(true) // ~
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------- UART --
|
nxp.ClockIpLpuart1.Enable(true) // enable UART
|
||||||
nxp.ClockIpLpuart1.Enable(true) // enable UART clock gate
|
nxp.ClockIpLpuart2.Enable(true) //
|
||||||
nxp.ClockIpLpuart2.Enable(true) // ~
|
nxp.ClockIpLpuart3.Enable(true) //
|
||||||
nxp.ClockIpLpuart3.Enable(true) // ~
|
nxp.ClockIpLpuart4.Enable(true) //
|
||||||
nxp.ClockIpLpuart4.Enable(true) // ~
|
nxp.ClockIpLpuart5.Enable(true) //
|
||||||
nxp.ClockIpLpuart5.Enable(true) // ~
|
nxp.ClockIpLpuart6.Enable(true) //
|
||||||
nxp.ClockIpLpuart6.Enable(true) // ~
|
nxp.ClockIpLpuart7.Enable(true) //
|
||||||
nxp.ClockIpLpuart7.Enable(true) // ~
|
nxp.ClockIpLpuart8.Enable(true) //
|
||||||
nxp.ClockIpLpuart8.Enable(true) // ~
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------- FLEXIO --
|
nxp.ClockIpFlexio1.Enable(true) // enable FLEXIO
|
||||||
nxp.ClockIpFlexio1.Enable(true) // enable FLEXIO clock gates
|
nxp.ClockIpFlexio2.Enable(true) //
|
||||||
nxp.ClockIpFlexio2.Enable(true) // ~
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,50 +10,38 @@ func initCache() {
|
||||||
|
|
||||||
nxp.MPU.Enable(false)
|
nxp.MPU.Enable(false)
|
||||||
|
|
||||||
// -------------------------------------------------------- OVERLAY REGIONS --
|
|
||||||
|
|
||||||
// add Default [0] region to deny access to whole address space to workaround
|
// add Default [0] region to deny access to whole address space to workaround
|
||||||
// speculative prefetch. Refer to Arm errata 1013783-B for more details.
|
// speculative prefetch. Refer to Arm errata 1013783-B for more details.
|
||||||
|
|
||||||
// [0] Default {OVERLAY}:
|
// [0] Default {OVERLAY}: 4 GiB, -access, @device, -exec, -share, -cache, -buffer, -subregion
|
||||||
// 4 GiB, -access, @device, -exec, -share, -cache, -buffer, -subregion
|
|
||||||
nxp.MPU.SetRBAR(0, 0x00000000)
|
nxp.MPU.SetRBAR(0, 0x00000000)
|
||||||
nxp.MPU.SetRASR(nxp.RGNSZ_4GB, nxp.PERM_NONE, nxp.EXTN_DEVICE, false, false, false, false, false)
|
nxp.MPU.SetRASR(nxp.RGNSZ_4GB, nxp.PERM_NONE, nxp.EXTN_DEVICE, false, false, false, false, false)
|
||||||
|
|
||||||
// [1] Peripherals {OVERLAY}:
|
// [1] Peripherals {OVERLAY}: 64 MiB, +ACCESS, @device, +EXEC, -share, -cache, -buffer, -subregion
|
||||||
// 64 MiB, +ACCESS, @device, +EXEC, -share, -cache, -buffer, -subregion
|
|
||||||
nxp.MPU.SetRBAR(1, 0x40000000)
|
nxp.MPU.SetRBAR(1, 0x40000000)
|
||||||
nxp.MPU.SetRASR(nxp.RGNSZ_64MB, nxp.PERM_FULL, nxp.EXTN_DEVICE, true, false, false, false, false)
|
nxp.MPU.SetRASR(nxp.RGNSZ_64MB, nxp.PERM_FULL, nxp.EXTN_DEVICE, true, false, false, false, false)
|
||||||
|
|
||||||
// [2] RAM {OVERLAY}:
|
// [2] RAM {OVERLAY}: 1 GiB, +ACCESS, @device, +EXEC, -share, -cache, -buffer, -subregion
|
||||||
// 1 GiB, +ACCESS, @device, +EXEC, -share, -cache, -buffer, -subregion
|
|
||||||
nxp.MPU.SetRBAR(2, 0x00000000)
|
nxp.MPU.SetRBAR(2, 0x00000000)
|
||||||
nxp.MPU.SetRASR(nxp.RGNSZ_1GB, nxp.PERM_FULL, nxp.EXTN_DEVICE, true, false, false, false, false)
|
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.SetRBAR(3, 0x00000000)
|
||||||
nxp.MPU.SetRASR(nxp.RGNSZ_512KB, nxp.PERM_FULL, nxp.EXTN_NORMAL, true, false, false, false, false)
|
nxp.MPU.SetRASR(nxp.RGNSZ_512KB, nxp.PERM_FULL, nxp.EXTN_NORMAL, true, false, false, false, false)
|
||||||
|
|
||||||
// [4] DTCM:
|
// [4] DTCM: 512 KiB, +ACCESS, #NORMAL, +EXEC, -share, -cache, -buffer, -subregion
|
||||||
// 512 KiB, +ACCESS, #NORMAL, +EXEC, -share, -cache, -buffer, -subregion
|
|
||||||
nxp.MPU.SetRBAR(4, 0x20000000)
|
nxp.MPU.SetRBAR(4, 0x20000000)
|
||||||
nxp.MPU.SetRASR(nxp.RGNSZ_512KB, nxp.PERM_FULL, nxp.EXTN_NORMAL, true, false, false, false, false)
|
nxp.MPU.SetRASR(nxp.RGNSZ_512KB, nxp.PERM_FULL, nxp.EXTN_NORMAL, true, false, false, false, false)
|
||||||
|
|
||||||
// [5] RAM (AXI):
|
// [5] RAM (AXI): 512 KiB, +ACCESS, #NORMAL, +EXEC, -share, +CACHE, +BUFFER, -subregion
|
||||||
// 512 KiB, +ACCESS, #NORMAL, +EXEC, -share, +CACHE, +BUFFER, -subregion
|
|
||||||
nxp.MPU.SetRBAR(5, 0x20200000)
|
nxp.MPU.SetRBAR(5, 0x20200000)
|
||||||
nxp.MPU.SetRASR(nxp.RGNSZ_512KB, nxp.PERM_FULL, nxp.EXTN_NORMAL, true, false, true, true, false)
|
nxp.MPU.SetRASR(nxp.RGNSZ_512KB, nxp.PERM_FULL, nxp.EXTN_NORMAL, true, false, true, true, false)
|
||||||
|
|
||||||
// [6] FlexSPI:
|
// [6] FlexSPI: 512 MiB, +ACCESS, #NORMAL, +EXEC, -share, +CACHE, +BUFFER, -subregion
|
||||||
// 512 MiB, +ACCESS, #NORMAL, +EXEC, -share, +CACHE, +BUFFER, -subregion
|
|
||||||
nxp.MPU.SetRBAR(6, 0x70000000)
|
nxp.MPU.SetRBAR(6, 0x70000000)
|
||||||
nxp.MPU.SetRASR(nxp.RGNSZ_512MB, nxp.PERM_FULL, nxp.EXTN_NORMAL, true, false, true, true, false)
|
nxp.MPU.SetRASR(nxp.RGNSZ_512MB, nxp.PERM_FULL, nxp.EXTN_NORMAL, true, false, true, true, false)
|
||||||
|
|
||||||
// [7] QSPI flash:
|
// [7] QSPI flash: 2 MiB, +ACCESS, #NORMAL, +EXEC, -share, +CACHE, +BUFFER, -subregion
|
||||||
// 2 MiB, +ACCESS, #NORMAL, +EXEC, -share, +CACHE, +BUFFER, -subregion
|
|
||||||
nxp.MPU.SetRBAR(7, 0x60000000)
|
nxp.MPU.SetRBAR(7, 0x60000000)
|
||||||
nxp.MPU.SetRASR(nxp.RGNSZ_2MB, nxp.PERM_FULL, nxp.EXTN_NORMAL, true, false, true, true, false)
|
nxp.MPU.SetRASR(nxp.RGNSZ_2MB, nxp.PERM_FULL, nxp.EXTN_NORMAL, true, false, true, true, false)
|
||||||
|
|
||||||
|
|
|
@ -12,14 +12,14 @@ import (
|
||||||
|
|
||||||
type timeUnit int64
|
type timeUnit int64
|
||||||
|
|
||||||
const ( // HW divides 24 MHz XTALOSC down to 100 kHz
|
const (
|
||||||
lastCycle = SYSTICK_FREQ/1000 - 1
|
lastCycle = SYSTICK_FREQ/1000 - 1
|
||||||
cyclesPerMicro = CORE_FREQ / 1000000
|
cyclesPerMicro = CORE_FREQ / 1000000
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
PIT_FREQ = PERCLK_FREQ
|
pitFreq = OSC_FREQ // PIT/GPT are muxed to 24 MHz OSC
|
||||||
pitCyclesPerMicro = PIT_FREQ / 1000000
|
pitCyclesPerMicro = pitFreq / 1000000
|
||||||
pitSleepTimer = 0 // x4 32-bit PIT timers [0..3]
|
pitSleepTimer = 0 // x4 32-bit PIT timers [0..3]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -32,16 +32,11 @@ var (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// debug exception and monitor control
|
// debug exception and monitor control
|
||||||
DEMCR = (*volatile.Register32)(unsafe.Pointer(uintptr(0xe000edfc)))
|
DEM_CR = (*volatile.Register32)(unsafe.Pointer(uintptr(0xe000edfc)))
|
||||||
DWT_CTRL = (*volatile.Register32)(unsafe.Pointer(uintptr(0xe0001000)))
|
DWT_CR = (*volatile.Register32)(unsafe.Pointer(uintptr(0xe0001000)))
|
||||||
DWT_CYCCNT = (*volatile.Register32)(unsafe.Pointer(uintptr(0xe0001004)))
|
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 {
|
func ticksToNanoseconds(ticks timeUnit) int64 {
|
||||||
return int64(ticks) * 1000
|
return int64(ticks) * 1000
|
||||||
}
|
}
|
||||||
|
@ -51,22 +46,30 @@ func nanosecondsToTicks(ns int64) timeUnit {
|
||||||
}
|
}
|
||||||
|
|
||||||
func initSysTick() {
|
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) {
|
if arm.SYST.SYST_CSR.HasBits(arm.SYST_CSR_ENABLE_Msk) {
|
||||||
arm.SYST.SYST_CSR.ClearBits(arm.SYST_CSR_ENABLE_Msk)
|
arm.SYST.SYST_CSR.ClearBits(arm.SYST_CSR_ENABLE_Msk)
|
||||||
}
|
}
|
||||||
|
|
||||||
// zeroize the counter
|
// zeroize the counter
|
||||||
tickCount.Set(0)
|
tickCount.Set(0)
|
||||||
arm.SYST.SYST_RVR.Set(lastCycle)
|
arm.SYST.SYST_RVR.Set(lastCycle)
|
||||||
arm.SYST.SYST_CVR.Set(0)
|
arm.SYST.SYST_CVR.Set(0)
|
||||||
arm.SYST.SYST_CSR.Set(arm.SYST_CSR_TICKINT | arm.SYST_CSR_ENABLE)
|
arm.SYST.SYST_CSR.Set(arm.SYST_CSR_TICKINT | arm.SYST_CSR_ENABLE)
|
||||||
|
|
||||||
// set SysTick and PendSV priority to 32
|
// set SysTick and PendSV priority to 32
|
||||||
nxp.SystemControl.SHPR3.Set((0x20 << nxp.SCB_SHPR3_PRI_15_Pos) |
|
nxp.SystemControl.SHPR3.Set((0x20 << nxp.SCB_SHPR3_PRI_15_Pos) |
|
||||||
(0x20 << nxp.SCB_SHPR3_PRI_14_Pos))
|
(0x20 << nxp.SCB_SHPR3_PRI_14_Pos))
|
||||||
|
|
||||||
// turn on cycle counter
|
// turn on cycle counter
|
||||||
DEMCR.SetBits(DEMCR_TRCENA)
|
DEM_CR.SetBits(traceEnable)
|
||||||
DWT_CTRL.SetBits(DWT_CTRL_CYCCNTENA)
|
DWT_CR.SetBits(cycleCountEnable)
|
||||||
cycleCount.Set(DWT_CYCCNT.Get())
|
cycleCount.Set(DWT_CYCCNT.Get())
|
||||||
|
|
||||||
// enable PIT, disable counters
|
// enable PIT, disable counters
|
||||||
|
@ -74,6 +77,7 @@ func initSysTick() {
|
||||||
for i := range nxp.PIT.TIMER {
|
for i := range nxp.PIT.TIMER {
|
||||||
nxp.PIT.TIMER[i].TCTRL.Set(0)
|
nxp.PIT.TIMER[i].TCTRL.Set(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// register sleep timer interrupt
|
// register sleep timer interrupt
|
||||||
pitTimeout = interrupt.New(nxp.IRQ_PIT, timerWake)
|
pitTimeout = interrupt.New(nxp.IRQ_PIT, timerWake)
|
||||||
pitTimeout.SetPriority(0x21)
|
pitTimeout.SetPriority(0x21)
|
||||||
|
@ -101,7 +105,13 @@ func ticks() timeUnit {
|
||||||
cycs := cycleCount.Get()
|
cycs := cycleCount.Get()
|
||||||
curr := DWT_CYCCNT.Get()
|
curr := DWT_CYCCNT.Get()
|
||||||
arm.EnableInterrupts(mask)
|
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 {
|
if frac > 1000 {
|
||||||
frac = 1000
|
frac = 1000
|
||||||
}
|
}
|
||||||
|
@ -111,15 +121,14 @@ func ticks() timeUnit {
|
||||||
func sleepTicks(duration timeUnit) {
|
func sleepTicks(duration timeUnit) {
|
||||||
if duration >= 0 {
|
if duration >= 0 {
|
||||||
curr := ticks()
|
curr := ticks()
|
||||||
last := curr + duration
|
last := curr + duration // 64-bit overflow unlikely
|
||||||
for curr < last {
|
for curr < last {
|
||||||
cycles := timeUnit((last - curr) / pitCyclesPerMicro)
|
cycles := timeUnit((last - curr) / pitCyclesPerMicro)
|
||||||
if cycles > 0xFFFFFFFF {
|
if cycles > 0xFFFFFFFF {
|
||||||
cycles = 0xFFFFFFFF
|
cycles = 0xFFFFFFFF
|
||||||
}
|
}
|
||||||
if !timerSleep(uint32(cycles)) {
|
if !timerSleep(uint32(cycles)) {
|
||||||
// return early due to interrupt
|
return // return early due to interrupt
|
||||||
return
|
|
||||||
}
|
}
|
||||||
curr = ticks()
|
curr = ticks()
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,17 +4,13 @@
|
||||||
"cpu": "cortex-m7",
|
"cpu": "cortex-m7",
|
||||||
"build-tags": ["teensy40", "teensy", "mimxrt1062", "nxp"],
|
"build-tags": ["teensy40", "teensy", "mimxrt1062", "nxp"],
|
||||||
"automatic-stack-size": false,
|
"automatic-stack-size": false,
|
||||||
"default-stack-size": 131072,
|
"default-stack-size": 4096,
|
||||||
"cflags": [
|
"cflags": [
|
||||||
"--target=armv7em-none-eabi",
|
"--target=armv7em-none-eabi",
|
||||||
"-Qunused-arguments",
|
"-Qunused-arguments",
|
||||||
"-mfloat-abi=hard",
|
"-mfloat-abi=soft",
|
||||||
"-mfpu=fpv5-d16"
|
"-mfpu=fpv5-d16"
|
||||||
],
|
],
|
||||||
"ldflags": [
|
|
||||||
"--emit-relocs",
|
|
||||||
"--gc-sections"
|
|
||||||
],
|
|
||||||
"linkerscript": "targets/mimxrt1062-teensy40.ld",
|
"linkerscript": "targets/mimxrt1062-teensy40.ld",
|
||||||
"extra-files": [
|
"extra-files": [
|
||||||
"src/device/nxp/mimxrt1062.s",
|
"src/device/nxp/mimxrt1062.s",
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче