В сегод­няшней статье мы раз­берем­ся, почему мик­росхе­мы 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 ()

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

Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте

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

Вариант 2. Открой один материал

Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.


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

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

    Подписаться

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