¿Cómo se asigna la memoria en un AVR?

-1

Estoy escribiendo un programa para el microcontrolador AVR, y mis experimentos de código me han llevado a la confusión y al descubrimiento. Aquí está el primer código:

void USART_PutByte (int8_t byte)
{
uint8_t tempTxTail = (USART_TxTail + 1) & USART_BUFFER_MASK;            //  Creating temporary incremented tail (for interruptions)
while(USART_TxHead == tempTxTail);                                      //  Wait for free space in the buffer
USART_TxTail = tempTxTail;                                              //  Now update tail
USART_TransmitBuffer[USART_TxTail] = byte;                          //  And put byte in the Transmit buffer, which will handle the interrupt

UCSRB |= 1 << UDRIE;                                                    //  Enable interrupt handler
}

Y el segundo código, que me llevó a la confusión, pero, sin embargo, fue gratamente sorprendido:

void USART_PutByte (int8_t byte)
{
uint8_t tempTxTail = (USART_TxTail + 1) & USART_BUFFER_MASK;            //  Creating temporary incremented tail (for interruptions)
while(USART_TxHead == tempTxTail);                                      //  Wait for free space in the buffer
USART_TxTail = tempTxTail;                                              //  Now update tail
USART_TransmitBuffer[tempTxTail] = byte;                                //  And put byte in the Transmit buffer, which will handle the interrupt

UCSRB |= 1 << UDRIE;                                                    //  Enable interrupt handler
}

El segundo código es más ligero que el primero en 4 kb. Pero la diferencia solo está en la penúltima línea. Y me gustaría entender, por lo que el segundo código requiere menos memoria que el primero, para usar este entendimiento en mis proyectos. ¿Es una característica del lenguaje C, o un microcontrolador? ¿O depende del caso? P.S .: Lo siento, si se cometieron errores gramaticales, aprendo inglés. :-)

    
pregunta Ruslan Vostro

3 respuestas

1

He estado programando en C desde 1978, cuando trabajaba en el kernel de Unix, y lo he usado todos los años desde entonces. Así que conozco bastante bien el idioma, incluido el poder generar código de ensamblaje "sobre la marcha".

Puedo decirle que simplemente no se proporciona suficiente información.

Una posibilidad que me viene a la mente es que no midió la "diferencia de 4 kb" correctamente. No puedo decirlo, porque no revela cómo llegó a esa cifra. Pero tengo que considerarlo como una posibilidad lógica, ya que no creo que seas un experto.

Si obtuviste la cifra correcta, entonces no es posible decirlo a partir del código que proporcionaste aquí. Encontré un código en la web que proporciona un código de ejemplo que "parece" ser similar a mí. Podría asumir que su código se parece a las muestras. Pero las muestras que vi NO eran realmente la fuente del código de la biblioteca y no puedo decir si copió material del código de la muestra o si está usando alguna biblioteca. Esto podría importar. Así que de nuevo, no tengo suficiente información.

Una de las sugerencias que veo aquí es sobre la volatilidad de la variable que usaste. Ciertamente, dado que ese parece ser el único cambio que nos permitió ver (y asegura que es el único cambio, creo), es natural que nos enfoquemos en esa diferencia. Pero es completamente insuficiente para explicar el cambio en la huella que mencionó. Una variable volátil no puede ser optimizada de cierta manera (es un conjunto de reglas lo suficientemente complejo como para que no quiera analizarla aquí). Pero de ninguna manera imaginable puedo imaginar un compilador de C que pueda ser tan fundamentalmente defectuoso en su diseño que podría explicar eso.

(Excepto en un caso posible, es posible que su compilador sea la "versión gratuita" de una "versión comercial costosa" y que hayan hecho algo intencionalmente que ha activado. Pero con el AVR, No creo que esta sea una explicación posible. Por lo tanto, no voy a ir con esto.

Esto deja abiertas algunas preguntas:

  1. ¿Está utilizando el código de la biblioteca o obtuvo su código de uno de los varios conjuntos de códigos de ejemplo que vi que incluían una función main () y presentó un método que copió y modificó? Si copió algún código, ¿por qué no nos proporciona todo el contexto? Puede importar.
  2. Las diferencias como el tamaño que viste a menudo son una cuestión de mala interpretación. Me gustaría saber cómo en realidad midió esta diferencia. Discute tu método y tu forma de pensar sobre ello. ¿Miraste el archivo del mapa para resolver esto? Si es así, ¿por qué no incluir los dos archivos de mapas diferentes en su pregunta?
  3. Las diferencias de este tipo pueden ser si se insertó o no cierto código de biblioteca o no. Esto puede suceder si hizo otro en su código que creía que era no relacionado pero en realidad es la razón de La diferencia y en su lugar los ocultaste accidentalmente de nuestra vista. Por ejemplo, si agregó algún código para usar una función printf (), podría imaginar que no tiene nada que ver con su observación. Sin embargo, tal vez este fue el primer uso que se hizo e incluirlo significó que el enlazador instaló una biblioteca completa de código porque tenía que hacerlo. Necesito sus garantías de que esto no es parte del problema y que su diferencia presentada es la diferencia real sólo > en el código.
  4. Diferencias como esta también pueden ser la cuestión de si se agrega o no una matriz al código en el momento de la compilación frente al uso del espacio del montón. O puede tratarse de un "derrame" del vinculador de un código / segmento de datos a otro (según las reglas del vinculador).

Creo que probablemente las cosas más importantes son las siguientes:

  • Asegúrense de que este cambio que presentó es el cambio solo . Podría suponer por su escrito que esto es así. Y sería razonable hacerlo. Pero quiero sus garantías explícitas. No suposiciones.
  • Proporcione los dos archivos de mapas diferentes generados por el vinculador. Si no sabe cómo hacerlo, descúbralo y prodúzcalo con tantos detalles como lo permitan las opciones del enlazador. Casi todo estará allí y el resto "seguirá de allí".
respondido por el jonk
0

Como especulación, el compilador probablemente asignará un registro para tempTXTail en lugar de almacenar la variable en la memoria. En la arquitectura AVR (y en la mayoría de los demás), esto hace que el acceso a la eliminación de referencias al usar esta variable (como el acceso a la matriz que usó) sea mucho más rápido y use menos instrucciones.

¿La función se marcó como en línea (u optimizada para ser así)? Si hay muchas referencias a la función, esto podría explicar la diferencia de tamaño del código.

Para averiguarlo, mira el archivo de mapa y la salida del ensamblador del compilador. Una diferencia de 4K debería ser fácil de detectar.

    
respondido por el Dean Franks
0

USART_TxTail es volatile , por lo que el compilador necesita generar un almacén seguido de una carga en lugar de asumir que tiene el valor que se le asignó.

    
respondido por el τεκ

Lea otras preguntas en las etiquetas