[Me: I have multiple decades with C and C++ programming, I'm deeply familiar with ARM in general and SAMD21 in particular, and I've written lots of sketches using existing libraries in Arduino, but I'm a complete newcomer to developing complex systems in the Arduino framework.]
I'm working on a project that requires three SPIs: One for SD/FATFS, one for an LCD display, one for a touch screen. My target processor is a SAMD21J18A (not a SAMD21G) on a SAMD21 XPRO development board.
Making any ONE of those SPI devices work appears not to be a problem: I'm using the board manager from here:
[Atmel SAMD21/W25/R21 Xplained Pro Arduino IDE Board Manager Module](https://github.com/AtmelUniversityFrance/atmel-samd21-xpro-boardmanagermodule)
and it gets me partway there. I already have working code for the LCD display, I'm confident that the SD library would work with my setup, etc.
But where I'm stumped putting together an app that uses three SPIs simultaneously. I see that the SAMD21 XPRO variant.cpp file has support for multiple SERCOMs, but I don't understand how to instruct the mid-level libraries (i.e. SPI and SD) to use specific SERCOMs.
Do I create custom versions of those libraries with hardwired (or parameterized) pin numbers? Or is there some better way to do that?
SPI is a bus system, devices are selected by pulling their CS line low.
So as long as the devices are well-behaved - not driving bus lines when not selected -
you can run many of them on the same hardware SPI lines, each only needs an own CS pin.
@Whandall : I appreciate your replies. Two points:
I certainly know about using separate CS lines on a single SPI bus. The reason I asked about multiple SPIs is that -- due to external reasons -- I need multiple SPIs. Is that impossible in the Arduino world? (Seems hard to believe...)
"misusing the 3.3V 5V level shifter". What board are you talking about? I'm pretty sure the SAMD21 Xplained Pro board is 3.3V throughout.
The OP's processor data sheet claims an ability for it to configure up to 6 SPI interfaces, so the original question, how to get a library to use a specific capability stands.
As most of you already know, the SAMD21 is an ARM core, not an AVR. Regular AVR stuff doesn't apply.
I want to use separate SPI buses (rather than multiplexing one bus with separate CS lines) because:
The SAMD21 XPRO dev board breaks out three separate SERCOMs on edge connectors (SERCOM0, 1, 5).
My SD card plugs into one of those three edge connectors.
I think the touch screen SPI and LCD SPI use different clock modes than the SD card (and maybe different speeds), so I'd have to reconfigure the SPI bus between each operation if I use a single SPI bus.
I'd like the option in the future for a direct DMA operation between the SD and the LCD.
Having said as much, I've figured out the mapping for the SERCOMs and the "native" Arduino pins, as defined in the SAMD21 XPRO variant.cpp file:
SAMD21 XPRO EXT1:
Function
SAMD21 XPRO
SAMD21J GPIO
SERCOM[pad]
Arduino Pin
CS_
EXT1.15
PA05
SERCOM0[1]
37
MOSI
EXT1.16
PA06
SERCOM0[2]
34
MISO
EXT1.17
PA04
SERCOM0[0]
35
SCK
EXT1.18
PA07
SERCOM0[3]
36
SAMD21 XPRO EXT2:
Function
SAMD21 XPRO
SAMD21J GPIO
SERCOM[pad]
Arduino Pin
CS_
EXT2.15
PA17
SERCOM1[1]
42
MOSI
EXT2.16
PA18
SERCOM1[2]
39
MISO
EXT2.17
PA16
SERCOM1[0]
40
SCK
EXT2.18
PA19
SERCOM1[3]
41
SAMD21 XPRO EXT3:
Function
SAMD21 XPRO
SAMD21J GPIO
SERCOM[pad]
Arduino Pin
CS_
EXT3.15
PB17
SERCOM5[1]
47
MOSI
EXT3.16
PB22
SERCOM5[2]
44
MISO
EXT3.17
PB16
SERCOM5[0]
45
SCK
EXT3.18
PB23
SERCOM5[3]
46
So to get back to my original question: If I want the SD library to use Arduino Pins (for example) 44, 45, 46 for MOSI, MISO, SCK, what's the right way to do that? Do I need to modify the library? Or is there a way to tell the SD library to use the alternate pins?
There's an Adafruit topic called Creating a new SPI that talks about SERCOMs and which signals go to which "PADS". There are examples using SERCOM1 & SERCOM2, which may help you out.
@markd833 Thanks for that. I'd already read that article -- it's about how to create SERCOM1 and 2, and as I mentioned, I have the pins for multiple SERCOMs.
If you trace through the SD library (i.e. in Sd2Card.cpp) it uses MOSI, MISO, and SCK for its SPI bus which (as you can see above) maps to SERCOM0.
If I want the SD library to use (say) SERCOM1, what's the idiomatically correct "Arduio Way" to make that happen? Some alternatives I see:
Modify variant.h to redefine MOSI, MISO and SCK to use PIN_SPI1_MOSI, etc.
Modify SPI to take parameters on its init function and make appropriate changes to Sd2Card to provide those parameters
Something else?
edit: I also suspect that if I use something other than SERCOM0, I need to make sure the module gets initialized. Or maybe that happens regardless -- any pointers appreciated.
@rdpoor, there are some examples at the very end of the web page I mentioned earlier. They show how to use the SPIClass and how to define the pins you want to use.
The datasheet for the SAMD21 family in the section called I/O Multiplexing & Considerations (section 7 in my datasheet) has a table showing the relationship between actual pins and the the various peripheral devices within the chip.
For SERCOM0 you are using the alternate pins (?), and SERCOM1 is using the normal pins.
I'm not sure about your mapping for SERCOM5. According to the datasheet, you are using the alternate pins for MOSI & SCK, but the normal pin for MISO. I think it has to be all normal or all alternate, but I could be wrong as i've just started playing with the SAMD21 devices.