Jak skutecznie dekodować niestandardowy sygnał szeregowy

11

Jestem studentem zespołu badawczego pracującego nad projektem, który dotyczy ASIC transmitującego RF i jego bezprzewodowego odbiornika, który powinien ostatecznie wysyłać dane do komputera.

Odbiornik wysyła szybki , ciągły, asynchroniczny, niestandardowy sygnał szeregowy (tj. Nie SPI, I2C, UART itp.), Więc moim zadaniem jest napisanie oprogramowania mikrokontrolera w celu połączenia odbiornika z komputerem. Obecnie moim podejściem jest użycie przerwań wyzwalanych zboczem do umieszczenia danych w okrągłym buforze i wykonania całego procesu dekodowania krok po kroku w głównej pętli. Mikrokontroler musi jednocześnie wysyłać te dane za pomocą USB (wirtualny port COM) do komputera.

Mam problem, którego oczekuję:

  1. Nie mogę przetworzyć buforowanych danych wystarczająco szybko, nawet z moim dość potężnym procesorem ARM Cortex M3 o częstotliwości 72 MHz. Szybkość transmisji wynosi 400 Kb / s (2,5 us / bit). Dla odniesienia, który pozostawia tylko 180 cykli na bit (w tym dekodowanie ORAZ ISR, który ma ~ 30 cykli narzutu!). MCU musi również obsługiwać wiele innych zadań, do których sprawdza w głównej pętli.

  2. Sterownik wirtualnego portu USB na komputerze jest również oparty na przerwie. Daje mi to prawie pewność, że sterownik ostatecznie przerwie procesor tak długo, że ominie okno 2,5 mikrosekundy (180 cykli), w którym może zostać przesłany bit. Nie jestem pewien, w jaki sposób konflikty przerwane / wyścigi są zwykle rozwiązywane.

Pytanie brzmi po prostu: co można zrobić, aby rozwiązać te problemy, czy nie jest to w ogóle właściwe podejście? Jestem skłonny rozważyć również podejście mniej skoncentrowane na oprogramowaniu. Na przykład przy użyciu dedykowanego układu USB z jakimś sprzętowym urządzeniem stanu do dekodowania, ale to nieznane terytorium.

Keegan Jay
źródło
Muszę powiedzieć, że rzadko widzę, że wiele sugestii, na które lubię szybko odpowiedzieć, dobrze przemawia na twoje pytanie. Byłbym zainteresowany dowiedzieć się więcej o seriach danych. Czy są one gwałtowne, nagle pełne prędkości, a następnie okresy niskiej ilości danych, czy jest prawdopodobne, że wybrałbyś dłuższy okres z ciągłymi danymi?
Kortuk
Dopóki ASIC ma moc, wysyła ciągły strumień danych. W ogóle nie jest rozerwana. Jest to aplikacja wykrywająca w czasie rzeczywistym z odczytem komputerowym. Widziałeś kiedyś EKG?
Keegan Jay
Tyle wspaniałych odpowiedzi tutaj. Widziałem wyraźny podział między rozwiązaniami obejmującymi zmiany przerwań a rozwiązaniami obejmującymi dedykowaną logikę sprzętową / cyfrową. Rzeczy takie jak FPGA i Verilog, które znam, ale jeszcze nie mam doświadczenia, więc oznacza to, że należy je uratować na dłuższą metę. W krótkoterminowych @rocketmagnets metoda mniej intensywna przerwań jest w porządku. Podoba mi się elegancja poświęcania służebnych zadań logice cyfrowej i zapisywania ARM na prawdziwe obliczenia. W przyszłości moc ARM będzie wykorzystywana do analizy i filtrowania bezprzewodowych danych szeregowych.
Keegan Jay
Czy sygnał jest synchroniczny czy asynchroniczny?
markrages
Asynchroniczny. 4 bity początkowe, 10 bitów danych, 2 bity stopu. Ze względu na charakter transmitowanego ASIC czasy HI i LO różnią się znacznie w poszczególnych układach. Napisałem już algorytm, aby wydedukować szybkość transmisji.
Keegan Jay

Odpowiedzi:

5

Inna odpowiedź: przestań używać przerwań.

Ludzie zbyt łatwo skaczą, by używać przerwań. Osobiście rzadko ich używam, ponieważ faktycznie tracą dużo czasu, jak odkrywasz.

Często można napisać główną pętlę, która sonduje wszystko tak szybko, że opóźnienie mieści się w zakresie specyfikacji i bardzo mało czasu jest tracone.

loop
{
    if (serial_bit_ready)
    {
        // shift serial bit into a byte
    }

    if (serial_byte_ready)
    {
        // decode serial data
    }

    if (enough_serial_bytes_available)
    {
        // more decoding
    }        

    if (usb_queue_not_empty)
    {
        // handle USB data
    }        
}

Niektóre pętle mogą występować znacznie częściej niż inne. Być może na przykład przychodzące bity, w takim przypadku dodaj więcej tych testów, aby więcej procesorów było dedykowanych temu zadaniu.

loop
{
    if (serial_bit_ready)
    {
        // shift serial bit into a byte
    }

    if (serial_byte_ready)
    {
        // decode serial data
    }

    if (serial_bit_ready)
    {
        // shift serial bit into a byte
    }

    if (enough_serial_bytes_available)
    {
        // more decoding
    }        

    if (serial_bit_ready)
    {
        // shift serial bit into a byte
    }

    if (usb_queue_not_empty)
    {
        // handle USB data
    }        
}

Mogą wystąpić pewne zdarzenia, dla których opóźnienie tego podejścia jest zbyt duże. Na przykład może być potrzebne bardzo dokładne zdarzenie. W takim przypadku należy mieć to zdarzenie na przerwie i mieć wszystko inne w pętli.

Rocketmagnet
źródło
Lubię twoją odpowiedź bardziej niż odpowiedź innej osoby Rocketmagnet. Zamiast więcej oprogramowania hadrware, szybszego sprzętu, czegoś więcej, Rocketmagnet, sugerujesz: rób mniej, lepiej, prościej.
Okej, widziałem wiele przypadków, w których przerwania znacznie poprawiły rozwiązanie. Robią świetne rzeczy, umożliwiają dobrze ustrukturyzowany kod, małe opóźnienia i wiele innych zalet, ale muszę się z tobą zgodzić. Wygląda na to, że proces jest tak intensywny, że 1 kontroler może potrzebować poświęcić każdą część swojej uwagi na obsługę strumienia szeregowego. Cyfrowy interfejs wydaje mi się idealny, ale wiele razy masz jakieś mikroskopy i nie ma FPGA, gdy jest to projekt szkolny, prawdopodobnie poświęciłbym mikro na obsługę go najpierw, a później spróbuję dopasować FPGA, aby zastąpić go koszt.
Kortuk
Jest to prawdopodobnie rozwiązanie, na które pójdę w krótkim okresie. Miałem nadzieję tego uniknąć, ponieważ wiąże się to z przepisywaniem sporej części istniejących sterowników szeregowych, ale jest to eleganckie rozwiązanie, które jest w moich możliwościach w krótkim czasie.
Keegan Jay
1
@JayKeegan - Tak, to prawdopodobnie najszybsza droga do rozwiązania. PSoC i FPGA mogą być podejściem do następnego projektu.
Rocketmagnet
6

Możesz użyć FPGA zamiast Mikrokontrolera do dekodowania i buforowania bezprzewodowego strumienia danych. Następnie użyj procesora ARM, aby opróżnić bufory FPGA (np. Używając interfejsu SPI) i wysłać zawartość przez port USB Comm. To działa, ale FPGA powinna być w stanie łatwo nadążyć, o ile jesteś w stanie obsługiwać go wystarczająco często, aby zagwarantować, że jego bufory sprzętowe nie zostaną przepełnione (lub jeśli poradzisz sobie z upuszczonymi danymi na wyższym poziomie protokołu ).

vicatcu
źródło
To może być doskonałe rozwiązanie na dłuższą metę. Miałem nadzieję, że oprócz rozwiązań programowych otrzymałem wiele cyfrowych rozwiązań logicznych / sprzętowych, ponieważ teraz mam wymówkę, aby dowiedzieć się o tych rzeczach! Niestety nie mam jeszcze doświadczenia z układami FPGA.
Keegan Jay
6

Łatwo: użyj mikrokontrolera PSoC5 .

PSoC

Mikrokontroler jest łatwy w obsłudze, a ponadto zawiera CPLD, dzięki czemu możesz pisać własne urządzenia peryferyjne w Verilog. Po prostu napisz swój szeregowy dekoder danych w verilog i użyj DMA, aby przesłać go strumieniowo do portu USB.

Tymczasem potężny 32-bitowy rdzeń ARM może zmieniać instrukcje kciuka.

Rocketmagnet
źródło
Strona przeglądu nie zawiera częstotliwości zegara, co wzbudziło moje podejrzenia. Arkusz danych mówi 40 MHz (zauważyłem również 6 mA przy 6 MHz). To połowa tego, co ma teraz OP. „MCU musi również obsługiwać wiele innych zadań”, więc może zależeć od tego, czy to dobry pomysł, czy nie.
stevenvh
Idą w górę do 67 MHz. Jest więc prawie tak szybki jak obecny procesor OP, z tym wyjątkiem, że większość pracy zostanie wykonana sprzętowo, pozostawiając procesorowi znacznie więcej wolnego czasu.
Rocketmagnet
1
Nie spojrzałem na wszystkie arkusze danych. Pierwszy, który wybrałem, powiedział 40 MHz.
stevenvh
@stevenvh - Mają różne stopnie prędkości. Trzecią liczbą w PN jest klasa prędkości. (4 = 48 MHz, 6 = 67 MHz).
Rocketmagnet
1
Jest to również fantastyczne rozwiązanie na dłuższą metę, podobnie jak pomysł FPGA. Nigdy nie słyszałem o tego typu układzie, ale łączy on wiele funkcji z reszty mojej płyty w jednym układzie. W przyszłości może to oznaczać, że cały odbiornik zmieści się na czymś wielkości napędu kciuka, co jest wizją mojego projektu. Będę uczyć się Verilog w następnym semeseter.
Keegan Jay
4

Myślę, że masz do wyboru klasyczny wybór inżynierii: szybki, tani, działa: wybierz dwa.

Rozwiązanie @ vicatcu jest z pewnością dobre, ale jeśli nie możesz lub nie chcesz dodać do niego więcej sprzętu (w tym szybszego procesora), musisz dokonać wyboru. Jeśli to łącze szeregowe jest najważniejsze, powinieneś siedzieć w ISR, aż wszystkie bity zostaną zebrane. 180 instrukcji na bit nie jest wcale takie złe, ale nie próbuj robić wszystkiego. Po wykryciu początku transferu obracaj, aż transfer zostanie zakończony. Umieść wynik w FIFO, a następnie wznów normalne przetwarzanie.

Nie mówisz, jak długo trwa każda transmisja, ale jeśli są krótkie i pękające, byłoby to realne rozwiązanie. Założę się, że twoja implementacja wirtualnego portu COM ma również buforowanie sprzętowe, więc „opóźniona” usługa przerwań dla niego nie powinna przysparzać zbyt wiele problemów. Jeśli chodzi o resztę tego, co MCU musi zrobić ... musisz podjąć pewne decyzje projektowe.

akohlsmith
źródło
To rozwiązanie stanowi uzupełnienie podejścia Rocketmana do zmniejszenia liczby sterowników opartych na przerwie. Mogę zachować główny sterownik szeregowy, o którym wspomniałem, jako oparty na przerwie. Spróbuję też obracać, aż cała klatka zostanie odczytana, jak wspomniałeś.
Keegan Jay
3

Przede wszystkim podobają mi się niektóre odpowiedzi tutaj, a niektóre uzyskały mój głos.

Ale żeby rzucić jeszcze jedno możliwe rozwiązanie: biorąc pod uwagę ograniczenia twojego projektu, dodanie drugiego mikrokontrolera byłoby złe (czy wymagałoby to innego uruchomienia płyty)? Może prosty 8-bitowy mikrokontroler, który łączy się z Cortex-M3 za pomocą szybkiego urządzenia peryferyjnego, takiego jak SPI. Wybrany 8-bitowy kontroler odpytuje w poszukiwaniu bitów i bajtów form, tak jak w wybranej odpowiedzi, ale gdy ma bajt, może zrzucić go do rejestru danych SPI w celu przesłania.

Strona kory-M3 po prostu zakłóciłaby otrzymane dane SPI. To obniża twoje poprzednie 400 KHz przerwanie wyzwalane zboczem do 50 KHz.

Dwa powody, dla których to sugeruję, to fakt, że niektóre inne metody (PSoC lub dodane FPGA) są nieco drogie (chociaż prawdopodobnie nie ma to znaczenia w przypadku niewielkiego projektu akademickiego) i ponieważ może to pozwolić na zachowanie niektórych struktura twojego obecnego kodu.

Poza tym myślę, że pomysł PSoC jest niesamowity, jeśli masz własne niestandardowe urządzenie peryferyjne przesyłane przez DMA na USB.

Jon L.
źródło
To właściwie plan, który miałem na myśli, publikując to. Jeśli nie mogę usprawnić oprogramowania poprzez zmniejszenie zależności od przerwań (wybrana odpowiedź), to na pewno to zrobię. Ale tak, będzie to wymagało kolejnego uruchomienia płyty, prawdopodobnie dwóch, ponieważ mam problemy z poprawieniem moich projektów za pierwszym razem.
Keegan Jay
@JayKeegan, haha ​​witaj w klubie!
Jon L
2

Jeśli twój format danych jest podobny do formatu UART, ale z nieprzewidywalną, ale spójną szybkością transmisji, chętnie użyję CPLD do konwersji każdego słowa przychodzących danych na format SPI lub standardowy asynchroniczny. Nie sądzę, że trzeba wcisnąć się w królestwo CPLD. W rzeczywistości nawet dyskretna logika może być praktycznie wykonalna. Jeśli mógłbyś wygenerować zegar, który był o smidgin ponad 5 razy wyższy niż pożądana szybkość danych, możesz użyć licznika dzielenie przez pięć i dzielenie przez 16 z kilkoma bramkami. Ustaw licznik dzielenia na pięć, aby był resetowany za każdym razem, gdy wejście jest bezczynne, a licznik dzielenia na 16 jest zerowy. W przeciwnym razie wygeneruj impuls zegarowy SPI i uderz licznik dzielenia przez 16 za każdym razem, gdy licznik dzielenia przez pięć uderzy 2.

Biorąc pod uwagę 5-krotny zegar, można wygenerować zegar SPI przy użyciu 16V8 (najmniejsze i najtańsze obecnie dostępne programowalne urządzenie logiczne). Drugi 16V8 lub 22V10 może być użyty jako dzielnik ułamkowej prędkości do wygenerowania 5-krotnego zegara lub można użyć nieco większego układu (CPLD) i zrobić wszystko w jednym.

Edytuj / uzupełnienie

Po dalszym rozważeniu, jeśli zamierza się zastosować CPLD, można łatwo dodać kilka dodatkowych ulepszeń do obwodu. Na przykład, można dość łatwo dodać logikę, aby utknąć w obwodzie, dopóki nie otrzyma co najmniej 1,5 bitu bitu stopu, a następnie 3,5 bitu bitu startu; jeśli otrzyma zbyt krótki bit startu, powinien wrócić do szukania bitu stopu. Ponadto, jeśli używasz SPI, możesz użyć sygnału / CS, aby upewnić się, że urządzenie odbierające zobaczy prawidłowo oprawione dane. Jeśli urządzenie odbierające dane SPI może obsługiwać ramki 10-bitowe, można wysłać takie ramki bezpośrednio. W przeciwnym razie każda dziesięciobitowa ramka mogłaby zostać wysłana jako 8-bitowa ramka z zestawem LSB (7 bitów danych) i ramka z czystymi wszystkimi LSB (3 bity danych); zegar SPI byłby przyspieszany podczas bitów stopu, aby wszystkie dane były wysyłane.

Niektóre mikrokontrolery mają dość wszechstronne moduły generowania PWM, które obejmują między innymi możliwość utrzymywania resetowania przez sygnał zewnętrzny i synchronizację ich taktowania do uwolnienia takiego sygnału. Jeśli twój mikrokontroler może to zrobić, w zależności od jego dokładnych cech, może to znacznie uprościć CPLD lub zespół generowania taktowania.

Innym podejściem, do którego Rocketmagnet nieco się dotknął, byłoby posiadanie małej mikroprocesora, którego jedynym celem jest dekodowanie danych szeregowych i konwersja ich do formatu używanego przez główny mikro. Szybkość transmisji danych 400 KHz jest dość szybka do dekodowania programowego, ale coś takiego jak PIC poradziłoby sobie z tym, gdyby nie musiał robić nic innego w tym samym czasie. W zależności od tego, jakie urządzenia znasz, może to być łatwiejsze lub trudniejsze niż korzystanie z CPLD.

supercat
źródło
Wszystko to będzie bardzo cenne przy projektowaniu cyfrowej logiki do dekodowania. Rzeczywiście będę generować jako SPI. Na razie właśnie dekoduję za pomocą samodzielnego MCU (ograniczenia czasowe). Dziękuję Ci!
Keegan Jay,