Oprogramowanie mikrokontrolera niezbędne do działania komputera SDC_Zero jest dostępne na portalu EP w pliku SDC0.zip.
SDC_Zero składa się z taniej i popularnej płytki uruchomieniowej STM32F103C8T6 Minimum Development Board, znanej pod nazwą BluePill, oraz mikroprocesora typu 65C02 lub 80C85. Elementy te są umieszczone na popularnej płytce stykowe typu „830”. Do wykonania komputera potrzeba ponadto ok. 40 przewodów połączeniowych (w tym jednego zakończonego z jednej strony wtykiem, a z drugiej – gniazdem) i dwóch kondensatorów ceramicznych 100 nF. W wersji z procesorem 65C02 potrzebny jest ponadto rezystor 10 kΩ, a przy użycia procesora 8085 w wersji NMOS – kilka rezystorów 4,7 kΩ i dowolnych diod prostowniczych (np. 1N4148 lub 1N5819). Wygląd zmontowanego komputera SDC_Zero pokazano na pierszej fotografii – otwierającej artykuł.
Ograniczenie repertuaru dostępnych procesorów w porównaniu do SDC_One wynika z niewielkiej liczby wyprowadzeń użytego na płytce BluePill mikrokontrolera STM32F103C8T6. Do dyspozycji jest tu tylko 28 sygnałów, które mogą być wykorzystane do współpracy z szyną procesora. Taka liczba sygnałów wystarcza do obsługi bardzo prostej szyny mikroprocesora 65C02 lub bardziej złożonej, lecz multipleksowanej szyny 80C85.
Zbudowany w ten sposób komputer jest wyposażony w 16 kB pamięci RAM i 64 kB pamięci ROM, co umożliwia uruchomienie na nim np. interpretera języka Basic. Jako terminal służy komputer PC z programem TeraTerm lub podobnym. SDC_Zero jest połączony z komputerem PC przy użyciu kabla USB, zapewniającego zasilanie oraz komunikację. Oprogramowanie urządzenia realizuje złożone urządzenie USB, udostępniające dwa wirtualne porty szeregowe – jeden do współpracy z monitorem sprzętu, drugi do komunikacji z komputerem docelowym.
Monitor sprzętu umożliwia pełne sterowanie komputerem na poziomie szyny procesora, w tym:
- inicjowanie (RESET) i generowanie przebiegu zegarowego,
- wyświetlanie i edycję zawartości pamięci,
- ładowanie do pamięci programów w postaci plików Intel HEX i Motorola S-record,
- pracę krokową na poziomie cykli szyny lub instrukcji z wyświetlaniem wykonywanych transferów i deasemblacją instrukcji,
- pracę ciągłą z opcjonalnym pułapkowaniem i gromadzeniem śladu wykonania,
- programowanie pamięci ROM komputera docelowego poprzez kopiowanie zawartości pamięci RAM.
Dzięki takiej funkcjonalności komputer może być używany jako narzędzie dydaktyczne – do demonstrowania działania procesora (w tym przebiegu wykonania instrukcji, adresowania pamięci, operacji stosowych i obsługi przerwań) oraz do nauki programowania asemblerowego.
Schematy
Linie portów mikrokontrolera STM32F103C umieszczonego na płytce BluePill, które mogą być użyte do komunikacji z procesorem komputera SDC_One, to PA0..10, PA15, PB0..15 i PC14..15. Pozostałe linie służą do programowania mikrokontrolera i do komunikacji przez interfejs USB. Linia PB2 mikrokontrolera jest dostępna tylko na złączu BOOT1, a dostęp do niej wymaga wprowadzenia drobnej modyfikacji na płytce.
Na schematach na rysunkach 2 i 3 pokazano połączenia linii mikroprocesorów. Komputer został zaprojektowany głównie do współpracy z mikroprocesorami wykonanymi w technologii CMOS i zasilanymi napięciem 3,3 V. Połączenia z portami mikrokontrolera zostały zaplanowane tak, by zminimalizować liczbę elementów dopasowujących w przypadku zastosowania w komputerze mikroprocesora z zasilaniem 5 V. Niektóre linie mają wymuszone stałe poziomy logiczne poprzez połączenie z linią zasilania bezpośrednio lub przez rezystor. Linia RDY mikrokontrolera 65C02 musi być dołączona do zasilania przez rezystor rzędu 10 kΩ.
W komputerze nie może być użyty mikrokontroler 6502 wykonany w technologii NMOS z powodu zastosowania w nim struktur dynamicznych uniemożliwiających dłuższe wstrzymanie cyklu szyny.
W wersji z procesorem 80C85, w przypadku niedostępności wersji CMOS, mogącej pracować z zasilaniem 3,3 V, można użyć mikroprocesora NMOS z zasilaniem 5 V, jednak niezbędne będzie wtedy dodanie szeregowych rezystorów zabezpieczających o wartości 4,7 kΩ na połączeniach procesora z liniami PA0, PA1, PA2, PB0, PB1 i PB5 mikrokontrolera (pozostałe linie portów albo są używane jako wyjścia, albo tolerują poziomy logiczne 5 V).
Modyfikacja płytki BluePill
Przed przystąpieniem do montażu komputera należy poddać niewielkim modyfikacjom płytkę BluePill. Ponieważ komputer używa linii PB2, która na płytce BluePill jest połączona przez rezystor szeregowy R4 (100 kΩ, rozmiar 0603) ze złączem zwór konfiguracyjnych, niezbędne jest zastąpienie go rezystorem o wartości nieprzekraczającej 10 kΩ lub zwarcie go krótkim odcinkiem cienkiego drutu (np. kynar). Ponadto dla wygody użytkownika warto wymienić rezystory szeregowe diod LED R1 i R5 (typowo 510R) na rezystory o wartości 2..3 kΩ, by zredukować jasność świecenia diod.
Programowanie mikrokontrolera
Mikrokontroler STM32F103 umieszczony na płytce BluePill może być programowany przez interfejs SWD przy użyciu interfejsu ST-Link (np. z płytki serii Nucleo lub Discovery) lub innego interfejsu SWD. Jeśli nie dysponujemy programatorem z interfejsem SWD, możemy wgrać oprogramowanie do pamięci mikrokontrolera, korzystając z wbudowanego bootloadera mikrokontrolera.
Programowanie przy użyciu interfejsu ST-Link
W celu zaprogramowania mikrokontrolera przy użyciu interfejsu SWD z płytki Nucleo należy:
- Usunąć z płytki Nucleo zwory łączące interfejs SWD z mikrokontrolerem umieszczonym na płytce Nucleo.
- Połączyć cztery linie dostępne na złączu programowania płytki BluePill z odpowiednimi złączami płytki Nucleo; linię 3,3 V należy połączyć z jedną z dostępnych linii zasilania 3,3 V na płytce Nucleo, a GND, SWDIO i SWCLK – ze złączem ST-Link.
- Uruchomić program ST-Link Utility, a następnie załadować plik sdc0_65.bin lub sdc0_85.bin, stosownie do typu używanego mikroprocesora.
- Nacisnąć przycisk Program-Verify.
Programowanie mikrokontrolera przy użyciu wbudowanego bootloadera
Ponieważ bootloader korzysta z linii PA9 i PA10, programowanie musi nastąpić przed połączeniem płytki BluePill z mikroprocesorem naszego komputera. Do zaprogramowania płytki potrzebujemy interfejsu USB-UART z liniami UART na poziomach logicznych 3,3 V. Podczas programowania możemy zasilić płytkę z interfejsu USB-UART, doprowadzając napięcie 3,3 V do jednego ze styków 3,3 V płytki BluePill. Do programowania mikrokontrolera należy użyć programu Flash Loader Demonstrator, udostępnianego przez ST Microelectronics na witrynie internetowej (plik zawierający program nosi nazwę STSW-MCU005.zip).
W celu zaprogramowania mikeokontrolera przy użyciu bootloadera należy:
- Połączyć masę z wyjście zasilania 3,3 V modułu USB-UART z masą i zasilaniem 3,3 V płytki BluePill.
- Połączyć wyjście TX modułu z linią PA10 mikrokontrolera, a wejście RX – z linią PA9.
- Ustawić zworę BOOT0 w pozycję 1, a zworę BOOT1 w pozycję 0.
Po uruchomieniu programu Flash Loader Demonstrator wybrać właściwy interfejs szeregowy (numer portu COM przypisany do używanego interfejsu możemy sprawdzić w menedżerze urządzeń), pozostawiając wartości domyślne pozostałych ustawień. Po pomyślnym nawiązaniu komunikacji przechodzimy przez kilka kolejnych dialogów z informacjami o stanie układu, a następnie w dialogu programowania należy wybrać plik sdc0_65.bin lub sdc0_85.bin, stosownie do typu używanego mikroprocesora i nacisnąć przycisk Next.
Po zaprogramowaniu mikrokontrolera należy przestawić zworę BOOT0 w pozycję 0 i usunąć zworę Boot1, tak by nie wpływała ona na stan linii PB2, używanej do współpracy z mikroprocesorem
Montaż komputera
Montaż SDC_Zero rozpoczynamy od umieszczenia na skraju płytki stykowej płytki BluePill, orientując ją złączem microUSB na zewnątrz płytki stykowej. Wyprowadzenia GND i 3,3 V płytki BluePill łączymy z obiema szynami zasilania płytki stykowej. Jeżeli używamy mikrokontrolera zasilanego napięciem 5 V, zamiast wyjścia 3,3 V łączymy z szyną zasilania wyjście 5 V płytki BluePill.
Wersja z 65C02
Aktualna dokumentacja mikroprocesora jest dostępna u producenta – westerndesigncenter.com. Mikrokontroler umieszczamy na płytce stykowej, pozostawiając ok. 10 rzędów styków wolnych pomiędzy płytką BluePill i mikrokontrolerem, orientując mikrokontroler wycięciem (wyprowadzeniami 1 i 40) w stronę płytki BluePill. Wykonujemy połączenia zasilania i wejść mikrokontrolera zwartych z liniami zasilania lub masy i łączymy wejście RDY poprzez rezystor 10 kV z dodatnim biegunem zasilania. Na szynie zasilania, w pobliżu doprowadzenia bieguna dodatniego i masy do mikrokontrolera, umieszczamy kondensatory 100 nF. Następnie wykonujemy połączenia pomiędzy mikroprocesorem i BluePill w następującej kolejności (wynikającej z topologii połączeń i wygody ich prowadzenia):
- szyna danych D0…D7 z PA0…PA7,
- IRQB z PC14, NMIB z PC15,
- linie adresu A3…A9 z PB3…PB9,
- linie adresu A12…A15 z PB12…PB15,
- linie adresu A0, A1, A10, A11 z PB0, PB1, PB10, PB11,
- linie RWB, SYNC, RESB, PHI2 z PA8, PA9, PA10 i PA15,
- linia adresu A2 do PB2 – środkowy styk zwory BOOT1, przy przycisku RESET na płytce BluePill.
Wersja z 80C85
Mikrokontroler umieszczamy na płytce stykowej, pozostawiając ok. 10 rzędów styków wolnych pomiędzy płytką BluePill i mikrokontrolerem, orientując mikrokontroler wyprowadzeniami 20 i 21 w stronę płytki BluePill (wycięciem w kierunku przeciwnym do płytki). Wykonujemy połączenia zasilania i wejść mikrokontrolera zwartych z liniami masy (INTR, HOLD). Na szynie zasilania, w pobliżu doprowadzenia bieguna dodatniego i masy do mikrokontrolera, umieszczamy kondensatory 100 nF. Następnie wykonujemy połączenia pomiędzy mikroprocesorem i BluePill w następującej kolejności:
- szyna adresowa A8…A15 z PB8…PA15,
- linie adresu/danych AD0, AD1, AD3…AD7 z PB0, PB1, PB3…PB7,
- wszystkie linie sterowania i stanu wg tabeli 1,
- linia adresu A2 do PB2 – środkowy styk zwory BOOT1, przy przycisku RESET na płytce BluePill.
Użytkowanie SDC_Zero
Do działań z komputerem potrzebny jest program emulatora terminalu działający na komputerze PC. W roli tej dobrze sprawdza się np. popularny TeraTerm. Komputer jest widoczny jako dwa wirtualne porty szeregowe, z których pierwszy służy do komunikacji z monitorem sprzętu, a drugi – do komunikacji z komputerem docelowym.
Monitor sprzętu
Monitor sprzętu służy do sterowania pracą komputera. Umożliwia on m.in.:
- inicjowanie procesora sygnałem RESET,
- pracę krokową mikroprocesora w cyklach szyny lub cyklach instrukcyjnych,
- pracę ciągłą z opcjonalnym pułapkowaniem i gromadzeniem śladu,
- przeglądanie i edycję zawartości pamięci,
- ładowanie do pamięci programów poprzez przeciągnięcie pliku HEX do okna monitora sprzętu,
- programowanie dostępnej dla procesora pamięci Flash zawartością pamięci RAM.
Interakcja z monitorem odbywa się przez terminal przy użyciu poleceń wpisywanych z klawiatury. Monitor umożliwia przywoływanie kilku ostatnich poleceń i ich edycję. Monitor jest napisany w konwencji maszyny stosowej – argumenty poprzedzają nazwę polecenia. Argumenty poleceń są liczbami; mogą one być podawane w postaci dziesiętnej, ósemkowej, szesnastkowej lub binarnej, zgodnej ze składnią języka C. Najważniejsze polecenia monitora sprzętu zestawiono w tabeli 2.
Wybrane polecenia monitora, w tym polecenie przeglądania pamięci (md) i pracy krokowej (si, sc), są automatycznie powtarzane po naciśnięciu klawisza Enter, bez potrzeby powtórnego wpisywania polecenia (rysunek 4).
Pamięć
Komputer docelowy dysponuje pamięcią RAM o pojemności 16 kB i pamięcią Flash o pojemności 64 kB. Obie pamięci są udostępniane przez mikrokontroler STM32F103. Ponieważ mikroprocesory używane w SDC_Zero mają przestrzeń adresową o wielkości 64 kB, równocześnie mogą one mieć dostęp do 16 kB RAM i 48 kB ROM. W SDC_Zero przyjęto następujące zasady dostępu do pamięci:
- Jeśli pamięć Flash nie jest pusta, przy starcie komputera zawartość pierwszych 16 kB pamięci Flash jest kopiowana do pamięci RAM.
- Podczas normalnej pracy w przestrzeni adresowej procesora pamięć RAM jest widoczna pod adresami 0x0000..0x3FFF, a ostatnie 48 kB pamięci Flash – pod adresami 0x4000..0xFFFF.
- Używając polecenia monitora sprzętu (mmm), można odwzorować pamięć RAM w całej przestrzeni adresowej – ten sam blok o rozmiarze 16 kB jest wtedy widoczny pod adresami 0x0000, 0x4000, 0x8000 i 0xC000.
Po załadowaniu zawartości pamięci RAM może ona zostać skopiowana do pamięci Flash przy użyciu polecenia monitora sprzętu. W ten sposób można zaprogramować całą pamięć Flash, ładując zawartość poszczególnych jej bloków do pamięci RAM.
Monitor umożliwia ładowanie do pamięci komputera dowolnych programów zapisanych w postaci plików Intel HEX lub Motorola S-record. Programy mogą być pisane i translowane na komputerze PC. Załadowania programu do pamięci polega na przeciągnięciu ikony pliku do okna monitora sprzętu w TeraTerm i potwierdzeniu operacji przesłania pliku. Dzięki temu można szybko i wygodnie uruchomić na komputerze dowolny program.
Wejście-wyjście
SDC_Zero jest wyposażony w sterownik wejścia-wyjścia, zawierający interfejs terminalu, timer i jednobitowy port wyjściowy sterujący diodą LED umieszczoną na płytce BluePill. Sterownik zajmuje 4 lokacje w przestrzeni adresowej. W wersji z 80C85 jest on umieszczony pod adresem 0 w przestrzeni wejścia-wyjścia; w wersji z 65C02 sterownik jest położony pod adresem 0xFE00 w jednolitej przestrzeni adresowej.
Rejestry sterownika przedstawiono na rysunku 5. Sterownik stanowi podzbiór bloku wejścia-wyjścia komputera SDC_One. Rejestr LED służy do sterowania świeceniem diody. Rejestr CON zawiera dane przysyłane do terminalu i odbierane z terminalu. Rejestr TIM służy do programowania okresu timera. Okres może być zadawany w milisekundach (DIV8 = 0) lub w jednostkach 8 ms (DIV8 = 1). Rejestr CSR zawiera trzy znaczniki: TIF – znacznik końca okresu timera, TXE – gotowość do transmisji danych terminalu, RXNE – obecność danych odebranych.
Oprogramowanie
Do translacji programów asemblerowych użyto popularnego asemblera TASM (Table-driven Assembler).
Na obu wersjach komputera SDC_Zero uruchomiono interpretery języka BASIC z lat 70. Dla wersji z 80C85 jest to TinyBasic, a wersji z 65C02 – OSI Basic. Oba interpretery są dostępne w sieci w postaci źródłowej. Wersje programów dostosowane dla SDC_One zostały udostępnione w pliku towarzyszącym artykułowi. Adaptacja polegała gównie na napisaniu procedur związanych z obsługą terminalu.
Tiny BASIC 8080. Interpreter TinyBasic dla mikroprocesora 8080 został napisany w 1976 roku i zajmuje zaledwie 2 kB pamięci. Może on działać na procesorach zgodnych z 8080, w tym na 8085 i Z80. Jest on napisany w taki sposób, że musi być umieszczony w pamięci, począwszy od adresu 0. Interpreter został poddany niezbędnym modyfikacjom i doprowadzony do postaci translowalnej przy użyciu asemblera TASM (rysunek 6). Po zresetowaniu procesora, w stanie zatrzymania, należy załadować pamięć RAM zawartością pliku .HEX interpretera. Interpreter można uruchomić z pamięci RAM poleceniem run monitora sprzętu. Można go również umieścić na stałe w pamięci Flash, skąd będzie automatycznie kopiowany do pamięci RAM przy każdym uruchomieniu komputera. W celu zapisania interpretera do pamięci flash należy w monitorze sprzętu wpisać polecenie 0 0x800 ms.
Interpreter OSI BASIC dla 6502 z 1977 roku jest jednym z pierwszych produktów firmy Microsoft. Z powodu błędów w aktualnej wersji programu TeraTerm (4.100) interpreter nie może być załadowany w postaci jednego pliku HEX. Dlatego został on podzielony w edytorze tekstu na dwa pliki o rozmiarze poniżej 16 kB, bas65-1.hex i bas65-2.hex, które należy kolejno załadować do pamięci. Interpreter jest umieszczony w pamięci Flash, począwszy od adresu 0xd000 i używa pamięci RAM od adresu 0. W celu zapisania interpretera do pamięci Flash należy:
- Zresetować procesor i pozostawić go w stanie zatrzymania – polecenie rst.
- Włączyć odwzorowanie pamięci RAMN w całej przestrzeni adresowej – polecenie 1 mmm.
- Załadować do pamięci oba pliki HEX, przeciągając je kolejno do okna terminalu monitora sprzętu i odczekując na zakończenie ładowania (czas rzędu 1...2 sekund).
- Zaprogramować pamięć Flash – polecenie 0xd000 0x3000 ms.
- Wyłączyć wielokrotne odwzorowanie RAM – polecenie 0 mmm.
- Uruchomić komputer – polecenie run (rysunek 7).
Grzegorz Mazur
Instytut Informatyki
Politechnika Warszawska