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.

TMS570LS0914: ADC G2_Thr falls below 0

Part Number: TMS570LS0914

Dear Ti support,

 

We found a potential bug / undocumented behaviour in the ADC module in connection with the DMA module.

We have found a workaround that works for us, but hopefully you can review it or give us alternative.

 

First, let me explain our setup:

We are using 21 adc channel from the TMS.

17 Channel are in group 1 and will be triggered by the SW. The channels are triggered by a Task (SafeRTOS) using the function adc_TMS570LS_getADCValue (see below)

 

4 channel are in group 2 and are triggered as a group conversion by RTI_COMP_0.

Every group conversion should trigger a DMA request, which then copies the group buffer into RAM.

The DMA is configured as follows:

  • 8 elements per frame ( = ADC group 2 fifo size)
  • Element size 32bit
  • Frame Transfer

 

The RTI_COMP_0 timer is also used as the systick interrupt for the OS. (1000hz frequency)

 

We have noticed, that after an undefined but certain time the G2_Thr is  decreasing slowly from 8(=FifoSize = ElementCount) to 0.

When G2_Thr reaches 0, the DMA request is triggered more frequently and the values read by DMA are invalid. 

We have understood that the G2_Thr decreases if we are start the conversion and it increases again, if it is not read.

 

We expect the following behavior:

  • Every 1ms the ADC conversions are triggered
  • 4 valid ADC values are written into the group2 buffer
  • DMA is triggered after successfully writing the 4 ADC values into the group buffer
  • DMA copies the whole group buffer (8 elements) into the configured RAM section.
  • So every 1ms we should see 4 new adc values in the RAM

 

In our system we also use CAN-nodes. If we increase the bus load on CAN, we noticed that the value of G2_Thr decreases faster.

At the same time, the  adc channel triggered by SW times out more often (check adc_TMS570LS_getADCValue).

 

To us it appears there are two issues:

  1. Collisions between manual ADC conversions triggered by the Software and automatic conversions triggered directly via RTI can happen
  • Is there any Documentation on that collisions can happen? If so, how to prevent collisions?

 

  1. After a collision happens, DMA is requested too quickly
  • We expect a DMA request to happen only when 4 valid ADC values have been written

 

In identifying the problem, we developed a workaround that works for us, but we need you to verify it.

  1. we set the HW-trigger source to NHET-14
    1. so that the trigger timing is shifted and independent of the RTI
  2. We check G2_Thr in our SW and if it falls below 5, then:
    1. Reset Fifo:                                                                 adc[0]->GxFIFORESETCR[2] = 1;
    2. Clear Conversion Endflag and Threshold IRQ Flag,   adc[0]->GxINTFLG[2] = 9;
    3. Set Threshold Counter to 8;                                         adc[0]->GxINTCR[2] = 8;
    4. Set G2_Blocks to 8:                                                     adc[0]->G2DMACR= 0x0008000D;
  3. Enable Group1 Conversion End Interrupt Enable
    1. So the SW-triggered ADC conversions do not timeout.

 

Here are our code functions:

ADC_STATUS_t adc_TMS570LS_getADCValue(const ADC_SignalConfig* signal, uint16_t* adcValue)

{

    ADC_STATUS_t adcStatus  = ADC_FAILRUE;

    ADC_DATA_t convData[22] = { 0 };

    uint8_t adcPortIndex = (signal->port == ADC_PORTA) ? 0 : 1;

 

    adc_TMS570LS_startConversion(signal); /* Aquire Conversion Data */

 

    if((adcReg[adcPortIndex]->GxSEL[signal->group] != 0U))

    {

            uint16_t timeout = 0xffff;

            // wait for completion

            while(!adc_TMS570LS_isConversionComplete(signal) && timeout)

            {

                timeout--;

            }

            if(timeout != 0u)

            {

                 adc_TMS570LS_getData(signal, convData);

                *adcValue = convData[0].value;

                adcStatus = ADC_SUCCESS;

            }

            else

            {

                adcStatus = ADC_TIMEOUT;

            }

    }

    return adcStatus;

}

adc_TMS570LS_getData:

static uint32_t adc_TMS570LS_getData(const ADC_SignalConfig* signal, ADC_DATA_t* data)

{

    uint32_t count = UINT32_MAX;

    uint8_t adcPortIndex = (signal->port == ADC_PORTA) ? 0 : 1;

 

        uint32_t buf;

        uint32_t intcr_reg = adcReg[adcPortIndex]->GxINTCR[signal->group];  // polyspace RTE:NIV [Justified]

        ADC_DATA_t* ptr    = data;

 

        uint32_t count = (intcr_reg >= 256U) ? FiFoSize[adcPortIndex] : (FiFoSize[adcPortIndex] – (intcr_reg & 0xFFU));

 

        if((adcReg[(uint8_t)signal->port - 1u]->OPMODECR & 0x80000000U) > 0)  // if ADC configured for 12-Bit resolution

        {                                                                    

            /** -  Get conversion data and channel/pin id */

            for(uint32_t i = 0U; i < count; i++)

            {

                buf        = adcReg[adcPortIndex]->GxBUF[signal->group].BUF0;  // polyspace RTE:NIV [Justified]

                ptr->value = (uint16)(buf & 0xFFFU);

                ptr->id    = (uint32)((buf >> 16U) & 0x1FU);

                ptr++;

            }

       }

    adcReg[adcPortIndex]->GxINTFLG[signal->group] = 9U;

 

    return count;

}

Best Regards,

Thorben