Hello,
thank you for your help to solve my previous issue with resetting the RTC event ( nRF52832: problem with refreshing/clearing RTC for looping). I'm glad to move to the next problem with my task, which is triggering the SAADC sampling every time an RTC event occurs.
Description:
I would like to use RTC event COMPARE0 via PPI to trigger SAADC's sampling task. The SAADC sampling/conversion isn't continuous in a sense, since it shouldn't use internal clock, but is dependent on an external signal. The RTC would trigger an event on it's own refresh pace, and so the SAADC conversion isn't critically timing-bound (the sampling rate is roughly 3 Hz).
The RTC inititalization has been tested by connecting the COMPARE0 event to a GPIOTE toggle task. The result occurs as a PWM-type behaviour, which suggests that the RTC succesfully regenerates the COMPARE0 event.
mm_rtc.c (only the essential for this problem)
uint32_t mm_rtc_address_event_comp0(void) { return nrfx_rtc_event_address_get(&mm_rtc, NRF_RTC_EVENT_COMPARE_0); } uint32_t mm_rtc_address_task_clear(void) { return nrfx_rtc_task_address_get(&mm_rtc, NRF_RTC_TASK_CLEAR); }
mm_ppi.c
static nrf_ppi_channel_t mm_ppi_ch0; void ppi_init(void) { nrfx_ppi_channel_alloc(&mm_ppi_ch0); nrfx_ppi_channel_assign(mm_ppi_ch0, mm_rtc_address_event_comp0(), mm_saadc_address_task_sample()); nrfx_ppi_channel_fork_assign(mm_ppi_ch0, mm_rtc_address_task_clear()); nrfx_ppi_channel_enable(mm_ppi_ch0); }
To solve my problem I'm using a single SAADC channel and a result buffer array, which holds 2 samples. If I want to use external source to trigger the sampling, I should use the advanced mode. From the nrfx_saadc.h:
"*The advanced mode allows performing double-buffered conversions of arbitrary length.
* The conversions can be done in a blocking or non-blocking manner. When performing conversions
* in the non-blocking manner and @ref nrfx_saadc_adv_config_t.internal_timer_cc is set to 0,
* sampling needs to be done by triggering @ref NRF_SAADC_TASK_SAMPLE externally
* (for example by using the TIMER and/or the PPI/DPPI)."
mm_saadc.c
#define MM_SAADC_BUF_CNT 2 static nrf_saadc_value_t buffer[MM_SAADC_BUF_CNT]; static nrfx_saadc_channel_t channels[1] = { NRFX_SAADC_DEFAULT_CHANNEL_SE(NRF_SAADC_INPUT_AIN0, 0), //NRFX_SAADC_DEFAULT_CHANNEL_SE(NRF_SAADC_INPUT_AIN1, 1), }; static nrfx_saadc_adv_config_t p_config = NRFX_SAADC_DEFAULT_ADV_CONFIG; uint32_t mm_saadc_address_task_sample() { return nrf_saadc_task_address_get(NRF_SAADC, NRF_SAADC_TASK_SAMPLE); } uint32_t mm_saadc_address_event_done() { return nrf_saadc_event_address_get(NRF_SAADC, NRF_SAADC_EVENT_END); } static uint8_t next_free_buf_index(void) { static uint8_t buffer_index = -1; buffer_index = (buffer_index + 1) % MM_SAADC_BUF_CNT; return buffer_index; } static void event_handler(nrfx_saadc_evt_t const * p_event) { nrfx_err_t err; switch (p_event->type) { case NRFX_SAADC_EVT_DONE: LOG_INF("-------------> NRFX_SAADC_EVT_DONE"); for (int i = 0; i < p_event->data.done.size; i++) { LOG_INF("CH%d: %d", i, p_event->data.done.p_buffer[i]); } break; case NRFX_SAADC_EVT_BUF_REQ: LOG_INF("NRFX_SAADC_EVT_BUF_REQ"); err = nrfx_saadc_buffer_set(&buffer[next_free_buf_index()], 1); LOG_INF("nrfx_saadc_buffer_set err: %x", err); break; default: LOG_INF("default: event type %x", p_event->type); break; } } int mm_saadc_init(void) { nrfx_err_t err; IRQ_CONNECT(DT_IRQN(DT_NODELABEL(adc)), DT_IRQ(DT_NODELABEL(adc), priority), nrfx_isr, nrfx_saadc_irq_handler, 0); err = nrfx_saadc_init(NRFX_SAADC_DEFAULT_CONFIG_IRQ_PRIORITY); err = nrfx_saadc_channels_config(channels, 1); err = nrfx_saadc_advanced_mode_set(BIT(0), NRF_SAADC_RESOLUTION_12BIT, &p_config, event_handler); err = nrfx_saadc_buffer_set(&buffer[next_free_buf_index()], 1); err = nrfx_saadc_mode_trigger(); return NRFX_SUCCESS; }
The problem:
The SAADC eventually reaches the case NRFX_SAADC_EVT_DONE once, prints out the buffer values, and stops there; so called one-shot. Since the RTC event re-triggering has been proven, I believe the problem lies within the SAADC module. I'm not 100% sure what I'm missing, but I think it might have something to do with the result buffer. While searching for any help on this forum, I came across with a function that does not exist in my version:
nrf_drv_saadc_buffer_convert()
Does this have something to do with my problem?
Another thought I had was that maybe I should reset/clear some of the SAADC registers?
Essentially, how do I get the SAADC to provide a converted result every time an RTC event is triggered? I don't want to use SAADC's internal timers, refresh rates or what-have-yous.
Thank you.