github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/machine/machine_mimxrt1062.go (about)

     1  //go:build mimxrt1062
     2  
     3  package machine
     4  
     5  import (
     6  	"device/nxp"
     7  	"math/bits"
     8  	"runtime/interrupt"
     9  	"runtime/volatile"
    10  )
    11  
    12  // Peripheral abstraction layer for the MIMXRT1062
    13  
    14  const deviceName = nxp.Device
    15  
    16  func CPUFrequency() uint32 {
    17  	return 600000000
    18  }
    19  
    20  const (
    21  	// GPIO
    22  	PinInput PinMode = iota
    23  	PinInputPullup
    24  	PinInputPulldown
    25  	PinOutput
    26  	PinOutputOpenDrain
    27  	PinDisable
    28  
    29  	// ADC
    30  	PinInputAnalog
    31  
    32  	// UART
    33  	PinModeUARTTX
    34  	PinModeUARTRX
    35  
    36  	// SPI
    37  	PinModeSPISDI
    38  	PinModeSPISDO
    39  	PinModeSPICLK
    40  	PinModeSPICS
    41  
    42  	// I2C
    43  	PinModeI2CSDA
    44  	PinModeI2CSCL
    45  )
    46  
    47  // Deprecated: use PinInputPullup and PinInputPulldown instead.
    48  const (
    49  	PinInputPullUp   = PinInputPullup
    50  	PinInputPullDown = PinInputPulldown
    51  )
    52  
    53  type PinChange uint8
    54  
    55  const (
    56  	PinRising PinChange = iota + 2
    57  	PinFalling
    58  	PinToggle
    59  )
    60  
    61  // pinJumpTable represents a function lookup table for all 128 GPIO pins.
    62  //
    63  // There are 4 GPIO ports (A-D) and 32 pins (0-31) on each port. The uint8 value
    64  // of a Pin is used as table index. The number of pins with a defined (non-nil)
    65  // function is recorded in the uint8 field numDefined.
    66  type pinJumpTable struct {
    67  	lut        [4 * 32]func(Pin)
    68  	numDefined uint8
    69  }
    70  
    71  // pinISR stores the interrupt callbacks for GPIO pins, and pinInterrupt holds
    72  // an interrupt service routine that dispatches the interrupt callbacks.
    73  var (
    74  	pinISR       pinJumpTable
    75  	pinInterrupt *interrupt.Interrupt
    76  )
    77  
    78  // From the i.MXRT1062 Processor Reference Manual (Chapter 12 - GPIO):
    79  //
    80  // |  High-speed GPIOs exist in this device:
    81  // |    - GPIO1-5 are standard-speed GPIOs that run off the IPG_CLK_ROOT, while
    82  // |      GPIO6-9 are high-speed GPIOs that run at the AHB_CLK_ROOT frequency.
    83  // |      See the table "System Clocks, Gating, and Override" in CCM chapter.
    84  // |    - Regular GPIO and high speed GPIO are paired (GPIO1 and GPIO6 share the
    85  // |      same pins, GPIO2 and GPIO7 share, etc). The IOMUXC_GPR_GPR26-29
    86  // |      registers are used to determine if the regular or high-speed GPIO
    87  // |      module is used for the GPIO pins on a given port.
    88  //
    89  // Therefore, we do not even use GPIO1-5 and instead use their high-speed
    90  // partner for all pins. This is configured at startup in the runtime package
    91  // (func initPins() in `runtime_mimxrt1062.go`).
    92  // We cannot declare 32 pins for all available ports (GPIO1-9) anyway, since Pin
    93  // is only uint8, and 9*32=288 > 256, so something has to be sacrificed.
    94  
    95  const (
    96  	portA Pin = iota * 32 // GPIO1(6)
    97  	portB                 // GPIO2(7)
    98  	portC                 // GPIO3(8)
    99  	portD                 // GPIO4(9)
   100  )
   101  
   102  const (
   103  	//                   [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
   104  	//                   ----------  ---------------  ---------------  -------------------  --------------------  --------------------  -----------  --------------------  --------------------  ---------------------  ----------------
   105  	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             ~                      ~
   106  	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             ~                      ~
   107  	PA2  = portA + 2  // [AD_B0_02]: FLEXCAN2_TX      XBAR1_INOUT16    LPUART6_TX           USB_OTG1_PWR          FLEXPWM1_PWMX00       GPIO1_IO02   LPI2C1_HREQ           LPSPI3_SDI             ~                      ~
   108  	PA3  = portA + 3  // [AD_B0_03]: FLEXCAN2_RX      XBAR1_INOUT17    LPUART6_RX           USB_OTG1_OC           FLEXPWM1_PWMX01       GPIO1_IO03   REF_CLK_24M           LPSPI3_PCS0            ~                      ~
   109  	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            ~                      ~
   110  	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            ~                      ~
   111  	PA6  = portA + 6  // [AD_B0_06]: JTAG_TMS         GPT2_COMPARE1    ENET_RX_CLK          SAI2_RX_BCLK          CSI_DATA07            GPIO1_IO06   XBAR1_INOUT18         LPSPI3_PCS3            ~                      ~
   112  	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   ~                      ~
   113  	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    ~                      ~
   114  	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               ~
   115  	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
   116  	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
   117  	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           ~                      ~
   118  	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            ~                      ~
   119  	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            ~                      ~
   120  	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             ~
   121  	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
   122  	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
   123  	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
   124  	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
   125  	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
   126  	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
   127  	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
   128  	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
   129  	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        ~
   130  	PA25 = portA + 25 // [AD_B1_09]: FLEXSPIA_DQS     FLEXPWM4_PWMA01  FLEXCAN1_RX          SAI1_MCLK             CSI_DATA08            GPIO1_IO25   USDHC2_CLK            KPP_COL03             FLEXIO3_FLEXIO09        ~
   131  	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
   132  	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
   133  	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
   134  	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
   135  	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
   136  	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
   137  
   138  	PB0  = portB + 0  // [B0_00]:    LCD_CLK          QTIMER1_TIMER0   MQS_RIGHT            LPSPI4_PCS0           FLEXIO2_FLEXIO00      GPIO2_IO00   SEMC_CSX01            ENET2_MDC              ~                      ~
   139  	PB1  = portB + 1  // [B0_01]:    LCD_ENABLE       QTIMER1_TIMER1   MQS_LEFT             LPSPI4_SDI            FLEXIO2_FLEXIO01      GPIO2_IO01   SEMC_CSX02            ENET2_MDIO             ~                      ~
   140  	PB2  = portB + 2  // [B0_02]:    LCD_HSYNC        QTIMER1_TIMER2   FLEXCAN1_TX          LPSPI4_SDO            FLEXIO2_FLEXIO02      GPIO2_IO02   SEMC_CSX03            ENET2_1588_EVENT0_OUT  ~                      ~
   141  	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   ~                      ~
   142  	PB4  = portB + 4  // [B0_04]:    LCD_DATA00       QTIMER2_TIMER1   LPI2C2_SCL           ARM_TRACE0            FLEXIO2_FLEXIO04      GPIO2_IO04   SRC_BOOT_CFG00        ENET2_TDATA03          ~                      ~
   143  	PB5  = portB + 5  // [B0_05]:    LCD_DATA01       QTIMER2_TIMER2   LPI2C2_SDA           ARM_TRACE1            FLEXIO2_FLEXIO05      GPIO2_IO05   SRC_BOOT_CFG01        ENET2_TDATA02          ~                      ~
   144  	PB6  = portB + 6  // [B0_06]:    LCD_DATA02       QTIMER3_TIMER0   FLEXPWM2_PWMA00      ARM_TRACE2            FLEXIO2_FLEXIO06      GPIO2_IO06   SRC_BOOT_CFG02        ENET2_RX_CLK           ~                      ~
   145  	PB7  = portB + 7  // [B0_07]:    LCD_DATA03       QTIMER3_TIMER1   FLEXPWM2_PWMB00      ARM_TRACE3            FLEXIO2_FLEXIO07      GPIO2_IO07   SRC_BOOT_CFG03        ENET2_TX_ER            ~                      ~
   146  	PB8  = portB + 8  // [B0_08]:    LCD_DATA04       QTIMER3_TIMER2   FLEXPWM2_PWMA01      LPUART3_TX            FLEXIO2_FLEXIO08      GPIO2_IO08   SRC_BOOT_CFG04        ENET2_RDATA03          ~                      ~
   147  	PB9  = portB + 9  // [B0_09]:    LCD_DATA05       QTIMER4_TIMER0   FLEXPWM2_PWMB01      LPUART3_RX            FLEXIO2_FLEXIO09      GPIO2_IO09   SRC_BOOT_CFG05        ENET2_RDATA02          ~                      ~
   148  	PB10 = portB + 10 // [B0_10]:    LCD_DATA06       QTIMER4_TIMER1   FLEXPWM2_PWMA02      SAI1_TX_DATA03        FLEXIO2_FLEXIO10      GPIO2_IO10   SRC_BOOT_CFG06        ENET2_CRS              ~                      ~
   149  	PB11 = portB + 11 // [B0_11]:    LCD_DATA07       QTIMER4_TIMER2   FLEXPWM2_PWMB02      SAI1_TX_DATA02        FLEXIO2_FLEXIO11      GPIO2_IO11   SRC_BOOT_CFG07        ENET2_COL              ~                      ~
   150  	PB12 = portB + 12 // [B0_12]:    LCD_DATA08       XBAR1_INOUT10    ARM_TRACE_CLK        SAI1_TX_DATA01        FLEXIO2_FLEXIO12      GPIO2_IO12   SRC_BOOT_CFG08        ENET2_TDATA00          ~                      ~
   151  	PB13 = portB + 13 // [B0_13]:    LCD_DATA09       XBAR1_INOUT11    ARM_TRACE_SWO        SAI1_MCLK             FLEXIO2_FLEXIO13      GPIO2_IO13   SRC_BOOT_CFG09        ENET2_TDATA01          ~                      ~
   152  	PB14 = portB + 14 // [B0_14]:    LCD_DATA10       XBAR1_INOUT12    ARM_TXEV             SAI1_RX_SYNC          FLEXIO2_FLEXIO14      GPIO2_IO14   SRC_BOOT_CFG10        ENET2_TX_EN            ~                      ~
   153  	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          ~
   154  	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        ~
   155  	PB17 = portB + 17 // [B1_01]:    LCD_DATA13       XBAR1_INOUT15    LPUART4_RX           SAI1_TX_DATA00        FLEXIO2_FLEXIO17      GPIO2_IO17   FLEXPWM1_PWMB03       ENET2_RDATA00         FLEXIO3_FLEXIO17        ~
   156  	PB18 = portB + 18 // [B1_02]:    LCD_DATA14       XBAR1_INOUT16    LPSPI4_PCS2          SAI1_TX_BCLK          FLEXIO2_FLEXIO18      GPIO2_IO18   FLEXPWM2_PWMA03       ENET2_RDATA01         FLEXIO3_FLEXIO18        ~
   157  	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        ~
   158  	PB20 = portB + 20 // [B1_04]:    LCD_DATA16       LPSPI4_PCS0      CSI_DATA15           ENET_RX_DATA00        FLEXIO2_FLEXIO20      GPIO2_IO20   GPT1_CLK              FLEXIO3_FLEXIO20       ~                      ~
   159  	PB21 = portB + 21 // [B1_05]:    LCD_DATA17       LPSPI4_SDI       CSI_DATA14           ENET_RX_DATA01        FLEXIO2_FLEXIO21      GPIO2_IO21   GPT1_CAPTURE1         FLEXIO3_FLEXIO21       ~                      ~
   160  	PB22 = portB + 22 // [B1_06]:    LCD_DATA18       LPSPI4_SDO       CSI_DATA13           ENET_RX_EN            FLEXIO2_FLEXIO22      GPIO2_IO22   GPT1_CAPTURE2         FLEXIO3_FLEXIO22       ~                      ~
   161  	PB23 = portB + 23 // [B1_07]:    LCD_DATA19       LPSPI4_SCK       CSI_DATA12           ENET_TX_DATA00        FLEXIO2_FLEXIO23      GPIO2_IO23   GPT1_COMPARE1         FLEXIO3_FLEXIO23       ~                      ~
   162  	PB24 = portB + 24 // [B1_08]:    LCD_DATA20       QTIMER1_TIMER3   CSI_DATA11           ENET_TX_DATA01        FLEXIO2_FLEXIO24      GPIO2_IO24   FLEXCAN2_TX           GPT1_COMPARE2         FLEXIO3_FLEXIO24        ~
   163  	PB25 = portB + 25 // [B1_09]:    LCD_DATA21       QTIMER2_TIMER3   CSI_DATA10           ENET_TX_EN            FLEXIO2_FLEXIO25      GPIO2_IO25   FLEXCAN2_RX           GPT1_COMPARE3         FLEXIO3_FLEXIO25        ~
   164  	PB26 = portB + 26 // [B1_10]:    LCD_DATA22       QTIMER3_TIMER3   CSI_DATA00           ENET_TX_CLK           FLEXIO2_FLEXIO26      GPIO2_IO26   ENET_REF_CLK          FLEXIO3_FLEXIO26       ~                      ~
   165  	PB27 = portB + 27 // [B1_11]:    LCD_DATA23       QTIMER4_TIMER3   CSI_DATA01           ENET_RX_ER            FLEXIO2_FLEXIO27      GPIO2_IO27   LPSPI4_PCS3           FLEXIO3_FLEXIO27       ~                      ~
   166  	PB28 = portB + 28 // [B1_12]:    LPUART5_TX       CSI_PIXCLK       ENET_1588_EVENT0_IN  FLEXIO2_FLEXIO28      GPIO2_IO28            USDHC1_CD_B  FLEXIO3_FLEXIO28       ~                     ~                      ~
   167  	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        ~
   168  	PB30 = portB + 30 // [B1_14]:    ENET_MDC         FLEXPWM4_PWMA02  CSI_HSYNC            XBAR1_IN02            FLEXIO2_FLEXIO30      GPIO2_IO30   USDHC1_VSELECT        ENET2_TDATA00         FLEXIO3_FLEXIO30        ~
   169  	PB31 = portB + 31 // [B1_15]:    ENET_MDIO        FLEXPWM4_PWMA03  CSI_MCLK             XBAR1_IN03            FLEXIO2_FLEXIO31      GPIO2_IO31   USDHC1_RESET_B        ENET2_TDATA01         FLEXIO3_FLEXIO31        ~
   170  
   171  	PC0  = portC + 0  // [SD_B1_00]: USDHC2_DATA3     FLEXSPIB_DATA03  FLEXPWM1_PWMA03      SAI1_TX_DATA03        LPUART4_TX            GPIO3_IO00   SAI3_RX_DATA           ~                     ~                      ~
   172  	PC1  = portC + 1  // [SD_B1_01]: USDHC2_DATA2     FLEXSPIB_DATA02  FLEXPWM1_PWMB03      SAI1_TX_DATA02        LPUART4_RX            GPIO3_IO01   SAI3_TX_DATA           ~                     ~                      ~
   173  	PC2  = portC + 2  // [SD_B1_02]: USDHC2_DATA1     FLEXSPIB_DATA01  FLEXPWM2_PWMA03      SAI1_TX_DATA01        FLEXCAN1_TX           GPIO3_IO02   CCM_WAIT              SAI3_TX_SYNC           ~                      ~
   174  	PC3  = portC + 3  // [SD_B1_03]: USDHC2_DATA0     FLEXSPIB_DATA00  FLEXPWM2_PWMB03      SAI1_MCLK             FLEXCAN1_RX           GPIO3_IO03   CCM_PMIC_READY        SAI3_TX_BCLK           ~                      ~
   175  	PC4  = portC + 4  // [SD_B1_04]: USDHC2_CLK       FLEXSPIB_SCLK    LPI2C1_SCL           SAI1_RX_SYNC          FLEXSPIA_SS1_B        GPIO3_IO04   CCM_STOP              SAI3_MCLK              ~                      ~
   176  	PC5  = portC + 5  // [SD_B1_05]: USDHC2_CMD       FLEXSPIA_DQS     LPI2C1_SDA           SAI1_RX_BCLK          FLEXSPIB_SS0_B        GPIO3_IO05   SAI3_RX_SYNC           ~                     ~                      ~
   177  	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           ~                     ~                      ~
   178  	PC7  = portC + 7  // [SD_B1_07]: SEMC_CSX01       FLEXSPIA_SCLK    LPUART7_RTS_B        SAI1_TX_DATA00        LPSPI2_SCK            GPIO3_IO07    ~                     ~                     ~                      ~
   179  	PC8  = portC + 8  // [SD_B1_08]: USDHC2_DATA4     FLEXSPIA_DATA00  LPUART7_TX           SAI1_TX_BCLK          LPSPI2_SD0            GPIO3_IO08   SEMC_CSX02             ~                     ~                      ~
   180  	PC9  = portC + 9  // [SD_B1_09]: USDHC2_DATA5     FLEXSPIA_DATA01  LPUART7_RX           SAI1_TX_SYNC          LPSPI2_SDI            GPIO3_IO09    ~                     ~                     ~                      ~
   181  	PC10 = portC + 10 // [SD_B1_10]: USDHC2_DATA6     FLEXSPIA_DATA02  LPUART2_RX           LPI2C2_SDA            LPSPI2_PCS2           GPIO3_IO10    ~                     ~                     ~                      ~
   182  	PC11 = portC + 11 // [SD_B1_11]: USDHC2_DATA7     FLEXSPIA_DATA03  LPUART2_TX           LPI2C2_SCL            LPSPI2_PCS3           GPIO3_IO11    ~                     ~                     ~                      ~
   183  	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               ~
   184  	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          ~
   185  	PC14 = portC + 14 // [SD_B0_02]: USDHC1_DATA0     FLEXPWM1_PWMA01  LPUART8_CTS_B        XBAR1_INOUT06         LPSPI1_SDO            GPIO3_IO14   ENET2_RX_ER           SEMC_CLK5              ~                      ~
   186  	PC15 = portC + 15 // [SD_B0_03]: USDHC1_DATA1     FLEXPWM1_PWMB01  LPUART8_RTS_B        XBAR1_INOUT07         LPSPI1_SDI            GPIO3_IO15   ENET2_RDATA00         SEMC_CLK6              ~                      ~
   187  	PC16 = portC + 16 // [SD_B0_04]: USDHC1_DATA2     FLEXPWM1_PWMA02  LPUART8_TX           XBAR1_INOUT08         FLEXSPIB_SS0_B        GPIO3_IO16   CCM_CLKO1             ENET2_RDATA01          ~                      ~
   188  	PC17 = portC + 17 // [SD_B0_05]: USDHC1_DATA3     FLEXPWM1_PWMB02  LPUART8_RX           XBAR1_INOUT09         FLEXSPIB_DQS          GPIO3_IO17   CCM_CLKO2             ENET2_RX_EN            ~                      ~
   189  	PC18 = portC + 18 // [EMC_32]:   SEMC_DATA10      FLEXPWM3_PWMB01  LPUART7_RX           CCM_PMIC_RDY          CSI_DATA21            GPIO3_IO18   ENET2_TX_EN            ~                     ~                      ~
   190  	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         ~                      ~
   191  	PC20 = portC + 20 // [EMC_34]:   SEMC_DATA12      FLEXPWM3_PWMB02  USDHC1_VSELECT       SAI3_RX_SYNC          CSI_DATA19            GPIO3_IO20   ENET2_RX_ER            ~                     ~                      ~
   192  	PC21 = portC + 21 // [EMC_35]:   SEMC_DATA13      XBAR1_INOUT18    GPT1_COMPARE1        SAI3_RX_BCLK          CSI_DATA18            GPIO3_IO21   USDHC1_CD_B           ENET2_RDATA00          ~                      ~
   193  	PC22 = portC + 22 // [EMC_36]:   SEMC_DATA14      XBAR1_IN22       GPT1_COMPARE2        SAI3_TX_DATA          CSI_DATA17            GPIO3_IO22   USDHC1_WP             ENET2_RDATA01         FLEXCAN3_TX             ~
   194  	PC23 = portC + 23 // [EMC_37]:   SEMC_DATA15      XBAR1_IN23       GPT1_COMPARE3        SAI3_MCLK             CSI_DATA16            GPIO3_IO23   USDHC2_WP             ENET2_RX_EN           FLEXCAN3_RX             ~
   195  	PC24 = portC + 24 // [EMC_38]:   SEMC_DM01        FLEXPWM1_PWMA03  LPUART8_TX           SAI3_TX_BCLK          CSI_FIELD             GPIO3_IO24   USDHC2_VSELECT        ENET2_MDC              ~                      ~
   196  	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               ~
   197  	PC26 = portC + 26 // [EMC_40]:   SEMC_RDY         GPT2_CAPTURE2    LPSPI1_PCS2          USB_OTG2_OC           ENET_MDC              GPIO3_IO26   USDHC2_RESET_B        SEMC_CLK5              ~                      ~
   198  	PC27 = portC + 27 // [EMC_41]:   SEMC_CSX00       GPT2_CAPTURE1    LPSPI1_PCS3          USB_OTG2_PWR          ENET_MDIO             GPIO3_IO27   USDHC1_VSELECT         ~                     ~                      ~
   199  	_    = portC + 28 //
   200  	_    = portC + 29 //
   201  	_    = portC + 30 //
   202  	_    = portC + 31 //
   203  
   204  	PD0  = portD + 0  // [EMC_00]:   SEMC_DATA00      FLEXPWM4_PWMA00  LPSPI2_SCK           XBAR1_XBAR_IN02       FLEXIO1_FLEXIO00      GPIO4_IO00    ~                     ~                     ~                      ~
   205  	PD1  = portD + 1  // [EMC_01]:   SEMC_DATA01      FLEXPWM4_PWMB00  LPSPI2_PCS0          XBAR1_IN03            FLEXIO1_FLEXIO01      GPIO4_IO01    ~                     ~                     ~                      ~
   206  	PD2  = portD + 2  // [EMC_02]:   SEMC_DATA02      FLEXPWM4_PWMA01  LPSPI2_SDO           XBAR1_INOUT04         FLEXIO1_FLEXIO02      GPIO4_IO02    ~                     ~                     ~                      ~
   207  	PD3  = portD + 3  // [EMC_03]:   SEMC_DATA03      FLEXPWM4_PWMB01  LPSPI2_SDI           XBAR1_INOUT05         FLEXIO1_FLEXIO03      GPIO4_IO03    ~                     ~                     ~                      ~
   208  	PD4  = portD + 4  // [EMC_04]:   SEMC_DATA04      FLEXPWM4_PWMA02  SAI2_TX_DATA         XBAR1_INOUT06         FLEXIO1_FLEXIO04      GPIO4_IO04    ~                     ~                     ~                      ~
   209  	PD5  = portD + 5  // [EMC_05]:   SEMC_DATA05      FLEXPWM4_PWMB02  SAI2_TX_SYNC         XBAR1_INOUT07         FLEXIO1_FLEXIO05      GPIO4_IO05    ~                     ~                     ~                      ~
   210  	PD6  = portD + 6  // [EMC_06]:   SEMC_DATA06      FLEXPWM2_PWMA00  SAI2_TX_BCLK         XBAR1_INOUT08         FLEXIO1_FLEXIO06      GPIO4_IO06    ~                     ~                     ~                      ~
   211  	PD7  = portD + 7  // [EMC_07]:   SEMC_DATA07      FLEXPWM2_PWMB00  SAI2_MCLK            XBAR1_INOUT09         FLEXIO1_FLEXIO07      GPIO4_IO07    ~                     ~                     ~                      ~
   212  	PD8  = portD + 8  // [EMC_08]:   SEMC_DM00        FLEXPWM2_PWMA01  SAI2_RX_DATA         XBAR1_INOUT17         FLEXIO1_FLEXIO08      GPIO4_IO08    ~                     ~                     ~                      ~
   213  	PD9  = portD + 9  // [EMC_09]:   SEMC_ADDR00      FLEXPWM2_PWMB01  SAI2_RX_SYNC         FLEXCAN2_TX           FLEXIO1_FLEXIO09      GPIO4_IO09   FLEXSPI2_B_SS1_B       ~                     ~                      ~
   214  	PD10 = portD + 10 // [EMC_10]:   SEMC_ADDR01      FLEXPWM2_PWMA02  SAI2_RX_BCLK         FLEXCAN2_RX           FLEXIO1_FLEXIO10      GPIO4_IO10   FLEXSPI2_B_SS0_B       ~                     ~                      ~
   215  	PD11 = portD + 11 // [EMC_11]:   SEMC_ADDR02      FLEXPWM2_PWMB02  LPI2C4_SDA           USDHC2_RESET_B        FLEXIO1_FLEXIO11      GPIO4_IO11   FLEXSPI2_B_DQS         ~                     ~                      ~
   216  	PD12 = portD + 12 // [EMC_12]:   SEMC_ADDR03      XBAR1_IN24       LPI2C4_SCL           USDHC1_WP             FLEXPWM1_PWMA03       GPIO4_IO12   FLEXSPI2_B_SCLK        ~                     ~                      ~
   217  	PD13 = portD + 13 // [EMC_13]:   SEMC_ADDR04      XBAR1_IN25       LPUART3_TX           MQS_RIGHT             FLEXPWM1_PWMB03       GPIO4_IO13   FLEXSPI2_B_DATA00      ~                     ~                      ~
   218  	PD14 = portD + 14 // [EMC_14]:   SEMC_ADDR05      XBAR1_INOUT19    LPUART3_RX           MQS_LEFT              LPSPI2_PCS1           GPIO4_IO14   FLEXSPI2_B_DATA01      ~                     ~                      ~
   219  	PD15 = portD + 15 // [EMC_15]:   SEMC_ADDR06      XBAR1_IN20       LPUART3_CTS_B        SPDIF_OUT             QTIMER3_TIMER0        GPIO4_IO15   FLEXSPI2_B_DATA02      ~                     ~                      ~
   220  	PD16 = portD + 16 // [EMC_16]:   SEMC_ADDR07      XBAR1_IN21       LPUART3_RTS_B        SPDIF_IN              QTIMER3_TIMER1        GPIO4_IO16   FLEXSPI2_B_DATA03      ~                     ~                      ~
   221  	PD17 = portD + 17 // [EMC_17]:   SEMC_ADDR08      FLEXPWM4_PWMA03  LPUART4_CTS_B        FLEXCAN1_TX           QTIMER3_TIMER2        GPIO4_IO17    ~                     ~                     ~                      ~
   222  	PD18 = portD + 18 // [EMC_18]:   SEMC_ADDR09      FLEXPWM4_PWMB03  LPUART4_RTS_B        FLEXCAN1_RX           QTIMER3_TIMER3        GPIO4_IO18   SNVS_VIO_5_CTL         ~                     ~                      ~
   223  	PD19 = portD + 19 // [EMC_19]:   SEMC_ADDR11      FLEXPWM2_PWMA03  LPUART4_TX           ENET_RDATA01          QTIMER2_TIMER0        GPIO4_IO19   SNVS_VIO_5             ~                     ~                      ~
   224  	PD20 = portD + 20 // [EMC_20]:   SEMC_ADDR12      FLEXPWM2_PWMB03  LPUART4_RX           ENET_RDATA00          QTIMER2_TIMER1        GPIO4_IO20    ~                     ~                     ~                      ~
   225  	PD21 = portD + 21 // [EMC_21]:   SEMC_BA0         FLEXPWM3_PWMA03  LPI2C3_SDA           ENET_TDATA01          QTIMER2_TIMER2        GPIO4_IO21    ~                     ~                     ~                      ~
   226  	PD22 = portD + 22 // [EMC_22]:   SEMC_BA1         FLEXPWM3_PWMB03  LPI2C3_SCL           ENET_TDATA00          QTIMER2_TIMER3        GPIO4_IO22   FLEXSPI2_A_SS1_B       ~                     ~                      ~
   227  	PD23 = portD + 23 // [EMC_23]:   SEMC_ADDR10      FLEXPWM1_PWMA00  LPUART5_TX           ENET_RX_EN            GPT1_CAPTURE2         GPIO4_IO23   FLEXSPI2_A_DQS         ~                     ~                      ~
   228  	PD24 = portD + 24 // [EMC_24]:   SEMC_CAS         FLEXPWM1_PWMB00  LPUART5_RX           ENET_TX_EN            GPT1_CAPTURE1         GPIO4_IO24   FLEXSPI2_A_SS0_B       ~                     ~                      ~
   229  	PD25 = portD + 25 // [EMC_25]:   SEMC_RAS         FLEXPWM1_PWMA01  LPUART6_TX           ENET_TX_CLK           ENET_REF_CLK          GPIO4_IO25   FLEXSPI2_A_SCLK        ~                     ~                      ~
   230  	PD26 = portD + 26 // [EMC_26]:   SEMC_CLK         FLEXPWM1_PWMB01  LPUART6_RX           ENET_RX_ER            FLEXIO1_FLEXIO12      GPIO4_IO26   FLEXSPI2_A_DATA00      ~                     ~                      ~
   231  	PD27 = portD + 27 // [EMC_27]:   SEMC_CKE         FLEXPWM1_PWMA02  LPUART5_RTS_B        LPSPI1_SCK            FLEXIO1_FLEXIO13      GPIO4_IO27   FLEXSPI2_A_DATA01      ~                     ~                      ~
   232  	PD28 = portD + 28 // [EMC_28]:   SEMC_WE          FLEXPWM1_PWMB02  LPUART5_CTS_B        LPSPI1_SDO            FLEXIO1_FLEXIO14      GPIO4_IO28   FLEXSPI2_A_DATA02      ~                     ~                      ~
   233  	PD29 = portD + 29 // [EMC_29]:   SEMC_CS0         FLEXPWM3_PWMA00  LPUART6_RTS_B        LPSPI1_SDI            FLEXIO1_FLEXIO15      GPIO4_IO29   FLEXSPI2_A_DATA03      ~                     ~                      ~
   234  	PD30 = portD + 30 // [EMC_30]:   SEMC_DATA08      FLEXPWM3_PWMB00  LPUART6_CTS_B        LPSPI1_PCS0           CSI_DATA23            GPIO4_IO30   ENET2_TDATA00          ~                     ~                      ~
   235  	PD31 = portD + 31 // [EMC_31]:   SEMC_DATA09      FLEXPWM3_PWMA01  LPUART7_TX           LPSPI1_PCS1           CSI_DATA22            GPIO4_IO31   ENET2_TDATA01          ~                     ~                      ~
   236  )
   237  
   238  func (p Pin) getPos() uint8   { return uint8(p % 32) }
   239  func (p Pin) getMask() uint32 { return uint32(1) << p.getPos() }
   240  func (p Pin) getPort() Pin    { return Pin(p/32) * 32 }
   241  
   242  // Configure sets the GPIO pad and pin properties, and selects the appropriate
   243  // alternate function, for a given Pin and PinConfig.
   244  func (p Pin) Configure(config PinConfig) {
   245  	var (
   246  		sre = uint32(0x01 << 0)
   247  		dse = func(n uint32) uint32 { return (n & 0x07) << 3 }
   248  		spd = func(n uint32) uint32 { return (n & 0x03) << 6 }
   249  		ode = uint32(0x01 << 11)
   250  		pke = uint32(0x01 << 12)
   251  		pue = uint32(0x01 << 13)
   252  		pup = func(n uint32) uint32 { return (n & 0x03) << 14 }
   253  		hys = uint32(0x01 << 16)
   254  	)
   255  
   256  	_, gpio := p.getGPIO() // use fast GPIO for all pins
   257  	pad, mux := p.getPad()
   258  
   259  	// first configure the pad characteristics
   260  	switch config.Mode {
   261  	case PinInput:
   262  		gpio.GDIR.ClearBits(p.getMask())
   263  		pad.Set(dse(7))
   264  
   265  	case PinInputPullup:
   266  		gpio.GDIR.ClearBits(p.getMask())
   267  		pad.Set(dse(7) | pke | pue | pup(3) | hys)
   268  
   269  	case PinInputPulldown:
   270  		gpio.GDIR.ClearBits(p.getMask())
   271  		pad.Set(dse(7) | pke | pue | hys)
   272  
   273  	case PinOutput:
   274  		gpio.GDIR.SetBits(p.getMask())
   275  		pad.Set(dse(7))
   276  
   277  	case PinOutputOpenDrain:
   278  		gpio.GDIR.SetBits(p.getMask())
   279  		pad.Set(dse(7) | ode)
   280  
   281  	case PinDisable:
   282  		gpio.GDIR.ClearBits(p.getMask())
   283  		pad.Set(dse(7) | hys)
   284  
   285  	case PinInputAnalog:
   286  		gpio.GDIR.ClearBits(p.getMask())
   287  		pad.Set(dse(7))
   288  
   289  	case PinModeUARTTX:
   290  		pad.Set(sre | dse(3) | spd(3))
   291  
   292  	case PinModeUARTRX:
   293  		pad.Set(dse(7) | pke | pue | pup(3) | hys)
   294  
   295  	case PinModeSPISDI:
   296  		pad.Set(dse(7) | spd(2))
   297  
   298  	case PinModeSPISDO:
   299  		pad.Set(dse(7) | spd(2))
   300  
   301  	case PinModeSPICLK:
   302  		pad.Set(dse(7) | spd(2))
   303  
   304  	case PinModeSPICS:
   305  		pad.Set(dse(7))
   306  
   307  	case PinModeI2CSDA, PinModeI2CSCL:
   308  		pad.Set(ode | sre | dse(4) | spd(1) | pke | pue | pup(3))
   309  	}
   310  
   311  	// then configure the alternate function mux
   312  	mux.Set(p.getMuxMode(config))
   313  }
   314  
   315  // Get returns the current value of a GPIO pin.
   316  func (p Pin) Get() bool {
   317  	_, gpio := p.getGPIO() // use fast GPIO for all pins
   318  	return gpio.PSR.HasBits(p.getMask())
   319  }
   320  
   321  // Set changes the value of the GPIO pin. The pin must be configured as output.
   322  func (p Pin) Set(value bool) {
   323  	_, gpio := p.getGPIO() // use fast GPIO for all pins
   324  	if value {
   325  		gpio.DR_SET.Set(p.getMask())
   326  	} else {
   327  		gpio.DR_CLEAR.Set(p.getMask())
   328  	}
   329  }
   330  
   331  // Toggle switches an output pin from low to high or from high to low.
   332  func (p Pin) Toggle() {
   333  	_, gpio := p.getGPIO() // use fast GPIO for all pins
   334  	gpio.DR_TOGGLE.Set(p.getMask())
   335  }
   336  
   337  // dispatchInterrupt invokes the user-provided callback functions for external
   338  // interrupts generated on the high-speed GPIO pins.
   339  //
   340  // Unfortunately, all four high-speed GPIO ports (A-D) are connected to just a
   341  // single interrupt control line. Therefore, the interrupt status register (ISR)
   342  // must be checked in all four GPIO ports on every interrupt.
   343  func (jt *pinJumpTable) dispatchInterrupt(interrupt.Interrupt) {
   344  	handle := func(gpio *nxp.GPIO_Type, port Pin) {
   345  		if status := gpio.ISR.Get() & gpio.IMR.Get(); status != 0 {
   346  			gpio.ISR.Set(status) // clear interrupt
   347  			for status != 0 {
   348  				off := Pin(bits.TrailingZeros32(status)) // ctz
   349  				pin := Pin(port + off)
   350  				jt.lut[pin](pin)
   351  				status &^= 1 << off
   352  			}
   353  		}
   354  	}
   355  	if jt.numDefined > 0 {
   356  		handle(nxp.GPIO6, portA)
   357  		handle(nxp.GPIO7, portB)
   358  		handle(nxp.GPIO8, portC)
   359  		handle(nxp.GPIO9, portD)
   360  	}
   361  }
   362  
   363  // set associates a function with a given Pin in the receiver lookup table. If
   364  // the function is nil, the given Pin's associated function is removed.
   365  func (jt *pinJumpTable) set(pin Pin, fn func(Pin)) {
   366  	if int(pin) < len(jt.lut) {
   367  		if nil != fn {
   368  			if nil == jt.lut[pin] {
   369  				jt.numDefined++
   370  			}
   371  			jt.lut[pin] = fn
   372  		} else {
   373  			if nil != jt.lut[pin] {
   374  				jt.numDefined--
   375  			}
   376  			jt.lut[pin] = nil
   377  		}
   378  	}
   379  }
   380  
   381  // SetInterrupt sets an interrupt to be executed when a particular pin changes
   382  // state. The pin should already be configured as an input, including a pull up
   383  // or down if no external pull is provided.
   384  //
   385  // This call will replace a previously set callback on this pin. You can pass a
   386  // nil func to unset the pin change interrupt. If you do so, the change
   387  // parameter is ignored and can be set to any value (such as 0).
   388  func (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error {
   389  	_, gpio := p.getGPIO() // use fast GPIO for all pins
   390  	mask := p.getMask()
   391  	if nil != callback {
   392  		switch change {
   393  		case PinRising, PinFalling:
   394  			gpio.EDGE_SEL.ClearBits(mask)
   395  			var reg *volatile.Register32
   396  			var pos uint8
   397  			if pos = p.getPos(); pos < 16 {
   398  				reg = &gpio.ICR1 // ICR1 = pins 0-15
   399  			} else {
   400  				reg = &gpio.ICR2 // ICR2 = pins 16-31
   401  				pos -= 16
   402  			}
   403  			reg.ReplaceBits(uint32(change), 0x3, pos*2)
   404  		case PinToggle:
   405  			gpio.EDGE_SEL.SetBits(mask)
   406  		}
   407  		pinISR.set(p, callback) // associate the callback with the pin
   408  		gpio.ISR.Set(mask)      // clear any pending interrupt (W1C)
   409  		gpio.IMR.SetBits(mask)  // enable external interrupt
   410  	} else {
   411  		pinISR.set(p, nil)       // remove any associated callback from the pin
   412  		gpio.ISR.Set(mask)       // clear any pending interrupt (W1C)
   413  		gpio.IMR.ClearBits(mask) // disable external interrupt
   414  	}
   415  	// enable or disable the interrupt based on number of defined callbacks
   416  	if pinISR.numDefined > 0 {
   417  		if nil == pinInterrupt {
   418  			// create the Interrupt if it is not yet defined
   419  			irq := interrupt.New(nxp.IRQ_GPIO6_7_8_9, pinISR.dispatchInterrupt)
   420  			pinInterrupt = &irq
   421  			pinInterrupt.Enable()
   422  		}
   423  	} else {
   424  		if nil != pinInterrupt {
   425  			// disable the interrupt if it is defined
   426  			pinInterrupt.Disable()
   427  		}
   428  	}
   429  	return nil
   430  }
   431  
   432  // getGPIO returns both the normal (IPG_CLK_ROOT) and high-speed (AHB_CLK_ROOT)
   433  // GPIO peripherals to which a given Pin is connected.
   434  //
   435  // Note that, currently, the device is configured to use high-speed GPIO for all
   436  // pins (GPIO6-9), so the first return value should not be used (GPIO1-4).
   437  // See the remarks and documentation reference in the comments preceding the
   438  // const Pin definitions above.
   439  func (p Pin) getGPIO() (norm *nxp.GPIO_Type, fast *nxp.GPIO_Type) {
   440  	switch p.getPort() {
   441  	case portA:
   442  		return nxp.GPIO1, nxp.GPIO6
   443  	case portB:
   444  		return nxp.GPIO2, nxp.GPIO7
   445  	case portC:
   446  		return nxp.GPIO3, nxp.GPIO8
   447  	case portD:
   448  		return nxp.GPIO4, nxp.GPIO9
   449  	default:
   450  		panic("machine: unknown port")
   451  	}
   452  }
   453  
   454  // getPad returns both the pad and mux configration registers for a given Pin.
   455  func (p Pin) getPad() (pad *volatile.Register32, mux *volatile.Register32) {
   456  	switch p.getPort() {
   457  	case portA:
   458  		switch p.getPos() {
   459  		case 0:
   460  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_00
   461  		case 1:
   462  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_01
   463  		case 2:
   464  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_02
   465  		case 3:
   466  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_03
   467  		case 4:
   468  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_04
   469  		case 5:
   470  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_05
   471  		case 6:
   472  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_06, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_06
   473  		case 7:
   474  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_07, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_07
   475  		case 8:
   476  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_08, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_08
   477  		case 9:
   478  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_09, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_09
   479  		case 10:
   480  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_10, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_10
   481  		case 11:
   482  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_11, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_11
   483  		case 12:
   484  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_12, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_12
   485  		case 13:
   486  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_13, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_13
   487  		case 14:
   488  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_14, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_14
   489  		case 15:
   490  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B0_15, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B0_15
   491  		case 16:
   492  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_00
   493  		case 17:
   494  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_01
   495  		case 18:
   496  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_02
   497  		case 19:
   498  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_03
   499  		case 20:
   500  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_04
   501  		case 21:
   502  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_05
   503  		case 22:
   504  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_06, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_06
   505  		case 23:
   506  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_07, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_07
   507  		case 24:
   508  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_08, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_08
   509  		case 25:
   510  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_09, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_09
   511  		case 26:
   512  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_10, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_10
   513  		case 27:
   514  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_11, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_11
   515  		case 28:
   516  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_12, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_12
   517  		case 29:
   518  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_13, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_13
   519  		case 30:
   520  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_14, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_14
   521  		case 31:
   522  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_AD_B1_15, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_AD_B1_15
   523  		}
   524  	case portB:
   525  		switch p.getPos() {
   526  		case 0:
   527  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_00
   528  		case 1:
   529  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_01
   530  		case 2:
   531  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_02
   532  		case 3:
   533  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_03
   534  		case 4:
   535  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_04
   536  		case 5:
   537  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_05
   538  		case 6:
   539  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_06, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_06
   540  		case 7:
   541  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_07, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_07
   542  		case 8:
   543  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_08, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_08
   544  		case 9:
   545  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_09, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_09
   546  		case 10:
   547  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_10, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_10
   548  		case 11:
   549  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_11, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_11
   550  		case 12:
   551  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_12, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_12
   552  		case 13:
   553  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_13, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_13
   554  		case 14:
   555  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_14, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_14
   556  		case 15:
   557  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B0_15, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B0_15
   558  		case 16:
   559  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_00
   560  		case 17:
   561  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_01
   562  		case 18:
   563  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_02
   564  		case 19:
   565  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_03
   566  		case 20:
   567  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_04
   568  		case 21:
   569  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_05
   570  		case 22:
   571  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_06, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_06
   572  		case 23:
   573  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_07, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_07
   574  		case 24:
   575  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_08, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_08
   576  		case 25:
   577  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_09, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_09
   578  		case 26:
   579  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_10, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_10
   580  		case 27:
   581  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_11, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_11
   582  		case 28:
   583  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_12, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_12
   584  		case 29:
   585  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_13, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_13
   586  		case 30:
   587  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_14, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_14
   588  		case 31:
   589  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_B1_15, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_B1_15
   590  		}
   591  	case portC:
   592  		switch p.getPos() {
   593  		case 0:
   594  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_00
   595  		case 1:
   596  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_01
   597  		case 2:
   598  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_02
   599  		case 3:
   600  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_03
   601  		case 4:
   602  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_04
   603  		case 5:
   604  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_05
   605  		case 6:
   606  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_06, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_06
   607  		case 7:
   608  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_07, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_07
   609  		case 8:
   610  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_08, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_08
   611  		case 9:
   612  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_09, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_09
   613  		case 10:
   614  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_10, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_10
   615  		case 11:
   616  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B1_11, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B1_11
   617  		case 12:
   618  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B0_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B0_00
   619  		case 13:
   620  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B0_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B0_01
   621  		case 14:
   622  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B0_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B0_02
   623  		case 15:
   624  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B0_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B0_03
   625  		case 16:
   626  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B0_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B0_04
   627  		case 17:
   628  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_SD_B0_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_SD_B0_05
   629  		case 18:
   630  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_32, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_32
   631  		case 19:
   632  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_33, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_33
   633  		case 20:
   634  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_34, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_34
   635  		case 21:
   636  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_35, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_35
   637  		case 22:
   638  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_36, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_36
   639  		case 23:
   640  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_37, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_37
   641  		case 24:
   642  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_38, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_38
   643  		case 25:
   644  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_39, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_39
   645  		case 26:
   646  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_40, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_40
   647  		case 27:
   648  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_41, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_41
   649  		case 28, 29, 30, 31:
   650  		}
   651  	case portD:
   652  		switch p.getPos() {
   653  		case 0:
   654  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_00, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_00
   655  		case 1:
   656  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_01, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_01
   657  		case 2:
   658  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_02, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_02
   659  		case 3:
   660  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_03, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_03
   661  		case 4:
   662  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_04, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_04
   663  		case 5:
   664  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_05, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_05
   665  		case 6:
   666  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_06, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_06
   667  		case 7:
   668  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_07, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_07
   669  		case 8:
   670  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_08, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_08
   671  		case 9:
   672  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_09, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_09
   673  		case 10:
   674  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_10, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_10
   675  		case 11:
   676  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_11, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_11
   677  		case 12:
   678  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_12, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_12
   679  		case 13:
   680  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_13, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_13
   681  		case 14:
   682  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_14, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_14
   683  		case 15:
   684  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_15, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_15
   685  		case 16:
   686  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_16, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_16
   687  		case 17:
   688  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_17, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_17
   689  		case 18:
   690  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_18, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_18
   691  		case 19:
   692  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_19, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_19
   693  		case 20:
   694  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_20, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_20
   695  		case 21:
   696  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_21, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_21
   697  		case 22:
   698  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_22, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_22
   699  		case 23:
   700  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_23, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_23
   701  		case 24:
   702  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_24, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_24
   703  		case 25:
   704  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_25, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_25
   705  		case 26:
   706  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_26, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_26
   707  		case 27:
   708  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_27, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_27
   709  		case 28:
   710  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_28, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_28
   711  		case 29:
   712  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_29, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_29
   713  		case 30:
   714  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_30, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_30
   715  		case 31:
   716  			return &nxp.IOMUXC.SW_PAD_CTL_PAD_GPIO_EMC_31, &nxp.IOMUXC.SW_MUX_CTL_PAD_GPIO_EMC_31
   717  		}
   718  	}
   719  	panic("machine: invalid pin")
   720  }
   721  
   722  // muxSelect is yet another level of indirection required to connect pins in an
   723  // alternate function state to a desired peripheral (since more than one pin can
   724  // provide a given alternate function).
   725  //
   726  // Once a pin is configured with a given alternate function mode, the IOMUXC
   727  // device must then be configured to select which alternate function pin to
   728  // route to the desired peripheral.
   729  //
   730  // The reference manual refers to this functionality as a "Daisy Chain". The
   731  // associated docs are found in the i.MX RT1060 Processor Reference Manual:
   732  // "Chapter 11.3.3 Daisy chain - multi pads driving same module input pin"
   733  type muxSelect struct {
   734  	mux uint8                // AF mux selection (NOT a Pin type)
   735  	sel *volatile.Register32 // AF selection register
   736  }
   737  
   738  // connect configures the IOMUXC controller to route a given pin with alternate
   739  // function to a desired peripheral (see godoc comments on type muxSelect).
   740  func (s muxSelect) connect() {
   741  	s.sel.Set(uint32(s.mux))
   742  }
   743  
   744  // getMuxMode acts as a callback from the `(Pin).Configure(PinMode)` routine to
   745  // determine the alternate function setting for a given Pin and PinConfig.
   746  // This value is used in the IOMUXC device's SW_MUX_CTL_PAD_GPIO_* registers.
   747  func (p Pin) getMuxMode(config PinConfig) uint32 {
   748  	const forcePath = true // TODO: should be input parameter?
   749  	switch config.Mode {
   750  
   751  	// GPIO
   752  	case PinInput, PinInputPullup, PinInputPulldown,
   753  		PinOutput, PinOutputOpenDrain, PinDisable:
   754  		mode := uint32(0x5) // GPIO is always alternate function 5
   755  		if forcePath {
   756  			mode |= 0x10 // SION bit
   757  		}
   758  		return mode
   759  
   760  	// ADC
   761  	case PinInputAnalog:
   762  		mode := uint32(0x5) // use alternate function 5 (GPIO)
   763  		if forcePath {
   764  			mode |= 0x10 // SION bit
   765  		}
   766  		return mode
   767  
   768  	// UART RX/TX
   769  	case PinModeUARTRX, PinModeUARTTX:
   770  		mode := uint32(0x2) // UART is usually alternate function 2 on Teensy 4.x
   771  		// Teensy 4.1 has a UART (LPUART5) with alternate function 1
   772  		if p == PB28 || p == PB29 {
   773  			mode = 0x1
   774  		}
   775  		return mode
   776  
   777  	// SPI SDI
   778  	case PinModeSPISDI:
   779  		var mode uint32
   780  		switch p {
   781  		case PC15: // LPSPI1 SDI on PC15 alternate function 4
   782  			mode = uint32(0x4)
   783  		case PA2: // LPSPI3 SDI on PA2 alternate function 7
   784  			mode = uint32(0x7)
   785  		case PB1: // LPSPI4 SDI on PB1 alternate function 3
   786  			mode = uint32(0x3)
   787  		default:
   788  			panic("machine: invalid SPI SDI pin")
   789  		}
   790  		if forcePath {
   791  			mode |= 0x10 // SION bit
   792  		}
   793  		return mode
   794  
   795  	// SPI SDO
   796  	case PinModeSPISDO:
   797  		var mode uint32
   798  		switch p {
   799  		case PC14: // LPSPI1 SDO on PC14 alternate function 4
   800  			mode = uint32(0x4)
   801  		case PA30: // LPSPI3 SDO on PA30 alternate function 2
   802  			mode = uint32(0x2)
   803  		case PB2: // LPSPI4 SDO on PB2 alternate function 3
   804  			mode = uint32(0x3)
   805  		default:
   806  			panic("machine: invalid SPI SDO pin")
   807  		}
   808  		if forcePath {
   809  			mode |= 0x10 // SION bit
   810  		}
   811  		return mode
   812  
   813  	// SPI SCK
   814  	case PinModeSPICLK:
   815  		var mode uint32
   816  		switch p {
   817  		case PC12: // LPSPI1 SCK on PC12 alternate function 4
   818  			mode = uint32(0x4)
   819  		case PA31: // LPSPI3 SCK on PA31 alternate function 2
   820  			mode = uint32(0x2)
   821  		case PB3: // LPSPI4 SCK on PB3 alternate function 3
   822  			mode = uint32(0x3)
   823  		default:
   824  			panic("machine: invalid SPI CLK pin")
   825  		}
   826  		if forcePath {
   827  			mode |= 0x10 // SION bit
   828  		}
   829  		return mode
   830  
   831  	// SPI CS
   832  	case PinModeSPICS:
   833  		var mode uint32
   834  		switch p {
   835  		case PC13: // LPSPI1 CS on PC13 alternate function 4
   836  			mode = uint32(0x4)
   837  		case PA3: // LPSPI3 CS on PA3 alternate function 7
   838  			mode = uint32(0x7)
   839  		case PB0: // LPSPI4 CS on PB0 alternate function 3
   840  			mode = uint32(0x3)
   841  		default: // use alternate function 5 (GPIO) if non-CS pin selected
   842  			mode = uint32(0x5)
   843  		}
   844  		if forcePath {
   845  			mode |= 0x10 // SION bit
   846  		}
   847  		return mode
   848  
   849  	// I2C SDA
   850  	case PinModeI2CSDA:
   851  		var mode uint32
   852  		switch p {
   853  		case PA13: // LPI2C4 SDA on PA13 alternate function 0
   854  			mode = uint32(0)
   855  		case PA17: // LPI2C1 SDA on PA17 alternate function 3
   856  			mode = uint32(3)
   857  		case PA22: // LPI2C3 SDA on PA22 alternate function 1
   858  			mode = uint32(1)
   859  		default:
   860  			panic("machine: invalid I2C SDA pin")
   861  		}
   862  		if forcePath {
   863  			mode |= 0x10 // SION bit
   864  		}
   865  		return mode
   866  
   867  	// I2C SCL
   868  	case PinModeI2CSCL:
   869  		var mode uint32
   870  		switch p {
   871  		case PA12: // LPI2C4 SCL on PA12 alternate function 0
   872  			mode = uint32(0)
   873  		case PA16: // LPI2C1 SCL on PA16 alternate function 3
   874  			mode = uint32(3)
   875  		case PA23: // LPI2C3 SCL on PA23 alternate function 1
   876  			mode = uint32(1)
   877  		default:
   878  			panic("machine: invalid I2C SCL pin")
   879  		}
   880  		if forcePath {
   881  			mode |= 0x10 // SION bit
   882  		}
   883  		return mode
   884  
   885  	default:
   886  		panic("machine: invalid pin mode")
   887  	}
   888  }
   889  
   890  // maximum ADC value for the currently configured resolution (used for scaling)
   891  var adcMaximum uint32
   892  
   893  // InitADC is not used by this machine. Use `(ADC).Configure()`.
   894  func InitADC() {}
   895  
   896  // Configure initializes the receiver's ADC peripheral and pin for analog input.
   897  func (a ADC) Configure(config ADCConfig) {
   898  	// if not specified, use defaults: 10-bit resolution, 4 samples/conversion
   899  	const (
   900  		defaultResolution = uint32(10)
   901  		defaultSamples    = uint32(4)
   902  	)
   903  
   904  	a.Pin.Configure(PinConfig{Mode: PinInputAnalog})
   905  
   906  	resolution, samples := config.Resolution, config.Samples
   907  	if 0 == resolution {
   908  		resolution = defaultResolution
   909  	}
   910  	if 0 == samples {
   911  		samples = defaultSamples
   912  	}
   913  	if resolution > 12 {
   914  		resolution = 12 // maximum resolution of 12 bits
   915  	}
   916  	adcMaximum = (uint32(1) << resolution) - 1
   917  
   918  	mode, average := a.mode(resolution, samples)
   919  
   920  	nxp.ADC1.CFG.Set(mode | nxp.ADC_CFG_ADHSC) // configure ADC1
   921  	nxp.ADC2.CFG.Set(mode | nxp.ADC_CFG_ADHSC) // configure ADC2
   922  
   923  	// begin calibration
   924  	nxp.ADC1.GC.Set(average | nxp.ADC_GC_CAL)
   925  	nxp.ADC2.GC.Set(average | nxp.ADC_GC_CAL)
   926  
   927  	for a.isCalibrating() {
   928  	} // wait for calibration
   929  }
   930  
   931  // Get performs a single ADC conversion, returning a 16-bit unsigned integer.
   932  // The value returned will be scaled (uniformly distributed) if necessary so
   933  // that it is always in the range [0..65535], regardless of the ADC's configured
   934  // bit size (resolution).
   935  func (a ADC) Get() uint16 {
   936  	if ch1, ch2, ok := a.Pin.getADCChannel(); ok {
   937  		for a.isCalibrating() {
   938  		} // wait for calibration
   939  		var val uint32
   940  		if noADCChannel != ch1 {
   941  			nxp.ADC1.HC0.Set(uint32(ch1))
   942  			for !nxp.ADC1.HS.HasBits(nxp.ADC_HS_COCO0) {
   943  			}
   944  			val = nxp.ADC1.R0.Get() & 0xFFFF
   945  		} else {
   946  			nxp.ADC2.HC0.Set(uint32(ch2))
   947  			for !nxp.ADC2.HS.HasBits(nxp.ADC_HS_COCO0) {
   948  			}
   949  			val = nxp.ADC2.R0.Get() & 0xFFFF
   950  		}
   951  		// should never be zero, but just in case, use UINT16_MAX so that the scalar
   952  		// gets factored out of the conversion result, leaving the original reading
   953  		// to be returned unaltered/unscaled.
   954  		if adcMaximum == 0 {
   955  			adcMaximum = 0xFFFF
   956  		}
   957  		// scale up to a 16-bit value
   958  		return uint16((val * 0xFFFF) / adcMaximum)
   959  	}
   960  	return 0
   961  }
   962  
   963  // mode constructs bit masks for mode and average - used in ADC configuration
   964  // registers - from a given ADC bit size (resolution) and sample count.
   965  func (a ADC) mode(resolution, samples uint32) (mode, average uint32) {
   966  
   967  	// use asynchronous clock (ADACK) (0 = IPG, 1 = IPG/2, or 3 = ADACK)
   968  	mode = (nxp.ADC_CFG_ADICLK_ADICLK_3 << nxp.ADC_CFG_ADICLK_Pos) & nxp.ADC_CFG_ADICLK_Msk
   969  
   970  	// input clock DIV2 (0 = DIV1, 1 = DIV2, 2 = DIV4, or 3 = DIV8)
   971  	mode |= (nxp.ADC_CFG_ADIV_ADIV_1 << nxp.ADC_CFG_ADIV_Pos) & nxp.ADC_CFG_ADIV_Msk
   972  
   973  	switch resolution {
   974  	case 8: // 8-bit conversion, sample period (ADC clocks) = 8
   975  		mode |= (nxp.ADC_CFG_MODE_MODE_0 << nxp.ADC_CFG_MODE_Pos) & nxp.ADC_CFG_MODE_Msk
   976  		mode |= (nxp.ADC_CFG_ADSTS_ADSTS_3 << nxp.ADC_CFG_ADSTS_Pos) & nxp.ADC_CFG_ADSTS_Msk
   977  
   978  	case 12: // 12-bit conversion, sample period (ADC clocks) = 24
   979  		mode |= (nxp.ADC_CFG_MODE_MODE_2 << nxp.ADC_CFG_MODE_Pos) & nxp.ADC_CFG_MODE_Msk
   980  		mode |= (nxp.ADC_CFG_ADSTS_ADSTS_3 << nxp.ADC_CFG_ADSTS_Pos) & nxp.ADC_CFG_ADSTS_Msk
   981  		mode |= nxp.ADC_CFG_ADLSMP
   982  
   983  	default: // 10-bit conversion, sample period (ADC clocks) = 20
   984  		mode |= (nxp.ADC_CFG_MODE_MODE_1 << nxp.ADC_CFG_MODE_Pos) & nxp.ADC_CFG_MODE_Msk
   985  		mode |= (nxp.ADC_CFG_ADSTS_ADSTS_2 << nxp.ADC_CFG_ADSTS_Pos) & nxp.ADC_CFG_ADSTS_Msk
   986  		mode |= nxp.ADC_CFG_ADLSMP
   987  	}
   988  
   989  	if samples >= 4 {
   990  		if samples >= 32 {
   991  			// 32 samples averaged
   992  			mode |= (nxp.ADC_CFG_AVGS_AVGS_3 << nxp.ADC_CFG_AVGS_Pos) & nxp.ADC_CFG_AVGS_Msk
   993  		} else if samples >= 16 {
   994  			// 16 samples averaged
   995  			mode |= (nxp.ADC_CFG_AVGS_AVGS_2 << nxp.ADC_CFG_AVGS_Pos) & nxp.ADC_CFG_AVGS_Msk
   996  		} else if samples >= 8 {
   997  			// 8 samples averaged
   998  			mode |= (nxp.ADC_CFG_AVGS_AVGS_1 << nxp.ADC_CFG_AVGS_Pos) & nxp.ADC_CFG_AVGS_Msk
   999  		} else {
  1000  			// 4 samples averaged
  1001  			mode |= (nxp.ADC_CFG_AVGS_AVGS_0 << nxp.ADC_CFG_AVGS_Pos) & nxp.ADC_CFG_AVGS_Msk
  1002  		}
  1003  		average = nxp.ADC_GC_AVGE
  1004  	}
  1005  
  1006  	return mode, average
  1007  }
  1008  
  1009  // isCalibrating returns true if and only if either one (or both) of ADC1 and
  1010  // ADC2 have their calibrating flags set. ADC reads must wait until these flags
  1011  // are clear before attempting a conversion.
  1012  func (a ADC) isCalibrating() bool {
  1013  	return nxp.ADC1.GC.HasBits(nxp.ADC_GC_CAL) || nxp.ADC2.GC.HasBits(nxp.ADC_GC_CAL)
  1014  }
  1015  
  1016  const noADCChannel = uint8(0xFF)
  1017  
  1018  // getADCChannel returns the input channel for ADC1/ADC2 of the receiver Pin p.
  1019  func (p Pin) getADCChannel() (adc1, adc2 uint8, ok bool) {
  1020  	switch p {
  1021  	case PA12: // [AD_B0_12]:       ADC1_IN1        ~
  1022  		return 1, noADCChannel, true
  1023  	case PA13: // [AD_B0_13]:       ADC1_IN2        ~
  1024  		return 2, noADCChannel, true
  1025  	case PA14: // [AD_B0_14]:       ADC1_IN3        ~
  1026  		return 3, noADCChannel, true
  1027  	case PA15: // [AD_B0_15]:       ADC1_IN4        ~
  1028  		return 4, noADCChannel, true
  1029  	case PA16: // [AD_B1_00]:       ADC1_IN5     ADC2_IN5
  1030  		return 5, 5, true
  1031  	case PA17: // [AD_B1_01]:       ADC1_IN6     ADC2_IN6
  1032  		return 6, 6, true
  1033  	case PA18: // [AD_B1_02]:       ADC1_IN7     ADC2_IN7
  1034  		return 7, 7, true
  1035  	case PA19: // [AD_B1_03]:       ADC1_IN8     ADC2_IN8
  1036  		return 8, 8, true
  1037  	case PA20: // [AD_B1_04]:       ADC1_IN9     ADC2_IN9
  1038  		return 9, 9, true
  1039  	case PA21: // [AD_B1_05]:       ADC1_IN10    ADC2_IN10
  1040  		return 10, 10, true
  1041  	case PA22: // [AD_B1_06]:       ADC1_IN11    ADC2_IN11
  1042  		return 11, 11, true
  1043  	case PA23: // [AD_B1_07]:       ADC1_IN12    ADC2_IN12
  1044  		return 12, 12, true
  1045  	case PA24: // [AD_B1_08]:       ADC1_IN13    ADC2_IN13
  1046  		return 13, 13, true
  1047  	case PA25: // [AD_B1_09]:       ADC1_IN14    ADC2_IN14
  1048  		return 14, 14, true
  1049  	case PA26: // [AD_B1_10]:       ADC1_IN15    ADC2_IN15
  1050  		return 15, 15, true
  1051  	case PA27: // [AD_B1_11]:       ADC1_IN0     ADC2_IN0
  1052  		return 16, 16, true
  1053  	case PA28: // [AD_B1_12]:          ~         ADC2_IN1
  1054  		return noADCChannel, 1, true
  1055  	case PA29: // [AD_B1_13]:          ~         ADC2_IN2
  1056  		return noADCChannel, 2, true
  1057  	case PA30: // [AD_B1_14]:          ~         ADC2_IN3
  1058  		return noADCChannel, 3, true
  1059  	case PA31: // [AD_B1_15]:          ~         ADC2_IN4
  1060  		return noADCChannel, 4, true
  1061  	default:
  1062  		return noADCChannel, noADCChannel, false
  1063  	}
  1064  }