Compare commits
No commits in common. "4c49258506889a1530e02f538139d97706e2dd6c" and "72459052e05af14e260186f159da24545ac27f07" have entirely different histories.
4c49258506
...
72459052e0
|
|
@ -1,6 +1,6 @@
|
||||||
language: python
|
language: python
|
||||||
python:
|
python:
|
||||||
- "3.6"
|
- "2.7"
|
||||||
|
|
||||||
# Cache PlatformIO packages using Travis CI container-based infrastructure
|
# Cache PlatformIO packages using Travis CI container-based infrastructure
|
||||||
sudo: false
|
sudo: false
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
SPIFlash
|
SPIFlash
|
||||||
========
|
========
|
||||||
[](https://app.travis-ci.com/LowPowerLab/SPIFlash)
|
[](https://travis-ci.org/LowPowerLab/SPIFlash)
|
||||||
[](https://github.com/LowPowerLab/SPIFlash)
|
[](https://github.com/LowPowerLab/SPIFlash)
|
||||||
[](https://github.com/LowPowerLab/SPIFlash/issues)
|
[](https://github.com/LowPowerLab/SPIFlash/issues)
|
||||||
[](https://github.com/LowPowerLab/SPIFlash/pulls)
|
[](https://github.com/LowPowerLab/SPIFlash/pulls)
|
||||||
|
|
|
||||||
47
SPIFlash.cpp
47
SPIFlash.cpp
|
|
@ -41,11 +41,6 @@ uint8_t SPIFlash::UNIQUEID[8];
|
||||||
/// See http://en.wikipedia.org/wiki/Flash_memory
|
/// See http://en.wikipedia.org/wiki/Flash_memory
|
||||||
/// The smallest range that can be erased is a sector (4K, 32K, 64K); there is also a chip erase command
|
/// The smallest range that can be erased is a sector (4K, 32K, 64K); there is also a chip erase command
|
||||||
|
|
||||||
/// IMPORTANT: When flash chip is powered down, aka sleeping, the only command it will respond to is
|
|
||||||
/// Release Power-down / Device ID (ABh), per section 8.2.19 of the W25X40CL datasheet.
|
|
||||||
/// This means after using the sleep() function of this library, wake() must be the first
|
|
||||||
/// function called. If other commands are used, the flash chip will ignore the commands.
|
|
||||||
|
|
||||||
/// Constructor. JedecID is optional but recommended, since this will ensure that the device is present and has a valid response
|
/// Constructor. JedecID is optional but recommended, since this will ensure that the device is present and has a valid response
|
||||||
/// get this from the datasheet of your flash chip
|
/// get this from the datasheet of your flash chip
|
||||||
/// Example for Atmel-Adesto 4Mbit AT25DF041A: 0x1F44 (page 27: http://www.adestotech.com/sites/default/files/datasheets/doc3668.pdf)
|
/// Example for Atmel-Adesto 4Mbit AT25DF041A: 0x1F44 (page 27: http://www.adestotech.com/sites/default/files/datasheets/doc3668.pdf)
|
||||||
|
|
@ -188,11 +183,8 @@ void SPIFlash::command(uint8_t cmd, boolean isWrite){
|
||||||
//wait for any write/erase to complete
|
//wait for any write/erase to complete
|
||||||
// a time limit cannot really be added here without it being a very large safe limit
|
// a time limit cannot really be added here without it being a very large safe limit
|
||||||
// that is because some chips can take several seconds to carry out a chip erase or other similar multi block or entire-chip operations
|
// that is because some chips can take several seconds to carry out a chip erase or other similar multi block or entire-chip operations
|
||||||
//
|
// a recommended alternative to such situations where chip can be or not be present is to add a 10k or similar weak pulldown on the
|
||||||
// Note: If the MISO line is high, busy() will return true.
|
// open drain MISO input which can read noise/static and hence return a non 0 status byte, causing the while() to hang when a flash chip is not present
|
||||||
// This can be a problem and cause the code to hang when there is noise/static on MISO data line when:
|
|
||||||
// 1) There is no flash chip connected
|
|
||||||
// 2) The flash chip connected is powered down, aka sleeping.
|
|
||||||
if (cmd != SPIFLASH_WAKE) while(busy());
|
if (cmd != SPIFLASH_WAKE) while(busy());
|
||||||
select();
|
select();
|
||||||
SPI.transfer(cmd);
|
SPI.transfer(cmd);
|
||||||
|
|
@ -300,46 +292,11 @@ void SPIFlash::blockErase64K(uint32_t addr) {
|
||||||
unselect();
|
unselect();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// found() - checks there is a FLASH chip by checking the deviceID repeatedly - should be a consistent value
|
|
||||||
uint8_t SPIFlash::found() {
|
|
||||||
uint16_t deviceID=0;
|
|
||||||
wakeup(); //if sleep() was previously called, wakeup() is required or it's non responsive
|
|
||||||
for (uint8_t i=0;i<10;i++) {
|
|
||||||
uint16_t idNow = readDeviceId();
|
|
||||||
if (idNow==0 || idNow==0xffff || (i>0 && idNow != deviceID)) {
|
|
||||||
deviceID=0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
deviceID=idNow;
|
|
||||||
}
|
|
||||||
if (deviceID==0) { //NO FLASH CHIP FOUND, ABORTING
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
///regionIsEmpty() - check a random flashmem byte array is all clear and can be written to (ie. it's all 0xff)
|
|
||||||
uint8_t SPIFlash::regionIsEmpty(uint32_t startAddress, uint8_t length) {
|
|
||||||
uint8_t flashBuf[length];
|
|
||||||
readBytes(startAddress, flashBuf, length);
|
|
||||||
for (uint8_t i=0;i<length;i++) if (flashBuf[i]!=0xff) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Put flash memory chip into power down mode
|
|
||||||
/// WARNING: after this command, only the WAKEUP and DEVICE_ID commands are recognized
|
|
||||||
/// hence a wakeup() command should be invoked first before further operations
|
|
||||||
/// If a MCU soft restart is possible with flash chip left in sleep(), then a wakeup() command
|
|
||||||
/// should always be invoked before any other commands to ensure the flash chip was not left in sleep
|
|
||||||
void SPIFlash::sleep() {
|
void SPIFlash::sleep() {
|
||||||
command(SPIFLASH_SLEEP);
|
command(SPIFLASH_SLEEP);
|
||||||
unselect();
|
unselect();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wake flash memory from power down mode
|
|
||||||
/// NOTE: this command is required after a sleep() command is used, or no other commands will be recognized
|
|
||||||
/// If a MCU soft restart is possible with flash chip left in sleep(), then a wakeup() command
|
|
||||||
/// should always be invoked before any other commands to ensure the flash chip was not left in sleep
|
|
||||||
void SPIFlash::wakeup() {
|
void SPIFlash::wakeup() {
|
||||||
command(SPIFLASH_WAKE);
|
command(SPIFLASH_WAKE);
|
||||||
unselect();
|
unselect();
|
||||||
|
|
|
||||||
|
|
@ -105,8 +105,6 @@ public:
|
||||||
void blockErase64K(uint32_t addr);
|
void blockErase64K(uint32_t addr);
|
||||||
uint16_t readDeviceId();
|
uint16_t readDeviceId();
|
||||||
uint8_t* readUniqueId();
|
uint8_t* readUniqueId();
|
||||||
uint8_t found();
|
|
||||||
uint8_t regionIsEmpty(uint32_t startAddress, uint8_t length);
|
|
||||||
|
|
||||||
void sleep();
|
void sleep();
|
||||||
void wakeup();
|
void wakeup();
|
||||||
|
|
|
||||||
|
|
@ -3,30 +3,27 @@
|
||||||
#include <SPIFlash.h> //https://github.com/lowpowerlab/spiflash
|
#include <SPIFlash.h> //https://github.com/lowpowerlab/spiflash
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
|
|
||||||
#define SERIAL_BAUD 115200
|
#define SERIAL_ENABLE
|
||||||
#define BLINK_FAST_DELAY 50
|
#define BLINK_FAST_DELAY 100
|
||||||
#define BLINK_SLOW_DELAY 1000
|
#define BLINK_SLOW_DELAY 500
|
||||||
|
|
||||||
SPIFlash flash(SS_FLASHMEM, 0xEF30); //EF40 for 16mbit windbond chip
|
SPIFlash flash(SS_FLASHMEM, 0xEF30); //EF40 for 16mbit windbond chip
|
||||||
int LEDTIME = 500;
|
int LEDTIME = 500;
|
||||||
|
|
||||||
// the setup routine runs once when you press reset:
|
// the setup routine runs once when you press reset:
|
||||||
void setup() {
|
void setup() {
|
||||||
#ifdef SERIAL_BAUD
|
#ifdef SERIAL_ENABLE
|
||||||
Serial.begin(SERIAL_BAUD);
|
Serial.begin(115200);
|
||||||
while (!Serial) delay(100); //wait until Serial/monitor is opened
|
delay(4000); //wait a bit until SerialMonitor can be opened
|
||||||
#endif
|
#endif
|
||||||
pinMode(LED_BUILTIN, OUTPUT);
|
pinMode(LED_BUILTIN, OUTPUT);
|
||||||
|
|
||||||
//ensure the radio module CS pin is pulled HIGH or it might interfere!
|
|
||||||
pinMode(SS, OUTPUT); digitalWrite(SS, HIGH);
|
|
||||||
|
|
||||||
//ensure FLASH chip is not sleep mode (unresponsive)
|
|
||||||
flash.wakeup();
|
|
||||||
if (flash.initialize()) {
|
if (flash.initialize()) {
|
||||||
Serial.println("SPI Flash Init OK!");
|
Serial.println("SPI Flash Init OK!");
|
||||||
LEDTIME = BLINK_SLOW_DELAY;
|
LEDTIME = BLINK_SLOW_DELAY;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
Serial.println("SPI Flash Init FAIL! (is chip soldered?)");
|
Serial.println("SPI Flash Init FAIL! (is chip soldered?)");
|
||||||
LEDTIME = BLINK_FAST_DELAY;
|
LEDTIME = BLINK_FAST_DELAY;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,14 @@
|
||||||
// This sketch is an example of using the SPIFlash library with a Moteino
|
// This sketch is an example of using the SPIFlash library with a Moteino
|
||||||
// that has an onboard SPI Flash chip. This sketch listens to a few serial commands
|
// that has an onboard SPI Flash chip. This sketch listens to a few serial commands
|
||||||
// Hence type the following commands to interact with the SPI flash memory array:
|
// Hence type the following commands to interact with the SPI flash memory array:
|
||||||
//'c' - read flash chip's deviceID 10 times to ensure chip is present
|
// - 'd' dumps the first 256bytes of the flash chip to screen
|
||||||
//'d' - dump first 256 bytes on the chip
|
// - 'e' erases the entire memory chip
|
||||||
//'e' - erase entire flash chip
|
// - 'i' print manufacturer/device ID
|
||||||
//'E' - erase last 4K block in flash chip
|
// - [0-9] writes a random byte to addresses [0-9] (either 0xAA or 0xBB)
|
||||||
//'D' - dump first 256 bytes in the last 4K block
|
|
||||||
//'i' - read deviceID
|
|
||||||
//'0'-'9' - write 0xaa/0xbb bytes at addresses 0..9, 520192..520447
|
|
||||||
// Get the SPIFlash library from here: https://github.com/LowPowerLab/SPIFlash
|
// Get the SPIFlash library from here: https://github.com/LowPowerLab/SPIFlash
|
||||||
// Note: if other SPI devices are present, ensure their CS pins are pulled up or set HIGH
|
// Note: if other SPI devices are present, ensure their CS pins are pulled up or set HIGH
|
||||||
// **********************************************************************************
|
// **********************************************************************************
|
||||||
// (C) 2021 Felix Rusu, LowPowerLab.com
|
// (C) 2020 Felix Rusu, LowPowerLab.com
|
||||||
// Library and code by Felix Rusu - felix@lowpowerlab.com
|
// Library and code by Felix Rusu - felix@lowpowerlab.com
|
||||||
// **********************************************************************************
|
// **********************************************************************************
|
||||||
// License
|
// License
|
||||||
|
|
@ -56,17 +53,9 @@ uint16_t expectedDeviceID=0xEF30;
|
||||||
SPIFlash flash(SS_FLASHMEM, expectedDeviceID);
|
SPIFlash flash(SS_FLASHMEM, expectedDeviceID);
|
||||||
|
|
||||||
void setup(){
|
void setup(){
|
||||||
#ifdef SERIAL_BAUD
|
|
||||||
Serial.begin(SERIAL_BAUD);
|
Serial.begin(SERIAL_BAUD);
|
||||||
while (!Serial) delay(100); //wait until Serial/monitor is opened
|
|
||||||
#endif
|
|
||||||
pinMode(LED_BUILTIN, OUTPUT);
|
|
||||||
|
|
||||||
Serial.print("Start...");
|
Serial.print("Start...");
|
||||||
|
|
||||||
//ensure the radio module CS pin is pulled HIGH or it might interfere!
|
|
||||||
pinMode(SS, OUTPUT); digitalWrite(SS, HIGH);
|
|
||||||
|
|
||||||
if (flash.initialize())
|
if (flash.initialize())
|
||||||
{
|
{
|
||||||
Serial.println("Init OK!");
|
Serial.println("Init OK!");
|
||||||
|
|
@ -84,10 +73,7 @@ void setup(){
|
||||||
Serial.println("'c' - read flash chip's deviceID 10 times to ensure chip is present");
|
Serial.println("'c' - read flash chip's deviceID 10 times to ensure chip is present");
|
||||||
Serial.println("'d' - dump first 256 bytes on the chip");
|
Serial.println("'d' - dump first 256 bytes on the chip");
|
||||||
Serial.println("'e' - erase entire flash chip");
|
Serial.println("'e' - erase entire flash chip");
|
||||||
Serial.println("'E' - erase last 4K block in flash chip");
|
|
||||||
Serial.println("'D' - dump first 256 bytes in the last 4K block");
|
|
||||||
Serial.println("'i' - read deviceID");
|
Serial.println("'i' - read deviceID");
|
||||||
Serial.println("'0'-'9' - write 0xaa/0xbb bytes at addresses 0..9, 520192..520447");
|
|
||||||
Serial.println("************************\n");
|
Serial.println("************************\n");
|
||||||
delay(1000);
|
delay(1000);
|
||||||
}
|
}
|
||||||
|
|
@ -97,26 +83,16 @@ void loop(){
|
||||||
// ie: display first 256 bytes in FLASH, erase chip, write bytes at first 10 positions, etc
|
// ie: display first 256 bytes in FLASH, erase chip, write bytes at first 10 positions, etc
|
||||||
if (Serial.available() > 0) {
|
if (Serial.available() > 0) {
|
||||||
input = Serial.read();
|
input = Serial.read();
|
||||||
if (input == 'd') { //d=dump flash area
|
if (input == 'd') //d=dump flash area
|
||||||
Serial.println("Flash content (256 bytes, starting address 0):");
|
{
|
||||||
|
Serial.println("Flash content:");
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
|
|
||||||
while(counter<256){
|
while(counter<=256){
|
||||||
Serial.print(flash.readByte(counter), HEX);
|
Serial.print(flash.readByte(counter++), HEX);
|
||||||
counter++;
|
Serial.print('.');
|
||||||
if (counter%16 == 0) Serial.println(); else Serial.print('.');
|
|
||||||
}
|
}
|
||||||
Serial.println();
|
|
||||||
}
|
|
||||||
else if (input == 'D') { //d=dump flash area @ last 4K block
|
|
||||||
Serial.println("Flash content (256bytes, starting address 520192):");
|
|
||||||
uint32_t counter = 520192;
|
|
||||||
|
|
||||||
while(counter<520192+256){
|
|
||||||
Serial.print(flash.readByte(counter), HEX);
|
|
||||||
counter++;
|
|
||||||
if (counter%16 == 0) Serial.println(); else Serial.print('.');
|
|
||||||
}
|
|
||||||
Serial.println();
|
Serial.println();
|
||||||
}
|
}
|
||||||
else if (input == 'c') {
|
else if (input == 'c') {
|
||||||
|
|
@ -142,13 +118,6 @@ void loop(){
|
||||||
while(flash.busy());
|
while(flash.busy());
|
||||||
Serial.println("DONE");
|
Serial.println("DONE");
|
||||||
}
|
}
|
||||||
else if (input == 'E')
|
|
||||||
{
|
|
||||||
Serial.print("Erasing last 4K block @520192 ... ");
|
|
||||||
flash.blockErase4K(520192);
|
|
||||||
while(flash.busy());
|
|
||||||
Serial.println("DONE");
|
|
||||||
}
|
|
||||||
else if (input == 'i')
|
else if (input == 'i')
|
||||||
{
|
{
|
||||||
Serial.print("DeviceID: ");
|
Serial.print("DeviceID: ");
|
||||||
|
|
@ -158,19 +127,21 @@ void loop(){
|
||||||
{
|
{
|
||||||
Serial.print("\nWriteByte("); Serial.print(input); Serial.print(")");
|
Serial.print("\nWriteByte("); Serial.print(input); Serial.print(")");
|
||||||
flash.writeByte(input-48, millis()%2 ? 0xaa : 0xbb);
|
flash.writeByte(input-48, millis()%2 ? 0xaa : 0xbb);
|
||||||
flash.writeByte(input-48+520192, millis()%2 ? 0xaa : 0xbb);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Periodically blink the onboard LED while listening for serial commands
|
// Periodically blink the onboard LED while listening for serial commands
|
||||||
if ((int)(millis()/500) > lastPeriod) {
|
if ((int)(millis()/500) > lastPeriod)
|
||||||
|
{
|
||||||
lastPeriod++;
|
lastPeriod++;
|
||||||
|
pinMode(LED_BUILTIN, OUTPUT);
|
||||||
digitalWrite(LED_BUILTIN, lastPeriod%2);
|
digitalWrite(LED_BUILTIN, lastPeriod%2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Blink(int DELAY_MS, byte loops)
|
void Blink(int DELAY_MS, byte loops)
|
||||||
{
|
{
|
||||||
|
pinMode(LED_BUILTIN, OUTPUT);
|
||||||
while (loops--)
|
while (loops--)
|
||||||
{
|
{
|
||||||
digitalWrite(LED_BUILTIN,HIGH);
|
digitalWrite(LED_BUILTIN,HIGH);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue