nrfx_timer and nrfx_saadc #defines-> undefined variable issue nrf connect sdk

Hi Team,

I've recently transitioned from using Texas Instruments modules to Nordic modules for its low energy, specifically the NRF52832 DK with the NRF Connect SDK. Therefore, I am novice in zephyr environment.

I am in the process of developing a sensor which could send 400 samples per second via Bluetooth hence the ADC must process 400 samples every second without any CPU intervention.

After days of exploring I understood that I need to use PPI and timers to enable the ADC to work autonomously. However, I struggled to find relevant documentation or examples specifically tailored for the NRF Connect SDK.  Eventually I found this https://github.com/haakonsh/NCS_SAADC_example/tree/master which incorporated nrfx_saadc, nrfx_ppi and nrfx_timer to employ ADC autonomously.

When I attempted to use the provided code in my Visual Studio Code environment, I encountered numerous errors related to undefined identifiers for the nrfx_saadc and nrfx_timer headers. Additionally, several other headers required by the SAADC and timer modules themselves also resulted in undefined errors.

Below is the main.c

/*
 * Copyright (c) 2019 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/kernel.h>
#include <nrfx_ppi.h>
#include "nrfx_saadc.h"
#include <nrfx_timer.h>
#include <hal/nrf_timer.h>
#include <helpers/nrfx_gppi.h>
#include <zephyr/logging/log.h>
#define __ZEPHYR__ 1
LOG_MODULE_REGISTER(nrfx_sample, LOG_LEVEL_INF);

#define SAADC_CHANNEL_NUM 	0
#define SAMPLES_IN_BUFFER 	8
#define SAMPLE_RATE 		10000UL
#define TIMER1_INST_IDX 1
int16_t saadc_buf1[SAMPLES_IN_BUFFER];
int16_t saadc_buf2[SAMPLES_IN_BUFFER];

const nrfx_timer_t timer1_inst = NRFX_TIMER_INSTANCE(TIMER1_INST_IDX); //ERROR identifier "NRFX_TIMER1_INST_IDX" is undefined


void saadc_evt_handler(nrfx_saadc_evt_t const * p_event)
{
	nrfx_err_t err = NRFX_SUCCESS;
	static uint8_t counter = 0;

	if(p_event->type == NRFX_SAADC_EVT_DONE)
	{		
		printk("SAADC sampled: \n");
		for(uint8_t i = 0; i < p_event->data.done.size; i++)
		{
			printk("%hi\n", p_event->data.done.p_buffer[i]);
		}
	}
	else if(p_event->type == NRFX_SAADC_EVT_CALIBRATEDONE)
	{
		printk("SAADC calibrated.\n");
	}
	else if(p_event->type == NRFX_SAADC_EVT_BUF_REQ)
	{
		printk("SAADC buffer requested\n");
		counter++;

		if(counter%2)
		{
			err = nrfx_saadc_buffer_set(saadc_buf1, SAMPLES_IN_BUFFER);
			if(err != NRFX_SUCCESS)
			{
				LOG_ERR("Error! Could not set buffer2: %d\n", err);
			}
		}
		else
		{
			err = nrfx_saadc_buffer_set(saadc_buf2, SAMPLES_IN_BUFFER);
			if(err != NRFX_SUCCESS)
			{
				LOG_ERR("Error! Could not set buffer1: %d\n", err);
			}
		}
		
	}
	else if(p_event->type == NRFX_SAADC_EVT_FINISHED)
	{
		printk("SAADC finished sampling\n\n");
	}
}

void timer1_evt_handler(nrf_timer_event_t event_type, void * p_context)
{
	// Nothing to do here, the timer's IRQ is not enabled
}

void timer_init(void)
{
	nrfx_err_t err = NRFX_SUCCESS;
	uint32_t base_frequency = NRF_TIMER_BASE_FREQUENCY_GET(timer1_inst.p_reg);
	nrfx_timer_config_t timer_cfg = NRFX_TIMER_DEFAULT_CONFIG(base_frequency); //ERROR identifier "NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY" is undefined
	timer_cfg.bit_width = (nrf_timer_bit_width_t)NRF_TIMER_BIT_WIDTH_32;
    timer_cfg.mode = NRF_TIMER_MODE_TIMER;
    timer_cfg.p_context = &timer1_inst;
	err = nrfx_timer_init(&timer1_inst, &timer_cfg, timer1_evt_handler);
	// #if defined(__ZEPHYR__)
    // IRQ_DIRECT_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_TIMER_INST_GET(TIMER1_INST_IDX)), IRQ_PRIO_LOWEST,
    // NRFX_TIMER_INST_HANDLER_GET(TIMER1_INST_IDX), 0);
    // #endif
	if(err != NRFX_SUCCESS)
	{
		LOG_ERR("Error! Could not initialize TIMER1: %d\n", err);
	}

	nrfx_timer_extended_compare(&timer1_inst, NRF_TIMER_CC_CHANNEL0, SAMPLE_RATE, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, false);	
}


void saadc_init(void)
{
	nrfx_err_t err = NRFX_SUCCESS;
	nrfx_saadc_channel_t saadc_channel = NRFX_SAADC_DEFAULT_CHANNEL_SE(NRF_SAADC_INPUT_AIN0, SAADC_CHANNEL_NUM); //ERROR identifier "NRF_SAADC_REFERENCE_INTERNAL" is undefined
	nrfx_saadc_adv_config_t saadc_adv_cfg = NRFX_SAADC_DEFAULT_ADV_CONFIG;
	saadc_adv_cfg.start_on_end = true;
	
	err = nrfx_saadc_init(IRQ_PRIO_LOWEST); //ERROR identifier "IRQ_PRIO_LOWEST" is undefined
	if(err != NRFX_SUCCESS)
	{
		LOG_ERR("Error! Could not initialize SAADC: %d\n", err);
	}

	err = nrfx_saadc_offset_calibrate(NULL);
	if(err != NRFX_SUCCESS)
	{
		LOG_ERR("Error! Could not calibrate offset: %d\n", err);
	}

	err = nrfx_saadc_channel_config(&saadc_channel);
	if(err != NRFX_SUCCESS)
	{
		LOG_ERR("Error! Could not configure SAADC channels: %d\n", err);
	}	

	err = nrfx_saadc_advanced_mode_set((1 << SAADC_CHANNEL_NUM), NRF_SAADC_RESOLUTION_10BIT, &saadc_adv_cfg, saadc_evt_handler);
	if(err != NRFX_SUCCESS)
	{
		LOG_ERR("Error! Could not set advanced SAADC mode: %d\n", err);
	}

	err = nrfx_saadc_buffer_set(saadc_buf1, SAMPLES_IN_BUFFER);
	if(err != NRFX_SUCCESS)
	{
		LOG_ERR("Error! Could not set buffer1: %d\n", err);
	}

	err = nrfx_saadc_buffer_set(saadc_buf2, SAMPLES_IN_BUFFER);
	if(err != NRFX_SUCCESS)
	{
		LOG_ERR("Error! Could not set buffer2: %d\n", err);
	}

	err = nrfx_saadc_mode_trigger();
	if(err != NRFX_SUCCESS)
	{
		LOG_ERR("Error! Could trigger mode: %d\n", err);
	}	
}

int main()
{
	printk("nrfx_saadc sample on %s\n", CONFIG_BOARD); //ERROR printk identifier undefined - surprisingly printk other than main() has no error

	nrfx_err_t err;

	/* Connect SAADC IRQ to nrfx_saadc_irq_handler */
	IRQ_CONNECT(SAADC_IRQn, IRQ_PRIO_LOWEST, nrfx_isr, nrfx_saadc_irq_handler, 0); //ERROR IRQ_PRIO_LOWEST, nrfx_isr identifier undefined

	timer_init();
	saadc_init();

	/* Allocate a PPI channel. */
	nrf_ppi_channel_t channel;
	err = nrfx_ppi_channel_alloc(&channel);

	if (err != NRFX_SUCCESS) {
		LOG_ERR("PPI channel allocation error: %08x", err);
		return -1;
	}

	/* Configure endpoints of the channel so that the TIMER1 CAPTURE0
	 * event is connected with the SAADC SAMPLE task. This means that each time
	 * TIMER1 reaches it's set compare value, the SAADC will sample all 
	 * enabled channel once.
	 */
	nrfx_gppi_channel_endpoints_setup(channel,
		nrfx_timer_event_address_get(&timer1_inst, NRF_TIMER_EVENT_COMPARE0),
		nrf_saadc_task_address_get(NRF_SAADC, NRF_SAADC_TASK_SAMPLE));


	err = nrfx_ppi_channel_enable(channel);

	if (err != NRFX_SUCCESS) {
		LOG_ERR("Failed to enable PPI channel, error: %08x", err);
		return -1;
	}
	printk("PPI configured\n");

	nrfx_timer_enable(&timer1_inst);
	printk("TIMER1 started\n");

	while(1)
	{
		
	}
}

Below is the Kconfig

# Copyright (c) 2021 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0
config NRFX_DPPI
	default HAS_HW_NRF_DPPIC

config NRFX_PPI
	default HAS_HW_NRF_PPI


config NRFX_SAADC
    bool "Enable SAADC driver"
    depends on HAS_HW_NRF_SAADC && HAS_NRFX

config NRFX_TIMER
	bool "Enable TIMER driver"
	depends on HAS_HW_NRF_TIMER0 || HAS_HW_NRF_TIMER1 || \
		   HAS_HW_NRF_TIMER2 || HAS_HW_NRF_TIMER3 || \
		   HAS_HW_NRF_TIMER4

config NRFX_TIMER1
	bool "Enable TIMER1 instance"
	depends on HAS_HW_NRF_TIMER1
	select NRFX_TIMER


source "Kconfig.zephyr"

Below is the prj.conf

CONFIG_LOG=y
CONFIG_LOG_PROCESS_THREAD_SLEEP_MS=100
CONFIG_LOG_DEFAULT_LEVEL=4

CONFIG_ASSERT=y
CONFIG_RESET_ON_FATAL_ERROR=n

CONFIG_ADC=n
CONFIG_NRFX_SAADC=y

CONFIG_NRFX_TIMER1=y
CONFIG_PICOLIBC=y

Below is the CMakeLists.txt

# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(adcgit)

target_sources(app PRIVATE src/main.c)
target_include_directories(app PRIVATE ../../../common)

I haven't configured the timing for 400 samples here as I couldn't figure out these errors.

I referred to almost all the Nordic forums and tried everything with no success. Kindly guide me in resolving this issue ASAP. I appreciate any help provided in this regard. 

  • Hello,

    I copied and pasted your code from main.c into the main.c file of the 'hello_world' sample, and added the following Kconfig settings to prj.conf:

    CONFIG_NRFX_TIMER1=y
    CONFIG_NRFX_SAADC=y
    CONFIG_NRFX_PPI=y
    

    After doing this, the code compiled without errors. Could you please try the same? I used SDK v2.5.2 and built for the 'nrf52840dk_nrf52840' board.

    Best regards,

    Vidar

  • Hi Vidar,

    Thank you for the help, I was able to build and flash the code without any errors in the console however squiggles in the vscode did not disappear hopefully some intellisense issue. Anyhow when I connect to the serial port I do not see any messages or output printed in the console. 

    Any idea or help on why there is no output in the console of serial port? Even the main() --> printk is not outputted in the serial port. Kindly feel free to advise if I am missing something as I am still learning this environment.

    Regards

    Srinidhi Sasidharan

  • Hi Srinidhi,

    Relevant warnings and errors will be displayed in the build output. Any other warnings reported by intellisense can be safely ignored. Regarding the missing log output, are you using the DK? And, have you successfully received console output from other examples with your setup? I did not experience any logging problems when I ran the code on my end.

    Hex file from my build if you want to test it:

    0081.zephyr.hex

  • Thanks for the hex file Vidar, however even after flashing the hex file I couldn't see any log outputs. I tried the sample blinky application and I am able to see the log output(VCOM0). I even tried adc from zephyr drivers and I successfully received the log outputs. 

    Only the current application is having these issues. If you are able to log output then am I missing something? I used serial terminal from vscode as well as the nrf connect desktop tool to test the logging.

    I tried most ways possible, kindly guide me to resolve this issue. 

  • Apologies, I was testing with the nRF52840 DK, which explains why my .hex file would not run on your 52832 board. Are you using the nRF52 DK? 

    SAADC sample built for nrf52dk_nrf52832

    3750.zephyr.hex

    Programming the hex with nrfjprog 

    $ nrfjprog --program zephyr.hex --chiperase --verify --reset
    
    

    Project

    8540.nrfx_saadc.zip

Related