This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ADC INT flag not raising??

Other Parts Discussed in Thread: CONTROLSUITE

Hi Folks,

I am attempting to calibrate the ADC OFFTRIM value on an F28027.  I have an older project that uses the struct support files, the example DevInit() and example AdcOffsetSelfCal(), that appears to work as intended.

I have recreated the DevInit() and AdcOffsetSelfCal() in my main() initialization section of my new project, this time using the driver support files. The code is as below.

Currently my issue is as follows. When attempting the ping-pong sampling initially the first conversion SOC is forced, by writing 0x00FF to the ADCSOCFRC1 register, subsequent conversion SOCs should then be triggered by the ADCINT1 & 2 that occur at the end of the conversion. However, the flags for these ADCINTs never seem to be raised, meaning that after the first set of (forced) conversions the program gets stuck waiting for the flags to be raised (ln#:165)...

I have checked all the values set in the registers and the appear correct and matching to the values in my older, working, project. So I have a feeling I must be missing something silly somewhere, but i cant for the life of me see what it might be.

Note that I have also started this project from scratch instead of altering an example project as I did for my previous projects, so there may possibly be some issue there, but I couldn't think of anything in this regard that would affect the ADCs in this way.

the code is below, I'd appreciate if anyone could let me know if they can spot anything incorrect or if you suffer see a similar problem with this code. Many thanks.

#include "DSP28x_Project.h"

#include <clk.h>
#include <flash.h>
#include <gpio.h>
#include <pie.h>
#include <pll.h>
#include <pie.h>
#include <wdog.h>
#include <adc.h>
#include <DPlib.h>

#define ADC_usDELAY 	1000L
#define ADC_ADCCTL1_VREFLOCONV_BIT	1
#define ADC_OFFTRIM_CAL_SAMPLE_SIZE	256 /* NB: Sample size must be multiples of 2^x where is an integer >= 4). */

extern uint16_t RamfuncsLoadEnd;
volatile struct EPWM_REGS *ePWM[] = 	/* This is declared extern by DPLib.h.*/
 				  { &EPwm1Regs,			/* Intentional: (ePWM[0] not used). */
				  	&EPwm1Regs,
					&EPwm2Regs,
					&EPwm3Regs,
					&EPwm4Regs,
					#if (!DSP2802x_DEVICE_H)
					&EPwm5Regs,
					&EPwm6Regs,
					#if (DSP2803x_DEVICE_H || DSP2804x_DEVICE_H)
					&EPwm7Regs,
					#if (DSP2804x_DEVICE_H)
					&EPwm8Regs
					#endif
					#endif
					#endif
				  };
extern void ADC_SOC_CNF(int ChSel[], int Trigsel[], int ACQPS[], int IntChSel, int mode);
extern void PWM_1ch_CNF(int16 n, Uint16 period, int16 mode, int16 phase);

// This function configures the A channel of a ePWM with the settings specified by the arguments.
//	uint16_t 	pwm		Target ePWM module, 1,2,...16.  e.g. if n=2, then target is ePWM2.
//	uint16_t	f_pwm	PWM frequency in kHz.
//	bool_t 		master	Master mode selector.
//	uint16_t 	phase	Phase angle from upstream master in degrees, applicable only if master=false, i.e. slave.
void confgiure_dpl_pwm (uint16_t pwm, double f_pwm, bool_t master, uint16_t phase) {
	/* frequency parameter is in kHz, phase parameter is in degrees. */
	uint16_t t_pwm = (uint16_t)((1/f_pwm) * 1000.0) + 0.5;
	t_pwm = ((t_pwm/CPU_RATE) * 1000.0) + 0.5;
	uint16_t t_phi = ((t_pwm/360.0) * phase) + 0.5;
	PWM_1ch_CNF(pwm, t_pwm, (master?1:0), t_phi);
}

void MemCopy(uint16_t * SourceAddr, uint16_t * SourceEndAddr, uint16_t * DestAddr)
{
    while(SourceAddr < SourceEndAddr)
    {
       *DestAddr++ = *SourceAddr++;
    }
    return;
}

void main(void) {

	/* Initialize all the system handles needed for this application. */
	CPU_Handle cpu = CPU_init((void *)NULL, sizeof(CPU_Obj));
	WDOG_Handle wdog = WDOG_init((void *)WDOG_BASE_ADDR, sizeof(WDOG_Obj));
	WDOG_disable(wdog);			/* Disable the watchdog. */
	CPU_disableGlobalInts(cpu);	/* DINT (INTM = 1). */
	CPU_disableInts(cpu);		/* Clear CPU IER register. */
	CPU_clearIntFlags(cpu);		/* Clear CPU IFR register. */

	#ifdef FLASH
		FLASH_Handle flash = FLASH_init((void *)FLASH_BASE_ADDR, sizeof(FLASH_Obj));
	#endif

	CLK_Handle clk = CLK_init((void *)CLK_BASE_ADDR, sizeof(CLK_Obj));
	PLL_Handle pll = PLL_init((void *)PLL_BASE_ADDR, sizeof(PLL_Obj));
	PIE_Handle pie = PIE_init((void *)PIE_BASE_ADDR, sizeof(PIE_Obj));
	GPIO_Handle gpio = GPIO_init((void *)GPIO_BASE_ADDR, sizeof(GPIO_Obj));
	ADC_Handle adc = ADC_init((void *)ADC_BASE_ADDR, sizeof(ADC_Obj));

	/*=========================== DEVICE INITIALISATION ===========================*/
	CLK_enableAdcClock(clk);	/* Clock to ADC needs to be enabled for Device_cal(). */
	(*Device_cal)();			/* Calibrate the internal oscillators and ADC. */
	CLK_disableAdcClock(clk);

	CLK_enableOsc1(clk);		/* Enable internal oscillator 1. */
	CLK_setOscSrc(clk, CLK_OscSrc_Internal);	/* Select the internal oscillator 1 as the clock source. */
	CLK_disableClkIn(clk);		/* Disable the external clock input. */
	CLK_disableCrystalOsc(clk);	/* Disable the crystal oscillator. */
	CLK_disableOsc2(clk);		/* Disable the internal oscillator 2. */

	PLL_setup(pll, PLL_Multiplier_12, PLL_DivideSelect_ClkIn_by_2);	/* Setup the PLL for x12 /2 which will yield 60Mhz = 10Mhz * 12 / 2. */

	PIE_disable(pie);			/* Clear the PIE CTRL enable bit. */
	PIE_disableAllInts(pie);	/* Clear all PIE IER registers to all 0. */
	PIE_clearAllFlags(pie);		/* Clear all PIE IFR registers to 0. */
	PIE_setDefaultIntVectorTable(pie);	/* Initializes the vector table with illegal ISR handlers. */
	PIE_enable(pie);			/* Set the PIE CTRL enable bit. */

	CLK_setLowSpdPreScaler(clk, CLK_LowSpdPreScaler_SysClkOut_by_2);/* Setup the low-speed clock for SYSCLKOUT/(LOSPCP * 2) which will yield 15Mhz = 60Mhz / 4. */
	CLK_setClkOutPreScaler(clk, CLK_ClkOutPreScaler_SysClkOut_by_2);/* Setup the clock external output for /2, yielding 60MHz = 60MHz / 2. */

	CLK_enableI2cClock(clk);					/* Enable clock to I2C. */
	CLK_enableGpioInputClock(clk);				/* Enable clock to GPIO inputs. */
	CLK_disableCompClock(clk, CLK_CompNumber_1);/* Disable clock to comparator 1. */
	CLK_disableCompClock(clk, CLK_CompNumber_2);/* Disable clock to comparator 2. */
	CLK_disableSciaClock(clk);					/* Disable clock to SCI-A. */
	CLK_disableSpiaClock(clk);					/* Disable clock to SPI-A. */
	CLK_disableEcap1Clock(clk);					/* Disable clock to eCAP1. */

	#ifdef FLASH
		MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart);
						/* Copy time critical code and Flash setup code to RAM. */
		FLASH_setup(flash);		/* Call the flash wrapper init function. */
	#endif

	/*=============================== CONFIGURE ADC ===============================*/
	GPIO_Obj * gpioObj = (GPIO_Obj *)gpio;
	ENABLE_PROTECTED_REGISTER_WRITE_MODE;
	gpioObj->AIOMUX1 = 0x22202220;	/* Disables AIOIN lines, ADC & CMP only used. */
	DISABLE_PROTECTED_REGISTER_WRITE_MODE;

	CLK_enableAdcClock(clk);		/* Enable clock to ADC. */

	ADC_enableBandGap(adc);			/* Power up ADC and references. */
	ADC_enableRefBuffers(adc);
	ADC_powerUp(adc);
	ADC_enable(adc);
	ADC_setVoltRefSrc(adc, ADC_VoltageRefSrc_Int);
	DELAY_US(ADC_usDELAY);         /* Wait for power up to complete. */

	uint16_t adcConvMean;
	ADC_Obj * adcObj = (ADC_Obj *)adc;
	ADC_SocNumber_e soc = ADC_SocNumber_0;
	ENABLE_PROTECTED_REGISTER_WRITE_MODE;	/* Setup for OFFTRIM calibration. */
	adcObj->ADCCTL1 |= (1 << ADC_ADCCTL1_VREFLOCONV_BIT); /* Connect B5 to VREFLO instead of the ADCINB5 pin. */
	DISABLE_PROTECTED_REGISTER_WRITE_MODE;
	for (; soc <= ADC_SocNumber_15; ++soc)	/* Select channel B5 for all SOC. */
		ADC_setSocChanNumber(adc, (ADC_SocNumber_e)soc, ADC_SocChanNumber_B5);
	ENABLE_PROTECTED_REGISTER_WRITE_MODE;
	adcObj->ADCOFFTRIM = 80;	/* Apply artificial offset (+80) to account for a negative offset that may reside in the ADC core. */
	DISABLE_PROTECTED_REGISTER_WRITE_MODE;

	for (soc = ADC_SocNumber_0; soc <= ADC_SocNumber_15; ++soc)
		ADC_setSocSampleWindow(adc, soc, ADC_SocSampleWindow_7_cycles);

	ADC_enableInt(adc, ADC_IntNumber_1);	/* Setup for ping-pong sampling. */
	ADC_enableInt(adc, ADC_IntNumber_2);
	ADC_setIntMode(adc, ADC_IntNumber_1, ADC_IntMode_ClearFlag);
	ADC_setIntMode(adc, ADC_IntNumber_2, ADC_IntMode_ClearFlag);
	ADC_setIntPulseGenMode(adc, ADC_IntPulseGenMode_Prior);
	ADC_setIntSrc(adc, ADC_IntNumber_1, ADC_IntSrc_EOC6);
	ADC_setIntSrc(adc, ADC_IntNumber_2, ADC_IntSrc_EOC14);
	ENABLE_PROTECTED_REGISTER_WRITE_MODE;
	adcObj->ADCINTSOCSEL1 = 0xAAAA;	/* Set ADCINT1 to start SOC8-15. */
	adcObj->ADCINTSOCSEL2 = 0x5555;	/* Set ADCINT2 to start SOC0-7. */
	DISABLE_PROTECTED_REGISTER_WRITE_MODE;
	DELAY_US(ADC_usDELAY);
	ENABLE_PROTECTED_REGISTER_WRITE_MODE;
	adcObj->ADCSOCFRC1 = 0x00FF;	/* Force start SOC0-7 to begin ping-pong sampling. */
	DISABLE_PROTECTED_REGISTER_WRITE_MODE;

	uint16_t i = 0;	uint32_t sum = 0;	/* Take samples. */
	for (; i < ADC_OFFTRIM_CAL_SAMPLE_SIZE; i += 16) {
		ADC_ResultNumber_e result = ADC_ResultNumber_0;
		while (!ADC_getIntStatus(adc, ADC_IntNumber_1)) {}        // GETS STUCK HERE ON SECOND ITERATION
		ADC_clearIntFlag(adc, ADC_IntNumber_1);
		for (; result <= ADC_ResultNumber_7; ++result)
			sum += ADC_readResult(adc, result);

		while (!ADC_getIntStatus(adc, ADC_IntNumber_2)) {}
		ADC_clearIntFlag(adc, ADC_IntNumber_2);
		for (result = ADC_ResultNumber_8; result <= ADC_ResultNumber_15; ++result)
			sum += ADC_readResult(adc, result);
	}

	ADC_disableInt(adc, ADC_IntNumber_1);	/* Stop the ping-pong sampling. */
	ADC_disableInt(adc, ADC_IntNumber_2);

	adcConvMean = sum / ADC_OFFTRIM_CAL_SAMPLE_SIZE;	/* Average the sample data. */
	ENABLE_PROTECTED_REGISTER_WRITE_MODE;
	adcObj->ADCOFFTRIM = 80 - adcConvMean;	/* Set offtrim register with new value (i.e remove artical offset (+80) and create a two's compliment of the offset error). */
	adcObj->ADCCTL1 &= ~(1 << ADC_ADCCTL1_VREFLOCONV_BIT); /* Connect B5 to back to the ADCINB5 pin. */
	DISABLE_PROTECTED_REGISTER_WRITE_MODE;

	int chsel[16] = {0, 0x1, 0x9, 0x2, 0}; /* A0 Unused (SOC0 Errata), A1, B1, A2, all others unused */
	int trigsel[16] = {5, 5, 5, 5, 0};
	int acqps[16] = {0, 6, 6, 6, 0};
	ADC_SOC_CNF(chsel, trigsel, acqps, 16, 0);

	for (;;) {}	/* Super loop. */
}

  • Hi Toby,

    Can you try with the traditional approach ie v129. Something similar to:

    C:\ti\controlSUITE\device_support\f2802x\v129\DSP2802x_examples_ccsv4\adc_soc

    As per my personal opinion, the structure of the above version is bit more robust and user friendly.

    Regards,

    Gautam

  • Hi Gautam,

    so the program now consists of the following code:

    #include "DSP28x_Project.h
    
    void main(void) {
    	InitSysCtrl();
    	DINT;
    	InitPieCtrl();
    	IER = 0x0000;
    	IFR = 0x0000;
    	InitPieVectTable();
    	InitAdc();
    	AdcOffsetSelfCal();
    	for (;;) {}
    }

    However, execution still gets caught waiting for the ADCINTFLAG.ADCINT2, on the AdcOffsetSelfCal() second iteration of the sampling while loop (i.e. ln# 224 of DSP2802xadc.c)

    EDIT: If I use the adc soc example project and add a call to AdcOffsetSelfCal() at ln# 135 of main(), this works as expected... Yet executing the same code from the same files in my own project still exhibits this issue!!??!

  • Just created a new project from scratch again and added files and code to exactly match the adc soc example with the v220 support files, and it runs without issue with the AdcOffsetSelfCal() call added in...

    I guess I'll try the next step of creating a project from scratch *again* and use the driver code and see if this is some issue with the project setup of the project that is exhibiting the issue.

    Will post my results

  • Ok, so another project from scratch using the same files as the v220 adc soc *drivers* example, with a call tio AdcOffsetSelfCal() added at ln#: 110 (as well as a delay to allow the ADC power up to finish before starting the calibration).

    This does not get stuck.

    Changing this call out and replacing it with my version of the function using the driver functions does *still* get stuck however, so it seems there is another issue here as well... will have to step throught the code and compare register entries...

  • Read all your above cases... Good work. Do let me know if you further need any help.

    Regards,

    Gautam

  • Yay! I noticed that the ADC interrupt overflow flags weher being set during the sampling while loop, this led me to think that the for loops that read the result registers where taking too long to run the loop and the functional query of the result registers  and the clearing of the interrupt flag. So, I resorted to unrollingthe loops and addressing the registers directly, still via the driver ADC object rather than the structs, and viola, the loops run OK now :D

    The working code to replace the usage of f2802x_adc.c  is now:

        ADC_enableBandGap(myAdc); /* Initialise the ADC. */
        ADC_enableRefBuffers(myAdc);
        ADC_powerUp(myAdc);
        ADC_enable(myAdc);
        ADC_setVoltRefSrc(myAdc, ADC_VoltageRefSrc_Int);
        DELAY_US(ADC_usDELAY);         /* Wait for power up to complete. */
    
        uint16_t adcConvMean;
        ADC_Obj * adcObj = (ADC_Obj *)myAdc;
        ADC_SocNumber_e soc = ADC_SocNumber_0;
    
        ENABLE_PROTECTED_REGISTER_WRITE_MODE;	/* Setup for OFFTRIM calibration. */
        adcObj->ADCCTL1 |= (1 << ADC_ADCCTL1_VREFLOCONV_BIT); /* Connect B5 to VREFLO instead of the ADCINB5 pin. */
        DISABLE_PROTECTED_REGISTER_WRITE_MODE;
    
    	for (; soc <= ADC_SocNumber_15; ++soc)	/* Select channel B5 for all SOC. */
    		ADC_setSocChanNumber(myAdc, (ADC_SocNumber_e)soc, ADC_SocChanNumber_B5);
    
    	ENABLE_PROTECTED_REGISTER_WRITE_MODE;
    	adcObj->ADCOFFTRIM = 0x0050;	/* Apply artificial offset (+80) to account for a negative offset that may reside in the ADC core. */
    	DISABLE_PROTECTED_REGISTER_WRITE_MODE;
    
    	for (soc = ADC_SocNumber_0; soc <= ADC_SocNumber_15; ++soc) /* Slect windows for all SOC. */
    		ADC_setSocSampleWindow(myAdc, soc, ADC_SocSampleWindow_7_cycles);
    
    	ADC_enableInt(myAdc, ADC_IntNumber_1);	/* Setup for ping-pong sampling. */
    	ADC_enableInt(myAdc, ADC_IntNumber_2);
    	ADC_setIntMode(myAdc, ADC_IntNumber_1, ADC_IntMode_ClearFlag);
    	ADC_setIntMode(myAdc, ADC_IntNumber_2, ADC_IntMode_ClearFlag);
    	ADC_setIntPulseGenMode(myAdc, ADC_IntPulseGenMode_Prior);
    	ADC_setIntSrc(myAdc, ADC_IntNumber_1, ADC_IntSrc_EOC6);
    	ADC_setIntSrc(myAdc, ADC_IntNumber_2, ADC_IntSrc_EOC14);
    
    	ENABLE_PROTECTED_REGISTER_WRITE_MODE;
    	adcObj->ADCINTSOCSEL1 = 0xAAAA;	/* Set ADCINT1 to start SOC8-15. */
    	adcObj->ADCINTSOCSEL2 = 0x5555;	/* Set ADCINT2 to start SOC0-7. */
    	DISABLE_PROTECTED_REGISTER_WRITE_MODE;
    	DELAY_US(ADC_usDELAY);
    
    	adcObj->ADCSOCFRC1 = 0x00FF;	/* Force start SOC0-7 to begin ping-pong sampling. */
    
    	uint16_t i = 0;	uint32_t sum = 0;	/* Take samples. */
    	for (; i < ADC_OFFTRIM_CAL_SAMPLE_SIZE; i += 16) {
    		while(adcObj->ADCINTFLG & 0x01 == 0) {}
    		adcObj->ADCINTFLGCLR = 0x01;
    		sum += adcObj->ADCRESULT[0];
    		sum += adcObj->ADCRESULT[1];
    		sum += adcObj->ADCRESULT[2];
    		sum += adcObj->ADCRESULT[3];
    		sum += adcObj->ADCRESULT[4];
    		sum += adcObj->ADCRESULT[5];
    		sum += adcObj->ADCRESULT[6];
    		sum += adcObj->ADCRESULT[7];
    
    		while(adcObj->ADCINTFLG & 0x01 == 0) {}
    		adcObj->ADCINTFLGCLR = 0x02;
    		sum += adcObj->ADCRESULT[8];
    		sum += adcObj->ADCRESULT[9];
    		sum += adcObj->ADCRESULT[10];
    		sum += adcObj->ADCRESULT[11];
    		sum += adcObj->ADCRESULT[12];
    		sum += adcObj->ADCRESULT[13];
    		sum += adcObj->ADCRESULT[14];
    		sum += adcObj->ADCRESULT[15];
    	}
    
    	ADC_disableInt(myAdc, ADC_IntNumber_1);	/* Stop the ping-pong sampling. */
    	ADC_disableInt(myAdc, ADC_IntNumber_2);
    
    	adcConvMean = sum / ADC_OFFTRIM_CAL_SAMPLE_SIZE;	/* Average the sample data. */
    
    	ENABLE_PROTECTED_REGISTER_WRITE_MODE;
    	adcObj->ADCOFFTRIM = 80 - adcConvMean;	/* Set offtrim register with new value (i.e remove artical offset (+80) and create a two's compliment of the offset error). */
    	adcObj->ADCCTL1 &= ~(1 << ADC_ADCCTL1_VREFLOCONV_BIT); /* Connect B5 to back to the ADCINB5 pin. */
    	DISABLE_PROTECTED_REGISTER_WRITE_MODE;