Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki



Teraz jest 28 mar 2024, o 10:09


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 27 ] 
Autor Wiadomość
PostNapisane: 1 maja 2022, o 08:01 
Offline
Nowy

Dołączył(a): 05 paź 2021
Posty: 24
Pomógł: 0

Przecieram od rana oczy, bo próbuję sobie ćwiczyć timery programowe na diodzie i głośniczku.
Zredukowałem do testów kod do chyba najprostszej możliwej formy. Przerwanie CTC ustawione co 1000ms.

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


...i głośniczek kołacze jak chce, led mruga jak chce ale na pewno nie są to zadane interwały.
Jak umieszczę zmianę stanów w kodzie przerwania to wszystko jest jak najbardziej OK.

Czegoś tu nie widzę?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 1 maja 2022, o 08:25 
Offline
Użytkownik

Dołączył(a): 29 paź 2017
Posty: 230
Pomógł: 26

Czy timer_1000ms i timer_300ms są volatile ?
To po pierwsze
Po drugie badanie w pętli głównej czy zmienna w przerwaniu osiąga 0 jest ryzykowne.
W czasie wykonania przerwania może się zdarzyć że zero stanie się jedynką i pętla główna nie zdąży zareagować
Gdybyś w przerwaniu postawił jakąś flagę i w pętli głównej ją zerował to wtedy miałbyś pewność że zawsze zdążysz.


Autor postu otrzymał pochwałę

_________________
Jestem na GG 31324
Nowy soft, nowa nadzieja.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 1 maja 2022, o 08:32 
Offline
Nowy

Dołączył(a): 05 paź 2021
Posty: 24
Pomógł: 0

JarekB napisał(a):
Czy timer_1000ms i timer_300ms są volatile ?
To po pierwsze

Tak, tak, naturalnie.

JarekB napisał(a):
Po drugie badanie w pętli głównej czy zmienna w przerwaniu osiąga 0 jest ryzykowne.
W czasie wykonania przerwania może się zdarzyć że zero stanie się jedynką i pętla główna nie zdąży zareagować
Gdybyś w przerwaniu postawił jakąś flagę i w pętli głównej ją zerował to wtedy miałbyś pewność że zawsze zdążysz.

Adaptacja niemal żywcem z bluebooka. Ale racja, dodam flagę.

------------------------ [ Dodano po: 7 minutach ]

No i super - z flagą pomocniczą wszystko działa perfect. Dzięki!



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 1 maja 2022, o 17:20 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27212
Lokalizacja: Szczecin
Pomógł: 1041

Rnext napisał(a):
No i super - z flagą pomocniczą wszystko działa perfect. Dzięki!

To jest bardzo zły sposób na realizację timerów programowych

poza tym pisałeś:
Rnext napisał(a):
Adaptacja niemal żywcem z bluebooka.


to "niemal" to u ciebie całkiem inaczej i źle - stąd twoje problemy. Gdybyś jednak spróbował jak w Bluebooku to mógłbyś działać DOKŁADNIE i tak samo wygodnie jak w Bluebooku i to bez żadnych dodatkowych flag - bo te dodatkowe flagi twoje to po prostu będą tylko zawalizdrogą przy bardziej rozbudowanych programach.

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 2 maja 2022, o 05:43 
Offline
Nowy

Dołączył(a): 05 paź 2021
Posty: 24
Pomógł: 0

mirekk36 napisał(a):
Rnext napisał(a):
to "niemal" to u ciebie całkiem inaczej i źle - stąd twoje problemy. Gdybyś jednak spróbował jak w Bluebooku to mógłbyś działać DOKŁADNIE

Sam bardzo chętnie pozbył bym się flag. Pierwotnie zrobiłem DOKŁADNIE jak w BB i też działało nierówno. Stąd kolejne kombinacje w kodzie.

Tak wyglądała przepisana żywcem pętla główna:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

A tak przepisałem obsługa przerwania:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Po samej LED pewnie bym się nie zorientował, bo na oko mrugała jak powinna, ale głośniczek daje możliwość łatwego wyłapania skoków "taktu".



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 2 maja 2022, o 13:04 
Offline
Użytkownik

Dołączył(a): 25 lut 2022
Posty: 38
Pomógł: 5

Poczytaj sobie o współdzieleniu danych i atomowym dostępie.

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 2 maja 2022, o 13:38 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 15 lut 2017
Posty: 369
Lokalizacja: Gliwice
Pomógł: 34

ord napisał(a):
Poczytaj sobie o współdzieleniu danych i atomowym dostępie.

Tylko co to ma do rzeczy w kontekście problemu?
Przy miganiu diody czy też buzzera nie ma żadnego znaczenia czy ktoś się pomyli o "kilka taktów zegara"

Timery z bluebooka były wielokrotnie sprawdzane i używane do zadań jak w temacie i stawiam orzechy przeciwko kokosom, że autor coś pokikciał.

Jeśli ktoś się wykłada na timerach programowych to niech jeszcze się nie bierze za "atomowość".



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 2 maja 2022, o 13:56 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 22 paź 2013
Posty: 1960
Lokalizacja: Lipsko
Pomógł: 125

Cytuj:
Tylko co to ma do rzeczy w kontekście problemu?

Więcej niż Ci się wydaje. Przy przekazywaniu 16bitowych parametrów do przerwania dzieją się różne rzeczy. Doczytaj jak Cię o to proszą, wiedzą co mówią....

_________________
http://www.sylwekkuna.com



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 2 maja 2022, o 15:20 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 15 lut 2017
Posty: 369
Lokalizacja: Gliwice
Pomógł: 34

SylwekK napisał(a):
Więcej niż Ci się wydaje.

Nie w tym banalnym przykładzie. Jest dość czasu na odczyt i zapis i "składanie" rejestrów. Nie ma innych przerwań, nie ma konfliktu dostępu do rejestrów mikrokontrolera
Natomiast na pewno autor źle przepisał kod z bluebooka i od poprawnego powinien był zacząć.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 2 maja 2022, o 17:53 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 22 paź 2013
Posty: 1960
Lokalizacja: Lipsko
Pomógł: 125

Nie zgodzę się. Nawet w tym banalnym przykładzie gdy timer programowy będzie 16bitowy to zwykle miganie diodą nie będzie idealnie równe. Dawno temu to przerabiałem w równie prostym programie i pytałem po forach co jest nie tak, że nie działa jak powinno.

_________________
http://www.sylwekkuna.com



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 3 maja 2022, o 16:09 
Offline
Nowy

Dołączył(a): 05 paź 2021
Posty: 24
Pomógł: 0

Zealota napisał(a):
SylwekK napisał(a):
Więcej niż Ci się wydaje.

Nie w tym banalnym przykładzie. {...}
Natomiast na pewno autor źle przepisał kod z bluebooka i od poprawnego powinien był zacząć.


Nie no, bez przesady :) Przecież sam możesz sprawdzić (lub ktokolwiek). Przecież wkleiłem też ten pierwotny, przepisany kod. Tym bardziej że za wiele do przepisywania tu nie ma, zwłaszcza że na pierwszy rzut oka w kod z BB wiadomo o co w nim chodzi.

------------------------ [ Dodano po: 19 minutach ]

ord napisał(a):
Poczytaj sobie o współdzieleniu danych i atomowym dostępie.


Dzięki! Do głowy mi nie przyszło, żeby zerknąć w generowany ASM. Wstępnie zerknąłem w temat dostępu atomowego. Zdaje się tu jest pies pogrzebany.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 3 maja 2022, o 17:49 
Offline
Użytkownik

Dołączył(a): 06 lut 2018
Posty: 58
Pomógł: 0

Rnext napisał(a):
Zealota napisał(a):
SylwekK napisał(a):
Więcej niż Ci się wydaje.

Nie w tym banalnym przykładzie. {...}
Natomiast na pewno autor źle przepisał kod z bluebooka i od poprawnego powinien był zacząć.


Nie no, bez przesady :) Przecież sam możesz sprawdzić (lub ktokolwiek). Przecież wkleiłem też ten pierwotny, przepisany kod. Tym bardziej że za wiele do przepisywania tu nie ma, zwłaszcza że na pierwszy rzut oka w kod z BB wiadomo o co w nim chodzi.

------------------------ [ Dodano po: 19 minutach ]

ord napisał(a):
Poczytaj sobie o współdzieleniu danych i atomowym dostępie.


Dzięki! Do głowy mi nie przyszło, żeby zerknąć w generowany ASM. Wstępnie zerknąłem w temat dostępu atomowego. Zdaje się tu jest pies pogrzebany.



Możesz pokazać ciało swojej funkcji: hw_timer0_ctc_enable?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 4 maja 2022, o 11:12 
Offline
Nowy

Dołączył(a): 05 paź 2021
Posty: 24
Pomógł: 0

mtbchn napisał(a):
Możesz pokazać ciało swojej funkcji: hw_timer0_ctc_enable?


Jasne. Nic szczególnego w niej nie ma a jak pisałem, umieszczenie przełączania w obsłudze przerwania chodzi idealnie.
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 4 maja 2022, o 12:08 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 15 lut 2017
Posty: 369
Lokalizacja: Gliwice
Pomógł: 34

Rnext napisał(a):
Nie no, bez przesady Przecież sam możesz sprawdzić (lub ktokolwiek).

Sprawdziłem, masz rację - zwracam honor.
Na "usprawiedliwienie" :) mam to, że pomyliłem chyba Bluebooka z Greenbookiem.
Różnica polega na tym, że w późniejszych implementacjach Mirek w obsłudze timerów programowych, przy inkrementacji, używa specyfikatora "register", który prawdopodobnie daje odpowiednią ochronę kodu. Takiego rozwiązania użyłem w wielu projektach i nigdy nie było problemu z działaniem w odpowiednim czasie.
Sprawdź proszę, czy ta drobna zmiana spowoduje poprawne działanie.
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 4 maja 2022, o 16:21 
Offline
Użytkownik

Dołączył(a): 25 lut 2022
Posty: 38
Pomógł: 5

Słowo kluczowe "register" użyte w taki sposób nic nie daje. Kod będzie identyczny.
Generalnie w nowoczesnych kompilatorach słowo jest ignorowane. W przypadku C++ jest to wręcz wymuszone przez standard.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 4 maja 2022, o 16:26 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 22 paź 2013
Posty: 1960
Lokalizacja: Lipsko
Pomógł: 125

Dokładnie. Teoretycznie kod wykona się szybciej, ale zmienna dostarczana do przerwana i tak może być przecięta na pół w losowych momentach...

