Skip to content
stm32_hrtim.c 151 KiB
Newer Older
/****************************************************************************
 * arch/arm/src/stm32/stm32_hrtim.c
 *
 *   Copyright (C) 2017-2018 Gregory Nutt. All rights reserved.
 *   Author: Mateusz Szafoni <raiden00@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 <stdint.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>

#include <arch/board/board.h>

#include "chip.h"
#include "stm32.h"
#include "stm32_gpio.h"
#include "stm32_hrtim.h"

#if defined(CONFIG_STM32_HRTIM1)

/* Only STM32F33XXX  */

#if defined(CONFIG_STM32_STM32F33XX)

#if defined(CONFIG_STM32_HRTIM_TIMA_PWM) || defined(CONFIG_STM32_HRTIM_TIMA_DAC) || \
    defined(CONFIG_STM32_HRTIM_TIMA_CAP) || defined(CONFIG_STM32_HRTIM_TIMA_IRQ) || \
    defined(CONFIG_STM32_HRTIM_TIMA_DT)  || defined(CONFIG_STM32_HRTIM_TIMA_CHOP)
#  ifndef CONFIG_STM32_HRTIM_TIMA
#    error "CONFIG_STM32_HRTIM_TIMA must be set"
#  endif
#endif
#if defined(CONFIG_STM32_HRTIM_TIMB_PWM) || defined(CONFIG_STM32_HRTIM_TIMB_DAC) || \
    defined(CONFIG_STM32_HRTIM_TIMB_CAP) || defined(CONFIG_STM32_HRTIM_TIMB_IRQ) || \
    defined(CONFIG_STM32_HRTIM_TIMB_DT)  || defined(CONFIG_STM32_HRTIM_TIMB_CHOP)
#  ifndef CONFIG_STM32_HRTIM_TIMB
#    error "CONFIG_STM32_HRTIM_TIMB must be set"
#  endif
#endif
#if defined(CONFIG_STM32_HRTIM_TIMC_PWM) || defined(CONFIG_STM32_HRTIM_TIMC_DAC) || \
    defined(CONFIG_STM32_HRTIM_TIMC_CAP) || defined(CONFIG_STM32_HRTIM_TIMC_IRQ) || \
    defined(CONFIG_STM32_HRTIM_TIMC_DT)  || defined(CONFIG_STM32_HRTIM_TIMC_CHOP)
#  ifndef CONFIG_STM32_HRTIM_TIMC
#    error "CONFIG_STM32_HRTIM_TIMC must be set"
#  endif
#endif
#if defined(CONFIG_STM32_HRTIM_TIMD_PWM) || defined(CONFIG_STM32_HRTIM_TIMD_DAC) || \
    defined(CONFIG_STM32_HRTIM_TIMD_CAP) || defined(CONFIG_STM32_HRTIM_TIMD_IRQ) || \
    defined(CONFIG_STM32_HRTIM_TIMD_DT)  || defined(CONFIG_STM32_HRTIM_TIMD_CHOP)
#  ifndef CONFIG_STM32_HRTIM_TIMD
#    error "CONFIG_STM32_HRTIM_TIMD must be set"
#  endif
#endif
#if defined(CONFIG_STM32_HRTIM_TIME_PWM) || defined(CONFIG_STM32_HRTIM_TIME_DAC) || \
    defined(CONFIG_STM32_HRTIM_TIME_CAP) || defined(CONFIG_STM32_HRTIM_TIME_IRQ) || \
    defined(CONFIG_STM32_HRTIM_TIME_DT)  || defined(CONFIG_STM32_HRTIM_TIME_CHOP)
#  ifndef CONFIG_STM32_HRTIM_TIME
#    error "CONFIG_STM32_HRTIM_TIME must be set"
#  endif
#endif

#if defined(CONFIG_STM32_HRTIM_PWM)
#if !defined(CONFIG_STM32_HRTIM_TIMA_PWM) && !defined(CONFIG_STM32_HRTIM_TIMB_PWM) && \
    !defined(CONFIG_STM32_HRTIM_TIMC_PWM) && !defined(CONFIG_STM32_HRTIM_TIMD_PWM) && \
    !defined(CONFIG_STM32_HRTIM_TIME_PWM)
#    warning "CONFIG_STM32_HRTIM_PWM enabled but no timer selected"
#  endif
#if defined(CONFIG_STM32_HRTIM_DAC)
#if !defined(CONFIG_STM32_HRTIM_MASTER_DAC) && !defined(CONFIG_STM32_HRTIM_TIMA_DAC) && \
    !defined(CONFIG_STM32_HRTIM_TIMB_DAC)   && !defined(CONFIG_STM32_HRTIM_TIMC_DAC) && \
    !defined(CONFIG_STM32_HRTIM_TIMD_DAC)   && !defined(CONFIG_STM32_HRTIM_TIME_DAC)
#    warning "CONFIG_STM32_HRTIM_DAC enabled but no timer selected"
#  endif
#endif
#if defined(CONFIG_STM32_HRTIM_CAPTURE)
#if !defined(CONFIG_STM32_HRTIM_TIMA_CAP) && !defined(CONFIG_STM32_HRTIM_TIMB_CAP) && \
    !defined(CONFIG_STM32_HRTIM_TIMC_CAP) && !defined(CONFIG_STM32_HRTIM_TIMD_CAP) && \
    !defined(CONFIG_STM32_HRTIM_TIME_CAP)
#    warning "CONFIG_STM32_HRTIM_CAPTURE enabled but no timer selected"
#  endif
#endif
#if defined(CONFIG_STM32_HRTIM_INTERRUPTS)
#if !defined(CONFIG_STM32_HRTIM_MASTER_IRQ) && !defined(CONFIG_STM32_HRTIM_TIMA_IRQ) && \
    !defined(CONFIG_STM32_HRTIM_TIMB_IRQ) && !defined(CONFIG_STM32_HRTIM_TIMC_IRQ) && \
    !defined(CONFIG_STM32_HRTIM_TIMD_IRQ) && !defined(CONFIG_STM32_HRTIM_TIME_IRQ) && \
    !defined(CONFIG_STM32_HRTIM_COMMON_IRQ)
#    warning "CONFIG_STM32_HRTIM_INTERRUPTS enabled but no timer selected"
#  endif
#endif
#if defined(CONFIG_STM32_HRTIM_DEADTIME)
#if !defined(CONFIG_STM32_HRTIM_TIMA_DT) && !defined(CONFIG_STM32_HRTIM_TIMB_DT) && \
    !defined(CONFIG_STM32_HRTIM_TIMC_DT) && !defined(CONFIG_STM32_HRTIM_TIMD_DT) && \
    !defined(CONFIG_STM32_HRTIM_TIME_DT)
#    warning "CONFIG_STM32_HRTIM_DEADTIME enabled but no timer selected"
#  endif
#endif
#if defined(CONFIG_STM32_HRTIM_CHOPPER)
#if !defined(CONFIG_STM32_HRTIM_TIMA_CHOP) && !defined(CONFIG_STM32_HRTIM_TIMB_CHOP) && \
    !defined(CONFIG_STM32_HRTIM_TIMC_CHOP) && !defined(CONFIG_STM32_HRTIM_TIMD_CHOP) && \
    !defined(CONFIG_STM32_HRTIM_TIME_CHOP)
#    warning "CONFIG_STM32_HRTIM_CHOPPER enabled but no timer selected"
#  endif
#endif

#if defined(CONFIG_STM32_HRTIM_TIMA_PWM) || defined(CONFIG_STM32_HRTIM_TIMB_PWM) || \
    defined(CONFIG_STM32_HRTIM_TIMC_PWM) || defined(CONFIG_STM32_HRTIM_TIMD_PWM) || \
    defined(CONFIG_STM32_HRTIM_TIME_PWM)
#  ifndef CONFIG_STM32_HRTIM_PWM
#    error "CONFIG_STM32_HRTIM_PWM must be set"
#  endif
#endif
#if defined(CONFIG_STM32_HRTIM_MASTER_DAC) || defined(CONFIG_STM32_HRTIM_TIMA_DAC) || \
    defined(CONFIG_STM32_HRTIM_TIMB_DAC)   || defined(CONFIG_STM32_HRTIM_TIMC_DAC) || \
    defined(CONFIG_STM32_HRTIM_TIMD_DAC)   || defined(CONFIG_STM32_HRTIM_TIME_DAC)
#  ifndef CONFIG_STM32_HRTIM_DAC
#    error "CONFIG_STM32_HRTIM_DAC must be set"
#  endif
#if defined(CONFIG_STM32_HRTIM_TIMA_CAP) || defined(CONFIG_STM32_HRTIM_TIMB_CAP) || \
    defined(CONFIG_STM32_HRTIM_TIMC_CAP) || defined(CONFIG_STM32_HRTIM_TIMD_CAP) || \
    defined(CONFIG_STM32_HRTIM_TIME_CAP)
#  ifndef CONFIG_STM32_HRTIM_CAPTURE
#    error "CONFIG_STM32_HRTIM_CAPTURE must be set"
#  endif
#if defined(CONFIG_STM32_HRTIM_TIMA_IRQ) || defined(CONFIG_STM32_HRTIM_TIMB_IRQ) || \
    defined(CONFIG_STM32_HRTIM_TIMC_IRQ) || defined(CONFIG_STM32_HRTIM_TIMD_IRQ) || \
    defined(CONFIG_STM32_HRTIM_TIME_IRQ)
#  ifndef CONFIG_STM32_HRTIM_INTERRUPTS
#    error "CONFIG_STM32_HRTIM_INTERRUPTS must be set"
#  endif
#endif
#if defined(CONFIG_STM32_HRTIM_TIMA_DT) || defined(CONFIG_STM32_HRTIM_TIMB_DT) || \
    defined(CONFIG_STM32_HRTIM_TIMC_DT) || defined(CONFIG_STM32_HRTIM_TIMD_DT) || \
    defined(CONFIG_STM32_HRTIM_TIME_DT)
#  ifndef CONFIG_STM32_HRTIM_DEADTIME
#    error "CONFIG_STM32_HRTIM_DEADTIME must be set"
#  endif
#endif
#if defined(CONFIG_STM32_HRTIM_TIMA_CHOP) || defined(CONFIG_STM32_HRTIM_TIMB_CHOP) || \
    defined(CONFIG_STM32_HRTIM_TIMC_CHOP) || defined(CONFIG_STM32_HRTIM_TIMD_CHOP) || \
    defined(CONFIG_STM32_HRTIM_TIME_CHOP)
#  ifndef CONFIG_STM32_HRTIM_CHOPPER
#    error "CONFIG_STM32_HRTIM_CHOPPER must be set"
#  endif
#if defined(CONFIG_STM32_HRTIM_TIMA_PSHPLL) || defined(CONFIG_STM32_HRTIM_TIMB_PSHPLL) || \
    defined(CONFIG_STM32_HRTIM_TIMC_PSHPLL) || defined(CONFIG_STM32_HRTIM_TIMD_PSHPLL) || \
    defined(CONFIG_STM32_HRTIM_TIME_PSHPLL)
#  ifndef CONFIG_STM32_HRTIM_PUSHPULL
#    error "CONFIG_STM32_HRTIM_PUSHPULL must be set"
#  endif
#endif

