CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

SPI on timer2

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

SPI on timer2
PostPosted: Mon Apr 22, 2019 2:18 pm     Reply with quote

Needing SPI to be faster than the fosc/4
I am running a 20MHz crystal on a 18F87K22 Not really wanting to run higher clock speeds.
Shouldn't I be able to set the SPI up to run on timer2?
this line:
Code:
#USE SPI(MASTER, MODE=0, SPI1, STREAM=SPI,FORCE_HW)


sets my SPI up but having problems finding how to syntax the timer2 clock option with USE SPI.

Also, pitfalls on going this route? If I cannot get SPI to run faster will have to ditch SPI SRAM and go to parallel RAM.

I have done tests and running Fosc at 20MHz my SPI takes 2E-5 sec to transmit one 16bit word in the sequential mode of the 23LC1024 SRAM chip. I am afraid that the write will not happen fast enough before another write is needed.
I am taking 8000 16 bit words in 0.1S of time. Based off of my test code it will require 0.08S to do the writes. not much time to do everything else.

I am calling the following function once to do 250 byte writes in sequential mode of the 23LC1024 SRAM chip.

Code:
void SRAM_write_block(unsigned int32 address, byte *block, int16 number)
{
// send a block of data stored at 'block'
// number is how many items to send.

   int8 dummy;

   if(number<1) return;     // do nothing if zero items requested to send.

   output_low(SRAM_CS1);              // test with chip 1
   spi_xfer(SPI, WRITE_CMD, 8);       // send write command
   spi_xfer(SPI, address, 24);        // send address

   // Now, loop through the data

   while(--number)                    // do except for the last byte
   {
      spi_xfer(SPI, *(block++), 8); // send each byte
   }                                  // end while loop for data send
   
    dummy=spi_xfer(SPI,*(block++),8); // send last byte
    output_high(SRAM_CS1);   

}   // end SRAM_write_block()


The math of the SPI running at fosc/4 with a 20MHz clock would show there should be time to do all this but the scope data shows otherwise.
overhead? CCS options to speed up the SPI without going huge on Fosc?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

Re: SPI on timer2
PostPosted: Mon Apr 22, 2019 2:46 pm     Reply with quote

beaker404 wrote:

sets my SPI up but having problems finding how to syntax the timer2 clock option with USE SPI.

If you did want to use Timer2, the following code looks like it would work
to change the SPI clock source, while still allowing you to use spi_xfer():
Code:

#include <18F87K22.h>
#FUSES NOWDT
#use delay(internal=64M)

#USE SPI(MASTER, MODE=0, SPI1, STREAM=SPI,FORCE_HW)

#define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L)
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H)

//==================================
void main()
{
setup_spi(SPI_MASTER | SPI_CLK_T2 | SPI_MODE_0); // Use T2 as clock

// Also add code to setup Timer2.


while (TRUE);
}
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

PostPosted: Mon Apr 22, 2019 2:56 pm     Reply with quote

Thanks PCM.
Not sure Timer2 will get me there either, T2 runs at fosc/4 itself, so anything it does will slow SPI down more. If I am reading it correctly.

Really hate to keep going up in CPU speed. My experience has been boards and crystals get flakey the faster you go.

There must be some overhead I am not accounting for because it looks like a 20MHz crystal letting the SPI run at 5MHz and sending 8000 16bit words should be faster than what I am seeing.

In a perfect world, 8000 16 bit words clocked at 5MHz is 25mS. not 160mS. Is there really that much overhead?
jeremiah



Joined: 20 Jul 2010
Posts: 1315

View user's profile Send private message

PostPosted: Mon Apr 22, 2019 3:21 pm     Reply with quote

beaker404 wrote:
Thanks PCM.
Not sure Timer2 will get me there either, T2 runs at fosc/4 itself, so anything it does will slow SPI down more. If I am reading it correctly.

Really hate to keep going up in CPU speed. my experience has been boards and crystals get flakey the faster you go.

There must be some overhead I am not accounting for becuase it looks like a 20MHz crystal letting the SPI run at 5MHz and sending 8000 16bit words should be faster than what I am seeing.

In perfect world, 8000 16 bit words clocked at 5MHz is 25mS. not 160mS. Is there really that much overhead?


Well if you are gonna have to spend some time looping through your data and writing it to the SPI functions, and even those might require some under the hood assembly to ensure the byte can be written to the register, etc. None of that is free. When you put it on an oscope, is the actual SPI clock running slow? I would expect it to be right at 5MHz (with it stopping inbetween bytes) but you would probably have some overhead inbetween bytes slowing the overall payload transfer time. You can always try and reduce that per byte overhead, but you will still have to have some mostly likely.
newguy



Joined: 24 Jun 2004
Posts: 1900

View user's profile Send private message

PostPosted: Mon Apr 22, 2019 4:53 pm     Reply with quote

Writing to SPI isn't a continuous thing - the processor must fetch the next word/byte, put that into the proper register(s), transmit, repeat.

To increase speed, practically you'd need to use a processor with DMA. Not aware of any 8 bit PICs with DMA, but the 16 bit dsPICs et al definitely have it.

Edit: there now seems to be 8 bit PICs with DMA. PIC18F26K83 is an example.
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Tue Apr 23, 2019 3:19 am     Reply with quote

Yes. It is an issue with SPI, that the transmit is not buffered. So you always
have to wait for a byte to complete, before you can load the next.
One issue in the code posted, is that it has to do the array access,
_after_ it has waited for the transfer. You can speed it
a little by doing this 'while' (pointer accessed are slow):
Code:

void SRAM_write_block2(unsigned int32 address, byte *block, int16 number)
{
// send a block of data stored at 'block'
// number is how many items to send.

   int8 dummy;

   if(number<1) return;     // do nothing if zero items requested to send.

   output_low(SRAM_CS1);              // test with chip 1
   spi_xfer(SPI, WRITE_CMD, 8);       // send write command
   spi_xfer(SPI, address, 24);        // send address

   // Now, loop through the data

   while(--number)                    // do except for the last byte
   {
      dummy=*(block++); //preload the byte
      spi_xfer(SPI, dummy, 8); // now do the wait/transfer
   }                                  // end while loop for data send
   
    dummy=spi_xfer(SPI,*(block++),8); // send last byte
    output_high(SRAM_CS1);   

}   // end SRAM_write_block()


This actually saves about 2 machine cycles per transfer. Not huge,
but possibly worthwhile. However the biggest saving here is to use
spi_write, rather than spi_xfer. Unfortunately, the ability of spi_xfer
to perform multiple byte transfers comes at the cost of having a loop
counter in the routine. Result it is several instructions less efficient
when performing single byte transfers. :(

So, though I don't actually 'like' mixing the two ways of operating,
for ultimate speed, use:
Code:

void SRAM_write_block2(unsigned int32 address, byte *block, int16 number)
{
// send a block of data stored at 'block'
// number is how many items to send.

   int8 dummy;

   if(number<1) return;     // do nothing if zero items requested to send.

   output_low(SRAM_CS1);              // test with chip 1
   spi_xfer(SPI, WRITE_CMD, 8);       // send write command
   spi_xfer(SPI, address, 24);        // send address

   // Now, loop through the data

   while(--number)                    // do except for the last byte
   {
      dummy=*(block++);
      //spi_xfer(SPI, dummy, 8); // send each byte
      spi_write(dummy);
   }                                  // end while loop for data send
   
    dummy=spi_xfer(SPI,*(block++),8); // send last byte
    output_high(SRAM_CS1);   

}   // end SRAM_write_block()


This is about 20 instructions faster per byte, than the original code!....
temtronic



Joined: 01 Jul 2010
Posts: 9097
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Apr 23, 2019 5:02 am     Reply with quote

re:
Quote:
Really hate to keep going up in CPU speed. My experience has been boards and crystals get flakey the faster you go.

This is usually down to improper design (PCB layout) and materials (thin CU, no bypass caps, etc.). When you consider the modern PC is running a LOT faster, tain't no excuse to not run the PIC at 64 Megs.
beaker404



Joined: 24 Jul 2012
Posts: 163

View user's profile Send private message

PostPosted: Tue Apr 23, 2019 10:24 am     Reply with quote

Thanks guys for all the input on this topic. I will be running at 60MHz once I get my 15MHz crystal in.

Side note: running at 40 MHz right now, making the speed changes to the code yielded a 930uS write time for 250 bytes down from the original 1.13mS time! savings of 200uS

For the data block I will be writing that is a time savings of 12.8mS!!!

nice tip.
temtronic



Joined: 01 Jul 2010
Posts: 9097
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Apr 24, 2019 5:19 am     Reply with quote

hmm, for test purposes, why not use the internal osc + PLL to run the PIC at 64MHz ? While not as stable or accurate as a real xtal/2 caps, it should run fine.

Jay
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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