Skip to content

SPI peripheral mapping not working on some RP2040 based boards #469

@caternuson

Description

@caternuson

This forum poster was trying to get a Feather RP2040 CAN working with a TFT FeatherWing:
https://forums.adafruit.com/viewtopic.php?t=217465

Dealing with ensuring the various CS pins were being handled properly worked to a certain point, however, it was not possible to get a full working example using both CAN and TFT at the same time. I tried to work up an example and ran into a similar issue. Drilling into things, it seems like an issue with some conditional mapping being done to set up the SPI peripheral being used. There are numerous instances of this code:

#elif defined(ARDUINO_ARCH_RP2040)
spi_inst_t *pi_spi = hwspi._spi == &SPI ? spi0 : spi1;

However, it seems the philhower core maps spi0 and spi1 to the RP2040's SPI0 and SPI1 peripherals. The Feather RP2040 CAN's default SPI pins use the SPI1 peripheral:

Image

also:
https://github.com/earlephilhower/arduino-pico/blob/e05dd50d626d2871ab988d8e72aa7c12e18e603c/variants/adafruit_feather_can/pins_arduino.h#L32-L37

So it seems like that tertiary logic ends up mapping to spi0 instead of spi1 as needed.

Doing a quick hack and changing all instances of:

spi_inst_t *pi_spi = hwspi._spi == &SPI ? spi0 : spi1;

to:

spi_inst_t *pi_spi = spi1;

resolves the issue.

So the problem is known, but at this point unclear what a good code fix would be.

Example test sketch:

/*
 * TFTFeatherWing + Feather RP2040 CAN Example
 */
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <Adafruit_MCP2515.h>

#define MCP_CS PIN_CAN_CS   // CAN
#define STMPE_CS 6          // touch
#define TFT_CS   9          // TFT
#define TFT_DC   10
#define SD_CS    5          // SD
   
#define CAN_BAUDRATE (250000)

// CAN
Adafruit_MCP2515 mcp(MCP_CS);

// TFT
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

void setup() {
  Serial.begin(115200);
  while(!Serial) delay(10);

  Serial.println("TX Feather RP2040 CAN + TFT FeatherWing test!");

  // force disable all SPI things
  pinMode(MCP_CS, OUTPUT); digitalWrite(MCP_CS, HIGH);
  pinMode(STMPE_CS, OUTPUT); digitalWrite(STMPE_CS, HIGH);
  pinMode(SD_CS, OUTPUT); digitalWrite(SD_CS, HIGH);
  pinMode(TFT_CS, OUTPUT); digitalWrite(9, HIGH); 

  Serial.println("CAN init");
  if (!mcp.begin(CAN_BAUDRATE)) {
    Serial.println("Error initializing MCP2515.");
    while(1) delay(10);
  }
  Serial.println("MCP2515 chip found");

  Serial.println("TFT init");
  tft.begin();
  uint8_t x = tft.readcommand8(ILI9341_RDMODE);
  Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDMADCTL);
  Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDPIXFMT);
  Serial.print("Pixel Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDIMGFMT);
  Serial.print("Image Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDSELFDIAG);
  Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX);

  // fill color pattern
  tft.fillScreen(ILI9341_RED);
  delay(5000);
  tft.fillScreen(ILI9341_GREEN);
  delay(5000);
  tft.fillScreen(ILI9341_BLUE);
  delay(5000);

  Serial.println("START DONE");
}

void loop() {
  // send packet: id is 11 bits, packet can contain up to 8 bytes of data
  Serial.print("Sending packet ... ");

  mcp.beginPacket(0x12);
  mcp.write('h');
  mcp.write('e');
  mcp.write('l');
  mcp.write('l');
  mcp.write('o');
  mcp.endPacket();

  Serial.println("done");

  delay(1000);

  // send extended packet: id is 29 bits, packet can contain up to 8 bytes of data
  Serial.print("Sending extended packet ... ");

  mcp.beginExtendedPacket(0xabcdef);
  mcp.write('w');
  mcp.write('o');
  mcp.write('r');
  mcp.write('l');
  mcp.write('d');
  mcp.endPacket();

  Serial.println("done");

  delay(1000);
}

CURRENT BEHAVIOR:
Image

BEHAVIOR WITH HACK FIX:
Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions