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.

Concerto to ADS1278 using McBSP and DMA

Other Parts Discussed in Thread: ADS1278, ADS1274

Hello,

I'm trying to connect a Concerto to an ADS1278 A to D.  I have my init code for the McBSP and the DMA shown below.

The ADS1278 is sending 4 channels of 24 bit data after every frame sync signal sent from the Concerto.  I can see that on the scope.

The SPCR1 register in the McBSP becomes 0x3 and then 0x7, meaning data is ready. But if I put a breakpoint in the DMA ISR it never gets hit.  

When I stop execution, DMACH2_CONTROL is 0x0100, which means the peripheral interrupt flag is true and the RUNSTS bit = 0.  DMACH2_TRANSFER_COUNT is 0.  It seems like the transfer is complete.  

In the PIE control register, PIEIER7 = 2, and CPU interrupt 7 is enabled.  

Why am I not getting an interrupt?  Does the DMA init look correct?  I've looked at all the McBSP and DMA example code and I'm still lost.

Thank you,

Joel

void InitMcbsp(void)
{
    // Reset FS generator, sample rate generator & transmitter
    // Reset Receiver, Right justify word
    //
    // Disable all McBSP interrupts 
    McbspaRegs.MFFINT.all=0x0;
    // Single-phase frame, No companding (Receive) 
    McbspaRegs.RCR2.all=0x0;

    // 4 words per frame since there are 4 ADC channels being read simultaneously
    McbspaRegs.RCR1.bit.RFRLEN1 = 3; // The register is loaded with the number of words minus 1
    // 24 bit words 
    McbspaRegs.RCR1.bit.RWDLEN1 = 4;
    //
    // Receiver's frame sync signal is generated internally (output from the Concerto to the ADC)
    // Receiver's clock generated internally (also output to the ADC)
    //
    McbspaRegs.PCR.bit.FSRM = 1; 
    McbspaRegs.PCR.bit.CLKRM = 1;  
    McbspaRegs.PCR.bit.SCLKME = 0;
    //
    // CLKSM = 1 and SCLKME=0, clock source for sample rate generator is low speed clock (SYSCLKOUT /    LSPCLK, which is 75MHz / 4 = 18.75MHz in our case)
    // Let the frame period FPER = 200 CLKG periods. Time between frame sync pulses will be 200 x 1/18.75MHz =       10.67uS
    //  
    McbspaRegs.SRGR2.bit.CLKSM = 1;
    McbspaRegs.SRGR2.bit.FPER = 199; // Register = 200 - 1
    //

    // Reset TX and RX
    // Enable interrupts for RX so it will trigger the transfer out of the DRR1 and DRR2 registers
    McbspaRegs.SPCR2.bit.XRST = 0;
    McbspaRegs.SPCR1.bit.RRST = 0;
    McbspaRegs.MFFINT.bit.RINT = 1;
}


void StartMcBSP(void)
{
    // Enable the sample rate generator
    // Wait at least 2 SRG clock cycles
    // Release RX from Reset
    // Frame Sync Generator reset
    //
    McbspaRegs.SPCR2.bit.GRST=1;
    DELAY_US(20);
    McbspaRegs.SPCR1.bit.RRST=1;
    McbspaRegs.SPCR2.bit.FRST=1;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void InitDMA(void)
{
    EALLOW;
    DmaRegs.DMACTRL.bit.HARDRESET = 1;
    __asm(" NOP"); // Only 1 NOP needed per Design

    // Allow DMA to run free on emulation suspend
    DmaRegs.DEBUGCTRL.bit.FREE = 0; // 0 = Halt DMA during emulation halt. 1 = Run free.

    //
    // Enable DMA channel 2, it will be from McBSP-A receive
    //
    // To accommodate a McBSP data size of > 16-bits, the
    // DMA will read 16 bits from McBSP's data receive register 1 and 16 bits from McBSP receive register 2.
    //
    // Transfer 2 16-bit words per burst. There are 2 words per adc channel (to get 24 bits).
    // Increment the destination address by 1 between words
    DmaRegs.CH2.BURST_SIZE.all = 1; // 2 words per burst
    DmaRegs.CH2.SRC_BURST_STEP = 1; // Add 1 to the 16 bit source address between words 
    DmaRegs.CH2.DST_BURST_STEP = 1; // Add 1 to the destination address. The lower address will hold the       most significant bits read from DRR2. The higher address will hold the bits from DRR1.
    //
    DmaRegs.CH2.TRANSFER_SIZE = 3; // = (8 / 2) - 1; There are eight 16 bit words and we're doing 32 bit DMA     transfers.
    //
    // After each burst:
    // Subtract 1 from the source address (back to DRR2)
    // Add 1 to the destination address: to move to the next word
    DmaRegs.CH2.SRC_TRANSFER_STEP = 0xFFFF; 
    DmaRegs.CH2.DST_TRANSFER_STEP = 1;
    //
    // Receiver data source and destination:
    // McBSP (source) -> DMA -> ADC data buffer (destination)
    // Set the source to the McBSP DRR2 (data receive register, upper 16 bits)
    // The lower 16 bits will be read from the DRR1 register as part of each burst. 
    DmaRegs.CH2.SRC_ADDR_SHADOW = (Uint32) &McbspaRegs.DRR2.all;
    DmaRegs.CH2.DST_ADDR_SHADOW = (Uint32) &HiResADCdata[0];
    //
    // Clear sync flag and error flag
    //
    DmaRegs.CH2.CONTROL.bit.ERRCLR = 1;
    //
    // Do not use the wrap function
    // Set the wrap size to the maximum value
    // which in effect disables it.
    //
    DmaRegs.CH2.DST_WRAP_SIZE = 0xFFFF; 
    DmaRegs.CH2.SRC_WRAP_SIZE = 0xFFFF;
    //
    // Enable channel interrupt at end of transfer
    // Peripheral interrupt for receive is McBSP MREVTA
    // McBSP receive buffer is full
    // Clear any interrupt flags
    // 
    DmaRegs.CH2.MODE.bit.CHINTE = 1; 
    DmaRegs.CH2.MODE.bit.CHINTMODE = 1;
    DmaRegs.CH2.MODE.bit.PERINTE = 1; 
    DmaRegs.CH2.MODE.bit.PERINTSEL = DMA_MREVTA;
    DmaRegs.CH2.MODE.bit.ONESHOT = 1;
    DmaRegs.CH2.CONTROL.bit.PERINTCLR = 1;
    EnableInterrupt(INT_DMA_CH2);

    // Enable DMA channel 2
    DmaRegs.CH2.CONTROL.bit.RUN = 1;

    EDIS;
}

  • I just noticed that I may have had the DMA ONESHOT bit set incorrectly.  I think it needs to be zero, meaning the DMA will wait for the next peripheral interrupt after each burst (as the McBSP continues to fill with data).  I hope I'm understanding that correctly.

    But I changed it to 0 and it didn't help.  Still no DMA interrupts.

    When I stop executing the program I get the following:

    DMACH2_MODE = 0x830F

    DMACH2_CONTROL = 0x0100 (was 0x2200 before data was received)

    DMACH2_BURST_COUNT = 0

    DMACH2_TRANSFER_COUNT = 0

  • By the way, I meant to say ADS1274, not ADS1278.

    Any help would be appreciated.

  • Hi Joel,

    first check whether the DMA clock is enabled:

    EALLOW;

    ....

       SysCtrlRegs.PCLKCR3.bit.DMAENCLK = 1;       // DMA Clock

    ...

    EDIS;

    This is typically done in the InitSysCtrl() function call.

    Secondly, the problem could be with the order in which the McBSP and DMA peripherals are initialized. Could you please take a look at this forum thread (it applies to F28335, but the peripherals are very similar):

    http://e2e.ti.com/support/microcontrollers/c2000/f/171/t/244747.aspx

    Please let us know if that works out, otherwise we will explore more possibilities.

  • Thanks for the reply, Lenio.

    I think I just figured out the problem.  There were two things.  

    First, I had to set the DMA "continuous" bit.  This bit is not set in the McBSP loopback to DMA example code, and I thought my application was pretty much the same thing, so I left the bit clear.  But there must be something about the timing of my application.  I was getting to the end of the first transfer (transfer count = 0) but then getting stuck there.

    The second thing is that I think there may have been times when I was actually getting to my DMA ISR but I didn't know it.  I noticed while running the McBSP to DMA example code that I was sometimes not hitting a breakpoint placed in the DMA ISR, but I could tell from the data that the ISR was in fact getting hit.  

    Looks like the continuous bit was the real key for me, and even though I'm not stopping at breakpoints in my ISR, I can tell that my ISR is running.  So I guess everything is good now.

    Thanks,

    Joel