ПРОГРАММИРОВАНИЕ МИКРОСХЕМ FLASH-ПАМЯТИ


А. ДОЛГИЙ, г. Москва

Микросхемы репрограммируемой постоянной памяти с электрическим стиранием данных, выполненные по технологии FLASH, заняли прочные позиции в электронной и вычислительной технике, потеснив другие виды энергонезависимых запоминающих устройств. Их главное достоинство - возможность перепрограммирования "в системе", не выпаивая микросхему из печатной платы или не вынимая ее из панели. Большое допустимое число циклов перепрограммирования позволяет строить на таких микросхемах "FLASH-ДИСКИ" объемом в десятки мегабайт, отличающиеся от обычных накопителей на жестких или гибких магнитных дисках полным отсутствием движущихся частей. Благодаря этому они долговечны и способны работать в условиях сильной вибрации, например, на автомобилях и других движущихся объектах. Публикуемая статья посвящена вопросам программирования микросхем FLASH-памяти.

От РПЗУ других типов микросхемы FLASH-памяти отличает наличие непосредственно на кристалле встроенного "программатора" - автомата стирания и записи (АСЗ). Он освобождает от необходимости в процессе программирования подавать на выводы микросхемы повышенное напряжение, формировать определенные последовательности импульсов. Все это АСЗ делает самостоятельно и незаметно для пользователя, которому остается лишь с помощью соответствующей команды сообщить адрес ячейки и код, который следует в нее записать, и ждать завершения операции. Во многих случаях длительную операцию (например, стирание блока данных) можно приостановить, прочитать нужную информацию из другой области памяти, а затем продолжить.

Сегодня многие фирмы (наиболее известные Intel, AMD, Atmel, Winbond) выпускают большой ассортимент микросхем FLASH-памяти объемом до 4 Мбайт. Их внешний интерфейс бывает параллельным или последовательным. Микросхемы с последовательным интерфейсом предназначены в основном для хранения небольших массивов данных в малогабаритных или специализированных устройствах, например, для запоминания фиксированных настроек радиоприемника или программы работы бытового электроприбора.

Далее речь пойдет о "параллельных" FLASH-микросхемах, которые по физическому и логическому устройству интерфейса с процессором ничем не отличаются от обычных ПЗУ за исключением того, что у них, подобно ОЗУ, имеется вход разрешения записи. Именно в таких микросхемах хранят коды BIOS современных компьютеров. Организация данных бывает восьми-или 16-разрядной. Нередко ее можно выбирать, соединяя специально предусмотренный вывод с общим проводом или источником питания. Кроме шин адреса и данных, к микросхемам подводят три управляющих сигнала: выбор кристалла (СЕ), включение выхода (ОЕ) и разрешение записи (WE). Последний - только в случае, если микросхему необходимо программировать. Минимальная длительность цикла чтения -70...150 нc.

В первых FLASH-микросхемах массив ячеек памяти представлял собой единый блок, причем стереть данные можно было только целиком из всего массива. Во многих современных микросхемах память разбита на блоки, и стирание данных в одном из них не влияет на хранящиеся в других. Размеры блоков бывают самыми разными - от 128 байт до 128 Кбайт и более. Однако при чтении данных вся память микросхемы рассматривается как единый массив и то, что физически она разделена на блоки, не имеет никакого значения.

Обычно блоки одинаковы и равноправны, но могут быть и разными. Например, в микросхемах серии 28Fххх фирмы Intel имеются так называемый загрузочный (boot) блок объемом 16 Кбайт и два блока параметров по 8 Кбайт каждый. Далее следует блок объемом 96 Кбайт, а оставшаяся часть памяти состоит из блоков по 128 Кбайт. Свойства названных блоков несколько различаются. Для загрузочного предусмотрена аппаратная защита от записи и стирания. Ее включают, подав соответствующий логический уровень на специально предусмотренный вывод микросхемы. Блоки параметров предназначены для хранения часто изменяемых данных и выдерживают большее, по сравнению с другими, число циклов стирания/записи.

Каждую из микросхем рассматриваемой серии изготавливают в двух вариантах, различающихся размещением блоков в адресном пространстве. В микросхемах с индексом В (bottom) они расположены, начиная с нулевого адреса, в указанном выше порядке. В изделиях с индексом Т (top) порядок обратный (загрузочный - в области старших адресов).

