Poza popularnymi mostkami USB-UART (FT232 i jego odmianach, FT230) oraz SPI-Pararrel (FT245, FT240) USB-SPI/I2C w ofercie dostępne są inne układy. Pomijając konwertery FT260 obsługujące klasę HID (klawiatura, mysz) dostępne są dwie rodziny: FT12x i FT22x/20x.
Układy FT12x wymagają konfiguracji, odczytania identyfikatora nadanego przez system (enumeracja), odpowiedzi swoim numerem VID, PID, zapotrzebowaniem na prąd. Układy dają duże możliwości – można otworzyć kilka kanałów logicznych (jak portów w Ethernecie), realizować szybkie transmisje o wysokim priorytecie. Niestety, są kłopotliwe w konfiguracji, dlatego na razie nie będziemy się nimi zajmowali.
Układy FT22x/20x są łatwe w implementacji. Poza tym, że zamiast przez UART czy interfejs równoległy komunikują się z użyciem SPI lub IIC, umożliwiają dostęp do pamięci konfiguracji (MTP). Dzięki temu, że tę pamięć można zarówno czytać, jak i zapisywać, to z poziomu aplikacji mikrokontrolera jest możliwość zmiany konfiguracji układu (VID, PID, nazwa producenta, numer seryjny, funkcje linii CBUS). Ponadto, aplikacja ma dostęp do wolnej przestrzeni pamięci EEPROM (prawie 1 kB!). W tej pamięci można przechowywać konfigurację programu mikrokontrolera (np. backup wewnętrznej EEPROM), licznik czasu pracy programu i inne dane. Zaletą takiej pamięci jest, że nie jest kasowana po wgraniu programu do mikrokontrolera. Ponadto, za pomocą bibliotek D2XX można z poziomu systemu zapisywać i odczytywać pamięć MTP.
Układy FT220 i 221
Komunikacja za pomocą SPI w trybie 1-bit, 2-bit, 4-bit (jak w wypadku kart SD) oraz 8-bit (FT221). Od strony USB 1 Mb/s (FT221) i 500 kb/s (FT220). Komunikacja z układem jest banalnie łatwa. Najpierw jest przesyłana komenda, a po niej zapisywane/odczytywane dane. W wypadku odbierania danych z komputera, po wysłaniu komendy należy sprawdzić stan linii MISO układu (nie mylić z linią MIOSIO0), co pokazano na listingu 1. MISO informuje czy w buforze jest choć jeden znak do odczytu. Można odczytać wiele bajtów, jeśli oczywiście są do odebrania (listing 2).
Przy zapisie sytuacja jest nieco inna. Linia MIOSIO0 (nie mylić z linią MISO) informuje czy bufor nadawczy jest pełny. Trzeba pamiętać, że stan tej linii jest ważny przed uaktywnieniem układu sygnałem strobującym CS (SS). W większości mikrokontrolerów zapełnienie bufora nadawczego jest w mało prawdopodobne i można ignorować stan tej linii. Istotne jest to, że po wysłaniu komendy można wysłać dowolną (do zapełnienia bufora) liczbę znaków. Dlatego, jeśli wysyłamy kilka bajtów, można to zrobić w sposób pokazany na listingu 3.
Taki system komunikacji jest dobry gdy na magistrali SPI jest jeden układ. Spowodowane jest to tym, że linia MIOSIO0 może zakłócać transmisję innych układów. Aby tego uniknąć a nie rozbudowywać sprzętu (bramki truj-stanowe) funkcjonalność linii MIOSIO0 w roli statusu zapełnienia bufora nadawczego, można wyłączyć z poziomu aplikacji FT_PROG (rysunek 1).
Układy FT22x umożliwiają zapis i odczyt linii statusowych modemu (RTC, CTS, DTR, DSR, CDC, RI). Jest to o tyle przydatne, że w Windows (sprawdziłem w XP, problem sygnalizowano mi także w Windows 7) ma pewien błąd. Gdy mostek FTDI wysyła paczki po kilkanaście bajtów do hosta, a nie jest otworzony port (wirtualny COM lub biblioteką D2XX), np. otworzony program terminala, to Windows może traktować takie dane jako informacje z klawiatury/myszki. Powoduje to, że kursor zaczyna poruszać się w przypadkowy sposób, otwierają się okna, bufor klawiatury przepełnia się. W Linuksie nie stwierdziłem takich problemów. Błąd w Windows można łatwo naprawić. Każde otwarcie portu powoduje uaktywnieni linii DTR i RTS bez względu na to czy sterowanie przepływem jest włączone, czy nie. W układach FT22x można programowo odczytać stan tych linii i nie wysyłać danych, jeśli port nie jest otwarty. Warto też wspomnieć o możliwości generowania przerwań w razie pojawienia się znaku w odbiorniku linią CBUS.
Układy FT201, FT200
Układy mają interfejs I2C przesyłający dane z prędkością 3,4 Mb/s (FT200) lub 400 kb/s (FT201). Interfejs USB pracuje z prędkością 1 Mb/s, realny transfer to 1 Mb/s w FT200 i 200 kb/w w FT201. Mniejsza prędkość transmisji FT201 wynika z faktu, że przy przesłaniu każdej danej układ należy zaadresować i nie można (jak w przypadku układów z interfejsem SPI) wysłać komendy i dowolnej liczby danych. Nadawanie/odbiór z USB jest banalnie łatwe. Przy nadawaniu, po zaadresowaniu układu (domyślny adres 22) sprawdzamy czy układ potwierdził obecność ACK. Jeśli tak, to bufor nadawczy może odebrać najmniej jeden znak (listing 4). Przy odczycie, jeśli po zaadresowaniu układu do odczytu otrzymamy ACK oznacza to, że w buforze odbiorczym FIFO znajduje się co najmniej jeden znak do odczytu (listing 5).
Czyli na dobrą sprawę nie ma jak sprawdzić czy układ jest obecny na magistrali. Sygnał ACK przy odczycie jest tylko, gdy w FIFO znajduje się znak. Przy zapisie nie ma gwarancji, że układ skomunikował się z hostem (wtedy też nie da ACK), a jeśli tak, to znak zostanie wysłany przez USB co czasem może być niekorzystne (problem zamkniętego portu w Windows). Konstruktorzy układu, aby nie zmniejszać przepustowości komunikacji przez dodatkowe wysłanie komendy wykorzystali adres rozgłoszeniowy (broadcast). Co ciekawe, do niektórych operacji jest używany adres 0x7C.
Układ w sumie zajmuje aż 3 adresy I2C. Broadcast to adres 0x00. Pod ten adres jest wysyłana komenda dla FT20x. Komenda jest potwierdzona przez wszystkie układy slave obsługujące broadcast. Następnie pod adres układu (domyślnie 22) wysyłane/odbierane są dane. Przykład odczytu liczby znaków w FIFO pokazano na listingu 6.
Na listingu 7 pokazano przydatną funkcję, za której pomocą można sprawdzić status układu. Taka funkcja istnieje także dla układu FT22x. Dzięki niej można dowiedzieć się czy można już wysyłać odbierać dane przez USB (czy układ jest skonfigurowany, czy zakończono proces enumeracji).
Do identyfikacji układu, poza deskryptorem, można użyć 3 bajtów ID, przy czym jeden można ustawić z poziomu FT_PROG (rysunek 2). Mikrokontroler może odczytać ID używają funkcji z listingu 8. Wyróżniony fragment „0xF8/*0x7C*/” jest pewną niekonsekwencją w sposobie komunikacji z układem. W tym wypadku adres układu jest na stałe ustawiony przez producenta na 0x7C. Czemu tak to zrobiono? Nie jestem w stanie zrozumieć.
Pamięć MTP
Dostęp do tej pamięci zapewniają zarówno konwertery IIC jak i SPI. Dla ułatwienia wszystkie funkcje bibliotek dla FT22x jak i FT20x nazwałem tak samo. Różnią się tylko sufiksem:
ReadMtpFT201 – ReadMtpFT22x
PutCharFT201 – PutCharFT22x
Parametry funkcji są takie same tyle, że niektóre nie będą istniały. Na przykład, nie ma funkcji AvailableFT22x dla FT22x czy dla FT201: ReadModemFT201, SetModemFT201. Wracając do pamięci MTP. Jej obszar jest podzielony na kilka części – podział pokazano na rysunku 3. Obszary oznaczone zielonym kolorem można używać do swoich celów, przy czym „User Area 1” jest widoczny w aplikacji FT_PROG. Obszary „czerwone” są chronione sumą kontrolną. Sumę tę oblicza funkcja „CalculateMtpCrc” w bibliotece „FTDI.c”. Sumę kontrolną można odczytać także FT_PROG-iem, jak pokazano na rysunku 4.
Dokładniej omówimy obszar konfiguracji (czerwony). Jego mapę pokazano na rysunku 5. Można w nim zapisywać i odczytywać informacje o VID, PID, funkcjach CBUS, poborze prądu, itp. Oczywiście, zmiana adresu I2C nie odniesie skutku dla układów komunikujących się po SPI, podobnie jak konfiguracja nieistniejącego CBUS. Obszar od 0xA0 do 0xF8 (w słowach 0x50..0x7C) przechowuje informacje o nazwie interfejsu, producencie, numerze seryjnym. Wskaźniki do tego obszaru zawierają bajty 0x0E..0x13. Jak później pokażę, wskaźników tych w wielu wypadkach nie trzeba obliczać. Dość istotne znaczenie ma pierwszy bajt. W nim jest zawarta informacja między innymi o tym, czy ładować biblioteki VCP, czy nie. W przeciwieństwie do układów z rodziny FT232, FT23x, w mostkach IIC/SPI domyślnym ustawieniem jest nieładowanie VCP (ładowanie D2XX). Jest to o tyle istotne, że taki układ nie będzie widziany jako wirtualny COM i komunikacja z nim będzie możliwa tylko przez biblioteki D2XX. Można to zmienić za pomocą Menedżera Urządzeń zaznaczając opcję „załaduj VCP” jak na rysunku 6 lub lepiej – z użyciem FTProg, jak na rysunku 7. Dlaczego sugeruję robić to z poziomu FT_PROG? Otóż, jeśli zrobimy to w „Menedżerze Urządzeń”, to po zmianie deskryptora i enumeracji konieczne będzie powtórzenie operacji w „Menedżerze Urządzeń”. Jeśli zrobimy to w FT_PROG, to ta „wątpliwa przyjemność” ominie nas. Oczywiście, lepszym rozwiązaniem będzie zmiana bitu odpowiedzialnego za tę funkcje z poziomu mikrokontrolera. Jest siódmy bit (licząc od zera) pierwszego bajtu obszaru MTP (rysunek 8). Można to również wykonać za pomocą programu w sposób pokazany na listingu 9.
Sławomir Skrzyński, EP