Come comunicare tra compiti cooperativi "prima io, poi tu"?

3

Sono nella fase finale di sviluppo di un semplice sistema embedded. Il dispositivo esegue la stima del coefficiente PID e quindi istanzia un controller PID con i coefficienti stimati.

L'architettura del programma è il multitasking cooperativo. Il file main.c definisce una serie di funzioni void task_...(void) e le chiama una dopo l'altra su ogni tick del timer.

Vorrei eseguire l'operazione void task_pid_tune(void) per tutto il tempo necessario. Quindi, voglio eseguire l'operazione pid_configure(coefficients) una volta. Da quel momento in poi, voglio eseguire l'operazione pid_run() invece dei due precedenti.

Attualmente tutte e 4 le attività ( pid_tune() non è ancora stata implementata) vengono eseguite in un modo estremamente semplice

while( wait_for_timer_tick() )
{
    task1();
    task2();
    task3();
    task4();
 }

Preferirei mantenerla in questo modo, invece di scrivere la logica all'interno di questa funzione. Sto scrivendo in C99 . Sto bene con le variabili statiche e globali, così come i getter pubblici.

Si prega di indicare come implementare la comunicazione tra void task_pid_tune(void) e void task_pid_run(void) . Tieni presente che quest'ultimo verrà chiamato molto più spesso del primo, quindi le prestazioni sono importanti in questo caso.

Chiarimento.

Nessuna attività può bloccare. In altre parole, tutte le attività pianificate devono tornare prima del successivo tick del timer.

Di conseguenza, l'ordine di esecuzione richiesto è:

    task1();
    task2();
    task3();
    task4();
    task_pid_tune();
    // this loops until pid tuning is ready
    // that is, pid_tune() samples some signal once per system tick
    // and at some point, it gets happy and provides estimated pid coefficients

    task1();
    task2();
    task3();
    task4();
    task_pid_configure();  // this runs only one 

    task1();
    task2();
    task3();
    task4();
    task_pid_run();
    // This loops forever.
    
posta Vorac 11.01.2016 - 22:23
fonte

1 risposta

2

Un modo facile e leggibile per passare tra le attività PID consiste nell'utilizzare un puntatore a funzione, come questo:

void (*pid_task)() = &task_pid_tune;

int main() {
  //... startup code

  while( wait_for_timer_tick() )
  {
    task1();
    task2();
    task3();
    task4();
    pid_task();
  }
}

void task_pid_run()
{
  //... run the PID
}

void task_pid_configure()
{
  //... perform configuration

  pid_task = &task_pid_run;
}

void task_pid_tune()
{
  //... perform PID tuning

  if (tuning done)
    pid_task = &task_pid_configure;
}

Qui le attività pid_tune e pid_configure determinano quando una nuova attività dovrebbe sostituirle e quale attività dovrebbe essere. Il ciclo di esecuzione principale esegue solo l'attività PID attualmente assegnata al puntatore della funzione per l'esecuzione.

    
risposta data 12.01.2016 - 09:07
fonte

Leggi altre domande sui tag