Выпускаемые в настоящее время микросхемы FLASH-памяти рассчитаны на номинальные напряжения питания от 2,7 до 5 В. Повышенное напряжение (12В) для них не требуется вовсе или необходимо лишь в некоторых специальных режимах. В пассивном ("невыбранном") состоянии такие микросхемы потребляют от источника питания ток не более 1 мА (в большинстве случаев - в десятки раз меньше). Иногда предусмотрен особый режим полного выключения (sleep mode), в котором потребление пренебрежимо мало. Правда, читать данные из "заснувшей" микросхемы невозможно, а чтобы "разбудить" ее, порой требуется несколько десятков микросекунд. Потребляемый ток в активном режиме - десятки миллиампер, причем, если перевести в пассивное состояние микросхему, АСЗ которой выполняет длительную операцию (например, стирает данные), ток не уменьшится до тех пор, пока она не завершится.

Большое внимание уделяют защите хранящихся во FLASH-памяти данных от случайного изменения, особенно под воздействием помех и переходных процессов при включении и выключении питания. В большинстве случаев предусмотрено три вида аппаратной защиты. Первый заключается в том, что на импульсы в цепи WE длительностью менее 15...20 нc микросхема не реагирует, второй - в том, что при низком логическом уровне на входе ОЕ никакие манипуляции сигналами на других входах не могут вызвать запись, третий - в том, что при уменьшении напряжения питания ниже некоторого уровня АСЗ отключается. У микросхем разных типов порог отключения находится в пределах 1,5...3,8 В.

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

Предусматривается и программная защита. Для изменения содержимого ячейки FLASH-памяти недостаточно, как в обычном ОЗУ, записать один код по одному адресу. Необходима команда, состоящая из нескольких кодов, записываемых по определенным адресам.

Любая FLASH-микросхема способна сообщить свой тип устройству, в которое она установлена, что позволяет автоматически выбирать нужные алгоритмы записи и стирания данных. Для программного включения и выключения режима считывания идентификаторов предусмотрены соответствующие команды. Включив его, по адресу ОН читают идентификатор изготовителя, а по адресу 1Н - устройства (идентификаторы некоторых микросхем приведены в таблице). В этом же режиме, но по другим адресам, в некоторых случаях можно получить дополнительную информацию, например, о состоянии аппаратной защиты от записи.

Перейти в режим чтения идентификаторов можно и без команды, подав на адресный вход А9 напряжение +12 В. Допускаемое отклонение его величины у микросхем разных типов различно. В одних случаях оно не более ±5 %, в других достаточно, чтобы напряжение лишь превысило некоторое значение, например 10В. Идентификаторы читают по указанным выше адресам, устанавливая их без учета разряда А9. Обычно этот способ применяют в универсальных программаторах.

Микросхема

Организация

Идентификатор

изготовителя

устройства

AMDAm29F010

128Kx8

01H

20H

AMDAm29F040

512х8

01 Н

A4H

SST 39SF010

128Kx8

0BFH

0B5H

Winbond W29EE011

128Kx8

0DAH

0C1H

Wtnbond W29C020

256Kx8

0DAH

45H

Intel 28F200-T

256Kx8 (128K" 16)

89H

74H (2274H)

Intel 28F200-8

256Kx8 (128Kx16)

89H

75H (2275H)

Intel 28F400-T

512Kx8 (256Kx16)

89H

70H (4470H)

Intel 28F400-B

512Кх8(256К"1в)

89H

71Н (4471Н)

Intel 28F004-T

512Kx8

89H

78Н

Intel 28F004-B

512Kx8

89H

79Н

Intel 28F800-T

1Mx8 (256Kx16)

89H

9СН (889СН)

Intel 28F800-B

1Mx8(256Kx16)

89H

9DH (889DH)


АСЗ большинства микросхем FLASH-памяти воспринимают команды, подаваемые в соответствии с так называемым стандартом JEDEC, хотя есть и исключения. Иногда при модернизации микросхем их систему команд дополняют стандартными кодовыми комбинациями, сохраняя, однако, и старые команды (это необходимо для того, чтобы модернизированные кристаллы могли работать в ранее выпущенных устройствах). Свою систему команд применяет фирма Intel.

Прежде чем подробно рассматривать команды, расскажем немного о подключении FLASH-микросхем. Однотипные микросхемы, как правило, выпускают в корпусах нескольких типов, различающихся расположением, шагом и числом выводов. Нередко предусматривают "зеркальные" варианты, позволяющие устанавливать микросхемы на любой стороне платы, не изменяя топологию печатных проводников.

Номера выводов на приводимых ниже схемах стандартны для микросхем памяти объемом 512 Кбайт в наиболее распространенных 32-выводных корпусах PLCC и PDIP. "Цоколевка" микросхем меньшего объема аналогична, но выводы старших разрядов у них не подключены (например, у Am29F010 свободны 30-й и 1-й).

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

cif-r8o1.gif
Puc.1

Предполагается, что системная шина данных - восьмиразрядная, адреса - 16-разрядная. ПЗУ отведено в адресном пространстве 32 Кбайт, остальную его часть может занимать ОЗУ. Так как объем памяти Am29F040 - 512 Кбайт, предусмотрен регистр страницы FLASH-памяти, управляющий старшими разрядами адреса. Для чтения и записи данных можно воспользоваться следующими простыми процедурами (написанными на языке Pascal):

{Выбор страницы} procedure SetFLASHPage(A:longint);

const PageReg= ; {Здесь указывают адрес регистра DD1 (см. рис. 1) в пространстве ввода/вывода микропроцессорной системы} begin port[PageReg]:=(A shr 15) and $FF;

end:

{Запись во FLASH кода В по адресу А} procedure WriteFLASH(A:longint;B:byte);

begin

SetFLASHPage(A);

mem[A and $7FFF]:=B;

end:

{Чтение из FLASH данных по адресу А} function ReadFLASH(A:longint):byte;

begin

SetFLASHPage(A);

ReadFLASH:=mem(A and $7FFF);

end;

Если необходимо запрограммировать FLASH-микросхему вне устройства, в котором она будет работать, ее можно подключить к персональному компьютеру. Проще всего это сделать, установив в компьютер дополнительную плату параллельного ввода/вывода. Такие платы, например, PCL-731 фирмы Advantech, DIO-48 фирмы ICP DAS или PET-48DIO фирмы ADLink имеются в продаже. Как правило, у них 48 входов/выходов и работают они аналогично двум микросхемам 8255 (КР580ВВ55А) в режиме 0 с теми же информационными и управляющими портами, даже если в действительности таких микросхем в их составе нет. При необходимости плату параллельного ввода/вывода можно изготовить самостоятельно, воспользовавшись статьей Н. Васильева "Расширитель интерфейса PC" ("Радио", 1994, № 6, с. 20, 21).

Для чтения или программирования FLASH-микросхему подключают к портам двух микросхем 8255 по схеме, показанной на рис. 2. Порт РА первой из них использован для ввода/вывода данных, отдельные разряды ее же порта PC - для вывода сигналов управления СЕ, ОЕ и WE. Порты PA, PB и PC второй образуют 24-разрядную шину адреса FLASH-микросхемы. Если достаточна меньшая разрядность этой шины, соответствующее число старших разрядов порта PC не подключают.

cif-r8o2.gif
Рис.2

Порты платы ввода/вывода и вспомогательные константы должны быть описаны в программе следующим образом:

{Адреса портов первой 8255} const PA1=...: {Значение берут из описания применяемой платы ввода/вывода}

PC1=PA1+2;CW1=PA1+3:

{Адреса портов второй 8255} const РА2=...: {Это значение тоже берут из описания применяемой платы ввода/вывода}

РВ2=РА2+1 ;PC2=PA2+2;CW2=PA2+3;

{Даем портам символические имена}

CTRL=PC1; {Управление чтением/ записью}

ADDRO=PA2; {Младший байт адреса}


ADDR1=PB2; {Второй байт адреса}

ADDR2=PC2; {Старшие биты адреса)

DB=PA1; {Шина данных} {Управляющие константы) const AIIOut=$80;{Bce порты на вывод);

Allln=$9В: {Все порты на ввод):

OutData=$8A: {PA, PC - вывод, РВ-ввод};

lnData=$9A; {PA. PB - ввод, PC-вывод);

{Маски разрядов порта CTRL) constCE:=1;

ОЕ:=2;

WE:=4;

StandBy=$FF;

GoRead=not(CE+OE) and $PF:

GoWrite=not(CE+WE) and $FF;

NoWrite=not(OE) and $FF;

А описанные выше процедуры обращения к FLASH-памяти заменяют следующими:

procedure SetFLASHAddr(A:longint);

var AA:array[0..3] of byte absolute A;

begin

port[ADDR0]:=AA[0];

port[ADDR1]:=AA(1];

port[ADDR2]:=AA[21;

end:

procedure WriteFLASH(A:longint:B:byte);

begin

SetFLASHAddr(A);

port[CW1]:=OutData;

port(DB]:=B;

portICTRL]:=GoWrite;

port[CTRL]:=StandBy;

port[CW1]:=lnData;

end;

function ReadFLASH(A:longint):byte;

begin

SetFLASHAddr(A);

port[CTRL]:=GoRead;

ReadFLASH:=port[DB],

port[CTRL]:=StandBy;

end;

Теперь - собственно о программировании FLASH-микросхем. По стандарту JEDEC каждая команда начинается записью кода 0ААН по адресу 5555H. Далее записывают код 55Н по адресу 2АААН и в заключение - код выполняемой операции по адресу 5555Н.

procedure Command(OpCode:byte):

begin

WriteFLASH($5555,$AA);

WriteFLASH($2AAA,$55);

WriteFLASH($5555,OpCode):

end:

Говоря, например, о команде 40Н, мы будем подразумевать именно такую последовательность с числом 40Н в качестве кода операции.

Команда "Читать массив данных".

Код операции - 0F0H.

procedure SetReadArray:

begin Command($F0) end:

После включения питания любая FLASH-микросхема автоматически входит в этот режим и устанавливать его специальной командой нет необходимости. Однако она требуется, например, для возврата из режима чтения идентификаторов. Иногда ее называют командой сброса или начальной установки. Для перевода некоторых микросхем в режим чтения массива достаточно одного цикла записи кода OFOH по любому адресу.

procedure SetReadArray, begin WriteFLASH(0,$F0) end:

Микросхемы фирмы Intel переводят в исходное состояние, записывая по любому адресу код 0FFH.

procedure SetREADArray:{lntel} begin WriteFLASH(0,$FF) end:

Во всех случаях данные читают с помощью функции ReadFLASH:

D:=ReadFLASH(A);

Команда "Программировать". Код

операции - 0А0Н.

procedure ProgFLASH(A:longint:B:byte):

begin

Command($A0):

WriteFLASH(A.D) end;

Следующий за командой 0А0Н цикл записи содержит адрес программируемой ячейки и записываемый в нее код. В большинстве случаев для записи в каждую ячейку требуется подать отдельную команду. Имейте в виду, что подобно обычным РПЗУ, в разрядах программируемой ячейки можно лишь заменять логические единицы нулями. Для выполнения обратной операции требуется, как правило, предварительно стереть содержимое целого блока памяти и повторить программирование всех его ячеек. Учтите, что АСЗ многих FLASH-микросхем не распознают подобные ошибки и сообщают об успешном выполнении операции. Чтобы убедиться в правильности программирования, необходимо контрольное считывание записанных данных.

В микросхемах фирмы Winbond с блоками размером 128 байт программированию любой ячейки автоматически предшествует стирание всех данных содержащего ее блока. Поэтому всегда следует предварительно скопировать блок в оперативную память, внести нужные изменения в копию и запрограммировать заново все 128 байт. Получив команду ОАОН, адрес и первый из программируемых байтов, АСЗ заносит его во внутренний буфер блока и ждет 200 мкс, не начиная программирования. Если за это время будут получены еще одна команда ОАОН и очередной байт, он тоже поступит в буфер, а АСЗ будет ждать следующий еще 300 мкс. Так продолжается до тех пор, пока не будут получены все 128 байт блока или пауза не превысит допустимого значения (300 мкс). После этого АСЗ стирает блок и начинает собственно программирование. Последовательность записи в буфер данных, предназначенных для различных ячеек блока, не имеет значения, но те ячейки, данные для которых не поступили, после программирования будут содержать коды 0FFH.

Существует два способа записи данных для программирования в подобную микросхему. Первый из них (для других обычный) называют программно защищенным. Каждому записываемому байту должна предшествовать команда 0А0Н. Однако защиту можно отключить, подав последовательно команды 80Н и 20H.

procedure SetProtectionOff; {Winbond} begin Command($80):Command($20) end:

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

Для записи данных во FLASH-микро-схему фирмы Intel предусмотрено два равносильных варианта команды. Прежде всего, по любому адресу записывают один из кодов 40Н или 10Н, а затем - программируемый код по нужному адресу.

procedure ProgFLASH(A:longint;B:byte);

{Intel} begin

WriteFLASH(A,$40);

{или WriteFLASH(A,$10);}

WriteFLASH(A,B);

end;

Команда "Стереть всю память".

Эту ответственную операцию АСЗ FLASH-микросхемы начинает, получив последовательность из двух команд - 80Н и 10H.

procedure EraseAII:

begin Command($80);Command($10) end;

Микросхемам фирмы Intel аналогичную команду подают записью по произвольным адресам кодов 20Н и 0D0H.

procedure EraseAII;{lntel} begin

WriteFLASH(0,$20);

WriteFLASH(0,$D0) end:

Стирание всего содержимого памяти занимает от десятков миллисекунд до нескольких секунд. В некоторых микросхемах предусмотрена возможность приостановки этого процесса записью кода 0В0Н по любому адресу. После записи (также по любому адресу) кода 30Н (для микросхем фирмы Intel - 0D0H) стирание продолжится.

Команда "Стереть блок". Чтобы стереть содержимое блока памяти, необходимо подать две команды. Первая из них - 80Н, вторая отличается тем, что ее код операции ЗОН должен быть записан не по адресу 5555Н, а по адресу любой из ячеек стираемого блока.

procedure EraseBlock(A:longint):

begin

Command($80);

WriteFLASH($5555,$AA);

WriteFLASH($2AAA,$55);

WriteFLASH(A,$30);

end:

Команда "Читать идентификаторы". Для перехода в этот режим служит команда 90Н, но иногда требуется последовательность из двух команд - 80Н и 60Н.

type tID=record

Mnf:byte; {Код производителя} Dvc:byte; {Код устройства} end:

procedure ReadlD(var ID:tlD);

begin

Command($90);

{или Command($80);Command($60);}

ID.Mnf:=ReadFLASH(0);

ID.Dvc:=ReadFLASH(1):

SetReadArray, end:

В микросхемы фирмы Intel достаточно записать код 90Н по любому адресу. Выходят из этого режима рассмотренной выше командой "Читать массив данных".

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

Точно узнать момент окончания той или иной операции позволяет считывание регистра состояния АСЗ. FLASH-микросхема выдает на шину данных содержимое этого регистра все время, пока АСЗ занят выполнением процедуры стирания или программирования. Существует два признака того, что процесс не закончен. Первый заключается в том, что значение бита D7 регистра состояния инверсно по отношению к записываемому в тот же бит ячейки памяти значению (во время стирания - равно 0). По завершении операции оно совпадет с записанным. Второй признак - "мерцание" бита D6 (его значение изменяется при каждом чтении регистра, пока операция не завершится).

Как правило, наблюдаются оба признака, однако встречаются и исключения. Например, в микросхемах фирмы Intel "мерцающий" бит отсутствует, а бит D7 во время программирования равен 0 независимо от записываемого кода. Об окончании операции в данном случае свидетельствует D7=1. В микросхемах с блочной записью (например, фирмы Winbond) значение бита D7 инверсно аналогичному биту последнего из кодов, записанных в буфер блока.

Обычно по завершении программирования или стирания FLASH-микросхема автоматически возвращается в режим чтения массива данных, но микросхемам фирмы Intel для этого требуется соответствующая команда.

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

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

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

Утилиту запускают как обычную прикладную программу, указав в качестве параметра имя файла, содержащего коды новой версии BIOS. Она читает этот файл, создавая в ОЗУ массив данных, подлежащих записи во FLASH-память. Затем определяет тип микросхемы и выбирает соответствующие процедуры для работы с ней. После этого начинается стирание старых и запись новых данных, причем в это время программа не может пользоваться никакими функциями BIOS, в том числе и для вывода информации на экран или опроса клавиатуры. Если делать это все-таки необходимо, нужные подпрограммы вводят в состав самой утилиты. После завершения программирования и проверки его правильности обычно следует перезапуск компьютера, и он начинает "новую жизнь" с обновленной BIOS.


Радио 8/2000, с.20-23.