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

Enabling 4kb sector erase and smaller erasable filesizes on winbond chips #67

Open
wants to merge 2 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
6 changes: 3 additions & 3 deletions SerialFlash.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class SerialFlashChip
static bool begin(uint8_t pin = 6);
static uint32_t capacity(const uint8_t *id);
static uint32_t blockSize();
static uint32_t eraseSectorSize();
static void sleep();
static void wakeup();
static void readID(uint8_t *buf);
Expand All @@ -50,12 +51,11 @@ class SerialFlashChip
static void write(uint32_t addr, const void *buf, uint32_t len);
static void eraseAll();
static void eraseBlock(uint32_t addr);
static void eraseSector(uint32_t addr);

static SerialFlashFile open(const char *filename);
static bool create(const char *filename, uint32_t length, uint32_t align = 0);
static bool createErasable(const char *filename, uint32_t length) {
return create(filename, length, blockSize());
}
static bool createErasable(const char *filename, uint32_t length);
static bool exists(const char *filename);
static bool remove(const char *filename);
static bool remove(SerialFlashFile &file);
Expand Down
35 changes: 35 additions & 0 deletions SerialFlashChip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ static SPIClass& SPIPORT = SPI;
#define FLAG_DIFF_SUSPEND 0x04 // uses 2 different suspend commands
#define FLAG_MULTI_DIE 0x08 // multiple die, don't read cross 32M barrier
#define FLAG_256K_BLOCKS 0x10 // has 256K erase blocks
#define FLAG_SECTOR_ERASE 0x20 // has 4k erase sectors
#define FLAG_DIE_MASK 0xC0 // top 2 bits count during multi-die erase

void SerialFlashChip::wait(void)
Expand Down Expand Up @@ -288,6 +289,30 @@ void SerialFlashChip::eraseBlock(uint32_t addr)
}


void SerialFlashChip::eraseSector(uint32_t addr)
{
uint8_t f = flags;
if (busy) wait();
SPIPORT.beginTransaction(SPICONFIG);
CSASSERT();
SPIPORT.transfer(0x06); // write enable command
CSRELEASE();
delayMicroseconds(1);
CSASSERT();
if (f & FLAG_32BIT_ADDR) {
SPIPORT.transfer(0x20);
Copy link
Author

Choose a reason for hiding this comment

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

Here is the new special command from the winbond datasheet

SPIPORT.transfer16(addr >> 16);
SPIPORT.transfer16(addr);
} else {
SPIPORT.transfer16(0x2000 | ((addr >> 16) & 255));
SPIPORT.transfer16(addr);
}
CSRELEASE();
SPIPORT.endTransaction();
busy = 2;
}


bool SerialFlashChip::ready()
{
uint32_t status;
Expand Down Expand Up @@ -391,6 +416,9 @@ bool SerialFlashChip::begin(uint8_t pin)
// Micron requires busy checks with a different command
f |= FLAG_STATUS_CMD70; // TODO: all or just multi-die chips?
}
if (id[0] == ID0_WINBOND) {
f |= FLAG_SECTOR_ERASE;
}
flags = f;
readID(id);
return true;
Expand Down Expand Up @@ -478,6 +506,13 @@ uint32_t SerialFlashChip::blockSize()
return 65536;
}

uint32_t SerialFlashChip::eraseSectorSize()
{
if (flags & FLAG_SECTOR_ERASE) return 4096;
// everything else seems to have 64K sectors
return blockSize();
}




Expand Down
28 changes: 21 additions & 7 deletions SerialFlashDirectory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,14 @@ bool SerialFlashChip::create(const char *filename, uint32_t length, uint32_t ali
return true;
}

bool SerialFlashChip::createErasable(const char *filename, uint32_t length) {
uint32_t filesize = SerialFlash.eraseSectorSize();
while (length > filesize) {
filesize = filesize * 2;
}
return create(filename, length, filesize);
}

bool SerialFlashChip::readdir(char *filename, uint32_t strsize, uint32_t &filesize)
{
uint32_t maxfiles, index, straddr;
Expand Down Expand Up @@ -381,13 +389,19 @@ bool SerialFlashChip::readdir(char *filename, uint32_t strsize, uint32_t &filesi

void SerialFlashFile::erase()
{
uint32_t i, blocksize;

blocksize = SerialFlash.blockSize();
if (address & (blocksize - 1)) return; // must begin on a block boundary
if (length & (blocksize - 1)) return; // must be exact number of blocks
for (i=0; i < length; i += blocksize) {
SerialFlash.eraseBlock(address + i);
uint32_t i, blockSize, sectorSize;

blockSize = SerialFlash.blockSize();
sectorSize = SerialFlash.eraseSectorSize();

if (address & (sectorSize - 1)) return; // must begin on a block boundary
if (length & (sectorSize - 1)) return; // must be exact number of blocks
for (i=0; i < length; i += sectorSize) {
if (sectorSize < blockSize) {
SerialFlash.eraseSector(address + i);
} else {
SerialFlash.eraseBlock(address + i);
}
}
}