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

Reset programowy AtTiny2313 w C - poprawność funkcji i przerwania?

AVATAR_PL 29 Mar 2006 16:11 9957 30
  • #1 2471371
    AVATAR_PL
    Poziom 14  
    Posty: 178
    Pomógł: 4
    Ocena: 14
    Witam!!
    Napisałem funkcje w C, która ma za zadanie zresetować procesor AtTiny2313 i mam pytanie odnośnie tego czy ta funkcja rzeczywiście resetuje procesor (chodzi mi o taki twardy reset jaki jest wykonywany po ręcznym resetowaniu)

    
    void reset(void)
    {
    asm("ldi R30,0");
    asm("ldi R31,0");
    asm("ijmp");
    }
    


    Funkcja realizuje skok pod adres wskazany w rejestrze Z (czyli 0x0000), jak rozumiem jest to wektor przerwań wskazujący na RESET.

    Czy ta funkcja jest poprawna i czy w momencie jej wykonania przerwania mają być włączone czy wyłączone???

    Dziękuję za odpowiedzi :)
  • #2 2471519
    MirekCz
    Poziom 35  
    Posty: 2220
    Pomógł: 330
    Ocena: 62
    Wyłącz przed wykonaniem skoku przerwania, inaczej w czasie inicjalizacji danych/przerwań (którą robisz na początku programu) mogłoby zostać wywołane jakieś przerwanie i namieszać
  • #4 2472352
    AVATAR_PL
    Poziom 14  
    Posty: 178
    Pomógł: 4
    Ocena: 14
    OK, ale czy jest to taki sam reset jak reset ręczny czy tylko skok na początek programu a rejestry procesora nie zerują się ???
  • #5 2472402
    MirekCz
    Poziom 35  
    Posty: 2220
    Pomógł: 330
    Ocena: 62
    Tylko skok na początek programu.
    Dlatego na początku programu powinieneś ustawić wszystkie używane rejestry itd.
  • #6 2472533
    AVATAR_PL
    Poziom 14  
    Posty: 178
    Pomógł: 4
    Ocena: 14
    A więc to nie jest reset :( :(, może ktoś wie jak wywołać Reset programowy bez udziału watchdoga??
  • #7 2472598
    mzielin
    Poziom 22  
    Posty: 483
    Pomógł: 31
    Ocena: 16
    Jedyne co Ci pozostaje, to napisać procedurkę w asemblerze, która zrobi dokładnie to co reset, czyli przestawi porty IO, wyzeruje stos, liczniki, znaczniki i dopiero wykona jmp 0.
  • #8 2473004
    MirekCz
    Poziom 35  
    Posty: 2220
    Pomógł: 330
    Ocena: 62
    Można też zrobić jakiś sprzętowy reset z podtrzymaniem stanu niskiego przez kilka us... ale to raczej szkoda zachodu - niepotrzebne komponenty na płytce i ew. problemy, podczas kiedy programowo można to zrobić szybko i względnie przyjemnie.
  • #9 2473567
    mcy
    Poziom 15  
    Posty: 154
    Pomógł: 7
    Ocena: 18
    NIestety poprzednicy mają rację 2313 ma trzy źródła sygnału zerującego:
    1. Power on reset - gdy napięcie zasilania spadnie poniżej 1.0 - 1.4V
    dla zbocza narastającego (wł. zasilania) i 0,4 - 0,6 dla opadającego (wył. zasilania).
    2. External reset - stan niski na wejściu RESET przez 50us
    3. Watchdog - gdy jest uaktywniony
    Powyższe sygnały zerujące zerują również LICZNIK ROZKAZÓW, czego nie osiągniesz żadną procedurą!

    Możliwe rozwiązanie:
    Wykonanie procedury włączającej watchdoga z najmniejszym limitem czasu timeoutu - wówczas procek sam się wyzeruje:
    bity: WDE - 1, WDP0..2 - 0 (16 kcykli zegara tj. ok15ms dla zegara watchdoga 1MHz -posiada on własny wewnętrzny zegar)
    WTDOE -1.


    ldi temp,$08 - przygotowanie wpisu do rej watchdoga
    wdr - reset watchdoga
    out wdtr,temp - wpis do rejestru watchdoga z minimalnym timeoutem
    cli - zablokowanie przerwań
    ...
    ... pętla programu, która przekroczy timeout watchdoga

    i nastąpi reset.

    źródło - nota katalogowa 2313

    mam nadzieję że teochę pomogłem - pozdrawiam i życzę miłogo eksperymentowania
  • #10 2475372
    shg
    Poziom 35  
    Posty: 2289
    Pomógł: 339
    Ocena: 135
    mcy napisał:
    (...)Powyższe sygnały zerujące zerują również LICZNIK ROZKAZÓW, czego nie osiągniesz żadną procedurą!

    ldi R30,0
    ldi R31,0
    ijmp

    Jak na mój gust, to ta sekwencja instrukcji zeruje PC. :P
  • #11 2475655
    mcy
    Poziom 15  
    Posty: 154
    Pomógł: 7
    Ocena: 18
    ldi R30,0 ;rejestr ZL
    ldi R31,0 ;rejestr ZH
    ijmp ;skok do adresu wpisanego do ZL i ZH w tym przyladku do $0000

    -->
    TA instrukcja wpisuje wartości 0 do rejestrów ZH ZL. Są to rejestry indeksowe ogólnego przenaczenia. Zazwyczaj stosuje się je do pośredniego adresowania rejestrów roboczych względem adresu bazowego.
    -->
    Stąd po wykonaniu rozkazu IJMP lub ICALL program jest KONTYNUOWANY od adresu wskazanego w rejestrze Z. Licznik rozkazów NIE JEST ZEROWANY! Spójrz na notę katalogową.
    Poza tym procedura opisana przez Ciebie nie spowoduje wyczyszczenia rejestrów roboczych, SREG itd. Zerownaie licznika rozkazów powoduje,że pierwszy rozkaz jest wykonywany od adresu $0000 wraz ustawieniem początkowym SREG itd.

    Pozdrawiam
  • #12 2476128
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    mcy napisał:

    ...
    -->
    Stąd po wykonaniu rozkazu IJMP lub ICALL program jest KONTYNUOWANY od adresu wskazanego w rejestrze Z. Licznik rozkazów NIE JEST ZEROWANY! Spójrz na notę katalogową.

    Fantazjujesz ;)
    W nocie katalogowej (Instruction Set Summary) stoi:
    IJMP Indirect Jump to (Z) PC ← Z
    Czyż PC i "licznik rozkazów" to nie ten sam rejestr :?:
    Albo co się stanie po ...
    
    ...
    LDI R16,0
    PUSH R16
    PUSH R16
    RET
    ...
    

    mcy napisał:

    Poza tym procedura opisana przez Ciebie nie spowoduje wyczyszczenia rejestrów roboczych, SREG itd. Zerownaie licznika rozkazów powoduje,że pierwszy rozkaz jest wykonywany od adresu $0000 wraz ustawieniem początkowym SREG itd.

    Pozdrawiam

    Z 1-szym zdaniem się zgadzam ;)

    Piotrek

    PS
    Polecam rzucić okiem , na Block Diagram str.3
  • #13 2476422
    mcy
    Poziom 15  
    Posty: 154
    Pomógł: 7
    Ocena: 18
    strona 3 pokazuje architekturę całego układu - popatrz na stronę 6
    Architektura rdzenia. Gwoli wyjaśnienia: każdy skok powoduje automatyczne zapisanie aktualnego stanu licznika na stos (w tym również przy wykonywaniu instrukcji IJMP ). Co prawda do licznika przepisujesz adres $0000 - jako adres z pod którego będzie pobrana następna instrukcja programu, ale nie jest to równoznaczne z jego zerowaniem, gdyż po powrocie ze skoku zostanie automatycznie przywrócona jego wartość z przed skoku. To co nazywasz zerowaniem jest skokiem pod adres $0000, a aktualny stan licznika jest zachowywany na stosie!

    Teraz przykładzik:
    LDI R16,0 ;ładujesz 0 do r16
    PUSH R16 ;odkładasz na stos (od góry do dołu w SRAM [ale brzydka nazwa]). Po tej operacji wskaźnik stosu ulega dekrementacji.
    PUSH R16 ;j.w.
    RET ; wracasz do programu. Rozumiem że ten kawałek kodu był podprogramem do którego skoczyłeś. Program scięgnie wartość 0 jako adres powrotu zapisany wcześniej przez licznik rozkazów, ponieważ nie zastosowałeś instrukcji POP x 2 oraz dokona inkrementacji wskaźnika stosu

    STOS:
    WARTOŚĆ PC = adres z przed skoku
    R16 =0
    R16 =0 <- aktualnie ustawiony wskaźnik stosu

    po instrukcji RET:
    WARTOŚĆ PC = adres z przed skoku
    R16 =0 <- ustawiony wskaźnik stosu

    tak naprawdę wykonywany jest skok - powrót pod adres $0000 oszukanego licznika rozkazów, a licznik powinien odczytać WARTOŚĆ PC = adres z przed skoku jako adres powrotu

    Tak nie powinno się programować :D (mam na myśli brak POP). Tak naprawdę do licznika sztucznie (w zasadzie poprzez niepolecany sposób) wpisałeś adres $0000, licznik przez skoki nie jest zerowany (przechowuje swój aktualny stan na stosie). Prawdziwe zerowanie licznika bez oszukiwania i kombinowania i zgodnie z zaleceniami producenta generują tylko sygnały zerujące RESET, zasilanie, WATCHDOG.

    PS Nie fantazjuję, tylko czytam.

    Pozdrawiam
  • #14 2476969
    shg
    Poziom 35  
    Posty: 2289
    Pomógł: 339
    Ocena: 135
    mcy napisał:
    Gwoli wyjaśnienia: każdy skok powoduje automatyczne zapisanie aktualnego stanu licznika na stos (w tym również przy wykonywaniu instrukcji IJMP ).

    Hmmm, może używasz procesorów z jakimś 'innym' rdzeniem AVR...
    ATtiny2313/V Preliminary, strona 7 napisał:
    During interrupts and subroutine calls, the return address Program Counter (PC) is stored on the Stack.

    Czyli licznik programu jest zapisywany na stos podczas wywoływania przerwań i skoków do podprogramów. Instrukcje skoku do podprogramu to: ICALL, RCALL, natomiast zwykłe instrukcje skoku to: IJMP i RJMP.
    Różnica między nimi jest zasadnicza, patrz załącznik.

    mcy napisał:
    Co prawda do licznika przepisujesz adres $0000 - jako adres z pod którego będzie pobrana następna instrukcja programu, ale nie jest to równoznaczne z jego zerowaniem

    Jest.
    mcy napisał:
    gdyż po powrocie ze skoku zostanie automatycznie przywrócona jego wartość z przed skoku.

    Wraca się tylko z podprogramów wywołanych przez ICALL i RCALL, jeżeli wywołano skok bezpośredni (RJMP i IJMP) wykonywanie instrukcji powrotu jest zabronione.
    mcy napisał:
    To co nazywasz zerowaniem jest skokiem pod adres $0000, a aktualny stan licznika jest zachowywany na stosie!

    A licznik i tak jest wyzerowany.
    a = 8734
    b = a
    a = 0

    Jaka jest teraz wartość zmiennej 'a'? Zero! czyli zmienna 'a' ZOSTAŁA wyzerowana.

    Co do reszty się oczywiści zgadzam, wyzerowanie PC ma się nijak do resetu procesora.

    Literatura:
    [1]ATtiny2313 Preliminary Complete
    [2]AVR Instruction Set
    Załączniki:
    • Reset programowy AtTiny2313 w C - poprawność funkcji i przerwania? IJMP.gif (14.57 KB) Musisz być zalogowany, aby pobrać ten załącznik.
    • Reset programowy AtTiny2313 w C - poprawność funkcji i przerwania? ICALL.gif (18.06 KB) Musisz być zalogowany, aby pobrać ten załącznik.
  • #15 2477294
    mzielin
    Poziom 22  
    Posty: 483
    Pomógł: 31
    Ocena: 16
    Zajęliście się tylko jednym aspektem, mianowicie licznikiem programu, pozostaje SREG i rejestry, nie jest np: zerowany watchdog. Uważam, że zmiana stanów portów WE/WY, może powodować poważniejsze skutki. Ponadto pomijana jest mozliwość wejścia procesora w tryb programowania.
    I tak jak napisał mcy aby wystąpił reset możliwe są jedynie 3 przypadki.
    Pytanie do AVATAR_PL - czy 16ms to za długo, aby poczekać na reset ?, watchdog załatwi wszystko.
  • #16 2477454
    mcy
    Poziom 15  
    Posty: 154
    Pomógł: 7
    Ocena: 18
    W tekście chodziło mi o każdy skok do i z procedury - zasugerowałem się twoim przykładem oraz podadełem nie tą instrukcję (miało być ICALL). Powinienem być bardziej precyzyjny. Masz rację co do skoków IJMP, RJMP z nich nie ma powrotu i nie jest potrzebny PC. W tym przypadku jest zerowany licznik rozkazów, ale nijak się to nie ma do restartu procka.

    Pozdrawiam
  • #17 2477950
    AVATAR_PL
    Poziom 14  
    Posty: 178
    Pomógł: 4
    Ocena: 14
    @mzielin może i masz racje z tym watchdogiem (szczerze myślałem że się bez niego obejdzie :) ), jednak chyba nie umiem go prawidłowo zaprogramować, a mianowicie:

    
    void reset(void)
    {
    asm("cli"); //na wszelki wypadek
    asm("wdr"); //reset flagi WDRF w rejestrze MCUSR
                   //nie ustawiam bitów WDP0..3, ponieważ mają wartość 0 jako wartość początkową
    WDTCSR|=(1<<WDCE);  //ustawiam WDCE aby móc ustawić WDE
    WDTCSR|=(1<<WDE);  // ustawiam WDE (włączam watchdoga)
    while(1);         // coś na wytracenie czasu w oczekiwaniu na reset
    }
    


    Pewnie coś jest źle, ponieważ procek po wywołaniu tej procedury bardzo dziwnie się zachowuje, tak jakby resetował się bez końca.
  • #18 2553139
    al555
    Poziom 20  
    Posty: 485
    Pomógł: 32
    Ocena: 8
    AVATAR_PL napisał:
    @mzielin może i masz racje z tym watchdogiem (szczerze myślałem że się bez niego obejdzie :) ), jednak chyba nie umiem go prawidłowo zaprogramować, a mianowicie:

    
    void reset(void)
    {
    asm("cli"); //na wszelki wypadek
    asm("wdr"); //reset flagi WDRF w rejestrze MCUSR
                   //nie ustawiam bitów WDP0..3, ponieważ mają wartość 0 jako wartość początkową
    WDTCSR|=(1<<WDCE);  //ustawiam WDCE aby móc ustawić WDE
    WDTCSR|=(1<<WDE);  // ustawiam WDE (włączam watchdoga)
    while(1);         // coś na wytracenie czasu w oczekiwaniu na reset
    }
    


    Pewnie coś jest źle, ponieważ procesor po wywołaniu tej procedury bardzo dziwnie się zachowuje, tak jakby resetował się bez końca.


    Nie wiem czy to jeszcze aktualna uwaga, ale miałem ten sam problem, a po wczytaniu się w dokumentacje pisze tam że po włączeniu watchdoga i zresetowaniu układu - watchdog nie jest wyłączonay ( bit WDE w rejestrze WDTCSR nie jest zerowany ).
    Musisz jako pierwszą instrukcję w programie umieścić albo wyłączenie watchdoga albo resetowanie (wdr) timera watchdoga.

    Zmiana ta ( że watchdog nie jest wyłączany po resecie ) wprowadzona została do nowszych kontrolerów ( ATtiny2313, ATmega168).
    W starszych rozwiązaniach (ATmega16) wszystkie rejestry są zerowane ( a więc watchdog będzie wyłączony).

    Pozdrawiam
  • #19 2557778
    Nawigator
    Poziom 33  
    Posty: 1923
    Pomógł: 167
    Ocena: 160
    Witam,
    widzę ze shg ładnie i poprawnie odrobił zadanie domowe, brawo ten gość, wygrał tę rundę.
    Chciałbym tylko dodać że skok z programu do adresu $0 nie zawsze oznacza wejście w podprogram RESET: bo może tam być inna procedura.
    Oprócz programowego istnieje jeszcze reset sprzętowy, np. przez podłączony przez ograniczający prąd rozładowania kondensatora kolektor tranzystora npn do nóżki resetu. Baza sterowana z dowolnego pinu i instrukcja sbi PORTn itd załatwia definitywnie sprawę.
    Pozdr. N.
  • #20 2562135
    BoskiDialer
    Poziom 34  
    Posty: 1530
    Pomógł: 353
    Ocena: 42
    Cytat:
    Chciałbym tylko dodać że skok z programu do adresu $0 nie zawsze oznacza wejście w podprogram RESET: bo może tam być inna procedura.

    a w jakim jeszcze innym adresie może sie znajdować wektor resetu?? [niewliczająć możliwości bootcode]

    Owszem skok do adresu 0 (czy to przez "jmp 0"; "ijmp" przy Z = 0; "ret" przy wierzchu stosu: 00 00 czy jak kolwiek inaczej) niepowoduje sprzętowego resetu.. pamięci nietrzeba czyścić - o ile pamiętam w dokumentacji jest kruczek że stan pamięci po uruchomieniu uC jest niezdefiniowany.. rejestry zawsze są najpierw inicjalizowane w programie więc też nietrzeba ich czyścić. używane porty IO, timery itp mają przeważnie na początku programu kod inicjujący więc też można pominąć milczeniem czyszczenie (z pewnymi wyjątkami). stan SREG niema znaczenia (co może zawierać ciekawego SREG po sprzętowym resecie?) z wyjątkiem I, gdyż przerwanie podczas inicjowania może być trudne do wykrycia. SP nietrzeba czyścić - zawsze sie przyjmuje że po resecie SP ma wartośc niezdefiniowaną, niema kodu który nieinicjalizował by SP po resecie.

    ostatecznie wystarczy:
    - wyłączyć przerwania,
    - ustawić wszystkie piny IO na Open Collector (lub Pull-up, często programy korzystają z takiej konfiguracji, w niektórych przypadkach gdy piny mają stały kierunek można pominąć zmiane gdyż po sztucznym resecie nastąpi wpisanie tam takich samych wartości ..)
    - skoczyć pod adres 0

    ----
    przypomniał mi sie kod asemblera generowany przez avr-gcc: bezpośrednio po resecie wczytuje sekcje Data(RAM) z pamięci flash, sekcja BSS(RAM) zostaje wyczyszczona, SP jest ustawiany na ostatni bajt pamięci SRAM a r1 jest zerowany.
  • #21 2562664
    Nawigator
    Poziom 33  
    Posty: 1923
    Pomógł: 167
    Ocena: 160
    >>>a w jakim jeszcze innym adresie może sie znajdować wektor resetu?? pyta BoskiDialer.
    - napisałem "wejście w podprogram RESET:"
    wektor reset jest pod stałym adresem $0 i dopiero z niego jest skok dalej - jak widzę pojęcia wektora i jego adresu są często utożsamiane.
    Pozdr. N.
  • #22 2563883
    BoskiDialer
    Poziom 34  
    Posty: 1530
    Pomógł: 353
    Ocena: 42
    Nawigator: pisząc
    Cytat:
    skok z programu do adresu $0 NIE ZAWSZE oznacza wejście w podprogram RESET: bo może tam być inna procedura

    dajesz do zrozumienia, że skok pod adres $0 nie musi oznaczać skoku do wektora resetu, gdyż może tam być inny podprogram (a raczej skok do innego podprogramu). Pytam: skoro pod adresem $0 może niebyć wektora resetu to gdzie on sie w tej sytuacji będzie znajdował[wektor resetu]? twoja odpowiedź jest błędna gdyż pod adresem $0 zawsze sie znajduje wektor resetu (z wyjątkiem bootcode, ale nawet w takiej sytuacji się go daje)

    ps. pojęcie wektora i jego adresu są utożsamiane z prostego powodu - nieda sie przenieść wektora do innego miejsca(czyt.adresu).
  • #23 2566570
    Nawigator
    Poziom 33  
    Posty: 1923
    Pomógł: 167
    Ocena: 160
    Przeczytaj BoskiDialer jeszcze raz. nic nie daję do zrozumienia, wrzucasz do jednego worka określenia wektora, jego adresu i podprogramu (procedury) RESET. Krótko mówiąc pod adresem $0 może być program użytkowy (nawet jeżeli używamy przerwań). Pisanie kodu w obszarze wektorów przerwań jest może mało eleganckie ale możliwe i czasem ratuje sytuację w ciasnych pętlach.
    Nawiasem mówiąc nowe serie avr te które mają przerwanie resetu od watchdoga zachowują się inaczej niż te starsze (pisał o tym al555) co umożliwia dowolną obsługę tego przerwania.
    Piszesz że: "wystarczy ustawić wszystkie piny IO na Open Collector" a co z resztą rejestrów konfiguracyjnych? Zostają bez zmian i jeżeli w programie domyślnie zakładamy np. zerowe wartości bitów a np. z powodu zakłóceń wpisały się gdzieniegdzie jedynki to reset softwarowy (który jest procedurą ratunkową) nic nie pomoże. No chyba że przy inicjalizacji ustawisz wszystkie rejestry od nowa ale często z braku miejsca się tego nie robi.
    A żeby ostatecznie odpowiedziec na pytanie AVATAR'a:
    >>>mam pytanie odnośnie tego czy ta funkcja rzeczywiście resetuje procesor (chodzi mi o taki twardy reset jaki jest wykonywany po ręcznym resetowaniu)
    to ta funkcja lub skok w programie pod adres zerowy mu tego nie zapewnią.
    Pozdr. N.
  • #24 2575758
    Nawigator
    Poziom 33  
    Posty: 1923
    Pomógł: 167
    Ocena: 160
    Akurat temat jest bieżąco równiez na avrfreaks.net gdzie Dean cytuje oficjalna odpowiedź z Atmela:
    Cytat:
    Hi Dean,

    Here is the answer to your question from our new FAQ (not published). I hope this is clearifying.

    Q:
    How can I reset my AVR through software?

    A:
    If you want to perform a software reset of your AVR you should use the internal Watchdog. Simply enable it and let it time out. When the Watchdog triggers it resets the program counter back to 0, clears all the registers and performs all the other tasks. This operation gives the same result as pulling the RESET line low.

    You should not try to:
    - Use another pin of the AVR to pull the external RESET line. The pins of the AVR are tristated halfway through the minimum reset time, this releases the RESET line and hence nothing happens.
    - Jump to program location 0. Jumping to program location 0 does not clear all the registers and hence you do not have a "clean" reset.


    Example Code (GCC) Resetting the AVR every 30mS:

    #include <avr/io.h>
    #include <avr/wdt.h>

    int main(void)
    {
    wdt_enable(WDTO_30MS);
    while(1) {};
    }


    Alternatively you can create a macro:

    Code:

    #include <avr/io.h>
    #include <avr/wdt.h>

    #define Reset_AVR() wdt_enable(WDTO_30MS); while(1) {}

    int main(void)
    {
    Reset_AVR();
    }


    Best regards
    Marius Leine With
    Atmel AVR Technical Support


    Potwierdza sie więc możliwosć poprawnego resetu przez watchdoga.
    Niestety trwa to kilkanaście ms, co nie zawsze przeszkadza
    Podłączenie hardwarowe pinu wyjsciowego do pinu resetu nie skutkuje bowiem w połowie czasu linia wyjściowa staje się trzystanowa i reset nie może być ukończony. Nie wspomina sie tu o kondensatorze resetu który musi przecież przedłużyć czas trwania impulsu.
    I jeszcze inny wątek gdzie cytowany jest kod inicjalizacji po resecie soft dla mega48 gwarantujacy poprawne wyzerowanie rejestrów sprzętowych (a gdzie robocze?).
    http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=34049
    Pozdr. N.
  • #25 2651347
    pgp
    Poziom 19  
    Posty: 412
    Pomógł: 6
    Ocena: 17
    Chciałbym wykonac reset uC po odebraniu danych z kompa - ma to być pojedynczy reset rozkaz któego umieszczę w procedurze przerwania. Jak to zrobic ? (ATmega32 , pisze w C).
  • #26 2651909
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    pgp napisał:
    Chciałbym wykonac reset uC po odebraniu danych z komputera - ma to być pojedynczy reset rozkaz któego umieszczę w procedurze przerwania. Jak to zrobic ? (ATmega32 , pisze w C).

    Odpowiedź masz powyżej.Chyba że masz jakieś szczególne wymagania :D

    Piotrek
  • #27 2652129
    pgp
    Poziom 19  
    Posty: 412
    Pomógł: 6
    Ocena: 17
    No tylko ze ja chcę pojedynczy Reset a nie co 30 ms...
  • #28 2652241
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    pgp napisał:
    No tylko ze ja chcę pojedynczy Reset a nie co 30 ms...

    To na początku kodu , wyłącz GO. Jeśli zajdzie potrzeba zresetować uC , to włączasz watchdoga i czekasz na resecik.

    Piotrek
  • #29 2652442
    pgp
    Poziom 19  
    Posty: 412
    Pomógł: 6
    Ocena: 17
    Zrobiłem takie cos (wykorzystując biblioteke wdt.h):

    wdt_reset();
    wdt_enable(WDTO_15MS);
    czekaj(60*tau); //czeka 60 ms	
    wdt_disable();



    niestety nie działa...

    spróbowałem też bez użycia biblioteki i wstawiłem w odpowiednie miejsce:

    _WDR();//reset licznika watchdoga
    WDTCR |= (1<<WDE);//start watchdoga z domyślnym opóźnieniem 
    czekaj(1000*tau); 


    i nadal nic..
    moze sa jakieś dodatkowe Fuse bity któe trzeba załaczyc czy jak ?
  • #30 2713022
    maly35
    Poziom 14  
    Posty: 91
    Pomógł: 6
    Ocena: 2
    Nie działa ci pierwszy sposób ponieważ deaktywujesz watchdog po watchdogu:) tzn nigdy nie dojdzie to tej linijki kodu ponieważ zawsze wcześniej się zresetuje. Daj wdt_disable() na początku programu (a napewno przed włączeniem watchdoga). Ja tak zrobiłem i działa bez problemu.

    A swoją drogą używałem resetu ponieważ mam dziwny proble, może tu mi ktoś pomoże.
    Odczytuję temperaturę na DS18B20. Pierwszy odczyt zawsze jest poprawny, ale jeżeli programowo wrócę do początku programu tzn. znów wykonam pierwszą procedurę to następne odczyty już są błędne (wywala 85). Czego to może być wina? Brakiem RAM'u? Dodam że program jest dosyć rozbudowany

Podsumowanie tematu

✨ Dyskusja dotyczy możliwości wykonania programowego resetu mikrokontrolera AtTiny2313 w języku C oraz poprawności zaproponowanej funkcji resetującej. Zaproponowana funkcja wykonująca skok do adresu 0x0000 (wektor resetu) za pomocą instrukcji IJMP nie powoduje twardego resetu procesora, a jedynie skok do początku programu bez zerowania rejestrów, licznika rozkazów, SREG czy innych układów peryferyjnych. Wskazano, że przerwania powinny być wyłączone przed wykonaniem takiego skoku, aby uniknąć niepożądanych wywołań podczas inicjalizacji.

Jedynym skutecznym sposobem na programowy twardy reset jest wykorzystanie Watchdoga – włączenie go z minimalnym timeoutem (np. 15 ms) i oczekiwanie na jego wywołanie resetu. Kod w C powinien wyłączyć przerwania, włączyć Watchdoga i zatrzymać program w nieskończonej pętli, co spowoduje reset sprzętowy. Po resecie należy pamiętać o wyłączeniu Watchdoga na początku programu, gdyż w nowszych mikrokontrolerach (w tym AtTiny2313) Watchdog nie jest automatycznie wyłączany po resecie.

Alternatywnie można napisać procedurę asemblerową, która ręcznie wyzeruje rejestry, stos i porty IO, ale nie zastąpi to pełnego resetu sprzętowego. Reset sprzętowy można też wykonać zewnętrznie, np. przez sterowanie linią RESET za pomocą tranzystora i kondensatora.

Podsumowując, skok do adresu 0 nie jest równoważny resetowi sprzętowemu, a jedyną pewną metodą programowego resetu jest użycie Watchdoga. Dyskusja zawiera także uwagi dotyczące architektury rdzenia AVR, działania licznika programu, stosu oraz różnic między instrukcjami skoku.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA