Skocz do zawartości

free RTOS bezpieczne usuwanie zadania i zwalnianie zasobów (esp idf)


Pomocna odpowiedź

Napisano

Mam task który używa UART jako modbus RTU, mam też inne zadanie które może odebrać nową konfigurację, zatem aby przesłać nową konfigurację - na przykład: zmieniony baudrate, zaktualizowaną tablicę deskryptorów czy częstotliwość odpytywania - powinienem to zadanie skreować z nowymi parametrami.

Pytanie, czy zanim usunę zadanie modbus, czy i w jaki sposób zwolnić zasoby, tj: wiem że istnieje coś takiego jak vTaskDelete(); API RTOSa mówi że zadanie zostanie usunięte natychmiast z listy zadań, co się stanie kiedy program będzie aktualnie używał magistrali UART? Czy zanim usunę zadanie powinienem w jakiś sposób wyłączyć magistralę?

vTaskDelete informuje task że ma się skończyć. Dopóki działa pętla wewnętrzna to będzie działać. To nie linuksowy kill.

A semafor nie pomoże?

(edytowany)

To ja wiem, ale co z zajętym uartem?, ja muszę go później uruchomić z nowymi parametrami. Chodzi o to czy takie zamykanie na żywca nie wysypie mi kiedyś aplikacji

Edytowano przez _LM_
(edytowany)

A, semafor albo inne powiadomienie że task ma kończyć robotę i się usunąć, o to ci chodziło? 

Edytowano przez _LM_

Chyba tak bym to widział: appmain sprawdzać czy uchwyt zadania modbus jest != NULL, jeśli NULL to znaczy że zadanie modbusowe usunęło się bo dostało rozkaz z innego (bt) że trzeba zaktualizować jakieś parametry. I wtedy kiedy ten uchwyt jest zwolniony, zainicjować modbusa z nowymi parametrami, przypisując wartość do handlera. Czy za bardzo kombinuję? 

Niezupełnie - task musi dostać informację (np. zmienna uint8_t czy bool) że ma się skończyć. Coś w stylu

while (enabled) loop()

Suicide()

Btw. @Treker co spier...liłeś że z telefonu nie da się włączyć code? Nie pomyliłeś technicznego forum z blogiem trzynastolatki?

2 minuty temu, ethanak napisał:

task musi dostać informację (np. zmienna uint8_t czy bool) że ma się skończyć

To przez powiadomienie do taska i później, usuwanie siebie przez vTaskDelete(NULL);

(edytowany)
TaskHandle_t handle;

app_main(void)
{
    
xTaskCrate(bt_task,.....);
for(;;)
{
    if(handle == NULL)
    {
        xTaskCreate(modbusTask..&handle. &new_param);
    }
}
}


bt_task(void * arg)
{
    for(;;)
    {
        if(cos_nowego)
        {
            if(handle != NULL)
            {
                xTaskNotify( handle, 0, eNoAction ); // wyslij powiadominie do task modbus ze trzeba konczyc robote
            }
        }
    }
}


modbus_task(void *)
{
    // tu powiadomienie 
    if( NotifyTake)
    // konczymy zadanie i 
    vTaskDelete(handle); // lub NULL
}

Sprawdzę tę wersję 

Edytowano przez _LM_
(edytowany)

Ok to należy pokazać wersję którą uruchomiłem i póki co wygląda że działa według powyższego schematu:

app_main sprawdza czy task rtu jest przypisany, jeśli nie, jest inicjalizowany z parametrami zapisanymi w spiffs

     while (1)
     {
        
        if(NULL == mb_rtu_task)
        {
               ret = load_or_create_modbus_config(&rtuconfig);

    if (ret == ESP_OK) {
        ESP_LOGI("MAIN_APP", "System uruchomiony z konfiguracją z pliku");
        
    } else {
        ESP_LOGW("MAIN_APP", "System uruchomiony z DOMYŚLNĄ konfiguracją z powodu błędu.");
    }
              master_init(&rtuconfig, &mb_rtu_task);
        }
        vTaskDelay(100);              
    }
}                 
 

po czym uchwyt ma już jakąś wartość więc warunek zostanie pominięty. 

Następnie kiedy przyleci nowa konfiguracja:

             FILE *fw = fopen(modbus_rtu_config, "wb"); // zapisz nowe ustawienia RTU
            if (fw) {
                 fwrite(rbuf_buffer, 1, data_len, fw);
                 fclose(fw);
                    
                /* wysłać powiadomienie do taska RTU że należy zaktualizaować ustawinia*/
                    if(mb_rtu_task != NULL)
                    {
                        xTaskNotifyGive(mb_rtu_task);
                    }
                
                } else {
                    ESP_LOGE(BLE_RTU_TAG, "Nie udało się otworzyć pliku do zapisu!");
                    free(rbuf_buffer);
                    return ESP_FAIL;
        }
        free(rbuf_buffer);
      

Zostanie ona zapisana do pliku oraz wysyłam powiadomienie do zadania RTU:

        if(ulTaskNotifyTake(pdTRUE,0))
        {
               ESP_LOGW(MBTAG,"Usuwanie siebie");
               mbc_master_delete(master_handle);
               mb_rtu_task = NULL; 
               vTaskDelete(NULL);
        }  

Ważne jest aby zwolnić zasoby sprzętowe przed usunięciem zadania. Następnie "zeruję" uchwyt i usuwam task. Kiedy program wróci do main() i zauważy że wskaźnik nie ma przypisania, rozpocznie ponowne kreowanie funkcji modbus. 

Z mojego punktu widzenia ciekawa funkcjonalność bo nie muszę resetować mikrokontrolera po jakichś zmianach w konfiguracji sprzętu.

 

Edytowano przez _LM_

Można powiedzieć że i zmienna globalna ma tutaj zastosowanie bo taką właśnie jest uchwyt do rtu_task. Nie wykluczone że zostanie to naprawione i prześlę uchwyt przez referencję

@_LM_ chodziło mi o coś trochę innego. Zmienna typu byte (nie wymaga jakchś mutexów) może przechowywać np. "Pracuję", "masz się wyłączyć", "a wiem bo coś jeszcze muszę zrobić" czy nawet "sp...dajal". Zachowując zasadę izolacji kod ustawiający czy sprawdzający stan tej zmiennej nie musi nic wiedzieć o taskach, sraskach czy innych notyfajach - po prostu nic nie wie o multitaskingu.

Akurat teraz siedzę nad kodem playera do książek i coś takiego wykorzystuję. "Stop speaking" po prostu ustawia speaker.disabled i czeka na speaker.isspeking() równy false. Biorąc pod uwagę to, że nie wiem na którym tasku aktualnie działa speaker (czy mp3player) jest to łatwiejsze do opanowania.

(edytowany)

To ja aktualnie: przechowywanie tablicy o nieokreślonej ilości deskryptorów w spiffs, z dynamicznym dodawaniem i usuwaniem z pliku. Już mi się kurzy z głowy. A przy okazji, jakakolwiek ingerencja w rozmiar tej tablicy znów wymusza restartowanie zadania które je obsługuje.  

Edytowano przez _LM_

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...