Arduino R4 SPI cambio velocità

Ciao a tutti,
mi sono imbattuto in un comportamento anomalo durante la configurazione della velocità della SPI.
Il problema è il seguente:

  1. Configuro la SPI con la velocità di 20MHz

  2. Chiamo la funzione di SPI.begin();

  3. Invio un byte e misuro il clock a di 12MHz (Arduino configura la massima F possibie)

  4. Disabilito la SPI con la funzione SPI.end

  5. Inizializzo di nuovo la SPI richiamando le mie configurazioni della SPI

  6. Invio un byte e misuro il clock a di 1MHz anche se il valore impostato è 12MHz

  7. Si ripete il loop e ora misuro sempre 1MHz di clock anche se imposto 20MHz

Qui sotto il codice di esempio per riprodurre il problema

#include <SPI.h>
uint32_t clkSPI = 20000000;
BitOrder bitOrder = MSBFIRST;
uint8_t spiMode = SPI_MODE0;
SPISettings mySettings(clkSPI, bitOrder, spiMode);


void setup() {
}

void loop() {  
  clkSPI = 20000000;
  SPI.begin();
  mySettings = SPISettings(clkSPI, bitOrder, spiMode);
  SPI.beginTransaction(mySettings);
  SPI.transfer(0x00);
  SPI.endTransaction();
  SPI.end();
  
  delay(1000);

  //
  SPI.begin();
  mySettings = SPISettings(clkSPI, bitOrder, spiMode);
  SPI.beginTransaction(mySettings);
  SPI.transfer(0x00);
  SPI.endTransaction();
  SPI.end();
  
  delay(1000);
}

Mentre se cambio la velocità dopo aver riaperto la SPI non noto problemi ovvero il clock cambia da 12MHz->3MHz->12MHz->3MHz...e così via


Qui sotto il codice di esempio

#include <SPI.h>
uint32_t clkSPI = 20000000;
BitOrder bitOrder = MSBFIRST;
uint8_t spiMode = SPI_MODE0;
SPISettings mySettings(clkSPI, bitOrder, spiMode);


void setup() {

}

void loop() {
  
  clkSPI = 20000000;
  SPI.begin();
  mySettings = SPISettings(clkSPI, bitOrder, spiMode);
  SPI.beginTransaction(mySettings);
  SPI.transfer(0x00);
  SPI.endTransaction();
  SPI.end();
  
  delay(1000);

  clkSPI = 3000000;
  SPI.begin();
  mySettings = SPISettings(clkSPI, bitOrder, spiMode);
  SPI.beginTransaction(mySettings);
  SPI.transfer(0x00);
  SPI.endTransaction();
  SPI.end();
  
  delay(1000);
}

A questo punto ho indagato nel core di Arduino ArduinoCore-renesas e ho trovato che ogni chiamata SPI.begin(SPI.cpp) iniziallizza la velocità ad un default che è 1MHz

SPI.h
arduino::SPISettings const DEFAULT_SPI_SETTINGS = arduino::SPISettings(1000000, MSBFIRST, arduino::SPI_MODE0);

Poi analizzando SPI.beginTransaction in SPI.cpp

void ArduinoSPI::beginTransaction(arduino::SPISettings settings)
{
  if (!_is_initialized)
    begin();

  if (_settings != settings) //<-SOLO SE È DIVERSO DAL SETTING PRECEDENTE
  {
    configSpiSettings(settings);
    _settings = settings; //<-COPIA LA NUOVA IMPOSTAZIONE
    /*
    if (_is_sci) {
      _close(&_spi_sci_ctrl);
      _open(&_spi_sci_ctrl, &_spi_cfg);
    } else {
      _close(&_spi_ctrl);
      _open(&_spi_ctrl, &_spi_cfg);
    }
    */
  }
}

La funzione cambia configurazione solo se la varibile "_settings" è diversa dal "setting"... questo spiega il perchè vedo funzionare la configurazione a 20MHz solo una volta .
Avete altre idee?

Grazie Jampag
PS:Ho questa necessità di aprire e chiudere la SPI perchè nel mio progetto devo liberare i pin SPI e poi ho la necessità di cambiare la SPI dinamicamente a volte.

@jampag ha inviato un rapporto agli sviluppatori:

Grazie!

2 Likes

Ciao @ptillisch , se avete una versione di prova posso fare delle prove con oscilloscopio.

Grazie :slight_smile:

Grazie!

Puoi applicare manualmente la modifica mostrata qui al percorso libraries/SPI/SPI.cpp che si trova nell'installazione "Arduino Renesas UNO Boards" sul tuo computer:

--- a/libraries/SPI/SPI.cpp
+++ b/libraries/SPI/SPI.cpp
@@ -139,6 +139,7 @@ void ArduinoSPI::begin()
   _sci_spi_ext_cfg.clk_div.mddr = 0;
 
   configSpiSettings(DEFAULT_SPI_SETTINGS);
+  _settings = DEFAULT_SPI_SETTINGS;
 
   /* Configure the Interrupt Controller. */
   if (_is_sci)
1 Like

Grazie @ptillisch ,

ho appena verifica con oscilloscopio la frequenza rimane quella settata e non piu 1MHz.

#include <SPI.h>
uint32_t clkSPI = 20000000;
BitOrder bitOrder = MSBFIRST;
uint8_t spiMode = SPI_MODE0;
SPISettings mySettings(clkSPI, bitOrder, spiMode);


void setup() {
}

void loop() {  
  clkSPI = 20000000;
  SPI.begin();
  mySettings = SPISettings(clkSPI, bitOrder, spiMode);
  SPI.beginTransaction(mySettings);
  SPI.transfer(0x00);
  SPI.endTransaction();
  SPI.end();
  
  delay(1000);

  //
  SPI.begin();
  mySettings = SPISettings(clkSPI, bitOrder, spiMode);
  SPI.beginTransaction(mySettings);
  SPI.transfer(0x00);
  SPI.endTransaction();
  SPI.end();
  
  delay(1000);
}

NOTA: Anche se la frequenza settata è 20MHz la frequenza massima che misuro è 12MHz su Arduino uno R4 Minima

Non pensavo si potesse cambiare così facilmente la libreria, si impara sempre. Questo mi da un buono spunto per cercare di invertire i pin CIPO e COPI

Grazie mille

2 Likes