1919#include <init.h>
2020
2121#include <drivers/clock_control/stm32_clock_control.h>
22+ #include <dt-bindings/pwm/stm32_pwm.h>
2223
2324#include <logging/log.h>
2425LOG_MODULE_REGISTER (pwm_stm32 , CONFIG_PWM_LOG_LEVEL );
@@ -40,6 +41,10 @@ struct pwm_stm32_capture_data {
4041 bool capture_pulse ;
4142 bool continuous ;
4243};
44+
45+ /* first capture is always nonsense, second is nonsense when polarity changed */
46+ #define SKIPPED_PWM_CAPTURES 2u
47+
4348#endif /*CONFIG_PWM_CAPTURE*/
4449
4550/** PWM data. */
@@ -66,34 +71,15 @@ struct pwm_stm32_config {
6671#endif /* CONFIG_PWM_CAPTURE */
6772};
6873
69- /** Series F3, F7, G0, G4, H7, L4, MP1 and WB have up to 6 channels, others up
70- * to 4.
71- */
72- #if defined(CONFIG_SOC_SERIES_STM32F3X ) || \
73- defined(CONFIG_SOC_SERIES_STM32F7X ) || \
74- defined(CONFIG_SOC_SERIES_STM32G0X ) || \
75- defined(CONFIG_SOC_SERIES_STM32G4X ) || \
76- defined(CONFIG_SOC_SERIES_STM32H7X ) || \
77- defined(CONFIG_SOC_SERIES_STM32L4X ) || \
78- defined(CONFIG_SOC_SERIES_STM32MP1X ) || \
79- defined(CONFIG_SOC_SERIES_STM32WBX )
74+ /** Maximum number of timer channels : some stm32 soc have 6 else only 4 */
75+ #if defined(LL_TIM_CHANNEL_CH6 )
8076#define TIMER_HAS_6CH 1
81- #else
82- #define TIMER_HAS_6CH 0
83- #endif
84-
85- /** Maximum number of timer channels. */
86- #if TIMER_HAS_6CH
8777#define TIMER_MAX_CH 6u
8878#else
79+ #define TIMER_HAS_6CH 0
8980#define TIMER_MAX_CH 4u
9081#endif
9182
92- /* first capture is always nonsense, second is nonsense when polarity changed */
93- #ifdef CONFIG_PWM_CAPTURE
94- #define SKIPPED_PWM_CAPTURES 2u
95- #endif /* CONFIG_PWM_CAPTURE */
96-
9783/** Channel to LL mapping. */
9884static const uint32_t ch2ll [TIMER_MAX_CH ] = {
9985 LL_TIM_CHANNEL_CH1 , LL_TIM_CHANNEL_CH2 ,
@@ -103,6 +89,21 @@ static const uint32_t ch2ll[TIMER_MAX_CH] = {
10389#endif
10490};
10591
92+
93+ /** Some stm32 mcus have complementary channels : 3 or 4 */
94+ static const uint32_t ch2ll_n [] = {
95+ #if defined(LL_TIM_CHANNEL_CH1N )
96+ LL_TIM_CHANNEL_CH1N ,
97+ LL_TIM_CHANNEL_CH2N ,
98+ LL_TIM_CHANNEL_CH3N ,
99+ #if defined(LL_TIM_CHANNEL_CH4N )
100+ /** stm32g4x and stm32u5x have 4 complementary channels */
101+ LL_TIM_CHANNEL_CH4N ,
102+ #endif /* LL_TIM_CHANNEL_CH4N */
103+ #endif /* LL_TIM_CHANNEL_CH1N */
104+ };
105+ /** Maximum number of complemented timer channels is ARRAY_SIZE(ch2ll_n)*/
106+
106107/** Channel to compare set function mapping. */
107108static void (* const set_timer_compare [TIMER_MAX_CH ])(TIM_TypeDef * ,
108109 uint32_t ) = {
@@ -227,6 +228,7 @@ static int pwm_stm32_pin_set(const struct device *dev, uint32_t pwm,
227228 const struct pwm_stm32_config * cfg = dev -> config ;
228229
229230 uint32_t channel ;
231+ uint32_t current_channel ; /* complementary output if used */
230232
231233 if (pwm < 1u || pwm > TIMER_MAX_CH ) {
232234 LOG_ERR ("Invalid channel (%d)" , pwm );
@@ -259,20 +261,47 @@ static int pwm_stm32_pin_set(const struct device *dev, uint32_t pwm,
259261
260262 channel = ch2ll [pwm - 1u ];
261263
264+ /* in LL_TIM_CC_DisableChannel and LL_TIM_CC_IsEnabledChannel,
265+ * the channel param could be the complementary one
266+ */
267+ if ((flags & PWM_STM32_COMPLEMENTARY_MASK ) == PWM_STM32_COMPLEMENTARY ) {
268+ if (pwm > ARRAY_SIZE (ch2ll_n )) {
269+ /* setting a flag on a channel that has not this capability */
270+ LOG_ERR ("Channel %d has NO complementary output" , pwm );
271+ return - EINVAL ;
272+ }
273+ current_channel = ch2ll_n [pwm - 1u ];
274+ } else {
275+ current_channel = channel ;
276+ }
277+
262278 if (period_cycles == 0u ) {
263- LL_TIM_CC_DisableChannel (cfg -> timer , channel );
279+ LL_TIM_CC_DisableChannel (cfg -> timer , current_channel );
264280 return 0 ;
265281 }
266282
267- if (!LL_TIM_CC_IsEnabledChannel (cfg -> timer , channel )) {
283+ if (!LL_TIM_CC_IsEnabledChannel (cfg -> timer , current_channel )) {
268284 LL_TIM_OC_InitTypeDef oc_init ;
269285
270286 LL_TIM_OC_StructInit (& oc_init );
271287
272288 oc_init .OCMode = LL_TIM_OCMODE_PWM1 ;
289+
290+ #if defined(LL_TIM_CHANNEL_CH1N )
291+ /* the flags holds the PWM_STM32_COMPLEMENTARY information */
292+ if ((flags & PWM_STM32_COMPLEMENTARY_MASK ) == PWM_STM32_COMPLEMENTARY ) {
293+ oc_init .OCNState = LL_TIM_OCSTATE_ENABLE ;
294+ oc_init .OCNPolarity = get_polarity (flags );
295+ } else {
296+ oc_init .OCState = LL_TIM_OCSTATE_ENABLE ;
297+ oc_init .OCPolarity = get_polarity (flags );
298+ }
299+ #else /* LL_TIM_CHANNEL_CH1N */
300+
273301 oc_init .OCState = LL_TIM_OCSTATE_ENABLE ;
274- oc_init .CompareValue = pulse_cycles ;
275302 oc_init .OCPolarity = get_polarity (flags );
303+ #endif /* LL_TIM_CHANNEL_CH1N */
304+ oc_init .CompareValue = pulse_cycles ;
276305
277306#ifdef CONFIG_PWM_CAPTURE
278307 if (IS_TIM_SLAVE_INSTANCE (cfg -> timer )) {
@@ -283,17 +312,20 @@ static int pwm_stm32_pin_set(const struct device *dev, uint32_t pwm,
283312 }
284313#endif /* CONFIG_PWM_CAPTURE */
285314
315+ /* in LL_TIM_OC_Init, the channel is always the non-complementary */
286316 if (LL_TIM_OC_Init (cfg -> timer , channel , & oc_init ) != SUCCESS ) {
287317 LOG_ERR ("Could not initialize timer channel output" );
288318 return - EIO ;
289319 }
290320
291321 LL_TIM_EnableARRPreload (cfg -> timer );
322+ /* in LL_TIM_OC_EnablePreload, the channel is always the non-complementary */
292323 LL_TIM_OC_EnablePreload (cfg -> timer , channel );
293324 LL_TIM_SetAutoReload (cfg -> timer , period_cycles - 1u );
294325 LL_TIM_GenerateEvent_UPDATE (cfg -> timer );
295326 } else {
296- LL_TIM_OC_SetPolarity (cfg -> timer , channel , get_polarity (flags ));
327+ /* in LL_TIM_OC_SetPolarity, the channel could be the complementary one */
328+ LL_TIM_OC_SetPolarity (cfg -> timer , current_channel , get_polarity (flags ));
297329 set_timer_compare [pwm - 1u ](cfg -> timer , pulse_cycles );
298330 LL_TIM_SetAutoReload (cfg -> timer , period_cycles - 1u );
299331 }
0 commit comments