2010-05-02 8 views
7

Chciałbym mieć kod, który musi zostać uruchomiony w wyniku przerwania określonego przerwania.Które przerwań Cortex-M3 można użyć do pracy ogólnego przeznaczenia?

Nie chcę wykonywać go w kontekście samego przerwania, ale także nie chcę, aby był wykonywany w trybie wątku.

Chciałbym uruchomić go z priorytetem, który jest niższy niż przerwanie wysokiego poziomu, które przyspieszyło jego działanie, ale także priorytet wyższy niż poziom wątku (i niektóre inne przerwań również).

Myślę, że potrzebuję użyć jednego z innych programów obsługi przerwań.

Które z nich najlepiej używać i jak najlepiej je wywoływać?

W tej chwili mam zamiar używać tylko procedur obsługi przerwań dla niektórych urządzeń peryferyjnych, których nie używam i wywołując je poprzez ustawienie bitów bezpośrednio przez NVIC, ale miałem nadzieję, że jest lepszy, bardziej oficjalny sposób.

Dzięki,

Odpowiedz

15

ARM Cortex obsługuje wyjątek specjalny o nazwie PendSV. Wygląda na to, że możesz użyć tego wyjątku dokładnie do wykonania swojej pracy. Praktycznie wszystkie wyprzedzające RTOS dla ARM Cortex używają PendSV do implementacji przełącznika kontekstu.

Aby to działało, musisz nadać priorytet niskiej wartości PendSV (napisz 0xFF do rejestru PRI_14 w NVIC). Powinieneś także nadać priorytet wszystkim przerywnikom IRQ powyżej PendSV (zapisz niższe liczby w odpowiednich rejestrach priorytetowych w NVIC). Gdy jesteś gotowy, aby przetworzyć całą wiadomość, wywołać PendSV z wysokim priorytecie ISR:

*((uint32_t volatile *)0xE000ED04) = 0x10000000; // trigger PendSV 

ARM Cortex CPU wtedy kasy ISR i wszystkie inne ISR, które ewentualnie zostały wywłaszczony przez niego i ostatecznie go będzie ogonować łańcuch do wyjątku PendSV. Tutaj powinien znajdować się twój kod do analizowania wiadomości.

Należy pamiętać, że PendSV może zostać wywłaszczony przez innych ISR. Wszystko jest w porządku, ale musisz oczywiście pamiętać, aby chronić wszystkie udostępnione zasoby przez krytyczną sekcję kodu (krótko wyłączając i włączając przerywanie). W ARM Cortex wyłączasz przerwania, wykonując __asm ​​("cpsid i") i włączasz przerywanie przez __asm ​​("cpsie i"). (Większość kompilatorów języka C udostępnia wbudowane funkcje wewnętrzne lub makra do tego celu.)

+0

Dzięki, Miro! Szukałem wszędzie informacji o tym, jak uruchomić przerwanie PendSV, i to jest, gdzie w końcu znalazłem! Chociaż przypuszczam, że przeczytałbym bardziej uważnie mój podręcznik techniczny Cortex M3 r1p1, znalazłbym go na stronie opisującej rejestr państwa kontroli przerwań: http://infocenter.arm.com/help/topic/com.arm .doc.ddi0337e/DDI0337E_cortex_m3_r1p1_trm.pdf –

+0

Z mojego odczytu Prawie cały czas RTOS na CortexM3 wykorzystuje przerwanie Timera Systicka (45 dziesiętnych, 2D hex) do uruchomienia ich harmonogramu. W takim razie PendSV jest sposobem na zainicjowanie specjalnej "syscall"? Mam nadzieję, że to rozumiem. –

+1

@WarrenP: PendSV służy do obsługi przełącznika kontekstu. Znacznik sys jest używany do zadań typu round-robin - sys tick z kolei generalnie ustawia PendSV. –

3

Czy korzystasz z systemu operacyjnego czasu rzeczywistego? Ogólnie rzecz biorąc, ten typ rzeczy byłby obsługiwany przez posiadanie wątku o wysokim priorytecie, który zostanie zasygnalizowany, aby wykonać jakąś pracę przez przerwanie.

Jeśli nie korzystasz z systemu operacyjnego czasu rzeczywistego, masz tylko kilka zadań, a praca wykonywana przez przerwanie nie wymaga dużego nakładu zasobów, najprościej może być wykonanie zadania o wysokim priorytecie w kontekście przerywacz. Jeśli te warunki nie zostaną spełnione, wdrożenie tego, co mówisz, będzie początkiem podstawowego wielozadaniowego systemu operacyjnego. To może być interesujący projekt sam w sobie, ale jeśli chcesz po prostu wykonać pracę, możesz rozważyć prosty RTOS.

Skoro wspomniano kilka szczegółów na temat pracy robisz, oto przegląd jak mam obchodzić podobny problem w przeszłości:

Dla obsługi otrzymanych danych przez UART jednym ze sposobów, że mam używane w przypadku prostszego systemu, który nie ma pełnego wsparcia dla zadań (tj. zadania są zaokrąglone i na prostej pętli while) ma mieć wspólną kolejkę dla danych, które zostały odebrane z UART. Po uruchomieniu przerwania UART dane są odczytywane z rejestru RDR (Receive Data Register) UART i umieszczane w kolejce. Sztuczka, która radzi sobie z tym w taki sposób, że wskaźniki kolejki nie są uszkodzone, to ostrożne ustawianie wskaźników kolejek i upewnianie się, że tylko przerywnik modyfikuje wskaźnik końcowy i że tylko zadanie "pierwszego planu" odczytuje dane z kolejki zmodyfikował wskaźnik główny. Przegląd danych na wysokim poziomie:

  • wytwórca (procedura obsługi przerwania UART):

    1. czytać queue.head i queue.tail do mieszkańców;
    2. inkrement lokalnego wskaźnika ogonka (nie rzeczywistego wskaźnika queue.tail). Owiń go na początku buforu kolejek, jeśli inkrementujesz po zakończeniu buforu kolejki.
    3. Porównaj local.tail i local.head - jeśli są one równe, kolejka jest pełna, a będziesz musiał zrobić to, co jest właściwe.
    4. inaczej można zapisać nowe dane do gdzie local.tail punkty
    5. dopiero teraz można ustawić queue.tail == local.tail
    6. powrót z przerwania (lub obsługiwać inne zadania związane z UART, jeśli stosowne, jak czytanie z kolejki nadawczej)
  • konsumentów ('zadania' na pierwszym planie)

    1. czytać queue.head i queue.tail do mieszkańców;
    2. jeśli local.head == local.tail kolejka jest pusta; powrót do niech następnym zadaniem popracować
    3. odczytać bajt wskazywanego przez local.head
    4. przyrostu local.head i zawinąć go w razie potrzeby;
    5. ustawić queue.head = local.head
    6. goto krok 1

Upewnij się, że queue.head i queue.tailvolatile (lub napisać te bity w zespole), aby upewnić się, że nie istnieją żadne problemy sekwencjonowania.

Teraz wystarczy upewnić się, że kolejka danych odbieranych przez system UART jest wystarczająco duża, aby pomieścić wszystkie bajty, które można odebrać, zanim zadanie pierwszego planu zostanie uruchomione. Zadanie pierwszego planu musi wyciągnąć dane z kolejki do własnych buforów, aby zebrać wiadomości do zadania "procesor wiadomości".

+0

Nie korzystam z systemu operacyjnego czasu rzeczywistego. To, co mam, to przerwanie o wysokim priorytecie, które włącza się za każdym razem, gdy otrzymuję bajty przez port szeregowy. Działa na wysokim priorytecie (o niskim priorytecie), więc nie pomijam bajtów. Po otrzymaniu kompletnej wiadomości muszę wykonać pewną pracę i chociaż mam zamiar, aby ta praca nie miała charakteru całkowicie blokującego, nie chcę ograniczać się do posiadania maksymalnej dozwolonej ilości czasu (Nie będę pisać tego kodu). Nie robię żadnej wielozadaniowości zapobiegawczej. –

+0

Jaka jest prędkość danych szeregowych? Czy wskaźnik jest naprawdę tak wysoki lub inne procedury obsługi przerwań są tak źle zaprojektowane, że poziom priorytetu przerwań będzie miał znaczenie? Dlaczego nie skorzystać z transferów DMA, aby zmniejszyć częstotliwość przerwania lub całkowicie ich uniknąć? – Clifford

+0

Pracujemy na 57600, ale prawdopodobnie wzrośnie do 115200. Nie mogę używać transferów DMA w drodze, ponieważ to, co sygnalizuje koniec wiadomości, to czas pomiędzy bajtami przekraczającymi pewną liczbę. Mam trzy zadania, które muszę uruchomić: 1. odbiornik/nadajnik z komunikatem szeregowym 2. procesor komunikatów 3. pewne podnoszenie ciężarów w tle. Środkowa to maszyna państwowa, więc nie ma prawie żadnej pracy (wystarczy zaktualizować stan). Chciałbym, żeby były uruchamiane w różnych poziomach przerwań, ponieważ brakujące terminy na niższych poziomach są mniej trudne do debugowania (dla mnie). –

1

"Bardziej oficjalna metoda", a raczej metoda konwencjonalna, to stosowanie opartego na priorytetach, wyprzedzającego wielozadaniowego programu szeregującego i wzorca "odroczonego przerwań".

+0

@Clifford: Czy masz link do opisu "odroczonego wzorca przerwania"? – simon

0

Sprawdź dokumentację procesora. Niektóre procesory przerywają, jeśli napiszesz bit, który normalnie musisz wyczyścić wewnątrz przerwania.Obecnie używam SiLabs c8051F344 i w arkuszu specyfikacji sekcja 9.3.1:

"Oprogramowanie może symulować przerwanie poprzez ustawienie dowolnej flagi oczekującej na przerwanie na logikę 1. Jeśli dla flagi zostaną włączone przerwań, żądanie przerwania będzie być generowane, a procesor będzie wektorem do adresu ISR powiązanego z flagą oczekującą na przerwanie. "

1

To, o co prosisz, jest bardzo proste w Cortex-M3. Musisz włączyć rejestr STIR, aby móc wywołać ISR o niskim priorytecie z oprogramowaniem. Kiedy ISR o wysokim priorytecie zostanie zrobiony z kluczowymi elementami, po prostu uruchamia przerwanie o niskim priorytecie i kończy działanie. NVIC będzie następnie łączyć łańcuch z obsługą obsługi o niskim priorytecie, jeśli nie ma już nic ważniejszego.

Powiązane problemy