Add SPWM example to test STM32L4 PWM driver low level operations
Author: Alan Carvalho de Assis <acassis@gmail.com> Run nxstyle again .c file and fix error message Author: Daniel P. Carvalho <danieloak@gmail.com> Add SPWM example to test STM32L4 PWM driver low level operations. Fix BUGs.
This commit is contained in:
parent
21ea255ea4
commit
bf5d48acac
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/************************************************************************************
|
||||
/****************************************************************************
|
||||
* arch/arm/src/stm32l4/stm32l4_pwm.h
|
||||
*
|
||||
* Copyright (C) 2011, 2015 Gregory Nutt. All rights reserved.
|
||||
@ -33,36 +33,38 @@
|
||||
* 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 <nuttx/timers/pwm.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 +101,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 +121,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 +508,19 @@
|
||||
#endif
|
||||
#define PWM_LPTIM2_NCHANNELS PWM_LPTIM2_CHANNEL1
|
||||
|
||||
#define PWM_MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#else /* !CONFIG_STM32L4_PWM_MULTICHAN */
|
||||
|
||||
#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
|
||||
|
||||
/* 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 +529,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 +593,7 @@
|
||||
# else
|
||||
# error "Unsupported value of CONFIG_STM32L4_TIM2_CHANNEL"
|
||||
# endif
|
||||
# define PWM_TIM2_NCHANNELS 1
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32L4_TIM3_PWM
|
||||
@ -604,6 +618,7 @@
|
||||
# else
|
||||
# error "Unsupported value of CONFIG_STM32L4_TIM3_CHANNEL"
|
||||
# endif
|
||||
# define PWM_TIM3_NCHANNELS 1
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32L4_TIM4_PWM
|
||||
@ -628,6 +643,7 @@
|
||||
# else
|
||||
# error "Unsupported value of CONFIG_STM32L4_TIM4_CHANNEL"
|
||||
# endif
|
||||
# define PWM_TIM4_NCHANNELS 1
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32L4_TIM5_PWM
|
||||
@ -652,6 +668,7 @@
|
||||
# else
|
||||
# error "Unsupported value of CONFIG_STM32L4_TIM5_CHANNEL"
|
||||
# endif
|
||||
# define PWM_TIM5_NCHANNELS 1
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32L4_TIM8_PWM
|
||||
@ -679,6 +696,7 @@
|
||||
# else
|
||||
# error "Unsupported value of CONFIG_STM32L4_TIM8_CHANNEL"
|
||||
# endif
|
||||
# define PWM_TIM8_NCHANNELS 1
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32L4_TIM15_PWM
|
||||
@ -696,6 +714,7 @@
|
||||
# else
|
||||
# error "Unsupported value of CONFIG_STM32L4_TIM15_CHANNEL"
|
||||
# endif
|
||||
# define PWM_TIM15_NCHANNELS 1
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32L4_TIM16_PWM
|
||||
@ -709,6 +728,7 @@
|
||||
# else
|
||||
# error "Unsupported value of CONFIG_STM32L4_TIM16_CHANNEL"
|
||||
# endif
|
||||
# define PWM_TIM16_NCHANNELS 1
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32L4_TIM17_PWM
|
||||
@ -722,6 +742,7 @@
|
||||
# else
|
||||
# error "Unsupported value of CONFIG_STM32L4_TIM17_CHANNEL"
|
||||
# endif
|
||||
# define PWM_TIM17_NCHANNELS 1
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32L4_LPTIM1_PWM
|
||||
@ -734,6 +755,7 @@
|
||||
# else
|
||||
# error "Unsupported value of CONFIG_STM32L4_LPTIM1_CHANNEL"
|
||||
# endif
|
||||
# define PWM_LPTIM1_NCHANNELS 1
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32L4_LPTIM2_PWM
|
||||
@ -746,19 +768,258 @@
|
||||
# else
|
||||
# error "Unsupported value of CONFIG_STM32L4_LPTIM2_CHANNEL"
|
||||
# endif
|
||||
# define PWM_LPTIM2_NCHANNELS 1
|
||||
#endif
|
||||
|
||||
#define PWM_NCHANNELS 1
|
||||
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
/* 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 stm32l4_pwm_dev_s
|
||||
*/
|
||||
|
||||
#define PWM_SETUP(dev) \
|
||||
(dev)->ops->setup((FAR struct pwm_lowerhalf_s *)dev)
|
||||
#define PWM_SHUTDOWN(dev) \
|
||||
(dev)->ops->shutdown((FAR struct pwm_lowerhalf_s *)dev)
|
||||
#define PWM_CCR_UPDATE(dev, index, ccr) \
|
||||
(dev)->llops->ccr_update((FAR struct pwm_lowerhalf_s *)dev, index, ccr)
|
||||
#define PWM_MODE_UPDATE(dev, index, mode) \
|
||||
(dev)->llops->mode_update((FAR struct pwm_lowerhalf_s *)dev, index, mode)
|
||||
#define PWM_CCR_GET(dev, index) \
|
||||
(dev)->llops->ccr_get((FAR struct pwm_lowerhalf_s *)dev, index)
|
||||
#define PWM_ARR_UPDATE(dev, arr) \
|
||||
(dev)->llops->arr_update((FAR struct pwm_lowerhalf_s *)dev, arr)
|
||||
#define PWM_ARR_GET(dev) \
|
||||
(dev)->llops->arr_get((FAR struct pwm_lowerhalf_s *)dev)
|
||||
#define PWM_OUTPUTS_ENABLE(dev, out, state) \
|
||||
(dev)->llops->outputs_enable((FAR struct pwm_lowerhalf_s *)dev, out, state)
|
||||
#define PWM_SOFT_UPDATE(dev) \
|
||||
(dev)->llops->soft_update((FAR struct pwm_lowerhalf_s *)dev)
|
||||
#define PWM_CONFIGURE(dev) \
|
||||
(dev)->llops->configure((FAR struct pwm_lowerhalf_s *)dev)
|
||||
#define PWM_SOFT_BREAK(dev, state) \
|
||||
(dev)->llops->soft_break((FAR struct pwm_lowerhalf_s *)dev, state)
|
||||
#define PWM_FREQ_UPDATE(dev, freq) \
|
||||
(dev)->llops->freq_update((FAR struct pwm_lowerhalf_s *)dev, freq)
|
||||
#define PWM_TIM_ENABLE(dev, state) \
|
||||
(dev)->llops->tim_enable((FAR struct pwm_lowerhalf_s *)dev, state)
|
||||
#ifdef CONFIG_DEBUG_STM32L4_PWM_INFO
|
||||
# define PWM_DUMP_REGS(dev, msg) \
|
||||
(dev)->llops->dump_regs((FAR struct pwm_lowerhalf_s *)dev, msg)
|
||||
#else
|
||||
# define PWM_DUMP_REGS(dev, msg)
|
||||
#endif
|
||||
#define 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 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.
|
||||
*/
|
||||
|
||||
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 +1032,11 @@ extern "C"
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
************************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
/************************************************************************************
|
||||
/****************************************************************************
|
||||
* Name: stm32l4_pwminitialize
|
||||
*
|
||||
* Description:
|
||||
@ -790,7 +1051,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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
1360
boards/arm/stm32l4/nucleo-l432kc/configs/spwm/defconfig
Executable file
1360
boards/arm/stm32l4/nucleo-l432kc/configs/spwm/defconfig
Executable file
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
|
664
boards/arm/stm32l4/nucleo-l432kc/src/stm32_spwm.c
Normal file
664
boards/arm/stm32l4/nucleo-l432kc/src/stm32_spwm.c
Normal file
@ -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 <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 <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 */
|
Loading…
Reference in New Issue
Block a user