_________________
http://www.sylwekkuna.com



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 4 maja 2022, o 19:00 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 15 lut 2017
Posty: 369
Lokalizacja: Gliwice
Pomógł: 34

SylwekK napisał(a):
przecięta na pół w losowych momentach...

W przykładzie z jednym przerwaniem i modyfikacją w pętli głównej kiedy ma nastąpić to "przecięcie na pół"?
Modyfikacja zmiennej następuje tylko w przerwaniu oraz w pętli głównej.

Jeśli mikrokontroler wchodzi w obsługę przerwania, to póki nie skończy obsługi - podziała na rejestrach - to nic mu nie przerwie działania na rejestrach.
"Atomowość" przerwania nie jest potrzebna, bo pętla główna nie jest wstanie zaburzyć/przerwać działania żadnego przerwania.
W AVR przerwanie może zostać jedynie "przecięte na pół" przez inne przerwanie, czyż nie?

No to może podczas modyfikacji zmiennej w pętli głównej?
Nie, bo przerwanie wykonuje się co milisekundy, a inkrementacja dwubajtowej w pętli głównej, wraz z sprawdzeniem warunku będzie trwała wielokrotnie dłużej.
Mamy zatem sekwencję:
1. Wejście w przerwanie
2. Obliczenia
3. Wyjście z przerwania

4. Wejście do pętli głównej

5. Co kilkanaście taktów zegara jest sprawdzany warunek - mikrosekundy najwyżej
Gdy tylko przerwanie zmieni wartość licznika na 0 - w tym przerwaniu PĘTLA nie zmieni rejestrów, to DOPIERO po wyjściu z przerwania pętla będzie mogła wpisać nową wartość.
PONIEWAŻ przerwanie nastąpi dopiero za kolejne milisekundy JEST DOŚĆ czasu na modyfikację dwóch jednobajtowych rejestrów.

6. Pętla sprawdza warunek (licznik == 0) wpisuje nową wartość w ciągu maks. kilku mikrosekund
7. Wielokrotnie sprawdzany jest warunek (licznik==0).
Były ms zanim po raz kolejny nastąpiło przerwanie, ale zmienna już została zmodyfikowana do wartości początkowej (licznik = 1000 /ms/ )

8. Wejście w przerwanie - po ms
9. Obliczenia
10. Wyjście z przerwania
itd

Mikrokontroler działa sekwencyjnie. Dopiero zagnieżdżanie przerwań wymusza w odp. momencie atomowość. Bo jedno jak i drugie przerwanie może zostać "przerwane", pokićkać wspólne rejestry.
Nie pojedyncze przerwanie i pętla główna.
No chyba, że coś pominąłem, ale co?
Jaki macie pomysł na wytłumaczenie? Nie zadowala mnie "bo ktoś powiedział', albo że "tak ma być", "atomowość rozwiązała problem" :)

Taki kod działa u mnie bezbłędnie nawet jeśli jest kilka liczników i kilka diod czy inne proste zmiany portów.
Greenbook'owe kody też działają, a mamy tam przecież dość skomplikowane projekty, a softtimery są wykorzystywane.

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 4 maja 2022, o 20:41 
Offline
Użytkownik

Dołączył(a): 07 cze 2016
Posty: 563
Pomógł: 143

Zealota napisał(a):
Mikrokontroler działa sekwencyjnie. Dopiero zagnieżdżanie przerwań wymusza w odp. momencie atomowość.


W Twoim przykładzie linia 17. (if( softTimer1 == 0 )) wygeneruje mniej więcej taki kod asm:
Składnia: [ Pobierz ] [ Ukryj ]
język asm
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Jak widać dwubajtowa zmienna softTimer1 jest umieszczona w RAM pod adresami 0x0100 (low) i 0x0101 (high).
Przyjmijmy, że zmienna softTimer1=256, czyli adres 0x0100 = 0x00, a adres 0x0101 = 0x01.


    Scenariusz może być taki:
  • do rejestru R24 zostaje skopiowana wartość niskiego bajtu zmiennej softTimer1, czyli 0x00
  • po tej operacji może nastąpić skok do procedury obsługi przerwania, w której zmienna softTimer1 zostaje zmniejszona o 1, czyli adres 0x0100 zawiera teraz 0xFF, a adres 0x0101 zawiera 0x00,
  • po powrocie z procedury obsługi przerwania do rejestru R25 zostaje załadowana wartość adresu 0x0101, ale teraz już nie 0x01, tylko 0x00
  • obydwa rejestry (R24 i R25) są równe 0x00, w związku z czym operacja testu zmiennej softTimer1==0 da wynik fałszywie pozytywny.

Coś takiego będzie się dziać bez zagnieżdżania, a nawet bez innych przerwań.
Oczywiście nie będzie tak w każdym obiegu timera. Prawdopodobieństwo "trafienia" przerwania w nieodpowiednim momencie może nie jest duże, ale prędzej czy później się przytrafi, w efekcie czego program może działać niestabilnie.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 4 maja 2022, o 21:46 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 22 paź 2013
Posty: 1960
Lokalizacja: Lipsko
Pomógł: 125

Dokładnie! Gdybym nie miał takiej sytuacji to bym nie mówił.

_________________
http://www.sylwekkuna.com



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 5 maja 2022, o 10:04 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 15 lut 2017
Posty: 369
Lokalizacja: Gliwice
Pomógł: 34

andrews napisał(a):
Scenariusz może być taki:

Świetnie opisałeś moment "rozrywania" zmiennej, natomiast wg mnie takie coś w tym przykładzie być może nastąpi raz, na początku, po starcie programu.

Od momentu uruchomienia globalnego przerwań sei() do pierwszego wejścia w warunek if (softTimer1 == 0) {} przerwanie może zaburzyć ten warunek wpisując "randomowe" wartości do zmiennej, poprzez rozerwanie dwubajtowej wartości softTimer1.

Natomiast po wyjściu z pierwszego przerwania następne będzie dopiero po milisekundach. Być może pierwszy "tik" będzie dłuższy albo krótszy od zadanego softTimer1, ale następnie dojdzie do zsychronizowania pętli głównej z licznikiem i przerwaniami, a późniejsze sekwencje będą już "po kolei" i zgodnie z założeniami dla TEGO przykładu

Jak pisałem wyżej:
1. Obsługa przerwania bezwzględnie blokuje obsługę kodu pętli while.
2. Pętla while nie "wywłaszcza" przerwania
3. Nie ma nic innego co "wywłaszczy" przerwanie i rozerwie słowo na bajty

Te trzy warunki zapewniają, że po "rozkręceniu" licznika przerwań program będzie pracował poprawnie.
Dodatkowo modyfikacja zmiennej softTimer1 przez pętlę główną, będzie zawsze po kilkunastu mikrosekundach od wyjścia z przerwania i czasu starczy na poprawną obsługę zmiennej softTimer1. Wyjście z przerwania da zawsze stabilną wartość zmiennej softTimer1
Stabilność "danych" w pętli while zapewnia bardzo długi czas pomiędzy przerwaniami.

Może źle to tłumaczę, może mi coś umyka, ale ten przykład musi działać poprawnie.
Dziś jeszcze dokonam prób sprzętowych na większej liczbie zmiennych, może coś się wyjaśni.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 5 maja 2022, o 11:29 
Offline
Użytkownik

Dołączył(a): 06 lut 2018
Posty: 58
Pomógł: 0

Zealota napisał(a):
andrews napisał(a):
Scenariusz może być taki:

Świetnie opisałeś moment "rozrywania" zmiennej, natomiast wg mnie takie coś w tym przykładzie być może nastąpi raz, na początku, po starcie programu.

Od momentu uruchomienia globalnego przerwań sei() do pierwszego wejścia w warunek if (softTimer1 == 0) {} przerwanie może zaburzyć ten warunek wpisując "randomowe" wartości do zmiennej, poprzez rozerwanie dwubajtowej wartości softTimer1.

Natomiast po wyjściu z pierwszego przerwania następne będzie dopiero po milisekundach. Być może pierwszy "tik" będzie dłuższy albo krótszy od zadanego softTimer1, ale następnie dojdzie do zsychronizowania pętli głównej z licznikiem i przerwaniami, a późniejsze sekwencje będą już "po kolei" i zgodnie z założeniami dla TEGO przykładu

Jak pisałem wyżej:
1. Obsługa przerwania bezwzględnie blokuje obsługę kodu pętli while.
2. Pętla while nie "wywłaszcza" przerwania
3. Nie ma nic innego co "wywłaszczy" przerwanie i rozerwie słowo na bajty

Te trzy warunki zapewniają, że po "rozkręceniu" licznika przerwań program będzie pracował poprawnie.
Dodatkowo modyfikacja zmiennej softTimer1 przez pętlę główną, będzie zawsze po kilkunastu mikrosekundach od wyjścia z przerwania i czasu starczy na poprawną obsługę zmiennej softTimer1. Wyjście z przerwania da zawsze stabilną wartość zmiennej softTimer1
Stabilność "danych" w pętli while zapewnia bardzo długi czas pomiędzy przerwaniami.

Może źle to tłumaczę, może mi coś umyka, ale ten przykład musi działać poprawnie.
Dziś jeszcze dokonam prób sprzętowych na większej liczbie zmiennych, może coś się wyjaśni.



Daj znać jak będziesz już po testach. Proponuję pomiar programowych timerów na kilku kanałach analizatora stanów logicznych. Jeśli byś mógł, wrzuć screeny.

A w międzyczasie, może Mirosław zabierze głos i wyjaśni powyższe wątpliwości.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 5 maja 2022, o 12:48 
Offline
Użytkownik

Dołączył(a): 07 cze 2016
Posty: 563
Pomógł: 143

Niestety kolego Zealota nie masz racji.

Patrzysz na program z punktu widzenia języka C, a tu (aby zrozumieć problem) niestety trzeba spojrzeć na asemblera, bo instrukcje języka C nie są wykonywane przez mikrokontroler "atomowo".

Przykładowo instrukcja porównania softTimer1==0 wymaga najpierw załadowania obydwu bajtów zmiennej softTimer1 do rejestrów. Odbywa się to w dwóch taktach mikrokontrolera, między którymi może wystąpić przerwanie, które zmodyfikuje zawartość zmiennej. Spowoduje to, że w rejestrach R25:R24 zmienna zostanie złożona z młodszego bajtu zmiennej softTimer1 w RAM przed modyfikacją i starszego bajtu zmiennej softTimer1 w RAM po modyfikacji (w przerwaniu), czyli wartość zmiennej będzie nieprawidłowa. I to na tyle. Struktura programu w języku C jak i wywłaszczanie nie mają tu nic do rzeczy. istotny jest tylko ten fragment dwóch instrukcji asm, pomiędzy którymi może wystąpić przerwanie (które zmodyfikuje wartość kopiowanej akurat zmiennej).

