Stop and start PWM with a PPI

Hi,

Is there anyway to start after stopping the PWM with a PPI channel?

There is a start task in the PWM, but

But not defined in the nrfx pwm driver (nrf_pwm.h)

/** @brief PWM tasks. */
typedef enum
{
    NRF_PWM_TASK_STOP      = offsetof(NRF_PWM_Type, TASKS_STOP),             ///< Stops PWM pulse generation on all channels at the end of the current PWM period, and stops the sequence playback.
#if NRF_PWM_HAS_DMA_TASKS_EVENTS
    NRF_PWM_TASK_SEQSTART0 = offsetof(NRF_PWM_Type, TASKS_DMA.SEQ[0].START), ///< Starts playback of sequence 0.
    NRF_PWM_TASK_SEQSTART1 = offsetof(NRF_PWM_Type, TASKS_DMA.SEQ[1].START), ///< Starts playback of sequence 1.
#else
    NRF_PWM_TASK_SEQSTART0 = offsetof(NRF_PWM_Type, TASKS_SEQSTART[0]),      ///< Starts playback of sequence 0.
    NRF_PWM_TASK_SEQSTART1 = offsetof(NRF_PWM_Type, TASKS_SEQSTART[1]),      ///< Starts playback of sequence 1.
#endif
    NRF_PWM_TASK_NEXTSTEP  = offsetof(NRF_PWM_Type, TASKS_NEXTSTEP)          ///< Steps by one value in the current sequence if the decoder is set to @ref NRF_PWM_STEP_TRIGGERED mode.
} nrf_pwm_task_t;

I'm developing a battery application, and the PWM is only needed for a short time, in regular intervals.

  • Hi!
    I will test your code.
    Could you let me know what SDK version you are using?

  •    I have the exact same issue in NCS v2.6.1 on the nRF52832!

    However, I found a workaround:

    static void pwm_handler(nrfx_pwm_evt_type_t event_type, void *p_context)
    {
        NRFX_LOG_INFO("PWM handler");
        nrfx_pwm_simple_playback(&pwm_instance, &seq[0], 1, NRFX_PWM_FLAG_START_VIA_TASK);
    }

    If I call the playback function in the PWM interrupt handler, my PPI-based TIMER looping works

    // Restart timer when the PWM has started the pulse
    nrfx_gppi_channel_endpoints_setup(gppi_channel_biphasic_started,
                                      nrfx_pwm_event_address_get(&pwm_instance, NRF_PWM_EVENT_SEQSTARTED0),
                                      nrfx_timer_task_address_get(&timer_inst, NRF_TIMER_TASK_START));
    nrfx_gppi_channels_enable(BIT(gppi_channel_biphasic_started));
    
    // Stop the PWM peripheral at the end of SEQ[0]
    nrfx_gppi_channel_endpoints_setup(gppi_channel_seq_end,
                                      nrfx_pwm_event_address_get(&pwm_instance, NRF_PWM_EVENT_SEQEND0),
                                      nrfx_pwm_task_address_get(&pwm_instance, NRF_PWM_TASK_STOP));
    nrfx_gppi_channels_enable(BIT(gppi_channel_seq_end));
    
    // Start PWM when timer runs out
    nrfx_gppi_channel_endpoints_setup(gppi_channel_biphasic_trigger,
                                      nrfx_timer_compare_event_address_get(&timer_inst, NRF_TIMER_CC_CHANNEL0),
                                      nrfx_pwm_task_address_get(&pwm_instance, NRF_PWM_TASK_SEQSTART0));
    nrfx_gppi_channels_enable(BIT(gppi_channel_biphasic_trigger));

    This isn't ideal though because the PPI should be able to restart PWM just by triggering the NRF_PWM_TASK_SEQSTART0 task.

    Maybe something in the playback start functions is locking out NRF_PWM_TASK_SEQSTART0 until it's called? Can someone on the NCS team possibly shed light on this  ?

    The full code I'm using is in a github repo.

    Edit 1:

    I did some testing and looks like setting enable register is the important part:

    static void pwm_handler(nrfx_pwm_evt_type_t event_type, void *p_context)
    {
        NRFX_LOG_INFO("PWM handler");
        nrf_pwm_enable(pwm_instance.p_reg);
    }

    Is there some way to set a register via PPI?

  • Thank you for you reply and attention to this thread/problem.
    Yes, it might be work like that, but I was trying to everything in hardware/ppi itself without calling an interrupt.

Related