Как адресуются ячейки во FLASH-памяти?

Есть внешняя флэш-память (W25Q80DV), которую я хочу использовать с Arduino. Эта память имеет 4096 страниц по 256 байт каждая.

Я хочу сделать несколько операций записи на страницу, чтобы равномерно использовать память и меньше стирать.

Проверочный код:

#include <SPI.h>

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

#define FLASH_SELECT_CHIP 33

// # Выбрать/Отменить выбор чипа
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;
  }
}

// # Ожидание состояния готовности флэш-памяти
void notBusy() {
  uint16_t whileCounter;
  selectChip(true);
  SPI.transfer(readStatusReg_1);
  while((SPI.transfer(0) & 1) && whileCounter < 45000) { whileCounter++; }
  selectChip(false);
}

// # Отправить команду и адрес
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);
}

// # Запись разрешена
void writeEnable() {
  notBusy();
  selectChip(true);
  SPI.transfer(writeEnableReg);
  selectChip(false);
}

// # Запись FLASH-страницы
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() {
  // СПИ
  pinMode(FLASH_SELECT_CHIP, OUTPUT);
  digitalWrite(FLASH_SELECT_CHIP, HIGH);
  SPI.begin();
  SPI.setDataMode(0);
  SPI.setBitOrder(MSBFIRST);
  
  // Запись FLASH
  #define TESTADDRESS 0x1000
  byte msgData[] = "Hi all!";
  writeFlashData(TESTADDRESS, msgData);
}

void loop() {}

Здесь указан адрес #define TESTADDRESS 0x1000 (4096) для записи данных.

Я не понимаю, это адрес страницы или адрес байта, с которого я начну запись?

Я хотел бы разделить одну страницу на несколько блоков и записать данные для них отдельно.

, 👍0


1 ответ


Лучший ответ:

1

Я не понимаю, это адрес страницы или адрес байта, с которого я начну запись?

Это адрес байта. Как сказано в спецификации в разделе 8.5.13:

Если необходимо запрограммировать всю 256-байтовую страницу, последний байт адреса (8 младших битов адреса) должен быть установлен в 0. Если последний байт адреса не равен нулю, а количество тактов превышает оставшуюся страницу length адресация будет перенесена на начало страницы.

Другими словами: если вы хотите написать всю страницу, начните с начала страницы. Если вы этого не сделаете и напишете больше, чем осталось места на странице, вы снова вернетесь к началу страницы.

Поэтому, если вы запишете два байта, начиная с адреса 0x10FF, вы на самом деле запишете один байт по адресу 0x10FF, а второй по адресу 0x1000, а не 0x1100, так как вы выполняете перенос на границе страницы.

,

Спасибо за твой ответ!, @Delta

Хороший ответ, за исключением того, что я не думаю, что ваш пример правильный. На 8-битном устройстве, таком как Arduino на базе AVR, граница страницы составляет 256 байт. Диапазон от 0x100F до 0x1010 не является границей страницы. В примере должно быть от 0x10FF до 0x1100. На 16-, 32- и 64-битных процессорах часто также возникают соображения по выравниванию слов даже по 2-, 4- и 8-байтовым адресам, но они не применяются к Arduino (по крайней мере, к Arduino на основе AVR)., @Duncan C

@DuncanC Это не имеет ничего общего с AVR. Это флэш-чип с SPI-подключением — W25Q80DV., @Majenko

@DuncanC Но вы правы насчет границы - это просто я перепутал свои байты и откусывания., @Majenko

Да, я понял это после поста. Однако флэш-чип почти наверняка имеет 8-битную шину, поэтому он использует 256-байтовые страницы., @Duncan C