mimxrt: Support PWM using the FLEXPWM and QTMR modules.

Frequency range 15Hz/18Hz to > 1 MHz, with decreasing resolution of the
duty cycle.  The basic API is supported as documentated, except that
keyword parameters are accepted for both the instatiaton and the
PWM.init() call.

Extensions: support PWM for channel pairs.  Channel pairs are declared by
supplying 2-element tuples for the pins.  The two channels of a pair must
be the A/B channel of a FLEXPWM module.  These form than a complementary
pair.

Additional supported keyword arguments:

- center=value Defines the center position of a pulse within the pulse
  cycle.  The align keyword is actually shortcut for center.

- sync=True|False: If set to True, the channels will be synchronized to a
  submodule 0 channel, which has already to be enabled.

- align=PWM.MIDDLE | PMW.BEGIN | PWM.END. It defines, whether synchronized
  channels are Center-Aligned or Edge-aligned.  The channels must be either
  complementary a channel pair or a group of synchronized channels.  It may
  as well be applied to a single channel, but withiout any benefit.

- invert= 0..3. Controls ouput inversion of the pins.  Bit 0 controls the
  first pin, bit 1 the second.

- deadtime=time_ns time of complementary channels for delaying the rising
  slope.

- xor=0|1|2 xor causes the output of channel A and B to be xored.  If
  applied to a X channel, it shows the value oif A ^ B.  If applied to an A
  or B channel, both channel show the xored signal for xor=1.  For xor=2,
  the xored signal is split between channels A and B.  See also the
  Reference Manual, chapter about double pulses.  The behavior of xor=2 can
  also be achieved using the center method for locating a pulse within a
  clock period.

The output is enabled for board pins only.

CPU pins may still be used for FLEXPWM, e.g. as sync source, but the signal
will not be routed to the output.  That applies only to FLEXPWM pins.  The
use of QTMR pins which are not board pins will be rejected.

As part of this commit, the _WFE() statement is removed from
ticks_delay_us64() to prevent PWM glitching during calls to sleep().
pull/7999/head
robert-hh 2021-07-26 12:48:25 +02:00 zatwierdzone przez Damien George
rodzic bb7aae557b
commit 81f706aee4
13 zmienionych plików z 922 dodań i 55 usunięć

Wyświetl plik

@ -194,6 +194,7 @@ SRC_HAL_IMX_C += \
$(MCU_DIR)/drivers/fsl_lpuart.c \
$(MCU_DIR)/drivers/fsl_ocotp.c \
$(MCU_DIR)/drivers/fsl_pit.c \
$(MCU_DIR)/drivers/fsl_pwm.c \
$(MCU_DIR)/drivers/fsl_snvs_lp.c \
$(MCU_DIR)/drivers/fsl_trng.c \
$(MCU_DIR)/drivers/fsl_wdog.c \
@ -209,6 +210,11 @@ ifeq ($(MICROPY_PY_MACHINE_SDCARD),1)
SRC_HAL_IMX_C += $(MCU_DIR)/drivers/fsl_usdhc.c
endif
ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES), MIMXRT1015 MIMXRT1021 MIMXRT1052 MIMXRT1062 MIMXRT1064))
SRC_HAL_IMX_C += \
$(MCU_DIR)/drivers/fsl_qtmr.c
endif
SRC_C += \
board_init.c \
dma_channel.c \
@ -220,6 +226,7 @@ SRC_C += \
extmod/modusocket.c \
extmod/uos_dupterm.c \
fatfs_port.c \
hal/pwm_backport.c \
led.c \
machine_adc.c \
machine_bitstream.c \
@ -384,6 +391,7 @@ SRC_QSTR += \
machine_adc.c \
machine_led.c \
machine_pin.c \
machine_pwm.c \
machine_rtc.c \
machine_sdcard.c \
machine_spi.c \

Wyświetl plik

@ -14,12 +14,12 @@
// LPUART4 on D6/D7 -> 2
#define MICROPY_HW_UART_NUM (sizeof(uart_index_table) / sizeof(uart_index_table)[0])
#define MICROPY_HW_UART_INDEX { 0, 1, 4, 3 }
#define MICROPY_HW_UART_INDEX { 0, 1, 4 }
#define IOMUX_TABLE_UART \
{ IOMUXC_GPIO_10_LPUART1_TXD }, { IOMUXC_GPIO_09_LPUART1_RXD }, \
{ 0 }, { 0 }, \
{ IOMUXC_GPIO_08_LPUART3_TXD }, { IOMUXC_GPIO_AD_07_LPUART3_RXD }, \
{ 0 }, { 0 }, \
{ IOMUXC_GPIO_AD_02_LPUART4_TXD }, { IOMUXC_GPIO_AD_01_LPUART4_RXD },
#define MICROPY_HW_SPI_INDEX { 1 }

Wyświetl plik

@ -21,11 +21,11 @@ vfs_start = flash_start + 0x00100000;
text_size = ((vfs_start) - (text_start));
vfs_size = ((flash_end) - (vfs_start));
itcm_start = 0x00000000;
itcm_size = 0x00008000;
itcm_size = 0x00010000;
dtcm_start = 0x20000000;
dtcm_size = 0x00018000;
ocrm_start = 0x20200000;
ocrm_size = 0x00020000;
ocrm_size = 0x00018000;
#ifdef MICROPY_HW_SDRAM_AVAIL
sdram_start = 0x80000000;

Wyświetl plik

@ -5,30 +5,30 @@ GPIO_AD_B0_02,JTAG_MOD,,,,,GPIO1_IO02,USBPHY1_TSTI_TX_LS_MODE,GPT1_CAPTURE1,,,,,
GPIO_AD_B0_03,JTAG_TDI,USDHC2_CD_B,WDOG1_B,SAI1_MCLK,USDHC1_WP,GPIO1_IO03,USB_OTG1_OC,CCM_PMIC_RDY,,,,,ALT0
GPIO_AD_B0_04,JTAG_TDO,FLEXCAN1_TX,USDHC1_WP,TMR2_TIMER0,ENET_MDIO,GPIO1_IO04,USB_OTG1_PWR,EWM_OUT_B,,,,,ALT0
GPIO_AD_B0_05,JTAG_TRSTB,FLEXCAN1_RX,USDHC1_CD_B,TMR2_TIMER1,ENET_MDC,GPIO1_IO05,USB_OTG1_ID,ARM_NMI,,,,,ALT0
GPIO_AD_B0_06,PIT_TRIGGER0,MQS_RIGHT,LPUART1_TXD,TMR2_TIMER2,FLEXPWM2_PWMA3,GPIO1_IO06,REF_32K_OUT,,,,,,ALT5
GPIO_AD_B0_07,PIT_TRIGGER1,MQS_LEFT,LPUART1_RXD,TMR2_TIMER3,FLEXPWM2_PWMB3,GPIO1_IO07,REF_24M_OUT,,,,,,ALT5
GPIO_AD_B0_06,PIT_TRIGGER0,MQS_RIGHT,LPUART1_TXD,TMR2_TIMER2,FLEXPWM2_PWM3_A,GPIO1_IO06,REF_32K_OUT,,,,,,ALT5
GPIO_AD_B0_07,PIT_TRIGGER1,MQS_LEFT,LPUART1_RXD,TMR2_TIMER3,FLEXPWM2_PWM3_B,GPIO1_IO07,REF_24M_OUT,,,,,,ALT5
GPIO_AD_B0_08,ENET_TX_CLK,LPI2C3_SCL,LPUART1_CTS_B,KPP_COL0,ENET_REF_CLK,GPIO1_IO08,ARM_CM7_TXEV,,,,,ACMP1_IN4,ALT5
GPIO_AD_B0_09,ENET_RX_DATA1,LPI2C3_SDA,LPUART1_RTS_B,KPP_ROW0,,GPIO1_IO09,ARM_CM7_RXEV,,,,,ACMP2_IN4,ALT5
GPIO_AD_B0_10,ENET_RX_DATA0,LPSPI1_SCK,LPUART5_TXD,KPP_COL1,FLEXPWM2_PWMA2,GPIO1_IO10,ARM_TRACE_CLK,,,,,ACMP3_IN4,ALT5
GPIO_AD_B0_11,ENET_RX_EN,LPSPI1_PCS0,LPUART5_RXD,KPP_ROW1,FLEXPWM2_PWMB2,GPIO1_IO11,ARM_TRACE_SWO,,,,,ACMP4_IN4,ALT5
GPIO_AD_B0_12,ENET_RX_ER,LPSPI1_SDO,LPUART3_CTS_B,KPP_COL2,FLEXPWM2_PWMA1,GPIO1_IO12,ARM_TRACE0,SNVS_VIO_5_CTL,,,ADC1_IN0,,ALT5
GPIO_AD_B0_13,ENET_TX_EN,LPSPI1_SDI,LPUART3_RTS_B,KPP_ROW2,FLEXPWM2_PWMB1,GPIO1_IO13,,SNVS_VIO_5_B,,,ADC2_IN0,,ALT5
GPIO_AD_B0_14,ENET_TX_DATA0,FLEXCAN2_TX,LPUART3_TXD,KPP_COL3,FLEXPWM2_PWMA0,GPIO1_IO14,,WDOG1_ANY,,,"ADC1_IN1,ADC2_IN1","ACMP1_IN0,ACMP2_IN0,ACMP3_IN0,ACMP4_IN0",ALT5
GPIO_AD_B0_15,ENET_TX_DATA1,FLEXCAN2_RX,LPUART3_RXD,KPP_ROW3,FLEXPWM2_PWMB0,GPIO1_IO15,,,,,"ADC1_IN2,ADC2_IN2","ACMP1_IN1,ACMP2_IN1,ACMP3_IN1,ACMP4_IN1",ALT5
GPIO_AD_B0_10,ENET_RX_DATA0,LPSPI1_SCK,LPUART5_TXD,KPP_COL1,FLEXPWM2_PWM2_A,GPIO1_IO10,ARM_TRACE_CLK,,,,,ACMP3_IN4,ALT5
GPIO_AD_B0_11,ENET_RX_EN,LPSPI1_PCS0,LPUART5_RXD,KPP_ROW1,FLEXPWM2_PWM2_B,GPIO1_IO11,ARM_TRACE_SWO,,,,,ACMP4_IN4,ALT5
GPIO_AD_B0_12,ENET_RX_ER,LPSPI1_SDO,LPUART3_CTS_B,KPP_COL2,FLEXPWM2_PWM1_A,GPIO1_IO12,ARM_TRACE0,SNVS_VIO_5_CTL,,,ADC1_IN0,,ALT5
GPIO_AD_B0_13,ENET_TX_EN,LPSPI1_SDI,LPUART3_RTS_B,KPP_ROW2,FLEXPWM2_PWM1_B,GPIO1_IO13,,SNVS_VIO_5_B,,,ADC2_IN0,,ALT5
GPIO_AD_B0_14,ENET_TX_DATA0,FLEXCAN2_TX,LPUART3_TXD,KPP_COL3,FLEXPWM2_PWM0_A,GPIO1_IO14,,WDOG1_ANY,,,"ADC1_IN1,ADC2_IN1","ACMP1_IN0,ACMP2_IN0,ACMP3_IN0,ACMP4_IN0",ALT5
GPIO_AD_B0_15,ENET_TX_DATA1,FLEXCAN2_RX,LPUART3_RXD,KPP_ROW3,FLEXPWM2_PWM0_B,GPIO1_IO15,,,,,"ADC1_IN2,ADC2_IN2","ACMP1_IN1,ACMP2_IN1,ACMP3_IN1,ACMP4_IN1",ALT5
GPIO_AD_B1_00,SEMC_RDY,FLEXSPI_A_DATA3,FLEXCAN2_TX,SAI1_MCLK,FLEXIO1_D15,GPIO1_IO16,ENET_1588_EVENT2_OUT,KPP_COL4,,,,ACMP1_IN2,ALT5
GPIO_AD_B1_01,SEMC_CSX0,FLEXSPI_A_SCLK,FLEXCAN2_RX,SAI1_TX_BCLK,FLEXIO1_D14,GPIO1_IO17,ENET_1588_EVENT2_IN,KPP_ROW4,,,ADC1_IN3,ACMP2_IN2,ALT5
GPIO_AD_B1_02,SEMC_CSX1,FLEXSPI_A_DATA0,LPSPI4_SCK,SAI1_TX_SYNC,FLEXIO1_D13,GPIO1_IO18,ENET_1588_EVENT3_OUT,KPP_COL5,,,ADC2_IN3,ACMP3_IN2,ALT5
GPIO_AD_B1_03,SEMC_CSX2,FLEXSPI_A_DATA2,LPSPI4_PCS0,SAI1_TX_DATA0,FLEXIO1_D12,GPIO1_IO19,ENET_1588_EVENT3_IN,KPP_ROW5,,,ADC1_IN4,ACMP4_IN2,ALT5
GPIO_AD_B1_04,SEMC_CSX3,FLEXSPI_A_DATA1,LPSPI4_SDO,SAI1_RX_SYNC,FLEXIO1_D11,GPIO1_IO20,LPSPI1_PCS1,KPP_COL6,,,ADC2_IN4,ACMP1_IN3,ALT5
GPIO_AD_B1_05,USDHC1_WP,FLEXSPI_A_SS0_B,LPSPI4_SDI,SAI1_RX_DATA0,FLEXIO1_D10,GPIO1_IO21,LPSPI1_PCS2,KPP_ROW6,,,"ADC1_IN5,ADC2_IN5",ACMP2_IN3,ALT5
GPIO_AD_B1_06,USDHC1_RESET_B,FLEXPWM1_PWMA0,LPUART2_CTS_B,SAI1_RX_BCLK,FLEXIO1_D09,GPIO1_IO22,LPSPI1_PCS3,KPP_COL7,,,"ADC1_IN6,ADC2_IN6",ACMP3_IN3,ALT5
GPIO_AD_B1_07,USDHC1_VSELECT,FLEXPWM1_PWMB0,LPUART2_RTS_B,SAI1_TX_DATA1,FLEXIO1_D08,GPIO1_IO23,LPSPI3_PCS3,KPP_ROW7,,,"ADC1_IN7,ADC2_IN7",ACMP4_IN3,ALT5
GPIO_AD_B1_08,LPI2C2_SCL,FLEXPWM1_PWMA1,LPUART2_TXD,SAI1_TX_DATA2,FLEXIO1_D07,GPIO1_IO24,LPSPI3_PCS2,XBAR_INOUT12,,,"ADC1_IN8,ADC2_IN8",ACMP1_IN5,ALT5
GPIO_AD_B1_09,LPI2C2_SDA,FLEXPWM1_PWMB1,LPUART2_RXD,SAI1_TX_DATA3,FLEXIO1_D06,GPIO1_IO25,LPSPI3_PCS1,XBAR_INOUT13,,,"ADC1_IN9,ADC2_IN9",ACMP2_IN5,ALT5
GPIO_AD_B1_10,USB_OTG1_PWR,FLEXPWM1_PWMA2,LPUART4_TXD,USDHC1_CD_B,FLEXIO1_D05,GPIO1_IO26,GPT2_CAPTURE1,,,,"ADC1_IN10,ADC2_IN10",ACMP3_IN5,ALT5
GPIO_AD_B1_11,USB_OTG1_ID,FLEXPWM1_PWMB2,LPUART4_RXD,USDHC1_WP,FLEXIO1_D04,GPIO1_IO27,GPT2_COMPARE1,,,,"ADC1_IN11,ADC2_IN11",ACMP4_IN5,ALT5
GPIO_AD_B1_12,USB_OTG1_OC,ACMP1_OUT,LPSPI3_SCK,USDHC2_CD_B,FLEXIO1_D03,GPIO1_IO28,FLEXPWM1_PWMA3,,,,"ADC1_IN12,ADC2_IN12","ACMP1_IN6,ACMP1_OUT",ALT5
GPIO_AD_B1_13,LPI2C1_HREQ,ACMP2_OUT,LPSPI3_PCS0,USDHC2_WP,FLEXIO1_D02,GPIO1_IO29,FLEXPWM1_PWMB3,,,,"ADC1_IN13,ADC2_IN13","ACMP2_IN6,ACMP2_OUT",ALT5
GPIO_AD_B1_06,USDHC1_RESET_B,FLEXPWM1_PWM0_A,LPUART2_CTS_B,SAI1_RX_BCLK,FLEXIO1_D09,GPIO1_IO22,LPSPI1_PCS3,KPP_COL7,,,"ADC1_IN6,ADC2_IN6",ACMP3_IN3,ALT5
GPIO_AD_B1_07,USDHC1_VSELECT,FLEXPWM1_PWM0_B,LPUART2_RTS_B,SAI1_TX_DATA1,FLEXIO1_D08,GPIO1_IO23,LPSPI3_PCS3,KPP_ROW7,,,"ADC1_IN7,ADC2_IN7",ACMP4_IN3,ALT5
GPIO_AD_B1_08,LPI2C2_SCL,FLEXPWM1_PWM1_A,LPUART2_TXD,SAI1_TX_DATA2,FLEXIO1_D07,GPIO1_IO24,LPSPI3_PCS2,XBAR_INOUT12,,,"ADC1_IN8,ADC2_IN8",ACMP1_IN5,ALT5
GPIO_AD_B1_09,LPI2C2_SDA,FLEXPWM1_PWM1_B,LPUART2_RXD,SAI1_TX_DATA3,FLEXIO1_D06,GPIO1_IO25,LPSPI3_PCS1,XBAR_INOUT13,,,"ADC1_IN9,ADC2_IN9",ACMP2_IN5,ALT5
GPIO_AD_B1_10,USB_OTG1_PWR,FLEXPWM1_PWM2_A,LPUART4_TXD,USDHC1_CD_B,FLEXIO1_D05,GPIO1_IO26,GPT2_CAPTURE1,,,,"ADC1_IN10,ADC2_IN10",ACMP3_IN5,ALT5
GPIO_AD_B1_11,USB_OTG1_ID,FLEXPWM1_PWM2_B,LPUART4_RXD,USDHC1_WP,FLEXIO1_D04,GPIO1_IO27,GPT2_COMPARE1,,,,"ADC1_IN11,ADC2_IN11",ACMP4_IN5,ALT5
GPIO_AD_B1_12,USB_OTG1_OC,ACMP1_OUT,LPSPI3_SCK,USDHC2_CD_B,FLEXIO1_D03,GPIO1_IO28,FLEXPWM1_PWM3_A,,,,"ADC1_IN12,ADC2_IN12","ACMP1_IN6,ACMP1_OUT",ALT5
GPIO_AD_B1_13,LPI2C1_HREQ,ACMP2_OUT,LPSPI3_PCS0,USDHC2_WP,FLEXIO1_D02,GPIO1_IO29,FLEXPWM1_PWM3_B,,,,"ADC1_IN13,ADC2_IN13","ACMP2_IN6,ACMP2_OUT",ALT5
GPIO_AD_B1_14,LPI2C1_SCL,ACMP3_OUT,LPSPI3_SDO,ENET_1588_EVENT0_OUT,FLEXIO1_D01,GPIO1_IO30,,,,,"ADC1_IN14,ADC2_IN14","ACMP3_IN6,ACMP3_OUT",ALT5
GPIO_AD_B1_15,LPI2C1_SDA,ACMP4_OUT,LPSPI3_SDI,ENET_1588_EVENT0_IN,FLEXIO1_D00,GPIO1_IO31,,,,,"ADC1_IN15,ADC2_IN15","ACMP4_IN6,ACMP4_OUT",ALT5
GPIO_EMC_00,SEMC_DA00,TMR2_TIMER0,LPUART4_CTS_B,SPDIF_SR_CLK,LPSPI2_SCK,GPIO2_IO00,FLEXCAN1_TX,PIT_TRIGGER2,,,,,ALT5
@ -41,36 +41,36 @@ GPIO_EMC_06,SEMC_DA06,XBAR_INOUT06,LPUART3_TXD,SAI2_TX_DATA,FLEXIO1_D18,GPIO2_IO
GPIO_EMC_07,SEMC_DA07,XBAR_INOUT07,LPUART3_RXD,SAI2_RX_SYNC,FLEXIO1_D19,GPIO2_IO07,USBPHY1_TSTO_RX_SQUELCH,,,,,,ALT5
GPIO_EMC_08,SEMC_DM0,XBAR_INOUT08,FLEXCAN2_TX,SAI2_RX_DATA,FLEXIO1_D20,GPIO2_IO08,USBPHY1_TSTO_RX_DISCON_DET,,,,,,ALT5
GPIO_EMC_09,SEMC_WE,XBAR_INOUT09,FLEXCAN2_RX,SAI2_RX_BCLK,FLEXIO1_D21,GPIO2_IO09,USBPHY1_TSTO_RX_HS_RXD,,,,,,ALT5
GPIO_EMC_10,SEMC_CAS,XBAR_INOUT10,LPI2C4_SDA,SAI1_TX_SYNC,LPSPI2_SCK,GPIO2_IO10,FLEXPWM2_PWMX0,,,,,,ALT5
GPIO_EMC_11,SEMC_RAS,XBAR_INOUT11,LPI2C4_SCL,SAI1_TX_BCLK,LPSPI2_PCS0,GPIO2_IO11,FLEXPWM2_PWMX1,,,,,,ALT5
GPIO_EMC_12,SEMC_CS0,XBAR_INOUT12,LPUART6_TXD,SAI1_TX_DATA0,LPSPI2_SDO,GPIO2_IO12,FLEXPWM2_PWMX2,,,,,,ALT5
GPIO_EMC_13,SEMC_BA0,XBAR_INOUT13,LPUART6_RXD,SAI1_RX_DATA0,LPSPI2_SDI,GPIO2_IO13,FLEXPWM2_PWMX3,CCM_PMIC_RDY,,,,,ALT5
GPIO_EMC_10,SEMC_CAS,XBAR_INOUT10,LPI2C4_SDA,SAI1_TX_SYNC,LPSPI2_SCK,GPIO2_IO10,FLEXPWM2_PWM0_X,,,,,,ALT5
GPIO_EMC_11,SEMC_RAS,XBAR_INOUT11,LPI2C4_SCL,SAI1_TX_BCLK,LPSPI2_PCS0,GPIO2_IO11,FLEXPWM2_PWM1_X,,,,,,ALT5
GPIO_EMC_12,SEMC_CS0,XBAR_INOUT12,LPUART6_TXD,SAI1_TX_DATA0,LPSPI2_SDO,GPIO2_IO12,FLEXPWM2_PWM2_X,,,,,,ALT5
GPIO_EMC_13,SEMC_BA0,XBAR_INOUT13,LPUART6_RXD,SAI1_RX_DATA0,LPSPI2_SDI,GPIO2_IO13,FLEXPWM2_PWM3_X,CCM_PMIC_RDY,,,,,ALT5
GPIO_EMC_14,SEMC_BA1,XBAR_INOUT14,LPUART6_CTS_B,SAI1_RX_BCLK,LPSPI2_PCS1,GPIO2_IO14,FLEXCAN1_TX,,,,,,ALT5
GPIO_EMC_15,SEMC_ADDR10,XBAR_INOUT15,LPUART6_RTS_B,SAI1_RX_SYNC,WDOG1_B,GPIO2_IO15,FLEXCAN1_RX,,,,,,ALT5
GPIO_EMC_16,SEMC_ADDR00,,MQS_RIGHT,SAI2_MCLK,,GPIO2_IO16,SRC_BOOT_MODE0,,,,,,ALT5
GPIO_EMC_17,SEMC_ADDR01,,MQS_LEFT,SAI3_MCLK,,GPIO2_IO17,SRC_BOOT_MODE1,,,,,,ALT5
GPIO_EMC_18,SEMC_ADDR02,XBAR_INOUT16,LPI2C2_SDA,SAI1_RX_SYNC,FLEXIO1_D22,GPIO2_IO18,SRC_BT_CFG0,,,,,,ALT5
GPIO_EMC_19,SEMC_ADDR03,XBAR_INOUT17,LPI2C2_SCL,SAI1_RX_BCLK,FLEXIO1_D23,GPIO2_IO19,SRC_BT_CFG1,,,,,,ALT5
GPIO_EMC_20,SEMC_ADDR04,FLEXPWM1_PWMA3,LPUART2_CTS_B,SAI1_MCLK,FLEXIO1_D24,GPIO2_IO20,SRC_BT_CFG2,,,,,,ALT5
GPIO_EMC_21,SEMC_ADDR05,FLEXPWM1_PWMB3,LPUART2_RTS_B,SAI1_RX_DATA0,FLEXIO1_D25,GPIO2_IO21,SRC_BT_CFG3,,,,,,ALT5
GPIO_EMC_22,SEMC_ADDR06,FLEXPWM1_PWMA2,LPUART2_TXD,SAI1_TX_DATA3,FLEXIO1_D26,GPIO2_IO22,SRC_BT_CFG4,,,,,,ALT5
GPIO_EMC_23,SEMC_ADDR07,FLEXPWM1_PWMB2,LPUART2_RXD,SAI1_TX_DATA2,FLEXIO1_D27,GPIO2_IO23,SRC_BT_CFG5,,,,,,ALT5
GPIO_EMC_24,SEMC_ADDR08,FLEXPWM1_PWMA1,LPUART8_CTS_B,SAI1_TX_DATA1,FLEXIO1_D28,GPIO2_IO24,SRC_BT_CFG6,,,,,,ALT5
GPIO_EMC_25,SEMC_ADDR09,FLEXPWM1_PWMB1,LPUART8_RTS_B,SAI1_TX_DATA0,FLEXIO1_D29,GPIO2_IO25,SRC_BT_CFG7,,,,,,ALT5
GPIO_EMC_26,SEMC_ADDR11,FLEXPWM1_PWMA0,LPUART8_TXD,SAI1_TX_BCLK,FLEXIO1_D30,GPIO2_IO26,SRC_BT_CFG8,,,,,,ALT5
GPIO_EMC_27,SEMC_ADDR12,FLEXPWM1_PWMB0,LPUART8_RXD,SAI1_TX_SYNC,FLEXIO1_D31,GPIO2_IO27,SRC_BT_CFG9,,,,,,ALT5
GPIO_EMC_28,SEMC_DQS,FLEXPWM2_PWMA3,XBAR_INOUT18,SAI3_MCLK,EWM_OUT_B,GPIO2_IO28,GPT2_CAPTURE2,FLEXPWM1_PWMX0,,,,,ALT5
GPIO_EMC_29,SEMC_CKE,FLEXPWM2_PWMB3,XBAR_INOUT19,SAI3_RX_BCLK,WDOG2_RST_B_DEB,GPIO2_IO29,GPT2_COMPARE2,FLEXPWM1_PWMX1,,,,,ALT5
GPIO_EMC_30,SEMC_CLK,FLEXPWM2_PWMA2,LPUART4_CTS_B,SAI3_RX_SYNC,WDOG1_RST_B_DEB,GPIO2_IO30,GPT2_COMPARE3,FLEXPWM1_PWMX2,,,,,ALT5
GPIO_EMC_31,SEMC_DM1,FLEXPWM2_PWMB2,LPUART4_RTS_B,SAI3_RX_DATA,WDOG2_B,GPIO2_IO31,GPT2_CLK,FLEXPWM1_PWMX3,,,,,ALT5
GPIO_EMC_20,SEMC_ADDR04,FLEXPWM1_PWM3_A,LPUART2_CTS_B,SAI1_MCLK,FLEXIO1_D24,GPIO2_IO20,SRC_BT_CFG2,,,,,,ALT5
GPIO_EMC_21,SEMC_ADDR05,FLEXPWM1_PWM3_B,LPUART2_RTS_B,SAI1_RX_DATA0,FLEXIO1_D25,GPIO2_IO21,SRC_BT_CFG3,,,,,,ALT5
GPIO_EMC_22,SEMC_ADDR06,FLEXPWM1_PWM2_A,LPUART2_TXD,SAI1_TX_DATA3,FLEXIO1_D26,GPIO2_IO22,SRC_BT_CFG4,,,,,,ALT5
GPIO_EMC_23,SEMC_ADDR07,FLEXPWM1_PWM2_B,LPUART2_RXD,SAI1_TX_DATA2,FLEXIO1_D27,GPIO2_IO23,SRC_BT_CFG5,,,,,,ALT5
GPIO_EMC_24,SEMC_ADDR08,FLEXPWM1_PWM1_A,LPUART8_CTS_B,SAI1_TX_DATA1,FLEXIO1_D28,GPIO2_IO24,SRC_BT_CFG6,,,,,,ALT5
GPIO_EMC_25,SEMC_ADDR09,FLEXPWM1_PWM1_B,LPUART8_RTS_B,SAI1_TX_DATA0,FLEXIO1_D29,GPIO2_IO25,SRC_BT_CFG7,,,,,,ALT5
GPIO_EMC_26,SEMC_ADDR11,FLEXPWM1_PWM0_A,LPUART8_TXD,SAI1_TX_BCLK,FLEXIO1_D30,GPIO2_IO26,SRC_BT_CFG8,,,,,,ALT5
GPIO_EMC_27,SEMC_ADDR12,FLEXPWM1_PWM0_B,LPUART8_RXD,SAI1_TX_SYNC,FLEXIO1_D31,GPIO2_IO27,SRC_BT_CFG9,,,,,,ALT5
GPIO_EMC_28,SEMC_DQS,FLEXPWM2_PWM3_A,XBAR_INOUT18,SAI3_MCLK,EWM_OUT_B,GPIO2_IO28,GPT2_CAPTURE2,FLEXPWM1_PWM0_X,,,,,ALT5
GPIO_EMC_29,SEMC_CKE,FLEXPWM2_PWM3_B,XBAR_INOUT19,SAI3_RX_BCLK,WDOG2_RST_B_DEB,GPIO2_IO29,GPT2_COMPARE2,FLEXPWM1_PWM1_X,,,,,ALT5
GPIO_EMC_30,SEMC_CLK,FLEXPWM2_PWM2_A,LPUART4_CTS_B,SAI3_RX_SYNC,WDOG1_RST_B_DEB,GPIO2_IO30,GPT2_COMPARE3,FLEXPWM1_PWM2_X,,,,,ALT5
GPIO_EMC_31,SEMC_DM1,FLEXPWM2_PWM2_B,LPUART4_RTS_B,SAI3_RX_DATA,WDOG2_B,GPIO2_IO31,GPT2_CLK,FLEXPWM1_PWM3_X,,,,,ALT5
GPIO_EMC_32,SEMC_DA08,TMR1_TIMER0,LPUART4_TXD,SAI3_TX_DATA,LPSPI4_SCK,GPIO3_IO00,USBPHY1_TSTO_RX_FS_RXD,REF_24M_OUT,,,,,ALT5
GPIO_EMC_33,SEMC_DA09,TMR1_TIMER1,LPUART4_RXD,SAI3_TX_BCLK,LPSPI4_PCS0,GPIO3_IO01,USBPHY1_TSTI_TX_DP,SRC_TESTER_ACK,,,,,ALT5
GPIO_EMC_34,SEMC_DA10,TMR1_TIMER2,LPUART7_TXD,SAI3_TX_SYNC,LPSPI4_SDO,GPIO3_IO02,ENET_CRS,,,,,,ALT5
GPIO_EMC_35,SEMC_DA11,TMR1_TIMER3,LPUART7_RXD,USDHC2_WP,LPSPI4_SDI,GPIO3_IO03,ENET_COL,,,,,,ALT5
GPIO_EMC_36,SEMC_DA12,FLEXPWM2_PWMA1,LPUART5_CTS_B,CCM_PMIC_RDY,LPSPI4_PCS1,GPIO3_IO04,ENET_RX_CLK,USDHC1_WP,,,,,ALT5
GPIO_EMC_37,SEMC_DA13,FLEXPWM2_PWMB1,LPUART5_RTS_B,MQS_RIGHT,LPSPI4_PCS2,GPIO3_IO05,ENET_RX_DATA3,USDHC1_VSELECT,,,,,ALT5
GPIO_EMC_38,SEMC_DA14,FLEXPWM2_PWMA0,LPUART5_TXD,MQS_LEFT,LPSPI4_PCS3,GPIO3_IO06,ENET_RX_DATA2,USDHC1_CD_B,,,,,ALT5
GPIO_EMC_39,SEMC_DA15,FLEXPWM2_PWMB0,LPUART5_RXD,USB_OTG1_OC,WDOG1_B,GPIO3_IO07,ENET_TX_ER,GPT1_CLK,,,,,ALT5
GPIO_EMC_36,SEMC_DA12,FLEXPWM2_PWM1_A,LPUART5_CTS_B,CCM_PMIC_RDY,LPSPI4_PCS1,GPIO3_IO04,ENET_RX_CLK,USDHC1_WP,,,,,ALT5
GPIO_EMC_37,SEMC_DA13,FLEXPWM2_PWM1_B,LPUART5_RTS_B,MQS_RIGHT,LPSPI4_PCS2,GPIO3_IO05,ENET_RX_DATA3,USDHC1_VSELECT,,,,,ALT5
GPIO_EMC_38,SEMC_DA14,FLEXPWM2_PWM0_A,LPUART5_TXD,MQS_LEFT,LPSPI4_PCS3,GPIO3_IO06,ENET_RX_DATA2,USDHC1_CD_B,,,,,ALT5
GPIO_EMC_39,SEMC_DA15,FLEXPWM2_PWM0_B,LPUART5_RXD,USB_OTG1_OC,WDOG1_B,GPIO3_IO07,ENET_TX_ER,GPT1_CLK,,,,,ALT5
GPIO_EMC_40,SEMC_CSX0,XBAR_INOUT18,SPDIF_OUT,USB_OTG1_ID,ENET_MDIO,GPIO3_IO08,ENET_TX_DATA3,GPT1_COMPARE3,,,,,ALT5
GPIO_EMC_41,SEMC_RDY,XBAR_INOUT19,SPDIF_IN,USB_OTG1_PWR,ENET_MDC,GPIO3_IO09,ENET_TX_DATA2,GPT1_COMPARE2,,,,,ALT5
GPIO_SD_B0_00,USDHC1_DATA2,TMR1_TIMER0,SAI1_MCLK,SAI2_MCLK,LPI2C3_SCL,GPIO3_IO13,FLEXSPI_A_SS1_B,XBAR_INOUT14,,,,,ALT5

