Как работает spi flash память

Обновлено: 04.07.2024

(2088) 5.00 (4) Оценки, комментарии

2020-03-20 Дата последнего изменения: 2021-03-04


Автор: Тиком — разработчик и производитель программаторов ChipStar .

В статье рассматриваются особенности применения микросхем SPI NAND FLASH (часто их еще называют Serial NAND), методы разметки страниц и управления плохими блоками, даны рекомендации по программированию на программаторах ChipStar.

CОДЕРЖАНИЕ:

1. ТЕОРИЯ

1.1. Коротко об SPI NAND FLASH

Микросхемы SPI NAND или Serial NAND являются разновидностью микросхем FLASH памяти типа NAND. Как и у всех подобных микросхем, их отличительными чертами являются:

  • Очень большой объем памяти.
  • Не гарантированное качество записи (возможно наличие ошибок).
  • Микросхемы могут иметь плохие (сбойные) блоки.
  • Размер страницы записи не является степенью 2.
  • Запись в микросхему осуществляетсятолько страницами, стирание- минимум блоками.

Подробно о классификации микросхем NAND, их видах, внутренней логической структуре подробно написано в нашей первой статье о NAND микросхемах. В этой статье мы больше коснемся особенностей SPI NAND (Serial NAND) и практической работы с ними.

1.2. Отличие микросхем SPI NAND от обычных (параллельных) микросхем NAND FLASH

Основное отличие заключается в том, что SPI NAND используют последовательный (serial) аппаратный интерфейс стандарта SPI (Serial Peripheral Interface).

Использование SPI дает ряд преимуществ:

  • Позволяет сделать корпус микросхем более компактным;
  • Позволяет использовать меньшее количество сигналов для управления микросхемой (4 против минимум 13 у параллельных NAND).

Однако SPI интерфейс при прочих равных условиях более медленный, поэтому микросхемы будут читаться и писаться несколько медленнее, чем традиционные NAND.

Все остальные особенности SPI NAND (логическая организация, управление плохими блоками и исправление ошибок) идентичны используемым у параллельных NAND и подробно рассмотрены в основной статье. Единственное отличие лишь в том, что в SPI NAND более широко используется механизм встроенного вычисления ECC кодов и исправления ошибок сразу внутри микросхемы. По этому признаку SPI NAND относятся к категории Managed NAND (управляемые NAND).

Главной особенностью логической организации SPI NAND является то, что большинство из них поддерживают встроенную генерацию кодов исправления ошибок (ECC) при записи и автоматическое исправление ошибок при чтении:

  • Коды ECC вычисляются непосредственно перед записью страницы;
  • Корректировка происходит сразу после считывания страницы;
  • Коды ЕСС записываются в определенное место SPARE области страницы;
  • Коды ECC вычисляются для всей области данных страницы, но только для некоторой части SPARE области;
  • Разметка SPARE области для разных микросхем разная;
  • Вычисление ECC у большинства микросхем можно временно отключить;
  • У некоторых микросхем часть области SPARE, в которой сохраняются коды ECC, недоступна для пользователя;
  • У некоторых микросхем при включении или выключении внутреннего вычисления ЕСС изменяется размер SPARE области;

Все вышеописанное скорее усложняет, чем упрощает, работу тем, кто занимается ремонтом аппаратуры и заранее не знает, каким образом и в каком режиме ECC используется микросхема в аппаратуре.

2. ПРАКТИКА

2.1. Настройка интерфейса SPI

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


Например, можно уменьшить скорость работы SPI интерфейса или переключить формат адреса в режим совместимости с обычными SPI FLASH.

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

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

Рисунок: Формат spare области в редакторе программатора

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

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

Рисунок: Формат spare области в редакторе программатора

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

2.3. Поддержка разных форматов резервной области

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

Рисунок: Отчет о конфигурации NAND в редакторе программатора

  • ECC коды хранятся в резервной (spare) области начиная с адреса 0x840 по адрес 0x87F (конец области) одним непрерывным блоком.
  • В отчете о внутренних ошибках ЕСС видно, что страницы 1 и 2 содержат исправляемые ошибки (менее 8 на сектор для данной микросхемы), а вот ошибок на странице 3 оказалось слишком много, и они не исправлены.

2.4. Запись образа SPI NAND

Рассмотрим несколько примеров. На рисунке ниже показано окно подтверждения начала записи с открытой закладкой ECC в случае, если форматы резервной области и исходного файла и микросхемы совпадают:


На следующем рисунке когда форматы резервной области и исходного файла также совпадают, но формат другой:


Ниже показан случай несовпадения разметки резервных областей:


В этом случае программа выдает предупреждение и блокирует попытку записи такой микросхемы, как заведомо неуспешную.

Попробуем записать файл в микросхему SPI NAND с включенным режимом внутренней генерации ECC. На рисунке ниже показан пример такой записи:


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

  1. Основная область страницы в редакторе показана обычным шрифтом;
  2. Резервная (spare) область микросхемы показана тусклым шрифтом, место маркера плохого блока показано на оранжевом фоне;
  3. Резервная (spare) область микросхемы предназначенная для размещения ECC выделена светло-голубым фоном;
  4. Резервная (spare) область микросхемы заполненная кодами ECC (результат внутренней генерации ECC).

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

Программное обеспечение программатора ChipStar знает о такой особенности этих микросхем и не выдает ошибок при верификации таких микросхем: все различия в области ECC будут учтены в отчете о верификации, но ошибка верификации выдана не будет. А вот при сравнении двух файлов эти области будут отмечены как ошибочные. Таким образом, можно гибко анализировать и сравнивать содержимое микросхем.

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

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

Рисунок: Информация ONFI считанная из микросхемы

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

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

2.6. Как узнать, использует ли целевое устройство встроенную в микросхему коррекцию ошибок (ECC)

Этот практический совет может пригодиться тем, кто занимается ремонтом РЭА . Часто в этом случае на руках имеется только устройство с микросхемой и не ясно, по каким алгоритмам работает программное обеспечение устройства. Поэтому важно правильно считать дамп микросхемы. Но какой дамп будет правильный: считанный с включенной коррекцией ECC или с выключенной?

Эта статья продолжает тему, связанную с угрозой искажения BIOS материнской
платы вредоносными программами. В ранее опубликованном материале
"Проникновение в BIOS ROM"
N1 и N2 был
приведен пример программы, выполняющей запись в микросхему BIOS, рассмотрены
механизмы защиты, используемые производителями материнских плат и причины, по
которым данные механизмы часто оказываются неэффективными. Напомним, что эта
проблема возникла более 10 лет назад, когда в качестве носителя BIOS начали
использовать микросхемы Flash ROM, допускающие перезапись содержимого без
физического вмешательства в компьютер. Таким образом, возможность оперативной
перезаписи (обновления) BIOS, привела к побочному эффекту – риску его случайного
или преднамеренного искажения.

Казалось бы, сегодня на эту тему уже все сказано. Но время идет, появляются
новые типы микросхем Flash ROM и интерфейсов для их подключения. Это
сопровождается появлением новых методов защиты BIOS от несанкционированного
искажения, и, конечно, новых уязвимостей. В ранее опубликованном материале,
ссылка на который приведена в начале статьи, рассматриваемая тема раскрыта на
примере платформы, использующей микросхему SST 49LF004A, подключенную к
интерфейсу LPC (Low Pin Count). Сегодня, ему на смену пришел интерфейс SPI
(Serial Peripheral Interface). Напомним, что для перезаписи содержимого
микросхемы BIOS, программа должна взаимодействовать с двумя блоками регистров:
регистры интерфейса Flash ROM, расположенные в составе "южного моста" чипсета и
регистры, входящие в состав самой микросхемы Flash ROM. При переходе от
интерфейса LPC к SPI, архитектура двух указанных блоков существенно изменилась.
Поэтому есть смысл рассмотреть взаимодействие программ с микросхемой BIOS,
механизмы защиты и их уязвимости применительно к современным платформам.
Материал снабжен примерами на ассемблере. Для экспериментов использовалась
материнская плата Gigabyte GA-965P-S3, построенная на чипсете Intel 965,
описанном в 2. В качестве носителя BIOS на данной плате используется
микросхема SST 25VF080B, описанная в [5]. Эта микросхема имеет объем 8 Мегабит
(1 Мегабайт) и подключается к интерфейсу SPI. Некоторые микросхемы других
производителей, использующих тот же интерфейс, описаны в [4,6,7]. Описание
интерфейса SPI приведено в [8,9]. При взаимодействии с контроллером SPI, нам
потребуется использовать механизмы доступа к конфигурационному пространству,
описанные в документах 11.

Интерфейс SPI: историческая справка

Как известно, быстродействие микросхемы постоянного запоминающего устройства
(Flash ROM), используемой в качестве носителя BIOS, практически не влияет на
общую производительность компьютера. Это связано с тем, что при старте
материнской платы, BIOS переписывается (или распаковывается) в оперативную
память Shadow RAM и при обращении к BIOS в сеансе ОС, программы работают с
оперативной памятью, а не с микросхемой Flash ROM. Поэтому, в отличие от
процессора, памяти, графической подсистемы, эволюция которых сопровождается
ростом производительности, микросхемы Flash ROM и их интерфейсы развиваются в
другом направлении. Здесь главными критериями являются уменьшение стоимости,
потребляемой мощности и занимаемой площади на материнской плате. Главный метод
достижения этих целей – уменьшение количества проводников между микросхемой BIOS
и контроллером, обычно входящим в состав "южного моста" чипсета. С точки зрения
метода подключения микросхемы BIOS, можно выделить три поколения материнских
плат:

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

2) С появлением чипсетов Intel 810, 815, на основе "хабовой" архитектуры,
шина ISA ушла в прошлое. Ряд устройств материнской платы, ранее подключаемых к
ISA (контроллер гибких дисков, порты COM и LPT, микросхема BIOS), "переехали" на
интерфейс Low Pin Count или LPC, название которого переводится как "малое
количество сигналов". Сигналы адреса, данных и управления в этом интерфейсе
передаются по пяти линиям (не считая сигналов сброса, тактирования и линий
питания), в режиме мультиплексирования во времени. Микросхемы BIOS, используемые
в таких платформах, иногда называют Firmware Hub или FWH. Пример программы
стирания и записи микросхемы BIOS, приведенный в ранее опубликованной статье
"Проникновение в BIOS ROM" N1 и N2" предназначен для таких платформ.

Отметим, что интерфейс LPC также поддерживается современными чипсетами и
разработчик материнской платы может использовать для подключения микросхемы BIOS
как LPC, так и SPI. Сфера применения интерфейса SPI не ограничивается
материнскими платами компьютеров. Внимательный читатель мог обратить внимание на
то, что из-за перехода к последовательному формату данных, каждый из описанных
интерфейсов использует больше тактов для выполнения операций чтения и записи,
чем его предшественник, что чревато снижением быстродействия. Но этого не
происходит, так как указанное обстоятельство компенсируется ростом частоты и
оптимизацией форматов данных. Шина ISA работает на частотах 5-8MHz, LPC на
33MHz, SPI на 33-50 MHz.

Архитектура микросхемы SPI Flash ROM

Микросхемы SPI Flash, в частности SST25VF080B, используют три сигнала для
приема и передачи данных. SCK (Serial Clock) – вход для тактирования
передаваемых или принимаемых данных. SI (Serial Input) – вход для передачи
данных от контроллера к микросхеме, по этой линии побитно передаются адрес,
данные для записи, и коды команд управления микросхемой. SO (Serial Output) –
выход для передачи данных от микросхемы к контроллеру, по этой линии побитно
передаются читаемые данные, а также информация о состоянии микросхемы.
Контроллер управляет микросхемой посредством команд, инициирующих операции
чтения и записи данных, стирания, чтения идентификаторов микросхемы, чтения и
записи регистра статуса и т.п.

Назначение каждого из восьми контактов микросхемы, описание всех команд, а
также другие подробности содержатся в [5].

Архитектура контроллера SPI

Контроллер SPI, входящий в состав "южного моста" Intel ICH8, содержит более
20 регистров управления и состояния. Регистры адресуются в пространстве памяти с
использованием технологии memory-mapped I/O, рассмотренной в ранее
опубликованной статье "Устройства системной поддержки. Исследовательская работа
N 7". Описание всех регистров и команд контроллера SPI выходит за рамки
данной статьи, рассмотрим основные отличия программной модели интерфейса SPI от
его предшественника - интерфейса LPC, акцентируя внимание на регистрах,
используемых при выполнении основных операций – чтении идентификаторов, записи и
стирании Flash ROM.

Напомним, что физический доступ к микросхеме BIOS (не путать с областью
Shadow RAM) осуществляется посредством окна, примыкающего к верхней границе
диапазона 0-4GB. Например, Flash ROM размером 1 Мбайт будет доступен в диапазоне
FFF00000h-FFFFFFFFh. В платформах, использующих интерфейсы ISA и LPC, через тот
же диапазон, при выполнении операций стирания и записи выполняется передача
команд и записываемых данных для микросхемы Flash ROM, а также чтение ее
статуса. Платформа, использующая интерфейс SPI, рассматриваемая в данной статье,
также поддерживает чтение содержимого микросхемы BIOS через указанный диапазон,
но для передачи управляющей и статусной информации во время записи и стирания
Flash ROM, используется другой метод доступа. Информация для выполнения цикла на
шине SPI (адрес и данные) записывается в специальные регистры контроллера SPI
(Flash Address и Flash Data соответственно), затем в регистр Software Sequencing
Flash Control передается команда на выполнение цикла обращения к Flash ROM
(чтения или записи). После этого, через регистр Software Sequencing Flash Status
можно определить момент завершения операции и проконтролировать наличие ошибок.
Данные, прочитанные из Flash ROM, находятся в регистре Flash Data.

Бит 0 (SPI Cycle In Progress) – используется для определения момента
завершения операции на шине SPI. "0" означает, что шина SPI свободна и программа
может запускать следующий цикл. "1" означает, что шина SPI занята, выполняется
транзакция. Бит устанавливается и сбрасывается аппаратно, доступен только для
чтения.

Бит 1 (Reserved) – не используется.

Бит 2 (Cycle Done Status) – устанавливается в "1" аппаратно, при
завершении транзакции на шине SPI. Для сброса, программа должна записать "1" в
данный бит.

Бит 3 (Flash Cycle Error) – устанавливается в "1" аппаратно, если при
выполнении транзакции имели место ошибки: защита записи или попытка запуска
следующей транзакции до завершения предыдущей. Для сброса, программа должна
записать "1" в данный бит.

Бит 4 (Access Error Log) – устанавливается в "1" аппаратно, если имели
место попытки обращения к микросхеме BIOS, нарушающие права доступа к заданным
диапазонам адресов, запрограммированным в конфигурационных регистрах контроллера
SPI.

Биты 5-7 (Reserved) – не используются.

Бит 9 (SPI Cycle Go) – запуск транзакции на SPI. Запись "1" в этот бит
запускает выполнение транзакции, тип и содержание которой определяются
состоянием битов 10-31 этого же регистра.

Бит 10 (Atomic Cycle Sequence) – при передаче приказа на выполнение
транзакции, запись "1" в этот бит запрещает внешним событиям вмешиваться в
процессы, происходящие на интерфейсе SPI до тех пор, пока не будут выполнены три
фазы: передача префиксной команды, передача основной команды и завершение
выполнения основной команды.

Отметим, что таким образом реализуется один из механизмов защиты от
случайного искажения содержимого микросхемы BIOS. Так называемые префиксные
команды (например, Write Enable) должны предшествовать командам, изменяющим
содержимое микросхемы (например, Write, Erase). Получив код команды, содержащий
"1" в данном бите, все три фазы контроллер выполняет аппаратно, без
вмешательства процессора до завершения выполнения основной команды.

Бит 11 (Sequence Prefix Opcode Pointer) – при использовании префиксных
команд (когда бит 10 установлен в "1", см. выше), этот бит выбирает один из двух
байтов, который будет передан в качестве префиксной команды для микросхемы SPI
Flash. При "0" выбирается младший байт регистра Prefix Opcode Configuration
Register, при "1" – старший.

Бит 12-14 (Cycle Opcode Pointer) – это битовое поле выбирает один из
восьми байтов, который будет передан в качестве основной команды для микросхемы
SPI Flash. Указанные байты находятся в регистре Opcode Menu Configuration
Register.

Бит 15 (Reserved) – не используется.

Биты 16-21 (Data Byte Count) – задает количество байтов данных для
операций чтения или записи данных. Количество равно значению этого поля плюс 1.
Например: 000000b=1 байт, 111111b=64 байта.

Бит 22 (Data Cycle) – Задает наличие байтов данных в команде. "0"
означает, данные отсутствуют (например, в команде стирания), "1" означает, что
данные присутствуют (например, в команде чтения статуса, данными является
содержимое регистра статуса).

Биты 24-26 (SPI Cycle Frequency) – задает частоту битовой
синхронизации при выполнении транзакции на SPI. Используются два значения
(остальные зарезервированы): 000b=20MHz, 001b=33MHz.

Биты 27-31 (Reserved) – не используются.

Отметим, что предварительное заполнение восьми байтов регистра Opcode Menu
Configuration Register и двух байтов регистра Prefix Opcode Configuration
Register выполняет BIOS при старте платформы. Поэтому, при формировании битовых
полей, выбирающих код команды и код префикса, программа должна просканировать
указанные регистры и найти, под каким номером в них находятся коды требуемых
операций. Варианты заполнения могут быть разными, даже среди материнских плат
одной модели, использующих различные версии BIOS. Некоторые утилиты перезаписи
Flash изменяют содержимое указанных регистров.

Детальное описание всех регистров и команд контроллера SPI приводится в [3].
Описание команд микросхемы SPI Flash приводится в 5. Информация, изложенная
выше, также проиллюстрирована ассемблерными примерами, прилагаемыми к статье.

Механизмы доступа к Flash ROM и защита записи

В общем случае, для инициирования операций стирания или перезаписи микросхемы
BIOS, программа должна выполнить четыре действия:

  1. Настроить регистры "южного моста" чипсета, управляющие размещением
    микросхемы BIOS в адресном пространстве для обеспечения доступа к полному
    объему микросхемы.
  2. Выключить режим защиты записи BIOS, реализуемый средствами "южного моста"
    чипсета.
  3. Выключить режим защиты записи BIOS, реализуемый средствами микросхемы
    Flash ROM.
  4. Передать команду стирания или записи микросхеме Flash ROM.

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

Как было сказано выше, при выполнении операций записи и стирания, программный
доступ к микросхеме SPI Flash осуществляется посредством регистров контроллера
SPI, без использования диапазона адресов, в котором доступен образ микросхемы
BIOS. Поэтому перенастройка чипсета для доступа к диапазону FFF00000h-FFFFFFFFh
в данном примере не потребуется.

Практика показывает, что данный механизм "защиты от снятия защиты" обычно не
активируется разработчиками BIOS. Во всех материнских платах, исследованных
автором, бит BLE=0, поэтому для снятия защиты записи достаточно установить бит
BIOSWE=1, эта операция не будет перехвачена.

Микросхема Intel ICH8 также поддерживает защиту содержимого микросхемы BIOS,
путем задания адресных диапазонов, защищенных от чтения и (или) записи.
Теоретически, на базе данного механизма можно реализовать эффективную защиту,
так как запрет программно включается процедурами BIOS при старте платформы, и
может быть снят только при аппаратном сбросе. Но и этот механизм обычно не
активируется разработчиками BIOS.

Источники информации

1) Intel Low Pin Count (LPC) Interface Specification. Revision 1.1. Document
Number 251289-001.
2) Intel P965 Express Chipset Family Datasheet – For the Intel 82P965 Memory
Controller Hub (MCH). Document Number: 313053-001.
3) Intel I/O Controller Hub 8 (ICH8) Family Datasheet – For the Intel 82801HB
ICH8 and 82801HR ICH8R I/O Controller Hubs. Document Number: 313056-001.

4) 1 Mbit SPI Serial Flash SST25VF010 Data Sheet. Document Number:
S71233-01-000.
5) 8 Mbit SPI Serial Flash SST25VF080B Data Sheet. Document Number:
S71296-01-000.

6) W25X10A, W25X20A, W25X40A, W25X80A 1M-bit, 2M-bit, 4M-bit and 8M-bit
Serial Flash Memory with 4KB sectors and dual output SPI Data Sheet.

7) MX25L802 8M-bit [8Mx1] CMOS Serial Flash EEPROM Data Sheet.

8) SPI EEPROM Interface Specification. Part Number 223-0017-004 Revision H.

Микроконтроллеры STM32: работа с SPI на примере флеш-памяти AT45DB161E

Благодаря заметке Микроконтроллеры STM32: работа с внешним EEPROM мы научились работать с внешней EEPROM-памятью с I2C-интерфейсом. Сегодня же мы научимся использовать флеш-память с SPI-интерфейсом на примере популярных чипов AT45DBxx. Существуют разные модификации этих чипов, отличающиеся в основном объемом памяти. При написании этой заметки я использовал AT45DB161E объемом 16 Мбит (2 Мб). Но, по идее, все описанное ниже справедливо и для других чипов этой серии.

Пожалуй, наиболее очевидное преимущество чипов AT45DBxx перед рассмотренными ранее 24Cxx заключается в существенно большем объеме памяти. У первых я видел модификации, хранящие 8 Мб данных (AT45DB641E), и теоретически протокол позволяет работать с объемами данных до 16 Мб. Вторые же предлагают максимум 256 Кб. AT45DB161E поддерживает передачу данных с тактовой частотой до 85 МГц, против 400 КГц у 24LC64. То есть, чипы AT45DBxx позволяют передавать данные намного быстрее. Но при этом следует учитывать время выполнения конкретных операций. Например, операция очистки и записи одной страницы в случае AT45DBxx занимает десятки миллисекунд.

EEPROM хорош тем, что он более долговечен. Даташит 24LC64 [PDF] сообщает, что чип переживает более 1 миллиона циклов очистки-записи, и что данные будут хранится более 200 лет. Для сравнения, согласно даташиту AT45DB161E, гарантируется только 100 000 циклов очистки-записи, и данные хранятся лишь 20 лет. Кроме того, чипы 24Cxx заметно дешевле. Розничные цены в России на них начинаются где-то от 0.1$, против 0.6$ у чипов AT45DBxx. Наконец, как мы скоро убедимся, работать с AT45DBxx несколько сложнее, хотя эта сложность и может быть завернута в библиотеку.

Итак, создадим новый проект в STM32CubeMX. Для своих экспериментов я все также использую отладочную плату Nucleo-F411RE. Если у вас другая отладочная плата, отличия в настройке будут минимальными. Для общения с ПК включаем USART2, как делали это в статье Микроконтроллеры STM32: обмен данными по UART. Также включаем периферию SPI1, в выпадающем списке Mode выбираем «Full-Duplex Master». В этом режиме периферии нужен пин PA5, который по умолчанию управляет светодиодом на отладочной плате. Поэтому STM32CubeMX будет жаловаться на ошибку в конфигурации, пока мы не освободим пин PA5. Также помечаем пин PB6 как GPIO_Output. Он будет использоваться для выбора SPI устройства, с которым мы хотим поговорить (так называемый «chip select» или «slave select»).

Вот что должно получиться:

Настройка SPI в STM32CubeMX

$(FIRMWARE)/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c \

Взглянем на распиновку AT45DB161E (иллюстрация из даташита [PDF]):

Распиновка SPI-flash памяти AT45DB161E

С учетом всего вышесказанного, у меня получился такой сэндвич:

Подключение SPI-flash памяти к отладочной плате Nucleo

На этом работа с железной частью завершена, переходим к софтверной. Даташит содержит подробное описание множества команд, поддерживаемых чипом. Рассмотрим некоторые из них.

Важно! Существует две модификации чипов AT45DBxx. Первая модификация работает со страницами размером 528 байт. Пример полной маркировки такого чипа: AT45DB161E-SHD. Вторая модификация работает со страницами размером 512 байт, пример маркировки: AT45DB161E-SHD2B, где часть «2B» как раз указывает на размер страниц в 512 байт (см разел 27.1 даташита). В зависимости от размера страницы меняется и их адресация. Далее приводится код для -SHD чипов, в котором также присутствует закомментированный код для -SHD2B чипов.

Самая простая команда, это, пожалуй, получение device id. Я бы советовал выполнить ее в первую очередь, чтобы убедиться в правильности подключения и всего такого. Команда имеет код 0 x 9F и принимает в ответ 5 байт:

Ответ должен быть следующим:

Manufacturer ID: 0x1F
Device ID (byte 1): 0x26
Device ID (byte 2): 0x00
Extended device information (EDI) string length: 0x01
EDI byte 1: 0x00

Для чтения и записи существует сильно больше одной команды. Устройство имеет два SRAM-буфера, каждый размером в одну страницу. И предусмотрены команды вроде «записать содержимое буфера 1 в страницу», «прочитать содержимое буфера 2», «очистить страницу», и подобного рода. В определенных задачах эти команды могут быть полезны, однако мы рассмотрим лишь самые простые с точки зрения использования команды.

Чтобы записать данные через буфер 1 с предварительной очисткой страницы, воспользуемся командой 0 x 82. Следом за кодом команды должны следовать три байта, содержащие адрес, по которому мы хотим осуществить запись, а затем и сами данные. О том, что передача данных завершилась, устройство узнает по исчезновению низкого напряжения с пина CS:

Выполнение команды происходит не моментально. Поэтому если сразу после записи мы попытаемся прочитать данные, то, скорее всего, увидим мусор. Можно просто сделать HAL_Delay , скажем, на 20 мс, но, строго говоря, такой вызов не гарантирует, что при возвращении из него запись данных будет обязательно завершена. Действительно работающее решение заключается в чтении status register устройства и проверки его флага RDY. Соответствующая команда имеет код 0 x D7 и получает в ответ два байта с содержимым регистра. Если после выполнения команды не вернуть высокое напряжение на CS, устройство продолжит посылать обновленные значения регистра. Пример кода:

Await loop took 10 ms, 1750 iterations
Sector protection status: disabled
Page size: 528 bytes
Erase/program error: no error
Sector lockdown command: enabled

Дождавшись завершения записи, можно попытаться и прочитать только что записанные данные. Для этого существуют команды 0 x 0B и 0 x 1B. Последняя, насколько я смог выяснить, появилась лишь в более поздних чипах производства Adesto (компания купила эту часть бизнеса у Atmel в 2012 году), и не упоминается в даташитах более старых устройств, например AT45DB161D [PDF]. Поэтому рассмотрим более переносимую команду 0 x 0B. Как и в случае с записью, за ней должны следовать три байта, содержащие адрес, который мы читаем. Кроме того, должен следовать один байт, значение которого будет проигнорировано. Пример кода:

// for 512 bytes/page chip address is transfered in form:
// rcmd[1] = (pageAddr >> 7) & 0x1F;
// rcmd[2] = (pageAddr << 1) & 0xFE;
// rcmd[3] = 0x00;

Итак, теперь мы знаем, как осуществлять чтение и запись. Этих знаний должно вполне хватить для решения 99% практических задач.

Важно! Обратите внимание, что процедуры HAL_SPI_* принимают размер данных в виде типа uint16_t . То есть, если вам когда-нибудь понадобится передать или принять по SPI больше 64 Кб, данные придется нарезать на куски.

Полную версию исходного кода, как обычно, вы найдете на GitHub. Напомню, что в настоящем, боевом коде вы, вероятно, захотите более серьезно отнестись к проверьке кодов возврата, чем это делал я. Кроме того, я бы советовал хранить вместе с данными их контрольную сумму. За более подробной информацией по чипу AT45DB161E обращайтесь к даташиту [PDF], он классный. Что же касается работы с SPI, стоит отметить, что за кадром осталось использование его совместно с прерываниями и DMA. Но об этом уж как-нибудь в другой раз.

А доводилось ли вам работать с чипами AT45DBxx или чем-то аналогичным? Возникали ли у вас с ними какие-то проблемы? Если не секрет, что именно вы в них хранили?

SPI (Serial Peripheral Interface, последовательный периферийный интерфейс, шина SPI) - Это интерфейс для передачи данных на короткое расстояние, разработанный Motorola. Данные передаются в режиме полного дуплекса (в обе стороны) используя архитектуру ведущий - ведомый (master-slave). SPI также иногда называют четырёхпроводным (four-wire) интерфейсом.


Рис.1 стандартное общение по SPI

В шине SPI используются 4 цифровых сигнала:

  • MOSI : (Master Out Slave In) выход ведущего, вход ведомого.
  • MISO : (Master In Slave Out) вход ведущего, выход ведомого.
  • SCLK : (Serial Clock) тактовый сигнал.
  • CS или SS : (Chip Select, Slave Select) выбор микросхемы, выбор ведомого.
  • MOSI : SIMO, SDO, DO, DOUT, SI, MTSR;
  • MISO : SOMI, SDI, DI, DIN, SO, MRST;
  • SCLK : SCK, CLK;
  • SS : nCS, CS, CSB, CSN, nSS, STE, SYNC.

Если использовать несколько ведомых устройств, то нужно повесить подтягивающие резисторы на каждый из выводов SS и убедиться что выходы MISO каждого из устройств подключены через буфер с высокоимпедансным состоянием (практически вывод считается отключённым), это может быть реализовано внутри микросхемы, нужно изучать документацию на конкретное устройство.


Рис.2 Правильное включение нескольких SPI устройств
Если внутри устройств не предусмотрен буфер, то линия MISO будет всегда в состоянии лог.0 или лог.1. (также она может сгореть). Чтобы проверить есть ли внутри нашего устройства буфер, можно прочитать документацию или подключить делитель напряжения, чтобы на линии MISO была половина напряжения питания, затем замерить настоящее напряжение. Если замеренное нами значение отличается (будет 0 В или напряжение питания), то буфера нет и его нужно поставить отдельной микросхемой.


Рис.3 Проверка присутствия внутреннего буфера

Ведущий и ведомый передают друг другу данные одновременно. Сперва нужно выбрать ведомое устройство выставив на его входе SS низкий логический уровень (может меняться в зависимости от производителя). Данные для передачи помещаются в сдвиговые регистры. Затем ведущий генерирует синхросигналы частотой около нескольких МГц, ведущий и ведомый начинают посылать друг другу информацию хранимую в сдвиговых регистрах бит за битом начиная со старшего разряда.


Рис.4 Передача данных по SPI
Всего используется 2 сдвиговых регистра, старший бит из одного устройства передаётся в младший бит другого устройства, после чего регистр сдвигает хранимую в нём информацию. Количество бит в 1 пакете данных зависит от конкретного устройства, некоторые производители добавляют возможность изменять длину пакета.

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

Для настройки интерфейса используются несколько регистров, Можно регулировать частоту, прерывания, порядок бит и многое другое, подробнее об этом можно узнать в документации от Motorola ee.nmt.edu, этот документ взят как стандарт для SPI. Но производители могут не использовать всех настроек описанных там, также биты могут быть расставлены в другой последовательности в отличии от описания Motorola. В любом случае нужно читать документацию на конкретное устройство.

Если про настройку частоты передачи и выбор ведущего/ведомого понятно, то про настройку фазы и полярности тактового сигнала можно расписать подробней.

В принципе, эти настройки можно понять из временной диаграммы:

  • CPOL = 0 : сигнал синхронизации начинается с низкого уровня;
  • CPOL = 1 : сигнал синхронизации начинается с высокого уровня;
  • CPHA = 0 : данные записываются по переднему фронту сигнала синхронизации;
  • CPHA = 1 : данные записываются по заднему фронту сигнала синхронизации.

В зависимости от состояния битов CPHA и CPOL, различают 4 режима работы SPI интерфейса (0, 1, 2 или 3). Но в зависимости от производителя они часто соответствуют разным состояниям битов, к примеру, у ARM и PIC32MX контроллеров ни 1 из режимов не совпадает.

Есть 2 популярных способа включения нескольких SPI, первый из них подключение "звезда" (daisy chain):


Рис.5 Топология типа "звезда"
В этом случае ведущий выбирает, кому из ведомых устройств следует передать данные.

Может быть такое что ведомые устройства не совместимы друг с другом и им нужны разные настройки, к примеру различная длина пакета, в таком случае используют соединение типа "кольцо":


Рис.6 Топология типа "кольцо"
В данном случае все устройства включаются одновременно и данные передаются последовательно, для того чтобы передать информацию какому либо устройству, либо от него ведущему, необходимо пройти несколько циклов передачи.

SPI интерфейс заслужил свою популярность благодаря простоте и дешевизне. Сейчас его можно встретить в огромном количестве устройств, С его помощью программируются МК, JTAG также реализован на основе SPI. он часто используется для общения с различными микросхемами: Flash память, EEPROM, LCD, SD карты, АЦП, ЦАП микросхемы и многое другое.

Хоть стандарт и описан Моторолой, нет чётких определений и границ для SPI, из-за чего можно встретить различные реализации этого интерфейса, может использоваться другое количество сигнальных линий, количество бит в пакете и другие способы настройки. Так что сперва нужно читать документацию на устройство с которым вы работаете.

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

Читайте также: