SAADC sample via PPI not working without previous trigger

Hello,

I'm trying to achieve a rather simple program with three steps.

  1. I initialize the SAADC to sample three channels (currently I only have one setup)
  2. I "arm/prepare" the ADC and a timer to control the SAADC samples via PPI
  3. SAADC samples n times until buffer is full, driven by the timer.

This setup seems to work if I first trigger a sample manually during the init phase, which I do not want to do.

Here is the initialization code, where adc_end_cb just prints the ADC event.
When I uncomment the nrfx_saadc_mode_trigger(); command, the PPI seems to work and collect samples. If it's commented, the callback is never invoked, as the ADC was disabled or similar.

int hw_adc_init(void (*cb)(void), uint16_t *buffer, size_t buffer_size){
    nrfx_err_t err;

    adc_end_cb_ptr = cb;

    err = nrfx_saadc_init(5);
    if(err != NRFX_SUCCESS){
        LOG_ERR("Failed to initialize SAADC");
        return err;
    }

	IRQ_CONNECT(DT_IRQN(SAADC_NODE), DT_IRQ(SAADC_NODE, priority), nrfx_isr, nrfx_saadc_irq_handler, 0);


    nrfx_saadc_adv_config_t channel_config = NRFX_SAADC_DEFAULT_ADV_CONFIG;
    channel_config.oversampling = NRF_SAADC_OVERSAMPLE_DISABLED;
    channel_config.burst = NRF_SAADC_BURST_DISABLED;
    channel_config.internal_timer_cc = 0;   // if set to 0, TASK_SAMPLE must be triggered manually
    channel_config.start_on_end = true;     // seems to be a "restart" task a the end of sampling
    // todo get pins from dts
    nrfx_saadc_channel_t config = NRFX_SAADC_DEFAULT_CHANNEL_SE(NRF_SAADC_INPUT_AIN0, 0);
    config.channel_config.reference = NRF_SAADC_REFERENCE_VDD4;
    config.channel_config.gain = NRF_SAADC_GAIN1_4;

    err = nrfx_saadc_channel_config(&config);
    if(err != NRFX_SUCCESS){
        LOG_ERR("Failed to configure SAADC channel");
        return err;
    }

    err = nrfx_saadc_advanced_mode_set(0x01,
                                    NRF_SAADC_RESOLUTION_10BIT,
                                    &channel_config,
                                    adc_end_cb);
    if(err != NRFX_SUCCESS){
        LOG_ERR("Failed to set SAADC advanced mode");
        return err;
    }

    err = nrfx_saadc_buffer_set((nrf_saadc_value_t*)buffer, buffer_size);
    if(err != NRFX_SUCCESS){
        LOG_ERR("Failed to set SAADC buffer");
        return err;
    }


    // err = nrfx_saadc_mode_trigger();
    // if(err != NRFX_SUCCESS){
    //     LOG_ERR("Failed to trigger SAADC");
    //     return err;
    // }



    return 0;
}

Then I trigger the START task in software while preparing the timers etc

    nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_START);

The PPI channel is connected with the SAMPLE task
    err = nrfx_ppi_channel_assign(ppi_ch_adc_trigger,
        nrfx_timer_event_address_get(&timer, NRF_TIMER_EVENT_COMPARE4),
        nrf_saadc_task_address_get(NRF_SAADC, NRF_SAADC_TASK_SAMPLE));

Maybe I have some confusion about the TASK and SAMPLE tasks? I thought the START would "prepare" the ADC for sampling, and the SAMPLE actually triggers one sample. Is this assumption wrong? Maybe I'm also mixing APIs a bit but the nrfx does not seem to have a good way of doing this.

Thanks!
Parents Reply Children
No Data
Related