Go Down

Topic: Problemi con puntatore su vettore interrupt (Read 730 times) previous topic - next topic

niki77

Buongiorno a tutti.

Ho messo insieme alcune righe di codice che impostano un interrupt sull'overflow del timer generandomi una chiamata allo stesso vettore ogni secondo (ma questo tanto è ininfluente)
All'interno di questo interrupt vado ad effettuare una chiamata ad una void con parametri, tramite un puntatore alla stessa, contenuto in una struttura.
All'interno della stessa struttura è contenuto anche un puntatore uint8_t che contiene il valore delll'area di memoria dove sono presenti dei dati che voglio passare alla funzione menzionata sopra.

il codice 'looks like above':

Code: [Select]


//struttura dati task
struct TaskData
{
void (*functionPointer)(uint8_t *);
uint8_t * parameterPointer;
};


// questo è il vettore dell'interrupt
ISR(TIMER1_COMPA_vect)
{
  seconds++;
  if (seconds == UPDATE_INTERVALL )
  {
    if(task_data.functionPointer !=NULL)
    {
      task_data.functionPointer(task_data.parameterPointer);
    }
  }
}



Il codice in oggetto riesce tranquillamente ad effettuare la chiamata alla funzione , ma il parametro non viene passato.
Ho provato anche a sostituire

Code: [Select]
task_data.functionPointer(task_data.parameterPointer);

con

Code: [Select]

uint8_t params[2] = {1,0};
task_data.functionPointer(params);


Nel secondo caso i parametri vengono passati correttamente.
Avete qualche idea?
Grazie.
Vi è una spiegazione scientifica a tutto.
La fede è solo quell'anello che si porta al dito dopo il matrimonio.

nid69ita

Sbaglio o dovresti sostituire

task_data.functionPointer(task_data.parameterPointer);

con

task_data.functionPointer(&task_data.parameterPointer);

tu chiedi un indirizzo, nel caso successivo passi un vettore che in C è implicitamente un indirizzo.
my name is IGOR, not AIGOR

niki77

#2
Jan 29, 2013, 10:49 am Last Edit: Jan 29, 2013, 10:50 am by niki77 Reason: 1
In effetti ti sbagli, perchè il parametro passato è già un puntatore, quindi un indirizzo.
Dereferenziando come hai mostrato tu,  nemmeno compila.
Vi è una spiegazione scientifica a tutto.
La fede è solo quell'anello che si porta al dito dopo il matrimonio.

nid69ita

#3
Jan 29, 2013, 11:19 am Last Edit: Jan 29, 2013, 11:32 am by nid69ita Reason: 1
Arduino non è un compilatore C++ (anche se parziale)?
http://www.html.it/pag/15499/parametri-per-valore-o-per-riferimento/

A me questo Arduino lo compila, sintassi tipica di C++ per il primo parametro (non del C)
Code: [Select]

struct TaskData
{ void (*functionPointer)(uint8_t *);
  uint8_t * parameterPointer;
};

void xfunc(int &a,int b, int *c)
{ Serial.println(a);
  Serial.println(b);
  Serial.println((int)c);
}

void yfunc(struct TaskData& p1,struct TaskData* p2)
{
}

void setup()
{ int var=10;
  TaskData varTD;
  Serial.begin(9600);
  xfunc(var,var,&var);
  yfunc(varTD,&varTD);
}

void loop()
{
}
my name is IGOR, not AIGOR

niki77

Scusa ma non mi sembra che stiamo parlando della stessa cosa.

Code: [Select]

struct TaskData
{
  void (*functionPointer)(uint8_t *);
  uint8_t * parameterPointer;
};

void xfunc(uint8_t * params)
{
}


void setup()
{
  uint8_t arr[2] = {2,0};
  xfunc(&arr);
}

void loop()
{
}


Vedi se ti compila questo.

A me interessa capire cosa c'è che non và a livello di concetto, non una scappatella per farlo compilare.  ;)
Vi è una spiegazione scientifica a tutto.
La fede è solo quell'anello che si porta al dito dopo il matrimonio.

nid69ita

#5
Jan 29, 2013, 12:02 pm Last Edit: Jan 29, 2013, 12:05 pm by nid69ita Reason: 1
Quell'esempio tuo per forza non lo compila. Quello è già un vettore perciò un puntatore.
La mia spiegazione non è una scappatella.
Alle funzioni un compilatore C/C++ passa di default i parametri variabili e strutture per copia, i vettori per funzione.
(Vedi il link che ti ho messo)
Ti stò solo dicenendo che se passi alla tua funzione un vettore non devi mettere & mentre se passi una struttura si.
Code: [Select]

struct TaskData
{ void (*functionPointer)(uint8_t *);
  uint8_t * parameterPointer;
};

void xfunc(uint8_t * params)
{ }

void yfunc(struct TaskData *p)
{ }

void setup()
{ TaskData xTD;
  uint8_t arr[2] = {2,0};
  xfunc(arr);           // vettore, perciò puntatore
  yfunc(&xTD);       // struct perciò ne passo l'indirizzo altrimenti mi passa una copia
}

void loop()
{ }


infatti se provi a compilare, questo funziona.
my name is IGOR, not AIGOR

niki77

Scusami , c'è stato un miss-undestand, avevo dato per scontato che nel post iniziale avessi scritto che passavo un vettore di valori ed invece ho controllato e non c'è!!!!  :smiley-sad-blue:

E' stata una mia mancanza, lungi da me pensare che stai a dì fregnacce, ci mancherebbe!!  :smiley-mr-green:

Facendo dei test sul simulatore ho scoperto un altra cosa strana:

Code: [Select]

//struttura dati task
struct TaskData
{
void (*functionPointer)(uint8_t *);
uint8_t * parameterPointer ;
};

TaskData t;

//setup
void setup()
{
  Serial.begin(57600);
  uint8_t params[2] = {2,0};
  t.functionPointer = test;
  t.parameterPointer = params;
  Serial.print((uint16_t)t.parameterPointer,HEX);
  Serial.print(" - ");
  Serial.println(*t.parameterPointer,HEX);
}


//inizio del ciclo
void loop()
{
  delay(250);
  Serial.print((uint16_t)t.parameterPointer,HEX);
  Serial.print(" - ");
  Serial.println(*t.parameterPointer,HEX);
  delay(250);
}


output generato :

8F4 - 2
8F4 - 5  :smiley-eek-blue:
8F4 - 5  :smiley-eek-blue: :smiley-eek-blue:
8F4 - 5  :smiley-eek-blue: :smiley-eek-blue: :smiley-eek-blue:
...
Vi è una spiegazione scientifica a tutto.
La fede è solo quell'anello che si porta al dito dopo il matrimonio.

nid69ita

Pensavo tu passassi tutta la struttura. Quel che ho detto io è in generale sul passaggio di strutture come parametri.
Nel tuo caso specifico CREDO di aver capito.

task_data.functionPointer(task_data.parameterPointer);
stai passando un parametro come pointer ad una variabile che è già pointer
mentre
uint8_t params[2] = {1,0};
task_data.functionPointer(params);
passi un puntatore

nel secondo caso puoi leggere subito i parametri mentre nel secondo devi ulteriormente usare l'indirizzo.
nel primo caso è come se tu usassi un uint8_t* *    pointer a pointer




my name is IGOR, not AIGOR

niki77

Ok tutto comincia a quagliare.

Ho trovato la spiegazione anche all'ultimo codice postato.
Praticamente non posso utilizzare un puntatore in questo caso, perchè andrei a valorizzarlo con l'indirizzo di memoria di una variabile che subito dopo esce dallo scope, e questo mi giustifica il valore cambiato, sicuramente nel frattempo sarà stato valorizzato da qualcos'altro...

Cambierò il tipo di dati nella struttura da uint8_t * ad un vettore uint8_t [2] .

Ora provo a mettere in campo la modifica per vedere se funziona.

Alla fine pare che la problematica sia del tutto scollegata dal fatto che la funzione venga chiamata dalla routine ISR.

Grazie!!
Vi è una spiegazione scientifica a tutto.
La fede è solo quell'anello che si porta al dito dopo il matrimonio.

Go Up