[5] SDC One = Software Defined Computer na STM32: oprogramowanie sterujące i sprzętowy monitor systemu

Wszystkie części cyklu artykułów są dostępne pod adresem.

Oprogramowanie mikrokontrolera STM32L476 sterujące działaniem SDC_One składa się z kilkudziesięciu plików źródłowych i nagłówkowych w języku C. W oprogramowaniu można wyróżnić następujące składniki:

  • Stos USB, działający w przerwaniu o niskim priorytecie i realizujący funkcjonalność urządzenia złożonego.
  • Interpreter poleceń monitora systemu z obsługą ładowania programów w postaci .HEX.
  • Moduł inicjowania sprzętu, obsługi szyny procesora komputera docelowego, pamięci i układu pułapkowania.
  • Deasembler instrukcji maszynowych komputera docelowego.
  • Moduł obsługi sterownika wejścia-wyjścia Mini_IO.
  • Moduł pamięci masowej.

Tylko dwa pliki źródłowe są specyficzne dla zastosowanego w SDC_One mikroprocesora: moduł obsługi szyny i deasembler. Najistotniejszy dla działania komputera moduł obsługi szyny ma długość około 500 linii. W celu umożliwienia pracy z nowym procesorem należy stworzyć nową wersję tego modułu, realizującą obsługę szyny danego procesora. Opracowanie kolejnej wersji tego pliku na bazie innej, już istniejącej, zajmuje zwykle kilka godzin.

Obsługa szyny procesora

Najciekawszą i najistotniejszą częścią oprogramowania SDC_One jest specyficzny dla procesora komputera docelowego moduł obsługi szyny. Najważniejsza procedura tego modułu jest wywoływana w wyniku przerwania sygnalizowanego w chwili rozpoczęcia cyklu transmisji przez procesor komputera. Procedura ta rozpoznaje rodzaj cyklu transmisji, a następnie, o ile komputer znajduje się i ma pozostać w trybie pracy ciągłej, realizuje żądanie procesora i kończy cykl, podając do procesora sygnał gotowości. Jeżeli komputer działa w trybie pracy krokowej lub zachodzą warunki do zatrzymania go i wyjścia z trybu pracy ciągłej, procedura kończy się bez zakończenia cyklu transmisji. W takiej sytuacji procedura interpretera poleceń monitora szyny wyświetla na terminalu monitora szyny informacje o stanie komputera, w tym opis wstrzymanego cyklu, oraz znak zachęty do wprowadzenia polecenia. Zakończenie cyklu następuje po podaniu odpowiedniego polecenia (np. wykonania kolejnego kroku lub włączenia pracy ciągłej) przez terminal monitora szyny. Po każdym poleceniu edycji pamięci lub wejścia wyjścia oraz po poleceniu powodującym zakończenie cyklu, a przed samym zakończeniem cyklu, następuje ponowne określenie wartości danych transmitowanych w danym cyklu. Zwykle są to dane odczytywane przez procesor z pamięci lub portu wejściowego. Jest jednak możliwe wymuszenie na szynie wartości danej niezależnie od zawartości pamięci – służy do tego polecenie dbs.

Ze względu na ostre wymagania czasowe całe oprogramowanie zostało zrealizowane w konwencji zdarzeniowej. Zdarzenia są sygnalizowane asynchronicznie i obsługiwane jako przerwania sterownika NVIC, stanowiącego część rdzenia ARM Cortex-M. Poszczególne zdarzenia-przerwania są wywoływane przez sprzęt lub oprogramowanie.

Wydajność komputera docelowego

O maksymalnej osiągalnej wydajności komputera docelowego decyduje złożoność procedury obsługi transmisji na szynie oraz częstotliwość zegara procesora docelowego. Domyślna częstotliwość zegara poszczególnych wersji SDC_One jest zbadaną doświadczalnie minimalną częstotliwością, powyżej której nie następuje widoczny wzrost wydajności komputera. W praktycznych testach wydajność SDC_One odpowiada ok. 35..60% maksymalnej wydajności procesora docelowego przy dobranej w opisany sposób częstotliwości zegara procesora. Parametry wydajnościowe poszczególnych wersji SDC_One zestawiono w tabeli 1.

Procesor docelowy Domyślna częstotliwość zegara [MHz] Wydajność (cykle szyny na sekundę) Orientacyjna wydajności procesora w stosunku do maksymalnej
Z80CPU 2.5 376000 60%
8085 2 (4) 363000 60%
MC68008 5 420000 35%
65C02 1 486000 49%

W wersji z mikroprocesorem 8085 częstotliwość wejściowego przebiegu zegarowego jest dwukrotnie większa od częstotliwości wewnętrznego taktowania procesora.

Pamięć komputera docelowego

W projekcie SDC_One przyjęto, że cała pamięć dostępna dla komputera docelowego może być przezeń czytana i zapisywana. Podczas inicjowania działania SDC_One pamięć jest zerowana, a następnie jest do niej wpisywany program startowy, zależny od wersji komputera. W przypadku procesorów, dla których opracowano port systemu operacyjnego, w pamięci znajduje się program rozpoczynający ładowanie systemu. W innych wersjach do pamięci wpisywany jest prosty program demonstracyjny.

Program ładujący jest zamazywany przez system operacyjny. W celu ponownego załadowania systemu można użyć polecenia monitora przywracającego inicjalną zawartość pamięci.

Pojemność pamięci komputera docelowego jest zależna od wersji komputera i typu mikrokontrolera. Wersje z mikroprocesorami 8-bitowymi i adresowaniem 16-bitowym (Z80, 8085, 65C02) mają po 64 KiB pamięci. Maksymalny rozmiar pamięci, który może być udostępniony przez mikrokontroler STM32L476 dla komputera docelowego, wynosi 80 KiB – taką pojemność pamięci mają wersje z mikroprocesorami MC68008 i W65C816. W celu umożliwienia pracy mikroprocesora MC68008 z systemem operacyjnym CP/M-68k opracowano wersję oprogramowania dla mikrokontrolera STM32L496 i płytki Nucleo-144, która udostępnia komputerowi docelowemu pamięć o pojemności 256 KiB.

Porty wejścia-wyjścia

Komputer docelowy ma dostęp do 256 8-bitowych portów wejścia-wyjścia. Pierwsze 16 adresów przestrzeni wejścia-wyjścia zajmuje sterownik  Mini_IO, opisany w 3. części artykułu. Pozostałe 240 bajtów jest dostępnych do odczytu i zapisu, ale nie pełnią one żadnej funkcji. Dodatkowa funkcjonalność może zostać łatwo zrealizowana poprzez modyfikację modułu oprogramowania realizującego funkcje wejścia-wyjścia.

W celach eksperymentalnych w jednej z wersji oprogramowania zrealizowano w przestrzeni wejścia-wyjścia sterownik przerwań dla mikroprocesora Z80CPU, umożliwiający demonstrację obsługi przerwań w każdym z trzech dostępnych w tym mikroprocesorze trybów.

W wersjach SDC_One z mikroprocesorami z wydzieloną przestrzenią wejścia-wyjścia portysą odwzorowane w tej przestrzeni. W wersji z mikroprocesorem MC68008 porty wejścia wyjścia zostały odwzorowane w ostatnich 256 lokacjach przestrzeni adresowej (pod adresami 0xFFF00..0xFFFFF), co umożliwia dostęp do nich przy użyciu 16-bitowych adresów i jest dość typowym sposobem adresowania sterowników wejścia-wyjścia w komputerach z procesorami rodziny M68k. W wersjach z mikroprocesorami W65C02 i W65C816 porty zostały odwzorowane w zakres adresów 0xFE00..0xFEFF, gdyż zarówno początek przestrzeni adresowej, jak i ostatnie lokacje poniżej adresu 64 KiB powinny w przypadku tych procesorów zawierać pamięć.

Interfejs USB – urządzenie złożone

SDC_One po podłączeniu do komputera nadrzędnego jest widziany jako urządzenie złożone USB, w skład którego wchodzi urządzenie pamięci masowej oraz dwa wirtualne porty szeregowe. Urządzenie pamięci masowej zawiera plik .INF potrzebny do instalacji wirtualnych portów szeregowych w starszych wersjach systemu Windows. Planujemy rozszerzenie jego funkcjonalności w kolejnych wersjach oprogramowania. Jeden z dwóch wirtualnych portów szeregowych służy do komunikacji z monitorem szyny, a drugi – do komunikacji z komputerem docelowym. W celu nawiązania połączenia z oboma z tych interfejsów, należy na komputerze otworzyć dwa terminale. Rekomendujemy użycie do tego celu programu TeraTerm. Konfiguracja parametrów portu szeregowego  (szybkość, synchronizacja) może być niemal dowolna, dla poprawnej współpracy przy przesyłaniu większych bloków danych (np. przy ładowaniu programów) warto jednak ustawić niezerowy odstęp czasowy na końcu wiersza.

Uruchomienie komputera

Po włączeniu zasilania SDC_One inicjuje działanie generatora przebiegu zegarowego mikroprocesora, inicjuje zawartość pamięci komputera docelowego, generuje sygnał RESET dla mikroprocesora i zatrzymuje go w pierwszym cyklu transmisji. Rozpoczęcie wykonywania programu przez komputer następuje po wydaniu polecenia przez użytkownika poprzez konsolę monitora sprzętu.

Funkcje monitora sprzętu

Monitor sprzętu umożliwia sterowanie pracą komputera docelowego na poziomie transakcji na szynie procesora, w tym m.in.:

  • Sterowanie częstotliwością przebiegu zegarowego.
  • Inicjowanie procesora (RESET).
  • Ładowanie programów do pamięci komputera docelowego.
  • Wyświetlanie i zmianę zawartości pamięci i portów wejścia-wyjścia.
  • Sterowanie pracą procesora, w tym pracę krokową, pułapkowanie, gromadzenie śladu wykonania i szybką pracę ciągłą.
  • Krokowe wykonanie instrukcji z wyświetlaniem informacji o każdym cyklu transmisji inicjowanym przez procesor i deasemblacją wykonywanych instrukcji.

Sterowanie działaniem pamięci masowej komputera docelowego

Monitor został zrealizowany jako oprogramowanie mikrokontrolera STM32. Do komunikacji  użytkownika z monitorem służy pierwszy z dwóch wirtualnych portów szeregowych. Można się z nim połączyć przy użyciu programu emulatora terminala działającego na komputerze PC. Po otwarciu terminala i przesłaniu pierwszego znaku, monitor wyświetla na terminalu winietę startową i łańcuch zachęty (prompt). Łańcuch zachęty zawiera informację o stanie komputera. Ma ona postać ciągu znaków, zawierającego kolejno:

  • Identyfikator typu cyklu transmisji rozpoczętego przez procesor.
  • Adres odwołania.
  • Wartość transmitowanych danych.
  • W przypadku, gdy bieżący cykl jest cyklem pobrania pierwszego bajtu kodu operacyjnego – zdeasemblowaną instrukcję.

Jeżeli komputer działa w trybie pracy ciągłej, wszystkie wymienione elementy przyjmują postać znaków ‘#’.

Rys. 1. Terminal monitora szyny – rozpoczęcie pracy z komputerem z mikroprocesorem Z80CPU

Po włączeniu komputera procesor zostaje zainicjowany, a następnie zatrzymany w pierwszym cyklu transmisji. W zależności od typu procesora jest to zwykle cykl pobrania pierwszej instrukcji lub pierwszego bajtu adresu, od którego rozpocznie się wykonanie programu.

Łańcuch zachęty oznacza możliwość wprowadzenia z terminala polecenia dla monitora. Wprowadzane polecenia mogą być edytowane przy użyciu klawisza Backspace. Klawisze sterowania kursorem (góra/dół) umożliwiają przywołanie kilku ostatnich wierszy w celu powtórzenia jednego z poleceń. Naciśnięcie klawiszy Enter powoduje interpretację linii polecenia.

Interpreter poleceń monitora szyny został zrealizowany jako stosowy – polecenia nie mają budowy wierszowej, lecz każdy ciąg znaków pomiędzy separatorami (nowy wiersz, spacja, tabulacja) jest interpretowany oddzielnie jako polecenie lub argument. Argumenty poleceń są liczbami całkowitymi bez znaku – mogą one być wprowadzane w postaci dziesiętnej, ósemkowej, szesnastkowej binarnej lub znakowej, zgodnej ze składnią języka C. Stałe znakowe (jednoliterowe) są zawarte w apostrofach, a stałe binarne – poprzedzone prefiksem 0b. Każda napotkana stała jest umieszczana na kilkuelementowym stosie, zrealizowanym w postaci bufora cyklicznego. Ciąg znaków nie rozpoczynający się od cyfry ani nie będący stałą znakową jest traktowany jako nazwa polecenia. Jeżeli polecenie to zostanie rozpoznane, jest ono wykonywane, a jego argumentami (o ile występują) są wartości ostatnio umieszczone na stosie, Większość poleceń nie zmienia zawartości ani stanu stosu; tylko niektóre polecenia usuwają daną z wierzchołka stosu lub modyfikują jej wartość. Dzięki takiej konstrukcji interpreter poleceń jest prosty, szybki, łatwy w rozbudowie i zajmuje mało miejsca w pamięci.

Dla ułatwienia interakcji z użytkownikiem wprowadzono również zestaw poleceń, których jedynym skutkiem jest umieszczenie na stosie argumentów stałej. Dzięki temu użytkownik może zamiast wartości często używanych stałych używać do sterowania monitorem szyny ich nazw mnemonicznych.

Niektóre z poleceń monitora mają własność samopowtarzania – jeżeli po wykonaniu takiego polecenia w następnym wierszu poleceń naciśniemy klawisz Enter bez wcześniejszego wpisania znaków, nastąpi powtórzenie ostatniego polecenia. Dotyczy to m.in. poleceń związanych z uruchamianiem programów w trybie pracy krokowej.

Zestaw poleceń monitora sprzętu

Wśród poleceń monitora sprzętu można wyróżnić dwie główne grupy: polecenia sterujące działaniem komputera docelowego oraz polecenia monitorowania i edycji zawartości pamięci i sterownika wejścia-wyjścia.

Sterowanie pracą komputera i procesora

Polecenie sterujące komputerem przedstawiono w tabeli 2.

 

Tab. 2. Polecenia sterowania komputerem

argumenty polecenie opis
? Wyświetlenie listy poleceń z opisami
?clk Wyświetlenie bieżących wartości okresu i częstotliwości zegara procesora
<period> clkp Ustawienie okresu zegara w nanosekundach
run Uruchomienie w trybie pracy ciągłej
ct Uruchomienie w trybie pracy ciągłej na okres 1 sekundy i wyświetlenie liczby wykonanych cykli szyny (test wydajności komputera)
<intnum> is Zgłoszenie przerwania
<intnum> ic Wycofanie zgłoszenia przerwania
mi Załadowanie domyślnej zawartości pamięci
rst Sprzętowe inicjowanie procesora, inicjowanie peryferiów i ustawienie trybu pracy krokowej w cyklach szyny
sc Wykonanie jednego cyklu szyny
si Wykonanie jednego cyklu instrukcyjnego z zatrzymaniem przy rozpoczęciu pobierania następnej instrukcji.
s Wykonanie jednego cyklu (takiego, jak ostatni – szyny lub instrukcyjnego)
<num> ns Wykonanie zadanej liczby cykli
<val> dbs Wymuszenie zawartość szyny danych w cyklu szyny, niezależnie od zawartości pamięci lub portu wejściowego
ds Synchronizacja pamięci masowej – wymuszenie zapisu zmian do pamięci Flash.

Polecenie clkp umożliwia ustawienie długości okresu zegara procesora podanej w nanosekundach.

Polecenia zgłaszania i kasowania przerwań umożliwiają łatwą demonstrację obsługi przerwań przez procesor. Argumentem poleceń jest numer przerwania, interpretowany w sposób zależny od procesora Dla procesorów z dwiema liniami zgłoszeń przerwań – maskowalnego i niemaskowalnego – wartość 0 identyfikuje przerwanie maskowalne, a wartość 1 – maskowalne. W przypadku 8085 0 odpowiada linii INT, 1 – linii RST5.5, 2 – linii RST6.5, 3 – linii RST7.5 a 4 – linii NMI. Dla MC68008 argument jest wartością liczbową reprezentowaną przez stany linii -IPL1 i -IPL2/0. Wartość 0 oznacza brak zgłoszenia, wartości 1 i 2 – przerwania maskowalne, wartość 3 – przerwanie niemaskowalne.

Polecenie mi powoduje załadowanie domyślnej zawartości do pamięci komputera.

Polecenie rst powoduje sprzętowe zainicjowanie procesora poprzez wygenerowanie sygnału RESET. Polecenie to nie ma wpływu na zawartość pamięci.

Ładowanie zawartości pamięci z pliku

Jeżeli zamiast zwykłego polecenia monitora z terminala zostanie przesłany rekord pliku ładowalnego .HEX, jest on interpretowany przez monitor zgodnie ze specyfikacją danego formatu – dane zawarte w rekordach są ładowane do pamięci. Bez konieczności podawania dodatkowych poleceń. Format interpretowanych plików zależy od typu procesora zastosowanego w komputerze. Dla procesorów Z80CPU, 8085 i 6502 stosowany jest format Intel HEX, a dla MC68008 – Motorola S-record. Monitor sprzętu obsługuje ładowania obu formatów, niezależnie od typu mikroprocesora- Podczas ładowania pliku HEX na ekranie terminala jest wyświetlany tylko pierwszy rekord. Jeżeli do współpracy z monitorem sprzętu użyjemy programu terminala z funkcjonalnością „Drag and drop” dla przesyłania plików (np. TeraTerm), załadowanie pliku HEX do pamięci komputera wymaga jedynie przeciągnięcia ikony pliku do okna terminala. Przy ładowaniu należy pamiętać, by rekord zaczynał się od początku wiersza – przed załadowaniem pliku nie należy wprowadzać w terminalu wiersza poleceń nie zakończonego klawiszem Enter.

Przeglądanie i edycja pamięci i portów wejścia-wyjścia

Polecenia monitorowania i edycji pamięci i portów wejścia-wyjścia przedstawiono w tabeli 3.

Tab. 3. Polecenia wyświetlania i edycji pamięci i portów wejścia-wyjścia

argumenty polecenie opis
<ioaddr> ior Wyświetlenie bieżących zawartości portów wejściowych bez zmiany stanu peryferiów wynikającej z odczytu
<ioaddr> iot Wyświetlenie bieżących zawartości portów wejściowych z ew. zmianą stanu peryferiów wynikającej z odczytu, jak przy odczycie przez procesor
<data> <ioaddr> iow Zapis wartości do portu wyjściowego
<addr> md Wyświetlenie zawartości 128 bajtów pamięci i modyfikacja adresu na stosie argumentów do kolejnej wielokrotności 128
<len> <val> <addr> mf Wypełnianie obszaru pamięci stałą zawartością
<val> <addr> mw Zapis bajtu do pamięci
<val> <addr> mww Zapis słowa 16-bitowego do pamięci
<target> <addr> wj Zapis do pamięci instrukcji skoku do zadanego adresu

Polecenie ior umożliwia podglądanie wartości portów wejściowych bez wpływu na stan sterownika wejścia-wyjścia, czyli np. odczyt znaku z klawiatury bez kasowania znacznika gotowości. Polecenie iot odczytuje port tak samo, jak procesor komputera – z efektami ubocznymi.

Polecenie wj umożliwia łatwy zapis do pamięci instrukcji skoku pod zadany adres, w celu przekazania sterowania pod adres, pod którym umieszczony jest uruchamiany program.

W kolejnej części artykułu przedstawimy sposoby programowania komputera SDC_One.

Julia Kosowska

Grzegorz Mazur