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.

Piccolo controlSTICK ADC speed seems too slow

Hello

I am experimenting with the 28027 Piccolo controlSTICK and have been unable to reach 4.6 MSPS - perhaps there is a clock divider or something I am missing?

I am using InitSysCtrl(), InitPieCtrl(), InitPieVectTable(), InitAdc() as used in the adc_soc and adc_temp_sensor project examples. Using the following C code:

AdcRegs.ADCSOCFRC1.bit.SOC0 = 1;
while(AdcRegs.ADCCTL1.bit.ADCBSY) continue;
*bufPtr++ = AdcResult.ADCRESULT0;

This executes in 46 CPU cycles according to the timer in code composer. At a 60MHz clock this appears to correspond to 1.3 MSPS, and timing 10 million executions with a stopwatch takes over 10 seconds, indicating a sampling speed closer to 800 kSPS

Using interrupts and ePWM trigger as in the example results in even slower execution, probably due to the overhead of continually saving and reloading the CPU registers.

I was hoping to be able to sample at ~1 MSPS and have a few clock cycles spare for an optimised asm iir filtering routine - is there any way to achieve this on this MCU?

Thanks for your consideration

  • The ADC can continuously sample at 4.6msps (13 cycles conversion time at 60Mhz) where it takes advantage of each sequential sample overlapping the current sample's conversion. However, the very first sample from a ePWM or software trigger, etc., takes 22 cycles at 60Mhz (~2.7msps). Refer to Section 1.11 ADC timings in the user's guide for more details: http://www.ti.com/litv/pdf/spruge5b.

    Not sure why you observed only 1.3msps. Try running the adc_soc example as is and check the sample rate you get.

    How many consecutive sample are you wanting to take before crunching the converted data? I recommend using the ADCINTs (i.e. while(AdcRegs.ADCINTFLG.bit.ADCINT1){//wait for adc to finish conversion} ) instead of ADCBSY to help with timing the ISR call. Also, use the early interrupt feature (set AdcRegs.ADCCTL1.bit.INTPULSEPOS = 0), so that you can begin your ISR before the the ADC finishes converting, not wasting dead cycles. Referring to Section 1.11 for the timings.

    Regards,

    Nicholas Smith

  • One additional suggestion: Enable XCLKOUT on GPIO18 via GPAMUX2 selection and confirm you are running at 60mhz. By default, XCLKOUT = SYSCLK / 4.

    If you are only observing 1.3msps, you might be running at only 30Mhz.

    Regards,

    Nicholas Smith

  • Hi Nicholas, thanks for your quick reply.

    As you suggested I am now looking at the speed of the adc_soc example. As I understand it, it should run at 458 S/s since the ePWM clock is SYSCLK / 2 == 30MHz by default and the TBPRD register is set to 0xFFFF. This works out correctly as it takes approximately 22 seconds for ConversionCount to reach 10000 (~455 S/s), so I expect the clock is correct. However, as I decrease TBPRD the sampling rate appears to approach a limit.

    I modified the ISR just a little:


    Voltage1[ConversionCount%10] = AdcResult.ADCRESULT0;
    Voltage2[ConversionCount%10] = AdcResult.ADCRESULT1;

    // If 20 conversions have been logged, start over
    if(ConversionCount == 10000)
    {
      ConversionCount = 0;
      if(count2 == 500) {
        count2 = 0;
      } else count2++;
    }
    else ConversionCount++;

    Setting TBPRD to 0x0020 (and decreasing CMPA so conversion is still triggered) should result in a conversion rate of 909 kS/s according to the equation in section 2.2.3 of the ePWM note (spruge9c). I measure a wall time of 11 seconds to reach a breakpoint at 'count2 = 0;' , corresponding to a sampling rate of just 455 kS/s. If I want 1 MS/s I understand I should set TBPRD to 0x001E. In this case the breakpoint never triggers - I assume because interrupts are being fired faster than they can be acknowledged.

    I was hoping to be able to sample at 1 MS/s and have enough spare cycles to run a 9-tap assembly down-sampling filter in real time - surely this should be possible if the ADC is capable of running at 4.6 MS/s?

  • On a related point - you suggest using the ISRs but if I can avoid this without compromising the modularity of the application would it not be faster to poll the ADCBSY register to avoid the context switching overhead in a relatively short ISR? I imagine this is dependent on the instruction pipelining scheme wrt. the conditional branch statement that would introduce

    Could the slowness perhaps be due to the debugging procedure? I am not familiar with the internals of JTAG debugging - would the presence of additional breakpoints or watches slow the effective CPU speed?