PPI delay due to interrupt disable.

Hello,
I implemented the function to receive an external 62.5KHz clock as an interrupt and repeat the process at a very regular time using PPI.
However, sometimes PPI processing is delayed(No interrupt received) as shown in the following figure. What could be the reason for this?


I guess the ability to receive an external 62.5KHz as an interrupt is delayed because of the interrupt inhibition of the MCU.
Is there a way to solve this interrupt receive delay and PPI delay?

Best Regards,

SunBae Yim.

Parents
  • Hello SunBae Yim,

    It looks to me like your PPI might not be set up correctly. Could you share the section of your code in which this takes place?
    When PPI is set up correctly you will not need the CPU to handle any interrupts, in order for the connected TASK to be triggered by the generated EVENT.
    Therefore, there should be no delay on the triggering of the TASK as well, since it will happen as soon as the connected EVENT is generated.

    Are you using the nRF5 SDK, and if so, are also using the SoftDevice in your project?

    Best regards,
    Karl

  • My source code is here;

    /*******************************************************************************
     * @file	
     * @author	
     * @version	V1.0.0
     * @date	2022-09-05
     * @brief   
     ******************************************************************************/
    
    #include "sdk_common.h"
    			
    #include <stdbool.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <string.h>
    #include "nrf.h"
    #include "boards.h"
    #include "app_error.h"
    #include "nrf_drv_saadc.h"
    #include "nrfx_gpiote.h"
    #include "app_timer.h"
    #include "nrf_drv_timer.h"
    #include "nrf_delay.h"
    #include "nrf_drv_ppi.h"
    #include "ada2200_spi.h"
    #include "ble_nus.h"
    #include "fstorage.h"
    #include "measurements.h"
    #include "meas_pd_voltage_full.h"
    #include "mcp4725_i2c.h"
    #include "ad5272_i2c.h"
    #include "main_timer.h"
    #include "battery_saadc.h"
    #include "main.h"
    
    #define FULL_REF_VOLTAGE_IN_MILLIVOLTS   	600.0f                                     /**< Reference voltage (in milli volts) used by ADC while doing conversion. */
    #define FULL_PRE_SCALING_COMPENSATION    	6.0f                                       /**< The ADC is configured to use VDD with 1/3 prescaling as input. And hence the result of conversion is to be multiplied by 3 to get the actual value of the battery voltage.*/
    #define FULL_ADC_RES_10BITS             	1024.0f                                    /**< Maximum digital value for 10-bit ADC conversion. */
    
    /**@brief Macro to convert the result of ADC conversion in millivolts.
     *
     * @param[in]  ADC_VALUE   ADC result.
     *
     * @retval     Result converted to millivolts.
     */
    #define FULL_VOUT_IN_MILLI_VOLTS(ADC_VALUE)\
    				((((ADC_VALUE) * FULL_REF_VOLTAGE_IN_MILLIVOLTS) / FULL_ADC_RES_10BITS) * FULL_PRE_SCALING_COMPENSATION)
    
    #define FULL_SAMPLES_IN_BUFFER 		1
    static nrf_saadc_value_t pd_full_adc_buf[2][FULL_SAMPLES_IN_BUFFER];
    bool  pd_adc_full_start	= false;
    
    
    uint8_t led_full_list[6];
    uint8_t pd_full_list[12];
    
    uint8_t led_full_list_a[6]	= {1,2,3,4,5,6};
    uint8_t pd_full_list_a[12]	= {5,6,7,8,9,10,15,16,17,18,19,20};
    
    uint8_t led_full_list_b[6]	= {7,8,9,10,11,12};
    uint8_t pd_full_list_b[12]	= {6,5,4,3,2,1,16,15,14,13,12,11};
    
    uint8_t led_full_list_c[6]	= {13,14,15,16,17,18};
    uint8_t pd_full_list_c[12]	= {15,16,17,18,19,20,5,6,7,8,9,10};
    
    uint8_t led_full_list_d[6]	= {19,20,21,22,23,24};
    uint8_t pd_full_list_d[12]	= {16,15,14,13,12,11,6,5,4,3,2,1};
    
    
    static uint16_t FULL_DELAY_CLK = 0;
    static bool full_main_delay = false;
    static bool full_main_testing = false;
    #define full_main_clock_delay(delay_cnt) 	full_main_delay = true;\
    										full_main_testing = false;\
    										FULL_DELAY_CLK = delay_cnt;
    
    #define FULL_CYCLE_CNT 			32	/* Dummy=16, Cycle_Max_Cnt=32*/
    /* ----------------  +  --------                         */
    /*       Dummy 16       Cycle = 8                        */
    /*                                                       */
    /* ----------------  +  ----------------                 */
    /*       Dummy 16       Cycle = 16                       */
    /*                                                       */
    /* ----------------  +  ------------------------         */
    /*       Dummy 16       Cycle = 24                       */
    /*                                                       */
    /* ----------------  +  -------------------------------- */
    /*       Dummy 16       Cycle = 32                       */
    /*                                                       */
    
    #define FULL_CYCLE_SEND_CNT 	12
    
    static float	full_cycle_buff[FULL_CYCLE_CNT] = {0,};
    static float	full_cycle_send_buff[FULL_CYCLE_SEND_CNT] = {0,};
    
    uint8_t	FULL_IRQ_NO			= 7;
    #define FULL_PD_NO			11
    #define FULL_LED_NO			5
    
    static int16_t 	buf_seq		= 0;
    static int16_t 	irq_no 		= 0;
    static int8_t 	pd_no 		= 0;
    static int8_t 	led_no 		= 0;
    
    extern bool pd_adc_full_a_start; 
    extern bool pd_adc_full_a_end; 
    
    extern bool pd_adc_full_b_start; 
    extern bool pd_adc_full_b_end; 
    
    extern bool pd_adc_full_c_start; 
    extern bool pd_adc_full_c_end; 
    
    extern bool pd_adc_full_d_start;
    extern bool pd_adc_full_d_end; 
    
    
    static nrf_ppi_channel_t	m_ppi_channel;
    
    extern char		ble_tx_buffer[BLE_NUS_MAX_DATA_LEN];
    
    
    void full_ppi_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_drv_ppi_init();
        APP_ERROR_CHECK(err_code);
    
        uint32_t gpiote_event_addr = nrf_drv_gpiote_in_event_addr_get(ADA2200_SYNCO_PIN);	
        uint32_t saadc_sample_task_addr   = nrf_drv_saadc_sample_task_get();
    
        /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
        err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_ppi_channel_assign(m_ppi_channel,
                                              gpiote_event_addr,
                                              saadc_sample_task_addr);
        APP_ERROR_CHECK(err_code);
    }
    
    
    void full_ppi_uninit(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_drv_ppi_uninit();
        APP_ERROR_CHECK(err_code);
    }
    
    
    void full_sampling_event_enable(void)
    {
        ret_code_t err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);
        APP_ERROR_CHECK(err_code);
    }
    
    
    void full_sampling_event_disable(void)
    {
    	ret_code_t err_code = nrf_drv_ppi_channel_disable(m_ppi_channel);
    	APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for handling the ADC interrupt.
     *
     * @details  This function will fetch the conversion result from the ADC, convert the value into
     *           percentage and send it to peer.
     */
    static inline void full_main_meas_process(void)
    {
    	static float sum = 0.0f;
    
    	if(irq_no < FULL_IRQ_NO) {
    		irq_no++;
    	} else if(irq_no >= FULL_IRQ_NO) {
    
    		///////////////////////////////////////////				/* Calculation Cycle-8, Cycle-16, Cycle-24, Cycle-32 */
    		for(uint8_t i = 0; i <= FULL_IRQ_NO; i++) {
    			sum += full_cycle_buff[i];
    		}
    
    		full_cycle_send_buff[buf_seq] = sum;
    //#if FEATURE_PRINTF
    //		printf("\r\n===============\r\n");
    //		printf("sum = %f\r\nfull_cycle_send_buff=\r\n", sum);
    //
    //		for(uint8_t i = 0; i < FULL_CYCLE_SEND_CNT; i++) {
    //			printf("<%d>= %f\r\n", i, full_cycle_send_buff[i]);
    //		}
    //		printf("===============\r\n\r\n");
    //#endif
    
    		sum = 0;
    
    		for(uint8_t i = 0; i < FULL_CYCLE_CNT; i++) {
    			full_cycle_buff[i] = 0.0f;
    		}
    
    		buf_seq++;
    		irq_no = 0;
    		
    		///////////////////////////////////////////				/* PD Changed */
    		if(pd_no < FULL_PD_NO) {
    			
    			pd_no++;
    #if FEATURE_PRINTF
    			printf("\r\nPD changed(a) to %d ---------------------------\r\n\r\n", pd_no);
    #endif
    
    			led_pd_matching_value_set(led_full_list[led_no], pd_full_list[pd_no]); /* MCP4725 DAC setting and PD on */
    			full_main_clock_delay(m_config.pd_delay_us/16);
    
    		} else if(pd_no >= FULL_PD_NO) {
    			pd_no = 0;
    			buf_seq = 0;
    
    			printf("Tj%d,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f\r\n", led_full_list[led_no], full_cycle_send_buff[0], full_cycle_send_buff[1], full_cycle_send_buff[2], full_cycle_send_buff[3], full_cycle_send_buff[4], full_cycle_send_buff[5], full_cycle_send_buff[6], full_cycle_send_buff[7], full_cycle_send_buff[8], full_cycle_send_buff[9], full_cycle_send_buff[10], full_cycle_send_buff[11]);
    			sprintf(ble_tx_buffer, "Tj%d,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f\r\n", led_full_list[led_no], full_cycle_send_buff[0], full_cycle_send_buff[1], full_cycle_send_buff[2], full_cycle_send_buff[3], full_cycle_send_buff[4], full_cycle_send_buff[5], full_cycle_send_buff[6], full_cycle_send_buff[7], full_cycle_send_buff[8], full_cycle_send_buff[9], full_cycle_send_buff[10], full_cycle_send_buff[11]);
    			data_tx_handler(ble_tx_buffer);
    			
    #if FEATURE_PRINTF
    			printf(">>>>> SEND 12 data <<<<<\r\n");
    			printf("PD changed(b) to %d ---------------------------\r\n", pd_no);
    #endif
    			for(uint8_t i = 0; i < FULL_CYCLE_SEND_CNT; i++) {
    				full_cycle_send_buff[i] = 0.0f;
    			}
    
    			/////////////////////////////////////////////
    			led_pd_matching_value_set(led_full_list[led_no], pd_full_list[pd_no]); /* MCP4725 DAC setting and PD on */
    //			full_main_clock_delay(m_config.pd_delay_us/16);				/* PD와 LED 딜레이가 이중으로 적용되므로 하나 막는다. */
    			/////////////////////////////////////////////
    
    			////////////////////////////////////////////////////	/* LED Changed */
    			if(led_no < FULL_LED_NO) {
    				led_no++;
    #if FEATURE_PRINTF
    				printf("LED changed to %d ---------------------------\r\n", led_no);
    #endif
    				////////////////////////////////////////////////
    				led_on(led_full_list[led_no]);
    				full_main_clock_delay(m_config.led_delay_us/16);
    				////////////////////////////////////////////////
    
    			} else if(led_no >= FULL_LED_NO) {
    				if(pd_adc_full_a_start == true) {
    					pd_adc_full_a_start = false;
    					pd_adc_full_a_end = true;
    								
    					main_timer_start();
    				}
    
    				if(pd_adc_full_b_start == true) {
    					pd_adc_full_b_start = false;
    					pd_adc_full_b_end = true;
    								
    					main_timer_start();
    				}
    
    				if(pd_adc_full_c_start == true) {
    					pd_adc_full_c_start = false;
    					pd_adc_full_c_end = true;
    								
    					main_timer_start();
    				}
    
    				if(pd_adc_full_d_start == true) {
    					pd_adc_full_d_start = false;
    					pd_adc_full_d_end = true;
    								
    					main_timer_start();
    				}
    				
    				printf("\r\n");
    				full_adc_end();
    				return;
    			}
    		}
    	}
    } 
    
    
    static void full_voltage_handler(nrf_drv_saadc_evt_t const * p_event)	/* PD Voltage reading */
    {
    
        if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
        {	
    		static uint16_t main_delay_cnt = 0;
    		static float imsi_voltage = 0;
    
    #if FEATURE_FOR_SCOPE    
    		nrf_gpio_pin_set(ADC_CLK_18);
    		nrf_gpio_pin_clear(ADC_CLK_18);
    #endif
    
            nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, FULL_SAMPLES_IN_BUFFER);
    		imsi_voltage = FULL_VOUT_IN_MILLI_VOLTS(p_event->data.done.p_buffer[0]);
    
    		if(full_main_testing == true) {
    
    #if FEATURE_PRINTF
    			printf("[buf_seq=%d], led_no=%d(%d), pd_no=%d(%d), irq_no=%d V=%f\r\n", buf_seq, led_no, led_full_list[led_no], pd_no, pd_full_list[pd_no], irq_no, imsi_voltage);
    #endif			
    			full_cycle_buff[irq_no] = imsi_voltage;
    
    //#if FEATURE_PRINTF
    //			printf("full_cycle_buff=\r\n");
    //			switch(m_config.pd_adc_cnt){
    //				case 8:
    //					for(uint8_t i = 16; i < 24; i++) {
    //						printf("<%d>= %f\r\n", i, full_cycle_buff[i]);
    //					}
    //					break;
    //			
    //				case 16:
    //					for(uint8_t i = 16; i < 32; i++) {
    //						printf("<%d>= %f\r\n", i, full_cycle_buff[i]);
    //					}
    //					break;
    //			
    //				case 24:
    //					for(uint8_t i = 16; i < 40; i++) {
    //						printf("<%d>= %f\r\n", i, full_cycle_buff[i]);
    //					}
    //					break;
    //			
    //				case 32:
    //					for(uint8_t i = 16; i < 48; i++) {
    //						printf("<%d>= %f\r\n", i, full_cycle_buff[i]);
    //					}
    //					break;
    //			
    //				default:
    //					break;
    //			}
    //			printf("===============\r\n");
    //		
    //			printf("full_cycle_send_buff=\r\n");
    //			for(uint8_t i = 0; i < FULL_CYCLE_SEND_CNT; i++) {
    //				printf("<%d>= %f\r\n", i, full_cycle_send_buff[i]);
    //			}
    //			printf("===============\r\n\r\n");
    //#endif
    
    			full_main_meas_process();
    			
    		}else if(full_main_delay) {
    #if FEATURE_PRINTF
    			printf("m_d = %d  ", main_delay_cnt);
    #endif			
    			if(main_delay_cnt++ >= FULL_DELAY_CLK-1) {
    #if FEATURE_PRINTF
    				printf("\r\n");
    #endif					
    				main_delay_cnt = 0;
    				full_main_delay = false;
    				full_main_testing = true;
    			}
    		}
        }
    }
    
    
    void full_adc_init(void)
    {
    	static nrfx_saadc_config_t default_config;
    	default_config.resolution			= (nrf_saadc_resolution_t)NRFX_SAADC_CONFIG_RESOLUTION; /* Resolution is 10bits */
    	default_config.oversample			= (nrf_saadc_oversample_t)NRFX_SAADC_CONFIG_OVERSAMPLE; /* Over Sampling Disabled */
    	default_config.interrupt_priority	= NRFX_SAADC_CONFIG_IRQ_PRIORITY;						/* Interrupt Priority is 0(Highest) */
    	default_config.low_power_mode		= NRFX_SAADC_CONFIG_LP_MODE;							/* Low Power Mode is Disabled */
    
    	static nrf_saadc_channel_config_t config;
    	config.resistor_p	= NRF_SAADC_RESISTOR_DISABLED;
    	config.resistor_n	= NRF_SAADC_RESISTOR_DISABLED;
    	config.gain 		= NRF_SAADC_GAIN1_6;
    	config.reference	= NRF_SAADC_REFERENCE_INTERNAL;
    	config.acq_time 	= NRF_SAADC_ACQTIME_10US;
    	config.mode 		= NRF_SAADC_MODE_DIFFERENTIAL;
    	config.burst		= NRF_SAADC_BURST_DISABLED;
    	config.pin_p		= (nrf_saadc_input_t)(NRF_SAADC_INPUT_AIN0);
    	config.pin_n		= (nrf_saadc_input_t)(NRF_SAADC_INPUT_AIN1);
    	
    	ret_code_t err_code = nrf_drv_saadc_init(&default_config, full_voltage_handler);
    	APP_ERROR_CHECK(err_code);
    
    	err_code = nrf_drv_saadc_channel_init(0, &config);
    	APP_ERROR_CHECK(err_code);
    
    	err_code = nrf_drv_saadc_buffer_convert(pd_full_adc_buf[0], FULL_SAMPLES_IN_BUFFER);
    	APP_ERROR_CHECK(err_code);
    
    	err_code = nrf_drv_saadc_buffer_convert(pd_adc_buf[1], SIM_SAMPLES_IN_BUFFER);
    	APP_ERROR_CHECK(err_code);	
    }
    
    
    
    void full_adc_uninit(void)
    {
    #if FEATURE_PRINTF
    	printf("pd_full_adc_uninit\r\n");
    #endif
    
    	nrf_drv_saadc_uninit();
    	nrf_drv_saadc_channel_uninit(0);
    }
    
    
    void full_adc_start(void)
    {
    
    	battery_timer_stop();
    
    	full_adc_init();
    	full_irq_init();
    	full_ppi_init();
    	ada2200_start();
    
    	full_sampling_event_enable();	
    
    	if(pd_adc_full_a_start == true) {
    #if FEATURE_PRINTF
    		printf("\r\n===============================================================\r\n");
    		printf("===== Full_A start ============================================\r\n");
    		printf("===============================================================\r\n");
    #endif
    		memcpy(led_full_list, led_full_list_a, 6);
    		memcpy(pd_full_list, pd_full_list_a, 12);
    	}
    
    	if(pd_adc_full_b_start == true) {
    #if FEATURE_PRINTF
    		printf("\r\n===============================================================\r\n");
    		printf("===== Full_B start ============================================\r\n");
    		printf("===============================================================\r\n");
    #endif
    		memcpy(led_full_list, led_full_list_b, 6);
    		memcpy(pd_full_list, pd_full_list_b, 12);
    	}
    
    	if(pd_adc_full_c_start == true) {
    #if FEATURE_PRINTF
    		printf("\r\n===============================================================\r\n");
    		printf("===== Full_C start ============================================\r\n");
    		printf("===============================================================\r\n");
    #endif
    		memcpy(led_full_list, led_full_list_c, 6);
    		memcpy(pd_full_list, pd_full_list_c, 12);
    	}
    
    	if(pd_adc_full_d_start == true) {
    #if FEATURE_PRINTF
    		printf("\r\n===============================================================\r\n");
    		printf("===== Full_D start ============================================\r\n");
    		printf("===============================================================\r\n");
    #endif
    		memcpy(led_full_list, led_full_list_d, 6);
    		memcpy(pd_full_list, pd_full_list_d, 12);
    	}
    
    #if FEATURE_PRINTF
    	printf("LED(0) ON, PD(0) ON\r\n");
    #endif
    
    	led_on(led_full_list[0]);
    
    	led_pd_matching_value_set(led_full_list[0], pd_full_list[0]); /* MCP4725 DAC setting And PD on */
    	nrf_delay_us(m_config.pd_delay_us);
    
    #if FEATURE_PRINTF
    	printf("\r\nfull_cycle_buff Cleared<start>\r\n");
    	printf("full_cycle_send_buff Cleared<start>\r\n");
    #endif
    	
    	for(uint8_t i = 0; i < FULL_CYCLE_CNT; i++) {
    		full_cycle_buff[i] = 0.0f;
    	}
    	for(uint8_t i = 0; i < FULL_CYCLE_SEND_CNT; i++) {
    		full_cycle_send_buff[i] = 0.0f;
    	}
    
    #if FEATURE_PRINTF
    	printf("full_cycle_buff=\r\n");
    	switch(m_config.pd_adc_cnt){
    		case 8:
    			for(uint8_t i = 16; i < 24; i++) {
    				printf("<%d>= %f\r\n", i, full_cycle_buff[i]);
    			}
    			break;
    	
    		case 16:
    			for(uint8_t i = 16; i < 32; i++) {
    				printf("<%d>= %f\r\n", i, full_cycle_buff[i]);
    			}
    			break;
    	
    		case 24:
    			for(uint8_t i = 16; i < 40; i++) {
    				printf("<%d>= %f\r\n", i, full_cycle_buff[i]);
    			}
    			break;
    	
    		case 32:
    			for(uint8_t i = 16; i < 48; i++) {
    				printf("<%d>= %f\r\n", i, full_cycle_buff[i]);
    			}
    			break;
    	
    		default:
    			break;
    	}
    	printf("===============\r\n");
    
    	printf("===============\r\n");
    
    	printf("full_cycle_send_buff=\r\n");
    	for(uint8_t i = 0; i < FULL_CYCLE_SEND_CNT; i++) {
    		printf("<%d>= %f\r\n", i, full_cycle_send_buff[i]);
    	}
    	printf("===============\r\n\r\n");
    #endif
    
    	buf_seq		= 0;
    	irq_no		= 0;
    	pd_no 		= 0;
    	led_no		= 0;
    
    	full_main_testing = true;
    	
    }
    
    
    void full_adc_end(void) 
    {
    #if FEATURE_PRINTF
    	printf("full_adc_end\r\n");
    #endif
    
    	battery_timer_start();
    
    	ada2200_stop();
    	full_sampling_event_disable();
    
    	full_irq_uninit();
    	full_adc_uninit();
    	full_ppi_uninit();
    
    #if FEATURE_PRINTF
    	printf("\r\nfull_cycle_buff Cleared<end>\r\n");
    	printf("full_cycle_send_buff Cleared<end>\r\n");
    #endif
    
    	for(uint8_t i = 0; i < FULL_CYCLE_CNT; i++) {
    		full_cycle_buff[i] = 0.0f;
    	}
    	for(uint8_t i = 0; i < FULL_CYCLE_SEND_CNT; i++) {
    		full_cycle_send_buff[i] = 0.0f;
    	}
    
    #if FEATURE_PRINTF
    	printf("full_cycle_buff=\r\n");
    	switch(m_config.pd_adc_cnt){
    		case 8:
    			for(uint8_t i = 16; i < 24; i++) {
    				printf("<%d>= %f\r\n", i, full_cycle_buff[i]);
    			}
    			break;
    	
    		case 16:
    			for(uint8_t i = 16; i < 32; i++) {
    				printf("<%d>= %f\r\n", i, full_cycle_buff[i]);
    			}
    			break;
    	
    		case 24:
    			for(uint8_t i = 16; i < 40; i++) {
    				printf("<%d>= %f\r\n", i, full_cycle_buff[i]);
    			}
    			break;
    	
    		case 32:
    			for(uint8_t i = 16; i < 48; i++) {
    				printf("<%d>= %f\r\n", i, full_cycle_buff[i]);
    			}
    			break;
    	
    		default:
    			break;
    	}
    	printf("===============\r\n");
    
    	printf("===============\r\n");
    
    	printf("full_cycle_send_buff=\r\n");
    	for(uint8_t i = 0; i < FULL_CYCLE_SEND_CNT; i++) {
    		printf("<%d>= %f\r\n", i, full_cycle_send_buff[i]);
    	}
    	printf("===============\r\n\r\n");
    #endif
    
    	led_off(99);
    	pd_off(99);
    
    	full_main_testing = false;
    	full_main_delay = false;
    }
    
    
    void full_irq_init(void){
        ret_code_t err_code;
    #if FEATURE_PRINTF
    	printf("full_irq_init\r\n");
    #endif
    
    	/* Initialize int pin */
    	if (!nrfx_gpiote_is_init())
    	{
    	  err_code = nrfx_gpiote_init();
    	  APP_ERROR_CHECK(err_code);
    	}
    
        nrfx_gpiote_in_config_t in_config = NRFX_GPIOTE_CONFIG_IN_SENSE_LOTOHI(true);
        in_config.pull = NRF_GPIO_PIN_PULLDOWN;
    
        err_code = nrfx_gpiote_in_init(ADA2200_SYNCO_PIN, &in_config, NULL);
        APP_ERROR_CHECK(err_code);
    
        nrfx_gpiote_in_event_enable(ADA2200_SYNCO_PIN, true);
    }
    
    
    void full_irq_uninit(void){
    #if FEATURE_PRINTF
    	printf("full_irq_uninit\r\n");
    #endif	
    	nrfx_gpiote_in_event_disable(ADA2200_SYNCO_PIN);
    	nrfx_gpiote_in_uninit(ADA2200_SYNCO_PIN);
    }
    
    

    Please review whether PPI, EasyDMA, etc. are implemented well.

    And I use 2 channels for ADC sampling with DIFFRENTIAL Mode. It takes a register value and calculates the actual voltage value using the following formula:

    #define FULL_REF_VOLTAGE_IN_MILLIVOLTS   	600.0f                                     /**< Reference voltage (in milli volts) used by ADC while doing conversion. */
    #define FULL_PRE_SCALING_COMPENSATION    	6.0f                                       /**< The ADC is configured to use VDD with 1/3 prescaling as input. And hence the result of conversion is to be multiplied by 3 to get the actual value of the battery voltage.*/
    #define FULL_ADC_RES_10BITS             	1024.0f                                    /**< Maximum digital value for 10-bit ADC conversion. */
    
    #define FULL_VOUT_IN_MILLI_VOLTS(ADC_VALUE)\
    				((((ADC_VALUE) * FULL_REF_VOLTAGE_IN_MILLIVOLTS) / FULL_ADC_RES_10BITS) * FULL_PRE_SCALING_COMPENSATION)

    Is it correct to use this formula? Or should the formula be changed?

    Best Regards,

    SunBae Yim.

  • Hello again, SunBae Yim

    ParanBada said:
    Why is there a delay when the ADC only samples through the PPI?

    Thank you for sharing the source code used for the measuring.
    The GPIO is being set by the CPU when it goes to process the SAADC DONE event, which is not necessarily immediately after the SAADC has performed a sampling. The CPU could be busy handling a higher level interrupt, such as any SoftDevice activity, and thus the processing of the DONE event could be delayed. This is likely what is happening in your measurements.

    If you want the GPIO to accurately portray when the DONE event occurs you should instead have a PPI channel connect the DONE event and a GPIO toggle task. This way, you will see that the DONE event is actually generated as soon as the sampling finishes, which should be [t_CONV + t_ACQ] after the 62.5 kHz pulse.

    Additionally, I also note that you are using a SAADC buffer size of 1, which means that the CPU needs to intervene for every sample to provide the next buffer to use by the ADC. Instead, I would recommend increasing the SAADC buffer to a higher number, so that you only need to do processing every so often, instead of after each sampling.

    Best regards,
    Karl

  • Hello,

    Your advice to increase the SAADC buffer size is good.
    How many SAADC buffers can I increase?
    Is there any documentation to refer to the SAADC buffer max size?

    I want to set the SAADC Buffer size to 4127. Is it possible?

    Best Regards,

    SunBae Yim.

  • Hello again, SunBae Yim

    ParanBada said:
    Your advice to increase the SAADC buffer size is good.

    I am glad to hear you say so! :)

    ParanBada said:

    Is there any documentation to refer to the SAADC buffer max size?

    I want to set the SAADC Buffer size to 4127. Is it possible?

    The SAADC uses EasyDMA and so the provided buffer must be in RAM.
    Additionally, the maximum value of the MAXCNT register is 2^14 -1, and so that is the maximal buffer size for a single buffer.
    You can read more about this in the SAADC EasyDMA documentation.

    Best regards,
    Karl

  • Hello,

    ADC sampling using the PPI function. Where is the source code for that part?
    Is it done inside the soft device? Or does it not work on the hardware inside the MCU?

    I want to check the code that works when performing ADC sampling through PPI.
    For example, if the SAADC buffer size is 100, ADC sampling is executed 100 times and the value is stored in this RAM buffer.
    Whenever ADC sampling is performed 100 times, I want to control the GPIO port in that part of the source code as follows.

    #if FEATURE_FOR_SCOPE
    nrf_gpio_pin_set(ADC_CLK_18);
    nrf_gpio_pin_clear(ADC_CLK_18);
    #endif

    Then I want to check 100 ADC samplings through a logic analyzer.

    Best Regards,

    SunBae Yim.

  • Hello SunBae Yim,

    ParanBada said:
    ADC sampling using the PPI function. Where is the source code for that part?

    If you just would like to see how to trigger SAADC sampling through PPI then you could take a look at the SAADC example in the SDK.
    You could also see some examples of common SAADC usage in this repository.

    ParanBada said:
    Is it done inside the soft device?

    No - the SoftDevice does use some PPI channels, but your application can use the channels that are not being used by the SoftDevice for whatever you would like.

    ParanBada said:
    Or does it not work on the hardware inside the MCU?

    I am not sure that I understand this question, could you elaborate?

    ParanBada said:
    For example, if the SAADC buffer size is 100, ADC sampling is executed 100 times and the value is stored in this RAM buffer.
    Whenever ADC sampling is performed 100 times, I want to control the GPIO port in that part of the source code as follows.

    To achieve this you could set the GPIO as part of the DONE handling - just keep in mind that the processing of the DONE event could be postponed if there is a higher priority interrupt being processed at the time where it is generated, so the GPIO will then not show exactly when the 100 samples have completed.
    If you want the GPIO to accurately reflect when the 100 samples have been collected you would have to set up a PPI channel between the GPIO and the SAADC DONE event - in this case, it would toggle immediately when the DONE event is generated.

    Best regards,
    Karl

Reply
  • Hello SunBae Yim,

    ParanBada said:
    ADC sampling using the PPI function. Where is the source code for that part?

    If you just would like to see how to trigger SAADC sampling through PPI then you could take a look at the SAADC example in the SDK.
    You could also see some examples of common SAADC usage in this repository.

    ParanBada said:
    Is it done inside the soft device?

    No - the SoftDevice does use some PPI channels, but your application can use the channels that are not being used by the SoftDevice for whatever you would like.

    ParanBada said:
    Or does it not work on the hardware inside the MCU?

    I am not sure that I understand this question, could you elaborate?

    ParanBada said:
    For example, if the SAADC buffer size is 100, ADC sampling is executed 100 times and the value is stored in this RAM buffer.
    Whenever ADC sampling is performed 100 times, I want to control the GPIO port in that part of the source code as follows.

    To achieve this you could set the GPIO as part of the DONE handling - just keep in mind that the processing of the DONE event could be postponed if there is a higher priority interrupt being processed at the time where it is generated, so the GPIO will then not show exactly when the 100 samples have completed.
    If you want the GPIO to accurately reflect when the 100 samples have been collected you would have to set up a PPI channel between the GPIO and the SAADC DONE event - in this case, it would toggle immediately when the DONE event is generated.

    Best regards,
    Karl

Children
No Data
Related