This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

PWM configuration is causing BLE failures

Using the nRF52840 with SDK15.3.0 and S140, I am seeing strange interactions between PWM and BLE.

The PWM is configured to create a continuous 175kHz output just under 50% duty cycle.

        nrfx_pwm_t pwm_instance = NRFX_PWM_INSTANCE(0);
        nrfx_err_t err_code;

        nrfx_pwm_config_t const config0 =
        {
            // Use "GROUPED" load mode to generate two different outputs.
            // Channels 0 and 1 are common and 2 and 3 are common
            .output_pins =
            {
                 NRF_GPIO_PIN_MAP(0,5) | NRFX_PWM_PIN_INVERTED, // channel 0
                 NRFX_PWM_PIN_NOT_USED,               // channel 1
                 NRFX_PWM_PIN_INVERTED, // channel 2
                 NRFX_PWM_PIN_NOT_USED,               // channel 3
            },
            .irq_priority = APP_IRQ_PRIORITY_LOWEST,
            .base_clock   = NRF_PWM_CLK_16MHz,
            .count_mode   = NRF_PWM_MODE_UP,
            .top_value    = 46,
            .load_mode    = NRF_PWM_LOAD_GROUPED,
            .step_mode    = NRF_PWM_STEP_AUTO
        };
        
        err_code = nrfx_pwm_init(&pwm_instance, &config0, NULL);
        APP_ERROR_CHECK(err_code);

        // This array cannot be allocated on stack (hence "static") and it must
        // be in RAM (hence no "const", though its content is not changed).
        // This sequence is only one period. The period is then repeated in the
        // param to nrfx_pwm_simple_playback below
        static nrf_pwm_values_grouped_t /*const*/ seq_values[2];
        seq_values[0] =
        {
            .group_0 = 40,
            .group_1 = 0
        };
        seq_values[1] =
        {
            .group_0 = 0,
            .group_1 = 40
        };
        nrf_pwm_sequence_t const seq =
        {
            .values.p_grouped = seq_values,
            .length           = NRF_PWM_VALUES_LENGTH(seq_values),
            .repeats          = 0U,
            .end_delay        = 0U
        };

        nrfx_pwm_simple_playback(&pwm_instance, &seq, 61, NRFX_PWM_FLAG_LOOP);

When I start the PWM after entering a BLE connection, the Nordic stops responding over BLE, as shown by not sending empty packet responses in each connection event. If the PWM is stopped prior to the supervision timeout, the BLE behavior does recover. NRF logging shows that the Nordic is not faulting or resetting. The PWM output is correct during this whole time.

If I change the PWM base_clock to from 16MHz to 1MHz and adjust top and group values accordingly, BLE behavior is fine. Alternatively, if I change the output_pin to a different pin such as 0.6, BLE is fine. Neither of these pins are designated as low frequency only. Lastly, if I reduce the group values from 44 down to 37 or lower, BLE behaves correctly.

Is there any limitation to PWM or the softdevice in this situation?

I thought maybe this related to errata 183 (infocenter.nordicsemi.com/index.jsp, but sequence 1's count value is >1 and I also see this behavior if LOOPSDONE_SEQSTARTn shortcuts are not enabled.
  • This is running on custom HW. It is likely a crosstalk issue. It turns out the P0.5 trace runs parallel to the external 32k oscillator trace for a short distance. When I change the LF CLOCK source from xtal to internal RC, the issue goes away.

    More investigation is needed in order to confirm this as the root cause.

  • Hello,

    It looks like you are onto something if the PWM trace is next to the 32k oscillator line, and you see connection drops that occur when the PWM is turned on, but it doesn't happen if you use the RC oscillator. And the fact that the link doesn't time out if you stop the PWM before the supervision timeout.

    All the symptoms match the root issue that the nRF's LFXTAL doesn't work properly when the PWM is running.

    Is it possible to move the trace for the PWM? Or perhaps to change the pin that you use?

    BR,

    Edvin

Related