Emulator konsoli NES w systemie Linux na komputerze SoMLabs VisonSOM

Kontroler zbudowany z wykorzystaniem układu MCP23S08

Jeżeli nie dysponujemy żadnym kontrolerem, wówczas idealnym rozwiązaniem (choćby ze względu na walor edukacyjny) jest konstrukcja własnego prostego urządzenia. Oryginalny kontroler konsoli NES posiada 8 przycisków: cztery do kontroli kierunku, dwa przyciski akcji (oznaczone jako A i B) oraz przyciski START i SELECT. Aby uniknąć problemów z wyborem i konfiguracją multipleksacji wyprowadzeń GPIO (co nawet przy dużej liczbie wyprowadzeń I/O dostępnych na złączach komputerów jednopłytkowych nie zawsze jest proste), do sprzętowej budowy kontrolera wykorzystamy moduł KAmodEXP1, będący adresowalnym ekspanderem GPIO z układem MCP23S08. Układ ten może pracować zarówno na magistrali SPI jak i I2C oraz posiada dokładnie osiem konfigurowalnych linii GPIO, a więc idealnie wpisuje się w realizowany projekt. Prosty schemat połączeń przedstawiono na rysunku 4 (układ MCP23S08 podłączony w konfiguracji SPI).

Rys. 4. Schemat połączeń dla modułu KAmodEXP1 i płyty bazowej VisionCB-STD

Aby uniknąć programowej  implementacji obsługi układu MCP23S08 w przestrzeni użytkownika, wykorzystamy gotowy sterownik dostępny w jądrze systemu. Konfigurację jądra rozpoczynamy od włączenia sprzętowego kontrolera magistrali SPI dla układów i.MX:

Następnie włączamy docelowy sterownik układu MCP23S08:

Włączenie sterownika układu MCP23S08 oraz przygotowanie dla niego opisu Device Tree (co przedstawiono poniżej), spowoduje pojawienie się w systemie nowego kontrolera GPIO dostępnego w przestrzeni użytkownika poprzez interfejs /sys/class/gpio. Aby maksymalnie uprościć obsługę projektowanego urządzenia, linie kontrolera GPIO wykorzystamy w sterowniku klawiatury Polled GPIO buttons [więcej informacji – patrz ramka]:

Konfigurację jądra należy uzupełnić opisem Device Tree wymaganym przez włączone powyżej sterowniki. Edycję pliku somlabs-visionsom-6ull.dts rozpoczynamy od dodania opisów dla kontrolera SPI oraz układu MCP23S08listing 1.

List. 1. Opis Device Tree dla kontrolera SPI3 oraz układu MCP23S08

Do komunikacji z układem MCP23S08 wykorzystamy kontroler SPI3 (ecspi3) w konfiguracji z jedną linią CS (wartość określona poprzez pole fsl,spi-num-chipselects), sterowaną poprzez wyprowadzenie GPIO1_20 (definicja linii w polu cs-gpios). W opisie kontrolera wskazujemy również odwołanie do multipleksacji wyprowadzeń I/O (pinctrl-0=<&pinctrl_ecspi3>). Następnie umieszczamy opis nowego kontrolera gpiom1, którego funkcję pełni układ MCP23S08. Opis rozpoczynamy od wskazania typu układu (układ ekspandera występuje również w wersji z 16. liniami GPIO), jak i sposobu jego podłączenia (SPI lub I2C):

  • compatible = „microchip,mcp23s08” – dla wersji SPI z 8. liniami GPIO
  • compatible = „microchip,mcp23s17” – dla wersji SPI z 16. liniami GPIO
  • compatible = „microchip,mcp23008” – dla wersji I2C z 8. liniami GPIO
  • compatible = „microchip,mcp23017” – dla wersji I2C z 16. liniami GPIO

Wpisem gpio-controller oznaczamy urządzenie jako pełniące rolę kontrolera GPIO. Pole microchip,spi-present-mask jest istotne wyłącznie gdy jedna linia CS jest dzielona przez większą liczbę adresowalnych układów. Pole reg – dla konfiguracji MCP23S08 jako układu SPI – określa numer porządkowy wyprowadzenia linii CS.

Zaimplementowany w jądrze systemu Linux sterownik układu MCP23S08 nie wspiera aktualnie funkcji przerwań dla konfiguracji SPI (opcja te jest wspierana wyłącznie przez układy pracujące na magistrali I2C). Z tego powodu, na kolejnym etapie konfiguracji jądra wykorzystano sterownik „Polled GPIO buttons” z aktywnym odpytywaniem. Dla układów pracujących na magistrali I2C bardziej optymalnym rozwiązaniem będzie wybór sterownika „GPIO Buttons” oraz konfiguracja kontrolera GPIO jako „interrupt-controller”. Przykładowy opis Device Tree dla układu MCP23S08 pracującego na magistrali I2C może wyglądać następująco:

W powyżej przedstawionym opisie, pole reg definiuje sprzętowy adres układu MCP23S08 na magistrali I2C.

Wpisem spi-max-frequency określamy maksymalną dopuszczalną częstotliwość pracy układu na magistrali (tutaj 10MHz). Tak przygotowany opis kontrolera SPI oraz układu MCP23S08 należy uzupełnić o opis konfiguracji multipleksacji wyprowadzeń I/O – listing 2.

List. 2. Konfiguracja wyprowadzeń I/O dla kontrolera SPI3

Wyprowadzenia, którym na listingu 2 przypisano role linii SCLK oraz CS, w domyślnym opisie Device Tree dostarczanym przez producenta płytki VisionSOM pełnią rolę linii RX oraz TX kontrolera UART2. Aby uniknąć konfliktu, należy wyłączyć kontroler UART2, poprzez wykomentowanie linii statusu, jak przedstawiono to na listingu 3.

List. 3. Wyłączenie kontrolera UART2 w opisie Device Tree

Ostatnim etapem przygotowania opisu Device Tree jest zdefiniowanie ośmiu przycisków w ramach sterownika gpio-keys-polled. Ponieważ sterownik pracuje w trybie odpytywania, niezbędne jest określenie interwału czasowego poprzez pole poll-interval (wartość wyrażona w milisekundach). Następnie dokonano opisu ośmiu przycisków definiując ich etykiety (pole label), odwołania do kontrolera GPIO (do kolejnych linii I/O kontrolera gpiom1/układu MCP23S08) oraz przypisując im wybrane kod, zdefiniowane przez podsystem wejścia. Fragment opisu Device Tree przedstawiono na listingu 4.

List. 4. Opis Device Tree dla sterownika gpio-keys-polled

Po skompilowaniu nowego obrazu jądra oraz opisu Device Tree z wykorzystaniem poleceń:

pliki wynikowe (tj. zImage oraz somlabs-visionsom-6ull.dtb) należy skopiować do katalog /boot na karcie SD. Po ponownym uruchomieniu systemu, w buforze komunikatów jądra zostaną wyświetlone komunikaty informujące o poprawnej konfiguracji sterownika:

Poprawność działania kontrolera oraz podłączonych przycisków może zostać przetestowana za pomocą narzędzia evtest:

Ostatecznej konfiguracji przycisków należy dokonać z wykorzystaniem opcji Gamepad Config w emulatorze Fceux.

 Fot. 5. Moduł VisionSOM z uruchomionym emulator konsoli Famicon/NES

Łukasz Skalski

contact@lukasz-skalski.com

O autorze