Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyj±tek www.elektroda.pl do Adblock.
Dzięki temu, że ogl±dasz reklamy, wspierasz portal i użytkowników.

Jak u¶pić ARMa instrukcj± __WFI ?

Zlotorowicz 08 Kwi 2018 11:27 774 23
  • #1 08 Kwi 2018 11:27
    Zlotorowicz
    Poziom 4  

    Witam,

    Mam program, w którym procesor nic nie robi, tylko czeka na przerwanie od Timera.
    W tle pracuje DMA na kilku kanałach.
    Chciałem zmniejszyć pobór pr±du i w chwili wyczekiwania na przerwanie Timera dałem polecenie u¶pienia __WFI.
    Ale nie ma reakcji, pobór pr±du jest identyczny.
    Co więcej, jesli zablokuje Timer a także Systick to procek, jakby nie reagował na to polecenie.
    Czy trzeba jeszcze co¶ zrobić, aby ten tryb u¶pienia uzyskać?

    Próbowałem jeszcze dodać wcze¶niej : NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT,ENABLE); ale to blokuje całkowicie procesor.


    pozdrawiam

    0 23
  • #2 08 Kwi 2018 11:43
    BlueDraco
    Specjalista - Mikrokontrolery

    Albo __WFI() w pętli for (;;), albo wł±czyć SleepOnExit i potem pojedyncze WFI (ładniej). Je¶li nie zauważasz spadku natężenia pr±du, to być może masz stale aktywne przerwanie, bo np. nie kasujesz znacznika jego zgłoszenia. Dopóki nie pokażesz minimalnego kodu - możemy tylko pogdybać.

    0
  • #3 08 Kwi 2018 11:59
    Zlotorowicz
    Poziom 4  

    No więc mam w Mainie co¶ takiego:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Timer na 100% dziala, przerwanie wygl±da tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    A jednak efekt jest taki, że procesor zatrzymuje się na tym __WFI jesli jest wcze¶niej NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT,ENABLE);.

    Chyba że Ľle rozumiem ten __WFI, bo wydaje mi się, że powinno być tak, że procek na tej instrukcji sie zatrzymuje i czeka na dowolne przerwanie.
    Gdy je uzyska, to idzie dalej.
    Czy tak to działa?

    0
  • #5 08 Kwi 2018 12:06
    Zlotorowicz
    Poziom 4  

    Dzieki.
    Spróbuje zmienić wszystkie piny i sprawdzę jaki to ma wpływ na pobór pr±du.
    A mam jeszcze pytanie, czy użycie tego __WFI wymaga jeszcze czego¶ wcze¶niej?
    Czy wł±czenie jakiego¶ zegara jest potrzebne?
    Zastanawia mnie to, bo bez przerwania procek przechodzi przez to __WFI.

    Wstawienie NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT,ENABLE); blokuje mi działanie programu nawet gdy zadziała przerwanie.

    Wydaje mi się, że je¶li będzie tak:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    To procek powinien sie zatrzymać.

    A je¶li tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    to powienien po otrzymania przerwania pój¶ć dalej.
    Czy dobrze rozumuje?

    0
  • Pomocny post
    #6 08 Kwi 2018 12:19
    BlueDraco
    Specjalista - Mikrokontrolery

    Fakt, nieużywane linie trzeba ustawić inaczej niż jako wisz±ce wej¶cia - w tryb analogowy, jako wyj¶cie, lub wej¶cie podci±gnięte.
    Problem może też leżeć w użyciu "wygodnych" funkcji i stałych. Zwłaszcza niebezpieczna jest stała SET.
    __WFI tak wła¶nie działa. Je¶li ustawisz SleepOnExit, to już nie "idzie dalej" nawet po przerwaniu.

    0
  • #7 08 Kwi 2018 12:39
    Zlotorowicz
    Poziom 4  

    BlueDraco napisał:
    __WFI tak wła¶nie działa. Je¶li ustawisz SleepOnExit, to już nie "idzie dalej" nawet po przerwaniu.


    to jak zrobić, aby procesor poszedł dalej , ale dopiero po przerwaniu?

    0
  • #8 08 Kwi 2018 15:24
    BlueDraco
    Specjalista - Mikrokontrolery

    Proste: nie ustawiaj SleepOnExit i wrzuć WFI w pętlę. Tylko zupełnie nie wiem, po co ma "chodzić dalej". Kod, który pokazujesz, jest dziwny, WFI jest zwykle ostatni± instrukcj± prohgramu inicjuj±cego - dalsza aktywno¶ć dzieje się wył±cznie w przerwaniach.

    0
  • #9 08 Kwi 2018 20:28
    Zlotorowicz
    Poziom 4  

    Może co¶ Ľle rozumiem.
    WFI to znaczy Wait For Interrupt.
    Czyli procesor w tym momencie sie zatrzymuje i czeka na jakiekolwiek przerwanie.
    Je¶li przerwanie się pojawia, to procesor sie budzi i przechodzi do nastepnej instrukcji po __WFI.
    Ale tak nie jest, bo u mnie bez przerwań , procesor nie zwraca uwagę na to WFI i leci dalej.

    Moja konstrukcja programu polegała na tym, aby w pętli głównej wykonywać tylko komendy po ustawieniu się flagi w przerwaniu.
    Pozwoliłem sobie upro¶cić program następuj±co:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Powyższy program według mojej logiki powinien działać w taki sposób, że dioda LED nie mruga gdy nie ma przerwan.
    Ale je¶li przerwanie się pojawi, to dioda powinna mrugnac.
    Dobrze my¶le?
    Bo u mnie jest dokładnie tak jak wyżej, przerwania wyłaczyłem a dioda LED mruga.

    0
  • #10 08 Kwi 2018 21:17
    BlueDraco
    Specjalista - Mikrokontrolery

    Ľle my¶lisz.
    Po co Ci ta "pętla główna"? Do sztucznego podziału akcji podejmowanych w wyniku przerwania na dwa kawałki kodu bez potrzeby? (Ew. po co przerwanie i drugi znacznik programowy, skoro sam timer sprzętowo ustawia znacznik zdarzenia?)
    Jeżeli odblokowane w NVIC przerwanie jest zgłoszone, a priorytet procesora nie zezwala na jego obsługę,WFI się wykona i zakończy, a wykonanie programu będzie kontynuowane.

    0
  • #11 08 Kwi 2018 22:05
    Zlotorowicz
    Poziom 4  

    Faktycznie nie ogarniam tego.
    Wygladaj±ca banalnie funkcja, a jednak nie do końca.
    Proste pytanie:
    Czy je¶li program zostanie ograniczony do czegos takiego:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Czy dioda będzie ¶wiecić, czy nie?

    0
  • #12 08 Kwi 2018 22:51
    BlueDraco
    Specjalista - Mikrokontrolery

    Nie za¶wieci, bo:
    - nie zainicjowałe¶ portu dla LED, więc jest wej¶ciem ;)
    - żadne przerwanie nie zostało wł±czone w NVIC ani w SYS. WFI zawi¶nie na zawsze.

    0
  • #13 08 Kwi 2018 23:09
    Zlotorowicz
    Poziom 4  

    Faktycznie nie dodałem inicjacji portu od LEda.
    Raczej był to tylko przykład.

    Ale tak czy inaczej, jesli __WFI jest pierwsz± instrukcj± w programie i nie ma mozliwosci aby jakiekolwiek przerwanie było uruchomione to procesor przechodzi przez t± komendę bez problemu.

    Nie wiem o co chodzi.

    0
  • Pomocny post
    #14 09 Kwi 2018 12:37
    BlueDraco
    Specjalista - Mikrokontrolery

    Nie przechodzi. Zatrzymuje się i czeka na przerwanie z NVIC lub rdzenia. Przerwanie to nie musi być odblokowane w NVIC i nie musi być obsługiwane, ważne, żeby wyst±piło.

    0
  • #15 09 Kwi 2018 19:26
    Zlotorowicz
    Poziom 4  

    Tylko ze, jesli umieszczam instrukcje WFI jako pierwsza w Main, to czemu procesor przechodzi przez nia ? Nie zatrzymuje sie, na nic nie czeka tylko jakby to byl NOP idzie dalej. To jest dla mnie niezrozumiale.

    0
  • #16 13 Kwi 2018 08:42
    Zlotorowicz
    Poziom 4  

    Czy taka koncepcja jest prawidłowa:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Cały program dałem do procedury obsługi przerwania.
    Czy teraz jest dobrze?

    0
  • Pomocny post
    #17 13 Kwi 2018 09:25
    BlueDraco
    Specjalista - Mikrokontrolery

    Ľle, bo po wyj¶ciu z WFI procesor będzie kręcił się w pętli i już nie u¶nie. Umie¶ć WFI w pętli lub (lepiej) wł±cz SleepOnExit przed WFI.

    0
  • #18 13 Kwi 2018 11:28
    Zlotorowicz
    Poziom 4  

    Dziękuję BlueDraco za cierpliowo¶ć i cenne rady.

    Czy tak będzie dobrze?

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Tylko, że mam inny problem.
    Otóż nie mogę wszystkiego przerzucić do przerwania.
    Czy może więc być tak, że w przerwaniu ustawiana jest tylko flaga, a w Mainie jest oczekiwanie na ni± w u¶pieniu.
    My¶lę o czyms takim:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #19 13 Kwi 2018 14:57
    BlueDraco
    Specjalista - Mikrokontrolery

    A z jakiego to niby powodu nie możesz przerzucić wszystkiego do przerwania?

    Pomy¶l, co się stanie, gdy przerwanie nast±pi po sprawdzeniu znacznika w warunku if(), a przed _WFI...

    Pro¶ciutki bł±d pocz±tkuj±cych.

    0
  • #20 13 Kwi 2018 17:00
    Zlotorowicz
    Poziom 4  

    Przerzuciłem cały program do przerwania, ale nie działał mi prawidłowo. Chodzi o to, że w programie też używam przerwań, więc powstaj± przerwania w przerwaniu. Wiem że to sie da jako¶ ze sob± poł±czyć, ale nie jestem na tyle biegły aby to zrobić.
    Chciałem zrobić prosty delay , w czasie którego procesor będzie pobieral mniej pr±du.
    Ale widzę że to nie jest proste.

    0
  • #21 13 Kwi 2018 18:00
    nowyARM
    Poziom 24  

    Zlotorowicz napisał:
    Chodzi o to, że w programie też używam przerwań, więc powstaj± przerwania w przerwaniu. Wiem że to sie da jako¶ ze sob± poł±czyć, ale nie jestem na tyle biegły aby to zrobić.

    Deklaruj±c poziomy przerwań.

    Zlotorowicz napisał:
    Chciałem zrobić prosty delay , w czasie którego procesor będzie pobieral mniej pr±du.

    Użyj timera, który po zadanym czasie wygeneruje przerwanie.


    Je¶li używasz STM32Fxxx to może użyj CubeMX. Tam łatwo ustawia się różne opcje, Cube wygeneruje kod, który zaimportujesz.

    0
  • #22 13 Kwi 2018 18:26
    BlueDraco
    Specjalista - Mikrokontrolery

    Priorytetów przerwań nie ruszaj. Najpierw zastanów się, co wła¶ciwie chcesz osi±gn±ć i jakie przerwania s± do tego potrzebne. Podajesz tak wyrywkowe informacje, że nie sposób zrozumieć, o co wła¶ciwie chodzi.

    0
  • #23 14 Kwi 2018 08:32
    Zlotorowicz
    Poziom 4  

    Ok, to wyja¶nie raz jeszcze.
    Mam program, który wykorzystuje DMA do pomiaru ADC, wysyłki i odbioru UARTA.
    Program używa też wtedy innych Timerów.
    Wszystko pieknie działa.
    Postanowiłem powalczyć trochę o ekologię i obniżyć pobór pr±du.
    Działanie całego programu sprowadziłem do tego, że może on tylko zostawać wykonywany raz na 100ms.
    Program sie wykonuje i znów Delay(100) i tak w kółko.
    Użyłem do tego Timera, który co 100ms ustawia flagę i program sie uruchamia.
    I teraz postanowiłem, aby do czasu gdy Timer nie zgłosi przerwania panował stan u¶pienia.
    Cało¶ć zatem działa następuj±co:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Wydaje mi się, że znalazłem rozwi±zanie.
    Niby działa, ale nie wiem, czy jest to prawidłowe:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Nie jestem pewien, czy bezpieczniej użyć __WFI() w ifie. czy w głónej pętli.

    0
  • #24 14 Kwi 2018 08:43
    BlueDraco
    Specjalista - Mikrokontrolery

    Przemy¶l i napisz jeszcze raz od pocz±tku. Co naprawdę masz do zrobienia co 100 ms? Nie wiemy. Powieniene¶ to robić w przerwaniu, ale w tym przerwaniu nie możesz na nic czekać - do akcji wymagaj±cych oczekiwania/rozci±gnięcia w czasie użyj innych przerwań lub DMA. Póki co nic nie wskazuje na to, że musisz mieć jak±¶ "pętlę główn±", a funkcjonalno¶ć programu trzymasz w tajemnicy.
    Odbiór z UART najłtwiej zrobić na przerwaniach, nadawanie być może łatwiej przez DMA. Odliczaj w przerwaniu timera do 100 ms i inicjuj odpowiednie akcje, które dalej będ± wykonywać się "same".

    0