Właściwie jedynym sensownym rozwiązaniem tego problemu jest wyłączenie przerwań na czas kopiowania z RAM do rejestrów, czyli w asemblerze wyglądałoby to tak:
Składnia: [ Pobierz ] [ Ukryj ]
język asm
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

W C można użyć makra ATOMIC_BLOCK() lub instrukcji cli(); i sei();



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 5 maja 2022, o 22:43 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27212
Lokalizacja: Szczecin
Pomógł: 1041

mtbchn napisał(a):
A w międzyczasie, może Mirosław zabierze głos i wyjaśni powyższe wątpliwości.

Ja tak obserwuję sobie z doskoku tę dyskusję i po prostu oczom własnym nie wierzę ;) ... bo tu w zasadzie jest spór ideologiczny i na dodatek (ku mojemu zdumieniu) kompletnie oderwany od pytania i problemów autora - co zaciemnia w ogóle obraz i wyłania się tylko jedno:

Stosować Atomowe podejście przy timerach programowych czy nie ?

No i są dwie grupy (o ile tak można powiedzieć) bo jedna grupa to zaledwie pojedynczy użytkownik forum - kolega ZELAOTA a druga grupa to kilku użytkowników, którzy przekonują że nie da się inaczej jak bez ATOMIC BLOCK .... i to pomimo to, że ZELAOTA wyraźnie też po drodze pisał, że jak chodzi o problem autora to nie może mieć żadnego wpływu czy mamy podejście atomowe czy nie.

Oczywiście kolega Andrews jak zawsze (spec w asemblerze) ładnie wyłożył i pokazał przykłady (fajna nazwa) ROZRYWANIA zmiennej 16-bitowej podczas gdy wystąpi przerwanie i w ogóle ciężko z tym dyskutować bo taka jest prawda i nie ma co się z tym nawet sprzeczać, że TEORETYCZNIE - może do tego dojść a wtedy w JEDNYM z najgorszych przypadków (którego prawdopodobieństwo wystąpienia jest chyba porównywalne do wygranej w toto lotka) - czyli gdy softimer = 256 i akurat przy sprawdzaniu if() nastąpi przerwanie i to pomiędzy pobieraniem młodszego i starszego bajtu - no to co tu dużo mówić - to jest OCZYWISTE JAK SŁOŃCE że tak będzie - że ten IF się źle wykona i biedny softTimer1 źle zadziała tym razem ....

Krótko mówiąc nawet nie ma co kruszyć kopii że w większości wypadków gdy szczególnie nam zależy na wyśrubowanych warunkach działania programu i korzystamy ze zmiennych więcej niż 8-bitowe w przerwaniu i w programie głównym - to ATOMIC BLOCK musi nam przyrosnąć do ręki ....

ALE ........ no właśnie jest moim zdaniem jedno małe ALE i nie musicie się z tym zgadzać oczywiście

PO PIERWSZE - proste timerki programowe absolutnie nie służą do super precyzyjnego odmierzania czasu - a jeśli ktoś się z tym spiera to jest w błędzie. Bo nawet przy nie wiem jakich ATOMIC BLOKACH - gdy inna część większego programu zużyje dużo więcej czasu niż czas najszybciej ustawionego timera programowego przy podstawie czasu 10ms czyli przy wartości 1, to na kiszkę zdadzą się wszystkie Atomic Bloki

PO DRUGIE - jest dokładnie tak jak pisze ZELAOTA - że skoro podstawa czasu to 10ms to jest to KOSMICZNY odstęp od przerwania do przerwania więc prawdopodobieństwo tego, że kolejne przerwania timera sprzętowego utrafią akurat w obsłudze tych timerków programowych w IF()'a albo w ładowanie nowej wartości do softTimer - moim zdaniem jest właśnie jak w totolotku albo i jeszcze mniejsze


Zealota napisał(a):
Od momentu uruchomienia globalnego przerwań sei() do pierwszego wejścia w warunek if (softTimer1 == 0) {} przerwanie może zaburzyć ten warunek wpisując "randomowe" wartości do zmiennej, poprzez rozerwanie dwubajtowej wartości softTimer1.

Wcale nie - będzie dużo lepsza sytuacja i nie będzie ŻADNYCH randomowych wartości które mogą zaburzyć przy starcie bo przecież jeśli zmienne globalne softTimers nie są zainicjowane to mają wartość = 0, więc przerwanie przy starcie ich nie będzie ruszać. Przerwanie wystartuje od razu po SEI() i nie zmieni wartości żadnego softTimera i UWAGA! bo tu ZELAOTA ma rację, następne przerwanie odbędzie się aż za 10 ms, zatem rozpocznie się pętla główna która odpali każdy softTimer i ustawi im wartości na nowe, czyli ich zmniejszanie w przerwaniu rozpocznie się za jakiś czas ...

... i OK nie jesteśmy w stanie przewidzieć kiedy nadejdzie to kolejne przerwanie za 10ms to czy akurat nie trafi w któregoś IF()'a albo w któreś napełnianie nową wartością jednego z softTimerów. Ale zakładając - że NAWET TRAFI w któregoś IF()'a to teraz czy akurat trafi nie dość że dokładnie w momencie ładowania dwóch bajtów do porównania ... .i ..... dodatkowo gdy akurat w softTimer jest wartość 256 ????? (oczywiście ja rozumiem Andrews - że to nie chodzi o tylko ten przypadek ale o każdy inny bo można twój przykład w ASM rozpisać sobie dla wartości nie 256 ale np 512 albo i dla byle jakiej np 613 ... i bez ATOMIC BLOCK gdyby te przerwanie trafiało akurat zawsze na IF()'y i rwało nawet te porównania to będą one zakłócone - ale o ile ? wziąwszy pod uwagę podstawę czasu 10ms ? ... o tyle co było utracone w młodszym bajcie - czyli softTimer zadziała załóżmy nieco albo i sporo szybciej niż trzeba - a nie że program się (potocznie mówiąc) WYSYPIE.

Mi nawet przez myśl nie przechodzi żeby się zastanawiać i dbać o to czy przy zastosowaniu prostych timerków programowych brać pod uwagę takie różnice czasu. To jest kompletnie nieistotne

a teraz NAJWAŻNIEJSZE - spróbujcie się Panowie - którzy tak naciskacie na atomowe podejście przy tych timerkach ... więc spróbujcie powiedzieć - przypatrzyć się, przeanalizować kod autora !!!! Pomijam że autor gra w mega kalambury i przez cały wątek ktoś go wciąż prosi żeby udostępnił kolejny puzzel kodu bo nie wiadomo co może mu źle działać ... że jaki TAKT jest zakłócony jeśli chodzi o BUZZER .... więc proszę - powiedzcie mi czy analizowaliście ten kod - zbierając puzzle z kolejnych postów - bo ja w końcu tak - i co ? NADAL nie wiadomo co ile dokładnie czasu on odpala ten buzer żeby słyszeć równy takt. Nie wiemy bowiem o kolejnym puzlu czyli jaką częstotliwością jest taktowany u niego procek i czy aby na pewno w ogóle korzysta z podstawy czasu dla timerów 10Hz ? Ja coś w to bardzo wątpię i już to może być pierwszym krokiem do jego problemów a nie żaden brak atomowiści w tych timerkach bo to wręcz nonses !

Zobaczcie sami że w przykładowych kawałkach kodu które pokazał - przeładowuje timer buzzera wartością 1000 !!!!!!

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


czyli gdyby była podstawa czasu 10ms to buzzer brzęczałby przez 10s i przez kolejne 10s byłby cicho - CZY DAŁOBY się usłyszeć różnice w takim TAKCIE ???? gdyby zmieniał się powiedzmy nawet o kilkadziesiąt ms ????????????

No dobra - załóżmy że autor ustawił sobie jakąś randomową podstawę czasu albo nawet niech będzie że ustawił podstawę czasu 1ms co wg mnie jest już nonsensem (albo nie będzie nonsensem dla kogoś kto ew już ma większe doświadczenie w pisaniu programów w sposób nieblokujący i w takim wypadku rzeczywiście warto byłoby już sięgać po AtomicBLOCK) ... Więc jeśli ja miałbym pomóc autorowi w rozwiązaniu problemu to najpierw nakierowałbym go na właściwe tory - żeby zaczął od podstaw bo widać, że jeszcze jest mocno początkujący, a szczególnie w porządnym opisie problemu.

---------------------------------------

krótko albo długo mówiąc ALE WYJAŚNIAJĄC dokładnie przyczynę problemów autora - proszę bardzo pierwszy przykład, z porządną podstawą czasu 10ms dla timerów programowych - jak w Bluebooku - a autor zarzekał się, że wszystko zrobił jak z Bluebooka - ileż ja to razy już słyszałem, a wszyscy poszli tropem opowieści autora - wierząc mu że zrobił jak w Bluebooku - no to jeśli słyszy różny TAKT - to nic tylko ATOMIC BLOCK nie dał ;)

A tymczasem to jest dla niego prawidłowy kod i to bez żadnych kocich kalamburów - w którym widać jak na dłoni co i jak jest skonfigurowane
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


No i niech mi ktoś powie, że tu coś będzie źle śmigało bez atomowego podejścia - MOWA O TYM PROSTYM KODZIE - a nie o domysłach - co by było gdyby, warto się czasem skupić na problemie autora. Ja wprawdzie gdy widzę że kogoś trzeba ciągnąć za język to się po prostu wyłączam i nic dalej się nie odzywam bo po co - strata czasu. Ale że rozgorzała - fajna dyskusja ;) to w końcu też zabrałem głos - ot mogłem się oderwać na chwilę od kursu ESP :)

ale żeby nie było że sobie gdybam to proszę widok z analizatora:
Obrazek

no i zobaczcie Panowie, którzy twierdzicie że tu bez atomic block się nie obejdzie - jak pomimo wszystko są równe odcinki czasu - ok wprawdzie mało ich widać ;) ale spokojnie poczekajcie co dalej pokażę


więc tu spłodziłem nowy kod - tyle że prawdopodobnie zbliżony jak chodzi o czasówki do tego co stworzył autor i to być może nieświadomie - albo i świadomie ale nie raczył puzla pokazać ;)

TYM RAZEM ----- UWAGA !!!! ------ podstawa czasu = 1ms !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


no i może zanim coś powiem to rzućcie okiem na widok z analizatora:
Obrazek

widzicie różnicę ???? Nagle się okazuje, że bardzo często wskakują krótsze odcinki czasowe niż 1s !!!! te krótsze są krótsze aż o ok 30% !!!!! Jak myślicie z czego to wynika ????? .... No to dodajmy ATOMOWE PODEJŚCIE ;)

Więc ten sam kod co wyżej z podstawą czasu 1 ms !!!!!!!!! ale z ATOMIC BLOCK
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


no i już nie będę wklejał kolejnego obrazka z analizatora - bo wygląda on DOOOOKŁAAADNIE tak samo jak ten pierwszy który pokazałem - czyli czasy są równe i wynoszą 1,009 s !!! czyli znowu dobrze !

------------------------------------------------------------------------

PODSUMOWUJĄC - rację mają wszyscy i zwolennicy łupania wszędzie ATOMIC BLOCK nawet bez zastanowienia się - no bo to szkody jakiejś nie przyniesie .... przecież ... ale zawsze dodatkowy kod, miejsce we flashu ;) no i zawsze parę taktów ale zegara ubywa hahahahaha ;)

Rację też ma ZELAOTA - ale właśnie w aspekcie tego co mówił - czyli kodu autora że na kodzie z BLUEBOOKA nie może mieć ŻADNYCH niespodzianek, tylko że każdy wierzy że jak autor napisał - że na 100% zrobił jak w książce to to prawda - a po pierwszej pobieżnej analizie jego kodu widać że NIEPRAWDA bo właśnie podstawa czasu wg mnie jest na 100% inna niż ta o której mówię w Bluebooku i NACISKAM wręcz że dla prostych timerków programowych nie schodźcie poniżej 10ms .... Ale co tam pomyślał autor ;) i zrobił po swojemu. Tyle że ciekaw jestem czy ten czas dobrał świadomie czy przypadkowo mu tak wyszło - jeśli się nie obrazi to może odwróci ostatnie puzzle i wypowie się - co i jak ustawiał i jakie ma F_CPU i dlaczego zrobił TAK a nie jak Bluebooku. A na dodatek może sobie skopiować ten pierwszy kod - który pokazałem z timerami z podstawą 10ms (tylko niech przerobi rejestry dla swojego procka bo nie miał m32 tylko jakiś nowszy) i niech sprawdzi sobie jeden, drugi i trzeci kod który pokazałem - to mam nadzieję, że w końcu mu to coś powie.

------------------------

Na ZAKOŃCZENIE moja odpowiedź:

TAK tego typu proste timerki programowe można używać bez ATOMIC BLOCK bo po to one są stworzone i nawet jeśli raz na pierdyliard obiegów pętli głównej dojdzie do super specyficznej sytuacji jaką słusznie opisał i pokazał w ASM kolega Andrews - to proszę pamiętać - timerki programowe mogą mieć spory rozrzut i są używane do rozdzielania czasu dla ZADAŃ - coś na zasadzie RTOS'a ;)

zresztą jak myślicie - dlaczego w RTOS'ach - nawet na bajecznie szybszych procesorach - podstawa czasu to właśnie 10ms a nie żadna 1ms ?

Tak więc Andrews nie myśl, że ja tu chcę z kolei podważać to co mówisz - i widzisz że przyznaję rację nawet w tym, że i w tych timerkach programowych może dojść (choć wg mnie cholernie rzadko - totolotek) do takich sytuacji o których piszesz - tak więc tu chodzi też troszkę o taką hmmm praktykę programowania

ZELAOTA - jeśli miałeś na myśli podstawę czasu 10ms - to praktycznie wszystkie twoje uwagi były słuszne - szczególnie te odnośnie że chodzi o problem autora i że nie może się tu nic złego dziać, i o to, że takie przerwanie praktcznie nie będzie trafiać przy podstawie 10ms ani drastycznie niszczyć czasów pracy timerów - a NAWET jeśli raz na miliard obiegów jakiś TASK (timer programowy wykona szybciej swoje zadanie) to nikt od tego nie zginie - o ile wie co to są timery programowe i jak się z nich korzysta i wie jak pisać programy w sposób nieblokujący.

.... miało być krótko - a wyszło jak to u mnie - poemat - sorki ;)

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 6 maja 2022, o 06:14 
Offline
Nowy

Dołączył(a): 05 paź 2021
Posty: 24
Pomógł: 0

Przerwanie miałem ustawione co 1ms. Po zmianie na 10ms efekt "cudów" zniknął.
Dziękuję wszystkim za pomoc i przede wszystkim ciekawą dyskusję.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 6 maja 2022, o 07:19 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 22 paź 2013
Posty: 1960
Lokalizacja: Lipsko
Pomógł: 125

No piękny felieton Mirek :) Teraz to i mnie się rozjaśniło. Wg powyższego moje problemy z nierównym odliczaniem, są tak widoczne, bo stosuję zazwyczaj podstawę nie większą niż 1ms - dość często 100us, a bywało, że i 50us i mniej. Może to dziwić, ale bardzo mi pomaga takie poganianie przerwań. Często umieszczam tam algorytmy, które wymagają szybkiego odświeżania, a o pętlę główną się nie martwię, bo ZAWSZE jest w pełni przelotowa nawet z wyświetlaczem LCD, który jest buforowany i jego obsługa zajmuje jednorazowo kilka/naście us. Może jestem szalony, ale ja na tych prostych timerach zegary dokładnie odliczające czas zawsze robię :)
Jak w takim razie sobie radzę z dłuższym odcinkami? Na dwa sposoby - dokładny i mniej dokładny (teoretycznie, bo w praktyce nie widzę różnicy). Dokładny to użycie dodatkowej zmiennej w przerwaniach jako dzielnik dziełu czemu z pętli głównej wysyłam do timera zmienną jednobajtową, a mniej dokładny - w przerwaniach jest jeden timer sterujący, a w pętli głównej pod tym timerem kolejne timery już z wykorzystaniem dowolnej zmiennej (nawet 32bitowej). Jak wspominałem pętla główna u mnie jest nieblokująca i zabieg ten w moich programach sprawdza się praktycznie zawsze. Polecam :)

_________________
http://www.sylwekkuna.com



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 6 maja 2022, o 08:08 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27212
Lokalizacja: Szczecin
Pomógł: 1041

SylwekK napisał(a):
bo stosuję zazwyczaj podstawę nie większą niż 1ms

Ja to doskonale wiem, bo kiedyś pisaliśmy nawet o tym na tym forum i wcale nikt nie jest szalony skoro takich technik używa, po to jest procek, żeby go cisnąć na maxa gdy trzeba. Powiem tak mnóstwo ludzi tak korzysta z procka - tylko, że tego już się nie da nazwać typowymi prostymi timerkami programowymi. W takich wypadkach gdy już schodzisz nawet do 100us czy 50us to jest już odmierzanie czasu dla konkretnych i sam przyznasz b.krótkich zdarzeń bo przecież przy 50us nie powiesz, że pakujesz tam jakiś kod który potrzebuje na wykonanie więcej niż 50us - pewnie zajmuje on nawet mniej niż połowę tego czasu. I to jest normalne jak jedzenie bułek z masłem i serem w programowaniu ... tylko właśnie trzeba mieć już na prawdę dobre doświadczenie w pisaniu programów w sposób nieblokujący ... a wiem, że ty masz i to duże bo już Bascoma wyciskałeś na MAXA kiedyś (ja też zresztą zanim przesiadłem się na C). Dlatego też na końcu mówiłem, że każdy ma rację - tylko w nieco innych aspektach i nie dotyczących koniecznie akurat tego konkretnego przypadku u autora tego wątku.

------------------------ [ Dodano po: kilkunastu sekundach ]

Rnext napisał(a):
Przerwanie miałem ustawione co 1ms. Po zmianie na 10ms efekt "cudów" zniknął.
Dziękuję wszystkim za pomoc i przede wszystkim ciekawą dyskusję.


No i bardzo fajnie - cieszę się, że ruszyło - teraz na pewno w przyszłości łatwiej będzie ci korzystać z tych mechanizmów

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 6 maja 2022, o 08:57 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 15 lut 2017
Posty: 369
Lokalizacja: Gliwice
Pomógł: 34

SylwekK napisał(a):
nie większą niż 1ms - dość często 100us, a bywało, że i 50us

Tak też podejrzewałem, ze w tym wątku piszemy głównie o CZYM INNYM.
Ja o softTimerach w rozumieniu bluebook, a Autor o czym innym :)
Jakiś kod ma u siebie, do wątku wrzuca jakieś tylko swoje zmiany wyrwane z kontekstu, opisuje to kodem przepisanym "żywcem" z książki, a tak na prawdę to działa chaotycznie, nieprecyzyjnie przedstawia problem. To najgorszy ze sposobów szukania pomocy
Jakie to charakterystyczne dla programistów, którzy już mają sporą wiedzę, ale brakuje pokory :)

SylwekK to już w ogóle o czym innym. soft timer 100us - w ogóle bym tego nie nazwał soft timerem jak uczono nas w Bluebooku.

Dziwię się tylko, że jeszcze takie coś "wchodzi" na forum Atnel, kiedy Mirek od chyba już 10 lat mówi jak działać.

To takie ogólne obserwacje i one tyczą się wszelkim gremiów technicznych.
Musiałem to wyrzuć z siebie, bo od połowy wątku już mnie to gryzło :)
Nie miałem na myśli oczywiście nic złego tak pisząc, jedynie komentuję "rzeczywistość"

Jeszcze apropos roboty Andrews, to faktycznie "wyprostował" mnie w tym sensie, że zupełnie pominąłem fakt możliwości "rozdarcia" warunku IF.
Cały czas byłem skupiony na modyfikacji softTimer1 = 1000, która była zabezpieczona poprzez długi okres między przerwaniami.
Natomiast zarzut o patrzeniu z perspektywy C nie był zasadny, bo pierwsze co zrobiłem przy analizie to spojrzenie do asemblera :)

Tyle wyjaśnień.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
Wyświetl posty nie starsze niż:  Sortuj wg  
Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 27 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Google [Bot] i 7 gości


Nie możesz rozpoczynać nowych wątków
Nie możesz odpowiadać w wątkach
Nie możesz edytować swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Skocz do:  
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO