horkesley
Super Member
- Total Posts : 288
- Reward points : 0
- Joined: 2008/09/09 00:13:17
- Location: Essex,UK
- Status: offline
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,
|
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)
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.
|
leon_heller
Super Member
- Total Posts : 6413
- 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)
How long are the connections? Leon
|
Kiwi Mike AZ
Super Member
- Total Posts : 2056
- Reward points : 0
- Status: offline
RE: SPI 20MHz
2009/06/10 08:48:06
(permalink)
Do you have Pull up resistors on the SPI? If Not - Add them If So - What value. This really does make a difference. Mike
|
leon_heller
Super Member
- Total Posts : 6413
- 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)
SPI doesn't need pull-up resistors, and they can cause problems if fitted. I2C does, of course. Leon
|
Kiwi Mike AZ
Super Member
- Total Posts : 2056
- Reward points : 0
- Status: offline
RE: SPI 20MHz
2009/06/10 09:52:08
(permalink)
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
|
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)
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
|
horkesley
Super Member
- Total Posts : 288
- Reward points : 0
- Joined: 2008/09/09 00:13:17
- Location: Essex,UK
- Status: offline
RE: SPI 20MHz
2009/06/10 10:51:59
(permalink)
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,
|
leon_heller
Super Member
- Total Posts : 6413
- 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)
How close are the data and clock tracks? You might be getting crosstalk. Leon
|
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)
Check Microchip Errata too. Its SPI and I2C silicon module are always buggy which makes programmers headache.
|
danish.ali
Super Member
- Total Posts : 1721
- 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)
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
|
horkesley
Super Member
- Total Posts : 288
- Reward points : 0
- Joined: 2008/09/09 00:13:17
- Location: Essex,UK
- Status: offline
RE: SPI 20MHz
2009/06/23 11:55:20
(permalink)
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,
|
horkesley
Super Member
- Total Posts : 288
- Reward points : 0
- Joined: 2008/09/09 00:13:17
- Location: Essex,UK
- Status: offline
RE: SPI 20MHz
2009/06/23 12:04:54
(permalink)
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); // } }
|
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)
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.
|
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)
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/
|
horkesley
Super Member
- Total Posts : 288
- Reward points : 0
- Joined: 2008/09/09 00:13:17
- Location: Essex,UK
- Status: offline
RE: SPI 20MHz
2009/06/23 12:57:21
(permalink)
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
|
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)
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/
|
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)
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
|
horkesley
Super Member
- Total Posts : 288
- Reward points : 0
- Joined: 2008/09/09 00:13:17
- Location: Essex,UK
- Status: offline
RE: SPI 20MHz
2009/07/03 05:43:44
(permalink)
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,
|