• AVR Freaks

SPI 20MHz

Author
horkesley
Super Member
  • Total Posts : 259
  • Reward points : 0
  • Joined: 2008/09/09 00:13:17
  • Location: Colchester,Essex,UK
  • Status: offline
2009/06/10 08:13:40 (permalink)
0

SPI 20MHz

Hi,
 
I am using the SPI interface on a PIC32MX360F512.
 
At 5MHz the SPI works fine, but the slave is able to operate at 27MHz so I am trying 20MHz.
 
This fails to operate correctly reading data incorrectly.
 
Looking at the SPI clock the waveform is tending towards a sine (slow edges).
 
The data pin does have the correct data on it, but this is not read by the PIC.
 
Are there any parameters in software that affect the clock shape?
 
Unfortunatly, I can not disconnect the slave to see unloading the SPI improves the waveform.
 
Regards,
 
 
#1

18 Replies Related Threads

    jmag99
    Super Member
    • Total Posts : 486
    • Reward points : 0
    • Joined: 2007/09/21 08:04:33
    • Location: RI, United States
    • Status: offline
    RE: SPI 20MHz 2009/06/10 08:16:08 (permalink)
    0
    What do you have between the slave and the PIC?  How long is the PCB trace?  Is there a cable?  Are there any gates?  All of this will affect the max spi rate.  If there are no components between the devices and the distance between them is short, you should be able to achieve 20MHz fairly easily.  You may need to terminate the spi network.
    #2
    leon_heller
    Super Member
    • Total Posts : 6411
    • Reward points : 0
    • Joined: 2004/08/17 13:19:45
    • Location: St. Leonards-on-Sea, E. Sussex, UK.
    • Status: offline
    RE: SPI 20MHz 2009/06/10 08:16:12 (permalink)
    0
    How long are the connections?

    Leon

    Leon Heller
    G1HSM

    #3
    Kiwi Mike AZ
    Super Member
    • Total Posts : 2044
    • Reward points : 0
    • Status: offline
    RE: SPI 20MHz 2009/06/10 08:48:06 (permalink)
    0
    Do you have Pull up resistors on the SPI?
    If Not - Add them
    If So - What value.
     
    This really does make a difference.
     
     
    Mike
    #4
    leon_heller
    Super Member
    • Total Posts : 6411
    • Reward points : 0
    • Joined: 2004/08/17 13:19:45
    • Location: St. Leonards-on-Sea, E. Sussex, UK.
    • Status: offline
    RE: SPI 20MHz 2009/06/10 09:44:36 (permalink)
    0
    SPI doesn't need pull-up resistors, and they can cause problems if fitted. I2C does, of course.

    Leon

    Leon Heller
    G1HSM

    #5
    Kiwi Mike AZ
    Super Member
    • Total Posts : 2044
    • Reward points : 0
    • Status: offline
    RE: SPI 20MHz 2009/06/10 09:52:08 (permalink)
    0
    Interesting
     
    I have had to add pull-up resistors on a number of occasions, especially at the higher frequencies, which fixed the issue I was having (Especially with SD Cards).
     
    Mike
    #6
    jamodio
    Super Member
    • Total Posts : 2197
    • Reward points : 0
    • Joined: 2006/03/01 19:29:13
    • Location: San Antonio, Texas
    • Status: offline
    RE: SPI 20MHz 2009/06/10 09:58:58 (permalink)
    0

    If you have a scope doube check that you don't have excesive undershoots
    on the SPI signals, some devices don't like much those negative spikes and
    you may need to add some small (100-200ohms) resistors in series to
    reduce that.

    My .02

    Jorge Amodio - LJCV Electronics, San Antonio, Texas
    "If everything seems to be going well, you obviously overlooked something. Murphy's law"
    #7
    horkesley
    Super Member
    • Total Posts : 259
    • Reward points : 0
    • Joined: 2008/09/09 00:13:17
    • Location: Colchester,Essex,UK
    • Status: offline
    RE: SPI 20MHz 2009/06/10 10:51:59 (permalink)
    0
    Hi,
     
    Thanks for the replies.
     
    PCB track only, max. length 40mm.
     
    Direct connection, no other connections, no buffers.
     
    SPI does (should) not need pullup resistors, but I think they may help, as Mike and jamodio suggests.
     
    Series resistors may also help, but it means cutting track.
     
    Thanks for your input, I will try line matching resistors.
     
    Regards,
     
    #8
    leon_heller
    Super Member
    • Total Posts : 6411
    • Reward points : 0
    • Joined: 2004/08/17 13:19:45
    • Location: St. Leonards-on-Sea, E. Sussex, UK.
    • Status: offline
    RE: SPI 20MHz 2009/06/10 11:05:48 (permalink)
    0
    How close are the data and clock tracks? You might be getting crosstalk.

    Leon

    Leon Heller
    G1HSM

    #9
    FunnyNYPD
    Super Member
    • Total Posts : 1553
    • Reward points : 0
    • Joined: 2007/09/28 20:06:59
    • Location: USA & Canada
    • Status: offline
    RE: SPI 20MHz 2009/06/10 13:37:28 (permalink)
    0
    Check Microchip Errata too. Its SPI and I2C silicon module are always buggy which makes programmers headache.
    #10
    danish.ali
    Super Member
    • Total Posts : 1714
    • Reward points : 0
    • Joined: 2004/11/16 02:02:02
    • Location: Surrey, UK
    • Status: offline
    RE: SPI 20MHz 2009/06/11 00:31:07 (permalink)
    0
    If reading is incorrect, can you tell the PIC to read on the other clock edge?

    This might only work above a minimum clock frequency! And you might be one bit out.

    Regards,
    Danish
    #11
    horkesley
    Super Member
    • Total Posts : 259
    • Reward points : 0
    • Joined: 2008/09/09 00:13:17
    • Location: Colchester,Essex,UK
    • Status: offline
    RE: SPI 20MHz 2009/06/23 11:55:20 (permalink)
    0
    Hi
     
    Thank you for your comments.
     
    I thought the SPI was working at low frequency, but I still get data read errors.
     
    Rich, offered a suggestion but this code (drivers) is part of the driver code available with the Nanotron product. So I have modified the code to work with the PIC32, with the minimum of changes.
     
    The code includes an SPI dump, showing the read and writes to the SPI module.
     
    I get  strange results, without going into detail I wonder if anyone would like to comment on the the code.
     
    To answer previous questions, I have no other SPI device on the same port, the tracks are separated by a ground plane and the waveforms look correct.
     
    Following this, if required I can post SPI dumps and watch window results. But hopefully someone will spot an errorin my code. I hope!!!
     
    Best regards,
     
     
     
    #12
    horkesley
    Super Member
    • Total Posts : 259
    • Reward points : 0
    • Joined: 2008/09/09 00:13:17
    • Location: Colchester,Essex,UK
    • Status: offline
    RE: SPI 20MHz 2009/06/23 12:04:54 (permalink)
    0
    Hi,
     
    Woops, here is the code.
     
    Regards

     
    /*
    This file contains the SPI interface functions.
    */

    #include "config.h"
    #include "ntrxtypes.h"
    #include "nnspi.h"
    #include "picport.h"
    #include "plib.h"
    #define CONFIG_SPI_TRACE 1
    #ifdef CONFIG_SPI_TRACE
    #include <stdio.h>
    static int traceId = 0;
    static int traceOn = TRUE;
    void SpiTraceOn (MyBoolT flag)
    {
    traceOn = flag;
    }
    void PrintSpi(CMDT command, MyByte8T address,
    MyByte8T *buffer, MyByte8T len)
    {
    char c;
    int n;
    printf ("%4d:", traceId++);
    c = (command == WRITE_CMD) ? 'W' : 'R';
    printf (" %c", c);
    if (address < 16)
    {
    printf (" 0x0");
    }
    else
    {
    printf (" 0x");
    }
    printf ("%x", address);

    printf (" %3d: ", len);
    //if (len > 6) len = 6;//I remmed this so we print whole line
    for (n = 0; n < len; n++)
    {
    if (buffer[n] < 16)
    {
    printf ("0");
    }
    printf ("%x ", buffer[n]);
    }
    printf ("\n\r");
    }
    void traceSpiReset (void)
    {
    traceId = 0;
    }
    #endif /* CONFIG_SPI_TRACE */
    /*
    NanoReset:
    NanoReset() resets the nanoNET chip.
    Returns: none
    */
    void init_nano_i_o(void)
    {
    nano_CS_LAT_BIT=1; //nano_CS
    nano_CS_TRIS_BIT=0;
    nano_POR_LAT_BIT=1; //nano_POR
    nano_POR_TRIS_BIT=0;

    }

     
    /*
    I realize all these delays are not required.
    */
    void NanoReset(void)
    {
    nano_POR_LAT_BIT=1; //should be high, but make sure.
    DelayMs(5); //5mS delay
    nano_POR_LAT_BIT=0; //reset low
    DelayMs(2); //delay
    nano_POR_LAT_BIT=1; //reset high
    DelayMs(5);
    }
     
    /*
    Initialize SPI module in pic32.
    The Nanotron module SPI can be clocked at 27MHz max, 18.5nS tlc and thc.
    Here we are clocking at 20MHz, for debug reasons we are clocking at 5MHz.
    See OpenSPI1 below.
    */
    void InitSPI(void)
    {
    int rData;
    nano_CS_LAT_BIT=1; //nano deselected
    rData=SPI1BUF; //dummy read
    SPI1CON=0;
    SPI1STAT=0;
     
    /*
    SPI_SMP_OFF = 0, input data sampled in middle of output time.
    SPI_CKE_OFF = 0, data changes when clock goes from idle, (high) to active (low)
    CLK_POL_ACTIVE_LOW, means clock is high when idle and goes low to be active.
    I have checked SPI1CON, CKP=1, CKE=0, SMP=0
    PRI_PRESCAL_16_1 = 5MHz SPI clock speed. CPU clock 80MHz/16=5MHz
    PRI_PRESCAL_4_1 = 20MHz SPI clock speed. CPU clock 80MHz/4=20MHz
     
    */
    SPI1CON=0;
    SPI1BRG=0;
    OpenSPI1(SPI_MODE8_ON | MASTER_ENABLE_ON | SEC_PRESCAL_1_1 | PRI_PRESCAL_16_1 | SPI_SMP_ON | SPI_CKE_OFF | CLK_POL_ACTIVE_LOW , SPI_ENABLE);
    ConfigIntSPI1(SPI_TX_INT_DIS | SPI_RX_INT_DIS | SPI_FAULT_INT_DIS); //SPI interrupts not used.
    }
     

    // InitSPI:
    //set up I/O
    //called from ntrxinit.c
    //Set nano spi. push-pull output, msb first?????????
    void SetupSPI(void)
    {
    /*
    This number is a mirror, a 1 in bit 0, requires a 1 in bit 7
    eg 10000001, I require 0x03, 11000011 - 0xc3
    bit 0 set =SPI MSB first, bit 1 set = SPI output push-pull
    */

    NTRXSPIWriteByte (0x00, 0xc3);
    DelayMs(1);
    }
    //**************************************************************************
    /*
    Read more than one byte from SPI. This routine reads version and revision ok.
    */
    void NTRXSPIRead(MyByte8T address, MyByte8T *buffer, MyByte8T len)
    {
    int x;
    # ifdef CONFIG_SPI_TRACE
    MyByte8T *tb;
    MyByte8T tl;
    tb=buffer;
    tl=len;
    # endif
    if (len > 0x80 || len ==0) return ;

    INTDisableInterrupts();
    nano_CS_LAT_BIT=0; //enable RF module
    SPI1BUF=len & 0x7f; //read bit7=0, bits[0:6] length of data to read
    while(SPI1STATbits.SPIBUSY)
    {
    }
    SPI1BUF=address; //address to read from
    while(SPI1STATbits.SPIBUSY)
    {
    }
    SPI1STATCLR=0x00000040;

    while (len -- >0)
    {
    x=SPI1BUF; //clear rx buffer
    //SPI1STATbits.SPIROV=0;
    SPI1BUF=0x00; //read spi into buffer
    while( ! SPI1STATbits.SPIRBF)//RBF)
    {
    }

    //*buffer++ = SPI1BUF; //read into buffer
    x=SPI1BUF;
    *buffer=x;
    *buffer++;


    }
    while (SPI1STATbits.SPIBUSY)
    {
    }
    nano_CS_LAT_BIT=1; //deselect RF module
    INTEnableInterrupts();
    # ifdef CONFIG_SPI_TRACE
    if(traceOn==TRUE)
    {
    PrintSpi(READ_CMD,address,tb,tl); //print SPI data
    }
    # endif
    }
    //***********************************************************************
    //Write more than one byte to SPI
    void NTRXSPIWrite(MyByte8T address, MyByte8T *buffer, MyByte8T len)
    {
    # ifdef CONFIG_SPI_TRACE
    if(traceOn==TRUE)
    {
    PrintSpi(WRITE_CMD,address, buffer, len);
    }
    # endif
    INTDisableInterrupts();
    nano_CS_LAT_BIT=0;

    //DelayMs(1);
    while(SPI1STATbits.SPIBUSY)
    {
    }
    SPI1BUF=(0x80 | (len & 0x7F));
    while(SPI1STATbits.SPIBUSY)
    {
    }
    SPI1BUF=address;
    while(len-- >0)
    {
    while(SPI1STATbits.SPIBUSY)
    {
    }
    SPI1BUF=*buffer++;
    }
    while(SPI1STATbits.SPIBUSY)
    {
    }
    nano_CS_LAT_BIT=1;
    INTEnableInterrupts();
    }
    //*********************************************************************
    /*
    Read one byte only from SPI
    */
    void NTRXSPIReadByte(MyByte8T address, MyByte8T *buffer)
    {

    MyByte8T x;
    INTDisableInterrupts();
    nano_CS_LAT_BIT=0; //enable RF module
    SPI1BUF=0x01; //read bit7=0, bits[0:6] length of data to read
    while(SPI1STATbits.SPIBUSY)
    {
    }
    SPI1BUF=address; //address to read from
    while(SPI1STATbits.SPIBUSY)
    {
    }
    //SPI1STATCLR=0x00000040;
    //x=SPI1BUF;
    SPI1BUF=0x00;
    while( SPI1STATbits.SPIBUSY)//was RBF
    {
    }
    x=SPI1BUF;
    *buffer=x;
    while (SPI1STATbits.SPIBUSY)
    {
    }
    nano_CS_LAT_BIT=1;
    INTEnableInterrupts();

    # ifdef CONFIG_SPI_TRACE
    if(traceOn==TRUE)
    {
    PrintSpi(READ_CMD,address, buffer, 1);

    }
    # endif
    }
    //*************************************************************************
    /*
    Write one byte only from SPI
    This is a new function introduced in version 2.01 to speed up the SPI when reading one byte.
    */
    void NTRXSPIWriteByte(MyByte8T address, MyByte8T buffer)
    {
    # ifdef CONFIG_SPI_TRACE
    if(traceOn==TRUE)
    {
    PrintSpi(WRITE_CMD,address, &buffer, 1);
    }
    # endif
    INTDisableInterrupts();
    nano_CS_LAT_BIT=0;
    while(SPI1STATbits.SPIBUSY)
    {
    }
    SPI1BUF=0x81;
    while(SPI1STATbits.SPIBUSY)
    {
    }
    SPI1BUF=address;
    while(SPI1STATbits.SPIBUSY)
    {
    }
    SPI1BUF=buffer;
    while(SPI1STATbits.SPIBUSY)
    {
    }
    //DelayMs(1);
    nano_CS_LAT_BIT=1;
    INTEnableInterrupts();
    }
    //****************************************************************************
    /**
    * nanosetIRQ:
    * @value: -input- boolean enables (TRUE) or disables (FALSE) the external
    * interrupt request (interrupts from the nanochip)
    *
    * Returns: none
    */
    //We do not use Nanotron hardware interrupt.
    void nanosetIRQ(MyBoolT value)
    {
    //if (value==TRUE)
    //{
    // EIMSK |=(1<<INT4);
    // }
    // else
    // {
    // EIMSK &=~(1<<INT4);
    // }

    }

     
     
     
     
     
     
     
     



    #13
    asmallri
    Super Member
    • Total Posts : 1864
    • Reward points : 0
    • Joined: 2004/05/26 09:00:05
    • Location: Perth, Australia
    • Status: offline
    RE: SPI 20MHz 2009/06/23 12:22:38 (permalink)
    0
    ORIGINAL: leon_heller

    SPI doesn't need pull-up resistors, and they can cause problems if fitted. I2C does, of course.

    Leon


    The SPI bus, when connected to a native SPI device, do not need pull-ups provided the bus is actively driven. Some devices, such as SD/MMC cards, are not native SPI devices and require pull-ups. IN the case of the SD/MMC card the pullup resistor is required on the DO line during the SPI initialization process.

    Regards, Andrew

    http://www.brushelectronics.com/index.php?page=software
    Home of Ethernet, SD Card, and Encrypted Serial and USB Bootloaders for PICs!!
    #14
    zardoz1
    Super Member
    • Total Posts : 1852
    • Reward points : 0
    • Joined: 2005/07/09 08:03:28
    • Location: 's-Hertogenbosch, The Netherlands
    • Status: offline
    RE: SPI 20MHz 2009/06/23 12:29:56 (permalink)
    0
    Just a guess.

    I expect this is not all your code. You are using a lot of SFR bits and these are manipulated in a non-atomic fashion. This can produce read-modify-write problems when also using interrupts and/or an RTOS.

    It is good practice with PIC32 to only use atomic bit manipulation to prevent these problems. Microchip offers the m... macros for atomic SFR manipulation and AVIX-RT offers a utility library doing the same but with code portable to dsPIC/PIC24 and allowing bitfields to be set atomic to any desired value.

    Of course I am not sure wheter this is happening here but just to inform you.


    AVIX
    the PIC32 & dsPIC/PIC24 RTOS with:
    - Zero Latency Interrupts
    - The best performance!
    - Integrated Power Management
    Download here: http://www.avix-rt.com/
    #15
    horkesley
    Super Member
    • Total Posts : 259
    • Reward points : 0
    • Joined: 2008/09/09 00:13:17
    • Location: Colchester,Essex,UK
    • Status: offline
    RE: SPI 20MHz 2009/06/23 12:57:21 (permalink)
    0
    Hi,
     
    The SPI slave I am using does not require pullup as the device is actively driven.
     
    During these functions the interrupts are not enabled. The supplier of the slave device suggests the interrupts are disabled during SPI read/write.
     
    I understand atomic bit manipulation in terms of changing port bits, but I am not sure how it relates to the SPI functions.
     
    I am not using RTOS.
     
    Regards
     
     
    #16
    zardoz1
    Super Member
    • Total Posts : 1852
    • Reward points : 0
    • Joined: 2005/07/09 08:03:28
    • Location: 's-Hertogenbosch, The Netherlands
    • Status: offline
    RE: SPI 20MHz 2009/06/23 13:20:07 (permalink)
    0
    You are right, I did not see that the interrupts are disabled.

    Anyway, to give some background of what I meant:

    The problem I mentioned is not likely to occur when using the SPI registers since these are not used from main code and from an ISR (at least this is not likely). The problem has to do with manipulating one or more bits in an SFR where an ISR manipulates other bits in the same SFR. The reason I mentioned it was because I see that at least in your code fragment single bits are set in an SFR (the latch bits).

    When in the same SFR other bits are manipulated in an ISR, the result may not be as intended since PIC32 uses a read-modify-write sequence to change bits in an SFR. When the interrupt occurs between the read and the write, when the interrupt returns, the write destroys what the ISR has changed in the SFR.

    To prevent this, PIC32 has three additional registers for almost all SFR;s, the SET, CLR and INV register. Writing a bitpattern to the SET register sets the bits having one in this bitpattern. Likewise for CLR and INV. These additional registers are for atomic bitmanipulation of the SFR and in general it is good practice with PIC32 to only use these.



    AVIX
    the PIC32 & dsPIC/PIC24 RTOS with:
    - Zero Latency Interrupts
    - The best performance!
    - Integrated Power Management
    Download here: http://www.avix-rt.com/
    #17
    conprove
    New Member
    • Total Posts : 14
    • Reward points : 0
    • Joined: 2009/03/30 12:00:08
    • Location: Brazil
    • Status: offline
    RE: SPI 20MHz 2009/07/03 05:21:55 (permalink)
    0
    If you are using an oscilloscope to watch the waveforms remember to use the probe in 10x because the capacitance. In 20MHz the capacitance of probe (~100pF) can deform the waveform and this issues can happen. When you out the probe in 10x the input capacitance fall to ~15pF.Just a guess.
    I'm currently using SPI in 40MHZ whitout problems.

    Cristiano Moreira Martins
    R&D Engineer
    Conprove Ind & Comercio Ltda
    #18
    horkesley
    Super Member
    • Total Posts : 259
    • Reward points : 0
    • Joined: 2008/09/09 00:13:17
    • Location: Colchester,Essex,UK
    • Status: offline
    RE: SPI 20MHz 2009/07/03 05:43:44 (permalink)
    0
    Hi,
     
    Thanks for the comments.
     
    I have 10x probe.
     
    I don't have a storage scope so I loop the routine looking at clock and data.
     
    I have reduced the speed to 5MHz and still data is not reliable.
     
    The waveforms look correct apart from positive and negative spikes with a little ringing. This is all I can see wrong.
     
    If I loop a read routine, dumping to a RS232 port, the data is correct about 33% of the time, the remainder is mostly 0xFF.
     
    I can only guess the over/unshoot is the problem.
     
    I have tried series/ pullup/pull down resistors, but no change. With the slave removed the waveform still does not look good.
     
    At 40MHz what is your waveform like?
     
     
     
    Best regards,
     
     
    #19
    Jump to:
    © 2019 APG vNext Commercial Version 4.5