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.

CCS/F28M36P63C2: ADCRESULT2 does not update

Part Number: F28M36P63C2


Tool/software: Code Composer Studio

Hello all,

i am having an issue i with my ADC configuration. Please see attached images. There are three sinusoidal sync pulses of same amplitude but different phases being read by three ADC channels. Each of the channels have to read this sync pulse and an additional DC offset calibrated in my docking board. The ADC conversions of the three inputs are SOC2, SOC3 and SOC4. But when i look at the ADC results in the watch window(see image attached of watch window),  I can only see SOC3 and SOC 4 update its values. SOC2 remains frozen and only reads the DC offset much like other ADC results in the image. What could cause this to happen?? i can rule out hardware issues as i measured the offset on the respective pins and also measure the sync pulses to be identical in amplitude and physically checked if that voltage is being fed into all three pins.

The issue is only with SOC2 and the peculiar thing is when i change SOC2 to other adc channels, the problem persists, which leads me to believe it must be something to do with the ADC configuration.

my ADC config code is below. And i verified that  Adc1Regs.ADCSOCFRC1.all register is set to 0x007f and that there are no overwrites to this value.

void ConfAdc(void)
{

	// Configure ADC
	    EALLOW;

	    Adc1Regs.ADCCTL2.bit.ADCNONOVERLAP = 1;     // Enable non-overlap mode i.e.
	                                                // conversion and future
	                                                // sampling
	                                                // events dont overlap

	    Adc1Regs.ADCCTL1.bit.INTPULSEPOS   = 1;     // ADCINT1 trips after
	                                                // AdcResults latch

	    Adc1Regs.INTSEL1N2.bit.INT1E       = 1;     // enable ADCINT1

	    Adc1Regs.INTSEL1N2.bit.INT1CONT    = 0;     // Disable ADCINT1 Continuous
	                                                // mode

	    Adc1Regs.INTSEL1N2.bit.INT1SEL     = 6;     // Setup EOC6 to trigger ADCINT1
	                                                // to fire
	    Adc1Regs.ADCINTSOCSEL1.all = 0x0000; 	// No ADCInterrupt will trigger SOCx
	    Adc1Regs.ADCINTSOCSEL2.all = 0x0000;
//	    Adc1Regs.ADCSOC0CTL.bit.CHSEL      = 0x4;   // Set SOC0 channel select to
//	                                                // ADC1A4 for Vout
	    Adc1Regs.ADCSOC0CTL.bit.CHSEL      = 0x2;   // Set SOC0 channel select to
	                                                // ADC1A2 for Vout
	    Adc1Regs.ADCSOC1CTL.bit.CHSEL      = 0x7;   // Set SOC1 channel select to
	                                                // ADC1A7, for Iout
//	    Adc1Regs.ADCSOC1CTL.bit.CHSEL      = 0x3;   // Set SOC1 channel select to
//	                                                // ADC1A3, for Iout
	    Adc1Regs.ADCSOC2CTL.bit.CHSEL      = 0x8;   // Set SOC2 channel select to
	                                                // ADC1B0,for VinA
	    Adc1Regs.ADCSOC3CTL.bit.CHSEL      = 0xb;   // Set SOC3 channel select to
	                                                // ADC1B3,for VinB
	    Adc1Regs.ADCSOC4CTL.bit.CHSEL      = 0xf;   // Set SOC4 channel select to
	                                                // ADC1B7,for VinC
	    Adc1Regs.ADCSOC5CTL.bit.CHSEL      = 0x3;   // Set SOC5 channel select to
	                                                // ADC1A3,for VoltagePot
	    Adc1Regs.ADCSOC6CTL.bit.CHSEL      = 0x4;   // Set SOC6 channel select to
	                                                // ADC1A4,for CurrentPot

	    AnalogSysctrlRegs.TRIG1SEL.all     = 0;     // Assigning ADC Trigger 1 to Nothing
//	    AnalogSysctrlRegs.TRIG1SEL.all     = 5;     // Assigning EPWM1SOCA to
//	                                                // ADC TRIGGER 1 of the ADC module

	    Adc1Regs.ADCSOC0CTL.bit.ACQPS      = 6;     // Set SOC0 S/H Window to 7 ADC
	                                                // Clock Cycles, (6 ACQPS plus
	    Adc1Regs.ADCSOC1CTL.bit.ACQPS      = 6;     // Set SOC1 S/H Window to 7 ADC
	                                                // Clock Cycles, (6 ACQPS plus
	    Adc1Regs.ADCSOC2CTL.bit.ACQPS      = 6;     // Set SOC2 S/H Window to 7 ADC
	                                                // Clock Cycles, (6 ACQPS plus
	    Adc1Regs.ADCSOC3CTL.bit.ACQPS      = 6;     // Set SOC3 S/H Window to 7 ADC
	                                                // Clock Cycles, (6 ACQPS plus
	    Adc1Regs.ADCSOC4CTL.bit.ACQPS      = 6;     // Set SOC4 S/H Window to 7 ADC
	                                                // Clock Cycles, (6 ACQPS plus
	    Adc1Regs.ADCSOC5CTL.bit.ACQPS      = 6;     // Set SOC5 S/H Window to 7 ADC
	                                                // Clock Cycles, (6 ACQPS plus
	    Adc1Regs.ADCSOC6CTL.bit.ACQPS      = 6;     // Set SOC6 S/H Window to 7 ADC
	                                                // Clock Cycles, (6 ACQPS plus

//	    AdcRegs.ADCINTFLG.bit.ADCINT1 = 0;
	    AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;// clear interrupt flag for ADCINT1
	    AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 5;			//SOC0 from Analog Trigger 1
	    AdcRegs.ADCSOC1CTL.bit.TRIGSEL = 5;			//SOC1 from Analog Trigger 1
	    AdcRegs.ADCSOC2CTL.bit.TRIGSEL = 5;			//SOC2 from Analog Trigger 1
	    AdcRegs.ADCSOC3CTL.bit.TRIGSEL = 5;			//SOC3 from Analog Trigger 1
	    AdcRegs.ADCSOC4CTL.bit.TRIGSEL = 5;			//SOC4 from Analog Trigger 1
	    AdcRegs.ADCSOC5CTL.bit.TRIGSEL = 5;			//SOC5 from Analog Trigger 1
	    AdcRegs.ADCSOC6CTL.bit.TRIGSEL = 5;			//SOC6 from Analog Trigger 1

		Adc1Regs.ADCSOCFRC1.bit.SOC0 = 1; 				// kick-start ADC
		Adc1Regs.ADCSOCFRC1.bit.SOC1 = 1; 				// kick-start ADC
		Adc1Regs.ADCSOCFRC1.bit.SOC2 = 1; 				// kick-start ADC
		Adc1Regs.ADCSOCFRC1.bit.SOC3 = 1; 				// kick-start ADC
		Adc1Regs.ADCSOCFRC1.bit.SOC4 = 1; 				// kick-start ADC
		Adc1Regs.ADCSOCFRC1.bit.SOC5 = 1; 				// kick-start ADC
		Adc1Regs.ADCSOCFRC1.bit.SOC6 = 1; 				// kick-start ADC

	    EDIS;
}

Any suggestion is greatly appreciated,

Thank you,

Srini

  • Srini,

    Can you replace the individual SOCFRC bit sets with a single write in the initialization block? Or even remove them if they are not necessary?

    Adc1Regs.ADCSOCFRC1.bit.SOC0 = 1; // kick-start ADC
    Adc1Regs.ADCSOCFRC1.bit.SOC1 = 1; // kick-start ADC
    Adc1Regs.ADCSOCFRC1.bit.SOC2 = 1; // kick-start ADC
    Adc1Regs.ADCSOCFRC1.bit.SOC3 = 1; // kick-start ADC
    Adc1Regs.ADCSOCFRC1.bit.SOC4 = 1; // kick-start ADC
    Adc1Regs.ADCSOCFRC1.bit.SOC5 = 1; // kick-start ADC
    Adc1Regs.ADCSOCFRC1.bit.SOC6 = 1; // kick-start ADC

    Can you read back the ADCSOCFLG1 register contents into a variable immediately after setting the ADCSOCFRC1 register? This will sanity check that the ADC is receiving the correct force triggers.

    Also check on the *OVF registers to see if there are any issues.

    -Tommy
  • Hey Tommy,

    I removed the individual assignments to SOCFRC bits. it did not fix the issue. ADCResult2 still won't read the sync input.

    I declared a variable "Uint16 ADCReadCheck " to store the contents of the ADCSOCFLG1 register immediately after setting the ADCSOCFRC1 register as shown below,

    		if(SystemTag.bit.StartTag)
    		{
    			EALLOW;
    			Adc1Regs.ADCSOCFRC1.all = 0x007f;   
    			EDIS;
    
    			ADCReadCheck=Adc1Regs.ADCSOCFLG1.all;
    		}

    ADCReadCheck reads a value that keeps changing 63,95,111 and 125. And the contents of ADCINTOVF register is 0x0001 and that of the ADCSOCOVF1 is also 0x007F.

    When i stop my system and generate the cycle by cycle trip, ADCReadCheck reads a value of 125. Not sure what to make of this because the decimal equivalent of 0x007F is 127.

    Thanks,

    Srini

  • Srini,

    It would seem that there might be some servicing deadline issues. The OVF flags should be 0 when the system is operating as intended. Make sure that you also clear the OVF status flags during initialization.

    Are you servicing the ADCINT using an ISR? You might try to read the SOCFLG value before writing the SOCFRC bits. You can use an if/then statement to provide a place to set a breakpoint if SOCFLG is non-zero. This will help you track down the sequence that leads up to the SOCOVF.

    -Tommy
  • Srini,

    It has been a while since your last update. I assume that you were able to resolve your issue. If this isn’t the case, please reject this resolution and reply to this thread. If this thread is locked, please make a new thread describing the current status of your issue.

    -Tommy
  • Hey tommy,

    I still haven't been able to fix the issue. The ADC register "ADCSOCOVF1" gets set to 0x007f indicating that there was an overflow on each of the SOC's. This does not stop the process but this makes the system miss triggers because an SOC was initiated before the EOC was achieved. Does merely setting the respective bits in the ADCSOCOVFCLR1 and clearing the overflow fix this issue? will that make the system not miss any triggers?

    I am servicing the ADC using ADCint1 and i have disabled the continuous mode.

    Following are the code changes i have made upon your previous suggestion,

    I added these two lines to the initialization function

    Adc1Regs.ADCINTOVFCLR.bit.ADCINT1  = 1;      
    Adc1Regs.ADCSOCOVFCLR1.all         = 1;

    I added the SOCFLAG check before setting the ADCSOCFRC1 bits,

    		if(Adc1Regs.ADCSOCFLG1.all==0x0000)
    		{
    		EALLOW;
    		Adc1Regs.ADCSOCFRC1.all = 0x007f; //Enable SOC
    		EDIS;
    		ADCReadCheck=Adc1Regs.ADCSOCFLG1.all;
    		}



    Srini

  • Srini,

    Clearing the bits will not solve the root cause of your overflow issue, however it is important to design your system so that they are handled properly because they have the potential to disrupt the normal operation of interrupt triggering.

    Do note that you will need to clear all of the SOCOVF bits so your Adc1Regs.ADCSOCOVFCLR1.all  = 1 instruction will need to be expanded.  If you are doing this once during initialization, you may as well clear all SOCs with Adc1Regs.ADCSOCOVFCLR1.all = 0xFFFF;

    With respect to checking SOCFLG, make sure that you add an else condition with an ESTOP or placeholder instruction (like NOP) for setting a breakpoint. Whenever your execution halts there, you can try to trace back the events that led up to the impending overflow.

    -Tommy

  • I understand, i think the changes fixed the overflow issue in ADCINTOVF and ADCSOCOVF1 registers. But that did not solve my issue regarding SOC2. it still does not read the sync pulse.
  • Srini,

    Can you do a sanity check of the ADC registers through the watch window or memory browser? I cannot think of a reason why SOC2 would not trigger unless its configuration (like ADCINTSOCSEL) was overwritten.

    -Tommy
  • ADCINTSOCSEL1 has been assigned a value of 0x0000 in the initialization function and that register is not reassigned or accessed elsewhere. i don't see anything peculiar when i do the sanity check. Except that ADCSOCFLG1.all, reads 0x0000 and transitions periodically to 0x0078. The corresponding variable that stores the result of ADCSOCFLG1.all reads 126. That read command is just after i assign the ADCSOCFRC1 bits.
  • What is the value of SOCPRICTL just before forcing the conversions?
  • it reads a value of 0x00C0 (192).
  • Srini,

    0x00C0 looks right. The value of ADCSOCFLG1=0x78 does not make sense to me because it would imply that the SOCs were forced or processed out of order. You may want to confirm that it is just a CCS refresh artifact rather than the actual ADCSOCFLG1 value.

    What happens if you software force trigger SOC2 by itself? Does it run?

    -Tommy
  • Hey Tommy,

    You were right, that was a CCS refresh issue. The ADCSOCFLG1 reads 0x0000 in the watch window. And as was the case previously, the OVF registers are also 0x0000.

    By software force trigger, do you mean setting the appropriate SOC bit in ADCSOCFRC1 register?? if so, where would you recommend i do it?? in the initialization function or in the condition block below,

    		if(Adc1Regs.ADCSOCFLG1.all==0x0000)
    		{
    		EALLOW;
    		Adc1Regs.ADCSOCFRC1.all = 0x007f; //Enable SOC
    		EDIS;
    		ADCReadCheck=Adc1Regs.ADCSOCFLG1.all;
    		}

    Thanks,

    Srini

  • Srini,

    Based on your original problem statement that ADCRESULT2 is not updating, I would like to focus just on SOC2. The idea would be to trigger only SOC2 in the conditional block where you would normally trigger all conversions. I would not recommend triggering any SOCs in your initialization routine unless it is kicking off a self-sustaining background triggering scheme.

    -Tommy
  • Hey tommy,

    Individual software force triggering did not get ADCResult2 to update. Infact i have been checking every step of my hardware configuration and they all check out. I have even assigned different hardware pins and channels to SOC2, it won't update. It really is very peculiar. I have even replaced all my hardware with new boards and that hasn't helped.

    I still find it odd that the variable "ADCReadCheck=Adc1Regs.ADCSOCFLG1.all;" always reads 126.

    Thanks,

    Srini

  • Srini,

    The read back value of 126 is not unexpected. The SOCFLG bits indicate pending SOCs to be processed. Once the conversion process begins, the bit is cleared. When you force SOCs 0 through 6, SOC0 is the first to be processed so its status will clear very quickly. Given the ACIB latency, you will probably not be able to read back 127.

    The setting of SOCFLG[2] and subsequent clearing means that the SOC is being processed. How are you determining if ADCRESULT2 has updated? From your previous screenshot, the ADCRESULT2 register is highlighted yellow meaning that it updated since that last read.

    -Tommy
  • Tommy,

    When i said ADCResult2 does not get updated, what i mean is i am feeding sinusoidal pulses to the three channels whose corresponding ADC readings are reflected by ADCResult2, 3 and 4. While the ADCResult3 and ADCResult4 update and change their values according to the sinusoidal input, ADC result2 does not recognize it. it stays frozen and just reads the inherent 1.5V DC offset. (sown in the screenshot as 0x0749).

    issue is with the ADCResult2 not reading the sine wave?

    Thanks,
    Srini
  • Tommy,

    i made a few hardware changes and ran the system again, ADCResult2 will still not recognize the sine wave. But more importantly, i believe my ADC interrupt overflows. ADCINTOVF gets set to 0x0001. The ADCSOCFLG still is 0x0000. i will have to troubleshoot where the interrupt overflows and then maybe i will get a clearer picture as to why the ADCResult2 will not recognize.

    I have assigned Adc1Regs.ADCINTFLGCLR.bit.ADCINT1 to 1, any idea why it still causes the overflow. do i have to reduce my interrupt frequency to accommodate all the SOC's? could that be the reason?

    Thanks for your time and assistance,
    Srini
  • Srini,

    Thanks for clarifying the issue.  I was interpreting "update" strictly from a hardware register standpoint.

    Yes, I would recommend that you slow down the SOC trigger frequency until the overflow goes away.  You can try disabling all other ISRs as well.  Since there is no interrupt nesting on the C28, a long ISR can often block other ISR activity long enough to cause an overflow.

    -Tommy

  • How can i slow down the trigger frequency?
  • Srini,

    And to confirm my understanding, the B0 channel assigned to SOC2 is working? For example, if you swap B0 to SOC3, then it does convert correctly?

    -Tommy
  • Srini,

    Most applications use a time-based module to trigger the ADC conversions like the adc_soc and epwm_adc_soc examples. Then it's a simple matter of adjusting the module count for triggering.

    If you are manually forcing in the background loop, you would have to resort to something less elegant like using a wait loop or using some rudimentary handshaking flags between the ADC ISR and background loop.

    Have you tried different ACQPS values? There's a possibility of carryover crosstalk between SOC1 and SOC2 if ACQPS is too small.

    -Tommy
  • Yes, that's right. I get an accurate conversion for every SOC except SOC2. Conversely, setting the input going into B0 to other SOC's also checks out. Setting the Channel BO to another SOC also works well.
  • I understand, I will give this a try and get back to ou with my observations. Thanks for your time.

    Srini
  • Srini,

    It has been a while since your last update. I assume that you were able to resolve your issue. If this isn’t the case, please reject this resolution and reply to this thread. If this thread is locked, please make a new thread describing the current status of your issue.

    -Tommy
  • Hey Tommy,

    I wasn't able to resolve the issue with different ACQPS values. I decided to decrease my ISR frequency and reduce the number of conversions to 4 and SOC2 now reads the sync signal. I had to cut corners in my design to get my way around the issue. I still can't put a finger on why it wouldn't read the sync input as per previous design and why the OVF occurred.

    Thanks,
    Srini
  • Srini,

    My focus had been on trying to understand why SOC2 was not updating. Since the device is showing signs of life, we can dig into the overflow some more. How much time are you allowing between ADC triggers?

    Assuming that your C28x is running at 150MHz with /4 ADC clock, the ADC is running at 37.5MHz (26.67ns).

    With ADC Non Overlap mode and ACQPS=6, each conversion will take 6+1 [ACQPS] + 13 [Conversion] = 20 cycles. For 7 SOCs, that is 140 cycles x 26.67ns = 3.73us.

    The non-optimized read of 7 ADC conversions across the ACIB bus, you would require 10 [ACIB] x 7 [SOCs] = 70 cycles, giving us another 1.87us.

    So without taking into account any optimization or ACIB activity from the ISR, the ADC cannot support the 7 SOCs any faster than 3.73us + 1.87us = 5.6us.

    -Tommy
  • I understand, that is almost definitely why i was having the Overflow issue. Maybe i could have just adjusted the module count and given sufficient time between the triggering. The new design with only 4 conversions and slower interrupts do not have an OVF problem and i can get an accurate reading of the sync inputs. But i will still try and get it to work with the older design. Maybe i will try to set the Interrupt period to under 5.6us and see if that fixes both issues. Thanks a bunch.
  • Srini,

    A couple of tips that may help to improve your system performance:

    1. Triggering the ADCINT on say SOC4 would reduce the ACIB read penalty by allowing the CPU to read SOC0-SOC4 while SOC5-SOC6 are converting, and
    2. The SOCs can be distributed between the two ADCs so that they convert in parallel, which will improve the overall conversion time

    -Tommy

  • I understand, Thank you.