logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

LPC2142 + RTC - brak wywołania przerwania od inkrementacji np. sekund

kk.krz 02 Paź 2017 23:00 1053 8
REKLAMA
  • #1 16734545
    kk.krz
    Poziom 4  
    Posty: 186
    Ocena: 2
    Chcę, aby mój RTC przy inkrementacji sekund wywołał przerwanie, w którym sobie np. sczytam dane z zegara...

    No to inicjuję RTC tak:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    i nijak mi procek nie wchodzi w procedurę obsługi przerwania show_time.

    RTC działa, sprawdzam go sobie we

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    i ładnie sekundy się zmieniają.
    A w przerwanie nie wchodzi i juz...
    Co może być jeszcze?
  • REKLAMA
  • #2 16735131
    es2
    Poziom 16  
    Posty: 226
    Pomógł: 8
    Ocena: 26
    Nie działa przerwanie tylko od RTC czy wszystkie?
  • REKLAMA
  • #3 16735340
    kk.krz
    Poziom 4  
    Posty: 186
    Ocena: 2
    Ogólnie przerwania chodzą, ale problem pewnie w tym, że w obsłudze przerwania od timera chce wyświetlić
    tekst na lcd (hd44780). LCD używam bez wykorzystania linii busy, więc wszystkie komendy idą na delayach zrealizowanych przez timer.


    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Więc stawiam na jakiś konflikt przerwań, chociaż chodzą w innych VIC, bo delay_ms chodzi
    na VIC1, a RTC robie na VIC0.

    O tak:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Jak widać zakomentowałem wysyłanie tekstu. No i teraz działa. A jak w obsłudze przerwania
    od RTC ma się wysłać tekst na LCD (a tam troche opóźnień jest na VIC1), to sie sypie i nie działa.

    Teoretycznie, moge zrobić w while(1) wypisywanie na lcd tego, co w zmiennych h,m i s odczytam w funkcji przerwania od RTC, ale to chyba niezbyt eleganckie w pętli nieskończonej ładować wciąż dane do LCD...

    Ale tak czy inaczej stawiam na to, że w mojej idei jest błąd, że obsługa przerwania od RTC
    zawiera czasochłonną instrukcję ( lcd_text(m_text);) w której siedzą delay'e...i to wszystko tak nie może być. Przerwanie od RTC to sczytanie czasu z rejestru do zmiennych i czym prędzej ucieczka z przerwania...A obsługa wyświetlania tych zmiennych na LCD to zrobić inaczej. Ale jak? Trzecie przerwanie co 1s czy we while sprawdzanie flagi zmiany np. sekund i jak się zmieni to wyświetlić nowy czas.
    Przepraszam...głośno sobie myślę...
  • REKLAMA
  • #4 16735698
    rb401
    Poziom 39  
    Posty: 3002
    Pomógł: 750
    Ocena: 984
    kk.krz napisał:
    Więc stawiam na jakiś konflikt przerwań


    Bardzo możliwe. Nie znam się akurat na ARM7TDMI-S ale generalnie jeśli priorytet przerwania od timera nie jest na tyle wyższy by przerwać obsługę przerwania od RTC, to naturalnym jest że obsługa przerwania RTC utknie w pierwszym delay_ms, na oczekiwaniu na odpowiednią wartość zmiennej flag, która to z kolei inkrementuje się wyłącznie w obsłudze przerwania od timera (które akurat wtedy w tym miejscu będzie niemożliwe do wykonania).
    Ewentualnie zmiana tych priorytetów był by rozwiązaniem.

    Niestety nie potrafię znaleźć dokumentu w którym konkretnie opisane są priorytety przerwań od peryferii w Twoim procesorze. Tak że podrzucam tylko hipotezę. Może masz gdzieś pod ręką taki opis to sprawdź.

    kk.krz napisał:
    A obsługa wyświetlania tych zmiennych na LCD to zrobić inaczej. Ale jak?


    Najprościej w ogóle nie robić obsługi LCD na przerwaniach, tylko w pętli głównej programu, ale poprzedzoną i uwarunkowaną sprawdzeniem flag, które to z kolei będą ustawiane przez obsługę przerwań w przypadku pojawienia się nowych danych do wyświetlenia i umieszczeniu ich w jakiś zmiennych volatile.
    Wtedy wyświetlacz jest modyfikowany wyłącznie w chwilach kiedy są nowe dane, a całość pracuje mało kolizyjnie np. taki delay_ms niczego nie zablokuje.

    Dodano po 1 [godziny] 2 [minuty]:

    Teraz doczytałem tu coś o przerwaniach w LPC2142:
    http://engenuics.com/wp-content/uploads/notes_mpgl1_chapter91.pdf
    i rzeczywiście standardowo nie ma możliwości przerwania obsługi jednego przerwania drugim niezależnie od ich priorytetów. Chyba że poprzez tryb FIQ ustawiony akurat dla przerwania timera, ale to oznacza dodatkowe problemy, moim zdaniem niepotrzebna komplikacja.
    Jeśli się bardzo upierasz by w przerwaniu używać coś takiego jak delay_ms, to trzeba by go przerobić tak by czytać, nie zmienną inkrementowaną w przerwaniu, a konkretny sprzętowy licznik (odpowiednio taktowany itp.), wtedy jest gwarancja że podczas obsługi przerwania będzie się zmieniał.
  • REKLAMA
  • #5 16736103
    kk.krz
    Poziom 4  
    Posty: 186
    Ocena: 2
    Na razie zrobiłem tak:

    Przerwanie RTC wywoływane jest inkrementacją sekund. Sekunde się inkrementuje, wywołuje się procedura przerwania, odczytywany jest w niej czas i wpisywany do zmiennych globalnych. W procedurze ustawia się flaga.

    W głównym programie, w pętli nieskończonej sprawdzana jest flaga. Gdy f==1 wykonywane jest wyświetlenie danych i wykonywane jest czyszczenie flagi f=0;

    No i działa.
  • #6 16736572
    rb401
    Poziom 39  
    Posty: 3002
    Pomógł: 750
    Ocena: 984
    kk.krz napisał:
    w pętli nieskończonej sprawdzana jest flaga. Gdy f==1 wykonywane jest wyświetlenie danych i wykonywane jest czyszczenie flagi f=0;


    To właśnie miałem na myśli.
    Tak dopowiem tu tylko, że w tym podejściu warto całe wyświetlanie podzielić na uruchamiane j/w osobnymi flagami części np. osobno każda liczba dotycząca czego innego (np. czas, temperatura status bateriii itp.) , osobno napisy stałe itd. Wtedy ustawienie danej flagi (niekoniecznie tylko z przerwania) powoduje wyłącznie modyfikację tylko fragmentu wyświetlacza (nadpisanie) co przyspiesza i likwiduje ewentualne migotanie. A ustawienie naraz wszystkich flag powoduje odrysowanie całego wyświetlacza, na samym początku programu czy np. po wyświetleniu jakiegoś komunikatu "całostronnicowego".
    Oczywiście przy wyświetlaniu liczb czy napisów zmiennej długości trzeba pamiętać o uzupełnianiu ich spacjami do stałego rozmiaru by nadpisać całkowicie co było pod nią wcześniej.
  • #7 16736970
    kk.krz
    Poziom 4  
    Posty: 186
    Ocena: 2
    Hm...a jak zatem rozumieć priorytety przerwań związane ze slotami? W instrukcji stoi, że VicVectCtl0 ma wyższy priorytet niż VicVectCtl1.
    Skoro mówisz, że jedynie FIQ może przerwać jakieś IRQ albo non vectored IRQ, to po co
    to całe priorytetowanie względem slotów?
  • Pomocny post
    #8 16737142
    rb401
    Poziom 39  
    Posty: 3002
    Pomógł: 750
    Ocena: 984
    kk.krz napisał:
    a jak zatem rozumieć priorytety przerwań związane ze slotami?


    Nie jestem biegły w ARM7, powtórzę, ale polegam tu na tej publikacji:

    http://engenuics.com/wp-content/uploads/notes_mpgl1_chapter91.pdf

    a szczególnie na tym fragmencie:


    Cytat:

    4.
    On the LPC214x processors, two hardware priority groups are available. The high priority interrupt is referred to as FIQ and the low priority interrupt is the IRQ. The low priority ISR can be interrupted by the higher priority interrupt. Another way to say that is that a high-priority interrupt can pre-empt a low-priority interrupt. Multiple interrupt sources can be assigned to either of the two groups using configuration registers.
    5.
    Active interrupts of the same hardware priority can be prioritized in firmware, so even if two interrupts occur simultaneously, the higher priority interrupt can be serviced first.
    6.
    An interrupt source can occur even if its ISR is already executing. Since interrupts of the same priority level are disabled while an ISR runs, the new interrupt event will not have any impact until the current ISR exits. The interrupt signal will trigger another call to the ISR as soon as the interrupts are re-enabled as the ISR exits, unless the ISR has cleared the new source event flag.


    z którego wynika, przynajmniej dla mnie, że priorytet wewnątrz grupy (np. grupy wszystkich IRQ) dotyczy tylko pierwszeństwa obsługi jeśli jest kolejka oczekujących przerwań.
    A wywłaszczanie (przerwanie obsługi) to inny temat i zachodzi tylko między grupami IRQ a FIQ.

    Tak na marginesie. Coś pamiętam że to właśnie elastyczna i bez udziwnień realizacja grup przerwań, wywłaszczeń przerwań itp, była intensywnie marketingowo wykorzystywana w promocji Cortexów M3 kiedy wchodziły na rynek, że tym są lepsze od "starych" ARM7. I tu to widać :wink: .

    A jeszcze, co do problemu głównego, czyli niedziałania delay_ms() wewnątrz obsługi przerwania od RTC, to zauważyłem że bardzo prosto można to poprawić (w ogóle ten delay_ms jest niepotrzebnie przekomplikowany). Wystarczy zlikwidować obsługę i włączenie przerwań od Timera0, wywalić zmienną flag a w jej miejsce w tym while (flag<time) użyć rejestru T0TC.
    A przy inicjalizacji timera preskaler (T0PR) ustawić tak, by na licznik timera wchodziło 1000Hz. I wtedy całe to wywłaszczanie w ogóle nie jest istotne.

Podsumowanie tematu

LABEL_AI_GENERATED
Użytkownik ma problem z wywołaniem przerwania od RTC przy inkrementacji sekund w mikrokontrolerze LPC2142. Mimo poprawnej inicjalizacji RTC, procedura obsługi przerwania nie jest wywoływana. Po dyskusji ustalono, że problem może wynikać z konfliktu priorytetów przerwań, gdzie obsługa przerwania od timera blokuje wywołanie przerwania RTC. Użytkownik zmodyfikował kod, aby w procedurze przerwania RTC ustawiać flagę, a w głównym programie sprawdzać tę flagę przed wyświetleniem danych na LCD. To rozwiązanie okazało się skuteczne. Dodatkowo, zasugerowano, aby wyświetlanie danych na LCD było podzielone na różne flagi, co poprawi wydajność i zminimalizuje migotanie.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA