Programátor SPI FlashROM na paralelní port

      23.3.2008 Jelikož jsem takový šťoura, co se rád vrtá v kódech BIOSů počítačů a nedá si pokoj dokud obrazovka nadobro nezčerná :), tak také potřebuju mít možnost FlashROM ručně přeprogramovat. Dříve jsem to u paralelních flashek, které byli na desce v DIL32 nebo PLCC32 patici, řešil jednoduše hotflashem, kdy jsem měl v záloze připravený druhý čip s funkčním BIOSem. Ten jsem strčil do patice, za běhu vyměnil za špatně naprogramovaný čip a přeprogramoval.
      Teď jsem se na své nové základní desce Gigabyte GA-P31-DS3L setkal s novým typem paměti - vysokorychlostní sériovou SPI FlashROM Winbond 25X40VSIG v SMD pouzdru SOIC-8, která je připájená přímo na desku. Jižní můstky intel ICHx již delší dobu podporují obě varianty FWH a SPI. Pomocí určitých registrů a pinů chipsetu lze vybírat, které z rozhraní se primárně použije pro BIOS. Díky tomu, že se u SMD součástky ušetří desetník za patici, celkově klesnou náklady na výrobu a manažeři tak mají více $ na lepší auta a kurvy ;). Nám šťouralům pak nezbývá, než vzít do ruky pájku... Aby se s tou flash dalo rozumně pracovat, připájel jsem ji na precizní DIL8 patici. Druhou patici DIL8 jsem pak připájel na základní desku. Protože bych se na daném místě s pájkou kolem patice (naproti SATA konektoru) už nedostal, nechal jsem ji plandat na dvou kouskách 4-žilové kšandy:

SPI FlashROM SOIC-8 v DIL8 patici

      Následovala výroba programátoru. K připojení SPI zařízení k PC však stačí obyčejný paralelní port, 5 drátů, pár odporů a konektory. Zapojení vychází z programovacího SPI kabelu typu BSD na programování mikrokontrolérů Atmel AVR. Zmiňovaná paměť W25X40V je určená pro napájecí napětí 3,3V, proto jsem datové linky oddělil odpory, aby netrpěla vyšším napětím z LPT. Zároveň odpory plní funkci tlumení, bez nich totiž na delším (cca 1,5m) plochém kabelu bez stínicích linek mezi signálovými docházelo k přeslechům a tím chybnému přenosu dat. Zajímavé, že AVRka mi se stejným káblem fungujou bez potíží. K napájení jsem použil externí zdroj.

SPI FlashROM programator - schema

Celé to pak splácané na univerzálním plošňáku vypadá nějako takhle:

SPI FlashROM programator - hardware

      Další už je jen věc software, který jsem si musel napsat. Nejprve bylo třeba naprogramovat nejnižší vrstvu, která pracuje s registry LPT a nastavuje/čte požadované úrovně na daných SPI linkách. K tomuto tématu můžu odkázat na knížku Burkhard Kainka - Využití rozhraní PC z nakladatelství HEL 1997, z které jsem se kdysi učil, jak rozblikat svoji první LEDku na LPT. Ale i na Internetu je zdrojů k tomuto tématu víc než dost.
      Dále bych něco řekl k samotné sběrnici SPI. Ta sestává ze tří linek: SCK - Serial ClocK (až desítky MHz), MISO - Master Input Slave Output, MOSI - Master Output Slave Input a v tomto případě je zde ještě pomocná řídicí linka CS# - Chip Select. Komunikace typicky probíhá mezi dvěma zařízeními, z nichž jedno je Master (v tomto případě PC), který ovládá hodiny SCK (zde je klidová úroveň log. 0) a posílá příkazy/data na linku MOSI a přitom zároveň čte data z linky MISO. Slave zařízení (v tomto případě paměť) pak reaguje na hodiny SCK tím, že při sestupné hraně hodin odešle bit na linku MISO a při vzestupné hraně hodin čte bit z linky MOSI. Byte se odesílá v pořadí MSB jako první, LSB jako poslední. Po dokončení přenosu Master vrací hodiny na klidovou úroveň (log. 0). Sběrnice je tedy narozdíl třeba od I2C plně duplexní. Slave zařízení se neidentifikují žádnou adresou. Aby bylo možno připojit na linky SPI více Slave zařízení, musí být Master s každým zařízením propojen samostatnou řídicí linkou CS#, která úrovní log. 0 aktivuje jedno z n Slave zařízení (ostatní mají SPI výstupy ve stavu vysoké impedance, aby neovlivňovali probíhající komunikaci (SPI zařízení mají 3-stavové výstupy, nejsou potřeba pull-upy). V případě SPI Flash paměti se CS# používá pro začátek a konec rámce, takže ho nelze jednoduše spojit se zemí. Více napoví následující obrázek jak probíhá čtení z paměti:

SPI FlashROM read command

      Nejprve Master zahájí rámec přechodem CS# do log. 0 a tím se aktivuje paměť. Pak Master spustí hodiny a vysílá první Byte příkaz 3h - čtení z paměti. Paměť zjišťuje, cože to po ní chceme a ví, že musí ještě dostat adresu. Tu posílá master v následujících 3 Bytech. Paměť adresu dekóduje a okamžitě začíná v dalším Byte posílat data. Pokud Master požaduje data i z následujících adres, nechá spuštěné hodiny a paměť automaticky inkrementuje adresu. Další příchozí data od Mastera se ignorují. Konec rámce pak Master ukončí přechodem hodin do klidového stavu log. 0 a přechodem CS# do klidového stavu log. 1.
      Paměť podporuje určitou standardní množinu příkazů, mezi něž patří třeba čtení, zápis, mazání stránky, mazání sektoru, mazaní celého čipu, zamknutí, odemknutí, identifikace výrobce a typu čipu JEDEC ID, čtení stavového registru, ... Některé příkazy jsou jednobajtové, jiné mají parametry a data. Na některé paměť odpovídá vysláním dat, na jiné ne. Další podrobnosti viz datasheet ke konkrétní paměti.
      Dalším krokem bylo tedy napsání funkcí pro odesílání a příjem Bytů a bloků dat a nakonec funkce pro zpracování jednotlivých příkazů Flash paměti. Současná verze programu umožňuje identifikovat typ paměti /i , číst a zobrazit blok dat dané velikosti od dané adresy /r, přečíst celou paměť do souboru /d, naprogramovat celou paměť ze souboru /p, smazat celou paměť /e a odemknout write protect bity /u. Dalšími parametry /l= lze nastavit bázovou adresu LPT a /d= prodloužení doby SCK pulsu v mikrosekundách (vyjma Windowsí verze, kde není k dispozici časovač s vyšším rozlišením jak 1 ms). V balíčku ke stažení jsou 3 verze pro DOS, Windows a Linux.
      Vzhledem k limitované rychlosti LPT a sériovému způsobu přenosu trvá čtení nebo zápis desítky sekund až minuty. Doba mazání čipu závisí na rychlosti interních mechanismů v paměti a trvá zhruba jednotky až desítky sekund. Rychlejší komunikace by šlo dosáhnout pomocí mikrokontroléru, nejlépe s hardwarovým SPI řadičem, který by s PC komunikoval buď 8-bitově po LPT nebo po USB. Ukázka akce programu s pamětí ST M25P32:


SPI FlashROM Programmer 1.0 (C) 2008 by Martin Rehak; rayer^seznam*cz
Compiled by GCC 3.4.5 (mingw special) at 18:41:28, Mar 26 2008

SPI connected to LPT port at I/O base address: 378h, SCK pulse width: t+0us
FlashROM JEDEC ID, type: 202016h
ST Microelectronic M25P32 (4MB)
Reading sector at: 00396000h (89%)

      21.7.2010 Ve spolupráci s lidmi z projektů Flashrom a Coreboot, kterým jsem poskytl zdrojový kód SPIPGM, byla přidána podpora mojeho SPI programátoru do tohoto univerzálního flashovacího nástroje. Zároveň byla také vytvořena i DOSová verze (kompilovaná v DJGPP), kterou si můžete stáhnout zde. Uživatelé flashromu tak získali možnost programování přes LPT port a uživatelé SPIPGM zas širokou podporu různých typů flash pamětí. SPI programátor na LPT portu se vybere přepínačem:
flashrom -p rayer_spi [další příkazy]
Udělal jsem srovnávací test s 4MB FlashROM pamětí ST M25P32:

program čtení mazání
SPIPGM 2:41 0:21 (bez verifikace)
flashrom 2:44 3:34 (s verifikací)

Rychlost čtení je tedy plně srovnatelná, zatímco mazání je ve flashromu pomalejší, protože obsahuje i nucenou verifikaci (tedy kompletní čtení). Navíc já používám jediný příkaz chip erase. Stávající verze flashromu zatím neobsahuje žádný indikátor průběhu prováděných operací, takže nepanikařte a zajděte si mezitím na kafe :)

      19.3.2011 Abych se nemusel stydět za ten bastl vyfocený výše (navíc na neprakticky velké desce), rozhodl jsem se postavit si nový SPI FlashROM programátor. Hlavním důvodem však byla potřeba umět pohodlně programovat i SMD paměti v pouzdru SOIC-8, které jsou v současnosti nejrozšířenější. Nastal tedy problém, kde sehnat odpovídající ZIF patici, což se ukázalo jako tvrdý oříšek. Patice vyrábí např. taiwanská společnost LOTES Co., Ltd., která nemá u nás distributora, nebo je lze koupit min. po 1000 ks. u americké firmy Larsen Associates či za 48$ hotovou redukci na DigiKey.

Advantech AIMB-766 ZIF socket for BIOS
bílá vrána: Advantech AIMB-766 se ZIF soketem

      Na tyto podmínky jsem nechtěl přistoupit a tak jsem bádal, jak si tu ZIFku vyrobit doma na koleně. Zkoumal jsem své zásoby různých počítačových konektorů a vybral 3 potenciální kandidáty: RJ-45 zásuvku z ethernet karty, DIMM slot, a PCI slot. Jako nejlepší se ukázal PCI slot, protože má dlouhá a pružná pérka a po rozříznutí se nerozsype. Z PCI slotu jsem uřízl kousek s 2 x 4 piny a ten pak rozřízl na půl. Částečně jsem také ubrousil vršek konektoru tak, aby konce pérek vylezly ven. Při této operaci jsem pérka z konektoru vytáhl a pak zase zastrčil zpět. Peánem to jde docela snadno. Na plošňáku jsou obě poloviny konektoru od sebe vzdálené na šířku čipu, tj. asi 5,5 mm i s rezervou a tím vymezují jeho horizontální polohu. Po přiložení na pérka se čip zatlačí dolů tak, že plastové přepážky mezi pérky jednoznačně vymezují vertikální polohu nožiček a v této poloze se čip zajistí nasunutím "C" profilu z plexiskla. Průhyb pérek je asi o 1 mm dolů. Zakládání čipu chce trochu cvik, ale teď už to umím docela rychle.
      Plošňák jsem vyrobil rychlou metodou z hlavy pomocí lihové fixy a vyleptal ve FeCl3. Hodnoty odporů pro linky MISO, MOSI, SCK a CS# jsem zvýšil na 220 Ω. O blokování napájení se stará 100µF tantal a 3 keramiky. Na desku jsem dal také 3,3V LDO stabilizátor LE33CZ. Napájení pro něj lze získat např. z PC zdroje, USB portu nebo PS/2 portu. Programátor mi funguje bez problémů na plnou rychlost. Zkoušel jsem naprogramovat a zverifikovat několik čipů a neobjevila se žádná neshoda (s dřívějším bastlem se mi to občas stávalo). Na digitálním osciloskopu jsem ještě zkontroloval průběh signálu SCK, na jehož hranách se vyskytují zákmity max. 0,4 V, což je v pohodě. Pokud bych chtěl být perfekcionista, přidal bych na desku ještě oddělovací 3,3V buffer, který by pomohl některým PC s neduživým LPT, ale zatím jsem neměl problém. SPIPGM fungoval i na novém kompu v práci, kde je PCI-E adaptér s 2x COM a 1x LPT na vysoké I/O adrese E800h. Zde je ke stažení aktuální verze SPIPGM 1.9c.

SPIPGM top SPIPGM bottom SPIPGM with chip SPIPGM with chip SCK line signal oscillogram

      24.10.2014 Už dříve jsem dostal několik dotazů jak naprogramovat 1,8V paměti a tak jsem dotyčné odkázal, ať si vyberou nějaký voltage level translator např. od Texas Instruments. Teď jsem se dostal sám do situace, kdy jsem potřeboval přeflashnout paměť Macronix MX25U6435F, když jsem si při pokusech s Corebootem bricknul své 86Duino ZERO. V práci jsem našel v šuplíku vzorek převodníku TXS0108E pouzdru TSSOP20 (pro bastlení zrovna nic moc), ale říkal jsem si, že ho aspoň vyzkouším.
      Jedná se o převodník s automatickou detekcí směru toku, ke kterému stačí připojit 2 napájení a zapnout enable. Uříznul jsem si kousek univerzální destičky a švába na ni přibastlil pomocí tenkých drátků. Byla to docela piplačka. Napájecí napětí 1,8 V jsem si vytvořil z 5 V pomocí malého LDO TLV70018. Datové linky z LPT jsem připojil na port B a stávající destičku programátoru s paměti k portu A. Oměřil jsem klidové hodnoty bez připojené paměti a vše se zdálo být v pořádku. Tak jsem to připojil k paměti a k PC, ale detekce se paměti nezdařila. Vzal jsem si tedy k ruce digitální osciloskop a zjistil, že se obvod chová poněkud nevyzpytatelně - např. signál SCK měl na 1,8V straně A první 3 pulzy amplitudy asi 1,2 V a teprve další měly správně 1,8 V. MISO zas na výstupu převodníku B (na straně LPT) nedosahovalo v log. 0 dostatečně nízké napětí. I když jsem linku portu A natvrdo uzemnil, bylo na výstupu B asi 0,5 V a pokud sem ho stáhnul přes odpor 220 Ω, tak už bylo na výstupu B 2,6 V, což lze těžko brát za log. 0. Pokud jsem výstup B odpojil od LPT, spadlo napětí na 35 mV. Jelikož vstup LPT tahá nahoru, tak to vypadá, že převodník asi nemá dostatečně tvrdé výstupy. Nakonec jsem po další hodině laborování švába naštvaně odpájel a zahodil. Možná, že by byl vhodnější obvod TXB0104, (případně dvojice jednosměrných translátorů), ale ten jsem k dispozici neměl a nechtělo se mi na něj čekat.
      Jak se ukazuje, někdy ta jednodušší řešení fungují lépe a tak jsem se vrátil k pasivnímu omezení napětí z LPT pomocí odporů a diod. Diody jsem dopájel na stávající destičku programátoru, viz aktualizované schéma výše. Výstup paměti MISO jsem zvednul pomocí kaskády 2 tranzistorů BC547.

redukce pro 1,8V SPI FlashROM - schema

Dohromady s připojeným programátorem to pak vypadá takto:

redukce pro 1,8V SPI FlashROM s programátorem

S tímto zapojením jsem už neměl problém paměť naprogramovat. Ještě bych upozornil na poslední aktualizaci mého programu SPIPGM 2.22, kde jsem přidal experimentální podporu 32-bitového adresního režimu pro paměti větší než 16 MB.



Zpět

Aktualizováno 9.12.2014 v 2:49