#if defined(CONFIG_STM32_HRTIM_TIMA_DT) && defined(CONFIG_STM32_HRTIM_TIMA_PSHPLL)
#  error "The deadtime cannot be used simultaneously with the push-pull mode"
#endif
#if defined(CONFIG_STM32_HRTIM_TIMB_DT) && defined(CONFIG_STM32_HRTIM_TIMB_PSHPLL)
#  error "The deadtime cannot be used simultaneously with the push-pull mode"
#endif
#if defined(CONFIG_STM32_HRTIM_TIMC_DT) && defined(CONFIG_STM32_HRTIM_TIMC_PSHPLL)
#  error "The deadtime cannot be used simultaneously with the push-pull mode"
#endif
#if defined(CONFIG_STM32_HRTIM_TIMD_DT) && defined(CONFIG_STM32_HRTIM_TIMD_PSHPLL)
#  error "The deadtime cannot be used simultaneously with the push-pull mode"
#endif
#if defined(CONFIG_STM32_HRTIM_TIME_DT) && defined(CONFIG_STM32_HRTIM_TIME_PSHPLL)
#  error "The deadtime cannot be used simultaneously with the push-pull mode"
#endif
#if defined(CONFIG_STM32_HRTIM_ADC1_TRG1) || defined(CONFIG_STM32_HRTIM_ADC1_TRG2) || \
    defined(CONFIG_STM32_HRTIM_ADC1_TRG3) || defined(CONFIG_STM32_HRTIM_ADC1_TRG4) || \
    defined(CONFIG_STM32_HRTIM_ADC2_TRG1) || defined(CONFIG_STM32_HRTIM_ADC2_TRG2) || \
    defined(CONFIG_STM32_HRTIM_ADC2_TRG3) || defined(CONFIG_STM32_HRTIM_ADC2_TRG4)
#  define HRTIM_HAVE_ADC
#endif

#if defined(CONFIG_STM32_HRTIM_ADC1_TRG1) || defined(CONFIG_STM32_HRTIM_ADC2_TRG1)
#  define HRTIM_HAVE_ADC_TRG1
#endif
#if defined(CONFIG_STM32_HRTIM_ADC1_TRG2) || defined(CONFIG_STM32_HRTIM_ADC2_TRG2)
#  define HRTIM_HAVE_ADC_TRG2
#endif
#if defined(CONFIG_STM32_HRTIM_ADC1_TRG3) || defined(CONFIG_STM32_HRTIM_ADC2_TRG3)
#  define HRTIM_HAVE_ADC_TRG3
#endif
#if defined(CONFIG_STM32_HRTIM_ADC1_TRG4) || defined(CONFIG_STM32_HRTIM_ADC2_TRG4)
#  define HRTIM_HAVE_ADC_TRG4
#endif

/****************************************************************************
 * Pre-processor Definitions
 ****************************************************************************/

/* HRTIM default configuration **********************************************/

#if defined(CONFIG_STM32_HRTIM_MASTER) && !defined(HRTIM_MASTER_MODE)
#  warning "HRTIM_MASTER_MODE is not set. Set the default value 0"
#  define HRTIM_MASTER_MODE 0
#endif
#if defined(CONFIG_STM32_HRTIM_TIMA) && !defined( HRTIM_TIMA_MODE)
#  warning "HRTIM_TIMA_MODE is not set. Set the default value 0"
#  define HRTIM_TIMA_MODE 0
#endif
#if defined(CONFIG_STM32_HRTIM_TIMB) && !defined(HRTIM_TIMB_MODE)
#  warning "HRTIM_TIMB_MODE is not set. Set the default value 0"
#  define HRTIM_TIMB_MODE 0
#endif
#if defined(CONFIG_STM32_HRTIM_TIMC) && !defined(HRTIM_TIMC_MODE)
#  warning "HRTIM_TIMC_MODE is not set. Set the default value 0"
#  define HRTIM_TIMC_MODE 0
#endif
#if defined(CONFIG_STM32_HRTIM_TIMD) && !defined(HRTIM_TIMD_MODE)
#  warning "HRTIM_TIMD_MODE is not set. Set the default value 0"
#  define HRTIM_TIMD_MODE 0
#endif
#if defined(CONFIG_STM32_HRTIM_TIME) && !defined(HRTIM_TIME_MODE)
#  warning "HRTIM_TIME_MODE is not set. Set the default value 0"
#  define HRTIM_TIME_MODE 0
#endif

#if defined(CONFIG_STM32_HRTIM_TIMA) && !defined( HRTIM_TIMA_UPDATE)
#  warning "HRTIM_TIMA_UPDATE is not set. Set the default value 0"
#  define HRTIM_TIMA_UPDATE 0
#endif
#if defined(CONFIG_STM32_HRTIM_TIMB) && !defined(HRTIM_TIMB_UPDATE)
#  warning "HRTIM_TIMB_UPDATE is not set. Set the default value 0"
#  define HRTIM_TIMB_UPDATE 0
#endif
#if defined(CONFIG_STM32_HRTIM_TIMC) && !defined(HRTIM_TIMC_UPDATE)
#  warning "HRTIM_TIMC_UPDATE is not set. Set the default value 0"
#  define HRTIM_TIMC_UPDATE 0
#endif
#if defined(CONFIG_STM32_HRTIM_TIMD) && !defined(HRTIM_TIMD_UPDATE)
#  warning "HRTIM_TIMD_UPDATE is not set. Set the default value 0"
#  define HRTIM_TIMD_UPDATE 0
#endif
#if defined(CONFIG_STM32_HRTIM_TIME) && !defined(HRTIM_TIME_UPDATE)
#  warning "HRTIM_TIME_UPDATE is not set. Set the default value 0"
#  define HRTIM_TIME_UPDATE 0
#endif

#if defined(CONFIG_STM32_HRTIM_TIMA) && !defined( HRTIM_TIMA_RESET)
#  warning "HRTIM_TIMA_RESET is not set. Set the default value 0"
#  define HRTIM_TIMA_RESET 0
#endif
#if defined(CONFIG_STM32_HRTIM_TIMB) && !defined(HRTIM_TIMB_RESET)
#  warning "HRTIM_TIMB_RESET is not set. Set the default value 0"
#  define HRTIM_TIMB_RESET 0
#endif
#if defined(CONFIG_STM32_HRTIM_TIMC) && !defined(HRTIM_TIMC_RESET)
#  warning "HRTIM_TIMC_RESET is not set. Set the default value 0"
#  define HRTIM_TIMC_RESET 0
#endif
#if defined(CONFIG_STM32_HRTIM_TIMD) && !defined(HRTIM_TIMD_RESET)
#  warning "HRTIM_TIMD_RESET is not set. Set the default value 0"
#  define HRTIM_TIMD_RESET 0
#endif
#if defined(CONFIG_STM32_HRTIM_TIME) && !defined(HRTIM_TIME_RESET)
#  warning "HRTIM_TIME_RESET is not set. Set the default value 0"
#  define HRTIM_TIME_RESET 0
#endif

#ifndef HRTIM_IRQ_COMMON
#  define HRTIM_IRQ_COMMON 0
#endif

#if defined(CONFIG_STM32_HRTIM_TIMA) && !defined(HRTIM_TIMA_CH1_POL)
#  define HRTIM_TIMA_CH1_POL HRTIM_OUT_POL_POS
#endif
#if defined(CONFIG_STM32_HRTIM_TIMA) && !defined(HRTIM_TIMA_CH2_POL)
#  define HRTIM_TIMA_CH2_POL HRTIM_OUT_POL_POS
#endif
#if defined(CONFIG_STM32_HRTIM_TIMB) && !defined(HRTIM_TIMB_CH1_POL)
#  define HRTIM_TIMB_CH1_POL HRTIM_OUT_POL_POS
#endif
#if defined(CONFIG_STM32_HRTIM_TIMB) && !defined(HRTIM_TIMB_CH2_POL)
#  define HRTIM_TIMB_CH2_POL HRTIM_OUT_POL_POS
#endif
#if defined(CONFIG_STM32_HRTIM_TIMC) && !defined(HRTIM_TIMC_CH1_POL)
#  define HRTIM_TIMC_CH1_POL HRTIM_OUT_POL_POS
#endif
#if defined(CONFIG_STM32_HRTIM_TIMC) && !defined(HRTIM_TIMC_CH2_POL)
#  define HRTIM_TIMC_CH2_POL HRTIM_OUT_POL_POS
#endif
#if defined(CONFIG_STM32_HRTIM_TIMD) && !defined(HRTIM_TIMD_CH1_POL)
#  define HRTIM_TIMD_CH1_POL HRTIM_OUT_POL_POS
#endif
#if defined(CONFIG_STM32_HRTIM_TIMD) && !defined(HRTIM_TIMD_CH2_POL)
#  define HRTIM_TIMD_CH2_POL HRTIM_OUT_POL_POS
#endif
#if defined(CONFIG_STM32_HRTIM_TIME) && !defined(HRTIM_TIME_CH1_POL)
#  define HRTIM_TIME_CH1_POL HRTIM_OUT_POL_POS
#endif
#if defined(CONFIG_STM32_HRTIM_TIME) && !defined(HRTIM_TIME_CH2_POL)
#  define HRTIM_TIME_CH2_POL HRTIM_OUT_POL_POS
#endif

/****************************************************************************
 * Private Types
 ****************************************************************************/

#ifdef CONFIG_STM32_HRTIM_PWM
raiden00pl's avatar
raiden00pl committed
/* HRTIM Slave Timer Single Output Set/Reset Configuration */

struct stm32_hrtim_timout_s
{
  uint32_t set;                 /* Set events*/
  uint32_t rst;                 /* Reset events*/
  uint8_t  pol:1;               /* Output polarisation */
raiden00pl's avatar
raiden00pl committed
/* HRTIM Slave Timer Chopper Configuration */
#ifdef CONFIG_STM32_HRTIM_CHOPPER
  uint16_t start_pulse:4;        /* Chopper start pulsewidth */
  uint16_t freq:4;               /* Chopper carrier frequency value */
raiden00pl's avatar
raiden00pl committed
  uint16_t duty:3;               /* Chopper duty cycle */
  uint16_t _res:5;               /* Reserved */
raiden00pl's avatar
raiden00pl committed
/* HRTIM Slave Timer Deadtime Configuration */
#ifdef CONFIG_STM32_HRTIM_DEADTIME
  uint8_t  en:1;                 /* Enable deadtime for timer */
  uint8_t  fsign_lock:1;         /* Deadtime falling sing lock */
  uint8_t  rsign_lock:1;         /* Deadtime rising sing lock */
  uint8_t  falling_lock:1;       /* Deadtime falling value lock */
  uint8_t  rising_lock:1;        /* Deadtime rising value lock */
  uint8_t  fsign:1;              /* Deadtime falling sign */
  uint8_t  rsign:1;              /* Deadtime rising sign */
  uint8_t  prescaler:3;          /* Deadtime prescaler */
  uint16_t rising:9;             /* Deadtime rising value */
  uint16_t falling:9;            /* Deadtime falling value */
/* HRTIM Timer Burst Mode Configuration */

struct stm32_hrtim_tim_burst_s
{
  uint8_t ch1_en:1;                   /* Enable burst mode operation for CH1 */
  uint8_t ch1_state:1;                /* CH1 IDLE state */
  uint8_t ch2_en:1;                   /* Enable burst mode operation for CH2 */
  uint8_t ch2_state:1;                /* CH2 IDLE state */
  uint8_t res:4;
};

/* HRTIM Timer PWM structure */

struct stm32_hrtim_pwm_s
{
  uint8_t pushpull:1;
  uint8_t res:7;
  struct stm32_hrtim_timout_s ch1; /* Channel 1 Set/Reset configuration*/
  struct stm32_hrtim_timout_s ch2; /* Channel 2 Set/Reset configuration */

#ifdef CONFIG_STM32_HRTIM_BURST
  struct stm32_hrtim_tim_burst_s burst;
#endif
#ifdef CONFIG_STM32_HRTIM_CHOPPER
#ifdef CONFIG_STM32_HRTIM_DEADTIME
/* HRTIM TIMER Capture sturcutre */

#ifdef CONFIG_STM32_HRTIM_CAPTURE
  uint32_t cap1;            /* Capture 1 configuration */
  uint32_t cap2;            /* Capture 2 configuration */
};
#endif

/* Common data structure for Master Timer and Slave Timers*/

struct stm32_hrtim_timcmn_s
{
  uint32_t base;                /* The base adress of the timer */
  uint64_t fclk;                /* The frequency of the peripheral clock
raiden00pl's avatar
raiden00pl committed
                                 * that drives the timer module.
  uint8_t prescaler:3;          /* Prescaler */
  uint8_t mode;                 /* Timer mode */
  uint8_t dac:2;                /* DAC triggering */
  uint8_t reserved:3;
#ifdef CONFIG_STM32_HRTIM_INTERRUPTS
  uint16_t irq;                 /* interrupts configuration */
  uint16_t dma;
#endif
#ifdef CONFIG_STM32_HRTIM_DMABURST
  uint32_t dmaburst;
#endif
};

/* Master Timer and Slave Timers structure */

struct stm32_hrtim_tim_s
{
  struct stm32_hrtim_timcmn_s tim; /* Common Timer data */
  FAR void *priv;                  /* Timer private data */
};

/* Master Timer private data structure */

struct stm32_hrtim_master_priv_s
{
  uint32_t reserved;            /* reserved for future use */
};

/* Slave Timer (A-E) private data structure */

struct stm32_hrtim_slave_priv_s
{
#ifdef CONFIG_STM32_HRTIM_FAULTS
  uint8_t flt;                      /* Faults configuration.
                                     * First five bits are fault sources,
raiden00pl's avatar
raiden00pl committed
                                     * last bit is lock configuration.
#ifdef CONFIG_STM32_HRTIM_AUTODELAYED
  uint8_t auto_delayed;              /* Auto-delayed mode configuration */
#endif
#endif
  uint16_t update;                  /* Update configuration */
  uint64_t reset;                   /* Timer reset events */
#ifdef CONFIG_STM32_HRTIM_PWM
  struct stm32_hrtim_pwm_s pwm;     /* PWM configuration */
#endif
#ifdef CONFIG_STM32_HRTIM_CAPTURE
  struct stm32_hrtim_capture_s cap; /* Capture configuration */
#endif
};

#ifdef CONFIG_STM32_HRTIM_FAULTS
/* Structure describes single HRTIM Fault configuration */

struct stm32_hrtim_fault_cfg_s
{
  uint8_t pol:1;                /* Fault polarity */
  uint8_t src:1;                /* Fault source */
  uint8_t filter:4;             /* Fault filter */
  uint8_t lock:1;               /* Fault lock */
raiden00pl's avatar
raiden00pl committed
  uint8_t _res:1;               /* Reserved */
};

/* Structure describes HRTIM Faults configuration */

struct stm32_hrtim_faults_s
{
#ifdef CONFIG_STM32_HRTIM_FAULT1
  struct stm32_hrtim_fault_cfg_s flt1;
#endif
#ifdef CONFIG_STM32_HRTIM_FAULT2
  struct stm32_hrtim_fault_cfg_s flt2;
#endif
#ifdef CONFIG_STM32_HRTIM_FAULT3
  struct stm32_hrtim_fault_cfg_s flt3;
#endif
#ifdef CONFIG_STM32_HRTIM_FAULT4
  struct stm32_hrtim_fault_cfg_s flt4;
#endif
#ifdef CONFIG_STM32_HRTIM_FAULT5
  struct stm32_hrtim_fault_cfg_s flt5;
#endif
};
#endif

#ifdef CONFIG_STM32_HRTIM_EVENTS
/* Structure describes single HRTIM External Event configuration */

struct stm32_hrtim_eev_cfg_s
{
  uint8_t filter:4;             /* External Event filter */
  uint8_t src:4;                /* External Event source */
  uint8_t pol:1;                /* External Event polarity */
  uint8_t sen:1;                /* External Event sensivity */
  uint8_t mode:1;               /* External Event mode */
  uint8_t _res:5;
};

/* Structure describes HRTIM External Events configuration */

struct stm32_hrtim_eev_s
{
#ifdef CONFIG_STM32_HRTIM_EEV1
  struct stm32_hrtim_eev_cfg_s eev1;
#endif
#ifdef CONFIG_STM32_HRTIM_EEV2
  struct stm32_hrtim_eev_cfg_s eev2;
#endif
#ifdef CONFIG_STM32_HRTIM_EEV3
  struct stm32_hrtim_eev_cfg_s eev3;
#endif
#ifdef CONFIG_STM32_HRTIM_EEV4
  struct stm32_hrtim_eev_cfg_s eev4;
#endif
#ifdef CONFIG_STM32_HRTIM_EEV5
  struct stm32_hrtim_eev_cfg_s eev5;
#endif
#ifdef CONFIG_STM32_HRTIM_EEV6
  struct stm32_hrtim_eev_cfg_s eev6;
#endif
#ifdef CONFIG_STM32_HRTIM_EEV7
  struct stm32_hrtim_eev_cfg_s eev7;
#endif
#ifdef CONFIG_STM32_HRTIM_EEV8
  struct stm32_hrtim_eev_cfg_s eev8;
#endif
#ifdef CONFIG_STM32_HRTIM_EEV9
  struct stm32_hrtim_eev_cfg_s eev9;
#endif
#ifdef CONFIG_STM32_HRTIM_EEV10
  struct stm32_hrtim_eev_cfg_s eev10;
#endif
};
#endif

#ifdef HRTIM_HAVE_ADC
/* Structure describes HRTIM ADC triggering configuration */

struct stm32_hrtim_adc_s
{
#ifdef HRTIM_HAVE_ADC_TRG1
  uint32_t trg1;
#endif
#ifdef HRTIM_HAVE_ADC_TRG2
  uint32_t trg2;
#endif
#ifdef HRTIM_HAVE_ADC_TRG3
  uint32_t trg3;
#endif
#ifdef HRTIM_HAVE_ADC_TRG4
#endif

/* Structure describes HRTIM Burst mode configuratione */

#ifdef CONFIG_STM32_HRTIM_BURST
  uint8_t clk:4;                /* Burst mode clock source */
  uint8_t presc:4;              /* Prescaler for f_HRTIM clock*/
  uint32_t trg;                 /* Burst mode triggers */
/* This structure describes the configuration of HRTIM device */

struct stm32_hrtim_s
{
  uint32_t base;                     /* Base adress of HRTIM block */
  struct stm32_hrtim_tim_s *master;  /* Master Timer */
#ifdef CONFIG_STM32_HRTIM_TIMA
  struct stm32_hrtim_tim_s *tima;    /* HRTIM Timer A */
#endif
#ifdef CONFIG_STM32_HRTIM_TIMB
  struct stm32_hrtim_tim_s *timb;    /* HRTIM Timer B */
#endif
#ifdef CONFIG_STM32_HRTIM_TIMC
  struct stm32_hrtim_tim_s *timc;    /* HRTIM Timer C */
#endif
#ifdef CONFIG_STM32_HRTIM_TIMD
  struct stm32_hrtim_tim_s *timd;    /* HRTIM Timer D */
#endif
#ifdef CONFIG_STM32_HRTIM_TIME
  struct stm32_hrtim_tim_s *time;    /* HRTIM Timer E */
#endif
#ifdef CONFIG_STM32_HRTIM_FAULTS
  struct stm32_hrtim_faults_s *flt;  /* Faults configuration */
#ifdef CONFIG_STM32_HRTIM_EVENTS
  struct stm32_hrtim_eev_s *eev;     /* External Events configuration  */
#endif
#ifdef HRTIM_HAVE_ADC
  struct stm32_hrtim_adc_s *adc;     /* ADC triggering configuration */
#ifdef CONFIG_STM32_HRTIM_BURST
  struct stm32_hrtim_burst_s *burst; /* Burst mode configuration */
#endif
#ifdef CONFIG_STM32_HRTIM_INTERRUPTS
  uint32_t irq;                      /* Common interrupts configuration */
#endif
};

/****************************************************************************
 * Private Function Prototypes
 ****************************************************************************/

#ifndef CONFIG_STM32_HRTIM_DISABLE_CHARDRV

/* HRTIM Driver Methods */

static int stm32_hrtim_open(FAR struct file *filep);
static int stm32_hrtim_close(FAR struct file *filep);
static int stm32_hrtim_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
/* HRTIM Register access */

static void stm32_modifyreg32(unsigned int addr, uint32_t clrbits,
                              uint32_t setbits);
static uint32_t hrtim_cmn_getreg(FAR struct stm32_hrtim_s *priv, uint32_t offset);
static void hrtim_cmn_putreg(FAR struct stm32_hrtim_s *priv, uint32_t offset,
static void hrtim_cmn_modifyreg(FAR struct stm32_hrtim_s *priv, uint32_t offset,
raiden00pl's avatar
raiden00pl committed
static void hrtim_tim_putreg(FAR struct stm32_hrtim_s *priv, uint8_t timer,
raiden00pl's avatar
raiden00pl committed
static void hrtim_tim_modifyreg(FAR struct stm32_hrtim_s *priv, uint8_t timer,
                                uint32_t offset, uint32_t clrbits, uint32_t setbits);
#ifdef CONFIG_DEBUG_TIMER_INFO
static void hrtim_dumpregs(FAR struct stm32_hrtim_s *priv, uint8_t timer,
                           FAR const char *msg);
#else
#  define hrtim_dumpregs(priv, timer, msg)
#endif

raiden00pl's avatar
raiden00pl committed
static uint32_t hrtim_tim_getreg(FAR struct stm32_hrtim_s *priv, uint8_t timer,
static FAR struct stm32_hrtim_tim_s *hrtim_tim_get(FAR struct stm32_hrtim_s *priv,
static FAR struct stm32_hrtim_slave_priv_s *hrtim_slave_get(FAR struct stm32_hrtim_s *priv,
                                                            uint8_t timer);
static uint32_t hrtim_base_get(FAR struct stm32_hrtim_s *priv, uint8_t timer);

/* Configuration */

static int hrtim_dll_cal(FAR struct stm32_hrtim_s *priv);
raiden00pl's avatar
raiden00pl committed
static int hrtim_tim_clock_config(FAR struct stm32_hrtim_s *priv, uint8_t timer,
                                  uint8_t pre);
static int hrtim_tim_clocks_config(FAR struct stm32_hrtim_s *priv);
#if defined(CONFIG_STM32_HRTIM_PWM) || defined(CONFIG_STM32_HRTIM_SYNC)
static int hrtim_gpios_config(FAR struct stm32_hrtim_s *priv);
#endif
#if defined(CONFIG_STM32_HRTIM_CAPTURE)
static int hrtim_capture_config(FAR struct stm32_hrtim_s *priv);
static uint16_t hrtim_capture_get(FAR struct hrtim_dev_s *dev, uint8_t timer,
                                  uint8_t index);
static int hrtim_soft_capture(FAR struct hrtim_dev_s *dev, uint8_t timer,
                              uint8_t index);
#if defined(CONFIG_STM32_HRTIM_SYNC)
static int hrtim_synch_config(FAR struct stm32_hrtim_s *priv);
#endif
#if defined(CONFIG_STM32_HRTIM_PWM)
static int hrtim_outputs_config(FAR struct stm32_hrtim_s *priv);
raiden00pl's avatar
raiden00pl committed
static int hrtim_outputs_enable(FAR struct hrtim_dev_s *dev, uint16_t outputs,
static int hrtim_output_set_set(FAR struct hrtim_dev_s *dev, uint16_t output,
                                uint32_t set);
static int hrtim_output_rst_set(FAR struct hrtim_dev_s *dev, uint16_t output,
                                 uint32_t rst);
#ifdef HRTIM_HAVE_ADC
static int hrtim_adc_config(FAR struct stm32_hrtim_s *priv);
#endif
#ifdef CONFIG_STM32_HRTIM_DAC
static int hrtim_dac_config(FAR struct stm32_hrtim_s *priv);
#endif
#ifdef CONFIG_STM32_HRTIM_DMA
static int hrtim_dma_cfg(FAR struct stm32_hrtim_s *priv);
static int hrtim_tim_dma_cfg(FAR struct stm32_hrtim_s *priv, uint8_t timer,
                             uint16_t dma);
#endif
#ifdef CONFIG_STM32_HRTIM_DEADTIME
static int hrtim_deadtime_update(FAR struct hrtim_dev_s *dev, uint8_t timer,
                                 uint8_t dt, uint16_t value);
static uint16_t hrtim_deadtime_get(FAR struct hrtim_dev_s *dev, uint8_t timer,
                                   uint8_t dt);
static int hrtim_tim_deadtime_cfg(FAR struct stm32_hrtim_s *priv, uint8_t timer);
static int hrtim_deadtime_config(FAR struct stm32_hrtim_s *priv);
#endif
#ifdef CONFIG_STM32_HRTIM_CHOPPER
static int hrtim_chopper_enable(FAR struct hrtim_dev_s *dev, uint8_t timer,
                                uint8_t chan, bool state);
static int hrtim_tim_chopper_cfg(FAR struct stm32_hrtim_s *priv, uint8_t timer);
static int hrtim_chopper_config(FAR struct stm32_hrtim_s *priv);
#endif
#ifdef CONFIG_STM32_HRTIM_BURST
static int hrtim_burst_enable(FAR struct hrtim_dev_s *dev, bool state);
static int hrtim_burst_cmp_update(FAR struct hrtim_dev_s *dev, uint16_t cmp);
static int hrtim_burst_per_update(FAR struct hrtim_dev_s *dev, uint16_t per);
static uint16_t hrtim_burst_cmp_get(FAR struct hrtim_dev_s *dev);
static uint16_t hrtim_burst_per_get(FAR struct hrtim_dev_s *dev);
static int hrtim_burst_pre_update(FAR struct hrtim_dev_s *dev, uint8_t pre);
static int hrtim_burst_pre_get(FAR struct hrtim_dev_s *dev);
static int hrtim_burst_config(FAR struct stm32_hrtim_s *priv);
#endif
#ifdef CONFIG_STM32_HRTIM_FAULTS
static int hrtim_faults_config(FAR struct stm32_hrtim_s *priv);
static int hrtim_flt_cfg(FAR struct stm32_hrtim_s *priv, uint8_t index);
raiden00pl's avatar
raiden00pl committed
static int hrtim_tim_faults_cfg(FAR struct stm32_hrtim_s *priv, uint8_t timer);
#ifdef CONFIG_STM32_HRTIM_EVENTS
static int hrtim_events_config(FAR struct stm32_hrtim_s *priv);
static int hrtim_eev_cfg(FAR struct stm32_hrtim_s *priv, uint8_t index);
#ifdef CONFIG_STM32_HRTIM_INTERRUPTS
static int hrtim_irq_config(FAR struct stm32_hrtim_s *priv);
static uint16_t hrtim_irq_get(FAR struct hrtim_dev_s *dev, uint8_t timer);
static int hrtim_irq_ack(FAR struct hrtim_dev_s *dev, uint8_t timer, int source);
raiden00pl's avatar
raiden00pl committed
static int hrtim_cmp_update(FAR struct hrtim_dev_s *dev, uint8_t timer,
raiden00pl's avatar
raiden00pl committed
static int hrtim_per_update(FAR struct hrtim_dev_s *dev, uint8_t timer,
static int hrtim_rep_update(FAR struct hrtim_dev_s *dev, uint8_t timer,
                            uint8_t rep);
raiden00pl's avatar
raiden00pl committed
static uint16_t hrtim_per_get(FAR struct hrtim_dev_s *dev, uint8_t timer);
static uint16_t hrtim_cmp_get(FAR struct hrtim_dev_s *dev, uint8_t timer,
static uint64_t hrtim_fclk_get(FAR struct hrtim_dev_s *dev, uint8_t timer);
static int hrtim_soft_update(FAR struct hrtim_dev_s *dev, uint8_t timer);
static int hrtim_soft_reset(FAR struct hrtim_dev_s *dev, uint8_t timer);
static int hrtim_tim_freq_set(FAR struct hrtim_dev_s  *hrtim, uint8_t timer,
                              uint64_t freq);
static int hrtim_tim_reset_set(FAR struct stm32_hrtim_s *priv, uint8_t timer,
static int hrtim_reset_config(FAR struct stm32_hrtim_s *priv);
static int hrtim_tim_update_set(FAR struct stm32_hrtim_s *priv, uint8_t timer,
                                uint16_t update);
static int hrtim_update_config(FAR struct stm32_hrtim_s *priv);

static void hrtim_tim_mode_set(FAR struct stm32_hrtim_s *priv, uint8_t timer,
                               uint8_t mode);
static void hrtim_mode_config(FAR struct stm32_hrtim_s *priv);
/* Initialization */

static int stm32_hrtimconfig(FAR struct stm32_hrtim_s *priv);

/****************************************************************************
 * Private Data
 ****************************************************************************/

#ifndef CONFIG_STM32_HRTIM_DISABLE_CHARDRV
static const struct file_operations hrtim_fops =
  stm32_hrtim_open,   /* open */
  stm32_hrtim_close,  /* close */
  NULL,               /* read */
  NULL,               /* write */
  NULL,               /* seek */
  stm32_hrtim_ioctl   /* ioctl */
#ifndef CONFIG_DISABLE_POLL
  , NULL              /* poll */
#endif
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
  , NULL              /* unlink */
#endif
#endif  /* CONFIG_STM32_HRTIM_DISABLE_CHARDRV */

/* Master Timer data */

static struct stm32_hrtim_tim_s g_master =
{
  .tim =
  {
    .base  = STM32_HRTIM1_MASTER_BASE,

    /* If MASTER is disabled, we need only MASTER base */

#ifdef CONFIG_STM32_HRTIM_MASTER
    .fclk      = HRTIM_CLOCK/(1<<HRTIM_MASTER_PRESCALER),
    .prescaler = HRTIM_MASTER_PRESCALER,
    .mode      = HRTIM_MASTER_MODE,
#  ifdef CONFIG_STM32_HRTIM_MASTER_DAC
    .dac       = HRTIM_MASTER_DAC,
#  endif
#  ifdef CONFIG_STM32_HRTIM_MASTER_IRQ
    .irq       = HRTIM_MASTER_IRQ
#  endif
#  ifdef CONFIG_STM32_HRTIM_MASTER_DMA
    .dma       = HRTIM_MASTER_DMA
};

#ifdef CONFIG_STM32_HRTIM_TIMA

/* Timer A private data */

static struct stm32_hrtim_slave_priv_s g_tima_priv =
{
  .update = HRTIM_TIMA_UPDATE,
  .reset  = HRTIM_TIMA_RESET,
#ifdef CONFIG_STM32_HRTIM_TIMA_PSHPLL
    .pushpull = 1,
#endif
      .rst = HRTIM_TIMA_CH1_RST,
      .pol = HRTIM_TIMA_CH1_POL
#endif
#ifdef CONFIG_STM32_HRTIM_TIMA_PWM_CH2
      .rst = HRTIM_TIMA_CH2_RST,
      .pol = HRTIM_TIMA_CH2_POL
#ifdef CONFIG_STM32_HRTIM_TIMA_BURST
    .burst =
    {
#  ifdef CONFIG_STM32_HRTIM_TIMA_BURST_CH1
      .ch1_en    = 1,
      .ch1_state = HRTIM_TIMA_CH1_IDLE_STATE,
#  else
      .ch1_en    = 0,
#  endif
#  ifdef CONFIG_STM32_HRTIM_TIMA_BURST_CH2
      .ch2_en    = 1,
      .ch2_state = HRTIM_TIMA_CH2_IDLE_STATE
#  else
      .ch2_en    = 0,
#  endif
    },
#endif
      .start_pulse = HRTIM_TIMA_CHOP_START,
      .duty        = HRTIM_TIMA_CHOP_DUTY,
      .freq        = HRTIM_TIMA_CHOP_FREQ
      .en           = 1,
      .fsign_lock   = HRTIM_TIMA_DT_FSLOCK,
      .rsign_lock   = HRTIM_TIMA_DT_RSLOCK,
      .falling_lock = HRTIM_TIMA_DT_FVLOCK,
      .rising_lock  = HRTIM_TIMA_DT_RVLOCK,
      .fsign        = HRTIM_TIMA_DT_FSIGN,
      .rsign        = HRTIM_TIMA_DT_RSIGN,
      .prescaler    = HRTIM_TIMA_DT_PRESCALER
    .cap1 = HRTIM_TIMA_CAPTURE1,
    .cap2 = HRTIM_TIMA_CAPTURE2,
    .base      = STM32_HRTIM1_TIMERA_BASE,
    .fclk      = HRTIM_CLOCK/(1<<HRTIM_TIMA_PRESCALER),
    .prescaler = HRTIM_TIMA_PRESCALER,
    .mode      = HRTIM_TIMA_MODE,
#ifdef CONFIG_STM32_HRTIM_TIMA_DAC
    .dac       = HRTIM_TIMA_DAC,
    .irq       = HRTIM_TIMA_IRQ,
#endif
#ifdef CONFIG_STM32_HRTIM_TIMA_DMA
    .dma       = HRTIM_TIMA_DMA
  .priv        = &g_tima_priv
#endif

#ifdef CONFIG_STM32_HRTIM_TIMB
/* Timer B private data */

static struct stm32_hrtim_slave_priv_s g_timb_priv =
{
  .update = HRTIM_TIMB_UPDATE,
  .reset  = HRTIM_TIMB_RESET,
#ifdef CONFIG_STM32_HRTIM_TIMB_PWM
  .pwm =
  {
#ifdef CONFIG_STM32_HRTIM_TIMB_PSHPLL
    .pushpull = 1,
#endif
#ifdef CONFIG_STM32_HRTIM_TIMB_PWM_CH1
    .ch1 =
    {
      .set = HRTIM_TIMB_CH1_SET,
      .rst = HRTIM_TIMB_CH1_RST,
      .pol = HRTIM_TIMB_CH1_POL
    },
#endif
#ifdef CONFIG_STM32_HRTIM_TIMB_PWM_CH2
    .ch2 =
    {
      .set = HRTIM_TIMB_CH2_SET,
      .rst = HRTIM_TIMB_CH2_RST,
      .pol = HRTIM_TIMB_CH2_POL
#ifdef CONFIG_STM32_HRTIM_TIMB_BURST
    .burst =
    {
#  ifdef CONFIG_STM32_HRTIM_TIMB_BURST_CH1
      .ch1_en    = 1,
      .ch1_state = HRTIM_TIMB_CH1_IDLE_STATE,
#  else
      .ch1_en    = 0,
#  endif
#  ifdef CONFIG_STM32_HRTIM_TIMB_BURST_CH2
      .ch2_en    = 1,
      .ch2_state = HRTIM_TIMB_CH2_IDLE_STATE
#  else
      .ch2_en    = 0,
#  endif
    },
#endif
#ifdef CONFIG_STM32_HRTIM_TIMB_CHOP
    .chp =
    {
      .start_pulse = HRTIM_TIMB_CHOP_START,
      .duty        = HRTIM_TIMB_CHOP_DUTY,
      .freq        = HRTIM_TIMB_CHOP_FREQ
    },
#endif
#ifdef CONFIG_STM32_HRTIM_TIMB_DT
    .dt =
    {
      .en           = 1,
      .fsign_lock   = HRTIM_TIMB_DT_FSLOCK,
      .rsign_lock   = HRTIM_TIMB_DT_RSLOCK,
      .falling_lock = HRTIM_TIMB_DT_FVLOCK,
      .rising_lock  = HRTIM_TIMB_DT_RVLOCK,
      .fsign        = HRTIM_TIMB_DT_FSIGN,
      .rsign        = HRTIM_TIMB_DT_RSIGN,