Support Complementary PWM outputs on STM32L4

This commit is contained in:
Sebastien Lorquet 2016-10-14 18:06:11 +02:00
parent c77af11b0d
commit fb1f424e12
3 changed files with 211 additions and 11 deletions

View File

@ -731,6 +731,13 @@ config STM32L4_TIM1_CH1OUT
---help---
Enables channel 1 output.
config STM32L4_TIM1_CH1NOUT
bool "TIM1 Channel 1 Complementary Output"
default n
depends on STM32L4_TIM1_CH1OUT
---help---
Enables channel 1 complementary output.
endif # STM32L4_TIM1_CHANNEL1
config STM32L4_TIM1_CHANNEL2
@ -754,6 +761,13 @@ config STM32L4_TIM1_CH2OUT
---help---
Enables channel 2 output.
config STM32L4_TIM1_CH2NOUT
bool "TIM1 Channel 2 Complemenrary Output"
default n
depends on STM32L4_TIM1_CH2OUT
---help---
Enables channel 2 complementary output.
endif # STM32L4_TIM1_CHANNEL2
config STM32L4_TIM1_CHANNEL3
@ -777,6 +791,13 @@ config STM32L4_TIM1_CH3OUT
---help---
Enables channel 3 output.
config STM32L4_TIM1_CH3NOUT
bool "TIM1 Channel 3 Complementary Output"
default n
depends on STM32L4_TIM1_CH3OUT
---help---
Enables channel 3 complementary output.
endif # STM32L4_TIM1_CHANNEL3
config STM32L4_TIM1_CHANNEL4
@ -1426,6 +1447,13 @@ config STM32L4_TIM8_CH1OUT
---help---
Enables channel 1 output.
config STM32L4_TIM8_CH1NOUT
bool "TIM8 Channel 1 Complementary Output"
default n
depends on STM32L4_TIM8_CH1OUT
---help---
Enables channel 1 complementary output.
endif # STM32L4_TIM8_CHANNEL1
config STM32L4_TIM8_CHANNEL2
@ -1449,6 +1477,13 @@ config STM32L4_TIM8_CH2OUT
---help---
Enables channel 2 output.
config STM32L4_TIM8_CH2NOUT
bool "TIM8 Channel 2 Complementary Output"
default n
depends on STM32L4_TIM8_CH2OUT
---help---
Enables channel 2 complementary output.
endif # STM32L4_TIM8_CHANNEL2
config STM32L4_TIM8_CHANNEL3
@ -1472,6 +1507,13 @@ config STM32L4_TIM8_CH3OUT
---help---
Enables channel 3 output.
config STM32L4_TIM8_CH3NOUT
bool "TIM8 Channel 3 Complementary Output"
default n
depends on STM32L4_TIM8_CH3OUT
---help---
Enables channel 3 complementary output.
endif # STM32L4_TIM8_CHANNEL3
config STM32L4_TIM8_CHANNEL4
@ -1557,6 +1599,13 @@ config STM32L4_TIM15_CH1OUT
---help---
Enables channel 1 output.
config STM32L4_TIM15_CH1NOUT
bool "TIM15 Channel 1 Complementary Output"
default n
depends on STM32L4_TIM15_CH1OUT
---help---
Enables channel 1 complementary output.
endif # STM32L4_TIM15_CHANNEL1
config STM32L4_TIM15_CHANNEL2
@ -1642,6 +1691,13 @@ config STM32L4_TIM16_CH1OUT
---help---
Enables channel 1 output.
config STM32L4_TIM16_CH1NOUT
bool "TIM16 Channel 1 Complementary Output"
default n
depends on STM32L4_TIM16_CH1OUT
---help---
Enables channel 1 complementary output.
endif # STM32L4_TIM16_CHANNEL1
endif # STM32L4_PWM_MULTICHAN
@ -1704,6 +1760,13 @@ config STM32L4_TIM17_CH1OUT
---help---
Enables channel 1 output.
config STM32L4_TIM17_CH1NOUT
bool "TIM17 Channel 1 Complementary Output"
default n
depends on STM32L4_TIM17_CH1OUT
---help---
Enables channel 1 complementary output.
endif # STM32L4_TIM17_CHANNEL1
endif # STM32L4_PWM_MULTICHAN

View File

@ -128,6 +128,7 @@ struct stm32l4_pwmchan_s
uint8_t channel; /* Timer output channel: {1,..4} */
uint32_t pincfg; /* Output pin configuration */
enum stm32l4_chanmode_e mode;
uint32_t npincfg; /* Complementary output pin configuration (only TIM1/8 CH1-3)*/
};
/* This structure represents the state of one PWM timer */
@ -229,6 +230,7 @@ static struct stm32l4_pwmtimer_s g_pwm1dev =
.channel = 1,
.pincfg = PWM_TIM1_CH1CFG,
.mode = CONFIG_STM32L4_TIM1_CH1MODE,
.npincfg = PWM_TIM1_CH1NCFG,
},
#endif
#ifdef CONFIG_STM32L4_TIM1_CHANNEL2
@ -236,6 +238,7 @@ static struct stm32l4_pwmtimer_s g_pwm1dev =
.channel = 2,
.pincfg = PWM_TIM1_CH2CFG,
.mode = CONFIG_STM32L4_TIM1_CH2MODE,
.npincfg = PWM_TIM1_CH2NCFG,
},
#endif
#ifdef CONFIG_STM32L4_TIM1_CHANNEL3
@ -243,6 +246,7 @@ static struct stm32l4_pwmtimer_s g_pwm1dev =
.channel = 3,
.pincfg = PWM_TIM1_CH3CFG,
.mode = CONFIG_STM32L4_TIM1_CH3MODE,
.npincfg = PWM_TIM1_CH3NCFG,
},
#endif
#ifdef CONFIG_STM32L4_TIM1_CHANNEL4
@ -250,6 +254,7 @@ static struct stm32l4_pwmtimer_s g_pwm1dev =
.channel = 4,
.pincfg = PWM_TIM1_CH4CFG,
.mode = CONFIG_STM32L4_TIM1_CH4MODE,
.npincfg = 0,
},
#endif
},
@ -275,6 +280,7 @@ static struct stm32l4_pwmtimer_s g_pwm2dev =
.channel = 1,
.pincfg = PWM_TIM2_CH1CFG,
.mode = CONFIG_STM32L4_TIM2_CH1MODE,
.npincfg = 0,
},
#endif
#ifdef CONFIG_STM32L4_TIM2_CHANNEL2
@ -282,6 +288,7 @@ static struct stm32l4_pwmtimer_s g_pwm2dev =
.channel = 2,
.pincfg = PWM_TIM2_CH2CFG,
.mode = CONFIG_STM32L4_TIM2_CH2MODE,
.npincfg = 0,
},
#endif
#ifdef CONFIG_STM32L4_TIM2_CHANNEL3
@ -289,6 +296,7 @@ static struct stm32l4_pwmtimer_s g_pwm2dev =
.channel = 3,
.pincfg = PWM_TIM2_CH3CFG,
.mode = CONFIG_STM32L4_TIM2_CH3MODE,
.npincfg = 0,
},
#endif
#ifdef CONFIG_STM32L4_TIM2_CHANNEL4
@ -296,6 +304,7 @@ static struct stm32l4_pwmtimer_s g_pwm2dev =
.channel = 4,
.pincfg = PWM_TIM2_CH4CFG,
.mode = CONFIG_STM32L4_TIM2_CH4MODE,
.npincfg = 0,
},
#endif
},
@ -321,6 +330,7 @@ static struct stm32l4_pwmtimer_s g_pwm3dev =
.channel = 1,
.pincfg = PWM_TIM3_CH1CFG,
.mode = CONFIG_STM32L4_TIM3_CH1MODE,
.npincfg = 0,
},
#endif
#ifdef CONFIG_STM32L4_TIM3_CHANNEL2
@ -328,6 +338,7 @@ static struct stm32l4_pwmtimer_s g_pwm3dev =
.channel = 2,
.pincfg = PWM_TIM3_CH2CFG,
.mode = CONFIG_STM32L4_TIM3_CH2MODE,
.npincfg = 0,
},
#endif
#ifdef CONFIG_STM32L4_TIM3_CHANNEL3
@ -335,6 +346,7 @@ static struct stm32l4_pwmtimer_s g_pwm3dev =
.channel = 3,
.pincfg = PWM_TIM3_CH3CFG,
.mode = CONFIG_STM32L4_TIM3_CH3MODE,
.npincfg = 0,
},
#endif
#ifdef CONFIG_STM32L4_TIM3_CHANNEL4
@ -342,6 +354,7 @@ static struct stm32l4_pwmtimer_s g_pwm3dev =
.channel = 4,
.pincfg = PWM_TIM3_CH4CFG,
.mode = CONFIG_STM32L4_TIM3_CH4MODE,
.npincfg = 0,
},
#endif
},
@ -367,6 +380,7 @@ static struct stm32l4_pwmtimer_s g_pwm4dev =
.channel = 1,
.pincfg = PWM_TIM4_CH1CFG,
.mode = CONFIG_STM32L4_TIM4_CH1MODE,
.npincfg = 0,
},
#endif
#ifdef CONFIG_STM32L4_TIM4_CHANNEL2
@ -374,6 +388,7 @@ static struct stm32l4_pwmtimer_s g_pwm4dev =
.channel = 2,
.pincfg = PWM_TIM4_CH2CFG,
.mode = CONFIG_STM32L4_TIM4_CH2MODE,
.npincfg = 0,
},
#endif
#ifdef CONFIG_STM32L4_TIM4_CHANNEL3
@ -381,6 +396,7 @@ static struct stm32l4_pwmtimer_s g_pwm4dev =
.channel = 3,
.pincfg = PWM_TIM4_CH3CFG,
.mode = CONFIG_STM32L4_TIM4_CH3MODE,
.npincfg = 0,
},
#endif
#ifdef CONFIG_STM32L4_TIM4_CHANNEL4
@ -388,6 +404,7 @@ static struct stm32l4_pwmtimer_s g_pwm4dev =
.channel = 4,
.pincfg = PWM_TIM4_CH4CFG,
.mode = CONFIG_STM32L4_TIM4_CH4MODE,
.npincfg = 0,
},
#endif
},
@ -413,6 +430,7 @@ static struct stm32l4_pwmtimer_s g_pwm5dev =
.channel = 1,
.pincfg = PWM_TIM5_CH1CFG,
.mode = CONFIG_STM32L4_TIM5_CH1MODE,
.npincfg = 0,
},
#endif
#ifdef CONFIG_STM32L4_TIM5_CHANNEL2
@ -420,6 +438,7 @@ static struct stm32l4_pwmtimer_s g_pwm5dev =
.channel = 2,
.pincfg = PWM_TIM5_CH2CFG,
.mode = CONFIG_STM32L4_TIM5_CH2MODE,
.npincfg = 0,
},
#endif
#ifdef CONFIG_STM32L4_TIM5_CHANNEL3
@ -427,6 +446,7 @@ static struct stm32l4_pwmtimer_s g_pwm5dev =
.channel = 3,
.pincfg = PWM_TIM5_CH3CFG,
.mode = CONFIG_STM32L4_TIM5_CH3MODE,
.npincfg = 0,
},
#endif
#ifdef CONFIG_STM32L4_TIM5_CHANNEL4
@ -434,6 +454,7 @@ static struct stm32l4_pwmtimer_s g_pwm5dev =
.channel = 4,
.pincfg = PWM_TIM5_CH4CFG,
.mode = CONFIG_STM32L4_TIM5_CH4MODE,
.npincfg = 0,
},
#endif
},
@ -459,6 +480,7 @@ static struct stm32l4_pwmtimer_s g_pwm8dev =
.channel = 1,
.pincfg = PWM_TIM8_CH1CFG,
.mode = CONFIG_STM32L4_TIM8_CH1MODE,
.npincfg = PWM_TIM8_CH1NCFG,
},
#endif
#ifdef CONFIG_STM32L4_TIM8_CHANNEL2
@ -466,6 +488,7 @@ static struct stm32l4_pwmtimer_s g_pwm8dev =
.channel = 2,
.pincfg = PWM_TIM8_CH2CFG,
.mode = CONFIG_STM32L4_TIM8_CH2MODE,
.npincfg = PWM_TIM8_CH2NCFG,
},
#endif
#ifdef CONFIG_STM32L4_TIM8_CHANNEL3
@ -473,6 +496,7 @@ static struct stm32l4_pwmtimer_s g_pwm8dev =
.channel = 3,
.pincfg = PWM_TIM8_CH3CFG,
.mode = CONFIG_STM32L4_TIM8_CH3MODE,
.npincfg = PWM_TIM8_CH3NCFG,
},
#endif
#ifdef CONFIG_STM32L4_TIM8_CHANNEL4
@ -480,6 +504,7 @@ static struct stm32l4_pwmtimer_s g_pwm8dev =
.channel = 4,
.pincfg = PWM_TIM8_CH4CFG,
.mode = CONFIG_STM32L4_TIM8_CH4MODE,
.npincfg = 0,
},
#endif
},
@ -505,6 +530,7 @@ static struct stm32l4_pwmtimer_s g_pwm15dev =
.channel = 1,
.pincfg = PWM_TIM15_CH1CFG,
.mode = CONFIG_STM32L4_TIM15_CH1MODE,
.npincfg = PWM_TIM15_CH1NCFG,
},
#endif
#ifdef CONFIG_STM32L4_TIM15_CHANNEL2
@ -512,6 +538,7 @@ static struct stm32l4_pwmtimer_s g_pwm15dev =
.channel = 2,
.pincfg = PWM_TIM15_CH2CFG,
.mode = CONFIG_STM32L4_TIM15_CH2MODE,
.npincfg = 0,
},
#endif
},
@ -537,6 +564,7 @@ static struct stm32l4_pwmtimer_s g_pwm16dev =
.channel = 1,
.pincfg = PWM_TIM16_CH1CFG,
.mode = CONFIG_STM32L4_TIM16_CH1MODE,
.npincfg = PWM_TIM16_CH1NCFG,
},
#endif
},
@ -562,6 +590,7 @@ static struct stm32l4_pwmtimer_s g_pwm17dev =
.channel = 1,
.pincfg = PWM_TIM17_CH1CFG,
.mode = CONFIG_STM32L4_TIM17_CH1MODE,
.npincfg = PWM_TIM17_CH1NCFG,
},
#endif
},
@ -737,6 +766,7 @@ static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv,
/* New timer register bit settings */
uint16_t ccenable;
uint16_t ccnenable;
uint32_t ocmode1;
uint32_t ocmode2;
@ -967,6 +997,7 @@ static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv,
/* Handle channel specific setup */
ccenable = 0;
ccnenable = 0;
ocmode1 = 0;
ocmode2 = 0;
@ -976,6 +1007,7 @@ static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv,
{
ub16_t duty;
uint32_t chanmode;
uint32_t compout; /* Complementary output config */
bool ocmbit = false;
uint8_t channel;
#ifdef CONFIG_PWM_MULTICHAN
@ -1001,6 +1033,7 @@ static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv,
if (priv->channels[j].channel == channel)
{
mode = priv->channels[j].mode;
compout = priv->channels[j].npincfg;
break;
}
}
@ -1014,6 +1047,7 @@ static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv,
duty = info->duty;
channel = priv->channels[0].channel;
mode = priv->channels[0].mode;
compout = priv->channels[0].npincfg;
#endif
/* Duty cycle:
@ -1068,6 +1102,13 @@ static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv,
ccenable |= ATIM_CCER_CC1E;
/* Conditionnaly enable the complementary output */
if(compout)
{
ccnenable |= ATIM_CCER_CC1NE;
}
/* Set the CCMR1 mode values (leave CCMR2 zero) */
ocmode1 |= (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC1S_SHIFT) |
@ -1091,6 +1132,13 @@ static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv,
ccenable |= ATIM_CCER_CC2E;
/* Conditionnaly enable the complementary output */
if(compout)
{
ccnenable |= ATIM_CCER_CC2NE;
}
/* Set the CCMR1 mode values (leave CCMR2 zero) */
ocmode1 |= (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR1_CC2S_SHIFT) |
@ -1114,6 +1162,13 @@ static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv,
ccenable |= ATIM_CCER_CC3E;
/* Conditionnaly enable the complementary output */
if(compout)
{
ccnenable |= ATIM_CCER_CC3NE;
}
/* Set the CCMR2 mode values (leave CCMR1 zero) */
ocmode2 |= (ATIM_CCMR_CCS_CCOUT << ATIM_CCMR2_CC3S_SHIFT) |
@ -1208,6 +1263,8 @@ static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv,
ccer &= ~(ATIM_CCER_CC1NE | ATIM_CCER_CC1NP | ATIM_CCER_CC2NE | ATIM_CCER_CC2NP |
ATIM_CCER_CC3NE | ATIM_CCER_CC3NP);
ccer |= ccnenable;
/* Reset the output compare and output compare N IDLE State */
cr2 &= ~(ATIM_CR2_OIS1 | ATIM_CR2_OIS1N | ATIM_CR2_OIS2 | ATIM_CR2_OIS2N |
@ -1223,9 +1280,23 @@ static int stm32l4pwm_timer(FAR struct stm32l4_pwmtimer_s *priv,
stm32l4pwm_putreg(priv, STM32L4_ATIM_BDTR_OFFSET, bdtr);
}
else
#if defined(CONFIG_STM32L4_TIM15_PWM) || defined(CONFIG_STM32L4_TIM15_PWM) || defined(CONFIG_STM32L4_TIM15_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;
}
else
#endif
#endif
{
ccer &= ~(GTIM_CCER_CC1NP | GTIM_CCER_CC2NP | GTIM_CCER_CC3NP);
ccer &= ~(GTIM_CCER_CC1NP | GTIM_CCER_CC2NP | GTIM_CCER_CC3NP); //Not sure why ??
}
/* Save the modified register values */
@ -1646,14 +1717,24 @@ static int stm32l4pwm_setup(FAR struct pwm_lowerhalf_s *dev)
for (i = 0; i < PWM_NCHANNELS; i++)
{
pincfg = priv->channels[i].pincfg;
if (pincfg == 0)
if (pincfg != 0)
{
continue;
pwminfo("pincfg: %08x\n", pincfg);
stm32l4_configgpio(pincfg);
}
pwminfo("pincfg: %08x\n", pincfg);
stm32l4_configgpio(pincfg);
/* Enable complementary channel if available */
pincfg = priv->channels[i].npincfg;
if (pincfg != 0)
{
pwminfo("npincfg: %08x\n", pincfg);
stm32l4_configgpio(pincfg);
}
pwm_dumpgpio(pincfg, "PWM setup");
}
@ -1697,18 +1778,29 @@ static int stm32l4pwm_shutdown(FAR struct pwm_lowerhalf_s *dev)
for (i = 0; i < PWM_NCHANNELS; i++)
{
pincfg = priv->channels[i].pincfg;
if (pincfg == 0)
if (pincfg != 0)
{
continue;
pwminfo("pincfg: %08x\n", pincfg);
pincfg &= (GPIO_PORT_MASK | GPIO_PIN_MASK);
pincfg |= GPIO_INPUT | GPIO_FLOAT;
stm32l4_configgpio(pincfg);
}
pwminfo("pincfg: %08x\n", pincfg);
pincfg = priv->channels[i].npincfg;
if (pincfg != 0)
{
pwminfo("npincfg: %08x\n", pincfg);
pincfg &= (GPIO_PORT_MASK | GPIO_PIN_MASK);
pincfg &= (GPIO_PORT_MASK | GPIO_PIN_MASK);
pincfg |= GPIO_INPUT | GPIO_FLOAT;
pincfg |= GPIO_INPUT | GPIO_FLOAT;
stm32l4_configgpio(pincfg);
}
stm32l4_configgpio(pincfg);
}
return OK;

View File

@ -114,6 +114,11 @@
# else
# define PWM_TIM1_CH1CFG 0
# endif
# ifdef CONFIG_STM32L4_TIM1_CH1NOUT
# define PWM_TIM1_CH1NCFG GPIO_TIM1_CH1NOUT
# else
# define PWM_TIM1_CH1NCFG 0
# endif
# define PWM_TIM1_CHANNEL1 1
#else
# define PWM_TIM1_CHANNEL1 0
@ -124,6 +129,11 @@
# else
# define PWM_TIM1_CH2CFG 0
# endif
# ifdef CONFIG_STM32L4_TIM1_CH2NOUT
# define PWM_TIM1_CH2NCFG GPIO_TIM1_CH2NOUT
# else
# define PWM_TIM1_CH2NCFG 0
# endif
# define PWM_TIM1_CHANNEL2 1
#else
# define PWM_TIM1_CHANNEL2 0
@ -134,6 +144,11 @@
# else
# define PWM_TIM1_CH3CFG 0
# endif
# ifdef CONFIG_STM32L4_TIM1_CH3NOUT
# define PWM_TIM1_CH3NCFG GPIO_TIM1_CH3NOUT
# else
# define PWM_TIM1_CH3NCFG 0
# endif
# define PWM_TIM1_CHANNEL3 1
#else
# define PWM_TIM1_CHANNEL3 0
@ -329,6 +344,11 @@
# else
# define PWM_TIM8_CH1CFG 0
# endif
# ifdef CONFIG_STM32L4_TIM8_CH1OUT
# define PWM_TIM8_CH1NCFG GPIO_TIM8_CH1NOUT
# else
# define PWM_TIM8_CH1NCFG 0
# endif
# define PWM_TIM8_CHANNEL1 1
#else
# define PWM_TIM8_CHANNEL1 0
@ -339,6 +359,11 @@
# else
# define PWM_TIM8_CH2CFG 0
# endif
# ifdef CONFIG_STM32L4_TIM8_CH2NOUT
# define PWM_TIM8_CH2NCFG GPIO_TIM8_CH2NOUT
# else
# define PWM_TIM8_CH2NCFG 0
# endif
# define PWM_TIM8_CHANNEL2 1
#else
# define PWM_TIM8_CHANNEL2 0
@ -349,6 +374,11 @@
# else
# define PWM_TIM8_CH3CFG 0
# endif
# ifdef CONFIG_STM32L4_TIM8_CH3NOUT
# define PWM_TIM8_CH3NCFG GPIO_TIM8_CH3NOUT
# else
# define PWM_TIM8_CH3NCFG 0
# endif
# define PWM_TIM8_CHANNEL3 1
#else
# define PWM_TIM8_CHANNEL3 0
@ -372,6 +402,11 @@
# else
# define PWM_TIM15_CH1CFG 0
# endif
# ifdef CONFIG_STM32L4_TIM15_CH1NOUT
# define PWM_TIM15_CH1NCFG GPIO_TIM15_CH1NOUT
# else
# define PWM_TIM15_CH1NCFG 0
# endif
# define PWM_TIM15_CHANNEL1 1
#else
# define PWM_TIM15_CHANNEL1 0
@ -394,6 +429,11 @@
# else
# define PWM_TIM16_CH1CFG 0
# endif
# ifdef CONFIG_STM32L4_TIM16_CH1NOUT
# define PWM_TIM16_CH1NCFG GPIO_TIM16_CH1NOUT
# else
# define PWM_TIM16_CH1NCFG 0
# endif
# define PWM_TIM16_CHANNEL1 1
#else
# define PWM_TIM16_CHANNEL1 0
@ -406,6 +446,11 @@
# else
# define PWM_TIM17_CH1CFG 0
# endif
# ifdef CONFIG_STM32L4_TIM17_CH1NOUT
# define PWM_TIM17_CH1NCFG GPIO_TIM17_CH1NOUT
# else
# define PWM_TIM17_CH1NCFG 0
# endif
# define PWM_TIM17_CHANNEL1 1
#else
# define PWM_TIM17_CHANNEL1 0