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.

DMA and ADC Problem

Other Parts Discussed in Thread: HALCOGEN

Hi all,

I do not manage so far to have a functionnal ADC and DMA on the TMS570L or RM48x.

My sequence is :

After having initialised the adc module, with all the 64 buffers on the group1 of ADC1 (2 x 32), I start the continuous conversion on pin0 using :

adcREG1->G1DMACR |= 0x00400005;    // =>  1 block of 64 values  should be converted

and not :            adc->GxINTCR[group] = s_adcFiFoSize[index][group];             which is using interrupt threshold as specified in the user manual.

I start the conversion by : adc->GxSEL[group] = s_adcSelect[index][group]; // write on pin0 tu strat conversion

I go on with dmaEnable, and assign the chanel 0 on request 1,

then configure the DMApacket to read at the ADC Memory 0xFF3E0000, and not the Fifo implementation (ADC1BUFF).

The value should be written in an array of size 64. 

then dmaSetcCtrPacket, and dmaSetChanel.

 

What I observe is that 1 DMA request is well done but after I can't read new value of ADC anymore.

After  one go, I have in the register and that never change

G1IntCtrl 0x00000000 

...

G1DmaCtrl 0x00000005 

Is there someone to help me on that ? I can share the example

Tks.

  • Brice,

    I would suggest the following.

    (1) In your ADC settings, the buffer size is 64. Since it takes time for DMA to read the data, You need to make the DMA block size smaller so that no input data will be missed in continuous conversion mode. For example, adcREG1->G1DMACR |= 0x00200005;    // =>  DMA request is generated after 32 converted data are saved to buffer. For debugging purpose, you may want to enable the channel ID information in the converted data.

    (2) On the DMA side, read from the ADC FIFO as a fixed address. In this way, you do not need to worry about the actual address the new data is save in ADC RAM. Set the block transfer of two frames. Each frame contains 32 32bit data element. Use ADC to trigger the frame transfer. You will need to allocate a 64x32bit buffer in system RAM to save the ADC data. In order to easily read the data, you can enable two DMA interrupts: HBC (Half Block Complete) and BTC (Block Transfer Complete). After HBC interrupt, you can read data in the first half of the buffer while DMA is moving data to second half. After BTC interrupt, you can read data in the second half of the buffer while DMA is moving data to first half. You will need to enable the DMA autoinit feature so that DMA can automatically repeats operation.

    Thanks and regards,

    Zhaohong

  • Hello,

    Please also note that the ADC does not automatically reconfigure the "G1 BLOCKS" field of the Group1 DMA control register, so that the application must rewrite the number of results you need to accumulate before generating the next DMA request. You can consider this as a bug since it does limit the usefulness of the block DMA transfer feature. This will be taken as an enhancement in future updates of this design.

    For your use case, do you generate an interrupt to the CPU when the DMA transfer is completed? You could also reconfigure the group1 DMA control register as part of this interrupt service routine. However, since you have the group1 conversions running in continuous conversion mode, you will need to synchronize the value you write to the "G1 BLOCKS" field based on how many group1 conversions the ADC has already completed by the time you write to the DMA control register.

    Regards, Sunil

  • Hi Zhaohong,

    Thank you very much for your quick answer, so I am trying now with the ADC FIfo buff "&(adcREG1->GxBUF[adcGROUP1].BUF0)" That seems to be alright. I have to test now with the 2 interrupts on DMA to see if I don't write the same value, but it looks like better.

    So if I want sumarizem when I used the ADC Memory, the value was always the same even if a DMA was generated each time.

    And to make it work I should have to precise each time where the DMA has to look for the new ADC value isn't it ?

    Thank you !

    Brice.

  • Hi Sunil,

    I did not generate an interrupt when DMA transfert is done, but I surely have to later, to use the ADC values.

    So do I have to configure each time the G1 BLOCKS ? 

     

    Regards.

  • Hi Brice,

    The G1 BLOCKS field reflects the number of conversions stored by the ADC and it is a down-counter. A DMA request is generated whenever this counter decrements from 1 to 0. As conversion results are read out of the FIFO interface (from ADG1BUFFER location) this counter is incremented. If conversion results continue to be stored before the DMA starts reading the results, the G1 BLOCKS field goes negative.

    You indicated that you always read zeros from the G1 BLOCKS field of the group1 DMA control register. This indicates that the ADC has stopped writing further conversion results to the RAM. You may have run into the group1 memory overflow condition, which prevents the ADC from writing any more conversion results.

    Regards, Sunil

  • Hi Sunil,

    Thank you for this precision, yes I realized that when I watched to the Register G1DMA stay at 0, but I but next my post, I put a test on it

    if (adcREG1->G1DMACR & 0x00400005 == 0x00400005) {i++ ;} and a breakpoint, and the GI block is well reseted, but doesn't mean that without a breakpoint that would append.

    So I need an accurate synchrononization.

    Tks

  • Hi Zhaohong,

    I am trying to initiate the 2 interrupts on DMA HBC and BTC, but unsuccessfully so far.

    I use the Halcogen v03.04  tool to initiate the VIM with these two interrupts but, I think it doesn't work properly, I cannot see the interrupt functions in the sys_vim or sys_startup.

    What I tried is :

     - in the sys_vim initiate to functions :

    extern void dmaHBCInterrupt(void); and extern void dmaBTCInterrupt(void);

    - in the sys_startup replace the phantomInterrupt s (39 and 40) by the reference on this two functions.

    - in the sys_dma.c I fill in this function with :

    #pragma CODE_STATE(dmaHBCInterrupt, 32)

    #pragma INTERRUPT(dmaHBCInterrupt, FIQ)

    void dmaHBCInterrupt(void)

    {

    dmaREG-> GCHIENAS |= 1U; //chanel 0 is enabled for interrupt

    dmaNotification(dmaREG,HBC);

    }

    #pragma CODE_STATE(dmaBTCInterrupt, 32)

    #pragma INTERRUPT(dmaBTCInterrupt, FIQ)

    void dmaBTCInterrupt(void)

    {

    dmaREG->GCHIENAS |= 1U; //chanel 0 is enabled for interrupt

    dmaNotification(dmaREG,BTC);

    }

    and in the notification I just display the part of the adc values availlable at the moment.

    I cannot handle the interrupts, nothingth appends,

    Do you have a sample of code for that ? or can you tell me what is wrong ?

    Tks beforehand,

    regards.

    Brice

     

  • Brice,

    By default, all peripheral interrupts are set to be IRQs. If you want set DMA interrupts as FIQ, you need to configure the VIM registers. I do not know how Halcogen handles this. Assume that it leaves VIM interrupt config register as default. You need to set you ISR  as IRQ. that is, you will need to change"#pragma INTERRUPT(dmaHBCInterrupt, FIQ)" to "#pragma INTERRUPT(dmaHBCInterrupt, IRQ)". Same thing for BTC interrupts.

    Thanks and regards,

    Zhaohong

  • Hi Zhaohong, Sunil,

    I have two issues,

    - I manage to have only one DMA interruption for the channel 0, either I have HBC and not BTC, or inverse (if I disable HBC I can interrupt with BTC).

    - This issue is maybe related to this second issue and Sunil I think is aware about it because I saw that he answers to Jason for the same problem (http://e2e.ti.com/support/microcontrollers/hercules/f/312/t/119037.aspx

    -> When for example I stop in HBC, I just have 3 or 4 value fill with good adc values, some after are 0x80000xxx and the remaining is 0x00

    And when let it run, I never fill the 64 values but just these 4values (and sometime the 53th value) .  I suppose so that there is a DMA request although there have not been 64 conversions since the last time that the DMA request was generated

    How can I deal with that  ? (I am pretty new on this subjet )

    Thanks for your help