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.

CC1111 DMA interrupt setup

Other Parts Discussed in Thread: SIMPLICITI

Hello,


I have problems getting a DMA interrupt setup. I am developping in eclipse in combination with the SDCC compiler.

The problem that I have is that I want to receive packets with variable lengths but the devices that send the packages have the length byte in the second byte after the sync word instead of the first byte.

I came accross this post with the solution to this problem:

http://e2e.ti.com/support/low_power_rf/f/155/p/83997/289501.aspx


Now I am trying to setup the receiver that the first time the dma will read only 2 bytes thus I can get the length of the rest from the package from the second byte.  The problem is that I don't seem to get the DMA interrupt.


I have enabled the DMA interrupt as follows:

IEN1 |= DMAIE;

I have the following options configured:

VLEN = 0 // use fixed length

LEN = 0x02 // fixed length of 2 bytes

WORDSIZE = 0 // byte

TMODE = 0 // single

TRIGGER = 19 // radio trigger

SRCINC = 0

DSTINC = 1 // increment 1 byte

IRQMASK = 1 //enable interrupt

M8 = 0 // use all 8 bits

PRIORITY = 1 // normal


For the interrupt I have defined the following function:

void dmaIntHandler(void) interrupt DMA_VECTOR;

In this function I have tried to put a LED on or try to enable a variable and look in the main program if it was set, but both with no effect.

Am I missing/misconfigured something in order to get the interrupt?


Regards,

