Настройка lpt для spipgm

Содержание

Программирование через OpenProg

Устанавливают программу OpenProg на ПК, запускают и проверяют подключенное устройство. Последовательность прошивки программатора Spi Flash:

Подключают USB-разъем к ПК.
Открывают OpenProg и убеждаются, что программатор обнаружен.
Нажимают «Параметры» -> «Проверка оборудования».
Выполняют аппаратный тест

Он проверяет все контакты программирования, и пользователь может легко отлаживать устройство при обнаружении ошибок.
Аппаратный тест показывает напряжение на VODU, VPPU, CLK, DATA, PGM в разные моменты времени, что важно учитывать при выполнении своими руками программатора Spi Flash на SMD.
Измеряют напряжение между выводами VODU, VPPU, CLK, DATA, PGM и проверяют его значениями на экране.
VPP может иметь разницу в 1 В из-за преобразования переменного тока в постоянный.
Если напряжение этих выводов части контроллера и то, что отображается на экране, схожи, программатор работает отлично.
Если напряжение отличается, проверяют цепь соответствующих контактов.

Утилита для идентификации

Flashrom — это утилита для идентификации, чтения, записи, проверки и удаления флеш-чипов. Она предназначена для прошивки образов BIOS/EFI/coreboot/firmware/optionROM на материнских платах, картах контроллера сети/графики/хранения и на различных других устройствах программирования. Функциональные возможности:

  1. Поддерживает более 476 чипов флэш-памяти, 291 наборов микросхем, 500 материнских плат, 79 устройств PCI, 17 устройств USB и различные программаторы Spi Flash на основе параллельных/последовательных портов.
  2. Поддерживает параллельные интерфейсы, интерфейсы флэш-памяти LPC, FWH и SPI и различные пакеты микросхем (DIP32, PLCC32, DIP8, SO8/SOIC8, TSOP32, TSOP40, TSOP48, BGA и другие).
  3. Физический доступ не требуется, root-доступ достаточен или вообще не требуется для некоторых программаторов.
  4. Не требуется загрузочная дискета, CD-ROM или другой носитель.
  5. Клавиатура и мониторы не требуются, просто перепрошиваются удаленно через SSH.
  6. Не требуется мгновенная перезагрузка.
  7. Переписывают чип в работающей системе и проверяют его, новая прошивка будет работать при следующей загрузке.
  8. Доступна частичная поддержка Windows.

Что нас побудило разработать этот программатор.

Есть великое множество простых специализированных программаторов, пригодных для самостоятельного изготовления.

Есть множество дешевых китайских программаторов в уже готовом виде.

Есть немало любительских разработок, часто по качеству превосходящих последние.

Казалось бы, в чем смысл очередной поделки?

Мы длительное время занимаемся разработкой производством и поддержкой универсальных программаторов, в основном специального назначения. У нас богатый опыт работы с самыми разными микросхемами. Часто к нам обращаются люди уже собравшие, а часто и купившие, какой-нибудь из выше названных «изделий». Нашим специалистам часто без смеха/слез/ужаса (нужное подчеркнуть) невозможно смотреть на схемные решения, качество сборки и, особенно, на программное обеспечение этих приборов. Ладно когда программатор стоит «три копейки», купил, что-то работает, что-то не работает, зато деньги не большие. Но часто соотношение цена/возможности таких приборов у нас вызывают, мягко говоря, удивление. Хочется воскликнуть: это столько не стоит!

Кроме всего выше названного есть особая категория программаторов, пригодных для самостоятельного изготовления — это программаторы (точнее, схемы программаторов и программное обеспечение), разработанные специалистами фирм производящих микросхемы (в основном микроконтроллеры). Такие программаторы спроектированы вполне профессионально, в их схемотехнике нет «ляпов». Они поддерживают все заявленные микросхемы. Но есть два «маленьких» недостатка: перечень программируемых микросхем весьма ограничен (что вполне понятно) и программное обеспечение весьма спартанское — никаких лишних функций, как правило — только стереть, записать, верифицировать. Часто даже функции чтения микросхемы нет.

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

Итак, программатор ChipStar-Janus в начальной конфигурации — это внутрисхемный программатор. В таком режиме он поддерживает микроконтроллеры PIC и AVR фирмы Microchip, некоторые микроконтроллеры архитектуры MCS51, микроконтроллеры фирмы STMicroelectronics и еще ряд других, а также микросхемы последовательной памяти с интерфейсом I2C (в основном серия 24). К разъему расширения программатора можно подключить простейшие адаптеры и начать программировать микросхемы памяти «в панельке».

Сейчас реализовано программирование «в панельке»:

  1. микросхемы последовательной памяти (Serial EPROM) с интерфейсом I2C (серия 24xx);
  2. микросхемы последовательной флэш памяти (Serial FLASH) с интерфейсом SPI (SPI Flash);
  3. микросхемы последовательной памяти (Serial EPROM) с интерфейсом MW (серия 93xx);
  4. микросхемы NAND FLASH;

3Очистка флеш-памяти с помощью Arduino

Перед тем как записывать данные в флеш-память, необходимо стереть тот сектор или страницу, в который мы собираемся записывать. Если записываемых данных немного (в нашем учебном примере это будут всего 16 байт), то достаточно стереть 1 сектор. Из документации на микросхему мы видим, что последовательность стирания такая: выставить разрешение на запись (1 байт), послать команду на стирание (1 байт) и адрес (3 байта), выставить запрет записи (1 байт). Данная последовательность приведена на рисунке ниже:

Диаграмма очистки одного сектора флеш-памяти 25L8005

Именно это и делает приведённый ниже скетч:

#include <SPI.h>

const int SSPin = 10;
const byte WREN = 0x06;
const byte WRDI = 0x04;
const byte SER = 0x20;
const byte ADDR1 = 0;
const byte ADDR2 = 0;
const byte ADDR3 = 0;

void setup() {
  pinMode(SSPin, OUTPUT);
  SPI.begin();

  SPISettings mySet(100000, MSBFIRST, SPI_MODE0);
  
  // Выставление разрешения записи:
  SPI.beginTransaction(mySet);
  digitalWrite(SSPin, LOW);
  SPI.transfer(WREN);
  digitalWrite(SSPin, HIGH);
  SPI.endTransaction();

  // Очистка сектора:
  SPI.beginTransaction(mySet);
  digitalWrite(SSPin, LOW);
  SPI.transfer(SER);
  SPI.transfer(ADDR1);
  SPI.transfer(ADDR2);
  SPI.transfer(ADDR3);
  digitalWrite(SSPin, HIGH);
  SPI.endTransaction();
 
  // Выставление запрета записи:
  SPI.beginTransaction(mySet);
  digitalWrite(SSPin, LOW);
  SPI.transfer(WRDI);
  digitalWrite(SSPin, HIGH);
  SPI.endTransaction();
}

void loop() {
  // ничего не делаем в цикле
}

Загрузим этот скетч в Arduino с подключённой по приведённой выше схеме микросхемой памяти. После того как он отработал, флешка готова к записи.

2.5. Чтение информации ONFI

SPI NAND, как и параллельные (обычные) микросхемы NAND, поддерживают считывание таблиц конфигурации устройства в соответствии со спецификацией ONFI (Open Nand Flash Interface):

В отличие от паралельных NAND у SPI NAND с поддержкой ONFI дела обстоят значительно лучше. Все известные нам микросхемы поддерживают ONFI.

На рисунке выше значение «ширина шины данных» (data bus) в отчете ONFI указывается как 8 бит, хотя, как известно, SPI интерфейс однобитный. В этом нет ничего странного: здесь имеется в виду организация памяти по восемь бит. Также в отчете ONFI указано требование к внешнему алгоритму ECC исправлять 0 ошибок (исправлять не требуется). Однако внутренний алгоритм исправляет до 8 ошибок, поэтому при выключенном внутреннем ECC внешний алгоритм просто обязан исправлять те же восемь ошибок. Поэтому в базе данных программатора прописано именно «8» и это не является ошибкой.

2.2. Считывание образа SPI NAND

Считывание SPI NAND происходит абсолютно идентично чтению любых других микросхем. После начала чтения сразу открывается окно редактора:

Как и для обычных NAND резервная (spare) область в редакторе показана более тусклым шрифтом, присутствует навигация по страницам, блокам и плохим блокам. Кроме того, часть резервной (spare) области, в которую записываются коды исправления ошибок (ECC), дополнительно выделена бледно-голубым. Это сделано не просто так: такое выделение существенно поможет вам в анализе содержимого образа микросхемы.

Как уже мы писали выше, у разных микросхем spare области имеют разный формат.

Выделение другим цветом части резервной области, предназначенной для записи ECC, существенно облегчает просмотр дампа.

Двуликий Янус

Мы решили назвать этот программатор «Янус».

Почему так? Потому что в римской мифологии Янус — это двуликий бог дверей, входов и выходов, а также начала и конца. Какая связь? Почему наш программатор ChipStar-Janus двуликий?

А вот почему:

  • C одной стороны, этот программатор — простой. Распространяется как бесплатный проект, его можно легко изготовить самому.
  • C другой стороны, он разработан фирмой, длительное время профессионально занимающейся разработкой и производством различной радиоэлектронной аппаратуры, в том числе программаторами.
  • C одной стороны, этот программатор — простой, с первого взгляда имеет не сильно впечатляющие характеристики.
  • C другой стороны, работает совместно с профессиональной программой (кстати, точно такой же, как и остальные профессиональные программаторы ChipStar).
  • C одной стороны, мы предлагаем этот программатор для свободной сборки.
  • C одной стороны, мы его продаем и в готовом виде, как обычный бюджетный продукт.
  • C одной стороны, на самодельный программатор не распространяется гарантия (что естественно).
  • C одной стороны, если вы его смогли собрать, то и отремонтировать сможете, да и программатор настолько простой, что ломаться, собственно, нечему.
  • C одной стороны, это простой внутрисхемный программатор.
  • C одной стороны, через простые адаптеры расширения он поддерживает программирование NAND FLASH и других микросхем уже «в панельке».

Таким образом, программатор ChipStar-Janus для многих специалистов может стать настоящим выходом в ситуации, когда разных простых или любительских программаторов уже недостаточно, а более сложный программатор кажется избыточным или на него не хватает выделенного бюджета.

2Подключение Arduino к микросхеме flash-памяти 25L8005

Назначение выводов микросхемы ПЗУ, приведённое в техническом описании на микросхему (datasheet), следующее:

Назначение выводов микросхемы флеш-памяти 25L8005

Кстати, datasheet на микросхему флеш-памяти 25L8005 можно скачать в конце статьи.

Будем использовать для программирования флэш-памяти интерфейс SPI, поэтому подключимся к стандартным SPI выводам Arduino:

Вывод микросхемы флеш-памяти Вывод платы Arduino
CS# цифровой пин 10
SI цифровой пин 11
SO цифровой пин 12
SCLK цифровой пин 13
WP# 3V3
HOLD# 3V3
VCC 3V3
GND GND

Здесь символом решётки # отмечены выводы, которые активируются логическим нулём.

Соберём электрическую схему подключения микросхемы флеш-памяти MX25L8005 к Arduino.

Схема подключения микросхемы флеш-памяти 25L8005 к Arduino

У меня ПЗУ на монтажной плате и подключённое к Arduino выглядит вот так:

Флеш-память на ZIF-панели, подключённая к ArduinoФлеш-память на ZIF-панели, подключённая к Arduino

Немного предыстории:

Материнская плата ASUS Commando, без, модного нынче, Dual BIOS. Только Boot Block – небольшая область BIOS, не затрагиваемая записью, которая позволяет, в случае необходимости, инициализировать минимальный набор компонентов, необходимых для включения компьютера, произвести поиск BIOS на съемных носителях. Обычно подходят Floppy или флешка с файлом прошивки, переименованным в AMIBOOT.ROM (зависит от BIOS и материнской платы, точнее написано в инструкции к плате), либо CD с драйверами из комплекта поставки. Обнаружив подходящий файл, boot block запишет его в BIOS и, если все прошло правильно, компьютер после перезагрузки оживет. Неплохая фишка, несколько раз выручала, но в данном случае она не сработала, видимо, оказался поврежден и boot block.

Пришлось искать другие решения. Так как в своем арсенале инструмента у меня не было паяльной станции и стационарного программатора для разных eeprom’ок, пришлось искать более доступные решения. Рассматривая плату, я обнаружил на ней небольшой разъем SPI_J1, а микросхема флеш памяти как раз с SPI интерфейсом. Поиск в Интернет показал, что существуют вполне приличные заводские девайсы и немало самоделок для прошивки SPI микросхем через USB (об универсальных программаторах с поддержкой SPI даже не говорю, это само собой). Правда, поиск по местным магазинам, СЦ и форумам в отличии от Google ничего не дал, а заказывать и ждать месяц очень не хотелось.

Еще немного поиска, и вот оно, решение – статья чешского комрада (на чешском) о предельно простом программаторе и софтине к нему для прошивки микросхем флеш памяти с SPI интерфейсом! Ничего сложного, минимум компонентов.

Технически это очень простой способ, и требует лишь базового понимания схемотехники, умения припаять пару проводков и воспользоваться командной строкой (cmd). Но если вы не уверены в своих силах, лучше не рискуйте. Кроме того, всегда можно попросить друга, дружащего с паяльником.

Завершение процесса создания

После изготовления части контроллера и платы расширения, можно сразу перейти к программированию устройства:

  1. Находят устройство и серию устройства для программирования.
  2. Выбирают подходящую плату расширения устройства.
  3. Подключают устройство к плате расширения.
  4. Присоединяют плату расширения к блоку контроллера.
  5. Подключают соединительный кабель USB B к программатору и к ПК.
  6. Открывают OpenProg.exe и убеждаются, что программатор обнаружен.
  7. Открывают устройства и выбирают нужное для программирования.
  8. Нажимают зеленую стрелку в верхней части, чтобы прочитать устройство.
  9. Для записи/прошивки нажимают левую кнопку сверху, чтобы выбрать код «.hex», и нажимают «Ok».
  10. Нажимают красную кнопку со стрелкой рядом с зеленой кнопкой со стрелкой, чтобы запрограммировать устройство.
  11. Убеждаются, что LED мигает во время программирования, показывая статус процесса.
  12. Проверяют результат и убеждаются, что мигание прошло успешно.

4Чтение данных из флеш-памяти с помощью Arduino

Согласно документации, чтение из флешки выполняется посредством такой последовательности: отправка команды на чтение (1 байт), начальный адрес (3 байта), а далее запрашивается столько байтов, сколько хотим прочитать из ПЗУ. Собственно, мы будем передавать в ПЗУ 16 нулей. Так как SPI – синхронный интерфейс, нам в ответ вернутся 16 записанных в ПЗУ байтов. Вот такая диаграмма приводится в описании к микросхеме:

Диаграмма чтения данных из флеш-памяти 25L8005

Напишем скетч для чтения наших заветных 16-ти байт из микросхемы флеш-памяти 25L8005:

#include <SPI.h>

const int SSPin = 10;
const byte READ = 0x03;
const byte ADDR1 = 0;
const byte ADDR2 = 0;
const byte ADDR3 = 0;

void setup() {
  Serial.begin(9600);
  pinMode(SSPin, OUTPUT);
  SPI.begin();  
}

void loop() { 
  SPISettings mySet(100000, MSBFIRST, SPI_MODE0);
  SPI.beginTransaction(mySet);
  digitalWrite(SSPin, LOW);
  SPI.transfer(READ); 
  SPI.transfer(ADDR1);
  SPI.transfer(ADDR2);
  SPI.transfer(ADDR3);
  for (int i=0; i<16; i++) {
    byte data = SPI.transfer(0);
    Serial.print((char)data);
  }
  Serial.println();
  digitalWrite(SSPin, HIGH);
  SPI.endTransaction();
  delay(1000); // повторяем чтение каждую секунду
}

Загрузим скетч в Arduino и откроем монитор последовательных портов. В мониторе, как и ожидалось, 1 раз в секунду будет выводиться наш массив, считанный из флеш-памяти с помощью Arduino.

Чтение из флеш-памяти с помощью Arduino и вывод в монитор последовательных портов

Вот как выглядит чтение из ПЗУ, если подключиться к линиям SPI логическим анализатором:

Временная диаграмма чтения данных из ПЗУ по SPI

Как видно, байты этого массива соответствуют кодам ASCII строки «HELLO, SOLTAU.RU», которые мы и записали в микросхему памяти 25L8005 🙂

Прошивка (чтение) памяти через Raspberry Pi 3 (Pi 2)

Интерфейс GPIO конструктора открывает широкие возможности для контроля и мониторинга периферийных устройств. Соответственно, есть возможность подключаться к электронным схемам, в частности – программировать (читать и прошивать) чипы памяти.

Детский мини компьютер через порт GPIO учит детей управлять светодиодами, запускать миниатюрные двигатели, выполнять многие другие простые действия, характерные для электроники.

Но компьютер конструктор Raspberry Pi 3 – это также реальный инструмент для прошивки BIOS, благодаря интерфейсу GPIO и поддержке технологии SPI.

Модели плат из новой серии детского конструктора  имеют 40-пиновый интерфейс GPIO. Более старые версии оснащены 26-пиновым разъёмом.

Разобранный планшет Lenovo ThinkPad X60, извлечённая материнская плата и заветный ПЗУ, который теперь нужно через подключение «прищепкой» прочитать и затем прошить новым содержимым

На материнской плате планшета Lenovo модели T60 чип памяти находится под опорной панелью и закреплён дюралюминиевой рамкой. Крепёж нужно снять, рамку демонтировать.

На следующем этапе подключение микросхемы памяти к интерфейсу GPIO мини компьютера конструктора Raspberry Pi 3.

Чип подключается, оставаясь непосредственно на плате, без выпаивания, через пружинный контактор (прищепка). Соединения проводников следует выполнять согласно раскладке:

Подключение MX25L1605 на 8 ножек: 1 ножка (CS) — 24 контакт; 2 ножка (MISO) — 21 контакт; 3 ножка — не используется; 4 ножка (GND) — 25 контакт; 5 ножка (MOSI) — 19 контакт; 6 ножка (CLK) — 23 контакт; 7 ножка — не используется; 8 ножка (3.3В) — 17 контакт

Питание на микросхему можно подать одним из двух способов:

  1. Через адаптер ноутбука, подключив низковольтный разъём адаптера к материнской плате, а его сетевой разъём в розетку 220В.
  2. От внешнего источника питания на 3.3В, плюсовой шиной на 8 ножку, минусовой на 4 ножку, соответственно.

Чтение подключенного ПЗУ MX25L1605

Рекомендуется точно определить производителя чипа BIOS, прежде чем пытаться начинать процедуру чтения содержимого.

Затем необходимо загрузить на компьютер Raspberry Pi и скомпилировать утилиту Flashrom. Делается это посредством следующего кода:

Кодовая комбинация 1

Далее для ПЗУ производства SST, выполнить команду:

Кодовая комбинация 2

Для ПЗУ производства Macronix выполнить последовательность:

Проверить контрольную сумму командой:

Кодовая комбинация 3

Повторно запустить утилиту Flashrom командой проверки контрольной суммы и следом выполнить команду на тест содержимого BIOS:

Кодовая комбинация 4Кодовая комбинация 5

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

Прошивка микросхемы flash серии 25хх

После удачных операций чтения дампа и сверки контрольной суммы, остаётся только выполнить завершающее действие – прошить микросхему памяти – записать в чип новую информацию, необходимую пользователю.

Для ПЗУ производства SST нужна команда:

Кодовая комбинация 6

Для ПЗУ производства Macronix нужна команда:

Кодовая комбинация 7

При этом путь к файлу «.rom» следует указывать по существу. То есть, если дамп прошивки лежит по пути: «/bin/x60/libreboot_usqwerty.rom», значит так и нужно указывать вместо строки: «/path/to/libreboot.rom».

После успешно завершённой операции, утилита выдаёт последовательность сообщений:

  1. Чтение старого содержимого чипа…успешно.
  2. Очистка и запись в чип…успешно.
  3. Проверка флеш…проверено.

Если операция завершилась неудачно, с частично исполненными командами, процедуру следует повторить. Иногда с первого раза чипы не прошиваются, особенно если производители памяти не относятся к фирмам, обозначенным здесь.

Аналогичным способом прошиваются ПЗУ других моделей планшетных компьютеров, а также чипы памяти из категории EEPROM и FLASH. Возможны определённые отклонения или дополнения в операциях с другими чипами в зависимости от конфигураций и требований. Однако в целом алгоритм процедуры сохраняется.

Пины только для входа

GPIO с 34 по 39 являются GPI — только входные. Эти контакты не имеют внутренних подтягивающих или понижающих резисторов. Они не могут быть использованы как выходы, поэтому используйте эти контакты только как входы:

  • GPIO 34
  • GPIO 35
  • GPIO 36
  • GPIO 39

SPI-flash встроена в ESP-WROOM-32

От GPIO 6 до GPIO 11 представлены в некоторых платах ESP32. Однако эти пины подключены к встроенной флэш-памяти SPI на микросхеме ESP-WROOM-32 их рекомендуется использовать для других целей. Назначение этих пинов:

  • GPIO 6 (SCK / CLK)
  • GPIO 7 (SDO / SD0)
  • GPIO 8 (SDI / SD1)
  • GPIO 9 (SHD / SD2)
  • GPIO 10 (SWP / SD3)
  • GPIO 11 (CSC / CMD)

Емкостные сенсорные GPIO

ESP32 имеет 10 внутренних емкостных сенсорных датчиков. Они могут отслеживать всё, что содержит электрический заряд, например, они могут обнаруживать изменения, возникающие при касании пальцами GPIO. Эти контакты могут быть легко встроены в датчики касания и заменять механические кнопки. Емкостные сенсорные контакты также могут быть использованы для пробуждения ESP32 от глубокого сна.

Внутренние сенсорные датчики подключены к этим GPIO:

  • T0 (GPIO 4)
  • T1 (GPIO 0)
  • T2 (GPIO 2)
  • T3 (GPIO 15)
  • T4 (GPIO 13)
  • T5 (GPIO 12)
  • T6 (GPIO 14)
  • T7 (GPIO 27)
  • T8 (GPIO 33)
  • T9 (GPIO 32)

Аналого-цифровой преобразователь (АЦП)

ESP32 имеет входные каналы АЦП 18 x 12 бит. Это GPIO, которые можно использовать в качестве АЦП:

  • ADC1_CH0 (GPIO 36)
  • ADC1_CH1 (GPIO 37)
  • ADC1_CH2 (GPIO 38)
  • ADC1_CH3 (GPIO 39)
  • ADC1_CH4 (GPIO 32)
  • ADC1_CH5 (GPIO 33)
  • ADC1_CH6 (GPIO 34)
  • ADC1_CH7 (GPIO 35)
  • ADC2_12 GPO (0)
  • ADC2_CH2 (GPIO 2)
  • ADC2_CH3 (GPIO 15)
  • ADC2_CH4 (GPIO 13)
  • ADC2_CH5 (GPIO 12)
  • ADC2_CH6 (GPIO 14)
  • ADC2_CH7 (GPIO 27)
  • ADC2_CH8 (GPIO 25)
  • ADC2_CH9 (GPIO 26)

Примечание: контакты ADC2 нельзя использовать при использовании Wi-Fi. Поэтому, если вы используете Wi-Fi и у вас возникают проблемы с получением значения от GPIO ADC2, вы можете вместо этого рассмотреть возможность использования GPIO ADC1, что должно решить вашу проблему.

Входные каналы АЦП имеют разрешение 12 бит. Это означает, что вы можете получить аналоговые показания в диапазоне от 0 до 4095, в которых 0 соответствует 0 В, а 4095 — 3,3 В. У вас также есть возможность установить разрешение ваших каналов в коде, а также диапазон АЦП.

Выводы АЦП ESP32 работают не линейно. Об этом следует помнить при использовании выводов АЦП. Ниже представлен график получемых значений в зависимости от напряжения:

4Запись данных в флеш-память с помощью Arduino

Теперь запишем на неё данные. Для примера возьмём небольшой массив из 16-ти байтов. Как видно из документации, для записи данных во флеш сначала нужно выставить разрешение на запись (1 байт), затем послать команду на запись (1 байт), передать начальный адрес (3 байта) и данные (в нашем примере 16 байт), а в конце выставить запрет записи (1 байт):

Диаграмма записи данных во флеш-память 25L8005

Напишем скетч, который записывает массив из 16-ти байт данных в ПЗУ:

#include <SPI.h>

const int SSPin = 10;
const byte WREN = 0x06;
const byte WRDI = 0x04;
const byte READ = 0x03;
const byte PP = 0x02;
const byte ADDR1 = 0;
const byte ADDR2 = 0;
const byte ADDR3 = 0;

void setup() {
  pinMode(SSPin, OUTPUT);
  SPI.begin();

  SPISettings mySet(100000, MSBFIRST, SPI_MODE0);
  
  // Выставление разрешения записи:
  SPI.beginTransaction(mySet);
  digitalWrite(SSPin, LOW);
  SPI.transfer(WREN);
  digitalWrite(SSPin, HIGH);
  SPI.endTransaction();

  // Запись массива данных в ПЗУ:
  SPI.beginTransaction(mySet);
  digitalWrite(SSPin, LOW);
  SPI.transfer(PP);
  SPI.transfer(ADDR1);
  SPI.transfer(ADDR2);
  SPI.transfer(ADDR3);
  byte data[] = {0x48,0x45,0x4c,0x4c,0x4f,0x2c,0x20,0x53,0x4f,0x4c,0x54,0x41,0x55,0x2e,0x52,0x55};
  for (int i=0; i<sizeof(data); i++) {
    SPI.transfer(data);
  }
  digitalWrite(SSPin, HIGH);
  SPI.endTransaction();
  
  // Выставление запрета записи:
  SPI.beginTransaction(mySet);
  digitalWrite(SSPin, LOW);
  SPI.transfer(WRDI);
  digitalWrite(SSPin, HIGH);
  SPI.endTransaction();
}

void loop() {
  // ничего не делаем в цикле
}

Загрузим скетч в Arduino. Кстати, вот так выглядит на логическом анализаторе обмен по SPI между Arduino и ПЗУ 25L8005, когда выполняется данный скетч.

Временная диаграмма записи в ПЗУ массива данных по SPI

После выполнения данного скетча во флеш-память должен был записаться наш тестовый массив. Давайте проверим, так ли это.