chipKIT® Development Platform

Inspired by Arduino™

Fubarino SD-library SPI, FULL speed ?

Created Mon, 22 Jul 2013 00:31:00 +0000 by Omnimusha


Omnimusha

Mon, 22 Jul 2013 00:31:00 +0000

hello, the maximum speed that can throw is 40 MHz?? as I can put this at full speed? so?

     SPI.setClockDivider (SPI_CLOCK_DIV2) / / 40 MHz??

majenko

Mon, 23 Dec 2013 23:55:30 +0000

Your best bet is to use the DSPI library instead of the SPI library - it is far more advanced. Setting the speed in the DSPI library is slightly different, but gives better results, as you set the actual speed you want, not the divider:

#include <DSPI.h>

DSPI0 SPI;

void begin() {
    SPI.begin();
    SPI.setSpeed(40000000UL);
}

You can also do full 32-bit transfers with the DSPI library to get things running even more smoothly:

uint32_t data = 0x12345678;
SPI.setTransferSize(32);
SPI.transfer(data);

pito

Sat, 28 Dec 2013 11:45:56 +0000

I think you cannot set 40MHz SPI clock, however..

The minimum clock period for SCKx is 40 ns. Therefore, the clock generated in Master mode must not violate this specification.

A pity..


majenko

Sat, 28 Dec 2013 11:58:50 +0000

You should be able to - the master clock is 80MHz, the peripheral clock is 1:1, so also 80MHz, and with a BRG of 0 you get a /2 of the PB clock, so 40MHz. As is depicted in this table in section 23.3.7 of the PIC32 FRM: [attachment=0]brg.png[/attachment] However, there is a caveat in the '795 data sheet:

The minimum clock period for SCKx is 40 ns. Therefore, the clock generated in Master mode must not violate this specification.

1/0.00000004 = 25000000Hz, so to stay inside the specifications you cannot reliably generate an SCK of more than 25MHz.

It also states:

These parameters are characterized, but not tested in manufacturing.

So it may be possible to do it, but it's not guaranteed, and what may work on one batch of chips may not work on another batch of chips. As with all these characteristics they err on the side of caution so ensure that they are valid for all imprints of a chip, so you may get lucky have have a chip that can do >25MHz, or you may not - who knows?


pito

Sun, 29 Dec 2013 12:18:37 +0000

The max SPI clock you can get in reality with 80MHz peripheral bus speed is 20MHz. The another option is to run pic32mx @120MHz. Maybe you can get 30MHz SPI clock then.

PS: there were fellows who said they saw 40MHz clock at SCLK output, the ?? is whether the internal logic is able to process the data properly when SCLK=Pbus/2, though..


majenko

Sun, 29 Dec 2013 12:24:32 +0000

Alternatively slow it down and use a smaller divider to get the higher SPI speeds. Running at 50MHz should let you get at the 25MHz SPI, or 60MHz to push the boundaries and try for 30MHz.


pito

Sun, 29 Dec 2013 12:32:31 +0000

Yes, that may work as well. But there is a ?? of a balance between the cpu mips vs. sdcard r/w speed. Ie. 25% less cpu and 33% more sdcard.. Probably application specific decision.. :)

PS: is the chipkit's sdcard driver as fast as ie. the retrobsd's one? Talking about the enhanced buffering for example.. That gives you 25% speedup easily..


majenko

Sun, 29 Dec 2013 12:44:09 +0000

Hell no - it barely functions as it is!

I have a slightly better version in UECIDE that actually allows you to specify the SPI port (and uses HARDWARE SPI!!!) but it doesn't do enhanced buffering yet. Not all the chips (the one on the Uno32 for example) have an enhanced buffer.


pito

Sun, 29 Dec 2013 12:51:14 +0000

Sd2Card.cpp l.352:

// transfer data
  for (uint16_t i = 0; i < count; i++) {
    dst[i] = spiRec();
  }

The above code is MUCH slower than with enhanced buffering - experts may consider the redesign of those 3 lines and you get much better performance.. A few minutes of work :twisted: ..

The code: http://retrobsd.org/viewtopic.php?f=5&t=502

There is a function mips_bswap in the code, search for it in the repo, it reverts the order of the bits in the 32bit word sent (it uses 32bit spi transfer).

You may use enhaced buffering with 8bit transfers:

http://retrobsd.org/viewtopic.php?f=5&t=513

//  READ: 8bit mode, 16bytes FIFO buffer:
//  Pito 2011
//  --------------------------------
static void spi_get_sector (char *data)
{
	register struct sdreg *reg = (struct sdreg*) &SD_PORT;
	int i,r;
	reg->conset = PIC32_SPICON_ENHBUF;
	r = 0; 
	i = SECTSIZE;
	while (r < (SECTSIZE))
	{
		if ((!(reg->stat & PIC32_SPISTAT_SPITBF)) && (i) )
		{ 
			reg->buf = ~0; 
			i--; 
		}
		if (!(reg->stat & PIC32_SPISTAT_SPIRBE))
		{ 
			*data++ = reg->buf; 
			r++; 
		}
	}
	reg->conclr = PIC32_SPICON_ENHBUF;
}

//  WRITE: 8bit mode, 16bytes FIFO buffer:
//  Pito 2011
//  --------------------------------
static void spi_put_sector (char *data)
{
	register struct sdreg *reg = (struct sdreg*) &SD_PORT;
	int i,r;
	reg->conset = PIC32_SPICON_ENHBUF;
	r = 0; 
	i = SECTSIZE;
	while (r < (SECTSIZE))
	{
		if ((!(reg->stat & PIC32_SPISTAT_SPITBF)) && (i) )
		{ 
			reg->buf = *data++; 
			i--; 
		}
		if (!(reg->stat & PIC32_SPISTAT_SPIRBE))
		{ 
			(void) reg->buf; 
			r++; 
		}
	}
	reg->conclr = PIC32_SPICON_ENHBUF;
}

The difference against 32bit transfers is small, so go with 8bit transfers when 32bit transfers not available on certain chips.. ;)


majenko

Sun, 29 Dec 2013 13:20:27 +0000

32 bit transfers are available on all chips (pic32 chips that is, but that's all we care about). The FIFO buffering, however, is not. At the moment it "works" on all chips. To add the enhanced buffering you'd first have to identify which chips have it available an conditionally compile for only those chips. More than a couple of minutes work...


pito

Sun, 29 Dec 2013 13:30:07 +0000

Above are the two 8bit functions (compare them with the 32bit ones pls - as I'm not sure they are the last revs I've found somewhere).. If you have got 30mins time spare :) , you may try with ie fubarino to see whether it is worth of the effort.. My guess is 20-30% speed increase..

PS: it may work without FIFO.. There is no specific setting for FIFO size.. it depends on how the flags will react when fifo=1.. PS1: without fifo the 32bit version could be the faster one..