SparkFun Forums 

Where electronics enthusiasts find answers.

Topics pertaining to the Arduino Core & software used with the Artemis module and Artemis development boards.
User avatar
By robin_hodgson
#216935
I've been using the Arduino standard SPI interface for a while now. There are 6 total SPI units on a Redboard though. A new project is using SPI2/IOM2. The strange part is that when I perform a write to SPI2, I don't get any activity on IOM2 SCK or MOSI. I see my test program assert CS, then there is a blank spot where my data should be, and then CS gets deasserted. I do see the time it takes to perform the transfer, but nothing appears on SCK2 or MOSI2. I did an SPI2.begin(), and I am calling SPI2.transferOut() to send my data.

I must be missing something obvious here. My interpretation of the definition of Arduino SPI2 is that it uses the Apollo3 IOM2. This means that it would drive its clock on SCK2 (Redboard silkscreen D6, corresponding to Apollo3 pin 27). It would drive the data out on MOSI2 (Redboard silkscreen D7, corresponding to Apollo3 pin 28). I just see SCK2 and MOSI2 sit there at '0'. Any ideas?
User avatar
By robin_hodgson
#216943
OK, there are some issues here. Here is a trivial test program:
Code: Select all
  Serial.println("At SPI.begin()");
  SPI.begin();
  Serial.println("At SPI1.begin()");
  SPI1.begin();
  Serial.println("At SPI2.begin()");
  SPI2.begin();
  Serial.println("At SPI3.begin()");
  SPI3.begin();
  Serial.println("At SPI4.begin()");
  SPI4.begin();
  Serial.println("At SPI5.begin()");
  SPI5.begin();
Strangely, this won't even compile. I get errors that SPI4 and SPI5 are undefined. The Sparkfun SPI.cpp file shows that I have 6 SPI units declared.

Ignoring that weirdness, I deleted the references to SPI4 and SPI5 in the test. Then I instrumented the Sparkfun SPI.cpp code to tell me which pins it was initializing for each of the SPI units. That gave me this:
Code: Select all
At SPI.begin()
Inside SPIClass::begin() for instance 0
Setting up SPI instance 0 pin 5 as SCK
Setting up SPI instance 0 pin 7 as MOSI
Setting up SPI instance 0 pin 6 as MISO
At SPI1.begin()
Inside SPIClass::begin() for instance 2
Setting up SPI instance 2 pin 27 as SCK
Setting up SPI instance 2 pin 28 as MOSI
Setting up SPI instance 2 pin 25 as MISO
At SPI2.begin()
Inside SPIClass::begin() for instance 1
Setting up SPI instance 1 pin 8 as SCK
Setting up SPI instance 1 pin 10 as MOSI
Setting up SPI instance 1 pin 9 as MISO
At SPI3.begin()
Inside SPIClass::begin() for instance 3
Setting up SPI instance 3 pin 42 as SCK
Setting up SPI instance 3 pin 38 as MOSI
Setting up SPI instance 3 pin 43 as MISO
There is the problem: IOM1 and IOM2 are swapped. SPI.begin properly set up IOM0, and SPI3.begin properly set up IOM3. But it explains why my data is not showing up on the bus: it must be going out on the wrong pins because it is using the wrong IOM.

Something is obviously funky. Maybe it is related to the fact that SPI4 and 5 do not exist when they obviously should exist. Any ideas out there?
User avatar
By robin_hodgson
#216944
OK, I found this in the definition of a Redboard:
Code: Select all
// SPI Defines
#define SPI_INTERFACES_COUNT 4

#define AP3_SPI_IOM 0                   // Specify that SPI uses IOMaster 0
#define AP3_SPI_DUP ap3_spi_full_duplex // Specify that SPI is full-duplex (as opposed to ap3_spi_tx_only or ap3_spi_rx_only)

#define AP3_SPI1_IOM 2
#define AP3_SPI1_DUP ap3_spi_full_duplex

#define AP3_SPI2_IOM 1
#define AP3_SPI2_DUP ap3_spi_full_duplex

#define AP3_SPI3_IOM 3
#define AP3_SPI3_DUP ap3_spi_full_duplex
There it is: SPI1 is IOM2 and SPI2 is IOM1.

I can see why a Redboard Arduino variant would not support IOM5 and 6 because the Artemis pins don't make it to the Redboard pins, but what was the theory behind swapping IOM1 and 2? That's a totally unnecessary source of confusion.
User avatar
By liquid.soulder
#216946
Robin, which redboard definition is that in?

Typically the variant definitions are only exposing "dedicated" (labelled) interfaces. It is left up to the user to create their own additional SPIClass objects using the constructor "SPIClass mySPI(IOM#, DUPLEX_SETTING)"

On the regular redboard we've made SPI use the IOM peripheral that was most convenient to route to the equivalent Arduino Uno pins (also considering pin capability priorities)

I'm unfamiliar with which board has SPI_INTERFACES_COUNT set to 4 (excluding SPI5 and SPI6 by default)... did you modify anything in your local core?
User avatar
By robin_hodgson
#216948
I did not modify my local core. The Redboard is defined here: <...>\AppData\Local\Arduino15\packages\SparkFun\hardware\apollo3\1.1.1\variants\redboard_artemis\config

The compile commands during the arduino build show that this is the file being used:
... "-IC:\\Users\\robin\\AppData\\Local\\Arduino15\\packages\\SparkFun\\hardware\\apollo3\\1.1.1\\variants\\redboard_artemis/config" ...

It is left up to the user to create their own additional SPIClass objects using the constructor "SPIClass mySPI(IOM#, DUPLEX_SETTING)"
I searched all over, but I can't find that documented anywhere. If it is, my apologies, and can you point me at what I should be reading?
User avatar
By liquid.soulder
User avatar
By robin_hodgson
#216957
I don't get it. How come my variants.h file for a Redboard is so different than yours? My board manager says it is at revision 1.1.1, which is the most recent.

Yours:
Code: Select all
// SPI Defines
#define SPI_INTERFACES_COUNT 1

#define AP3_SPI_IOM 0                   // Specify that SPI uses IOMaster 0
#define AP3_SPI_DUP ap3_spi_full_duplex // Specify that SPI is full-duplex (as opposed to ap3_spi_tx_only or ap3_spi_rx_only)
Mine:
Code: Select all
// SPI Defines
#define SPI_INTERFACES_COUNT 4

#define AP3_SPI_IOM 0                   // Specify that SPI uses IOMaster 0
#define AP3_SPI_DUP ap3_spi_full_duplex // Specify that SPI is full-duplex (as opposed to ap3_spi_tx_only or ap3_spi_rx_only)

#define AP3_SPI1_IOM 2
#define AP3_SPI1_DUP ap3_spi_full_duplex

#define AP3_SPI2_IOM 1
#define AP3_SPI2_DUP ap3_spi_full_duplex

#define AP3_SPI3_IOM 3
#define AP3_SPI3_DUP ap3_spi_full_duplex
User avatar
By robin_hodgson
#216967
To sum it all up for anyone googling this thread:
  • In the Artemis Arduino world, there is no relationship to be expected between the 'n' of predefined SPI<n> objects and the IOM unit 'n' that is used by those objects. It was just happenstance that SPI0 mapped to IOM0 and SPI3 mapped to IOM3 on a Redboard.
  • It would be wise for a software developer to assume that the different Artemis-based Arduino boards may perform the SPI->IOM mappings as they see fit. So far, the basic Artemis Arduino SPI class always uses IOM0, but beyond that, it would be safest for a software developer to make no further assumptions regarding the SPI->IOM mappings.
  • If you need to perform SPI using a particular IOM, instead of trying to figure out the SPI->IOM mappings for your specific Arduino board, just create your own SPI class that explicitly defines the relationship:
    Code: Select all
    SPIClass mySPI(IOM# [, DUPLEX_SETTING])
    where:
    • IOM# ranges from [0..5]
    • The optional duplex setting can be:
      • ap3_spi_tx_only
      • ap3_spi_rx_only
      • ap3_spi_full_duplex (the default, performs R/W transfers)
    Creating an SPI interface in this fashion ensures that it will continue to function as expected if you move your project to a different Artemis board that may implement different SPI->IOM mappings.
User avatar
By liquid.soulder
#216973
Great summary Robin, thank you.

The only thing I would change is to say that people should not even rely on SPI mapping to IOM0. That is merely happenstance. The method you described above is the preferred way of specifying SPI ports.

Also, it is OK to declare SPI ports using IOM modules that are already associated with another SPI object. Say SPI maps to IOM0, but you create your own SPIClass object "mySPI" that also uses IOM0. This is OK as long as only one object gets used (either SPI or mySPI but not both) because the IOM module is actually configured in the ".begin()" method.
 Topic permissions

You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum