Autor Tema: Calificador volatile  (Leído 3027 veces)

0 Usuarios y 3 Visitantes están viendo este tema.

Desconectado antayhua

  • PIC10
  • *
  • Mensajes: 32
Calificador volatile
« en: 02 de Octubre de 2015, 10:17:32 »
Alguien por favor me puede dar una explicación magistral de como o donde puedo usar el calificador volatile no logro entender para que sirve, solo se que lo usan en interrupciones, gracias por sus respuestas.

Desconectado omix

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 244
Re: Calificador volatile
« Respuesta #1 en: 02 de Octubre de 2015, 12:49:36 »
Hola,
 no se si mi explicación sera magistral o no, pero básicamente volatile se utiliza para indicarle al compilador que dicha variable debe tratarla con más "cuidado "y no realizar ciertas optimizaciones con ella, ya que puede modificarse en cualquier momento por medios ajenos al programa, es decir, un registro del micro es de tipo volatile, ya que puede modificarse en cualquier instante por el hardware del micro.
Otro ejemplo, seria por ejemplo una variable compartida que se utiliza en una interrupción y fuera de esta, mientras tu estas leyendo dicha variable desde el programa, se podría modificar en la interrupción obteniendo un valor incorrecto, por eso conviene declararlas como volatile, aunque con solo hacer esto no es suficiente, hay que tener otras precauciones al trabajar en este tipo de situaciones.

Espero haberte aclarado un poquito más el tema.

Un saludo.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Calificador volatile
« Respuesta #2 en: 02 de Octubre de 2015, 13:17:25 »
Normalmente se utilizan en registros de memoria del PIC, o cosas que pueden cambiar sin que vos las toques. Ejemplo
Código: C
  1. void main(){
  2.  int variable, deposito1,deposito2;
  3.  deposito1=variable;
  4.  deposito2=variable;
  5. }
  6.  
  7. void main(){
  8.  volatile int variable
  9.  int deposito1,deposito2;
  10.  deposito1=variable;
  11.  deposito2=variable;
  12. }

Entre esos 2 codigos hay una buena diferencia para el compilador. Voy a intenter explicartelo sin usar ASM.
El micro posee un registro W que es el de trabajo. en el primer codigo C asume que se trata del mismo valor, entonces lo que tiene que hacer el micro es:

- Toma el valor de variable y lo guarda en W
- Toma el valor de W y lo guarda en deposito1
- Toma el valor de W y lo guarda en deposito2

Como ves solamente 1 sola ves se tomo el valor de variable.
Con volatile ocurre lo siguiente

- Toma el valor de variable y lo guarda en W
- Toma el valor de W y lo guarda en deposito1
- Toma el valor de variable y lo guarda en W
- Toma el valor de W y lo guarda en deposito2

El por que es necesario esto?, Imaginate un puerto, como PORTB, el compilador no sabe que va a cambiar, entonces vos le decis que no importa pero que siempre pida el valor de nuevo, por si cambio el puerto. Espero haber sido claro.
En las interrupciones no se si es obligatorio, a mi me parece que no. Por que si ambos programas estan trabajando con una misma variable todo va a depender de donde exactamente se produzca la interrupcion. Y el volatile no te va a salvar de eso.

Desconectado elgarbe

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2178
Re: Calificador volatile
« Respuesta #3 en: 02 de Octubre de 2015, 13:17:31 »
Otro ejemplo, seria por ejemplo una variable compartida que se utiliza en una interrupción y fuera de esta, mientras tu estas leyendo dicha variable desde el programa, se podría modificar en la interrupción obteniendo un valor incorrecto, por eso conviene declararlas como volatile, aunque con solo hacer esto no es suficiente, hay que tener otras precauciones al trabajar en este tipo de situaciones.

ese es el mejor ejemplo en donde se suele utilizar volatil, en variables que van a ser usada fuera y dentro de las rutinas de atension de una interrupcion.

sds
-
Leonardo Garberoglio

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Calificador volatile
« Respuesta #4 en: 02 de Octubre de 2015, 14:06:18 »
Otro ejemplo, seria por ejemplo una variable compartida que se utiliza en una interrupción y fuera de esta, mientras tu estas leyendo dicha variable desde el programa, se podría modificar en la interrupción obteniendo un valor incorrecto, por eso conviene declararlas como volatile, aunque con solo hacer esto no es suficiente, hay que tener otras precauciones al trabajar en este tipo de situaciones.

ese es el mejor ejemplo en donde se suele utilizar volatil, en variables que van a ser usada fuera y dentro de las rutinas de atension de una interrupcion.

sds

Al menos en los PICs es una "ayuda" pero no soluciona el problema. Supongamos el codigo en ASM


MOVWF Variable
ADDLW 0x10
GOTO XXXXX

Si la interrupcion se produce en luego del MOVWF estas perdido, no hay volatile que se te salve. Por que cuando vuelva de la interrupcion va a ejecutar la instruccion ADDLW y si variable fue modificada en la interrupcion cuando se devuelva el valor W que poseia antes variable va a tener un valor erroneo. Por eso mi razonamiento de que el volatile no es una obligacion . Otros micros tienen otras instrucciones para cuando varios codigos comparten la misma variable asi o se modifican. Aca habria que hacerlo, y si haces un mecanismo de eso el volatile ya no posee sentido tenerlo. me refiero a un mecanismo asi:

variable_en_uso=1;
variable += 0x10;
variable_en_uso=0;

Y tu rutina de interrupciones que pregunte por si se esta usando esa variable o no. Y ya esto presenta otros problemas, como disparar nuevamente la interrupcion luego de tratada la variable, asi que vas por el otro lado:

interrupcion_desactivada();
variable += 0x10;
interrupcion_activada();

Y sigue sin importar si es volatile o no en estos casos.

Otra idea que se puede ocurrir es que use lo del registro W el compilador, pero esto es imposible, ya que el compilador NO conoce cuando se va a producir la interrupcion, asi que se encuentra obligado a pedir el valor de variable nuevamente dentro de la interrupcion.

En otros micros sucede algo parecido, por mas que tengan 32 registros, ocurren los mismo problemas que antes, el compilador no sabe donde esta su variable. utiliza lso registros como papel y los tira, cuando entra a una interrupcion se produce un push al stack para consevar el contexto del programa principal, la mayoria de los registros hacia una llamada tiene un destino especifico, y ninguno es guardar el valor de una variable todo el tiempo, los argumentos se pasan por algunos registros + pila. etc No veo desde el punto de vista de ASM + el funcionamiento de C como puede afectar el ponerlo volatile o no.

PD: Este es mi punto de vista, si alguno tiene un ejemplo para demostrar que justamente el volatile sirve para una interrupcion estaria agradecido que me logre cambiar la idea.
« Última modificación: 02 de Octubre de 2015, 14:16:35 por KILLERJC »

Desconectado elgarbe

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 2178
Re: Calificador volatile
« Respuesta #5 en: 02 de Octubre de 2015, 14:17:43 »
Otro ejemplo, seria por ejemplo una variable compartida que se utiliza en una interrupción y fuera de esta, mientras tu estas leyendo dicha variable desde el programa, se podría modificar en la interrupción obteniendo un valor incorrecto, por eso conviene declararlas como volatile, aunque con solo hacer esto no es suficiente, hay que tener otras precauciones al trabajar en este tipo de situaciones.

ese es el mejor ejemplo en donde se suele utilizar volatil, en variables que van a ser usada fuera y dentro de las rutinas de atension de una interrupcion.

sds

Al menos en los PICs es una "ayuda" pero no soluciona el problema. Supongamos el codigo en ASM


bueno, pero es lo que estamos diciendo, que previene ciertas optimizaciones, que se utiliza cuando las variables pueden ser modificadas dentro y fuera de la ISR y que con hacerla volatile solo no es suficiente. Yo comenté que me parece que el ejemplo más común es justamente el de las ISR. Pero nadie dijo que sea la solucion al problema de que estas planteando vos.  ;-)

sds!
-
Leonardo Garberoglio

Desconectado antayhua

  • PIC10
  • *
  • Mensajes: 32
Re: Calificador volatile
« Respuesta #6 en: 02 de Octubre de 2015, 14:25:10 »
Ahora entiendo un poco más lo que es volatile,muchas gracias por su ayuda, he visto esto:
Volatile static char dato @0x100,
Siendo la variable volatile y static como se podría interpretar esto, si es static es porque se va conservar el valor de la variable dato, o me equivoco.


Desconectado antayhua

  • PIC10
  • *
  • Mensajes: 32
Re: Calificador volatile
« Respuesta #8 en: 02 de Octubre de 2015, 14:33:06 »
Al parecer el calificador volatile es un tema muy amplio, leo diferentes ideas y me confundo más, parece que necesitamos a un experto para que nos saque de dudas.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Calificador volatile
« Respuesta #9 en: 02 de Octubre de 2015, 14:55:31 »
Con el link de RICHI ahi puedo comprender por que usar volatile en variables globales que afecten a las interrupciones. Eso es lo que necesitaba, un ejemplo :P

Citar
Al parecer el calificador volatile es un tema muy amplio, leo diferentes ideas y me confundo más, parece que necesitamos a un experto para que nos saque de dudas.

En resumen tenes que pensar en ASM para entenderlo o seguir la costumbre:

- volatile a todo aquello que pueda cambiarlo el hardware ( normalmente definido como volatile dentro del .h del micro que trae el compilador )
- volatile a variables globales que se modifiquen en el programa y en la interrupcion, pero esto no soluciona el tema de la atomicidad(no se la traduccion atomicity) por lo que explique y requiere de un bloqueo, desactivar las interrupciones ( para caso de no tener un RTOS ).
- Cuando te enfrentas a varios threads o hilos / task (RTOS) tambien deberias tenerlo en cuenta de usar volatile en variables globales que son compartidas por las tareas. Aunque deberias usar Queue y otras cosas mas.
- Si declaraste volatile a una variable en un archivo y luego usas extern para usarlo en otro archivo, asegurate que tambien este definido como extern volatile.


Casos que hay que tener en cuenta (este si que no lo sabia ):

- el compilador C puede mover las instrucciones para el caso de los volatiles y no cumplir exactamente con el orden del programa escrito en C, esto esta explicado en el 1er link que paso RICHI punto 5, y da un muy buen ejemplo pasado a ASM, en el que se ejecuta el ready=1; antes que la otra instruccion(que estaba antes de esa), que si va el caso de que ocurra una interrupcion seria un error. Y hay que aplicar otras soluciones, memory-lock (si es que lo ofrece el compilador), call a una funcion, declarar todo como volatile, etc.

Este ultimo algunos dicen que no es asi y otros dicen que si, ahi en el link provee un codigo ASM de lo generado y se ve que si. Otros como el 3er link dice que usar volatile ( imagino que siempre y cuando se trate de todas variables como volatile ) no modificaria el orden del programa.

En fin, para todos gracias por haberme solucionado las dudas a mi tambien, y con ejemplos y todo :P

Citar
Volatile static char dato @0x100,

Con respecto a lo de static, lo que tengo entendido es que habla sobre la permanencia y el linkage(ni idea de la traduccion) del dato.
Definido dentro de la funcion habla sobre la permanencia, es que no se destruye.
Definido fuera de la funcion lo que lo diferencia de una variable "global" cualquiera es que lo restringe solamente al archivo ese.

La diferencia entre:

Archivo1.c
Código: [Seleccionar]
int x=0;
static int i=0;

es que:

Archivo2.c
Código: [Seleccionar]
extern int x; // Valido
extern int i;  // No valido

Con respecto a la permanencia:

Ejemplo sacado de internet:
Código: C
  1. #include <stdio.h>
  2.  
  3. void foo()
  4. {
  5.     int a = 10;
  6.     static int sa = 10;
  7.  
  8.     a += 5;
  9.     sa += 5;
  10.  
  11.     printf("a = %d, sa = %d\n", a, sa);
  12. }
  13.  
  14.  
  15. int main()
  16. {
  17.     int i;
  18.  
  19.     for (i = 0; i < 10; ++i)
  20.         foo();
  21. }

Salida del printf:
Código: [Seleccionar]
a = 15, sa = 15
a = 15, sa = 20
a = 15, sa = 25
a = 15, sa = 30
a = 15, sa = 35
a = 15, sa = 40
a = 15, sa = 45
a = 15, sa = 50
a = 15, sa = 55
a = 15, sa = 60

Como ves "a" se crea y se destruye en esa funcion , mientras que "sa" por ser static no se destruye
« Última modificación: 02 de Octubre de 2015, 15:39:46 por KILLERJC »