Go Down

Topic: spi on other pins (Read 1 time) previous topic - next topic

bobricius

Hi, please can anybody help how to configure SPI to work on digital pins 10,11,12,13 for old SD card shields?
World smallest Arduino, Attiny85 wave player
https://www.tindie.com/stores/bobricius/

david_prentice

I am in the UK.  So I can only buy the "Zero Pro" (now called "M0 Pro")
Since the warring Italians don't let you run a Zero Pro on v1.6.5 I can only show you how I have patched v1.7.5  "libraries/SPI/SPI.cpp"
Code: [Select]

void SPIClass::begin()
{
  // PIO init
  if (_p_sercom == &sercom1) {
    // this forces the pads and pins for 11,12,13 regardless of pin descriptions or constructor()
 pinPeripheral(12, PIO_SERCOM);
 pinPeripheral(13, PIO_SERCOM);
 pinPeripheral(11, PIO_SERCOM);
 _p_sercom->initSPI(SPI_PAD_0_SCK_1, SERCOM_RX_PAD_3, SPI_CHAR_SIZE_8_BITS, MSB_FIRST);
  }
  else {
 pinPeripheral(_uc_pinMiso, g_APinDescription[_uc_pinMiso].ulPinType);
 pinPeripheral(_uc_pinSCK, g_APinDescription[_uc_pinSCK].ulPinType);
 pinPeripheral(_uc_pinMosi, g_APinDescription[_uc_pinMosi].ulPinType);

 // Default speed set to 4Mhz, SPI mode set to MODE 0 and Bit order set to MSB first.
 _p_sercom->initSPI(SPI_PAD_2_SCK_3, SERCOM_RX_PAD_0, SPI_CHAR_SIZE_8_BITS, MSB_FIRST);
  }
 _p_sercom->initSPIClock(SERCOM_SPI_MODE_0, 4000000);
 
 _p_sercom->enableSPI();
}


...

//SPIClass SPI(&sercom4, 18, 20, 21);     // .kbv replace the default ICSP header pins
SPIClass SPI(&sercom1, 12, 13, 11);       // .kbv with the traditional UNO pins


The g_APinDescription[] table in v1.7.5 does not have the relevant description for using SERCOM1 as SPI.   As you can see,   the constructor arguments are ignored if it is using SERCOM1.    And the SERCOM4 code depends on you sending the correct ICSP pin numbers too.  

I only hope that the v1.6.5 code has been written more carefully.  

David.

david_prentice

#2
Jul 09, 2015, 01:18 pm Last Edit: Jul 09, 2015, 01:23 pm by david_prentice
I have since installed v1.6.5 which in turn installs the ZERO package with "SPI.cpp" into my "C:\Users\David Prentice\AppData\Roaming\Arduino15\packages\arduino\hardware\samd\1.6.0\libraries\SPI" directory

The v1.6.x code appears to be far better organised than the v1.7.5 stuff for the "M0" and "M0 Pro"

I installed the ZERO bootloader via EDBG and have been successfully running v1.6.5 on my "M0 Pro" (formerly known as Zero Pro)

A "better" patch of the v1.6.0 SPI.cpp file is in the config() method instead of the begin() method:
Code: [Select]

void SPIClass::config(SPISettings settings)
{
  _p_sercom->disableSPI();
#if 1
  if (_p_sercom == &sercom1) {
    // this forces the pads and pins for 11,12,13 regardless of pin descriptions or constructor()
 pinPeripheral(12, PIO_SERCOM);
 pinPeripheral(13, PIO_SERCOM);
 pinPeripheral(11, PIO_SERCOM);
 _p_sercom->initSPI(SPI_PAD_0_SCK_1, SERCOM_RX_PAD_3, SPI_CHAR_SIZE_8_BITS, settings.bitOrder);
  }
  else {
 _p_sercom->initSPI(SPI_PAD_2_SCK_3, SERCOM_RX_PAD_0, SPI_CHAR_SIZE_8_BITS, settings.bitOrder);
  }
#else
  _p_sercom->initSPI(SPI_PAD_2_SCK_3, SERCOM_RX_PAD_0, SPI_CHAR_SIZE_8_BITS, settings.bitOrder);
#endif
  _p_sercom->initSPIClock(settings.dataMode, settings.clockFreq);

  _p_sercom->enableSPI();
}

...

//SPIClass SPI( &sercom4, PIN_SPI_MISO, PIN_SPI_SCK, PIN_SPI_MOSI );
SPIClass SPI( &sercom1, 12, 13, 11 );


I also patched "variant.cpp" for the different assignment of digital#2 and #4 pins:
Code: [Select]

  // 2..12
  // Digital Low
#if M0_PRO
  { PORTA,  8, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI }, // TCC0/WO[0]
  { PORTA,  9, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_9 }, // TCC0/WO[1]
  { PORTA, 14, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH0, TC3_CH0, EXTERNAL_INT_14 }, // TC3/WO[0]
#else
  { PORTA, 14, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_14 },
  { PORTA,  9, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_9 }, // TCC0/WO[1]
  { PORTA,  8, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI },  // TCC0/WO[0]
#endif


I can run a TFT display on the regular "UNO" SPI pins and read a microSD card connected to the same bus.    If you use my "SERCOM1" patch,   you should be able to run two independent SPI buses if you want to.    Note that the <SD.h> library seems to require hard-named SPI object.    Your TFT code could use a differently named object.

David.

Dameer

Hi David,

I find your replies very helpful. I am just curios if the one you written would allow using both the ICSP SPI and the new declared 1

//SPIClass SPI( &sercom4, PIN_SPI_MISO, PIN_SPI_SCK, PIN_SPI_MOSI );
SPIClass SPI( &sercom1, 12, 13, 11 );

I find your replies very helpful. I am just curios if the one you written would allow using both the ICSP SPI and the new declared 11, 12, 13 simultaneously.

Thank you

Go Up