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

[STM32][C] FreeRTOS -Ustawianie semafora w przerwaniu od TIM

22 Lis 2010 02:43 2843 9
  • Poziom 8  
    Witam.
    Mam następujący problem. Otóż, chcę w obsłudze przerwania od kanału 1 timera TIM1 ustawiać semafor, na podstawie którego wykonuje się jedno z zadań. Robię to w standardowy (chyba) sposób:

    Code:

    // Obsluga przerwania od TIM1
    void TIM1_CC_IRQHandler(void)
    {
       static portBASE_TYPE xHigherPriorityTaskWoken;
       xHigherPriorityTaskWoken = pdFALSE;
       if(TIM_GetITStatus(TIM1, TIM_IT_CC1) != RESET)
       {
          // Ustaw odpowiedni stan semafora
          xSemaphoreGiveFromISR(xSemaphoreTIM1, &xHigherPriorityTaskWoken);
          // Czyszczenie flagi przerwania
          TIM_ClearITPendingBit(TIM1, TIM_IT_CC1);
          // Ponowne ustawienie rejestru przepelnienia
          TIM_SetCompare1(TIM1, TIM_GetCapture1(TIM1) + CC1);
       }    
    }


    Niestety przy próbie wykonania instrukcji

    Code:

    xSemaphoreGiveFromISR(xSemaphoreTIM1, &xHigherPriorityTaskWoken);

    pojawia się Hard Fault.

    Z kolei przerwania zewnętrzne EXTI obsługuję w identyczny sposób i tam ustawianie semaforów działa bez problemów. Za drugim razem w obsłudze przerwania od TIM umieściłem dodawanie do kolejki zamiast ustawiania semafora, jednak ponownie w momencie wpisywania do kolejki - Hard Fault. W debuggerze Keila podejrzałem, że przy Hard Fault zaznaczone jest IMPRECISERR w okienku Bus Faults.

    Chwilowo wyczerpały mi się pomysły dlaczego to nie działa. Czy ma ktoś może jakąś koncepcję o co chodzi?
  • Poziom 35  
    1) Sprawdz co robi procesor, instrukcja po instrukcji. Postaw breakpointa w linijce gdzie funkcja jest wywolywana, a nastepnie idz przez assembler.
    Zwróć uwagę na:
    - adresy dostepu. Jak wystąpi ci np. str z adresem docelowym zero, znajdz dlaczego zero...
    - stos. Czy aby na pewno sie nie przepełnia?...

    U mnie nigdy takich szopek nie bylo...
  • Poziom 25  
    Jak inicjalizujesz semafor?
  • Poziom 8  
    nsvinc napisał:
    1) Sprawdz co robi procesor, instrukcja po instrukcji. Postaw breakpointa w linijce gdzie funkcja jest wywolywana, a nastepnie idz przez assembler.
    Zwróć uwagę na:
    - adresy dostepu. Jak wystąpi ci np. str z adresem docelowym zero, znajdz dlaczego zero...
    - stos. Czy aby na pewno sie nie przepełnia?...

    Wcześniej krokowałem swój program i ostatnią instrukcją jaka się wykonuje jest linijka 998 w pliku queue.c:
    Code:
    memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( unsigned ) pxQueue->uxItemSize );

    Zwrócę uwagę na powyższe sugestie, dzięki.
    Co do inicjalizacji semafora:
    Code:
    xSemaphoreHandle xSemaphoreTIM1 = NULL;
  • Pomocny post
    Poziom 35  
    Jesli ostatni próbuje się wykonać memcpy, to na 99% jest to zapisz danych pod zero lub inna pamięc RO.
    Dowiedz się ile wynosi parametr pxQueue->pcWriteTo. Jeśli ta liczba to nie jest adres RAMu (0x20000000+[wielkoscRamu] ), to musisz sprawdzić dlaczego.

    Czemu przypisujesz NULL do semafora? xSemaphoreHandle jest wskaznikiem, z ktorego korzysta RTOS. Skoro ten wskaznik u ciebie ==0, no to krzaki gotowe...
  • Poziom 25  
    @Misztel_1
    Wszystko fajnie tylko zapomniałeś o tym że poza zadeklarowaniem semafora trzeba go jeszcze zainicjalizować:
    Code:

    xSemaphoreHandle xSemaphore = NULL;
    xSemaphoreCreateBinary(xSemaphore);
    if(xSemaphore != NULL){
        //semafor binarny utworzony mozna dzialac dalej
    }

    lub
    Code:

    xSemaphoreHandle xMutex = NULL;
    xMutex = xSemaphoreCreateMutex();
    if(xMutex != NULL){
        //mutex utworzony mozna dzialac dalej
    }
  • Poziom 8  
    Inicjalizację semafora robię już w obsłudze zadania, to błąd? Inne zadania z semaforami ustawianymi przez EXTI mam napisane dokładnie w ten sam sposób i działają OK.

    Code:
    // Zadanie obslugujace przerwanie od TIM1
    
    void vTaskTIM1(void * pvParameters)
    {   
       vSemaphoreCreateBinary( xSemaphoreTIM1 );
       // Nieskonczona petla zadania
       for(;;)
       {
          // Poczekaj az przerwanie od TIM1 ustawi semafor
          if(xSemaphoreTake(xSemaphoreTIM1,( portTickType ) 10) == pdTRUE)
          {
             ...
  • Pomocny post
    Poziom 25  
    Więc proponuję Ci włączyć dane przerwanie dopiero po zarejestrowaniu semafora. Tak naprawde to powinieneś tak postępować z każdym mutexem,kolejką czy semaforem, niezależnie czy operują one w przerwaniu czy w tasku.
    Czyli najpierw tworzymy semafor, a potem uruchamiamy task, czy też włączamy dane przerwanie.
  • Poziom 8  
    Faktycznie, inicjalizacja semafora wykonana przed włączeniem timera rozwiązała sprawę. Teraz jest on już elegancko ustawiany w przerwaniu od TIM. Pojawiły się co prawda inne problemy w dalszej części programu, ale muszę je spokojnie przemyśleć.

    Dziękuję Wam za pomoc!
  • Poziom 21  
    Miałem podobny problem z przerwaniem od RTC (przeliczanie/odświeżanie dnia/miesiąca/godziny itd do struktury). Po zainicjowaniu przerwań:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Flaga przerwania od RTC była aktywna.
    Wystarczy że ręcznie ją kasuję po inicjalizacji przerwania:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    I jest po problemie.. Inicjalizację sprzętu mam przed wystartowaniem FreeRTOS'a.
    Może komuś się przyda - w tym wypadku zerowanie tej flagi nie ma najmniejszego znaczenia.

    Pozdrawiam