Autor Tema: Complicando para simplificar  (Leído 16344 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: Complicando para simplificar
« Respuesta #45 en: 31 de Marzo de 2010, 13:47:26 »
Hola.

Una preguntica: Como accedo a esa info desde el MPLAB?



Saludos
El papel lo aguanta todo

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Complicando para simplificar
« Respuesta #46 en: 31 de Marzo de 2010, 13:50:09 »
En el menú "View" tienes "Memory usage gauge" que te da la misma información, y te pinta un grafiquito.

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: Complicando para simplificar
« Respuesta #47 en: 31 de Marzo de 2010, 13:52:57 »
Seee

Pero es que quería esa info mas detallada ... como la tuya ...  :P Eso esta compilado desde el IDE del CCS cierto?

Saludos
El papel lo aguanta todo

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Complicando para simplificar
« Respuesta #48 en: 31 de Marzo de 2010, 13:53:18 »
Yes, my friend

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Complicando para simplificar
« Respuesta #49 en: 31 de Marzo de 2010, 14:08:24 »
No sé de qué va eso del stack, ¿cómo puedo optimizar mi código para que utilice un nivel menos?, ¿qué tipo de funciones lo llenan?

El STACK es la pila. Cada vez que se ejecuta una instruccion CALL o se ingresa al ISR(vector de interrupcion) por haber sucedido una interrupción, se carga la PILA en 1 nivel. Las instrucciones RETURN y RETFIE son las instrucciones que la descarga.

El STACK es el lugar donde se almacenan las posiciones de memoria de codigo que le permiten al PIC saber adónde debe volver cuando se ha finalizado de ejecutar una sub-rutina(una "función").

En CCS es algo más complejo responder a la pregunta. Esto es debido a que principalmente, el CCS elige por defecto si una funcion debe ser llamada como subrutina, o ser incluida como MACRO.

Un caso práctico lo ilustra mejor:

Código: C#
  1. void parpadea(void)
  2. {
  3.     output_high(LED);  
  4.     delay_ms(500);
  5.     output_low(LED);  
  6.     delay_ms(500);    
  7. }

Si ahora en mi main yo hago, por ejemplo:

Código: C#
  1. void main(void)
  2. {
  3.     //...inicializacion omitida...
  4.     while(1)
  5.     {
  6.        parpadea();
  7.     }
  8. }

Es altamente probable, que el CCS traduzca lo anterior a:

Código: C#
  1. void main(void)
  2. {
  3.     //...inicializacion omitida...
  4.     while(1)
  5.     {
  6.         output_high(LED);  
  7.         delay_ms(500);
  8.         output_low(LED);  
  9.         delay_ms(500);    
  10.     }
  11. }

eliminando en realidad a la subrutina, y de esa manera, ahorrandose el nivel de STACK( por no tener que hacer el CALL y llamarla).

Ahora, si mi main fuese asi:

Código: C#
  1. void main(void)
  2. {
  3.     //...inicializacion omitida...
  4.     while(1)
  5.     {
  6.         parpadea();
  7.         //...
  8.         parpadea();
  9.         //...
  10.         parpadea();
  11.         //...
  12.     }
  13. }

Ya el CCS detecta que llamas a la funcion 3 veces, por lo que reemplazar su contenido directamente puede afectar duramente a la ROM que ocupe el codigo, por lo que en ese caso lo que probablemente hara es utilizar a parpadea() como funcion, consumiendo el nivel de STACK pero ahorrando ROM.

Este comportamiento puede cambiarse. Podés forzar a que el compilador, por ejemplo, utilice a parpadea() como MACRO, no importa la cantidad de veces que sea llamada(obviamente pagando las  consecuencias en ROM) agregando el modificador INLINE.

Ejemplo:

Código: C#
  1. inline void parpadea(void)
  2. {
  3.     output_high(LED);  
  4.     delay_ms(500);
  5.     output_low(LED);  
  6.     delay_ms(500);    
  7. }
  8.  
  9. void main(void)
  10. {
  11.     //...inicializacion omitida...
  12.     while(1)
  13.     {
  14.         parpadea();
  15.         //...
  16.         parpadea();
  17.         //...
  18.         parpadea();
  19.         //...
  20.     }
  21. }

Deberia obligar al compilador a que en realidad, reemplace internamente a la hora de compilar lo anterior por:

Código: C#
  1. void main(void)
  2. {
  3.     //...inicializacion omitida...
  4.     while(1)
  5.     {
  6.         output_high(LED);  
  7.         delay_ms(500);
  8.         output_low(LED);  
  9.         delay_ms(500);    
  10.         //...
  11.         output_high(LED);  
  12.         delay_ms(500);
  13.         output_low(LED);  
  14.         delay_ms(500);    
  15.         //...
  16.         output_high(LED);  
  17.         delay_ms(500);
  18.         output_low(LED);  
  19.         delay_ms(500);    
  20.         //...
  21.     }
  22. }

Si bien la eleccion que hace el CCS automaticamente no es tan sencilla seguramente como sólo considerar la cantidad de veces que se llama a la subrutina(también es relevante cuántas líneas ASM ocupa, el tiempo que debe tardar en ejecutarse,etc) es una buena primera aproximación para intentar explicarlo.

Por defecto, considerá que cada vez que llamás a una función el STACK se incrementa en un lugar. Obviamente cuando se retorna de la subrutina se libera esa posición. Entonces el problema surge cuando anidás muchas llamandas a subrutinas. Las interrupciones ocupan se comportan como una funcion más. Ocupan 1 lugar al ingresar y lo liberan al finalizar.

Reducí la cantidad de subrutinas anidadas para bajar el nivel máximo de STACK. Por otro lado, el CCS no es tan inteligente, sólo analiza el peor caso considerando los anidamientos presentes en tu código, pero no puede predecir si el flujo de tu código efectivamente puede llegar a ejecutar todos los niveles del peor caso por lo que puede estar advirtiendo de un peor caso que técnicamente jamás puede ocurrir en tu flujo de ejecución.

Saludos.


« Última modificación: 31 de Marzo de 2010, 14:11:25 por BrunoF »
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: Complicando para simplificar
« Respuesta #50 en: 31 de Marzo de 2010, 14:11:30 »
 :shock:

Muy buena info maestro!!!!!

Es decir que es mejor usar funciones que retornen datos (asi no los retornen) para asegurar la descarga del STACK?

Saludos
El papel lo aguanta todo

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Complicando para simplificar
« Respuesta #51 en: 31 de Marzo de 2010, 14:20:24 »
Magnífico Don Bruno, lo tendré en cuenta.

Me parece que mi programa no llega ni a 4 niveles de pila, por lo que imagino que CCS ha supuesto un caso que no podrá darse.
En cualquier caso lo revisaré.

Gracias

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Complicando para simplificar
« Respuesta #52 en: 31 de Marzo de 2010, 14:26:07 »
Hola MLO.

No. Es lo mísmo. Toda porción de código puede escribirse o bien como subrutina("función") o bien como MACRO. La diferencia es que en el primer caso, se ahorra ROM mediante la reutilización de código, pero se ocupa temporalmente 1 nivel de PILA al ejecutarse. La segunda no ocupa nivel de PILA, pero ocupa ROM cada vez que se la llama.

Lo mejor es no anidar muchas funciones unas dentro de otras, porque ahi es cuando sucede el problema. Ni hablar cuando hay interrupciones presentes.Estas consumen 1 nivel de STACK, y cualquier llamada a subrutina que hagamos dentro de ellas seguiran incrementando aun más la cantidad de PILA necesaria.

Para imaginarlo más prácticamente. "La PILA es una memoria limitada que permite al PIC saber cómo volver a casa".
Imaginen que son viajantes y parten siempre desde su casa. Pueden recorrer la ciudad donde se encuentran actualmente sin mayores problemas de memoria, una calle por vez, pero si por casualidad son llamados a otra ciudad inmediatamente, deben recordar desde donde retomar el recorrido en la ciudad en la que estaban. Una vez terminado el recorrido por una ciudad, si quedaba algo de una ciudad previa por recorrer, utilizan esa memoria para saber desde donde retomar el recorrido. Bueno, ahora sólo pueden recordar 8 posiciones(en los 16F que es el caso involucrado) de ciudades previas. Si se exceden, Alzheimer se apodera y los problemas aparecen porque no hay más lugar para almacenar otra posición.


"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Complicando para simplificar
« Respuesta #53 en: 31 de Marzo de 2010, 14:27:27 »
No sé de qué va eso del stack, ¿cómo puedo optimizar mi código para que utilice un nivel menos?, ¿qué tipo de funciones lo llenan?

 :z) Así me dejaste y me corrió un chucho por la espalda!  :D :D

Muy bien explicado Bruno!  :-)

Es decir que es mejor usar funciones que retornen datos (asi no los retornen) para asegurar la descarga del STACK?

Hay que colocar la directiva INLINE para que reemplace el código y no la tome como función.

Saludos!


Edit: Bueno, lo explico bien detalladito el maestro Bruno  :mrgreen:
« Última modificación: 31 de Marzo de 2010, 14:29:50 por Suky »
No contesto mensajes privados, las consultas en el foro

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Complicando para simplificar
« Respuesta #54 en: 31 de Marzo de 2010, 14:29:52 »
Magnífico Don Bruno, lo tendré en cuenta.

Me parece que mi programa no llega ni a 4 niveles de pila, por lo que imagino que CCS ha supuesto un caso que no podrá darse.
En cualquier caso lo revisaré.

Gracias

Fijate si no sucede lo que comento en rojo en el post anterior.

Si bien decís que no hay más de 4 funciones anidadas, si JUSTO sucede una interrupción en el peor caso(cuando el PIC tiene 4 niveles de STACK ocupados por tus funciones anidadas) la interrupción mísma ya te ocupa un 5to lugar. Si ahora encima hacés llamadas a subrutinas dentro de la interrupción, seguís elevando los niveles de STACK. Te hacen falta tener 4 funciones mas anidadas dentro de la interr. para reventar la STACK.

Y ojo, que hay funciones que por mas que vengan con el CCS consumen posiciones de PILA seguramente, como un printf();

"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Complicando para simplificar
« Respuesta #55 en: 31 de Marzo de 2010, 14:30:23 »

 :z) Así me dejaste y me corrió un chucho por la espalda!  :D :D


Es que los enfermos del ASM tenéis unas costumbres muy raras: ¡Una pila para recordar el camino de vuelta!, con lo fácil que es tirar de GPS, hombre.

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Complicando para simplificar
« Respuesta #56 en: 31 de Marzo de 2010, 14:40:05 »
Mano, ahora que lo recuerdo. Usá el call Tree para ver cómo están anidadas las funciones en tu programa. Ahí seguro salta el peor caso cómo ocurre y los demás que deban ser corregidos u optimizados.
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Complicando para simplificar
« Respuesta #57 en: 31 de Marzo de 2010, 14:46:24 »
Magnífica herramienta de depuración. Siempre he visto el botón del Call tree y nunca me había dado por pulsarlo.

He encontrado hasta 7 niveles de profundidad, porque la librería del LCD hace muchas llamadas, así que no me extraña que en alguna parte se consuman los 9 niveles que indica la compilación, aunque aún no lo encuentro.

Sigo buscando.

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Complicando para simplificar
« Respuesta #58 en: 31 de Marzo de 2010, 14:50:20 »

 :z) Así me dejaste y me corrió un chucho por la espalda!  :D :D


Es que los enfermos del ASM tenéis unas costumbres muy raras: ¡Una pila para recordar el camino de vuelta!, con lo fácil que es tirar de GPS, hombre.

Jejeje! En los 16F preocúpate de forma sería que tienen 8 niveles, en los 18F es de 32, y en los PIC24 es por software  :P
No contesto mensajes privados, las consultas en el foro

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: Complicando para simplificar
« Respuesta #59 en: 31 de Marzo de 2010, 14:59:38 »
Excelente info.

La función sprintf también consume PILA

Mejor voy a cambiar a una de 9V cuadrada .. y que sea alcalina para que aguante mas!!!

El papel lo aguanta todo