• AVR Freaks

AnsweredHot!Error with SPI Communication using DMA

Author
lgabs
New Member
  • Total Posts : 7
  • 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
Lubin
Moderator
  • Total Posts : 397
  • 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 : 7
  • 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 : 18141
  • 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 : 7
  • 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 : 7
  • 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
lgabs
New Member
  • Total Posts : 7
  • Reward points : 0
  • Joined: 2019/07/11 08:24:46
  • Location: 0
  • Status: offline
Re: Error with SPI Communication using DMA 2019/11/20 10:40:48 (permalink)
0
Hi Lubin,
 
Any updates on if or when you will be able to look into this?
 
Best,
Lukas
#7
Lubin
Moderator
  • Total Posts : 397
  • Reward points : 5
  • Joined: 2007/03/31 07:38:15
  • Location: Bayonne, France
  • Status: offline
Re: Error with SPI Communication using DMA 2019/11/22 09:09:28 (permalink)
0
Hi Lukas,
 
My apologize for the delay.
 
I will check the problem reported related to DMA size transfert beeing incorrect.
 
Regarding the hang issue, I find an errata about DMA on the chip which might be the root cause:
Check errata 55 in http://ww1.microchip.com/downloads/en/DeviceDoc/PIC32MK_GP_MC%20_Family_DS80000737F.pdf
"a simultaneous access by the CPU and the DMA controller to the same peripheral bus may result in bus conflict and CPU stall." 
Are you seeing a stall ?
 
Have you tested using the SPI peripheral without DMA (thus using the FIFO buffer) ?
The SPI peripheral have an internal 16 bytes FIFO buffer. Thus using the DMA will not improve CPU load unless you must receive/send more than 16 bytes at once (within one SPI block).
 
Lubin
#8
Lubin
Moderator
  • Total Posts : 397
  • Reward points : 5
  • Joined: 2007/03/31 07:38:15
  • Location: Bayonne, France
  • Status: offline
Re: Error with SPI Communication using DMA 2019/11/29 07:44:25 (permalink) ☼ Best Answerby lgabs 2019/11/29 14:35:30
5 (1)
Hi Lukas,
 
A Beta with some SPI update regarding DMA implementation for PIC32 and dsPIC are available from this installer.
Would you give it a try ?
 
https://github.com/LubinKerhuel/MPLAB-Device-Blocks-for-Simulink/archive/Beta.zip
 
Master mode seems ok. I have not tested Slave so far.
 
Lubin
#9
lgabs
New Member
  • Total Posts : 7
  • Reward points : 0
  • Joined: 2019/07/11 08:24:46
  • Location: 0
  • Status: offline
Re: Error with SPI Communication using DMA 2019/11/29 14:39:33 (permalink)
0
Hi Lubin,
 
Thanks for posting that update, the code works well for slave mode in my application. I can't overstate how helpful your blockset is for making the PIC devices more accessible, and for making control implementation easier.
 
Thanks for bringing the CPU/DMA errata issue to my attention. I don't think the device was hanging up completely, as other processes would still work. However, I found what I think was the issue with SPI hanging up. I never checked the MIPS setting in the chip configuration, and the default is 8 MIPS. So, I was trying to communicate at 4MHz with only 8 MIPS from the device, and I think it just could not handle it when going that slowly. Now that I changed the configuration to 120 MIPS it works well. Turns out it was a very simple issue *facepalm*.
 
Thanks again,
Lukas
post edited by lgabs - 2019/11/29 14:42:03
#10
Jump to:
© 2020 APG vNext Commercial Version 4.5