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

Wyjście z przerwanie, wyzerowanie stosu, czyli powrót do....

wind_energy 18 Lis 2010 15:15 2259 23
  • #1 8759055
    wind_energy
    Poziom 14  
    Witam,
    Nic nie przychodzi mi do głowy, choć rozwiązanie jest z pewnościa banalne.
    Chodzi o to, że jeżeli nastąpi przerwanie z INTn, po jego wykonaniu uP ma wrócić do głównej pętli, czyli zakończyć wykonywany podprogram niezależnie w którym miejscu został przerwany. Nie wiem jakiej instrukcji użyć być może z assemblera, którego już w ogóle nie pamiętam - reti to powrót do podprogramu. Piszę w C. Dziękuję za pomoc i olśnienie mojego umysłu.
    Pozdrawiam,
    WE
  • #2 8759062
    tadzik85
    Poziom 38  
    Pętlę glówną definiujesz jako funkcję np. main_func(). Przed nią w main ustawiasz SP na max. A w twoim przerwaniu po prostu wywołujesz funkcję main_func.

    Trochę to wykombinowane, ale działa bez zarzutu. Tworząc coś w rodzaju resetu aplikacji.
  • #4 8759080
    tadzik85
    Poziom 38  
    W C wyjście z przerwanie dodawane jest automatycznie. Zmyliło mnie twoje zerowanie stosu w temacie.
  • #5 8759141
    Konto nie istnieje
    Poziom 1  
  • #6 8759270
    tmf
    VIP Zasłużony dla elektroda
    Nie do końca nic nie musi robić - musi poinformować kompilator, że dana funkcja jest kodem obsługi przerwania - może to zrobić stosując makro ISR, chyba, że woli babrać się w attribute signal.
  • #7 8759315
    wind_energy
    Poziom 14  
    Freddie - takie zastosowanie musi być tylko dla jednego z INT`a, natomiast dla drugiego musi działać normalnie, czyli wracać do podprogramu - nie mogę zastosować globalnej struktury. Tadzik - nie bardzo rozumiem jak zrobić reset o którym piszesz bo podprogram w przerwaniu z INT`a to zupełnie inna historia niż pętla główna - po przerwaniu ma się wykonać jego podprogram, a następnie wrócić do początku pętli głównej.
    Atom - też pomyślałem o ret, ale gdzie to wstawić, bo ret wychodzi z podprogramu, a nie z podprogramu przerwania?
    Proszę o dalsze sugestie.
  • #8 8759341
    tmf
    VIP Zasłużony dla elektroda
    Kolego, czas zaglądnąć do książek. Jak pisali poprzednicy, nic nie musisz robić - tylko napisać procedurę obsługi przerwania opatrując ją odpowiednimi atrybutami, co załatwia makro ISR. Zobacz w helpie do avr-libc przykłady i opis do interrupt.h.
  • #9 8759359
    tadzik85
    Poziom 38  
    Lepiej powiedz dokładnie dokąd chcesz wrócić z tego przerwania. czy do miejsca w którym jego wywołanie przerwało twój program czy do konkretnego miejsca w programie, niezależnego od etapu jego wykonywania.
  • #10 8759363
    wind_energy
    Poziom 14  
    TMF - mój kompilator to IAR, więc nie dogadamy się po bibliotece avr-libc.
    Jeżeli nie macie pomysłu jak załatwić to w kodzie, niestety będę zmuszony usiąść do bardzo słabo napisanego manuala IAR`a, nie ukrywam, że wieczór przed tym to katusze. Myślałem, że konsultacja z Wami natchnie mnie jak zrobić to w kodzie.

    Dodano po 6 [minuty]:

    Tadzik, mamy coś takiego

    void podprogram()
    {
    rozkazy1; //A
    rozkazy2;
    rozkazy3;
    }
    
    void main(){
    
    rozkazyx;
    while(1)
    {
    rozkazyx;  //B
    }
    
    #pragma vector= INT1_vect 
    __interrupt void przerwanie_INT1(void)
    {
    rozkazyx;  //C
    }


    Jesteśmy w punkcie A, uP wykonuje rozkazy1 i rozkazy2, przychodzi przerwanie. Przechodzimy do punktu C, wykonuje rozkazyx, kończy i idzie do B, czyli do głównej pętli, czyli zapomina o rozkazie 3 z punktu A.
    [/code]
  • #11 8759411
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Zawsze możesz włączyć watchdoga i "zapętlić się" - reset układu będzie sprzętowy, a więc zawsze pewniejszy niż jakieś programowe skoki gdzieś-tam.

    Rozwiązań jest setka, wybór konkretnego zależy od specyficznego przypadku i dokładnych założeń.

    4\/3!!
  • Pomocny post
    #12 8759429
    tadzik85
    Poziom 38  
    main()
    {
    /inicjacja
    flag = 0;
    sp= ram_end
    main_funck()
    
    }
    
    main_funck()
    {
    
    do
    {
    if(flag = 0)
    {
    //a
    }
    b
    c
    flag = 0;
    while();
    
    }
    
    int()
    {
        set flag
       //c
    sp = ram_end
       main_func();
    }


    pisane na szybko. Pomiędzy instrukcjami a - b musisz znajdować się na poziomie funkcji main_funck
  • #13 8759439
    wind_energy
    Poziom 14  
    Nie mogę użyć watchdoga, bo to zbyt duży program i co chwilę musiałbym karmić pieska. Rozwiązań z pewnością jest ich setka, ale wszystkie rozwiązania mile widziane.
  • #14 8759610
    Konto nie istnieje
    Poziom 1  
  • #15 8760372
    janbernat
    Poziom 38  
    Cytat:

    Jesteśmy w punkcie A, uP wykonuje rozkazy1 i rozkazy2, przychodzi przerwanie. Przechodzimy do punktu C, wykonuje rozkazyx, kończy i idzie do B, czyli do głównej pętli, czyli zapomina o rozkazie 3 z punktu A.

    A dlaczego idzie do B a nie tam gdzie przerwanie zostało wywołane czyli do rozkazy3 albo w środek rozkazy2 jeśli tam było wywołane?
    Przecież to nie początek programu po resecie i nie musi zaczynać się od main().
  • #16 8760625
    tmf
    VIP Zasłużony dla elektroda
    Zamiast tak kombinować nie lepiej to zrobić jak należy - czyli np. flagę i ją sprawdzać w procedurze? W AVR-libc (przypuszczam, żę w IAR podobnie) można zapamiętać stan stosu i potem do niego w dowolnej chwili wracać - zobacz setjmp/longjmp. Jeśli nie wiesz jaki jest odpowiednik w IAR, to od czego masz technical support - w końcu wydałeś kupę kasy na kompilator, to ich pomęcz.
  • #17 8761385
    wind_energy
    Poziom 14  
    A co powiecie na zerowanie stosu? Właśnie wyzerowany stos w warunku, gdy podprogram z punktu A nie zakończył się,nie wie gdzie wrócić więc wraca do początku. Zeruje SPH i SPL, uP wraca do początku, jak po resecie:)

    Dodano po 1 [minuty]:

    Tak wydaliśmy trochę kasy, ale C wygląda jak C i może do tego usiąść większość programistów C++.
  • #18 8761593
    Freddie Chopin
    Specjalista - Mikrokontrolery
    wind_energy napisał:
    Zeruje SPH i SPL, uP wraca do początku, jak po resecie:)

    Stan przerwań - nieznany. Stan peryferiów - nieznany. Stan zmiennych statycznych - nieznany. => Efekt takiej operacji - nieznany.

    4\/3!!
  • Pomocny post
    #19 8761751
    kemot55
    Poziom 31  
    Ja też bym to realizował poprzez WATCHDOG'a. Tyle tylko, że nie musisz z niego korzystać cały czas a włączać programowo tuż przed zapętleniem (i nie wykonywać resetu WD w pętli). Sprzętowy reset jest najpewniejszy.
  • #20 8761964
    rpal
    Poziom 27  
    Jak kolega jest taki wybredny to na 74123 zbuduj sobie uklad resetu wyzwalany narastającym napięciem zasilania a jedną z liniii wejściowych tego układu podepnij pod jakiś pin wyjściowy AVR-a i bedziesz sobie robił swój wlasny reset sprzętowy w zależności od wlasnych upodobań i aktualnych fanaberii. koszt pewnie 3 PLN bo to tylko 1 scalak 2 rezystory i 2 kondensatory elektrolityczne.
  • #21 8762201
    wind_energy
    Poziom 14  
    kemot55 napisał:
    Ja też bym to realizował poprzez WATCHDOG'a. Tyle tylko, że nie musisz z niego korzystać cały czas a włączać programowo tuż przed zapętleniem (i nie wykonywać resetu WD w pętli). Sprzętowy reset jest najpewniejszy.


    Tak, to wydaje się faktycznie najbezpieczniejsze, tak też zrobię włączę watchdoga w warunku tuż przed zerowaniem.

    RPAL - po co coś komplikować, wrzucać dodatkowe elementy, jak można kiwnąć palcem i dodać 2 linijki w kodzie.

    Dzięki za dyskusję i wymianę opinii.

    Pozdrawiam,
    WE
  • #22 8762355
    mirekk36
    Poziom 42  
    Tak sobie czytam i się dziwię. Od samego początku widać, że pomysł "wyzerowania stosu czyli powrót do..." jest delikatnie mówiąc mało trafiony. Wszyscy to po kolei tłumaczą a kolega broni się rękami i nogami próbując z uporem maniaka szukać takiego cudownego rozwiązania - które tak nawiasem mówiąc można rozwiązać w bardzo prosty sposób. Zresztą mówiło tu już o tym wiele osób. Tzn napisać program po ludzku ;) ... warto nauczyć się korzystania ze zwykłych flag i poprawnej obsługi przerwań zamiast tak cudować. A w ostateczności posłużyć się Watchdog'iem.

    ..... no i proszę na końcu to co było niemożliwe okazuje się możliwe ;) .... a jakby tak kolega więcej przemyślał to i watchdog okazałby się niepotrzebny.
  • #23 8763845
    rpal
    Poziom 27  
    kol win_costam pierwsze 5 słow mojego postu wyjaśnia o co biega :)
  • #24 8764104
    mirekk36
    Poziom 42  
    I co z tego że wyjaśnia o co mu chodzi, skoro tak nieśmiało przypuszczam, że on sam nie wie o co chodzi albo może inaczej się wyrażę, nie wie jak osiągnąć jakiś tam cel i wymyśla pomysły z kosmosu.

    Niedawno był podobny wątek, gdzie też autor twierdził, że nie można inaczej rozwiązać jego problemu (którego nie opisał) jak tylko poprzez takie dziwne opuszczanie przerwań. No i co??? w końcu pociągnięty za język, powiedział jaki ma cel i okazało się, że jest milion sposobów żeby to rozwiązać normalnymi drogami programowania a nie poprzez szukanie takich udziwnień.

    Jakby ci zadał np pytanie jak zrobić, żeby z jednego przerwania wskoczyć w drugie a potem wyjść do jakiejś konkretnej funkcji w programie głównym i żeby ją kontynuować do czasu aż w innym przerwaniu zajdzie jakaś zmiana stanu na pinie to wtedy żeby z tej funkcji wskoczyć znowu do innego przerwania itd itd ...... to byś zastanawiał się jak to wykonać? czy może zadałabyś pytanie dodatkowe - jaki jest cel?

    Ja bym zadał to drugie - wtedy zwykle się okazuje że rozwiązanie leży w zasięgu ręki. Wystarczy zresztą spojrzeć na początek tej dyskusji, gdzie autor twierdzi że Watchdog absolutnie odpada aby po krótkiej chwili uznać że to dobre rozwiązanie. A ja się założę, że gdyby powiedział jaki mu cel przyświeca to dałoby radę to w inny sposób zrobić .
REKLAMA