[HELP] Aumentare velocità della SPI

Una richiesta veloce, senza che devo sbattermi tra duecento ricerche su Google...

Si può aumentare la velocità di clock della SPI (board = MEGA) o è già tirata per il collo (non credo)?

Ci ho attaccato un sistema di prova al volo, ma non riesce a stare al passo sopra le 1000 transazioni al sec.

default setting is SPI_CLOCK_DIV4, which sets the SPI clock to one-quarter the frequency of the system clock (4 Mhz for the boards at 16 MHz).

In alcuni esperimenti l'avevo settata a DIV2, ma non mi è sembrata sta gran differenza

E quanti sono i cicli che ti servono?

BaBBuino:
Si può aumentare la velocità di clock della SPI (board = MEGA) o è già tirata per il collo (non credo)?

Sugli AVR la velocità massima del clock per la SPI è Fclock/2, dato che servono otto cicli clock per una transazione SPI il massimo transfer rate, teorico, è 1000 kBytes/sec.
Dato che molte transazioni spi richiedono la trasmissione e la ricezione di un byte questo porta il transfer rate medio a circa 600-700 kBytes/sec.
Non so Arduino come inizializza la SPI, tocca verificare nel core come viene settato il registro SPCR – SPI, in particolare i bit SPI2X, SPR1, SPR0 che determinano il valore del prescaler clock.
Va da se che gestire un flusso dati continuo a 1 MBytes/sec richiede l'impegno quasi al 100% della cpu dato che gli AVR non dispongono del DMA.

Mi basterebbero 100KHz, o meglio, 100.000 transazioni di un Byte al sec, quindi 800.000 colpi di clock più un poco di overhead. Non credo sia impossibile. Il processore cmq deve fare solo quello, più qualche interrupt poco frequente per aggiornare il dato.

Adesso smanetto un pò con i registri. Cmq thanks, vi faccio sapere...

Ecco la tabellla SPIesca...

Table 21-5. Relationship Between SCK and the Oscillator Frequency
SPI2X SPR1 SPR0 SCK Frequency
0........0.......0....... fosc/4
0........0.......1....... fosc/16
0........1.......0....... fosc/64
0........1.......1....... fosc/128
1........0.......0....... fosc/2
1........0.......1....... fosc/8
1........1.......0....... fosc/32
1........1.......1........fosc/64

Se ne deduce che è sufficiente portare a 1 il bit SPI2X per avere un amento di velocità di.... 2X !

Ed infatti ecco la conferma:

Bit 0 – SPI2X: Double SPI Speed Bit
When this bit is written logic one the SPI speed (SCK Frequency) will be doubled when the SPI is in Master mode
(see Table 21-5). This means that the minimum SCK period will be two CPU clock periods.

Alura...

Ho buttato nel setup() questa semplice istruzione:

SPSR = (1<<SPI2X);

...e visto che è il bit zero del registro, lo shift a sinistra non altera nessun altro bit del registro...

...ottengo...

...una sega!

Come osservato da Paolo non c'è nessuna variazione significativa!

Ah! Istruzione messa DOPO il SPI.begin(); così da sovrascrivere il valore precedente settato nell'inizializzazione

ma così non alteri tutto il registro?, quel registro non ha anche un flag di sola lettura? bho la mega non la ricordo a memoria ma sulla uno faccio cosi:

SPIF &= ~3;
SPSR |= 1;

vbextreme:
ma così non alteri tutto il registro?, quel registro non ha anche un flag di sola lettura? bho la mega non la ricordo a memoria ma sulla uno faccio cosi:

SPIF &= ~3;

SPSR |= 1;

None, è un'operazione atomica.

Non so sulla mega ma sulla uno il primo flags(MSB) del SPSR è di sola lettura, eseguire un assegnamento su un registro dove hai solo un bit W e il resto privati e R non mi sembra una operazione carina..... e sinceramente io non ho mai provato a fare l'assegnazione diretta o indagare cosa realmente accade modificando tali bit e se realmente si modificano oppure vengono bloccati in qualche modo, mica sono così bravo :frowning:

L'atomicita non è quando l'operazione viene eseguita senza interruzioni?
che centra adesso?

ma non mi tornano i conti:
16mhz/2pre = 8mhz/ 8clock = 1000000byte/1024 = 976kb.
quindi 10 volte più veloce di quanto ti serve.
forse devi ottimizzare qualcos'altro?
ma che fai di cosi veloce?

leggi 1.000 tranzioni e ne vorresti 100.000 ... azz stai chiedendo una risoluzione X100 di quella che hai.

Su arduino DUE volevo la massima velocità sulla ethernet e ho notato una velicità soddisfacente modificando le impostazioni a setClockDivider 10 (+/- 8Mhz) contro i 4Mhz dell'AVR massimo disponibile.
Questo divisore è il massimo che posso mettere, successive divisioni mandano tutto in trip SD e W5100 ... però c'è ancora un elevato margine da utilizzare. Non ti so dire però quanti trans. passano dividendo x1 :slight_smile:

Pablo la SPI si usa perchè è molto semplice ma sopratutto molto veloce. E' un semplice Shift Register con un buffer circolare. L' overhead è veramente minimo (I2C ne ha molto di più, oltre non essere così performante per via del fatto che elettricamente è un (N)AND cablato.

Di più veloce mi viene in mente solo un bus parallelo, ma non posso cablare 16 linee, oltre che dover ingegnerizzare bene il PCB visto che un bus parallelo alle velocità necessarie, comincia a soffrire fenomeni di schew.

Come al solito dovrò ripiegare su un PIC serio...

Sgrunt...

Vbextreme i bit W sono fatti per essere Write, appunto. Le modificazioni dei registri è pratica comune nella programmazione dei Micro, non c'è nulla di "oscuro", a patto di saper leggere un Datasheet.

Ci sono innumerevoli modi per agire sui bit di un registro, uno dei quali - se l'Hardware lo permette - è appunto la modificazione atomica, ovvero del singolo bit.

@babbuino:
Vbextreme i bit W sono fatti per essere Write, appunto. Le modificazioni dei registri è pratica comune nella programmazione dei Micro, non c'è nulla di "oscuro", a patto di saper leggere un Datasheet.

Ci sono innumerevoli modi per agire sui bit di un registro, uno dei quali - se l'Hardware lo permette - è appunto la modificazione atomica, ovvero del singolo bit.

Forse non mi sono spiegato, ok il fatto dei flags W che si possono settare.
Ma il flags R e P? quelli che sul datasheet dichiara di sola lettura e privati?
SPSR se non ricordo male è cosi

|R|P|P|P|P|P|P|W|

da quel che scrivi deduco che usando l'assegnazione

SPSR = 1;

si impostera solo il bit scrivibile, ma perchè? perchè ci aiuta il compilatore? o perchè il chip blocca fisicamente la scrittura su quei flags?
rimango dell'idea che sia piu cortese usare sempre la forma

SPSR |= 1;

non hai mica detto cosa devi fare...
teoricamente si può ottimizzare la lettura della spi, devi togliere di mezzo la classe SPI di arduino, vai nel codice sorgente spi.h e fai copia incolla dalla funzione che invia il dato.
Ora dopo aver settato il registro devi aggiungere tanti nop quanti ne servono perchè venga ricevuto il dato, infine elimini di mezzo il while con il controllo sul registro e ti salvi direttamente il valore prendendolo dal suo registro.
Tutta questa pappardella ti incrementa almeno almeno di un 2/3% la velocità complessiva.

BaBBuino:
se l'Hardware lo permette - è appunto la modificazione atomica, ovvero del singolo bit.

C'è un piccolo problema di termini, in informatica non esiste la modificazione atomica, esiste la transazione atomica che è ben altra cosa.
Sugli AVR esistono le operazioni atomiche, definite nella libreria atomic.h delle avrlibc, sono riferite ad operazioni non interrompibili, ovvero durante la loro esecuzione vengono bloccati gli interrupt, tutti o solo parzialmente.
Il termine operazione atomica deriva dal significato stesso della parola atomo, che vuol dire indivisibile, per estensione applicato ad una operazione che non può essere divisa in più parti.
Parlare di modificazione atomica per indicare una semplice operazione di bit set/reset a livello di registro non ha alcun senso ne informatico ne lessicale :slight_smile:

p.s.
Ha ragione VB quando dice che i bit non scrivibili e/o riservati non vanno mai toccati, cercare di scriverli, sopratutto i riservati, può portare a spiacevoli sorprese.