|
|
View previous topic :: View next topic |
Author |
Message |
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
Difference between <#USE SPI> and setup_spi() |
Posted: Thu Mar 09, 2017 8:48 am |
|
|
Compiler: 5.026
Device: PIC24EP512GP806
Yet another question that needs clarification where manuals and help files are not always ideal (in my case anyhow!).
My MCU is tied to two external SPI devices on SPI3 (pins RE7, RE3 and RE2):
Device 1 uses RE4 for /CS (EEPROM 24LC1024)
Device 2 uses RF0 for /CS (ACCELEROMETER ADXL0345)
Of course, ideally, I want to take advantage of the maximum speed when accessing either device.
Initially at MCU startup, I am using the following to configure SPI3 because that's how the SPI bus needs to be configured for the EEPROM:
setup_spi3( SPI_MASTER | SPI_XMIT_L_TO_H | SPI_CLK_DIV_16 );
Then later in the code, I have functions that use spi_write3() for accessing both devices. So far so good, all works fine, no issues here, its been like this forever.
But as I learn more and more while working on this project, I am wondering if I am really taking advantage of the full SPI bus capabilities.
When I need to read or write to either device, the only differece is with the accelerometer's SPI configuration when I need to access it:
1) I must first call setup_spi3( SPI_MASTER | SPI_XMIT_L_TO_H | SPI_H_TO_L | SPI_CLK_DIV_16 );
2) Then I can read or write to the device;
3) Lastly I must call setup_spi3( SPI_MASTER | SPI_XMIT_L_TO_H | SPI_CLK_DIV_16 ); to put the SPI bus back to 'EEPROM' mode since it is accessed much more often.
The accelerometer is rarely accessed after it is initially configured, the EEPROM is more accessed therefore I set the SPI back to the 'EEPROM' mode.
All this being said, hoping I didn't give too much irrelevant information, what is the difference between setting-up the SPI port with setup_spi vs #USE SPI?
Is there a difference in speed when the device is accessed? I haven't tried using the #USE SPI because I am not sure what else is required when using that fuse.
Thanks,
Ben |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Mar 09, 2017 12:07 pm |
|
|
benoitstjean wrote: |
Device 1 uses RE4 for /CS (EEPROM 24LC1024) |
This eeprom part number doesn't exist, or no longer exists. You almost
certainly are really using 25LC1024.
benoitstjean wrote: |
I must first call setup_spi3( SPI_MASTER | SPI_XMIT_L_TO_H | SPI_H_TO_L | SPI_CLK_DIV_16 );
2) Then I can read or write to the device;
3) Lastly I must call setup_spi3( SPI_MASTER | SPI_XMIT_L_TO_H | SPI_CLK_DIV_16 );
to put the SPI bus back to 'EEPROM' mode since it is accessed much more often.
|
The data sheet for 25LC1024 says it can use SPI modes 0 or 3.
This is stated in the following diagram in the data sheet:
Quote: | FIGURE 1-2: SERIAL INPUT TIMING |
The ADXL345 also uses SPI mode 3. This is stated in the SPI section
of the data sheet:
Quote: |
The maximum SPI clock speed is 5 MHz with 100 pF maximum loading,
and the timing scheme follows clock polarity (CPOL) = 1 and clock
phase (CPHA) = 1.
|
Since both chips can use Mode 3, you don't need to change modes. |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Thu Mar 09, 2017 12:18 pm |
|
|
Hi PCM Programmer, correct, typo from my end, it is a 25LC1024.
Ok for the modes... thanks.
But the general question is still valid:
What is the difference between setting-up the SPI port with setup_spi vs #USE SPI?
And which SPI 'model' will take advantage of the max speed of the SPI bus?
Thanks again,
Benoit |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Fri Mar 10, 2017 4:00 am |
|
|
setup_spi, is the older way of using the SPI.
Only works with hardware ports.
Uses spi_write and spi_read for transfers.
Only supports 8bit transfers.
Does not offer any control of handshake lines.
Requires direct control of the configuration bits (directions, levels etc.). Simpler defines for these though are easy.
#USE_SPI is the more powerful 'modern' way of controlling SPI.
Supports software and hardware ports.
Requires spi_xfer for the actual transfers.
spi_xfer is coded slightly differently. For a transmit transfer, on the hardware port, it'll check if the peripheral is 'free' before transferring a byte, then transfer _and immediately return_. This means you code can be preparing the next byte while this transfer is occurring.
Supports automatic multi byte transfers (up to 4 bytes).
Can control latch and enable pins.
Supports 'mode' names for configuring the port.
Also allows you to specify bit order and byte order for the transfers.
SPI_XFER for sequential writes is faster, because of the ordering of the 'device ready' test. |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Fri Mar 10, 2017 5:39 am |
|
|
In terms of bus clock rate, they will both give the same maximum. Any difference in throughput will be due to firmware overheads, giving slighty larger gaps between transfers.
I am running a 25AA1024 on a PIC24HJ128GP504 on 3.3V. The bus lines are maybe 30mm long. I cannot reliably run at the maximum SPI clock rate that the 25AA1025 of 10MHz as even with the short, direct PCB traces, I am getting a lot of overshoot and ringing, making the waveforms a bit dodgy. So, I've had to slug the SPI to 5MHz (the clock rate divider only allows, obviously, integer sub-multiples of my Fcyc, 80MHz, so I can have 20MHz, 10MHz, 5MMhz, 2.5MHz, etc. but nothing in-between) to get reliable transfers in all my available hardware (granted not many: one prototype board worked fine, one didn't... sometimes). I could have probably fiddled wround with termination resistors to improve the waveforms, but there was no need, running at half-speed is just fine in my application (serving wepages on a LAN). So, I'd not recommend running at top speed for the sake of it, and it may not be easy to guarantee. |
|
|
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
|
Posted: Fri Mar 10, 2017 5:53 am |
|
|
Hi guys,
Thanks both for your replies, it's appreciated.
So maybe then when I get a bit of time, I will look at using the more "modern" version.
Thanks a lot!
Benoit |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1353
|
|
Posted: Fri Mar 10, 2017 8:09 am |
|
|
It's worth noting that at least for some chips for some compiler revisions, the #use spi generates slightly more code and takes a few instructions longer (for hardware mode).
Consider:
Code: |
#include <24FJ64GA104.h>
#use delay(clock=8MHz)
#pin_select SDO1 = PIN_B7
#pin_select SDI1 = PIN_B6
#pin_select SCK1OUT = PIN_B8
#pin_select SDO2 = PIN_B9
#pin_select SDI2 = PIN_B10
#pin_select SCK2OUT = PIN_B11
#use spi(SPI2,FORCE_HW,master,bits=8,mode=0)
void main(){
setup_spi(SPI_MASTER);
spi_write(0x00);
spi_xfer(0x00);
while(TRUE){
}
}
|
The spi_write() call generates:
Code: |
.................... spi_write(0x00);
0292: BCLR.B 240.6
0294: BTSS.B 240.0
0296: BRA 29C
0298: MOV.B 248,W0L
029A: BRA 294
029C: CLR.B 248
029E: BTSS.B 240.0
02A0: BRA 29E
|
And the spi_xfer() call generates:
Code: |
.................... spi_xfer(0x00);
02A2: MOV #8,W2
02A4: MOV #0,W0
02A6: MOV #0,W1
02A8: CALL 200
|
which calls
Code: |
.................... #use spi(SPI2,FORCE_HW,master,mode=0)
*
0200: MOV W5,[W15++]
0202: MOV W0,W4
0204: MOV W1,W5
0206: MOV #18,W3
0208: CPSGT W2,W3
020A: BRA 210
020C: MOV #B,W3
020E: BRA 222
0210: MOV #10,W3
0212: CPSGT W2,W3
0214: BRA 21A
0216: MOV #A,W3
0218: BRA 222
021A: MOV #8,W3
021C: CPSGT W2,W3
021E: BRA 222
0220: MOV #9,W3
0222: MOV.B [W3+#0],W0L
0224: MOV.B W0L,268
0226: BTSS.B 260.0
0228: BRA 226
022A: MOV.B 268,W0L
022C: MOV.B W0L,[W3--]
022E: BCLR.B 260.6
0230: SUB.B #8,W2L
0232: BRA GTU,222
0234: MOV W4,W0
0236: MOV W5,W1
0238: MOV [--W15],W5
023A: RETURN
|
Not all of that code is run for the call, it is basically a selector for 8bits vs 16 bits vs 24 or 32 bits, so the extra overhead, is just doing the checks versus the bits size and the built in looping.
I wish CCS was a bit smarter on this and if you select a size equal to a hardware option, then forgo the extra stuff and replicate what spi_write() does. It is a compile time option, so it is certainly possible for them to do so. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Fri Mar 10, 2017 9:46 am |
|
|
Interesting.
On the spi_write code. Note that it waits for the peripheral to be ready before sending, and then again afterwards.... :(
Now the multi byte code is silly. As you say it should not include this if you are fixing the transaction length. It doesn't on a PIC16/18.... Duh. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|