Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add Cypress/Ramtron FRAM support + add readManufacturerId() function #14

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 59 additions & 3 deletions SPIFlash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

#include <SPIFlash.h>

uint8_t SPIFlash::MANUFID[7];
uint8_t SPIFlash::UNIQUEID[8];

/// IMPORTANT: NAND FLASH memory requires erase before write, because
Expand All @@ -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
Expand Down Expand Up @@ -101,22 +103,35 @@ 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;
}

/// 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
#else
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
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Device specific logic should be kept out of library code.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, the whole Cypress/Ramtron family is using the 7F7F as a "continuation" ID because the returned ID is in fact 72 bits instead 24 bits like most other chips.

_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;
}
Expand All @@ -129,7 +144,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);
Expand All @@ -140,6 +158,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);
Expand Down Expand Up @@ -208,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)
Expand Down
14 changes: 13 additions & 1 deletion SPIFlash.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -76,6 +77,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)

Expand All @@ -85,15 +90,20 @@
#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();
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);
Expand All @@ -103,7 +113,8 @@ 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();

void sleep();
Expand All @@ -113,6 +124,7 @@ class SPIFlash {
void select();
void unselect();
uint8_t _slaveSelectPin;
boolean _fram_mode;
uint16_t _jedecID;
uint8_t _SPCR;
uint8_t _SPSR;
Expand Down