I made a library that can automatically save and restore Particle device keys. No more fast blinking cyan (possibly with red or orange blinks) and having to particle keys doctor with a laptop and USB (hopefully)!
The library and documentation are here:
The library needs a place to store the backup keys. The amount of space you need varies depending on the type of device:
- For Wi-Fi devices (Photon, P1): 1608 bytes
- For cellular devices (Electron, E series): 328 bytes
There’s an option to use the EEPROM emulation. This isn’t the best choice as it’s also in the STM32 flash and could be corrupted, and also especially for Wi-Fi devices, most of it would be used up by the saved keys.
Here’s an example of saving the keys to offset 100 in the EEPROM, however:
#include "Particle.h"
#include "DeviceKeyHelperRK.h"
SYSTEM_MODE(SEMI_AUTOMATIC);
SerialLogHandler logHandler;
// Save and restore the device keys in EEPROM at offset 100 in the EEPROM
DeviceKeyHelperEEPROM deviceKeyHelper(100);
void setup() {
// You must call this from setup to start monitoring for keys errors
deviceKeyHelper.startMonitor();
// You either need to use SYSTEM_THREAD(ENABLED) or SYSTEM_MODE(SEMI_AUTOMATIC) because
// in thread disabled AUTOMATIC mode, setup() isn't called until cloud connected and the
// code to monitor the connection would never be started via startMonitor().
Particle.connect();
}
void loop() {
}
Other storage medium include:
SpiffsParticleRK
The SpiffsParticleRK library supports SPI-connected NOR flash chips. These are typically tiny 8-SOIC surface mount chips, intended to be included on your own circuit board. There are also breadboard adapters that are available.
The chips are really inexpensive, less than US$0.50 in single quantities for a 1 Mbyte flash. They’re available in sizes up to 16 Mbyte.
SPI flash is less expensive than SD cards, and do not need an adapter or card slot. Of course they’re not removable.
The underlying SpiFlashRK library library supports SPI NOR flash from
- ISSI, such as a IS25LQ080B.
- Winbond, such as a W25Q32.
- Macronix, such as the MX25L8006EM1I-12G
- The external 1 Mbyte flash on the P1 module.
- Probably others.
P1 using flashee-eeprom
If you are already using flashee-eeprom to store files in the P1 external flash, you can easily add support for saving keys in it as well.
// Check the device public and private keys against the keys stored in the file "keys"
DeviceKeyHelperFlasheeFile deviceKeyHelper("keys");
SdFat
If you are using SdFat, with an SD card, it’s as easy as:
#include "Particle.h"
// Make sure you include SdFat.h before DeviceKeyHelperRK.h, otherwise you won't have support for SdFat
#include "SdFat.h"
#include "DeviceKeyHelperRK.h"
SYSTEM_MODE(SEMI_AUTOMATIC);
SerialLogHandler logHandler;
// Primary SPI with DMA
// SCK => A3, MISO => A4, MOSI => A5, SS => A2 (default)
SdFat sd;
const uint8_t chipSelect = A2;
// Secondary SPI with DMA
// SCK => D4, MISO => D3, MOSI => D2, SS => D1
// SdFat sd(1);
// const uint8_t chipSelect = D1;
DeviceKeyHelperSdFat deviceKeyHelper("keys");
void setup() {
Serial.begin();
if (sd.begin(chipSelect, SPI_HALF_SPEED)) {
// If the file system was mounted, enable monitoring for keys errors
deviceKeyHelper.startMonitor();
}
else {
Log.info("failed to initialize SD card");
}
// You either need to use SYSTEM_THREAD(ENABLED) or SYSTEM_MODE(SEMI_AUTOMATIC) because
// in thread disabled AUTOMATIC mode, setup() isn't called until cloud connected and the
// code to monitor the connection would never be started via startMonitor().
Particle.connect();
}
void loop() {
}
MB85RC256V I2C FRAM
The MB85RC256V 32 Kbyte ferro-electric non-volatile FRAM is another place you can store your keys.
MB85RC256V fram(Wire, 0);
// Store the device keys starting at address 1000 in the FRAM
DeviceKeyHelperFRAM deviceKeyHelper(fram, 1000);
And your own
You can easily add other storage medium without having to modify the library, too. Just add functions or C++11 lambdas for loading and storing a block of data and the library takes care of everything else.