You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2021/06/26 14:59:02 UTC

[incubator-nuttx] branch master updated (e401aa1 -> b88b5b1)

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git.


    from e401aa1  boards/xtensa/esp32: Update the defconfigs to account for the changes in TEXT_HEAP and the introduction of ESP32_IRAM_HEAP and ARCH_HAVE_EXTRA_HEAPS
     new addfe18  arch/arm/src/imxrt: added support for FlexPWM driver
     new 6e2db9b  boards/arm/imxrt/teensy-4.x: added board level support for FlexPWM driver
     new b88b5b1  Documentation/platforms/arm/imxrt: update documentation with FlexPWM support

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../arm/imxrt/boards/teensy-4.x/index.rst          |   11 +
 Documentation/platforms/arm/imxrt/index.rst        |    6 +-
 arch/arm/src/imxrt/Kconfig                         |  245 +++++
 arch/arm/src/imxrt/Make.defs                       |    4 +
 arch/arm/src/imxrt/hardware/imxrt_iomuxc.h         |    3 +
 arch/arm/src/imxrt/imxrt_flexpwm.c                 | 1061 ++++++++++++++++++++
 .../cxd56_geofence.h => imxrt/imxrt_flexpwm.h}     |   33 +-
 .../configs/{enc-4.1 => pwm-4.1}/defconfig         |   18 +-
 boards/arm/imxrt/teensy-4.x/include/board.h        |    5 +
 boards/arm/imxrt/teensy-4.x/src/Makefile           |    4 +
 boards/arm/imxrt/teensy-4.x/src/imxrt_bringup.c    |    9 +
 .../imxrt/teensy-4.x/src/imxrt_flexpwm.c}          |   73 +-
 boards/arm/imxrt/teensy-4.x/src/teensy-4.h         |   12 +
 13 files changed, 1445 insertions(+), 39 deletions(-)
 create mode 100644 arch/arm/src/imxrt/imxrt_flexpwm.c
 copy arch/arm/src/{cxd56xx/cxd56_geofence.h => imxrt/imxrt_flexpwm.h} (76%)
 copy boards/arm/imxrt/teensy-4.x/configs/{enc-4.1 => pwm-4.1}/defconfig (76%)
 copy boards/{risc-v/esp32c3/esp32c3-devkit/src/esp32c3_ledc.c => arm/imxrt/teensy-4.x/src/imxrt_flexpwm.c} (60%)

[incubator-nuttx] 02/03: boards/arm/imxrt/teensy-4.x: added board level support for FlexPWM driver

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 6e2db9bed139537a5bcb6c2da36342631eb29725
Author: Michal Lenc <mi...@seznam.cz>
AuthorDate: Sat Jun 26 11:55:09 2021 +0200

    boards/arm/imxrt/teensy-4.x: added board level support for FlexPWM driver
    
    Signed-off-by: Michal Lenc <mi...@seznam.cz>
---
 .../arm/imxrt/teensy-4.x/configs/pwm-4.1/defconfig |  57 ++++++++
 boards/arm/imxrt/teensy-4.x/include/board.h        |   5 +
 boards/arm/imxrt/teensy-4.x/src/Makefile           |   4 +
 boards/arm/imxrt/teensy-4.x/src/imxrt_bringup.c    |   9 ++
 boards/arm/imxrt/teensy-4.x/src/imxrt_flexpwm.c    | 151 +++++++++++++++++++++
 boards/arm/imxrt/teensy-4.x/src/teensy-4.h         |  12 ++
 6 files changed, 238 insertions(+)

diff --git a/boards/arm/imxrt/teensy-4.x/configs/pwm-4.1/defconfig b/boards/arm/imxrt/teensy-4.x/configs/pwm-4.1/defconfig
new file mode 100644
index 0000000..565e1c0
--- /dev/null
+++ b/boards/arm/imxrt/teensy-4.x/configs/pwm-4.1/defconfig
@@ -0,0 +1,57 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+CONFIG_ARCH="arm"
+CONFIG_ARCH_BOARD="teensy-4.x"
+CONFIG_ARCH_BOARD_TEENSY_4X=y
+CONFIG_ARCH_CHIP="imxrt"
+CONFIG_ARCH_CHIP_IMXRT=y
+CONFIG_ARCH_CHIP_MIMXRT1062DVL6A=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_ARMV7M_DCACHE=y
+CONFIG_ARMV7M_DCACHE_WRITETHROUGH=y
+CONFIG_ARMV7M_ICACHE=y
+CONFIG_ARMV7M_USEBASEPRI=y
+CONFIG_BOARD_LOOPSPERMSEC=104926
+CONFIG_BUILTIN=y
+CONFIG_EXAMPLES_PWM=y
+CONFIG_EXAMPLES_PWM_DEVPATH="/dev/pwm1"
+CONFIG_EXAMPLES_PWM_DURATION=10
+CONFIG_EXAMPLES_PWM_DUTYPCT1=30
+CONFIG_EXAMPLES_PWM_DUTYPCT2=80
+CONFIG_EXAMPLES_PWM_FREQUENCY=4000
+CONFIG_FS_PROCFS=y
+CONFIG_IDLETHREAD_STACKSIZE=2048
+CONFIG_IMXRT_FLEXPWM2=y
+CONFIG_IMXRT_FLEXPWM2_MOD1=y
+CONFIG_IMXRT_FLEXPWM2_MOD2=y
+CONFIG_IMXRT_LPUART1=y
+CONFIG_INTELHEX_BINARY=y
+CONFIG_IOB_NBUFFERS=24
+CONFIG_IOB_NCHAINS=24
+CONFIG_LIBC_FLOATINGPOINT=y
+CONFIG_LPUART1_SERIAL_CONSOLE=y
+CONFIG_MAX_TASKS=16
+CONFIG_MM_IOB=y
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_LINELEN=64
+CONFIG_NSH_READLINE=y
+CONFIG_PWM=y
+CONFIG_PWM_MULTICHAN=y
+CONFIG_PWM_NCHANNELS=2
+CONFIG_RAM_SIZE=1048576
+CONFIG_RAM_START=0x20200000
+CONFIG_SCHED_HPWORK=y
+CONFIG_SIG_DEFAULT=y
+CONFIG_START_DAY=14
+CONFIG_START_MONTH=3
+CONFIG_SYSTEM_NSH=y
+CONFIG_TEENSY_41=y
+CONFIG_USER_ENTRYPOINT="nsh_main"
+CONFIG_WQUEUE_NOTIFIER=y
diff --git a/boards/arm/imxrt/teensy-4.x/include/board.h b/boards/arm/imxrt/teensy-4.x/include/board.h
index ec9f415..0814c2d 100644
--- a/boards/arm/imxrt/teensy-4.x/include/board.h
+++ b/boards/arm/imxrt/teensy-4.x/include/board.h
@@ -276,6 +276,11 @@
 #define GPIO_FLEXCAN3_TX     (GPIO_FLEXCAN3_TX_3|IOMUX_CAN_DEFAULT) /* GPIO_EMC_36 */
 #define GPIO_FLEXCAN3_RX     (GPIO_FLEXCAN3_RX_3|IOMUX_CAN_DEFAULT) /* GPIO_EMC_37 */
 
+/* FlexPWM */
+
+#define GPIO_FLEXPWM2_MOD1_A (GPIO_FLEXPWM2_PWMA00_1|IOMUX_PWM_DEFAULT) /* GPIO_EMC_06 */
+#define GPIO_FLEXPWM2_MOD2_A (GPIO_FLEXPWM2_PWMA01_1|IOMUX_PWM_DEFAULT) /* GPIO_EMC_08 */
+
 /****************************************************************************
  * Public Types
  ****************************************************************************/
diff --git a/boards/arm/imxrt/teensy-4.x/src/Makefile b/boards/arm/imxrt/teensy-4.x/src/Makefile
index d15a030..631a070 100644
--- a/boards/arm/imxrt/teensy-4.x/src/Makefile
+++ b/boards/arm/imxrt/teensy-4.x/src/Makefile
@@ -46,6 +46,10 @@ ifeq ($(CONFIG_IMXRT_FLEXCAN),y)
 CSRCS += imxrt_flexcan.c
 endif
 
+ifeq ($(CONFIG_IMXRT_FLEXPWM),y)
+CSRCS += imxrt_flexpwm.c
+endif
+
 ifeq ($(CONFIG_IMXRT_ENET),y)
 CSRCS += imxrt_ethernet.c
 endif
diff --git a/boards/arm/imxrt/teensy-4.x/src/imxrt_bringup.c b/boards/arm/imxrt/teensy-4.x/src/imxrt_bringup.c
index b91b7ef..4674436 100644
--- a/boards/arm/imxrt/teensy-4.x/src/imxrt_bringup.c
+++ b/boards/arm/imxrt/teensy-4.x/src/imxrt_bringup.c
@@ -163,6 +163,15 @@ int imxrt_bringup(void)
     }
 #endif
 
+#ifdef CONFIG_IMXRT_FLEXPWM
+  ret = imxrt_pwm_setup();
+  if (ret < 0)
+    {
+      syslog(LOG_ERR, "ERROR: imxrt_pwm_setup() failed: %d\n", ret);
+      return ret;
+    }
+#endif
+
 #ifdef CONFIG_VIDEO_FB
   /* Initialize and register the framebuffer driver */
 
diff --git a/boards/arm/imxrt/teensy-4.x/src/imxrt_flexpwm.c b/boards/arm/imxrt/teensy-4.x/src/imxrt_flexpwm.c
new file mode 100644
index 0000000..fe17cb8
--- /dev/null
+++ b/boards/arm/imxrt/teensy-4.x/src/imxrt_flexpwm.c
@@ -0,0 +1,151 @@
+/****************************************************************************
+ * boards/arm/imxrt/teensy-4.x/src/imxrt_flexpwm.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/board.h>
+#include <nuttx/timers/pwm.h>
+
+#include <arch/board/board.h>
+
+#include "imxrt_flexpwm.h"
+#include "teensy-4.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Configuration ************************************************************/
+
+#ifdef CONFIG_PWM
+
+extern struct pwm_lowerhalf_s *imxrt_pwminitialize(int pwm);
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: imxrt_pwm_setup
+ *
+ * Description:
+ *   Initialize PWM and register the PWM device.
+ *
+ ****************************************************************************/
+
+int imxrt_pwm_setup(void)
+{
+  struct pwm_lowerhalf_s *pwm;
+  int ret;
+
+#ifdef CONFIG_IMXRT_FLEXPWM1
+  /* Call imxrt_pwminitialize() to get an instance of the PWM interface */
+
+  pwm = imxrt_pwminitialize(1);
+  if (!pwm)
+    {
+      aerr("ERROR: Failed to get the IMXRT PWM lower half\n");
+      return -ENODEV;
+    }
+
+  /* Register the PWM driver at "/dev/pwm0" */
+
+  ret = pwm_register("/dev/pwm0", pwm);
+  if (ret < 0)
+    {
+      aerr("ERROR: pwm_register failed: %d\n", ret);
+      return ret;
+    }
+
+#endif
+#ifdef CONFIG_IMXRT_FLEXPWM2
+  /* Call imxrt_pwminitialize() to get an instance of the PWM interface */
+
+  pwm = imxrt_pwminitialize(2);
+  if (!pwm)
+    {
+      aerr("ERROR: Failed to get the IMXRT PWM lower half\n");
+      return -ENODEV;
+    }
+
+  /* Register the PWM driver at "/dev/pwm1" */
+
+  ret = pwm_register("/dev/pwm1", pwm);
+  if (ret < 0)
+    {
+      aerr("ERROR: pwm_register failed: %d\n", ret);
+      return ret;
+    }
+
+#endif
+#ifdef CONFIG_IMXRT_FLEXPWM3
+  /* Call imxrt_pwminitialize() to get an instance of the PWM interface */
+
+  pwm = imxrt_pwminitialize(3);
+  if (!pwm)
+    {
+      aerr("ERROR: Failed to get the IMXRT PWM lower half\n");
+      return -ENODEV;
+    }
+
+  /* Register the PWM driver at "/dev/pwm2" */
+
+  ret = pwm_register("/dev/pwm2", pwm);
+  if (ret < 0)
+    {
+      aerr("ERROR: pwm_register failed: %d\n", ret);
+      return ret;
+    }
+
+#endif
+#ifdef CONFIG_IMXRT_FLEXPWM4
+  /* Call imxrt_pwminitialize() to get an instance of the PWM interface */
+
+  pwm = imxrt_pwminitialize(4);
+  if (!pwm)
+    {
+      aerr("ERROR: Failed to get the IMXRT PWM lower half\n");
+      return -ENODEV;
+    }
+
+  /* Register the PWM driver at "/dev/pwm3" */
+
+  ret = pwm_register("/dev/pwm3", pwm);
+  if (ret < 0)
+    {
+      aerr("ERROR: pwm_register failed: %d\n", ret);
+      return ret;
+    }
+
+#endif
+
+  UNUSED(ret);
+  return OK;
+}
+
+#endif /* CONFIG_PWM */
diff --git a/boards/arm/imxrt/teensy-4.x/src/teensy-4.h b/boards/arm/imxrt/teensy-4.x/src/teensy-4.h
index 1f0a8bc..849dd77 100644
--- a/boards/arm/imxrt/teensy-4.x/src/teensy-4.h
+++ b/boards/arm/imxrt/teensy-4.x/src/teensy-4.h
@@ -163,6 +163,18 @@ int imxrt_can_setup(void);
 #endif
 
 /****************************************************************************
+ * Name: imxrt_pwm_setup
+ *
+ * Description:
+ *   Initialize PWM and register the PWM device.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_IMXRT_FLEXPWM
+int imxrt_pwm_setup(void);
+#endif
+
+/****************************************************************************
  * Name: imxrt_adc_initialize
  *
  * Description:

[incubator-nuttx] 01/03: arch/arm/src/imxrt: added support for FlexPWM driver

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit addfe182aeb70b57dd48968cac2ad55a64249ac2
Author: Michal Lenc <mi...@seznam.cz>
AuthorDate: Sat Jun 26 11:49:38 2021 +0200

    arch/arm/src/imxrt: added support for FlexPWM driver
    
    Signed-off-by: Michal Lenc <mi...@seznam.cz>
---
 arch/arm/src/imxrt/Kconfig                 |  245 +++++++
 arch/arm/src/imxrt/Make.defs               |    4 +
 arch/arm/src/imxrt/hardware/imxrt_iomuxc.h |    3 +
 arch/arm/src/imxrt/imxrt_flexpwm.c         | 1061 ++++++++++++++++++++++++++++
 arch/arm/src/imxrt/imxrt_flexpwm.h         |   78 ++
 5 files changed, 1391 insertions(+)

diff --git a/arch/arm/src/imxrt/Kconfig b/arch/arm/src/imxrt/Kconfig
index 4cff2b4..e1165ea 100644
--- a/arch/arm/src/imxrt/Kconfig
+++ b/arch/arm/src/imxrt/Kconfig
@@ -170,6 +170,11 @@ config IMXRT_FLEXCAN
 	default n
 	select ARCH_HAVE_NETDEV_STATISTICS
 
+config IMXRT_FLEXPWM
+	bool
+	default n
+	select ARCH_HAVE_PWM_MULTICHAN
+
 config IMXRT_LPI2C
 	bool
 	default n
@@ -547,6 +552,246 @@ config FLEXCAN3_DATA_SAMPLEP
 
 endmenu # IMXRT_FLEXCAN3
 
+menu "FLEXPWM Peripherals"
+
+config IMXRT_FLEXPWM1
+	bool "FLEXPWM1"
+	default n
+	select IMXRT_FLEXPWM
+
+config IMXRT_FLEXPWM2
+	bool "FLEXPWM2"
+	default n
+	select IMXRT_FLEXPWM
+
+if ARCH_FAMILY_IMXRT105x || ARCH_FAMILY_IMXRT106x
+
+config IMXRT_FLEXPWM3
+	bool "FLEXPWM3"
+	default n
+	select IMXRT_FLEXPWM
+
+config IMXRT_FLEXPWM4
+	bool "FLEXPWM4"
+	default n
+	select IMXRT_FLEXPWM
+
+endif # ARCH_FAMILY_IMXRT105x || ARCH_FAMILY_IMXRT106x
+
+endmenu # FLEXPWM Peripherals
+
+menu "FLEXPWM1 Configuration"
+	depends on IMXRT_FLEXPWM1
+
+config IMXRT_FLEXPWM1_MOD1
+	bool "FLEXPWM1 Module 1"
+	default n
+
+if IMXRT_FLEXPWM1_MOD1
+
+config IMXRT_FLEXPWM1_MOD1_COMP
+	bool "Use complementary output"
+	default n
+
+endif
+
+config IMXRT_FLEXPWM1_MOD2
+	bool "FLEXPWM1 Module 2"
+	default n
+
+if IMXRT_FLEXPWM1_MOD2
+
+config IMXRT_FLEXPWM1_MOD2_COMP
+	bool "Use complementary output"
+	default n
+
+endif
+
+config IMXRT_FLEXPWM1_MOD3
+	bool "FLEXPWM1 Module 3"
+	default n
+
+if IMXRT_FLEXPWM1_MOD3
+
+config IMXRT_FLEXPWM1_MOD3_COMP
+	bool "Use complementary output"
+	default n
+
+endif
+
+config IMXRT_FLEXPWM1_MOD4
+	bool "FLEXPWM1 Module 4"
+	default n
+
+if IMXRT_FLEXPWM1_MOD4
+
+config IMXRT_FLEXPWM1_MOD4_COMP
+	bool "Use complementary output"
+	default n
+
+endif
+
+endmenu # IMXRT_FLEXPWM1
+
+menu "FLEXPWM2 Configuration"
+	depends on IMXRT_FLEXPWM2
+
+config IMXRT_FLEXPWM2_MOD1
+	bool "FLEXPWM2 Module 1"
+	default n
+
+if IMXRT_FLEXPWM2_MOD1
+
+config IMXRT_FLEXPWM2_MOD1_COMP
+	bool "Use complementary output"
+	default n
+
+endif
+
+config IMXRT_FLEXPWM2_MOD2
+	bool "FLEXPWM2 Module 2"
+	default n
+
+if IMXRT_FLEXPWM2_MOD2
+
+config IMXRT_FLEXPWM2_MOD2_COMP
+	bool "Use complementary output"
+	default n
+
+endif
+
+config IMXRT_FLEXPWM2_MOD3
+	bool "FLEXPWM2 Module 3"
+	default n
+
+if IMXRT_FLEXPWM2_MOD3
+
+config IMXRT_FLEXPWM2_MOD3_COMP
+	bool "Use complementary output"
+	default n
+
+endif
+
+config IMXRT_FLEXPWM2_MOD4
+	bool "FLEXPWM2 Module 4"
+	default n
+
+if IMXRT_FLEXPWM2_MOD4
+
+config IMXRT_FLEXPWM2_MOD4_COMP
+	bool "Use complementary output"
+	default n
+
+endif
+
+endmenu # IMXRT_FLEXPWM2
+
+menu "FLEXPWM3 Configuration"
+	depends on IMXRT_FLEXPWM3
+
+config IMXRT_FLEXPWM3_MOD1
+	bool "FLEXPWM3 Module 1"
+	default n
+
+if IMXRT_FLEXPWM3_MOD1
+
+config IMXRT_FLEXPWM3_MOD1_COMP
+	bool "Use complementary output"
+	default n
+
+endif
+
+config IMXRT_FLEXPWM3_MOD2
+	bool "FLEXPWM3 Module 2"
+	default n
+
+if IMXRT_FLEXPWM3_MOD2
+
+config IMXRT_FLEXPWM3_MOD2_COMP
+	bool "Use complementary output"
+	default n
+
+endif
+
+config IMXRT_FLEXPWM3_MOD3
+	bool "FLEXPWM3 Module 3"
+	default n
+
+if IMXRT_FLEXPWM3_MOD3
+
+config IMXRT_FLEXPWM3_MOD3_COMP
+	bool "Use complementary output"
+	default n
+
+endif
+
+config IMXRT_FLEXPWM3_MOD4
+	bool "FLEXPWM3 Module 4"
+	default n
+
+if IMXRT_FLEXPWM3_MOD4
+
+config IMXRT_FLEXPWM3_MOD4_COMP
+	bool "Use complementary output"
+	default n
+
+endif
+
+endmenu # IMXRT_FLEXPWM3
+
+menu "FLEXPWM4 Configuration"
+	depends on IMXRT_FLEXPWM4
+
+config IMXRT_FLEXPWM4_MOD1
+	bool "FLEXPWM4 Module 1"
+	default n
+
+if IMXRT_FLEXPWM4_MOD1
+
+config IMXRT_FLEXPWM4_MOD1_COMP
+	bool "Use complementary output"
+	default n
+
+endif
+
+config IMXRT_FLEXPWM4_MOD2
+	bool "FLEXPWM4 Module 2"
+	default n
+
+if IMXRT_FLEXPWM4_MOD2
+
+config IMXRT_FLEXPWM4_MOD2_COMP
+	bool "Use complementary output"
+	default n
+
+endif
+
+config IMXRT_FLEXPWM4_MOD3
+	bool "FLEXPWM4 Module 3"
+	default n
+
+if IMXRT_FLEXPWM4_MOD3
+
+config IMXRT_FLEXPWM4_MOD3_COMP
+	bool "Use complementary output"
+	default n
+
+endif
+
+config IMXRT_FLEXPWM4_MOD4
+	bool "FLEXPWM4 Module 4"
+	default n
+
+if IMXRT_FLEXPWM4_MOD4
+
+config IMXRT_FLEXPWM4_MOD4_COMP
+	bool "Use complementary output"
+	default n
+
+endif
+
+endmenu # IMXRT_FLEXPWM4
+
 menu "LPI2C Peripherals"
 
 menuconfig IMXRT_LPI2C1
diff --git a/arch/arm/src/imxrt/Make.defs b/arch/arm/src/imxrt/Make.defs
index ba9195a..ae90261 100644
--- a/arch/arm/src/imxrt/Make.defs
+++ b/arch/arm/src/imxrt/Make.defs
@@ -116,6 +116,10 @@ ifeq ($(CONFIG_IMXRT_FLEXCAN),y)
 CHIP_CSRCS += imxrt_flexcan.c
 endif
 
+ifeq ($(CONFIG_IMXRT_FLEXPWM),y)
+CHIP_CSRCS += imxrt_flexpwm.c
+endif
+
 ifeq ($(CONFIG_IMXRT_SNVS_LPSRTC),y)
 CHIP_CSRCS += imxrt_lpsrtc.c
 CHIP_CSRCS += imxrt_hprtc.c
diff --git a/arch/arm/src/imxrt/hardware/imxrt_iomuxc.h b/arch/arm/src/imxrt/hardware/imxrt_iomuxc.h
index 2987af1..3f06ce7 100644
--- a/arch/arm/src/imxrt/hardware/imxrt_iomuxc.h
+++ b/arch/arm/src/imxrt/hardware/imxrt_iomuxc.h
@@ -154,6 +154,9 @@
 #define IOMUX_CAN_DEFAULT                     (IOMUX_SLEW_SLOW | \
                                                IOMUX_DRIVE_50OHM | IOMUX_SPEED_LOW )
 
+#define IOMUX_PWM_DEFAULT                     (IOMUX_SLEW_FAST | \
+                                               IOMUX_DRIVE_50OHM | IOMUX_SPEED_LOW )
+
 #define IOMUX_USDHC1_DATAX_DEFAULT            (IOMUX_SLEW_FAST | IOMUX_DRIVE_130OHM | \
                                                IOMUX_PULL_UP_47K | IOMUX_SCHMITT_TRIGGER)
 #define IOMUX_USDHC1_CMD_DEFAULT              (IOMUX_SLEW_FAST | IOMUX_DRIVE_130OHM | \
diff --git a/arch/arm/src/imxrt/imxrt_flexpwm.c b/arch/arm/src/imxrt/imxrt_flexpwm.c
new file mode 100644
index 0000000..5f4bf25
--- /dev/null
+++ b/arch/arm/src/imxrt/imxrt_flexpwm.c
@@ -0,0 +1,1061 @@
+/****************************************************************************
+ * arch/arm/src/imxrt/imxrt_flexpwm.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <time.h>
+#include <string.h>
+#include <debug.h>
+#include <errno.h>
+
+#include <nuttx/timers/pwm.h>
+
+#include "arm_arch.h"
+#include "chip.h"
+#include "imxrt_config.h"
+#include "imxrt_flexpwm.h"
+#include "imxrt_periphclks.h"
+#include "hardware/imxrt_flexpwm.h"
+#include "hardware/imxrt_pinmux.h"
+#include "hardware/imxrt_ccm.h"
+
+#include <arch/board/board.h>
+
+#include <sys/time.h>
+
+#ifdef CONFIG_IMXRT_FLEXPWM
+
+#ifdef CONFIG_PWM_NCHANNELS
+# define PWM_NCHANNELS CONFIG_PWM_NCHANNELS
+#else
+# define PWM_NCHANNELS 1
+#endif
+
+#define MODULE_OFFSET 0x60
+#define CLK_FREQ  132000000
+#define PWM_RES 65535
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct imxrt_flexpwm_out_s
+{
+  bool used;
+  uint32_t pin;                   /* Output pin */
+};
+
+struct imxrt_flexpwm_module_s
+{
+  uint8_t module;                   /* Number of PWM module */
+  bool used;                        /* True if the module is used */
+  struct imxrt_flexpwm_out_s out_a; /* PWM output */
+  struct imxrt_flexpwm_out_s out_b; /* PWM output */
+  bool complementary;               /* True if outputs are complementary */
+  uint32_t irq;                     /* Combined interrupt */
+};
+
+struct imxrt_flexpwm_s
+{
+  const struct pwm_ops_s *ops;    /* PWM operations */
+  FAR struct imxrt_flexpwm_module_s *modules;
+  uint8_t modules_num;            /* Number of modules */
+  uint32_t frequency;             /* PWM frequency */
+  uint32_t base;                  /* Base addres of peripheral register */
+};
+
+/* PWM driver methods */
+
+static int pwm_setup(FAR struct pwm_lowerhalf_s *dev);
+static int pwm_shutdown(FAR struct pwm_lowerhalf_s *dev);
+static int pwm_start(FAR struct pwm_lowerhalf_s *dev,
+                     FAR const struct pwm_info_s *info);
+static int pwm_stop(FAR struct pwm_lowerhalf_s *dev);
+static int pwm_ioctl(FAR struct pwm_lowerhalf_s *dev,
+                     int cmd, unsigned long arg);
+
+/* Helper functions */
+
+static int pwm_set_output(FAR struct pwm_lowerhalf_s *dev, uint8_t channel,
+                           ub16_t duty);
+static int pwm_change_freq(FAR struct pwm_lowerhalf_s *dev,
+                     FAR const struct pwm_info_s *info, uint8_t channel);
+
+/****************************************************************************
+  * Private Data
+ ****************************************************************************/
+
+static const struct pwm_ops_s g_pwmops =
+{
+  .setup      = pwm_setup,
+  .shutdown   = pwm_shutdown,
+  .start      = pwm_start,
+  .stop       = pwm_stop,
+  .ioctl      = pwm_ioctl,
+};
+
+#ifdef CONFIG_IMXRT_FLEXPWM1
+
+static struct imxrt_flexpwm_module_s g_pwm1_modules[] =
+{
+  /* FlexPWM1 has 4 submodules with 2 outputs for each */
+
+#ifdef CONFIG_IMXRT_FLEXPWM1_MOD1
+  {
+    .module = 1,
+    .used = true,
+    .out_a =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM1_MOD1_A
+    },
+#ifdef CONFIG_IMXRT_FLEXPWM1_MOD1_COMP
+    .out_b =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM1_MOD1_B
+    },
+    .complementary = true
+#else
+    .complementary = false
+#endif
+  },
+#endif
+#ifdef CONFIG_IMXRT_FLEXPWM1_MOD2
+  {
+    .module = 2,
+    .used = true,
+    .out_a =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM1_MOD2_A
+    },
+#ifdef CONFIG_IMXRT_FLEXPWM1_MOD2_COMP
+    .out_b =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM1_MOD2_B
+    },
+    .complementary = true
+#else
+    .complementary = false
+#endif
+  },
+#endif
+#ifdef CONFIG_IMXRT_FLEXPWM1_MOD3
+  {
+    .module = 3,
+    .used = true,
+    .out_a =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM1_MOD3_A
+    },
+#ifdef CONFIG_IMXRT_FLEXPWM1_MOD3_COMP
+    .out_b =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM1_MOD3_B
+    },
+    .complementary = true
+#else
+    .complementary = false
+#endif
+  },
+#endif
+#ifdef CONFIG_IMXRT_FLEXPWM1_MOD4
+  {
+    .module = 4,
+    .used = true,
+    .out_a =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM1_MOD4_A
+    },
+#ifdef CONFIG_IMXRT_FLEXPWM1_MOD4_COMP
+    .out_b =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM1_MOD4_B
+    },
+    .complementary = true
+#else
+    .complementary = false
+#endif
+  },
+#endif
+};
+
+static struct imxrt_flexpwm_s g_pwm1 =
+{
+  .ops = &g_pwmops,
+  .modules = g_pwm1_modules,
+  .modules_num = 4,
+  .frequency = 0,
+  .base = IMXRT_FLEXPWM1_BASE,
+};
+#endif /* CONFIG_IMXRT_FLEXPWM1 */
+
+#ifdef CONFIG_IMXRT_FLEXPWM2
+
+static struct imxrt_flexpwm_module_s g_pwm2_modules[] =
+{
+  /* FlexPWM2 has 4 submodules with 2 outputs for each */
+
+#ifdef CONFIG_IMXRT_FLEXPWM2_MOD1
+  {
+    .module = 1,
+    .used = true,
+    .out_a =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM2_MOD1_A
+    },
+#ifdef CONFIG_IMXRT_FLEXPWM2_MOD1_COMP
+    .out_b =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM2_MOD1_B
+    },
+    .complementary = true
+#else
+    .complementary = false
+#endif
+  },
+#endif
+#ifdef CONFIG_IMXRT_FLEXPWM2_MOD2
+  {
+    .module = 2,
+    .used = true,
+    .out_a =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM2_MOD2_A,
+    },
+#ifdef CONFIG_IMXRT_FLEXPWM2_MOD2_COMP
+    .out_b =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM2_MOD2_B
+    }
+    .complementary = true
+#else
+    .complementary = false
+#endif
+  },
+#endif
+#ifdef CONFIG_IMXRT_FLEXPWM2_MOD3
+  {
+    .module = 3,
+    .used = true,
+    .out_a =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM2_MOD3_A
+    },
+#ifdef CONFIG_IMXRT_FLEXPWM2_MOD3_COMP
+    .out_b =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM2_MOD3_B
+    },
+    .complementary = true
+#else
+    .complementary = false
+#endif
+  },
+#endif
+#ifdef CONFIG_IMXRT_FLEXPWM2_MOD4
+  {
+    .module = 4,
+    .used = true,
+    .out_a =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM2_MOD4_A
+    },
+#ifdef CONFIG_IMXRT_FLEXPWM2_MOD4_COMP
+    .out_b =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM2_MOD4_B
+    },
+    .complementary = true
+#else
+    .complementary = false
+#endif
+  }
+#endif
+};
+
+static struct imxrt_flexpwm_s g_pwm2 =
+{
+  .ops = &g_pwmops,
+  .modules = g_pwm2_modules,
+  .modules_num = 4,
+  .frequency = 0,
+  .base = IMXRT_FLEXPWM2_BASE,
+};
+#endif /* CONFIG_IMXRT_FLEXPWM2 */
+
+#ifdef CONFIG_IMXRT_FLEXPWM3
+
+static struct imxrt_flexpwm_module_s g_pwm3_modules[] =
+{
+  /* FlexPWM3 has 4 submodules with 2 outputs for each */
+
+#ifdef CONFIG_IMXRT_FLEXPWM3_MOD1
+  {
+    .module = 1,
+    .used = true,
+    .out_a =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM3_MOD1_A
+    },
+#ifdef CONFIG_IMXRT_FLEXPWM3_MOD1_COMP
+    .out_b =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM3_MOD1_B
+    },
+    .complementary = true
+#else
+    .complementary = false
+#endif
+  },
+#endif
+#ifdef CONFIG_IMXRT_FLEXPWM3_MOD2
+  {
+    .module = 2,
+    .used = true,
+    .out_a =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM3_MOD2_A
+    },
+#ifdef CONFIG_IMXRT_FLEXPWM3_MOD2_COMP
+    .out_b =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM3_MOD2_B
+    },
+    .complementary = true
+#else
+    .complementary = false
+#endif
+  },
+#endif
+#ifdef CONFIG_IMXRT_FLEXPWM3_MOD3
+  {
+    .module = 3,
+    .used = true,
+    .out_a =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM3_MOD3_A
+    },
+#ifdef CONFIG_IMXRT_FLEXPWM3_MOD3_COMP
+    .out_b =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM3_MOD3_B
+    },
+    .complementary = true
+#else
+    .complementary = false
+#endif
+  },
+#endif
+#ifdef CONFIG_IMXRT_FLEXPWM3_MOD4
+  {
+    .module = 4,
+    .used = true,
+    .out_a =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM3_MOD4_A
+    },
+#ifdef CONFIG_IMXRT_FLEXPWM3_MOD4_COMP
+    .out_b =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM3_MOD4_B
+    },
+    .complementary = true
+#else
+    .complementary = false
+#endif
+  },
+#endif
+};
+
+static struct imxrt_flexpwm_s g_pwm3 =
+{
+  .ops = &g_pwmops,
+  .modules = g_pwm3_modules,
+  .modules_num = 4,
+  .frequency = 0,
+  .base = IMXRT_FLEXPWM3_BASE,
+};
+#endif /* CONFIG_IMXRT_FLEXPWM3 */
+
+#ifdef CONFIG_IMXRT_FLEXPWM4
+
+static struct imxrt_flexpwm_module_s g_pwm4_modules[] =
+{
+  /* FlexPWM4 has 4 submodules with 2 outputs for each */
+
+#ifdef CONFIG_IMXRT_FLEXPWM4_MOD1
+  {
+    .module = 1,
+    .used = true,
+    .out_a =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM4_MOD1_A
+    },
+#ifdef CONFIG_IMXRT_FLEXPWM4_MOD1_COMP
+    .out_b =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM4_MOD1_B
+    }
+    .complementary = true
+#else
+    .complementary = false
+#endif
+  },
+#endif
+#ifdef CONFIG_IMXRT_FLEXPWM4_MOD2
+  {
+    .module = 2,
+    .used = true,
+    .out_a =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM4_MOD2_A
+    },
+#ifdef CONFIG_IMXRT_FLEXPWM4_MOD2_COMP
+    .out_b =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM4_MOD2_B
+    }
+    .complementary = true
+#else
+    .complementary = false
+#endif
+  },
+#endif
+#ifdef CONFIG_IMXRT_FLEXPWM4_MOD3
+  {
+    .module = 3,
+    .used = true,
+    .out_a =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM4_MOD3_A
+    },
+#ifdef CONFIG_IMXRT_FLEXPWM4_MOD3_COMP
+    .out_b =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM4_MOD3_B
+    }
+    .complementary = true
+#else
+    .complementary = false
+#endif
+  },
+#endif
+#ifdef CONFIG_IMXRT_FLEXPWM4_MOD4
+  {
+    .module = 4,
+    .used = true,
+    .out_a =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM4_MOD4_A
+    },
+#ifdef CONFIG_IMXRT_FLEXPWM4_MOD3_COMP
+    .out_b =
+    {
+      .used = true,
+      .pin = GPIO_FLEXPWM4_MOD4_B
+    }
+    .complementary = true
+#else
+    .complementary = false
+#endif
+  },
+#endif
+};
+
+static struct imxrt_flexpwm_s g_pwm4 =
+{
+  .ops = &g_pwmops,
+  .modules = g_pwm4_modules,
+  .modules_num = 4,
+  .frequency = 0,
+  .base = IMXRT_FLEXPWM4_BASE,
+};
+#endif /* CONFIG_IMXRT_FLEXPWM4 */
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pwm_change_freq
+ *
+ * Description:
+ *   Set timer frequency and change registers value to respect that
+ *   frequency.
+ *
+ * Input Parameters:
+ *   dev  - A reference to the lower half PWM driver state structure
+ *   info - A reference to the characteristics of the pulsed output
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int pwm_change_freq(FAR struct pwm_lowerhalf_s *dev,
+                     FAR const struct pwm_info_s *info, uint8_t channel)
+{
+  FAR struct imxrt_flexpwm_s *priv = (FAR struct imxrt_flexpwm_s *)dev;
+#ifdef CONFIG_PWM_MULTICHAN
+  uint8_t shift = info->channels[channel].channel - 1;
+#else
+  uint8_t shift = priv->modules[0].module - 1;
+#endif
+  uint16_t regval;
+  uint16_t olddiv = getreg16(priv->base + IMXRT_FLEXPWM_SM0VAL1_OFFSET
+                                        + MODULE_OFFSET * shift);
+  uint16_t newdiv = (uint32_t)((float)CLK_FREQ / info->frequency + 0.5f);
+  uint16_t prescale = 0;
+
+  while (newdiv > PWM_RES && prescale < 7)
+    {
+      newdiv = newdiv >> 1;
+      prescale = prescale + 1;
+    }
+
+  if (newdiv > PWM_RES)
+    {
+      newdiv = PWM_RES;
+    }
+  else if (newdiv < 2)
+    {
+      newdiv = 2;
+    }
+
+  regval = getreg16(priv->base + IMXRT_FLEXPWM_MCTRL_OFFSET);
+  regval |= MCTRL_CLDOK(1 << shift);
+  putreg16(regval, priv->base + IMXRT_FLEXPWM_MCTRL_OFFSET);
+
+  regval = SMCTRL_FULL | SMCTRL_PRSC(prescale);
+  putreg16(regval, priv->base + IMXRT_FLEXPWM_SM0CTRL_OFFSET
+                              + MODULE_OFFSET * shift);
+
+  putreg16(newdiv - 1, priv->base + IMXRT_FLEXPWM_SM0VAL1_OFFSET
+                                  + MODULE_OFFSET * shift);
+
+  /* Update VAL0, VAL3 and VAL5 registers */
+
+  regval = getreg16(priv->base + IMXRT_FLEXPWM_SM0VAL0_OFFSET
+                               + MODULE_OFFSET * shift);
+  regval = regval * newdiv / olddiv;
+  putreg16(regval, priv->base + IMXRT_FLEXPWM_SM0VAL0_OFFSET
+                              + MODULE_OFFSET * shift);
+
+  regval = getreg16(priv->base + IMXRT_FLEXPWM_SM0VAL3_OFFSET
+                               + MODULE_OFFSET * shift);
+  regval = regval * newdiv / olddiv;
+  putreg16(regval, priv->base + IMXRT_FLEXPWM_SM0VAL3_OFFSET
+                              + MODULE_OFFSET * shift);
+
+  regval = getreg16(priv->base + IMXRT_FLEXPWM_SM0VAL5_OFFSET
+                               + MODULE_OFFSET * shift);
+  regval = regval * newdiv / olddiv;
+  putreg16(regval, priv->base + IMXRT_FLEXPWM_SM0VAL5_OFFSET
+                              + MODULE_OFFSET * shift);
+
+  regval = getreg16(priv->base + IMXRT_FLEXPWM_MCTRL_OFFSET);
+  regval |= MCTRL_LDOK(1 << shift);
+  putreg16(regval, priv->base + IMXRT_FLEXPWM_MCTRL_OFFSET);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_set_output
+ *
+ * Description:
+ *   Set duty cycle and enable PWM output.
+ *
+ * Input Parameters:
+ *   dev     - A reference to the lower half PWM driver state structure
+ *   channel - Channel to by updated
+ *   duty    - New duty
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int pwm_set_output(FAR struct pwm_lowerhalf_s *dev, uint8_t channel,
+                           ub16_t duty)
+{
+  FAR struct imxrt_flexpwm_s *priv = (FAR struct imxrt_flexpwm_s *)dev;
+  uint16_t period;
+  uint16_t width;
+  uint16_t regval;
+  double duty_pct;
+  uint8_t shift = channel - 1;  /* Shift submodle offset addresses */
+
+  /* Get the period value */
+
+  period = getreg16(priv->base + IMXRT_FLEXPWM_SM0VAL1_OFFSET
+                               + MODULE_OFFSET * shift);
+
+  /* Compute PWM width (count value to set PWM low) */
+
+  duty_pct = (duty / 65536.0) * 100;
+  width = (uint16_t)(((uint16_t)duty_pct * period) / 100);
+
+  /* Clear corresponding MCTRL[LDOK] bit  */
+
+  regval = getreg16(priv->base + IMXRT_FLEXPWM_MCTRL_OFFSET);
+  regval |= MCTRL_CLDOK(1 << shift);
+  putreg16(regval, priv->base + IMXRT_FLEXPWM_MCTRL_OFFSET);
+
+  /* Write width to value register 3 and enable output A */
+
+  putreg16(width, priv->base + IMXRT_FLEXPWM_SM0VAL3_OFFSET
+                             + MODULE_OFFSET * shift);
+
+  regval = getreg16(priv->base + IMXRT_FLEXPWM_OUTEN_OFFSET);
+  regval |= OUTEN_PWMA_EN(1 << shift);
+  putreg16(regval, priv->base + IMXRT_FLEXPWM_OUTEN_OFFSET);
+
+  /* Enable output B if complementary option is turn on */
+
+  if (priv->modules[shift].complementary)
+    {
+      regval = getreg16(priv->base + IMXRT_FLEXPWM_OUTEN_OFFSET);
+      regval |= OUTEN_PWMB_EN(1 << shift);
+      putreg16(regval, priv->base + IMXRT_FLEXPWM_OUTEN_OFFSET);
+    }
+
+  regval = getreg16(priv->base + IMXRT_FLEXPWM_MCTRL_OFFSET);
+  regval |= MCTRL_LDOK(1 << shift);
+  putreg16(regval, priv->base + IMXRT_FLEXPWM_MCTRL_OFFSET);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_setup
+ *
+ * Description:
+ *   This method is called when the driver is opened.  The lower half driver
+ *   should configure and initialize the device so that it is ready for use.
+ *   It should not, however, output pulses until the start method is called.
+ *
+ * Input Parameters:
+ *   dev - A reference to the lower half PWM driver state structure
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int pwm_setup(FAR struct pwm_lowerhalf_s *dev)
+{
+  FAR struct imxrt_flexpwm_s *priv = (FAR struct imxrt_flexpwm_s *)dev;
+  uint32_t pin = 0;
+  uint16_t regval;
+
+  putreg16(FCTRL0_FLVL(15), priv->base + IMXRT_FLEXPWM_FCTRL0_OFFSET);
+  putreg16(0x000f, priv->base + IMXRT_FLEXPWM_FSTS0_OFFSET);
+  putreg16(0, priv->base + IMXRT_FLEXPWM_FFILT0_OFFSET);
+
+  for (int i = 0; i < priv->modules_num; i++)
+    {
+      /* Configure the module only if is set to be used */
+
+      if (priv->modules[i].used != 1)
+        {
+          continue;
+        }
+
+      if (priv->modules[i].out_a.used)
+        {
+          pin = priv->modules[i].out_a.pin;
+          if (pin != 0)
+            {
+              imxrt_config_gpio(pin);
+            }
+        }
+
+      /* Configure PIN_B if complementary option is turn on */
+
+      if (priv->modules[i].complementary)
+        {
+          if (priv->modules[i].out_b.used)
+            {
+              pin = priv->modules[i].out_b.pin;
+              if (pin != 0)
+                {
+                  imxrt_config_gpio(pin);
+                }
+            }
+        }
+
+      regval = getreg16(priv->base + IMXRT_FLEXPWM_MCTRL_OFFSET);
+      regval |= MCTRL_CLDOK(1 << i);
+      putreg16(regval, priv->base + IMXRT_FLEXPWM_MCTRL_OFFSET);
+
+      /* Set control registers 1 and 2 */
+
+      if (!priv->modules[i].complementary)
+        {
+          /* Enable independent PWM_A and PWM_B output */
+
+          regval = SMCTRL2_INDEP;
+          putreg16(regval, priv->base + IMXRT_FLEXPWM_SM0CTRL2_OFFSET
+                                    + MODULE_OFFSET * i);
+        }
+
+      regval = SMCTRL_FULL;     /* Enable full read cycle reload */
+      putreg16(regval, priv->base + IMXRT_FLEXPWM_SM0CTRL_OFFSET
+                                  + MODULE_OFFSET * i);
+
+      /* Set output control register */
+
+      putreg16(0, priv->base + IMXRT_FLEXPWM_SM0OCTRL_OFFSET
+                             + MODULE_OFFSET * i);
+
+      /* Set deadtime count register 0 */
+
+      putreg16(0, priv->base + IMXRT_FLEXPWM_SM0DTCNT0_OFFSET
+                             + MODULE_OFFSET * i);
+
+      /* Set initial count register */
+
+      putreg16(0, priv->base + IMXRT_FLEXPWM_SM0INIT_OFFSET
+                             + MODULE_OFFSET * i);
+
+      /* Set value registers */
+
+      putreg16(0, priv->base + IMXRT_FLEXPWM_SM0VAL0_OFFSET
+                             + MODULE_OFFSET * i);
+      putreg16(0x82b8, priv->base + IMXRT_FLEXPWM_SM0VAL1_OFFSET
+                                  + MODULE_OFFSET * i);
+      putreg16(0, priv->base + IMXRT_FLEXPWM_SM0VAL2_OFFSET
+                             + MODULE_OFFSET * i);
+      putreg16(0, priv->base + IMXRT_FLEXPWM_SM0VAL3_OFFSET
+                             + MODULE_OFFSET * i);
+      putreg16(0, priv->base + IMXRT_FLEXPWM_SM0VAL4_OFFSET
+                             + MODULE_OFFSET * i);
+      putreg16(0, priv->base + IMXRT_FLEXPWM_SM0VAL5_OFFSET
+                             + MODULE_OFFSET * i);
+
+      regval = getreg16(priv->base + IMXRT_FLEXPWM_MCTRL_OFFSET);
+      regval |= MCTRL_LDOK(1 << i);
+      putreg16(regval, priv->base + IMXRT_FLEXPWM_MCTRL_OFFSET);
+
+      regval = getreg16(priv->base + IMXRT_FLEXPWM_MCTRL_OFFSET);
+      regval |= MCTRL_RUN(1 << i);
+      putreg16(regval, priv->base + IMXRT_FLEXPWM_MCTRL_OFFSET);
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_shutdown
+ *
+ * Description:
+ *   This method is called when the driver is closed.  The lower half driver
+ *   stop pulsed output, free any resources, disable the timer hardware, and
+ *   put the system into the lowest possible power usage state
+ *
+ * Input Parameters:
+ *   dev - A reference to the lower half PWM driver state structure
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int pwm_shutdown(FAR struct pwm_lowerhalf_s *dev)
+{
+  FAR struct imxrt_flexpwm_s *priv = (FAR struct imxrt_flexpwm_s *)dev;
+
+  for (int i = 0; i < priv->modules_num; i++)
+    {
+      /* Skip modules that are not used */
+
+      if (priv->modules[i].used != 1)
+        {
+          continue;
+        }
+
+      putreg16(0, priv->base + IMXRT_FLEXPWM_SM0CTRL_OFFSET
+                                  + MODULE_OFFSET * i);
+
+      /* Reset fractional value registers */
+
+      putreg16(0, priv->base + IMXRT_FLEXPWM_SM0VAL0_OFFSET
+                             + MODULE_OFFSET * i);
+      putreg16(0, priv->base + IMXRT_FLEXPWM_SM0VAL1_OFFSET
+                                  + MODULE_OFFSET * i);
+      putreg16(0, priv->base + IMXRT_FLEXPWM_SM0VAL2_OFFSET
+                             + MODULE_OFFSET * i);
+      putreg16(0, priv->base + IMXRT_FLEXPWM_SM0VAL3_OFFSET
+                             + MODULE_OFFSET * i);
+      putreg16(0, priv->base + IMXRT_FLEXPWM_SM0VAL4_OFFSET
+                             + MODULE_OFFSET * i);
+      putreg16(0, priv->base + IMXRT_FLEXPWM_SM0VAL5_OFFSET
+                             + MODULE_OFFSET * i);
+    }
+
+  /* Stop run */
+
+  putreg16(0, priv->base + IMXRT_FLEXPWM_MCTRL_OFFSET);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_start
+ *
+ * Description:
+ *   (Re-)initialize the timer resources and start the pulsed output
+ *
+ * Input Parameters:
+ *   dev  - A reference to the lower half PWM driver state structure
+ *   info - A reference to the characteristics of the pulsed output
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int pwm_start(FAR struct pwm_lowerhalf_s *dev,
+                     FAR const struct pwm_info_s *info)
+{
+  FAR struct imxrt_flexpwm_s *priv = (FAR struct imxrt_flexpwm_s *)dev;
+  int ret = OK;
+
+  /* Change frequency only if it is needed */
+
+  if (info->frequency != priv->frequency)
+    {
+      for (int i = 0; i < PWM_NCHANNELS; i++)
+        {
+          /* Configure the module freq only if is set to be used */
+
+          ret = pwm_change_freq(dev, info, i);
+        }
+
+      /* Save current frequency */
+
+      if (ret == OK)
+        {
+          priv->frequency = info->frequency;
+        }
+    }
+
+#ifdef CONFIG_PWM_MULTICHAN
+  for (int i = 0; ret == OK && i < PWM_NCHANNELS; i++)
+    {
+      /* Enable PWM output for each channel */
+
+      ret = pwm_set_output(dev, info->channels[i].channel,
+                                info->channels[i].duty);
+    }
+#else
+  /* Enable PWM output just for first channel */
+
+  ret = pwm_set_output(dev, priv->modules[0].module, info->duty);
+#endif /* CONFIG_PWM_MULTICHAN */
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: pwm_stop
+ *
+ * Description:
+ *   Stop the pulsed output and reset the timer resources
+ *
+ * Input Parameters:
+ *   dev - A reference to the lower half PWM driver state structure
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure
+ *
+ * Assumptions:
+ *   This function is called to stop the pulsed output at anytime.  This
+ *   method is also called from the timer interrupt handler when a repetition
+ *   count expires... automatically stopping the timer.
+ *
+ ****************************************************************************/
+
+static int pwm_stop(FAR struct pwm_lowerhalf_s *dev)
+{
+  FAR struct imxrt_flexpwm_s *priv = (FAR struct imxrt_flexpwm_s *)dev;
+  uint8_t shift;
+  uint16_t regval;
+
+#ifdef CONFIG_PWM_MULTICHAN
+  for (int i = 0; i < priv->modules_num; i++)
+    {
+      /* Skip settings if channel is not configured */
+
+      if (!priv->modules[i].used)
+        {
+          continue;
+        }
+
+      shift = priv->modules[i].module - 1;
+
+      regval = OUTEN_PWMA_EN(0 << shift);
+      putreg16(regval, priv->base + IMXRT_FLEXPWM_OUTEN_OFFSET);
+
+      regval = OUTEN_PWMB_EN(0 << shift);
+      putreg16(regval, priv->base + IMXRT_FLEXPWM_OUTEN_OFFSET);
+    }
+#else
+    shift = priv->modules[0].module - 1;
+
+    regval = OUTEN_PWMA_EN(0 << shift);
+    putreg16(regval, priv->base + IMXRT_FLEXPWM_OUTEN_OFFSET);
+
+    regval = OUTEN_PWMB_EN(0 << shift);
+    putreg16(regval, priv->base + IMXRT_FLEXPWM_OUTEN_OFFSET);
+
+#endif /* CONFIG_PWM_MULTICHAN */
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_ioctl
+ *
+ * Description:
+ *   Lower-half logic may support platform-specific ioctl commands
+ *
+ * Input Parameters:
+ *   dev - A reference to the lower half PWM driver state structure
+ *   cmd - The ioctl command
+ *   arg - The argument accompanying the ioctl command
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, int cmd,
+                     unsigned long arg)
+{
+  return -ENOTTY;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: imxrt_pwminitialize
+ *
+ * Description:
+ *   Initialize the PWM channel for use with the upper level PWM driver.
+ *
+ * Input Parameters:
+ *   channel - a number identifying the PWM channel.
+ *
+ * Returned Value:
+ *   A pointer to the lower half PWM driver is returned on success,
+ *   NULL on failure.
+ *
+ ****************************************************************************/
+
+FAR struct pwm_lowerhalf_s *imxrt_pwminitialize(int pwm)
+{
+  FAR struct imxrt_flexpwm_s *priv;
+
+  pwminfo("Initializing pwm %d\n", pwm);
+
+  switch (pwm)
+  {
+#ifdef CONFIG_IMXRT_FLEXPWM1
+    case 1:
+      imxrt_clockall_pwm1();
+      priv = &g_pwm1;
+      break;
+#endif
+#ifdef CONFIG_IMXRT_FLEXPWM2
+    case 2:
+      imxrt_clockall_pwm2();
+      priv = &g_pwm2;
+      break;
+#endif
+#ifdef CONFIG_IMXRT_FLEXPWM3
+    case 3:
+      imxrt_clockall_pwm3();
+      priv = &g_pwm3;
+      break;
+#endif
+#ifdef CONFIG_IMXRT_FLEXPWM4
+    case 4:
+      imxrt_clockall_pwm4();
+      priv = &g_pwm4;
+      break;
+#endif
+    default:
+      pwmerr("ERROR: PWM number invalid or not configured %d\n", pwm);
+      return NULL;
+  }
+
+  return (FAR struct pwm_lowerhalf_s *)priv;
+}
+#endif /* CONFIG_IMXRT_FLEXPWM */
diff --git a/arch/arm/src/imxrt/imxrt_flexpwm.h b/arch/arm/src/imxrt/imxrt_flexpwm.h
new file mode 100644
index 0000000..591fd8b
--- /dev/null
+++ b/arch/arm/src/imxrt/imxrt_flexpwm.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+ * arch/arm/src/imxrt/imxrt_flexpwm.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_IMXRT_IMXRT_FLEXPWM_H
+#define __ARCH_ARM_SRC_IMXRT_IMXRT_FLEXPWM_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/timers/pwm.h>
+
+#include "hardware/imxrt_flexpwm.h"
+
+#ifdef CONFIG_IMXRT_FLEXPWM
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Function: imxrt_pwminitialize
+ *
+ * Description:
+ *   Initialize the PWM module for use with the upper level PWM driver.
+ *
+ * Input Parameters:
+ *   pwm - a number identifying the PWM driver.
+ *
+ * Returned Value:
+ *   A pointer to the lower half PWM driver is returned on success,
+ *   NULL on failure.
+ *
+ ****************************************************************************/
+
+FAR struct pwm_lowerhalf_s *imxrt_pwminitialize(int pwm);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* CONFIG_IMXRT_FLEXPWM */
+#endif /* __ARCH_ARM_SRC_IMXRT_IMXRT_FLEXPWM_H */

[incubator-nuttx] 03/03: Documentation/platforms/arm/imxrt: update documentation with FlexPWM support

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit b88b5b14c89aefbd926d62899fc108d23a4a97df
Author: Michal Lenc <mi...@seznam.cz>
AuthorDate: Sat Jun 26 11:56:20 2021 +0200

    Documentation/platforms/arm/imxrt: update documentation with FlexPWM support
    
    Signed-off-by: Michal Lenc <mi...@seznam.cz>
---
 Documentation/platforms/arm/imxrt/boards/teensy-4.x/index.rst | 11 +++++++++++
 Documentation/platforms/arm/imxrt/index.rst                   |  6 ++++--
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/Documentation/platforms/arm/imxrt/boards/teensy-4.x/index.rst b/Documentation/platforms/arm/imxrt/boards/teensy-4.x/index.rst
index ccb33c3..d3dcb1b 100644
--- a/Documentation/platforms/arm/imxrt/boards/teensy-4.x/index.rst
+++ b/Documentation/platforms/arm/imxrt/boards/teensy-4.x/index.rst
@@ -118,6 +118,17 @@ focused on network-related testing.
 This configuration cannot be changed to Teensy 4.0 as this board does
 not have Ethernet capability.
 
+pwm-4.1
+-------
+
+This configuration is similar to the nsh configuration with enabled
+FlexPWM driver. Submodules 1 (pin 4) and 2 (pin 5) of FlexPWM2 are turn
+on aswell as ultiple channel PWM output. Functionality can be tested
+with example application "pwm". Each channel runs different duty cycle.
+
+This configuration can be easily changed to work with Teensy 4.0 by
+selecting ``CONFIG_TEENSY_40=y``.
+
 sd-4.1
 ------
 
diff --git a/Documentation/platforms/arm/imxrt/index.rst b/Documentation/platforms/arm/imxrt/index.rst
index f694e89..95381f5 100644
--- a/Documentation/platforms/arm/imxrt/index.rst
+++ b/Documentation/platforms/arm/imxrt/index.rst
@@ -52,7 +52,7 @@ ENET        Yes
 FlexIO      No
 GPIO        Yes
 I2S         Yes
-PWM         No
+PWM         Yes
 SAI         No
 SPDIF       No
 SPI         Yes
@@ -150,7 +150,9 @@ as a slave. The lower-half of this driver is initialize by calling :c:func:`imxr
 PWM
 ---
 
-Pulse width modulator supported in i.MX RT1010 and higher.
+Pulse width modulator supported in i.MX RT1010 and higher. Multiple channels option is evailable.
+Output on pin B is currently supported only as a complementary option to pin A.
+The lower-half of this driver is initialize by calling :c:func:`imxrt_pwminitialize`.
 
 SAI
 ---