Gerard


  • Here is the code used by SimpliciTI to setup the DMA and radio to receive radio receive events.

    uint8_t XDATA * pCfg;

    /* configure DMA channel for receive */
    pCfg = MRFI_DMA_CFG_ADDRESS;
    *pCfg++ = /* offset 0 : */  HIGH_BYTE_OF_WORD( &X_RFD );  /* SRCADDRH */
    *pCfg++ = /* offset 1 : */  LOW_BYTE_OF_WORD ( &X_RFD );  /* SRCADDRL */
    *pCfg++ = /* offset 2 : */  HIGH_BYTE_OF_WORD( &(mrfiIncomingPacket.frame[0]) );  /* DSTADDRH */
    *pCfg++ = /* offset 3 : */  LOW_BYTE_OF_WORD ( &(mrfiIncomingPacket.frame[0]) );  /* DSTADDRL */
    *pCfg++ = /* offset 4 : */  RXTX_DMA_VLEN_XFER_BYTES_PLUS_3;
    *pCfg++ = /* offset 5 : */  RXTX_DMA_LEN;
    *pCfg++ = /* offset 6 : */  RXTX_DMA_WORDSIZE | RXTX_DMA_TMODE | RXTX_DMA_TRIG;
    *pCfg   = /* offset 7 : */  RXTX_DMA_SRCINC_NONE | RXTX_DMA_DESTINC_PLUS_1 |
                                RXTX_DMA_IRQMASK | RXTX_DMA_M8 | RXTX_DMA_PRIORITY;

    /* abort any DMA transfer that might be in progress */
    DMAARM = ABORT | BV( MRFI_DMA_CHAN );

    /* clean out buffer to help protect against spurious frames */
    memset(mrfiIncomingPacket.frame, 0x00, sizeof(mrfiIncomingPacket.frame));

    /* arm the dma channel for receive */
    DMAARM |= BV( MRFI_DMA_CHAN );

    /* Clear interrupts */
    S1CON = 0; /* Clear MCU interrupt flag */
    RFIF = ~IRQ_DONE;           /* Clear the interrupt at the source */

    /* send strobe to enter receive mode */
    RFST = SRX;

    /* enable "receive/transmit done" interrupts */
    RFIM |= IM_DONE;

    I would suggest leaving it set in variable length packet mode since the DMA can handle this.  Set an interrupt on the initial receive event and read the first byte manually, then setup the DMA and allow the second byte to act as the first byte in the transfer and the DMA should be able to handle this.  You may need to kick off the DMA manually in the ISR if the length byte has already been received by the time you configure the DMA.

    Hope this helps.

    Jim Noxon

  • Thank you for the suggestion, I have it partially working, it only doesn't seem to fill the DMA buffer.

    I have setup the receiver as follows, I already configured DMA but not enabling it yet.

    void startRX(void)
    {
        xdata u8* pDMACfg = rftxbuf;
        xdata u8* loop;

        mMsg = FIRST;

        // configure DMA for transmission
        *pDMACfg++  = (u16)X_RFD>>8;
        *pDMACfg++  = (u16)X_RFD&0xff;
        *pDMACfg++  = (u16)rfrxbuf>>8;
        *pDMACfg++  = (u16)rfrxbuf&0xff;
        *pDMACfg++  = RF_DMA_VLEN_3;
        *pDMACfg++  = RF_DMA_LEN;
        *pDMACfg++  = RF_DMA_WORDSIZE | RF_DMA_TMODE | RF_DMA_TRIGGER;
        *pDMACfg++  = RF_DMA_DST_INC | RF_DMA_IRQMASK | RF_DMA_M8 | RF_DMA_PRIO;

        DMAARM |= 0x81;                 // ABORT anything on DMA 0

        for (loop=rfrxbuf+sizeof(rfrxbuf)-1;loop+1==rfrxbuf; loop--)
            *loop = 0;

        S1CON &= ~(S1CON_RFIF_0|S1CON_RFIF_1);
        RFIF &= ~RFIF_IRQ_DONE;

        RFST = RFST_SRX;
        RFIM |= RFIF_IRQ_DONE;
    }

    The first byte I am receiving from the RFTXRX interrupt, I check here if our extra identifier byte matches and then enable the DMA and trigger it manually.

    void rfTxRxIntHandler(void) interrupt RFTXRX_VECTOR  // interrupt handler should transmit or receive the next byte
    {
        unsigned char ucTmpRecv = 0;

        if(mMsg == FIRST)
        {
            if(MARCSTATE == MARC_STATE_RX)
            {
                ucTmpRecv = RFD;
                //debughex(ucTmpRecv);
                /* Check if this is our extra sync word byte */
                if(ucTmpRecv == 0xc6)
                {
                    mMsg = SECOND;
                    DMAARM |= 0x01;                 // enable DMA 0
                    DMAREQ |= 0x01;                    // manual trigger DMA
                }
            }
        }

     RFTXRXIF = 0;

    }

    Then in the main interrupt the RFIF status is copied to a global variable so it can be viewed in the main program.

    In the main program I have the following construction:

    if (rfif){
            IEN2 &= ~IEN2_RFIE;

            debughex(rfif);
            /* Check for RX done */
            if((rfif & RFIF_IRQ_DONE) && (mMsg == SECOND))
            {
                pucData = (unsigned char *)pPacket;
                for(i = 0; i < sizeof(packet_t); i++)
                {
                    *pucData = rfrxbuf[i];
                    pucData++;
                }
                packet_debug(&pPacket);
                stopRX();
                startRX();
            }
               rfif = 0;
            IEN2 |= IEN2_RFIE;
        }

    But when printing the package it appears to be empty however the RX done flag is set.

  • I think you want to arm the DMA regardless so that statement should be before the if statement.  You only need to manually trigger the DMA if the length byte has already been received, i.e. you have missed the receive event for the DMA.

    Finally, you may want to turn off the RFTXRX interrupt after you arm the DMA and turn on the DMA complete interrupt.  This will tell you the entire packet has been received.  In this interrupt you will then disable the DMA and re-enable the RFTXRX interrupt for the next message.

    Jim Noxon

  • I guess it doesn't really hurt anything if you keep entering the ISR for each character received by the radio as your test for FIRST will bypass the code but this seems a bit redundant and wasteful of CPU cycles if you have the DMA doing this work for you in the first place.  Just my opinion here.

    Jim Noxon