Hi I am using nRF connect 2.3.0 with VS Code on Windows 11. My board is a Custom board with nRF52832 QFAA.
I am trying to find a working example of PPI with SAADC collection. I found this and it has A LOT of what I want but doesnt actually work. There are several issues with it including the fact that it isnt using NRF Connect 2.x.x.
This is my sample code:
#include <inttypes.h> #include <stddef.h> #include <stdint.h> #include <errno.h> #include <time.h> #include <zephyr/kernel.h> #include <zephyr/logging/log.h> #include <nrfx_saadc.h> #include <nrfx_ppi.h> #include <nrfx_timer.h> #include <drivers/nrfx_errors.h> #include <zephyr/drivers/gpio.h> //This is set so battery power can be down to mins and still work #define NRF_POWER_HAS_POFCON 0 #define LOG_MODULE_NAME drone_controller_main LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_DBG); #if !DT_NODE_EXISTS(DT_PATH(zephyr_user)) || \ !DT_NODE_HAS_PROP(DT_PATH(zephyr_user), io_channels) #error "No suitable devicetree overlay specified" #endif //SAADC Defines // define the number of SAADC channels and parameters #define SAADC_CHANNELS_IN_USE 4 #define SAADC_SAMPLE_INTERVAL_MS 100 #define SAADC_RESOLUTION NRF_SAADC_RESOLUTION_10BIT #define SAADC_OVERSAMPLE NRF_SAADC_OVERSAMPLE_DISABLED //define the buttons #define SW0 DT_ALIAS(sw0) #define SW1 DT_ALIAS(sw1) #define SW2 DT_ALIAS(sw2) #define SW3 DT_ALIAS(sw3) #define SW4 DT_ALIAS(sw4) #define SW5 DT_ALIAS(sw5) #define SW6 DT_ALIAS(sw6) #define SW7 DT_ALIAS(sw7) #define SW8 DT_ALIAS(sw8) //Devicetree node for the var resistor power #define PWRR_NODE DT_ALIAS(pwrr) #define PWRL_NODE DT_ALIAS(pwrl) //Power the joysticks #define PWRR DT_ALIAS(pwrr) #define PWRL DT_ALIAS(pwrl) //setup the LED's #define LED0_R DT_ALIAS(led0) #define LED3_G DT_ALIAS(led3) #define LED4_B DT_ALIAS(led4) //Timer settings #define TIMER_INTERVAL_MS 1000 #define NRFX_SAADC_CHANNEL_COUNT 4 #define SAADC_BUF_SIZE NRFX_SAADC_CHANNEL_COUNT #define SAADC_BUF_COUNT 2 static nrfx_timer_t timer1 = NRFX_TIMER_INSTANCE(1); //timer instance static nrf_saadc_value_t samples[SAADC_BUF_COUNT][SAADC_BUF_SIZE]; //sample buffer static nrf_ppi_channel_t m_timer_saadc_ppi_channel; //timer to ppi channel static const uint32_t saadc_sampling_rate = 250; // milliseconds (ms) static const nrf_saadc_input_t ANALOG_INPUT_MAP[NRFX_SAADC_CHANNEL_COUNT] = {NRF_SAADC_INPUT_AIN0, NRF_SAADC_INPUT_AIN1, NRF_SAADC_INPUT_AIN4, NRF_SAADC_INPUT_AIN5}; static void timer_event_handler(nrf_timer_event_t event_type, void *p_context) { printk("Event"); } // Simple function to provide an index to the next input buffer // Will simply alernate between 0 and 1 when SAADC_BUF_COUNT is 2 static uint32_t next_free_buf_index(void) { static uint32_t buffer_index = -1; buffer_index = (buffer_index + 1) % SAADC_BUF_COUNT; return buffer_index; } static void ppi_init(void) { nrfx_err_t err; // Trigger task sample from timer err = nrfx_ppi_channel_alloc(&m_timer_saadc_ppi_channel); if(err==NRFX_SUCCESS) LOG_DBG("ppi alloc success"); err = nrfx_ppi_channel_assign(m_timer_saadc_ppi_channel, nrfx_timer_event_address_get(&timer1, NRF_TIMER_EVENT_COMPARE0), nrf_saadc_task_address_get(NRF_SAADC,NRF_SAADC_TASK_SAMPLE)); err = nrfx_ppi_channel_enable(m_timer_saadc_ppi_channel); if(err==NRFX_SUCCESS) LOG_DBG("PPI enable ok"); } static void timer_init(void) { nrfx_timer_config_t timer_cfg = NRFX_TIMER_DEFAULT_CONFIG; timer_cfg.frequency = NRF_TIMER_FREQ_31250Hz; nrfx_timer_init(&timer1, &timer_cfg, timer_event_handler); nrfx_timer_extended_compare(&timer1,NRF_TIMER_CC_CHANNEL0,nrfx_timer_ms_to_ticks(&timer1, saadc_sampling_rate),NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,false); nrfx_timer_resume(&timer1); } /* * Function: saadc_handler * Description: This handler is called when there is SAADC data available * when the data is processed, saadc is re-enabled for more data. * Data is sent to the calibrate routine until the drone is ready * then the data is formatted for the joystick. */ static void saadc_handler(nrfx_saadc_evt_t const * p_event) { uint16_t samples_number; uint16_t flydata[4]; nrfx_err_t err; switch (p_event->type) { case NRFX_SAADC_EVT_DONE: samples_number = p_event->data.done.size; for (uint16_t i = 0; i < samples_number; i++) { LOG_DBG("SAADC_Value: Channel[%d] - %d",i,p_event->data.done.p_buffer[i]); //flydata[i]=p_event->data.done.p_buffer[i]; } break; case NRFX_SAADC_EVT_BUF_REQ: err = nrfx_saadc_buffer_set(&samples[next_free_buf_index()][0], SAADC_BUF_SIZE); break; default: LOG_DBG("SAADC evt %d", p_event->type); break; } } static void saadc_configure(void) { nrfx_err_t err; uint8_t channel_mask = 0; static nrfx_saadc_channel_t channel_configs[NRFX_SAADC_CHANNEL_COUNT]; nrfx_saadc_adv_config_t saadc_adv_config = NRFX_SAADC_DEFAULT_ADV_CONFIG; //Update the timer and start for the adv config saadc_adv_config.internal_timer_cc = 0; saadc_adv_config.start_on_end = true; err = nrfx_saadc_init(NRFX_SAADC_DEFAULT_CONFIG_IRQ_PRIORITY); if(err!=NRFX_SUCCESS) LOG_INF("Error: SAADC init failed"); for(int i=0;i<NRFX_SAADC_CHANNEL_COUNT;i++) { nrf_saadc_input_t pin = ANALOG_INPUT_MAP[i]; nrfx_saadc_channel_t config = NRFX_SAADC_DEFAULT_CHANNEL_SE(pin, i); // Replace some parameters in default config config.channel_config.reference = NRF_SAADC_REFERENCE_INTERNAL; config.channel_config.gain = NRF_SAADC_GAIN1_4; // Copy to list of channel configs memcpy(&channel_configs[i], &config, sizeof(config)); // Update channel mask channel_mask |= 1 << i; } err = nrfx_saadc_channels_config(channel_configs, NRFX_SAADC_CHANNEL_COUNT); err = nrfx_saadc_advanced_mode_set(channel_mask, NRF_SAADC_RESOLUTION_10BIT, &saadc_adv_config, saadc_handler); // Configure two buffers to ensure double buffering of samples, to avoid data loss when the sampling frequency is high err = nrfx_saadc_buffer_set(&samples[next_free_buf_index()][0], SAADC_BUF_SIZE); err = nrfx_saadc_mode_trigger(); } void main(void) { printk("Hello World! %s\n", CONFIG_BOARD); LOG_DBG("LOG DBG test"); timer_init(); ppi_init(); saadc_configure(); while(1) { __WFE(); } }
This is the conf file:
#required for the custom board CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=n CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y #memory settings CONFIG_HEAP_MEM_POOL_SIZE=16384 CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2304 CONFIG_MAIN_STACK_SIZE=2048 #Thread settings CONFIG_THREAD_NAME=y CONFIG_THREAD_MONITOR=y #GPIO and ADC settings CONFIG_GPIO=y CONFIG_NRFX_SAADC=y CONFIG_NRFX_PPI=y CONFIG_NRFX_TIMER1=y #Enable statistics (MCU ADDED) CONFIG_STATS=y CONFIG_STATS_NAMES=y #MCU Manager CONFIG_MCUMGR=y CONFIG_MCUMGR_CMD_IMG_MGMT=y CONFIG_MCUMGR_CMD_OS_MGMT=y CONFIG_BOOTLOADER_MCUBOOT=y # Support for taskstat command CONFIG_OS_MGMT_TASKSTAT=y #Logging CONFIG_CONSOLE=y CONFIG_LOG_BACKEND_RTT=y CONFIG_LOG_DEFAULT_LEVEL=4 CONFIG_USE_SEGGER_RTT=y CONFIG_RTT_CONSOLE=y CONFIG_PRINTK=y CONFIG_LOG_PRINTK=y CONFIG_CBPRINTF_FP_SUPPORT=y CONFIG_LOG=y CONFIG_LOG_MODE_IMMEDIATE=y
My problem is that NO sample is ever printed in the event handler and it is not even called. What happens when I run it without stepping through is a fault:
[00:00:00.002,532] <err> os: >>> ZEPHYR FATAL ERROR 1: Unhandled interrupt on CPU 0
[00:00:00.003,112] <err> os: Current thread: 0x20000368 (main)
[00:00:00.008,575] <err> fatal_error: Resetting system
I am very new to this and am trying to get samples first. Please let me know if you see anything I missed or more likely didn't configure correctly. If there is a PPI SAADC example somewhere I could look at that would help. I have looked at the PPI Trace example and it doesn't seem to apply.
Thanks