0

There is an external FLASH memory (W25Q80DV) that I want to use with the Arduino. This memory has 4096 pages of 256 bytes each.

I want to make multiple writes per page to use memory evenly and erase less.

Test code:

#include <SPI.h>

#define readStatusReg_1 0x05
#define readArrayReg 0x0B
#define writeEnableReg 0x06
#define pageProgramStatusReg 0x02

#define FLASH_SELECT_CHIP 33

// # Select / Unselect chip
void selectChip(bool state) {
  switch (state) {
    case true:
     digitalWrite(FLASH_SELECT_CHIP, HIGH);
     digitalWrite(FLASH_SELECT_CHIP, LOW);
      break;
    case false:
     digitalWrite(FLASH_SELECT_CHIP, HIGH);
      break;
  }
}

// # Wait flash ready state
void notBusy() {
  uint16_t whileCounter;
  selectChip(true);
  SPI.transfer(readStatusReg_1);
  while((SPI.transfer(0) & 1) && whileCounter < 45000) { whileCounter++; }
  selectChip(false);
}

// # Send command and address
void sendCommandAndAddress(const byte command, const unsigned long address) {
  SPI.transfer(command);
  SPI.transfer((address >> 16) & 0xFF);
  SPI.transfer((address >> 8) & 0xFF);
  SPI.transfer(address & 0xFF);
}

// # Write enable
void writeEnable() {
  notBusy();
  selectChip(true);
  SPI.transfer(writeEnableReg);
  selectChip(false);
}

// # Write FLASH page
bool writeFlashData(const unsigned long address, byte * data) {
  writeEnable();
  selectChip(true);
  sendCommandAndAddress(pageProgramStatusReg, address);
  uint16_t len = sizeof(data);
  for(uint16_t i = 0; i < len; i++) {
    SPI.transfer(*data++);
  }
  selectChip(false);
  notBusy();
  return true;
}

void setup() {
  // SPI
  pinMode(FLASH_SELECT_CHIP, OUTPUT);
  digitalWrite(FLASH_SELECT_CHIP, HIGH);
  SPI.begin();
  SPI.setDataMode(0);
  SPI.setBitOrder(MSBFIRST);
  
  // Write FLASH
  #define TESTADDRESS 0x1000
  byte msgData[] = "Hi all!";
  writeFlashData(TESTADDRESS, msgData);
}

void loop() {}

Here, the address #define TESTADDRESS 0x1000 (4096) is specified for writing data.

I'm not clear if this is the page address or the byte address from which I will start recording?

I would like to actually split one page into multiple blocks and write data for them separately.

1 Answer 1

1

I'm not clear if this is the page address or the byte address from which I will start recording?

That is the byte address. As the data sheet in section 8.5.13 says:

If an entire 256 byte page is to be programmed, the last address byte (the 8 least significant address bits) should be set to 0. If the last address byte is not zero, and the number of clocks exceed the remaining page length, the addressing will wrap to the beginning of the page.

In other words: if you want to write an entire page then start at the beginning of the page. If you don't and you write more than there is room left in the page you will wrap round back to the beginning of the page again.

So if you write two bytes starting with address 0x10FF you will actually write one at 0x10FF and the second at 0x1000, not 0x1100, since you wrap at the page boundary.

5
  • thank you for the answer!
    – Delta
    Commented Jul 26, 2020 at 9:29
  • Good answer, except I don't think your example is correct. On an 8-bit device like an AVR-based arduino, a page boundary is a 256 byte page. The range 0x100F to 0x1010 is not a page boundary. The example should 0x10FF to 0x1100. On 16, 32 and 64 bit processors, there are often also word alignment considerations around even 2 byte, 4 byte, or 8 byte addresses, but those don't apply to Arduinos (at least not to AVR-based Arduinos.)
    – Duncan C
    Commented Jul 26, 2020 at 14:45
  • @DuncanC This has nothing to do with AVR. This is an SPI-connected Flash chip - the W25Q80DV.
    – Majenko
    Commented Jul 26, 2020 at 14:58
  • @DuncanC But you're right about the boundary - that was just me getting my bytes and nibbles muddled up.
    – Majenko
    Commented Jul 26, 2020 at 15:00
  • Yeah, I realized that after the post. The flash chip almost certainly has an 8 bit bus though, which would be why it uses 256 byte pages.
    – Duncan C
    Commented Jul 26, 2020 at 17:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.