[V850ES/JG3 + IAR] DMA problem

Hi,

     i need to enable 12 DMA transferts from each ADC buffers (12) to internal RAM.

The ADC triggers DMA when conversion of the analog input pin (12th ADC channel) specified by the ADA0S register is completed.

The DMA generates an interrupt when transfers are completed.

The ADC is set in continuos scan mode over all adc channel (12th).

The DMA is set to perform 12 transferts (DBCn = 11).

The problem is that ADC performs the scan of all channels at XX Hz... but the DMA generates an interrupt at (XX/12) Hz!!! It's normally?

I need that for each ADC complete scan of 12 channels the DMA performs the transfer of all ADC conversion result registers (ADA0CRn) to RAM.

Can someone help me?

Any Idea?

Thanks

Code:

/** Configure ADC.

*

*  Performs ADC setup setting it in Continuous Scan Mode. It sets the High

*  Speed Conversione Mode (3,25us) and selects to scan all channels.

*  Finally starts the ADC.

*/

void adcInit()

{

    // clears ADC ADA0M0 register

    ADA0M0 = 0;

    // continuous scan mode

    ADA0M0 = ADA0M0 | 0x10;

    // clears ADC ADA0M1 register

    ADA0M1 = 0;

    // high speed conversion mode

    ADA0M1 = ADA0M1 | 0x80;

    // 3.25us conversion time

    ADA0M1 = ADA0M1 | 0x03;

    // clears ADC ADA0S register

    ADA0S = 0;

    // selects to scan all channels

    ADA0S = 0x0B;

    // clears trigger sources

    ADA0M2 = 0;

    // enbles ADC interrupt

    ADIC = 0x04;  

    // starts ADC conversion

    ADA0M0 = ADA0M0 | 0x80; 

}

/** Configure DMA.

*

*  Sets DMA channel 0 with ADC output registers as source address and

*  ADCDMABuff as destination address. Sets number of transmit to 12 and

*  selects 16bit as transfer unit. DMA trigger is connected to INTAD signal,

*  which is generated at the end of each ADC scan. In the end enables

*  interrupts and DMA.

*/

void dmaCh0Init()

{

    UINT32 addr ;

    // disables DMA

    E00 = 0 ;

    // disables DMA interrupt

    DMAMK0 = 1U ;

    // clears interruot flag

    DMAIF0 = 0U ;

    // enables DMA channel 0 programming

    INIT0 = 1 ;

    // sets DMA channel 0 destination address

    addr = (UINT32) &ADCDMABuff[0] ;

    DDA0H = (UINT16)(addr>>16) & 0x03FF | 0x8000;

    DDA0L = (UINT16)(addr & 0x0000FFFF);

    //DDA0H = DDA0H & 0x03FF;

    //DDA0H = DDA0H | 0x8000;  

    // sets DMA channel 0 source address to ADC output registers

    DSA0H = 0x03FF;//0xFF;

    DSA0L = 0xF210;

    //DSA0H = DSA0H & 0x03FF;

    // sets tranfers number

    DBC0 = 11;

    // sets 16 bit transfer unit

    DADC0 = 0x4000;

    // sets DMA trigger source to ADC INTAD signal

    DTFR0 = 0x2C;

    // clears DCHC0 register

    DCHC0  = 0x00;

    // clears interrupt flag

    DMAIF0 = 0 ;

    // enables interrupt

    DMAMK0 = 0 ;

    // enables DMA

    E00 = 1U ;

    // enables DMA interrupt

    //DMAIC0 = 0x00;          // probably not needed

    //DMAIC0 = DMAIC0 | 0x04; // probably not needed

}

#pragma vector=INTDMA0_vector //0x00000380

__interrupt void dmaISR(void)

{

    flash_led();

    E00 = 1U ;

}

  • I don't know V850 in detail, but I would expect that each DMA trigger transfers 1 byte or 1 word (or whatever the data size is), and NOT 12 values. To transfer 12 values you would need 12 DMA triggers.

  • Ok, but if i need a continuos scan of 12 ADC channels and i need to transfer all ADC conversion result registers to ram using DMA without using CPU.... how can I do?

    ....I can do?

    Thanks.

  • From reading this device user manual, unfortunately it does not  appear that you will be able to use a single DMA operation to transfer  all A/D conversion result data to RAM.  For this mcu, you only get one  interrupt at the end of the conversion scan, which is the only trigger  signal sent to the DMA.  The DMA requires a trigger for every transfer,  as FrankL mentioned, so you would need 12 triggers/interrupts from the  ADC to get all of the results transfered (this is why you see the noted  behavior that after 12 conversion scans of the ADC, you get the DMA  completion interrupt).

    The solution should be to write a simple interrupt handler for  the A/D conversion end interrupt, and transfer the data using the CPU.  I believe the CPU time will be quite small.

  • If possible, you could use a software trigger. Start your DMA transfer from the interrupt routine of your ADC, it should than transfer amount of data defined in the DBCn register. You have to write a short interrupt routine in this case. It is not a pure hardware solution, but could help.