• AVR Freaks

Hot!Error with SPI Communication using DMA

Author
lgabs
New Member
  • Total Posts : 5
  • Reward points : 0
  • Joined: 2019/07/11 08:24:46
  • Location: 0
  • Status: offline
2019/10/03 15:13:24 (permalink)
5 (1)

Error with SPI Communication using DMA

Hi Lubin,
 
I am using SPI on a PIC32MK0512MCF100. I have had a great time with your blockset, but I've run into an issue with 8-bit transfers using SPI with DMA. Although I set the SPI block for an 8-bit transfer, the code generated creates a uint16_T variable, not uint8_T, so I have to change the code in MPLAB to get it to run. I have uploaded code titled "ForumCode_v1."
 
 
Specifically, in my example, I have to change the instances of uint16_T to uint8_T in the following code:
MCHP_SPI1_Interrupt_data.c
MCHP_SPI5_Interrupt_data.c
ForumCode_v1_private.h
I have had to change the size of the DMA transfer (DCH2DSIZ,DCH3SSIZ and DCH5SSIZ,DCH4DSIZ) in every case in the following files, cutting the values in half due to the change from uint16_T to uint8_T:
MCHP_SPI1_Interrupt.c
MCHP_SPI5_Interrupt.c
 
Also, and I am not sure why this is, but the code does not run using the build button in Matlab, and only runs from MPLAB X. However, this isn't a big issue, as it is easy to just run the code from MPLAB.
 
In a similar issue, I am attempting to use the PIC32 as both a Master and slave device, being a slave on SPI bus 1 and a master on SPI bus 5. The code on bus 5 runs perfectly until I make a slave request on bus 1. From then on, the data sent over SPI Bus 5 is corrupted (i.e. the data transferred cannot be interpreted by the receiving SPI slave unit). Is there a good way to organize the code so that I can run as both a master and slave on the same device with no issues?
 
Thank you,
Lukas

Attached Image(s)

#1

5 Replies Related Threads

    Lubin
    Moderator
    • Total Posts : 383
    • Reward points : 5
    • Joined: 2007/03/31 07:38:15
    • Location: Bayonne, France
    • Status: offline
    Re: Error with SPI Communication using DMA 2019/10/04 01:50:02 (permalink)
    0
    Hi Lukas,
     
    Thanks for the detailed feedback and in deph analysis.
    I check all theses by next week. I'll keep you updated with hopefully fix proposal.
     
    Lubin
    #2
    lgabs
    New Member
    • Total Posts : 5
    • Reward points : 0
    • Joined: 2019/07/11 08:24:46
    • Location: 0
    • Status: offline
    Re: Error with SPI Communication using DMA 2019/10/16 10:14:46 (permalink)
    0
    Hi Lubin,
     
    I was able to probe the SPI lines for bus 5 with an oscilloscope, and have seen that it immediately stops sending anything as soon as I send a request from the master on bus 1. I have played a lot with the configuration bits and interrupt priorities, and nothing seems to help. Is it possible that the PIC32MK can't communicate on two SPI buses at the same time? That doesn't seem right though. Have you had a chance to look at this at all?
     
    We really appreciate your help.
     
    Thanks,
    Lukas
    #3
    NKurzman
    A Guy on the Net
    • Total Posts : 17912
    • Reward points : 0
    • Joined: 2008/01/16 19:33:48
    • Location: 0
    • Status: offline
    Re: Error with SPI Communication using DMA 2019/10/16 10:20:27 (permalink)
    0
    Do  the SPI5 and SPI 1 share and common registers? Setting or clearing any bits in these registers must be done with only the SET,CLR,and INV Registers to avoid Read-Modify-Write Issues.
    There there is the COpy / Paste Error.  Is SPI1 changing any bits in SPI5, accidentally. 
    #4
    lgabs
    New Member
    • Total Posts : 5
    • Reward points : 0
    • Joined: 2019/07/11 08:24:46
    • Location: 0
    • Status: offline
    Re: Error with SPI Communication using DMA 2019/10/16 10:52:54 (permalink)
    0
    Hi NKurzman,
     
    I can't find any common registers that they share. All registers that are changed are SPIx registers, and so are separate for SPI1 and SPI5. I have checked, and all code in SPI5 only changes SPI5 registers, there is no copy/paste error.
     
    The following is the code in the main loop that calls SPI1:
      /* S-Function (MCHP_BUS_SPI): '<Root>/BUS SPI to RPI' */
      /* number of SPI blocks : 1 ; Current: 1 ; MCHP_SPI_StartImplemented = 1*/
      if (MCHP_SPI1_State == 0) /* Free for next sequence ?*/
      {
        /* SPI sequence No : 1 */
        ForumCode_v1_DW.BUSSPItoRPI[0] = SPI1_Buff16[0];
        ForumCode_v1_DW.BUSSPItoRPI[1] = SPI1_Buff16[1];
        ForumCode_v1_DW.BUSSPItoRPI[2] = SPI1_Buff16[2];
        ForumCode_v1_DW.BUSSPItoRPI[3] = SPI1_Buff16[3];
        ForumCode_v1_DW.BUSSPItoRPI[4] = SPI1_Buff16[4];
        ForumCode_v1_DW.BUSSPItoRPI[5] = SPI1_Buff16[5];
        ForumCode_v1_DW.BUSSPItoRPI[6] = SPI1_Buff16[6];
        ForumCode_v1_DW.BUSSPItoRPI[7] = SPI1_Buff16[7];
        ForumCode_v1_DW.BUSSPItoRPI[8] = SPI1_Buff16[8];
        ForumCode_v1_DW.BUSSPItoRPI[9] = SPI1_Buff16[9];
        ForumCode_v1_DW.BUSSPItoRPI[10] = SPI1_Buff16[10];
        ForumCode_v1_DW.BUSSPItoRPI[11] = SPI1_Buff16[11];
        ForumCode_v1_DW.BUSSPItoRPI[12] = SPI1_Buff16[12];
        ForumCode_v1_DW.BUSSPItoRPI[13] = SPI1_Buff16[13];
        ForumCode_v1_DW.BUSSPItoRPI[14] = SPI1_Buff16[14];
        ForumCode_v1_DW.BUSSPItoRPI[15] = SPI1_Buff16[15];
        SPI1_Buff16[1]= ForumCode_v1_DW.VectorConcatenate1[0];
        SPI1_Buff16[2]= ForumCode_v1_DW.VectorConcatenate1[1];
        SPI1_Buff16[3]= ForumCode_v1_DW.VectorConcatenate1[2];
        SPI1_Buff16[4]= ForumCode_v1_DW.VectorConcatenate1[3];
        SPI1_Buff16[5]= ForumCode_v1_DW.VectorConcatenate1[4];
        SPI1_Buff16[6]= ForumCode_v1_DW.VectorConcatenate1[5];
        SPI1_Buff16[7]= ForumCode_v1_DW.VectorConcatenate1[6];
        SPI1_Buff16[8]= ForumCode_v1_DW.VectorConcatenate1[7];
        SPI1_Buff16[9]= ForumCode_v1_DW.VectorConcatenate1[8];
        SPI1_Buff16[10]= ForumCode_v1_DW.VectorConcatenate1[9];
        SPI1_Buff16[11]= ForumCode_v1_DW.VectorConcatenate1[10];
        SPI1_Buff16[12]= ForumCode_v1_DW.VectorConcatenate1[11];
        SPI1_Buff16[13]= ForumCode_v1_DW.VectorConcatenate1[12];
        SPI1_Buff16[14]= ForumCode_v1_DW.VectorConcatenate1[13];
        SPI1_Buff16[15]= ForumCode_v1_DW.VectorConcatenate1[14];
        SPI1_Buff16[16]= ForumCode_v1_DW.VectorConcatenate1[15];
        MCHP_SPI1_State = 1;
        IFS2SET = 0x0400; /* _DMA2IF = 1 Force Interrupt */
      }

     
    The following is the interrupt that is called for SPI1:
     
    #include "ForumCode_v1.h"
    #include "ForumCode_v1_private.h"

    /* Implement SPI 1 TX Interrupts */
    void __attribute__((interrupt(IPL4SOFT), no_fpu, vector(_DMA2_VECTOR)))
      DMA2_VECTOR_Handler(void)
    {
      DCH2INTCLR = 0xFF;
      IFS2CLR = 0x0400; /* _DMA2IF = 0 Clear DMA2 Interrupt Flag */

      /* Declaration of Variables */
      uint_T static tmp __attribute__((coherent));
      switch (MCHP_SPI1_State)
      {
       case 0: /* Idle */
        DCH3CONCLR = 0x80; /* CHEN - Disable DMA Tx */
        DCH2CONCLR = 0x80; /* CHEN - Disable DMA Rx */
        break;

       case 1: /* Start a new SPI Sequence */
        SPI1STATbits.SPIROV = 0; /* Reset possible receive overflow */
        SPI1CONbits.ON = 1; /* Re-Enable SPI to listen for one sequence */

        /* Read - Write Sequence */
        DCH2DSIZ = 32; /* Destination Size for DMA (SPI) Rx */
        DCH2DSA = (unsigned int) &SPI1_Buff16[0] & 0x1FFFFFFF;/* Physical address for Rx Buffer */
        DCH3SSIZ = 32; /* Source Size for DMA (SPI) Tx */
        DCH3SSA = (unsigned int) &SPI1_Buff16[1] & 0x1FFFFFFF;/* Physical address for Tx Buffer */
        DCH2CONSET = 0x80; /* CHEN - Enable DMA Rx */
        DCH3CONSET = 0x80; /* CHEN - Enable DMA Tx */
        DCH3ECONSET = 0x80;
        /* CFORCE DMA Forced transfer on DMA Tx so as to receive out SPI Rx values */
        MCHP_SPI1_State++;
        break;

       case 2:
        SPI1CONbits.ON = 0; /* Disable SPI until next demand to listen a sequence */
        MCHP_SPI1_State = 0;
                      /* End of SPI Sequence. SPI is available for a new sequence */
        break;

       default: /* Sequence finished */
        MCHP_SPI1_State = 0; /* Should never happend */
        break;
      } /* End of switch case sequence*/
    } /* Enf of interrupt */

     
    The following is the code which configures SPI1:
      /* Start for S-Function (MCHP_BUS_SPI): '<Root>/BUS SPI to RPI' */

      /* Set-up SPI 1 peripheral with Fsck = 500000 (500000 with 0.0 \% error) */
      SPI1STAT = 0;
      SPI1CON2 = 0;
      SPI1BRG = 0x07;
      SPI1CON = 0x0100;

      /* Configure DMA for SPI Reception (Rx) */
      DMACONSET = 0x8000; /* Enable DMA Controller */

      /* DMA Setup Rx setting which will remains constants */
      DCH2CON = 2; /* DMA Priority, within [0-3] */
      DCH2ECON = (_SPI1_RX_VECTOR << 8) + 0x10;
                        /* DMA initiate SPI transfert when Rx buffer is not empty */
      DCH2SSIZ = 1; /* Source Size is 1 within SPI1BUF */
      DCH2CSIZ = 1; /* 1 byte per SPI transfert request */
      DCH2SSA = (volatile unsigned int) &SPI1BUF & 0x1FFFFFFF;
                                         /* Physical Address for SPI BUF register */

      /* Configure DMA for SPI Emission (Tx) */
      DMACONSET = 0x8000; /* Enable DMA Controller */
      DCH3CON = 2; /* Priority, within [0-3] */
      DCH3ECON = (_SPI1_TX_VECTOR << 8) + 0x10;
      DCH3DSIZ = 1; /* Destination size is one byte */
      DCH3CSIZ = 1; /* 1 byte per SPI transfert request */
      DCH3DSA = (volatile unsigned int) &SPI1BUF & 0x1FFFFFFF;
                                         /* Physical Address for SPI BUF register */

      /* Configure DMA for SPI (Rx). Even when sending only, DMA for SPI (Rx) interrupt is used because is is triggered after the SPI transaction is completed. */
      DCH2INTCLR = 0x00FF00FF; /* Clear existing event, disable all interrupts */
      DCH2INTSET = 0x00090000;
                          /* Enable Block Complete interrupt and error interrupts */
      IPC18INV = ( 0x001C0000 & (0x00100000 ^ IPC18) ) ;
                                       /* _DMA2IP = 4 Set DMA interrupt priority */
      IFS2CLR = 0x0400; /* _DMA2IF = 0 Clear DMA2 Interrupt Flag */
      IEC2SET = 0x0400; /* _DMA2IE = 1 Enable DMA2 Interrupt */

     
    The only thing that I have found is that if I disable SPI1 using "SPI1CONbits.ON = 0;" Then SPI5 works fine, but SPI1 does not work. 
     
    The weird thing is that the code only stops working once a transmission is made on SPI1 from the master. I don't think that actually changes how the code is executed in the program, but I will put it in debug mode and look.
     
    Thanks,
    Lukas
    #5
    lgabs
    New Member
    • Total Posts : 5
    • Reward points : 0
    • Joined: 2019/07/11 08:24:46
    • Location: 0
    • Status: offline
    Re: Error with SPI Communication using DMA 2019/10/17 11:44:14 (permalink)
    0
    I tried to use debug mode, but I can't get the SPI peripherals to act correctly in debug mode. Not sure what the issue is, but I won't be able to step through the program and see how the code responds to a transmission from the SPI master.
    #6
    Jump to:
    © 2019 APG vNext Commercial Version 4.5