1 Pad ALT0 ALT1 ALT2 ALT3 ALT4 ALT5 ALT6 ALT7 ALT8 ALT9 ADC ACMP Default
5 GPIO_AD_B0_03 JTAG_TDI USDHC2_CD_B WDOG1_B SAI1_MCLK USDHC1_WP GPIO1_IO03 USB_OTG1_OC CCM_PMIC_RDY ALT0
6 GPIO_AD_B0_04 JTAG_TDO FLEXCAN1_TX USDHC1_WP TMR2_TIMER0 ENET_MDIO GPIO1_IO04 USB_OTG1_PWR EWM_OUT_B ALT0
7 GPIO_AD_B0_05 JTAG_TRSTB FLEXCAN1_RX USDHC1_CD_B TMR2_TIMER1 ENET_MDC GPIO1_IO05 USB_OTG1_ID ARM_NMI ALT0
8 GPIO_AD_B0_06 PIT_TRIGGER0 MQS_RIGHT LPUART1_TXD TMR2_TIMER2 FLEXPWM2_PWMA3 FLEXPWM2_PWM3_A GPIO1_IO06 REF_32K_OUT ALT5
9 GPIO_AD_B0_07 PIT_TRIGGER1 MQS_LEFT LPUART1_RXD TMR2_TIMER3 FLEXPWM2_PWMB3 FLEXPWM2_PWM3_B GPIO1_IO07 REF_24M_OUT ALT5
10 GPIO_AD_B0_08 ENET_TX_CLK LPI2C3_SCL LPUART1_CTS_B KPP_COL0 ENET_REF_CLK GPIO1_IO08 ARM_CM7_TXEV ACMP1_IN4 ALT5
11 GPIO_AD_B0_09 ENET_RX_DATA1 LPI2C3_SDA LPUART1_RTS_B KPP_ROW0 GPIO1_IO09 ARM_CM7_RXEV ACMP2_IN4 ALT5
12 GPIO_AD_B0_10 ENET_RX_DATA0 LPSPI1_SCK LPUART5_TXD KPP_COL1 FLEXPWM2_PWMA2 FLEXPWM2_PWM2_A GPIO1_IO10 ARM_TRACE_CLK ACMP3_IN4 ALT5
13 GPIO_AD_B0_11 ENET_RX_EN LPSPI1_PCS0 LPUART5_RXD KPP_ROW1 FLEXPWM2_PWMB2 FLEXPWM2_PWM2_B GPIO1_IO11 ARM_TRACE_SWO ACMP4_IN4 ALT5
14 GPIO_AD_B0_12 ENET_RX_ER LPSPI1_SDO LPUART3_CTS_B KPP_COL2 FLEXPWM2_PWMA1 FLEXPWM2_PWM1_A GPIO1_IO12 ARM_TRACE0 SNVS_VIO_5_CTL ADC1_IN0 ALT5
15 GPIO_AD_B0_13 ENET_TX_EN LPSPI1_SDI LPUART3_RTS_B KPP_ROW2 FLEXPWM2_PWMB1 FLEXPWM2_PWM1_B GPIO1_IO13 SNVS_VIO_5_B ADC2_IN0 ALT5
16 GPIO_AD_B0_14 ENET_TX_DATA0 FLEXCAN2_TX LPUART3_TXD KPP_COL3 FLEXPWM2_PWMA0 FLEXPWM2_PWM0_A GPIO1_IO14 WDOG1_ANY ADC1_IN1,ADC2_IN1 ACMP1_IN0,ACMP2_IN0,ACMP3_IN0,ACMP4_IN0 ALT5
17 GPIO_AD_B0_15 ENET_TX_DATA1 FLEXCAN2_RX LPUART3_RXD KPP_ROW3 FLEXPWM2_PWMB0 FLEXPWM2_PWM0_B GPIO1_IO15 ADC1_IN2,ADC2_IN2 ACMP1_IN1,ACMP2_IN1,ACMP3_IN1,ACMP4_IN1 ALT5
18 GPIO_AD_B1_00 SEMC_RDY FLEXSPI_A_DATA3 FLEXCAN2_TX SAI1_MCLK FLEXIO1_D15 GPIO1_IO16 ENET_1588_EVENT2_OUT KPP_COL4 ACMP1_IN2 ALT5
19 GPIO_AD_B1_01 SEMC_CSX0 FLEXSPI_A_SCLK FLEXCAN2_RX SAI1_TX_BCLK FLEXIO1_D14 GPIO1_IO17 ENET_1588_EVENT2_IN KPP_ROW4 ADC1_IN3 ACMP2_IN2 ALT5
20 GPIO_AD_B1_02 SEMC_CSX1 FLEXSPI_A_DATA0 LPSPI4_SCK SAI1_TX_SYNC FLEXIO1_D13 GPIO1_IO18 ENET_1588_EVENT3_OUT KPP_COL5 ADC2_IN3 ACMP3_IN2 ALT5
21 GPIO_AD_B1_03 SEMC_CSX2 FLEXSPI_A_DATA2 LPSPI4_PCS0 SAI1_TX_DATA0 FLEXIO1_D12 GPIO1_IO19 ENET_1588_EVENT3_IN KPP_ROW5 ADC1_IN4 ACMP4_IN2 ALT5
22 GPIO_AD_B1_04 SEMC_CSX3 FLEXSPI_A_DATA1 LPSPI4_SDO SAI1_RX_SYNC FLEXIO1_D11 GPIO1_IO20 LPSPI1_PCS1 KPP_COL6 ADC2_IN4 ACMP1_IN3 ALT5
23 GPIO_AD_B1_05 USDHC1_WP FLEXSPI_A_SS0_B LPSPI4_SDI SAI1_RX_DATA0 FLEXIO1_D10 GPIO1_IO21 LPSPI1_PCS2 KPP_ROW6 ADC1_IN5,ADC2_IN5 ACMP2_IN3 ALT5
24 GPIO_AD_B1_06 USDHC1_RESET_B FLEXPWM1_PWMA0 FLEXPWM1_PWM0_A LPUART2_CTS_B SAI1_RX_BCLK FLEXIO1_D09 GPIO1_IO22 LPSPI1_PCS3 KPP_COL7 ADC1_IN6,ADC2_IN6 ACMP3_IN3 ALT5
25 GPIO_AD_B1_07 USDHC1_VSELECT FLEXPWM1_PWMB0 FLEXPWM1_PWM0_B LPUART2_RTS_B SAI1_TX_DATA1 FLEXIO1_D08 GPIO1_IO23 LPSPI3_PCS3 KPP_ROW7 ADC1_IN7,ADC2_IN7 ACMP4_IN3 ALT5
26 GPIO_AD_B1_08 LPI2C2_SCL FLEXPWM1_PWMA1 FLEXPWM1_PWM1_A LPUART2_TXD SAI1_TX_DATA2 FLEXIO1_D07 GPIO1_IO24 LPSPI3_PCS2 XBAR_INOUT12 ADC1_IN8,ADC2_IN8 ACMP1_IN5 ALT5
27 GPIO_AD_B1_09 LPI2C2_SDA FLEXPWM1_PWMB1 FLEXPWM1_PWM1_B LPUART2_RXD SAI1_TX_DATA3 FLEXIO1_D06 GPIO1_IO25 LPSPI3_PCS1 XBAR_INOUT13 ADC1_IN9,ADC2_IN9 ACMP2_IN5 ALT5
28 GPIO_AD_B1_10 USB_OTG1_PWR FLEXPWM1_PWMA2 FLEXPWM1_PWM2_A LPUART4_TXD USDHC1_CD_B FLEXIO1_D05 GPIO1_IO26 GPT2_CAPTURE1 ADC1_IN10,ADC2_IN10 ACMP3_IN5 ALT5
29 GPIO_AD_B1_11 USB_OTG1_ID FLEXPWM1_PWMB2 FLEXPWM1_PWM2_B LPUART4_RXD USDHC1_WP FLEXIO1_D04 GPIO1_IO27 GPT2_COMPARE1 ADC1_IN11,ADC2_IN11 ACMP4_IN5 ALT5
30 GPIO_AD_B1_12 USB_OTG1_OC ACMP1_OUT LPSPI3_SCK USDHC2_CD_B FLEXIO1_D03 GPIO1_IO28 FLEXPWM1_PWMA3 FLEXPWM1_PWM3_A ADC1_IN12,ADC2_IN12 ACMP1_IN6,ACMP1_OUT ALT5
31 GPIO_AD_B1_13 LPI2C1_HREQ ACMP2_OUT LPSPI3_PCS0 USDHC2_WP FLEXIO1_D02 GPIO1_IO29 FLEXPWM1_PWMB3 FLEXPWM1_PWM3_B ADC1_IN13,ADC2_IN13 ACMP2_IN6,ACMP2_OUT ALT5
32 GPIO_AD_B1_14 LPI2C1_SCL ACMP3_OUT LPSPI3_SDO ENET_1588_EVENT0_OUT FLEXIO1_D01 GPIO1_IO30 ADC1_IN14,ADC2_IN14 ACMP3_IN6,ACMP3_OUT ALT5
33 GPIO_AD_B1_15 LPI2C1_SDA ACMP4_OUT LPSPI3_SDI ENET_1588_EVENT0_IN FLEXIO1_D00 GPIO1_IO31 ADC1_IN15,ADC2_IN15 ACMP4_IN6,ACMP4_OUT ALT5
34 GPIO_EMC_00 SEMC_DA00 TMR2_TIMER0 LPUART4_CTS_B SPDIF_SR_CLK LPSPI2_SCK GPIO2_IO00 FLEXCAN1_TX PIT_TRIGGER2 ALT5
41 GPIO_EMC_07 SEMC_DA07 XBAR_INOUT07 LPUART3_RXD SAI2_RX_SYNC FLEXIO1_D19 GPIO2_IO07 USBPHY1_TSTO_RX_SQUELCH ALT5
42 GPIO_EMC_08 SEMC_DM0 XBAR_INOUT08 FLEXCAN2_TX SAI2_RX_DATA FLEXIO1_D20 GPIO2_IO08 USBPHY1_TSTO_RX_DISCON_DET ALT5
43 GPIO_EMC_09 SEMC_WE XBAR_INOUT09 FLEXCAN2_RX SAI2_RX_BCLK FLEXIO1_D21 GPIO2_IO09 USBPHY1_TSTO_RX_HS_RXD ALT5
44 GPIO_EMC_10 SEMC_CAS XBAR_INOUT10 LPI2C4_SDA SAI1_TX_SYNC LPSPI2_SCK GPIO2_IO10 FLEXPWM2_PWMX0 FLEXPWM2_PWM0_X ALT5
45 GPIO_EMC_11 SEMC_RAS XBAR_INOUT11 LPI2C4_SCL SAI1_TX_BCLK LPSPI2_PCS0 GPIO2_IO11 FLEXPWM2_PWMX1 FLEXPWM2_PWM1_X ALT5
46 GPIO_EMC_12 SEMC_CS0 XBAR_INOUT12 LPUART6_TXD SAI1_TX_DATA0 LPSPI2_SDO GPIO2_IO12 FLEXPWM2_PWMX2 FLEXPWM2_PWM2_X ALT5
47 GPIO_EMC_13 SEMC_BA0 XBAR_INOUT13 LPUART6_RXD SAI1_RX_DATA0 LPSPI2_SDI GPIO2_IO13 FLEXPWM2_PWMX3 FLEXPWM2_PWM3_X CCM_PMIC_RDY ALT5
48 GPIO_EMC_14 SEMC_BA1 XBAR_INOUT14 LPUART6_CTS_B SAI1_RX_BCLK LPSPI2_PCS1 GPIO2_IO14 FLEXCAN1_TX ALT5
49 GPIO_EMC_15 SEMC_ADDR10 XBAR_INOUT15 LPUART6_RTS_B SAI1_RX_SYNC WDOG1_B GPIO2_IO15 FLEXCAN1_RX ALT5
50 GPIO_EMC_16 SEMC_ADDR00 MQS_RIGHT SAI2_MCLK GPIO2_IO16 SRC_BOOT_MODE0 ALT5
51 GPIO_EMC_17 SEMC_ADDR01 MQS_LEFT SAI3_MCLK GPIO2_IO17 SRC_BOOT_MODE1 ALT5
52 GPIO_EMC_18 SEMC_ADDR02 XBAR_INOUT16 LPI2C2_SDA SAI1_RX_SYNC FLEXIO1_D22 GPIO2_IO18 SRC_BT_CFG0 ALT5
53 GPIO_EMC_19 SEMC_ADDR03 XBAR_INOUT17 LPI2C2_SCL SAI1_RX_BCLK FLEXIO1_D23 GPIO2_IO19 SRC_BT_CFG1 ALT5
54 GPIO_EMC_20 SEMC_ADDR04 FLEXPWM1_PWMA3 FLEXPWM1_PWM3_A LPUART2_CTS_B SAI1_MCLK FLEXIO1_D24 GPIO2_IO20 SRC_BT_CFG2 ALT5
55 GPIO_EMC_21 SEMC_ADDR05 FLEXPWM1_PWMB3 FLEXPWM1_PWM3_B LPUART2_RTS_B SAI1_RX_DATA0 FLEXIO1_D25 GPIO2_IO21 SRC_BT_CFG3 ALT5
56 GPIO_EMC_22 SEMC_ADDR06 FLEXPWM1_PWMA2 FLEXPWM1_PWM2_A LPUART2_TXD SAI1_TX_DATA3 FLEXIO1_D26 GPIO2_IO22 SRC_BT_CFG4 ALT5
57 GPIO_EMC_23 SEMC_ADDR07 FLEXPWM1_PWMB2 FLEXPWM1_PWM2_B LPUART2_RXD SAI1_TX_DATA2 FLEXIO1_D27 GPIO2_IO23 SRC_BT_CFG5 ALT5
58 GPIO_EMC_24 SEMC_ADDR08 FLEXPWM1_PWMA1 FLEXPWM1_PWM1_A LPUART8_CTS_B SAI1_TX_DATA1 FLEXIO1_D28 GPIO2_IO24 SRC_BT_CFG6 ALT5
59 GPIO_EMC_25 SEMC_ADDR09 FLEXPWM1_PWMB1 FLEXPWM1_PWM1_B LPUART8_RTS_B SAI1_TX_DATA0 FLEXIO1_D29 GPIO2_IO25 SRC_BT_CFG7 ALT5
60 GPIO_EMC_26 SEMC_ADDR11 FLEXPWM1_PWMA0 FLEXPWM1_PWM0_A LPUART8_TXD SAI1_TX_BCLK FLEXIO1_D30 GPIO2_IO26 SRC_BT_CFG8 ALT5
61 GPIO_EMC_27 SEMC_ADDR12 FLEXPWM1_PWMB0 FLEXPWM1_PWM0_B LPUART8_RXD SAI1_TX_SYNC FLEXIO1_D31 GPIO2_IO27 SRC_BT_CFG9 ALT5
62 GPIO_EMC_28 SEMC_DQS FLEXPWM2_PWMA3 FLEXPWM2_PWM3_A XBAR_INOUT18 SAI3_MCLK EWM_OUT_B GPIO2_IO28 GPT2_CAPTURE2 FLEXPWM1_PWMX0 FLEXPWM1_PWM0_X ALT5
63 GPIO_EMC_29 SEMC_CKE FLEXPWM2_PWMB3 FLEXPWM2_PWM3_B XBAR_INOUT19 SAI3_RX_BCLK WDOG2_RST_B_DEB GPIO2_IO29 GPT2_COMPARE2 FLEXPWM1_PWMX1 FLEXPWM1_PWM1_X ALT5
64 GPIO_EMC_30 SEMC_CLK FLEXPWM2_PWMA2 FLEXPWM2_PWM2_A LPUART4_CTS_B SAI3_RX_SYNC WDOG1_RST_B_DEB GPIO2_IO30 GPT2_COMPARE3 FLEXPWM1_PWMX2 FLEXPWM1_PWM2_X ALT5
65 GPIO_EMC_31 SEMC_DM1 FLEXPWM2_PWMB2 FLEXPWM2_PWM2_B LPUART4_RTS_B SAI3_RX_DATA WDOG2_B GPIO2_IO31 GPT2_CLK FLEXPWM1_PWMX3 FLEXPWM1_PWM3_X ALT5
66 GPIO_EMC_32 SEMC_DA08 TMR1_TIMER0 LPUART4_TXD SAI3_TX_DATA LPSPI4_SCK GPIO3_IO00 USBPHY1_TSTO_RX_FS_RXD REF_24M_OUT ALT5
67 GPIO_EMC_33 SEMC_DA09 TMR1_TIMER1 LPUART4_RXD SAI3_TX_BCLK LPSPI4_PCS0 GPIO3_IO01 USBPHY1_TSTI_TX_DP SRC_TESTER_ACK ALT5
68 GPIO_EMC_34 SEMC_DA10 TMR1_TIMER2 LPUART7_TXD SAI3_TX_SYNC LPSPI4_SDO GPIO3_IO02 ENET_CRS ALT5
69 GPIO_EMC_35 SEMC_DA11 TMR1_TIMER3 LPUART7_RXD USDHC2_WP LPSPI4_SDI GPIO3_IO03 ENET_COL ALT5
70 GPIO_EMC_36 SEMC_DA12 FLEXPWM2_PWMA1 FLEXPWM2_PWM1_A LPUART5_CTS_B CCM_PMIC_RDY LPSPI4_PCS1 GPIO3_IO04 ENET_RX_CLK USDHC1_WP ALT5
71 GPIO_EMC_37 SEMC_DA13 FLEXPWM2_PWMB1 FLEXPWM2_PWM1_B LPUART5_RTS_B MQS_RIGHT LPSPI4_PCS2 GPIO3_IO05 ENET_RX_DATA3 USDHC1_VSELECT ALT5
72 GPIO_EMC_38 SEMC_DA14 FLEXPWM2_PWMA0 FLEXPWM2_PWM0_A LPUART5_TXD MQS_LEFT LPSPI4_PCS3 GPIO3_IO06 ENET_RX_DATA2 USDHC1_CD_B ALT5
73 GPIO_EMC_39 SEMC_DA15 FLEXPWM2_PWMB0 FLEXPWM2_PWM0_B LPUART5_RXD USB_OTG1_OC WDOG1_B GPIO3_IO07 ENET_TX_ER GPT1_CLK ALT5
74 GPIO_EMC_40 SEMC_CSX0 XBAR_INOUT18 SPDIF_OUT USB_OTG1_ID ENET_MDIO GPIO3_IO08 ENET_TX_DATA3 GPT1_COMPARE3 ALT5
75 GPIO_EMC_41 SEMC_RDY XBAR_INOUT19 SPDIF_IN USB_OTG1_PWR ENET_MDC GPIO3_IO09 ENET_TX_DATA2 GPT1_COMPARE2 ALT5
76 GPIO_SD_B0_00 USDHC1_DATA2 TMR1_TIMER0 SAI1_MCLK SAI2_MCLK LPI2C3_SCL GPIO3_IO13 FLEXSPI_A_SS1_B XBAR_INOUT14 ALT5

Wyświetl plik

@ -8,7 +8,7 @@ import sys
import csv
import re
SUPPORTED_AFS = {"GPIO", "USDHC", "SEMC"}
SUPPORTED_AFS = {"GPIO", "USDHC", "FLEXPWM", "TMR"}
MAX_AF = 10 # AF0 .. AF9
ADC_COL = 11
@ -282,29 +282,33 @@ class Pins(object):
hdr_file.write("extern const mp_obj_dict_t machine_pin_board_pins_locals_dict;\n")
hdr_file.write("\n// Defines\n")
usdhc_instance_factory(self.cpu_pins, hdr_file)
module_instance_factory(self.cpu_pins, hdr_file, "USDHC")
module_instance_factory(self.cpu_pins, hdr_file, "FLEXPWM")
module_instance_factory(self.cpu_pins, hdr_file, "TMR")
def usdhc_instance_factory(pins, output_file):
usdhc_pins = filter(lambda p: any([af for af in p.alt_fn if "USDHC" in af.af_str]), pins)
def module_instance_factory(pins, output_file, name):
module_pin = filter(lambda p: any([af for af in p.alt_fn if name in af.af_str]), pins)
usdhc_instances = dict()
for pin in usdhc_pins:
module_instances = dict()
for pin in module_pin:
for idx, alt_fn in enumerate(pin.alt_fn):
if "USDHC" in alt_fn.instance:
if name in alt_fn.instance:
format_string = "#define {0}_{1} &pin_{0}, {2}"
if alt_fn.instance not in usdhc_instances:
usdhc_instances[alt_fn.instance] = [
if alt_fn.instance not in module_instances:
module_instances[alt_fn.instance] = [
format_string.format(pin.name, alt_fn.af_str, idx)
]
else:
usdhc_instances[alt_fn.instance].append(
module_instances[alt_fn.instance].append(
format_string.format(pin.name, alt_fn.af_str, idx)
)
for k, v in usdhc_instances.items():
for k, v in module_instances.items():
output_file.write(f"// {k}\n")
output_file.write(f"#define {k}_AVAIL (1)\n")
if name == "FLEXPWM":
output_file.write(f"#define {k} {k[-4:]}\n")
for i in v:
output_file.write(i + "\n")
@ -326,7 +330,7 @@ def main():
"-i",
"--iomux",
dest="iomux_filename",
help="Specifies the fsl_iomux.h file for the chip",
help="Specifies the fsl_iomuxc.h file for the chip",
default="fsl_iomuxc.h",
)
parser.add_argument(

Wyświetl plik

@ -0,0 +1,180 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP *
* Copyright (c) 2021 Robert Hammelrath
* SPDX-License-Identifier: BSD-3-Clause
*
*/
// These are a few functions taken from the NXP-Lib
// for PWM, for
// - dealing with an u16 duty cycle setting,
// - setting the pulse center position, and
// - factoring out pure duty cycle change.
#include "py/runtime.h"
#include "hal/pwm_backport.h"
void PWM_UpdatePwmDutycycle_u16(
PWM_Type *base, pwm_submodule_t subModule, pwm_channels_t pwmSignal, uint16_t dutyCycle, uint16_t Center_u16) {
assert((uint16_t)pwmSignal < 2U);
uint16_t pulseCnt = 0, pwmHighPulse = 0;
uint16_t center;
// check and confine bounds for Center_u16
if ((Center_u16 + dutyCycle / 2) >= PWM_FULL_SCALE) {
Center_u16 = PWM_FULL_SCALE - dutyCycle / 2 - 1;
} else if (Center_u16 < (dutyCycle / 2)) {
Center_u16 = dutyCycle / 2;
}
pulseCnt = base->SM[subModule].VAL1 + 1;
// Calculate pulse width and center position
pwmHighPulse = (pulseCnt * dutyCycle) / PWM_FULL_SCALE;
center = (pulseCnt * Center_u16) / PWM_FULL_SCALE;
// Setup the PWM dutycycle of channel A or B
if (pwmSignal == kPWM_PwmA) {
base->SM[subModule].VAL2 = center - pwmHighPulse / 2;
base->SM[subModule].VAL3 = base->SM[subModule].VAL2 + pwmHighPulse;
} else {
base->SM[subModule].VAL4 = center - pwmHighPulse / 2;
base->SM[subModule].VAL5 = base->SM[subModule].VAL4 + pwmHighPulse;
}
}
void PWM_SetupPwm_u16(PWM_Type *base, pwm_submodule_t subModule, pwm_signal_param_u16_t *chnlParams,
uint32_t pwmFreq_Hz, uint32_t srcClock_Hz, bool output_enable) {
uint32_t pwmClock;
uint16_t pulseCnt = 0;
uint8_t polarityShift = 0, outputEnableShift = 0;
// Divide the clock by the prescale value
pwmClock = (srcClock_Hz / (1U << ((base->SM[subModule].CTRL & PWM_CTRL_PRSC_MASK) >> PWM_CTRL_PRSC_SHIFT)));
pulseCnt = pwmClock / pwmFreq_Hz;
base->SM[subModule].INIT = 0;
base->SM[subModule].VAL1 = pulseCnt - 1;
// Set up the Registers VAL2..VAL5 controlling the duty cycle of channel A/B
PWM_UpdatePwmDutycycle_u16(base, subModule, chnlParams->pwmChannel,
chnlParams->dutyCycle_u16, chnlParams->Center_u16);
// Setup register shift values based on the channel being configured.
// Also setup the deadtime value
if (chnlParams->pwmChannel == kPWM_PwmA) {
polarityShift = PWM_OCTRL_POLA_SHIFT;
outputEnableShift = PWM_OUTEN_PWMA_EN_SHIFT;
base->SM[subModule].DTCNT0 = PWM_DTCNT0_DTCNT0(chnlParams->deadtimeValue);
} else {
polarityShift = PWM_OCTRL_POLB_SHIFT;
outputEnableShift = PWM_OUTEN_PWMB_EN_SHIFT;
base->SM[subModule].DTCNT1 = PWM_DTCNT1_DTCNT1(chnlParams->deadtimeValue);
}
// Setup signal active level
if (chnlParams->level == kPWM_HighTrue) {
base->SM[subModule].OCTRL &= ~(1U << polarityShift);
} else {
base->SM[subModule].OCTRL |= (1U << polarityShift);
}
// Enable PWM output
if (output_enable) {
base->OUTEN |= (1U << (outputEnableShift + subModule));
}
}
void PWM_SetupPwmx_u16(PWM_Type *base, pwm_submodule_t subModule,
uint32_t pwmFreq_Hz, uint16_t duty_cycle, uint8_t invert, uint32_t srcClock_Hz) {
uint32_t pulseCnt;
uint32_t pwmClock;
// Divide the clock by the prescale value
pwmClock = (srcClock_Hz / (1U << ((base->SM[subModule].CTRL & PWM_CTRL_PRSC_MASK) >> PWM_CTRL_PRSC_SHIFT)));
pulseCnt = pwmClock / pwmFreq_Hz;
base->SM[subModule].INIT = 0;
base->SM[subModule].VAL0 = ((uint32_t)duty_cycle * pulseCnt) / PWM_FULL_SCALE;
base->SM[subModule].VAL1 = pulseCnt - 1;
base->SM[subModule].OCTRL = (base->SM[subModule].OCTRL & ~PWM_OCTRL_POLX_MASK) | PWM_OCTRL_POLX(!invert);
base->OUTEN |= (1U << subModule);
}
void PWM_SetupFaultDisableMap(PWM_Type *base, pwm_submodule_t subModule,
pwm_channels_t pwmChannel, pwm_fault_channels_t pwm_fault_channels, uint16_t value) {
uint16_t reg = base->SM[subModule].DISMAP[pwm_fault_channels];
switch (pwmChannel) {
case kPWM_PwmA:
reg &= ~((uint16_t)PWM_DISMAP_DIS0A_MASK);
reg |= (((uint16_t)(value) << (uint16_t)PWM_DISMAP_DIS0A_SHIFT) & (uint16_t)PWM_DISMAP_DIS0A_MASK);
break;
case kPWM_PwmB:
reg &= ~((uint16_t)PWM_DISMAP_DIS0B_MASK);
reg |= (((uint16_t)(value) << (uint16_t)PWM_DISMAP_DIS0B_SHIFT) & (uint16_t)PWM_DISMAP_DIS0B_MASK);
break;
case kPWM_PwmX:
reg &= ~((uint16_t)PWM_DISMAP_DIS0X_MASK);
reg |= (((uint16_t)(value) << (uint16_t)PWM_DISMAP_DIS0X_SHIFT) & (uint16_t)PWM_DISMAP_DIS0X_MASK);
break;
default:
assert(false);
break;
}
base->SM[subModule].DISMAP[pwm_fault_channels] = reg;
}
#ifdef FSL_FEATURE_SOC_TMR_COUNT
status_t QTMR_SetupPwm_u16(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t pwmFreqHz,
uint16_t dutyCycleU16, bool outputPolarity, uint32_t srcClock_Hz, bool is_init) {
uint32_t periodCount, highCount, lowCount, reg;
if (dutyCycleU16 >= PWM_FULL_SCALE) {
// Invalid dutycycle
return kStatus_Fail;
}
// Counter values to generate a PWM signal
periodCount = (srcClock_Hz / pwmFreqHz) - 1;
highCount = (periodCount * dutyCycleU16) / PWM_FULL_SCALE;
lowCount = periodCount - highCount;
// Setup the compare registers for PWM output
if (is_init == false) {
base->CHANNEL[channel].COMP1 = lowCount;
base->CHANNEL[channel].COMP2 = highCount;
}
// Setup the pre-load registers for PWM output
base->CHANNEL[channel].CMPLD1 = lowCount;
base->CHANNEL[channel].CMPLD2 = highCount;
reg = base->CHANNEL[channel].CSCTRL;
// Setup the compare load control for COMP1 and COMP2.
// Load COMP1 when CSCTRL[TCF2] is asserted, load COMP2 when CSCTRL[TCF1] is asserted
reg &= ~(TMR_CSCTRL_CL1_MASK | TMR_CSCTRL_CL2_MASK);
reg |= (TMR_CSCTRL_CL1(kQTMR_LoadOnComp2) | TMR_CSCTRL_CL2(kQTMR_LoadOnComp1));
base->CHANNEL[channel].CSCTRL = reg;
// Set OFLAG pin for output mode
base->CHANNEL[channel].SCTRL |= TMR_SCTRL_OEN_MASK;
if (outputPolarity) {
// Invert the polarity
base->CHANNEL[channel].SCTRL |= TMR_SCTRL_OPS_MASK;
} else {
// True polarity, no inversion
base->CHANNEL[channel].SCTRL &= ~TMR_SCTRL_OPS_MASK;
}
reg = base->CHANNEL[channel].CTRL;
reg &= ~(TMR_CTRL_OUTMODE_MASK);
// Count until compare value is reached and re-initialize the counter, toggle OFLAG output
// using alternating compare register
reg |= (TMR_CTRL_LENGTH_MASK | TMR_CTRL_OUTMODE(kQTMR_ToggleOnAltCompareReg));
base->CHANNEL[channel].CTRL = reg;
return kStatus_Success;
}
#endif // FSL_FEATURE_SOC_TMR_COUNT

Wyświetl plik

@ -0,0 +1,51 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP *
* Copyright (c) 2021 Robert Hammelrath
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef PWM_BACKPORT_H
#define PWM_BACKPORT_H
#include "fsl_pwm.h"
#ifdef FSL_FEATURE_SOC_TMR_COUNT
#include "fsl_qtmr.h"
#endif
typedef struct _pwm_signal_param_u16
{
pwm_channels_t pwmChannel; // PWM channel being configured; PWM A or PWM B
uint16_t dutyCycle_u16; // PWM pulse width, value should be between 0 to 65536
uint16_t Center_u16; // Center of the pulse, value should be between 0 to 65536
pwm_level_select_t level; // PWM output active level select */
uint16_t deadtimeValue; // The deadtime value; only used if channel pair is operating in complementary mode
} pwm_signal_param_u16_t;
typedef enum _pwm_fault_channels {
kPWM_faultchannel_0 = 0U,
kPWM_faultchannel_1
} pwm_fault_channels_t;
#define PWM_FULL_SCALE (65536UL)
void PWM_UpdatePwmDutycycle_u16(PWM_Type *base, pwm_submodule_t subModule,
pwm_channels_t pwmSignal, uint16_t dutyCycle, uint16_t center);
void PWM_SetupPwm_u16(PWM_Type *base, pwm_submodule_t subModule, pwm_signal_param_u16_t *chnlParams,
uint32_t pwmFreq_Hz, uint32_t srcClock_Hz, bool output_enable);
void PWM_SetupPwmx_u16(PWM_Type *base, pwm_submodule_t subModule,
uint32_t pwmFreq_Hz, uint16_t duty_cycle, uint8_t invert, uint32_t srcClock_Hz);
void PWM_SetupFaultDisableMap(PWM_Type *base, pwm_submodule_t subModule,
pwm_channels_t pwmChannel, pwm_fault_channels_t pwm_fault_channels, uint16_t value);
#ifdef FSL_FEATURE_SOC_TMR_COUNT
status_t QTMR_SetupPwm_u16(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t pwmFreqHz,
uint16_t dutyCycleU16, bool outputPolarity, uint32_t srcClock_Hz, bool is_init);
#endif // FSL_FEATURE_SOC_TMR_COUNT
#endif // PWM_BACKPORT_H

Wyświetl plik

@ -0,0 +1,618 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020-2021 Damien P. George
* Copyright (c) 2021 Robert Hammelrath
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/runtime.h"
#include "py/mphal.h"
#include "modmachine.h"
#include "pin.h"
#include "fsl_clock.h"
#include "fsl_iomuxc.h"
#include "hal/pwm_backport.h"
#define PWM_MIDDLE (0)
#define PWM_BEGIN (1)
#define PWM_END (2)
#define PWM_CHANNEL1 (1)
#define PWM_CHANNEL2 (2)
typedef struct _machine_pwm_obj_t {
mp_obj_base_t base;
PWM_Type *instance;
bool is_flexpwm;
uint8_t complementary;
uint8_t module;
uint8_t submodule;
uint8_t channel1;
uint8_t channel2;
uint8_t invert;
bool sync;
uint32_t freq;
int16_t prescale;
uint16_t duty_u16;
uint32_t duty_ns;
uint16_t center;
uint32_t deadtime;
bool output_enable_1;
bool output_enable_2;
uint8_t xor;
bool is_init;
} machine_pwm_obj_t;
static char channel_char[] = {'B', 'A', 'X' };
static char *ERRMSG_FREQ = "PWM frequency too low";
static char *ERRMSG_INIT = "PWM set-up failed";
static char *ERRMSG_VALUE = "value larger than period";
STATIC void machine_pwm_start(machine_pwm_obj_t *self);
STATIC void mp_machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
machine_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (self->is_flexpwm) {
mp_printf(print, "<FLEXPWM module=%u submodule=%u ", self->module, self->submodule);
if (self->complementary) {
mp_printf(print, "channel=%c/%c", channel_char[self->channel1], channel_char[self->channel2]);
} else {
mp_printf(print, "channel=%c", channel_char[self->channel1]);
}
if (self->duty_ns != 0) {
mp_printf(print, " duty_ns=%u", self->duty_ns);
} else {
mp_printf(print, " duty_u16=%u", self->duty_u16);
}
mp_printf(print, " freq=%u center=%u, deadtime=%u, sync=%u>",
self->freq, self->center, self->deadtime, self->sync);
#ifdef FSL_FEATURE_SOC_TMR_COUNT
} else {
mp_printf(print, "<QTMR_PWM module=%u channel=%u freq1=%u ",
self->module, self->channel1, self->freq);
if (self->duty_ns != 0) {
mp_printf(print, "duty_ns=%u>", self->duty_ns);
} else {
mp_printf(print, "duty_u16=%u>", self->duty_u16);
}
#endif
}
}
// Utility functions for decoding and convertings
//
STATIC uint32_t duty_ns_to_duty_u16(uint32_t freq, uint32_t duty_ns) {
uint64_t duty = (uint64_t)duty_ns * freq * PWM_FULL_SCALE / 1000000000ULL;
if (duty >= PWM_FULL_SCALE) {
mp_raise_ValueError(MP_ERROR_TEXT(ERRMSG_VALUE));
}
return (uint32_t)duty;
}
STATIC uint8_t module_decode(char channel) {
switch (channel) {
case '0':
return kPWM_Module_0;
case '1':
return kPWM_Module_1;
case '2':
return kPWM_Module_2;
case '3':
return kPWM_Module_3;
default:
return kPWM_Module_1;
}
}
STATIC uint8_t channel_decode(char channel) {
switch (channel) {
case 'A':
return kPWM_PwmA;
case 'B':
return kPWM_PwmB;
case 'X':
return kPWM_PwmX;
default:
return kPWM_PwmA;
}
}
// decode the AF objects module and Port numer. Returns NULL if it is not a FLEXPWM object
STATIC const machine_pin_af_obj_t *af_name_decode_flexpwm(const machine_pin_af_obj_t *af_obj,
uint8_t *module, uint8_t *submodule, uint8_t *channel) {
const char *str;
size_t len;
str = (char *)qstr_data(af_obj->name, &len);
// test for the name starting with FLEXPWM
if (len < 15 || strncmp(str, "FLEXPWM", 7) != 0) {
return NULL;
}
// Get module, submodule and channel from the name, e.g. FLEXPWM1_PWM0_A
*module = str[7] - '0';
*submodule = module_decode(str[12]);
*channel = channel_decode(str[14]);
return af_obj;
}
#ifdef FSL_FEATURE_SOC_TMR_COUNT
STATIC uint8_t qtmr_decode(char channel) {
switch (channel) {
case '0':
return kQTMR_Channel_0;
case '1':
return kQTMR_Channel_1;
case '2':
return kQTMR_Channel_2;
case '3':
return kQTMR_Channel_3;
default:
return kPWM_Module_1;
}
}
// decode the AF objects module and Port numer. Returns NULL if it is not a QTMR object
STATIC const machine_pin_af_obj_t *af_name_decode_qtmr(const machine_pin_af_obj_t *af_obj, uint8_t *module, uint8_t *channel) {
const char *str;
size_t len;
str = (char *)qstr_data(af_obj->name, &len);
// test for the name starting with TMR
if (len < 11 || strncmp(str, "TMR", 3) != 0) {
return NULL;
}
// Get module, submodule and channel from the name, e.g. FLEXPWM1_PWM0_A
*module = str[3] - '0';
*channel = qtmr_decode(str[10]);
return af_obj;
}
#endif
STATIC bool is_board_pin(const machine_pin_obj_t *pin) {
for (int i = 0; i < num_board_pins; i++) {
if (pin == machine_pin_board_pins[i]) {
return true;
}
}
return false;
}
// Functions for configuring the PWM Device
//
STATIC int calc_prescaler(uint32_t clock, uint32_t freq) {
float temp = (float)clock / (float)PWM_FULL_SCALE / (float)freq;
for (int prescale = 0; prescale < 8; prescale++, temp /= 2) {
if (temp <= 1) {
return prescale;
}
}
// Frequency too low, cannot scale down.
return -1;
}
STATIC void configure_flexpwm(machine_pwm_obj_t *self) {
pwm_signal_param_u16_t pwmSignal;
// Initialize PWM module.
uint32_t pwmSourceClockInHz = CLOCK_GetFreq(kCLOCK_IpgClk);
int prescale = calc_prescaler(pwmSourceClockInHz, self->freq);
if (prescale < 0) {
mp_raise_ValueError(MP_ERROR_TEXT(ERRMSG_FREQ));
}
if (self->prescale != prescale || self->is_init == false) {
pwm_config_t pwmConfig;
PWM_GetDefaultConfig(&pwmConfig);
self->prescale = prescale;
pwmConfig.prescale = prescale;
pwmConfig.reloadLogic = kPWM_ReloadPwmFullCycle;
if (self->complementary) {
pwmConfig.pairOperation = self->channel1 == kPWM_PwmA ? kPWM_ComplementaryPwmA : kPWM_ComplementaryPwmB;
} else {
pwmConfig.pairOperation = kPWM_Independent;
}
pwmConfig.clockSource = kPWM_BusClock;
pwmConfig.enableWait = false;
pwmConfig.initializationControl = self->sync ? kPWM_Initialize_MasterSync : kPWM_Initialize_LocalSync;
if (PWM_Init(self->instance, self->submodule, &pwmConfig) == kStatus_Fail) {
mp_raise_ValueError(MP_ERROR_TEXT(ERRMSG_INIT));
}
}
// Disable the fault detect function to avoid using the xbara
PWM_SetupFaultDisableMap(self->instance, self->submodule, self->channel1, kPWM_faultchannel_0, 0);
PWM_SetupFaultDisableMap(self->instance, self->submodule, self->channel1, kPWM_faultchannel_1, 0);
if (self->complementary) {
PWM_SetupFaultDisableMap(self->instance, self->submodule, self->channel2, kPWM_faultchannel_0, 0);
PWM_SetupFaultDisableMap(self->instance, self->submodule, self->channel2, kPWM_faultchannel_1, 0);
}
if (self->channel1 != kPWM_PwmX) { // Only for A/B channels
// Initialize the channel parameters
pwmSignal.pwmChannel = self->channel1;
pwmSignal.level = (self->invert & PWM_CHANNEL1) ? kPWM_LowTrue : kPWM_HighTrue;
pwmSignal.dutyCycle_u16 = self->duty_u16;
pwmSignal.Center_u16 = self->center;
pwmSignal.deadtimeValue = ((uint64_t)pwmSourceClockInHz * self->deadtime) / 1000000000ULL;
PWM_SetupPwm_u16(self->instance, self->submodule, &pwmSignal, self->freq,
pwmSourceClockInHz, self->output_enable_1);
if (self->complementary) {
// Initialize the second channel of the pair.
pwmSignal.pwmChannel = self->channel2;
pwmSignal.level = (self->invert & PWM_CHANNEL2) ? kPWM_LowTrue : kPWM_HighTrue;
PWM_SetupPwm_u16(self->instance, self->submodule, &pwmSignal, self->freq,
pwmSourceClockInHz, self->output_enable_2);
}
if (self->xor == 1) {
// Set the DBLEN bit for A, B = A ^ B
self->instance->SM[self->submodule].CTRL &= ~PWM_CTRL_SPLIT_MASK;
self->instance->SM[self->submodule].CTRL |= PWM_CTRL_DBLEN_MASK;
} else if (self->xor == 2) {
// Set the DBLEN and SPLIT bits for A, B = A ^ B
self->instance->SM[self->submodule].CTRL |= PWM_CTRL_DBLEN_MASK | PWM_CTRL_SPLIT_MASK;
} else {
self->instance->SM[self->submodule].CTRL &= ~(PWM_CTRL_DBLEN_MASK | PWM_CTRL_SPLIT_MASK);
}
} else {
PWM_SetupPwmx_u16(self->instance, self->submodule, self->freq, self->duty_u16,
self->invert, pwmSourceClockInHz);
if (self->xor) {
// Set the DBLX bit for X = A ^ B
self->instance->SM[self->submodule].CTRL |= PWM_CTRL_DBLX_MASK;
} else {
self->instance->SM[self->submodule].CTRL &= ~PWM_CTRL_DBLX_MASK;
}
}
// Set the load okay bit for the submodules
PWM_SetPwmLdok(self->instance, 1 << self->submodule, true);
// Start the PWM generation from the Submodules
PWM_StartTimer(self->instance, 1 << self->submodule);
}
#ifdef FSL_FEATURE_SOC_TMR_COUNT
STATIC void configure_qtmr(machine_pwm_obj_t *self) {
qtmr_config_t qtmrConfig;
int prescale;
TMR_Type *instance = (TMR_Type *)self->instance;
prescale = calc_prescaler(CLOCK_GetFreq(kCLOCK_IpgClk), self->freq);
if (prescale < 0) {
mp_raise_ValueError(MP_ERROR_TEXT(ERRMSG_FREQ));
}
if (prescale != self->prescale) {
QTMR_GetDefaultConfig(&qtmrConfig);
qtmrConfig.primarySource = prescale + kQTMR_ClockDivide_1;
QTMR_Init(instance, self->channel1, &qtmrConfig);
self->prescale = prescale;
}
// Set up the PWM channel
if (QTMR_SetupPwm_u16(instance, self->channel1, self->freq, self->duty_u16,
self->invert, CLOCK_GetFreq(kCLOCK_IpgClk) / (1 << prescale), self->is_init) == kStatus_Fail) {
mp_raise_ValueError(MP_ERROR_TEXT(ERRMSG_INIT));
}
// Start the output
QTMR_StartTimer(instance, self->channel1, kQTMR_PriSrcRiseEdge);
}
#endif // FSL_FEATURE_SOC_TMR_COUNT
STATIC void configure_pwm(machine_pwm_obj_t *self) {
// Set the clock frequencies
// Freq range is 15Hz to ~ 3 MHz.
static bool set_frequency = true;
// set the frequency only once
if (set_frequency) {
CLOCK_SetDiv(kCLOCK_IpgDiv, 0x3); // Set IPG PODF to 3, divide by 4
set_frequency = false;
}
if (self->duty_ns != 0) {
self->duty_u16 = duty_ns_to_duty_u16(self->freq, self->duty_ns);
}
if (self->is_flexpwm) {
configure_flexpwm(self);
#ifdef FSL_FEATURE_SOC_TMR_COUNT
} else {
configure_qtmr(self);
#endif
}
}
// Micropython API functions
//
STATIC void mp_machine_pwm_init_helper(machine_pwm_obj_t *self,
size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_freq, ARG_duty_u16, ARG_duty_ns, ARG_center, ARG_align,
ARG_invert, ARG_sync, ARG_xor, ARG_deadtime };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_freq, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_duty_u16, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_duty_ns, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_center, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_align, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1}},
{ MP_QSTR_invert, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1}},
{ MP_QSTR_sync, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1}},
{ MP_QSTR_xor, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1}},
{ MP_QSTR_deadtime, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1}},
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args,
MP_ARRAY_SIZE(allowed_args), allowed_args, args);
if ((n_args + kw_args->used) > 0 || self->is_init == false) {
// Maybe change PWM timer
if (args[ARG_freq].u_int > 0) {
self->freq = args[ARG_freq].u_int;
}
// Set duty_u16 cycle?
uint32_t duty = args[ARG_duty_u16].u_int;
if (duty != 0) {
if (duty >= PWM_FULL_SCALE) {
mp_raise_ValueError(MP_ERROR_TEXT(ERRMSG_VALUE));
}
self->duty_u16 = duty;
self->duty_ns = 0;
}
// Set duty_ns value?
duty = args[ARG_duty_ns].u_int;
if (duty != 0) {
self->duty_ns = duty;
self->duty_u16 = duty_ns_to_duty_u16(self->freq, self->duty_ns);
}
// Set center value?
int32_t center = args[ARG_center].u_int;
if (center >= 0) {
if (center >= PWM_FULL_SCALE) {
mp_raise_ValueError(MP_ERROR_TEXT(ERRMSG_VALUE));
}
self->center = center;
} else { // Use alignment setting shortcut
if (args[ARG_align].u_int >= 0) {
uint8_t align = args[ARG_align].u_int & 3; // limit to 0..3
if (align == PWM_BEGIN) {
self->center = self->duty_u16 / 2;
} else if (align == PWM_END) {
self->center = PWM_FULL_SCALE - self->duty_u16 / 2;
} else {
self->center = 32768; // Default value: mid.
}
}
}
if (args[ARG_invert].u_int >= 0) {
self->invert = args[ARG_invert].u_int & (PWM_CHANNEL1 | PWM_CHANNEL2);
}
if (args[ARG_sync].u_int >= 0) {
self->sync = args[ARG_sync].u_int != false && self->submodule != 0;
}
if (args[ARG_xor].u_int >= 0) {
self->xor = args[ARG_xor].u_int & 0x03;
}
if (args[ARG_deadtime].u_int >= 0) {
self->deadtime = args[ARG_deadtime].u_int;
}
configure_pwm(self);
self->is_init = true;
} else {
machine_pwm_start(self);
}
}
// PWM(pin | pin-tuple, freq, [args])
STATIC mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
// Check number of arguments
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
mp_obj_t *pins;
const machine_pin_obj_t *pin1;
const machine_pin_obj_t *pin2;
// Get referred Pin object(s)
if (mp_obj_is_type(args[0], &mp_type_tuple)) {
mp_obj_get_array_fixed_n(args[0], 2, &pins);
pin1 = pin_find(pins[0]);
pin2 = pin_find(pins[1]);
} else {
pin1 = pin_find(args[0]);
pin2 = NULL;
}
// Check whether it supports PWM and decode submodule & channel
const machine_pin_af_obj_t *af_obj1 = NULL;
uint8_t submodule1;
uint8_t channel1;
const machine_pin_af_obj_t *af_obj2 = NULL;
uint8_t submodule2;
uint8_t channel2;
uint8_t module;
bool is_flexpwm = false;
for (int i = 0; i < pin1->af_list_len; ++i) {
af_obj1 = af_name_decode_flexpwm(&(pin1->af_list[i]), &module, &submodule1, &channel1);
if (af_obj1 != NULL) {
break;
}
}
if (pin2 != NULL) {
for (int i = 0; i < pin1->af_list_len; ++i) {
af_obj2 = af_name_decode_flexpwm(&(pin2->af_list[i]), &module, &submodule2, &channel2);
if (af_obj2 != NULL) {
break;
}
}
}
if (af_obj1 == NULL) {
submodule1 = 0;
#ifdef FSL_FEATURE_SOC_TMR_COUNT
// Check for QTimer support
if (is_board_pin(pin1)) {
for (int i = 0; i < pin1->af_list_len; ++i) {
af_obj1 = af_name_decode_qtmr(&(pin1->af_list[i]), &module, &channel1);
if (af_obj1 != NULL) {
break;
}
}
}
#endif
if (af_obj1 == NULL) {
mp_raise_ValueError(MP_ERROR_TEXT("the requested Pin(s) does not support PWM"));
}
} else {
// is flexpwm, check for instance match
is_flexpwm = true;
if (pin2 != NULL && af_obj1->instance != af_obj2->instance && submodule1 != submodule2) {
mp_raise_ValueError(MP_ERROR_TEXT("the pins must be a A/B pair of a submodule"));
}
}
// Create and populate the PWM object.
machine_pwm_obj_t *self = m_new_obj(machine_pwm_obj_t);
self->base.type = &machine_pwm_type;
self->is_flexpwm = is_flexpwm;
self->instance = af_obj1->instance;
self->module = module;
self->submodule = submodule1;
self->channel1 = channel1;
self->invert = 0;
self->freq = 1000;
self->prescale = -1;
self->duty_u16 = 32768;
self->duty_ns = 0;
self->center = 32768;
self->output_enable_1 = is_board_pin(pin1);
self->sync = false;
self->deadtime = 0;
self->xor = 0;
self->is_init = false;
// Initialize the Pin(s).
CLOCK_EnableClock(kCLOCK_Iomuxc); // just in case it was not set yet
IOMUXC_SetPinMux(pin1->muxRegister, af_obj1->af_mode, af_obj1->input_register, af_obj1->input_daisy,
pin1->configRegister, 0U);
IOMUXC_SetPinConfig(pin1->muxRegister, af_obj1->af_mode, af_obj1->input_register, af_obj1->input_daisy,
pin1->configRegister, 0x10B0U);
// Settings for the second pin, if given.
if (pin2 != NULL && pin2 != pin1) {
self->complementary = 1;
self->channel2 = channel2;
self->output_enable_2 = is_board_pin(pin2);
// Initialize the Pin(s)
IOMUXC_SetPinMux(pin2->muxRegister, af_obj2->af_mode, af_obj2->input_register, af_obj2->input_daisy,
pin2->configRegister, 0U);
IOMUXC_SetPinConfig(pin2->muxRegister, af_obj2->af_mode, af_obj2->input_register, af_obj2->input_daisy,
pin2->configRegister, 0x10B0U);
} else {
self->complementary = 0;
}
// Process the remaining parameters.
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
mp_machine_pwm_init_helper(self, n_args - 1, args + 1, &kw_args);
return MP_OBJ_FROM_PTR(self);
}
// Disable all PWM devices. Called on soft reset
void machine_pwm_deinit_all(void) {
static PWM_Type *const pwm_bases[] = PWM_BASE_PTRS;
for (int i = 1; i < ARRAY_SIZE(pwm_bases); i++) {
PWM_StopTimer(pwm_bases[i], 0x0f); // Stop all submodules
pwm_bases[i]->OUTEN = 0; // Disable ouput on all submodules, all channels
}
#ifdef FSL_FEATURE_SOC_TMR_COUNT
static TMR_Type *const tmr_bases[] = TMR_BASE_PTRS;
for (int i = 1; i < ARRAY_SIZE(tmr_bases); i++) {
for (int j = 0; j < 4; j++) {
QTMR_StopTimer(tmr_bases[i], j); // Stop all timers
}
}
#endif
}
STATIC void machine_pwm_start(machine_pwm_obj_t *self) {
if (self->is_flexpwm) {
PWM_StartTimer(self->instance, 1 << self->submodule);
#ifdef FSL_FEATURE_SOC_TMR_COUNT
} else {
QTMR_StartTimer((TMR_Type *)self->instance, self->channel1, kQTMR_PriSrcRiseEdge);
#endif
}
}
STATIC void mp_machine_pwm_deinit(machine_pwm_obj_t *self) {
if (self->is_flexpwm) {
PWM_StopTimer(self->instance, 1 << self->submodule);
#ifdef FSL_FEATURE_SOC_TMR_COUNT
} else {
QTMR_StopTimer((TMR_Type *)self->instance, self->channel1);
#endif
}
}
mp_obj_t mp_machine_pwm_freq_get(machine_pwm_obj_t *self) {
return MP_OBJ_NEW_SMALL_INT(self->freq);
}
void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq) {
self->freq = freq;
configure_pwm(self);
}
mp_obj_t mp_machine_pwm_duty_get_u16(machine_pwm_obj_t *self) {
return MP_OBJ_NEW_SMALL_INT(self->duty_u16);
}
void mp_machine_pwm_duty_set_u16(machine_pwm_obj_t *self, mp_int_t duty) {
if (duty >= 0) {
if (duty >= PWM_FULL_SCALE) {
mp_raise_ValueError(MP_ERROR_TEXT(ERRMSG_VALUE));
}
self->duty_u16 = duty;
self->duty_ns = 0;
configure_pwm(self);
}
}
mp_obj_t mp_machine_pwm_duty_get_ns(machine_pwm_obj_t *self) {
return MP_OBJ_NEW_SMALL_INT(1000000000ULL / self->freq * self->duty_u16 / PWM_FULL_SCALE);
}
void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty) {
if (duty >= 0) {
self->duty_ns = duty;
self->duty_u16 = duty_ns_to_duty_u16(self->freq, self->duty_ns);
configure_pwm(self);
}
}

Wyświetl plik

@ -119,6 +119,7 @@ int main(void) {
#if MICROPY_PY_NETWORK
mod_network_deinit();
#endif
machine_pwm_deinit_all();
gc_sweep_all();
mp_deinit();
}

Wyświetl plik

@ -129,6 +129,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
#if MICROPY_PY_MACHINE_SDCARD
{ MP_ROM_QSTR(MP_QSTR_SDCard), MP_ROM_PTR(&machine_sdcard_type) },
#endif
{ MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) },
{ MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) },
{ MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) },
{ MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) },

Wyświetl plik

@ -31,6 +31,7 @@
extern const mp_obj_type_t machine_adc_type;
extern const mp_obj_type_t machine_i2c_type;
extern const mp_obj_type_t machine_pwm_type;
extern const mp_obj_type_t machine_rtc_type;
extern const mp_obj_type_t machine_sdcard_type;
extern const mp_obj_type_t machine_spi_type;
@ -40,6 +41,7 @@ extern const mp_obj_type_t machine_wdt_type;
void machine_adc_init(void);
void machine_pin_irq_deinit(void);
void machine_pwm_deinit_all(void);
void machine_timer_init_PIT(void);
void machine_sdcard_init0(void);
void mimxrt_sdram_init(void);

Wyświetl plik

@ -129,6 +129,10 @@ uint32_t trng_random_u32(void);
#define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new
#define MICROPY_PY_MACHINE_BITSTREAM (1)
#define MICROPY_PY_MACHINE_PULSE (1)
#define MICROPY_PY_MACHINE_PWM (1)
#define MICROPY_PY_MACHINE_PWM_INIT (1)
#define MICROPY_PY_MACHINE_PWM_DUTY_U16_NS (1)
#define MICROPY_PY_MACHINE_PWM_INCLUDEFILE "ports/mimxrt/machine_pwm.c"
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_SOFTI2C (1)
#define MICROPY_PY_MACHINE_SPI (1)

Wyświetl plik

@ -129,9 +129,7 @@ void ticks_delay_us64(uint64_t us) {
dt = 0xffffffff;
}
ticks_wake_after_us32((uint32_t)dt);
if (dt < 50) {
__WFE();
} else {
if (dt > 50) {
MICROPY_EVENT_POLL_HOOK
}
}