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

[STM32][C] Usypianie procesora sleep-on-exit

onicram 03 Kwi 2010 17:00 2881 5
  • #1 03 Kwi 2010 17:00
    onicram
    Poziom 9  

    Witam,

    Mam pewien problem z usypianiem/wybudzaniem procesora. Chciałbym uśpić procesor na czas wykonania konwersji przez przetwornik. Chciałem do tego celu wykorzystać tryb SLEEP ON EXIT. Rozpoczęcie konwersji wykonywane jest w przerwaniu od Timera, po wykonaniu instrukcji rozpoczynającej konwersję chciałem uśpić procesor, a wybudzić go w procedurze obsługi przerwania od zakończenia konwersji przetwornika.

    Mam jednak pewien problem, procesor się usypia jednak nie wybudza się. Czy aby go wybudzić przerwaniem od przetwornika trzeba jeszcze coś ustawiać?
    Niestety opis całego procesu usypiania/wybudzania procesora zawarty zarówno w dokumentacji jak i w książce K. Paprockiego jest dla mnie trochę niejasny.
    Czy ktoś umiałby mi wyjaśnić jak należy całą operację wykonać?
    Jakie działanie ma makro __WFE, a jakie użycie instrukcji z biblioteki API NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT, ENABLE)?
    Czy żeby procesor budził się tylko i wyłącznie od przerwania ADC należy "sterować" priorytetami przerwań?

    Będę bardzo wdzięczny za pomoc.
    Pozdrawiam
    Marcin.

    0 5
  • Metal Work Pneumatic
  • #2 03 Kwi 2010 18:37
    michalko12
    Specjalista - Mikrokontrolery

    __WFE to nic innego jak instrukcja asemblerowa "wfe". NVIC_SystemLPConfig() ustawia sposób wejścia w tryb uśpienia.
    Jesli chcesz to zrobić poprzez WFE musisz jeszcze ustawić SEVONPEND, NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT | NVIC_LP_SEVONPEND, ENABLE).
    Możesz tez zostawić NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT, ENABLE) w takiej wersji i zamiast __WFE użyć __WFI .

    0
  • Metal Work Pneumatic
  • #3 04 Kwi 2010 13:36
    onicram
    Poziom 9  

    Witam,

    Dzięki za zainteresowanie tematem i za pomoc. Moje rozumowanie było bardzo podobne do tego co opisałeś w swoim poście, jednak nadal mam problem.

    Usypianie i wybudzanie procesora działa, ale tylko wtedy kiedy robię to np w pętli głównej - używałem zarówno instrukcji __WFI(); jak i __WFE(); i obie działają bez ustawiania czegokolwiek więcej. Procesor wybudza się bez problemu.
    Kiedy użyje tych instrukcji w przerwaniu aby uśpić procesor, po to aby następne przerwanie go wybudziło, procesor usypia się ale nie wybudza.
    Użycie gdziekolwiek w programie czy to w przerwaniu czy to w pętli głównej instrukcji NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT, ENABLE) powoduje uspanie procesora (nieużywane są wtedy WFI i WFE) - nie da się go wybudzić innym przerwaniem.

    Czy jeszcze coś może robię źle? Może jeszcze jakieś inne wskazówki? Jest to trochę dla mnie niezrozumiałe dlaczego nie można wybudzić procesora uspanego w przerwaniu...

    Będę bardzo wdzięczny za kolejne wskazówki.
    Pozdrawiam
    Marcin

    0
  • #4 05 Kwi 2010 17:14
    michalko12
    Specjalista - Mikrokontrolery

    onicram napisał:
    Usypianie i wybudzanie procesora działa, ale tylko wtedy kiedy robię to np w pętli głównej - używałem zarówno instrukcji __WFI(); jak i __WFE(); i obie działają bez ustawiania czegokolwiek więcej. Procesor wybudza się bez problemu.
    Kiedy użyje tych instrukcji w przerwaniu aby uśpić procesor, po to aby następne przerwanie go wybudziło, procesor usypia się ale nie wybudza.
    Użycie gdziekolwiek w programie czy to w przerwaniu czy to w pętli głównej instrukcji NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT, ENABLE) powoduje uspanie procesora (nieużywane są wtedy WFI i WFE) - nie da się go wybudzić innym przerwaniem.

    NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT, ENABLE) nie powinna powodować wejścia w tryb uśpienia, to co się dzieje mysi być związane z czymś innym. Może występuje jakiś inny wyjątek. Jeśli nie użyjesz tej funkcji w takiej postaci to jeśli procesor został uśpiony z funkcji przerwania, wybudzić go może tylko przerwanie o wyższym priorytecie.
    Po czym poznajesz, że procesor wchodzi w tryb uśpienia po wykonaniu NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT, ENABLE)?

    0
  • #5 05 Kwi 2010 23:09
    onicram
    Poziom 9  

    Mam przerwanie od odbioru po UARCIE, w którym mam instrukcje NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT, ENABLE) i ta instrukcją usypiam procesor (wiem że się usypia, ponieważ w pętli głównej migam diodą, która przestaje migać).
    Faktem jest to, że przerwanie o wyższym priorytecie budzi procesor, w przerwaniu które budzi procesor, należy użyć jeszcze instrukcji NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT, DISABLE). Mam inne takie przerwanie którym mogę obudzić procesor. Teraz wydaje się że wszystko działa. Pytanie jest tylko takie, jak zrobić, żeby procesor nie budził się od przerwania o wyższym priorytecie, a od przerwania o jakimkolwiek priorytecie... jeżeli w ogóle da się tak zrobić.

    Cytat:
    NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT, ENABLE) nie powinna powodować wejścia w tryb uśpienia, to co się dzieje mysi być związane z czymś innym. Może występuje jakiś inny wyjątek. Jeśli nie użyjesz tej funkcji w takiej postaci to jeśli procesor został uśpiony z funkcji przerwania, wybudzić go może tylko przerwanie o wyższym priorytecie.


    Znalazłem coś takiego jeszcze:
    Cytat:

    ENTER SLEEPONEXIT:
    If the SLEEPONEXIT bit of the SCR is set to 1, when the processor completes the execution of an exception handler it returns to Thread mode and immediately enters sleep mode. Use this mechanism in applications that only require the processor to run when an exception occurs.

    EXIT SLEEPONEXIT
    Normally, the processor wakes up only when it detects an exception with sufficient priority to cause exception entry.

    Źródło: Link (Strona 30).

    Co jednak oznacza, że samo użycie instrukcji NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT, ENABLE) może jednak uśpić procesor. Z tego co zrozumiałem budzić procesor może jedynie przerwanie o wyższym priorytecie... Czy tak? Pytanie dodatkowe: jak najłatwiej chwilowo blokować dane przerwania? Tylko wyłączając je kolejno?

    Pozdrawiam
    Marcin

    0
  • #6 06 Kwi 2010 12:58
    michalko12
    Specjalista - Mikrokontrolery

    onicram napisał:
    Mam przerwanie od odbioru po UARCIE, w którym mam instrukcje NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT, ENABLE) i ta instrukcją usypiam procesor (wiem że się usypia, ponieważ w pętli głównej migam diodą, która przestaje migać).
    Faktem jest to, że przerwanie o wyższym priorytecie budzi procesor, w przerwaniu które budzi procesor, należy użyć jeszcze instrukcji NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT, DISABLE). Mam inne takie przerwanie którym mogę obudzić procesor. Teraz wydaje się że wszystko działa. Pytanie jest tylko takie, jak zrobić, żeby procesor nie budził się od przerwania o wyższym priorytecie, a od przerwania o jakimkolwiek priorytecie... jeżeli w ogóle da się tak zrobić.

    Cytat:
    NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT, ENABLE) nie powinna powodować wejścia w tryb uśpienia, to co się dzieje mysi być związane z czymś innym. Może występuje jakiś inny wyjątek. Jeśli nie użyjesz tej funkcji w takiej postaci to jeśli procesor został uśpiony z funkcji przerwania, wybudzić go może tylko przerwanie o wyższym priorytecie.


    Znalazłem coś takiego jeszcze:
    Cytat:

    ENTER SLEEPONEXIT:
    If the SLEEPONEXIT bit of the SCR is set to 1, when the processor completes the execution of an exception handler it returns to Thread mode and immediately enters sleep mode. Use this mechanism in applications that only require the processor to run when an exception occurs.

    EXIT SLEEPONEXIT
    Normally, the processor wakes up only when it detects an exception with sufficient priority to cause exception entry.

    Źródło: Link (Strona 30).

    Co jednak oznacza, że samo użycie instrukcji NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT, ENABLE) może jednak uśpić procesor. Z tego co zrozumiałem budzić procesor może jedynie przerwanie o wyższym priorytecie... Czy tak? Pytanie dodatkowe: jak najłatwiej chwilowo blokować dane przerwania? Tylko wyłączając je kolejno?

    Pozdrawiam
    Marcin


    Rzeczywiście, bit SLEEPONEXIT usypia procesor, miałem trochę inne wyobrażenie o tym bicie, że działa w połączeniu z instrukcja wfi lub wfe. W takim wypadku przerwanie o dowolnym priorytecie wybudza procesor, ponieważ procesor nie uśpi się dopóki nie przejdzie w tryb Thread Mode.

    Co do blokowania przerwań no to jest kilka sposobów
    Poprzez rejestry maskujące PRIMASK, FAULTMASK, BASEPRI
    Poprzez zablokowanie ich w NVIC lub w rejestrach peryferiów.
    Dobra opcją jest maskowanie grupy przerwań poprzez rejestr BASEPRI, ale w tym przypadku odpowiednio muszą być skonfigurowane priorytety przerwań.

    0
  Szukaj w 5mln produktów