Uso excesivo de RAM estática AVR con operaciones matemáticas de tipo mixto

3

He reducido un problema en mi código que crea 260 bytes adicionales de uso de RAM estática:

BYTE Height = 150;

BYTE sampleLevel(BYTE ADCchan,BYTE averages)
{
    float samp;
    //int samp;
    BYTE level;

    samp = avgSampleADC(ADCchan,averages);
    level = 100-(samp*100/Height);

    return level;
}

BYTE aquí es un tipo uint8_t. Si comento float samp y lo convierto en un tipo int , el uso de RAM estática se reduce a lo que espero que sea. Supongo que esto tiene algo que ver con la operación matemática level = 100-(samp*100/Height); pero no sé qué es. ¿Qué está sucediendo para crear tal comportamiento?

    
pregunta Jon L

4 respuestas

11

Para muchas funciones matemáticas, hay un equilibrio entre el uso de RAM y la velocidad. Supongo que la biblioteca de punto flotante AVR se optimizará para la velocidad.
Bitrex tiene razón: intente evitar el punto flotante en los microcontroladores a menos que sea absolutamente necesario. ¿Realmente necesitas punto flotante, o lo harás punto fijo? Puede emular un punto fijo colocando un punto decimal virtual en algún lugar de un int.

En tu ejemplo, multiplicas samp por \ $ \ frac {2} {3} \ $. El resultado, almacenado en un BYTE no tendrá una precisión muy alta. En un caso así, puede elegir un factor de escala que sea más fácil de calcular que el \ $ \ frac {2} {3} \ $. Encuentre una aproximación de la forma \ $ \ frac {A} {2 ^ N} \ $. En este caso \ $ \ frac {171} {256} \ $ ~ 0.668 es una buena opción, con un error de solo 0.2%. Y es mucho más fácil de calcular: multiplicar por 171 y desplazar a la derecha 8 bits. No se necesita división.

    
respondido por el stevenvh
3

¿Estás utilizando flotadores en otro lugar? Si no, el flotador aquí puede estar arrastrando toda la biblioteca de punto flotante, que puede estar asignando memoria para sí misma. Rara vez es necesario utilizar un punto flotante en las aplicaciones integradas, ya que no necesita la gran variedad de PF para procesar el rango limitado de valores de las entradas del mundo real como los ADC, etc. Recuerde que el FP le da rango, no precisión. Casi siempre es mucho más pequeño y más rápido de usar de punto fijo, y un valor de punto fijo siempre será más preciso que un FP de igual tamaño.

    
respondido por el mikeselectricstuff
2

Lo que probablemente estés viendo es lo que se conoce como Promoción de variables .

Al realizar cualquier operación matemática que involucre múltiples tipos de variables, todas las variables dentro de la fórmula se promueven a los tipos de mayor precisión (flotante en su caso). Por lo tanto, la variable Altura se copiará en una variable temporal float antes de que se realice la operación.

Esto solo representará una pequeña parte del aumento en el uso de la memoria.

Lo más probable es que el resto se deba a la inclusión de toda la biblioteca de punto flotante en el sistema. Sin conocer los aspectos internos de la biblioteca de punto flotante del AVR, no puedo decir qué haría con dicha memoria (la mayoría de la memoria utilizada sería la memoria del programa y no la RAM).

Como ha señalado stevenvh , hay formas mucho más eficientes de realizar este tipo de operaciones que no utilizan la biblioteca de punto flotante en absoluto, y el punto flotante, como se ha mencionado correctamente en otro lugar, No es realmente lo que buscas aquí, ya que tiene un factor de error inherente. Lo que realmente desea es doble no flotar , ya que esta es una precisión fija con una mejor precisión que la flotación, aunque no es tan eficiente como hacer un 100% de matemáticas enteras. p>     

respondido por el Majenko
1

He visto una explosión en la utilización de la memoria flash en avr-gcc si no usas el indicador -lm en el vinculador para vincular las rutinas de emulación de punto flotante optimizadas de AVR a través de la biblioteca matemática. Es probable que también debas tener la eliminación de las funciones no utilizadas (-ffunction-sections) establecida en los indicadores del compilador y -Wl,-gc-sections establecida en los indicadores del vinculador si te importa minimizar la huella de memoria. Tenga en cuenta los guiones iniciales en todas las banderas.

Como referencia, Preguntas frecuentes sobre el manual de avr-gcc habla explícitamente sobre esto . Aquí también es otra buena referencia para las optimizaciones que puede aplicar en avr- gcc.

Habiendo dicho todo lo anterior, ahorrará la mayor cantidad de memoria simplemente al no utilizar las variables de punto flotante en su código, si puede formular su problema en matemáticas estrictamente enteras o de punto fijo , ¡debe hacerlo!

    
respondido por el vicatcu

Lea otras preguntas en las etiquetas