[3] SDC One = Software Defined Computer na STM32: opis mikroprocesorowej części komputera

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

Docelowy komputer składa się z mikroprocesora (fotografia 1) oraz ze zrealizowanych przez mikrokontroler STM32L4 bloków peryferyjnych: pamięci i wielofunkcyjnego sterownika wejścia-wyjścia Mini_IO. Pamięć dostępna dla mikroprocesora w podstawowej wersji SDC_One ma rozmiar 64 KiB. Cała pamięć może być odczytywana i zapisywana przez procesor, zachowuje się więc ona jak pamięć RAM. Przy uruchomieniu SDC_One do pamięci jest ładowany, w zależności od typu użytego procesora, program ładujący system operacyjny CP/M lub program demonstracyjny.

Fot. 1. Płytka mikroprocesora Z80 (co ciekawe, produkowanego przez STMicroelectronics, podobnie do STM32)

Mini_IO

Sterownik wejścia-wyjścia Mini_IO umożliwia współpracę procesora komputera SDC_One z urządzeniami wejścia-wyjścia, na które składają się:

  • dioda LED RGB na płytce mikrokontrolera i dioda LED na płytce Nucleo-64, sterowane z wyjść PWM timerów mikrokontrolera STM32L4,
  • przycisk umieszczony na płytce Nucleo-64,
  • konsola umożliwiająca dwukierunkowe połączenie z PC poprzez wirtualny port szeregowy,
  • pamięć masowa w postaci dwóch jednostek dyskowych, symulowanych w pamięci Flash i RAM mikrokontrolera.

Ponadto Mini_IO zawiera prosty timer systemowy, który może odmierzać odcinki czasu o długości ustawionej przez oprogramowanie komputera docelowego, w zakresie od 1 ms do ponad 1 s.

Wszystkie urządzenia zostały zrealizowane przy użyciu zasobów sprzętowych i oprogramowania mikrokontrolera STM32. Sterownik Mini_IO jest dostępny dla mikroprocesora poprzez 16 8-bitowych rejestrów odwzorowanych w przestrzeni wejścia-wyjścia, a jeśli procesor zastosowany w komputerze takiej nie posiada – w 16 lokacjach przestrzeni adresowej pamięci. Nazwy i opis rejestrów Mini_IO przedstawiono na rysunku 2.

Rys. 2. Rejestry sterownika wejścia-wyjścia Mini_IO

Sterowanie bitowe LED

Rejestr IO_LED służy do prostego sterowania diod LED (zaświecanie, gaszenie). Przy zapisie rejestru pole bitowe FUN określa operację, a pole LED – wartość sterującą stanem diod. W zależności od wartości pola FUN, pojedynczy zapis może na różne sposoby zmienić stan bitów sterujących świeceniem wybranych diod:

  • FUN = 00 – ustawienie stanu diod wg wartości zapisanej do pola LED,
  • FUN = 01 – ustawienie w stan 1 bitów, które w polu LED mają wartość 1,
  • FUN = 10 – ustawienie w stan 0 bitów, które w polu LED mają wartość 1,
  • FUN = 11 – zmiana stanu (negacja) bitów, które w polu LED mają wartość 1.
  • Jeżeli bit sterujący stanem diody zostanie ustawiony w stan 0 – dioda gaśnie. Ustawienie w stan 1 powoduje zaświecenie diody z pełną jasnością.

Konsola i timer

Do współpracy z konsolą i timerem oraz odczytem stanu przycisku służą trzy rejestry Mini_IO:

  • Rejestr IO_CON służy do zapisu danych przesyłanych do konsoli i odczytu danych odbieranych z konsoli (terminala). Zawiera on 8-bitową daną przesłaną lub odebraną przez interfejs VCOM konsoli.
  • Rejestr IO_TIM zawiera okres timera systemowego. Jego wartość początkowa wynosi 0, co odpowiada zatrzymaniu timera.
    • Bit 7 – G – określa granularność okresu timera. Wartość 0 odpowiada jednostkom 1 ms, 1 – 8 ms.
    • Bity 6..0 zawierają okres timera wyrażony w jednostkach zależnych od wartości bitu G. Zapis wartości 0 powoduje zatrzymanie timera i wyzerowanie znacznika końca okresu w rejestrze IO:CSR. Zapis wartości z zakresu 1..127 powoduje uruchomienie timera. Maksymalny okres timera, odpowiadający wartości 0xff rejestru IO_TIM, może trwać 1016 ms.
  • Rejestr IO_CSR zawiera znaczniku stanu timera i interfejsu konsoli.
    • Bit 0 – RXNE – ma wartość 1, gdy w rejestrze IO_CON jest dostępny do odczytu znak przesłany z konsoli. Bit ten jest zerowany przy odczycie rejestru IO_CON i ustawiany przy odebraniu znaku z konsoli.
    • Bit 1 – TXE – ma wartość 1, gdy interfejs konsoli jest gotowy do wysłania znaku na konsolę (do rejestru IO_CON można zapisać kolejny znak). Bit ten jest zerowany przy zapisie rejestru IO_CON, po czym jest on samoczynnie ustawiany w stan 1, gdy interfejs staje się gotowy na przyjęcie kolejnego znaku.
    • Bit 2 – TIF jest ustawiany po zakończeniu okresu timera. Jest on zerowany poprzez zapis do rejestru IO_CSR wartości, w której bit ten jest jedynką.

Sterowanie jasnością LED

Rejestry IO_DUTYR, IO_DUTYRG, IO_DUTYB i IO_DUTYN umożliwiają sterowanie jasnością świecenia diody RGB i diody LED umieszczonej na płytce Nucleo-64. Wartość zapisywana do tych rejestrów jest interpretowana jako licznik ułamka o mianowniku 250, określającego wypełnienie przebiegu sterującego jasnością diody. Ustawienie bitu w rejestrze IO_LEDS ma skutek taki sam, jak zapis wartości 255 do rejestru wypełnienia. Wyzerowanie bitu w rejestrze IO_LEDS ma skutek taki sam, jak zapis wartości 0 do rejestru wypełnienia. Zawartości rejestrów wypełnień i rejestru IO_LEDS nie są ze sobą powiązane – przy odczycie jest zawsze pobierana wartość wpisana ostatnio do odczytywanego rejestru.

Sterownik pamięci masowej

Sterownik pamięci masowej emuluje dwie jednostki dyskowe. Pierwsza z nich korzysta z pamięci Flash mikrokontrolera sterującego, a druga – z pamięci RAM. Pierwsza jednostka ma pojemność 512 KiB, a druga – 32 KiB. Zawartość drugiej jednostki jest tracona przy wyłączeniu komputera, można ją jednak przed wyłączeniem skopiować do pamięci Flash mikrokontrolera używając polecenia monitora. Po włączeniu SDC_One zawartość jest inicjowana z pamięci Flash.Emulowane jednostki pamięci masowej mają ścieżki o pojemności 2 KiB.

Dla systemów CP/M ścieżka składa się z 16 sektorów po 128 bajtów, pierwsza jednostka ma 256 ścieżek, a druga 16. Sterownik jest widziany przez komputer docelowy jako 7 8-bitowych rejestrów:

  • IO_MSSEC zawiera numer sektora dla operacji odczytu lub zapisu. Dozwolony zakres wartości od 0 do 15.
  • IO_MSTRK zawiera numer ścieżki. Zakres zależy od numeru jednostki: 0..255 dla jednostki 0, 0..15 dla jednostki 1.
  • IO_MSUNIT zawiera numer jednostki – 0 lub 1.

Zapis do rejestru IO_MSCMD powoduje wykonanie operacji zależnej od zapisywanej wartości:

  • 1 – odczyt sektora z jednostki pamięci masowej do pamięci komputera;
  • 2 – zapis  sektora z  pamięci komputera do jednostki pamięci masowej;
  • 3 – synchronizacja wybranej jednostki,
  • 4 – synchronizacja wszystkich jednostek.
  • Synchronizacja jednostki 0 polega na skopiowaniu zawartości buforów ostatnio używanych sektorów do pamięci Flash mikrokontrolera. Synchronizacja jednostki 1 polega na przepisaniu całej zawartości jednostki z pamięci RAM do pamięci Flash.Odczyt rejestru IO_MSCMD zwraca kod zakończenia operacji. Wartość 0 oznacza pomyślne zakończenie; wartość niezerowa – błąd.

Odczyt każdego z pozostałych rejestrów sterownika zwraca ostatnio zapisaną wartość. W celu odczytu lub zapisu sektora przez komputer docelowy, jego oprogramowanie powinno:

  • zapisać numer sektora do rejestru IO_MSSEC,
  • zapisać numer ścieżki do rejestru IO_MSTRK,
  • zapisać numer jednostki do rejestru IO_MSUNIT,
  • zapisać adres bufora sektora do rejestrów IO_MSADDR0, IO_MSADDR1 i IO_MSADDR2,
  • zapisać polecenie do rejestru IO_MSCMD.

W wersjach SDC_One z mikroprocesorami 80C85 i Z80CPU sterownik Mini_IO jest odwzorowany w przestrzeni adresowej wejścia-wyjścia. W wersjach komputera wyposażonych w procesory bez wydzielonej przestrzeni wejścia-wyjścia (MC68008 i 65C02) sterownik jest dostępny dla procesora w przestrzeni adresowej pamięci. Domyślny adres bazowy sterownika (0 dla 80C85, Z80CPU i 65C02, 0xFFFF0 dla MC68008) może być zmieniany poleceniem monitora systemu.

W kolejnej części przedstawimy schematy ideowe SDC_One oraz szczegóły połączeń pomiędzy mikrokontrolerem STM32L4 i procesorem komputera docelowego.

Julia Kosowska

Grzegorz Mazur