I am working on an application where I am using 3 SAADC channels all with the same reference pin.
Upon startup, I will call app_sensor_init() to initialize my SAADC, timer and PPI to measure at 80Hz over 6.4s.
#define SAMPLING_RATE_US (12500) // 80Hz = 1e6/80 = 12500us #define MAX_SAMPLE_COUNT (512) // duration = 6.4 seconds @ 80Hz -- 80 * 6.4 = 512 #define SAADC_PRIMARY_DATA_BUFFER_IDX (0) #define SAADC_SECONDARY_DATA_BUFFER_IDX (1) #define SAADC_DATA_BUFFER_NB (2) // allows 2 buffers, one for data and one for backup // The size of the data buffer dictates when a SAADC DONE task is raised given the frequency of the clock #define SAADC_DATA_BUFFER_SIZE (MAX_SAMPLE_COUNT * SENSOR_SAADC_CHANNEL_MAX) static nrf_saadc_value_t saadc_data_buffer[SAADC_DATA_BUFFER_NB][SAADC_DATA_BUFFER_SIZE] = { 0 }; void app_sensor_init(nrf_drv_saadc_event_handler_t saadc_handler) { NRF_LOG_INFO("%s()", __func__); ret_code_t ret = NRF_SUCCESS; /// Initialize signal handler errno_t err = sys_signal_module_init(SIGNAL_MOD_SENSOR, app_sensor_signal_handler); APP_ERROR_CHECK_BOOL(ERR_NONE == err); // Optional parameter for testing nrf_drv_saadc_event_handler_t handler = saadc_event_handler; if (saadc_handler != NULL) { handler = saadc_handler; } /// Initialize SAADC peripheral const nrf_drv_saadc_config_t saadc_config = { .resolution = NRF_SAADC_RESOLUTION_12BIT, // Resolution configuration. .oversample = NRF_SAADC_OVERSAMPLE_DISABLED, // Oversampling configuration. .interrupt_priority = SAADC_IRQ_PRIORITY, // Interrupt priority. .low_power_mode = true // Indicates if low power mode is active. }; ret = nrf_drv_saadc_init(&saadc_config, handler); APP_ERROR_CHECK(ret); /// Enable SAADC channels for (sensor_saadc_channel_e ch = (sensor_saadc_channel_e)0; ch < SENSOR_SAADC_CHANNEL_MAX; ch++) { ret = nrf_drv_saadc_channel_init(ch, &channel_configs[ch]); APP_ERROR_CHECK(ret); } /// Configure SAADC EasyDMA buffers ret = nrf_drv_saadc_buffer_convert(saadc_data_buffer[SAADC_PRIMARY_DATA_BUFFER_IDX], SAADC_DATA_BUFFER_SIZE); APP_ERROR_CHECK(ret); ret = nrf_drv_saadc_buffer_convert(saadc_data_buffer[SAADC_SECONDARY_DATA_BUFFER_IDX], SAADC_DATA_BUFFER_SIZE); APP_ERROR_CHECK(ret); /// Initialize PPI peripheral ret = nrf_drv_ppi_init(); APP_ERROR_CHECK(ret); /// Initialize sampling timer nrf_drv_timer_config_t timer_config = { .frequency = NRF_TIMER_FREQ_500kHz, // Frequency. .mode = NRF_TIMER_MODE_TIMER, // Mode of operation. .bit_width = NRF_TIMER_BIT_WIDTH_32, // Bit width. .interrupt_priority = SAMPLING_TIMER_IRQ_PRIORITY, // Interrupt priority. .p_context = NULL // Context passed to interrupt handler. }; // nrf_drv_timer_config_t timer_config = NRF_DRV_TIMER_DEFAULT_CONFIG; ret = nrf_drv_timer_init(&sampling_timer_id, &timer_config, sampling_timer_event_handler); APP_ERROR_CHECK(ret); /// Configure sampling timer's rate nrf_drv_timer_extended_compare( &sampling_timer_id, NRF_TIMER_CC_CHANNEL0, nrf_drv_timer_us_to_ticks(&sampling_timer_id, SAMPLING_RATE_US), // shortcut between the compare event on the channel and the timer task (STOP or CLEAR). NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, // leave interrupt disabled to connect with PPI false); /// Configure PPI channel so timer compare event is triggering sample task in SAADC const uint32_t sampling_timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&sampling_timer_id, NRF_TIMER_CC_CHANNEL0); uint32_t saadc_sample_task_addr = nrf_drv_saadc_sample_task_get(); ret = nrf_drv_ppi_channel_alloc(&sampling_ppi_channel); APP_ERROR_CHECK(ret); ret = nrf_drv_ppi_channel_assign(sampling_ppi_channel, sampling_timer_compare_event_addr, saadc_sample_task_addr); APP_ERROR_CHECK(ret); }
This doesn't start sampling, rather I have a BLE command that I use to trigger sampling via:
/// Reset sampling timer nrf_drv_timer_clear(&sampling_timer_id); /// Start/enable sampling timer nrf_drv_timer_enable(&sampling_timer_id); /// Enable sampling PPI events ret = nrf_drv_ppi_channel_enable(sampling_ppi_channel); // All error codes bad if (NRF_SUCCESS != ret) { NRF_LOG_ERROR("%s(): Failed to enable sampling PPI channel! Error 0x%02X", __func__, ret); }
What I expect is upon the DONE task in the saadc_interrupt_handler, my saadc_data_buffer will have filled up indicating my measurement sequence is complete. In testing this, my thoughts are correct WHEN AND ONLY WHEN I am attached with my debugger. However, when I do not have a debugger attached, I'm not observing my RTT output from the saadc_interrupt_handler which also sends a stop signal to stop my PPI and timer from sampling the SAADC.
Why is this only working when I have my debugger attached? I'm thinking it might have something to do with the IDLE state when no activity is occurring on BLE? My project originally was based off ble_app_template example if that means anything.
Any thoughts would be appreciated!