From 7d88d344a4a807adc41797016743935438b5b6d5 Mon Sep 17 00:00:00 2001 From: Martin Ayotte Date: Thu, 14 Jan 2016 12:01:36 -0500 Subject: [PATCH 1/4] add Cypress/Ramtron FRAM support + add readManufacturerId() function --- SPIFlash.cpp | 32 +++++++++++++++++++++++++++++++- SPIFlash.h | 5 +++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/SPIFlash.cpp b/SPIFlash.cpp index 63642a2..f01ef12 100644 --- a/SPIFlash.cpp +++ b/SPIFlash.cpp @@ -34,6 +34,7 @@ #include +uint8_t SPIFlash::MANUFID[7]; uint8_t SPIFlash::UNIQUEID[8]; /// IMPORTANT: NAND FLASH memory requires erase before write, because @@ -48,6 +49,7 @@ uint8_t SPIFlash::UNIQUEID[8]; SPIFlash::SPIFlash(uint8_t slaveSelectPin, uint16_t jedecID) { _slaveSelectPin = slaveSelectPin; _jedecID = jedecID; + _fram_mode = false; } /// Select the flash chip @@ -117,6 +119,15 @@ uint16_t SPIFlash::readDeviceId() #endif uint16_t jedecid = SPI.transfer(0) << 8; jedecid |= SPI.transfer(0); + if (jedecid == 0x7F7F) { // The 0x7F7F signature means it is a Cypress/Ramtron chip, the real ID will follow in additionnal bytes + _fram_mode = true; + MANUFID[0] = (jedecid & 0xFF00) >> 8; + MANUFID[1] = jedecid & 0x00FF; + for (uint8_t i=2;i<7;i++) + MANUFID[i] = SPI.transfer(0); + jedecid = SPI.transfer(0) << 8; + jedecid |= SPI.transfer(0); + } unselect(); return jedecid; } @@ -129,7 +140,10 @@ uint16_t SPIFlash::readDeviceId() /// flash.readUniqueId(); uint8_t* MAC = flash.readUniqueId(); for (uint8_t i=0;i<8;i++) { Serial.print(MAC[i], HEX); Serial.print(' '); } uint8_t* SPIFlash::readUniqueId() { - command(SPIFLASH_MACREAD); + if (_fram_mode) + command(SPIFLASH_SNREAD); // it is a Cypress/Ramtron chip + else + command(SPIFLASH_MACREAD); SPI.transfer(0); SPI.transfer(0); SPI.transfer(0); @@ -140,6 +154,22 @@ uint8_t* SPIFlash::readUniqueId() return UNIQUEID; } +uint8_t* SPIFlash::readManufacturerId() +{ + if (_fram_mode) + readDeviceId(); // it is a Cypress/Ramtron chip + else { + command(SPIFLASH_MANUFIDREAD); + SPI.transfer(0); + SPI.transfer(0); + SPI.transfer(0); + for (uint8_t i=0;i<3;i++) + MANUFID[i] = SPI.transfer(0); + } + unselect(); + return MANUFID; +} + /// read 1 byte from flash memory uint8_t SPIFlash::readByte(uint32_t addr) { command(SPIFLASH_ARRAYREADLOWFREQ); diff --git a/SPIFlash.h b/SPIFlash.h index 5a98f56..c444c6e 100644 --- a/SPIFlash.h +++ b/SPIFlash.h @@ -85,10 +85,13 @@ #define SPIFLASH_IDREAD 0x9F // read JEDEC manufacturer and device ID (2 bytes, specific bytes for each manufacturer and device) // Example for Atmel-Adesto 4Mbit AT25DF041A: 0x1F44 (page 27: http://www.adestotech.com/sites/default/files/datasheets/doc3668.pdf) // Example for Winbond 4Mbit W25X40CL: 0xEF30 (page 14: http://www.winbond.com/NR/rdonlyres/6E25084C-0BFE-4B25-903D-AE10221A0929/0/W25X40CL.pdf) +#define SPIFLASH_MANUFIDREAD 0x90 // another Manufacturer ID #define SPIFLASH_MACREAD 0x4B // read unique ID number (MAC) +#define SPIFLASH_SNREAD 0xC3 // read Serial Number (Cypress/Ramtron FRAM chip) class SPIFlash { public: + static uint8_t MANUFID[7]; static uint8_t UNIQUEID[8]; SPIFlash(uint8_t slaveSelectPin, uint16_t jedecID=0); boolean initialize(); @@ -104,6 +107,7 @@ class SPIFlash { void blockErase32K(uint32_t address); void blockErase64K(uint32_t addr); uint16_t readDeviceId(); + uint8_t* readManufacturerId(); uint8_t* readUniqueId(); void sleep(); @@ -113,6 +117,7 @@ class SPIFlash { void select(); void unselect(); uint8_t _slaveSelectPin; + boolean _fram_mode; uint16_t _jedecID; uint8_t _SPCR; uint8_t _SPSR; From e17409b434177be17e2d6714d9aa50dfe533fd93 Mon Sep 17 00:00:00 2001 From: Martin Ayotte Date: Fri, 15 Jan 2016 16:02:22 -0500 Subject: [PATCH 2/4] fix readDeviceId() to get JedecID + Size --- SPIFlash.cpp | 5 +++-- SPIFlash.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/SPIFlash.cpp b/SPIFlash.cpp index f01ef12..0a73a1e 100644 --- a/SPIFlash.cpp +++ b/SPIFlash.cpp @@ -109,7 +109,7 @@ boolean SPIFlash::initialize() } /// Get the manufacturer and device ID bytes (as a short word) -uint16_t SPIFlash::readDeviceId() +uint32_t SPIFlash::readDeviceId() { #if defined(__AVR_ATmega32U4__) // Arduino Leonardo, MoteinoLeo command(SPIFLASH_IDREAD); // Read JEDEC ID @@ -117,7 +117,8 @@ uint16_t SPIFlash::readDeviceId() select(); SPI.transfer(SPIFLASH_IDREAD); #endif - uint16_t jedecid = SPI.transfer(0) << 8; + uint32_t jedecid = SPI.transfer(0) << 16; + jedecid |= SPI.transfer(0) << 8; jedecid |= SPI.transfer(0); if (jedecid == 0x7F7F) { // The 0x7F7F signature means it is a Cypress/Ramtron chip, the real ID will follow in additionnal bytes _fram_mode = true; diff --git a/SPIFlash.h b/SPIFlash.h index c444c6e..d1f0ec7 100644 --- a/SPIFlash.h +++ b/SPIFlash.h @@ -106,7 +106,7 @@ class SPIFlash { void blockErase4K(uint32_t address); void blockErase32K(uint32_t address); void blockErase64K(uint32_t addr); - uint16_t readDeviceId(); + uint32_t readDeviceId(); uint8_t* readManufacturerId(); uint8_t* readUniqueId(); From b0694e9cfb6d8b056d3992769789eac83d124608 Mon Sep 17 00:00:00 2001 From: Martin Ayotte Date: Fri, 15 Jan 2016 20:39:38 -0500 Subject: [PATCH 3/4] add readStatus2() and readStatus3() + fix initialize() which required also status3 to be zero --- SPIFlash.cpp | 25 +++++++++++++++++++++++++ SPIFlash.h | 6 ++++++ 2 files changed, 31 insertions(+) diff --git a/SPIFlash.cpp b/SPIFlash.cpp index 0a73a1e..1600133 100644 --- a/SPIFlash.cpp +++ b/SPIFlash.cpp @@ -103,6 +103,9 @@ boolean SPIFlash::initialize() command(SPIFLASH_STATUSWRITE, true); // Write Status Register SPI.transfer(0); // Global Unprotect unselect(); + command(SPIFLASH_STATUS3WRITE, true); // Write Status Register + SPI.transfer(0); // Write Protect scheme to Normal, not to Individual Block Locks + unselect(); return true; } return false; @@ -239,6 +242,28 @@ uint8_t SPIFlash::readStatus() } +/// return the STATUS2 register +uint8_t SPIFlash::readStatus2() +{ + select(); + SPI.transfer(SPIFLASH_STATUS2READ); + uint8_t status = SPI.transfer(0); + unselect(); + return status; +} + + +/// return the STATUS3 register +uint8_t SPIFlash::readStatus3() +{ + select(); + SPI.transfer(SPIFLASH_STATUS3READ); + uint8_t status = SPI.transfer(0); + unselect(); + return status; +} + + /// Write 1 byte to flash memory /// WARNING: you can only write to previously erased memory locations (see datasheet) /// use the block erase commands to first clear memory (write 0xFFs) diff --git a/SPIFlash.h b/SPIFlash.h index d1f0ec7..a55f3be 100644 --- a/SPIFlash.h +++ b/SPIFlash.h @@ -76,6 +76,10 @@ // but no actual need to wait for completion (instead need to check the status register BUSY bit) #define SPIFLASH_STATUSREAD 0x05 // read status register #define SPIFLASH_STATUSWRITE 0x01 // write status register +#define SPIFLASH_STATUS2READ 0x35 // read status2 register +#define SPIFLASH_STATUS2WRITE 0x31 // write status2 register +#define SPIFLASH_STATUS3READ 0x15 // read status3 register +#define SPIFLASH_STATUS3WRITE 0x11 // write status3 register #define SPIFLASH_ARRAYREAD 0x0B // read array (fast, need to add 1 dummy byte after 3 address bytes) #define SPIFLASH_ARRAYREADLOWFREQ 0x03 // read array (low frequency) @@ -97,6 +101,8 @@ class SPIFlash { boolean initialize(); void command(uint8_t cmd, boolean isWrite=false); uint8_t readStatus(); + uint8_t readStatus2(); + uint8_t readStatus3(); uint8_t readByte(uint32_t addr); void readBytes(uint32_t addr, void* buf, uint16_t len); void writeByte(uint32_t addr, uint8_t byt); From 9c80f54ee0d1288fe70868e2a8664c63052fa562 Mon Sep 17 00:00:00 2001 From: Martin Ayotte Date: Fri, 15 Jan 2016 21:08:29 -0500 Subject: [PATCH 4/4] add comment to update header --- SPIFlash.h | 1 + 1 file changed, 1 insertion(+) diff --git a/SPIFlash.h b/SPIFlash.h index a55f3be..28ea96c 100644 --- a/SPIFlash.h +++ b/SPIFlash.h @@ -6,6 +6,7 @@ // DEPENDS ON: Arduino SPI library // > Updated Jan. 5, 2015, TomWS1, modified writeBytes to allow blocks > 256 bytes and handle page misalignment. // > Updated Feb. 26, 2015 TomWS1, added support for SPI Transactions (Arduino 1.5.8 and above) +// > Updated Jan. 15, 2016 Martin ayotte, add readStatus2(), readStatus3(), readManufacturerId(), fix initialize(), readDeviceId() also return Size // > Selective merge by Felix after testing in IDE 1.0.6, 1.6.4 // ********************************************************************************** // License