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

PPI interrupt was influenced by BLE connecting event

Hi,

I used PPI module and Timer2 to generate a 4Mhz pwm. But I founld when using softdevice(s110 v7.0), the pwm will be broke a while by BLE advertising or connecting event. So I suppose the ble event will influence the PPI module ?

And is there any other method to generate a 4Mhz or 8Mhz clock to driver external device?

Parents
  • You need to use the GPIOTE tasks to have the PPI driver the GPIO directly without any intervention. I had the same problem and had to jiggle around to get it to work.

    This snippet of code is used to drive a buzzer (via PWM) with two output lines tied together and another output line at the opposite (so when the two are high, I set the other low). But you can strip out a bunch of these to just have it toggle one line.

    // Configure as outputs
    nrf_gpio_cfg_output(BUZZER_OUT_0);
    nrf_gpio_cfg_output(BUZZER_OUT_1);
    nrf_gpio_cfg_output(BUZZER_IN_0);
    
    // Configure GPIOTE_CHANNEL_NUMBER to toggle the GPIO pin state with input.
    // @note Only one GPIOTE task can be coupled to an output pin.
    nrf_gpiote_task_config(0 /*GPIOTE_CHANNEL_NUMBER*/, BUZZER_OUT_0, \
                           NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);
    nrf_gpiote_task_config(1 /*GPIOTE_CHANNEL_NUMBER*/, BUZZER_OUT_1, \
                           NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_LOW);
    nrf_gpiote_task_config(2 /*GPIOTE_CHANNEL_NUMBER*/, BUZZER_IN_0, \
                           NRF_GPIOTE_POLARITY_TOGGLE, NRF_GPIOTE_INITIAL_VALUE_HIGH);
    
    // Clear TIMER2
    NRF_TIMER2->TASKS_CLEAR = 1;
    
    // Configure TIMER2 for compare[0] event every xx 
    NRF_TIMER2->PRESCALER = 0;
    NRF_TIMER2->CC[0]     = 1904;
    NRF_TIMER2->MODE      = TIMER_MODE_MODE_Timer;
    NRF_TIMER2->BITMODE   = TIMER_BITMODE_BITMODE_16Bit;
    NRF_TIMER2->SHORTS    = (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos);
    
    // Configure the PPI
    sd_ppi_channel_assign(0 /*ch_num*/, &NRF_TIMER2->EVENTS_COMPARE[0], &NRF_GPIOTE->TASKS_OUT[0]);
    sd_ppi_channel_enable_set(1 << 0 /*ch_num*/);
    
    sd_ppi_channel_assign(1 /*ch_num*/, &NRF_TIMER2->EVENTS_COMPARE[0], &NRF_GPIOTE->TASKS_OUT[1]);
    sd_ppi_channel_enable_set(1 << 1 /*ch_num*/);
    
    sd_ppi_channel_assign(2 /*ch_num*/, &NRF_TIMER2->EVENTS_COMPARE[0], &NRF_GPIOTE->TASKS_OUT[2]);
    sd_ppi_channel_enable_set(1 << 2 /*ch_num*/);
    // Start it
    NRF_TIMER2->TASKS_START = 1;  // Start event generation.
    

    This value here 1904 is for about 4.1Khz. You can calculate this with the formula

    pwm_max_value = 16.000.000 / (2 * 2^PRESCALER * FREQUENCY)

    Hope that helps, I had exactly the same problem with the BLE SD as the interrupts are the highest priority so all the nrf_pwm.c sample code had issues..

  • First thank you very much. In fact, my method is same to your, but I found the PWM sitll has a interval when BLE event is working. After I tested this config, the interval was disappeared.

    SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, false); change to :

    SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_SYNTH_250_PPM, false);

Reply Children
No Data
Related