adafruit / Adafruit_QSPI

MIT License
8 stars 6 forks source link

need to get working on Metro M4 #1

Closed dhalbert closed 5 years ago

dhalbert commented 6 years ago

flash_erase.ino with some revisions for the GD25Q doesn't work on Rev E Metro M4 boards; not sure why. flash.begin() fails. Revised code below (with some NeoPixel status code added from https://github.com/adafruit/Adafruit_SPIFlash/blob/master/examples/flash_erase_express/flash_erase_express.ino)

/* Test QSPI read and write functionality. Erase chip, write sequential bytes, verify.
 */
//#include "Adafruit_QSPI_S25FL1.h"
#include "Adafruit_QSPI_GD25Q.h"
#include <Adafruit_NeoPixel.h>

#define NEOPIXPIN     40
// Adafruit_QSPI_S25FL1 flash;
Adafruit_QSPI_GD25Q flash;
Adafruit_NeoPixel pixel = Adafruit_NeoPixel(1, NEOPIXPIN, NEO_GRB + NEO_KHZ800);

uint32_t BLUE = pixel.Color(0, 0, 100);
uint32_t GREEN = pixel.Color(0, 100, 0);
uint32_t RED = pixel.Color(100, 0, 0);
uint32_t OFF = pixel.Color(0, 0, 0);

void setup(){
  Serial.begin(115200);
  pixel.begin();
  pixel.setBrightness(30);
  pixel.setPixelColor(0, BLUE);
  pixel.show();
  delay(500);

  Serial.println("Adafruit QSPI Eraser!");

  if (!flash.begin()){
    Serial.println("Could not find flash on QSPI bus!");
    // blink red
    blink(2, RED);
  }
  Serial.println("Found QSPI Flash");

  Serial.print("Erasing...");
  pixel.setPixelColor(0, RED);
  pixel.show();
  flash.chipErase();
  Serial.println("done!");
  blink(1, GREEN);

}

void loop(){
  //don't even do anything
}

void blink(int times, uint32_t color) {
  while (1) {
    for (int i = 0; i < times; i++) {
      pixel.setPixelColor(0, color);
      pixel.show();
      delay(100);
      pixel.setPixelColor(0, OFF);
      pixel.show();
      delay(100);
    }
    delay(1000);
  }
}
ladyada commented 6 years ago

i vaguely remember not getting qspi working due to some instruction differences but you can always fall back to spi for now

https://github.com/adafruit/Adafruit_Arduino_Tester_Code/blob/master/DevBoards/Metro_M4/metro_m4_basic_selftest/metro_m4_basic_selftest.ino

dhalbert commented 6 years ago

I got the erase to work after disabling the cache via the Arduino IDE Tools menu. I was getting an incorrect Manufacturer ID, but this was due to the cache interfering with the QSPI ABH memory map. It came back as the device ID fetched previously. I'll clean this up and make a .uf2 for erase the Metro M4 SPI flash.

Another odd thing happened after that: Linux became confused about something about the USB ports and I got a fast pulse instead of a slow pulse for METROBOOT. I had to switch to a different set of USB ports to get a slow pulse again. Not sure if this is reproducible.

deanm1278 commented 6 years ago

Yea we'll probably have to be more careful with the cache while using QSPI. We should be able to keep it on but invalidate the specific lines (or the whole thing) when reading those registers. See SAMD51 datasheet section 11.6.8 "Cache Maintenance"

dhalbert commented 6 years ago

Yeah, I am invalidating and disabling the cache already when CircuitPython does QSPI: https://github.com/adafruit/circuitpython/blob/master/ports/atmel-samd/external_flash/qspi_flash.c.

deanm1278 commented 6 years ago

Ok I spoke to @dhalbert about this for a while and we decided that for this library we should try to disable and invalidate the entire cache when reading or writing any registers on a flash chip, and also invalidate and disable the cache when we are writing any data to the flash chip. It should be safe to leave the cache on when reading QSPI data.

I will try to put in and test these changes soon.

dhalbert commented 6 years ago

I had tried using the MPU (Memory Protection Unit) to disable caching in the QSPI_AHB region, but was unsuccessful. The MPU is common across ARM processors: see chapter 11 in the Yiu book. It does not seem like the CMCC pays attention to the MPU cache settings. The code I tried to use to set up the MPU is here: https://github.com/adafruit/circuitpython/blob/9a6a5ea2d989577edc74bf301390398ab2e133f9/ports/atmel-samd/supervisor/port.c#L119.

curtpw commented 6 years ago

Hi Ladyada, your link to the SPI fallback code is dead. Would you mind reposting? This is what I can't get: https://github.com/adafruit/Adafruit_Arduino_Tester_Code/blob/master/DevBoards/Metro_M4/metro_m4_basic_selftest/metro_m4_basic_selftest.ino

ladyada commented 6 years ago
#define FLASHSCK      PIN_QSPI_SCK
#define FLASHMISO     PIN_QSPI_IO1
#define FLASHMOSI     PIN_QSPI_IO0
#define FLASHCS       PIN_QSPI_CS
Adafruit_SPIFlash flash(FLASHSCK, FLASHMISO, FLASHMOSI, FLASHCS);

is the code you wat to use, that will give you access to the flash chip

SapientHetero commented 6 years ago

Is it possible to use the Metro M4's QSPI flash chip as an SD file system?

dhalbert commented 6 years ago

@SapientHetero CircuitPython provides this, but I know of no working Arduino library that provides a USB mass storage filesystem. There are Atmel START drivers and examples: https://start.atmel.com -- browse the examples and look for USB MSC. And then you'd need to hook that up to the flash chip.

ladyada commented 5 years ago

I think this is resolved? also we added M4 pinout examples to the SPIFlash library so you can use that (bitbang plain SPI instead of QSPI) - please reopen if still an issue!