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.

SPI with DMA

Other Parts Discussed in Thread: CC2430, TIMAC

Hi,

I'm following DN113 to connect two CC2430 via SPI. Without DMA it works fine, but when I add DMA (4.1.3 of DN113) I have some questions:

  1. Page 12: I understand that first it configures DMA, then it configures the flags for the later interrupts. But what is happening in the interruption dma_IRQ(void)? I mean, from where it's getting the information to send via SPI? I don't know what I have to do to send 10bytes of information using DMA. Without DMA it's easy because you directly write on the buffer, but now I'm lost.
  2. The following thing it does is to set some registers, and after pulling SSN to high it begins to send like in background mode, am I wrong?

Thanks

P.D: I'm using TIMAC, I don't know if this information is useful.

  • I see that here is maybe when the information is written:

    SET_WORD(dmaConfigTx.SRCADDRH, dmaConfigTx.SRCADDRL, txBufferMaster);

    I get a warning about problems with truncation. It is a vector: uint8 txBufferMaster[10]. In the DN113 it appears always as txBufferMaster[i] so I don't know what type of variable is it.

    Another thing is that when I modify this vector is AFTER I do this SET_WORD, should I have to do another SET_WORD after modifying it?

     

    I've placed a breakpoint inside the interruption:

    #pragma vector=DMA_VECTOR
    __interrupt void dma_IRQ(void)

    But it never enters. When should it enter? After doing this?:

    DMAARM = DMAARM0; // Arm DMA channel 0
    SSN = LOW;
    DMAREQ = 0x01;

    I'm very lost as you can imagine. Need help with this...

  • No one knows it? :(

  • Hi.

    Don't know this design note in detail nor TIMAC but let me give it a try explaining what is happening.

    Seems like you need to understand the DMA descriptor (see chapter 7 and the DMA_DESC struct).
    For this specific setup (page 12) you are transmitting a byte from a buffer named txBufferMaster to the U1DBUF register every time the dma gets a trigger of UTX1 (SPI transmit trigger). For each transmit it will increase the source with 1, making it iterate through the txBuffer. It is also set up to interrupt for every n+1 bytes.

    Chapter 4 in the design note assumes you already have a txBufferMaster array decleared with lenght of 10. and code on page 7 says you have defined N to be 9.

    Once set up properly, the DMAREQ = 0x01 will trigger the DMA transfer and once 10 bytes are sent (N+1) it will end up in the dma_IRQ.

    Your txBufferMaster have to be a byte array with lenght of 10 for the code to work.

    Hope this helps.
    Kjetil

  • Thank you so much for your reply Kjetil !! =)

    Now I understand more about DMA, and how the information is written in the buffer and sended. But I can't make it work well.

    I've checked the length of txBufferMaster, the N which is 9, and changed "uint8 txBufferMaster[10]" for "BYTE txBufferMaster[10]" and also tested with "WORD txBufferMaster[10]".

    After DMAREQ = 0x01 the program continues and it never goes to the interruption dma_IRQ (I've been waiting like 2minutes..). It only goes there if I do expressly DMAIF = 1, which is not the correct solution.

    I don't know what can be wrong, I've followed the design note step by step...

    Thank you

  • Hi again,

    Found a weakness (bug) in the DN.Ordering of bitfield members in structs is compiler specific. By default, IAR and most others places bitfield members from the least significant bit to the most significant bit. The code in the DN does it the other way around and thus it will not work. You will either have to rearrange this or do the following:


    #pragma bitfields=reversed
    typedef struct {
      unsigned char SRCADDRH; // High byte of the source address
      unsigned char SRCADDRL; // Low byte of the source address
      unsigned char DESTADDRH; // High byte of the destination address
      unsigned char DESTADDRL; // Low byte of the destination address
      unsigned char VLEN : 3; // Length configuration
      unsigned char LENH : 5; // High byte of fixed length
      unsigned char LENL : 8; // Low byte of fixed length
      unsigned char WORDSIZE : 1; // Number of bytes per transfer element
      unsigned char TMODE : 2; // DMA trigger mode (e.g. single or repeated)
      unsigned char TRIG : 5; // DMA trigger; SPI RX/TX
      unsigned char SRCINC : 2; // Number of source address increments
      unsigned char DESTINC : 2; // Number of destination address increments
      unsigned char IRQMASK : 1; // DMA interrupt mask
      unsigned char M8 : 1; // Number of desired bit transfers in byte mode
      unsigned char PRIORITY : 2; // The DMA memory access priority
    } DMA_DESC;

    Try this and see if you can make it work.

    Kjetil

  • Thankyou Kjetil!!

    Now it's working perfectly!! It has entered in the interruption after sending the information!

    Thankyou so much,

     

    T3

     

  • Hi,

    I'm checking if everything is working well, it sends the information (or i think it does). But I can't receive.

    The receptor enters in the interruption after receiving the information, it set sDataReceived=TRUE. After that, when I push a button it does:

    if (sDataReceived){
          HalLedSet(2,HAL_LED_MODE_TOGGLE); //Check reception
          sDataReceived=FALSE;
        }

    But the information in rxBufferSlave is empty (all 0's).

    I've filled the txBufferMaster before doing the SET_WORDs:

    for (int i = 0; i <= N; i++)
       txBufferMaster[i] = i;

    SET_WORD(dmaConfigTx.SRCADDRH, dmaConfigTx.SRCADDRL, txBufferMaster);
    SET_WORD(dmaConfigTx.DESTADDRH, dmaConfigTx.DESTADDRL, &X_U1DBUF);
    [...continues with all the configuration parameters...]

    So the info, I think that is correctly sended.

    What can be wrong?

  • So what you are saying is that the reciever does enter the interrupt and set sDataReceived = TRUE? It's just that your buffer is emty?
    What is the DMA configuration for the receiver. Is the source address and destination address set correctly etc.?

    Kjetil

  • Yes, it enters but the buffer as you said is empty.

    The configuration of source and destination address is the following:

    DMA_DESC __xdata dmaConfigRx;
    SET_WORD(dmaConfigRx.SRCADDRH, dmaConfigRx.SRCADDRL, &X_U1DBUF);
    SET_WORD(dmaConfigRx.DESTADDRH, dmaConfigRx.DESTADDRL, rxBufferSlave);

    And the other parameters are the same from page 13 of DN113.

    DMA_DESC as you told me:

    #pragma bitfields=reversed
    typedef struct {
      unsigned char SRCADDRH; // High byte of the source address
      unsigned char SRCADDRL; // Low byte of the source address
      unsigned char DESTADDRH; // High byte of the destination address
      unsigned char DESTADDRL; // Low byte of the destination address
      unsigned char VLEN : 3; // Length configuration
      unsigned char LENH : 5; // High byte of fixed length
      unsigned char LENL : 8; // Low byte of fixed length
      unsigned char WORDSIZE : 1; // Number of bytes per transfer element
      unsigned char TMODE : 2; // DMA trigger mode (e.g. single or repeated)
      unsigned char TRIG : 5; // DMA trigger; SPI RX/TX
      unsigned char SRCINC : 2; // Number of source address increments
      unsigned char DESTINC : 2; // Number of destination address increments
      unsigned char IRQMASK : 1; // DMA interrupt mask
      unsigned char M8 : 1; // Number of desired bit transfers in byte mode
      unsigned char PRIORITY : 2; // The DMA memory access priority
    } DMA_DESC;

     

    As I've learned from yesterday, for every trigger of U1DBUF the information is copied to rxBufferSlave, right?

    I don't know what's happening.

    Thankyou.

  • Hi,

    I still can't make it work.

    Can be a problem if I've declared rxBufferSlave as a static BYTE?

    I need to use it in other parts of the code, and the only way to do it is declaring it as static and writing functions like "Set_rxBufferSlave" and "Get_rxBufferSlave".

     

    I'm stuck here... I though for a moment I almost have it working...

     

  • Well, I've been trying all day long and I can't do it...

    I checked that the receiver receives information, but it is not copied to rxBufferSlave.

    I think that both source and destination address are set correctly and also are all the other parameters.

    I'm getting a bit frustrated with this... :(

  • Hi all,

    I know I'm being a pain in the neck, but I need this for my project.

    If anyone can try it and tell me if he can make it work or whatever... I mean, anything related to this would be a great help, please...


    Thanks so much

  • I also tried the code in page 12 of DN113. I put all the code in a function called void spi_dma(void), and this function is in hal_spi.c.

    but I experiences the following error:

     

    I found a solution which resolves the error.

    but I am not so sure whether dmaConfigRx, rxBufferSlave and sDataReceived are declared as global variables somewhere because the files in IAR are huge.

    Besides this error, I also found a weird error which I posted here: http://e2e.ti.com/forums/t/7315.aspx

     

    Thanks if anyone could help.