В сегод­няшней статье мы раз­берем­ся, почему мик­росхе­мы Macronix отка­зыва­ются работать с самодель­ным прог­рамма­тором на базе Arduino UNO и при чем здесь дли­на про­водов. А заод­но раз­работа­ем методи­ку модели­рова­ния таких схем и авто­мати­зиру­ем тес­тирова­ние чте­ния‑записи.

На рын­ке дос­тупно мно­жес­тво мик­росхем памяти SPI Flash 25-й серии, которые сов­мести­мы меж­ду собой по прин­ципу работы и элек­три­чес­ким парамет­рам. Но, как ока­залось, не все они оди­нако­во хорошо работа­ют с са­модель­ным прог­рамма­тором, соб­ранным на осно­ве кло­на Arduino UNO.

В этой статье мы раз­берем­ся, почему такой прог­рамма­тор отка­зыва­ется работать с чипом MX25L6406E про­изводс­тва Macronix. По ходу дела раз­работа­ем и обос­нуем метод оцен­ки качес­тва работы прог­рамма­тора, про­ведем мно­жес­тво экспе­римен­тов, выд­винем и опро­вер­гнем нес­коль­ко гипотез, пос­тро­им теоре­тичес­кие модели соеди­нитель­ных про­водов.

Еще мы выпол­ним ими­тацию их работы в прог­рамме Quite Universal Circuit Simulator и в кон­це кон­цов най­дем и устра­ним «сла­бое зве­но». Ты уви­дишь, что дли­на соеди­нитель­ных про­водов име­ет зна­чение, но отнюдь не реша­ющее.

 

От полного непонимания к началу диалога

В пре­дыду­щей статье «UNO-прог­рамма­тор для SPI Flash. Про­шива­ем мар­шру­тиза­тор под­ручны­ми средс­тва­ми» я рас­ска­зал о том, как соб­рал прог­рамма­тор, записав скетч frser-duino в клон Arduino UNO, и успешно при­менил его для записи дам­па про­шив­ки мар­шру­тиза­тора в мик­росхе­му Winbond 25Q128FVSG с помощью ути­литы flashrom. К сожале­нию, мар­шру­тиза­тор с новой про­шив­кой не завел­ся, и воз­никла мысль записать про­шив­ку в мик­росхе­му Macronix MX25L6406E, объ­ем памяти которой в точ­ности соот­ветс­тво­вал раз­меру фай­ла с дам­пом. В спе­цифи­кации на этот чип ука­зано, что он работа­ет на нап­ряжени­ях от 2,7 до 3,6 В и все восемь его кон­тактов име­ют те же наз­начения, что и у пре­дыду­щего «паци­ента».

www

Спе­цифи­кация мик­росхе­мы Macronix MX25L6406E дос­тупна на сай­те про­изво­дите­ля.

Я не испы­тывал тре­воги: ну что тут может пой­ти не так? Раз­ве что емкость мик­росхе­мы сос­тавля­ет не 16 Мбайт, а толь­ко 8 Мбайт, но это и к луч­шему — про­цесс зай­мет мень­ше вре­мени. О, как же я оши­бал­ся!

Мне так пон­равилось поль­зовать­ся «кар­трид­жем», изго­тов­ленным из мик­росхе­мы SPI Flash, что изде­лие MX25L6406E я тоже помес­тил на переход­нике SOP8 — DIP8 с кон­такта­ми и уста­новил на панель­ку DIP8 пла­ты прог­рамма­тора с резис­тивны­ми делите­лями для сог­ласова­ния уров­ней сиг­налов. Конс­трук­цию пла­ты тебе напом­нит этот рисунок.

Согласующая плата для подключения трехвольтовой микросхемы SPI Flash к UNO-программатору
Сог­ласу­ющая пла­та для под­клю­чения трех­воль­товой мик­росхе­мы SPI Flash к UNO-прог­рамма­тору

Не ожи­дая никако­го под­воха, я наб­рал коман­ду, что­бы узнать иден­тифика­тор мик­росхе­мы в кон­тек­сте UNO-прог­рамма­тора:

flashrom -p serprog:dev=/dev/ttyUSB0:115200

Но вмес­то ожи­даемых све­дений на экра­не появи­лось сооб­щение об ошиб­ке:

No EEPROM/flash device found

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

Я перечи­тал спе­цифи­кацию MX25L6406E и не нашел ничего нового для себя. Резуль­таты поис­ка в интерне­те тоже не дали готово­го решения. Те, у кого воз­никла такая же проб­лема, в основном сетова­ли на боль­шое количес­тво под­дель­ных чипов и отка­зыва­лись от даль­нейших попыток. Но встре­тилось нес­коль­ко упо­мина­ний о том, что иног­да прог­рамми­рова­ние про­ходит с боль­шей ста­биль­ностью при понижен­ном нап­ряжении. Это уже кое‑что!

Почему резистивный делитель не подходит для питания

Ты можешь спро­сить: а почему бы не понизить нап­ряжение питания с помощью резис­тивно­го делите­ля так, как мы делали для сиг­наль­ных линий? Но это пло­хая идея, и вот почему. Во‑пер­вых, на парамет­ры резис­тивно­го делите­ля боль­шое вли­яние ока­зыва­ет соп­ротив­ление вхо­да наг­рузки, которое в нашем слу­чае не так велико.

Во‑вто­рых, ток питания мик­росхе­мы в режиме записи VCC Program Current сос­тавля­ет, если верить спе­цифи­кации, 20 мА, что на мно­го поряд­ков пре­выша­ет ток сиг­налов. Это не поз­воля­ет исполь­зовать высоко­омные резис­торы в пле­чах делите­ля — они прос­то не обес­печат про­хож­дения необ­ходимо­го тока.

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

Нем­ного понизить нап­ряжение питания про­ще все­го пос­ледова­тель­ным вклю­чени­ем на линии VCC диода в пря­мом нап­равле­нии. Я под­клю­чил диод 1N4148, и нап­ряжение с 3,3 В упа­ло до 2,9 В. При этом оно все еще находит­ся в допус­тимом диапа­зоне, который ука­зан в спе­цифи­кации.

В ответ на пов­торный ввод коман­ды я уви­дел такие стро­ки:

...

Found Macronix flash chip "MX25L6405" (8192 kB, SPI) on serprog.

Found Macronix flash chip "MX25L6406E/MX25L6408E" (8192 kB, SPI) on serprog.

Found Macronix flash chip "MX25L6436E/MX25L6445E/MX25L6465E/MX25L6473E" (8192 kB, SPI) on serprog.

Multiple flash chip definition match the detected chip(s): "MX25L6405","MX25L6406E/MX25L6408E","MX25L6436E/MX25L6445E/MX25L6465E/MX25L6473E".

Please specify which chip definition to use with the -c option.

Ну вот, дело сдви­нулось с мер­твой точ­ки! Про­читан­ному прог­рамма­тором иден­тифика­тору мик­росхе­мы удов­летво­ряют нес­коль­ко моделей чипов, и нам пред­лага­ется ука­зать кон­крет­ный модель­ный ряд с помощью парамет­ра -c. В нашем слу­чае под­ходит вто­рой из пред­ложен­ных вари­антов, поэто­му коман­ду записи фай­ла zte_h118n.bin, раз­мер которо­го сов­пада­ет с емкостью мик­росхе­мы, мож­но сфор­мулиро­вать так:

flashrom -p serprog:dev=/dev/ttyUSB0:115200 -c "MX25L6406E/MX25L6408E" -w zte_h118n.bin

На экра­не побежа­ли информа­цион­ные сооб­щения выпол­няемо­го про­цес­са, но завер­шился он неуда­чей:

...

Verifying flash... FAILED at 0x00000002!

Expected = 0x00, Found = 0x01, failed byte count from 0x00000000-0x007fffff: 0x15a53

Your flash chip is in an unknown state.

Вот так, при свер­ке было обна­руже­но 88 659 рас­хожде­ний, а мик­росхе­ма переш­ла в неоп­ределен­ное сос­тояние.

 

Как слышно? Прием!

Я про­бовал пов­торить опе­рацию, но без осо­бых успе­хов. Надо было что‑то менять в устрой­стве этой экспе­римен­таль­ной уста­нов­ки. Поп­робовал под­клю­чить еще один диод по линии питания, но пос­ле это­го мик­росхе­ма сно­ва перес­тала опре­делять­ся.

Мо­жет быть, понизить нап­ряжение не питания, а информа­цион­ных сиг­налов? Давай поп­робу­ем! Тем более что для это­го нам не при­дет­ся вно­сить сущес­твен­ных изме­нений в конс­трук­цию. У нас уже есть три «понизи­теля» нап­ряжения на резис­тивных делите­лях. Для ясности схе­му одно­го из них я показал на рисун­ке.

Ес­ли уве­личи­вать соп­ротив­ление резис­тора R1, то нап­ряжение сиг­нала на выходе будет умень­шать­ся. А для уве­личе­ния соп­ротив­ления дос­таточ­но пос­ледова­тель­но к R1 под­клю­чить резис­тор R3. Это мож­но сде­лать даже без пай­ки, прос­то скру­тив один вывод резис­тора R3 c кон­цом соеди­нитель­ного про­вода, а дру­гой вывод исполь­зовать в качес­тве ште­кера.

Увеличение сопротивления плеча резистивного делителя
Уве­личе­ние соп­ротив­ления пле­ча резис­тивно­го делите­ля

Что­бы сни­зить риск пов­режде­ния мик­росхе­мы памяти во вре­мя экспе­римен­тов, я решил сна­чала добить­ся устой­чивого чте­ния, а к записи перей­ти поз­же. И вот, убрав диод с линии питания и под­клю­чив на линии SCK (вывод 13 UNO-прог­рамма­тора) и MOSI (вывод 11 UNO-прог­рамма­тора) по одно­му добавоч­ному резис­тору соп­ротив­лени­ем 2000 Ом, я выпол­нил чте­ние содер­жимого мик­росхе­мы памяти.

info

Счи­тыва­ние содер­жимого мик­росхе­мы памяти было воз­можно толь­ко в том слу­чае, если добавоч­ные резис­торы раз­мещались на кон­це про­вода, под­клю­чен­ного к UNO-прог­рамма­тору. Если перевер­нуть про­вод и помес­тить резис­тор на сто­роне пла­ты SPI Flash, то прог­рамма­тор вол­шебным обра­зом перес­тает обна­ружи­вать мик­росхе­му.

Но как узнать, было ли это чте­ние безоши­боч­ным, если дан­ные в мик­росхе­му были записа­ны с ошиб­кой? Срав­нение с исходным фай­лом в этом слу­чае ничего не даст. Тог­да я решил выпол­нить чте­ние еще раз и срав­нить меж­ду собой получен­ные резуль­таты. Если они сов­падут, то цель дос­тигну­та. А если нет, то за оцен­ку количес­тва оши­бок чте­ния мож­но при­нять величи­ну d/2, где количес­тво рас­хожде­ний d зна­читель­но мень­ше раз­мера фай­ла (пос­мотри на рисунок).

Количество ошибок e при чтении и число расхождений d при сравнении
Ко­личес­тво оши­бок e при чте­нии и чис­ло рас­хожде­ний d при срав­нении

У меня получи­лось d = 399 858 рас­хожде­ний, что соот­ветс­тву­ет 199 929 ошиб­кам, или ошиб­кам в (199 929 / 8 388 608) × 100 = 2,38% байт. Нас­коль­ко мож­но доверять такой оцен­ке и нас­коль­ко она ста­биль­на? Может быть, в сле­дующий раз будет 25%, а потом 0,01%?

 

Обратимся к статистике

Что­бы не гадать на кофей­ной гуще, я решил при­бег­нуть к ста­тис­тике. Для это­го написал на Python прог­рамму compare.py, которая побай­тово срав­нива­ет два фай­ла и под­счи­тыва­ет количес­тво обна­ружен­ных раз­личий.

Вот лис­тинг прог­раммы compare.py для побай­тового срав­нения двух фай­лов.

import sys
if len (sys.argv) != 3:
print ("Binary files comparison.")
print ("Usage: %s file1 file2" % sys.argv[0])
quit ()
print ("Files comparison: %s <---> %s" % (sys.argv[1], sys.argv[2]))
bufsize = 4096
diffs = 0
size = 0
f1 = open (sys.argv[1], 'rb')
f2 = open (sys.argv[2], 'rb')
n = 1
while n > 0:
b1 = f1.read (bufsize)
b2 = f2.read (bufsize)
n = min (len (b1), len (b2))
if n > 0:
size += n
for i in range (0, n):
if b1[i] != b2[i]:
diffs += 1
print ("Compared size : %d" % size)
print ("Differences : %d (%.2f%%)" % (diffs, round(diffs / size * 100, 2)))
f2.close ()
f1.close ()

Продолжение доступно только участникам

Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».

Присоединяйся к сообществу «Xakep.ru»!

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии