diff --git a/Makefile b/Makefile index 46a11530..f0e5917e 100644 --- a/Makefile +++ b/Makefile @@ -325,6 +325,8 @@ smoketest: @$(MD5SUM) test.hex $(TINYGO) build -size short -o test.hex -target=qtpy examples/blinky1 @$(MD5SUM) test.hex + $(TINYGO) build -size short -o test.hex -target=teensy40 examples/blinky1 + @$(MD5SUM) test.hex # test pwm $(TINYGO) build -size short -o test.hex -target=itsybitsy-m0 examples/pwm @$(MD5SUM) test.hex diff --git a/src/machine/board_teensy40.go b/src/machine/board_teensy40.go new file mode 100644 index 00000000..558a09bc --- /dev/null +++ b/src/machine/board_teensy40.go @@ -0,0 +1,177 @@ +// +build teensy40 + +package machine + +const ( + NUM_DIGITAL_IO_PINS = 40 + NUM_ANALOG_IO_PINS = 14 +) + +// Digital pins +const ( + // = Pin // [Pad]: Alt Func 0 Alt Func 1 Alt Func 2 Alt Func 3 Alt Func 4 Alt Func 5 Alt Func 6 Alt Func 7 Alt Func 8 Alt Func 9 + // = ---- ----------- --------------- --------------- --------------- -------------- -------------------- ---------- -------------------- --------------------- --------------------- ---------------- + D0 = PA3 // [AD_B0_03]: FLEXCAN2_RX XBAR1_INOUT17 LPUART6_RX USB_OTG1_OC FLEXPWM1_PWMX01 GPIO1_IO03 REF_CLK_24M LPSPI3_PCS0 ~ ~ + D1 = PA2 // [AD_B0_02]: FLEXCAN2_TX XBAR1_INOUT16 LPUART6_TX USB_OTG1_PWR FLEXPWM1_PWMX00 GPIO1_IO02 LPI2C1_HREQ LPSPI3_SDI ~ ~ + D2 = PD4 // [EMC_04]: SEMC_DATA04 FLEXPWM4_PWMA02 SAI2_TX_DATA XBAR1_INOUT06 FLEXIO1_FLEXIO04 GPIO4_IO04 ~ ~ ~ ~ + D3 = PD5 // [EMC_05]: SEMC_DATA05 FLEXPWM4_PWMB02 SAI2_TX_SYNC XBAR1_INOUT07 FLEXIO1_FLEXIO05 GPIO4_IO05 ~ ~ ~ ~ + D4 = PD6 // [EMC_06]: SEMC_DATA06 FLEXPWM2_PWMA00 SAI2_TX_BCLK XBAR1_INOUT08 FLEXIO1_FLEXIO06 GPIO4_IO06 ~ ~ ~ ~ + D5 = PD8 // [EMC_08]: SEMC_DM00 FLEXPWM2_PWMA01 SAI2_RX_DATA XBAR1_INOUT17 FLEXIO1_FLEXIO08 GPIO4_IO08 ~ ~ ~ ~ + D6 = PB10 // [B0_10]: LCD_DATA06 QTIMER4_TIMER1 FLEXPWM2_PWMA02 SAI1_TX_DATA03 FLEXIO2_FLEXIO10 GPIO2_IO10 SRC_BOOT_CFG06 ENET2_CRS ~ ~ + D7 = PB17 // [B1_01]: LCD_DATA13 XBAR1_INOUT15 LPUART4_RX SAI1_TX_DATA00 FLEXIO2_FLEXIO17 GPIO2_IO17 FLEXPWM1_PWMB03 ENET2_RDATA00 FLEXIO3_FLEXIO17 ~ + D8 = PB16 // [B1_00]: LCD_DATA12 XBAR1_INOUT14 LPUART4_TX SAI1_RX_DATA00 FLEXIO2_FLEXIO16 GPIO2_IO16 FLEXPWM1_PWMA03 ENET2_RX_ER FLEXIO3_FLEXIO16 ~ + D9 = PB11 // [B0_11]: LCD_DATA07 QTIMER4_TIMER2 FLEXPWM2_PWMB02 SAI1_TX_DATA02 FLEXIO2_FLEXIO11 GPIO2_IO11 SRC_BOOT_CFG07 ENET2_COL ~ ~ + D10 = PB0 // [B0_00]: LCD_CLK QTIMER1_TIMER0 MQS_RIGHT LPSPI4_PCS0 FLEXIO2_FLEXIO00 GPIO2_IO00 SEMC_CSX01 ENET2_MDC ~ ~ + D11 = PB2 // [B0_02]: LCD_HSYNC QTIMER1_TIMER2 FLEXCAN1_TX LPSPI4_SDO FLEXIO2_FLEXIO02 GPIO2_IO02 SEMC_CSX03 ENET2_1588_EVENT0_OUT ~ ~ + D12 = PB1 // [B0_01]: LCD_ENABLE QTIMER1_TIMER1 MQS_LEFT LPSPI4_SDI FLEXIO2_FLEXIO01 GPIO2_IO01 SEMC_CSX02 ENET2_MDIO ~ ~ + D13 = PB3 // [B0_03]: LCD_VSYNC QTIMER2_TIMER0 FLEXCAN1_RX LPSPI4_SCK FLEXIO2_FLEXIO03 GPIO2_IO03 WDOG2_RESET_B_DEB ENET2_1588_EVENT0_IN ~ ~ + D14 = PA18 // [AD_B1_02]: USB_OTG1_ID QTIMER3_TIMER2 LPUART2_TX SPDIF_OUT ENET_1588_EVENT2_OUT GPIO1_IO18 USDHC1_CD_B KPP_ROW06 GPT2_CLK FLEXIO3_FLEXIO02 + D15 = PA19 // [AD_B1_03]: USB_OTG1_OC QTIMER3_TIMER3 LPUART2_RX SPDIF_IN ENET_1588_EVENT2_IN GPIO1_IO19 USDHC2_CD_B KPP_COL06 GPT2_CAPTURE1 FLEXIO3_FLEXIO03 + D16 = PA23 // [AD_B1_07]: FLEXSPIB_DATA00 LPI2C3_SCL LPUART3_RX SPDIF_EXT_CLK CSI_HSYNC GPIO1_IO23 USDHC2_DATA3 KPP_COL04 GPT2_COMPARE3 FLEXIO3_FLEXIO07 + D17 = PA22 // [AD_B1_06]: FLEXSPIB_DATA01 LPI2C3_SDA LPUART3_TX SPDIF_LOCK CSI_VSYNC GPIO1_IO22 USDHC2_DATA2 KPP_ROW04 GPT2_COMPARE2 FLEXIO3_FLEXIO06 + D18 = PA17 // [AD_B1_01]: USB_OTG1_PWR QTIMER3_TIMER1 LPUART2_RTS_B LPI2C1_SDA CCM_PMIC_READY GPIO1_IO17 USDHC1_VSELECT KPP_COL07 ENET2_1588_EVENT0_IN FLEXIO3_FLEXIO01 + D19 = PA16 // [AD_B1_00]: USB_OTG2_ID QTIMER3_TIMER0 LPUART2_CTS_B LPI2C1_SCL WDOG1_B GPIO1_IO16 USDHC1_WP KPP_ROW07 ENET2_1588_EVENT0_OUT FLEXIO3_FLEXIO00 + D20 = PA26 // [AD_B1_10]: FLEXSPIA_DATA03 WDOG1_B LPUART8_TX SAI1_RX_SYNC CSI_DATA07 GPIO1_IO26 USDHC2_WP KPP_ROW02 ENET2_1588_EVENT1_OUT FLEXIO3_FLEXIO10 + D21 = PA27 // [AD_B1_11]: FLEXSPIA_DATA02 EWM_OUT_B LPUART8_RX SAI1_RX_BCLK CSI_DATA06 GPIO1_IO27 USDHC2_RESET_B KPP_COL02 ENET2_1588_EVENT1_IN FLEXIO3_FLEXIO11 + D22 = PA24 // [AD_B1_08]: FLEXSPIA_SS1_B FLEXPWM4_PWMA00 FLEXCAN1_TX CCM_PMIC_READY CSI_DATA09 GPIO1_IO24 USDHC2_CMD KPP_ROW03 FLEXIO3_FLEXIO08 ~ + D23 = PA25 // [AD_B1_09]: FLEXSPIA_DQS FLEXPWM4_PWMA01 FLEXCAN1_RX SAI1_MCLK CSI_DATA08 GPIO1_IO25 USDHC2_CLK KPP_COL03 FLEXIO3_FLEXIO09 ~ + D24 = PA12 // [AD_B0_12]: LPI2C4_SCL CCM_PMIC_READY LPUART1_TX WDOG2_WDOG_B FLEXPWM1_PWMX02 GPIO1_IO12 ENET_1588_EVENT1_OUT NMI_GLUE_NMI ~ ~ + D25 = PA13 // [AD_B0_13]: LPI2C4_SDA GPT1_CLK LPUART1_RX EWM_OUT_B FLEXPWM1_PWMX03 GPIO1_IO13 ENET_1588_EVENT1_IN REF_CLK_24M ~ ~ + D26 = PA30 // [AD_B1_14]: FLEXSPIA_SCLK ACMP_OUT02 LPSPI3_SDO SAI1_TX_BCLK CSI_DATA03 GPIO1_IO30 USDHC2_DATA6 KPP_ROW00 ENET2_1588_EVENT3_OUT FLEXIO3_FLEXIO14 + D27 = PA31 // [AD_B1_15]: FLEXSPIA_SS0_B ACMP_OUT03 LPSPI3_SCK SAI1_TX_SYNC CSI_DATA02 GPIO1_IO31 USDHC2_DATA7 KPP_COL00 ENET2_1588_EVENT3_IN FLEXIO3_FLEXIO15 + D28 = PC18 // [EMC_32]: SEMC_DATA10 FLEXPWM3_PWMB01 LPUART7_RX CCM_PMIC_RDY CSI_DATA21 GPIO3_IO18 ENET2_TX_EN ~ ~ ~ + D29 = PD31 // [EMC_31]: SEMC_DATA09 FLEXPWM3_PWMA01 LPUART7_TX LPSPI1_PCS1 CSI_DATA22 GPIO4_IO31 ENET2_TDATA01 ~ ~ ~ + D30 = PC23 // [EMC_37]: SEMC_DATA15 XBAR1_IN23 GPT1_COMPARE3 SAI3_MCLK CSI_DATA16 GPIO3_IO23 USDHC2_WP ENET2_RX_EN FLEXCAN3_RX ~ + D31 = PC22 // [EMC_36]: SEMC_DATA14 XBAR1_IN22 GPT1_COMPARE2 SAI3_TX_DATA CSI_DATA17 GPIO3_IO22 USDHC1_WP ENET2_RDATA01 FLEXCAN3_TX ~ + D32 = PB12 // [B0_12]: LCD_DATA08 XBAR1_INOUT10 ARM_TRACE_CLK SAI1_TX_DATA01 FLEXIO2_FLEXIO12 GPIO2_IO12 SRC_BOOT_CFG08 ENET2_TDATA00 ~ ~ + D33 = PD7 // [EMC_07]: SEMC_DATA07 FLEXPWM2_PWMB00 SAI2_MCLK XBAR1_INOUT09 FLEXIO1_FLEXIO07 GPIO4_IO07 ~ ~ ~ ~ + D34 = PC15 // [SD_B0_03]: USDHC1_DATA1 FLEXPWM1_PWMB01 LPUART8_RTS_B XBAR1_INOUT07 LPSPI1_SDI GPIO3_IO15 ENET2_RDATA00 SEMC_CLK6 ~ ~ + D35 = PC14 // [SD_B0_02]: USDHC1_DATA0 FLEXPWM1_PWMA01 LPUART8_CTS_B XBAR1_INOUT06 LPSPI1_SDO GPIO3_IO14 ENET2_RX_ER SEMC_CLK5 ~ ~ + D36 = PC13 // [SD_B0_01]: USDHC1_CLK FLEXPWM1_PWMB00 LPI2C3_SDA XBAR1_INOUT05 LPSPI1_PCS0 GPIO3_IO13 FLEXSPIB_SS1_B ENET2_TX_CLK ENET2_REF_CLK2 ~ + D37 = PC12 // [SD_B0_00]: USDHC1_CMD FLEXPWM1_PWMA00 LPI2C3_SCL XBAR1_INOUT04 LPSPI1_SCK GPIO3_IO12 FLEXSPIA_SS1_B ENET2_TX_EN SEMC_DQS4 ~ + D38 = PC17 // [SD_B0_05]: USDHC1_DATA3 FLEXPWM1_PWMB02 LPUART8_RX XBAR1_INOUT09 FLEXSPIB_DQS GPIO3_IO17 CCM_CLKO2 ENET2_RX_EN ~ ~ + D39 = PC16 // [SD_B0_04]: USDHC1_DATA2 FLEXPWM1_PWMA02 LPUART8_TX XBAR1_INOUT08 FLEXSPIB_SS0_B GPIO3_IO16 CCM_CLKO1 ENET2_RDATA01 ~ ~ +) + +// Analog pins +const ( + // = Pin // Dig | [Pad] {Ch} + A0 = PA18 // D14 | [AD_B1_02] {7} + A1 = PA19 // D15 | [AD_B1_03] {8} + A2 = PA23 // D16 | [AD_B1_07] {12} + A3 = PA22 // D17 | [AD_B1_06] {11} + A4 = PA17 // D18 | [AD_B1_01] {6} + A5 = PA16 // D19 | [AD_B1_00] {5} + A6 = PA26 // D20 | [AD_B1_10] {15} + A7 = PA27 // D21 | [AD_B1_11] {0} + A8 = PA24 // D22 | [AD_B1_08] {13} + A9 = PA25 // D23 | [AD_B1_09] {14} + A10 = PA12 // D24 | [AD_B0_12] {1} + A11 = PA13 // D25 | [AD_B0_13] {2} + A12 = PA30 // D26 | [AD_B1_14] {128+3} + A13 = PA31 // D27 | [AD_B1_15] {128+4} +) + +func init() { + initLED() + initUART() + initSPI() + initI2C() +} + +// -- LEDs --------------------------------------------------------------------- + +const ( + NUM_BOARD_LED = 1 + + LED_BUILTIN = D13 + LED = LED_BUILTIN +) + +func initLED() {} + +// -- UART --------------------------------------------------------------------- + +const ( + // #===========#===========#=============#===========#=============# + // | Interface | Hardware | Clock(Freq) | RX/TX Pin | RX/TX AltFn | + // #===========#===========#=============#===========#=============# + // | UART1 | LPUART6 | OSC(24 MHz) | D0/D1 | 2/2 | + // | UART2 | LPUART4 | OSC(24 MHz) | D7/D8 | 2/2 | + // | UART3 | LPUART2 | OSC(24 MHz) | D15/D14 | 2/2 | + // | UART4 | LPUART3 | OSC(24 MHz) | D16/D17 | 2/2 | + // | UART5 | LPUART8 | OSC(24 MHz) | D21/D20 | 2/2 | + // | UART6 | LPUART1 | OSC(24 MHz) | D25/D24 | 2/2 | + // | UART7 | LPUART7 | OSC(24 MHz) | D28/D29 | 2/2 | + // #===========#===========#=============#===========#=============# + NUM_UART_INTERFACES = 7 + + UART1_RX_PIN = D0 + UART1_TX_PIN = D1 + + UART2_RX_PIN = D7 + UART2_TX_PIN = D8 + + UART3_RX_PIN = D15 + UART3_TX_PIN = D14 + + UART4_RX_PIN = D16 + UART4_TX_PIN = D17 + + UART5_RX_PIN = D21 + UART5_TX_PIN = D20 + + UART6_RX_PIN = D25 + UART6_TX_PIN = D24 + + UART7_RX_PIN = D28 + UART7_TX_PIN = D29 + + UART_RX_PIN = UART1_RX_PIN + UART_TX_PIN = UART1_TX_PIN +) + +func initUART() {} + +// -- SPI ---------------------------------------------------------------------- + +const ( + // #===========#==========#===================#===========================# + // | Interface | Hardware | Clock(Freq) | SDI/SDO/SCK/CS : Alt | + // #===========#==========#===================#=================-=========# + // | SPI1 | LPSPI4 | PLL3PFD1(130 MHz) | D12/D11/D13/D10 : 3/3/3/3 | + // | SPI2 | LPSPI3 | PLL3PFD1(130 MHz) | D1/D26/D27/D0 : 7/2/2/7 | + // | SPI3 | LPSPI1 | PLL3PFD1(130 MHz) | D34/D35/D37/D36 : 4/4/4/4 | + // #===========#==========#===================#=================-=========# + NUM_SPI_INTERFACES = 3 + + SPI1_SDI_PIN = D12 + SPI1_SDO_PIN = D11 + SPI1_SCK_PIN = D13 + SPI1_CS_PIN = D10 + + SPI2_SDI_PIN = D1 + SPI2_SDO_PIN = D26 + SPI2_SCK_PIN = D27 + SPI2_CS_PIN = D0 + + SPI3_SDI_PIN = D34 + SPI3_SDO_PIN = D35 + SPI3_SCK_PIN = D37 + SPI3_CS_PIN = D36 + + SPI_SDI_PIN = SPI1_SDI_PIN + SPI_SDO_PIN = SPI1_SDO_PIN + SPI_SCK_PIN = SPI1_SCK_PIN + SPI_CS_PIN = SPI1_CS_PIN +) + +func initSPI() {} + +// -- I2C ---------------------------------------------------------------------- + +const ( + NUM_I2C_INTERFACES = 3 +) + +func initI2C() {} diff --git a/src/machine/machine_mimxrt1062.go b/src/machine/machine_mimxrt1062.go new file mode 100644 index 00000000..6fe0639f --- /dev/null +++ b/src/machine/machine_mimxrt1062.go @@ -0,0 +1,591 @@ +// +build mimxrt1062 + +package machine + +import ( + "device/nxp" + "runtime/volatile" +) + +// Peripheral abstraction layer for the MIMXRT1062 + +func CPUFrequency() uint32 { + return 600000000 +} + +type PinMode uint8 + +// muxSelect is yet another level of indirection required to connect pins in an +// alternate function state to a desired peripheral (since more than one pin can +// provide a given alternate function). +// +// Once a pin is configured with a given alternate function mode, the IOMUXC +// device must then be configured to select which alternate function pin to +// route to the desired peripheral. +// +// The reference manual refers to this functionality as a "Daisy Chain". The +// associated docs are found in the i.MX RT1060 Processor Reference Manual: +// "Chapter 11.3.3 Daisy chain - multi pads driving same module input pin" +type muxSelect struct { + mux uint8 // AF mux selection (NOT a Pin type) + sel *volatile.Register32 // AF selection register +} + +// connect configures the IOMUXC controller to route a given pin with alternate +// function to a desired peripheral (see godoc comments on type muxSelect). +func (s muxSelect) connect() { + s.sel.Set(uint32(s.mux)) +} + +const ( + // GPIO + PinInput PinMode = iota + PinInputPullUp + PinInputPullDown + PinOutput + PinOutputOpenDrain + PinDisable +) + +// Configure sets the GPIO pad and pin properties, and selects the appropriate +// alternate function, for a given Pin and PinConfig. +func (p Pin) Configure(config PinConfig) { + var ( + // padSRE = uint32(0x01 << 0) + padDSE = func(n uint32) uint32 { return (n & 0x07) << 3 } + // padSPD = func(n uint32) uint32 { return (n & 0x03) << 6 } + padODE = uint32(0x01 << 11) + padPKE = uint32(0x01 << 12) + padPUE = uint32(0x01 << 13) + padPUP = func(n uint32) uint32 { return (n & 0x03) << 14 } + padHYS = uint32(0x01 << 16) + ) + + _, gpio := p.getGPIO() // use fast GPIO for all pins + pad, mux := p.getPad() + + // first configure the pad characteristics + switch config.Mode { + case PinInput: + gpio.GDIR.ClearBits(p.getMask()) + pad.Set(padDSE(7)) + + case PinInputPullUp: + gpio.GDIR.ClearBits(p.getMask()) + pad.Set(padDSE(7) | padPKE | padPUE | padPUP(3) | padHYS) + + case PinInputPullDown: + gpio.GDIR.ClearBits(p.getMask()) + pad.Set(padDSE(7) | padPKE | padPUE | padHYS) + + case PinOutput: + gpio.GDIR.SetBits(p.getMask()) + pad.Set(padDSE(7)) + + case PinOutputOpenDrain: + gpio.GDIR.SetBits(p.getMask()) + pad.Set(padDSE(7) | padODE) + + case PinDisable: + gpio.GDIR.ClearBits(p.getMask()) + pad.Set(padDSE(7) | padHYS) + } + + // then configure the alternate function mux + mux.Set(p.getMuxMode(config)) +} + +// getMuxMode acts as a callback from the `(Pin).Configure(PinMode)` routine to +// determine the alternate function setting for a given Pin and PinConfig. +// This value is used in the IOMUXC device's SW_MUX_CTL_PAD_GPIO_* registers. +func (p Pin) getMuxMode(config PinConfig) uint32 { + const forcePath = true // TODO: should be input parameter? + switch config.Mode { + + // GPIO + case PinInput, PinInputPullUp, PinInputPullDown, + PinOutput, PinOutputOpenDrain, PinDisable: + mode := uint32(0x5) // GPIO is always alternate function 5 + if forcePath { + mode |= 0x10 // SION bit + } + return mode + + default: + panic("machine: invalid pin mode") + } +} + +// Set changes the value of the GPIO pin. The pin must be configured as output. +func (p Pin) Set(value bool) { + _, gpio := p.getGPIO() // use fast GPIO for all pins + if value { + gpio.DR_SET.Set(p.getMask()) + } else { + gpio.DR_CLEAR.Set(p.getMask()) + } +} + +// Get returns the current value of a GPIO pin. +func (p Pin) Get() bool { + _, gpio := p.getGPIO() // use fast GPIO for all pins + return gpio.PSR.HasBits(p.getMask()) +} + +// From the i.MXRT1062 Processor Reference Manual (Chapter 12 - GPIO): +// +// | High-speed GPIOs exist in this device: +// | - GPIO1-5 are standard-speed GPIOs that run off the IPG_CLK_ROOT, while +// | GPIO6-9 are high-speed GPIOs that run at the AHB_CLK_ROOT frequency. +// | See the table "System Clocks, Gating, and Override" in CCM chapter. +// | - Regular GPIO and high speed GPIO are paired (GPIO1 and GPIO6 share the +// | same pins, GPIO2 and GPIO7 share, etc). The IOMUXC_GPR_GPR26-29 +// | registers are used to determine if the regular or high-speed GPIO +// | module is used for the GPIO pins on a given port. +// +// Therefore, we do not even use GPIO1-5 and instead use their high-speed +// partner for all pins. This is configured at startup in the runtime package +// (func initPins() in `runtime_mimxrt1062.go`). +// We cannot declare 32 pins for all available ports (GPIO1-9) anyway, since Pin +// is only uint8, and 9*32=288 > 256, so something has to be sacrificed. + +const numPorts, pinsPerPort = 4, 32 + +const ( + portA Pin = iota * pinsPerPort // GPIO1(6) + portB // GPIO2(7) + portC // GPIO3(8) + portD // GPIO4(9) +) + +const numPins = numPorts * pinsPerPort + +const ( + // [Pad]: Alt Func 0 Alt Func 1 Alt Func 2 Alt Func 3 Alt Func 4 Alt Func 5 Alt Func 6 Alt Func 7 Alt Func 8 Alt Func 9 + // ---------- --------------- --------------- ------------------- -------------------- -------------------- ----------- -------------------- -------------------- --------------------- ---------------- + PA0 = portA + 0 // [AD_B0_00]: FLEXPWM2_PWMA03 XBAR1_INOUT14 REF_CLK_32K USB_OTG2_ID LPI2C1_SCLS GPIO1_IO00 USDHC1_RESET_B LPSPI3_SCK ~ ~ + PA1 = portA + 1 // [AD_B0_01]: FLEXPWM2_PWMB03 XBAR1_INOUT15 REF_CLK_24M USB_OTG1_ID LPI2C1_SDAS GPIO1_IO01 EWM_OUT_B LPSPI3_SDO ~ ~ + PA2 = portA + 2 // [AD_B0_02]: FLEXCAN2_TX XBAR1_INOUT16 LPUART6_TX USB_OTG1_PWR FLEXPWM1_PWMX00 GPIO1_IO02 LPI2C1_HREQ LPSPI3_SDI ~ ~ + PA3 = portA + 3 // [AD_B0_03]: FLEXCAN2_RX XBAR1_INOUT17 LPUART6_RX USB_OTG1_OC FLEXPWM1_PWMX01 GPIO1_IO03 REF_CLK_24M LPSPI3_PCS0 ~ ~ + PA4 = portA + 4 // [AD_B0_04]: SRC_BOOT_MODE00 MQS_RIGHT ENET_TX_DATA03 SAI2_TX_SYNC CSI_DATA09 GPIO1_IO04 PIT_TRIGGER00 LPSPI3_PCS1 ~ ~ + PA5 = portA + 5 // [AD_B0_05]: SRC_BOOT_MODE01 MQS_LEFT ENET_TX_DATA02 SAI2_TX_BCLK CSI_DATA08 GPIO1_IO05 XBAR1_INOUT17 LPSPI3_PCS2 ~ ~ + PA6 = portA + 6 // [AD_B0_06]: JTAG_TMS GPT2_COMPARE1 ENET_RX_CLK SAI2_RX_BCLK CSI_DATA07 GPIO1_IO06 XBAR1_INOUT18 LPSPI3_PCS3 ~ ~ + PA7 = portA + 7 // [AD_B0_07]: JTAG_TCK GPT2_COMPARE2 ENET_TX_ER SAI2_RX_SYNC CSI_DATA06 GPIO1_IO07 XBAR1_INOUT19 ENET_1588_EVENT3_OUT ~ ~ + PA8 = portA + 8 // [AD_B0_08]: JTAG_MOD GPT2_COMPARE3 ENET_RX_DATA03 SAI2_RX_DATA CSI_DATA05 GPIO1_IO08 XBAR1_IN20 ENET_1588_EVENT3_IN ~ ~ + PA9 = portA + 9 // [AD_B0_09]: JTAG_TDI FLEXPWM2_PWMA03 ENET_RX_DATA02 SAI2_TX_DATA CSI_DATA04 GPIO1_IO09 XBAR1_IN21 GPT2_CLK SEMC_DQS4 ~ + PA10 = portA + 10 // [AD_B0_10]: JTAG_TDO FLEXPWM1_PWMA03 ENET_CRS SAI2_MCLK CSI_DATA03 GPIO1_IO10 XBAR1_IN22 ENET_1588_EVENT0_OUT FLEXCAN3_TX ARM_TRACE_SWO + PA11 = portA + 11 // [AD_B0_11]: JTAG_TRSTB FLEXPWM1_PWMB03 ENET_COL WDOG1_WDOG_B CSI_DATA02 GPIO1_IO11 XBAR1_IN23 ENET_1588_EVENT0_IN FLEXCAN3_RX SEMC_CLK6 + PA12 = portA + 12 // [AD_B0_12]: LPI2C4_SCL CCM_PMIC_READY LPUART1_TX WDOG2_WDOG_B FLEXPWM1_PWMX02 GPIO1_IO12 ENET_1588_EVENT1_OUT NMI_GLUE_NMI ~ ~ + PA13 = portA + 13 // [AD_B0_13]: LPI2C4_SDA GPT1_CLK LPUART1_RX EWM_OUT_B FLEXPWM1_PWMX03 GPIO1_IO13 ENET_1588_EVENT1_IN REF_CLK_24M ~ ~ + PA14 = portA + 14 // [AD_B0_14]: USB_OTG2_OC XBAR1_IN24 LPUART1_CTS_B ENET_1588_EVENT0_OUT CSI_VSYNC GPIO1_IO14 FLEXCAN2_TX FLEXCAN3_TX ~ ~ + PA15 = portA + 15 // [AD_B0_15]: USB_OTG2_PWR XBAR1_IN25 LPUART1_RTS_B ENET_1588_EVENT0_IN CSI_HSYNC GPIO1_IO15 FLEXCAN2_RX WDOG1_WDOG_RST_B_DEB FLEXCAN3_RX ~ + PA16 = portA + 16 // [AD_B1_00]: USB_OTG2_ID QTIMER3_TIMER0 LPUART2_CTS_B LPI2C1_SCL WDOG1_B GPIO1_IO16 USDHC1_WP KPP_ROW07 ENET2_1588_EVENT0_OUT FLEXIO3_FLEXIO00 + PA17 = portA + 17 // [AD_B1_01]: USB_OTG1_PWR QTIMER3_TIMER1 LPUART2_RTS_B LPI2C1_SDA CCM_PMIC_READY GPIO1_IO17 USDHC1_VSELECT KPP_COL07 ENET2_1588_EVENT0_IN FLEXIO3_FLEXIO01 + PA18 = portA + 18 // [AD_B1_02]: USB_OTG1_ID QTIMER3_TIMER2 LPUART2_TX SPDIF_OUT ENET_1588_EVENT2_OUT GPIO1_IO18 USDHC1_CD_B KPP_ROW06 GPT2_CLK FLEXIO3_FLEXIO02 + PA19 = portA + 19 // [AD_B1_03]: USB_OTG1_OC QTIMER3_TIMER3 LPUART2_RX SPDIF_IN ENET_1588_EVENT2_IN GPIO1_IO19 USDHC2_CD_B KPP_COL06 GPT2_CAPTURE1 FLEXIO3_FLEXIO03 + PA20 = portA + 20 // [AD_B1_04]: FLEXSPIB_DATA03 ENET_MDC LPUART3_CTS_B SPDIF_SR_CLK CSI_PIXCLK GPIO1_IO20 USDHC2_DATA0 KPP_ROW05 GPT2_CAPTURE2 FLEXIO3_FLEXIO04 + PA21 = portA + 21 // [AD_B1_05]: FLEXSPIB_DATA02 ENET_MDIO LPUART3_RTS_B SPDIF_OUT CSI_MCLK GPIO1_IO21 USDHC2_DATA1 KPP_COL05 GPT2_COMPARE1 FLEXIO3_FLEXIO05 + PA22 = portA + 22 // [AD_B1_06]: FLEXSPIB_DATA01 LPI2C3_SDA LPUART3_TX SPDIF_LOCK CSI_VSYNC GPIO1_IO22 USDHC2_DATA2 KPP_ROW04 GPT2_COMPARE2 FLEXIO3_FLEXIO06 + PA23 = portA + 23 // [AD_B1_07]: FLEXSPIB_DATA00 LPI2C3_SCL LPUART3_RX SPDIF_EXT_CLK CSI_HSYNC GPIO1_IO23 USDHC2_DATA3 KPP_COL04 GPT2_COMPARE3 FLEXIO3_FLEXIO07 + PA24 = portA + 24 // [AD_B1_08]: FLEXSPIA_SS1_B FLEXPWM4_PWMA00 FLEXCAN1_TX CCM_PMIC_READY CSI_DATA09 GPIO1_IO24 USDHC2_CMD KPP_ROW03 FLEXIO3_FLEXIO08 ~ + PA25 = portA + 25 // [AD_B1_09]: FLEXSPIA_DQS FLEXPWM4_PWMA01 FLEXCAN1_RX SAI1_MCLK CSI_DATA08 GPIO1_IO25 USDHC2_CLK KPP_COL03 FLEXIO3_FLEXIO09 ~ + PA26 = portA + 26 // [AD_B1_10]: FLEXSPIA_DATA03 WDOG1_B LPUART8_TX SAI1_RX_SYNC CSI_DATA07 GPIO1_IO26 USDHC2_WP KPP_ROW02 ENET2_1588_EVENT1_OUT FLEXIO3_FLEXIO10 + PA27 = portA + 27 // [AD_B1_11]: FLEXSPIA_DATA02 EWM_OUT_B LPUART8_RX SAI1_RX_BCLK CSI_DATA06 GPIO1_IO27 USDHC2_RESET_B KPP_COL02 ENET2_1588_EVENT1_IN FLEXIO3_FLEXIO11 + PA28 = portA + 28 // [AD_B1_12]: FLEXSPIA_DATA01 ACMP_OUT00 LPSPI3_PCS0 SAI1_RX_DATA00 CSI_DATA05 GPIO1_IO28 USDHC2_DATA4 KPP_ROW01 ENET2_1588_EVENT2_OUT FLEXIO3_FLEXIO12 + PA29 = portA + 29 // [AD_B1_13]: FLEXSPIA_DATA00 ACMP_OUT01 LPSPI3_SDI SAI1_TX_DATA00 CSI_DATA04 GPIO1_IO29 USDHC2_DATA5 KPP_COL01 ENET2_1588_EVENT2_IN FLEXIO3_FLEXIO13 + PA30 = portA + 30 // [AD_B1_14]: FLEXSPIA_SCLK ACMP_OUT02 LPSPI3_SDO SAI1_TX_BCLK CSI_DATA03 GPIO1_IO30 USDHC2_DATA6 KPP_ROW00 ENET2_1588_EVENT3_OUT FLEXIO3_FLEXIO14 + PA31 = portA + 31 // [AD_B1_15]: FLEXSPIA_SS0_B ACMP_OUT03 LPSPI3_SCK SAI1_TX_SYNC CSI_DATA02 GPIO1_IO31 USDHC2_DATA7 KPP_COL00 ENET2_1588_EVENT3_IN FLEXIO3_FLEXIO15 + + PB0 = portB + 0 // [B0_00]: LCD_CLK QTIMER1_TIMER0 MQS_RIGHT LPSPI4_PCS0 FLEXIO2_FLEXIO00 GPIO2_IO00 SEMC_CSX01 ENET2_MDC ~ ~ + PB1 = portB + 1 // [B0_01]: LCD_ENABLE QTIMER1_TIMER1 MQS_LEFT LPSPI4_SDI FLEXIO2_FLEXIO01 GPIO2_IO01 SEMC_CSX02 ENET2_MDIO ~ ~ + PB2 = portB + 2 // [B0_02]: LCD_HSYNC QTIMER1_TIMER2 FLEXCAN1_TX LPSPI4_SDO FLEXIO2_FLEXIO02 GPIO2_IO02 SEMC_CSX03 ENET2_1588_EVENT0_OUT ~ ~ + PB3 = portB + 3 // [B0_03]: LCD_VSYNC QTIMER2_TIMER0 FLEXCAN1_RX LPSPI4_SCK FLEXIO2_FLEXIO03 GPIO2_IO03 WDOG2_RESET_B_DEB ENET2_1588_EVENT0_IN ~ ~ + PB4 = portB + 4 // [B0_04]: LCD_DATA00 QTIMER2_TIMER1 LPI2C2_SCL ARM_TRACE0 FLEXIO2_FLEXIO04 GPIO2_IO04 SRC_BOOT_CFG00 ENET2_TDATA03 ~ ~ + PB5 = portB + 5 // [B0_05]: LCD_DATA01 QTIMER2_TIMER2 LPI2C2_SDA ARM_TRACE1 FLEXIO2_FLEXIO05 GPIO2_IO05 SRC_BOOT_CFG01 ENET2_TDATA02 ~ ~ + PB6 = portB + 6 // [B0_06]: LCD_DATA02 QTIMER3_TIMER0 FLEXPWM2_PWMA00 ARM_TRACE2 FLEXIO2_FLEXIO06 GPIO2_IO06 SRC_BOOT_CFG02 ENET2_RX_CLK ~ ~ + PB7 = portB + 7 // [B0_07]: LCD_DATA03 QTIMER3_TIMER1 FLEXPWM2_PWMB00 ARM_TRACE3 FLEXIO2_FLEXIO07 GPIO2_IO07 SRC_BOOT_CFG03 ENET2_TX_ER ~ ~ + PB8 = portB + 8 // [B0_08]: LCD_DATA04 QTIMER3_TIMER2 FLEXPWM2_PWMA01 LPUART3_TX FLEXIO2_FLEXIO08 GPIO2_IO08 SRC_BOOT_CFG04 ENET2_RDATA03 ~ ~ + PB9 = portB + 9 // [B0_09]: LCD_DATA05 QTIMER4_TIMER0 FLEXPWM2_PWMB01 LPUART3_RX FLEXIO2_FLEXIO09 GPIO2_IO09 SRC_BOOT_CFG05 ENET2_RDATA02 ~ ~ + PB10 = portB + 10 // [B0_10]: LCD_DATA06 QTIMER4_TIMER1 FLEXPWM2_PWMA02 SAI1_TX_DATA03 FLEXIO2_FLEXIO10 GPIO2_IO10 SRC_BOOT_CFG06 ENET2_CRS ~ ~ + PB11 = portB + 11 // [B0_11]: LCD_DATA07 QTIMER4_TIMER2 FLEXPWM2_PWMB02 SAI1_TX_DATA02 FLEXIO2_FLEXIO11 GPIO2_IO11 SRC_BOOT_CFG07 ENET2_COL ~ ~ + PB12 = portB + 12 // [B0_12]: LCD_DATA08 XBAR1_INOUT10 ARM_TRACE_CLK SAI1_TX_DATA01 FLEXIO2_FLEXIO12 GPIO2_IO12 SRC_BOOT_CFG08 ENET2_TDATA00 ~ ~ + PB13 = portB + 13 // [B0_13]: LCD_DATA09 XBAR1_INOUT11 ARM_TRACE_SWO SAI1_MCLK FLEXIO2_FLEXIO13 GPIO2_IO13 SRC_BOOT_CFG09 ENET2_TDATA01 ~ ~ + PB14 = portB + 14 // [B0_14]: LCD_DATA10 XBAR1_INOUT12 ARM_TXEV SAI1_RX_SYNC FLEXIO2_FLEXIO14 GPIO2_IO14 SRC_BOOT_CFG10 ENET2_TX_EN ~ ~ + PB15 = portB + 15 // [B0_15]: LCD_DATA11 XBAR1_INOUT13 ARM_RXEV SAI1_RX_BCLK FLEXIO2_FLEXIO15 GPIO2_IO15 SRC_BOOT_CFG11 ENET2_TX_CLK ENET2_REF_CLK2 ~ + PB16 = portB + 16 // [B1_00]: LCD_DATA12 XBAR1_INOUT14 LPUART4_TX SAI1_RX_DATA00 FLEXIO2_FLEXIO16 GPIO2_IO16 FLEXPWM1_PWMA03 ENET2_RX_ER FLEXIO3_FLEXIO16 ~ + PB17 = portB + 17 // [B1_01]: LCD_DATA13 XBAR1_INOUT15 LPUART4_RX SAI1_TX_DATA00 FLEXIO2_FLEXIO17 GPIO2_IO17 FLEXPWM1_PWMB03 ENET2_RDATA00 FLEXIO3_FLEXIO17 ~ + PB18 = portB + 18 // [B1_02]: LCD_DATA14 XBAR1_INOUT16 LPSPI4_PCS2 SAI1_TX_BCLK FLEXIO2_FLEXIO18 GPIO2_IO18 FLEXPWM2_PWMA03 ENET2_RDATA01 FLEXIO3_FLEXIO18 ~ + PB19 = portB + 19 // [B1_03]: LCD_DATA15 XBAR1_INOUT17 LPSPI4_PCS1 SAI1_TX_SYNC FLEXIO2_FLEXIO19 GPIO2_IO19 FLEXPWM2_PWMB03 ENET2_RX_EN FLEXIO3_FLEXIO19 ~ + PB20 = portB + 20 // [B1_04]: LCD_DATA16 LPSPI4_PCS0 CSI_DATA15 ENET_RX_DATA00 FLEXIO2_FLEXIO20 GPIO2_IO20 GPT1_CLK FLEXIO3_FLEXIO20 ~ ~ + PB21 = portB + 21 // [B1_05]: LCD_DATA17 LPSPI4_SDI CSI_DATA14 ENET_RX_DATA01 FLEXIO2_FLEXIO21 GPIO2_IO21 GPT1_CAPTURE1 FLEXIO3_FLEXIO21 ~ ~ + PB22 = portB + 22 // [B1_06]: LCD_DATA18 LPSPI4_SDO CSI_DATA13 ENET_RX_EN FLEXIO2_FLEXIO22 GPIO2_IO22 GPT1_CAPTURE2 FLEXIO3_FLEXIO22 ~ ~ + PB23 = portB + 23 // [B1_07]: LCD_DATA19 LPSPI4_SCK CSI_DATA12 ENET_TX_DATA00 FLEXIO2_FLEXIO23 GPIO2_IO23 GPT1_COMPARE1 FLEXIO3_FLEXIO23 ~ ~ + PB24 = portB + 24 // [B1_08]: LCD_DATA20 QTIMER1_TIMER3 CSI_DATA11 ENET_TX_DATA01 FLEXIO2_FLEXIO24 GPIO2_IO24 FLEXCAN2_TX GPT1_COMPARE2 FLEXIO3_FLEXIO24 ~ + PB25 = portB + 25 // [B1_09]: LCD_DATA21 QTIMER2_TIMER3 CSI_DATA10 ENET_TX_EN FLEXIO2_FLEXIO25 GPIO2_IO25 FLEXCAN2_RX GPT1_COMPARE3 FLEXIO3_FLEXIO25 ~ + PB26 = portB + 26 // [B1_10]: LCD_DATA22 QTIMER3_TIMER3 CSI_DATA00 ENET_TX_CLK FLEXIO2_FLEXIO26 GPIO2_IO26 ENET_REF_CLK FLEXIO3_FLEXIO26 ~ ~ + PB27 = portB + 27 // [B1_11]: LCD_DATA23 QTIMER4_TIMER3 CSI_DATA01 ENET_RX_ER FLEXIO2_FLEXIO27 GPIO2_IO27 LPSPI4_PCS3 FLEXIO3_FLEXIO27 ~ ~ + PB28 = portB + 28 // [B1_12]: LPUART5_TX CSI_PIXCLK ENET_1588_EVENT0_IN FLEXIO2_FLEXIO28 GPIO2_IO28 USDHC1_CD_B FLEXIO3_FLEXIO28 ~ ~ ~ + PB29 = portB + 29 // [B1_13]: WDOG1_B LPUART5_RX CSI_VSYNC ENET_1588_EVENT0_OUT FLEXIO2_FLEXIO29 GPIO2_IO29 USDHC1_WP SEMC_DQS4 FLEXIO3_FLEXIO29 ~ + PB30 = portB + 30 // [B1_14]: ENET_MDC FLEXPWM4_PWMA02 CSI_HSYNC XBAR1_IN02 FLEXIO2_FLEXIO30 GPIO2_IO30 USDHC1_VSELECT ENET2_TDATA00 FLEXIO3_FLEXIO30 ~ + PB31 = portB + 31 // [B1_15]: ENET_MDIO FLEXPWM4_PWMA03 CSI_MCLK XBAR1_IN03 FLEXIO2_FLEXIO31 GPIO2_IO31 USDHC1_RESET_B ENET2_TDATA01 FLEXIO3_FLEXIO31 ~ + + PC0 = portC + 0 // [SD_B1_00]: USDHC2_DATA3 FLEXSPIB_DATA03 FLEXPWM1_PWMA03 SAI1_TX_DATA03 LPUART4_TX GPIO3_IO00 SAI3_RX_DATA ~ ~ ~ + PC1 = portC + 1 // [SD_B1_01]: USDHC2_DATA2 FLEXSPIB_DATA02 FLEXPWM1_PWMB03 SAI1_TX_DATA02 LPUART4_RX GPIO3_IO01 SAI3_TX_DATA ~ ~ ~ + PC2 = portC + 2 // [SD_B1_02]: USDHC2_DATA1 FLEXSPIB_DATA01 FLEXPWM2_PWMA03 SAI1_TX_DATA01 FLEXCAN1_TX GPIO3_IO02 CCM_WAIT SAI3_TX_SYNC ~ ~ + PC3 = portC + 3 // [SD_B1_03]: USDHC2_DATA0 FLEXSPIB_DATA00 FLEXPWM2_PWMB03 SAI1_MCLK FLEXCAN1_RX GPIO3_IO03 CCM_PMIC_READY SAI3_TX_BCLK ~ ~ + PC4 = portC + 4 // [SD_B1_04]: USDHC2_CLK FLEXSPIB_SCLK LPI2C1_SCL SAI1_RX_SYNC FLEXSPIA_SS1_B GPIO3_IO04 CCM_STOP SAI3_MCLK ~ ~ + PC5 = portC + 5 // [SD_B1_05]: USDHC2_CMD FLEXSPIA_DQS LPI2C1_SDA SAI1_RX_BCLK FLEXSPIB_SS0_B GPIO3_IO05 SAI3_RX_SYNC ~ ~ ~ + PC6 = portC + 6 // [SD_B1_06]: USDHC2_RESET_B FLEXSPIA_SS0_B LPUART7_CTS_B SAI1_RX_DATA00 LPSPI2_PCS0 GPIO3_IO06 SAI3_RX_BCLK ~ ~ ~ + PC7 = portC + 7 // [SD_B1_07]: SEMC_CSX01 FLEXSPIA_SCLK LPUART7_RTS_B SAI1_TX_DATA00 LPSPI2_SCK GPIO3_IO07 ~ ~ ~ ~ + PC8 = portC + 8 // [SD_B1_08]: USDHC2_DATA4 FLEXSPIA_DATA00 LPUART7_TX SAI1_TX_BCLK LPSPI2_SD0 GPIO3_IO08 SEMC_CSX02 ~ ~ ~ + PC9 = portC + 9 // [SD_B1_09]: USDHC2_DATA5 FLEXSPIA_DATA01 LPUART7_RX SAI1_TX_SYNC LPSPI2_SDI GPIO3_IO09 ~ ~ ~ ~ + PC10 = portC + 10 // [SD_B1_10]: USDHC2_DATA6 FLEXSPIA_DATA02 LPUART2_RX LPI2C2_SDA LPSPI2_PCS2 GPIO3_IO10 ~ ~ ~ ~ + PC11 = portC + 11 // [SD_B1_11]: USDHC2_DATA7 FLEXSPIA_DATA03 LPUART2_TX LPI2C2_SCL LPSPI2_PCS3 GPIO3_IO11 ~ ~ ~ ~ + PC12 = portC + 12 // [SD_B0_00]: USDHC1_CMD FLEXPWM1_PWMA00 LPI2C3_SCL XBAR1_INOUT04 LPSPI1_SCK GPIO3_IO12 FLEXSPIA_SS1_B ENET2_TX_EN SEMC_DQS4 ~ + PC13 = portC + 13 // [SD_B0_01]: USDHC1_CLK FLEXPWM1_PWMB00 LPI2C3_SDA XBAR1_INOUT05 LPSPI1_PCS0 GPIO3_IO13 FLEXSPIB_SS1_B ENET2_TX_CLK ENET2_REF_CLK2 ~ + PC14 = portC + 14 // [SD_B0_02]: USDHC1_DATA0 FLEXPWM1_PWMA01 LPUART8_CTS_B XBAR1_INOUT06 LPSPI1_SDO GPIO3_IO14 ENET2_RX_ER SEMC_CLK5 ~ ~ + PC15 = portC + 15 // [SD_B0_03]: USDHC1_DATA1 FLEXPWM1_PWMB01 LPUART8_RTS_B XBAR1_INOUT07 LPSPI1_SDI GPIO3_IO15 ENET2_RDATA00 SEMC_CLK6 ~ ~ + PC16 = portC + 16 // [SD_B0_04]: USDHC1_DATA2 FLEXPWM1_PWMA02 LPUART8_TX XBAR1_INOUT08 FLEXSPIB_SS0_B GPIO3_IO16 CCM_CLKO1 ENET2_RDATA01 ~ ~ + PC17 = portC + 17 // [SD_B0_05]: USDHC1_DATA3 FLEXPWM1_PWMB02 LPUART8_RX XBAR1_INOUT09 FLEXSPIB_DQS GPIO3_IO17 CCM_CLKO2 ENET2_RX_EN ~ ~ + PC18 = portC + 18 // [EMC_32]: SEMC_DATA10 FLEXPWM3_PWMB01 LPUART7_RX CCM_PMIC_RDY CSI_DATA21 GPIO3_IO18 ENET2_TX_EN ~ ~ ~ + PC19 = portC + 19 // [EMC_33]: SEMC_DATA11 FLEXPWM3_PWMA02 USDHC1_RESET_B SAI3_RX_DATA CSI_DATA20 GPIO3_IO19 ENET2_TX_CLK ENET2_REF_CLK2 ~ ~ + PC20 = portC + 20 // [EMC_34]: SEMC_DATA12 FLEXPWM3_PWMB02 USDHC1_VSELECT SAI3_RX_SYNC CSI_DATA19 GPIO3_IO20 ENET2_RX_ER ~ ~ ~ + PC21 = portC + 21 // [EMC_35]: SEMC_DATA13 XBAR1_INOUT18 GPT1_COMPARE1 SAI3_RX_BCLK CSI_DATA18 GPIO3_IO21 USDHC1_CD_B ENET2_RDATA00 ~ ~ + PC22 = portC + 22 // [EMC_36]: SEMC_DATA14 XBAR1_IN22 GPT1_COMPARE2 SAI3_TX_DATA CSI_DATA17 GPIO3_IO22 USDHC1_WP ENET2_RDATA01 FLEXCAN3_TX ~ + PC23 = portC + 23 // [EMC_37]: SEMC_DATA15 XBAR1_IN23 GPT1_COMPARE3 SAI3_MCLK CSI_DATA16 GPIO3_IO23 USDHC2_WP ENET2_RX_EN FLEXCAN3_RX ~ + PC24 = portC + 24 // [EMC_38]: SEMC_DM01 FLEXPWM1_PWMA03 LPUART8_TX SAI3_TX_BCLK CSI_FIELD GPIO3_IO24 USDHC2_VSELECT ENET2_MDC ~ ~ + PC25 = portC + 25 // [EMC_39]: SEMC_DQS FLEXPWM1_PWMB03 LPUART8_RX SAI3_TX_SYNC WDOG1_WDOG_B GPIO3_IO25 USDHC2_CD_B ENET2_MDIO SEMC_DQS4 ~ + PC26 = portC + 26 // [EMC_40]: SEMC_RDY GPT2_CAPTURE2 LPSPI1_PCS2 USB_OTG2_OC ENET_MDC GPIO3_IO26 USDHC2_RESET_B SEMC_CLK5 ~ ~ + PC27 = portC + 27 // [EMC_41]: SEMC_CSX00 GPT2_CAPTURE1 LPSPI1_PCS3 USB_OTG2_PWR ENET_MDIO GPIO3_IO27 USDHC1_VSELECT ~ ~ ~ + _ = portC + 28 // + _ = portC + 29 // + _ = portC + 30 // + _ = portC + 31 // + + PD0 = portD + 0 // [EMC_00]: SEMC_DATA00 FLEXPWM4_PWMA00 LPSPI2_SCK XBAR1_XBAR_IN02 FLEXIO1_FLEXIO00 GPIO4_IO00 ~ ~ ~ ~ + PD1 = portD + 1 // [EMC_01]: SEMC_DATA01 FLEXPWM4_PWMB00 LPSPI2_PCS0 XBAR1_IN03 FLEXIO1_FLEXIO01 GPIO4_IO01 ~ ~ ~ ~ + PD2 = portD + 2 // [EMC_02]: SEMC_DATA02 FLEXPWM4_PWMA01 LPSPI2_SDO XBAR1_INOUT04 FLEXIO1_FLEXIO02 GPIO4_IO02 ~ ~ ~ ~ + PD3 = portD + 3 // [EMC_03]: SEMC_DATA03 FLEXPWM4_PWMB01 LPSPI2_SDI XBAR1_INOUT05 FLEXIO1_FLEXIO03 GPIO4_IO03 ~ ~ ~ ~ + PD4 = portD + 4 // [EMC_04]: SEMC_DATA04 FLEXPWM4_PWMA02 SAI2_TX_DATA XBAR1_INOUT06 FLEXIO1_FLEXIO04 GPIO4_IO04 ~ ~ ~ ~ + PD5 = portD + 5 // [EMC_05]: SEMC_DATA05 FLEXPWM4_PWMB02 SAI2_TX_SYNC XBAR1_INOUT07 FLEXIO1_FLEXIO05 GPIO4_IO05 ~ ~ ~ ~ + PD6 = portD + 6 // [EMC_06]: SEMC_DATA06 FLEXPWM2_PWMA00 SAI2_TX_BCLK XBAR1_INOUT08 FLEXIO1_FLEXIO06 GPIO4_IO06 ~ ~ ~ ~ + PD7 = portD + 7 // [EMC_07]: SEMC_DATA07 FLEXPWM2_PWMB00 SAI2_MCLK XBAR1_INOUT09 FLEXIO1_FLEXIO07 GPIO4_IO07 ~ ~ ~ ~ + PD8 = portD + 8 // [EMC_08]: SEMC_DM00 FLEXPWM2_PWMA01 SAI2_RX_DATA XBAR1_INOUT17 FLEXIO1_FLEXIO08 GPIO4_IO08 ~ ~ ~ ~ + PD9 = portD + 9 // [EMC_09]: SEMC_ADDR00 FLEXPWM2_PWMB01 SAI2_RX_SYNC FLEXCAN2_TX FLEXIO1_FLEXIO09 GPIO4_IO09 FLEXSPI2_B_SS1_B ~ ~ ~ + PD10 = portD + 10 // [EMC_10]: SEMC_ADDR01 FLEXPWM2_PWMA02 SAI2_RX_BCLK FLEXCAN2_RX FLEXIO1_FLEXIO10 GPIO4_IO10 FLEXSPI2_B_SS0_B ~ ~ ~ + PD11 = portD + 11 // [EMC_11]: SEMC_ADDR02 FLEXPWM2_PWMB02 LPI2C4_SDA USDHC2_RESET_B FLEXIO1_FLEXIO11 GPIO4_IO11 FLEXSPI2_B_DQS ~ ~ ~ + PD12 = portD + 12 // [EMC_12]: SEMC_ADDR03 XBAR1_IN24 LPI2C4_SCL USDHC1_WP FLEXPWM1_PWMA03 GPIO4_IO12 FLEXSPI2_B_SCLK ~ ~ ~ + PD13 = portD + 13 // [EMC_13]: SEMC_ADDR04 XBAR1_IN25 LPUART3_TX MQS_RIGHT FLEXPWM1_PWMB03 GPIO4_IO13 FLEXSPI2_B_DATA00 ~ ~ ~ + PD14 = portD + 14 // [EMC_14]: SEMC_ADDR05 XBAR1_INOUT19 LPUART3_RX MQS_LEFT LPSPI2_PCS1 GPIO4_IO14 FLEXSPI2_B_DATA01 ~ ~ ~ + PD15 = portD + 15 // [EMC_15]: SEMC_ADDR06 XBAR1_IN20 LPUART3_CTS_B SPDIF_OUT QTIMER3_TIMER0 GPIO4_IO15 FLEXSPI2_B_DATA02 ~ ~ ~ + PD16 = portD + 16 // [EMC_16]: SEMC_ADDR07 XBAR1_IN21 LPUART3_RTS_B SPDIF_IN QTIMER3_TIMER1 GPIO4_IO16 FLEXSPI2_B_DATA03 ~ ~ ~ + PD17 = portD + 17 // [EMC_17]: SEMC_ADDR08 FLEXPWM4_PWMA03 LPUART4_CTS_B FLEXCAN1_TX QTIMER3_TIMER2 GPIO4_IO17 ~ ~ ~ ~ + PD18 = portD + 18 // [EMC_18]: SEMC_ADDR09 FLEXPWM4_PWMB03 LPUART4_RTS_B FLEXCAN1_RX QTIMER3_TIMER3 GPIO4_IO18 SNVS_VIO_5_CTL ~ ~ ~ + PD19 = portD + 19 // [EMC_19]: SEMC_ADDR11 FLEXPWM2_PWMA03 LPUART4_TX ENET_RDATA01 QTIMER2_TIMER0 GPIO4_IO19 SNVS_VIO_5 ~ ~ ~ + PD20 = portD + 20 // [EMC_20]: SEMC_ADDR12 FLEXPWM2_PWMB03 LPUART4_RX ENET_RDATA00 QTIMER2_TIMER1 GPIO4_IO20 ~ ~ ~ ~ + PD21 = portD + 21 // [EMC_21]: SEMC_BA0 FLEXPWM3_PWMA03 LPI2C3_SDA ENET_TDATA01 QTIMER2_TIMER2 GPIO4_IO21 ~ ~ ~ ~ + PD22 = portD + 22 // [EMC_22]: SEMC_BA1 FLEXPWM3_PWMB03 LPI2C3_SCL ENET_TDATA00 QTIMER2_TIMER3 GPIO4_IO22 FLEXSPI2_A_SS1_B ~ ~ ~ + PD23 = portD + 23 // [EMC_23]: SEMC_ADDR10 FLEXPWM1_PWMA00 LPUART5_TX ENET_RX_EN GPT1_CAPTURE2 GPIO4_IO23 FLEXSPI2_A_DQS ~ ~ ~ + PD24 = portD + 24 // [EMC_24]: SEMC_CAS FLEXPWM1_PWMB00 LPUART5_RX ENET_TX_EN GPT1_CAPTURE1 GPIO4_IO24 FLEXSPI2_A_SS0_B ~ ~ ~ + PD25 = portD + 25 // [EMC_25]: SEMC_RAS FLEXPWM1_PWMA01 LPUART6_TX ENET_TX_CLK ENET_REF_CLK GPIO4_IO25 FLEXSPI2_A_SCLK ~ ~ ~ + PD26 = portD + 26 // [EMC_26]: SEMC_CLK FLEXPWM1_PWMB01 LPUART6_RX ENET_RX_ER FLEXIO1_FLEXIO12 GPIO4_IO26 FLEXSPI2_A_DATA00 ~ ~ ~ + PD27 = portD + 27 // [EMC_27]: SEMC_CKE FLEXPWM1_PWMA02 LPUART5_RTS_B LPSPI1_SCK FLEXIO1_FLEXIO13 GPIO4_IO27 FLEXSPI2_A_DATA01 ~ ~ ~ + PD28 = portD + 28 // [EMC_28]: SEMC_WE FLEXPWM1_PWMB02 LPUART5_CTS_B LPSPI1_SDO FLEXIO1_FLEXIO14 GPIO4_IO28 FLEXSPI2_A_DATA02 ~ ~ ~ + PD29 = portD + 29 // [EMC_29]: SEMC_CS0 FLEXPWM3_PWMA00 LPUART6_RTS_B LPSPI1_SDI FLEXIO1_FLEXIO15 GPIO4_IO29 FLEXSPI2_A_DATA03 ~ ~ ~ + PD30 = portD + 30 // [EMC_30]: SEMC_DATA08 FLEXPWM3_PWMB00 LPUART6_CTS_B LPSPI1_PCS0 CSI_DATA23 GPIO4_IO30 ENET2_TDATA00 ~ ~ ~ + 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) getMask() uint32 { return uint32(1) << p.getPos() } +func (p Pin) getPort() Pin { return Pin(p/pinsPerPort) * pinsPerPort } + +// getGPIO returns both the normal (IPG_CLK_ROOT) and high-speed (AHB_CLK_ROOT) +// GPIO peripherals to which a given Pin is connected. +// +// Note that, currently, the device is configured to use high-speed GPIO for all +// pins (GPIO6-9), so the first return value should not be used (GPIO1-4). +// See the remarks and documentation reference in the comments preceding the +// const Pin definitions above. +func (p Pin) getGPIO() (norm *nxp.GPIO_Type, fast *nxp.GPIO_Type) { + switch p.getPort() { + case portA: + return nxp.GPIO1, nxp.GPIO6 + case portB: + return nxp.GPIO2, nxp.GPIO7 + case portC: + return nxp.GPIO3, nxp.GPIO8 + case portD: + return nxp.GPIO4, nxp.GPIO9 + default: + panic("machine: unknown port") + } +} + +// getPad returns both the pad and mux configration registers for a given Pin. +func (p Pin) getPad() (pad *volatile.Register32, mux *volatile.Register32) { + switch p.getPort() { + case portA: + switch p.getPos() { + case 0: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_00 + case 1: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_01 + case 2: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_02 + case 3: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_03 + case 4: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_04 + case 5: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_05 + case 6: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_06, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_06 + case 7: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_07, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_07 + case 8: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_08, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_08 + case 9: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_09, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_09 + case 10: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_10, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_10 + case 11: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_11, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_11 + case 12: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_12, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_12 + case 13: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_13, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_13 + case 14: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_14, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_14 + case 15: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_15, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_15 + case 16: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_00 + case 17: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_01 + case 18: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_02 + case 19: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_03 + case 20: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_04 + case 21: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_05 + case 22: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_06, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_06 + case 23: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_07, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_07 + case 24: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_08, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_08 + case 25: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_09, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_09 + case 26: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_10, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_10 + case 27: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_11, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_11 + case 28: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_12, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_12 + case 29: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_13, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_13 + case 30: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_14, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_14 + case 31: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_15, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_15 + } + case portB: + switch p.getPos() { + case 0: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_00 + case 1: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_01 + case 2: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_02 + case 3: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_03 + case 4: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_04 + case 5: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_05 + case 6: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_06, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_06 + case 7: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_07, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_07 + case 8: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_08, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_08 + case 9: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_09, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_09 + case 10: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_10, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_10 + case 11: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_11, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_11 + case 12: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_12, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_12 + case 13: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_13, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_13 + case 14: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_14, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_14 + case 15: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_15, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_15 + case 16: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_00 + case 17: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_01 + case 18: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_02 + case 19: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_03 + case 20: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_04 + case 21: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_05 + case 22: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_06, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_06 + case 23: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_07, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_07 + case 24: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_08, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_08 + case 25: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_09, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_09 + case 26: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_10, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_10 + case 27: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_11, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_11 + case 28: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_12, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_12 + case 29: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_13, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_13 + case 30: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_14, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_14 + case 31: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_15, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_15 + } + case portC: + switch p.getPos() { + case 0: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_00 + case 1: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_01 + case 2: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_02 + case 3: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_03 + case 4: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_04 + case 5: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_05 + case 6: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_06, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_06 + case 7: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_07, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_07 + case 8: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_08, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_08 + case 9: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_09, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_09 + case 10: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_10, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_10 + case 11: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_11, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_11 + case 12: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B0_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B0_00 + case 13: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B0_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B0_01 + case 14: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B0_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B0_02 + case 15: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B0_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B0_03 + case 16: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B0_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B0_04 + case 17: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B0_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B0_05 + case 18: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_32, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_32 + case 19: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_33, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_33 + case 20: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_34, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_34 + case 21: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_35, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_35 + case 22: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_36, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_36 + case 23: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_37, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_37 + case 24: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_38, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_38 + case 25: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_39, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_39 + case 26: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_40, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_40 + case 27: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_41, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_41 + case 28, 29, 30, 31: + } + case portD: + switch p.getPos() { + case 0: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_00 + case 1: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_01 + case 2: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_02 + case 3: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_03 + case 4: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_04 + case 5: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_05 + case 6: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_06, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_06 + case 7: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_07, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_07 + case 8: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_08, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_08 + case 9: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_09, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_09 + case 10: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_10, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_10 + case 11: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_11, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_11 + case 12: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_12, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_12 + case 13: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_13, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_13 + case 14: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_14, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_14 + case 15: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_15, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_15 + case 16: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_16, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_16 + case 17: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_17, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_17 + case 18: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_18, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_18 + case 19: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_19, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_19 + case 20: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_20, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_20 + case 21: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_21, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_21 + case 22: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_22, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_22 + case 23: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_23, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_23 + case 24: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_24, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_24 + case 25: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_25, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_25 + case 26: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_26, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_26 + case 27: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_27, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_27 + case 28: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_28, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_28 + case 29: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_29, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_29 + case 30: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_30, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_30 + case 31: + return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_31, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_31 + } + } + panic("machine: invalid pin") +} diff --git a/src/machine/uart.go b/src/machine/uart.go index 40d2d99c..1c8d84cb 100644 --- a/src/machine/uart.go +++ b/src/machine/uart.go @@ -1,4 +1,4 @@ -// +build avr esp nrf sam sifive stm32 k210 nxp +// +build avr esp nrf sam sifive stm32 k210 nxp,!mimxrt1062 package machine diff --git a/src/runtime/runtime_cortexm_hardfault_config.go b/src/runtime/runtime_cortexm_hardfault_config.go new file mode 100644 index 00000000..3667f221 --- /dev/null +++ b/src/runtime/runtime_cortexm_hardfault_config.go @@ -0,0 +1,27 @@ +// +build nxp,!mimxrt1062 + +package runtime + +import "device/nxp" + +const ( + CFSR_IACCVIOL = nxp.SystemControl_CFSR_IACCVIOL + CFSR_DACCVIOL = nxp.SystemControl_CFSR_DACCVIOL + CFSR_MUNSTKERR = nxp.SystemControl_CFSR_MUNSTKERR + CFSR_MSTKERR = nxp.SystemControl_CFSR_MSTKERR + CFSR_MLSPERR = nxp.SystemControl_CFSR_MLSPERR + CFSR_IBUSERR = nxp.SystemControl_CFSR_IBUSERR + CFSR_PRECISERR = nxp.SystemControl_CFSR_PRECISERR + CFSR_IMPRECISERR = nxp.SystemControl_CFSR_IMPRECISERR + CFSR_UNSTKERR = nxp.SystemControl_CFSR_UNSTKERR + CFSR_STKERR = nxp.SystemControl_CFSR_STKERR + CFSR_LSPERR = nxp.SystemControl_CFSR_LSPERR + CFSR_UNDEFINSTR = nxp.SystemControl_CFSR_UNDEFINSTR + CFSR_INVSTATE = nxp.SystemControl_CFSR_INVSTATE + CFSR_INVPC = nxp.SystemControl_CFSR_INVPC + CFSR_NOCP = nxp.SystemControl_CFSR_NOCP + CFSR_UNALIGNED = nxp.SystemControl_CFSR_UNALIGNED + CFSR_DIVBYZERO = nxp.SystemControl_CFSR_DIVBYZERO + CFSR_MMARVALID = nxp.SystemControl_CFSR_MMARVALID + CFSR_BFARVALID = nxp.SystemControl_CFSR_BFARVALID +) diff --git a/src/runtime/runtime_cortexm_hardfault_config_mimxrt1062.go b/src/runtime/runtime_cortexm_hardfault_config_mimxrt1062.go new file mode 100644 index 00000000..230b1cfd --- /dev/null +++ b/src/runtime/runtime_cortexm_hardfault_config_mimxrt1062.go @@ -0,0 +1,27 @@ +// +build nxp,mimxrt1062 + +package runtime + +import "device/nxp" + +const ( + CFSR_IACCVIOL = nxp.SCB_CFSR_IACCVIOL + CFSR_DACCVIOL = nxp.SCB_CFSR_DACCVIOL + CFSR_MUNSTKERR = nxp.SCB_CFSR_MUNSTKERR + CFSR_MSTKERR = nxp.SCB_CFSR_MSTKERR + CFSR_MLSPERR = nxp.SCB_CFSR_MLSPERR + CFSR_IBUSERR = nxp.SCB_CFSR_IBUSERR + CFSR_PRECISERR = nxp.SCB_CFSR_PRECISERR + CFSR_IMPRECISERR = nxp.SCB_CFSR_IMPRECISERR + CFSR_UNSTKERR = nxp.SCB_CFSR_UNSTKERR + CFSR_STKERR = nxp.SCB_CFSR_STKERR + CFSR_LSPERR = nxp.SCB_CFSR_LSPERR + CFSR_UNDEFINSTR = nxp.SCB_CFSR_UNDEFINSTR + CFSR_INVSTATE = nxp.SCB_CFSR_INVSTATE + CFSR_INVPC = nxp.SCB_CFSR_INVPC + CFSR_NOCP = nxp.SCB_CFSR_NOCP + CFSR_UNALIGNED = nxp.SCB_CFSR_UNALIGNED + CFSR_DIVBYZERO = nxp.SCB_CFSR_DIVBYZERO + CFSR_MMARVALID = nxp.SCB_CFSR_MMARVALID + CFSR_BFARVALID = nxp.SCB_CFSR_BFARVALID +) diff --git a/src/runtime/runtime_cortexm_hardfault_debug.go b/src/runtime/runtime_cortexm_hardfault_debug.go index 25d3e550..6aca3a26 100644 --- a/src/runtime/runtime_cortexm_hardfault_debug.go +++ b/src/runtime/runtime_cortexm_hardfault_debug.go @@ -8,7 +8,11 @@ import ( ) const ( - SystemControl_CFSR_KnownFault = nxp.SystemControl_CFSR_IACCVIOL | nxp.SystemControl_CFSR_DACCVIOL | nxp.SystemControl_CFSR_MUNSTKERR | nxp.SystemControl_CFSR_MSTKERR | nxp.SystemControl_CFSR_MLSPERR | nxp.SystemControl_CFSR_IBUSERR | nxp.SystemControl_CFSR_PRECISERR | nxp.SystemControl_CFSR_IMPRECISERR | nxp.SystemControl_CFSR_UNSTKERR | nxp.SystemControl_CFSR_STKERR | nxp.SystemControl_CFSR_LSPERR | nxp.SystemControl_CFSR_UNDEFINSTR | nxp.SystemControl_CFSR_INVSTATE | nxp.SystemControl_CFSR_INVPC | nxp.SystemControl_CFSR_NOCP | nxp.SystemControl_CFSR_UNALIGNED | nxp.SystemControl_CFSR_DIVBYZERO + SystemControl_CFSR_KnownFault = CFSR_IACCVIOL | CFSR_DACCVIOL | + CFSR_MUNSTKERR | CFSR_MSTKERR | CFSR_MLSPERR | CFSR_IBUSERR | + CFSR_PRECISERR | CFSR_IMPRECISERR | CFSR_UNSTKERR | CFSR_STKERR | + CFSR_LSPERR | CFSR_UNDEFINSTR | CFSR_INVSTATE | CFSR_INVPC | CFSR_NOCP | + CFSR_UNALIGNED | CFSR_DIVBYZERO ) // See runtime_cortexm_hardfault.go @@ -128,7 +132,7 @@ func (fs FaultStatus) Unknown() bool { return fs&SystemControl_CFSR_KnownFault = // the faulting instruction. The processor has not written a fault address to // the MMAR." func (fs MemFaultStatus) InstructionAccessViolation() bool { - return fs&nxp.SystemControl_CFSR_IACCVIOL != 0 + return fs&CFSR_IACCVIOL != 0 } // DataAccessViolation: the processor attempted a load or store at a location @@ -137,7 +141,7 @@ func (fs MemFaultStatus) InstructionAccessViolation() bool { // "When this bit is 1, the PC value stacked for the exception return points to // the faulting instruction. The processor has loaded the MMAR with the address // of the attempted access." -func (fs MemFaultStatus) DataAccessViolation() bool { return fs&nxp.SystemControl_CFSR_DACCVIOL != 0 } +func (fs MemFaultStatus) DataAccessViolation() bool { return fs&CFSR_DACCVIOL != 0 } // WhileUnstackingException: unstack for an exception return has caused one or // more access violations @@ -147,7 +151,7 @@ func (fs MemFaultStatus) DataAccessViolation() bool { return fs&nxp.SystemContro // the SP from the failing return, and has not performed a new save. The // processor has not written a fault address to the MMAR." func (fs MemFaultStatus) WhileUnstackingException() bool { - return fs&nxp.SystemControl_CFSR_MUNSTKERR != 0 + return fs&CFSR_MUNSTKERR != 0 } // WileStackingException: stacking for an exception entry has caused one or more @@ -156,11 +160,11 @@ func (fs MemFaultStatus) WhileUnstackingException() bool { // "When this bit is 1, the SP is still adjusted but the values in the context // area on the stack might be incorrect. The processor has not written a fault // address to the MMAR." -func (fs MemFaultStatus) WileStackingException() bool { return fs&nxp.SystemControl_CFSR_MSTKERR != 0 } +func (fs MemFaultStatus) WileStackingException() bool { return fs&CFSR_MSTKERR != 0 } // DuringFPLazyStatePres: A MemManage fault occurred during floating-point lazy // state preservation -func (fs MemFaultStatus) DuringFPLazyStatePres() bool { return fs&nxp.SystemControl_CFSR_MLSPERR != 0 } +func (fs MemFaultStatus) DuringFPLazyStatePres() bool { return fs&CFSR_MLSPERR != 0 } // InstructionBusError: instruction bus error // @@ -170,11 +174,11 @@ func (fs MemFaultStatus) DuringFPLazyStatePres() bool { return fs&nxp.SystemCont // // When the processor sets this bit is 1, it does not write a fault address to // the BFAR." -func (fs BusFaultStatus) InstructionBusError() bool { return fs&nxp.SystemControl_CFSR_IBUSERR != 0 } +func (fs BusFaultStatus) InstructionBusError() bool { return fs&CFSR_IBUSERR != 0 } // PreciseDataBusError: a data bus error has occurred, and the PC value stacked // for the exception return points to the instruction that caused the fault -func (fs BusFaultStatus) PreciseDataBusError() bool { return fs&nxp.SystemControl_CFSR_PRECISERR != 0 } +func (fs BusFaultStatus) PreciseDataBusError() bool { return fs&CFSR_PRECISERR != 0 } // ImpreciseDataBusError: a data bus error has occurred, but the return address // in the stack frame is not related to the instruction that caused the error @@ -189,7 +193,7 @@ func (fs BusFaultStatus) PreciseDataBusError() bool { return fs&nxp.SystemContro // enters the handler for the imprecise BusFault, the handler detects both // IMPRECISERR set to 1 and one of the precise fault status bits set to 1." func (fs BusFaultStatus) ImpreciseDataBusError() bool { - return fs&nxp.SystemControl_CFSR_IMPRECISERR != 0 + return fs&CFSR_IMPRECISERR != 0 } // WhileUnstackingException: unstack for an exception return has caused one or @@ -200,7 +204,7 @@ func (fs BusFaultStatus) ImpreciseDataBusError() bool { // does not adjust the SP from the failing return, does not performed a new // save, and does not write a fault address to the BFAR." func (fs BusFaultStatus) WhileUnstackingException() bool { - return fs&nxp.SystemControl_CFSR_UNSTKERR != 0 + return fs&CFSR_UNSTKERR != 0 } // WhileStackingException: stacking for an exception entry has caused one or @@ -209,11 +213,11 @@ func (fs BusFaultStatus) WhileUnstackingException() bool { // "When the processor sets this bit to 1, the SP is still adjusted but the // values in the context area on the stack might be incorrect. The processor // does not write a fault address to the BFAR." -func (fs BusFaultStatus) WhileStackingException() bool { return fs&nxp.SystemControl_CFSR_STKERR != 0 } +func (fs BusFaultStatus) WhileStackingException() bool { return fs&CFSR_STKERR != 0 } // DuringFPLazyStatePres: A bus fault occurred during floating-point lazy state // preservation -func (fs BusFaultStatus) DuringFPLazyStatePres() bool { return fs&nxp.SystemControl_CFSR_LSPERR != 0 } +func (fs BusFaultStatus) DuringFPLazyStatePres() bool { return fs&CFSR_LSPERR != 0 } // UndefinedInstruction: the processor has attempted to execute an undefined // instruction @@ -223,7 +227,7 @@ func (fs BusFaultStatus) DuringFPLazyStatePres() bool { return fs&nxp.SystemCont // // An undefined instruction is an instruction that the processor cannot decode." func (fs UsageFaultStatus) UndefinedInstruction() bool { - return fs&nxp.SystemControl_CFSR_UNDEFINSTR != 0 + return fs&CFSR_UNDEFINSTR != 0 } // IllegalUseOfEPSR: the processor has attempted to execute an instruction that @@ -233,19 +237,19 @@ func (fs UsageFaultStatus) UndefinedInstruction() bool { // points to the instruction that attempted the illegal use of the EPSR. // // This bit is not set to 1 if an undefined instruction uses the EPSR." -func (fs UsageFaultStatus) IllegalUseOfEPSR() bool { return fs&nxp.SystemControl_CFSR_INVSTATE != 0 } +func (fs UsageFaultStatus) IllegalUseOfEPSR() bool { return fs&CFSR_INVSTATE != 0 } // IllegalExceptionReturn: the processor has attempted an illegal load of // EXC_RETURN to the PC // // "When this bit is set to 1, the PC value stacked for the exception return // points to the instruction that tried to perform the illegal load of the PC." -func (fs UsageFaultStatus) IllegalExceptionReturn() bool { return fs&nxp.SystemControl_CFSR_INVPC != 0 } +func (fs UsageFaultStatus) IllegalExceptionReturn() bool { return fs&CFSR_INVPC != 0 } // AttemptedToAccessCoprocessor: the processor has attempted to access a // coprocessor func (fs UsageFaultStatus) AttemptedToAccessCoprocessor() bool { - return fs&nxp.SystemControl_CFSR_NOCP != 0 + return fs&CFSR_NOCP != 0 } // UnalignedMemoryAccess: the processor has made an unaligned memory access @@ -256,7 +260,7 @@ func (fs UsageFaultStatus) AttemptedToAccessCoprocessor() bool { // Unaligned LDM, STM, LDRD, and STRD instructions always fault irrespective of // the setting of UNALIGN_TRP." func (fs UsageFaultStatus) UnalignedMemoryAccess() bool { - return fs&nxp.SystemControl_CFSR_UNALIGNED != 0 + return fs&CFSR_UNALIGNED != 0 } // DivideByZero: the processor has executed an SDIV or UDIV instruction with a @@ -267,7 +271,7 @@ func (fs UsageFaultStatus) UnalignedMemoryAccess() bool { // // Enable trapping of divide by zero by setting the DIV_0_TRP bit in the CCR to // 1." -func (fs UsageFaultStatus) DivideByZero() bool { return fs&nxp.SystemControl_CFSR_DIVBYZERO != 0 } +func (fs UsageFaultStatus) DivideByZero() bool { return fs&CFSR_DIVBYZERO != 0 } // Address returns the MemManage Fault Address Register if the fault status // indicates the address is valid. @@ -277,7 +281,7 @@ func (fs UsageFaultStatus) DivideByZero() bool { return fs&nxp.SystemControl_CFS // problems on return to a stacked active MemManage fault handler whose MMAR // value has been overwritten." func (fs MemFaultStatus) Address() (uintptr, bool) { - if fs&nxp.SystemControl_CFSR_MMARVALID == 0 { + if fs&CFSR_MMARVALID == 0 { return 0, false } else { return uintptr(nxp.SystemControl.MMFAR.Get()), true @@ -296,7 +300,7 @@ func (fs MemFaultStatus) Address() (uintptr, bool) { // returning to a stacked active BusFault handler whose BFAR value has been // overwritten."" func (fs BusFaultStatus) Address() (uintptr, bool) { - if fs&nxp.SystemControl_CFSR_BFARVALID == 0 { + if fs&CFSR_BFARVALID == 0 { return 0, false } else { return uintptr(nxp.SystemControl.BFAR.Get()), true diff --git a/src/runtime/runtime_mimxrt1062.go b/src/runtime/runtime_mimxrt1062.go new file mode 100644 index 00000000..147c4aad --- /dev/null +++ b/src/runtime/runtime_mimxrt1062.go @@ -0,0 +1,117 @@ +// +build mimxrt1062 + +package runtime + +import ( + "device/arm" + "device/nxp" + "unsafe" +) + +const asyncScheduler = false + +//go:extern _svectors +var _svectors [0]byte + +//go:extern _flexram_cfg +var _flexram_cfg [0]byte + +func postinit() {} + +//export Reset_Handler +func main() { + + // disable interrupts + irq := arm.DisableInterrupts() + + // initialize FPU and VTOR, reset watchdogs + initSystem() + + // configure core and peripheral clocks/PLLs/PFDs + initClocks() + + // copy data/bss sections from flash to RAM + preinit() + + // initialize cache and MPU + initCache() + + // enable SysTick, GPIO, and peripherals + initPeripherals() + + // reenable interrupts + arm.EnableInterrupts(irq) + + run() + abort() +} + +func initSystem() { + + // configure SRAM capacity + ramc := uintptr(unsafe.Pointer(&_flexram_cfg)) + nxp.IOMUXC_GPR.GPR17.Set(uint32(ramc)) + nxp.IOMUXC_GPR.GPR16.Set(0x00200007) + nxp.IOMUXC_GPR.GPR14.Set(0x00AA0000) + + // use bandgap-based bias currents for best performance (Page 1175) [Teensyduino] + nxp.PMU.MISC0_SET.Set(1 << 3) + + // install vector table (TODO: initialize interrupt/exception table?) + vtor := uintptr(unsafe.Pointer(&_svectors)) + nxp.SystemControl.VTOR.Set(uint32(vtor)) + + // disable watchdog powerdown counter + nxp.WDOG1.WMCR.ClearBits(nxp.WDOG_WMCR_PDE_Msk) + nxp.WDOG2.WMCR.ClearBits(nxp.WDOG_WMCR_PDE_Msk) + + // disable watchdog + if nxp.WDOG1.WCR.HasBits(nxp.WDOG_WCR_WDE_Msk) { + nxp.WDOG1.WCR.ClearBits(nxp.WDOG_WCR_WDE_Msk) + } + if nxp.WDOG2.WCR.HasBits(nxp.WDOG_WCR_WDE_Msk) { + nxp.WDOG2.WCR.ClearBits(nxp.WDOG_WCR_WDE_Msk) + } + if nxp.RTWDOG.CS.HasBits(nxp.RTWDOG_CS_CMD32EN_Msk) { + nxp.RTWDOG.CNT.Set(0xD928C520) // 0xD928C520 is the update key + } else { + nxp.RTWDOG.CNT.Set(0xC520) + nxp.RTWDOG.CNT.Set(0xD928) + } + nxp.RTWDOG.TOVAL.Set(0xFFFF) + nxp.RTWDOG.CS.Set((nxp.RTWDOG.CS.Get() & ^uint32(nxp.RTWDOG_CS_EN_Msk)) | nxp.RTWDOG_CS_UPDATE_Msk) +} + +func initPeripherals() { + + // enable FPU - set CP10, CP11 full access + nxp.SystemControl.CPACR.SetBits((3 << (10 * 2)) | (3 << (11 * 2))) + + enableTimerClocks() // activate GPT/PIT clock gates + initSysTick() // enable SysTick + + enablePinClocks() // activate IOMUXC(_GPR)/GPIO clock gates + initPins() // configure GPIO + + enablePeripheralClocks() // activate peripheral clock gates +} + +func initPins() { + // use fast GPIO for all pins (GPIO6-9) + nxp.IOMUXC_GPR.GPR26.Set(0xFFFFFFFF) + nxp.IOMUXC_GPR.GPR27.Set(0xFFFFFFFF) + nxp.IOMUXC_GPR.GPR28.Set(0xFFFFFFFF) + nxp.IOMUXC_GPR.GPR29.Set(0xFFFFFFFF) +} + +func putchar(c byte) {} + +func abort() { + for { + arm.Asm("wfe") + } +} + +func waitForEvents() { + arm.Asm("wfe") +} diff --git a/src/runtime/runtime_mimxrt1062_clock.go b/src/runtime/runtime_mimxrt1062_clock.go new file mode 100644 index 00000000..949870e8 --- /dev/null +++ b/src/runtime/runtime_mimxrt1062_clock.go @@ -0,0 +1,1242 @@ +// +build mimxrt1062 + +package runtime + +import ( + "device/nxp" + "runtime/volatile" + "unsafe" +) + +// Core, bus, and peripheral clock frequencies (Hz) +const ( + CORE_FREQ = 600000000 // 600 MHz + OSC_FREQ = 100000 // 100 kHz (see note below) + _ // ----------- + AHB_FREQ = 600000000 // 600 MHz + CAN_FREQ = 40000000 // 40 MHz + CKIL_SYNC_FREQ = 32768 // 32.768 kHz + CSI_FREQ = 12000000 // 12 MHz + FLEXIO1_FREQ = 30000000 // 30 MHz + FLEXIO2_FREQ = 30000000 // 30 MHz + FLEXSPI2_FREQ = 327724137 // 327.7 MHz + FLEXSPI_FREQ = 327724137 // 327.7 MHz + IPG_FREQ = 150000000 // 150 MHz + LCDIF_FREQ = 39272727 // 39.3 MHz + LPI2C_FREQ = 60000000 // 60 MHz + LPSPI_FREQ = 132000000 // 132 MHz + PERCLK_FREQ = 24000000 // 24 MHz + SAI1_FREQ = 63529411 // 63.5 MHz + SAI2_FREQ = 63529411 // 63.5 MHz + SAI3_FREQ = 63529411 // 63.5 MHz + SEMC_FREQ = 163862068 // 163.9 MHz + SPDIF0_FREQ = 30000000 // 30 MHz + TRACE_FREQ = 132000000 // 132 MHz + UART_FREQ = 24000000 // 24 MHz + USDHC1_FREQ = 198000000 // 198 MHz + USDHC2_FREQ = 198000000 // 198 MHz +) + +// Note about OSC_FREQ from Teensyduino (cores/teensy4/startup.c): +// +// | ARM SysTick is used for most Ardiuno timing functions, delay(), millis(), +// | micros(). SysTick can run from either the ARM core clock, or from an +// | "external" clock. NXP documents it as "24 MHz XTALOSC can be the external +// | clock source of SYSTICK" (RT1052 ref manual, rev 1, page 411). However, +// | NXP actually hid an undocumented divide-by-240 circuit in the hardware, so +// | the external clock is really 100 kHz. We use this clock rather than the +// | ARM clock, to allow SysTick to maintain correct timing even when we change +// | the ARM clock to run at different speeds. + +// initClocks configures the core, buses, and all peripherals' clock source mux +// and dividers for runtime. The clock gates for individual peripherals are all +// disabled prior to configuration and must be enabled afterwards using function +// `enableClocks()`. +func initClocks() { + // disable low-power mode so that __WFI doesn't lock up at runtime. + // see: Using the MIMXRT1060/4-EVK with MCUXpresso IDE v10.3.x (v1.0.2, + // 2019MAR01), chapter 14 + modeClkRun.set() + + // enable 1MHz clock output + nxp.XTALOSC24M.OSC_CONFIG2.SetBits(nxp.XTALOSC24M_OSC_CONFIG2_ENABLE_1M_Msk) + // use free 1MHz clock output + nxp.XTALOSC24M.OSC_CONFIG2.ClearBits(nxp.XTALOSC24M_OSC_CONFIG2_MUX_1M_Msk) + + // initialize external 24 MHz clock + nxp.CCM_ANALOG.MISC0_CLR.Set(nxp.CCM_ANALOG_MISC0_XTAL_24M_PWD_Msk) // power + for !nxp.XTALOSC24M.LOWPWR_CTRL.HasBits(nxp.XTALOSC24M_LOWPWR_CTRL_XTALOSC_PWRUP_STAT_Msk) { + } + nxp.CCM_ANALOG.MISC0_SET.Set(nxp.CCM_ANALOG_MISC0_OSC_XTALOK_EN_Msk) // detect freq + for !nxp.CCM_ANALOG.MISC0.HasBits(nxp.CCM_ANALOG_MISC0_OSC_XTALOK_Msk) { + } + nxp.CCM_ANALOG.MISC0_CLR.Set(nxp.CCM_ANALOG_MISC0_OSC_XTALOK_EN_Msk) + + // initialize internal RC oscillator 24 MHz clock + nxp.XTALOSC24M.LOWPWR_CTRL.SetBits(nxp.XTALOSC24M_LOWPWR_CTRL_RC_OSC_EN_Msk) + + // switch clock source to external oscillator + nxp.XTALOSC24M.LOWPWR_CTRL_CLR.Set(nxp.XTALOSC24M_LOWPWR_CTRL_CLR_OSC_SEL_Msk) + + // set oscillator ready counter value + nxp.CCM.CCR.Set((nxp.CCM.CCR.Get() & ^uint32(nxp.CCM_CCR_OSCNT_Msk)) | + ((127 << nxp.CCM_CCR_OSCNT_Pos) & nxp.CCM_CCR_OSCNT_Msk)) + + // set PERIPH2_CLK and PERIPH to provide stable clock before PLLs initialed + muxIpPeriphClk2.mux(1) // PERIPH_CLK2 select OSC24M + muxIpPeriph.mux(1) // PERIPH select PERIPH_CLK2 + + // set VDD_SOC to 1.275V, necessary to config AHB to 600 MHz + nxp.DCDC.REG3.Set((nxp.DCDC.REG3.Get() & ^uint32(nxp.DCDC_REG3_TRG_Msk)) | + ((13 << nxp.DCDC_REG3_TRG_Pos) & nxp.DCDC_REG3_TRG_Msk)) + + // wait until DCDC_STS_DC_OK bit is asserted + for !nxp.DCDC.REG0.HasBits(nxp.DCDC_REG0_STS_DC_OK_Msk) { + } + + // -------------------------------------------------------------------- AHB -- + divIpAhb.div(0) // divide AHB_PODF (DIV1) + + // -------------------------------------------------------------------- ADC -- + clkIpAdc1.enable(false) // disable ADC clock gates + clkIpAdc2.enable(false) // ~ + + // ------------------------------------------------------------------- XBAR -- + clkIpXbar1.enable(false) // disable XBAR clock gates + clkIpXbar2.enable(false) // ~ + clkIpXbar3.enable(false) // ~ + + // ---------------------------------------------------------------- ARM/IPG -- + divIpIpg.div(3) // divide IPG_PODF (DIV4) + divIpArm.div(1) // divide ARM_PODF (DIV2) + divIpPeriphClk2.div(0) // divide PERIPH_CLK2_PODF (DIV1) + + // ---------------------------------------------------------------- GPT/PIT -- + clkIpGpt1.enable(false) // disable GPT/PIT clock gates + clkIpGpt1S.enable(false) // ~ + clkIpGpt2.enable(false) // ~ + clkIpGpt2S.enable(false) // ~ + clkIpPit.enable(false) // ~ + + // -------------------------------------------------------------------- PER -- + divIpPerclk.div(0) // divide PERCLK_PODF (DIV1) + + // ------------------------------------------------------------------ USDHC -- + clkIpUsdhc1.enable(false) // disable USDHC1 clock gate + divIpUsdhc1.div(1) // divide USDHC1_PODF (DIV2) + muxIpUsdhc1.mux(1) // USDHC1 select PLL2_PFD0 + clkIpUsdhc2.enable(false) // disable USDHC2 clock gate + divIpUsdhc2.div(1) // divide USDHC2_PODF (DIV2) + muxIpUsdhc2.mux(1) // USDHC2 select PLL2_PFD0 + + // ------------------------------------------------------------------- SEMC -- + clkIpSemc.enable(false) // disable SEMC clock gate + divIpSemc.div(1) // divide SEMC_PODF (DIV2) + muxIpSemcAlt.mux(0) // SEMC_ALT select PLL2_PFD2 + muxIpSemc.mux(1) // SEMC select SEMC_ALT + + // ---------------------------------------------------------------- FLEXSPI -- + if false { + // TODO: external flash is on this bus, configured via DCD block + clkIpFlexSpi.enable(false) // disable FLEXSPI clock gate + divIpFlexSpi.div(0) // divide FLEXSPI_PODF (DIV1) + muxIpFlexSpi.mux(2) // FLEXSPI select PLL2_PFD2 + } + clkIpFlexSpi2.enable(false) // disable FLEXSPI2 clock gate + divIpFlexSpi2.div(0) // divide FLEXSPI2_PODF (DIV1) + muxIpFlexSpi2.mux(0) // FLEXSPI2 select PLL2_PFD2 + + // -------------------------------------------------------------------- CSI -- + clkIpCsi.enable(false) // disable CSI clock gate + divIpCsi.div(1) // divide CSI_PODF (DIV2) + muxIpCsi.mux(0) // CSI select OSC24M + + // ------------------------------------------------------------------ LPSPI -- + clkIpLpspi1.enable(false) // disable LPSPI clock gate + clkIpLpspi2.enable(false) // ~ + clkIpLpspi3.enable(false) // ~ + clkIpLpspi4.enable(false) // ~ + divIpLpspi.div(3) // divide LPSPI_PODF (DIV4) + muxIpLpspi.mux(2) // LPSPI select PLL2 + + // ------------------------------------------------------------------ TRACE -- + clkIpTrace.enable(false) // disable TRACE clock gate + divIpTrace.div(3) // divide TRACE_PODF (DIV4) + muxIpTrace.mux(0) // TRACE select PLL2_MAIN + + // -------------------------------------------------------------------- SAI -- + clkIpSai1.enable(false) // disable SAI1 clock gate + divIpSai1Pre.div(3) // divide SAI1_CLK_PRED (DIV4) + divIpSai1.div(1) // divide SAI1_CLK_PODF (DIV2) + muxIpSai1.mux(0) // SAI1 select PLL3_PFD2 + clkIpSai2.enable(false) // disable SAI2 clock gate + divIpSai2Pre.div(3) // divide SAI2_CLK_PRED (DIV4) + divIpSai2.div(1) // divide SAI2_CLK_PODF (DIV2) + muxIpSai2.mux(0) // SAI2 select PLL3_PFD2 + clkIpSai3.enable(false) // disable SAI3 clock gate + divIpSai3Pre.div(3) // divide SAI3_CLK_PRED (DIV4) + divIpSai3.div(1) // divide SAI3_CLK_PODF (DIV2) + muxIpSai3.mux(0) // SAI3 select PLL3_PFD2 + + // ------------------------------------------------------------------ LPI2C -- + clkIpLpi2c1.enable(false) // disable LPI2C clock gate + clkIpLpi2c2.enable(false) // ~ + clkIpLpi2c3.enable(false) // ~ + divIpLpi2c.div(0) // divide LPI2C_CLK_PODF (DIV1) + muxIpLpi2c.mux(0) // LPI2C select PLL3_SW_60M + + // -------------------------------------------------------------------- CAN -- + clkIpCan1.enable(false) // disable CAN clock gate + clkIpCan2.enable(false) // ~ + clkIpCan3.enable(false) // ~ + clkIpCan1S.enable(false) // ~ + clkIpCan2S.enable(false) // ~ + clkIpCan3S.enable(false) // ~ + divIpCan.div(1) // divide CAN_CLK_PODF (DIV2) + muxIpCan.mux(2) // CAN select PLL3_SW_80M + + // ------------------------------------------------------------------- UART -- + clkIpLpuart1.enable(false) // disable UART clock gate + clkIpLpuart2.enable(false) // ~ + clkIpLpuart3.enable(false) // ~ + clkIpLpuart4.enable(false) // ~ + clkIpLpuart5.enable(false) // ~ + clkIpLpuart6.enable(false) // ~ + clkIpLpuart7.enable(false) // ~ + clkIpLpuart8.enable(false) // ~ + divIpUart.div(0) // divide UART_CLK_PODF (DIV1) + muxIpUart.mux(1) // UART select OSC + + // -------------------------------------------------------------------- LCD -- + clkIpLcdPixel.enable(false) // disable LCDIF clock gate + divIpLcdifPre.div(1) // divide LCDIF_PRED (DIV2) + divIpLcdif.div(3) // divide LCDIF_CLK_PODF (DIV4) + muxIpLcdifPre.mux(5) // LCDIF_PRE select PLL3_PFD1 + + // ------------------------------------------------------------------ SPDIF -- + clkIpSpdif.enable(false) // disable SPDIF clock gate + divIpSpdif0Pre.div(1) // divide SPDIF0_CLK_PRED (DIV2) + divIpSpdif0.div(7) // divide SPDIF0_CLK_PODF (DIV8) + muxIpSpdif.mux(3) // SPDIF select PLL3_SW + + // ----------------------------------------------------------------- FLEXIO -- + clkIpFlexio1.enable(false) // disable FLEXIO1 clock gate + divIpFlexio1Pre.div(1) // divide FLEXIO1_CLK_PRED (DIV2) + divIpFlexio1.div(7) // divide FLEXIO1_CLK_PODF (DIV8) + muxIpFlexio1.mux(3) // FLEXIO1 select PLL3_SW + clkIpFlexio2.enable(false) // enable FLEXIO2 clock gate + divIpFlexio2Pre.div(1) // divide FLEXIO2_CLK_PRED (DIV2) + divIpFlexio2.div(7) // divide FLEXIO2_CLK_PODF (DIV8) + muxIpFlexio2.mux(3) // FLEXIO2 select PLL3_SW + + // ---------------------------------------------------------------- PLL/PFD -- + muxIpPll3Sw.mux(0) // PLL3_SW select PLL3_MAIN + + armPllConfig.configure() // init ARM PLL + // SYS PLL (PLL2) @ 528 MHz + // PFD0 = 396 MHz -> USDHC1/USDHC2(DIV2)=198 MHz + // PFD1 = 594 MHz -> (currently unused) + // PFD2 = 327.72 MHz -> SEMC(DIV2)=163.86 MHz, FlexSPI/FlexSPI2=327.72 MHz + // PFD3 = 454.73 MHz -> (currently unused) + sysPllConfig.configure(24, 16, 29, 16) // init SYS PLL and PFDs + + // USB1 PLL (PLL3) @ 480 MHz + // PFD0 -> (currently unused) + // PFD1 -> (currently unused) + // PFD2 -> (currently unused) + // PFD3 -> (currently unused) + usb1PllConfig.configure() // init USB1 PLL and PFDs + usb2PllConfig.configure() // init USB2 PLL + + // --------------------------------------------------------------- ARM CORE -- + muxIpPrePeriph.mux(3) // PRE_PERIPH select ARM_PLL + muxIpPeriph.mux(0) // PERIPH select PRE_PERIPH + muxIpPeriphClk2.mux(1) // PERIPH_CLK2 select OSC + muxIpPerclk.mux(1) // PERCLK select OSC + + // ------------------------------------------------------------------- LVDS -- + // set LVDS1 clock source + nxp.CCM_ANALOG.MISC1.Set((nxp.CCM_ANALOG.MISC1.Get() & ^uint32(nxp.CCM_ANALOG_MISC1_LVDS1_CLK_SEL_Msk)) | + ((0 << nxp.CCM_ANALOG_MISC1_LVDS1_CLK_SEL_Pos) & nxp.CCM_ANALOG_MISC1_LVDS1_CLK_SEL_Msk)) + + // ----------------------------------------------------------------- CLKOUT -- + // set CLOCK_OUT1 divider + nxp.CCM.CCOSR.Set((nxp.CCM.CCOSR.Get() & ^uint32(nxp.CCM_CCOSR_CLKO1_DIV_Msk)) | + ((0 << nxp.CCM_CCOSR_CLKO1_DIV_Pos) & nxp.CCM_CCOSR_CLKO1_DIV_Msk)) + // set CLOCK_OUT1 source + nxp.CCM.CCOSR.Set((nxp.CCM.CCOSR.Get() & ^uint32(nxp.CCM_CCOSR_CLKO1_SEL_Msk)) | + ((1 << nxp.CCM_CCOSR_CLKO1_SEL_Pos) & nxp.CCM_CCOSR_CLKO1_SEL_Msk)) + // set CLOCK_OUT2 divider + nxp.CCM.CCOSR.Set((nxp.CCM.CCOSR.Get() & ^uint32(nxp.CCM_CCOSR_CLKO2_DIV_Msk)) | + ((0 << nxp.CCM_CCOSR_CLKO2_DIV_Pos) & nxp.CCM_CCOSR_CLKO2_DIV_Msk)) + // set CLOCK_OUT2 source + nxp.CCM.CCOSR.Set((nxp.CCM.CCOSR.Get() & ^uint32(nxp.CCM_CCOSR_CLKO2_SEL_Msk)) | + ((18 << nxp.CCM_CCOSR_CLKO2_SEL_Pos) & nxp.CCM_CCOSR_CLKO2_SEL_Msk)) + + nxp.CCM.CCOSR.ClearBits(nxp.CCM_CCOSR_CLK_OUT_SEL_Msk) // set CLK_OUT1 drives CLK_OUT + nxp.CCM.CCOSR.SetBits(nxp.CCM_CCOSR_CLKO1_EN_Msk) // enable CLK_OUT1 + nxp.CCM.CCOSR.SetBits(nxp.CCM_CCOSR_CLKO2_EN_Msk) // enable CLK_OUT2 + + // ----------------------------------------------------------------- IOMUXC -- + clkIpIomuxcGpr.enable(false) // disable IOMUXC_GPR clock gate + clkIpIomuxc.enable(false) // disable IOMUXC clock gate + // set GPT1 High frequency reference clock source + nxp.IOMUXC_GPR.GPR5.ClearBits(nxp.IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT1_Msk) + // set GPT2 High frequency reference clock source + nxp.IOMUXC_GPR.GPR5.ClearBits(nxp.IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT2_Msk) + + // ------------------------------------------------------------------- GPIO -- + clkIpGpio1.enable(false) // disable GPIO clock gates + clkIpGpio2.enable(false) // ~ + clkIpGpio3.enable(false) // ~ + clkIpGpio4.enable(false) // ~ +} + +func enableTimerClocks() { + + // ---------------------------------------------------------------- GPT/PIT -- + clkIpGpt1.enable(true) // enable GPT/PIT clock gates + clkIpGpt1S.enable(true) // ~ + clkIpGpt2.enable(true) // ~ + clkIpGpt2S.enable(true) // ~ + clkIpPit.enable(true) // ~ +} + +func enablePinClocks() { + + // ----------------------------------------------------------------- IOMUXC -- + clkIpIomuxcGpr.enable(true) // enable IOMUXC clock gates + clkIpIomuxc.enable(true) // ~ + + // ------------------------------------------------------------------- GPIO -- + clkIpGpio1.enable(true) // enable GPIO clock gates + clkIpGpio2.enable(true) // ~ + clkIpGpio3.enable(true) // ~ + clkIpGpio4.enable(true) // ~ +} + +// enableClocks enables the clock gates for peripherals used by this runtime. +func enablePeripheralClocks() { + + // -------------------------------------------------------------------- ADC -- + clkIpAdc1.enable(true) // enable ADC clock gates + clkIpAdc2.enable(true) // ~ + + // ------------------------------------------------------------------- XBAR -- + clkIpXbar1.enable(true) // enable XBAR clock gates + clkIpXbar2.enable(true) // ~ + clkIpXbar3.enable(true) // ~ + + // ------------------------------------------------------------------ USDHC -- + clkIpUsdhc1.enable(true) // enable USDHC clock gates + clkIpUsdhc2.enable(true) // ~ + + // ------------------------------------------------------------------- SEMC -- + clkIpSemc.enable(true) // enable SEMC clock gate + + // ---------------------------------------------------------------- FLEXSPI -- + clkIpFlexSpi2.enable(true) // enable FLEXSPI2 clock gate + + // ------------------------------------------------------------------ LPSPI -- + clkIpLpspi1.enable(true) // enable LPSPI clock gate + clkIpLpspi2.enable(true) // ~ + clkIpLpspi3.enable(true) // ~ + clkIpLpspi4.enable(true) // ~ + + // ------------------------------------------------------------------ LPI2C -- + clkIpLpi2c1.enable(true) // enable LPI2C clock gate + clkIpLpi2c2.enable(true) // ~ + clkIpLpi2c3.enable(true) // ~ + + // -------------------------------------------------------------------- CAN -- + clkIpCan1.enable(true) // enable CAN clock gate + clkIpCan2.enable(true) // ~ + clkIpCan3.enable(true) // ~ + clkIpCan1S.enable(true) // ~ + clkIpCan2S.enable(true) // ~ + clkIpCan3S.enable(true) // ~ + + // ------------------------------------------------------------------- UART -- + clkIpLpuart1.enable(true) // enable UART clock gate + clkIpLpuart2.enable(true) // ~ + clkIpLpuart3.enable(true) // ~ + clkIpLpuart4.enable(true) // ~ + clkIpLpuart5.enable(true) // ~ + clkIpLpuart6.enable(true) // ~ + clkIpLpuart7.enable(true) // ~ + clkIpLpuart8.enable(true) // ~ + + // ----------------------------------------------------------------- FLEXIO -- + clkIpFlexio1.enable(true) // enable FLEXIO clock gates + clkIpFlexio2.enable(true) // ~ +} + +type clock uint32 + +// Named oscillators +const ( + clkCpu clock = 0x0 // CPU clock + clkAhb clock = 0x1 // AHB clock + clkSemc clock = 0x2 // SEMC clock + clkIpg clock = 0x3 // IPG clock + clkPer clock = 0x4 // PER clock + clkOsc clock = 0x5 // OSC clock selected by PMU_LOWPWR_CTRL[OSC_SEL] + clkRtc clock = 0x6 // RTC clock (RTCCLK) + clkArmPll clock = 0x7 // ARMPLLCLK + clkUsb1Pll clock = 0x8 // USB1PLLCLK + clkUsb1PllPfd0 clock = 0x9 // USB1PLLPDF0CLK + clkUsb1PllPfd1 clock = 0xA // USB1PLLPFD1CLK + clkUsb1PllPfd2 clock = 0xB // USB1PLLPFD2CLK + clkUsb1PllPfd3 clock = 0xC // USB1PLLPFD3CLK + clkUsb2Pll clock = 0xD // USB2PLLCLK + clkSysPll clock = 0xE // SYSPLLCLK + clkSysPllPfd0 clock = 0xF // SYSPLLPDF0CLK + clkSysPllPfd1 clock = 0x10 // SYSPLLPFD1CLK + clkSysPllPfd2 clock = 0x11 // SYSPLLPFD2CLK + clkSysPllPfd3 clock = 0x12 // SYSPLLPFD3CLK + clkEnetPll0 clock = 0x13 // Enet PLLCLK ref_enetpll0 + clkEnetPll1 clock = 0x14 // Enet PLLCLK ref_enetpll1 + clkEnetPll2 clock = 0x15 // Enet PLLCLK ref_enetpll2 + clkAudioPll clock = 0x16 // Audio PLLCLK + clkVideoPll clock = 0x17 // Video PLLCLK +) + +// Named clocks of integrated peripherals +const ( + clkIpAipsTz1 clock = (0 << 8) | nxp.CCM_CCGR0_CG0_Pos // CCGR0, CG0 + clkIpAipsTz2 clock = (0 << 8) | nxp.CCM_CCGR0_CG1_Pos // CCGR0, CG1 + clkIpMqs clock = (0 << 8) | nxp.CCM_CCGR0_CG2_Pos // CCGR0, CG2 + clkIpFlexSpiExsc clock = (0 << 8) | nxp.CCM_CCGR0_CG3_Pos // CCGR0, CG3 + clkIpSimMMain clock = (0 << 8) | nxp.CCM_CCGR0_CG4_Pos // CCGR0, CG4 + clkIpDcp clock = (0 << 8) | nxp.CCM_CCGR0_CG5_Pos // CCGR0, CG5 + clkIpLpuart3 clock = (0 << 8) | nxp.CCM_CCGR0_CG6_Pos // CCGR0, CG6 + clkIpCan1 clock = (0 << 8) | nxp.CCM_CCGR0_CG7_Pos // CCGR0, CG7 + clkIpCan1S clock = (0 << 8) | nxp.CCM_CCGR0_CG8_Pos // CCGR0, CG8 + clkIpCan2 clock = (0 << 8) | nxp.CCM_CCGR0_CG9_Pos // CCGR0, CG9 + clkIpCan2S clock = (0 << 8) | nxp.CCM_CCGR0_CG10_Pos // CCGR0, CG10 + clkIpTrace clock = (0 << 8) | nxp.CCM_CCGR0_CG11_Pos // CCGR0, CG11 + clkIpGpt2 clock = (0 << 8) | nxp.CCM_CCGR0_CG12_Pos // CCGR0, CG12 + clkIpGpt2S clock = (0 << 8) | nxp.CCM_CCGR0_CG13_Pos // CCGR0, CG13 + clkIpLpuart2 clock = (0 << 8) | nxp.CCM_CCGR0_CG14_Pos // CCGR0, CG14 + clkIpGpio2 clock = (0 << 8) | nxp.CCM_CCGR0_CG15_Pos // CCGR0, CG15 + + clkIpLpspi1 clock = (1 << 8) | nxp.CCM_CCGR1_CG0_Pos // CCGR1, CG0 + clkIpLpspi2 clock = (1 << 8) | nxp.CCM_CCGR1_CG1_Pos // CCGR1, CG1 + clkIpLpspi3 clock = (1 << 8) | nxp.CCM_CCGR1_CG2_Pos // CCGR1, CG2 + clkIpLpspi4 clock = (1 << 8) | nxp.CCM_CCGR1_CG3_Pos // CCGR1, CG3 + clkIpAdc2 clock = (1 << 8) | nxp.CCM_CCGR1_CG4_Pos // CCGR1, CG4 + clkIpEnet clock = (1 << 8) | nxp.CCM_CCGR1_CG5_Pos // CCGR1, CG5 + clkIpPit clock = (1 << 8) | nxp.CCM_CCGR1_CG6_Pos // CCGR1, CG6 + clkIpAoi2 clock = (1 << 8) | nxp.CCM_CCGR1_CG7_Pos // CCGR1, CG7 + clkIpAdc1 clock = (1 << 8) | nxp.CCM_CCGR1_CG8_Pos // CCGR1, CG8 + clkIpSemcExsc clock = (1 << 8) | nxp.CCM_CCGR1_CG9_Pos // CCGR1, CG9 + clkIpGpt1 clock = (1 << 8) | nxp.CCM_CCGR1_CG10_Pos // CCGR1, CG10 + clkIpGpt1S clock = (1 << 8) | nxp.CCM_CCGR1_CG11_Pos // CCGR1, CG11 + clkIpLpuart4 clock = (1 << 8) | nxp.CCM_CCGR1_CG12_Pos // CCGR1, CG12 + clkIpGpio1 clock = (1 << 8) | nxp.CCM_CCGR1_CG13_Pos // CCGR1, CG13 + clkIpCsu clock = (1 << 8) | nxp.CCM_CCGR1_CG14_Pos // CCGR1, CG14 + clkIpGpio5 clock = (1 << 8) | nxp.CCM_CCGR1_CG15_Pos // CCGR1, CG15 + + clkIpOcramExsc clock = (2 << 8) | nxp.CCM_CCGR2_CG0_Pos // CCGR2, CG0 + clkIpCsi clock = (2 << 8) | nxp.CCM_CCGR2_CG1_Pos // CCGR2, CG1 + clkIpIomuxcSnvs clock = (2 << 8) | nxp.CCM_CCGR2_CG2_Pos // CCGR2, CG2 + clkIpLpi2c1 clock = (2 << 8) | nxp.CCM_CCGR2_CG3_Pos // CCGR2, CG3 + clkIpLpi2c2 clock = (2 << 8) | nxp.CCM_CCGR2_CG4_Pos // CCGR2, CG4 + clkIpLpi2c3 clock = (2 << 8) | nxp.CCM_CCGR2_CG5_Pos // CCGR2, CG5 + clkIpOcotp clock = (2 << 8) | nxp.CCM_CCGR2_CG6_Pos // CCGR2, CG6 + clkIpXbar3 clock = (2 << 8) | nxp.CCM_CCGR2_CG7_Pos // CCGR2, CG7 + clkIpIpmux1 clock = (2 << 8) | nxp.CCM_CCGR2_CG8_Pos // CCGR2, CG8 + clkIpIpmux2 clock = (2 << 8) | nxp.CCM_CCGR2_CG9_Pos // CCGR2, CG9 + clkIpIpmux3 clock = (2 << 8) | nxp.CCM_CCGR2_CG10_Pos // CCGR2, CG10 + clkIpXbar1 clock = (2 << 8) | nxp.CCM_CCGR2_CG11_Pos // CCGR2, CG11 + clkIpXbar2 clock = (2 << 8) | nxp.CCM_CCGR2_CG12_Pos // CCGR2, CG12 + clkIpGpio3 clock = (2 << 8) | nxp.CCM_CCGR2_CG13_Pos // CCGR2, CG13 + clkIpLcd clock = (2 << 8) | nxp.CCM_CCGR2_CG14_Pos // CCGR2, CG14 + clkIpPxp clock = (2 << 8) | nxp.CCM_CCGR2_CG15_Pos // CCGR2, CG15 + + clkIpFlexio2 clock = (3 << 8) | nxp.CCM_CCGR3_CG0_Pos // CCGR3, CG0 + clkIpLpuart5 clock = (3 << 8) | nxp.CCM_CCGR3_CG1_Pos // CCGR3, CG1 + clkIpSemc clock = (3 << 8) | nxp.CCM_CCGR3_CG2_Pos // CCGR3, CG2 + clkIpLpuart6 clock = (3 << 8) | nxp.CCM_CCGR3_CG3_Pos // CCGR3, CG3 + clkIpAoi1 clock = (3 << 8) | nxp.CCM_CCGR3_CG4_Pos // CCGR3, CG4 + clkIpLcdPixel clock = (3 << 8) | nxp.CCM_CCGR3_CG5_Pos // CCGR3, CG5 + clkIpGpio4 clock = (3 << 8) | nxp.CCM_CCGR3_CG6_Pos // CCGR3, CG6 + clkIpEwm0 clock = (3 << 8) | nxp.CCM_CCGR3_CG7_Pos // CCGR3, CG7 + clkIpWdog1 clock = (3 << 8) | nxp.CCM_CCGR3_CG8_Pos // CCGR3, CG8 + clkIpFlexRam clock = (3 << 8) | nxp.CCM_CCGR3_CG9_Pos // CCGR3, CG9 + clkIpAcmp1 clock = (3 << 8) | nxp.CCM_CCGR3_CG10_Pos // CCGR3, CG10 + clkIpAcmp2 clock = (3 << 8) | nxp.CCM_CCGR3_CG11_Pos // CCGR3, CG11 + clkIpAcmp3 clock = (3 << 8) | nxp.CCM_CCGR3_CG12_Pos // CCGR3, CG12 + clkIpAcmp4 clock = (3 << 8) | nxp.CCM_CCGR3_CG13_Pos // CCGR3, CG13 + clkIpOcram clock = (3 << 8) | nxp.CCM_CCGR3_CG14_Pos // CCGR3, CG14 + clkIpIomuxcSnvsGpr clock = (3 << 8) | nxp.CCM_CCGR3_CG15_Pos // CCGR3, CG15 + + clkIpIomuxc clock = (4 << 8) | nxp.CCM_CCGR4_CG1_Pos // CCGR4, CG1 + clkIpIomuxcGpr clock = (4 << 8) | nxp.CCM_CCGR4_CG2_Pos // CCGR4, CG2 + clkIpBee clock = (4 << 8) | nxp.CCM_CCGR4_CG3_Pos // CCGR4, CG3 + clkIpSimM7 clock = (4 << 8) | nxp.CCM_CCGR4_CG4_Pos // CCGR4, CG4 + clkIpTsc clock = (4 << 8) | nxp.CCM_CCGR4_CG5_Pos // CCGR4, CG5 + clkIpSimM clock = (4 << 8) | nxp.CCM_CCGR4_CG6_Pos // CCGR4, CG6 + clkIpSimEms clock = (4 << 8) | nxp.CCM_CCGR4_CG7_Pos // CCGR4, CG7 + clkIpPwm1 clock = (4 << 8) | nxp.CCM_CCGR4_CG8_Pos // CCGR4, CG8 + clkIpPwm2 clock = (4 << 8) | nxp.CCM_CCGR4_CG9_Pos // CCGR4, CG9 + clkIpPwm3 clock = (4 << 8) | nxp.CCM_CCGR4_CG10_Pos // CCGR4, CG10 + clkIpPwm4 clock = (4 << 8) | nxp.CCM_CCGR4_CG11_Pos // CCGR4, CG11 + clkIpEnc1 clock = (4 << 8) | nxp.CCM_CCGR4_CG12_Pos // CCGR4, CG12 + clkIpEnc2 clock = (4 << 8) | nxp.CCM_CCGR4_CG13_Pos // CCGR4, CG13 + clkIpEnc3 clock = (4 << 8) | nxp.CCM_CCGR4_CG14_Pos // CCGR4, CG14 + clkIpEnc4 clock = (4 << 8) | nxp.CCM_CCGR4_CG15_Pos // CCGR4, CG15 + + clkIpRom clock = (5 << 8) | nxp.CCM_CCGR5_CG0_Pos // CCGR5, CG0 + clkIpFlexio1 clock = (5 << 8) | nxp.CCM_CCGR5_CG1_Pos // CCGR5, CG1 + clkIpWdog3 clock = (5 << 8) | nxp.CCM_CCGR5_CG2_Pos // CCGR5, CG2 + clkIpDma clock = (5 << 8) | nxp.CCM_CCGR5_CG3_Pos // CCGR5, CG3 + clkIpKpp clock = (5 << 8) | nxp.CCM_CCGR5_CG4_Pos // CCGR5, CG4 + clkIpWdog2 clock = (5 << 8) | nxp.CCM_CCGR5_CG5_Pos // CCGR5, CG5 + clkIpAipsTz4 clock = (5 << 8) | nxp.CCM_CCGR5_CG6_Pos // CCGR5, CG6 + clkIpSpdif clock = (5 << 8) | nxp.CCM_CCGR5_CG7_Pos // CCGR5, CG7 + clkIpSimMain clock = (5 << 8) | nxp.CCM_CCGR5_CG8_Pos // CCGR5, CG8 + clkIpSai1 clock = (5 << 8) | nxp.CCM_CCGR5_CG9_Pos // CCGR5, CG9 + clkIpSai2 clock = (5 << 8) | nxp.CCM_CCGR5_CG10_Pos // CCGR5, CG10 + clkIpSai3 clock = (5 << 8) | nxp.CCM_CCGR5_CG11_Pos // CCGR5, CG11 + clkIpLpuart1 clock = (5 << 8) | nxp.CCM_CCGR5_CG12_Pos // CCGR5, CG12 + clkIpLpuart7 clock = (5 << 8) | nxp.CCM_CCGR5_CG13_Pos // CCGR5, CG13 + clkIpSnvsHp clock = (5 << 8) | nxp.CCM_CCGR5_CG14_Pos // CCGR5, CG14 + clkIpSnvsLp clock = (5 << 8) | nxp.CCM_CCGR5_CG15_Pos // CCGR5, CG15 + + clkIpUsbOh3 clock = (6 << 8) | nxp.CCM_CCGR6_CG0_Pos // CCGR6, CG0 + clkIpUsdhc1 clock = (6 << 8) | nxp.CCM_CCGR6_CG1_Pos // CCGR6, CG1 + clkIpUsdhc2 clock = (6 << 8) | nxp.CCM_CCGR6_CG2_Pos // CCGR6, CG2 + clkIpDcdc clock = (6 << 8) | nxp.CCM_CCGR6_CG3_Pos // CCGR6, CG3 + clkIpIpmux4 clock = (6 << 8) | nxp.CCM_CCGR6_CG4_Pos // CCGR6, CG4 + clkIpFlexSpi clock = (6 << 8) | nxp.CCM_CCGR6_CG5_Pos // CCGR6, CG5 + clkIpTrng clock = (6 << 8) | nxp.CCM_CCGR6_CG6_Pos // CCGR6, CG6 + clkIpLpuart8 clock = (6 << 8) | nxp.CCM_CCGR6_CG7_Pos // CCGR6, CG7 + clkIpTimer4 clock = (6 << 8) | nxp.CCM_CCGR6_CG8_Pos // CCGR6, CG8 + clkIpAipsTz3 clock = (6 << 8) | nxp.CCM_CCGR6_CG9_Pos // CCGR6, CG9 + clkIpSimPer clock = (6 << 8) | nxp.CCM_CCGR6_CG10_Pos // CCGR6, CG10 + clkIpAnadig clock = (6 << 8) | nxp.CCM_CCGR6_CG11_Pos // CCGR6, CG11 + clkIpLpi2c4 clock = (6 << 8) | nxp.CCM_CCGR6_CG12_Pos // CCGR6, CG12 + clkIpTimer1 clock = (6 << 8) | nxp.CCM_CCGR6_CG13_Pos // CCGR6, CG13 + clkIpTimer2 clock = (6 << 8) | nxp.CCM_CCGR6_CG14_Pos // CCGR6, CG14 + clkIpTimer3 clock = (6 << 8) | nxp.CCM_CCGR6_CG15_Pos // CCGR6, CG15 + + clkIpEnet2 clock = (7 << 8) | nxp.CCM_CCGR7_CG0_Pos // CCGR7, CG0 + clkIpFlexSpi2 clock = (7 << 8) | nxp.CCM_CCGR7_CG1_Pos // CCGR7, CG1 + clkIpAxbsL clock = (7 << 8) | nxp.CCM_CCGR7_CG2_Pos // CCGR7, CG2 + clkIpCan3 clock = (7 << 8) | nxp.CCM_CCGR7_CG3_Pos // CCGR7, CG3 + clkIpCan3S clock = (7 << 8) | nxp.CCM_CCGR7_CG4_Pos // CCGR7, CG4 + clkIpAipsLite clock = (7 << 8) | nxp.CCM_CCGR7_CG5_Pos // CCGR7, CG5 + clkIpFlexio3 clock = (7 << 8) | nxp.CCM_CCGR7_CG6_Pos // CCGR7, CG6 +) + +// Selected clock offsets +const ( + offCCSR = 0x0C + offCBCDR = 0x14 + offCBCMR = 0x18 + offCSCMR1 = 0x1C + offCSCMR2 = 0x20 + offCSCDR1 = 0x24 + offCDCDR = 0x30 + offCSCDR2 = 0x38 + offCSCDR3 = 0x3C + offCACRR = 0x10 + offCS1CDR = 0x28 + offCS2CDR = 0x2C + + offPllArm = 0x00 + offPllSys = 0x30 + offPllUsb1 = 0x10 + offPllAudio = 0x70 + offPllVideo = 0xA0 + offPllEnet = 0xE0 + offPllUsb2 = 0x20 + + noBusyWait = 0x20 +) + +// analog pll definition +const ( + pllBypassPos = 16 + pllBypassClkSrcMsk = 0xC000 + pllBypassClkSrcPos = 14 +) + +// getFreq returns the calculated frequency of the receiver clock clk. +func (clk clock) getFreq() uint32 { + switch clk { + case clkCpu, clkAhb: + return getAhbFreq() + case clkSemc: + return getSemcFreq() + case clkIpg: + return getIpgFreq() + case clkPer: + return getPerClkFreq() + case clkOsc: + return getOscFreq() + case clkRtc: + return getRtcFreq() + case clkArmPll: + return clkPllArm.getPllFreq() + case clkUsb1Pll: + return clkPllUsb1.getPllFreq() + case clkUsb1PllPfd0: + return clkPfd0.getUsb1PfdFreq() + case clkUsb1PllPfd1: + return clkPfd1.getUsb1PfdFreq() + case clkUsb1PllPfd2: + return clkPfd2.getUsb1PfdFreq() + case clkUsb1PllPfd3: + return clkPfd3.getUsb1PfdFreq() + case clkUsb2Pll: + return clkPllUsb2.getPllFreq() + case clkSysPll: + return clkPllSys.getPllFreq() + case clkSysPllPfd0: + return clkPfd0.getSysPfdFreq() + case clkSysPllPfd1: + return clkPfd1.getSysPfdFreq() + case clkSysPllPfd2: + return clkPfd2.getSysPfdFreq() + case clkSysPllPfd3: + return clkPfd3.getSysPfdFreq() + case clkEnetPll0: + return clkPllEnet.getPllFreq() + case clkEnetPll1: + return clkPllEnet2.getPllFreq() + case clkEnetPll2: + return clkPllEnet25M.getPllFreq() + case clkAudioPll: + return clkPllAudio.getPllFreq() + case clkVideoPll: + return clkPllVideo.getPllFreq() + default: + panic("runtime: 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 << nxp.CCM_CBCMR_PERIPH_CLK2_SEL_Pos) & nxp.CCM_CBCMR_PERIPH_CLK2_SEL_Msk +} + +func ccmCbcmrPrePeriphClkSel(n uint32) uint32 { + return (n << nxp.CCM_CBCMR_PRE_PERIPH_CLK_SEL_Pos) & nxp.CCM_CBCMR_PRE_PERIPH_CLK_SEL_Msk +} + +// getPeriphClkFreq returns the PERIPH clock frequency +func getPeriphClkFreq() uint32 { + freq := uint32(0) + if nxp.CCM.CBCDR.HasBits(nxp.CCM_CBCDR_PERIPH_CLK_SEL_Msk) { + // Periph_clk2_clk -> Periph_clk + switch nxp.CCM.CBCMR.Get() & nxp.CCM_CBCMR_PERIPH_CLK2_SEL_Msk { + case ccmCbcmrPeriphClk2Sel(0): + // Pll3_sw_clk -> Periph_clk2_clk -> Periph_clk + freq = clkPllUsb1.getPllFreq() + case ccmCbcmrPeriphClk2Sel(1): + // Osc_clk -> Periph_clk2_clk -> Periph_clk + freq = getOscFreq() + case ccmCbcmrPeriphClk2Sel(2): + freq = clkPllSys.getPllFreq() + case ccmCbcmrPeriphClk2Sel(3): + freq = 0 + } + freq /= ((nxp.CCM.CBCDR.Get() & nxp.CCM_CBCDR_PERIPH_CLK2_PODF_Msk) >> nxp.CCM_CBCDR_PERIPH_CLK2_PODF_Pos) + 1 + } else { + // Pre_Periph_clk -> Periph_clk + switch nxp.CCM.CBCMR.Get() & nxp.CCM_CBCMR_PRE_PERIPH_CLK_SEL_Msk { + case ccmCbcmrPrePeriphClkSel(0): + // PLL2 -> Pre_Periph_clk -> Periph_clk + freq = clkPllSys.getPllFreq() + case ccmCbcmrPrePeriphClkSel(1): + // PLL2 PFD2 -> Pre_Periph_clk -> Periph_clk + freq = clkPfd2.getSysPfdFreq() + case ccmCbcmrPrePeriphClkSel(2): + // PLL2 PFD0 -> Pre_Periph_clk -> Periph_clk + freq = clkPfd0.getSysPfdFreq() + case ccmCbcmrPrePeriphClkSel(3): + // PLL1 divided(/2) -> Pre_Periph_clk -> Periph_clk + freq = clkPllArm.getPllFreq() / (((nxp.CCM.CACRR.Get() & nxp.CCM_CACRR_ARM_PODF_Msk) >> nxp.CCM_CACRR_ARM_PODF_Pos) + 1) + } + } + return freq +} + +// getAhbFreq returns the AHB clock frequency +func getAhbFreq() uint32 { + return getPeriphClkFreq() / (((nxp.CCM.CBCDR.Get() & nxp.CCM_CBCDR_AHB_PODF_Msk) >> nxp.CCM_CBCDR_AHB_PODF_Pos) + 1) +} + +// getSemcFreq returns the SEMC clock frequency +func getSemcFreq() uint32 { + + freq := uint32(0) + + if nxp.CCM.CBCDR.HasBits(nxp.CCM_CBCDR_SEMC_CLK_SEL_Msk) { + // SEMC alternative clock -> SEMC Clock + + if nxp.CCM.CBCDR.HasBits(nxp.CCM_CBCDR_SEMC_ALT_CLK_SEL_Msk) { + // PLL3 PFD1 -> SEMC alternative clock -> SEMC Clock + freq = clkPfd1.getUsb1PfdFreq() + } else { + // PLL2 PFD2 -> SEMC alternative clock -> SEMC Clock + freq = clkPfd2.getSysPfdFreq() + } + } else { + // Periph_clk -> SEMC Clock + freq = getPeriphClkFreq() + } + + freq /= ((nxp.CCM.CBCDR.Get() & nxp.CCM_CBCDR_SEMC_PODF_Msk) >> nxp.CCM_CBCDR_SEMC_PODF_Pos) + 1 + + return freq +} + +// getIpgFreq returns the IPG clock frequency +func getIpgFreq() uint32 { + return getAhbFreq() / (((nxp.CCM.CBCDR.Get() & nxp.CCM_CBCDR_IPG_PODF_Msk) >> nxp.CCM_CBCDR_IPG_PODF_Pos) + 1) +} + +// getPerClkFreq returns the PER clock frequency +func getPerClkFreq() uint32 { + freq := uint32(0) + if nxp.CCM.CSCMR1.HasBits(nxp.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/((nxp.CCM.CSCMR1.Get()&nxp.CCM_CSCMR1_PERCLK_PODF_Msk)>> + nxp.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 clkPllArm: + freq *= (nxp.CCM_ANALOG.PLL_ARM.Get() & nxp.CCM_ANALOG_PLL_ARM_DIV_SELECT_Msk) >> nxp.CCM_ANALOG_PLL_ARM_DIV_SELECT_Pos + freq >>= 1 + case clkPllSys: + // PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM). + fFreq := float64(freq) * float64(nxp.CCM_ANALOG.PLL_SYS_NUM.Get()) + fFreq /= float64(nxp.CCM_ANALOG.PLL_SYS_DENOM.Get()) + if nxp.CCM_ANALOG.PLL_SYS.HasBits(nxp.CCM_ANALOG_PLL_SYS_DIV_SELECT_Msk) { + freq *= 22 + } else { + freq *= 20 + } + freq += uint32(fFreq) + case clkPllUsb1: + if nxp.CCM_ANALOG.PLL_USB1.HasBits(nxp.CCM_ANALOG_PLL_USB1_DIV_SELECT_Msk) { + freq *= 22 + } else { + freq *= 20 + } + case clkPllEnet: + divSelect := (nxp.CCM_ANALOG.PLL_ENET.Get() & nxp.CCM_ANALOG_PLL_ENET_DIV_SELECT_Msk) >> nxp.CCM_ANALOG_PLL_ENET_DIV_SELECT_Pos + freq = enetRefClkFreq[divSelect] + case clkPllEnet2: + divSelect := (nxp.CCM_ANALOG.PLL_ENET.Get() & nxp.CCM_ANALOG_PLL_ENET_ENET2_DIV_SELECT_Msk) >> nxp.CCM_ANALOG_PLL_ENET_ENET2_DIV_SELECT_Pos + freq = enetRefClkFreq[divSelect] + case clkPllEnet25M: + // ref_enetpll1 if fixed at 25MHz. + freq = 25000000 + case clkPllUsb2: + if nxp.CCM_ANALOG.PLL_USB2.HasBits(nxp.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 := clkPllSys.getPllFreq() + switch clk { + case clkPfd0: + freq /= (nxp.CCM_ANALOG.PFD_528.Get() & nxp.CCM_ANALOG_PFD_528_PFD0_FRAC_Msk) >> nxp.CCM_ANALOG_PFD_528_PFD0_FRAC_Pos + case clkPfd1: + freq /= (nxp.CCM_ANALOG.PFD_528.Get() & nxp.CCM_ANALOG_PFD_528_PFD1_FRAC_Msk) >> nxp.CCM_ANALOG_PFD_528_PFD1_FRAC_Pos + case clkPfd2: + freq /= (nxp.CCM_ANALOG.PFD_528.Get() & nxp.CCM_ANALOG_PFD_528_PFD2_FRAC_Msk) >> nxp.CCM_ANALOG_PFD_528_PFD2_FRAC_Pos + case clkPfd3: + freq /= (nxp.CCM_ANALOG.PFD_528.Get() & nxp.CCM_ANALOG_PFD_528_PFD3_FRAC_Msk) >> nxp.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 := clkPllUsb1.getPllFreq() + switch clk { + case clkPfd0: + freq /= (nxp.CCM_ANALOG.PFD_480.Get() & nxp.CCM_ANALOG_PFD_480_PFD0_FRAC_Msk) >> nxp.CCM_ANALOG_PFD_480_PFD0_FRAC_Pos + case clkPfd1: + freq /= (nxp.CCM_ANALOG.PFD_480.Get() & nxp.CCM_ANALOG_PFD_480_PFD1_FRAC_Msk) >> nxp.CCM_ANALOG_PFD_480_PFD1_FRAC_Pos + case clkPfd2: + freq /= (nxp.CCM_ANALOG.PFD_480.Get() & nxp.CCM_ANALOG_PFD_480_PFD2_FRAC_Msk) >> nxp.CCM_ANALOG_PFD_480_PFD2_FRAC_Pos + case clkPfd3: + freq /= (nxp.CCM_ANALOG.PFD_480.Get() & nxp.CCM_ANALOG_PFD_480_PFD3_FRAC_Msk) >> nxp.CCM_ANALOG_PFD_480_PFD3_FRAC_Pos + default: + freq = 0 + } + return freq * 18 +} + +// getCCGR returns the CCM clock gating register for the receiver clk. +func (clk clock) getCCGR() *volatile.Register32 { + switch clk >> 8 { + case 0: + return &nxp.CCM.CCGR0 + case 1: + return &nxp.CCM.CCGR1 + case 2: + return &nxp.CCM.CCGR2 + case 3: + return &nxp.CCM.CCGR3 + case 4: + return &nxp.CCM.CCGR4 + case 5: + return &nxp.CCM.CCGR5 + case 6: + return &nxp.CCM.CCGR6 + case 7: + return &nxp.CCM.CCGR7 + default: + panic("runtime: invalid clock") + } +} + +// control enables or disables the receiver clk using its gating register. +func (clk clock) control(value gate) { + reg := clk.getCCGR() + shift := clk & 0x1F + reg.Set((reg.Get() & ^(3 << shift)) | (uint32(value) << shift)) +} + +func (clk clock) enable(enable bool) { + if enable { + clk.control(gateClkNeededRunWait) + } else { + clk.control(gateClkNotNeeded) + } +} + +func (clk clock) mux(mux uint32) { clk.ccm(mux) } +func (clk clock) div(div uint32) { clk.ccm(div) } + +func (clk clock) ccm(value uint32) { + const ccmBase = 0x400fc000 + reg := (*volatile.Register32)(unsafe.Pointer(uintptr(ccmBase + (uint32(clk) & 0xFF)))) + msk := ((uint32(clk) >> 13) & 0x1FFF) << ((uint32(clk) >> 8) & 0x1F) + pos := (uint32(clk) >> 8) & 0x1F + bsy := (uint32(clk) >> 26) & 0x3F + reg.Set((reg.Get() & ^uint32(msk)) | ((value << pos) & msk)) + if bsy < noBusyWait { + for nxp.CCM.CDHIPR.HasBits(1 << bsy) { + } + } +} + +func setSysPfd(value ...uint32) { + for i, val := range value { + pfd528 := nxp.CCM_ANALOG.PFD_528.Get() & + ^((nxp.CCM_ANALOG_PFD_528_PFD0_CLKGATE_Msk | nxp.CCM_ANALOG_PFD_528_PFD0_FRAC_Msk) << (8 * uint32(i))) + frac := (val << nxp.CCM_ANALOG_PFD_528_PFD0_FRAC_Pos) & nxp.CCM_ANALOG_PFD_528_PFD0_FRAC_Msk + // disable the clock output first + nxp.CCM_ANALOG.PFD_528.Set(pfd528 | (nxp.CCM_ANALOG_PFD_528_PFD0_CLKGATE_Msk << (8 * uint32(i)))) + // set the new value and enable output + nxp.CCM_ANALOG.PFD_528.Set(pfd528 | (frac << (8 * uint32(i)))) + } +} + +func setUsb1Pfd(value ...uint32) { + for i, val := range value { + pfd480 := nxp.CCM_ANALOG.PFD_480.Get() & + ^((nxp.CCM_ANALOG_PFD_480_PFD0_CLKGATE_Msk | nxp.CCM_ANALOG_PFD_480_PFD0_FRAC_Msk) << (8 * uint32(i))) + frac := (val << nxp.CCM_ANALOG_PFD_480_PFD0_FRAC_Pos) & nxp.CCM_ANALOG_PFD_480_PFD0_FRAC_Msk + // disable the clock output first + nxp.CCM_ANALOG.PFD_480.Set(pfd480 | (nxp.CCM_ANALOG_PFD_480_PFD0_CLKGATE_Msk << (8 * uint32(i)))) + // set the new value and enable output + nxp.CCM_ANALOG.PFD_480.Set(pfd480 | (frac << (8 * uint32(i)))) + } +} + +func (clk clock) isPllEnabled() bool { + const ccmAnalogBase = 0x400d8000 + addr := ccmAnalogBase + ((uint32(clk) >> 16) & 0xFFF) + pos := uint32(1 << (uint32(clk) & 0x1F)) + return ((*volatile.Register32)(unsafe.Pointer(uintptr(addr)))).HasBits(pos) +} + +func (clk clock) isPllBypassed() bool { + const ccmAnalogBase = 0x400d8000 + addr := ccmAnalogBase + ((uint32(clk) >> 16) & 0xFFF) + pos := uint32(1 << pllBypassPos) + return ((*volatile.Register32)(unsafe.Pointer(uintptr(addr)))).HasBits(pos) +} + +func (clk clock) getBypassFreq() uint32 { + const ccmAnalogBase = 0x400d8000 + addr := ccmAnalogBase + ((uint32(clk) >> 16) & 0xFFF) + src := (((*volatile.Register32)(unsafe.Pointer(uintptr(addr)))).Get() & + pllBypassClkSrcMsk) >> pllBypassClkSrcPos + if src == uint32(pllSrc24M) { + return getOscFreq() + } + return 0 +} + +func (clk clock) bypass(bypass bool) { + const ccmAnalogBase = 0x400d8000 + if bypass { + addr := ccmAnalogBase + ((uint32(clk) >> 16) & 0xFFF) + 4 + ((*volatile.Register32)(unsafe.Pointer(uintptr(addr)))).Set(1 << pllBypassPos) + } else { + addr := ccmAnalogBase + ((uint32(clk) >> 16) & 0xFFF) + 8 + ((*volatile.Register32)(unsafe.Pointer(uintptr(addr)))).Set(1 << pllBypassPos) + } +} + +const ( + oscRc = 0 // On chip OSC + oscXtal = 1 // 24M Xtal OSC +) + +type gate uint8 + +const ( + gateClkNotNeeded gate = 0 // Clock is off during all modes + gateClkNeededRun gate = 1 // Clock is on in run mode, but off in WAIT and STOP modes + gateClkNeededRunWait gate = 3 // Clock is on during all modes, except STOP mode +) + +type clockMode uint8 + +const ( + modeClkRun clockMode = 0 // Remain in run mode + modeClkWait clockMode = 1 // Transfer to wait mode + modeClkStop clockMode = 2 // Transfer to stop mode +) + +func (m clockMode) set() { + nxp.CCM.CLPCR.Set((nxp.CCM.CLPCR.Get() & ^uint32(nxp.CCM_CLPCR_LPM_Msk)) | + ((uint32(m) << nxp.CCM_CLPCR_LPM_Pos) & nxp.CCM_CLPCR_LPM_Msk)) +} + +const ( + muxIpPll3Sw clock = (offCCSR & 0xFF) | (nxp.CCM_CCSR_PLL3_SW_CLK_SEL_Pos << 8) | (((nxp.CCM_CCSR_PLL3_SW_CLK_SEL_Msk >> nxp.CCM_CCSR_PLL3_SW_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // pll3_sw_clk mux name + muxIpPeriph clock = (offCBCDR & 0xFF) | (nxp.CCM_CBCDR_PERIPH_CLK_SEL_Pos << 8) | (((nxp.CCM_CBCDR_PERIPH_CLK_SEL_Msk >> nxp.CCM_CBCDR_PERIPH_CLK_SEL_Pos) & 0x1FFF) << 13) | (nxp.CCM_CDHIPR_PERIPH_CLK_SEL_BUSY_Pos << 26) // periph mux name + muxIpSemcAlt clock = (offCBCDR & 0xFF) | (nxp.CCM_CBCDR_SEMC_ALT_CLK_SEL_Pos << 8) | (((nxp.CCM_CBCDR_SEMC_ALT_CLK_SEL_Msk >> nxp.CCM_CBCDR_SEMC_ALT_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // semc mux name + muxIpSemc clock = (offCBCDR & 0xFF) | (nxp.CCM_CBCDR_SEMC_CLK_SEL_Pos << 8) | (((nxp.CCM_CBCDR_SEMC_CLK_SEL_Msk >> nxp.CCM_CBCDR_SEMC_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // semc mux name + muxIpPrePeriph clock = (offCBCMR & 0xFF) | (nxp.CCM_CBCMR_PRE_PERIPH_CLK_SEL_Pos << 8) | (((nxp.CCM_CBCMR_PRE_PERIPH_CLK_SEL_Msk >> nxp.CCM_CBCMR_PRE_PERIPH_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // pre-periph mux name + muxIpTrace clock = (offCBCMR & 0xFF) | (nxp.CCM_CBCMR_TRACE_CLK_SEL_Pos << 8) | (((nxp.CCM_CBCMR_TRACE_CLK_SEL_Msk >> nxp.CCM_CBCMR_TRACE_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // trace mux name + muxIpPeriphClk2 clock = (offCBCMR & 0xFF) | (nxp.CCM_CBCMR_PERIPH_CLK2_SEL_Pos << 8) | (((nxp.CCM_CBCMR_PERIPH_CLK2_SEL_Msk >> nxp.CCM_CBCMR_PERIPH_CLK2_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // periph clock2 mux name + muxIpFlexSpi2 clock = (offCBCMR & 0xFF) | (nxp.CCM_CBCMR_FLEXSPI2_CLK_SEL_Pos << 8) | (((nxp.CCM_CBCMR_FLEXSPI2_CLK_SEL_Msk >> nxp.CCM_CBCMR_FLEXSPI2_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // flexspi2 mux name + muxIpLpspi clock = (offCBCMR & 0xFF) | (nxp.CCM_CBCMR_LPSPI_CLK_SEL_Pos << 8) | (((nxp.CCM_CBCMR_LPSPI_CLK_SEL_Msk >> nxp.CCM_CBCMR_LPSPI_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // lpspi mux name + muxIpFlexSpi clock = (offCSCMR1 & 0xFF) | (nxp.CCM_CSCMR1_FLEXSPI_CLK_SEL_Pos << 8) | (((nxp.CCM_CSCMR1_FLEXSPI_CLK_SEL_Msk >> nxp.CCM_CSCMR1_FLEXSPI_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // flexspi mux name + muxIpUsdhc2 clock = (offCSCMR1 & 0xFF) | (nxp.CCM_CSCMR1_USDHC2_CLK_SEL_Pos << 8) | (((nxp.CCM_CSCMR1_USDHC2_CLK_SEL_Msk >> nxp.CCM_CSCMR1_USDHC2_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // usdhc2 mux name + muxIpUsdhc1 clock = (offCSCMR1 & 0xFF) | (nxp.CCM_CSCMR1_USDHC1_CLK_SEL_Pos << 8) | (((nxp.CCM_CSCMR1_USDHC1_CLK_SEL_Msk >> nxp.CCM_CSCMR1_USDHC1_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // usdhc1 mux name + muxIpSai3 clock = (offCSCMR1 & 0xFF) | (nxp.CCM_CSCMR1_SAI3_CLK_SEL_Pos << 8) | (((nxp.CCM_CSCMR1_SAI3_CLK_SEL_Msk >> nxp.CCM_CSCMR1_SAI3_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // sai3 mux name + muxIpSai2 clock = (offCSCMR1 & 0xFF) | (nxp.CCM_CSCMR1_SAI2_CLK_SEL_Pos << 8) | (((nxp.CCM_CSCMR1_SAI2_CLK_SEL_Msk >> nxp.CCM_CSCMR1_SAI2_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // sai2 mux name + muxIpSai1 clock = (offCSCMR1 & 0xFF) | (nxp.CCM_CSCMR1_SAI1_CLK_SEL_Pos << 8) | (((nxp.CCM_CSCMR1_SAI1_CLK_SEL_Msk >> nxp.CCM_CSCMR1_SAI1_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // sai1 mux name + muxIpPerclk clock = (offCSCMR1 & 0xFF) | (nxp.CCM_CSCMR1_PERCLK_CLK_SEL_Pos << 8) | (((nxp.CCM_CSCMR1_PERCLK_CLK_SEL_Msk >> nxp.CCM_CSCMR1_PERCLK_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // perclk mux name + muxIpFlexio2 clock = (offCSCMR2 & 0xFF) | (nxp.CCM_CSCMR2_FLEXIO2_CLK_SEL_Pos << 8) | (((nxp.CCM_CSCMR2_FLEXIO2_CLK_SEL_Msk >> nxp.CCM_CSCMR2_FLEXIO2_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // flexio2 mux name + muxIpCan clock = (offCSCMR2 & 0xFF) | (nxp.CCM_CSCMR2_CAN_CLK_SEL_Pos << 8) | (((nxp.CCM_CSCMR2_CAN_CLK_SEL_Msk >> nxp.CCM_CSCMR2_CAN_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // can mux name + muxIpUart clock = (offCSCDR1 & 0xFF) | (nxp.CCM_CSCDR1_UART_CLK_SEL_Pos << 8) | (((nxp.CCM_CSCDR1_UART_CLK_SEL_Msk >> nxp.CCM_CSCDR1_UART_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // uart mux name + muxIpSpdif clock = (offCDCDR & 0xFF) | (nxp.CCM_CDCDR_SPDIF0_CLK_SEL_Pos << 8) | (((nxp.CCM_CDCDR_SPDIF0_CLK_SEL_Msk >> nxp.CCM_CDCDR_SPDIF0_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // spdif mux name + muxIpFlexio1 clock = (offCDCDR & 0xFF) | (nxp.CCM_CDCDR_FLEXIO1_CLK_SEL_Pos << 8) | (((nxp.CCM_CDCDR_FLEXIO1_CLK_SEL_Msk >> nxp.CCM_CDCDR_FLEXIO1_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // flexio1 mux name + muxIpLpi2c clock = (offCSCDR2 & 0xFF) | (nxp.CCM_CSCDR2_LPI2C_CLK_SEL_Pos << 8) | (((nxp.CCM_CSCDR2_LPI2C_CLK_SEL_Msk >> nxp.CCM_CSCDR2_LPI2C_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // lpi2c mux name + muxIpLcdifPre clock = (offCSCDR2 & 0xFF) | (nxp.CCM_CSCDR2_LCDIF_PRE_CLK_SEL_Pos << 8) | (((nxp.CCM_CSCDR2_LCDIF_PRE_CLK_SEL_Msk >> nxp.CCM_CSCDR2_LCDIF_PRE_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // lcdif pre mux name + muxIpCsi clock = (offCSCDR3 & 0xFF) | (nxp.CCM_CSCDR3_CSI_CLK_SEL_Pos << 8) | (((nxp.CCM_CSCDR3_CSI_CLK_SEL_Msk >> nxp.CCM_CSCDR3_CSI_CLK_SEL_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // csi mux name +) + +const ( + divIpArm clock = (offCACRR & 0xFF) | (nxp.CCM_CACRR_ARM_PODF_Pos << 8) | (((nxp.CCM_CACRR_ARM_PODF_Msk >> nxp.CCM_CACRR_ARM_PODF_Pos) & 0x1FFF) << 13) | (nxp.CCM_CDHIPR_ARM_PODF_BUSY_Pos << 26) // core div name + divIpPeriphClk2 clock = (offCBCDR & 0xFF) | (nxp.CCM_CBCDR_PERIPH_CLK2_PODF_Pos << 8) | (((nxp.CCM_CBCDR_PERIPH_CLK2_PODF_Msk >> nxp.CCM_CBCDR_PERIPH_CLK2_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // periph clock2 div name + divIpSemc clock = (offCBCDR & 0xFF) | (nxp.CCM_CBCDR_SEMC_PODF_Pos << 8) | (((nxp.CCM_CBCDR_SEMC_PODF_Msk >> nxp.CCM_CBCDR_SEMC_PODF_Pos) & 0x1FFF) << 13) | (nxp.CCM_CDHIPR_SEMC_PODF_BUSY_Pos << 26) // semc div name + divIpAhb clock = (offCBCDR & 0xFF) | (nxp.CCM_CBCDR_AHB_PODF_Pos << 8) | (((nxp.CCM_CBCDR_AHB_PODF_Msk >> nxp.CCM_CBCDR_AHB_PODF_Pos) & 0x1FFF) << 13) | (nxp.CCM_CDHIPR_AHB_PODF_BUSY_Pos << 26) // ahb div name + divIpIpg clock = (offCBCDR & 0xFF) | (nxp.CCM_CBCDR_IPG_PODF_Pos << 8) | (((nxp.CCM_CBCDR_IPG_PODF_Msk >> nxp.CCM_CBCDR_IPG_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // ipg div name + divIpFlexSpi2 clock = (offCBCMR & 0xFF) | (nxp.CCM_CBCMR_FLEXSPI2_PODF_Pos << 8) | (((nxp.CCM_CBCMR_FLEXSPI2_PODF_Msk >> nxp.CCM_CBCMR_FLEXSPI2_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // flexspi2 div name + divIpLpspi clock = (offCBCMR & 0xFF) | (nxp.CCM_CBCMR_LPSPI_PODF_Pos << 8) | (((nxp.CCM_CBCMR_LPSPI_PODF_Msk >> nxp.CCM_CBCMR_LPSPI_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // lpspi div name + divIpLcdif clock = (offCBCMR & 0xFF) | (nxp.CCM_CBCMR_LCDIF_PODF_Pos << 8) | (((nxp.CCM_CBCMR_LCDIF_PODF_Msk >> nxp.CCM_CBCMR_LCDIF_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // lcdif div name + divIpFlexSpi clock = (offCSCMR1 & 0xFF) | (nxp.CCM_CSCMR1_FLEXSPI_PODF_Pos << 8) | (((nxp.CCM_CSCMR1_FLEXSPI_PODF_Msk >> nxp.CCM_CSCMR1_FLEXSPI_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // flexspi div name + divIpPerclk clock = (offCSCMR1 & 0xFF) | (nxp.CCM_CSCMR1_PERCLK_PODF_Pos << 8) | (((nxp.CCM_CSCMR1_PERCLK_PODF_Msk >> nxp.CCM_CSCMR1_PERCLK_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // perclk div name + divIpCan clock = (offCSCMR2 & 0xFF) | (nxp.CCM_CSCMR2_CAN_CLK_PODF_Pos << 8) | (((nxp.CCM_CSCMR2_CAN_CLK_PODF_Msk >> nxp.CCM_CSCMR2_CAN_CLK_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // can div name + divIpTrace clock = (offCSCDR1 & 0xFF) | (nxp.CCM_CSCDR1_TRACE_PODF_Pos << 8) | (((nxp.CCM_CSCDR1_TRACE_PODF_Msk >> nxp.CCM_CSCDR1_TRACE_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // trace div name + divIpUsdhc2 clock = (offCSCDR1 & 0xFF) | (nxp.CCM_CSCDR1_USDHC2_PODF_Pos << 8) | (((nxp.CCM_CSCDR1_USDHC2_PODF_Msk >> nxp.CCM_CSCDR1_USDHC2_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // usdhc2 div name + divIpUsdhc1 clock = (offCSCDR1 & 0xFF) | (nxp.CCM_CSCDR1_USDHC1_PODF_Pos << 8) | (((nxp.CCM_CSCDR1_USDHC1_PODF_Msk >> nxp.CCM_CSCDR1_USDHC1_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // usdhc1 div name + divIpUart clock = (offCSCDR1 & 0xFF) | (nxp.CCM_CSCDR1_UART_CLK_PODF_Pos << 8) | (((nxp.CCM_CSCDR1_UART_CLK_PODF_Msk >> nxp.CCM_CSCDR1_UART_CLK_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // uart div name + divIpFlexio2 clock = (offCS1CDR & 0xFF) | (nxp.CCM_CS1CDR_FLEXIO2_CLK_PODF_Pos << 8) | (((nxp.CCM_CS1CDR_FLEXIO2_CLK_PODF_Msk >> nxp.CCM_CS1CDR_FLEXIO2_CLK_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // flexio2 pre div name + divIpSai3Pre clock = (offCS1CDR & 0xFF) | (nxp.CCM_CS1CDR_SAI3_CLK_PRED_Pos << 8) | (((nxp.CCM_CS1CDR_SAI3_CLK_PRED_Msk >> nxp.CCM_CS1CDR_SAI3_CLK_PRED_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // sai3 pre div name + divIpSai3 clock = (offCS1CDR & 0xFF) | (nxp.CCM_CS1CDR_SAI3_CLK_PODF_Pos << 8) | (((nxp.CCM_CS1CDR_SAI3_CLK_PODF_Msk >> nxp.CCM_CS1CDR_SAI3_CLK_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // sai3 div name + divIpFlexio2Pre clock = (offCS1CDR & 0xFF) | (nxp.CCM_CS1CDR_FLEXIO2_CLK_PRED_Pos << 8) | (((nxp.CCM_CS1CDR_FLEXIO2_CLK_PRED_Msk >> nxp.CCM_CS1CDR_FLEXIO2_CLK_PRED_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // sai3 pre div name + divIpSai1Pre clock = (offCS1CDR & 0xFF) | (nxp.CCM_CS1CDR_SAI1_CLK_PRED_Pos << 8) | (((nxp.CCM_CS1CDR_SAI1_CLK_PRED_Msk >> nxp.CCM_CS1CDR_SAI1_CLK_PRED_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // sai1 pre div name + divIpSai1 clock = (offCS1CDR & 0xFF) | (nxp.CCM_CS1CDR_SAI1_CLK_PODF_Pos << 8) | (((nxp.CCM_CS1CDR_SAI1_CLK_PODF_Msk >> nxp.CCM_CS1CDR_SAI1_CLK_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // sai1 div name + divIpSai2Pre clock = (offCS2CDR & 0xFF) | (nxp.CCM_CS2CDR_SAI2_CLK_PRED_Pos << 8) | (((nxp.CCM_CS2CDR_SAI2_CLK_PRED_Msk >> nxp.CCM_CS2CDR_SAI2_CLK_PRED_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // sai2 pre div name + divIpSai2 clock = (offCS2CDR & 0xFF) | (nxp.CCM_CS2CDR_SAI2_CLK_PODF_Pos << 8) | (((nxp.CCM_CS2CDR_SAI2_CLK_PODF_Msk >> nxp.CCM_CS2CDR_SAI2_CLK_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // sai2 div name + divIpSpdif0Pre clock = (offCDCDR & 0xFF) | (nxp.CCM_CDCDR_SPDIF0_CLK_PRED_Pos << 8) | (((nxp.CCM_CDCDR_SPDIF0_CLK_PRED_Msk >> nxp.CCM_CDCDR_SPDIF0_CLK_PRED_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // spdif pre div name + divIpSpdif0 clock = (offCDCDR & 0xFF) | (nxp.CCM_CDCDR_SPDIF0_CLK_PODF_Pos << 8) | (((nxp.CCM_CDCDR_SPDIF0_CLK_PODF_Msk >> nxp.CCM_CDCDR_SPDIF0_CLK_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // spdif div name + divIpFlexio1Pre clock = (offCDCDR & 0xFF) | (nxp.CCM_CDCDR_FLEXIO1_CLK_PRED_Pos << 8) | (((nxp.CCM_CDCDR_FLEXIO1_CLK_PRED_Msk >> nxp.CCM_CDCDR_FLEXIO1_CLK_PRED_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // flexio1 pre div name + divIpFlexio1 clock = (offCDCDR & 0xFF) | (nxp.CCM_CDCDR_FLEXIO1_CLK_PODF_Pos << 8) | (((nxp.CCM_CDCDR_FLEXIO1_CLK_PODF_Msk >> nxp.CCM_CDCDR_FLEXIO1_CLK_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // flexio1 div name + divIpLpi2c clock = (offCSCDR2 & 0xFF) | (nxp.CCM_CSCDR2_LPI2C_CLK_PODF_Pos << 8) | (((nxp.CCM_CSCDR2_LPI2C_CLK_PODF_Msk >> nxp.CCM_CSCDR2_LPI2C_CLK_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // lpi2c div name + divIpLcdifPre clock = (offCSCDR2 & 0xFF) | (nxp.CCM_CSCDR2_LCDIF_PRED_Pos << 8) | (((nxp.CCM_CSCDR2_LCDIF_PRED_Msk >> nxp.CCM_CSCDR2_LCDIF_PRED_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // lcdif pre div name + divIpCsi clock = (offCSCDR3 & 0xFF) | (nxp.CCM_CSCDR3_CSI_PODF_Pos << 8) | (((nxp.CCM_CSCDR3_CSI_PODF_Msk >> nxp.CCM_CSCDR3_CSI_PODF_Pos) & 0x1FFF) << 13) | (noBusyWait << 26) // csi div name +) + +// USB clock source +const ( + usbSrc480M = 0 // Use 480M + usbSrcUnused = 0xFFFFFFFF // Used when the function does not care the clock source +) + +// Source of the USB HS PHY +const ( + usbhsPhy480M = 0 // Use 480M +) + +// PLL clock source, bypass cloco source also +const ( + pllSrc24M = 0 // Pll clock source 24M + pllSrcClkPN = 1 // Pll clock source CLK1_P and CLK1_N +) + +// PLL configuration for ARM +type clockConfigArmPll struct { + loopDivider uint32 // PLL loop divider. Valid range for divider value: 54-108. Fout=Fin*loopDivider/2. + src uint8 // Pll clock source, reference _clock_pll_clk_src +} + +func (cfg clockConfigArmPll) configure() { + + // bypass PLL first + src := (uint32(cfg.src) << nxp.CCM_ANALOG_PLL_ARM_BYPASS_CLK_SRC_Pos) & nxp.CCM_ANALOG_PLL_ARM_BYPASS_CLK_SRC_Msk + nxp.CCM_ANALOG.PLL_ARM.Set( + (nxp.CCM_ANALOG.PLL_ARM.Get() & ^uint32(nxp.CCM_ANALOG_PLL_ARM_BYPASS_CLK_SRC_Msk)) | + nxp.CCM_ANALOG_PLL_ARM_BYPASS_Msk | src) + + sel := (cfg.loopDivider << nxp.CCM_ANALOG_PLL_ARM_DIV_SELECT_Pos) & nxp.CCM_ANALOG_PLL_ARM_DIV_SELECT_Msk + nxp.CCM_ANALOG.PLL_ARM.Set( + (nxp.CCM_ANALOG.PLL_ARM.Get() & ^uint32(nxp.CCM_ANALOG_PLL_ARM_DIV_SELECT_Msk|nxp.CCM_ANALOG_PLL_ARM_POWERDOWN_Msk)) | + nxp.CCM_ANALOG_PLL_ARM_ENABLE_Msk | sel) + + for !nxp.CCM_ANALOG.PLL_ARM.HasBits(nxp.CCM_ANALOG_PLL_ARM_LOCK_Msk) { + } + + // disable bypass + nxp.CCM_ANALOG.PLL_ARM.ClearBits(nxp.CCM_ANALOG_PLL_ARM_BYPASS_Msk) +} + +// PLL configuration for System +type clockConfigSysPll struct { + loopDivider uint8 // PLL loop divider. Intended to be 1 (528M): 0 - Fout=Fref*20, 1 - Fout=Fref*22 + numerator uint32 // 30 bit numerator of fractional loop divider. + denominator uint32 // 30 bit denominator of fractional loop divider + src uint8 // Pll clock source, reference _clock_pll_clk_src + ssStop uint16 // Stop value to get frequency change. + ssEnable uint8 // Enable spread spectrum modulation + ssStep uint16 // Step value to get frequency change step. +} + +func (cfg clockConfigSysPll) configure(pfd ...uint32) { + + // bypass PLL first + src := (uint32(cfg.src) << nxp.CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC_Pos) & nxp.CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC_Msk + nxp.CCM_ANALOG.PLL_SYS.Set( + (nxp.CCM_ANALOG.PLL_SYS.Get() & ^uint32(nxp.CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC_Msk)) | + nxp.CCM_ANALOG_PLL_SYS_BYPASS_Msk | src) + + sel := (uint32(cfg.loopDivider) << nxp.CCM_ANALOG_PLL_SYS_DIV_SELECT_Pos) & nxp.CCM_ANALOG_PLL_SYS_DIV_SELECT_Msk + nxp.CCM_ANALOG.PLL_SYS.Set( + (nxp.CCM_ANALOG.PLL_SYS.Get() & ^uint32(nxp.CCM_ANALOG_PLL_SYS_DIV_SELECT_Msk|nxp.CCM_ANALOG_PLL_SYS_POWERDOWN_Msk)) | + nxp.CCM_ANALOG_PLL_SYS_ENABLE_Msk | sel) + + // initialize the fractional mode + nxp.CCM_ANALOG.PLL_SYS_NUM.Set((cfg.numerator << nxp.CCM_ANALOG_PLL_SYS_NUM_A_Pos) & nxp.CCM_ANALOG_PLL_SYS_NUM_A_Msk) + nxp.CCM_ANALOG.PLL_SYS_DENOM.Set((cfg.denominator << nxp.CCM_ANALOG_PLL_SYS_DENOM_B_Pos) & nxp.CCM_ANALOG_PLL_SYS_DENOM_B_Msk) + + // initialize the spread spectrum mode + inc := (uint32(cfg.ssStep) << nxp.CCM_ANALOG_PLL_SYS_SS_STEP_Pos) & nxp.CCM_ANALOG_PLL_SYS_SS_STEP_Msk + enb := (uint32(cfg.ssEnable) << nxp.CCM_ANALOG_PLL_SYS_SS_ENABLE_Pos) & nxp.CCM_ANALOG_PLL_SYS_SS_ENABLE_Msk + stp := (uint32(cfg.ssStop) << nxp.CCM_ANALOG_PLL_SYS_SS_STOP_Pos) & nxp.CCM_ANALOG_PLL_SYS_SS_STOP_Msk + nxp.CCM_ANALOG.PLL_SYS_SS.Set(inc | enb | stp) + + for !nxp.CCM_ANALOG.PLL_SYS.HasBits(nxp.CCM_ANALOG_PLL_SYS_LOCK_Msk) { + } + + // disable bypass + nxp.CCM_ANALOG.PLL_SYS.ClearBits(nxp.CCM_ANALOG_PLL_SYS_BYPASS_Msk) + + // update PFDs after update + setSysPfd(pfd...) +} + +// PLL configuration for USB +type clockConfigUsbPll struct { + instance uint8 // USB PLL number (1 or 2) + loopDivider uint8 // PLL loop divider: 0 - Fout=Fref*20, 1 - Fout=Fref*22 + src uint8 // Pll clock source, reference _clock_pll_clk_src +} + +func (cfg clockConfigUsbPll) configure(pfd ...uint32) { + + switch cfg.instance { + case 1: + + // bypass PLL first + src := (uint32(cfg.src) << nxp.CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC_Pos) & nxp.CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC_Msk + nxp.CCM_ANALOG.PLL_USB1.Set( + (nxp.CCM_ANALOG.PLL_USB1.Get() & ^uint32(nxp.CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC_Msk)) | + nxp.CCM_ANALOG_PLL_USB1_BYPASS_Msk | src) + + sel := uint32((cfg.loopDivider << nxp.CCM_ANALOG_PLL_USB1_DIV_SELECT_Pos) & nxp.CCM_ANALOG_PLL_USB1_DIV_SELECT_Msk) + nxp.CCM_ANALOG.PLL_USB1_SET.Set( + (nxp.CCM_ANALOG.PLL_USB1.Get() & ^uint32(nxp.CCM_ANALOG_PLL_USB1_DIV_SELECT_Msk)) | + nxp.CCM_ANALOG_PLL_USB1_ENABLE_Msk | nxp.CCM_ANALOG_PLL_USB1_POWER_Msk | + nxp.CCM_ANALOG_PLL_USB1_EN_USB_CLKS_Msk | sel) + + for !nxp.CCM_ANALOG.PLL_USB1.HasBits(nxp.CCM_ANALOG_PLL_USB1_LOCK_Msk) { + } + + // disable bypass + nxp.CCM_ANALOG.PLL_USB1_CLR.Set(nxp.CCM_ANALOG_PLL_USB1_BYPASS_Msk) + + // update PFDs after update + setUsb1Pfd(pfd...) + + case 2: + // bypass PLL first + src := (uint32(cfg.src) << nxp.CCM_ANALOG_PLL_USB2_BYPASS_CLK_SRC_Pos) & nxp.CCM_ANALOG_PLL_USB2_BYPASS_CLK_SRC_Msk + nxp.CCM_ANALOG.PLL_USB2.Set( + (nxp.CCM_ANALOG.PLL_USB2.Get() & ^uint32(nxp.CCM_ANALOG_PLL_USB2_BYPASS_CLK_SRC_Msk)) | + nxp.CCM_ANALOG_PLL_USB2_BYPASS_Msk | src) + + sel := uint32((cfg.loopDivider << nxp.CCM_ANALOG_PLL_USB2_DIV_SELECT_Pos) & nxp.CCM_ANALOG_PLL_USB2_DIV_SELECT_Msk) + nxp.CCM_ANALOG.PLL_USB2.Set( + (nxp.CCM_ANALOG.PLL_USB2.Get() & ^uint32(nxp.CCM_ANALOG_PLL_USB2_DIV_SELECT_Msk)) | + nxp.CCM_ANALOG_PLL_USB2_ENABLE_Msk | nxp.CCM_ANALOG_PLL_USB2_POWER_Msk | + nxp.CCM_ANALOG_PLL_USB2_EN_USB_CLKS_Msk | sel) + + for !nxp.CCM_ANALOG.PLL_USB2.HasBits(nxp.CCM_ANALOG_PLL_USB2_LOCK_Msk) { + } + + // disable bypass + nxp.CCM_ANALOG.PLL_USB2.ClearBits(nxp.CCM_ANALOG_PLL_USB2_BYPASS_Msk) + + default: + panic("runtime: invalid USB PLL") + } +} + +// PLL configuration for AUDIO +type 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 +type 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 +type 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 +} + +// PLL name +const ( + clkPllArm clock = ((offPllArm & 0xFFF) << 16) | nxp.CCM_ANALOG_PLL_ARM_ENABLE_Pos // PLL ARM + clkPllSys clock = ((offPllSys & 0xFFF) << 16) | nxp.CCM_ANALOG_PLL_SYS_ENABLE_Pos // PLL SYS + clkPllUsb1 clock = ((offPllUsb1 & 0xFFF) << 16) | nxp.CCM_ANALOG_PLL_USB1_ENABLE_Pos // PLL USB1 + clkPllAudio clock = ((offPllAudio & 0xFFF) << 16) | nxp.CCM_ANALOG_PLL_AUDIO_ENABLE_Pos // PLL Audio + clkPllVideo clock = ((offPllVideo & 0xFFF) << 16) | nxp.CCM_ANALOG_PLL_VIDEO_ENABLE_Pos // PLL Video + clkPllEnet clock = ((offPllEnet & 0xFFF) << 16) | nxp.CCM_ANALOG_PLL_ENET_ENABLE_Pos // PLL Enet0 + clkPllEnet2 clock = ((offPllEnet & 0xFFF) << 16) | nxp.CCM_ANALOG_PLL_ENET_ENET2_REF_EN_Pos // PLL Enet1 + clkPllEnet25M clock = ((offPllEnet & 0xFFF) << 16) | nxp.CCM_ANALOG_PLL_ENET_ENET_25M_REF_EN_Pos // PLL Enet2 + clkPllUsb2 clock = ((offPllUsb2 & 0xFFF) << 16) | nxp.CCM_ANALOG_PLL_USB2_ENABLE_Pos // PLL USB2 +) + +// PLL PFD name +const ( + clkPfd0 clock = 0 // PLL PFD0 + clkPfd1 clock = 1 // PLL PFD1 + clkPfd2 clock = 2 // PLL PFD2 + clkPfd3 clock = 3 // PLL PFD3 +) + +var ( + armPllConfig = clockConfigArmPll{ + loopDivider: 100, // PLL loop divider, Fout = Fin * 50 + src: 0, // Bypass clock source, 0 - OSC 24M, 1 - CLK1_P and CLK1_N + } + sysPllConfig = 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 = 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 = 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 = 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 + } +) diff --git a/src/runtime/runtime_mimxrt1062_mpu.go b/src/runtime/runtime_mimxrt1062_mpu.go new file mode 100644 index 00000000..c71bb67a --- /dev/null +++ b/src/runtime/runtime_mimxrt1062_mpu.go @@ -0,0 +1,349 @@ +// +build mimxrt1062 + +package runtime + +import ( + "device/arm" + "device/nxp" + "runtime/volatile" + "unsafe" +) + +type MPU_Type struct { + TYPE volatile.Register32 // 0x000 (R/ ) - MPU Type Register + CTRL volatile.Register32 // 0x004 (R/W) - MPU Control Register + RNR volatile.Register32 // 0x008 (R/W) - MPU Region RNRber Register + RBAR volatile.Register32 // 0x00C (R/W) - MPU Region Base Address Register + RASR volatile.Register32 // 0x010 (R/W) - MPU Region Attribute and Size Register + RBAR_A1 volatile.Register32 // 0x014 (R/W) - MPU Alias 1 Region Base Address Register + RASR_A1 volatile.Register32 // 0x018 (R/W) - MPU Alias 1 Region Attribute and Size Register + RBAR_A2 volatile.Register32 // 0x01C (R/W) - MPU Alias 2 Region Base Address Register + RASR_A2 volatile.Register32 // 0x020 (R/W) - MPU Alias 2 Region Attribute and Size Register + RBAR_A3 volatile.Register32 // 0x024 (R/W) - MPU Alias 3 Region Base Address Register + RASR_A3 volatile.Register32 // 0x028 (R/W) - MPU Alias 3 Region Attribute and Size Register +} + +var MPU = (*MPU_Type)(unsafe.Pointer(uintptr(0xe000ed90))) + +func initCache() { + MPU.initialize() +} + +func (mpu *MPU_Type) initialize() { + + mpu.enable(false) + + // -------------------------------------------------------- OVERLAY REGIONS -- + + // add Default [0] region to deny access to whole address space to workaround + // speculative prefetch. Refer to Arm errata 1013783-B for more details. + + // [0] Default {OVERLAY}: + // 4 GiB, -access, @device, -exec, -share, -cache, -buffer, -subregion + mpu.setRBAR(0, 0x00000000) + mpu.setRASR(rs4GB, apNone, exDevice, false, false, false, false, false) + + // [1] Peripherals {OVERLAY}: + // 64 MiB, +ACCESS, @device, +EXEC, -share, -cache, -buffer, -subregion + mpu.setRBAR(1, 0x40000000) + mpu.setRASR(rs64MB, apFull, exDevice, true, false, false, false, false) + + // [2] RAM {OVERLAY}: + // 1 GiB, +ACCESS, @device, +EXEC, -share, -cache, -buffer, -subregion + mpu.setRBAR(2, 0x00000000) + mpu.setRASR(rs1GB, apFull, exDevice, true, false, false, false, false) + + // ----------------------------------------------------- PERIPHERAL REGIONS -- + + // [3] ITCM: + // 512 KiB, +ACCESS, #NORMAL, +EXEC, -share, -cache, -buffer, -subregion + mpu.setRBAR(3, 0x00000000) + mpu.setRASR(rs512KB, apFull, exNormal, true, false, false, false, false) + + // [4] DTCM: + // 512 KiB, +ACCESS, #NORMAL, +EXEC, -share, -cache, -buffer, -subregion + mpu.setRBAR(4, 0x20000000) + mpu.setRASR(rs512KB, apFull, exNormal, true, false, false, false, false) + + // [5] RAM (AXI): + // 512 KiB, +ACCESS, #NORMAL, +EXEC, -share, +CACHE, +BUFFER, -subregion + mpu.setRBAR(5, 0x20200000) + mpu.setRASR(rs512KB, apFull, exNormal, true, false, true, true, false) + + // [6] FlexSPI: + // 512 MiB, +ACCESS, #NORMAL, +EXEC, -share, +CACHE, +BUFFER, -subregion + mpu.setRBAR(6, 0x70000000) + mpu.setRASR(rs512MB, apFull, exNormal, true, false, true, true, false) + + // [7] QSPI flash: + // 2 MiB, +ACCESS, #NORMAL, +EXEC, -share, +CACHE, +BUFFER, -subregion + mpu.setRBAR(7, 0x60000000) + mpu.setRASR(rs2MB, apFull, exNormal, true, false, true, true, false) + + mpu.enable(true) +} + +// MPU Type Register Definitions +const ( + MPU_TYPE_IREGION_Pos = 16 // MPU TYPE: IREGION Position + MPU_TYPE_IREGION_Msk = 0xFF << MPU_TYPE_IREGION_Pos // MPU TYPE: IREGION Mask + MPU_TYPE_DREGION_Pos = 8 // MPU TYPE: DREGION Position + MPU_TYPE_DREGION_Msk = 0xFF << MPU_TYPE_DREGION_Pos // MPU TYPE: DREGION Mask + MPU_TYPE_SEPARATE_Pos = 0 // MPU TYPE: SEPARATE Position + MPU_TYPE_SEPARATE_Msk = 1 // MPU TYPE: SEPARATE Mask +) + +// MPU Control Register Definitions +const ( + MPU_CTRL_PRIVDEFENA_Pos = 2 // MPU CTRL: PRIVDEFENA Position + MPU_CTRL_PRIVDEFENA_Msk = 1 << MPU_CTRL_PRIVDEFENA_Pos // MPU CTRL: PRIVDEFENA Mask + MPU_CTRL_HFNMIENA_Pos = 1 // MPU CTRL: HFNMIENA Position + MPU_CTRL_HFNMIENA_Msk = 1 << MPU_CTRL_HFNMIENA_Pos // MPU CTRL: HFNMIENA Mask + MPU_CTRL_ENABLE_Pos = 0 // MPU CTRL: ENABLE Position + MPU_CTRL_ENABLE_Msk = 1 // MPU CTRL: ENABLE Mask +) + +// MPU Region Number Register Definitions +const ( + MPU_RNR_REGION_Pos = 0 // MPU RNR: REGION Position + MPU_RNR_REGION_Msk = 0xFF // MPU RNR: REGION Mask +) + +// MPU Region Base Address Register Definitions +const ( + MPU_RBAR_ADDR_Pos = 5 // MPU RBAR: ADDR Position + MPU_RBAR_ADDR_Msk = 0x7FFFFFF << MPU_RBAR_ADDR_Pos // MPU RBAR: ADDR Mask + MPU_RBAR_VALID_Pos = 4 // MPU RBAR: VALID Position + MPU_RBAR_VALID_Msk = 1 << MPU_RBAR_VALID_Pos // MPU RBAR: VALID Mask + MPU_RBAR_REGION_Pos = 0 // MPU RBAR: REGION Position + MPU_RBAR_REGION_Msk = 0xF // MPU RBAR: REGION Mask +) + +// MPU Region Attribute and Size Register Definitions +const ( + MPU_RASR_ATTRS_Pos = 16 // MPU RASR: MPU Region Attribute field Position + MPU_RASR_ATTRS_Msk = 0xFFFF << MPU_RASR_ATTRS_Pos // MPU RASR: MPU Region Attribute field Mask + MPU_RASR_XN_Pos = 28 // MPU RASR: ATTRS.XN Position + MPU_RASR_XN_Msk = 1 << MPU_RASR_XN_Pos // MPU RASR: ATTRS.XN Mask + MPU_RASR_AP_Pos = 24 // MPU RASR: ATTRS.AP Position + MPU_RASR_AP_Msk = 0x7 << MPU_RASR_AP_Pos // MPU RASR: ATTRS.AP Mask + MPU_RASR_TEX_Pos = 19 // MPU RASR: ATTRS.TEX Position + MPU_RASR_TEX_Msk = 0x7 << MPU_RASR_TEX_Pos // MPU RASR: ATTRS.TEX Mask + MPU_RASR_S_Pos = 18 // MPU RASR: ATTRS.S Position + MPU_RASR_S_Msk = 1 << MPU_RASR_S_Pos // MPU RASR: ATTRS.S Mask + MPU_RASR_C_Pos = 17 // MPU RASR: ATTRS.C Position + MPU_RASR_C_Msk = 1 << MPU_RASR_C_Pos // MPU RASR: ATTRS.C Mask + MPU_RASR_B_Pos = 16 // MPU RASR: ATTRS.B Position + MPU_RASR_B_Msk = 1 << MPU_RASR_B_Pos // MPU RASR: ATTRS.B Mask + MPU_RASR_SRD_Pos = 8 // MPU RASR: Sub-Region Disable Position + MPU_RASR_SRD_Msk = 0xFF << MPU_RASR_SRD_Pos // MPU RASR: Sub-Region Disable Mask + MPU_RASR_SIZE_Pos = 1 // MPU RASR: Region Size Field Position + MPU_RASR_SIZE_Msk = 0x1F << MPU_RASR_SIZE_Pos // MPU RASR: Region Size Field Mask + MPU_RASR_ENABLE_Pos = 0 // MPU RASR: Region enable bit Position + MPU_RASR_ENABLE_Msk = 1 // MPU RASR: Region enable bit Disable Mask +) + +const ( + SCB_DCISW_WAY_Pos = 30 // SCB DCISW: Way Position + SCB_DCISW_WAY_Msk = 3 << SCB_DCISW_WAY_Pos // SCB DCISW: Way Mask + SCB_DCISW_SET_Pos = 5 // SCB DCISW: Set Position + SCB_DCISW_SET_Msk = 0x1FF << SCB_DCISW_SET_Pos // SCB DCISW: Set Mask +) + +const ( + SCB_DCCISW_WAY_Pos = 30 // SCB DCCISW: Way Position + SCB_DCCISW_WAY_Msk = 3 << SCB_DCCISW_WAY_Pos // SCB DCCISW: Way Mask + SCB_DCCISW_SET_Pos = 5 // SCB DCCISW: Set Position + SCB_DCCISW_SET_Msk = 0x1FF << SCB_DCCISW_SET_Pos // SCB DCCISW: Set Mask +) + +type regionSize uint32 + +const ( + rs32B regionSize = 0x04 // MPU Region Size 32 Bytes + rs64B regionSize = 0x05 // MPU Region Size 64 Bytes + rs128B regionSize = 0x06 // MPU Region Size 128 Bytes + rs256B regionSize = 0x07 // MPU Region Size 256 Bytes + rs512B regionSize = 0x08 // MPU Region Size 512 Bytes + rs1KB regionSize = 0x09 // MPU Region Size 1 KByte + rs2KB regionSize = 0x0A // MPU Region Size 2 KBytes + rs4KB regionSize = 0x0B // MPU Region Size 4 KBytes + rs8KB regionSize = 0x0C // MPU Region Size 8 KBytes + rs16KB regionSize = 0x0D // MPU Region Size 16 KBytes + rs32KB regionSize = 0x0E // MPU Region Size 32 KBytes + rs64KB regionSize = 0x0F // MPU Region Size 64 KBytes + rs128KB regionSize = 0x10 // MPU Region Size 128 KBytes + rs256KB regionSize = 0x11 // MPU Region Size 256 KBytes + rs512KB regionSize = 0x12 // MPU Region Size 512 KBytes + rs1MB regionSize = 0x13 // MPU Region Size 1 MByte + rs2MB regionSize = 0x14 // MPU Region Size 2 MBytes + rs4MB regionSize = 0x15 // MPU Region Size 4 MBytes + rs8MB regionSize = 0x16 // MPU Region Size 8 MBytes + rs16MB regionSize = 0x17 // MPU Region Size 16 MBytes + rs32MB regionSize = 0x18 // MPU Region Size 32 MBytes + rs64MB regionSize = 0x19 // MPU Region Size 64 MBytes + rs128MB regionSize = 0x1A // MPU Region Size 128 MBytes + rs256MB regionSize = 0x1B // MPU Region Size 256 MBytes + rs512MB regionSize = 0x1C // MPU Region Size 512 MBytes + rs1GB regionSize = 0x1D // MPU Region Size 1 GByte + rs2GB regionSize = 0x1E // MPU Region Size 2 GBytes + rs4GB regionSize = 0x1F // MPU Region Size 4 GBytes +) + +type accessPerms uint32 + +const ( + apNone accessPerms = 0 // MPU Access Permission no access + apPriv accessPerms = 1 // MPU Access Permission privileged access only + apURO accessPerms = 2 // MPU Access Permission unprivileged access read-only + apFull accessPerms = 3 // MPU Access Permission full access + apPRO accessPerms = 5 // MPU Access Permission privileged access read-only + apRO accessPerms = 6 // MPU Access Permission read-only access +) + +type extension uint32 + +const ( + exNormal extension = 0 + exDevice extension = 2 +) + +func (mpu *MPU_Type) enable(enable bool) { + if enable { + mpu.CTRL.Set(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk) + nxp.SystemControl.SHCSR.SetBits(nxp.SCB_SHCSR_MEMFAULTENA_Msk) + arm.AsmFull(` + dsb 0xF + isb 0xF + `, nil) + enableDcache(true) + enableIcache(true) + } else { + enableIcache(false) + enableDcache(false) + arm.AsmFull(` + dmb 0xF + `, nil) + nxp.SystemControl.SHCSR.ClearBits(nxp.SCB_SHCSR_MEMFAULTENA_Msk) + mpu.CTRL.ClearBits(MPU_CTRL_ENABLE_Msk) + } +} + +// MPU Region Base Address Register value +func (mpu *MPU_Type) setRBAR(region uint32, baseAddress uint32) { + mpu.RBAR.Set((baseAddress & MPU_RBAR_ADDR_Msk) | + (region & MPU_RBAR_REGION_Msk) | MPU_RBAR_VALID_Msk) +} + +// MPU Region Attribute and Size Register value +func (mpu *MPU_Type) setRASR(size regionSize, access accessPerms, ext extension, exec, share, cache, buffer, disable bool) { + boolBit := func(b bool) uint32 { + if b { + return 1 + } + return 0 + } + attr := ((uint32(ext) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | + ((boolBit(share) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | + ((boolBit(cache) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | + ((boolBit(buffer) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk) + mpu.RASR.Set(((boolBit(!exec) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | + ((uint32(access) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | + (attr & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk)) | + ((boolBit(disable) << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) | + ((uint32(size) << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk) | + MPU_RASR_ENABLE_Msk) +} + +func enableIcache(enable bool) { + if enable != nxp.SystemControl.CCR.HasBits(nxp.SCB_CCR_IC_Msk) { + if enable { + arm.AsmFull(` + dsb 0xF + isb 0xF + `, nil) + nxp.SystemControl.ICIALLU.Set(0) + arm.AsmFull(` + dsb 0xF + isb 0xF + `, nil) + nxp.SystemControl.CCR.SetBits(nxp.SCB_CCR_IC_Msk) + arm.AsmFull(` + dsb 0xF + isb 0xF + `, nil) + } else { + arm.AsmFull(` + dsb 0xF + isb 0xF + `, nil) + nxp.SystemControl.CCR.ClearBits(nxp.SCB_CCR_IC_Msk) + nxp.SystemControl.ICIALLU.Set(0) + arm.AsmFull(` + dsb 0xF + isb 0xF + `, nil) + } + } +} + +func enableDcache(enable bool) { + if enable != nxp.SystemControl.CCR.HasBits(nxp.SCB_CCR_DC_Msk) { + if enable { + nxp.SystemControl.CSSELR.Set(0) + arm.AsmFull(` + dsb 0xF + `, nil) + ccsidr := nxp.SystemControl.CCSIDR.Get() + sets := (ccsidr & nxp.SCB_CCSIDR_NUMSETS_Msk) >> nxp.SCB_CCSIDR_NUMSETS_Pos + for sets != 0 { + ways := (ccsidr & nxp.SCB_CCSIDR_ASSOCIATIVITY_Msk) >> nxp.SCB_CCSIDR_ASSOCIATIVITY_Pos + for ways != 0 { + nxp.SystemControl.DCISW.Set( + ((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) | + ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk)) + ways-- + } + sets-- + } + arm.AsmFull(` + dsb 0xF + `, nil) + nxp.SystemControl.CCR.SetBits(nxp.SCB_CCR_DC_Msk) + arm.AsmFull(` + dsb 0xF + isb 0xF + `, nil) + } else { + var ( + ccsidr volatile.Register32 + sets volatile.Register32 + ways volatile.Register32 + ) + nxp.SystemControl.CSSELR.Set(0) + arm.AsmFull(` + dsb 0xF + `, nil) + nxp.SystemControl.CCR.ClearBits(nxp.SCB_CCR_DC_Msk) + arm.AsmFull(` + dsb 0xF + `, nil) + ccsidr.Set(nxp.SystemControl.CCSIDR.Get()) + sets.Set((ccsidr.Get() & nxp.SCB_CCSIDR_NUMSETS_Msk) >> nxp.SCB_CCSIDR_NUMSETS_Pos) + for sets.Get() != 0 { + ways.Set((ccsidr.Get() & nxp.SCB_CCSIDR_ASSOCIATIVITY_Msk) >> nxp.SCB_CCSIDR_ASSOCIATIVITY_Pos) + for ways.Get() != 0 { + nxp.SystemControl.DCCISW.Set( + ((sets.Get() << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) | + ((ways.Get() << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk)) + ways.Set(ways.Get() - 1) + } + sets.Set(sets.Get() - 1) + } + arm.AsmFull(` + dsb 0xF + isb 0xF + `, nil) + } + } +} diff --git a/src/runtime/runtime_mimxrt1062_time.go b/src/runtime/runtime_mimxrt1062_time.go new file mode 100644 index 00000000..57390650 --- /dev/null +++ b/src/runtime/runtime_mimxrt1062_time.go @@ -0,0 +1,128 @@ +// +build mimxrt1062 + +package runtime + +import ( + "device/arm" + "device/nxp" + "runtime/interrupt" + "runtime/volatile" +) + +type timeUnit int64 + +const ( + SYST_FREQ = OSC_FREQ // HW divides 24 MHz XTALOSC down to 100 kHz + lastCycle = SYST_FREQ/1000 - 1 + microsPerCycle = 1000000 / SYST_FREQ +) + +const ( + PIT_FREQ = OSC_FREQ // HW divides 24 MHz XTALOSC down to 100 kHz + pitMicrosPerCycle = 1000000 / PIT_FREQ + pitSleepTimer = 0 // x4 32-bit PIT timers [0..3] +) + +var ( + tickCount volatile.Register64 + pitActive volatile.Register32 + pitTimeout interrupt.Interrupt +) + +func ticksToNanoseconds(ticks timeUnit) int64 { + return int64(ticks) * 1000 +} + +func nanosecondsToTicks(ns int64) timeUnit { + return timeUnit(ns / 1000) +} + +func initSysTick() { + // disable if already running + if arm.SYST.SYST_CSR.HasBits(arm.SYST_CSR_ENABLE_Msk) { + arm.SYST.SYST_CSR.ClearBits(arm.SYST_CSR_ENABLE_Msk) + } + // zeroize the counter + tickCount.Set(0) + arm.SYST.SYST_RVR.Set(lastCycle) + arm.SYST.SYST_CVR.Set(0) + arm.SYST.SYST_CSR.Set(arm.SYST_CSR_TICKINT | arm.SYST_CSR_ENABLE) + // set SysTick and PendSV priority to 32 + nxp.SystemControl.SHPR3.Set((0x20 << nxp.SCB_SHPR3_PRI_15_Pos) | + (0x20 << nxp.SCB_SHPR3_PRI_14_Pos)) + // enable PIT, disable counters + nxp.PIT.MCR.Set(0) + for i := range nxp.PIT.TIMER { + nxp.PIT.TIMER[i].TCTRL.Set(0) + } + // register sleep timer interrupt + pitTimeout = interrupt.New(nxp.IRQ_PIT, timerWake) + pitTimeout.SetPriority(0x21) + pitTimeout.Enable() +} + +//go:export SysTick_Handler +func tick() { + tickCount.Set(tickCount.Get() + 1) +} + +func ticks() timeUnit { + mask := arm.DisableInterrupts() + curr := arm.SYST.SYST_CVR.Get() + tick := tickCount.Get() + pend := nxp.SystemControl.ICSR.HasBits(nxp.SCB_ICSR_PENDSTSET_Msk) + arm.EnableInterrupts(mask) + mics := timeUnit(tick * 1000) + // if the systick counter was about to reset and ICSR indicates a pending + // SysTick IRQ, increment count + if pend && (curr > 50) { + mics += 1000 + } else { + mics += timeUnit((lastCycle - curr) * microsPerCycle) + } + return mics +} + +func sleepTicks(duration timeUnit) { + if duration >= 0 { + curr := ticks() + last := curr + duration + for curr < last { + cycles := timeUnit((last - curr) * pitMicrosPerCycle) + if cycles > 0xFFFFFFFF { + cycles = 0xFFFFFFFF + } + if !timerSleep(uint32(cycles)) { + // return early due to interrupt + return + } + curr = ticks() + } + } +} + +func timerSleep(cycles uint32) bool { + pitActive.Set(1) + nxp.PIT.TIMER[pitSleepTimer].LDVAL.Set(cycles) + nxp.PIT.TIMER[pitSleepTimer].TCTRL.Set(nxp.PIT_TIMER_TCTRL_TIE) // enable interrupts + nxp.PIT.TIMER[pitSleepTimer].TCTRL.SetBits(nxp.PIT_TIMER_TCTRL_TEN) // start timer + for { + //arm.Asm("wfi") // TODO: causes hardfault! why? + if pitActive.Get() == 0 { + return true + } + if hasScheduler { + break // some other interrupt occurred and needs servicing + } + } + timerWake(interrupt.Interrupt{}) // clear and disable timer + return false +} + +func timerWake(interrupt.Interrupt) { + pitActive.Set(0) + // TFLGn[TIF] are set to 1 when a timeout occurs on the associated timer, and + // are cleared to 0 by writing a 1 to the corresponding TFLGn[TIF]. + nxp.PIT.TIMER[pitSleepTimer].TFLG.Set(nxp.PIT_TIMER_TFLG_TIF) // clear interrupt flag + nxp.PIT.TIMER[pitSleepTimer].TCTRL.Set(0) // disable timer/interrupt enable flags +} diff --git a/targets/mimxrt1062-teensy40.ld b/targets/mimxrt1062-teensy40.ld new file mode 100644 index 00000000..312b1078 --- /dev/null +++ b/targets/mimxrt1062-teensy40.ld @@ -0,0 +1,108 @@ +MEMORY +{ + ITCM (rwx): ORIGIN = 0x00000000, LENGTH = 0x00080000 /* 512 Kib */ + DTCM (rwx): ORIGIN = 0x20000000, LENGTH = 0x00080000 /* 512 Kib */ + RAM (rwx): ORIGIN = 0x20200000, LENGTH = 0x00080000 /* 512 Kib */ + FLASH (rx): ORIGIN = 0x60000000, LENGTH = 0x001FFFF0 /* 1984 Kib */ +} + +ENTRY(Reset_Handler); + +_stack_size = 128K; +_heap_size = 512K; + +SECTIONS +{ + .text : ALIGN(8) { + + FILL(0xFFFFFFFF); + + /* place flash config at beginning of flash device */ + KEEP(*(.flash_config)); + + /* IVT must be located at +4 Kbyte offset from base address of flash. */ + . = ORIGIN(FLASH) + 0x1000; + KEEP(*(.ivt)); + + . = ORIGIN(FLASH) + 0x1020; + KEEP(*(.boot_data)); + + . = ORIGIN(FLASH) + 0x2000; + + _svectors = ABSOLUTE(.); + KEEP(*(.isr_vector)); + . = ALIGN(8); + + *(.text.Reset_Handler); + . = ALIGN(8); + + _stext = .; + *(.text*); + *(.rodata* .constdata*); + . = ALIGN(8); + _etext = .; + + } > FLASH + + .tinygo_stacksizes : ALIGN(8) { + + *(.tinygo_stacksizes); + . = ALIGN(8); + + } > FLASH + + .text.padding (NOLOAD) : { + + . = ALIGN(32768); + + } > ITCM + + .stack (NOLOAD) : { + + . = ALIGN(8); + . += _stack_size; + _stack_top = .; + + } > DTCM + + .data : ALIGN(8) { + + FILL(0xFFFFFFFF); + + _sdata = .; + *(.data*); + . = ALIGN(8); + _edata = .; + + } > DTCM AT > FLASH + + .bss : ALIGN(8) { + + _sbss = .; + *(.bss*); + *(COMMON); + . = ALIGN(8); + _ebss = .; + + } > DTCM AT > DTCM + + /DISCARD/ : { + + *(.ARM.exidx*); /* causes spurious 'undefined reference' errors */ + + } + + _sidata = LOADADDR(.data); + + _heap_start = ORIGIN(RAM); + _heap_end = ORIGIN(RAM) + LENGTH(RAM); + + _globals_start = _sdata; + _globals_end = _ebss; + + _image_size = SIZEOF(.text) + SIZEOF(.tinygo_stacksizes) + SIZEOF(.data); + + /* TODO: link .text to ITCM */ + _itcm_blocks = (0 + 0x7FFF) >> 15; + _flexram_cfg = 0xAAAAAAAA | ((1 << (_itcm_blocks * 2)) - 1); +} diff --git a/targets/teensy40.json b/targets/teensy40.json new file mode 100644 index 00000000..fe9994e5 --- /dev/null +++ b/targets/teensy40.json @@ -0,0 +1,25 @@ +{ + "inherits": ["cortex-m"], + "llvm-target": "armv7em-none-eabi", + "cpu": "cortex-m7", + "build-tags": ["teensy40", "teensy", "mimxrt1062", "nxp"], + "automatic-stack-size": false, + "default-stack-size": 131072, + "cflags": [ + "--target=armv7em-none-eabi", + "-Qunused-arguments", + "-mfloat-abi=hard", + "-mfpu=fpv5-d16" + ], + "ldflags": [ + "--emit-relocs", + "--gc-sections" + ], + "linkerscript": "targets/mimxrt1062-teensy40.ld", + "extra-files": [ + "src/device/nxp/mimxrt1062.s", + "targets/teensy40.s" + ], + "flash-command": "teensy_loader_cli -mmcu=imxrt1062 -v -w {hex}" +} + diff --git a/targets/teensy40.s b/targets/teensy40.s new file mode 100644 index 00000000..3f7c8aa7 --- /dev/null +++ b/targets/teensy40.s @@ -0,0 +1,199 @@ +// ----------------------------------------------------------------------------- +// file: teensy40.s +// desc: various startup and configuration data for Teensy 4.0. +// ----------------------------------------------------------------------------- +// References +// i.MX RT1060 Processor Reference Manual +// - Section 9.7.1 "Image Vector Table and Boot Data" +// Teensyduino 1.53 by Paul Stoffregen (PJRC) +// - cores/teensy4/bootdata.c +// - cores/teensy4/startup.c +// ----------------------------------------------------------------------------- + +.section .boot_data +.global __boot_data +__boot_data: + .word 0x60000000 // boot start location + .word _image_size // flash size + .word 0 // plugin flag, use 0 to indicate normal (non-plugin) ROM image + +.section .ivt +.global __ivt +__ivt: + .word 0x402000D1 // header (version 4.0) + .word _svectors // image entry function + .word 0 // reserved + .word 0 // DCD info (optional, set to 0|NULL if unused) + .word __boot_data // boot data struct + .word __ivt // self + .word 0 // command sequence file (CSF) not provided in image + .word 0 // reserved + +.section .flash_config +.global __flash_config +__flash_config: + // 448 byte common FlexSPI configuration block, 8.6.3.1 page 223 (RT1060 rev 0) + // MCU_Flashloader_Reference_Manual.pdf, 8.2.1, Table 8-2, page 72-75 + .word 0x42464346 // Tag 0x00 + .word 0x56010000 // Version + .word 0 // reserved + .word 0x00020101 // columnAdressWidth,dataSetupTime,dataHoldTime,readSampleClkSrc + + .word 0x00000000 // waitTimeCfgCommands,-,deviceModeCfgEnable + .word 0 // deviceModeSeq + .word 0 // deviceModeArg + .word 0x00000000 // -,-,-,configCmdEnable + + .word 0 // configCmdSeqs 0x20 + .word 0 + .word 0 + .word 0 + + .word 0 // cfgCmdArgs 0x30 + .word 0 + .word 0 + .word 0 + + .word 0x00000000 // controllerMiscOption 0x40 + .word 0x00030401 // lutCustomSeqEnable,serialClkFreq,sflashPadType,deviceType + .word 0 // reserved + .word 0 // reserved + + .word 0x00200000 // sflashA1Size (Teensy 4.0) 0x50 + //.word 0x00800000 // sflashA1Size (Teensy 4.1) 0x50 + + .word 0 // sflashA2Size + .word 0 // sflashB1Size + .word 0 // sflashB2Size + + .word 0 // csPadSettingOverride 0x60 + .word 0 // sclkPadSettingOverride + .word 0 // dataPadSettingOverride + .word 0 // dqsPadSettingOverride + + .word 0 // timeoutInMs 0x70 + .word 0 // commandInterval + .word 0 // dataValidTime + .word 0x00000000 // busyBitPolarity,busyOffset + + .word 0x0A1804EB // lookupTable[0] 0x80 + .word 0x26043206 // lookupTable[1] + .word 0 // lookupTable[2] + .word 0 // lookupTable[3] + + .word 0x24040405 // lookupTable[4] 0x90 + .word 0 // lookupTable[5] + .word 0 // lookupTable[6] + .word 0 // lookupTable[7] + + .word 0 // lookupTable[8] 0xA0 + .word 0 // lookupTable[9] + .word 0 // lookupTable[10] + .word 0 // lookupTable[11] + + .word 0x00000406 // lookupTable[12] 0xB0 + .word 0 // lookupTable[13] + .word 0 // lookupTable[14] + .word 0 // lookupTable[15] + + .word 0 // lookupTable[16] 0xC0 + .word 0 // lookupTable[17] + .word 0 // lookupTable[18] + .word 0 // lookupTable[19] + + .word 0x08180420 // lookupTable[20] 0xD0 + .word 0 // lookupTable[21] + .word 0 // lookupTable[22] + .word 0 // lookupTable[23] + + .word 0 // lookupTable[24] 0xE0 + .word 0 // lookupTable[25] + .word 0 // lookupTable[26] + .word 0 // lookupTable[27] + + .word 0 // lookupTable[28] 0xF0 + .word 0 // lookupTable[29] + .word 0 // lookupTable[30] + .word 0 // lookupTable[31] + + .word 0x081804D8 // lookupTable[32] 0x100 + .word 0 // lookupTable[33] + .word 0 // lookupTable[34] + .word 0 // lookupTable[35] + + .word 0x08180402 // lookupTable[36] 0x110 + .word 0x00002004 // lookupTable[37] + .word 0 // lookupTable[38] + .word 0 // lookupTable[39] + + .word 0 // lookupTable[40] 0x120 + .word 0 // lookupTable[41] + .word 0 // lookupTable[42] + .word 0 // lookupTable[43] + + .word 0x00000460 // lookupTable[44] 0x130 + .word 0 // lookupTable[45] + .word 0 // lookupTable[46] + .word 0 // lookupTable[47] + + .word 0 // lookupTable[48] 0x140 + .word 0 // lookupTable[49] + .word 0 // lookupTable[50] + .word 0 // lookupTable[51] + + .word 0 // lookupTable[52] 0x150 + .word 0 // lookupTable[53] + .word 0 // lookupTable[54] + .word 0 // lookupTable[55] + + .word 0 // lookupTable[56] 0x160 + .word 0 // lookupTable[57] + .word 0 // lookupTable[58] + .word 0 // lookupTable[59] + + .word 0 // lookupTable[60] 0x170 + .word 0 // lookupTable[61] + .word 0 // lookupTable[62] + .word 0 // lookupTable[63] + + .word 0 // LUT 0: Read 0x180 + .word 0 // LUT 1: ReadStatus + .word 0 // LUT 3: WriteEnable + .word 0 // LUT 5: EraseSector + + .word 0 // LUT 9: PageProgram 0x190 + .word 0 // LUT 11: ChipErase + .word 0 // LUT 15: Dummy + .word 0 // LUT unused? + + .word 0 // LUT unused? 0x1A0 + .word 0 // LUT unused? + .word 0 // LUT unused? + .word 0 // LUT unused? + + .word 0 // reserved 0x1B0 + .word 0 // reserved + .word 0 // reserved + .word 0 // reserved + + // 64 byte Serial NOR configuration block (8.6.3.2, page 346) + + .word 256 // pageSize 0x1C0 + .word 4096 // sectorSize + .word 1 // ipCmdSerialClkFreq + .word 0 // reserved + + .word 0x00010000 // block size 0x1D0 + .word 0 // reserved + .word 0 // reserved + .word 0 // reserved + + .word 0 // reserved 0x1E0 + .word 0 // reserved + .word 0 // reserved + .word 0 // reserved + + .word 0 // reserved 0x1F0 + .word 0 // reserved + .word 0 // reserved + .word 0 // reserved