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/TMS570LC4357: Getting values from multiple active ADC channels of one group with DMA

Part Number: TMS570LC4357
Other Parts Discussed in Thread: HALCOGEN

Tool/software: Code Composer Studio

Dear support Team,

first of all, thank you for the fast reply to my previous question: https://e2e.ti.com/support/microcontrollers/hercules/f/312/t/820493?CCS-TMS570LC4357-Read-multiple-ADC-channel-values-from-memory-with-DMA. 
Thanks to that, i finally managed to receive some data from my ADC. However, the data doesn't seem to be correct. 

The problem is, that only one channel conversion seems to be transferred. I send a constant signal of ~2.4 V to each of the three ( Channel 0, 7 and 18 are marked as active in HALGOGEN in adc group 1 ) adc channels. As you can see in the attachements, i try to get the results by addressing the ADC1 group 1 memory adress. For test purposes, I connected the signal to only one channel. Independently from the channel connected, the ADC1GROUP1 channel 0 adress delivered the right result ( ~ 3000 with an 12 BIT resolution ), whereas the other adresses had constant results of ~30500 and ~75000. So from my (beginner) point of view, it seems that all channel results are transferred to the adc1group1 base adress ( channel 0 ), instead of stacking up on each other until the group memory boundary is reached. 

P.S. When i don't use DMA and just poll the results, i can see that the channels are active and deliver the right results. So it seems to be an DMA ADC configuration issue. 

Thank you and kind regards,

Sebastian 

7536.PowerCalc_simple.zip

  • Hello Sebastian ,

    There are two ways to read the ADC conversion values:

    1. Read from the FIFO: The results are read out from the group’s memory region as a FIFO queue. The conversion result that get stored first is read out first..

    2. Read from results' memory: the base address for ADC1 is 0xFF3E_0000. The starting address of group1 is based on your ADC memory configuration (BNDA, BNDB, and BNDEND). I guess that the DMA request is generated when the conversion result from any channel (3 channels in your example) is written to the result's memory. Did you clear BLK_XFER bit in Group1 control register?

  • Hello Mr. Wang, 

    thank you again for the fast reply. I already read about the two ways ( Fifo, memory ) about getting the ADC conversion results in the user manual. I currently have, as you said, 3 channels active for conversion: channel 0, 7 and 18. If i understand it correctly ( My BNDA is set to 8) ,

    ADC1 base address + 2*4*BNDA   = results channel 0           [ e.g. 0xFF3E_0040]      

    ADC1 base address + 2*4*BNDA + 4 = results channel 7      [ e.g. 0xFF3E_0044]

    ADC1 base address + 2*4*BNDA  + 8 = results channel 18   [e.g. 0xFF3E_0048] . 

    In the attachement from my previsious post, you can find my whole project ( HalCoGen + HAL_sys_main ) . 
    I changes my ADC configurations ( ADC post INit function , line 167 ) to :

    void adcPostInit(adcBASE_t* adc){
    if(adc == adcREG1){
    adcREG1->G1DMACR |= (3 << 16); // number of group 1 result buffers to be transferred via DMA
    adcREG1->G1DMACR |= (1<< 0); // enable DMA , set G1DMA
    adcREG1->G1DMACR |= (1 << 2); // generates DMA request for each write to the group memory if G1DMA is set
    adcREG1->G1DMACR &= ~(1 << 3); // DMA request for each write to the group1 results RAM
    adcREG1->GxMODECR[1U] = (uint32)ADC_12_BIT
    | (uint32)0x00000030U //Channel ID and OVR_G1_RAM_IGN
    | (uint32)0x00000000U
    | (uint32)0x00000002U; //Continuous mode
    }

    }

    But it still doesn't work. I used 

    adc1_dmaCTRLPKT1.SADD = (uint32_t) 0xFF3E0000 + 4*(BNDA + 0); /* source address , here: ADC Base RAM Address */
    adc1_dmaCTRLPKT1.DADD = (uint32_t)&aADC1ConvertedData1[0]; /* destination address */
    adc1_dmaCTRLPKT1.CHCTRL = 0; /* next channel to be chained, 0 = disable chaining */
    adc1_dmaCTRLPKT1.FRCNT = 20000; /* frame count, num ADC samples*/
    adc1_dmaCTRLPKT1.ELCNT = 1; /* element count, num ADC channels*/
    adc1_dmaCTRLPKT1.ELDOFFSET = 0; /* element destination offset */
    adc1_dmaCTRLPKT1.ELSOFFSET = 0; /* element source offset */
    adc1_dmaCTRLPKT1.FRDOFFSET = 0; /* frame destination offset */
    adc1_dmaCTRLPKT1.FRSOFFSET = 0; /* frame destination offset */
    adc1_dmaCTRLPKT1.PORTASGN = 0; /* port B , always 0x100 for all TMS570 */
    adc1_dmaCTRLPKT1.RDSIZE = ACCESS_32_BIT; /* read size = 1 => 16bits */
    adc1_dmaCTRLPKT1.WRSIZE = ACCESS_32_BIT; /* write size */
    adc1_dmaCTRLPKT1.TTYPE = FRAME_TRANSFER; /* transfer type */
    adc1_dmaCTRLPKT1.ADDMODERD = ADDR_INC1; /* address mode read */
    adc1_dmaCTRLPKT1.ADDMODEWR = ADDR_INC1; /* address mode write */
    adc1_dmaCTRLPKT1.AUTOINIT = AUTOINIT_ON;

    this configuration to increment through the memory results and found, that only 1 adc conversion is transferred via DMA to the first entry of the field aADC1ConvertedData1. The results stored in 0xFF3E_0044 and 0xFF3E_0048 seem to be random numbers, that are even out of the 12 BIT resolution range. 

    Maybe you can have a look inside my project and tell me what is wrong? 

    Thank you and kind regards,

    Sebastian 

     

    P.S. : My BNDA variable in the code is actually 2*BNDA. That is why the *2 is missing. 

     

  • Hello Sebastian,

    If you have 3 channels, please try ELCNT=3, ELSOFFSET=4 (bytes), FRSOFFSET=0.

    1. Element 1 is data of buffer[0], ADC channel 0

    2. Element 2 is data of buffer[1], ADC channel 7

    3. Element 3 is data of buffer[2], ADC channel 18

  • Hello Mr. Wang,

    so like this: 

    -------------------------------- Buffer -------------------------------------

    uint32 aADC1ConvertedDataBuff[3] = {0};

    -------------------------------- ADC Init -------------------------------------

    void adcPostInit(adcBASE_t* adc){
    if(adc == adcREG1){
    adcREG1->G1DMACR |= (3 << 16); // number of group 1 result buffers to be transferred via DMA
    adcREG1->G1DMACR |= (1<< 0); // enable DMA , set G1DMA
    adcREG1->G1DMACR |= (1 << 2); // generates DMA request for each write to the group memory if G1DMA is set
    adcREG1->G1DMACR &= ~(1 << 3); // DMA request for each write to the group1 results RAM
    adcREG1->GxMODECR[1U] = (uint32)ADC_12_BIT
    | (uint32)0x00000030U //Channel ID and OVR_G1_RAM_IGN
    | (uint32)0x00000000U
    | (uint32)0x00000002U; //Continuous mode
    }

    }

    -------------------------------- Read Results 1: FIFO  -------------------------------------

    adc1_dmaCTRLPKT1.SADD = (uint32_t)&adcREG1->GxBUF[1]; /* source address , here: ADC Base RAM Address */
    adc1_dmaCTRLPKT1.DADD = (uint32_t)&aADC1ConvertedDataBuff[0]; /* destination address */
    adc1_dmaCTRLPKT1.CHCTRL = 0; /* next channel to be chained, 0 = disable chaining */
    adc1_dmaCTRLPKT1.FRCNT = 1; /* frame count, num ADC samples*/
    adc1_dmaCTRLPKT1.ELCNT = 3; /* element count, num ADC channels*/
    adc1_dmaCTRLPKT1.ELDOFFSET = 4; /* element destination offset */
    adc1_dmaCTRLPKT1.ELSOFFSET = 0; /* element source offset */
    adc1_dmaCTRLPKT1.FRDOFFSET = 0; /* frame destination offset */
    adc1_dmaCTRLPKT1.FRSOFFSET = 0; /* frame destination offset */
    adc1_dmaCTRLPKT1.PORTASGN = 0; /* port B , always 0x100 for all TMS570 */
    adc1_dmaCTRLPKT1.RDSIZE = ACCESS_32_BIT; /* read size = 1 => 16bits */
    adc1_dmaCTRLPKT1.WRSIZE = ACCESS_32_BIT; /* write size */
    adc1_dmaCTRLPKT1.TTYPE = FRAME_TRANSFER; /* transfer type */
    adc1_dmaCTRLPKT1.ADDMODERD = ADDR_OFFSET; /* address mode read */
    adc1_dmaCTRLPKT1.ADDMODEWR = ADDR_INC1; /* address mode write */
    adc1_dmaCTRLPKT1.AUTOINIT = AUTOINIT_ON; /* autoin

    -------------------------------- Read Results 2 : RAM  -------------------------------------

    adc1_dmaCTRLPKT1.SADD = (uint32_t)(0xFF3E0000 + 4*BNDA); /* source address , here: ADC Base RAM Address */
    adc1_dmaCTRLPKT1.DADD = (uint32_t)&aADC1ConvertedDataBuff[0]; /* destination address */
    adc1_dmaCTRLPKT1.CHCTRL = 0; /* next channel to be chained, 0 = disable chaining */
    adc1_dmaCTRLPKT1.FRCNT = 1; /* frame count, num ADC samples*/
    adc1_dmaCTRLPKT1.ELCNT = 3; /* element count, num ADC channels*/
    adc1_dmaCTRLPKT1.ELDOFFSET = 4; /* element destination offset */
    adc1_dmaCTRLPKT1.ELSOFFSET = 0; /* element source offset */
    adc1_dmaCTRLPKT1.FRDOFFSET = 0; /* frame destination offset */
    adc1_dmaCTRLPKT1.FRSOFFSET = 0; /* frame destination offset */
    adc1_dmaCTRLPKT1.PORTASGN = 0; /* port B , always 0x100 for all TMS570 */
    adc1_dmaCTRLPKT1.RDSIZE = ACCESS_32_BIT; /* read size = 1 => 16bits */
    adc1_dmaCTRLPKT1.WRSIZE = ACCESS_32_BIT; /* write size */
    adc1_dmaCTRLPKT1.TTYPE = FRAME_TRANSFER; /* transfer type */
    adc1_dmaCTRLPKT1.ADDMODERD = ADDR_OFFSET; /* address mode read */
    adc1_dmaCTRLPKT1.ADDMODEWR = ADDR_INC1; /* address mode write */
    adc1_dmaCTRLPKT1.AUTOINIT = AUTOINIT_ON; /* autoin

    -------------------------------- END  -------------------------------------

    Both of these options don't work properly. I send a 2.5 V DC Signal to ADC1 channel 0 and a 1.66 V DC signal to ADC1 channel 7 and 18. The configurations can be found in the previous attachement ( HalCoGen Project ). 

    What i receive with option 1 for my buffer :  

    buffer[0] = ~3000, ( 2.5 V signal ) 
    buffer[1] = ~460000,
    buffer[2] = ~1180000. 

    Option 2 : 

    buffer[0] = buffer[1] = buffer[2]  = ~3000 

    there is a slight difference between the buffer signals, but they all come from the 2.5 V DC signal ( channel 0 ). 

    If I remove the 2.5 V signal on channel 0, the results are the same expect I can see the 1.66 V signal ( ~2000). So the channels 7 and 18 are indeed active. 

    Thank you for your help. I really tried to solve this problem on my own but I just don't succeed. 

    Kind regards,

    Sebastian 

  • Hi Sebastian,

    The problem is caused by the combination of the ADC circuitry and ADC configuration. The time constant of the RC circuitry at ADC input is bigger than the sampling time, the capacitor is not fully charged. Please increase the ADC sample time. You use single mode rather than continuous mode for doing this test.

  • Dear Mr. Wang,

    unfortunately this did not resolve my issue. When I use a regular conversion without DMA, the data seems to be just fine, so it can't be an issue of the sample time? The result order, however, is not fixed. 

    In the meantime, i switched to a TMS570LS Launchpad and implemented the same procedure and still get the same results.

    It works without using DMA. With using dma, only 1 Channel seems to be converted. 

    Maybe we can somehow discuss this in private? I would really appreciate it. 

    Thank you very much for your support so far Mr. Wang!

    Kind regards,

    Sebastian 

  • Dear Mr. Wang,

    I now have changed the FIFO size in HalCoGen to the number of ADC channels that i used...  
    Then, if I use the Fifo Adress instead of the group1 memory adress, the DMA transfer works perfectly.

    So my issue is resolved. Thank you for the support and the oppurtunity to gain a lot of knowledge.

    Kind regards,

    Sebastian