You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2020/01/14 14:47:43 UTC

[incubator-nuttx] branch pr98 updated (e507ca4 -> 7b7d637)

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

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


    from e507ca4  imxrt1050-evk/include/board.h:  Add missing definitions.  Recent i.MXRT changes added the definition IMXRT_USB1_PLL_DIV_SELECT to the imxrt1020-evk and imxrt1060-evk board.h header files but NOT to the imxrt10%0-evk.  As a result EVERY i.MXR 1050 board configuration with USB enabled failed to compile during build testing.  Another day without a successfull build test 8( (#93)
     new 8c84d91  Low level operation support for STM32L4 PWM driver (Based on STM32 PWM driver).
     new f019d26  arch/mips/src/pic32mz/pic32mz-timer.c: Eliminate a warning found during testing.
     new b29f5e8  Fix format warn (#96)
     new b85c035  Fix a few errors concerning use of section block comments in .c files: (#95)
     new 4ad3378  net/devif/devif_poll.c:  Correct a new warning found in build testing.  devif/devif_poll.c:768:7: warning: unused variable 'hsec' [-Wunused-variable] (#97)
     new eb41649  Fix BUGs. Change macro names.
     new 7b7d637  Add SPWM example to test STM32L4 PWM driver low level operations.

The 7 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:
 arch/arm/src/cxd56xx/cxd56_dmac.c                  |    2 +-
 arch/arm/src/cxd56xx/cxd56_udmac.c                 |    2 +-
 arch/arm/src/efm32/efm32_dma.c                     |    3 +-
 arch/arm/src/efm32/efm32_gpioirq.c                 |    2 +-
 arch/arm/src/imx1/imx_boot.c                       |    2 +-
 arch/arm/src/stm32/stm32_ccm.c                     |    2 +-
 arch/arm/src/stm32f7/stm32_dtcm.c                  |   10 +-
 arch/arm/src/stm32l4/Kconfig                       | 1467 +++++++-
 arch/arm/src/stm32l4/stm32l4_pwm.c                 | 3790 ++++++++++++++------
 arch/arm/src/stm32l4/stm32l4_pwm.h                 |  371 +-
 arch/hc/src/m9s12/m9s12_dumpgpio.c                 |    2 +-
 arch/mips/src/pic32mz/pic32mz-timer.c              |    5 +-
 arch/renesas/src/rx65n/rx65n_eth.c                 |    2 +-
 arch/sim/src/sim/up_testset.c                      |    4 +-
 binfmt/libelf/libelf_load.c                        |    1 +
 boards/arm/cxd56xx/drivers/audio/cxd56_audio.c     |    4 -
 .../arm/cxd56xx/drivers/audio/cxd56_audio_ac_reg.c |    8 -
 boards/arm/cxd56xx/drivers/audio/cxd56_audio_aca.c |    8 -
 .../arm/cxd56xx/drivers/audio/cxd56_audio_analog.c |    6 +-
 .../cxd56xx/drivers/audio/cxd56_audio_bca_reg.c    |    8 -
 .../arm/cxd56xx/drivers/audio/cxd56_audio_beep.c   |    8 -
 .../arm/cxd56xx/drivers/audio/cxd56_audio_config.c |    9 +-
 .../cxd56xx/drivers/audio/cxd56_audio_digital.c    |   20 -
 boards/arm/cxd56xx/drivers/audio/cxd56_audio_dma.c |   20 +-
 .../arm/cxd56xx/drivers/audio/cxd56_audio_filter.c |   20 -
 boards/arm/cxd56xx/drivers/audio/cxd56_audio_irq.c |   16 -
 boards/arm/cxd56xx/drivers/audio/cxd56_audio_mic.c |   16 -
 .../arm/cxd56xx/drivers/audio/cxd56_audio_power.c  |   16 -
 .../arm/cxd56xx/drivers/audio/cxd56_audio_volume.c |    8 -
 boards/arm/imxrt/imxrt1020-evk/src/imxrt1020-evk.h |   14 +-
 boards/arm/imxrt/imxrt1020-evk/src/imxrt_bringup.c |    8 -
 boards/arm/lpc43xx/bambino-200e/src/lpc43_boot.c   |    2 +-
 boards/arm/stm32/omnibusf4/src/omnibusf4.h         |   24 +
 boards/arm/stm32/omnibusf4/src/stm32_bringup.c     |   16 -
 boards/arm/stm32l4/nucleo-l432kc/Kconfig           |   34 +
 boards/arm/stm32l4/nucleo-l432kc/README.txt        |   11 +
 .../stm32l4/nucleo-l432kc/configs/spwm/defconfig   | 1360 +++++++
 .../stm32l4/nucleo-l432kc/include/nucleo-l432kc.h  |   15 +-
 boards/arm/stm32l4/nucleo-l432kc/src/Makefile      |    4 +
 .../nucleo-l432kc}/src/stm32_spwm.c                |  501 +--
 fs/nxffs/nxffs_cache.c                             |   16 -
 fs/nxffs/nxffs_pack.c                              |    6 +-
 net/devif/devif_poll.c                             |    2 +
 net/procfs/netdev_statistics.c                     |    2 +-
 tools/bdf-converter.c                              |   19 +-
 wireless/bluetooth/bt_ioctl.c                      |    2 +-
 46 files changed, 5975 insertions(+), 1893 deletions(-)
 create mode 100755 boards/arm/stm32l4/nucleo-l432kc/configs/spwm/defconfig
 copy boards/arm/{stm32/nucleo-f334r8 => stm32l4/nucleo-l432kc}/src/stm32_spwm.c (55%)


[incubator-nuttx] 05/07: net/devif/devif_poll.c: Correct a new warning found in build testing. devif/devif_poll.c:768:7: warning: unused variable 'hsec' [-Wunused-variable] (#97)

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

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

commit 4ad3378b7ac956a67f6a140be468876320aa7a9b
Author: patacongo <sp...@yahoo.com>
AuthorDate: Mon Jan 13 20:11:43 2020 -0600

    net/devif/devif_poll.c:  Correct a new warning found in build testing.  devif/devif_poll.c:768:7: warning: unused variable 'hsec' [-Wunused-variable] (#97)
---
 net/devif/devif_poll.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/devif/devif_poll.c b/net/devif/devif_poll.c
index 75b0ff2..7c4fd04 100644
--- a/net/devif/devif_poll.c
+++ b/net/devif/devif_poll.c
@@ -765,7 +765,9 @@ int devif_poll(FAR struct net_driver_s *dev, devif_poll_callback_t callback)
 int devif_timer(FAR struct net_driver_s *dev, int delay,
                 devif_poll_callback_t callback)
 {
+#if defined(CONFIG_NET_IPv4_REASSEMBLY) || defined(NET_TCP_HAVE_STACK)
   int hsec = TICK2HSEC(delay);
+#endif
   int bstop = false;
 
 #ifdef CONFIG_NET_IPv4_REASSEMBLY


[incubator-nuttx] 03/07: Fix format warn (#96)

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

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

commit b29f5e8cb0e0552d68e5a6228d5c495da442c3bd
Author: Xiang Xiao <xi...@xiaomi.com>
AuthorDate: Tue Jan 14 06:41:09 2020 +0800

    Fix format warn (#96)
    
    * fix warning: format '%x' expects argument of type 'unsigned int', but argument 4 has type 'long unsigned int'
    * fix warning: implicit declaration of function 'up_init_exidx'
---
 binfmt/libelf/libelf_load.c    | 1 +
 net/procfs/netdev_statistics.c | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/binfmt/libelf/libelf_load.c b/binfmt/libelf/libelf_load.c
index a74ae3f..6460c79 100644
--- a/binfmt/libelf/libelf_load.c
+++ b/binfmt/libelf/libelf_load.c
@@ -51,6 +51,7 @@
 
 #include <nuttx/arch.h>
 #include <nuttx/addrenv.h>
+#include <nuttx/elf.h>
 #include <nuttx/mm/mm.h>
 #include <nuttx/binfmt/elf.h>
 
diff --git a/net/procfs/netdev_statistics.c b/net/procfs/netdev_statistics.c
index cdeb724..a75ee06 100644
--- a/net/procfs/netdev_statistics.c
+++ b/net/procfs/netdev_statistics.c
@@ -538,7 +538,7 @@ static int netprocfs_errors(FAR struct netprocfs_file_s *netfile)
   stats = &dev->d_statistics;
 
   return snprintf(netfile->line, NET_LINELEN , "\tTotal Errors: %08x\n\n",
-                  (unsigned long)stats->errors);
+                  stats->errors);
 }
 #endif /* CONFIG_NETDEV_STATISTICS */
 


[incubator-nuttx] 04/07: Fix a few errors concerning use of section block comments in .c files: (#95)

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

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

commit b85c035b5038078791bf7dcb280b231e89b96232
Author: patacongo <sp...@yahoo.com>
AuthorDate: Mon Jan 13 17:37:54 2020 -0600

    Fix a few errors concerning use of section block comments in .c files: (#95)
    
    1. No .c file should include a "Public Types" section.  Only a header file can define a public type.  A .c file can only define a private type.  Several files contained private type definitions.  The section that they were defined in, however, was incorrectly named "Public Types."  Those were easilty changed to "Private Types" which is what they are.
    
    2. No .c file should include a "Public Function Prototypes" section.  All global function prototypes should be provided via a header file and never declared with a .c file.
    
    For No. 2, I corrected as many cases as was reasonable for the time that I had available.  But there are still a dozen or so .c files that declare "Public Function Prototypes" within a .c file.  This is bad programming style.  These declarations should all be moved to the proper header files.
---
 arch/arm/src/cxd56xx/cxd56_dmac.c                  |  2 +-
 arch/arm/src/cxd56xx/cxd56_udmac.c                 |  2 +-
 arch/arm/src/efm32/efm32_dma.c                     |  3 ++-
 arch/arm/src/efm32/efm32_gpioirq.c                 |  2 +-
 arch/arm/src/imx1/imx_boot.c                       |  2 +-
 arch/arm/src/stm32/stm32_ccm.c                     |  2 +-
 arch/arm/src/stm32f7/stm32_dtcm.c                  | 10 +--------
 arch/hc/src/m9s12/m9s12_dumpgpio.c                 |  2 +-
 arch/renesas/src/rx65n/rx65n_eth.c                 |  2 +-
 arch/sim/src/sim/up_testset.c                      |  4 +++-
 boards/arm/cxd56xx/drivers/audio/cxd56_audio.c     |  4 ----
 .../arm/cxd56xx/drivers/audio/cxd56_audio_ac_reg.c |  8 --------
 boards/arm/cxd56xx/drivers/audio/cxd56_audio_aca.c |  8 --------
 .../arm/cxd56xx/drivers/audio/cxd56_audio_analog.c |  6 +++---
 .../cxd56xx/drivers/audio/cxd56_audio_bca_reg.c    |  8 --------
 .../arm/cxd56xx/drivers/audio/cxd56_audio_beep.c   |  8 --------
 .../arm/cxd56xx/drivers/audio/cxd56_audio_config.c |  9 +-------
 .../cxd56xx/drivers/audio/cxd56_audio_digital.c    | 20 ------------------
 boards/arm/cxd56xx/drivers/audio/cxd56_audio_dma.c | 20 +++++-------------
 .../arm/cxd56xx/drivers/audio/cxd56_audio_filter.c | 20 ------------------
 boards/arm/cxd56xx/drivers/audio/cxd56_audio_irq.c | 16 ---------------
 boards/arm/cxd56xx/drivers/audio/cxd56_audio_mic.c | 16 ---------------
 .../arm/cxd56xx/drivers/audio/cxd56_audio_power.c  | 16 ---------------
 .../arm/cxd56xx/drivers/audio/cxd56_audio_volume.c |  8 --------
 boards/arm/imxrt/imxrt1020-evk/src/imxrt1020-evk.h | 14 +++++++++++--
 boards/arm/imxrt/imxrt1020-evk/src/imxrt_bringup.c |  8 --------
 boards/arm/lpc43xx/bambino-200e/src/lpc43_boot.c   |  2 +-
 boards/arm/stm32/omnibusf4/src/omnibusf4.h         | 24 ++++++++++++++++++++++
 boards/arm/stm32/omnibusf4/src/stm32_bringup.c     | 16 ---------------
 fs/nxffs/nxffs_cache.c                             | 16 ---------------
 fs/nxffs/nxffs_pack.c                              |  6 +-----
 tools/bdf-converter.c                              | 19 +++++++++--------
 wireless/bluetooth/bt_ioctl.c                      |  2 +-
 33 files changed, 71 insertions(+), 234 deletions(-)

diff --git a/arch/arm/src/cxd56xx/cxd56_dmac.c b/arch/arm/src/cxd56xx/cxd56_dmac.c
index b40d35d..1554c75 100644
--- a/arch/arm/src/cxd56xx/cxd56_dmac.c
+++ b/arch/arm/src/cxd56xx/cxd56_dmac.c
@@ -269,7 +269,7 @@ static int (*intc_handler[])(int irq, FAR void *context, FAR void *arg) = {
 };
 
 /****************************************************************************
- * Public Types
+ * Private Types
  ****************************************************************************/
 
 /* This structure describes one DMA channel */
diff --git a/arch/arm/src/cxd56xx/cxd56_udmac.c b/arch/arm/src/cxd56xx/cxd56_udmac.c
index 67f0f53..258b4bd 100644
--- a/arch/arm/src/cxd56xx/cxd56_udmac.c
+++ b/arch/arm/src/cxd56xx/cxd56_udmac.c
@@ -65,7 +65,7 @@
 #define ALIGN_UP(v, m)   (((v) + (m)) & ~m)
 
 /****************************************************************************
- * Public Types
+ * Private Types
  ****************************************************************************/
 
 /* This structure describes one DMA channel */
diff --git a/arch/arm/src/efm32/efm32_dma.c b/arch/arm/src/efm32/efm32_dma.c
index 7afe854..6d8e238 100644
--- a/arch/arm/src/efm32/efm32_dma.c
+++ b/arch/arm/src/efm32/efm32_dma.c
@@ -63,8 +63,9 @@
 #define ALIGN_UP(v,m)   (((v) + (m)) & ~m)
 
 /****************************************************************************
- * Public Types
+ * Private Types
  ****************************************************************************/
+
 /* This structure describes one DMA channel */
 
 struct dma_channel_s
diff --git a/arch/arm/src/efm32/efm32_gpioirq.c b/arch/arm/src/efm32/efm32_gpioirq.c
index dd31f63..fe2ec8c 100644
--- a/arch/arm/src/efm32/efm32_gpioirq.c
+++ b/arch/arm/src/efm32/efm32_gpioirq.c
@@ -152,7 +152,7 @@ static int efm32_odd_interrupt(int irq, void *context, FAR void *arg)
 }
 
 /************************************************************************************
- * Public Function Prototypes
+ * Public Functions
  ************************************************************************************/
 
 /************************************************************************************
diff --git a/arch/arm/src/imx1/imx_boot.c b/arch/arm/src/imx1/imx_boot.c
index c429a31..d4d44d7 100644
--- a/arch/arm/src/imx1/imx_boot.c
+++ b/arch/arm/src/imx1/imx_boot.c
@@ -102,7 +102,7 @@ static const struct section_mapping_s section_mapping[] =
  ************************************************************************************/
 
 /* All i.MX architectures must provide the following entry point.  This entry point
- * is called early in the intitialization -- after all memory has been configured
+ * is called early in the initialization -- after all memory has been configured
  * and mapped but before any devices have been initialized.
  */
 
diff --git a/arch/arm/src/stm32/stm32_ccm.c b/arch/arm/src/stm32/stm32_ccm.c
index 95d5b3a..635f2a6 100644
--- a/arch/arm/src/stm32/stm32_ccm.c
+++ b/arch/arm/src/stm32/stm32_ccm.c
@@ -51,7 +51,7 @@
 struct mm_heap_s g_ccm_heap;
 
 /****************************************************************************
- * Public Function Prototypes
+ * Public Functions
  ****************************************************************************/
 
 #endif /* HAVE_CCM_HEAP */
diff --git a/arch/arm/src/stm32f7/stm32_dtcm.c b/arch/arm/src/stm32f7/stm32_dtcm.c
index 07dc04e..0044946 100644
--- a/arch/arm/src/stm32f7/stm32_dtcm.c
+++ b/arch/arm/src/stm32f7/stm32_dtcm.c
@@ -44,21 +44,13 @@
 #ifdef HAVE_DTCM_HEAP
 
 /****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-/****************************************************************************
- * Private Types
- ****************************************************************************/
-
-/****************************************************************************
  * Public Data
  ****************************************************************************/
 
 struct mm_heap_s g_dtcm_heap;
 
 /****************************************************************************
- * Public Function Prototypes
+ * Public Functions
  ****************************************************************************/
 
 #endif /* HAVE_DTCM_HEAP */
\ No newline at end of file
diff --git a/arch/hc/src/m9s12/m9s12_dumpgpio.c b/arch/hc/src/m9s12/m9s12_dumpgpio.c
index 4a7d386..30fd869 100644
--- a/arch/hc/src/m9s12/m9s12_dumpgpio.c
+++ b/arch/hc/src/m9s12/m9s12_dumpgpio.c
@@ -110,7 +110,7 @@
 #define MEBIPORT_K   2
 
 /****************************************************************************
- * Public Types
+ * Private Types
  ****************************************************************************/
 
 struct gpio_piminfo_s
diff --git a/arch/renesas/src/rx65n/rx65n_eth.c b/arch/renesas/src/rx65n/rx65n_eth.c
index 742479e..2a80765 100644
--- a/arch/renesas/src/rx65n/rx65n_eth.c
+++ b/arch/renesas/src/rx65n/rx65n_eth.c
@@ -386,7 +386,7 @@
 #define NX_ALIGN32 __attribute__((aligned(32)))
 
 /****************************************************************************
- * Public Types
+ * Private Types
  ****************************************************************************/
 
 /* Ethernet TX DMA Descriptor */
diff --git a/arch/sim/src/sim/up_testset.c b/arch/sim/src/sim/up_testset.c
index ec185c1..38d53b9 100644
--- a/arch/sim/src/sim/up_testset.c
+++ b/arch/sim/src/sim/up_testset.c
@@ -43,14 +43,16 @@
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
+
 /* Must match definitions in arch/sim/include/spinlock.h */
 
 #define SP_UNLOCKED 0   /* The Un-locked state */
 #define SP_LOCKED   1   /* The Locked state */
 
 /****************************************************************************
- * Public Types
+ * Private Types
  ****************************************************************************/
+
 /* Must match definitions in arch/sim/include/spinlock.h */
 
 typedef uint8_t spinlock_t;
diff --git a/boards/arm/cxd56xx/drivers/audio/cxd56_audio.c b/boards/arm/cxd56xx/drivers/audio/cxd56_audio.c
index ed2ae11..818f778 100644
--- a/boards/arm/cxd56xx/drivers/audio/cxd56_audio.c
+++ b/boards/arm/cxd56xx/drivers/audio/cxd56_audio.c
@@ -67,10 +67,6 @@
 #define AUDIO_VOL_ID_NUM      (CXD56_AUDIO_VOLID_MIXER_OUT + 1)
 
 /***************************************************************************
- * Public Function Prototypes
- ****************************************************************************/
-
-/***************************************************************************
  * Private Types
  ****************************************************************************/
 
diff --git a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_ac_reg.c b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_ac_reg.c
index aefb27b..1bd9bbf 100644
--- a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_ac_reg.c
+++ b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_ac_reg.c
@@ -115,10 +115,6 @@
 #define SRCIN_SEL_CODECDSP_MIX 3
 
 /****************************************************************************
- * Public Function Prototypes
- ****************************************************************************/
-
-/****************************************************************************
  * Private Data
  ****************************************************************************/
 
@@ -450,10 +446,6 @@ const struct audio_ac_reg_s g_ac_reg[RI_REG_MAX_ENTRY] =
 };
 
 /****************************************************************************
- * Public Data
- ****************************************************************************/
-
-/****************************************************************************
  * Private Functions
  ****************************************************************************/
 
diff --git a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_aca.c b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_aca.c
index e629464..30816ce 100644
--- a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_aca.c
+++ b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_aca.c
@@ -357,14 +357,6 @@ typedef enum
 extern uint32_t as_aca_control(uint8_t type, uint32_t param);
 
 /****************************************************************************
- * Private Data
- ****************************************************************************/
-
-/****************************************************************************
- * Public Data
- ****************************************************************************/
-
-/****************************************************************************
  * Private Functions
  ****************************************************************************/
 
diff --git a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_analog.c b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_analog.c
index c8ee809..dea2f42 100644
--- a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_analog.c
+++ b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_analog.c
@@ -64,9 +64,9 @@
  * Public Function Prototypes
  ****************************************************************************/
 
-  inline void cxd56_audio_clock_enable(uint32_t clk, uint32_t div);
-  inline void cxd56_audio_clock_disable(void);
-  inline bool cxd56_audio_clock_is_enabled(void);
+inline void cxd56_audio_clock_enable(uint32_t clk, uint32_t div);
+inline void cxd56_audio_clock_disable(void);
+inline bool cxd56_audio_clock_is_enabled(void);
 
 /****************************************************************************
  * Private Data
diff --git a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_bca_reg.c b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_bca_reg.c
index 266cf90..4b98536 100644
--- a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_bca_reg.c
+++ b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_bca_reg.c
@@ -71,14 +71,6 @@ enum dma_i2s_out_sel_e
 #define BCA_REG_MAX_BIT 32
 
 /***************************************************************************
- * Public Function Prototypes
- ****************************************************************************/
-
-/***************************************************************************
- * Private Data
- ****************************************************************************/
-
-/***************************************************************************
  * Public Data
  ****************************************************************************/
 
diff --git a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_beep.c b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_beep.c
index 7fd86b9..cba8773 100644
--- a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_beep.c
+++ b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_beep.c
@@ -64,10 +64,6 @@
 #define VOL_MIN         -90
 
 /***************************************************************************
- * Public Function Prototypes
- ****************************************************************************/
-
-/***************************************************************************
  * Private Data
  ****************************************************************************/
 
@@ -84,10 +80,6 @@ static const uint16_t g_beepfreqtable[] =
 };
 
 /***************************************************************************
- * Public Data
- ****************************************************************************/
-
-/***************************************************************************
  * Private Functions
  ****************************************************************************/
 
diff --git a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_config.c b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_config.c
index a856c00..8270bee 100644
--- a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_config.c
+++ b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_config.c
@@ -48,10 +48,6 @@
 #define MIC_CH_BITMAP  0xf
 
 /****************************************************************************
- * Public Function Prototypes
- ****************************************************************************/
-
-/****************************************************************************
  * Private Data
  ****************************************************************************/
 
@@ -64,6 +60,7 @@ struct cxd56_audio_cfg_s
   cxd56_audio_clkmode_t clk_mode;
   cxd56_audio_sp_drv_t  sp_driver;
 };
+
 static struct cxd56_audio_cfg_s g_audio_cfg =
 {
   1,
@@ -75,10 +72,6 @@ static struct cxd56_audio_cfg_s g_audio_cfg =
 };
 
 /****************************************************************************
- * Public Data
- ****************************************************************************/
-
-/****************************************************************************
  * Private Functions
  ****************************************************************************/
 
diff --git a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_digital.c b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_digital.c
index 1cd679f..e96f0bd 100644
--- a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_digital.c
+++ b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_digital.c
@@ -46,26 +46,6 @@
 #include "cxd56_audio_digital.h"
 
 /***************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-/***************************************************************************
- * Public Function Prototypes
- ****************************************************************************/
-
-/***************************************************************************
- * Private Data
- ****************************************************************************/
-
-/***************************************************************************
- * Public Data
- ****************************************************************************/
-
-/***************************************************************************
- * Private Functions
- ****************************************************************************/
-
-/***************************************************************************
  * Public Functions
  ****************************************************************************/
 
diff --git a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_dma.c b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_dma.c
index 8ea096e..ee734c2 100644
--- a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_dma.c
+++ b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_dma.c
@@ -92,9 +92,11 @@ enum audio_irq_reg_type_e
 #define DMA_SMP_WAIT_HIRES   10 /* usec per sample. */
 #define DMA_SMP_WAIT_NORMALT 40 /* usec per sample. */
 
-/***************************************************************************
- * Public Function Prototypes
- ****************************************************************************/
+/* Private Macros */
+
+#define SET_DMA_ACT(_path_)  g_dma_act_status |= (1 << _path_)
+#define CLR_DMA_ACT(_path_)  g_dma_act_status &= ~(1 << _path_)
+#define IS_DMA_ACT(_path_)   ((g_dma_act_status & (1 << _path_)) != 0)
 
 /***************************************************************************
  * Private Data
@@ -111,18 +113,6 @@ static bool s_work_arroud_dmac[DMA_HANDLE_MAX_NUM] =
 };
 
 /***************************************************************************
- * Private Macro
- ****************************************************************************/
-
-#define SET_DMA_ACT(_path_)  g_dma_act_status |= (1 << _path_)
-#define CLR_DMA_ACT(_path_)  g_dma_act_status &= ~(1 << _path_)
-#define IS_DMA_ACT(_path_)   ((g_dma_act_status & (1 << _path_)) != 0)
-
-/***************************************************************************
- * Public Data
- ****************************************************************************/
-
-/***************************************************************************
  * Private Functions
  ****************************************************************************/
 
diff --git a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_filter.c b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_filter.c
index 6db6b1a..cb26439 100644
--- a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_filter.c
+++ b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_filter.c
@@ -44,26 +44,6 @@
 #include "cxd56_audio_ac_reg.h"
 
 /***************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-/***************************************************************************
- * Public Function Prototypes
- ****************************************************************************/
-
-/***************************************************************************
- * Private Data
- ****************************************************************************/
-
-/***************************************************************************
- * Public Data
- ****************************************************************************/
-
-/***************************************************************************
- * Private Functions
- ****************************************************************************/
-
-/***************************************************************************
  * Public Functions
  ****************************************************************************/
 
diff --git a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_irq.c b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_irq.c
index d047976..10390a7 100644
--- a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_irq.c
+++ b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_irq.c
@@ -44,28 +44,12 @@
 #include "cxd56_audio_irq.h"
 
 /***************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-/***************************************************************************
  * Public Function Prototypes
  ****************************************************************************/
 
 extern void cxd56_audio_dma_int_handler(void);
 
 /***************************************************************************
- * Private Data
- ****************************************************************************/
-
-/***************************************************************************
- * Public Data
- ****************************************************************************/
-
-/***************************************************************************
- * Private Functions
- ****************************************************************************/
-
-/***************************************************************************
  * Public Functions
  ****************************************************************************/
 
diff --git a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_mic.c b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_mic.c
index 8ce972b..68d4e4e 100644
--- a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_mic.c
+++ b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_mic.c
@@ -55,22 +55,6 @@
 #define MIC_CH_BITMAP  0xf
 
 /***************************************************************************
- * Public Function Prototypes
- ****************************************************************************/
-
-/***************************************************************************
- * Private Data
- ****************************************************************************/
-
-/***************************************************************************
- * Public Data
- ****************************************************************************/
-
-/***************************************************************************
- * Private Functions
- ****************************************************************************/
-
-/***************************************************************************
  * Public Functions
  ****************************************************************************/
 
diff --git a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_power.c b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_power.c
index 9f38c1a..a6092a0 100644
--- a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_power.c
+++ b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_power.c
@@ -51,22 +51,6 @@
 #include "cxd56_audio_bca_reg.h"
 
 /***************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-/***************************************************************************
- * Public Function Prototypes
- ****************************************************************************/
-
-/***************************************************************************
- * Private Data
- ****************************************************************************/
-
-/***************************************************************************
- * Public Data
- ****************************************************************************/
-
-/***************************************************************************
  * Private Functions
  ****************************************************************************/
 
diff --git a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_volume.c b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_volume.c
index b1ec052..0d48cb5 100644
--- a/boards/arm/cxd56xx/drivers/audio/cxd56_audio_volume.c
+++ b/boards/arm/cxd56xx/drivers/audio/cxd56_audio_volume.c
@@ -76,10 +76,6 @@
   (((VOL_TO_REG(vol) - MUTE_VOL_REG) & 0xff) * (n_cycle + 1) * 4 / 48 * 1000)
 
 /****************************************************************************
- * Public Function Prototypes
- ****************************************************************************/
-
-/****************************************************************************
  * Private Type
  ****************************************************************************/
 
@@ -101,10 +97,6 @@ static struct set_vol_prm_s g_volparam[VOLUME_NUM] =
 };
 
 /****************************************************************************
- * Public Data
- ****************************************************************************/
-
-/****************************************************************************
  * Private Functions
  ****************************************************************************/
 
diff --git a/boards/arm/imxrt/imxrt1020-evk/src/imxrt1020-evk.h b/boards/arm/imxrt/imxrt1020-evk/src/imxrt1020-evk.h
index 29eeeb9..b09cee4 100644
--- a/boards/arm/imxrt/imxrt1020-evk/src/imxrt1020-evk.h
+++ b/boards/arm/imxrt/imxrt1020-evk/src/imxrt1020-evk.h
@@ -174,8 +174,6 @@ int imxrt_mmcsd_spi_initialize(int minor);
 void imxrt_autoled_initialize(void);
 #endif
 
-#ifdef CONFIG_DEV_GPIO
-
 /****************************************************************************
  * Name: imxrt_gpio_initialize
  *
@@ -184,8 +182,20 @@ void imxrt_autoled_initialize(void);
  *
  ****************************************************************************/
 
+#ifdef CONFIG_DEV_GPIO
 int imxrt_gpio_initialize(void);
 #endif
 
+/****************************************************************************
+ * Name: imxrt_usbhost_initialize
+ *
+ * Description:
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_USBHOST
+int imxrt_usbhost_initialize(void);
+#endif
+
 #endif /* __ASSEMBLY__ */
 #endif /* __BOARDS_ARM_IMXRT_IMXRT1020_EVK_SRC_IMXRT1020_EVK_H */
diff --git a/boards/arm/imxrt/imxrt1020-evk/src/imxrt_bringup.c b/boards/arm/imxrt/imxrt1020-evk/src/imxrt_bringup.c
index 3393ab1..4205646 100644
--- a/boards/arm/imxrt/imxrt1020-evk/src/imxrt_bringup.c
+++ b/boards/arm/imxrt/imxrt1020-evk/src/imxrt_bringup.c
@@ -83,14 +83,6 @@
 #endif
 
 /****************************************************************************
- * Public Function Prototypes
- ****************************************************************************/
-
-#ifdef CONFIG_USBHOST
-int imxrt_usbhost_initialize(void);
-#endif
-
-/****************************************************************************
  * Private Functions
  ****************************************************************************/
 
diff --git a/boards/arm/lpc43xx/bambino-200e/src/lpc43_boot.c b/boards/arm/lpc43xx/bambino-200e/src/lpc43_boot.c
index 1925b00..d6aa9fd 100644
--- a/boards/arm/lpc43xx/bambino-200e/src/lpc43_boot.c
+++ b/boards/arm/lpc43xx/bambino-200e/src/lpc43_boot.c
@@ -51,7 +51,7 @@
 #include "bambino-200e.h"
 
 /****************************************************************************
- * Public Types
+ * Private Types
  ****************************************************************************/
 
 enum devid_e
diff --git a/boards/arm/stm32/omnibusf4/src/omnibusf4.h b/boards/arm/stm32/omnibusf4/src/omnibusf4.h
index 057892e..afe1244 100644
--- a/boards/arm/stm32/omnibusf4/src/omnibusf4.h
+++ b/boards/arm/stm32/omnibusf4/src/omnibusf4.h
@@ -210,5 +210,29 @@ int stm32_can_setup(void);
 int stm32_timer_driver_setup(FAR const char *devpath, int timer);
 #endif
 
+/****************************************************************************
+ * Name: stm32_mpu6000_initialize
+ *
+ * Description:
+ *  Initialize the MPU6000 device.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SENSORS_MPU60X0
+int stm32_mpu6000_initialize(void);
+#endif
+
+/****************************************************************************
+ * Name: stm32_max7456_initialize
+ *
+ * Description:
+ *  Initialize the MAX7456 OSD device.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_VIDEO_MAX7456
+int stm32_max7456_initialize(void);
+#endif
+
 #endif /* __ASSEMBLY__ */
 #endif /* __BOARDS_ARM_STM32_OMNIBUSF4_SRC_OMNIBUSF4_H */
diff --git a/boards/arm/stm32/omnibusf4/src/stm32_bringup.c b/boards/arm/stm32/omnibusf4/src/stm32_bringup.c
index 819e06d..0957344 100644
--- a/boards/arm/stm32/omnibusf4/src/stm32_bringup.c
+++ b/boards/arm/stm32/omnibusf4/src/stm32_bringup.c
@@ -79,22 +79,6 @@
 #endif
 
 /****************************************************************************
- * Public Function Prototypes
- ****************************************************************************/
-
-#ifdef CONFIG_SENSORS_MPU60X0
-/* Initialize the MPU6000 device. */
-
-int stm32_mpu6000_initialize(void);
-#endif
-
-#ifdef CONFIG_VIDEO_MAX7456
-/* Initialize the MAX7456 OSD device. */
-
-int stm32_max7456_initialize(void);
-#endif
-
-/****************************************************************************
  * Public Functions
  ****************************************************************************/
 
diff --git a/fs/nxffs/nxffs_cache.c b/fs/nxffs/nxffs_cache.c
index 6a5c4c0..63bf071 100644
--- a/fs/nxffs/nxffs_cache.c
+++ b/fs/nxffs/nxffs_cache.c
@@ -50,22 +50,6 @@
 #include "nxffs.h"
 
 /****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-/****************************************************************************
- * Public Types
- ****************************************************************************/
-
-/****************************************************************************
- * Public Data
- ****************************************************************************/
-
-/****************************************************************************
- * Private Functions
- ****************************************************************************/
-
-/****************************************************************************
  * Public Functions
  ****************************************************************************/
 
diff --git a/fs/nxffs/nxffs_pack.c b/fs/nxffs/nxffs_pack.c
index 42ae428..08d04cb 100644
--- a/fs/nxffs/nxffs_pack.c
+++ b/fs/nxffs/nxffs_pack.c
@@ -52,11 +52,7 @@
 #include "nxffs.h"
 
 /****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-/****************************************************************************
- * Public Types
+ * Private Types
  ****************************************************************************/
 
 /* This structure supports access to one inode data stream */
diff --git a/tools/bdf-converter.c b/tools/bdf-converter.c
index d1e935a..bcca5c5 100644
--- a/tools/bdf-converter.c
+++ b/tools/bdf-converter.c
@@ -54,15 +54,16 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
-/*
-#define VERBOSE
-#define DBG
-*/
+#if 0
+#  define VERBOSE
+#  define DBG
+#endif
 
-// BDF Specification Version 2.2:
-// This version lifts the restriction on line length. In this version, the new
-// maximum length of a value of the type string is 65535 characters, and hence
-// lines may now be at least this long.
+/* BDF Specification Version 2.2:
+ * This version lifts the restriction on line length. In this version, the new
+ * maximum length of a value of the type string is 65535 characters, and hence
+ * lines may now be at least this long.
+ */
 
 #define BDF_MAX_LINE_LENGTH 65535
 
@@ -75,7 +76,7 @@
 #define NXFONT_MAX8BIT 255
 
 /****************************************************************************
- * Public Types
+ * Private Types
  ****************************************************************************/
 
 /* This structure holds information about a glyph */
diff --git a/wireless/bluetooth/bt_ioctl.c b/wireless/bluetooth/bt_ioctl.c
index a1d1053..e82e0b4 100644
--- a/wireless/bluetooth/bt_ioctl.c
+++ b/wireless/bluetooth/bt_ioctl.c
@@ -59,7 +59,7 @@
 #ifdef CONFIG_NETDEV_IOCTL  /* Not optional! */
 
 /****************************************************************************
- * Public Types
+ * Private Types
  ****************************************************************************/
 
 /* These structures encapsulate all globals used by the IOCTL logic. */


[incubator-nuttx] 02/07: arch/mips/src/pic32mz/pic32mz-timer.c: Eliminate a warning found during testing.

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

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

commit f019d26c92526d0bc5494d1b408c8a9217b4c368
Author: Ouss4 <ab...@gmail.com>
AuthorDate: Mon Jan 13 22:45:41 2020 +0000

    arch/mips/src/pic32mz/pic32mz-timer.c: Eliminate a warning found during
    testing.
---
 arch/mips/src/pic32mz/pic32mz-timer.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/arch/mips/src/pic32mz/pic32mz-timer.c b/arch/mips/src/pic32mz/pic32mz-timer.c
index 0b216f4..c7c38d6 100644
--- a/arch/mips/src/pic32mz/pic32mz-timer.c
+++ b/arch/mips/src/pic32mz/pic32mz-timer.c
@@ -974,7 +974,6 @@ static bool pic32mz_timer_setfreq(FAR struct pic32mz_timer_dev_s *dev,
                                   uint32_t freq)
 {
   uint16_t prescale;
-  uint32_t tmrfreq;
 
   DEBUGASSERT(dev != NULL);
 
@@ -1046,9 +1045,7 @@ static bool pic32mz_timer_setfreq(FAR struct pic32mz_timer_dev_s *dev,
       return false;
     }
 
-  tmrfreq = pic32mz_timer_getfreq(dev);
-
-  tmrinfo("Timer's frequency set to %luHz\n", tmrfreq);
+  tmrinfo("Timer's frequency set to %luHz\n", pic32mz_timer_getfreq(dev));
 
   return true;
 }


[incubator-nuttx] 07/07: Add SPWM example to test STM32L4 PWM driver low level operations.

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

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

commit 7b7d637f01204f5ea86d93c02edb7c5f6b63d4cc
Author: Daniel P. Carvalho <da...@gmail.com>
AuthorDate: Tue Jan 14 11:29:09 2020 -0300

    Add SPWM example to test STM32L4 PWM driver low level operations.
---
 boards/arm/stm32l4/nucleo-l432kc/Kconfig           |   34 +
 boards/arm/stm32l4/nucleo-l432kc/README.txt        |   11 +
 .../stm32l4/nucleo-l432kc/configs/spwm/defconfig   | 1360 ++++++++++++++++++++
 boards/arm/stm32l4/nucleo-l432kc/src/Makefile      |    4 +
 boards/arm/stm32l4/nucleo-l432kc/src/stm32_spwm.c  |  664 ++++++++++
 5 files changed, 2073 insertions(+)

diff --git a/boards/arm/stm32l4/nucleo-l432kc/Kconfig b/boards/arm/stm32l4/nucleo-l432kc/Kconfig
index f913f96..353f988 100644
--- a/boards/arm/stm32l4/nucleo-l432kc/Kconfig
+++ b/boards/arm/stm32l4/nucleo-l432kc/Kconfig
@@ -107,4 +107,38 @@ endchoice
 
 endmenu
 
+menuconfig NUCLEOL432KC_SPWM
+	bool "Sinusoidal PWM generator example"
+	default n
+
+if NUCLEOL432KC_SPWM
+
+choice
+	prompt "Sinusoidal PWM source"
+	default NUCLEOL432KC_SPWM_USE_TIM1
+
+config NUCLEOL432KC_SPWM_USE_TIM1
+	bool "Use TIM1 as PWM source"
+
+endchoice
+
+config NUCLEOL432KC_SPWM_PWM_FREQ
+	int "PWM frequency in Hz"
+	default 100000
+
+config NUCLEOL432KC_SPWM_SAMPLES
+	int "Sine samples"
+	default 100
+
+config NUCLEOL432KC_SPWM_FREQ
+	int "Waveform frequency in Hz"
+	default 60
+
+config NUCLEOL432KC_SPWM_PHASE_NUM
+	int "Number of phases"
+	default 1
+	range 1 4 if NUCLEOL432KC_SPWM_USE_TIM1
+
+endif
+
 endif # ARCH_BOARD_NUCLEO_L432KC
diff --git a/boards/arm/stm32l4/nucleo-l432kc/README.txt b/boards/arm/stm32l4/nucleo-l432kc/README.txt
index 5f19b4e..aac5e14 100644
--- a/boards/arm/stm32l4/nucleo-l432kc/README.txt
+++ b/boards/arm/stm32l4/nucleo-l432kc/README.txt
@@ -535,3 +535,14 @@ Configurations
        Pin 33 PA10 USART1_TX    some RS-232 converters
        Pin 20 GND
        Pin 8  U5V
+
+  spwm
+  ----
+
+    Configures the sinusoidal PWM (SPWM) example which presents a simple use case
+    of the STM32L4 PWM lower-half driver without generic upper-half PWM logic.
+
+    It uses TIM1 to generate PWM and TIM6 to change waveform samples
+
+    At the moment, the waveform parameters are hardcoded, but it should be easy to
+    modify this example and make it more functional.
\ No newline at end of file
diff --git a/boards/arm/stm32l4/nucleo-l432kc/configs/spwm/defconfig b/boards/arm/stm32l4/nucleo-l432kc/configs/spwm/defconfig
new file mode 100755
index 0000000..6c2ce2b
--- /dev/null
+++ b/boards/arm/stm32l4/nucleo-l432kc/configs/spwm/defconfig
@@ -0,0 +1,1360 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Nuttx/ Configuration
+#
+
+#
+# Build Setup
+#
+# CONFIG_EXPERIMENTAL is not set
+# CONFIG_DEFAULT_SMALL is not set
+CONFIG_HOST_LINUX=y
+# CONFIG_HOST_MACOS is not set
+# CONFIG_HOST_WINDOWS is not set
+# CONFIG_HOST_OTHER is not set
+
+#
+# Build Configuration
+#
+CONFIG_APPS_DIR="../apps"
+CONFIG_BUILD_FLAT=y
+# CONFIG_BUILD_2PASS is not set
+
+#
+# Binary Output Formats
+#
+# CONFIG_CXD56_BINARY is not set
+CONFIG_INTELHEX_BINARY=y
+# CONFIG_MOTOROLA_SREC is not set
+CONFIG_RAW_BINARY=y
+# CONFIG_UBOOT_UIMAGE is not set
+# CONFIG_DFU_BINARY is not set
+
+#
+# Customize Header Files
+#
+# CONFIG_ARCH_HAVE_STDINT_H is not set
+# CONFIG_ARCH_HAVE_STDBOOL_H is not set
+# CONFIG_ARCH_HAVE_MATH_H is not set
+CONFIG_ARCH_FLOAT_H=y
+CONFIG_ARCH_HAVE_STDARG_H=y
+# CONFIG_ARCH_STDARG_H is not set
+CONFIG_ARCH_HAVE_SETJMP=y
+# CONFIG_ARCH_SETJMP_H is not set
+# CONFIG_ARCH_DEBUG_H is not set
+
+#
+# Debug Options
+#
+CONFIG_DEBUG_ALERT=y
+# CONFIG_DEBUG_FEATURES is not set
+CONFIG_ARCH_HAVE_STACKCHECK=y
+# CONFIG_STACK_COLORATION is not set
+CONFIG_ARCH_HAVE_HEAPCHECK=y
+# CONFIG_HEAP_COLORATION is not set
+# CONFIG_DEBUG_SYMBOLS is not set
+CONFIG_ARCH_HAVE_CUSTOMOPT=y
+CONFIG_DEBUG_NOOPT=y
+# CONFIG_DEBUG_CUSTOMOPT is not set
+# CONFIG_DEBUG_FULLOPT is not set
+
+#
+# System Type
+#
+CONFIG_ARCH_ARM=y
+# CONFIG_ARCH_AVR is not set
+# CONFIG_ARCH_HC is not set
+# CONFIG_ARCH_MIPS is not set
+# CONFIG_ARCH_MISOC is not set
+# CONFIG_ARCH_RENESAS is not set
+# CONFIG_ARCH_RISCV is not set
+# CONFIG_ARCH_SIM is not set
+# CONFIG_ARCH_X86 is not set
+# CONFIG_ARCH_XTENSA is not set
+# CONFIG_ARCH_Z16 is not set
+# CONFIG_ARCH_Z80 is not set
+# CONFIG_ARCH_OR1K is not set
+CONFIG_ARCH="arm"
+
+#
+# ARM Options
+#
+# CONFIG_ARCH_CHIP_A1X is not set
+# CONFIG_ARCH_CHIP_AM335X is not set
+# CONFIG_ARCH_CHIP_C5471 is not set
+# CONFIG_ARCH_CHIP_DM320 is not set
+# CONFIG_ARCH_CHIP_EFM32 is not set
+# CONFIG_ARCH_CHIP_IMX1 is not set
+# CONFIG_ARCH_CHIP_IMX6 is not set
+# CONFIG_ARCH_CHIP_IMXRT is not set
+# CONFIG_ARCH_CHIP_KINETIS is not set
+# CONFIG_ARCH_CHIP_KL is not set
+# CONFIG_ARCH_CHIP_LC823450 is not set
+# CONFIG_ARCH_CHIP_LM is not set
+# CONFIG_ARCH_CHIP_LPC17XX_40XX is not set
+# CONFIG_ARCH_CHIP_LPC214X is not set
+# CONFIG_ARCH_CHIP_LPC2378 is not set
+# CONFIG_ARCH_CHIP_LPC31XX is not set
+# CONFIG_ARCH_CHIP_LPC43XX is not set
+# CONFIG_ARCH_CHIP_LPC54XX is not set
+# CONFIG_ARCH_CHIP_MAX326XX is not set
+# CONFIG_ARCH_CHIP_MOXART is not set
+# CONFIG_ARCH_CHIP_NRF52 is not set
+# CONFIG_ARCH_CHIP_NUC1XX is not set
+# CONFIG_ARCH_CHIP_S32K1XX is not set
+# CONFIG_ARCH_CHIP_SAMA5 is not set
+# CONFIG_ARCH_CHIP_SAMD2X is not set
+# CONFIG_ARCH_CHIP_SAML2X is not set
+# CONFIG_ARCH_CHIP_SAMD5X is not set
+# CONFIG_ARCH_CHIP_SAME5X is not set
+# CONFIG_ARCH_CHIP_SAM34 is not set
+# CONFIG_ARCH_CHIP_SAMV7 is not set
+# CONFIG_ARCH_CHIP_STM32 is not set
+# CONFIG_ARCH_CHIP_STM32F0 is not set
+# CONFIG_ARCH_CHIP_STM32L0 is not set
+# CONFIG_ARCH_CHIP_STM32G0 is not set
+# CONFIG_ARCH_CHIP_STM32F7 is not set
+# CONFIG_ARCH_CHIP_STM32H7 is not set
+CONFIG_ARCH_CHIP_STM32L4=y
+# CONFIG_ARCH_CHIP_STR71X is not set
+# CONFIG_ARCH_CHIP_TMS570 is not set
+# CONFIG_ARCH_CHIP_TIVA is not set
+# CONFIG_ARCH_CHIP_XMC4 is not set
+# CONFIG_ARCH_CHIP_CXD56XX is not set
+# CONFIG_ARCH_ARM7TDMI is not set
+# CONFIG_ARCH_ARM920T is not set
+# CONFIG_ARCH_ARM926EJS is not set
+# CONFIG_ARCH_ARM1136J is not set
+# CONFIG_ARCH_ARM1156T2 is not set
+# CONFIG_ARCH_ARM1176JZ is not set
+# CONFIG_ARCH_CORTEXM0 is not set
+# CONFIG_ARCH_CORTEXM23 is not set
+CONFIG_ARCH_ARMV7M=y
+# CONFIG_ARCH_CORTEXM3 is not set
+# CONFIG_ARCH_CORTEXM33 is not set
+CONFIG_ARCH_CORTEXM4=y
+# CONFIG_ARCH_CORTEXM7 is not set
+# CONFIG_ARCH_ARMV7A is not set
+# CONFIG_ARCH_CORTEXA5 is not set
+# CONFIG_ARCH_CORTEXA7 is not set
+# CONFIG_ARCH_CORTEXA8 is not set
+# CONFIG_ARCH_CORTEXA9 is not set
+# CONFIG_ARCH_ARMV7R is not set
+# CONFIG_ARCH_CORTEXR4 is not set
+# CONFIG_ARCH_CORTEXR5 is not set
+# CONFIG_ARCH_CORTEXR7 is not set
+CONFIG_ARCH_FAMILY="armv7-m"
+CONFIG_ARCH_CHIP="stm32l4"
+# CONFIG_ARCH_HAVE_TRUSTZONE is not set
+CONFIG_ARM_HAVE_MPU_UNIFIED=y
+# CONFIG_ARM_MPU is not set
+CONFIG_ARCH_HAVE_HARDFAULT_DEBUG=y
+# CONFIG_DEBUG_HARDFAULT_ALERT is not set
+CONFIG_ARCH_HAVE_MEMFAULT_DEBUG=y
+# CONFIG_ARM_SEMIHOSTING_SYSLOG is not set
+
+#
+# ARMV7M Configuration Options
+#
+# CONFIG_ARMV7M_HAVE_ICACHE is not set
+# CONFIG_ARMV7M_HAVE_DCACHE is not set
+# CONFIG_ARMV7M_LAZYFPU is not set
+CONFIG_ARMV7M_USEBASEPRI=y
+# CONFIG_ARMV7M_HAVE_ITCM is not set
+# CONFIG_ARMV7M_HAVE_DTCM is not set
+# CONFIG_ARMV7M_TOOLCHAIN_IARL is not set
+# CONFIG_ARMV7M_TOOLCHAIN_BUILDROOT is not set
+# CONFIG_ARMV7M_TOOLCHAIN_CODEREDL is not set
+CONFIG_ARMV7M_TOOLCHAIN_CODESOURCERYL=y
+# CONFIG_ARMV7M_TOOLCHAIN_GNU_EABIL is not set
+# CONFIG_ARMV7M_TOOLCHAIN_CLANGL is not set
+CONFIG_ARMV7M_HAVE_STACKCHECK=y
+# CONFIG_ARMV7M_STACKCHECK is not set
+# CONFIG_ARMV7M_ITMSYSLOG is not set
+# CONFIG_USART2_RS485 is not set
+# CONFIG_USART2_RXDMA is not set
+# CONFIG_USART2_TXDMA is not set
+
+#
+# STM32L4 Configuration Options
+#
+# CONFIG_ARCH_CHIP_STM32L412KB is not set
+# CONFIG_ARCH_CHIP_STM32L432KB is not set
+CONFIG_ARCH_CHIP_STM32L432KC=y
+# CONFIG_ARCH_CHIP_STM32L433CB is not set
+# CONFIG_ARCH_CHIP_STM32L433CC is not set
+# CONFIG_ARCH_CHIP_STM32L433RB is not set
+# CONFIG_ARCH_CHIP_STM32L433RC is not set
+# CONFIG_ARCH_CHIP_STM32L433VC is not set
+# CONFIG_ARCH_CHIP_STM32L442KC is not set
+# CONFIG_ARCH_CHIP_STM32L443CC is not set
+# CONFIG_ARCH_CHIP_STM32L443RC is not set
+# CONFIG_ARCH_CHIP_STM32L443VC is not set
+# CONFIG_ARCH_CHIP_STM32L451CC is not set
+# CONFIG_ARCH_CHIP_STM32L451CE is not set
+# CONFIG_ARCH_CHIP_STM32L451RC is not set
+# CONFIG_ARCH_CHIP_STM32L451RE is not set
+# CONFIG_ARCH_CHIP_STM32L451VC is not set
+# CONFIG_ARCH_CHIP_STM32L451VE is not set
+# CONFIG_ARCH_CHIP_STM32L452CC is not set
+# CONFIG_ARCH_CHIP_STM32L452CE is not set
+# CONFIG_ARCH_CHIP_STM32L452RC is not set
+# CONFIG_ARCH_CHIP_STM32L452RE is not set
+# CONFIG_ARCH_CHIP_STM32L452VC is not set
+# CONFIG_ARCH_CHIP_STM32L452VE is not set
+# CONFIG_ARCH_CHIP_STM32L462CE is not set
+# CONFIG_ARCH_CHIP_STM32L462RE is not set
+# CONFIG_ARCH_CHIP_STM32L462VE is not set
+# CONFIG_ARCH_CHIP_STM32L475RG is not set
+# CONFIG_ARCH_CHIP_STM32L475RE is not set
+# CONFIG_ARCH_CHIP_STM32L475RC is not set
+# CONFIG_ARCH_CHIP_STM32L475VG is not set
+# CONFIG_ARCH_CHIP_STM32L475VE is not set
+# CONFIG_ARCH_CHIP_STM32L475VC is not set
+# CONFIG_ARCH_CHIP_STM32L476RG is not set
+# CONFIG_ARCH_CHIP_STM32L476RE is not set
+# CONFIG_ARCH_CHIP_STM32L486RG is not set
+# CONFIG_ARCH_CHIP_STM32L486JG is not set
+# CONFIG_ARCH_CHIP_STM32L486VG is not set
+# CONFIG_ARCH_CHIP_STM32L486QG is not set
+# CONFIG_ARCH_CHIP_STM32L486ZG is not set
+# CONFIG_ARCH_CHIP_STM32L496RE is not set
+# CONFIG_ARCH_CHIP_STM32L496RG is not set
+# CONFIG_ARCH_CHIP_STM32L496VE is not set
+# CONFIG_ARCH_CHIP_STM32L496VG is not set
+# CONFIG_ARCH_CHIP_STM32L496ZE is not set
+# CONFIG_ARCH_CHIP_STM32L496ZG is not set
+# CONFIG_ARCH_CHIP_STM32L496AG is not set
+# CONFIG_ARCH_CHIP_STM32L4A6RG is not set
+# CONFIG_ARCH_CHIP_STM32L4A6VG is not set
+# CONFIG_ARCH_CHIP_STM32L4A6QG is not set
+# CONFIG_ARCH_CHIP_STM32L4A6ZG is not set
+# CONFIG_ARCH_CHIP_STM32L4A6AG is not set
+# CONFIG_ARCH_CHIP_STM32L4R5ZI is not set
+# CONFIG_ARCH_CHIP_STM32L4R9AI is not set
+# CONFIG_STM32L4_STM32L4X1 is not set
+CONFIG_STM32L4_STM32L4X2=y
+CONFIG_STM32L4_STM32L4X3=y
+# CONFIG_STM32L4_STM32L4X5 is not set
+# CONFIG_STM32L4_STM32L4X6 is not set
+# CONFIG_STM32L4_STM32L4XR is not set
+# CONFIG_STM32L4_STM32L412XX is not set
+# CONFIG_STM32L4_STM32L422XX is not set
+# CONFIG_STM32L4_STM32L431XX is not set
+CONFIG_STM32L4_STM32L432XX=y
+# CONFIG_STM32L4_STM32L433XX is not set
+# CONFIG_STM32L4_STM32L442XX is not set
+# CONFIG_STM32L4_STM32L443XX is not set
+# CONFIG_STM32L4_STM32L451XX is not set
+# CONFIG_STM32L4_STM32L452XX is not set
+# CONFIG_STM32L4_STM32L462XX is not set
+# CONFIG_STM32L4_STM32L471XX is not set
+# CONFIG_STM32L4_STM32L475XX is not set
+# CONFIG_STM32L4_STM32L476XX is not set
+# CONFIG_STM32L4_STM32L486XX is not set
+# CONFIG_STM32L4_STM32L496XX is not set
+# CONFIG_STM32L4_STM32L4A6XX is not set
+# CONFIG_STM32L4_STM32L4R5XX is not set
+# CONFIG_STM32L4_STM32L4S5XX is not set
+# CONFIG_STM32L4_STM32L4R7XX is not set
+# CONFIG_STM32L4_STM32L4S7XX is not set
+# CONFIG_STM32L4_STM32L4R9XX is not set
+# CONFIG_STM32L4_STM32L4S9XX is not set
+CONFIG_STM32L4_FLASH_OVERRIDE_DEFAULT=y
+# CONFIG_STM32L4_FLASH_OVERRIDE_8 is not set
+# CONFIG_STM32L4_FLASH_OVERRIDE_B is not set
+# CONFIG_STM32L4_FLASH_OVERRIDE_C is not set
+# CONFIG_STM32L4_FLASH_OVERRIDE_E is not set
+# CONFIG_STM32L4_FLASH_OVERRIDE_G is not set
+# CONFIG_STM32L4_FLASH_OVERRIDE_I is not set
+# CONFIG_STM32L4_FLASH_CONFIG_B is not set
+CONFIG_STM32L4_FLASH_CONFIG_C=y
+# CONFIG_STM32L4_FLASH_CONFIG_E is not set
+CONFIG_STM32L4_IO_CONFIG_K=y
+# CONFIG_STM32L4_IO_CONFIG_T is not set
+# CONFIG_STM32L4_IO_CONFIG_C is not set
+# CONFIG_STM32L4_IO_CONFIG_R is not set
+# CONFIG_STM32L4_IO_CONFIG_J is not set
+# CONFIG_STM32L4_IO_CONFIG_M is not set
+# CONFIG_STM32L4_IO_CONFIG_V is not set
+# CONFIG_STM32L4_IO_CONFIG_Q is not set
+# CONFIG_STM32L4_IO_CONFIG_Z is not set
+# CONFIG_STM32L4_IO_CONFIG_A is not set
+
+#
+# STM32L4 SRAM2 and SRAM3 Options
+#
+CONFIG_STM32L4_SRAM2_HEAP=y
+CONFIG_STM32L4_SRAM2_INIT=y
+
+#
+# STM32L4 Peripherals
+#
+
+#
+# STM32L4 Peripheral Support
+#
+# CONFIG_STM32L4_HAVE_ADC2 is not set
+# CONFIG_STM32L4_HAVE_ADC3 is not set
+# CONFIG_STM32L4_HAVE_AES is not set
+# CONFIG_STM32L4_HAVE_CAN2 is not set
+CONFIG_STM32L4_HAVE_COMP=y
+CONFIG_STM32L4_HAVE_DAC2=y
+# CONFIG_STM32L4_HAVE_DCMI is not set
+# CONFIG_STM32L4_HAVE_DFSDM1 is not set
+# CONFIG_STM32L4_HAVE_DMA2D is not set
+# CONFIG_STM32L4_HAVE_DMAMUX is not set
+# CONFIG_STM32L4_HAVE_FSMC is not set
+# CONFIG_STM32L4_HAVE_HASH is not set
+CONFIG_STM32L4_HAVE_HSI48=y
+# CONFIG_STM32L4_HAVE_I2C4 is not set
+# CONFIG_STM32L4_HAVE_LCD is not set
+# CONFIG_STM32L4_HAVE_LTDC is not set
+CONFIG_STM32L4_HAVE_LPTIM1=y
+CONFIG_STM32L4_HAVE_LPTIM2=y
+# CONFIG_STM32L4_HAVE_OTGFS is not set
+CONFIG_STM32L4_HAVE_USBFS=y
+CONFIG_STM32L4_HAVE_SAI1=y
+# CONFIG_STM32L4_HAVE_SAI2 is not set
+# CONFIG_STM32L4_RTC is not set
+# CONFIG_STM32L4_HAVE_SDMMC1 is not set
+# CONFIG_STM32L4_HAVE_TIM3 is not set
+# CONFIG_STM32L4_HAVE_TIM4 is not set
+# CONFIG_STM32L4_HAVE_TIM5 is not set
+CONFIG_STM32L4_HAVE_TIM7=y
+# CONFIG_STM32L4_HAVE_TIM8 is not set
+# CONFIG_STM32L4_HAVE_TIM17 is not set
+CONFIG_STM32L4_HAVE_USART1=y
+CONFIG_STM32L4_HAVE_USART2=y
+# CONFIG_STM32L4_HAVE_USART3 is not set
+# CONFIG_STM32L4_HAVE_UART4 is not set
+# CONFIG_STM32L4_HAVE_UART5 is not set
+# CONFIG_STM32L4_HAVE_QSPI is not set
+# CONFIG_STM32L4_ADC is not set
+# CONFIG_STM32L4_CAN is not set
+# CONFIG_STM32L4_DAC is not set
+# CONFIG_STM32L4_DFSDM is not set
+CONFIG_STM32L4_DMA=y
+# CONFIG_STM32L4_I2C is not set
+# CONFIG_STM32L4_SAI is not set
+# CONFIG_STM32L4_SPI is not set
+CONFIG_STM32L4_USART=y
+# CONFIG_STM32L4_LPTIM is not set
+# CONFIG_STM32L4_SDMMC is not set
+
+#
+# AHB1 Peripherals
+#
+CONFIG_STM32L4_DMA1=y
+CONFIG_STM32L4_DMA2=y
+# CONFIG_STM32L4_CRC is not set
+# CONFIG_STM32L4_TSC is not set
+
+#
+# AHB2 Peripherals
+#
+# CONFIG_STM32L4_ADC1 is not set
+# CONFIG_STM32L4_RNG is not set
+
+#
+# AHB3 Peripherals
+#
+
+#
+# APB1 Peripherals
+#
+# CONFIG_STM32L4_PWR is not set
+# CONFIG_STM32L4_TIM2 is not set
+CONFIG_STM32L4_TIM6=y
+# CONFIG_STM32L4_TIM7 is not set
+# CONFIG_STM32L4_SPI3 is not set
+CONFIG_STM32L4_USART2=y
+# CONFIG_STM32L4_I2C1 is not set
+# CONFIG_STM32L4_I2C3 is not set
+# CONFIG_STM32L4_CAN1 is not set
+# CONFIG_STM32L4_DAC1 is not set
+# CONFIG_STM32L4_DAC2 is not set
+# CONFIG_STM32L4_OPAMP is not set
+# CONFIG_STM32L4_LPTIM1 is not set
+# CONFIG_STM32L4_LPUART1 is not set
+# CONFIG_STM32L4_SWPMI is not set
+# CONFIG_STM32L4_LPTIM2 is not set
+# CONFIG_STM32L4_USBFS is not set
+
+#
+# APB2 Peripherals
+#
+# CONFIG_STM32L4_SYSCFG is not set
+CONFIG_STM32L4_TIM1=y
+# CONFIG_STM32L4_SPI1 is not set
+# CONFIG_STM32L4_USART1 is not set
+# CONFIG_STM32L4_TIM15 is not set
+# CONFIG_STM32L4_TIM16 is not set
+# CONFIG_STM32L4_COMP is not set
+# CONFIG_STM32L4_SAI1 is not set
+
+#
+# Other Peripherals
+#
+# CONFIG_STM32L4_BKPSRAM is not set
+# CONFIG_STM32L4_IWDG is not set
+# CONFIG_STM32L4_WWDG is not set
+# CONFIG_STM32L4_SAI1PLL is not set
+CONFIG_STM32L4_FLASH_PREFETCH=y
+CONFIG_STM32L4_DISABLE_IDLE_SLEEP_DURING_DEBUG=y
+# CONFIG_ARCH_BOARD_STM32L4_CUSTOM_CLOCKCONFIG is not set
+CONFIG_STM32L4_HAVE_RTC_SUBSECONDS=y
+
+#
+# Timer Configuration
+#
+# CONFIG_STM32L4_ONESHOT is not set
+# CONFIG_STM32L4_FREERUN is not set
+CONFIG_STM32L4_PWM_LL_OPS=y
+CONFIG_STM32L4_TIM1_PWM=y
+CONFIG_STM32L4_TIM1_MODE=0
+CONFIG_STM32L4_TIM1_LOCK=0
+CONFIG_STM32L4_TIM1_TDTS=0
+CONFIG_STM32L4_TIM1_DEADTIME=0
+CONFIG_STM32L4_TIM1_CH1OUT=y
+CONFIG_STM32L4_TIM1_CH1NOUT=y
+CONFIG_STM32L4_TIM1_CHANNEL=1
+CONFIG_STM32L4_TIM1_CHMODE=6
+# CONFIG_STM32L4_PWM_MULTICHAN is not set
+
+#
+# STM32L4 TIMx Outputs Configuration
+#
+CONFIG_STM32L4_TIM1_CH1POL=0
+CONFIG_STM32L4_TIM1_CH1IDLE=0
+CONFIG_STM32L4_TIM1_CH1NPOL=0
+CONFIG_STM32L4_TIM1_CH1NIDLE=0
+CONFIG_STM32L4_SERIALDRIVER=y
+
+#
+# U[S]ART Configuration
+#
+CONFIG_STM32L4_USART2_SERIALDRIVER=y
+# CONFIG_STM32L4_USART2_1WIREDRIVER is not set
+
+#
+# Serial Driver Configuration
+#
+# CONFIG_STM32L4_SERIAL_DISABLE_REORDERING is not set
+# CONFIG_STM32L4_FLOWCONTROL_BROKEN is not set
+# CONFIG_STM32L4_USART_BREAKS is not set
+# CONFIG_STM32L4_USART_SINGLEWIRE is not set
+# CONFIG_STM32L4_USART_INVERT is not set
+# CONFIG_STM32L4_USART_SWAP is not set
+# CONFIG_ARCH_TOOLCHAIN_IAR is not set
+CONFIG_ARCH_TOOLCHAIN_GNU=y
+# CONFIG_ARCH_GNU_NO_WEAKFUNCTIONS is not set
+
+#
+# Architecture Options
+#
+# CONFIG_ARCH_NOINTC is not set
+# CONFIG_ARCH_VECNOTIRQ is not set
+CONFIG_ARCH_HAVE_IRQTRIGGER=y
+CONFIG_ARCH_DMA=y
+CONFIG_ARCH_HAVE_IRQPRIO=y
+# CONFIG_ARCH_ICACHE is not set
+# CONFIG_ARCH_DCACHE is not set
+# CONFIG_ARCH_L2CACHE is not set
+# CONFIG_ARCH_HAVE_ADDRENV is not set
+# CONFIG_ARCH_NEED_ADDRENV_MAPPING is not set
+# CONFIG_ARCH_HAVE_MULTICPU is not set
+CONFIG_ARCH_HAVE_VFORK=y
+CONFIG_ARCH_HAVE_FPU=y
+# CONFIG_ARCH_HAVE_DPFPU is not set
+CONFIG_ARCH_HAVE_LAZYFPU=y
+# CONFIG_ARCH_HAVE_MMU is not set
+CONFIG_ARCH_HAVE_MPU=y
+# CONFIG_ARCH_NAND_HWECC is not set
+# CONFIG_ARCH_HAVE_EXTCLK is not set
+# CONFIG_ARCH_HAVE_POWEROFF is not set
+CONFIG_ARCH_HAVE_PROGMEM=y
+CONFIG_ARCH_HAVE_RESET=y
+CONFIG_ARCH_HAVE_TESTSET=y
+CONFIG_ARCH_HAVE_FETCHADD=y
+CONFIG_ARCH_HAVE_RTC_SUBSECONDS=y
+# CONFIG_ARCH_HAVE_GARBAGE is not set
+# CONFIG_ARCH_GLOBAL_IRQDISABLE is not set
+CONFIG_ARCH_FPU=y
+# CONFIG_ARCH_USE_MPU is not set
+CONFIG_ARCH_IRQPRIO=y
+CONFIG_ARCH_STACKDUMP=y
+# CONFIG_ENDIAN_BIG is not set
+# CONFIG_ARCH_IDLE_CUSTOM is not set
+# CONFIG_ARCH_HAVE_RAMFUNCS is not set
+CONFIG_ARCH_HAVE_RAMVECTORS=y
+CONFIG_ARCH_RAMVECTORS=y
+# CONFIG_ARCH_MINIMAL_VECTORTABLE is not set
+
+#
+# Board Settings
+#
+CONFIG_BOARD_LOOPSPERMSEC=8499
+
+#
+# Interrupt options
+#
+CONFIG_ARCH_HAVE_INTERRUPTSTACK=y
+CONFIG_ARCH_INTERRUPTSTACK=2048
+CONFIG_ARCH_HAVE_HIPRI_INTERRUPT=y
+CONFIG_ARCH_HIPRI_INTERRUPT=y
+
+#
+# Boot options
+#
+# CONFIG_BOOT_RUNFROMEXTSRAM is not set
+CONFIG_BOOT_RUNFROMFLASH=y
+# CONFIG_BOOT_RUNFROMISRAM is not set
+# CONFIG_BOOT_RUNFROMSDRAM is not set
+# CONFIG_BOOT_COPYTORAM is not set
+
+#
+# Boot Memory Configuration
+#
+CONFIG_RAM_START=0x20000000
+CONFIG_RAM_SIZE=65536
+# CONFIG_ARCH_HAVE_SDRAM is not set
+
+#
+# Board Selection
+#
+CONFIG_ARCH_BOARD_NUCLEO_L432KC=y
+# CONFIG_ARCH_BOARD_CUSTOM is not set
+CONFIG_ARCH_BOARD="nucleo-l432kc"
+
+#
+# Common Board Options
+#
+CONFIG_ARCH_HAVE_LEDS=y
+CONFIG_ARCH_LEDS=y
+CONFIG_ARCH_HAVE_BUTTONS=y
+# CONFIG_ARCH_BUTTONS is not set
+CONFIG_ARCH_HAVE_IRQBUTTONS=y
+
+#
+# Board-Specific Options
+#
+
+#
+# U[S]ART Pin Layouts
+#
+
+#
+# USART1 is disabled. (Enable it under: System Type -> STM32L4 Peripheral Support)
+#
+# CONFIG_ARCH_BOARD_USART2_RX_PA3 is not set
+CONFIG_ARCH_BOARD_USART2_RX_PA15=y
+CONFIG_ARCH_BOARD_USART2_TX_PA2=y
+
+#
+# LPUART1 is disabled. (Enable it under: System Type -> STM32L4 Peripheral Support)
+#
+CONFIG_NUCLEOL432KC_SPWM=y
+CONFIG_NUCLEOL432KC_SPWM_USE_TIM1=y
+CONFIG_NUCLEOL432KC_SPWM_PWM_FREQ=200000
+CONFIG_NUCLEOL432KC_SPWM_SAMPLES=100
+CONFIG_NUCLEOL432KC_SPWM_FREQ=60
+CONFIG_NUCLEOL432KC_SPWM_PHASE_NUM=1
+# CONFIG_BOARD_CRASHDUMP is not set
+CONFIG_LIB_BOARDCTL=y
+# CONFIG_BOARDCTL_FINALINIT is not set
+# CONFIG_BOARDCTL_RESET is not set
+# CONFIG_BOARDCTL_UNIQUEID is not set
+CONFIG_BOARDCTL_MKRD=y
+# CONFIG_BOARDCTL_ROMDISK is not set
+# CONFIG_BOARDCTL_APP_SYMTAB is not set
+# CONFIG_BOARDCTL_TESTSET is not set
+# CONFIG_BOARDCTL_IOCTL is not set
+
+#
+# RTOS Features
+#
+CONFIG_DISABLE_OS_API=y
+# CONFIG_DISABLE_POSIX_TIMERS is not set
+# CONFIG_DISABLE_PTHREAD is not set
+# CONFIG_DISABLE_MQUEUE is not set
+# CONFIG_DISABLE_ENVIRON is not set
+
+#
+# Clocks and Timers
+#
+CONFIG_ARCH_HAVE_TICKLESS=y
+# CONFIG_SCHED_TICKLESS is not set
+CONFIG_USEC_PER_TICK=10000
+# CONFIG_SYSTEMTICK_HOOK is not set
+# CONFIG_SYSTEM_TIME64 is not set
+# CONFIG_CLOCK_MONOTONIC is not set
+# CONFIG_ARCH_HAVE_TIMEKEEPING is not set
+# CONFIG_JULIAN_TIME is not set
+CONFIG_START_YEAR=2018
+CONFIG_START_MONTH=1
+CONFIG_START_DAY=1
+CONFIG_MAX_WDOGPARMS=2
+CONFIG_PREALLOC_WDOGS=8
+CONFIG_WDOG_INTRESERVE=1
+CONFIG_PREALLOC_TIMERS=4
+
+#
+# Tasks and Scheduling
+#
+# CONFIG_SPINLOCK is not set
+# CONFIG_IRQCHAIN is not set
+# CONFIG_IRQCOUNT is not set
+# CONFIG_INIT_NONE is not set
+CONFIG_INIT_ENTRYPOINT=y
+# CONFIG_INIT_FILEPATH is not set
+CONFIG_USER_ENTRYPOINT="spwm_main"
+CONFIG_USERMAIN_PRIORITY=100
+CONFIG_RR_INTERVAL=200
+# CONFIG_SCHED_SPORADIC is not set
+CONFIG_TASK_NAME_SIZE=0
+CONFIG_MAX_TASKS=16
+# CONFIG_SCHED_HAVE_PARENT is not set
+CONFIG_SCHED_WAITPID=y
+# CONFIG_SCHED_USER_IDENTITY is not set
+
+#
+# Pthread Options
+#
+CONFIG_NPTHREAD_KEYS=4
+# CONFIG_PTHREAD_MUTEX_TYPES is not set
+CONFIG_PTHREAD_MUTEX_ROBUST=y
+# CONFIG_PTHREAD_MUTEX_UNSAFE is not set
+# CONFIG_PTHREAD_MUTEX_BOTH is not set
+# CONFIG_PTHREAD_CLEANUP is not set
+# CONFIG_CANCELLATION_POINTS is not set
+
+#
+# Performance Monitoring
+#
+# CONFIG_SCHED_SUSPENDSCHEDULER is not set
+# CONFIG_SCHED_RESUMESCHEDULER is not set
+# CONFIG_SCHED_CPULOAD is not set
+# CONFIG_SCHED_INSTRUMENTATION is not set
+
+#
+# Files and I/O
+#
+CONFIG_DEV_CONSOLE=y
+# CONFIG_FDCLONE_DISABLE is not set
+# CONFIG_FDCLONE_STDIO is not set
+CONFIG_SDCLONE_DISABLE=y
+CONFIG_NFILE_DESCRIPTORS=8
+CONFIG_NFILE_STREAMS=8
+CONFIG_NAME_MAX=32
+# CONFIG_PRIORITY_INHERITANCE is not set
+
+#
+# RTOS hooks
+#
+# CONFIG_BOARD_EARLY_INITIALIZE is not set
+# CONFIG_BOARD_LATE_INITIALIZE is not set
+# CONFIG_SCHED_STARTHOOK is not set
+# CONFIG_SCHED_ATEXIT is not set
+# CONFIG_SCHED_ONEXIT is not set
+
+#
+# Signal Configuration
+#
+# CONFIG_SIG_DEFAULT is not set
+
+#
+# Signal Numbers
+#
+
+#
+# Standard Signal Numbers
+#
+CONFIG_SIG_SIGUSR1=1
+CONFIG_SIG_SIGUSR2=2
+CONFIG_SIG_SIGALRM=3
+CONFIG_SIG_PIPE=11
+
+#
+# Non-standard Signal Numbers
+#
+CONFIG_SIG_SIGCONDTIMEDOUT=16
+
+#
+# POSIX Message Queue Options
+#
+CONFIG_PREALLOC_MQ_MSGS=4
+CONFIG_MQ_MAXMSGSIZE=32
+# CONFIG_MODULE is not set
+
+#
+# Work queue support
+#
+# CONFIG_SCHED_WORKQUEUE is not set
+# CONFIG_SCHED_HPWORK is not set
+# CONFIG_SCHED_LPWORK is not set
+
+#
+# Stack and heap information
+#
+CONFIG_IDLETHREAD_STACKSIZE=1024
+CONFIG_USERMAIN_STACKSIZE=2048
+CONFIG_PTHREAD_STACK_MIN=256
+CONFIG_PTHREAD_STACK_DEFAULT=2048
+# CONFIG_LIB_SYSCALL is not set
+
+#
+# Device Drivers
+#
+# CONFIG_DEV_SIMPLE_ADDRENV is not set
+CONFIG_DEV_NULL=y
+# CONFIG_DEV_ZERO is not set
+# CONFIG_DEV_URANDOM is not set
+# CONFIG_DEV_LOOP is not set
+CONFIG_DRVR_MKRD=y
+
+#
+# Buffering
+#
+# CONFIG_DRVR_WRITEBUFFER is not set
+# CONFIG_DRVR_READAHEAD is not set
+# CONFIG_RAMDISK is not set
+# CONFIG_CAN is not set
+CONFIG_ARCH_HAVE_PWM_PULSECOUNT=y
+# CONFIG_ARCH_HAVE_PWM_MULTICHAN is not set
+CONFIG_ARCH_HAVE_I2CRESET=y
+# CONFIG_I2C is not set
+# CONFIG_ARCH_HAVE_SPI_CRCGENERATION is not set
+# CONFIG_ARCH_HAVE_SPI_CS_CONTROL is not set
+CONFIG_ARCH_HAVE_SPI_BITORDER=y
+CONFIG_SPI=y
+# CONFIG_SPI_SLAVE is not set
+CONFIG_SPI_EXCHANGE=y
+# CONFIG_SPI_CMDDATA is not set
+# CONFIG_SPI_CALLBACK is not set
+# CONFIG_SPI_HWFEATURES is not set
+# CONFIG_SPI_BITORDER is not set
+# CONFIG_SPI_CS_DELAY_CONTROL is not set
+# CONFIG_SPI_TRIGGER is not set
+# CONFIG_SPI_DRIVER is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_I2S is not set
+
+#
+# Timer Driver Support
+#
+CONFIG_PWM=y
+# CONFIG_PWM_PULSECOUNT is not set
+# CONFIG_TIMER is not set
+# CONFIG_ONESHOT is not set
+# CONFIG_RTC is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_ANALOG is not set
+# CONFIG_DRIVERS_AUDIO is not set
+# CONFIG_FB_CMAP is not set
+# CONFIG_FB_TRANSPARENCY is not set
+# CONFIG_DRIVERS_VIDEO is not set
+# CONFIG_BCH is not set
+# CONFIG_INPUT is not set
+
+#
+# IO Expander/GPIO Support
+#
+# CONFIG_IOEXPANDER is not set
+# CONFIG_DEV_GPIO is not set
+
+#
+# LCD Driver Support
+#
+# CONFIG_LCD is not set
+
+#
+# Character/Segment LCD Devices
+#
+# CONFIG_SLCD is not set
+
+#
+# Other LCD-related Devices
+#
+# CONFIG_LCD_OTHER is not set
+
+#
+# LED Support
+#
+# CONFIG_USERLED is not set
+# CONFIG_LEDS_APA102 is not set
+# CONFIG_LEDS_MAX7219 is not set
+# CONFIG_RGBLED is not set
+# CONFIG_PCA9635PW is not set
+# CONFIG_NCP5623C is not set
+# CONFIG_ARCH_HAVE_SDIO is not set
+# CONFIG_ARCH_HAVE_SDIOWAIT_WRCOMPLETE is not set
+# CONFIG_ARCH_HAVE_SDIO_PREFLIGHT is not set
+# CONFIG_ARCH_HAVE_SDIO_DELAYED_INVLDT is not set
+# CONFIG_MMCSD is not set
+# CONFIG_MODEM is not set
+# CONFIG_MTD is not set
+# CONFIG_EEPROM is not set
+# CONFIG_PIPES is not set
+# CONFIG_PM is not set
+# CONFIG_DRIVERS_POWERLED is not set
+# CONFIG_DRIVERS_SMPS is not set
+# CONFIG_DRIVERS_MOTOR is not set
+# CONFIG_POWER is not set
+# CONFIG_SENSORS is not set
+CONFIG_SERIAL=y
+# CONFIG_DEV_LOWCONSOLE is not set
+# CONFIG_SERIAL_REMOVABLE is not set
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_16550_UART is not set
+# CONFIG_OTHER_UART_SERIALDRIVER is not set
+CONFIG_MCU_SERIAL=y
+CONFIG_STANDARD_SERIAL=y
+CONFIG_SERIAL_NPOLLWAITERS=2
+# CONFIG_SERIAL_IFLOWCONTROL is not set
+# CONFIG_SERIAL_RS485CONTROL is not set
+# CONFIG_SERIAL_OFLOWCONTROL is not set
+# CONFIG_SERIAL_TXDMA is not set
+# CONFIG_SERIAL_RXDMA is not set
+CONFIG_ARCH_HAVE_SERIAL_TERMIOS=y
+# CONFIG_SERIAL_TERMIOS is not set
+CONFIG_USART2_SERIAL_CONSOLE=y
+# CONFIG_OTHER_SERIAL_CONSOLE is not set
+# CONFIG_NO_SERIAL_CONSOLE is not set
+# CONFIG_UART_SERIALDRIVER is not set
+# CONFIG_UART0_SERIALDRIVER is not set
+# CONFIG_UART1_SERIALDRIVER is not set
+# CONFIG_UART2_SERIALDRIVER is not set
+# CONFIG_UART3_SERIALDRIVER is not set
+# CONFIG_UART4_SERIALDRIVER is not set
+# CONFIG_UART5_SERIALDRIVER is not set
+# CONFIG_UART6_SERIALDRIVER is not set
+# CONFIG_UART7_SERIALDRIVER is not set
+# CONFIG_UART8_SERIALDRIVER is not set
+# CONFIG_LPUART_SERIALDRIVER is not set
+# CONFIG_LPUART0_SERIALDRIVER is not set
+# CONFIG_LPUART1_SERIALDRIVER is not set
+# CONFIG_LPUART2_SERIALDRIVER is not set
+# CONFIG_LPUART3_SERIALDRIVER is not set
+# CONFIG_LPUART4_SERIALDRIVER is not set
+# CONFIG_LPUART5_SERIALDRIVER is not set
+# CONFIG_LPUART6_SERIALDRIVER is not set
+# CONFIG_LPUART7_SERIALDRIVER is not set
+# CONFIG_LPUART8_SERIALDRIVER is not set
+# CONFIG_USART0_SERIALDRIVER is not set
+# CONFIG_USART1_SERIALDRIVER is not set
+CONFIG_USART2_SERIALDRIVER=y
+# CONFIG_USART3_SERIALDRIVER is not set
+# CONFIG_USART4_SERIALDRIVER is not set
+# CONFIG_USART5_SERIALDRIVER is not set
+# CONFIG_USART6_SERIALDRIVER is not set
+# CONFIG_USART7_SERIALDRIVER is not set
+# CONFIG_USART8_SERIALDRIVER is not set
+# CONFIG_USART9_SERIALDRIVER is not set
+
+#
+# USART2 Configuration
+#
+CONFIG_USART2_RXBUFSIZE=256
+CONFIG_USART2_TXBUFSIZE=256
+CONFIG_USART2_BAUD=115200
+CONFIG_USART2_BITS=8
+CONFIG_USART2_PARITY=0
+CONFIG_USART2_2STOP=0
+# CONFIG_USART2_IFLOWCONTROL is not set
+# CONFIG_USART2_OFLOWCONTROL is not set
+# CONFIG_SCI0_SERIALDRIVER is not set
+# CONFIG_SCI1_SERIALDRIVER is not set
+# CONFIG_SCI2_SERIALDRIVER is not set
+# CONFIG_SCI3_SERIALDRIVER is not set
+# CONFIG_SCI4_SERIALDRIVER is not set
+# CONFIG_SCI5_SERIALDRIVER is not set
+# CONFIG_SCI6_SERIALDRIVER is not set
+# CONFIG_SCI7_SERIALDRIVER is not set
+# CONFIG_SCI8_SERIALDRIVER is not set
+# CONFIG_SCI9_SERIALDRIVER is not set
+# CONFIG_SCI10_SERIALDRIVER is not set
+# CONFIG_SCI11_SERIALDRIVER is not set
+# CONFIG_SCI12_SERIALDRIVER is not set
+# CONFIG_PSEUDOTERM is not set
+# CONFIG_USBDEV is not set
+# CONFIG_USBHOST is not set
+# CONFIG_USBMISC is not set
+# CONFIG_HAVE_USBTRACE is not set
+# CONFIG_DRIVERS_WIRELESS is not set
+# CONFIG_DRIVERS_CONTACTLESS is not set
+# CONFIG_1WIRE is not set
+
+#
+# System Logging
+#
+# CONFIG_ARCH_SYSLOG is not set
+CONFIG_SYSLOG_WRITE=y
+# CONFIG_RAMLOG is not set
+# CONFIG_SYSLOG_BUFFER is not set
+# CONFIG_SYSLOG_INTBUFFER is not set
+# CONFIG_SYSLOG_TIMESTAMP is not set
+# CONFIG_SYSLOG_PREFIX is not set
+CONFIG_SYSLOG_SERIAL_CONSOLE=y
+# CONFIG_SYSLOG_CHAR is not set
+CONFIG_SYSLOG_CONSOLE=y
+# CONFIG_SYSLOG_NONE is not set
+# CONFIG_SYSLOG_FILE is not set
+# CONFIG_SYSLOG_CHARDEV is not set
+# CONFIG_SPECIFIC_DRIVERS is not set
+# CONFIG_DRIVERS_RF is not set
+
+#
+# Networking Support
+#
+# CONFIG_ARCH_HAVE_NET is not set
+# CONFIG_ARCH_HAVE_PHY is not set
+# CONFIG_NET_WRITE_BUFFERS is not set
+# CONFIG_NET_READAHEAD is not set
+# CONFIG_NET_MCASTGROUP is not set
+# CONFIG_NET is not set
+
+#
+# Crypto API
+#
+# CONFIG_CRYPTO is not set
+
+#
+# File Systems
+#
+
+#
+# File system configuration
+#
+# CONFIG_DISABLE_MOUNTPOINT is not set
+# CONFIG_FS_AUTOMOUNTER is not set
+# CONFIG_DISABLE_PSEUDOFS_OPERATIONS is not set
+# CONFIG_PSEUDOFS_SOFTLINKS is not set
+CONFIG_FS_READABLE=y
+CONFIG_FS_WRITABLE=y
+# CONFIG_FS_NAMED_SEMAPHORES is not set
+CONFIG_FS_MQUEUE_MPATH="/var/mqueue"
+# CONFIG_FS_RAMMAP is not set
+
+#
+# Partition Table
+#
+# CONFIG_PTABLE_PARTITION is not set
+# CONFIG_FS_FAT is not set
+# CONFIG_FS_NXFFS is not set
+# CONFIG_FS_ROMFS is not set
+# CONFIG_FS_CROMFS is not set
+# CONFIG_FS_TMPFS is not set
+# CONFIG_FS_SMARTFS is not set
+# CONFIG_FS_BINFS is not set
+# CONFIG_FS_PROCFS is not set
+# CONFIG_FS_SPIFFS is not set
+# CONFIG_FS_LITTLEFS is not set
+# CONFIG_FS_UNIONFS is not set
+# CONFIG_FS_HOSTFS is not set
+
+#
+# Graphics Support
+#
+# CONFIG_NX is not set
+# CONFIG_NXFONTS is not set
+
+#
+# Font Cache Pixel Depths
+#
+# CONFIG_NXFONTS_DISABLE_1BPP is not set
+# CONFIG_NXFONTS_DISABLE_2BPP is not set
+# CONFIG_NXFONTS_DISABLE_4BPP is not set
+# CONFIG_NXFONTS_DISABLE_8BPP is not set
+# CONFIG_NXFONTS_DISABLE_16BPP is not set
+# CONFIG_NXFONTS_DISABLE_24BPP is not set
+# CONFIG_NXFONTS_DISABLE_32BPP is not set
+CONFIG_NXFONTS_PACKEDMSFIRST=y
+# CONFIG_NXGLIB is not set
+
+#
+# Memory Management
+#
+# CONFIG_MM_SMALL is not set
+CONFIG_MM_REGIONS=2
+# CONFIG_ARCH_HAVE_HEAP2 is not set
+# CONFIG_GRAN is not set
+# CONFIG_MM_FILL_ALLOCATIONS is not set
+
+#
+# Common I/O Buffer Support
+#
+# CONFIG_MM_IOB is not set
+
+#
+# Audio Support
+#
+# CONFIG_AUDIO is not set
+
+#
+# Video Support
+#
+
+#
+# Video subsystem
+#
+# CONFIG_VIDEO is not set
+
+#
+# Wireless Support
+#
+# CONFIG_WIRELESS is not set
+
+#
+# Binary Loader
+#
+# CONFIG_BINFMT_DISABLE is not set
+# CONFIG_BINFMT_LOADABLE is not set
+# CONFIG_PIC is not set
+# CONFIG_NXFLAT is not set
+# CONFIG_ELF is not set
+# CONFIG_SYMTAB_ORDEREDBYNAME is not set
+
+#
+# Library Routines
+#
+
+#
+# Standard C Library Options
+#
+
+#
+# Standard C I/O
+#
+# CONFIG_STDIO_DISABLE_BUFFERING is not set
+CONFIG_STDIO_BUFFER_SIZE=64
+CONFIG_STDIO_LINEBUFFER=y
+CONFIG_NUNGET_CHARS=2
+# CONFIG_LIBC_PRINT_LEGACY is not set
+# CONFIG_LIBC_FLOATINGPOINT is not set
+CONFIG_LIBC_LONG_LONG=y
+# CONFIG_LIBC_NUMBERED_ARGS is not set
+# CONFIG_LIBC_SCANSET is not set
+# CONFIG_EOL_IS_CR is not set
+# CONFIG_EOL_IS_LF is not set
+# CONFIG_EOL_IS_BOTH_CRLF is not set
+CONFIG_EOL_IS_EITHER_CRLF=y
+# CONFIG_MEMCPY_VIK is not set
+CONFIG_LIBM=y
+
+#
+# Architecture-Specific Support
+#
+CONFIG_ARCH_LOWPUTC=y
+# CONFIG_ARCH_ROMGETC is not set
+# CONFIG_LIBC_ARCH_MEMCPY is not set
+# CONFIG_LIBC_ARCH_MEMCMP is not set
+# CONFIG_LIBC_ARCH_MEMMOVE is not set
+# CONFIG_LIBC_ARCH_MEMSET is not set
+# CONFIG_LIBC_ARCH_STRCHR is not set
+# CONFIG_LIBC_ARCH_STRCMP is not set
+# CONFIG_LIBC_ARCH_STRCPY is not set
+# CONFIG_LIBC_ARCH_STRNCPY is not set
+# CONFIG_LIBC_ARCH_STRLEN is not set
+# CONFIG_LIBC_ARCH_STRNLEN is not set
+# CONFIG_LIBC_ARCH_ELF is not set
+# CONFIG_ARMV7M_MEMCPY is not set
+# CONFIG_ARMV7M_LIBM is not set
+# CONFIG_MACHINE_OPTS_ARMV7M is not set
+# CONFIG_LIBM_ARCH_FABSF is not set
+# CONFIG_LIBM_ARCH_SQRTF is not set
+
+#
+# stdlib Options
+#
+CONFIG_LIB_RAND_ORDER=1
+CONFIG_LIB_HOMEDIR="/"
+CONFIG_LIBC_TMPDIR="/tmp"
+CONFIG_LIBC_MAX_TMPFILE=32
+
+#
+# Program Execution Options
+#
+# CONFIG_LIBC_EXECFUNCS is not set
+CONFIG_POSIX_SPAWN_PROXY_STACKSIZE=1024
+CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE=2048
+CONFIG_LIB_HOSTNAME=""
+
+#
+# errno Decode Support
+#
+# CONFIG_LIBC_STRERROR is not set
+# CONFIG_LIBC_PERROR_STDOUT is not set
+
+#
+# memcpy/memset Options
+#
+# CONFIG_MEMSET_OPTSPEED is not set
+
+#
+# pthread support
+#
+# CONFIG_LIBC_DLFCN is not set
+# CONFIG_LIBC_MODLIB is not set
+# CONFIG_LIBC_GROUP_FILE is not set
+# CONFIG_LIBC_PASSWD_FILE is not set
+# CONFIG_LIBC_WCHAR is not set
+# CONFIG_LIBC_LOCALE is not set
+# CONFIG_LIBC_LZF is not set
+
+#
+# Time/Time Zone Support
+#
+# CONFIG_LIBC_LOCALTIME is not set
+# CONFIG_TIME_EXTENDED is not set
+CONFIG_ARCH_HAVE_TLS=y
+
+#
+# Thread Local Storage (TLS)
+#
+# CONFIG_TLS is not set
+
+#
+# Network-Related Options
+#
+# CONFIG_LIBC_IPv4_ADDRCONV is not set
+# CONFIG_LIBC_IPv6_ADDRCONV is not set
+# CONFIG_LIBC_NETDB is not set
+
+#
+# NETDB Support
+#
+# CONFIG_LIBC_GAISTRERROR is not set
+# CONFIG_NETDB_HOSTFILE is not set
+# CONFIG_LIBC_IOCTL_VARIADIC is not set
+CONFIG_LIB_SENDFILE_BUFSIZE=512
+
+#
+# Non-standard Library Support
+#
+# CONFIG_LIB_CRC64_FAST is not set
+# CONFIG_LIB_KBDCODEC is not set
+# CONFIG_LIB_SLCDCODEC is not set
+# CONFIG_LIB_ENVPATH is not set
+# CONFIG_LIB_HEX2BIN is not set
+CONFIG_BUILTIN=y
+
+#
+# Basic CXX Support
+#
+# CONFIG_C99_BOOL8 is not set
+CONFIG_HAVE_CXX=y
+# CONFIG_CXX_NEWLONG is not set
+
+#
+# LLVM C++ Library (libcxx)
+#
+# CONFIG_LIBCXX is not set
+
+#
+# uClibc++ Standard C++ Library
+#
+# CONFIG_UCLIBCXX is not set
+# CONFIG_LIBDSP is not set
+
+#
+# Open Asymmetric Multi Processing
+#
+# CONFIG_OPENAMP is not set
+
+#
+# Application Configuration
+#
+
+#
+# Built-In Applications
+#
+CONFIG_BUILTIN_PROXY_STACKSIZE=1024
+
+#
+# CAN Utilities
+#
+
+#
+# Examples
+#
+# CONFIG_EXAMPLES_ABNTCODI is not set
+# CONFIG_EXAMPLES_ADXL372_TEST is not set
+# CONFIG_EXAMPLES_APA102 is not set
+# CONFIG_EXAMPLES_AUDIO_SOUND is not set
+# CONFIG_EXAMPLES_BATTERY is not set
+# CONFIG_EXAMPLES_SIXAXIS is not set
+# CONFIG_EXAMPLES_BUTTONS is not set
+# CONFIG_EXAMPLES_CALIB_UDELAY is not set
+# CONFIG_EXAMPLES_CCTYPE is not set
+# CONFIG_EXAMPLES_CHARGER is not set
+# CONFIG_EXAMPLES_CHAT is not set
+# CONFIG_EXAMPLES_CHRONO is not set
+# CONFIG_EXAMPLES_CONFIGDATA is not set
+# CONFIG_EXAMPLES_DHCPD is not set
+# CONFIG_EXAMPLES_DHTXX is not set
+# CONFIG_EXAMPLES_DSPTEST is not set
+# CONFIG_EXAMPLES_FTPC is not set
+# CONFIG_EXAMPLES_FTPD is not set
+# CONFIG_EXAMPLES_GPS is not set
+# CONFIG_EXAMPLES_HELLO is not set
+# CONFIG_EXAMPLES_HELLOXX is not set
+# CONFIG_EXAMPLES_HIDKBD is not set
+# CONFIG_EXAMPLES_IGMP is not set
+# CONFIG_EXAMPLES_INA219 is not set
+# CONFIG_EXAMPLES_INA226 is not set
+# CONFIG_EXAMPLES_LSM330SPI_TEST is not set
+# CONFIG_EXAMPLES_LVGLDEMO is not set
+# CONFIG_EXAMPLES_MAX31855 is not set
+# CONFIG_EXAMPLES_MEDIA is not set
+# CONFIG_EXAMPLES_MLX90614 is not set
+# CONFIG_EXAMPLES_MM is not set
+# CONFIG_EXAMPLES_MODBUS is not set
+# CONFIG_EXAMPLES_MODBUSMASTER is not set
+# CONFIG_EXAMPLES_MOUNT is not set
+# CONFIG_EXAMPLES_NULL is not set
+# CONFIG_EXAMPLES_NXDEMO is not set
+# CONFIG_EXAMPLES_OBD2 is not set
+# CONFIG_EXAMPLES_PCA9635 is not set
+# CONFIG_EXAMPLES_PDCURSES is not set
+# CONFIG_EXAMPLES_POSIXSPAWN is not set
+# CONFIG_EXAMPLES_POWERLED is not set
+# CONFIG_EXAMPLES_POWERMONITOR is not set
+# CONFIG_EXAMPLES_PPPD is not set
+# CONFIG_EXAMPLES_PWM is not set
+# CONFIG_EXAMPLES_RFID_READUID is not set
+# CONFIG_EXAMPLES_RGBLED is not set
+# CONFIG_EXAMPLES_SENDMAIL is not set
+# CONFIG_EXAMPLES_SERIALBLASTER is not set
+# CONFIG_EXAMPLES_SERIALRX is not set
+# CONFIG_EXAMPLES_SERLOOP is not set
+# CONFIG_EXAMPLES_SLCD is not set
+# CONFIG_EXAMPLES_SMPS is not set
+# CONFIG_EXAMPLES_STAT is not set
+# CONFIG_EXAMPLES_TCPECHO is not set
+# CONFIG_EXAMPLES_TIFF is not set
+# CONFIG_EXAMPLES_TOUCHSCREEN is not set
+# CONFIG_EXAMPLES_UID is not set
+# CONFIG_EXAMPLES_USBSERIAL is not set
+# CONFIG_EXAMPLES_USERFS is not set
+# CONFIG_EXAMPLES_WATCHDOG is not set
+# CONFIG_EXAMPLES_WEBSERVER is not set
+# CONFIG_EXAMPLES_XBC_TEST is not set
+
+#
+# File System Utilities
+#
+# CONFIG_FSUTILS_INIFILE is not set
+# CONFIG_FSUTILS_INIH is not set
+# CONFIG_FSUTILS_PASSWD is not set
+
+#
+# GPS Utilities
+#
+# CONFIG_GPSUTILS_MINMEA_LIB is not set
+
+#
+# Graphics Support
+#
+# CONFIG_GRAPHICS_FT80X is not set
+# CONFIG_GRAPHICS_LVGL is not set
+
+#
+# NxWidgets
+#
+
+#
+# NxWM
+#
+# CONFIG_GRAPHICS_PDCURSES is not set
+# CONFIG_TIFF is not set
+
+#
+# Industrial Applications
+#
+# CONFIG_INDUSTRY_ABNT_CODI_LIB is not set
+
+#
+# Interpreters
+#
+# CONFIG_INTERPRETERS_BAS is not set
+# CONFIG_INTERPRETERS_FICL is not set
+# CONFIG_INTERPRETERS_MINIBASIC is not set
+
+#
+# FreeModBus
+#
+# CONFIG_MODBUS is not set
+
+#
+# Network Utilities
+#
+# CONFIG_NETUTILS_CHAT is not set
+# CONFIG_NETUTILS_CJSON is not set
+# CONFIG_NETUTILS_CODECS is not set
+# CONFIG_NETUTILS_ESP8266 is not set
+# CONFIG_NETUTILS_FTPC is not set
+# CONFIG_NETUTILS_SMTP is not set
+
+#
+# NSH Library
+#
+# CONFIG_NSH_LIBRARY is not set
+
+#
+# Platform-specific Support
+#
+# CONFIG_PLATFORM_CONFIGDATA is not set
+CONFIG_HAVE_CXXINITIALIZE=y
+
+#
+# System Libraries and NSH Add-Ons
+#
+# CONFIG_SYSTEM_CLE is not set
+# CONFIG_SYSTEM_CUTERM is not set
+# CONFIG_SYSTEM_EMBEDLOG is not set
+# CONFIG_SYSTEM_HEX2BIN is not set
+# CONFIG_SYSTEM_HEXED is not set
+# CONFIG_SYSTEM_NSH is not set
+# CONFIG_SYSTEM_RAMTEST is not set
+# CONFIG_READLINE_HAVE_EXTMATCH is not set
+CONFIG_SYSTEM_READLINE=y
+CONFIG_READLINE_ECHO=y
+# CONFIG_READLINE_TABCOMPLETION is not set
+# CONFIG_READLINE_CMD_HISTORY is not set
+# CONFIG_SYSTEM_SETLOGMASK is not set
+# CONFIG_SYSTEM_SPITOOL is not set
+# CONFIG_SYSTEM_TEE is not set
+# CONFIG_SYSTEM_TERMCURSES is not set
+# CONFIG_SYSTEM_UBLOXMODEM is not set
+# CONFIG_SYSTEM_VI is not set
+# CONFIG_SYSTEM_ZMODEM is not set
+
+#
+# Testing
+#
+# CONFIG_TESTING_CXXTEST is not set
+# CONFIG_TESTING_FSTEST is not set
+# CONFIG_TESTING_GETPRIME is not set
+# CONFIG_TESTING_NXFFS is not set
+# CONFIG_TESTING_OSTEST is not set
+# CONFIG_TESTING_SCANFTEST is not set
+# CONFIG_TESTING_SMART is not set
+# CONFIG_TESTING_SMART_TEST is not set
+# CONFIG_TESTING_UNITY is not set
+
+#
+# Wireless Libraries and NSH Add-Ons
+#
+
+#
+# Bluetooth applications
+#
+# CONFIG_BTSAK is not set
+
+#
+# IEEE 802.15.4 applications
+#
+# CONFIG_IEEE802154_I8SAK is not set
+# CONFIG_IEEE802154_LIBMAC is not set
+# CONFIG_IEEE802154_LIBUTILS is not set
diff --git a/boards/arm/stm32l4/nucleo-l432kc/src/Makefile b/boards/arm/stm32l4/nucleo-l432kc/src/Makefile
index 9c0c71b..899191d 100644
--- a/boards/arm/stm32l4/nucleo-l432kc/src/Makefile
+++ b/boards/arm/stm32l4/nucleo-l432kc/src/Makefile
@@ -92,4 +92,8 @@ ifeq ($(CONFIG_LIB_BOARDCTL),y)
 CSRCS += stm32_appinit.c
 endif
 
+ifeq ($(CONFIG_NUCLEOL432KC_SPWM),y)
+CSRCS += stm32_spwm.c
+endif
+
 include $(TOPDIR)/boards/Board.mk
diff --git a/boards/arm/stm32l4/nucleo-l432kc/src/stm32_spwm.c b/boards/arm/stm32l4/nucleo-l432kc/src/stm32_spwm.c
new file mode 100644
index 0000000..132bca5
--- /dev/null
+++ b/boards/arm/stm32l4/nucleo-l432kc/src/stm32_spwm.c
@@ -0,0 +1,664 @@
+/****************************************************************************
+ * boards/arm/stm32/nucleo-l432kc/src/stm32_spwm.c
+ *
+ *   Copyright (C) 2018, 2019 Gregory Nutt. All rights reserved.
+ *   Author: Mateusz Szafoni <ra...@railab.me>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <unistd.h>
+#include <math.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/signal.h>
+
+#include <arch/irq.h>
+#include <arch/chip/chip.h>
+#include <arch/board/board.h>
+
+#include "up_internal.h"
+#include "ram_vectors.h"
+
+#include "stm32l4_pwm.h"
+#include "stm32l4_tim.h"
+
+#ifdef CONFIG_NUCLEOL432KC_SPWM
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Assertions ***************************************************************/
+
+#ifndef CONFIG_ARCH_CHIP_STM32L432KC
+#  warning "This only have been verified with CONFIG_ARCH_CHIP_STM32L432KC"
+#endif
+
+#ifndef CONFIG_ARCH_HIPRI_INTERRUPT
+#  error "CONFIG_ARCH_HIPRI_INTERRUPT is required"
+#endif
+
+#ifndef CONFIG_ARCH_RAMVECTORS
+#  error "CONFIG_ARCH_RAMVECTORS is required"
+#endif
+
+#ifndef CONFIG_ARCH_IRQPRIO
+#  error "CONFIG_ARCH_IRQPRIO is required"
+#endif
+
+#ifndef CONFIG_ARCH_FPU
+#  warning "Set CONFIG_ARCH_FPU for hardware FPU support"
+#endif
+
+/* Check the configuration for TIM1 */
+
+#ifdef CONFIG_NUCLEOL432KC_SPWM_USE_TIM1
+
+/* Phase 1 is TIM1 CH1 */
+
+#  if CONFIG_NUCLEOL432KC_SPWM_PHASE_NUM > 0
+#    ifndef CONFIG_STM32L4_TIM1_CH1OUT
+#      error
+#    endif
+#    ifndef CONFIG_STM32L4_TIM6
+#      error
+#    endif
+#  endif
+
+/* Phase 2 is TIM1 CH2 */
+
+#  if CONFIG_NUCLEOL432KC_SPWM_PHASE_NUM > 1
+#    ifndef CONFIG_STM32L4_TIM1_CH2OUT
+#      error
+#    endif
+#  endif
+
+/* Phase 3 is TIM1 CH3 */
+
+#  if CONFIG_NUCLEOL432KC_SPWM_PHASE_NUM > 2
+#    ifndef CONFIG_STM32L4_TIM1_CH3OUT
+#      error
+#    endif
+#  endif
+
+/* Phase 4 is TIM1 CH4 */
+
+#  if CONFIG_NUCLEOL432KC_SPWM_PHASE_NUM > 3
+#    ifndef CONFIG_STM32L4_TIM1_CH4OUT
+#      error
+#    endif
+#  endif
+
+#  if CONFIG_NUCLEOL432KC_SPWM_PHASE_NUM != PWM_TIM1_NCHANNELS
+#    error
+#  endif
+
+#endif  /* CONFIG_NUCLEOL432KC_SPWM_USE_TIM1 */
+
+/* Configuration ************************************************************/
+
+#ifdef CONFIG_NUCLEOL432KC_SPWM_USE_TIM1
+#  define PWM_TIMERS_IN_USE 1
+#endif
+
+#define SPWM_PHASE_SHIFT ((360.0f/CONFIG_NUCLEOL432KC_SPWM_PHASE_NUM))
+
+#define SAMPLES_NUM CONFIG_NUCLEOL432KC_SPWM_SAMPLES
+#define PHASES_NUM CONFIG_NUCLEOL432KC_SPWM_PHASE_NUM
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* SPWM private data */
+
+struct spwm_s
+{
+  FAR struct stm32l4_pwm_dev_s *pwm;
+#ifdef CONFIG_NUCLEOL432KC_SPWM_USE_TIM1
+  FAR struct stm32l4_tim_dev_s *tim;
+#endif
+  float waveform[SAMPLES_NUM];        /* Waveform samples */
+  float phase_step;                   /* Waveform phase step */
+  float waveform_freq;                /* Waveform frequency */
+  uint16_t cmp[SAMPLES_NUM];          /* PWM TIM compare table */
+  uint16_t per;                       /* PWM TIM period */
+  uint16_t samples;                   /* Modulation waveform samples num */
+  uint16_t phase_shift[PHASES_NUM];   /* Phase offset */
+  volatile uint16_t sample_now[PHASES_NUM];  /* Current sample number for
+                                              * phase */
+  uint8_t phases;                     /* Number of PWM phases */
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct spwm_s g_spwm =
+{
+  .waveform_freq = ((float)CONFIG_NUCLEOL432KC_SPWM_FREQ),
+  .phases        = PHASES_NUM,
+  .samples       = SAMPLES_NUM,
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static float waveform_func(float x);
+static int waveform_init(FAR struct spwm_s *spwm, float (*f)(float));
+static int spwm_start(FAR struct spwm_s *spwm);
+static int spwm_start(FAR struct spwm_s *spwm);
+static int spwm_stop(FAR struct spwm_s *spwm);
+#ifdef CONFIG_NUCLEOL432KC_SPWM_USE_TIM1
+static int spwm_tim1_setup(FAR struct spwm_s *spwm);
+static int spwm_tim6_setup(FAR struct spwm_s *spwm);
+static int spwm_tim1_start(FAR struct spwm_s *spwm);
+static int spwm_tim6_start(FAR struct spwm_s *spwm);
+static int spwm_tim1_stop(FAR struct spwm_s *spwm);
+static int spwm_tim6_stop(FAR struct spwm_s *spwm);
+#endif  /* CONFIG_NUCLEOL432KC_SPWM_USE_TIM1 */
+static int spwm_setup(FAR struct spwm_s *spwm);
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: waveform_func
+ *
+ * Description:
+ *   Modulation function. This function must return values from <0.0, 1.0>!
+ *
+ ****************************************************************************/
+
+static float waveform_func(float x)
+{
+  DEBUGASSERT(x >= 0 && x <= 2 * M_PI);
+
+  /* Sine modulation */
+
+  return (sinf(x) + 1.0f) / 2.0f;
+}
+
+/****************************************************************************
+ * Name: waveform_init
+ *
+ * Description:
+ *   Initialize modulation waveform
+ *
+ ****************************************************************************/
+
+static int waveform_init(FAR struct spwm_s *spwm, float (*f)(float))
+{
+  uint16_t i = 0;
+  int ret = 0;
+
+  printf("Initialize waveform\n");
+
+  /* Get phase step to achieve one sine waveform period */
+
+  spwm->phase_step = (float)(2 * M_PI / spwm->samples);
+
+  /* Initialize sine and PWM compare tables */
+
+  for (i = 0; i < spwm->samples; i += 1)
+    {
+      /* We need sine in range from 0 to 1.0 */
+
+      spwm->waveform[i] = f(spwm->phase_step * i);
+
+      DEBUGASSERT(spwm->waveform[i] >= 0.0 && spwm->waveform[i] <= 2 * M_PI);
+
+      spwm->cmp[i] = (uint16_t)(spwm->waveform[i] * spwm->per);
+    }
+
+  /* Configure phase shift TODO: this should be configurable */
+
+  for (i = 0; i < spwm->phases; i += 1)
+    {
+      spwm->phase_shift[i] =
+        (spwm->samples / CONFIG_NUCLEOL432KC_SPWM_PHASE_NUM) * i;
+    }
+
+  /* Initialize offstes */
+
+  for (i = 0; i < spwm->phases; i += 1)
+    {
+      spwm->sample_now[i] = spwm->phase_shift[i];
+    }
+
+  printf("\tsamples = %d\n", spwm->samples);
+  printf("\tper     = %d\n", spwm->per);
+  printf("\tphase   = %d\n", spwm->phases);
+  for (i = 0; i < spwm->phases; i += 1)
+    {
+      printf("\tsnow%d   = %d\n", i, spwm->sample_now[i]);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: spwm_start
+ *
+ * Description:
+ *   Start SPWM
+ *
+ ****************************************************************************/
+
+static int spwm_start(FAR struct spwm_s *spwm)
+{
+  /* Start TIM1 */
+
+  spwm_tim1_start(spwm);
+
+  /* Start TIM6 */
+
+  spwm_tim6_start(spwm);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: spwm_stop
+ *
+ * Description:
+ *   Stop SPWM
+ *
+ ****************************************************************************/
+
+static int spwm_stop(FAR struct spwm_s *spwm)
+{
+  /* Stop TIM1 */
+
+  spwm_tim1_stop(spwm);
+
+  /* Stop TIM6 */
+
+  spwm_tim6_stop(spwm);
+
+  return OK;
+}
+
+#ifdef CONFIG_NUCLEOL432KC_SPWM_USE_TIM1
+
+/****************************************************************************
+ * Name: tim6_handler
+ ****************************************************************************/
+
+static void tim6_handler(void)
+{
+  FAR struct spwm_s *spwm = &g_spwm;
+  FAR struct stm32l4_pwm_dev_s *pwm = spwm->pwm;
+  FAR struct stm32l4_tim_dev_s *tim = spwm->tim;
+  uint8_t i = 0;
+
+  for (i = 0; i < spwm->phases; i += 1)
+    {
+      /* Set new CMP for timers */
+
+      PWM_CCR_UPDATE(pwm, i + 1, spwm->cmp[spwm->sample_now[i]]);
+
+      /* Increase sample pointer */
+
+      spwm->sample_now[i] += 1;
+
+      if (spwm->sample_now[i] > spwm->samples)
+        {
+          spwm->sample_now[i] = 0;
+        }
+    }
+
+  /* TODO: Software update */
+
+  STM32L4_TIM_ACKINT(tim, ATIM_SR_UIF);
+}
+
+/****************************************************************************
+ * Name: spwm_tim6_setup
+ ****************************************************************************/
+
+static int spwm_tim6_setup(FAR struct spwm_s *spwm)
+{
+  FAR struct stm32l4_tim_dev_s *tim = NULL;
+  uint64_t freq = 0;
+  uint32_t per = 0;
+  int ret = OK;
+
+  /* Get TIM6 interface */
+
+  tim = stm32l4_tim_init(6);
+  if (tim == NULL)
+    {
+      printf("ERROR: Failed to get TIM6 interface\n");
+      ret = -1;
+      goto errout;
+    }
+
+  spwm->tim = tim;
+
+  /* Frequency with which we will change samples.
+   *
+   * tim6_freq = samples_num * waveform_freq.
+   */
+
+  freq = spwm->samples * spwm->waveform_freq;
+  per = BOARD_TIM6_FREQUENCY / freq;
+  if (per > 0xFFFF)
+    {
+      printf("ERROR: can not achieve TIM6 frequency\n");
+      ret = -1;
+      goto errout;
+    }
+
+  /* TODO: TIM_SETFREQ */
+
+  STM32L4_TIM_SETCLOCK(tim, BOARD_TIM6_FREQUENCY);
+  STM32L4_TIM_SETPERIOD(tim, per);
+
+  /* Attach TIM6 ram vector */
+
+  ret = up_ramvec_attach(STM32L4_IRQ_TIM6, tim6_handler);
+  if (ret < 0)
+    {
+      printf("ERROR: up_ramvec_attach failed: %d\n", ret);
+      ret = -1;
+      goto errout;
+    }
+
+  /* Set the priority of the TIM6 interrupt vector */
+
+  ret = up_prioritize_irq(STM32L4_IRQ_TIM6, NVIC_SYSH_HIGH_PRIORITY);
+  if (ret < 0)
+    {
+      printf("ERROR: up_prioritize_irq failed: %d\n", ret);
+      ret = -1;
+      goto errout;
+    }
+
+  spwm_tim6_stop(spwm);
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: spwm_tim6_start
+ ****************************************************************************/
+
+static int spwm_tim6_start(FAR struct spwm_s *spwm)
+{
+  FAR struct stm32l4_tim_dev_s *tim = spwm->tim;
+
+  /* Enable the timer interrupt at the NVIC and at TIM6 */
+
+  up_enable_irq(STM32L4_IRQ_TIM6);
+  STM32L4_TIM_ENABLEINT(tim, BTIM_DIER_UIE);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: spwm_tim6_stop
+ ****************************************************************************/
+
+static int spwm_tim6_stop(FAR struct spwm_s *spwm)
+{
+  FAR struct stm32l4_tim_dev_s *tim = spwm->tim;
+
+  /* Disable the timer interrupt at the NVIC and at TIM6 */
+
+  up_disable_irq(STM32L4_IRQ_TIM6);
+  STM32L4_TIM_DISABLEINT(tim, BTIM_DIER_UIE);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: spwm_tim1_setup
+ ****************************************************************************/
+
+static int spwm_tim1_setup(FAR struct spwm_s *spwm)
+{
+  FAR struct stm32l4_pwm_dev_s *pwm = NULL;
+  int ret = OK;
+
+  /* Get TIM1 PWM interface */
+
+  pwm = (FAR struct stm32l4_pwm_dev_s *)stm32l4_pwminitialize(1);
+  if (pwm == NULL)
+    {
+      printf("ERROR: Failed to get TIM1 PWM interface\n");
+      ret = -1;
+      goto errout;
+    }
+
+  spwm->pwm = pwm;
+
+  /* Initial PWM1 setup */
+
+  ret = PWM_SETUP(pwm);
+  if (ret < 0)
+    {
+      printf("ERROR: Failed to get setup TIM1 PWM\n");
+      ret = -1;
+      goto errout;
+    }
+
+  /* Configure TIM1 PWM frequency */
+
+  ret = PWM_FREQ_UPDATE(pwm, CONFIG_NUCLEOL432KC_SPWM_PWM_FREQ);
+  if (ret < 0)
+    {
+      printf("ERROR: Failed to set TIM1 PWM frequency\n");
+      ret = -1;
+      goto errout;
+    }
+
+  /* Get TIM1 period (ARR) */
+
+  spwm->per = PWM_ARR_GET(pwm);
+
+  spwm_tim1_stop(spwm);
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: spwm_tim1_start
+ ****************************************************************************/
+
+static int spwm_tim1_start(FAR struct spwm_s *spwm)
+{
+  FAR struct stm32l4_pwm_dev_s *pwm = spwm->pwm;
+  uint16_t outputs = 0;
+  int i = 0;
+
+  /* Get outputs */
+
+  for (i = 0; i < spwm->phases; i += 1)
+    {
+      outputs |= (1 << (i * 2));
+    }
+
+  /* Enable PWM outputs */
+
+  PWM_OUTPUTS_ENABLE(pwm, outputs, true);
+
+  /* Enable TIM1 */
+
+  PWM_TIM_ENABLE(pwm, true);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: spwm_tim1_stop
+ ****************************************************************************/
+
+static int spwm_tim1_stop(FAR struct spwm_s *spwm)
+{
+  FAR struct stm32l4_pwm_dev_s *pwm = spwm->pwm;
+  uint16_t outputs = 0;
+  int i = 0;
+
+  /* Get outputs */
+
+  for (i = 0; i < spwm->phases; i += 1)
+    {
+      outputs |= (1 << (i * 2));
+    }
+
+  /* Disable PWM outputs */
+
+  PWM_OUTPUTS_ENABLE(pwm, outputs, false);
+
+  /* Disable TIM1 */
+
+  PWM_TIM_ENABLE(pwm, false);
+
+  return OK;
+}
+
+#endif  /* CONFIG_NUCLEOL432KC_SPWM_USE_TIM1 */
+
+/****************************************************************************
+ * Name: spwm_setup
+ ****************************************************************************/
+
+static int spwm_setup(FAR struct spwm_s *spwm)
+{
+  int ret = OK;
+
+  /* TIM1 setup - PWM */
+
+  printf("Setup TIM1 and TIM6\n");
+  ret = spwm_tim1_setup(spwm);
+  if (ret < 0)
+    {
+      goto errout;
+    }
+
+  /* TIM6 setup - IRQ */
+
+  ret = spwm_tim6_setup(spwm);
+  if (ret < 0)
+    {
+      goto errout;
+    }
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: spwm_main
+ *
+ * Description:
+ *   Entrypoint for SPWM example.
+ *
+ ****************************************************************************/
+
+int spwm_main(int argc, char *argv[])
+{
+  FAR struct spwm_s *spwm = NULL;
+  int ret = OK;
+  int i = 0;
+
+  spwm = &g_spwm;
+
+  printf("\nspwm_main: Started\n");
+
+  /* Setup SPWM example */
+
+  ret = spwm_setup(spwm);
+  if (ret < 0)
+    {
+      printf("ERROR: failed to setup SPWM %d!\n", ret);
+      goto errout;
+    }
+
+  /* Initialize modulation waveform */
+
+  ret = waveform_init(spwm, waveform_func);
+  if (ret < 0)
+    {
+      printf("ERROR: failed initialize modulation wavefrom %d!\n", ret);
+      goto errout;
+    }
+
+  /* Start SPWM */
+
+  ret = spwm_start(spwm);
+  if (ret < 0)
+    {
+      printf("ERROR: failed start SPWM %d!\n", ret);
+      goto errout;
+    }
+
+  /* Main loop */
+
+  while (1)
+    {
+      /* Print counter */
+
+      printf("%d\n", i);
+
+      /* Increase counter */
+
+      i += 1;
+
+      /* Sleep */
+
+      nxsig_sleep(1);
+    }
+
+errout:
+  spwm_stop(spwm);
+
+  return 0;
+}
+
+#endif  /* CONFIG_NUCLEOL432KC_SPWM */


[incubator-nuttx] 06/07: Fix BUGs. Change macro names.

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

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

commit eb416498e2475f831260e7dc8aa3e63e280204e0
Author: Daniel P. Carvalho <da...@gmail.com>
AuthorDate: Tue Jan 14 11:26:51 2020 -0300

    Fix BUGs. Change macro names.
---
 arch/arm/src/stm32l4/stm32l4_pwm.h | 38 ++++++++++++++++++++------------------
 1 file changed, 20 insertions(+), 18 deletions(-)

diff --git a/arch/arm/src/stm32l4/stm32l4_pwm.h b/arch/arm/src/stm32l4/stm32l4_pwm.h
index d359c38..01832e2 100644
--- a/arch/arm/src/stm32l4/stm32l4_pwm.h
+++ b/arch/arm/src/stm32l4/stm32l4_pwm.h
@@ -50,6 +50,8 @@
 
 #include <nuttx/config.h>
 
+#include <nuttx/timers/pwm.h>
+
 #include "chip.h"
 
 /****************************************************************************
@@ -808,42 +810,42 @@
 #ifdef CONFIG_STM32L4_PWM_LL_OPS
 
 /* NOTE: low-level ops accept pwm_lowerhalf_s as first argument, but llops
- *       access can be found in stm32_pwm_dev_s
+ *       access can be found in stm32l4_pwm_dev_s
  */
 
-#define STM32L4_PWM_SETUP(dev)                                                             \
+#define PWM_SETUP(dev)                                                             \
         (dev)->ops->setup((FAR struct pwm_lowerhalf_s *)dev)
-#define STM32L4_PWM_SHUTDOWN(dev)                                                          \
+#define PWM_SHUTDOWN(dev)                                                          \
         (dev)->ops->shutdown((FAR struct pwm_lowerhalf_s *)dev)
-#define STM32L4_PWM_CCR_UPDATE(dev, index, ccr)                                            \
+#define PWM_CCR_UPDATE(dev, index, ccr)                                            \
         (dev)->llops->ccr_update((FAR struct pwm_lowerhalf_s *)dev, index, ccr)
-#define STM32L4_PWM_MODE_UPDATE(dev, index, mode)                                          \
+#define PWM_MODE_UPDATE(dev, index, mode)                                          \
         (dev)->llops->mode_update((FAR struct pwm_lowerhalf_s *)dev, index, mode)
-#define STM32L4_PWM_CCR_GET(dev, index)                                                    \
+#define PWM_CCR_GET(dev, index)                                                    \
         (dev)->llops->ccr_get((FAR struct pwm_lowerhalf_s *)dev, index)
-#define STM32L4_PWM_ARR_UPDATE(dev, arr)                                                   \
+#define PWM_ARR_UPDATE(dev, arr)                                                   \
         (dev)->llops->arr_update((FAR struct pwm_lowerhalf_s *)dev, arr)
-#define STM32L4_PWM_ARR_GET(dev)                                                           \
+#define PWM_ARR_GET(dev)                                                           \
         (dev)->llops->arr_get((FAR struct pwm_lowerhalf_s *)dev)
-#define STM32L4_PWM_OUTPUTS_ENABLE(dev, out, state)                                        \
+#define PWM_OUTPUTS_ENABLE(dev, out, state)                                        \
         (dev)->llops->outputs_enable((FAR struct pwm_lowerhalf_s *)dev, out, state)
-#define STM32L4_PWM_SOFT_UPDATE(dev)                                                       \
+#define PWM_SOFT_UPDATE(dev)                                                       \
         (dev)->llops->soft_update((FAR struct pwm_lowerhalf_s *)dev)
-#define STM32L4_PWM_CONFIGURE(dev)                                                         \
+#define PWM_CONFIGURE(dev)                                                         \
         (dev)->llops->configure((FAR struct pwm_lowerhalf_s *)dev)
-#define STM32L4_PWM_SOFT_BREAK(dev, state)                                                 \
+#define PWM_SOFT_BREAK(dev, state)                                                 \
         (dev)->llops->soft_break((FAR struct pwm_lowerhalf_s *)dev, state)
-#define STM32L4_PWM_FREQ_UPDATE(dev, freq)                                                 \
+#define PWM_FREQ_UPDATE(dev, freq)                                                 \
         (dev)->llops->freq_update((FAR struct pwm_lowerhalf_s *)dev, freq)
-#define STM32L4_PWM_TIM_ENABLE(dev, state)                                                 \
+#define PWM_TIM_ENABLE(dev, state)                                                 \
         (dev)->llops->tim_enable((FAR struct pwm_lowerhalf_s *)dev, state)
 #ifdef CONFIG_DEBUG_STM32L4_PWM_INFO
-#  define STM32L4_PWM_DUMP_REGS(dev, msg)                                                  \
+#  define PWM_DUMP_REGS(dev, msg)                                                  \
         (dev)->llops->dump_regs((FAR struct pwm_lowerhalf_s *)dev, msg)
 #else
-#  define STM32L4_PWM_DUMP_REGS(dev, msg)
+#  define PWM_DUMP_REGS(dev, msg)
 #endif
-#define STM32L4_PWM_DT_UPDATE(dev, dt)                                                     \
+#define PWM_DT_UPDATE(dev, dt)                                                     \
         (dev)->llops->dt_update((FAR struct pwm_lowerhalf_s *)dev, dt)
 #endif
 
@@ -933,7 +935,7 @@ enum stm32l4_pwm_output_e
  * "lower-half" PWM driver structure.
  */
 
-struct stm32_pwm_dev_s
+struct stm32l4_pwm_dev_s
 {
   /* The first field of this state structure must be a pointer to the PWM
    * callback structure to be consistent with upper-half PWM driver.


[incubator-nuttx] 01/07: Low level operation support for STM32L4 PWM driver (Based on STM32 PWM driver).

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

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

commit 8c84d91819578db00a039fdeb5b5f8f800c4bbc1
Author: Daniel P. Carvalho <da...@gmail.com>
AuthorDate: Mon Jan 13 16:54:57 2020 -0300

    Low level operation support for STM32L4 PWM driver (Based on STM32 PWM driver).
---
 arch/arm/src/stm32l4/Kconfig                       | 1467 +++++++-
 arch/arm/src/stm32l4/stm32l4_pwm.c                 | 3790 ++++++++++++++------
 arch/arm/src/stm32l4/stm32l4_pwm.h                 |  369 +-
 .../stm32l4/nucleo-l432kc/include/nucleo-l432kc.h  |   15 +-
 4 files changed, 4435 insertions(+), 1206 deletions(-)

diff --git a/arch/arm/src/stm32l4/Kconfig b/arch/arm/src/stm32l4/Kconfig
index 3d37219..d5e5bda 100644
--- a/arch/arm/src/stm32l4/Kconfig
+++ b/arch/arm/src/stm32l4/Kconfig
@@ -1878,6 +1878,12 @@ endchoice
 
 endif # STM32L4_LPTIM2_PWM
 
+config STM32L4_PWM_LL_OPS
+	bool "PWM low-level operations"
+	default n
+	---help---
+		Enable low-level PWM ops.
+
 config STM32L4_TIM1_PWM
 	bool "TIM1 PWM"
 	default n
@@ -1901,6 +1907,27 @@ config STM32L4_TIM1_MODE
 	---help---
 		Specifies the timer mode.
 
+config STM32L4_TIM1_LOCK
+	int "TIM1 Lock Level Configuration"
+	default 0
+	range 0 3
+	---help---
+		Timer 1 lock level configuration
+
+config STM32L4_TIM1_TDTS
+	int "TIM1 t_DTS Division"
+	default 0
+	range 0 2
+	---help---
+		Timer 1 dead-time and sampling clock (t_DTS) division
+
+config STM32L4_TIM1_DEADTIME
+	int "TIM1 Initial Dead-time"
+	default 0
+	range 0 255
+	---help---
+		Timer 1 initial dead-time
+
 if STM32L4_PWM_MULTICHAN
 
 config STM32L4_TIM1_CHANNEL1
@@ -1913,10 +1940,10 @@ if STM32L4_TIM1_CHANNEL1
 
 config STM32L4_TIM1_CH1MODE
 	int "TIM1 Channel 1 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM1_CH1OUT
 	bool "TIM1 Channel 1 Output"
@@ -1943,10 +1970,10 @@ if STM32L4_TIM1_CHANNEL2
 
 config STM32L4_TIM1_CH2MODE
 	int "TIM1 Channel 2 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM1_CH2OUT
 	bool "TIM1 Channel 2 Output"
@@ -1973,10 +2000,10 @@ if STM32L4_TIM1_CHANNEL3
 
 config STM32L4_TIM1_CH3MODE
 	int "TIM1 Channel 3 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM1_CH3OUT
 	bool "TIM1 Channel 3 Output"
@@ -2003,10 +2030,10 @@ if STM32L4_TIM1_CHANNEL4
 
 config STM32L4_TIM1_CH4MODE
 	int "TIM1 Channel 4 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM1_CH4OUT
 	bool "TIM1 Channel 4 Output"
@@ -2028,12 +2055,70 @@ config STM32L4_TIM1_CHANNEL
 		If TIM1 is enabled for PWM usage, you also need specifies the timer output
 		channel {1,..,4}
 
+if STM32L4_TIM1_CHANNEL = 1
+
+config STM32L4_TIM1_CH1OUT
+	bool "TIM1 Channel 1 Output"
+	default n
+	---help---
+		Enables channel 1 output.
+
+config STM32L4_TIM1_CH1NOUT
+	bool "TIM1 Channel 1 Complementary Output"
+	default n
+	---help---
+		Enables channel 1 Complementary Output.
+
+endif # STM32L4_TIM1_CHANNEL = 1
+
+if STM32L4_TIM1_CHANNEL = 2
+
+config STM32L4_TIM1_CH2OUT
+	bool "TIM1 Channel 2 Output"
+	default n
+	---help---
+		Enables channel 2 output.
+
+config STM32L4_TIM1_CH2NOUT
+	bool "TIM1 Channel 2 Complementary Output"
+	default n
+	---help---
+		Enables channel 2 Complementary Output.
+
+endif # STM32L4_TIM1_CHANNEL = 2
+
+if STM32L4_TIM1_CHANNEL = 3
+
+config STM32L4_TIM1_CH3OUT
+	bool "TIM1 Channel 3 Output"
+	default n
+	---help---
+		Enables channel 3 output.
+
+config STM32L4_TIM1_CH3NOUT
+	bool "TIM1 Channel 3 Complementary Output"
+	default n
+	---help---
+		Enables channel 3 Complementary Output.
+
+endif # STM32L4_TIM1_CHANNEL = 3
+
+if STM32L4_TIM1_CHANNEL = 4
+
+config STM32L4_TIM1_CH4OUT
+	bool "TIM1 Channel 4 Output"
+	default n
+	---help---
+		Enables channel 4 output.
+
+endif # STM32L4_TIM1_CHANNEL = 4
+
 config STM32L4_TIM1_CHMODE
 	int "TIM1 Channel Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 endif # !STM32L4_PWM_MULTICHAN
 
@@ -2074,10 +2159,10 @@ if STM32L4_TIM2_CHANNEL1
 
 config STM32L4_TIM2_CH1MODE
 	int "TIM2 Channel 1 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM2_CH1OUT
 	bool "TIM2 Channel 1 Output"
@@ -2097,10 +2182,10 @@ if STM32L4_TIM2_CHANNEL2
 
 config STM32L4_TIM2_CH2MODE
 	int "TIM2 Channel 2 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM2_CH2OUT
 	bool "TIM2 Channel 2 Output"
@@ -2120,10 +2205,10 @@ if STM32L4_TIM2_CHANNEL3
 
 config STM32L4_TIM2_CH3MODE
 	int "TIM2 Channel 3 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM2_CH3OUT
 	bool "TIM2 Channel 3 Output"
@@ -2143,10 +2228,10 @@ if STM32L4_TIM2_CHANNEL4
 
 config STM32L4_TIM2_CH4MODE
 	int "TIM2 Channel 4 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM2_CH4OUT
 	bool "TIM2 Channel 4 Output"
@@ -2168,12 +2253,52 @@ config STM32L4_TIM2_CHANNEL
 		If TIM2 is enabled for PWM usage, you also need specifies the timer output
 		channel {1,..,4}
 
+if STM32L4_TIM2_CHANNEL = 1
+
+config STM32L4_TIM2_CH1OUT
+	bool "TIM2 Channel 1 Output"
+	default n
+	---help---
+		Enables channel 1 output.
+
+endif # STM32L4_TIM2_CHANNEL = 1
+
+if STM32L4_TIM2_CHANNEL = 2
+
+config STM32L4_TIM2_CH2OUT
+	bool "TIM2 Channel 2 Output"
+	default n
+	---help---
+		Enables channel 2 output.
+
+endif # STM32L4_TIM2_CHANNEL = 2
+
+if STM32L4_TIM2_CHANNEL = 3
+
+config STM32L4_TIM2_CH3OUT
+	bool "TIM2 Channel 3 Output"
+	default n
+	---help---
+		Enables channel 3 output.
+
+endif # STM32L4_TIM2_CHANNEL = 3
+
+if STM32L4_TIM2_CHANNEL = 4
+
+config STM32L4_TIM2_CH4OUT
+	bool "TIM2 Channel 4 Output"
+	default n
+	---help---
+		Enables channel 4 output.
+
+endif # STM32L4_TIM2_CHANNEL = 4
+
 config STM32L4_TIM2_CHMODE
 	int "TIM2 Channel Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 endif # !STM32L4_PWM_MULTICHAN
 
@@ -2214,10 +2339,10 @@ if STM32L4_TIM3_CHANNEL1
 
 config STM32L4_TIM3_CH1MODE
 	int "TIM3 Channel 1 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM3_CH1OUT
 	bool "TIM3 Channel 1 Output"
@@ -2237,10 +2362,10 @@ if STM32L4_TIM3_CHANNEL2
 
 config STM32L4_TIM3_CH2MODE
 	int "TIM3 Channel 2 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM3_CH2OUT
 	bool "TIM3 Channel 2 Output"
@@ -2260,10 +2385,10 @@ if STM32L4_TIM3_CHANNEL3
 
 config STM32L4_TIM3_CH3MODE
 	int "TIM3 Channel 3 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM3_CH3OUT
 	bool "TIM3 Channel 3 Output"
@@ -2283,10 +2408,10 @@ if STM32L4_TIM3_CHANNEL4
 
 config STM32L4_TIM3_CH4MODE
 	int "TIM3 Channel 4 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM3_CH4OUT
 	bool "TIM3 Channel 4 Output"
@@ -2308,12 +2433,52 @@ config STM32L4_TIM3_CHANNEL
 		If TIM3 is enabled for PWM usage, you also need specifies the timer output
 		channel {1,..,4}
 
+if STM32L4_TIM3_CHANNEL = 1
+
+config STM32L4_TIM3_CH1OUT
+	bool "TIM3 Channel 1 Output"
+	default n
+	---help---
+		Enables channel 1 output.
+
+endif # STM32L4_TIM3_CHANNEL = 1
+
+if STM32L4_TIM3_CHANNEL = 2
+
+config STM32L4_TIM3_CH2OUT
+	bool "TIM3 Channel 2 Output"
+	default n
+	---help---
+		Enables channel 2 output.
+
+endif # STM32L4_TIM3_CHANNEL = 2
+
+if STM32L4_TIM3_CHANNEL = 3
+
+config STM32L4_TIM3_CH3OUT
+	bool "TIM3 Channel 3 Output"
+	default n
+	---help---
+		Enables channel 3 output.
+
+endif # STM32L4_TIM3_CHANNEL = 3
+
+if STM32L4_TIM3_CHANNEL = 4
+
+config STM32L4_TIM3_CH4OUT
+	bool "TIM3 Channel 4 Output"
+	default n
+	---help---
+		Enables channel 4 output.
+
+endif # STM32L4_TIM3_CHANNEL = 4
+
 config STM32L4_TIM3_CHMODE
 	int "TIM3 Channel Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 endif # !STM32L4_PWM_MULTICHAN
 
@@ -2354,10 +2519,10 @@ if STM32L4_TIM4_CHANNEL1
 
 config STM32L4_TIM4_CH1MODE
 	int "TIM4 Channel 1 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM4_CH1OUT
 	bool "TIM4 Channel 1 Output"
@@ -2377,10 +2542,10 @@ if STM32L4_TIM4_CHANNEL2
 
 config STM32L4_TIM4_CH2MODE
 	int "TIM4 Channel 2 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM4_CH2OUT
 	bool "TIM4 Channel 2 Output"
@@ -2400,10 +2565,10 @@ if STM32L4_TIM4_CHANNEL3
 
 config STM32L4_TIM4_CH3MODE
 	int "TIM4 Channel 3 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM4_CH3OUT
 	bool "TIM4 Channel 3 Output"
@@ -2423,10 +2588,10 @@ if STM32L4_TIM4_CHANNEL4
 
 config STM32L4_TIM4_CH4MODE
 	int "TIM4 Channel 4 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM4_CH4OUT
 	bool "TIM4 Channel 4 Output"
@@ -2448,12 +2613,52 @@ config STM32L4_TIM4_CHANNEL
 		If TIM4 is enabled for PWM usage, you also need specifies the timer output
 		channel {1,..,4}
 
+if STM32L4_TIM4_CHANNEL = 1
+
+config STM32L4_TIM4_CH1OUT
+	bool "TIM4 Channel 1 Output"
+	default n
+	---help---
+		Enables channel 1 output.
+
+endif # STM32L4_TIM4_CHANNEL = 1
+
+if STM32L4_TIM4_CHANNEL = 2
+
+config STM32L4_TIM4_CH2OUT
+	bool "TIM4 Channel 2 Output"
+	default n
+	---help---
+		Enables channel 2 output.
+
+endif # STM32L4_TIM4_CHANNEL = 2
+
+if STM32L4_TIM4_CHANNEL = 3
+
+config STM32L4_TIM4_CH3OUT
+	bool "TIM4 Channel 3 Output"
+	default n
+	---help---
+		Enables channel 3 output.
+
+endif # STM32L4_TIM4_CHANNEL = 3
+
+if STM32L4_TIM4_CHANNEL = 4
+
+config STM32L4_TIM4_CH4OUT
+	bool "TIM4 Channel 4 Output"
+	default n
+	---help---
+		Enables channel 4 output.
+
+endif # STM32L4_TIM4_CHANNEL = 4
+
 config STM32L4_TIM4_CHMODE
 	int "TIM4 Channel Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 endif # !STM32L4_PWM_MULTICHAN
 
@@ -2494,10 +2699,10 @@ if STM32L4_TIM5_CHANNEL1
 
 config STM32L4_TIM5_CH1MODE
 	int "TIM5 Channel 1 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM5_CH1OUT
 	bool "TIM5 Channel 1 Output"
@@ -2517,10 +2722,10 @@ if STM32L4_TIM5_CHANNEL2
 
 config STM32L4_TIM5_CH2MODE
 	int "TIM5 Channel 2 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM5_CH2OUT
 	bool "TIM5 Channel 2 Output"
@@ -2540,10 +2745,10 @@ if STM32L4_TIM5_CHANNEL3
 
 config STM32L4_TIM5_CH3MODE
 	int "TIM5 Channel 3 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM5_CH3OUT
 	bool "TIM5 Channel 3 Output"
@@ -2563,10 +2768,10 @@ if STM32L4_TIM5_CHANNEL4
 
 config STM32L4_TIM5_CH4MODE
 	int "TIM5 Channel 4 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM5_CH4OUT
 	bool "TIM5 Channel 4 Output"
@@ -2588,12 +2793,52 @@ config STM32L4_TIM5_CHANNEL
 		If TIM5 is enabled for PWM usage, you also need specifies the timer output
 		channel {1,..,4}
 
+if STM32L4_TIM5_CHANNEL = 1
+
+config STM32L4_TIM5_CH1OUT
+	bool "TIM5 Channel 1 Output"
+	default n
+	---help---
+		Enables channel 1 output.
+
+endif # STM32L4_TIM5_CHANNEL = 1
+
+if STM32L4_TIM5_CHANNEL = 2
+
+config STM32L4_TIM5_CH2OUT
+	bool "TIM5 Channel 2 Output"
+	default n
+	---help---
+		Enables channel 2 output.
+
+endif # STM32L4_TIM5_CHANNEL = 2
+
+if STM32L4_TIM5_CHANNEL = 3
+
+config STM32L4_TIM5_CH3OUT
+	bool "TIM5 Channel 3 Output"
+	default n
+	---help---
+		Enables channel 3 output.
+
+endif # STM32L4_TIM5_CHANNEL = 3
+
+if STM32L4_TIM5_CHANNEL = 4
+
+config STM32L4_TIM5_CH4OUT
+	bool "TIM5 Channel 4 Output"
+	default n
+	---help---
+		Enables channel 4 output.
+
+endif # STM32L4_TIM5_CHANNEL = 4
+
 config STM32L4_TIM5_CHMODE
 	int "TIM5 Channel Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 endif # !STM32L4_PWM_MULTICHAN
 
@@ -2622,6 +2867,27 @@ config STM32L4_TIM8_MODE
 	---help---
 		Specifies the timer mode.
 
+config STM32L4_TIM8_LOCK
+	int "TIM1 Lock Level Configuration"
+	default 0
+	range 0 3
+	---help---
+		Timer 8 lock level configuration
+
+config STM32L4_TIM8_TDTS
+	int "TIM8 t_DTS Division"
+	default 0
+	range 0 2
+	---help---
+		Timer 8 dead-time and sampling clock (t_DTS) division
+
+config STM32L4_TIM8_DEADTIME
+	int "TIM8 Initial Dead-time"
+	default 0
+	range 0 255
+	---help---
+		Timer 8 initial dead-time
+
 if STM32L4_PWM_MULTICHAN
 
 config STM32L4_TIM8_CHANNEL1
@@ -2634,10 +2900,10 @@ if STM32L4_TIM8_CHANNEL1
 
 config STM32L4_TIM8_CH1MODE
 	int "TIM8 Channel 1 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM8_CH1OUT
 	bool "TIM8 Channel 1 Output"
@@ -2664,10 +2930,10 @@ if STM32L4_TIM8_CHANNEL2
 
 config STM32L4_TIM8_CH2MODE
 	int "TIM8 Channel 2 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM8_CH2OUT
 	bool "TIM8 Channel 2 Output"
@@ -2694,10 +2960,10 @@ if STM32L4_TIM8_CHANNEL3
 
 config STM32L4_TIM8_CH3MODE
 	int "TIM8 Channel 3 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM8_CH3OUT
 	bool "TIM8 Channel 3 Output"
@@ -2724,10 +2990,10 @@ if STM32L4_TIM8_CHANNEL4
 
 config STM32L4_TIM8_CH4MODE
 	int "TIM8 Channel 4 Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM8_CH4OUT
 	bool "TIM8 Channel 4 Output"
@@ -2749,12 +3015,70 @@ config STM32L4_TIM8_CHANNEL
 		If TIM8 is enabled for PWM usage, you also need specifies the timer output
 		channel {1,..,4}
 
-config STM32L4_TIM8_CHMODE
+if STM32L4_TIM8_CHANNEL = 1
+
+config STM32L4_TIM8_CH1OUT
+	bool "TIM8 Channel 1 Output"
+	default n
+	---help---
+		Enables channel 1 output.
+
+config STM32L4_TIM8_CH1NOUT
+	bool "TIM8 Channel 1 Complementary Output"
+	default n
+	---help---
+		Enables channel 1 Complementary Output.
+
+endif # STM32L4_TIM8_CHANNEL = 1
+
+if STM32L4_TIM8_CHANNEL = 2
+
+config STM32L4_TIM8_CH2OUT
+	bool "TIM8 Channel 2 Output"
+	default n
+	---help---
+		Enables channel 2 output.
+
+config STM32L4_TIM8_CH2NOUT
+	bool "TIM8 Channel 2 Complementary Output"
+	default n
+	---help---
+		Enables channel 2 Complementary Output.
+
+endif # STM32L4_TIM8_CHANNEL = 2
+
+if STM32L4_TIM8_CHANNEL = 3
+
+config STM32L4_TIM8_CH3OUT
+	bool "TIM8 Channel 3 Output"
+	default n
+	---help---
+		Enables channel 3 output.
+
+config STM32L4_TIM8_CH3NOUT
+	bool "TIM8 Channel 3 Complementary Output"
+	default n
+	---help---
+		Enables channel 3 Complementary Output.
+
+endif # STM32L4_TIM8_CHANNEL = 3
+
+if STM32L4_TIM8_CHANNEL = 4
+
+config STM32L4_TIM8_CH4OUT
+	bool "TIM8 Channel 4 Output"
+	default n
+	---help---
+		Enables channel 4 output.
+
+endif # STM32L4_TIM8_CHANNEL = 4
+
+config STM32L4_TIM8_CHMODE
 	int "TIM8 Channel Mode"
-	default 0
-	range 0 5
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 endif # !STM32L4_PWM_MULTICHAN
 
@@ -2775,6 +3099,27 @@ config STM32L4_TIM15_PWM
 
 if STM32L4_TIM15_PWM
 
+config STM32L4_TIM15_LOCK
+	int "TIM15 Lock Level Configuration"
+	default 0
+	range 0 3
+	---help---
+		Timer 15 lock level configuration
+
+config STM32L4_TIM15_TDTS
+	int "TIM15 t_DTS Division"
+	default 0
+	range 0 2
+	---help---
+		Timer 15 dead-time and sampling clock (t_DTS) division
+
+config STM32L4_TIM15_DEADTIME
+	int "TIM15 Initial Dead-time"
+	default 0
+	range 0 255
+	---help---
+		Timer 15 initial dead-time
+
 if STM32L4_PWM_MULTICHAN
 
 config STM32L4_TIM15_CHANNEL1
@@ -2787,10 +3132,10 @@ if STM32L4_TIM15_CHANNEL1
 
 config STM32L4_TIM15_CH1MODE
 	int "TIM15 Channel 1 Mode"
-	default 0
-	range 0 3
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM15_CH1OUT
 	bool "TIM15 Channel 1 Output"
@@ -2817,10 +3162,10 @@ if STM32L4_TIM15_CHANNEL2
 
 config STM32L4_TIM15_CH2MODE
 	int "TIM15 Channel 2 Mode"
-	default 0
-	range 0 3
+	default 6
+	range 0 11
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM15_CH2OUT
 	bool "TIM15 Channel 2 Output"
@@ -2842,12 +3187,44 @@ config STM32L4_TIM15_CHANNEL
 		If TIM15 is enabled for PWM usage, you also need specifies the timer output
 		channel {1,2}
 
+if STM32L4_TIM15_CHANNEL = 1
+
+config STM32L4_TIM15_CH1OUT
+	bool "TIM15 Channel 1 Output"
+	default n
+	---help---
+		Enables channel 1 output.
+
+config STM32L4_TIM15_CH1NOUT
+	bool "TIM15 Channel 1 Complementary Output"
+	default n
+	---help---
+		Enables channel 1 Complementary Output.
+
+endif # STM32L4_TIM15_CHANNEL = 1
+
+if STM32L4_TIM15_CHANNEL = 2
+
+config STM32L4_TIM15_CH2OUT
+	bool "TIM15 Channel 2 Output"
+	default n
+	---help---
+		Enables channel 2 output.
+
+config STM32L4_TIM15_CH2NOUT
+	bool "TIM15 Channel 2 Complementary Output"
+	default n
+	---help---
+		Enables channel 2 Complementary Output.
+
+endif # STM32L4_TIM15_CHANNEL = 2
+
 config STM32L4_TIM15_CHMODE
 	int "TIM15 Channel Mode"
-	default 0
-	range 0 3
+	default 6
+	range 0 9
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 endif # !STM32L4_PWM_MULTICHAN
 
@@ -2868,6 +3245,27 @@ config STM32L4_TIM16_PWM
 
 if STM32L4_TIM16_PWM
 
+config STM32L4_TIM16_LOCK
+	int "TIM16 Lock Level Configuration"
+	default 0
+	range 0 3
+	---help---
+		Timer 16 lock level configuration
+
+config STM32L4_TIM16_TDTS
+	int "TIM16 t_DTS Division"
+	default 0
+	range 0 2
+	---help---
+		Timer 16 dead-time and sampling clock (t_DTS) division
+
+config STM32L4_TIM16_DEADTIME
+	int "TIM16 Initial Dead-time"
+	default 0
+	range 0 255
+	---help---
+		Timer 16 initial dead-time
+
 if STM32L4_PWM_MULTICHAN
 
 config STM32L4_TIM16_CHANNEL1
@@ -2880,10 +3278,10 @@ if STM32L4_TIM16_CHANNEL1
 
 config STM32L4_TIM16_CH1MODE
 	int "TIM16 Channel 1 Mode"
-	default 0
-	range 0 1
+	default 6
+	range 0 7
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM16_CH1OUT
 	bool "TIM16 Channel 1 Output"
@@ -2912,12 +3310,22 @@ config STM32L4_TIM16_CHANNEL
 		If TIM16 is enabled for PWM usage, you also need specifies the timer output
 		channel {1}
 
+if STM32L4_TIM16_CHANNEL = 1
+
+config STM32L4_TIM16_CH1OUT
+	bool "TIM16 Channel 1 Output"
+	default n
+	---help---
+		Enables channel 1 output.
+
+endif # STM32L4_TIM16_CHANNEL = 1
+
 config STM32L4_TIM16_CHMODE
 	int "TIM16 Channel Mode"
-	default 0
-	range 0 1
+	default 6
+	range 0 7
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 endif # !STM32L4_PWM_MULTICHAN
 
@@ -2938,6 +3346,27 @@ config STM32L4_TIM17_PWM
 
 if STM32L4_TIM17_PWM
 
+config STM32L4_TIM17_LOCK
+	int "TIM17 Lock Level Configuration"
+	default 0
+	range 0 3
+	---help---
+		Timer 17 lock level configuration
+
+config STM32L4_TIM17_TDTS
+	int "TIM17 t_DTS Division"
+	default 0
+	range 0 2
+	---help---
+		Timer 17 dead-time and sampling clock (t_DTS) division
+
+config STM32L4_TIM17_DEADTIME
+	int "TIM17 Initial Dead-time"
+	default 0
+	range 0 255
+	---help---
+		Timer 17 initial dead-time
+
 if STM32L4_PWM_MULTICHAN
 
 config STM32L4_TIM17_CHANNEL1
@@ -2950,10 +3379,10 @@ if STM32L4_TIM17_CHANNEL1
 
 config STM32L4_TIM17_CH1MODE
 	int "TIM17 Channel 1 Mode"
-	default 0
-	range 0 1
+	default 6
+	range 0 7
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 config STM32L4_TIM17_CH1OUT
 	bool "TIM17 Channel 1 Output"
@@ -2982,12 +3411,22 @@ config STM32L4_TIM17_CHANNEL
 		If TIM17 is enabled for PWM usage, you also need specifies the timer output
 		channel {1}
 
+if STM32_TIM17_CHANNEL = 1
+
+config STM32L4_TIM17_CH1OUT
+	bool "TIM17 Channel 1 Output"
+	default n
+	---help---
+		Enables channel 1 output.
+
+endif # STM32L4_TIM17_CHANNEL = 1
+
 config STM32L4_TIM17_CHMODE
 	int "TIM17 Channel Mode"
-	default 0
-	range 0 1
+	default 6
+	range 0 7
 	---help---
-		Specifies the channel mode.
+		Specifies the channel mode. See enum stm32l4_pwm_chanmode_e in stm32l4_pwm.h.
 
 endif # !STM32L4_PWM_MULTICHAN
 
@@ -3032,6 +3471,22 @@ config STM32L4_LPTIM1_CHANNEL
 		If LPTIM1 is enabled for PWM usage, you also need specifies the timer output
 		channel {1}
 
+if STM32L4_LPTIM1_CHANNEL = 1
+
+config STM32L4_LPTIM1_CH1OUT
+	bool "LPTIM1 Channel 1 Output"
+	default n
+	---help---
+		Enables channel 1 output.
+
+config STM32L4_LPTIM1_CH1NOUT
+	bool "LPTIM1 Channel 1 Complementary Output"
+	default n
+	---help---
+		Enables channel 1 Complementary Output.
+
+endif # STM32L4_LPTIM1_CHANNEL = 1
+
 endif # !STM32L4_PWM_MULTICHAN
 
 endif # STM32L4_LPTIM1_PWM
@@ -3075,6 +3530,22 @@ config STM32L4_LPTIM2_CHANNEL
 		If LPTIM2 is enabled for PWM usage, you also need specifies the timer output
 		channel {1}
 
+if STM32L4_LPTIM2_CHANNEL = 1
+
+config STM32L4_LPTIM2_CH1OUT
+	bool "LPTIM2 Channel 1 Output"
+	default n
+	---help---
+		Enables channel 1 output.
+
+config STM32L4_LPTIM2_CH1NOUT
+	bool "LPTIM2 Channel 1 Complementary Output"
+	default n
+	---help---
+		Enables channel 1 Complementary Output.
+
+endif # STM32L4_LPTIM2_CHANNEL = 1
+
 endif # !STM32L4_PWM_MULTICHAN
 
 endif # STM32L4_LPTIM2_PWM
@@ -3744,6 +4215,778 @@ config STM32L4_TIM8_CAP
 		Timer devices may be used for different purposes.  One special purpose is
 		to capture input.
 
+menu "STM32L4 TIMx Outputs Configuration"
+
+config STM32L4_TIM1_CH1POL
+	int "TIM1 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM1_CH1OUT
+	---help---
+		TIM1 Channel 1 output polarity
+
+config STM32L4_TIM1_CH1IDLE
+	int "TIM1 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM1_CH1OUT
+	---help---
+		TIM1 Channel 1 output IDLE
+
+config STM32L4_TIM1_CH1NPOL
+	int "TIM1 Channel 1 Complementary Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM1_CH1NOUT
+	---help---
+		TIM1 Channel 1 Complementary Output polarity
+
+config STM32L4_TIM1_CH1NIDLE
+	int "TIM1 Channel 1 Complementary Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM1_CH1NOUT
+	---help---
+		TIM1 Channel 1 Complementary Output IDLE
+
+config STM32L4_TIM1_CH2POL
+	int "TIM1 Channel 2 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM1_CH2OUT
+	---help---
+		TIM1 Channel 2 output polarity
+
+config STM32L4_TIM1_CH2IDLE
+	int "TIM1 Channel 2 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM1_CH2OUT
+	---help---
+		TIM1 Channel 2 output IDLE
+
+config STM32L4_TIM1_CH2NPOL
+	int "TIM1 Channel 2 Complementary Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM1_CH2NOUT
+	---help---
+		TIM1 Channel 2 Complementary Output polarity
+
+config STM32L4_TIM1_CH2NIDLE
+	int "TIM1 Channel 2 Complementary Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM1_CH2NOUT
+	---help---
+		TIM1 Channel 2 Complementary Output IDLE
+
+config STM32L4_TIM1_CH3POL
+	int "TIM1 Channel 3 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM1_CH3OUT
+	---help---
+		TIM1 Channel 3 output polarity
+
+config STM32L4_TIM1_CH3IDLE
+	int "TIM1 Channel 3 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM1_CH3OUT
+	---help---
+		TIM1 Channel 3 output IDLE
+
+config STM32L4_TIM1_CH3NPOL
+	int "TIM1 Channel 3 Complementary Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM1_CH3NOUT
+	---help---
+		TIM1 Channel 3 Complementary Output polarity
+
+config STM32L4_TIM1_CH3NIDLE
+	int "TIM1 Channel 3 Complementary Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM1_CH3NOUT
+	---help---
+		TIM1 Channel 3 Complementary Output IDLE
+
+config STM32L4_TIM1_CH4POL
+	int "TIM1 Channel 4 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM1_CH4OUT
+	---help---
+		TIM1 Channel 4 output polarity
+
+config STM32L4_TIM1_CH4IDLE
+	int "TIM1 Channel 4 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM1_CH4OUT
+	---help---
+		TIM1 Channel 4 output IDLE
+
+config STM32L4_TIM1_CH5POL
+	int "TIM1 Channel 5 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM1_CH5OUT
+	---help---
+		TIM1 Channel 5 output polarity
+
+config STM32L4_TIM1_CH5IDLE
+	int "TIM1 Channel 5 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM1_CH5OUT
+	---help---
+		TIM1 Channel 5 output IDLE
+
+config STM32L4_TIM1_CH6POL
+	int "TIM1 Channel 6 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM1_CH6OUT
+	---help---
+		TIM1 Channel 6 output polarity
+
+config STM32L4_TIM1_CH6IDLE
+	int "TIM1 Channel 6 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM1_CH6OUT
+	---help---
+		TIM1 Channel 6 output IDLE
+
+config STM32L4_TIM2_CH1POL
+	int "TIM2 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM2_CH1OUT
+	---help---
+		TIM2 Channel 1 output polarity
+
+config STM32L4_TIM2_CH1IDLE
+	int "TIM2 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM2_CH1OUT
+	---help---
+		TIM2 Channel 1 output IDLE
+
+config STM32L4_TIM2_CH2POL
+	int "TIM2 Channel 2 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM2_CH2OUT
+	---help---
+		TIM2 Channel 2 output polarity
+
+config STM32L4_TIM2_CH2IDLE
+	int "TIM2 Channel 2 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM2_CH2OUT
+	---help---
+		TIM2 Channel 2 output IDLE
+
+config STM32L4_TIM2_CH3POL
+	int "TIM2 Channel 3 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM2_CH3OUT
+	---help---
+		TIM2 Channel 3 output polarity
+
+config STM32L4_TIM2_CH3IDLE
+	int "TIM2 Channel 3 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM2_CH3OUT
+	---help---
+		TIM2 Channel 3 output IDLE
+
+config STM32L4_TIM2_CH4POL
+	int "TIM2 Channel 4 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM2_CH4OUT
+	---help---
+		TIM2 Channel 4 output polarity
+
+config STM32L4_TIM2_CH4IDLE
+	int "TIM2 Channel 4 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM2_CH4OUT
+	---help---
+		TIM2 Channel 4 output IDLE
+
+config STM32L4_TIM3_CH1POL
+	int "TIM3 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM3_CH1OUT
+	---help---
+		TIM3 Channel 1 output polarity
+
+config STM32L4_TIM3_CH1IDLE
+	int "TIM3 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM3_CH1OUT
+	---help---
+		TIM3 Channel 1 output IDLE
+
+config STM32L4_TIM3_CH2POL
+	int "TIM3 Channel 2 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM3_CH2OUT
+	---help---
+		TIM3 Channel 2 output polarity
+
+config STM32L4_TIM3_CH2IDLE
+	int "TIM3 Channel 2 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM3_CH2OUT
+	---help---
+		TIM3 Channel 2 output IDLE
+
+config STM32L4_TIM3_CH3POL
+	int "TIM3 Channel 3 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM3_CH3OUT
+	---help---
+		TIM3 Channel 3 output polarity
+
+config STM32L4_TIM3_CH3IDLE
+	int "TIM3 Channel 3 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM3_CH3OUT
+	---help---
+		TIM3 Channel 3 output IDLE
+
+config STM32L4_TIM3_CH4POL
+	int "TIM3 Channel 4 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM3_CH4OUT
+	---help---
+		TIM3 Channel 4 output polarity
+
+config STM32L4_TIM3_CH4IDLE
+	int "TIM3 Channel 4 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM3_CH4OUT
+	---help---
+		TIM3 Channel 4 output IDLE
+
+config STM32L4_TIM4_CH1POL
+	int "TIM4 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM4_CH1OUT
+	---help---
+		TIM4 Channel 1 output polarity
+
+config STM32L4_TIM4_CH1IDLE
+	int "TIM4 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM4_CH1OUT
+	---help---
+		TIM4 Channel 1 output IDLE
+
+config STM32L4_TIM4_CH2POL
+	int "TIM4 Channel 2 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM4_CH2OUT
+	---help---
+		TIM4 Channel 2 output polarity
+
+config STM32L4_TIM4_CH2IDLE
+	int "TIM4 Channel 2 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM4_CH2OUT
+	---help---
+		TIM4 Channel 2 output IDLE
+
+config STM32L4_TIM4_CH3POL
+	int "TIM4 Channel 3 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM4_CH3OUT
+	---help---
+		TIM4 Channel 3 output polarity
+
+config STM32L4_TIM4_CH3IDLE
+	int "TIM4 Channel 3 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM4_CH3OUT
+	---help---
+		TIM4 Channel 3 output IDLE
+
+config STM32L4_TIM4_CH4POL
+	int "TIM4 Channel 4 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM4_CH4OUT
+	---help---
+		TIM4 Channel 4 output polarity
+
+config STM32L4_TIM4_CH4IDLE
+	int "TIM4 Channel 4 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM4_CH4OUT
+	---help---
+		TIM4 Channel 4 output IDLE
+
+config STM32L4_TIM5_CH1POL
+	int "TIM5 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM5_CH1OUT
+	---help---
+		TIM5 Channel 1 output polarity
+
+config STM32L4_TIM5_CH1IDLE
+	int "TIM5 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM5_CH1OUT
+	---help---
+		TIM5 Channel 1 output IDLE
+
+config STM32L4_TIM5_CH2POL
+	int "TIM5 Channel 2 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM5_CH2OUT
+	---help---
+		TIM5 Channel 2 output polarity
+
+config STM32L4_TIM5_CH2IDLE
+	int "TIM5 Channel 2 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM5_CH2OUT
+	---help---
+		TIM5 Channel 2 output IDLE
+
+config STM32L4_TIM5_CH3POL
+	int "TIM5 Channel 3 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM5_CH3OUT
+	---help---
+		TIM5 Channel 3 output polarity
+
+config STM32L4_TIM5_CH3IDLE
+	int "TIM5 Channel 3 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM5_CH3OUT
+	---help---
+		TIM5 Channel 3 output IDLE
+
+config STM32L4_TIM5_CH4POL
+	int "TIM5 Channel 4 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM5_CH4OUT
+	---help---
+		TIM5 Channel 4 output polarity
+
+config STM32L4_TIM5_CH4IDLE
+	int "TIM5 Channel 4 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM5_CH4OUT
+	---help---
+		TIM5 Channel 4 output IDLE
+
+config STM32L4_TIM8_CH1POL
+	int "TIM8 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM8_CH1OUT
+	---help---
+		TIM8 Channel 1 output polarity
+
+config STM32L4_TIM8_CH1IDLE
+	int "TIM8 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM8_CH1OUT
+	---help---
+		TIM8 Channel 1 output IDLE
+
+config STM32L4_TIM8_CH1NPOL
+	int "TIM8 Channel 1 Complementary Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM8_CH1NOUT
+	---help---
+		TIM8 Channel 1 Complementary Output polarity
+
+config STM32L4_TIM8_CH1NIDLE
+	int "TIM8 Channel 1 Complementary Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM8_CH1NOUT
+	---help---
+		TIM8 Channel 1 Complementary Output IDLE
+
+config STM32L4_TIM8_CH2POL
+	int "TIM8 Channel 2 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM8_CH2OUT
+	---help---
+		TIM8 Channel 2 output polarity
+
+config STM32L4_TIM8_CH2IDLE
+	int "TIM8 Channel 2 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM8_CH2OUT
+	---help---
+		TIM8 Channel 2 output IDLE
+
+config STM32L4_TIM8_CH2NPOL
+	int "TIM8 Channel 2 Complementary Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM8_CH2NOUT
+	---help---
+		TIM8 Channel 2 Complementary Output polarity
+
+config STM32L4_TIM8_CH2NIDLE
+	int "TIM8 Channel 2 Complementary Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM8_CH2NOUT
+	---help---
+		TIM8 Channel 2 Complementary Output IDLE
+
+config STM32L4_TIM8_CH3POL
+	int "TIM8 Channel 3 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM8_CH3OUT
+	---help---
+		TIM8 Channel 3 output polarity
+
+config STM32L4_TIM8_CH3IDLE
+	int "TIM8 Channel 3 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM8_CH3OUT
+	---help---
+		TIM8 Channel 3 output IDLE
+
+config STM32L4_TIM8_CH3NPOL
+	int "TIM8 Channel 3 Complementary Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM8_CH3NOUT
+	---help---
+		TIM8 Channel 3 Complementary Output polarity
+
+config STM32L4_TIM8_CH3NIDLE
+	int "TIM8 Channel 3 Complementary Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM8_CH3NOUT
+	---help---
+		TIM8 Channel 3 Complementary Output IDLE
+
+config STM32L4_TIM8_CH4POL
+	int "TIM8 Channel 4 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM8_CH4OUT
+	---help---
+		TIM8 Channel 4 output polarity
+
+config STM32L4_TIM8_CH4IDLE
+	int "TIM8 Channel 4 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM8_CH4OUT
+	---help---
+		TIM8 Channel 4 output IDLE
+
+config STM32L4_TIM8_CH5POL
+	int "TIM8 Channel 5 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM8_CH5OUT
+	---help---
+		TIM8 Channel 5 output polarity
+
+config STM32L4_TIM8_CH5IDLE
+	int "TIM8 Channel 5 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM8_CH5OUT
+	---help---
+		TIM8 Channel 5 output IDLE
+
+config STM32L4_TIM8_CH6POL
+	int "TIM8 Channel 6 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM8_CH6OUT
+	---help---
+		TIM8 Channel 6 output polarity
+
+config STM32L4_TIM8_CH6IDLE
+	int "TIM8 Channel 6 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM8_CH6OUT
+	---help---
+		TIM8 Channel 6 output IDLE
+
+config STM32L4_TIM9_CH1POL
+	int "TIM9 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM9_CH1OUT
+	---help---
+		TIM9 Channel 1 output polarity
+
+config STM32L4_TIM9_CH1IDLE
+	int "TIM9 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM9_CH1OUT
+	---help---
+		TIM9 Channel 1 output IDLE
+
+config STM32L4_TIM9_CH2POL
+	int "TIM9 Channel 2 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM9_CH2OUT
+	---help---
+		TIM9 Channel 2 output polarity
+
+config STM32L4_TIM9_CH2IDLE
+	int "TIM9 Channel 2 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM9_CH2OUT
+	---help---
+		TIM9 Channel 2 output IDLE
+
+config STM32L4_TIM10_CH1POL
+	int "TIM10 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM10_CH1OUT
+	---help---
+		TIM10 Channel 1 output polarity
+
+config STM32L4_TIM10_CH1IDLE
+	int "TIM10 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM10_CH1OUT
+	---help---
+		TIM10 Channel 1 output IDLE
+
+config STM32L4_TIM11_CH1POL
+	int "TIM11 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM11_CH1OUT
+	---help---
+		TIM11 Channel 1 output polarity
+
+config STM32L4_TIM11_CH1IDLE
+	int "TIM11 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM11_CH1OUT
+	---help---
+		TIM11 Channel 1 output IDLE
+
+config STM32L4_TIM12_CH1POL
+	int "TIM12 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM12_CH1OUT
+	---help---
+		TIM12 Channel 1 output polarity
+
+config STM32L4_TIM12_CH1IDLE
+	int "TIM12 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM12_CH1OUT
+	---help---
+		TIM12 Channel 1 output IDLE
+
+config STM32L4_TIM12_CH2POL
+	int "TIM12 Channel 2 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM12_CH2OUT
+	---help---
+		TIM12 Channel 2 output polarity
+
+config STM32L4_TIM12_CH2IDLE
+	int "TIM12 Channel 2 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM12_CH2OUT
+	---help---
+		TIM12 Channel 2 output IDLE
+
+config STM32L4_TIM13_CH1POL
+	int "TIM13 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM13_CH1OUT
+	---help---
+		TIM13 Channel 1 output polarity
+
+config STM32L4_TIM13_CH1IDLE
+	int "TIM13 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM13_CH1OUT
+	---help---
+		TIM13 Channel 1 output IDLE
+
+config STM32L4_TIM14_CH1POL
+	int "TIM14 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM14_CH1OUT
+	---help---
+		TIM14 Channel 1 output polarity
+
+config STM32L4_TIM14_CH1IDLE
+	int "TIM14 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM14_CH1OUT
+	---help---
+		TIM14 Channel 1 output IDLE
+
+config STM32L4_TIM15_CH1POL
+	int "TIM15 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM15_CH1OUT
+	---help---
+		TIM15 Channel 1 output polarity
+
+config STM32L4_TIM15_CH1IDLE
+	int "TIM15 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM15_CH1OUT
+	---help---
+		TIM15 Channel 1 output IDLE
+
+config STM32L4_TIM15_CH1NPOL
+	int "TIM15 Channel 1 Complementary Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM15_CH1NOUT
+	---help---
+		TIM15 Channel 1 Complementary Output polarity
+
+config STM32L4_TIM15_CH1NIDLE
+	int "TIM15 Channel 1 Complementary Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM15_CH1NOUT
+	---help---
+		TIM15 Channel 1 Complementary Output IDLE
+
+config STM32L4_TIM15_CH2POL
+	int "TIM15 Channel 2 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM15_CH2OUT
+	---help---
+		TIM15 Channel 2 output polarity
+
+config STM32L4_TIM15_CH2IDLE
+	int "TIM15 Channel 2 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM15_CH2OUT
+	---help---
+		TIM15 Channel 2 output IDLE
+
+config STM32L4_TIM15_CH2NPOL
+	int "TIM15 Channel 2 Complementary Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM15_CH2NOUT
+	---help---
+		TIM15 Channel 2 Complementary Output polarity
+
+config STM32L4_TIM15_CH2NIDLE
+	int "TIM15 Channel 2 Complementary Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM15_CH2NOUT
+	---help---
+		TIM15 Channel 2 Complementary Output IDLE
+
+config STM32L4_TIM16_CH1POL
+	int "TIM16 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM16_CH1OUT
+	---help---
+		TIM16 Channel 1 output polarity
+
+config STM32L4_TIM16_CH1IDLE
+	int "TIM16 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM16_CH1OUT
+	---help---
+		TIM16 Channel 1 output IDLE
+
+config STM32L4_TIM17_CH1POL
+	int "TIM17 Channel 1 Output polarity"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM17_CH1OUT
+	---help---
+		TIM17 Channel 1 output polarity
+
+config STM32L4_TIM17_CH1IDLE
+	int "TIM17 Channel 1 Output IDLE"
+	default 0
+	range 0 1
+	depends on STM32L4_TIM17_CH1OUT
+	---help---
+		TIM17 Channel 1 output IDLE
+
+endmenu #STM32L4 TIMx Outputs Configuration
+
 endmenu # Timer Configuration
 
 menu "ADC Configuration"
diff --git a/arch/arm/src/stm32l4/stm32l4_pwm.c b/arch/arm/src/stm32l4/stm32l4_pwm.c
index 84b36eb..d9d34e9 100644
--- a/arch/arm/src/stm32l4/stm32l4_pwm.c
+++ b/arch/arm/src/stm32l4/stm32l4_pwm.c
@@ -77,12 +77,15 @@
 
 /* The following definitions are used to identify the various time types */
 
-#define TIMTYPE_BASIC      0  /* Basic timers: TIM6,7 */
-#define TIMTYPE_GENERAL16  1  /* General 16-bit timers: TIM3,4 */
-#define TIMTYPE_COUNTUP16  2  /* General 16-bit count-up timers: TIM15-17 */
-#define TIMTYPE_GENERAL32  3  /* General 32-bit timers: TIM2,5 */
-#define TIMTYPE_ADVANCED   4  /* Advanced timers:  TIM1,8 */
-#define TIMTYPE_LOWPOWER   5  /* Low Power timers: LPTIM1,2 */
+#define TIMTYPE_BASIC        0  /* Basic timers: TIM6,7 */
+#define TIMTYPE_GENERAL16    1  /* General 16-bit timers: TIM3,4 */
+#define TIMTYPE_COUNTUP16    2  /* General 16-bit count-up timers: TIM15-17 */
+#define TIMTYPE_COUNTUP16_N  3  /* General 16-bit count-up timers with
+                                 * complementary outptus
+                                 */
+#define TIMTYPE_GENERAL32    4  /* General 32-bit timers: TIM2,5 */
+#define TIMTYPE_ADVANCED     5  /* Advanced timers:  TIM1,8 */
+#define TIMTYPE_LOWPOWER     6  /* Low Power timers: LPTIM1,2 */
 
 #define TIMTYPE_TIM1       TIMTYPE_ADVANCED
 #define TIMTYPE_TIM2       TIMTYPE_GENERAL32
@@ -92,12 +95,60 @@
 #define TIMTYPE_TIM6       TIMTYPE_BASIC
 #define TIMTYPE_TIM7       TIMTYPE_BASIC
 #define TIMTYPE_TIM8       TIMTYPE_ADVANCED
-#define TIMTYPE_TIM15      TIMTYPE_COUNTUP16
-#define TIMTYPE_TIM16      TIMTYPE_COUNTUP16
-#define TIMTYPE_TIM17      TIMTYPE_COUNTUP16
+#define TIMTYPE_TIM15      TIMTYPE_COUNTUP16_N /* Treated as ADVTIM */
+#define TIMTYPE_TIM16      TIMTYPE_COUNTUP16_N /* Treated as ADVTIM */
+#define TIMTYPE_TIM17      TIMTYPE_COUNTUP16_N /* Treated as ADVTIM */
 #define TIMTYPE_LPTIM1     TIMTYPE_LOWPOWER
 #define TIMTYPE_LPTIM2     TIMTYPE_LOWPOWER
 
+/* Advanced Timer support
+ * NOTE: TIM15-17 are not ADVTIM but they support most of the
+ *       ADVTIM functionality.  The main difference is the number of
+ *       supported capture/compare.
+ */
+
+#if defined(CONFIG_STM32L4_TIM1_PWM) || defined(CONFIG_STM32L4_TIM8_PWM) || \
+    defined(CONFIG_STM32L4_TIM15_PWM) || defined(CONFIG_STM32L4_TIM16_PWM) || \
+    defined(CONFIG_STM32L4_TIM17_PWM)
+#  define HAVE_ADVTIM
+#else
+#  undef HAVE_ADVTIM
+#endif
+
+/* Low power Timer support */
+
+#if defined(CONFIG_STM32L4_LPTIM1_PWM) || defined(CONFIG_STM32L4_LPTIM2_PWM)
+#  define HAVE_LPTIM
+#else
+#  undef HAVE_LPTIM
+#endif
+
+/* Pulsecount support */
+
+#ifdef CONFIG_PWM_PULSECOUNT
+#  ifndef HAVE_ADVTIM
+#    error "PWM_PULSECOUNT requires HAVE_ADVTIM"
+#  endif
+#  if defined(CONFIG_STM32L4_TIM1_PWM) || defined(CONFIG_STM32L4_TIM8_PWM)
+#    define HAVE_PWM_INTERRUPT
+#  endif
+#endif
+
+/* Synchronisation support */
+
+#ifdef CONFIG_STM32L4_PWM_TRGO
+#  define HAVE_TRGO
+#endif
+
+/* Break support */
+
+#if defined(CONFIG_STM32L4_TIM1_BREAK1) || defined(CONFIG_STM32L4_TIM1_BREAK2) || \
+    defined(CONFIG_STM32L4_TIM8_BREAK1) || defined(CONFIG_STM32L4_TIM8_BREAK2) || \
+    defined(CONFIG_STM32L4_TIM15_BREAK1) || defined(CONFIG_STM32L4_TIM16_BREAK1) || \
+    defined(CONFIG_STM32L4_TIM17_BREAK1)
+#  defined HAVE_BREAK
+#endif
+
 /* Debug ********************************************************************/
 
 #ifdef CONFIG_DEBUG_PWM_INFO
@@ -110,44 +161,56 @@
  * Private Types
  ****************************************************************************/
 
-enum stm32l4_timmode_e
-{
-  STM32L4_TIMMODE_COUNTUP   = 0,
-  STM32L4_TIMMODE_COUNTDOWN = 1,
-  STM32L4_TIMMODE_CENTER1   = 2,
-  STM32L4_TIMMODE_CENTER2   = 3,
-  STM32L4_TIMMODE_CENTER3   = 4,
-};
+/* PWM output configuration */
 
-enum stm32l4_chanmode_e
+struct stm32l4_pwm_out_s
 {
-  STM32L4_CHANMODE_PWM1        = 0,
-  STM32L4_CHANMODE_PWM2        = 1,
-  STM32L4_CHANMODE_COMBINED1   = 2,
-  STM32L4_CHANMODE_COMBINED2   = 3,
-  STM32L4_CHANMODE_ASYMMETRIC1 = 4,
-  STM32L4_CHANMODE_ASYMMETRIC2 = 5,
+  uint8_t  in_use:1;                    /* Output in use */
+  uint8_t  pol:1;                       /* Polarity. Default: positive */
+  uint8_t  idle:1;                      /* Idle state. Default: inactive */
+  uint8_t  _res:5;                      /* Reserved */
+  uint32_t pincfg;                      /* Output pin configuration */
 };
 
+/* PWM channel configuration */
+
 struct stm32l4_pwmchan_s
 {
-  uint8_t channel;                     /* Timer output channel: {1,..4} */
-  enum stm32l4_chanmode_e mode;
-  uint32_t pincfg;                     /* Output pin configuration */
-  uint32_t npincfg;                    /* Complementary output pin configuration
-                                        * (only TIM1,8 CH1-3 and TIM15,16,17 CH1)
-                                        */
+  uint8_t                  channel:4;   /* Timer output channel: {1,..4} */
+  uint8_t                  mode:4;      /* PWM channel mode (see stm32l4_pwm_chanmode_e) */
+  struct stm32l4_pwm_out_s   out1;        /* PWM output configuration */
+#ifdef HAVE_BREAK
+  struct stm32l4_pwm_break_s brk;         /* PWM break configuration */
+#endif
+#ifdef HAVE_PWM_COMPLEMENTARY
+  struct stm32l4_pwm_out_s   out2;        /* PWM complementary output configuration */
+#endif
 };
 
 /* This structure represents the state of one PWM timer */
 
 struct stm32l4_pwmtimer_s
 {
-  FAR const struct pwm_ops_s *ops;     /* PWM operations */
-  struct stm32l4_pwmchan_s channels[PWM_NCHANNELS];
-  uint8_t timid;                       /* Timer ID {1,...,17} */
-  uint8_t timtype;                     /* See the TIMTYPE_* definitions */
-  enum stm32l4_timmode_e mode;
+  FAR const struct pwm_ops_s *ops;      /* PWM operations */
+#ifdef CONFIG_STM32L4_PWM_LL_OPS
+  FAR const struct stm32l4_pwm_ops_s *llops; /* Low-level PWM ops */
+#endif  
+  FAR struct stm32l4_pwmchan_s *channels; /* Channels configuration */
+  uint8_t  timid:5;                     /* Timer ID {1,...,17} */
+  uint8_t  chan_num:3;                  /* Number of configured channels */
+  uint8_t  timtype:3;                   /* See the TIMTYPE_* definitions */
+  uint8_t  mode:3;                      /* Timer mode (see stm32l4_pwm_tim_mode_e) */
+  uint8_t  lock:2;                      /* TODO: Lock configuration */
+  uint8_t  t_dts:3;                     /* Clock division for t_DTS */
+  uint8_t  _res:5;                      /* Reserved */
+#ifdef HAVE_PWM_COMPLEMENTARY
+  uint8_t  deadtime;                    /* Dead-time value */
+#endif
+#ifdef HAVE_TRGO
+  uint8_t  trgo;                        /* TRGO configuration:
+                                         * 4 LSB = TRGO, 4 MSB = TRGO2
+                                         */
+#endif  
 #ifdef CONFIG_PWM_PULSECOUNT
   uint8_t irq;                         /* Timer update IRQ */
   uint8_t prev;                        /* The previous value of the RCR (pre-loaded) */
@@ -157,7 +220,7 @@ struct stm32l4_pwmtimer_s
   uint32_t frequency;                  /* Current frequency setting */
 #endif
   uint32_t base;                       /* The base address of the timer */
-  uint32_t pclk;                       /* The frequency of the peripheral clock
+  uint32_t pclk;                       /* Frequency of the peripheral clock
                                         * that drives the timer module. */
 #ifdef CONFIG_PWM_PULSECOUNT
   FAR void *handle;                    /* Handle used for upper-half callback */
@@ -170,55 +233,84 @@ struct stm32l4_pwmtimer_s
 
 /* Register access */
 
-static uint16_t stm32l4pwm_getreg(struct stm32l4_pwmtimer_s *priv,
-                                  int offset);
-static void stm32l4pwm_putreg(struct stm32l4_pwmtimer_s *priv, int offset,
-                              uint16_t value);
+static uint16_t pwm_getreg(struct stm32l4_pwmtimer_s *priv, int offset);
+static void pwm_putreg(struct stm32l4_pwmtimer_s *priv, int offset,
+                       uint16_t value);
+static void pwm_modifyreg(struct stm32l4_pwmtimer_s *priv, uint32_t offset,
+                          uint32_t clearbits, uint32_t setbits);
 
 #ifdef CONFIG_DEBUG_PWM_INFO
-static void stm32l4pwm_dumpregs(struct stm32l4_pwmtimer_s *priv,
-                                const char *msg);
+static void pwm_dumpregs(FAR struct pwm_lowerhalf_s *dev,
+                         FAR const char *msg);
 #else
-#  define stm32l4pwm_dumpregs(priv,msg)
+#  define pwm_dumpregs(priv,msg)
 #endif
 
 /* Timer management */
 
-static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv,
-                            FAR const struct pwm_info_s *info);
-
-static int stm32l4pwm_lptimer(FAR struct stm32l4_pwmtimer_s *priv,
-                              FAR const struct pwm_info_s *info);
-
-#if defined(CONFIG_PWM_PULSECOUNT) && (defined(CONFIG_STM32L4_TIM1_PWM) || \
-    defined(CONFIG_STM32L4_TIM8_PWM))
-static int stm32l4pwm_interrupt(struct stm32l4_pwmtimer_s *priv);
-#if defined(CONFIG_STM32L4_TIM1_PWM)
-static int stm32l4pwm_tim1interrupt(int irq, void *context, FAR void *arg);
+#ifdef CONFIG_PWM_PULSECOUNT
+static int pwm_pulsecount_timer(FAR struct pwm_lowerhalf_s *dev,
+                                FAR const struct pwm_info_s *info);
+#else
+static int pwm_timer(FAR struct pwm_lowerhalf_s *dev,
+                     FAR const struct pwm_info_s *info);
+#  ifdef HAVE_LPTIM
+static int pwm_lptimer(FAR struct pwm_lowerhalf_s *dev,
+                       FAR const struct pwm_info_s *info);
+#  endif
+static int pwm_configure(FAR struct pwm_lowerhalf_s *dev);
+#endif
+static int pwm_soft_break(FAR struct pwm_lowerhalf_s *dev, bool state); /* REVISIT: valid for all timers? */
+static int pwm_ccr_update(FAR struct pwm_lowerhalf_s *dev, uint8_t index,
+                          uint32_t ccr);
+static int pwm_mode_configure(FAR struct pwm_lowerhalf_s *dev,
+                              uint8_t channel, uint32_t mode);
+#ifdef CONFIG_STM32L4_PWM_LL_OPS
+static uint32_t pwm_ccr_get(FAR struct pwm_lowerhalf_s *dev, uint8_t index);
+#endif
+static int pwm_arr_update(FAR struct pwm_lowerhalf_s *dev, uint32_t arr);
+static uint32_t pwm_arr_get(FAR struct pwm_lowerhalf_s *dev);
+static int pwm_outputs_enable(FAR struct pwm_lowerhalf_s *dev,
+                              uint16_t outputs, bool state);
+static int pwm_soft_update(FAR struct pwm_lowerhalf_s *dev);
+static int pwm_frequency_update(FAR struct pwm_lowerhalf_s *dev,
+                                uint32_t frequency);
+static int pwm_timer_enable(FAR struct pwm_lowerhalf_s *dev, bool state);
+#if defined(HAVE_PWM_COMPLEMENTARY) && defined(CONFIG_STM32L4_PWM_LL_OPS)
+static int pwm_deadtime_update(FAR struct pwm_lowerhalf_s *dev, uint8_t dt);
 #endif
-#if defined(CONFIG_STM32L4_TIM8_PWM)
-static int stm32l4pwm_tim8interrupt(int irq, void *context, FAR void *arg);
+#ifdef CONFIG_STM32L4_PWM_LL_OPS
+static uint32_t pwm_ccr_get(FAR struct pwm_lowerhalf_s *dev, uint8_t index);
 #endif
-static uint8_t stm32l4pwm_pulsecount(uint32_t count);
+
+#ifdef HAVE_PWM_INTERRUPT
+static int pwm_interrupt(FAR struct pwm_lowerhalf_s *dev);
+#  ifdef CONFIG_STM32L4_TIM1_PWM
+static int pwm_tim1interrupt(int irq, void *context, FAR void *arg);
+#  endif
+#  ifdef CONFIG_STM32L4_TIM8_PWM
+static int pwm_tim8interrupt(int irq, void *context, FAR void *arg);
+#  endif
+static uint8_t pwm_pulsecount(uint32_t count);
 #endif
 
 /* PWM driver methods */
 
-static int stm32l4pwm_setup(FAR struct pwm_lowerhalf_s *dev);
-static int stm32l4pwm_shutdown(FAR struct pwm_lowerhalf_s *dev);
+static int pwm_setup(FAR struct pwm_lowerhalf_s *dev);
+static int pwm_shutdown(FAR struct pwm_lowerhalf_s *dev);
 
 #ifdef CONFIG_PWM_PULSECOUNT
-static int stm32l4pwm_start(FAR struct pwm_lowerhalf_s *dev,
-                            FAR const struct pwm_info_s *info,
-                            FAR void *handle);
+static int pwm_start(FAR struct pwm_lowerhalf_s *dev,
+                     FAR const struct pwm_info_s *info,
+                     FAR void *handle);
 #else
-static int stm32l4pwm_start(FAR struct pwm_lowerhalf_s *dev,
-                            FAR const struct pwm_info_s *info);
+static int pwm_start(FAR struct pwm_lowerhalf_s *dev,
+                     FAR const struct pwm_info_s *info);
 #endif
 
-static int stm32l4pwm_stop(FAR struct pwm_lowerhalf_s *dev);
-static int stm32l4pwm_ioctl(FAR struct pwm_lowerhalf_s *dev,
-                            int cmd, unsigned long arg);
+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);
 
 /****************************************************************************
  * Private Data
@@ -230,416 +322,1032 @@ static int stm32l4pwm_ioctl(FAR struct pwm_lowerhalf_s *dev,
 
 static const struct pwm_ops_s g_pwmops =
 {
-  .setup       = stm32l4pwm_setup,
-  .shutdown    = stm32l4pwm_shutdown,
-  .start       = stm32l4pwm_start,
-  .stop        = stm32l4pwm_stop,
-  .ioctl       = stm32l4pwm_ioctl,
+  .setup       = pwm_setup,
+  .shutdown    = pwm_shutdown,
+  .start       = pwm_start,
+  .stop        = pwm_stop,
+  .ioctl       = pwm_ioctl,
+};
+
+#ifdef CONFIG_STM32L4_PWM_LL_OPS
+static const struct stm32l4_pwm_ops_s g_llpwmops =
+{
+  .configure       = pwm_configure,
+  .soft_break      = pwm_soft_break,
+  .ccr_update      = pwm_ccr_update,
+  .mode_update     = pwm_mode_configure,
+  .ccr_get         = pwm_ccr_get,
+  .arr_update      = pwm_arr_update,
+  .arr_get         = pwm_arr_get,
+  .outputs_enable  = pwm_outputs_enable,
+  .soft_update     = pwm_soft_update,
+  .freq_update     = pwm_frequency_update,
+  .tim_enable      = pwm_timer_enable,
+#  ifdef CONFIG_DEBUG_PWM_INFO
+  .dump_regs       = pwm_dumpregs,
+#  endif
+#  ifdef HAVE_PWM_COMPLEMENTARY
+  .dt_update       = pwm_deadtime_update,
+#  endif
 };
+#endif
 
 #ifdef CONFIG_STM32L4_TIM1_PWM
-static struct stm32l4_pwmtimer_s g_pwm1dev =
+
+static struct stm32l4_pwmchan_s g_pwm1channels[] =
 {
-  .ops         = &g_pwmops,
-  .timid       = 1,
-  .channels    =
-  {
+  /* TIM1 has 4 channels, 4 complementary */
+
 #ifdef CONFIG_STM32L4_TIM1_CHANNEL1
+  {
+    .channel = 1,
+    .mode    = CONFIG_STM32L4_TIM1_CH1MODE,
+#ifdef HAVE_BREAK
+    .brk =
+    {
+#ifdef CONFIG_STM32L4_TIM1_BREAK1
+      .en1 = 1,
+      .pol1 = CONFIG_STM32L4_TIM1_BRK1POL,
+#endif
+#ifdef CONFIG_STM32L4_TIM1_BREAK2
+      .en2 = 1,
+      .pol2 = CONFIG_STM32L4_TIM1_BRK2POL,
+      .flt2 = CONFIG_STM32L4_TIM1_BRK2FLT,
+#endif
+    },
+#endif
+#ifdef CONFIG_STM32L4_TIM1_CH1OUT
+    .out1 =
     {
-      .channel = 1,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM1_CH1POL,
+      .idle    = CONFIG_STM32L4_TIM1_CH1IDLE,
       .pincfg  = PWM_TIM1_CH1CFG,
-      .mode    = CONFIG_STM32L4_TIM1_CH1MODE,
-      .npincfg = PWM_TIM1_CH1NCFG,
     },
 #endif
+#ifdef CONFIG_STM32L4_TIM1_CH1NOUT
+    .out2 =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM1_CH1NPOL,
+      .idle    = CONFIG_STM32L4_TIM1_CH1NIDLE,
+      .pincfg  = PWM_TIM1_CH1NCFG,
+    }
+#endif
+  },
+#endif
 #ifdef CONFIG_STM32L4_TIM1_CHANNEL2
+  {
+    .channel = 2,
+    .mode    = CONFIG_STM32L4_TIM1_CH2MODE,
+#ifdef CONFIG_STM32L4_TIM1_CH2OUT
+    .out1 =
     {
-      .channel = 2,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM1_CH2POL,
+      .idle    = CONFIG_STM32L4_TIM1_CH2IDLE,
       .pincfg  = PWM_TIM1_CH2CFG,
-      .mode    = CONFIG_STM32L4_TIM1_CH2MODE,
-      .npincfg = PWM_TIM1_CH2NCFG,
     },
 #endif
+#ifdef CONFIG_STM32L4_TIM1_CH2NOUT
+    .out2 =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM1_CH2NPOL,
+      .idle    = CONFIG_STM32L4_TIM1_CH2NIDLE,
+      .pincfg  = PWM_TIM1_CH2NCFG,
+    }
+#endif
+  },
+#endif
 #ifdef CONFIG_STM32L4_TIM1_CHANNEL3
+  {
+    .channel = 3,
+    .mode    = CONFIG_STM32L4_TIM1_CH3MODE,
+#ifdef CONFIG_STM32L4_TIM1_CH3OUT
+    .out1 =
     {
-      .channel = 3,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM1_CH3POL,
+      .idle    = CONFIG_STM32L4_TIM1_CH3IDLE,
       .pincfg  = PWM_TIM1_CH3CFG,
-      .mode    = CONFIG_STM32L4_TIM1_CH3MODE,
-      .npincfg = PWM_TIM1_CH3NCFG,
     },
 #endif
+#ifdef CONFIG_STM32L4_TIM1_CH3NOUT
+    .out2 =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM1_CH3NPOL,
+      .idle    = CONFIG_STM32L4_TIM1_CH3NIDLE,
+      .pincfg  = PWM_TIM1_CH3NCFG,
+    }
+#endif
+  },
+#endif
 #ifdef CONFIG_STM32L4_TIM1_CHANNEL4
+  {
+    .channel = 4,
+    .mode    = CONFIG_STM32L4_TIM1_CH4MODE,
+#ifdef CONFIG_STM32L4_TIM1_CH4OUT
+    .out1 =
     {
-      .channel = 4,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4L4_TIM1_CH4POL,
+      .idle    = CONFIG_STM32L4L4_TIM1_CH4IDLE,
       .pincfg  = PWM_TIM1_CH4CFG,
-      .mode    = CONFIG_STM32L4_TIM1_CH4MODE,
-      .npincfg = 0,
-    },
+    }
+#endif
+  },
+#endif
+#ifdef CONFIG_STM32L4_TIM1_CHANNEL5
+  {
+    .channel = 5,
+    .mode    = CONFIG_STM32L4_TIM1_CH5MODE,
+#ifdef CONFIG_STM32L4_TIM1_CH5OUT
+    .out1 =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM1_CH5POL,
+      .idle    = CONFIG_STM32L4_TIM1_CH5IDLE,
+      .pincfg  = 0,    /* No available externaly */
+    }
 #endif
   },
+#endif
+#ifdef CONFIG_STM32L4_TIM1_CHANNEL6
+  {
+    .channel = 6,
+    .mode    = CONFIG_STM32L4_TIM1_CH6MODE,
+#ifdef CONFIG_STM32L4_TIM1_CH6OUT
+    .out1 =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM1_CH6POL,
+      .idle    = CONFIG_STM32L4_TIM1_CH6IDLE,
+      .pincfg  = 0,    /* No available externaly */
+    }
+#endif
+  }
+#endif
+};
+
+static struct stm32l4_pwmtimer_s g_pwm1dev =
+{
+  .ops         = &g_pwmops,
+#ifdef CONFIG_STM32L4_PWM_LL_OPS
+  .llops       = &g_llpwmops,
+#endif
+  .timid       = 1,
+  .chan_num    = PWM_TIM1_NCHANNELS,
+  .channels    = g_pwm1channels,
   .timtype     = TIMTYPE_TIM1,
   .mode        = CONFIG_STM32L4_TIM1_MODE,
+  .lock        = CONFIG_STM32L4_TIM1_LOCK,
+  .t_dts       = CONFIG_STM32L4_TIM1_TDTS,
+#ifdef HAVE_PWM_COMPLEMENTARY
+  .deadtime    = CONFIG_STM32L4_TIM1_DEADTIME,
+#endif
+#if defined(HAVE_TRGO) && defined(STM32L4_TIM1_TRGO)
+  .trgo        = STM32L4_TIM1_TRGO,
+#endif
 #ifdef CONFIG_PWM_PULSECOUNT
   .irq         = STM32L4_IRQ_TIM1UP,
 #endif
   .base        = STM32L4_TIM1_BASE,
   .pclk        = STM32L4_APB2_TIM1_CLKIN,
 };
-#endif
+#endif  /* CONFIG_STM32L4_TIM1_PWM */
 
 #ifdef CONFIG_STM32L4_TIM2_PWM
-static struct stm32l4_pwmtimer_s g_pwm2dev =
+
+static struct stm32l4_pwmchan_s g_pwm2channels[] =
 {
-  .ops         = &g_pwmops,
-  .timid       = 2,
-  .channels    =
-  {
+  /* TIM2 has 4 channels */
+
 #ifdef CONFIG_STM32L4_TIM2_CHANNEL1
+  {
+    .channel = 1,
+    .mode    = CONFIG_STM32L4_TIM2_CH1MODE,
+#ifdef CONFIG_STM32L4_TIM2_CH1OUT
+    .out1 =
     {
-      .channel = 1,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM2_CH1POL,
+      .idle    = CONFIG_STM32L4_TIM2_CH1IDLE,
       .pincfg  = PWM_TIM2_CH1CFG,
-      .mode    = CONFIG_STM32L4_TIM2_CH1MODE,
-      .npincfg = 0,
-    },
+    }
+#endif
+    /* No complementary outputs */
+  },
 #endif
 #ifdef CONFIG_STM32L4_TIM2_CHANNEL2
+  {
+    .channel = 2,
+    .mode    = CONFIG_STM32L4_TIM2_CH2MODE,
+#ifdef CONFIG_STM32L4_TIM2_CH2OUT
+    .out1 =
     {
-      .channel = 2,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM2_CH2POL,
+      .idle    = CONFIG_STM32L4_TIM2_CH2IDLE,
       .pincfg  = PWM_TIM2_CH2CFG,
-      .mode    = CONFIG_STM32L4_TIM2_CH2MODE,
-      .npincfg = 0,
-    },
+    }
+#endif
+    /* No complementary outputs */
+  },
 #endif
 #ifdef CONFIG_STM32L4_TIM2_CHANNEL3
+  {
+    .channel = 3,
+    .mode    = CONFIG_STM32L4_TIM2_CH3MODE,
+#ifdef CONFIG_STM32L4_TIM2_CH3OUT
+    .out1 =
     {
-      .channel = 3,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM2_CH3POL,
+      .idle    = CONFIG_STM32L4_TIM2_CH3IDLE,
       .pincfg  = PWM_TIM2_CH3CFG,
-      .mode    = CONFIG_STM32L4_TIM2_CH3MODE,
-      .npincfg = 0,
-    },
+    }
+#endif
+    /* No complementary outputs */
+  },
 #endif
 #ifdef CONFIG_STM32L4_TIM2_CHANNEL4
+  {
+    .channel = 4,
+    .mode    = CONFIG_STM32L4_TIM2_CH4MODE,
+#ifdef CONFIG_STM32L4_TIM2_CH4OUT
+    .out1 =
     {
-      .channel = 4,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM2_CH4POL,
+      .idle    = CONFIG_STM32L4_TIM2_CH4IDLE,
       .pincfg  = PWM_TIM2_CH4CFG,
-      .mode    = CONFIG_STM32L4_TIM2_CH4MODE,
-      .npincfg = 0,
-    },
+    }
 #endif
-  },
+    /* No complementary outputs */
+  }
+#endif
+};
+
+static struct stm32l4_pwmtimer_s g_pwm2dev =
+{
+  .ops         = &g_pwmops,
+#ifdef CONFIG_STM32L4_PWM_LL_OPS
+  .llops       = &g_llpwmops,
+#endif
+  .timid       = 2,
+  .chan_num    = PWM_TIM2_NCHANNELS,
+  .channels    = g_pwm2channels,
   .timtype     = TIMTYPE_TIM2,
   .mode        = CONFIG_STM32L4_TIM2_MODE,
+  .lock        = 0,             /* No lock */
+  .t_dts       = 0,             /* No t_dts */
+#ifdef HAVE_PWM_COMPLEMENTARY
+  .deadtime    = 0,             /* No deadtime */
+#endif
+#if defined(HAVE_TRGO) && defined(STM32L4_TIM2_TRGO)
+  .trgo        = STM32L4_TIM2_TRGO,
+#endif
 #ifdef CONFIG_PWM_PULSECOUNT
   .irq         = STM32L4_IRQ_TIM2,
 #endif
   .base        = STM32L4_TIM2_BASE,
   .pclk        = STM32L4_APB1_TIM2_CLKIN,
 };
-#endif
+
+#endif  /* CONFIG_STM32L4_TIM2_PWM */
 
 #ifdef CONFIG_STM32L4_TIM3_PWM
-static struct stm32l4_pwmtimer_s g_pwm3dev =
+
+static struct stm32l4_pwmchan_s g_pwm3channels[] =
 {
-  .ops         = &g_pwmops,
-  .timid       = 3,
-  .channels    =
-  {
+  /* TIM3 has 4 channels */
+
 #ifdef CONFIG_STM32L4_TIM3_CHANNEL1
+  {
+    .channel = 1,
+    .mode    = CONFIG_STM32L4_TIM3_CH1MODE,
+#ifdef CONFIG_STM32L4_TIM3_CH1OUT
+    .out1    =
     {
-      .channel = 1,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM3_CH1POL,
+      .idle    = CONFIG_STM32L4_TIM3_CH1IDLE,
       .pincfg  = PWM_TIM3_CH1CFG,
-      .mode    = CONFIG_STM32L4_TIM3_CH1MODE,
-      .npincfg = 0,
-    },
+    }
+#endif
+    /* No complementary outputs */
+  },
 #endif
 #ifdef CONFIG_STM32L4_TIM3_CHANNEL2
+  {
+    .channel = 2,
+    .mode    = CONFIG_STM32L4_TIM3_CH2MODE,
+#ifdef CONFIG_STM32L4_TIM3_CH2OUT
+    .out1    =
     {
-      .channel = 2,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM3_CH2POL,
+      .idle    = CONFIG_STM32L4_TIM3_CH2IDLE,
       .pincfg  = PWM_TIM3_CH2CFG,
-      .mode    = CONFIG_STM32L4_TIM3_CH2MODE,
-      .npincfg = 0,
-    },
+    }
+#endif
+    /* No complementary outputs */
+  },
 #endif
 #ifdef CONFIG_STM32L4_TIM3_CHANNEL3
+  {
+    .channel = 3,
+    .mode    = CONFIG_STM32L4_TIM3_CH3MODE,
+#ifdef CONFIG_STM32L4_TIM3_CH3OUT
+    .out1    =
     {
-      .channel = 3,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM3_CH3POL,
+      .idle    = CONFIG_STM32L4_TIM3_CH3IDLE,
       .pincfg  = PWM_TIM3_CH3CFG,
-      .mode    = CONFIG_STM32L4_TIM3_CH3MODE,
-      .npincfg = 0,
-    },
+    }
+#endif
+    /* No complementary outputs */
+  },
 #endif
 #ifdef CONFIG_STM32L4_TIM3_CHANNEL4
+  {
+    .channel = 4,
+    .mode    = CONFIG_STM32L4_TIM3_CH4MODE,
+#ifdef CONFIG_STM32L4_TIM3_CH4OUT
+    .out1    =
     {
-      .channel = 4,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM3_CH4POL,
+      .idle    = CONFIG_STM32L4_TIM3_CH4IDLE,
       .pincfg  = PWM_TIM3_CH4CFG,
-      .mode    = CONFIG_STM32L4_TIM3_CH4MODE,
-      .npincfg = 0,
-    },
+    }
 #endif
-  },
+    /* No complementary outputs */
+  }
+#endif
+};
+
+static struct stm32l4_pwmtimer_s g_pwm3dev =
+{
+  .ops         = &g_pwmops,
+#ifdef CONFIG_STM32L4_PWM_LL_OPS
+  .llops       = &g_llpwmops,
+#endif
+  .timid       = 3,
+  .chan_num    = PWM_TIM3_NCHANNELS,
+  .channels    = g_pwm3channels,
   .timtype     = TIMTYPE_TIM3,
   .mode        = CONFIG_STM32L4_TIM3_MODE,
+  .lock        = 0,             /* No lock */
+  .t_dts       = 0,             /* No t_dts */
+#ifdef HAVE_PWM_COMPLEMENTARY
+  .deadtime    = 0,             /* No deadtime */
+#endif
+#if defined(HAVE_TRGO) && defined(STM32L4_TIM3_TRGO)
+  .trgo        = STM32L4_TIM3_TRGO,
+#endif
 #ifdef CONFIG_PWM_PULSECOUNT
   .irq         = STM32L4_IRQ_TIM3,
 #endif
   .base        = STM32L4_TIM3_BASE,
   .pclk        = STM32L4_APB1_TIM3_CLKIN,
 };
-#endif
+#endif  /* CONFIG_STM32L4_TIM3_PWM */
 
 #ifdef CONFIG_STM32L4_TIM4_PWM
-static struct stm32l4_pwmtimer_s g_pwm4dev =
+
+static struct stm32l4_pwmchan_s g_pwm4channels[] =
 {
-  .ops         = &g_pwmops,
-  .timid       = 4,
-  .channels    =
-  {
+  /* TIM4 has 4 channels */
+
 #ifdef CONFIG_STM32L4_TIM4_CHANNEL1
+  {
+    .channel = 1,
+    .mode    = CONFIG_STM32L4_TIM4_CH1MODE,
+#ifdef CONFIG_STM32L4_TIM4_CH1OUT
+    .out1    =
     {
-      .channel = 1,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM4_CH1POL,
+      .idle    = CONFIG_STM32L4_TIM4_CH1IDLE,
       .pincfg  = PWM_TIM4_CH1CFG,
-      .mode    = CONFIG_STM32L4_TIM4_CH1MODE,
-      .npincfg = 0,
-    },
+    }
+#endif
+    /* No complementary outputs */
+  },
 #endif
 #ifdef CONFIG_STM32L4_TIM4_CHANNEL2
+  {
+    .channel = 2,
+    .mode    = CONFIG_STM32L4_TIM4_CH2MODE,
+#ifdef CONFIG_STM32L4_TIM4_CH2OUT
+    .out1    =
     {
-      .channel = 2,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM4_CH2POL,
+      .idle    = CONFIG_STM32L4_TIM4_CH2IDLE,
       .pincfg  = PWM_TIM4_CH2CFG,
-      .mode    = CONFIG_STM32L4_TIM4_CH2MODE,
-      .npincfg = 0,
-    },
+    }
+#endif
+    /* No complementary outputs */
+  },
 #endif
 #ifdef CONFIG_STM32L4_TIM4_CHANNEL3
+  {
+    .channel = 3,
+    .mode    = CONFIG_STM32L4_TIM4_CH3MODE,
+#ifdef CONFIG_STM32L4_TIM4_CH3OUT
+    .out1    =
     {
-      .channel = 3,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM4_CH3POL,
+      .idle    = CONFIG_STM32L4_TIM4_CH3IDLE,
       .pincfg  = PWM_TIM4_CH3CFG,
-      .mode    = CONFIG_STM32L4_TIM4_CH3MODE,
-      .npincfg = 0,
-    },
+    }
+#endif
+    /* No complementary outputs */
+  },
 #endif
 #ifdef CONFIG_STM32L4_TIM4_CHANNEL4
+  {
+    .channel = 4,
+    .mode    = CONFIG_STM32L4_TIM4_CH4MODE,
+#ifdef CONFIG_STM32L4_TIM4_CH4OUT
+    .out1    =
     {
-      .channel = 4,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM4_CH4POL,
+      .idle    = CONFIG_STM32L4_TIM4_CH4IDLE,
       .pincfg  = PWM_TIM4_CH4CFG,
-      .mode    = CONFIG_STM32L4_TIM4_CH4MODE,
-      .npincfg = 0,
-    },
+    }
 #endif
-  },
+    /* No complementary outputs */
+  }
+#endif
+};
+
+static struct stm32l4_pwmtimer_s g_pwm4dev =
+{
+  .ops         = &g_pwmops,
+#ifdef CONFIG_STM32L4_PWM_LL_OPS
+  .llops       = &g_llpwmops,
+#endif
+  .timid       = 4,
+  .chan_num    = PWM_TIM4_NCHANNELS,
+  .channels    = g_pwm4channels,
   .timtype     = TIMTYPE_TIM4,
   .mode        = CONFIG_STM32L4_TIM4_MODE,
+  .lock        = 0,             /* No lock */
+  .t_dts       = 0,             /* No t_dts */
+#ifdef HAVE_PWM_COMPLEMENTARY
+  .deadtime    = 0,             /* No deadtime */
+#endif
+#if defined(HAVE_TRGO) && defined(STM32L4_TIM4_TRGO)
+  .trgo        = STM32L4_TIM4_TRGO,
+#endif
 #ifdef CONFIG_PWM_PULSECOUNT
   .irq         = STM32L4_IRQ_TIM4,
 #endif
   .base        = STM32L4_TIM4_BASE,
   .pclk        = STM32L4_APB1_TIM4_CLKIN,
 };
-#endif
+#endif  /* CONFIG_STM32L4_TIM4_PWM */
 
 #ifdef CONFIG_STM32L4_TIM5_PWM
-static struct stm32l4_pwmtimer_s g_pwm5dev =
+
+static struct stm32l4_pwmchan_s g_pwm5channels[] =
 {
-  .ops         = &g_pwmops,
-  .timid       = 5,
-  .channels    =
-  {
+  /* TIM5 has 4 channels */
+
 #ifdef CONFIG_STM32L4_TIM5_CHANNEL1
+  {
+    .channel = 1,
+    .mode    = CONFIG_STM32L4_TIM5_CH1MODE,
+#ifdef CONFIG_STM32L4_TIM5_CH1OUT
+    .out1    =
     {
-      .channel = 1,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM5_CH1POL,
+      .idle    = CONFIG_STM32L4_TIM5_CH1IDLE,
       .pincfg  = PWM_TIM5_CH1CFG,
-      .mode    = CONFIG_STM32L4_TIM5_CH1MODE,
-      .npincfg = 0,
-    },
+    }
+#endif
+    /* No complementary outputs */
+  },
 #endif
 #ifdef CONFIG_STM32L4_TIM5_CHANNEL2
+  {
+    .channel = 2,
+    .mode    = CONFIG_STM32L4_TIM5_CH2MODE,
+#ifdef CONFIG_STM32L4_TIM5_CH2OUT
+    .out1    =
     {
-      .channel = 2,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM5_CH2POL,
+      .idle    = CONFIG_STM32L4_TIM5_CH2IDLE,
       .pincfg  = PWM_TIM5_CH2CFG,
-      .mode    = CONFIG_STM32L4_TIM5_CH2MODE,
-      .npincfg = 0,
-    },
+    }
+#endif
+    /* No complementary outputs */
+  },
 #endif
 #ifdef CONFIG_STM32L4_TIM5_CHANNEL3
+  {
+    .channel = 3,
+    .mode    = CONFIG_STM32L4_TIM5_CH3MODE,
+#ifdef CONFIG_STM32L4_TIM5_CH3OUT
+    .out1    =
     {
-      .channel = 3,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM5_CH3POL,
+      .idle    = CONFIG_STM32L4_TIM5_CH3IDLE,
       .pincfg  = PWM_TIM5_CH3CFG,
-      .mode    = CONFIG_STM32L4_TIM5_CH3MODE,
-      .npincfg = 0,
-    },
+    }
+#endif
+  },
 #endif
 #ifdef CONFIG_STM32L4_TIM5_CHANNEL4
+  {
+    .channel = 4,
+    .mode    = CONFIG_STM32L4_TIM5_CH4MODE,
+#ifdef CONFIG_STM32L4_TIM5_CH4OUT
+    .out1    =
     {
-      .channel = 4,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM5_CH4POL,
+      .idle    = CONFIG_STM32L4_TIM5_CH4IDLE,
       .pincfg  = PWM_TIM5_CH4CFG,
-      .mode    = CONFIG_STM32L4_TIM5_CH4MODE,
-      .npincfg = 0,
-    },
+    }
 #endif
   },
+#endif
+};
+
+static struct stm32l4_pwmtimer_s g_pwm5dev =
+{
+  .ops         = &g_pwmops,
+#ifdef CONFIG_STM32L4_PWM_LL_OPS
+  .llops       = &g_llpwmops,
+#endif
+  .timid       = 5,
+  .chan_num    = PWM_TIM5_NCHANNELS,
+  .channels    = g_pwm5channels,
   .timtype     = TIMTYPE_TIM5,
   .mode        = CONFIG_STM32L4_TIM5_MODE,
+  .lock        = 0,             /* No lock */
+  .t_dts       = 0,             /* No t_dts */
+#ifdef HAVE_PWM_COMPLEMENTARY
+  .deadtime    = 0,             /* No deadtime */
+#endif
+#if defined(HAVE_TRGO) && defined(STM32L4_TIM5_TRGO)
+  .trgo        = STM32L4_TIM5_TRGO
+#endif
 #ifdef CONFIG_PWM_PULSECOUNT
   .irq         = STM32L4_IRQ_TIM5,
 #endif
   .base        = STM32L4_TIM5_BASE,
   .pclk        = STM32L4_APB1_TIM5_CLKIN,
 };
-#endif
+#endif  /* CONFIG_STM32L4_TIM5_PWM */
 
 #ifdef CONFIG_STM32L4_TIM8_PWM
-static struct stm32l4_pwmtimer_s g_pwm8dev =
+
+static struct stm32l4_pwmchan_s g_pwm8channels[] =
 {
-  .ops         = &g_pwmops,
-  .timid       = 8,
-  .channels    =
-  {
+  /* TIM8 has 4 channels, 4 complementary */
+
 #ifdef CONFIG_STM32L4_TIM8_CHANNEL1
+  {
+    .channel = 1,
+    .mode    = CONFIG_STM32L4_TIM8_CH1MODE,
+#ifdef HAVE_BREAK
+    .brk =
     {
-      .channel = 1,
-      .pincfg  = PWM_TIM8_CH1CFG,
-      .mode    = CONFIG_STM32L4_TIM8_CH1MODE,
-      .npincfg = PWM_TIM8_CH1NCFG,
-    },
+#ifdef CONFIG_STM32L4_TIM8_BREAK1
+      .en1 = 1,
+      .pol1 = CONFIG_STM32L4_TIM8_BRK1POL,
+#endif
+#ifdef CONFIG_STM32L4_TIM8_BREAK2
+      .en2 = 1,
+      .pol2 = CONFIG_STM32L4_TIM8_BRK2POL,
+      .flt2 = CONFIG_STM32L4_TIM8_BRK2FLT,
 #endif
-#ifdef CONFIG_STM32L4_TIM8_CHANNEL2
-    {
-      .channel = 2,
-      .pincfg  = PWM_TIM8_CH2CFG,
-      .mode    = CONFIG_STM32L4_TIM8_CH2MODE,
-      .npincfg = PWM_TIM8_CH2NCFG,
     },
 #endif
-#ifdef CONFIG_STM32L4_TIM8_CHANNEL3
+#ifdef CONFIG_STM32L4_TIM8_CH1OUT
+    .out1 =
     {
-      .channel = 3,
-      .pincfg  = PWM_TIM8_CH3CFG,
-      .mode    = CONFIG_STM32L4_TIM8_CH3MODE,
-      .npincfg = PWM_TIM8_CH3NCFG,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM8_CH1POL,
+      .idle    = CONFIG_STM32L4_TIM8_CH1IDLE,
+      .pincfg  = PWM_TIM8_CH1CFG,
     },
 #endif
-#ifdef CONFIG_STM32L4_TIM8_CHANNEL4
+#ifdef CONFIG_STM32L4_TIM8_CH1NOUT
+    .out2 =
     {
-      .channel = 4,
-      .pincfg  = PWM_TIM8_CH4CFG,
-      .mode    = CONFIG_STM32L4_TIM8_CH4MODE,
-      .npincfg = 0,
-    },
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM8_CH1NPOL,
+      .idle    = CONFIG_STM32L4_TIM8_CH1NIDLE,
+      .pincfg  = PWM_TIM8_CH1NCFG,
+    }
 #endif
   },
+#endif
+#ifdef CONFIG_STM32L4_TIM8_CHANNEL2
+  {
+    .channel = 2,
+    .mode    = CONFIG_STM32L4_TIM8_CH2MODE,
+#ifdef CONFIG_STM32L4_TIM8_CH2OUT
+    .out1 =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM8_CH2POL,
+      .idle    = CONFIG_STM32L4_TIM8_CH2IDLE,
+      .pincfg  = PWM_TIM8_CH2CFG,
+    },
+#endif
+#ifdef CONFIG_STM32L4_TIM8_CH2NOUT
+    .out2 =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM8_CH2NPOL,
+      .idle    = CONFIG_STM32L4_TIM8_CH2NIDLE,
+      .pincfg  = PWM_TIM8_CH2NCFG,
+    }
+#endif
+  },
+#endif
+#ifdef CONFIG_STM32L4_TIM8_CHANNEL3
+  {
+    .channel = 3,
+    .mode    = CONFIG_STM32L4_TIM8_CH3MODE,
+#ifdef CONFIG_STM32L4_TIM8_CH3OUT
+    .out1 =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM8_CH3POL,
+      .idle    = CONFIG_STM32L4_TIM8_CH3IDLE,
+      .pincfg  = PWM_TIM8_CH3CFG,
+    },
+#endif
+#ifdef CONFIG_STM32L4_TIM8_CH3NOUT
+    .out2 =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM8_CH3NPOL,
+      .idle    = CONFIG_STM32L4_TIM8_CH3NIDLE,
+      .pincfg  = PWM_TIM8_CH3NCFG,
+    }
+#endif
+  },
+#endif
+#ifdef CONFIG_STM32L4_TIM8_CHANNEL4
+  {
+    .channel = 4,
+    .mode    = CONFIG_STM32L4_TIM8_CH4MODE,
+#ifdef CONFIG_STM32L4_TIM8_CH4OUT
+    .out1 =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM8_CH4POL,
+      .idle    = CONFIG_STM32L4_TIM8_CH4IDLE,
+      .pincfg  = PWM_TIM8_CH4CFG,
+    }
+#endif
+  },
+#endif
+#ifdef CONFIG_STM32L4_TIM8_CHANNEL5
+  {
+    .channel = 5,
+    .mode    = CONFIG_STM32L4_TIM8_CH5MODE,
+#ifdef CONFIG_STM32L4_TIM8_CH5OUT
+    .out1 =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM8_CH5POL,
+      .idle    = CONFIG_STM32L4_TIM8_CH5IDLE,
+      .pincfg  = 0,    /* No available externaly */
+    }
+#endif
+  },
+#endif
+#ifdef CONFIG_STM32L4_TIM8_CHANNEL6
+  {
+    .channel = 6,
+    .mode    = CONFIG_STM32L4_TIM8_CH6MODE,
+#ifdef CONFIG_STM32L4_TIM8_CH6OUT
+    .out1 =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM8_CH6POL,
+      .idle    = CONFIG_STM32L4_TIM8_CH6IDLE,
+      .pincfg  = 0,    /* No available externaly */
+    }
+#endif
+  }
+#endif
+};
+
+static struct stm32l4_pwmtimer_s g_pwm8dev =
+{
+  .ops         = &g_pwmops,
+#ifdef CONFIG_STM32L4_PWM_LL_OPS
+  .llops       = &g_llpwmops,
+#endif
+  .timid       = 8,
+  .chan_num    = PWM_TIM8_NCHANNELS,
+  .channels    = g_pwm8channels,
   .timtype     = TIMTYPE_TIM8,
   .mode        = CONFIG_STM32L4_TIM8_MODE,
+  .lock        = CONFIG_STM32L4_TIM8_LOCK,
+  .t_dts       = CONFIG_STM32L4_TIM8_TDTS,
+#ifdef HAVE_PWM_COMPLEMENTARY
+  .deadtime    = CONFIG_STM32L4_TIM8_DEADTIME,
+#endif
+#if defined(HAVE_TRGO) && defined(STM32L4_TIM8_TRGO)
+  .trgo        = STM32L4_TIM8_TRGO,
+#endif
 #ifdef CONFIG_PWM_PULSECOUNT
   .irq         = STM32L4_IRQ_TIM8UP,
 #endif
   .base        = STM32L4_TIM8_BASE,
   .pclk        = STM32L4_APB2_TIM8_CLKIN,
 };
-#endif
+#endif  /* CONFIG_STM32L4_TIM8_PWM */
 
 #ifdef CONFIG_STM32L4_TIM15_PWM
-static struct stm32l4_pwmtimer_s g_pwm15dev =
+
+static struct stm32l4_pwmchan_s g_pwm15channels[] =
 {
-  .ops         = &g_pwmops,
-  .timid       = 15,
-  .channels    =
-  {
+  /* TIM15 has 2 channels, 1 complementary */
+
 #ifdef CONFIG_STM32L4_TIM15_CHANNEL1
+  {
+    .channel = 1,
+    .mode    = CONFIG_STM32L4_TIM15_CH1MODE,
+#ifdef HAVE_BREAK
+    .brk =
+    {
+#ifdef CONFIG_STM32L4_TIM15_BREAK1
+      .en1 = 1,
+      .pol1 = CONFIG_STM32L4_TIM15_BRK1POL,
+#endif
+      /* No BREAK2 */
+    },
+#endif
+#ifdef CONFIG_STM32L4_TIM15_CH1OUT
+    .out1    =
     {
-      .channel = 1,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM15_CH1POL,
+      .idle    = CONFIG_STM32L4_TIM15_CH1IDLE,
       .pincfg  = PWM_TIM15_CH1CFG,
-      .mode    = CONFIG_STM32L4_TIM15_CH1MODE,
-      .npincfg = PWM_TIM15_CH1NCFG,
     },
 #endif
+#ifdef CONFIG_STM32L4_TIM15_CH1NOUT
+    .out2    =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM15_CH1NPOL,
+      .idle    = CONFIG_STM32L4_TIM15_CH1NIDLE,
+      .pincfg  = PWM_TIM15_CH2CFG,
+    }
+#endif
+  },
+#endif
 #ifdef CONFIG_STM32L4_TIM15_CHANNEL2
+  {
+    .channel = 2,
+    .mode    = CONFIG_STM32L4_TIM15_CH2MODE,
+#ifdef CONFIG_STM32L4_TIM12_CH2OUT
+    .out1    =
     {
-      .channel = 2,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM15_CH2POL,
+      .idle    = CONFIG_STM32L4_TIM15_CH2IDLE,
       .pincfg  = PWM_TIM15_CH2CFG,
-      .mode    = CONFIG_STM32L4_TIM15_CH2MODE,
-      .npincfg = 0,
-    },
+    }
 #endif
+    /* No complementary outputs */
   },
+#endif
+};
+
+static struct stm32l4_pwmtimer_s g_pwm15dev =
+{
+  .ops         = &g_pwmops,
+#ifdef CONFIG_STM32L4_PWM_LL_OPS
+  .llops       = &g_llpwmops,
+#endif
+  .timid       = 15,
+  .chan_num    = PWM_TIM15_NCHANNELS,
+  .channels    = g_pwm15channels,
   .timtype     = TIMTYPE_TIM15,
   .mode        = STM32L4_TIMMODE_COUNTUP,
+  .lock        = CONFIG_STM32L4_TIM15_LOCK,
+  .t_dts       = CONFIG_STM32L4_TIM15_TDTS,
+#ifdef HAVE_PWM_COMPLEMENTARY
+  .deadtime    = CONFIG_STM32L4_TIM15_DEADTIME,
+#endif
+#if defined(HAVE_TRGO) && defined(STM32L4_TIM15_TRGO)
+  .trgo        = STM32L4_TIM15_TRGO,
+#endif
 #ifdef CONFIG_PWM_PULSECOUNT
   .irq         = STM32L4_IRQ_TIM15,
 #endif
   .base        = STM32L4_TIM15_BASE,
   .pclk        = STM32L4_APB2_TIM15_CLKIN,
 };
-#endif
+#endif  /* CONFIG_STM32L4_TIM15_PWM */
 
 #ifdef CONFIG_STM32L4_TIM16_PWM
-static struct stm32l4_pwmtimer_s g_pwm16dev =
+
+static struct stm32l4_pwmchan_s g_pwm16channels[] =
 {
-  .ops         = &g_pwmops,
-  .timid       = 16,
-  .channels    =
-  {
+  /* TIM16 has 1 channel, 1 complementary */
+
 #ifdef CONFIG_STM32L4_TIM16_CHANNEL1
+  {
+    .channel = 1,
+    .mode    = CONFIG_STM32L4_TIM16_CH1MODE,
+#ifdef HAVE_BREAK
+    .brk =
+    {
+#ifdef CONFIG_STM32L4_TIM16_BREAK1
+      .en1 = 1,
+      .pol1 = CONFIG_STM32L4_TIM16_BRK1POL,
+#endif
+      /* No BREAK2 */
+    },
+#endif
+#ifdef CONFIG_STM32L4_TIM16_CH1OUT
+    .out1    =
     {
-      .channel = 1,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM16_CH1POL,
+      .idle    = CONFIG_STM32L4_TIM16_CH1IDLE,
       .pincfg  = PWM_TIM16_CH1CFG,
-      .mode    = CONFIG_STM32L4_TIM16_CH1MODE,
-      .npincfg = PWM_TIM16_CH1NCFG,
     },
 #endif
+#ifdef CONFIG_STM32L4_TIM16_CH1NOUT
+    .out2    =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM16_CH1NPOL,
+      .idle    = CONFIG_STM32L4_TIM16_CH1NIDLE,
+      .pincfg  = PWM_TIM16_CH2CFG,
+    }
+#endif
   },
+#endif
+};
+
+static struct stm32l4_pwmtimer_s g_pwm16dev =
+{
+  .ops         = &g_pwmops,
+#ifdef CONFIG_STM32L4_PWM_LL_OPS
+  .llops       = &g_llpwmops,
+#endif
+  .timid       = 16,
+  .chan_num    = PWM_TIM16_NCHANNELS,
+  .channels    = g_pwm16channels,
   .timtype     = TIMTYPE_TIM16,
   .mode        = STM32L4_TIMMODE_COUNTUP,
+  .lock        = CONFIG_STM32L4_TIM16_LOCK,
+  .t_dts       = CONFIG_STM32L4_TIM16_TDTS,
+#ifdef HAVE_PWM_COMPLEMENTARY
+  .deadtime    = CONFIG_STM32L4_TIM16_DEADTIME,
+#endif
+#if defined(HAVE_TRGO)
+  .trgo        = 0,             /* TRGO not supported for TIM16 */
+#endif
 #ifdef CONFIG_PWM_PULSECOUNT
   .irq         = STM32L4_IRQ_TIM16,
 #endif
   .base        = STM32L4_TIM16_BASE,
   .pclk        = STM32L4_APB2_TIM16_CLKIN,
 };
-#endif
+#endif  /* CONFIG_STM32L4_TIM16_PWM */
 
 #ifdef CONFIG_STM32L4_TIM17_PWM
-static struct stm32l4_pwmtimer_s g_pwm17dev =
+
+static struct stm32l4_pwmchan_s g_pwm17channels[] =
 {
-  .ops         = &g_pwmops,
-  .timid       = 17,
-  .channels    =
-  {
+  /* TIM17 has 1 channel, 1 complementary */
+
 #ifdef CONFIG_STM32L4_TIM17_CHANNEL1
+  {
+    .channel = 1,
+    .mode    = CONFIG_STM32L4_TIM17_CH1MODE,
+#ifdef HAVE_BREAK
+    .brk =
+    {
+#ifdef CONFIG_STM32L4_TIM17_BREAK1
+      .en1 = 1,
+      .pol1 = CONFIG_STM32L4_TIM17_BRK1POL,
+#endif
+      /* No BREAK2 */
+    },
+#endif
+#ifdef CONFIG_STM32L4_TIM17_CH1OUT
+    .out1    =
     {
-      .channel = 1,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM17_CH1POL,
+      .idle    = CONFIG_STM32L4_TIM17_CH1IDLE,
       .pincfg  = PWM_TIM17_CH1CFG,
-      .mode    = CONFIG_STM32L4_TIM17_CH1MODE,
-      .npincfg = PWM_TIM17_CH1NCFG,
     },
 #endif
+#ifdef CONFIG_STM32L4_TIM17_CH1NOUT
+    .out2    =
+    {
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_TIM17_CH1NPOL,
+      .idle    = CONFIG_STM32L4_TIM17_CH1NIDLE,
+      .pincfg  = PWM_TIM17_CH2CFG,
+    }
+#endif
   },
+#endif
+};
+
+static struct stm32l4_pwmtimer_s g_pwm17dev =
+{
+  .ops         = &g_pwmops,
+#ifdef CONFIG_STM32L4_PWM_LL_OPS
+  .llops       = &g_llpwmops,
+#endif
+  .timid       = 17,
+  .chan_num    = PWM_TIM17_NCHANNELS,
+  .channels    = g_pwm17channels,
   .timtype     = TIMTYPE_TIM17,
   .mode        = STM32L4_TIMMODE_COUNTUP,
+  .lock        = CONFIG_STM32L4_TIM17_LOCK,
+  .t_dts       = CONFIG_STM32L4_TIM17_TDTS,
+#ifdef HAVE_PWM_COMPLEMENTARY
+  .deadtime    = CONFIG_STM32L4_TIM17_DEADTIME,
+#endif
+#if defined(HAVE_TRGO)
+  .trgo        = 0,             /* TRGO not supported for TIM17 */
+#endif
 #ifdef CONFIG_PWM_PULSECOUNT
   .irq         = STM32L4_IRQ_TIM17,
 #endif
   .base        = STM32L4_TIM17_BASE,
   .pclk        = STM32L4_APB2_TIM17_CLKIN,
 };
-#endif
+#endif  /* CONFIG_STM32L4_TIM17_PWM */
 
 #ifdef CONFIG_STM32L4_LPTIM1_PWM
-static struct stm32l4_pwmtimer_s g_pwmlp1dev =
+
+static struct stm32l4_pwmchan_s g_pwmlp1channels[] =
 {
-  .ops         = &g_pwmops,
-  .timid       = 1,
-  .channels    =
-  {
+  /* LPTIM1 has 1 channel */
+
 #ifdef CONFIG_STM32L4_LPTIM1_CHANNEL1
+  {
+    .channel = 1,
+    .mode    = 0,
+#ifdef CONFIG_STM32L4_LPTIM1_CH1OUT
+    .out1    =
     {
-      .channel = 1,
+      .in_use  = 1,
+      .pol     = CONFIG_STM32L4_LPTIM1_CH1POL,
+      .idle    = 0,             /* No idle */
       .pincfg  = PWM_LPTIM1_CH1CFG,
-      .npincfg = PWM_LPTIM1_CH1NCFG,
-    },
+    }
 #endif
+    /* No complementary outputs */
   },
+#endif
+};
+
+static struct stm32l4_pwmtimer_s g_pwmlp1dev =
+{
+  .ops         = &g_pwmops,
+#ifdef CONFIG_STM32L4_PWM_LL_OPS
+  .llops       = &g_llpwmops,
+#endif
+  .timid       = 1,
+  .chan_num    = PWM_LPTIM1_NCHANNELS,
+  .channels    = g_pwmlp1channels,
   .timtype     = TIMTYPE_LPTIM1,
   .mode        = STM32L4_TIMMODE_COUNTUP,
+  .lock        = 0,             /* No lock */
+  .t_dts       = 0,             /* No t_dts */
+#ifdef HAVE_PWM_COMPLEMENTARY
+  .deadtime    = 0,             /* No deadtime */
+#endif
+#if defined(HAVE_TRGO)
+  .trgo        = 0,             /* TRGO not supported for LPTIM1 */
+#endif
+#ifdef CONFIG_PWM_PULSECOUNT
+  .irq         = STM32L4_IRQ_LPTIM1,
+#endif
   .base        = STM32L4_LPTIM1_BASE,
 #if defined(CONFIG_STM32L4_LPTIM1_CLK_APB1)
   .pclk        = STM32L4_PCLK1_FREQUENCY,
@@ -651,25 +1359,54 @@ static struct stm32l4_pwmtimer_s g_pwmlp1dev =
   .pclk        = STM32L4_HSI_FREQUENCY,
 #endif
 };
-#endif
+#endif  /* CONFIG_STM32L4_LPTIM1_PWM */
 
 #ifdef CONFIG_STM32L4_LPTIM2_PWM
-static struct stm32l4_pwmtimer_s g_pwmlp2dev =
+
+static struct stm32l4_pwmchan_s g_pwmlp2channels[] =
 {
-  .ops         = &g_pwmops,
-  .timid       = 2,
-  .channels    =
-  {
+  /* LPTIM2 has 1 channel */
+
 #ifdef CONFIG_STM32L4_LPTIM2_CHANNEL1
+  {
+    .channel = 1,
+    .mode    = 0,
+#ifdef CONFIG_STM32L4_LPTIM2_CH1OUT
+    .out1    =
     {
-      .channel = 1,
+      .in_use  = 1,
+      .pol     = 0,             /* REVISIT: Configure using CONFIG_STM32L4_LPTIM2_CH1POL, */
+      .idle    = 0,             /* No idle */
       .pincfg  = PWM_LPTIM2_CH1CFG,
-      .npincfg = PWM_LPTIM2_CH1NCFG,
-    },
+    }
 #endif
+    /* No complementary outputs */
   },
+#endif
+};
+
+static struct stm32l4_pwmtimer_s g_pwmlp2dev =
+{
+  .ops         = &g_pwmops,
+#ifdef CONFIG_STM32L4_PWM_LL_OPS
+  .llops       = &g_llpwmops,
+#endif
+  .timid       = 2,
+  .chan_num    = PWM_LPTIM2_NCHANNELS,
+  .channels    = g_pwmlp2channels,
   .timtype     = TIMTYPE_LPTIM2,
   .mode        = STM32L4_TIMMODE_COUNTUP,
+  .lock        = 0,             /* No lock */
+  .t_dts       = 0,             /* No t_dts */
+#ifdef HAVE_PWM_COMPLEMENTARY
+  .deadtime    = 0,             /* No deadtime */
+#endif
+#if defined(HAVE_TRGO)
+  .trgo        = 0,             /* TRGO not supported for LPTIM2 */
+#endif
+#ifdef CONFIG_PWM_PULSECOUNT
+  .irq         = STM32L4_IRQ_LPTIM2,
+#endif
   .base        = STM32L4_LPTIM2_BASE,
 #if defined(CONFIG_STM32L4_LPTIM2_CLK_APB1)
   .pclk        = STM32L4_PCLK1_FREQUENCY,
@@ -681,14 +1418,14 @@ static struct stm32l4_pwmtimer_s g_pwmlp2dev =
   .pclk        = STM32L4_HSI_FREQUENCY,
 #endif
 };
-#endif
+#endif  /* CONFIG_STM32L4_LPTIM2_PWM */
 
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
 
 /****************************************************************************
- * Name: stm32l4pwm_getreg
+ * Name: pwm_getreg
  *
  * Description:
  *   Read the value of an PWM timer register.
@@ -702,13 +1439,13 @@ static struct stm32l4_pwmtimer_s g_pwmlp2dev =
  *
  ****************************************************************************/
 
-static uint16_t stm32l4pwm_getreg(struct stm32l4_pwmtimer_s *priv, int offset)
+static uint16_t pwm_getreg(struct stm32l4_pwmtimer_s *priv, int offset)
 {
   return getreg16(priv->base + offset);
 }
 
 /****************************************************************************
- * Name: stm32l4pwm_putreg
+ * Name: pwm_putreg
  *
  * Description:
  *   Read the value of an PWM timer register.
@@ -722,7 +1459,7 @@ static uint16_t stm32l4pwm_getreg(struct stm32l4_pwmtimer_s *priv, int offset)
  *
  ****************************************************************************/
 
-static void stm32l4pwm_putreg(struct stm32l4_pwmtimer_s *priv, int offset,
+static void pwm_putreg(struct stm32l4_pwmtimer_s *priv, int offset,
                               uint16_t value)
 {
   if (priv->timtype == TIMTYPE_GENERAL32 &&
@@ -748,7 +1485,50 @@ static void stm32l4pwm_putreg(struct stm32l4_pwmtimer_s *priv, int offset,
 }
 
 /****************************************************************************
- * Name: stm32l4pwm_dumpregs
+ * Name: pwm_modifyreg
+ *
+ * Description:
+ *   Modify PWM register (32-bit or 16-bit)
+ *
+ * Input Parameters:
+ *   priv    - A reference to the PWM block status
+ *   offset  - The offset to the register to read
+ *   clrbits - The bits to clear
+ *   setbits - The bits to set
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void pwm_modifyreg(struct stm32l4_pwmtimer_s *priv, uint32_t offset,
+                          uint32_t clearbits, uint32_t setbits)
+{
+  if (priv->timtype == TIMTYPE_GENERAL32 &&
+      (offset == STM32L4_GTIM_CNT_OFFSET ||
+       offset == STM32L4_GTIM_ARR_OFFSET ||
+       offset == STM32L4_GTIM_CCR1_OFFSET ||
+       offset == STM32L4_GTIM_CCR2_OFFSET ||
+       offset == STM32L4_GTIM_CCR3_OFFSET ||
+       offset == STM32L4_GTIM_CCR4_OFFSET))
+    {
+      /* a 32 bit access is required for a 32 bit register:
+       * if only a 16 bit write would be performed, then the
+       * upper 16 bits of the 32 bit register will be a copy of
+       * the lower 16 bits.
+       */
+
+      modifyreg32(priv->base + offset, clearbits, setbits);
+    }
+  else
+    {
+      modifyreg16(priv->base + offset, (uint16_t)clearbits,
+                  (uint16_t)setbits);
+    }
+}
+
+/****************************************************************************
+ * Name: pwm_dumpregs
  *
  * Description:
  *   Dump all timer registers.
@@ -762,136 +1542,373 @@ static void stm32l4pwm_putreg(struct stm32l4_pwmtimer_s *priv, int offset,
  ****************************************************************************/
 
 #ifdef CONFIG_DEBUG_PWM_INFO
-static void stm32l4pwm_dumpregs(struct stm32l4_pwmtimer_s *priv,
-                                FAR const char *msg)
+static void pwm_dumpregs(FAR struct pwm_lowerhalf_s *dev,
+                         FAR const char *msg)
 {
+  FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev;
+
   if (priv->timtype == TIMTYPE_LOWPOWER)
     {
       pwminfo("%s:\n", msg);
       pwminfo("  CFGR: %04x CR:  %04x CMP:  %04x ARR:  %04x\n",
-              stm32l4pwm_getreg(priv, STM32L4_LPTIM_CFGR_OFFSET),
-              stm32l4pwm_getreg(priv, STM32L4_LPTIM_CR_OFFSET),
-              stm32l4pwm_getreg(priv, STM32L4_LPTIM_CMP_OFFSET),
-              stm32l4pwm_getreg(priv, STM32L4_LPTIM_ARR_OFFSET));
+              pwm_getreg(priv, STM32L4_LPTIM_CFGR_OFFSET),
+              pwm_getreg(priv, STM32L4_LPTIM_CR_OFFSET),
+              pwm_getreg(priv, STM32L4_LPTIM_CMP_OFFSET),
+              pwm_getreg(priv, STM32L4_LPTIM_ARR_OFFSET));
       pwminfo("  ISR:  %04x CNT: %04x\n",
-              stm32l4pwm_getreg(priv, STM32L4_LPTIM_ISR_OFFSET),
-              stm32l4pwm_getreg(priv, STM32L4_LPTIM_CNT_OFFSET));
+              pwm_getreg(priv, STM32L4_LPTIM_ISR_OFFSET),
+              pwm_getreg(priv, STM32L4_LPTIM_CNT_OFFSET));
     }
   else
     {
       pwminfo("%s:\n", msg);
       pwminfo("  CR1: %04x CR2:  %04x SMCR:  %04x DIER:  %04x\n",
-              stm32l4pwm_getreg(priv, STM32L4_GTIM_CR1_OFFSET),
-              stm32l4pwm_getreg(priv, STM32L4_GTIM_CR2_OFFSET),
-              stm32l4pwm_getreg(priv, STM32L4_GTIM_SMCR_OFFSET),
-              stm32l4pwm_getreg(priv, STM32L4_GTIM_DIER_OFFSET));
+              pwm_getreg(priv, STM32L4_GTIM_CR1_OFFSET),
+              pwm_getreg(priv, STM32L4_GTIM_CR2_OFFSET),
+              pwm_getreg(priv, STM32L4_GTIM_SMCR_OFFSET),
+              pwm_getreg(priv, STM32L4_GTIM_DIER_OFFSET));
       pwminfo("   SR: %04x EGR:  %04x CCMR1: %04x CCMR2: %04x\n",
-              stm32l4pwm_getreg(priv, STM32L4_GTIM_SR_OFFSET),
-              stm32l4pwm_getreg(priv, STM32L4_GTIM_EGR_OFFSET),
-              stm32l4pwm_getreg(priv, STM32L4_GTIM_CCMR1_OFFSET),
-              stm32l4pwm_getreg(priv, STM32L4_GTIM_CCMR2_OFFSET));
+              pwm_getreg(priv, STM32L4_GTIM_SR_OFFSET),
+              pwm_getreg(priv, STM32L4_GTIM_EGR_OFFSET),
+              pwm_getreg(priv, STM32L4_GTIM_CCMR1_OFFSET),
+              pwm_getreg(priv, STM32L4_GTIM_CCMR2_OFFSET));
       pwminfo(" CCER: %04x CNT:  %04x PSC:   %04x ARR:   %04x\n",
-              stm32l4pwm_getreg(priv, STM32L4_GTIM_CCER_OFFSET),
-              stm32l4pwm_getreg(priv, STM32L4_GTIM_CNT_OFFSET),
-              stm32l4pwm_getreg(priv, STM32L4_GTIM_PSC_OFFSET),
-              stm32l4pwm_getreg(priv, STM32L4_GTIM_ARR_OFFSET));
+              pwm_getreg(priv, STM32L4_GTIM_CCER_OFFSET),
+              pwm_getreg(priv, STM32L4_GTIM_CNT_OFFSET),
+              pwm_getreg(priv, STM32L4_GTIM_PSC_OFFSET),
+              pwm_getreg(priv, STM32L4_GTIM_ARR_OFFSET));
       pwminfo(" CCR1: %04x CCR2: %04x CCR3:  %04x CCR4:  %04x\n",
-              stm32l4pwm_getreg(priv, STM32L4_GTIM_CCR1_OFFSET),
-              stm32l4pwm_getreg(priv, STM32L4_GTIM_CCR2_OFFSET),
-              stm32l4pwm_getreg(priv, STM32L4_GTIM_CCR3_OFFSET),
-              stm32l4pwm_getreg(priv, STM32L4_GTIM_CCR4_OFFSET));
+              pwm_getreg(priv, STM32L4_GTIM_CCR1_OFFSET),
+              pwm_getreg(priv, STM32L4_GTIM_CCR2_OFFSET),
+              pwm_getreg(priv, STM32L4_GTIM_CCR3_OFFSET),
+              pwm_getreg(priv, STM32L4_GTIM_CCR4_OFFSET));
 #if defined(CONFIG_STM32L4_TIM1_PWM) || defined(CONFIG_STM32L4_TIM8_PWM)
       if (priv->timtype == TIMTYPE_ADVANCED)
         {
           pwminfo("  RCR: %04x BDTR: %04x DCR:   %04x DMAR:  %04x\n",
-              stm32l4pwm_getreg(priv, STM32L4_ATIM_RCR_OFFSET),
-              stm32l4pwm_getreg(priv, STM32L4_ATIM_BDTR_OFFSET),
-              stm32l4pwm_getreg(priv, STM32L4_ATIM_DCR_OFFSET),
-              stm32l4pwm_getreg(priv, STM32L4_ATIM_DMAR_OFFSET));
+              pwm_getreg(priv, STM32L4_ATIM_RCR_OFFSET),
+              pwm_getreg(priv, STM32L4_ATIM_BDTR_OFFSET),
+              pwm_getreg(priv, STM32L4_ATIM_DCR_OFFSET),
+              pwm_getreg(priv, STM32L4_ATIM_DMAR_OFFSET));
         }
       else
 #endif
         {
           pwminfo("  DCR: %04x DMAR: %04x\n",
-              stm32l4pwm_getreg(priv, STM32L4_GTIM_DCR_OFFSET),
-              stm32l4pwm_getreg(priv, STM32L4_GTIM_DMAR_OFFSET));
+              pwm_getreg(priv, STM32L4_GTIM_DCR_OFFSET),
+              pwm_getreg(priv, STM32L4_GTIM_DMAR_OFFSET));
         }
     }
 }
 #endif
 
 /****************************************************************************
- * Name: stm32l4pwm_timer
- *
- * Description:
- *   (Re-)initialize the timer resources and start the pulsed output
- *
- * Input Parameters:
- *   priv - 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
- *
+ * Name: pwm_ccr_update
  ****************************************************************************/
 
-static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv,
-                            FAR const struct pwm_info_s *info)
-{
-#ifdef CONFIG_PWM_MULTICHAN
-  int      i;
-#endif
+static int pwm_ccr_update(FAR struct pwm_lowerhalf_s *dev, uint8_t index,
+                          uint32_t ccr)
 
-  /* Calculated values */
+{
+  FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev;
+  uint32_t offset = 0;
 
-  uint32_t prescaler;
-  uint32_t timclk;
-  uint32_t reload;
-  uint32_t ccr;
+#ifdef HAVE_LPTIM
+  if (priv->timtype == TIMTYPE_LOWPOWER)
+    {
+      /* REVISIT: What about index? Is it necessary for LPTIM? */
 
-  /* Register contents */
+      offset = STM32L4_LPTIM_CMP_OFFSET;
+      pwm_putreg(priv, offset, ccr);
 
-  uint16_t cr1;
-  uint16_t ccer;
-  uint16_t cr2;
-  uint32_t ccmr1;
-  uint32_t ccmr2;
+      return OK;
+    }
+#endif
 
-  /* New timer register bit settings */
+  /* Only ADV timers have CC5 and CC6 */
 
-  uint16_t ccenable;
-  uint16_t ccnenable;
-  uint32_t ocmode1;
-  uint32_t ocmode2;
+  if (priv->timtype != TIMTYPE_ADVANCED && (index == 5 || index == 6))
+    {
+      pwmerr("ERROR: No such CCR: %u\n", index);
+      return -EINVAL;
+    }
 
-  DEBUGASSERT(priv != NULL && info != NULL);
+  /* REVISIT: start index from 0? */
 
-#if defined(CONFIG_PWM_MULTICHAN)
-  pwminfo("TIM%u frequency: %u\n",
-          priv->timid, info->frequency);
-#elif defined(CONFIG_PWM_PULSECOUNT)
-  pwminfo("TIM%u channel: %u frequency: %u duty: %08x count: %u\n",
-          priv->timid, priv->channels[0].channel, info->frequency,
-          info->duty, info->count);
-#else
-  pwminfo("TIM%u channel: %u frequency: %u duty: %08x\n",
-          priv->timid, priv->channels[0].channel, info->frequency, info->duty);
-#endif
+  switch (index)
+    {
+      case STM32L4_PWM_CHAN1:
+        {
+          offset = STM32L4_GTIM_CCR1_OFFSET;
+          break;
+        }
 
-  DEBUGASSERT(info->frequency > 0);
-#ifndef CONFIG_PWM_MULTICHAN
-  DEBUGASSERT(info->duty >= 0 && info->duty < uitoub16(100));
-#endif
+      case STM32L4_PWM_CHAN2:
+        {
+          offset = STM32L4_GTIM_CCR2_OFFSET;
+          break;
+        }
 
-  /* Disable all interrupts and DMA requests, clear all pending status */
+      case STM32L4_PWM_CHAN3:
+        {
+          offset = STM32L4_GTIM_CCR3_OFFSET;
+          break;
+        }
 
-#ifdef CONFIG_PWM_PULSECOUNT
-  stm32l4pwm_putreg(priv, STM32L4_GTIM_DIER_OFFSET, 0);
-  stm32l4pwm_putreg(priv, STM32L4_GTIM_SR_OFFSET, 0);
+      case STM32L4_PWM_CHAN4:
+        {
+          offset = STM32L4_GTIM_CCR4_OFFSET;
+          break;
+        }
+
+      case STM32L4_PWM_CHAN5:
+        {
+          offset = STM32L4_ATIM_CCR5_OFFSET;
+          break;
+        }
+
+      case STM32L4_PWM_CHAN6:
+        {
+          offset = STM32L4_ATIM_CCR6_OFFSET;
+          break;
+        }
+
+      default:
+        {
+          pwmerr("ERROR: No such CCR: %u\n", index);
+          return -EINVAL;
+        }
+    }
+
+  /* Update CCR register */
+
+  pwm_putreg(priv, offset, ccr);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_ccr_get
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32L4_PWM_LL_OPS
+static uint32_t pwm_ccr_get(FAR struct pwm_lowerhalf_s *dev, uint8_t index)
+{
+  FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev;
+  uint32_t offset = 0;
+
+  switch (index)
+    {
+      case STM32L4_PWM_CHAN1:
+        {
+          offset = STM32L4_GTIM_CCR1_OFFSET;
+          break;
+        }
+
+      case STM32L4_PWM_CHAN2:
+        {
+          offset = STM32L4_GTIM_CCR2_OFFSET;
+          break;
+        }
+
+      case STM32L4_PWM_CHAN3:
+        {
+          offset = STM32L4_GTIM_CCR3_OFFSET;
+          break;
+        }
+
+      case STM32L4_PWM_CHAN4:
+        {
+          offset = STM32L4_GTIM_CCR4_OFFSET;
+          break;
+        }
+
+      case STM32L4_PWM_CHAN5:
+        {
+          offset = STM32L4_ATIM_CCR5_OFFSET;
+          break;
+        }
+
+      case STM32L4_PWM_CHAN6:
+        {
+          offset = STM32L4_ATIM_CCR6_OFFSET;
+          break;
+        }
+
+      default:
+        {
+          pwmerr("ERROR: No such CCR: %u\n", index);
+          return -EINVAL;
+        }
+    }
+
+  /* Return CCR register */
+
+  return pwm_getreg(priv, offset);
+}
+#endif  /* CONFIG_STM32L4_PWM_LL_OPS */
+
+/****************************************************************************
+ * Name: pwm_arr_update
+ ****************************************************************************/
+
+static int pwm_arr_update(FAR struct pwm_lowerhalf_s *dev, uint32_t arr)
+{
+  FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev;
+
+  /* Update ARR register */
+
+  if (priv->timtype == TIMTYPE_LOWPOWER)
+    {
+      pwm_putreg(priv, STM32L4_LPTIM_ARR_OFFSET, arr);
+    }
+  else
+    {
+      pwm_putreg(priv, STM32L4_GTIM_ARR_OFFSET, arr);
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_arr_get
+ ****************************************************************************/
+
+static uint32_t pwm_arr_get(FAR struct pwm_lowerhalf_s *dev)
+{
+  FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev;
+
+  if (priv->timtype == TIMTYPE_LOWPOWER)
+    {
+      return pwm_getreg(priv, STM32L4_LPTIM_ARR_OFFSET);
+    }
+  else
+    {
+      return pwm_getreg(priv, STM32L4_GTIM_ARR_OFFSET);
+    }
+}
+
+/****************************************************************************
+ * Name: pwm_duty_update
+ *
+ * Description:
+ *   Try to change only channel duty
+ *
+ * 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_duty_update(FAR struct pwm_lowerhalf_s *dev, uint8_t channel,
+                           ub16_t duty)
+{
+  FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev;
+  uint32_t reload = 0;
+  uint32_t ccr    = 0;
+
+  /* We don't want compilation warnings if no DEBUGASSERT */
+
+  UNUSED(priv);
+
+  DEBUGASSERT(priv != NULL);
+
+  pwminfo("TIM%u channel: %u duty: %08x\n",
+          priv->timid, channel, duty);
+
+#ifndef CONFIG_STM32L4_PWM_MULTICHAN
+  DEBUGASSERT(channel == priv->channels[0].channel);
+  DEBUGASSERT(duty >= 0 && duty < uitoub16(100));
+#endif
+
+  /* Get the reload values */
+
+  reload = pwm_arr_get(dev);
+
+  /* Duty cycle:
+   *
+   * duty cycle = ccr / reload (fractional value)
+   */
+
+  ccr = b16toi(duty * reload + b16HALF);
+
+  pwminfo("ccr: %u\n", ccr);
+
+  /* Write coresponding CCR register */
+
+  pwm_ccr_update(dev, channel, ccr);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_timer_enable
+ ****************************************************************************/
+
+static int pwm_timer_enable(FAR struct pwm_lowerhalf_s *dev, bool state)
+{
+  FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev;
+
+#ifdef HAVE_LPTIM
+  if (priv->timtype != TIMTYPE_LOWPOWER)
+    {
+#endif
+      if (state == true)
+        {
+          /* Enable timer counter */
+
+          pwm_modifyreg(priv, STM32L4_GTIM_CR1_OFFSET, 0, GTIM_CR1_CEN);
+        }
+      else
+        {
+          /* Disable timer counter */
+
+          pwm_modifyreg(priv, STM32L4_GTIM_CR1_OFFSET, GTIM_CR1_CEN, 0);
+        }
+#ifdef HAVE_LPTIM
+    }
+  else
+    {
+      if (state == true)
+        {
+          /* Enable timer counter */
+
+          pwm_modifyreg(priv, STM32L4_LPTIM_CR_OFFSET, 0, LPTIM_CR_ENABLE);
+        }
+      else
+        {
+          /* Disable timer counter */
+
+          pwm_modifyreg(priv, STM32L4_LPTIM_CR_OFFSET, LPTIM_CR_ENABLE, 0);
+        }
+    }
 #endif
 
-  /* Calculate optimal values for the timer prescaler and for the timer reload
-   * register.  If 'frequency' is the desired frequency, then
+  return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_frequency_update
+ *
+ * Description:
+ *   Update a PWM timer frequency
+ *
+ ****************************************************************************/
+
+static int pwm_frequency_update(FAR struct pwm_lowerhalf_s *dev,
+                                uint32_t frequency)
+{
+  FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev;
+  uint32_t reload    = 0;
+  uint32_t timclk    = 0;
+  uint32_t prescaler = 0;
+
+  /* Calculate optimal values for the timer prescaler and for the timer
+   * reload register. If 'frequency' is the desired frequency, then
    *
    *   reload = timclk / frequency
    *   timclk = pclk / presc
@@ -923,7 +1940,18 @@ static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv,
    *            = 60,000
    */
 
-  prescaler = (priv->pclk / info->frequency + 65534) / 65535;
+  /* If timer mode is center aligned the frequency of PWM is the half of
+   * intended so multiply by x2
+   */
+
+  if ((priv->mode == STM32L4_TIMMODE_CENTER1) ||
+      (priv->mode == STM32L4_TIMMODE_CENTER2) ||
+      (priv->mode == STM32L4_TIMMODE_CENTER3))
+    {
+      frequency = frequency * 2;
+    }
+
+  prescaler = (priv->pclk / frequency + 65534) / 65535;
   if (prescaler < 1)
     {
       prescaler = 1;
@@ -935,7 +1963,7 @@ static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv,
 
   timclk = priv->pclk / prescaler;
 
-  reload = timclk / info->frequency;
+  reload = timclk / frequency;
   if (reload < 2)
     {
       reload = 1;
@@ -950,774 +1978,1387 @@ static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv,
     }
 
   pwminfo("TIM%u PCLK: %u frequency: %u TIMCLK: %u prescaler: %u reload: %u\n",
-          priv->timid, priv->pclk, info->frequency, timclk, prescaler, reload);
-
-  /* Set up the timer CR1 register:
-   *
-   * 1,8   CKD[1:0] ARPE CMS[1:0] DIR OPM URS UDIS CEN
-   * 2-5   CKD[1:0] ARPE CMS      DIR OPM URS UDIS CEN
-   * 6-7            ARPE              OPM URS UDIS CEN
-   * 9-14  CKD[1:0] ARPE                  URS UDIS CEN
-   * 15-17 CKD[1:0] ARPE              OPM URS UDIS CEN
-   */
+          priv->timid, priv->pclk, frequency, timclk, prescaler, reload);
 
-  cr1 = stm32l4pwm_getreg(priv, STM32L4_GTIM_CR1_OFFSET);
+  /* Set the reload and prescaler values */
 
-  /* Disable the timer until we get it configured */
+  pwm_arr_update(dev, reload);
+  pwm_putreg(priv, STM32L4_GTIM_PSC_OFFSET, (uint16_t)(prescaler - 1));
 
-  cr1 &= ~GTIM_CR1_CEN;
+  return OK;
+}
 
-  /* Set the counter mode for the advanced timers (1,8) and most general
-   * purpose timers (all 2-5, but not 9-17), i.e., all but TIMTYPE_COUNTUP16
-   * and TIMTYPE_BASIC
-   */
+/****************************************************************************
+ * Name: pwm_lp_frequency_update
+ *
+ * Description:
+ *   Update a PWM timer frequency
+ *
+ ****************************************************************************/
 
-#if defined(CONFIG_STM32L4_TIM1_PWM) || defined(CONFIG_STM32L4_TIM2_PWM) || \
-    defined(CONFIG_STM32L4_TIM3_PWM) || defined(CONFIG_STM32L4_TIM4_PWM) || \
-    defined(CONFIG_STM32L4_TIM5_PWM) || defined(CONFIG_STM32L4_TIM8_PWM)
+#ifdef HAVE_LPTIM
+static int pwm_lp_frequency_update(FAR struct pwm_lowerhalf_s *dev,
+                                uint32_t frequency)
+{
+  FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev;
 
-  if (priv->timtype != TIMTYPE_BASIC && priv->timtype != TIMTYPE_COUNTUP16)
-    {
-      /* Select the Counter Mode:
-       *
-       * GTIM_CR1_EDGE: The counter counts up or down depending on the
-       *   direction bit (DIR).
-       * GTIM_CR1_CENTER1, GTIM_CR1_CENTER2, GTIM_CR1_CENTER3: The counter
-       *   counts up then down.
-       * GTIM_CR1_DIR: 0: count up, 1: count down
-       */
+  /* Calculated values */
 
-      cr1 &= ~(GTIM_CR1_DIR | GTIM_CR1_CMS_MASK);
+  uint8_t prescaler;
+  uint32_t timclk;
+  uint32_t reload;
 
-      switch (priv->mode)
-        {
-          case STM32L4_TIMMODE_COUNTUP:
-            cr1 |= GTIM_CR1_EDGE;
-            break;
+  /* Register contents */
 
-          case STM32L4_TIMMODE_COUNTDOWN:
-            cr1 |= GTIM_CR1_EDGE | GTIM_CR1_DIR;
-            break;
+  uint32_t cfgr;
 
-          case STM32L4_TIMMODE_CENTER1:
-            cr1 |= GTIM_CR1_CENTER1;
-            break;
+  /* LPTIM only has 8 possible prescaler values, from /1 to /128
+   * We will attempt to find the lowest prescaler that results
+   * in a maximum reload value which can be represented in 16 bit.
+   * For certain desired frequencies it is possible that the clock
+   * is too high and other one needs to be selected.
+   */
 
-          case STM32L4_TIMMODE_CENTER2:
-            cr1 |= GTIM_CR1_CENTER2;
-            break;
+  for (prescaler = 0; prescaler < 8; prescaler++)
+    {
+      timclk = priv->pclk / (1 << prescaler);
+      reload = timclk / frequency;
 
-          case STM32L4_TIMMODE_CENTER3:
-            cr1 |= GTIM_CR1_CENTER3;
-            break;
+      if (reload <= 65535)
+        {
+          /* The reload counter is feasible, go with it */
 
-          default:
-            pwmerr("ERROR: No such timer mode: %u\n", (unsigned int)priv->mode);
-            return -EINVAL;
+          break;
         }
     }
-#endif
 
-  /* Set the clock division to zero for all (but the basic timers, but there
-   * should be no basic timers in this context
-   */
+  if (reload < 2)
+    {
+      reload = 1;
+    }
+  else if (reload > 65535)
+    {
+      reload = 65535;
+    }
 
-  cr1 &= ~GTIM_CR1_CKD_MASK;
-  stm32l4pwm_putreg(priv, STM32L4_GTIM_CR1_OFFSET, cr1);
+  /* TODO: if the desired frequency is not possible this should give an error
+   * and not simply return the feasible frequency without complaining.
+   */
 
-  /* Set the reload and prescaler values */
+  pwminfo("LPTIM%u PCLK: %u frequency: %u TIMCLK: %u prescaler: %u reload: %u\n",
+          priv->timid, priv->pclk, frequency, timclk, prescaler, reload);
 
-  stm32l4pwm_putreg(priv, STM32L4_GTIM_ARR_OFFSET, (uint16_t)reload);
-  stm32l4pwm_putreg(priv, STM32L4_GTIM_PSC_OFFSET, (uint16_t)(prescaler - 1));
+  /* Set the reload register value */
 
-  /* Set the advanced timer's repetition counter */
+  pwm_arr_update(dev, reload);
 
-#if defined(CONFIG_STM32L4_TIM1_PWM) || defined(CONFIG_STM32L4_TIM8_PWM)
-  if (priv->timtype == TIMTYPE_ADVANCED)
+  /* Set the prescaler value */
+
+  cfgr = pwm_getreg(priv, STM32L4_LPTIM_CFGR_OFFSET);
+
+  cfgr &= ~LPTIM_CFGR_PRESC_MASK;
+  cfgr |= (prescaler << LPTIM_CFGR_PRESC_SHIFT);
+
+  pwm_putreg(priv, STM32L4_LPTIM_CFGR_OFFSET, cfgr);
+
+  return OK;
+}
+#endif /* HAVE_LPTIM */
+
+/****************************************************************************
+ * Name: pwm_timer_configure
+ *
+ * Description:
+ *   Initial configuration for PWM timer
+ *
+ ****************************************************************************/
+
+static int pwm_timer_configure(FAR struct stm32l4_pwmtimer_s *priv)
+{
+  uint16_t cr1 = 0;
+  int      ret = OK;
+
+  /* Set up the timer CR1 register:
+   *
+   * 1,8   CKD[1:0] ARPE CMS[1:0] DIR OPM URS UDIS CEN
+   * 2-5   CKD[1:0] ARPE CMS      DIR OPM URS UDIS CEN
+   * 6-7            ARPE              OPM URS UDIS CEN
+   * 9-14  CKD[1:0] ARPE                  URS UDIS CEN
+   * 15-17 CKD[1:0] ARPE              OPM URS UDIS CEN
+   */
+
+  cr1 = pwm_getreg(priv, STM32L4_GTIM_CR1_OFFSET);
+
+  /* Set the counter mode for the advanced timers (1,8) and most general
+   * purpose timers (all 2-5, but not 9-17), i.e., all but TIMTYPE_COUNTUP16
+   * and TIMTYPE_BASIC
+   */
+
+  if (priv->timtype != TIMTYPE_BASIC && priv->timtype != TIMTYPE_COUNTUP16)
     {
-      /* If a non-zero repetition count has been selected, then set the
-       * repitition counter to the count-1 (stm32l4pwm_start() has already
-       * assured us that the count value is within range).
+      /* Select the Counter Mode:
+       *
+       * GTIM_CR1_EDGE: The counter counts up or down depending on the
+       *   direction bit (DIR).
+       * GTIM_CR1_CENTER1, GTIM_CR1_CENTER2, GTIM_CR1_CENTER3: The counter
+       *   counts up then down.
+       * GTIM_CR1_DIR: 0: count up, 1: count down
        */
 
-#ifdef CONFIG_PWM_PULSECOUNT
-      if (info->count > 0)
+      cr1 &= ~(GTIM_CR1_DIR | GTIM_CR1_CMS_MASK);
+
+      switch (priv->mode)
+        {
+          case STM32L4_TIMMODE_COUNTUP:
+            {
+              cr1 |= GTIM_CR1_EDGE;
+              break;
+            }
+
+          case STM32L4_TIMMODE_COUNTDOWN:
+            {
+              cr1 |= GTIM_CR1_EDGE | GTIM_CR1_DIR;
+              break;
+            }
+
+          case STM32L4_TIMMODE_CENTER1:
+            {
+              cr1 |= GTIM_CR1_CENTER1;
+              break;
+            }
+
+          case STM32L4_TIMMODE_CENTER2:
+            {
+              cr1 |= GTIM_CR1_CENTER2;
+              break;
+            }
+
+          case STM32L4_TIMMODE_CENTER3:
+            {
+              cr1 |= GTIM_CR1_CENTER3;
+              break;
+            }
+
+          default:
+            {
+              pwmerr("ERROR: No such timer mode: %u\n",
+                     (unsigned int)priv->mode);
+              ret = -EINVAL;
+              goto errout;
+            }
+        }
+    }
+
+  /* Enable ARR Preload
+   * TODO: this should be configurable
+   */
+
+  cr1 |= GTIM_CR1_ARPE;
+
+  /* Write CR1 */
+
+  pwm_putreg(priv, STM32L4_GTIM_CR1_OFFSET, cr1);
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: pwm_mode_configure
+ *
+ * Description:
+ *   Configure a PWM mode for given channel
+ *
+ ****************************************************************************/
+
+static int pwm_mode_configure(FAR struct pwm_lowerhalf_s *dev,
+                              uint8_t channel, uint32_t mode)
+{
+  FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev;
+  uint32_t chanmode = 0;
+  uint32_t ocmode   = 0;
+  uint32_t ccmr     = 0;
+  uint32_t offset   = 0;
+  int      ret      = OK;
+  bool     ocmbit   = false;
+
+  /* Only advanced timers have channels 5-6 */
+
+  if (channel > 4 && priv->timtype != TIMTYPE_ADVANCED)
+    {
+      pwmerr("ERROR: No such channel: %u\n", channel);
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  /* Get channel mode
+   * TODO: configurable preload for CCxR
+   */
+
+  switch (mode)
+    {
+      case STM32L4_CHANMODE_FRZN:
+        {
+          chanmode = GTIM_CCMR_MODE_FRZN;
+          break;
+        }
+
+      case STM32L4_CHANMODE_CHACT:
+        {
+          chanmode = GTIM_CCMR_MODE_CHACT;
+          break;
+        }
+
+      case STM32L4_CHANMODE_CHINACT:
+        {
+          chanmode = GTIM_CCMR_MODE_CHINACT;
+          break;
+        }
+
+      case STM32L4_CHANMODE_OCREFTOG:
+        {
+          chanmode = GTIM_CCMR_MODE_OCREFTOG;
+          break;
+        }
+
+      case STM32L4_CHANMODE_OCREFLO:
+        {
+          chanmode = GTIM_CCMR_MODE_OCREFLO;
+          break;
+        }
+
+      case STM32L4_CHANMODE_OCREFHI:
+        {
+          chanmode = GTIM_CCMR_MODE_OCREFHI;
+          break;
+        }
+
+      case STM32L4_CHANMODE_PWM1:
+        {
+          chanmode = ATIM_CCMR_MODE_PWM1;
+          break;
+        }
+
+      case STM32L4_CHANMODE_PWM2:
+        {
+          chanmode = ATIM_CCMR_MODE_PWM2;
+          break;
+        }
+
+      case STM32L4_CHANMODE_COMBINED1:
+        {
+          chanmode = ATIM_CCMR_MODE_COMBINED1;
+          ocmbit   = true;
+          break;
+        }
+
+      case STM32L4_CHANMODE_COMBINED2:
+        {
+          chanmode = ATIM_CCMR_MODE_COMBINED2;
+          ocmbit   = true;
+          break;
+        }
+
+      case STM32L4_CHANMODE_ASYMMETRIC1:
+        {
+          chanmode = ATIM_CCMR_MODE_ASYMMETRIC1;
+          ocmbit   = true;
+          break;
+        }
+
+      case STM32L4_CHANMODE_ASYMMETRIC2:
+        {
+          chanmode = ATIM_CCMR_MODE_ASYMMETRIC2;
+          ocmbit   = true;
+          break;
+        }
+
+      default:
+        {
+          pwmerr("ERROR: No such mode: %u\n", (unsigned int)mode);
+          ret = -EINVAL;
+          goto errout;
+        }
+    }
+
+  /* PWM mode configuration */
+
+  switch (channel)
+    {
+      /* Get CCMR offset */
+
+      case STM32L4_PWM_CHAN1:
+      case STM32L4_PWM_CHAN2:
+        {
+          offset = STM32L4_GTIM_CCMR1_OFFSET;
+          break;
+        }
+
+      case STM32L4_PWM_CHAN3:
+      case STM32L4_PWM_CHAN4:
+        {
+          offset = STM32L4_GTIM_CCMR2_OFFSET;
+          break;
+        }
+
+      case STM32L4_PWM_CHAN5:
+      case STM32L4_PWM_CHAN6:
+        {
+          offset = STM32L4_ATIM_CCMR3_OFFSET;
+          break;
+        }
+
+      default:
+        {
+          pwmerr("ERROR: No such channel: %u\n", channel);
+          ret = -EINVAL;
+          goto errout;
+        }
+    }
+
+  /* Get current registers */
+
+  ccmr = pwm_getreg(priv, offset);
+
+  /* PWM mode configuration.
+   * NOTE: The CCMRx registers are identical if the channels are outputs.
+   */
+
+  switch (channel)
+    {
+      /* Configure channel 1/3/5 */
+
+      case STM32L4_PWM_CHAN1:
+      case STM32L4_PWM_CHAN3:
+      case STM32L4_PWM_CHAN5:
+        {
+          /* Reset current channel 1/3/5 mode configuration */
+
+          ccmr &= ~(ATIM_CCMR1_CC1S_MASK | ATIM_CCMR1_OC1M_MASK |
+                     ATIM_CCMR1_OC1PE);
+
+          /* Configure CC1/3/5 as output */
+
+          ocmode |= (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC1S_SHIFT);
+
+          /* Configure Compare 1/3/5 mode */
+
+          ocmode |= (chanmode << ATIM_CCMR1_OC1M_SHIFT);
+
+          /* Enable CCR1/3/5 preload */
+
+          ocmode |= ATIM_CCMR1_OC1PE;
+
+          /* Reset current OC bit */
+
+          ccmr &= ~(ATIM_CCMR1_OC1M);
+
+          /* Set an additional OC1/3/5M bit */
+
+          if (ocmbit)
+            {
+              ocmode |= ATIM_CCMR1_OC1M;
+            }
+          break;
+        }
+
+      /* Configure channel 2/4/6 */
+
+      case STM32L4_PWM_CHAN2:
+      case STM32L4_PWM_CHAN4:
+      case STM32L4_PWM_CHAN6:
+        {
+          /* Reset current channel 2/4/6 mode configuration */
+
+          ccmr &= ~(ATIM_CCMR1_CC2S_MASK | ATIM_CCMR1_OC2M_MASK |
+                     ATIM_CCMR1_OC2PE);
+
+          /* Configure CC2/4/6 as output */
+
+          ocmode |= (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC2S_SHIFT);
+
+          /* Configure Compare 2/4/6 mode */
+
+          ocmode |= (chanmode << ATIM_CCMR1_OC2M_SHIFT);
+
+          /* Enable CCR2/4/6 preload */
+
+          ocmode |= ATIM_CCMR1_OC2PE;
+
+          /* Reset current OC bit */
+
+          ccmr &= ~(ATIM_CCMR1_OC2M);
+
+          /* Set an additioneal OC2/4/6M bit */
+
+          if (ocmbit)
+            {
+              ocmode |= ATIM_CCMR1_OC2M;
+            }
+          break;
+        }
+    }
+
+  /* Set the selected output compare mode */
+
+  ccmr |= ocmode;
+
+  /* Write CCMRx registers */
+
+  pwm_putreg(priv, offset, ccmr);
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: pwm_output_configure
+ *
+ * Description:
+ *   Configure PWM output for given channel
+ *
+ ****************************************************************************/
+
+static int pwm_output_configure(FAR struct stm32l4_pwmtimer_s *priv,
+                                uint8_t channel)
+{
+  uint32_t cr2  = 0;
+  uint32_t ccer = 0;
+
+  /* Get current registers state */
+
+  cr2  = pwm_getreg(priv, STM32L4_GTIM_CR2_OFFSET);
+  ccer = pwm_getreg(priv, STM32L4_GTIM_CCER_OFFSET);
+
+  /* | OISx/OISxN  | IDLE | for ADVANCED and COUNTUP16 | CR2 register
+   * | CCxP/CCxNP  | POL  | all PWM timers             | CCER register
+   */
+
+  /* Configure output polarity (all PWM timers) */
+
+  if (priv->channels[channel - 1].out1.pol == STM32L4_POL_NEG)
+    {
+      ccer |= (GTIM_CCER_CC1P << ((channel - 1) * 4));
+    }
+  else
+    {
+      ccer &= ~(GTIM_CCER_CC1P << ((channel - 1) * 4));
+    }
+
+#ifdef HAVE_ADVTIM
+  if (priv->timtype == TIMTYPE_ADVANCED ||
+      priv->timtype == TIMTYPE_COUNTUP16_N)
+    {
+      /* Configure output IDLE State */
+
+      if (priv->channels[channel - 1].out1.idle == STM32L4_IDLE_ACTIVE)
+        {
+          cr2 |= (ATIM_CR2_OIS1 << ((channel - 1) * 2));
+        }
+      else
+        {
+          cr2 &= ~(ATIM_CR2_OIS1 << ((channel - 1) * 2));
+        }
+
+#ifdef HAVE_PWM_COMPLEMENTARY
+      /* Configure complementary output IDLE state */
+
+      if (priv->channels[channel - 1].out2.idle == STM32L4_IDLE_ACTIVE)
+        {
+          cr2 |= (ATIM_CR2_OIS1N << ((channel - 1) * 2));
+        }
+      else
         {
-          /* Save the remaining count and the number of counts that will have
-           * elapsed on the first interrupt.
-           */
+          cr2 &= ~(ATIM_CR2_OIS1N << ((channel - 1)* 2));
+        }
+
+      /* Configure complementary output polarity */
+
+      if (priv->channels[channel - 1].out2.pol == STM32L4_POL_NEG)
+        {
+          ccer |= (ATIM_CCER_CC1NP << ((channel - 1) * 4));
+        }
+      else
+        {
+          ccer &= ~(ATIM_CCER_CC1NP << ((channel - 1) * 4));
+        }
+#endif  /* HAVE_PWM_COMPLEMENTARY */
+
+      /* TODO: OIS5 and OIS6 */
+
+      cr2 &= ~(ATIM_CR2_OIS5 | ATIM_CR2_OIS6);
+
+      /* TODO: CC5P and CC6P */
+
+      ccer &= ~(ATIM_CCER_CC5P | ATIM_CCER_CC6P);
+    }
+#ifdef HAVE_GTIM_CCXNP
+  else
+#endif  /* HAVE_GTIM_CCXNP */
+#endif  /* HAVE_ADVTIM */
+#ifdef HAVE_GTIM_CCXNP
+    {
+      /* CCxNP must be cleared if not ADVANCED timer.
+       *
+       * REVISIT: not all families have CCxNP bits for GTIM,
+       *          which causes an ugly condition above
+       */
+
+      ccer &= ~(GTIM_CCER_CC1NP << ((channel - 1) * 4));
+    }
+#endif  /* HAVE_GTIM_CCXNP */
+
+  /* Write registers */
+
+  pwm_modifyreg(priv, STM32L4_GTIM_CR2_OFFSET, 0, cr2);
+  pwm_modifyreg(priv, STM32L4_GTIM_CCER_OFFSET, 0, ccer);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_outputs_enable
+ *
+ * Description:
+ *   Enable/disable given timer PWM outputs.
+ *
+ *   NOTE: This is bulk operation - we can enable/disable many outputs
+ *   at one time
+ *
+ * Input Parameters:
+ *   dev     - A reference to the lower half PWM driver state structure
+ *   outputs - outputs to set (look at enum stm32l4_chan_e in stm32l4_pwm.h)
+ *   state   - Enable/disable operation
+ *
+ ****************************************************************************/
+
+static int pwm_outputs_enable(FAR struct pwm_lowerhalf_s *dev,
+                              uint16_t outputs, bool state)
+{
+  FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev;
+  uint32_t ccer   = 0;
+  uint32_t regval = 0;
+
+  /* Get curren register state */
 
-          /* If the first interrupt occurs at the end end of the first
-           * repetition count, then the count will be the same as the RCR
-           * value.
-           */
+  ccer = pwm_getreg(priv, STM32L4_GTIM_CCER_OFFSET);
 
-          priv->prev  = stm32l4pwm_pulsecount(info->count);
-          stm32l4pwm_putreg(priv, STM32L4_ATIM_RCR_OFFSET, (uint16_t)priv->prev - 1);
+  /* Get outputs configuration */
 
-          /* Generate an update event to reload the prescaler.  This should
-           * preload the RCR into active repetition counter.
-           */
+  regval |= ((outputs & STM32L4_PWM_OUT1)  ? ATIM_CCER_CC1E  : 0);
+  regval |= ((outputs & STM32L4_PWM_OUT1N) ? ATIM_CCER_CC1NE : 0);
+  regval |= ((outputs & STM32L4_PWM_OUT2)  ? ATIM_CCER_CC2E  : 0);
+  regval |= ((outputs & STM32L4_PWM_OUT2N) ? ATIM_CCER_CC2NE : 0);
+  regval |= ((outputs & STM32L4_PWM_OUT3)  ? ATIM_CCER_CC3E  : 0);
+  regval |= ((outputs & STM32L4_PWM_OUT3N) ? ATIM_CCER_CC3NE : 0);
+  regval |= ((outputs & STM32L4_PWM_OUT4)  ? ATIM_CCER_CC4E  : 0);
 
-          stm32l4pwm_putreg(priv, STM32L4_GTIM_EGR_OFFSET, ATIM_EGR_UG);
+  /* NOTE: CC4N does not exist, but some docs show configuration bits for it */
 
-          /* Now set the value of the RCR that will be loaded on the next
-           * update event.
-           */
+  regval |= ((outputs & STM32L4_PWM_OUT5)  ? ATIM_CCER_CC5E  : 0);
+  regval |= ((outputs & STM32L4_PWM_OUT6)  ? ATIM_CCER_CC6E  : 0);
 
-          priv->count = info->count;
-          priv->curr  = stm32l4pwm_pulsecount(info->count - priv->prev);
-          stm32l4pwm_putreg(priv, STM32L4_ATIM_RCR_OFFSET, (uint16_t)priv->curr - 1);
+  if (state == true)
+    {
+      /* Enable outpus - set bits */
+
+      ccer |= regval;
+    }
+  else
+    {
+      /* Disable outputs - reset bits */
+
+      ccer &= ~regval;
+    }
+
+  /* Write register */
+
+  pwm_putreg(priv, STM32L4_GTIM_CCER_OFFSET, ccer);
+
+  return OK;
+}
+
+#if defined(HAVE_PWM_COMPLEMENTARY) && defined(CONFIG_STM32L4_PWM_LL_OPS)
+
+/****************************************************************************
+ * Name: pwm_deadtime_update
+ ****************************************************************************/
+
+static int pwm_deadtime_update(FAR struct pwm_lowerhalf_s *dev, uint8_t dt)
+{
+  FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev;
+  uint32_t bdtr = 0;
+  int      ret  = OK;
+
+  /* Check if locked */
+
+  if (priv->lock > 0)
+    {
+      ret = -EACCES;
+      goto errout;
+    }
+
+  /* Get current register state */
+
+  bdtr = pwm_getreg(priv, STM32L4_ATIM_BDTR_OFFSET);
+
+  /* TODO: check if BDTR not locked */
+
+  /* Update deadtime */
+
+  bdtr &= ~(ATIM_BDTR_DTG_MASK);
+  bdtr |= (dt << ATIM_BDTR_DTG_SHIFT);
+
+  /* Write BDTR register */
+
+  pwm_putreg(priv, STM32L4_ATIM_BDTR_OFFSET, bdtr);
+
+errout:
+  return ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: pwm_soft_update
+ *
+ * Description:
+ *   Generate an software update event
+ *
+ ****************************************************************************/
+
+static int pwm_soft_update(FAR struct pwm_lowerhalf_s *dev)
+{
+  FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev;
+
+  pwm_putreg(priv, STM32L4_GTIM_EGR_OFFSET, ATIM_EGR_UG);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_soft_break
+ *
+ * Description:
+ *   Generate an software break event
+ *
+ *   Outputs are enabled if state is false.
+ *   Outputs are disabled if state is true.
+ *
+ *   NOTE: only timers with complementary outputs have BDTR register and
+ *         support software break.
+ *
+ ****************************************************************************/
+
+static int pwm_soft_break(FAR struct pwm_lowerhalf_s *dev, bool state)
+{
+  FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev;
+
+  if (state == true)
+    {
+      /* Reset MOE bit */
+
+      pwm_modifyreg(priv, STM32L4_ATIM_BDTR_OFFSET, ATIM_BDTR_MOE, 0);
+    }
+  else
+    {
+      /* Set MOE bit */
+
+      pwm_modifyreg(priv, STM32L4_ATIM_BDTR_OFFSET, 0, ATIM_BDTR_MOE);
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: pwm_outputs_from_channels
+ *
+ * Description:
+ *   Get enabled outputs configuration from the PWM timer state
+ *
+ ****************************************************************************/
+
+static uint16_t pwm_outputs_from_channels(FAR struct stm32l4_pwmtimer_s *priv)
+{
+  uint16_t outputs = 0;
+  uint8_t  channel = 0;
+  uint8_t  i       = 0;
+
+  for (i = 0; i < priv->chan_num; i += 1)
+    {
+      /* Get channel */
+
+      channel = priv->channels[i].channel;
+
+      /* Set outputs if channel configured */
+
+      if (channel != 0)
+        {
+          /* Enable output if confiugred */
+
+          if (priv->channels[i].out1.in_use == 1)
+            {
+              outputs |= (STM32L4_PWM_OUT1 << ((channel - 1) * 2));
+            }
+
+#ifdef HAVE_PWM_COMPLEMENTARY
+          /* Enable complementary output if configured */
+
+          if (priv->channels[i].out2.in_use == 1)
+            {
+              outputs |= (STM32L4_PWM_OUT1N << ((channel - 1) * 2));
+            }
+#endif
         }
+    }
+
+  return outputs;
+}
+
+#ifdef HAVE_ADVTIM
+
+/****************************************************************************
+ * Name: pwm_break_dt_configure
+ *
+ * Description:
+ *   Configure break and deadtime
+ *
+ * NOTE: we have to configure all BDTR registers at once due to possible
+ *       lock configuration
+ *
+ ****************************************************************************/
 
-      /* Otherwise, just clear the repetition counter */
+static int pwm_break_dt_configure(FAR struct stm32l4_pwmtimer_s *priv)
+{
+  uint32_t bdtr = 0;
 
-      else
-#endif
-        {
-          /* Set the repetition counter to zero */
+  /* Set the clock division to zero for all (but the basic timers, but there
+   * should be no basic timers in this context
+   */
 
-          stm32l4pwm_putreg(priv, STM32L4_ATIM_RCR_OFFSET, 0);
+  pwm_modifyreg(priv, STM32L4_GTIM_CR1_OFFSET, GTIM_CR1_CKD_MASK,
+                priv->t_dts << GTIM_CR1_CKD_SHIFT);
 
-          /* Generate an update event to reload the prescaler */
+#ifdef HAVE_PWM_COMPLEMENTARY
+  /* Initialize deadtime */
 
-          stm32l4pwm_putreg(priv, STM32L4_GTIM_EGR_OFFSET, ATIM_EGR_UG);
-        }
-    }
-  else
+  bdtr |= (priv->deadtime << ATIM_BDTR_DTG_SHIFT);
 #endif
-    {
-      /* Generate an update event to reload the prescaler (all timers) */
 
-      stm32l4pwm_putreg(priv, STM32L4_GTIM_EGR_OFFSET, ATIM_EGR_UG);
-    }
-
-  /* Handle channel specific setup */
+#ifdef HAVE_BREAK
+  /* Configure Break 1 */
 
-  ccenable  = 0;
-  ccnenable = 0;
-  ocmode1   = 0;
-  ocmode2   = 0;
-
-#ifdef CONFIG_PWM_MULTICHAN
-  for (i = 0; i < CONFIG_PWM_NCHANNELS; i++)
-#endif
+  if (priv->brk.en1 == 1)
     {
-      ub16_t                duty;
-      uint32_t              chanmode;
-      uint32_t              compout; /* Complementary output config */
-      bool                  ocmbit = false;
-      uint8_t               channel;
-#ifdef CONFIG_PWM_MULTICHAN
-      int                   j;
-#endif
-      enum stm32l4_chanmode_e mode;
-
-#ifdef CONFIG_PWM_MULTICHAN
-      duty = info->channels[i].duty;
-      channel = info->channels[i].channel;
+      /* Enable Break 1 */
 
-      /* A value of zero means to skip this channel */
-
-      if (channel == 0)
-        {
-          continue;
-        }
+      bdtr |= ATIM_BDTR_BKE;
 
-      /* Find the channel */
+      /* Set Break 1 polarity */
 
-      for (j = 0; j < PWM_NCHANNELS; j++)
-        {
-          if (priv->channels[j].channel == channel)
-            {
-              mode = priv->channels[j].mode;
-              compout = priv->channels[j].npincfg;
-              break;
-            }
-        }
+      bdtr |= (priv->brk.pol1 == STM32L4_POL_NEG ? ATIM_BDTR_BKP : 0);
+    }
 
-      if (j >= PWM_NCHANNELS)
-        {
-          pwmerr("ERROR: No such channel: %u\n", channel);
-          return -EINVAL;
-        }
-#else
-      duty = info->duty;
-      channel = priv->channels[0].channel;
-      mode = priv->channels[0].mode;
-      compout = priv->channels[0].npincfg;
-#endif
+  /* Configure Break 1 */
 
-      /* Duty cycle:
-       *
-       * duty cycle = ccr / reload (fractional value)
-       */
+  if (priv->brk.en2 == 1)
+    {
+      /* Enable Break 2 */
 
-      ccr = b16toi(duty * reload + b16HALF);
+      bdtr |= ATIM_BDTR_BK2E;
 
-      pwminfo("ccr: %u\n", ccr);
+      /* Set Break 2 polarity */
 
-      switch (mode)
-        {
-          case STM32L4_CHANMODE_PWM1:
-            chanmode = ATIM_CCMR_MODE_PWM1;
-            break;
+      bdtr |= (priv->brk.pol2 == STM32L4_POL_NEG ? ATIM_BDTR_BK2P : 0);
 
-          case STM32L4_CHANMODE_PWM2:
-            chanmode = ATIM_CCMR_MODE_PWM2;
-            break;
+      /* Configure BRK2 filter */
 
-          case STM32L4_CHANMODE_COMBINED1:
-            chanmode = ATIM_CCMR_MODE_COMBINED1;
-            ocmbit = true;
-            break;
+      bdtr |= (priv->brk.flt2 << ATIM_BDTR_BK2F_SHIFT);
+    }
 
-          case STM32L4_CHANMODE_COMBINED2:
-            chanmode = ATIM_CCMR_MODE_COMBINED2;
-            ocmbit = true;
-            break;
+#endif  /* HAVE_BREAK */
 
-          case STM32L4_CHANMODE_ASYMMETRIC1:
-            chanmode = ATIM_CCMR_MODE_ASYMMETRIC1;
-            ocmbit = true;
-            break;
+  /* Clear the OSSI and OSSR bits in the BDTR register.
+   *
+   * REVISIT: this should be configurable
+   */
 
-          case STM32L4_CHANMODE_ASYMMETRIC2:
-            chanmode = ATIM_CCMR_MODE_ASYMMETRIC2;
-            ocmbit = true;
-            break;
+  bdtr &= ~(ATIM_BDTR_OSSI | ATIM_BDTR_OSSR);
 
-          default:
-            pwmerr("ERROR: No such mode: %u\n", (unsigned int)mode);
-            return -EINVAL;
-        }
+  /* Configure lock */
 
-      switch (channel)
-        {
-          case 1:  /* PWM Mode configuration: Channel 1 */
-            {
-              /* Select the CCER enable bit for this channel */
+  bdtr |= priv->lock << ATIM_BDTR_LOCK_SHIFT;
 
-              ccenable |= ATIM_CCER_CC1E;
+  /* Write BDTR register at once */
 
-              /* Conditionally enable the complementary output */
+  pwm_putreg(priv, STM32L4_ATIM_BDTR_OFFSET, bdtr);
 
-              if (compout)
-                {
-                  ccnenable |= ATIM_CCER_CC1NE;
-                }
+  return OK;
+}
 
-              /* Set the CCMR1 mode values (leave CCMR2 zero) */
+#endif /* HAVE_ADVTIM */
 
-              ocmode1  |= (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC1S_SHIFT) |
-                          (chanmode << ATIM_CCMR1_OC1M_SHIFT) |
-                          ATIM_CCMR1_OC1PE;
+/****************************************************************************
+ * Name: pwm_configure
+ *
+ * Description:
+ *   Configure PWM timer in normal mode (no PULSECOUNT)
+ *
+ ****************************************************************************/
 
-              if (ocmbit)
-                {
-                  ocmode1 |= ATIM_CCMR1_OC1M;
-                }
+static int pwm_configure(FAR struct pwm_lowerhalf_s *dev)
+{
+  FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev;
+  uint16_t outputs = 0;
+  uint8_t j        = 0;
+  int     ret      = OK;
 
-              /* Set the duty cycle by writing to the CCR register for this channel */
+  /* NOTE: leave timer counter disabled and all outputs disabled! */
 
-              stm32l4pwm_putreg(priv, STM32L4_GTIM_CCR1_OFFSET, (uint16_t)ccr);
-            }
-            break;
+  /* Disable the timer until we get it configured */
 
-          case 2:  /* PWM Mode configuration: Channel 2 */
-            {
-              /* Select the CCER enable bit for this channel */
+  pwm_timer_enable(dev, false);
 
-              ccenable |= ATIM_CCER_CC2E;
+  /* Get configured outputs */
 
-              /* Conditionally enable the complementary output */
+  outputs = pwm_outputs_from_channels(priv);
 
-              if (compout)
-                {
-                  ccnenable |= ATIM_CCER_CC2NE;
-                }
+  /* Disable outputs */
 
-              /* Set the CCMR1 mode values (leave CCMR2 zero) */
+  ret = pwm_outputs_enable(dev, outputs, false);
+  if (ret < 0)
+    {
+      pwmerr("ERROR on pwm_outputs_enable()\n");
+      goto errout;
+    }
 
-              ocmode1  |= (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC2S_SHIFT) |
-                          (chanmode << ATIM_CCMR1_OC2M_SHIFT) |
-                          ATIM_CCMR1_OC2PE;
+  /* Initial timer configuration */
 
-              if (ocmbit)
-                {
-                  ocmode1 |= ATIM_CCMR1_OC2M;
-                }
+  ret = pwm_timer_configure(priv);
+  if (ret < 0)
+    {
+      pwmerr("ERROR on pwm_timer_configure()\n");
+      goto errout;
+    }
 
-              /* Set the duty cycle by writing to the CCR register for this channel */
+  /* Some special setup for advanced timers */
 
-              stm32l4pwm_putreg(priv, STM32L4_GTIM_CCR2_OFFSET, (uint16_t)ccr);
-            }
-            break;
+#ifdef HAVE_ADVTIM
+  if (priv->timtype == TIMTYPE_ADVANCED ||
+      priv->timtype == TIMTYPE_COUNTUP16_N)
+    {
+      /* Configure break and deadtime register */
 
-          case 3:  /* PWM Mode configuration: Channel 3 */
-            {
-              /* Select the CCER enable bit for this channel */
+      ret = pwm_break_dt_configure(priv);
+      if (ret < 0)
+        {
+          pwmerr("ERROR on pwm_break_dt_configure()\n");
+          goto errout;
+        }
 
-              ccenable |= ATIM_CCER_CC3E;
+#ifdef HAVE_TRGO
+      /* Configure TRGO/TRGO2 */
 
-              /* Conditionally enable the complementary output */
+      ret = pwm_sync_configure(priv, priv->trgo);
+      if (ret < 0)
+        {
+          pwmerr("ERROR on pwm_sync_configure()\n");
+          goto errout;
+        }
+#endif
+    }
+#endif
 
-              if (compout)
-                {
-                  ccnenable |= ATIM_CCER_CC3NE;
-                }
+  /* Configure timer channels */
 
-              /* Set the CCMR2 mode values (leave CCMR1 zero) */
+  for (j = 0; j < priv->chan_num; j++)
+    {
+      /* Skip channle if not in use */
 
-              ocmode2  |= (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR2_CC3S_SHIFT) |
-                          (chanmode << ATIM_CCMR2_OC3M_SHIFT) |
-                          ATIM_CCMR2_OC3PE;
+      if (priv->channels[j].channel != 0)
+        {
+          /* Update PWM mode */
 
-              if (ocmbit)
-                {
-                  ocmode2 |= ATIM_CCMR2_OC3M;
-                }
+          ret = pwm_mode_configure(dev, priv->channels[j].channel,
+                                   priv->channels[j].mode);
+          if (ret < 0)
+            {
+              pwmerr("ERROR on pwm_mode_configure()\n");
+              goto errout;
+            }
 
-              /* Set the duty cycle by writing to the CCR register for this channel */
+          /* PWM outputs configuration */
 
-              stm32l4pwm_putreg(priv, STM32L4_GTIM_CCR3_OFFSET, (uint16_t)ccr);
+          ret = pwm_output_configure(priv, priv->channels[j].channel);
+          if (ret < 0)
+            {
+              pwmerr("ERROR on pwm_output_configure()\n");
+              goto errout;
             }
-            break;
+        }
+    }
 
-          case 4:  /* PWM Mode configuration: Channel 4 */
-            {
-              /* Select the CCER enable bit for this channel */
+  /* Disable software break at the end of the outputs configuration (enablei
+   * outputs).
+   *
+   * NOTE: Only timers with complementary outputs have BDTR register and
+   *       support software break.
+   */
 
-              ccenable |= ATIM_CCER_CC4E;
+  if (priv->timtype == TIMTYPE_ADVANCED ||
+      priv->timtype == TIMTYPE_COUNTUP16_N)
+    {
+      pwminfo("pwm_soft_break(dev, false)\n");
+      ret = pwm_soft_break(dev, false);
+      if (ret < 0)
+        {
+          pwmerr("ERROR on pwm_soft_break()\n");
+          goto errout;
+        }
+    }
 
-              /* Set the CCMR2 mode values (leave CCMR1 zero) */
+errout:
+  return ret;
+}
 
-              ocmode2  |= (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR2_CC4S_SHIFT) |
-                          (chanmode << ATIM_CCMR2_OC4M_SHIFT) |
-                          ATIM_CCMR2_OC4PE;
+#ifdef CONFIG_PWM_PULSECOUNT
 
-              if (ocmbit)
-                {
-                  ocmode2 |= ATIM_CCMR2_OC4M;
-                }
+/****************************************************************************
+ * Name: pwm_pulsecount_timer
+ *
+ * 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
+ *
+ * TODO: PWM_PULSECOUNT should be configurable for each timer instance
+ * TODO: PULSECOUNT doesnt work with MULTICHAN at this moment
+ *
+ ****************************************************************************/
 
-              /* Set the duty cycle by writing to the CCR register for this channel */
+static int pwm_pulsecount_timer(FAR struct pwm_lowerhalf_s *dev,
+                                FAR const struct pwm_info_s *info)
+{
+  FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev;
+  ub16_t    duty    = 0;
+  uint8_t   channel = 0;
+  uint16_t  outputs = 0;
+  int       ret     = OK;
 
-              stm32l4pwm_putreg(priv, STM32L4_GTIM_CCR4_OFFSET, (uint16_t)ccr);
-            }
-            break;
+  /* If we got here it means that timer instance support pulsecount mode! */
 
-          default:
-            pwmerr("ERROR: No such channel: %u\n", channel);
-            return -EINVAL;
-        }
-    }
+  DEBUGASSERT(priv != NULL && info != NULL);
 
-  /* Disable the Channel by resetting the CCxE Bit in the CCER register */
+  pwminfo("TIM%u channel: %u frequency: %u duty: %08x count: %u\n",
+          priv->timid, priv->channels[0].channel, info->frequency,
+          info->duty, info->count);
 
-  ccer = stm32l4pwm_getreg(priv, STM32L4_GTIM_CCER_OFFSET);
-  ccer &= ~ccenable;
-  stm32l4pwm_putreg(priv, STM32L4_GTIM_CCER_OFFSET, ccer);
+  DEBUGASSERT(info->frequency > 0);
 
-  /* Fetch the CR2, CCMR1, and CCMR2 register (already have cr1 and ccer) */
+  /* Channel specific setup */
 
-  cr2   = stm32l4pwm_getreg(priv, STM32L4_GTIM_CR2_OFFSET);
-  ccmr1 = stm32l4pwm_getreg(priv, STM32L4_GTIM_CCMR1_OFFSET);
-  ccmr2 = stm32l4pwm_getreg(priv, STM32L4_GTIM_CCMR2_OFFSET);
+  duty    = info->duty;
+  channel = priv->channels[0].channel;
 
-  /* Reset the Output Compare Mode Bits and set the select output compare mode */
+  /* Disable all interrupts and DMA requests, clear all pending status */
 
-  ccmr1 &= ~(ATIM_CCMR1_CC1S_MASK | ATIM_CCMR1_OC1M_MASK | ATIM_CCMR1_OC1PE |
-             ATIM_CCMR1_CC2S_MASK | ATIM_CCMR1_OC2M_MASK | ATIM_CCMR1_OC2PE
-             | ATIM_CCMR1_OC1M | ATIM_CCMR1_OC2M
-             );
-  ccmr2 &= ~(ATIM_CCMR2_CC3S_MASK | ATIM_CCMR2_OC3M_MASK | ATIM_CCMR2_OC3PE |
-             ATIM_CCMR2_CC4S_MASK | ATIM_CCMR2_OC4M_MASK | ATIM_CCMR2_OC4PE
-             | ATIM_CCMR2_OC3M | ATIM_CCMR2_OC4M
-             );
-  ccmr1 |= ocmode1;
-  ccmr2 |= ocmode2;
+  pwm_putreg(priv, STM32L4_GTIM_DIER_OFFSET, 0);
+  pwm_putreg(priv, STM32L4_GTIM_SR_OFFSET, 0);
 
-  /* Reset the output polarity level of all channels (selects high polarity)*/
+  /* Set timer frequency */
 
-  ccer &= ~(ATIM_CCER_CC1P | ATIM_CCER_CC2P | ATIM_CCER_CC3P | ATIM_CCER_CC4P);
+  ret = pwm_frequency_update(dev, info->frequency);
+  if (ret < 0)
+    {
+      goto errout;
+    }
 
-  /* Enable the output state of the selected channels */
+  /* Update duty cycle */
 
-  ccer &= ~(ATIM_CCER_CC1E | ATIM_CCER_CC2E | ATIM_CCER_CC3E | ATIM_CCER_CC4E);
-  ccer |= ccenable;
+  ret = pwm_duty_update(dev, channel, duty);
+  if (ret < 0)
+    {
+      goto errout;
+    }
 
-  /* Some special setup for advanced timers */
+  /* If a non-zero repetition count has been selected, then set the
+   * repitition counter to the count-1 (pwm_pulsecount_start() has already
+   * assured us that the count value is within range).
+   */
 
-#if defined(CONFIG_STM32L4_TIM1_PWM) || defined(CONFIG_STM32L4_TIM8_PWM)
-  if (priv->timtype == TIMTYPE_ADVANCED)
+  if (info->count > 0)
     {
-      uint16_t bdtr;
-
-      /* Reset output N polarity level, output N state, output compare state,
-       * output compare N idle state.
+      /* Save the remaining count and the number of counts that will have
+       * elapsed on the first interrupt.
        */
 
-      ccer &= ~(ATIM_CCER_CC1NE | ATIM_CCER_CC1NP | ATIM_CCER_CC2NE |
-                ATIM_CCER_CC2NP | ATIM_CCER_CC3NE | ATIM_CCER_CC3NP);
+      /* If the first interrupt occurs at the end end of the first
+       * repetition count, then the count will be the same as the RCR
+       * value.
+       */
 
-      ccer |= ccnenable;
+      priv->prev  = stm32l4pwm_pulsecount(info->count);
+      pwm_putreg(priv, STM32L4_ATIM_RCR_OFFSET, (uint16_t)priv->prev - 1);
 
-      /* Reset the output compare and output compare N IDLE State */
+      /* Generate an update event to reload the prescaler.  This should
+       * preload the RCR into active repetition counter.
+       */
 
-      cr2 &= ~(ATIM_CR2_OIS1 | ATIM_CR2_OIS1N | ATIM_CR2_OIS2 | ATIM_CR2_OIS2N |
-               ATIM_CR2_OIS3 | ATIM_CR2_OIS3N | ATIM_CR2_OIS4);
+      pwm_soft_update(dev);
 
-      /* Set the main output enable (MOE) bit and clear the OSSI and OSSR
-       * bits in the BDTR register.
+      /* Now set the value of the RCR that will be loaded on the next
+       * update event.
        */
 
-      bdtr  = stm32l4pwm_getreg(priv, STM32L4_ATIM_BDTR_OFFSET);
-      bdtr &= ~(ATIM_BDTR_OSSI | ATIM_BDTR_OSSR);
-      bdtr |= ATIM_BDTR_MOE;
-      stm32l4pwm_putreg(priv, STM32L4_ATIM_BDTR_OFFSET, bdtr);
+      priv->count = info->count;
+      priv->curr  = stm32l4pwm_pulsecount(info->count - priv->prev);
+      pwm_putreg(priv, STM32L4_ATIM_RCR_OFFSET, (uint16_t)priv->curr - 1);
     }
-  else
-#if defined(CONFIG_STM32L4_TIM15_PWM) || defined(CONFIG_STM32L4_TIM16_PWM) || \
-    defined(CONFIG_STM32L4_TIM17_PWM)
-  if (priv->timtype == TIMTYPE_COUNTUP16)
-    {
-      /* Reset output N polarity level, output N state, output compare state,
-       * output compare N idle state.
-       */
 
-      ccer &= ~(ATIM_CCER_CC1NE | ATIM_CCER_CC1NP);
-      ccer |= ccnenable;
-    }
+  /* Otherwise, just clear the repetition counter */
+
   else
-#endif
-#endif
     {
-      ccer &= ~(GTIM_CCER_CC1NP | GTIM_CCER_CC2NP | GTIM_CCER_CC3NP); /* Not sure why? */
+      /* Set the repetition counter to zero */
+
+      pwm_putreg(priv, STM32L4_ATIM_RCR_OFFSET, 0);
+
+      /* Generate an update event to reload the prescaler */
+
+      pwm_soft_update(dev);
     }
 
-  /* Save the modified register values */
+  /* Get configured outputs */
 
-  stm32l4pwm_putreg(priv, STM32L4_GTIM_CR2_OFFSET, cr2);
-  putreg32(ccmr1, priv->base + STM32L4_GTIM_CCMR1_OFFSET);
-  putreg32(ccmr2, priv->base + STM32L4_GTIM_CCMR2_OFFSET);
-  stm32l4pwm_putreg(priv, STM32L4_GTIM_CCER_OFFSET, ccer);
+  outputs = pwm_outputs_from_channels(priv);
 
-  /* Set the ARR Preload Bit */
+  /* Enable output */
 
-  cr1 = stm32l4pwm_getreg(priv, STM32L4_GTIM_CR1_OFFSET);
-  cr1 |= GTIM_CR1_ARPE;
-  stm32l4pwm_putreg(priv, STM32L4_GTIM_CR1_OFFSET, cr1);
+  ret = pwm_outputs_enable(dev, outputs, true);
+  if (ret < 0)
+    {
+      goto errout;
+    }
 
   /* Setup update interrupt.  If info->count is > 0, then we can be
-   * assured that stm32l4pwm_start() has already verified: (1) that this is an
-   * advanced timer, and that (2) the repetition count is within range.
+   * assured that pwm_pulsecount_start() has already verified: (1) that this
+   * is an advanced timer, and that (2) the repetition count is within range.
    */
 
-#ifdef CONFIG_PWM_PULSECOUNT
   if (info->count > 0)
     {
       /* Clear all pending interrupts and enable the update interrupt. */
 
-      stm32l4pwm_putreg(priv, STM32L4_GTIM_SR_OFFSET, 0);
-      stm32l4pwm_putreg(priv, STM32L4_GTIM_DIER_OFFSET, ATIM_DIER_UIE);
+      pwm_putreg(priv, STM32L4_GTIM_SR_OFFSET, 0);
+      pwm_putreg(priv, STM32L4_GTIM_DIER_OFFSET, ATIM_DIER_UIE);
 
       /* Enable the timer */
 
-      cr1 |= GTIM_CR1_CEN;
-      stm32l4pwm_putreg(priv, STM32L4_GTIM_CR1_OFFSET, cr1);
+      pwm_timer_enable(dev, true);
 
       /* And enable timer interrupts at the NVIC */
 
       up_enable_irq(priv->irq);
     }
-  else
-#endif
-    {
-      /* Just enable the timer, leaving all interrupts disabled */
 
-      cr1 |= GTIM_CR1_CEN;
-      stm32l4pwm_putreg(priv, STM32L4_GTIM_CR1_OFFSET, cr1);
-    }
+  pwm_dumpregs(dev, "After starting");
 
-  stm32l4pwm_dumpregs(priv, "After starting");
-  return OK;
+errout:
+  return ret;
 }
 
+#else  /* !CONFIG_PWM_PULSECOUNT */
+
 /****************************************************************************
- * Name: stm32l4pwm_lptimer
+ * Name: pwm_duty_channels_update
  *
  * Description:
- *   (Re-)initialize the low-power timer resources and start the
- *   pulsed output
- *
- * Input Parameters:
- *   priv - 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
+ *   Update duty cycle for given channels
  *
  ****************************************************************************/
 
-static int stm32l4pwm_lptimer(FAR struct stm32l4_pwmtimer_s *priv,
-                              FAR const struct pwm_info_s *info)
+static int pwm_duty_channels_update(FAR struct pwm_lowerhalf_s *dev,
+                                    FAR const struct pwm_info_s *info)
 {
-  /* Calculated values */
+  FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev;
+  uint8_t   channel = 0;
+  ub16_t    duty    = 0;
+  int       ret     = OK;
+#ifdef CONFIG_STM32L4_PWM_MULTICHAN
+  int       i       = 0;
+  int       j       = 0;
+#endif
 
-  uint8_t prescaler;
-  uint32_t timclk;
-  uint32_t reload;
-  uint32_t ccr;
+#ifdef CONFIG_STM32L4_PWM_MULTICHAN
+  for (i = 0; i < CONFIG_PWM_NCHANNELS; i++)
+#endif
+    {
+#ifdef CONFIG_STM32L4_PWM_MULTICHAN
+      duty    = info->channels[i].duty;
+      channel = info->channels[i].channel;
 
-  /* Register contents */
+      /* A value of zero means to skip this channel */
 
-  uint16_t cr;
-  uint32_t cfgr;
+      if (channel != 0)
+        {
+          /* Find the channel */
 
-  DEBUGASSERT(priv != NULL && info != NULL);
+          for (j = 0; j < priv->chan_num; j++)
+            {
+              if (priv->channels[j].channel == channel)
+                {
+                  break;
+                }
+            }
 
-  pwminfo("LPTIM%u frequency: %u duty: %08x\n",
-#ifdef CONFIG_PWM_MULTICHAN
-          priv->timid, info->frequency, info->channels[0].duty);
+          /* Check range */
+
+          if (j >= priv->chan_num)
+            {
+              pwmerr("ERROR: No such channel: %u\n", channel);
+              ret = -EINVAL;
+              goto errout;
+            }
 #else
-          priv->timid, info->frequency, info->duty);
+          duty = info->duty;
+          channel = priv->channels[0].channel;
 #endif
 
-  DEBUGASSERT(info->frequency > 0);
-  DEBUGASSERT(info->duty >= 0 && info->duty < uitoub16(100));
-
-  /* LPTIM only has 8 possible prescaler values, from /1 to /128
-   * We will attempt to find the lowest prescaler that results
-   * in a maximum reload value which can be represented in 16 bit.
-   * For certain desired frequencies it is possible that the clock
-   * is too high and other one needs to be selected.
-   */
-
-  for (prescaler = 0; prescaler < 8; prescaler++)
-    {
-      timclk = priv->pclk / (1 << prescaler);
-      reload = timclk / info->frequency;
-
-      if (reload <= 65535)
-        {
-          /* The reload counter is feasible, go with it */
+          /* Update duty cycle */
 
-          break;
+          ret = pwm_duty_update(dev, channel, duty);
+          if (ret < 0)
+            {
+              goto errout;
+            }
+#ifdef CONFIG_STM32L4_PWM_MULTICHAN
         }
+#endif
     }
 
-  if (reload < 2)
-    {
-      reload = 1;
-    }
-  else if (reload > 65535)
-    {
-      reload = 65535;
-    }
-
-  /* TODO: if the desired frequency is not possible this should give an error and
-   * not simply return the feasible frequency without complaining.
-   */
-
-  pwminfo("LPTIM%u PCLK: %u frequency: %u TIMCLK: %u prescaler: %u reload: %u\n",
-          priv->timid, priv->pclk, info->frequency, timclk, prescaler, reload);
-
-  /* Disable the timer to set the prescaler */
-
-  cr = stm32l4pwm_getreg(priv, STM32L4_LPTIM_CR_OFFSET);
+errout:
+  return OK;
+}
 
-  cr &= ~LPTIM_CR_ENABLE;
-  stm32l4pwm_putreg(priv, STM32L4_LPTIM_CR_OFFSET, cr);
+/****************************************************************************
+ * Name: pwm_timer
+ *
+ * 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
+ *
+ ****************************************************************************/
 
-  /* We have to way two counter clocks before the clock is actually enabled */
+static int pwm_timer(FAR struct pwm_lowerhalf_s *dev,
+                     FAR const struct pwm_info_s *info)
+{
+  FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev;
+  uint16_t outputs = 0;
+  int      ret     = OK;
 
-  up_udelay(2 * USEC_PER_SEC / timclk);
+  DEBUGASSERT(priv != NULL && info != NULL);
 
-  /* Set the prescaler value and choose high polarity */
+#if defined(CONFIG_STM32L4_PWM_MULTICHAN)
+  pwminfo("TIM%u frequency: %u\n",
+          priv->timid, info->frequency);
+#else
+  pwminfo("TIM%u channel: %u frequency: %u duty: %08x\n",
+          priv->timid, priv->channels[0].channel,
+          info->frequency, info->duty);
+#endif
 
-  cfgr = getreg32(priv->base + STM32L4_LPTIM_CFGR_OFFSET);
+  DEBUGASSERT(info->frequency > 0);
+#ifndef CONFIG_STM32L4_PWM_MULTICHAN
+  DEBUGASSERT(info->duty >= 0 && info->duty < uitoub16(100));
+#endif
 
-  cfgr &= ~LPTIM_CFGR_PRESC_MASK;
-  cfgr |= (prescaler << LPTIM_CFGR_PRESC_SHIFT) | LPTIM_CFGR_WAVPOL;
+  /* TODO: what if we have pwm running and we want disable some channels ? */
 
-  putreg32(cfgr, priv->base + STM32L4_LPTIM_CFGR_OFFSET);
+  /* Set timer frequency */
 
-  /* Enable again, ARR and CMP need to be written while enabled */
+  ret = pwm_frequency_update(dev, info->frequency);
+  if (ret < 0)
+    {
+      goto errout;
+    }
 
-  cr |= LPTIM_CR_ENABLE;
-  stm32l4pwm_putreg(priv, STM32L4_LPTIM_CR_OFFSET, cr);
+  /* Channel specific configuration */
 
-  /* Compute reload value */
+  ret = pwm_duty_channels_update(dev, info);
+  if (ret < 0)
+    {
+      goto errout;
+    }
 
-#ifdef CONFIG_PWM_MULTICHAN
-  ub16_t duty = info->channels[0].duty;
-#else
-  ub16_t duty = info->duty;
-#endif
+  /* Set the advanced timer's repetition counter */
 
-  /* Duty cycle:
-   *
-   * duty cycle = ccr / reload (fractional value)
-   */
+#ifdef HAVE_ADVTIM
+  if (priv->timtype == TIMTYPE_ADVANCED ||
+      priv->timtype == TIMTYPE_COUNTUP16_N)
+    {
+      /* If a non-zero repetition count has been selected, then set the
+       * repitition counter to the count-1 (pwm_start() has already
+       * assured us that the count value is within range).
+       */
 
-  ccr = b16toi(duty * reload + b16HALF);
+      /* Set the repetition counter to zero */
 
-  pwminfo("ccr: %u\n", ccr);
+      pwm_putreg(priv, STM32L4_ATIM_RCR_OFFSET, 0);
 
-  /* Set reload register */
+      /* Generate an update event to reload the prescaler */
 
-  stm32l4pwm_putreg(priv, STM32L4_LPTIM_ARR_OFFSET, (uint16_t)reload);
+      pwm_soft_update(dev);
+    }
+  else
+#endif
+    {
+      /* Generate an update event to reload the prescaler (all timers) */
 
-  /* Wait for write to complete */
+      pwm_soft_update(dev);
+    }
 
-  while (!(getreg32(priv->base + STM32L4_LPTIM_ISR_OFFSET) & LPTIM_ISR_ARROK));
+  /* Get configured outputs */
 
-  /* Set compare register */
+  outputs = pwm_outputs_from_channels(priv);
 
-  stm32l4pwm_putreg(priv, STM32L4_LPTIM_CMP_OFFSET, (uint16_t)ccr);
+  /* Enable outputs */
 
-  /* Wait for write to complete */
+  ret = pwm_outputs_enable(dev, outputs, true);
+  if (ret < 0)
+    {
+      goto errout;
+    }
 
-  while (!(getreg32(priv->base + STM32L4_LPTIM_ISR_OFFSET) & LPTIM_ISR_CMPOK));
+  /* Just enable the timer, leaving all interrupts disabled */
 
-  /* Start counter */
+  pwm_timer_enable(dev, true);
 
-  cr = stm32l4pwm_getreg(priv, STM32L4_LPTIM_CR_OFFSET);
-  cr |= LPTIM_CR_CNTSTRT;
-  stm32l4pwm_putreg(priv, STM32L4_LPTIM_CR_OFFSET, cr);
+  pwm_dumpregs(dev, "After starting");
 
-  stm32l4pwm_dumpregs(priv, "After starting");
-  return OK;
+errout:
+  return ret;
 }
 
-#ifndef CONFIG_PWM_PULSECOUNT
 /****************************************************************************
- * Name: stm32l4pwm_update_duty
+ * Name: pwm_lptimer
  *
  * Description:
- *   Try to change only channel duty.
+ *   (Re-)initialize the low-power timer resources and start the
+ *   pulsed output
  *
  * Input Parameters:
- *   priv    - A reference to the lower half PWM driver state structure
- *   channel - Channel to by updated
- *   duty    - New duty.
+ *   priv - 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 stm32l4pwm_update_duty(FAR struct stm32l4_pwmtimer_s *priv,
-                                   uint8_t channel, ub16_t duty)
+#ifdef HAVE_LPTIM
+static int pwm_lptimer(FAR struct pwm_lowerhalf_s *dev,
+                       FAR const struct pwm_info_s *info)
 {
-  /* Register offset */
-
-  int ccr_offset;
+  FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev;
+  uint16_t cr;
+  int      ret     = OK;
 
-  /* Calculated values */
+  DEBUGASSERT(priv != NULL && info != NULL);
 
-  uint32_t reload;
-  uint32_t ccr;
+#if defined(CONFIG_STM32L4_PWM_MULTICHAN)
+  pwminfo("LPTIM%u frequency: %u\n",
+          priv->timid, info->frequency);
+#else
+  pwminfo("LPTIM%u channel: %u frequency: %u duty: %08x\n",
+          priv->timid, priv->channels[0].channel,
+          info->frequency, info->duty);
+#endif
 
-  DEBUGASSERT(priv != NULL);
+  DEBUGASSERT(info->frequency > 0);
+#ifndef CONFIG_STM32L4_PWM_MULTICHAN
+  DEBUGASSERT(info->duty >= 0 && info->duty < uitoub16(100));
+#endif
 
-  pwminfo("%s%u channel: %u duty: %08x\n",
-          priv->timtype == TIMTYPE_LOWPOWER ? "LPTIM" : "TIM",
-          priv->timid, channel, duty);
+  /* Enable again, ARR and CMP need to be written while enabled */
 
-#ifndef CONFIG_PWM_MULTICHAN
-  DEBUGASSERT(channel == priv->channels[0].channel);
-  DEBUGASSERT(duty >= 0 && duty < uitoub16(100));
-#endif
+  pwm_timer_enable(dev, true);
 
-  /* Get the reload values */
+  /* Set timer frequency */
 
-  if (priv->timtype == TIMTYPE_LOWPOWER)
-    {
-      reload = stm32l4pwm_getreg(priv, STM32L4_LPTIM_ARR_OFFSET);
-    }
-  else
+  ret = pwm_lp_frequency_update(dev, info->frequency);
+  if (ret < 0)
     {
-      reload = stm32l4pwm_getreg(priv, STM32L4_GTIM_ARR_OFFSET);
+      goto errout;
     }
 
-  /* Duty cycle:
-   *
-   * duty cycle = ccr / reload (fractional value)
-   */
-
-  ccr = b16toi(duty * reload + b16HALF);
+#ifdef CONFIG_STM32L4_PWM_MULTICHAN
+  ub16_t duty = info->channels[0].duty;
+#else
+  ub16_t duty = info->duty;
+#endif
 
-  pwminfo("ccr: %u\n", ccr);
+  /* Update duty cycle */
 
-  if (priv->timtype == TIMTYPE_LOWPOWER)
+  ret = pwm_duty_update(dev, priv->channels[0].channel, duty);
+  if (ret < 0)
     {
-      /* Low-power timers only have a compare register */
-
-      ccr_offset = STM32L4_LPTIM_CMP_OFFSET;
+      goto errout;
     }
-  else
-    {
-      switch (channel)
-        {
-          case 1:  /* Register offset for Channel 1 */
-            ccr_offset = STM32L4_GTIM_CCR1_OFFSET;
-            break;
-
-          case 2:  /* Register offset for Channel 2 */
-            ccr_offset = STM32L4_GTIM_CCR2_OFFSET;
-            break;
 
-          case 3:  /* Register offset for Channel 3 */
-            ccr_offset = STM32L4_GTIM_CCR3_OFFSET;
-            break;
+  /* Start counter */
 
-          case 4:  /* Register offset for Channel 4 */
-            ccr_offset = STM32L4_GTIM_CCR4_OFFSET;
-            break;
+  cr = pwm_getreg(priv, STM32L4_LPTIM_CR_OFFSET);
+  cr |= LPTIM_CR_CNTSTRT;
+  pwm_putreg(priv, STM32L4_LPTIM_CR_OFFSET, cr);
 
-          default:
-            pwmerr("ERROR: No such channel: %u\n", channel);
-            return -EINVAL;
-        }
-    }
+  pwm_dumpregs(dev, "After starting");
 
-  /* Set the duty cycle by writing to the CCR register for this channel */
+errout:
+  return ret;
+}
+#endif /* HAVE_LPTIM */
 
-  stm32l4pwm_putreg(priv, ccr_offset, (uint16_t)ccr);
+#endif  /* CONFIG_PWM_PULSECOUNT */
 
-  return OK;
-}
-#endif
+#ifdef HAVE_PWM_INTERRUPT
 
 /****************************************************************************
- * Name: stm32l4pwm_interrupt
+ * Name: pwm_interrupt
  *
  * Description:
  *   Handle timer interrupts.
  *
  * Input Parameters:
- *   priv - A reference to the lower half PWM driver state structure
+ *   dev - A reference to the lower half PWM driver state structure
  *
  * Returned Value:
  *   Zero on success; a negated errno value on failure
  *
  ****************************************************************************/
 
-#if defined(CONFIG_PWM_PULSECOUNT) && (defined(CONFIG_STM32L4_TIM1_PWM) || defined(CONFIG_STM32L4_TIM8_PWM))
-static int stm32l4pwm_interrupt(struct stm32l4_pwmtimer_s *priv)
+static int pwm_interrupt(FAR struct pwm_lowerhalf_s *dev)
 {
+  FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev;
   uint16_t regval;
 
   /* Verify that this is an update interrupt.  Nothing else is expected. */
 
-  regval = stm32l4pwm_getreg(priv, STM32L4_ATIM_SR_OFFSET);
+  regval = pwm_getreg(priv, STM32L4_ATIM_SR_OFFSET);
   DEBUGASSERT((regval & ATIM_SR_UIF) != 0);
 
   /* Clear the UIF interrupt bit */
 
-  stm32l4pwm_putreg(priv, STM32L4_ATIM_SR_OFFSET, regval & ~ATIM_SR_UIF);
+  pwm_putreg(priv, STM32L4_ATIM_SR_OFFSET, regval & ~ATIM_SR_UIF);
 
   /* Calculate the new count by subtracting the number of pulses
    * since the last interrupt.
@@ -1729,13 +3370,13 @@ static int stm32l4pwm_interrupt(struct stm32l4_pwmtimer_s *priv)
        * quickly as possible.
        */
 
-      regval  = stm32l4pwm_getreg(priv, STM32L4_ATIM_BDTR_OFFSET);
+      regval  = pwm_getreg(priv, STM32L4_ATIM_BDTR_OFFSET);
       regval &= ~ATIM_BDTR_MOE;
-      stm32l4pwm_putreg(priv, STM32L4_ATIM_BDTR_OFFSET, regval);
+      pwm_putreg(priv, STM32L4_ATIM_BDTR_OFFSET, regval);
 
       /* Disable first interrtups, stop and reset the timer */
 
-      stm32l4pwm_stop((FAR struct pwm_lowerhalf_s *)priv);
+      pwm_stop(dev);
 
       /* Then perform the callback into the upper half driver */
 
@@ -1762,17 +3403,18 @@ static int stm32l4pwm_interrupt(struct stm32l4_pwmtimer_s *priv)
 
       priv->prev = priv->curr;
       priv->curr = stm32l4pwm_pulsecount(priv->count - priv->prev);
-      stm32l4pwm_putreg(priv, STM32L4_ATIM_RCR_OFFSET, (uint16_t)priv->curr - 1);
+      pwm_putreg(priv, STM32L4_ATIM_RCR_OFFSET, (uint16_t)priv->curr - 1);
     }
 
-  /* Now all of the time critical stuff is done so we can do some debug output */
+  /* Now all of the time critical stuff is done so we can do some debug
+   * output
+   */
 
   pwminfo("Update interrupt SR: %04x prev: %u curr: %u count: %u\n",
           regval, priv->prev, priv->curr, priv->count);
 
   return OK;
 }
-#endif
 
 /****************************************************************************
  * Name: pwm_tim1/8interrupt
@@ -1788,19 +3430,19 @@ static int stm32l4pwm_interrupt(struct stm32l4_pwmtimer_s *priv)
  *
  ****************************************************************************/
 
-#if defined(CONFIG_PWM_PULSECOUNT) && defined(CONFIG_STM32L4_TIM1_PWM)
-static int stm32l4pwm_tim1interrupt(int irq, void *context, FAR void *arg)
+#ifdef CONFIG_STM32L4_TIM1_PWM
+static int pwm_tim1interrupt(int irq, void *context, FAR void *arg)
 {
-  return stm32l4pwm_interrupt(&g_pwm1dev);
+  return pwm_interrupt((FAR struct pwm_lowerhalf_s *)&g_pwm1dev);
 }
-#endif
+#endif /* CONFIG_STM32L4_TIM1_PWM */
 
-#if defined(CONFIG_PWM_PULSECOUNT) && defined(CONFIG_STM32L4_TIM8_PWM)
-static int stm32l4pwm_tim8interrupt(int irq, void *context, FAR void *arg)
+#ifdef CONFIG_STM32L4_TIM8_PWM
+static int pwm_tim8interrupt(int irq, void *context, FAR void *arg)
 {
-  return stm32l4pwm_interrupt(&g_pwm8dev);
+  return pwm_interrupt((FAR struct pwm_lowerhalf_s *)&g_pwm8dev);
 }
-#endif
+#endif /* CONFIG_STM32L4_TIM8_PWM */
 
 /****************************************************************************
  * Name: stm32l4pwm_pulsecount
@@ -1816,7 +3458,6 @@ static int stm32l4pwm_tim8interrupt(int irq, void *context, FAR void *arg)
  *
  ****************************************************************************/
 
-#if defined(CONFIG_PWM_PULSECOUNT) && (defined(CONFIG_STM32L4_TIM1_PWM) || defined(CONFIG_STM32L4_TIM8_PWM))
 static uint8_t stm32l4pwm_pulsecount(uint32_t count)
 {
   /* The the remaining pulse count is less than or equal to the maximum, the
@@ -1825,7 +3466,7 @@ static uint8_t stm32l4pwm_pulsecount(uint32_t count)
 
   if (count <= ATIM_RCR_REP_MAX)
     {
-      return count;
+      return (uint8_t)count;
     }
 
   /* Otherwise, we have to be careful.  We do not want a small number of
@@ -1837,17 +3478,17 @@ static uint8_t stm32l4pwm_pulsecount(uint32_t count)
 
   else if (count < (3 * ATIM_RCR_REP_MAX / 2))
     {
-      return (ATIM_RCR_REP_MAX + 1) >> 1;
+      return (uint8_t)((ATIM_RCR_REP_MAX + 1) >> 1);
     }
 
   /* Otherwise, return the maximum.  The final count will be 64 or more */
 
   else
     {
-      return ATIM_RCR_REP_MAX;
+      return (uint8_t)ATIM_RCR_REP_MAX;
     }
 }
-#endif
+#endif /* HAVE_PWM_INTERRUPT */
 
 /****************************************************************************
  * Name: stm32l4pwm_setapbclock
@@ -1861,10 +3502,12 @@ static uint8_t stm32l4pwm_pulsecount(uint32_t count)
  *
  ****************************************************************************/
 
-static void stm32l4pwm_setapbclock(FAR struct stm32l4_pwmtimer_s *priv, bool on)
+static int stm32l4pwm_setapbclock(FAR struct stm32l4_pwmtimer_s *priv,
+                                  bool on)
 {
   uint32_t en_bit;
   uint32_t regaddr;
+  int      ret     = OK;
 
   /* Determine which timer to configure */
 
@@ -1874,60 +3517,91 @@ static void stm32l4pwm_setapbclock(FAR struct stm32l4_pwmtimer_s *priv, bool on)
         {
 #ifdef CONFIG_STM32L4_TIM1_PWM
           case 1:
-            regaddr  = STM32L4_RCC_APB2ENR;
-            en_bit   = RCC_APB2ENR_TIM1EN;
-            break;
+            {
+              regaddr  = STM32L4_RCC_APB2ENR;
+              en_bit   = RCC_APB2ENR_TIM1EN;
+              break;
+            }
 #endif
+
 #ifdef CONFIG_STM32L4_TIM2_PWM
           case 2:
-            regaddr  = STM32L4_RCC_APB1ENR1;
-            en_bit   = RCC_APB1ENR1_TIM2EN;
-            break;
+            {
+              regaddr  = STM32L4_RCC_APB1ENR1;
+              en_bit   = RCC_APB1ENR1_TIM2EN;
+              break;
+            }
 #endif
+
 #ifdef CONFIG_STM32L4_TIM3_PWM
           case 3:
-            regaddr  = STM32L4_RCC_APB1ENR1;
-            en_bit   = RCC_APB1ENR1_TIM3EN;
-            break;
+            {
+              regaddr  = STM32L4_RCC_APB1ENR1;
+              en_bit   = RCC_APB1ENR1_TIM3EN;
+              break;
+            }
 #endif
+
 #ifdef CONFIG_STM32L4_TIM4_PWM
           case 4:
-            regaddr  = STM32L4_RCC_APB1ENR1;
-            en_bit   = RCC_APB1ENR1_TIM4EN;
-            break;
+            {
+              regaddr  = STM32L4_RCC_APB1ENR1;
+              en_bit   = RCC_APB1ENR1_TIM4EN;
+              break;
+            }
 #endif
+
 #ifdef CONFIG_STM32L4_TIM5_PWM
           case 5:
-            regaddr  = STM32L4_RCC_APB1ENR1;
-            en_bit   = RCC_APB1ENR1_TIM5EN;
-            break;
+            {
+              regaddr  = STM32L4_RCC_APB1ENR1;
+              en_bit   = RCC_APB1ENR1_TIM5EN;
+              break;
+            }
 #endif
+
 #ifdef CONFIG_STM32L4_TIM8_PWM
           case 8:
-            regaddr  = STM32L4_RCC_APB2ENR;
-            en_bit   = RCC_APB2ENR_TIM8EN;
-            break;
+            {
+              regaddr  = STM32L4_RCC_APB2ENR;
+              en_bit   = RCC_APB2ENR_TIM8EN;
+              break;
+            }
 #endif
+
 #ifdef CONFIG_STM32L4_TIM15_PWM
           case 15:
-            regaddr  = STM32L4_RCC_APB2ENR;
-            en_bit   = RCC_APB2ENR_TIM15EN;
-            break;
+            {
+              regaddr  = STM32L4_RCC_APB2ENR;
+              en_bit   = RCC_APB2ENR_TIM15EN;
+              break;
+            }
 #endif
+
 #ifdef CONFIG_STM32L4_TIM16_PWM
           case 16:
-            regaddr  = STM32L4_RCC_APB2ENR;
-            en_bit   = RCC_APB2ENR_TIM16EN;
-            break;
+            {
+              regaddr  = STM32L4_RCC_APB2ENR;
+              en_bit   = RCC_APB2ENR_TIM16EN;
+              break;
+            }
 #endif
+
 #ifdef CONFIG_STM32L4_TIM17_PWM
           case 17:
-            regaddr  = STM32L4_RCC_APB2ENR;
-            en_bit   = RCC_APB2ENR_TIM17EN;
-            break;
+            {
+              regaddr  = STM32L4_RCC_APB2ENR;
+              en_bit   = RCC_APB2ENR_TIM17EN;
+              break;
+          }
 #endif
+
           default:
-            return;
+          {
+            pwmerr("ERROR: No such timer configured %d\n", priv->timid);
+            ret = -EINVAL;
+            goto errout;
+          }
         }
 
       /* Enable/disable APB 1/2 clock for timer */
@@ -1941,6 +3615,7 @@ static void stm32l4pwm_setapbclock(FAR struct stm32l4_pwmtimer_s *priv, bool on)
           modifyreg32(regaddr, en_bit, 0);
         }
     }
+#ifdef HAVE_LPTIM
   else
     {
       uint32_t clock_bits;
@@ -1949,67 +3624,86 @@ static void stm32l4pwm_setapbclock(FAR struct stm32l4_pwmtimer_s *priv, bool on)
         {
 #ifdef CONFIG_STM32L4_LPTIM1_PWM
           case 1:
+            {
 #if defined(CONFIG_STM32L4_LPTIM1_CLK_APB1)
-            /* Enable APB clock for LPTIM1 */
-
-            if (on)
-              {
-                modifyreg32(STM32L4_RCC_APB1ENR1, 0, RCC_APB1ENR1_LPTIM1EN);
-              }
-            else
-              {
-                modifyreg32(STM32L4_RCC_APB1ENR1, RCC_APB1ENR1_LPTIM1EN, 0);
-              }
-
-            clock_bits = RCC_CCIPR_LPTIM1SEL_PCLK;
+              /* Enable APB clock for LPTIM1 */
+
+              if (on)
+                {
+                  modifyreg32(STM32L4_RCC_APB1ENR1,
+                              0, RCC_APB1ENR1_LPTIM1EN);
+                }
+              else
+                {
+                  modifyreg32(STM32L4_RCC_APB1ENR1,
+                              RCC_APB1ENR1_LPTIM1EN, 0);
+                }
+
+              clock_bits = RCC_CCIPR_LPTIM1SEL_PCLK;
 #elif defined(CONFIG_STM32L4_LPTIM1_CLK_LSI)
-            clock_bits = RCC_CCIPR_LPTIM1SEL_LSI;
+              clock_bits = RCC_CCIPR_LPTIM1SEL_LSI;
 #elif defined(CONFIG_STM32L4_LPTIM1_CLK_LSE)
-            clock_bits = RCC_CCIPR_LPTIM1SEL_LSE;
+              clock_bits = RCC_CCIPR_LPTIM1SEL_LSE;
 #elif defined(CONFIG_STM32L4_LPTIM1_CLK_HSI)
-            clock_bits = RCC_CCIPR_LPTIM1SEL_HSI;
+              clock_bits = RCC_CCIPR_LPTIM1SEL_HSI;
 #endif
-            /* Choose which clock will be used for LPTIM1 */
+              /* Choose which clock will be used for LPTIM1 */
 
-            modifyreg32(STM32L4_RCC_CCIPR, RCC_CCIPR_LPTIM1SEL_MASK, clock_bits);
-            break;
+              modifyreg32(STM32L4_RCC_CCIPR, RCC_CCIPR_LPTIM1SEL_MASK,
+                          clock_bits);
+              break;
+            }
 #endif
 
 #ifdef CONFIG_STM32L4_LPTIM2_PWM
           case 2:
+            {
 #if defined(CONFIG_STM32L4_LPTIM2_CLK_APB1)
-            /* Enable APB clock for LPTIM2 */
-
-            if (on)
-              {
-                modifyreg32(STM32L4_RCC_APB1ENR2, 0, RCC_APB1ENR2_LPTIM2EN);
-              }
-            else
-              {
-                modifyreg32(STM32L4_RCC_APB1ENR2, RCC_APB1ENR2_LPTIM2EN, 0);
-              }
-
-            clock_bits = RCC_CCIPR_LPTIM2SEL_PCLK;
+              /* Enable APB clock for LPTIM2 */
+
+              if (on)
+                {
+                  modifyreg32(STM32L4_RCC_APB1ENR2,
+                              0, RCC_APB1ENR2_LPTIM2EN);
+                }
+              else
+                {
+                  modifyreg32(STM32L4_RCC_APB1ENR2,
+                              RCC_APB1ENR2_LPTIM2EN, 0);
+                }
+
+              clock_bits = RCC_CCIPR_LPTIM2SEL_PCLK;
 #elif defined(CONFIG_STM32L4_LPTIM2_CLK_LSI)
-            clock_bits = RCC_CCIPR_LPTIM2SEL_LSI;
+              clock_bits = RCC_CCIPR_LPTIM2SEL_LSI;
 #elif defined(CONFIG_STM32L4_LPTIM2_CLK_LSE)
-            clock_bits = RCC_CCIPR_LPTIM2SEL_LSE;
+              clock_bits = RCC_CCIPR_LPTIM2SEL_LSE;
 #elif defined(CONFIG_STM32L4_LPTIM2_CLK_HSI)
-            clock_bits = RCC_CCIPR_LPTIM2SEL_HSI;
+              clock_bits = RCC_CCIPR_LPTIM2SEL_HSI;
 #endif
-            /* Choose which clock will be used for LPTIM2 */
+              /* Choose which clock will be used for LPTIM2 */
+
+              modifyreg32(STM32L4_RCC_CCIPR, RCC_CCIPR_LPTIM2SEL_MASK,
+                          clock_bits);
+              break;
+            }
 
-            modifyreg32(STM32L4_RCC_CCIPR, RCC_CCIPR_LPTIM2SEL_MASK, clock_bits);
-            break;
 #endif
           default:
-            return;
+            {
+              pwmerr("ERROR: No such timer configured %d\n", priv->timid);
+              ret = -EINVAL;
+              goto errout;
+            }
         }
     }
+
+#endif /* HAVE_LPTIM */
+errout:
+  return ret;
 }
 
 /****************************************************************************
- * Name: stm32l4pwm_setup
+ * Name: pwm_setup
  *
  * Description:
  *   This method is called when the driver is opened.  The lower half driver
@@ -2028,10 +3722,11 @@ static void stm32l4pwm_setapbclock(FAR struct stm32l4_pwmtimer_s *priv, bool on)
  *
  ****************************************************************************/
 
-static int stm32l4pwm_setup(FAR struct pwm_lowerhalf_s *dev)
+static int pwm_setup(FAR struct pwm_lowerhalf_s *dev)
 {
   FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev;
   uint32_t pincfg;
+  int ret;
   int i;
 
   if (priv->timtype == TIMTYPE_LOWPOWER)
@@ -2043,42 +3738,55 @@ static int stm32l4pwm_setup(FAR struct pwm_lowerhalf_s *dev)
       pwminfo("TIM%u\n", priv->timid);
     }
 
-  stm32l4pwm_dumpregs(priv, "Initially");
-
   /* Enable APB1/2 clocking for timer. */
 
   stm32l4pwm_setapbclock(priv, true);
 
+  pwm_dumpregs(dev, "Initially");
+
   /* Configure the PWM output pins, but do not start the timer yet */
 
-  for (i = 0; i < PWM_NCHANNELS; i++)
+  for (i = 0; i < priv->chan_num; i++)
     {
-      pincfg = priv->channels[i].pincfg;
-      if (pincfg != 0)
+      if (priv->channels[i].out1.in_use == 1)
         {
+          pincfg = priv->channels[i].out1.pincfg;
           pwminfo("pincfg: %08x\n", pincfg);
 
           stm32l4_configgpio(pincfg);
+          pwm_dumpgpio(pincfg, "PWM setup");
         }
 
-      /* Enable complementary channel if available */
-
-      pincfg = priv->channels[i].npincfg;
-      if (pincfg != 0)
+#ifdef HAVE_PWM_COMPLEMENTARY
+      if (priv->channels[i].out2.in_use == 1)
         {
-          pwminfo("npincfg: %08x\n", pincfg);
+          pincfg = priv->channels[i].out2.pincfg;
+          pwminfo("pincfg: %08x\n", pincfg);
 
           stm32l4_configgpio(pincfg);
+          pwm_dumpgpio(pincfg, "PWM setup");
         }
+#endif
+    }
+
+  /* Configure PWM timer with the selected configuration.
+   *
+   * NOTE: We configure PWM here during setup, but leave timer with disabled
+   *       counter, disabled outputs, not configured frequency and duty cycle
+   */
 
-      pwm_dumpgpio(pincfg, "PWM setup");
+  ret = pwm_configure(dev);
+  if (ret < 0)
+    {
+      pwmerr("failed to configure PWM %d\n", priv->timid);
+      return ERROR;
     }
 
   return OK;
 }
 
 /****************************************************************************
- * Name: stm32l4pwm_shutdown
+ * Name: pwm_shutdown
  *
  * Description:
  *   This method is called when the driver is closed.  The lower half driver
@@ -2093,27 +3801,39 @@ static int stm32l4pwm_setup(FAR struct pwm_lowerhalf_s *dev)
  *
  ****************************************************************************/
 
-static int stm32l4pwm_shutdown(FAR struct pwm_lowerhalf_s *dev)
+static int pwm_shutdown(FAR struct pwm_lowerhalf_s *dev)
 {
   FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev;
-  uint32_t pincfg;
-  int i;
+  uint32_t pincfg = 0;
+  int      i      = 0;
+  int      ret    = OK;
 
-  pwminfo("TIM%u\n", priv->timid);
+  if (priv->timtype == TIMTYPE_LOWPOWER)
+    {
+      pwminfo("LPTIM%u\n", priv->timid);
+    }
+  else
+    {
+      pwminfo("TIM%u\n", priv->timid);
+    }
 
   /* Make sure that the output has been stopped */
 
-  stm32l4pwm_stop(dev);
+  pwm_stop(dev);
 
   /* Disable APB1/2 clocking for timer. */
 
-  stm32l4pwm_setapbclock(priv, false);
+  ret = stm32l4pwm_setapbclock(priv, false);
+  if (ret < 0)
+    {
+      goto errout;
+    }
 
   /* Then put the GPIO pins back to the default state */
 
-  for (i = 0; i < PWM_NCHANNELS; i++)
+  for (i = 0; i < priv->chan_num; i++)
     {
-      pincfg = priv->channels[i].pincfg;
+      pincfg = priv->channels[i].out1.pincfg;
       if (pincfg != 0)
         {
           pwminfo("pincfg: %08x\n", pincfg);
@@ -2124,23 +3844,26 @@ static int stm32l4pwm_shutdown(FAR struct pwm_lowerhalf_s *dev)
           stm32l4_configgpio(pincfg);
         }
 
-      pincfg = priv->channels[i].npincfg;
+#ifdef HAVE_PWM_COMPLEMENTARY
+      pincfg = priv->channels[i].out2.pincfg;
       if (pincfg != 0)
         {
-          pwminfo("npincfg: %08x\n", pincfg);
+          pwminfo("pincfg: %08x\n", pincfg);
 
           pincfg &= (GPIO_PORT_MASK | GPIO_PIN_MASK);
           pincfg |= GPIO_INPUT | GPIO_FLOAT;
 
           stm32l4_configgpio(pincfg);
         }
+#endif
     }
 
-  return OK;
+errout:
+  return ret;
 }
 
 /****************************************************************************
- * Name: stm32l4pwm_start
+ * Name: pwm_start
  *
  * Description:
  *   (Re-)initialize the timer resources and start the pulsed output
@@ -2155,7 +3878,7 @@ static int stm32l4pwm_shutdown(FAR struct pwm_lowerhalf_s *dev)
  ****************************************************************************/
 
 #ifdef CONFIG_PWM_PULSECOUNT
-static int stm32l4pwm_start(FAR struct pwm_lowerhalf_s *dev,
+static int pwm_start(FAR struct pwm_lowerhalf_s *dev,
                      FAR const struct pwm_info_s *info,
                      FAR void *handle)
 {
@@ -2181,17 +3904,11 @@ static int stm32l4pwm_start(FAR struct pwm_lowerhalf_s *dev,
 
   /* Start the time */
 
-  if (priv->timtype == TIMTYPE_LOWPOWER)
-    {
-      return stm32l4pwm_lptimer(priv, info);
-    }
-  else
-    {
-      return stm32l4pwm_timer(priv, info);
-    }
+  return pwm_pulsecount_timer(dev, info);
 }
-#else
-static int stm32l4pwm_start(FAR struct pwm_lowerhalf_s *dev,
+#else /* !CONFIG_PWM_PULSECOUNT */
+
+static int pwm_start(FAR struct pwm_lowerhalf_s *dev,
                      FAR const struct pwm_info_s *info)
 {
   int ret = OK;
@@ -2201,7 +3918,7 @@ static int stm32l4pwm_start(FAR struct pwm_lowerhalf_s *dev,
 
   if (info->frequency == priv->frequency)
     {
-#ifdef CONFIG_PWM_MULTICHAN
+#ifdef CONFIG_STM32L4_PWM_MULTICHAN
       int i;
 
       for (i = 0; ret == OK && i < CONFIG_PWM_NCHANNELS; i++)
@@ -2210,25 +3927,26 @@ static int stm32l4pwm_start(FAR struct pwm_lowerhalf_s *dev,
 
           if (info->channels[i].channel != 0)
             {
-              ret = stm32l4pwm_update_duty(priv, info->channels[i].channel,
-                                           info->channels[i].duty);
+              ret = pwm_duty_update(dev, info->channels[i].channel,
+                                    info->channels[i].duty);
             }
         }
-
 #else
-      ret = stm32l4pwm_update_duty(priv, priv->channels[0].channel, info->duty);
-#endif
+      ret = pwm_duty_update(dev, priv->channels[0].channel, info->duty);
+#endif /* CONFIG_STM32L4_PWM_MULTICHAN */
     }
   else
     {
-      if (priv->timtype == TIMTYPE_LOWPOWER)
+      if (priv->timtype != TIMTYPE_LOWPOWER)
         {
-          ret = stm32l4pwm_lptimer(priv, info);
+          ret = pwm_timer(dev, info);
         }
+#ifdef HAVE_LPTIM
       else
         {
-          ret = stm32l4pwm_timer(priv, info);
+          ret = pwm_lptimer(dev, info);
         }
+#endif
 
       /* Save current frequency */
 
@@ -2240,10 +3958,10 @@ static int stm32l4pwm_start(FAR struct pwm_lowerhalf_s *dev,
 
   return ret;
 }
-#endif
+#endif /* CONFIG_PWM_PULSECOUNT */
 
 /****************************************************************************
- * Name: stm32l4pwm_stop
+ * Name: pwm_stop
  *
  * Description:
  *   Stop the pulsed output and reset the timer resources
@@ -2261,7 +3979,7 @@ static int stm32l4pwm_start(FAR struct pwm_lowerhalf_s *dev,
  *
  ****************************************************************************/
 
-static int stm32l4pwm_stop(FAR struct pwm_lowerhalf_s *dev)
+static int pwm_stop(FAR struct pwm_lowerhalf_s *dev)
 {
   FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev;
   uint32_t resetbit = 0;
@@ -2278,21 +3996,6 @@ static int stm32l4pwm_stop(FAR struct pwm_lowerhalf_s *dev)
       pwminfo("TIM%u\n", priv->timid);
     }
 
-  /* Disable interrupts momentary to stop any ongoing timer processing and
-   * to prevent any concurrent access to the reset register.
-   */
-
-  flags = enter_critical_section();
-
-  /* Stopped so frequency is zero */
-
-  priv->frequency = 0;
-
-  /* Disable further interrupts and stop the timer */
-
-  stm32l4pwm_putreg(priv, STM32L4_GTIM_DIER_OFFSET, 0);
-  stm32l4pwm_putreg(priv, STM32L4_GTIM_SR_OFFSET, 0);
-
   /* Determine which timer to reset */
 
   if (priv->timtype != TIMTYPE_LOWPOWER)
@@ -2367,11 +4070,30 @@ static int stm32l4pwm_stop(FAR struct pwm_lowerhalf_s *dev)
             resetbit = RCC_APB1RSTR2_LPTIM2RST;
             break;
 #endif
+          default:
+            return -EINVAL;
         }
     }
 
+  /* Disable interrupts momentary to stop any ongoing timer processing and
+   * to prevent any concurrent access to the reset register.
+   */
+
+  flags = enter_critical_section();
+
+#ifndef CONFIG_PWM_PULSECOUNT
+  /* Stopped so frequency is zero */
+
+  priv->frequency = 0;
+#endif
+
+  /* Disable further interrupts and stop the timer */
+
+  pwm_putreg(priv, STM32L4_GTIM_DIER_OFFSET, 0);
+  pwm_putreg(priv, STM32L4_GTIM_SR_OFFSET, 0);
+
   /* Reset the timer - stopping the output and putting the timer back
-   * into a state where stm32l4pwm_start() can be called.
+   * into a state where pwm_start() can be called.
    */
 
   regval  = getreg32(regaddr);
@@ -2383,12 +4105,12 @@ static int stm32l4pwm_stop(FAR struct pwm_lowerhalf_s *dev)
   leave_critical_section(flags);
 
   pwminfo("regaddr: %08x resetbit: %08x\n", regaddr, resetbit);
-  stm32l4pwm_dumpregs(priv, "After stop");
+  pwm_dumpregs(dev, "After stop");
   return OK;
 }
 
 /****************************************************************************
- * Name: stm32l4pwm_ioctl
+ * Name: pwm_ioctl
  *
  * Description:
  *   Lower-half logic may support platform-specific ioctl commands
@@ -2403,8 +4125,8 @@ static int stm32l4pwm_stop(FAR struct pwm_lowerhalf_s *dev)
  *
  ****************************************************************************/
 
-static int stm32l4pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, int cmd,
-                            unsigned long arg)
+static int pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, int cmd,
+                     unsigned long arg)
 {
 #ifdef CONFIG_DEBUG_PWM_INFO
   FAR struct stm32l4_pwmtimer_s *priv = (FAR struct stm32l4_pwmtimer_s *)dev;
@@ -2538,6 +4260,7 @@ FAR struct pwm_lowerhalf_s *stm32l4_pwminitialize(int timer)
  *
  ****************************************************************************/
 
+#ifdef HAVE_LPTIM
 FAR struct pwm_lowerhalf_s *stm32l4_lp_pwminitialize(int timer)
 {
   FAR struct stm32l4_pwmtimer_s *lower;
@@ -2565,5 +4288,6 @@ FAR struct pwm_lowerhalf_s *stm32l4_lp_pwminitialize(int timer)
 
   return (FAR struct pwm_lowerhalf_s *)lower;
 }
+#endif /* HAVE_LPTIM */
 
 #endif /* CONFIG_STM32L4_TIMn_PWM, n = 1,...,17 */
diff --git a/arch/arm/src/stm32l4/stm32l4_pwm.h b/arch/arm/src/stm32l4/stm32l4_pwm.h
index c7a639d..d359c38 100644
--- a/arch/arm/src/stm32l4/stm32l4_pwm.h
+++ b/arch/arm/src/stm32l4/stm32l4_pwm.h
@@ -1,4 +1,4 @@
-/************************************************************************************
+/****************************************************************************
  * arch/arm/src/stm32l4/stm32l4_pwm.h
  *
  *   Copyright (C) 2011, 2015 Gregory Nutt. All rights reserved.
@@ -33,36 +33,36 @@
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  *
- ************************************************************************************/
+ ****************************************************************************/
 
 #ifndef __ARCH_ARM_SRC_STM32L4_STM32L4_PWM_H
 #define __ARCH_ARM_SRC_STM32L4_STM32L4_PWM_H
 
-/* The STM32L4 does not have dedicated PWM hardware.  Rather, pulsed output control
- * is a capability of the STM32L4 timers.  The logic in this file implements the
- * lower half of the standard, NuttX PWM interface using the STM32L4 timers.  That
- * interface is described in include/nuttx/timers/pwm.h.
+/* The STM32L4 does not have dedicated PWM hardware.  Rather, pulsed output
+ * control is a capability of the STM32L4 timers.  The logic in this file
+ * implements the lower half of the standard, NuttX PWM interface using the
+ * STM32L4 timers. That interface is described in include/nuttx/timers/pwm.h.
  */
 
-/************************************************************************************
+/****************************************************************************
  * Included Files
- ************************************************************************************/
+ ****************************************************************************/
 
 #include <nuttx/config.h>
 
 #include "chip.h"
 
-/************************************************************************************
+/****************************************************************************
  * Pre-processor Definitions
- ************************************************************************************/
+ ****************************************************************************/
 
-/* Configuration ********************************************************************/
+/* Configuration ************************************************************/
 
 /* Timer devices may be used for different purposes.  One special purpose is
  * to generate modulated outputs for such things as motor control.  If
- * CONFIG_STM32L4_TIMn is defined then the CONFIG_STM32L4_TIMn_PWM must also be
- * defined to indicate that timer "n" is intended to be used for pulsed output
- * signal generation.
+ * CONFIG_STM32L4_TIMn is defined then the CONFIG_STM32L4_TIMn_PWM must also
+ * be defined to indicate that timer "n" is intended to be used for pulsed
+ * output signal generation.
  */
 
 #ifndef CONFIG_STM32L4_TIM1
@@ -99,7 +99,9 @@
 #  undef CONFIG_STM32L4_LPTIM2_PWM
 #endif
 
-/* The basic timers (timer 6 and 7) are not capable of generating output pulses */
+/* The basic timers (timer 6 and 7) are not capable of generating output
+ *  pulses.
+ */
 
 #undef CONFIG_STM32L4_TIM6_PWM
 #undef CONFIG_STM32L4_TIM7_PWM
@@ -117,7 +119,9 @@
 #include "hardware/stm32l4_tim.h"
 #include "hardware/stm32l4_lptim.h"
 
-#ifdef CONFIG_PWM_MULTICHAN
+/* PWM driver channels configuration */
+
+#ifdef CONFIG_STM32L4_PWM_MULTICHAN
 
 #ifdef CONFIG_STM32L4_TIM1_CHANNEL1
 #  ifdef CONFIG_STM32L4_TIM1_CH1OUT
@@ -502,33 +506,19 @@
 #endif
 #define PWM_LPTIM2_NCHANNELS PWM_LPTIM2_CHANNEL1
 
-#define PWM_MAX(a, b) ((a) > (b) ? (a) : (b))
-
-#define PWM_NCHANNELS PWM_MAX(PWM_TIM1_NCHANNELS, \
-                      PWM_MAX(PWM_TIM2_NCHANNELS, \
-                      PWM_MAX(PWM_TIM3_NCHANNELS, \
-                      PWM_MAX(PWM_TIM4_NCHANNELS, \
-                      PWM_MAX(PWM_TIM5_NCHANNELS, \
-                      PWM_MAX(PWM_TIM8_NCHANNELS, \
-                      PWM_MAX(PWM_TIM15_NCHANNELS, \
-                      PWM_MAX(PWM_TIM16_NCHANNELS, \
-                      PWM_MAX(PWM_TIM17_NCHANNELS, \
-                      PWM_MAX(PWM_LPTIM1_NCHANNELS, \
-                              PWM_LPTIM2_NCHANNELS))))))))))
+#else /* !CONFIG_STM32L4_PWM_MULTICHAN */
 
-#else
-
-/* For each timer that is enabled for PWM usage, we need the following additional
- * configuration settings:
+/* For each timer that is enabled for PWM usage, we need the following
+ * additional configuration settings:
  *
  * CONFIG_STM32L4_TIMx_CHANNEL - Specifies the timer output channel {1,..,4}
- * PWM_TIMx_CHn - One of the values defined in chip/stm32*_pinmap.h.  In the case
- *   where there are multiple pin selections, the correct setting must be provided
- *   in the arch/board/board.h file.
+ * PWM_TIMx_CHn - One of the values defined in chip/stm32*_pinmap.h.  In the
+ *   case where there are multiple pin selections, the correct setting must be
+ *   provided in the arch/board/board.h file.
  *
- * NOTE: The STM32L4 timers are each capable of generating different signals on
- * each of the four channels with different duty cycles.  That capability is
- * not supported by this driver:  Only one output channel per timer.
+ * NOTE: The STM32L4 timers are each capable of generating different signals
+ * on each of the four channels with different duty cycles.  That capability
+ * is not supported by this driver:  Only one output channel per timer.
  */
 
 #ifdef CONFIG_STM32L4_TIM1_PWM
@@ -537,25 +527,46 @@
 #  elif CONFIG_STM32L4_TIM1_CHANNEL == 1
 #    define CONFIG_STM32L4_TIM1_CHANNEL1 1
 #    define CONFIG_STM32L4_TIM1_CH1MODE  CONFIG_STM32L4_TIM1_CHMODE
-#    define PWM_TIM1_CH1CFG            GPIO_TIM1_CH1OUT
-#    define PWM_TIM1_CH1NCFG           0
+#    ifdef CONFIG_STM32L4_TIM1_CH1OUT
+#      define PWM_TIM1_CH1CFG            GPIO_TIM1_CH1OUT
+#    endif
+#    ifdef CONFIG_STM32L4_TIM1_CH1NOUT
+#      define PWM_TIM1_CH1NCFG           GPIO_TIM1_CH1NOUT
+#    else
+#      define PWM_TIM1_CH1NCFG           0
+#    endif
 #  elif CONFIG_STM32L4_TIM1_CHANNEL == 2
 #    define CONFIG_STM32L4_TIM1_CHANNEL2 1
 #    define CONFIG_STM32L4_TIM1_CH2MODE  CONFIG_STM32L4_TIM1_CHMODE
-#    define PWM_TIM1_CH2CFG            GPIO_TIM1_CH2OUT
-#    define PWM_TIM1_CH2NCFG           0
+#    ifdef CONFIG_STM32L4_TIM1_CH2OUT
+#      define PWM_TIM1_CH2CFG            GPIO_TIM1_CH2OUT
+#    endif
+#    ifdef CONFIG_STM32L4_TIM1_CH2NOUT
+#      define PWM_TIM1_CH2NCFG           GPIO_TIM1_CH2NOUT
+#    else
+#      define PWM_TIM1_CH2NCFG           0
+#    endif
 #  elif CONFIG_STM32L4_TIM1_CHANNEL == 3
 #    define CONFIG_STM32L4_TIM1_CHANNEL3 1
 #    define CONFIG_STM32L4_TIM1_CH3MODE  CONFIG_STM32L4_TIM1_CHMODE
-#    define PWM_TIM1_CH3CFG            GPIO_TIM1_CH3OUT
-#    define PWM_TIM1_CH3NCFG           0
+#    ifdef CONFIG_STM32L4_TIM1_CH3OUT
+#      define PWM_TIM1_CH3CFG            GPIO_TIM1_CH3OUT
+#    endif
+#    ifdef CONFIG_STM32L4_TIM1_CH3NOUT
+#      define PWM_TIM1_CH3NCFG           GPIO_TIM1_CH3NOUT
+#    else
+#      define PWM_TIM1_CH3NCFG           0
+#    endif
 #  elif CONFIG_STM32L4_TIM1_CHANNEL == 4
 #    define CONFIG_STM32L4_TIM1_CHANNEL4 1
 #    define CONFIG_STM32L4_TIM1_CH4MODE  CONFIG_STM32L4_TIM1_CHMODE
-#    define PWM_TIM1_CH4CFG            GPIO_TIM1_CH4OUT
+#    ifdef CONFIG_STM32L4_TIM1_CH4OUT
+#      define PWM_TIM1_CH4CFG            GPIO_TIM1_CH4OUT
+#    endif
 #  else
 #    error "Unsupported value of CONFIG_STM32L4_TIM1_CHANNEL"
 #  endif
+#  define PWM_TIM1_NCHANNELS 1
 #endif
 
 #ifdef CONFIG_STM32L4_TIM2_PWM
@@ -580,6 +591,7 @@
 #  else
 #    error "Unsupported value of CONFIG_STM32L4_TIM2_CHANNEL"
 #  endif
+#  define PWM_TIM2_NCHANNELS 1
 #endif
 
 #ifdef CONFIG_STM32L4_TIM3_PWM
@@ -604,6 +616,7 @@
 #  else
 #    error "Unsupported value of CONFIG_STM32L4_TIM3_CHANNEL"
 #  endif
+#  define PWM_TIM3_NCHANNELS 1
 #endif
 
 #ifdef CONFIG_STM32L4_TIM4_PWM
@@ -628,6 +641,7 @@
 #  else
 #    error "Unsupported value of CONFIG_STM32L4_TIM4_CHANNEL"
 #  endif
+#  define PWM_TIM4_NCHANNELS 1
 #endif
 
 #ifdef CONFIG_STM32L4_TIM5_PWM
@@ -652,6 +666,7 @@
 #  else
 #    error "Unsupported value of CONFIG_STM32L4_TIM5_CHANNEL"
 #  endif
+#  define PWM_TIM5_NCHANNELS 1
 #endif
 
 #ifdef CONFIG_STM32L4_TIM8_PWM
@@ -679,6 +694,7 @@
 #  else
 #    error "Unsupported value of CONFIG_STM32L4_TIM8_CHANNEL"
 #  endif
+#  define PWM_TIM8_NCHANNELS 1
 #endif
 
 #ifdef CONFIG_STM32L4_TIM15_PWM
@@ -696,6 +712,7 @@
 #  else
 #    error "Unsupported value of CONFIG_STM32L4_TIM15_CHANNEL"
 #  endif
+#  define PWM_TIM15_NCHANNELS 1
 #endif
 
 #ifdef CONFIG_STM32L4_TIM16_PWM
@@ -709,6 +726,7 @@
 #  else
 #    error "Unsupported value of CONFIG_STM32L4_TIM16_CHANNEL"
 #  endif
+#  define PWM_TIM16_NCHANNELS 1
 #endif
 
 #ifdef CONFIG_STM32L4_TIM17_PWM
@@ -722,6 +740,7 @@
 #  else
 #    error "Unsupported value of CONFIG_STM32L4_TIM17_CHANNEL"
 #  endif
+#  define PWM_TIM17_NCHANNELS 1
 #endif
 
 #ifdef CONFIG_STM32L4_LPTIM1_PWM
@@ -734,6 +753,7 @@
 #  else
 #    error "Unsupported value of CONFIG_STM32L4_LPTIM1_CHANNEL"
 #  endif
+#  define PWM_LPTIM1_NCHANNELS 1
 #endif
 
 #ifdef CONFIG_STM32L4_LPTIM2_PWM
@@ -746,19 +766,258 @@
 #  else
 #    error "Unsupported value of CONFIG_STM32L4_LPTIM2_CHANNEL"
 #  endif
+#  define PWM_LPTIM2_NCHANNELS 1
+#endif
+
 #endif
 
-#define PWM_NCHANNELS 1
+/* Complementary outputs support */
 
+#if defined(CONFIG_STM32L4_TIM1_CH1NOUT) || defined(CONFIG_STM32L4_TIM1_CH2NOUT) || \
+    defined(CONFIG_STM32L4_TIM1_CH3NOUT)
+#  define HAVE_TIM1_COMPLEMENTARY
+#endif
+#if defined(CONFIG_STM32L4_TIM8_CH1NOUT) || defined(CONFIG_STM32L4_TIM8_CH2NOUT) || \
+    defined(CONFIG_STM32L4_TIM8_CH3NOUT)
+#  define HAVE_TIM8_COMPLEMENTARY
+#endif
+#if defined(CONFIG_STM32L4_TIM15_CH1NOUT)
+#  define HAVE_TIM15_COMPLEMENTARY
+#endif
+#if defined(CONFIG_STM32L4_TIM16_CH1NOUT)
+#  define HAVE_TIM16_COMPLEMENTARY
+#endif
+#if defined(CONFIG_STM32L4_TIM17_CH1NOUT)
+#  define HAVE_TIM17_COMPLEMENTARY
+#endif
+#if defined(CONFIG_STM32L4_LPTIM1_CH1NOUT)
+#  define HAVE_LPTIM1_COMPLEMENTARY
 #endif
+#if defined(CONFIG_STM32L4_LPTIM2_CH1NOUT)
+#  define HAVE_LPTIM2_COMPLEMENTARY
+#endif
+#if defined(HAVE_TIM1_COMPLEMENTARY) || defined(HAVE_TIM8_COMPLEMENTARY) ||   \
+    defined(HAVE_TIM15_COMPLEMENTARY) || defined(HAVE_TIM16_COMPLEMENTARY) || \
+    defined(HAVE_TIM17_COMPLEMENTARY) || defined(HAVE_LPTIM1_COMPLEMENTARY) || \
+    defined(HAVE_LPTIM2_COMPLEMENTARY)
+#  define HAVE_PWM_COMPLEMENTARY
+#endif
+
+/* Low-level ops helpers ************************************************************/
+
+#ifdef CONFIG_STM32L4_PWM_LL_OPS
+
+/* NOTE: low-level ops accept pwm_lowerhalf_s as first argument, but llops
+ *       access can be found in stm32_pwm_dev_s
+ */
 
-/************************************************************************************
+#define STM32L4_PWM_SETUP(dev)                                                             \
+        (dev)->ops->setup((FAR struct pwm_lowerhalf_s *)dev)
+#define STM32L4_PWM_SHUTDOWN(dev)                                                          \
+        (dev)->ops->shutdown((FAR struct pwm_lowerhalf_s *)dev)
+#define STM32L4_PWM_CCR_UPDATE(dev, index, ccr)                                            \
+        (dev)->llops->ccr_update((FAR struct pwm_lowerhalf_s *)dev, index, ccr)
+#define STM32L4_PWM_MODE_UPDATE(dev, index, mode)                                          \
+        (dev)->llops->mode_update((FAR struct pwm_lowerhalf_s *)dev, index, mode)
+#define STM32L4_PWM_CCR_GET(dev, index)                                                    \
+        (dev)->llops->ccr_get((FAR struct pwm_lowerhalf_s *)dev, index)
+#define STM32L4_PWM_ARR_UPDATE(dev, arr)                                                   \
+        (dev)->llops->arr_update((FAR struct pwm_lowerhalf_s *)dev, arr)
+#define STM32L4_PWM_ARR_GET(dev)                                                           \
+        (dev)->llops->arr_get((FAR struct pwm_lowerhalf_s *)dev)
+#define STM32L4_PWM_OUTPUTS_ENABLE(dev, out, state)                                        \
+        (dev)->llops->outputs_enable((FAR struct pwm_lowerhalf_s *)dev, out, state)
+#define STM32L4_PWM_SOFT_UPDATE(dev)                                                       \
+        (dev)->llops->soft_update((FAR struct pwm_lowerhalf_s *)dev)
+#define STM32L4_PWM_CONFIGURE(dev)                                                         \
+        (dev)->llops->configure((FAR struct pwm_lowerhalf_s *)dev)
+#define STM32L4_PWM_SOFT_BREAK(dev, state)                                                 \
+        (dev)->llops->soft_break((FAR struct pwm_lowerhalf_s *)dev, state)
+#define STM32L4_PWM_FREQ_UPDATE(dev, freq)                                                 \
+        (dev)->llops->freq_update((FAR struct pwm_lowerhalf_s *)dev, freq)
+#define STM32L4_PWM_TIM_ENABLE(dev, state)                                                 \
+        (dev)->llops->tim_enable((FAR struct pwm_lowerhalf_s *)dev, state)
+#ifdef CONFIG_DEBUG_STM32L4_PWM_INFO
+#  define STM32L4_PWM_DUMP_REGS(dev, msg)                                                  \
+        (dev)->llops->dump_regs((FAR struct pwm_lowerhalf_s *)dev, msg)
+#else
+#  define STM32L4_PWM_DUMP_REGS(dev, msg)
+#endif
+#define STM32L4_PWM_DT_UPDATE(dev, dt)                                                     \
+        (dev)->llops->dt_update((FAR struct pwm_lowerhalf_s *)dev, dt)
+#endif
+
+/****************************************************************************
  * Public Types
- ************************************************************************************/
+ ****************************************************************************/
+
+/* Timer mode */
+
+enum stm32l4_timmode_e
+{
+  STM32L4_TIMMODE_COUNTUP   = 0,
+  STM32L4_TIMMODE_COUNTDOWN = 1,
+  STM32L4_TIMMODE_CENTER1   = 2,
+  STM32L4_TIMMODE_CENTER2   = 3,
+  STM32L4_TIMMODE_CENTER3   = 4,
+};
+
+/* Timer output polarity */
+
+enum stm32l4_pwm_pol_e
+{
+  STM32L4_POL_POS  = 0,
+  STM32L4_POL_NEG  = 1,
+};
+
+/* Timer output IDLE state */
+
+enum stm32l4_pwm_idle_e
+{
+  STM32L4_IDLE_INACTIVE = 0,
+  STM32L4_IDLE_ACTIVE   = 1
+};
+
+/* PWM channel mode */
+
+enum stm32l4_chanmode_e
+{
+  STM32L4_CHANMODE_FRZN        = 0,  /* CCRx matches has no effects on outputs */
+  STM32L4_CHANMODE_CHACT       = 1,  /* OCxREF active on match */
+  STM32L4_CHANMODE_CHINACT     = 2,  /* OCxREF inactive on match */
+  STM32L4_CHANMODE_OCREFTOG    = 3,  /* OCxREF toggles when TIMy_CNT=TIMyCCRx */
+  STM32L4_CHANMODE_OCREFLO     = 4,  /* OCxREF is forced low */
+  STM32L4_CHANMODE_OCREFHI     = 5,  /* OCxREF is forced high */
+  STM32L4_CHANMODE_PWM1        = 6,  /* PWM mode 1 */
+  STM32L4_CHANMODE_PWM2        = 7,  /* PWM mode 2 */
+  STM32L4_CHANMODE_COMBINED1   = 8,  /* Combined PWM mode 1 */
+  STM32L4_CHANMODE_COMBINED2   = 9,  /* Combined PWM mode 2 */
+  STM32L4_CHANMODE_ASYMMETRIC1 = 10, /* Asymmetric PWM mode 1 */
+  STM32L4_CHANMODE_ASYMMETRIC2 = 11, /* Asymmetric PWM mode 2 */
+};
+
+/* PWM timer channel */
+
+enum stm32l4_pwm_chan_e
+{
+  STM32L4_PWM_CHAN1  = 1,
+  STM32L4_PWM_CHAN2  = 2,
+  STM32L4_PWM_CHAN3  = 3,
+  STM32L4_PWM_CHAN4  = 4,
+  STM32L4_PWM_CHAN5  = 5,
+  STM32L4_PWM_CHAN6  = 6,
+};
+
+/* PWM timer channel output */
+
+enum stm32l4_pwm_output_e
+{
+  STM32L4_PWM_OUT1  = (1 << 0),
+  STM32L4_PWM_OUT1N = (1 << 1),
+  STM32L4_PWM_OUT2  = (1 << 2),
+  STM32L4_PWM_OUT2N = (1 << 3),
+  STM32L4_PWM_OUT3  = (1 << 4),
+  STM32L4_PWM_OUT3N = (1 << 5),
+  STM32L4_PWM_OUT4  = (1 << 6),
+  /* 1 << 7 reserved - no complementary output for CH4 */
+  /* Only available inside micro */
+  STM32L4_PWM_OUT5  = (1 << 8),
+  /* 1 << 9 reserved - no complementary output for CH5 */
+  STM32L4_PWM_OUT6  = (1 << 10),
+  /* 1 << 11 reserved - no complementary output for CH6 */
+};
+
+#ifdef CONFIG_STM32L4_PWM_LL_OPS
+
+/* This structure provides the publicly visable representation of the
+ * "lower-half" PWM driver structure.
+ */
+
+struct stm32_pwm_dev_s
+{
+  /* The first field of this state structure must be a pointer to the PWM
+   * callback structure to be consistent with upper-half PWM driver.
+   */
+
+  FAR const struct pwm_ops_s *ops;
+
+  /* Publicly visible portion of the "lower-half" PWM driver structure */
+
+  FAR const struct stm32l4_pwm_ops_s *llops;
+
+  /* Require cast-compatibility with private "lower-half" PWM strucutre */
+};
+
+/* Low-level operations for PWM */
+
+struct pwm_lowerhalf_s;
+struct stm32l4_pwm_ops_s
+{
+  /* Update CCR register */
+
+  int (*ccr_update)(FAR struct pwm_lowerhalf_s *dev,
+                    uint8_t index, uint32_t ccr);
+
+  /* Update PWM mode */
+
+  int (*mode_update)(FAR struct pwm_lowerhalf_s *dev,
+                     uint8_t index, uint32_t mode);
+
+  /* Get CCR register */
+
+  uint32_t (*ccr_get)(FAR struct pwm_lowerhalf_s *dev, uint8_t index);
+
+  /* Update ARR register */
+
+  int (*arr_update)(FAR struct pwm_lowerhalf_s *dev, uint32_t arr);
+
+  /* Get ARR register */
+
+  uint32_t (*arr_get)(FAR struct pwm_lowerhalf_s *dev);
+
+  /* Enable outputs */
+
+  int (*outputs_enable)(FAR struct pwm_lowerhalf_s *dev,
+                        uint16_t outputs, bool state);
 
-/************************************************************************************
+  /* Software update */
+
+  int (*soft_update)(FAR struct pwm_lowerhalf_s *dev);
+
+  /* PWM configure */
+
+  int (*configure)(FAR struct pwm_lowerhalf_s *dev);
+
+  /* Software break */
+
+  int (*soft_break)(FAR struct pwm_lowerhalf_s *dev, bool state);
+
+  /* Update frequency */
+
+  int (*freq_update)(FAR struct pwm_lowerhalf_s *dev, uint32_t frequency);
+
+  /* Enable timer counter */
+
+  int (*tim_enable)(FAR struct pwm_lowerhalf_s *dev, bool state);
+
+#ifdef CONFIG_DEBUG_PWM_INFO
+  /* Dump timer registers */
+
+  void (*dump_regs)(FAR struct pwm_lowerhalf_s *dev, FAR const char *msg);
+#endif
+
+#ifdef HAVE_PWM_COMPLEMENTARY
+  /* Deadtime update */
+
+  int (*dt_update)(FAR struct pwm_lowerhalf_s *dev, uint8_t dt);
+#endif
+};
+
+#endif  /* CONFIG_STM32L4_PWM_LL_OPS */
+
+/****************************************************************************
  * Public Data
- ************************************************************************************/
+ ****************************************************************************/
 
 #ifndef __ASSEMBLY__
 
@@ -771,11 +1030,11 @@ extern "C"
 #define EXTERN extern
 #endif
 
-/************************************************************************************
+/****************************************************************************
  * Public Functions
- ************************************************************************************/
+ ****************************************************************************/
 
-/************************************************************************************
+/****************************************************************************
  * Name: stm32l4_pwminitialize
  *
  * Description:
@@ -790,7 +1049,7 @@ extern "C"
  *   On success, a pointer to the STM32 lower half PWM driver is returned.
  *   NULL is returned on any failure.
  *
- ************************************************************************************/
+ ****************************************************************************/
 
 FAR struct pwm_lowerhalf_s *stm32l4_pwminitialize(int timer);
 
diff --git a/boards/arm/stm32l4/nucleo-l432kc/include/nucleo-l432kc.h b/boards/arm/stm32l4/nucleo-l432kc/include/nucleo-l432kc.h
index a9819b8..964fffe 100644
--- a/boards/arm/stm32l4/nucleo-l432kc/include/nucleo-l432kc.h
+++ b/boards/arm/stm32l4/nucleo-l432kc/include/nucleo-l432kc.h
@@ -68,7 +68,8 @@
  * synced MSI.
  *
  *   System Clock source           : PLL (HSI)
- *   SYSCLK(Hz)                    : 80000000      Determined by PLL configuration
+ *   SYSCLK(Hz)                    : 80000000      Determined by PLL
+ *                                                 configuration
  *   HCLK(Hz)                      : 80000000     (STM32L4_RCC_CFGR_HPRE)
  *                                                (Max 80 MHz)
  *   AHB Prescaler                 : 1            (STM32L4_RCC_CFGR_HPRE)
@@ -233,9 +234,9 @@
 /* 'main' PLL config; we use this to generate our system clock via the R
  *  output.  We set it up as 16 MHz / 1 * 10 / 2 = 80 MHz
  *
- * XXX NOTE:  currently the main PLL is implicitly turned on and is implicitly
- * the system clock; this should be configurable since not all applications may
- * want things done this way.
+ * XXX NOTE:  currently the main PLL is implicitly turned on and is
+ * implicitly the system clock; this should be configurable since not all
+ * applications may want things done this way.
  */
 
 #define STM32L4_PLLCFG_PLLN             RCC_PLLCFG_PLLN(10)
@@ -495,6 +496,8 @@
 #define STM32L4_APB1_TIM2_CLKIN   (STM32L4_PCLK1_FREQUENCY)
 #define STM32L4_APB1_TIM6_CLKIN   (STM32L4_PCLK1_FREQUENCY)
 #define STM32L4_APB1_TIM7_CLKIN   (STM32L4_PCLK1_FREQUENCY)
+#define STM32L4_APB1_LPTIM1_CLKIN (STM32L4_PCLK1_FREQUENCY)
+#define STM32L4_APB1_LPTIM2_CLKIN (STM32L4_PCLK1_FREQUENCY)
 
 /* Configure the APB2 prescaler */
 
@@ -507,8 +510,8 @@
 
 #endif
 
-/* The timer clock frequencies are automatically defined by hardware.
- * If the APB prescaler equals 1, the timer clock frequencies are set to the same
+/* The timer clock frequencies are automatically defined by hardware. If the
+ * APB prescaler equals 1, the timer clock frequencies are set to the same
  * frequency as that of the APB domain. Otherwise they are set to twice.
  * Note: TIM1,15,16 are on APB2, others on APB1
  */