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

nRF52840 SAADC Hangs Waiting for End Event

Setup:

Device: nRF52840DK PCA10056

Software: NCS v1.3.99

What I am trying to do:

I have 3 SAADC sequences that I need to run for my application that I wish to poll periodically.

1. 1 input (single ended), 16x oversampling, 14bit

2. 1 input (single ended), 8x oversampling, 10bit

3.  3 inputs (2 single ended, 1 differential), no oversampling, 10bit

What is going wrong:

After running each sequence once, #3 from above hangs waiting for the END event, and sometimes the START event.

Code Isolating the Bug:

#include <zephyr.h>
#include <device.h>
#include <sys/printk.h>

#include <nrfx_saadc.h>
#include <hal/nrf_saadc.h>
#include <nrf52840.h>
#include <nrf52840_bitfields.h>

volatile int sampling = 0;
uint16_t buf0 = 0;
uint16_t buf1 = 0;
uint16_t buf2[3] = {0};


static void saadc_irq_handler(void *param)
{
	if (nrf_saadc_event_check(NRF_SAADC, NRF_SAADC_EVENT_END)) {
		nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_END);

		nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_STOP);
		nrf_saadc_disable(NRF_SAADC);
                
    sampling = 0;
	} 
        if (nrf_saadc_event_check(NRF_SAADC,
					 NRF_SAADC_EVENT_CALIBRATEDONE)) 
        {
		nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_CALIBRATEDONE);

		nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_STOP);
		nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_START);

	} 
        if (nrf_saadc_event_check(NRF_SAADC,
					 NRF_SAADC_EVENT_STARTED)) 
        {
          nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_STARTED);
          nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_SAMPLE);
        }
}


void setup_saadc()
{
  nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_END);
  nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_CALIBRATEDONE);
  nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_END);
	nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_CALIBRATEDONE);
	nrf_saadc_int_enable(NRF_SAADC,
			     NRF_SAADC_INT_END | NRF_SAADC_INT_CALIBRATEDONE | NRF_SAADC_INT_STARTED);
	NRFX_IRQ_ENABLE(SAADC_IRQn);

	IRQ_CONNECT(SAADC_IRQn, 1,
		    saadc_irq_handler, NULL, 0);
}


void config0()
{
  NRF_SAADC->OVERSAMPLE = NRF_SAADC_OVERSAMPLE_16X;
  NRF_SAADC->RESOLUTION = NRF_SAADC_RESOLUTION_14BIT;

  NRF_SAADC->CH[0].CONFIG =
            ((NRF_SAADC_RESISTOR_DISABLED   << SAADC_CH_CONFIG_RESP_Pos)   & SAADC_CH_CONFIG_RESP_Msk)
            | ((NRF_SAADC_RESISTOR_DISABLED << SAADC_CH_CONFIG_RESN_Pos)   & SAADC_CH_CONFIG_RESN_Msk)
            | ((NRF_SAADC_GAIN1_2           << SAADC_CH_CONFIG_GAIN_Pos)   & SAADC_CH_CONFIG_GAIN_Msk)
            | ((NRF_SAADC_REFERENCE_INTERNAL<< SAADC_CH_CONFIG_REFSEL_Pos) & SAADC_CH_CONFIG_REFSEL_Msk)
            | ((NRF_SAADC_ACQTIME_40US      << SAADC_CH_CONFIG_TACQ_Pos)   & SAADC_CH_CONFIG_TACQ_Msk)
            | ((NRF_SAADC_MODE_SINGLE_ENDED << SAADC_CH_CONFIG_MODE_Pos)   & SAADC_CH_CONFIG_MODE_Msk)
            | ((NRF_SAADC_BURST_ENABLED     << SAADC_CH_CONFIG_BURST_Pos)  & SAADC_CH_CONFIG_BURST_Msk);
  NRF_SAADC->CH[0].PSELP = NRF_SAADC_INPUT_AIN0;
  NRF_SAADC->CH[0].PSELN = NRF_SAADC_INPUT_DISABLED;

  NRF_SAADC->RESULT.MAXCNT = 1;
  NRF_SAADC->RESULT.PTR = (uint32_t)&buf0;
}


void config1()
{
  NRF_SAADC->OVERSAMPLE = NRF_SAADC_OVERSAMPLE_8X;
  NRF_SAADC->RESOLUTION = NRF_SAADC_RESOLUTION_10BIT;

  NRF_SAADC->CH[1].CONFIG =
            ((NRF_SAADC_RESISTOR_DISABLED   << SAADC_CH_CONFIG_RESP_Pos)   & SAADC_CH_CONFIG_RESP_Msk)
            | ((NRF_SAADC_RESISTOR_DISABLED << SAADC_CH_CONFIG_RESN_Pos)   & SAADC_CH_CONFIG_RESN_Msk)
            | ((NRF_SAADC_GAIN1_4           << SAADC_CH_CONFIG_GAIN_Pos)   & SAADC_CH_CONFIG_GAIN_Msk)
            | ((NRF_SAADC_REFERENCE_INTERNAL<< SAADC_CH_CONFIG_REFSEL_Pos) & SAADC_CH_CONFIG_REFSEL_Msk)
            | ((NRF_SAADC_ACQTIME_10US      << SAADC_CH_CONFIG_TACQ_Pos)   & SAADC_CH_CONFIG_TACQ_Msk)
            | ((NRF_SAADC_MODE_SINGLE_ENDED << SAADC_CH_CONFIG_MODE_Pos)   & SAADC_CH_CONFIG_MODE_Msk)
            | ((NRF_SAADC_BURST_ENABLED     << SAADC_CH_CONFIG_BURST_Pos)  & SAADC_CH_CONFIG_BURST_Msk);
  NRF_SAADC->CH[1].PSELP = NRF_SAADC_INPUT_AIN1;
  NRF_SAADC->CH[1].PSELN = NRF_SAADC_INPUT_DISABLED;

  NRF_SAADC->RESULT.MAXCNT = 1;
  NRF_SAADC->RESULT.PTR = (uint32_t)&buf1;
}


void config2()
{
  NRF_SAADC->OVERSAMPLE = NRF_SAADC_OVERSAMPLE_DISABLED;
  NRF_SAADC->RESOLUTION = NRF_SAADC_RESOLUTION_10BIT;

  NRF_SAADC->CH[2].CONFIG =
            ((NRF_SAADC_RESISTOR_DISABLED   << SAADC_CH_CONFIG_RESP_Pos)   & SAADC_CH_CONFIG_RESP_Msk)
            | ((NRF_SAADC_RESISTOR_DISABLED << SAADC_CH_CONFIG_RESN_Pos)   & SAADC_CH_CONFIG_RESN_Msk)
            | ((NRF_SAADC_GAIN1_6             << SAADC_CH_CONFIG_GAIN_Pos)   & SAADC_CH_CONFIG_GAIN_Msk)
            | ((NRF_SAADC_REFERENCE_INTERNAL<< SAADC_CH_CONFIG_REFSEL_Pos) & SAADC_CH_CONFIG_REFSEL_Msk)
            | ((NRF_SAADC_ACQTIME_40US      << SAADC_CH_CONFIG_TACQ_Pos)   & SAADC_CH_CONFIG_TACQ_Msk)
            | ((NRF_SAADC_MODE_SINGLE_ENDED << SAADC_CH_CONFIG_MODE_Pos)   & SAADC_CH_CONFIG_MODE_Msk)
            | ((NRF_SAADC_BURST_DISABLED     << SAADC_CH_CONFIG_BURST_Pos)  & SAADC_CH_CONFIG_BURST_Msk);
  NRF_SAADC->CH[2].PSELP = NRF_SAADC_INPUT_AIN2;
  NRF_SAADC->CH[2].PSELN = NRF_SAADC_INPUT_DISABLED;

  NRF_SAADC->CH[3].CONFIG =
            ((NRF_SAADC_RESISTOR_DISABLED   << SAADC_CH_CONFIG_RESP_Pos)   & SAADC_CH_CONFIG_RESP_Msk)
            | ((NRF_SAADC_RESISTOR_DISABLED << SAADC_CH_CONFIG_RESN_Pos)   & SAADC_CH_CONFIG_RESN_Msk)
            | ((NRF_SAADC_GAIN1_6             << SAADC_CH_CONFIG_GAIN_Pos)   & SAADC_CH_CONFIG_GAIN_Msk)
            | ((NRF_SAADC_REFERENCE_INTERNAL<< SAADC_CH_CONFIG_REFSEL_Pos) & SAADC_CH_CONFIG_REFSEL_Msk)
            | ((NRF_SAADC_ACQTIME_40US      << SAADC_CH_CONFIG_TACQ_Pos)   & SAADC_CH_CONFIG_TACQ_Msk)
            | ((NRF_SAADC_MODE_SINGLE_ENDED << SAADC_CH_CONFIG_MODE_Pos)   & SAADC_CH_CONFIG_MODE_Msk)
            | ((NRF_SAADC_BURST_DISABLED     << SAADC_CH_CONFIG_BURST_Pos)  & SAADC_CH_CONFIG_BURST_Msk);
  NRF_SAADC->CH[3].PSELP = NRF_SAADC_INPUT_AIN3;
  NRF_SAADC->CH[3].PSELN = NRF_SAADC_INPUT_DISABLED;

  NRF_SAADC->CH[4].CONFIG =
            ((NRF_SAADC_RESISTOR_DISABLED   << SAADC_CH_CONFIG_RESP_Pos)   & SAADC_CH_CONFIG_RESP_Msk)
            | ((NRF_SAADC_RESISTOR_DISABLED << SAADC_CH_CONFIG_RESN_Pos)   & SAADC_CH_CONFIG_RESN_Msk)
            | ((NRF_SAADC_GAIN1_6             << SAADC_CH_CONFIG_GAIN_Pos)   & SAADC_CH_CONFIG_GAIN_Msk)
            | ((NRF_SAADC_REFERENCE_INTERNAL<< SAADC_CH_CONFIG_REFSEL_Pos) & SAADC_CH_CONFIG_REFSEL_Msk)
            | ((NRF_SAADC_ACQTIME_40US      << SAADC_CH_CONFIG_TACQ_Pos)   & SAADC_CH_CONFIG_TACQ_Msk)
            | ((NRF_SAADC_MODE_DIFFERENTIAL << SAADC_CH_CONFIG_MODE_Pos)   & SAADC_CH_CONFIG_MODE_Msk)
            | ((NRF_SAADC_BURST_DISABLED     << SAADC_CH_CONFIG_BURST_Pos)  & SAADC_CH_CONFIG_BURST_Msk);
  NRF_SAADC->CH[4].PSELP = NRF_SAADC_INPUT_AIN4;
  NRF_SAADC->CH[4].PSELN = NRF_SAADC_INPUT_AIN5;

  NRF_SAADC->RESULT.MAXCNT = sizeof(buf2)/sizeof(buf2[0]);
  NRF_SAADC->RESULT.PTR = (uint32_t)buf2;
}


void clear_configs()
{
  for (int i = 0; i < 8; i++)
  {
    NRF_SAADC->CH[i].PSELP = NRF_SAADC_INPUT_DISABLED;
  }
}


void sample_saadc_blocking()
{
  sampling = 1;
  
  NRF_SAADC->ENABLE = 1;
  NRF_SAADC->TASKS_CALIBRATEOFFSET = 1;
  while (sampling)
  {
    k_sleep(K_MSEC(10));
  }
}


int main(void)
{
  printk("Begin Test\n");
  
  setup_saadc();

  for (int i = 0; ; i++)
  {
    printk("\ni = %d\n",i);
    
    clear_configs();
    config0();
    sample_saadc_blocking();
    printk("seq0\n");

    clear_configs();
    config1();
    sample_saadc_blocking();
    printk("seq1\n");

    clear_configs();
    config2();
    sample_saadc_blocking();
    printk("seq2\n");
  }
  return 0;
}

Console Output:

*** Booting Zephyr OS version 2.3.99  ***
Begin Test

i = 0
seq0
seq1
seq2

i = 1
seq0
seq1

Parents Reply Children
No Data
Related