MicroMod SAMD51 flash and Circuitpython

I’ve been working on getting the MicroMod SAMD51 working with Circuitpython. Almost there, but I’m having issues getting the external flash to mount. A couple of questions:

  • Is the external flash set up to use SPI or QSPI (the schematic implies SPI, but I’ve been getting a crash and forced into safe mode, when using it)

  • what’s the expected state of the WP and HOLD pins on the flash? Many boards tie those pins to VCC, but on the MicroMod SAMD51, they’re going to PB22/23 on the mcu.

  • I know that the flash is controlled by the bootloader. Anything in that config that might be preventing it from mounting the CIRCUITPY volume?

Pretty sure I have the SPI config for the main pins to the flash set up correctly (from https://github.com/adafruit/circuitpyth … 1_micromod):

// On-board flash
#define SPI_FLASH_MOSI_PIN &pin_PA09
#define SPI_FLASH_MISO_PIN &pin_PA10
#define SPI_FLASH_SCK_PIN  &pin_PA08
#define SPI_FLASH_CS_PIN   &pin_PA11

Any help/suggestions appreciated!

Don’t quote me on this, but it looks like QSPI https://cdn.sparkfun.com/assets/0/0/5/9/2/60001507C.pdf (page 1087 begins covering the protocol for this chip)

As for the bootloader, I would lean toward ‘no’ https://github.com/sparkfun/MicroMod_Pr … 1-micromod , though you may need to change these settings to switch from either SPI mode or Serial Memory Mode

Thanks for the reply.

I think it’s QSPI, too (even though the schematic implies SPI in the labeling). I’m going to try a couple of other things, and see if I can figure out what’s going on.

Hmm, maybe not. Looking at the SAMD5x datasheet, pads PB22/23 aren’t two of the pins that can be multiplexed for QSPI (it seems that must be (PA08, PA09, PA10, PA11, PB10, and PB11).

So I guess I’m back to figuring out what’s up with the SPI config.

Pretty sure the bootloader has exclusive control over the flash chip, it’s there pretty much only to enable uploading code via UF2.

If you’re somehow able to write code to access the flash chip, the bootloader is going to wipe any changed you made in flash at the next reboot. Sparkfun has some inexpensive SPI and I2C EEPROMs you can connect to the SAMD51 where you can store nonvolatile data if that’s what you’re after.

It doesn’t make sense why they would put a whole 16MB of flash that can’t be used except for the bootloader, while the onboard flash and program size of the SAMD51 is only 1MB.

A board like the Adafruit Grand Central M4 uses a SAMD51 with 1MB of built-in flash, has UF2 capability, and an external 8MB flash that CAN be used. So if it is tied to the bootloader on the MicroMod like one of the tech support reps said, I’d be curious why.

I think there is confusion between the SAMD51 onboard flash with the external W25Q128 flash of these boards. That wouldn’t explain why it still can’t be accessed though.

[EDIT] The Sparkfun Thing + uses the same SAMD51J20, and lets you access the external flash.

It’s not that the bootloader has exclusive control of the flash, it’s that there’s a design flaw on this module, and the flash chip is not accessible via hardware SPI (it can be made to work with bitbang SPI; there’s another thread about that).

It turns out the assignment of PA10 to MOSI is a mistake, because that pin cannot be muxed to that function. It’s unclear why the somewhat standard ordering of PA08/09/10/11 wasn’t used on this module (I assume it was down to routing issues), but in any case, it’s not going to work with hardware SPI on ANY platform.

I’ve put in a PR to have CircuitPython use the internal flash for now, with a reduced number of CP modules appropriate to the smaller 1MB available. I’m going to look into whether it’s possible to bitbang the SPI in CP, and if so, will update the board support with that.

Sooooooo frustrating.

You could always design your own board…

YellowDog:
You could always design your own board…

I don’t think it’s unreasonable to be frustrated with a design flaw. The MicroMod Artemis Processor also has a number of design flaws that frustrated the heck out of me.

I could design my own board, but I did buy this module, so I think it should work as expected. :wink:

But guess what? The new revision of this module is out and mine arrived from Sparkfun today. I’m just waiting for an updated version of the schematic so I can find out what pins the flash is using.

Bad news: it looks like the 1.3 version of the module doesn’t work any better than the 1.2 version. The new revision does fix one issue, now correctly attaching the correct pin for COPI to the DI pin on the flash. Sadly, that’s only half the problem, because the wrong pin is still going to CS on the flash. So it amounts to the same issue: the pins are connected in a fashion that isn’t supported by SERCOM2 on the SAMD51 (and SERCOM 0 is being used for the main SPI interface). So there’s no way to make the external flash work on either revision of the board.

I could be wrong about how the new revision is set up: the latest schematic has not been published. I figured out the pins by toning them out with my multimeter.

Attached are the results of checking the 1.2 and 1.3 version of the module.

I’m bummed about this. It feels like neither of these modules was fully tested.

Good morning! First off here’s an image writing to the external flash chip on the backside of the SAMD51 Processor Board:

I can provide more serial output images of writing and reading to the flash, but if you use SparkFun’s SPI Flash Arduino library you can recreate them as well.

Here’s the logic being used in for the SERCOM selections. The SAMD51 is using SERCOM2 as you mentioned. The SPI clock signal can only be routed on the PAD1 which both v12 and v13 had correct. However, data out (COPI) is limited to PAD3 or PAD0 which I incorrectly routed onto PAD2 in v12. Data In (CIPO) and chip select can be routed to any PAD (PAD0-PAD3). For the chip select pin the datasheet mentions that it is on PAD2 OR the system configuration i.e some other pin. All information above can be found in the SERCOM SPI section of the datasheet. To summarize: the clock and data out signals are limited to particular pins: clock to PAD1 and data out to PAD0 or PAD3. Data In and the chip select pins are much more flexible - chip select does not even need to be in the same SERCOM while data in can be any pad but is limited by other SPI signals instead.

My goal was to keep the changes small due to time constraints and because I really wanted a timely turn around. Limiting the number of changes lowers the risk of making other mistakes, something like woops the clock line has to be rerouted and now there’s cross talk for example. The external flash does work and if you’d like more images or the code specifically, I’d be happy to comply.

Just getting back to this. I’ll take a look at the Arduino Library and see if I can use that to extract what I need to get the config to work with CircuitPython.

Also: any chance I get to the 1.3 schematic? And sample code you used? (I assume this was just the standard library sample, with the WP and HOLD held high and the SPI port specificed, but I would like to be sure, rather than guessing)