@@ -20,15 +20,13 @@ LOG_MODULE_REGISTER(pwm_nrfx, CONFIG_PWM_LOG_LEVEL);
2020 * to 0 or 1, hence the use of #if IS_ENABLED().
2121 */
2222#if IS_ENABLED (NRFX_PWM_NRF52_ANOMALY_109_WORKAROUND_ENABLED )
23- #define ANOMALY_109_IRQ_CONNECT (...) IRQ_CONNECT(__VA_ARGS__)
2423#define ANOMALY_109_EGU_IRQ_CONNECT (idx ) _EGU_IRQ_CONNECT(idx)
2524#define _EGU_IRQ_CONNECT (idx ) \
2625 extern void nrfx_egu_##idx##_irq_handler(void); \
2726 IRQ_CONNECT(DT_IRQN(DT_NODELABEL(egu##idx)), \
2827 DT_IRQ(DT_NODELABEL(egu##idx), priority), \
2928 nrfx_isr, nrfx_egu_##idx##_irq_handler, 0)
3029#else
31- #define ANOMALY_109_IRQ_CONNECT (...)
3230#define ANOMALY_109_EGU_IRQ_CONNECT (idx )
3331#endif
3432
@@ -49,7 +47,8 @@ struct pwm_nrfx_data {
4947 /* Bit mask indicating channels that need the PWM generation. */
5048 uint8_t pwm_needed ;
5149 uint8_t prescaler ;
52- bool stop_requested ;
50+ volatile bool stop_requested ;
51+ volatile bool active ;
5352};
5453/* Ensure the pwm_needed bit mask can accommodate all available channels. */
5554#if (NRF_PWM_CHANNEL_COUNT > 8 )
@@ -63,6 +62,15 @@ static uint16_t *seq_values_ptr_get(const struct device *dev)
6362 return (uint16_t * )config -> seq .values .p_raw ;
6463}
6564
65+ static void pwm_handler (nrfx_pwm_evt_type_t event_type , void * p_context )
66+ {
67+ __ASSERT_NO_MSG (event_type == NRFX_PWM_EVT_STOPPED );
68+ struct pwm_nrfx_data * data = p_context ;
69+
70+ data -> stop_requested = false;
71+ data -> active = false;
72+ }
73+
6674static bool pwm_period_check_and_set (const struct device * dev ,
6775 uint32_t channel , uint32_t period_cycles )
6876{
@@ -209,27 +217,27 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel,
209217 /* Don't wait here for the peripheral to actually stop. Instead,
210218 * ensure it is stopped before starting the next playback.
211219 */
212- nrfx_pwm_stop (& config -> pwm , false);
213- data -> stop_requested = true;
220+ if (data -> active && !data -> stop_requested ) {
221+ data -> stop_requested = true;
222+ nrfx_pwm_stop (& config -> pwm , false);
223+ }
214224 } else {
215- if (data -> stop_requested ) {
216- data -> stop_requested = false;
217-
218- /* After a stop is requested, the PWM peripheral stops
219- * pulse generation at the end of the current period,
220- * and till that moment, it ignores any start requests,
221- * so ensure here that it is stopped.
222- */
223- while (!nrfx_pwm_stopped_check (& config -> pwm )) {
224- }
225+ /* After a stop is requested, the PWM peripheral stops
226+ * pulse generation at the end of the current period,
227+ * and till that moment, it ignores any start requests,
228+ * so ensure here that it is stopped.
229+ */
230+ while (data -> stop_requested ) {
225231 }
226232
227233 /* It is sufficient to play the sequence once without looping.
228234 * The PWM generation will continue with the loaded values
229235 * until another playback is requested (new values will be
230236 * loaded then) or the PWM peripheral is stopped.
231237 */
232- nrfx_pwm_simple_playback (& config -> pwm , & config -> seq , 1 , 0 );
238+ data -> active = true;
239+ nrfx_pwm_simple_playback (& config -> pwm , & config -> seq , 1 ,
240+ NRFX_PWM_FLAG_NO_EVT_FINISHED );
233241 }
234242
235243 return 0 ;
@@ -256,6 +264,7 @@ static int pwm_nrfx_init(const struct device *dev)
256264{
257265 const struct pwm_nrfx_config * config = dev -> config ;
258266 uint8_t initially_inverted = 0 ;
267+ nrfx_err_t result ;
259268
260269 int ret = pinctrl_apply_state (config -> pcfg , PINCTRL_STATE_DEFAULT );
261270
@@ -284,10 +293,7 @@ static int pwm_nrfx_init(const struct device *dev)
284293 seq_values_ptr_get (dev )[i ] = PWM_NRFX_CH_VALUE (0 , inverted );
285294 }
286295
287- nrfx_err_t result = nrfx_pwm_init (& config -> pwm ,
288- & config -> initial_config ,
289- NULL ,
290- NULL );
296+ result = nrfx_pwm_init (& config -> pwm , & config -> initial_config , pwm_handler , dev -> data );
291297 if (result != NRFX_SUCCESS ) {
292298 LOG_ERR ("Failed to initialize device: %s" , dev -> name );
293299 return - EBUSY ;
@@ -377,9 +383,8 @@ static int pwm_nrfx_pm_action(const struct device *dev,
377383 }; \
378384 static int pwm_nrfx_init##idx(const struct device *dev) \
379385 { \
380- ANOMALY_109_IRQ_CONNECT( \
381- DT_IRQN(PWM(idx)), DT_IRQ(PWM(idx), priority), \
382- nrfx_isr, nrfx_pwm_##idx##_irq_handler, 0); \
386+ IRQ_CONNECT(DT_IRQN(PWM(idx)), DT_IRQ(PWM(idx), priority), \
387+ nrfx_isr, nrfx_pwm_##idx##_irq_handler, 0); \
383388 return pwm_nrfx_init(dev); \
384389 }; \
385390 PM_DEVICE_DT_DEFINE(PWM(idx), pwm_nrfx_pm_action); \
0 commit comments