AVR04027: Ayudas y Trucos para optimizar tu código C...

18
Traducción Nota de Aplicación AVR4027 : Ayudas y Trucos para optimizar tu código C para microcontroladores AVR de 8 bits 1 Hecho en Bolivia | SuaCh AVR04027 : Ayudas y Trucos para optimizar tu código C para microcontroladores AVR de 8 bits Nota del Autor.- Este documento es una traducción no oficial del documento AVR4027 de ATMEL CORPORATION. Ha sido realizada por consentimiento y criterio del autor, los errores de traducción no tienen que ver con ATMEL CORPORATION. Sugerencias y comentarios a: [email protected] Autor’s Note.- This document is a non-oficial translation from the documment AVR4027 from ATMEL CORPORATION It has been made by the autor’s consideration, translation mistakes have nothing to do with ATMEL CORPORATION. Feedback me at: [email protected] Características: Núcleo Atmel® AVR® e introducción Atmel AVR GCC Ayuda y Trucos para reducir el tamaño del código Ayuda y Trucos para reducir el tiempo de ejecución Ejemplos de Aplicación 1. INTRODUCCION El núcleo AVR es una arquitectura RISC sintonizada para código en lenguaje C. Asegura el desarrollo de buenos productos con mas prestaciones a menor costo. Cuando se habla de optimización, usualmente nos referimos a dos aspectos: tamaño del código y velocidad de ejecución del código. En nuestros días, los compiladores de C tienen diferentes opciones de optimización para ayudar a los desarrolladores a obtener un código eficiente tanto en tamaño o velocidad. Sin embargo, una buena codificación en C brinda más oportunidades a los compiladores para optimizar el código como se desee. Y en algunos casos, la optimización para uno de los dos aspectos afecta o incluso causa degradación en el otro, entonces un desarrollador tiene que balancear los dos de acuerdo a sus necesidades específicas. Un entendimiento de algunos trucos y ayudas acerca de la codificación en C para un AVR de 8 bits ayuda a los desarrolladores a saber donde enfocarse en la mejora de eficiencia de código. En esta nota de aplicación, las ayudas están basadas en avr-gcc (compilador de lenguaje C). Sin embargo estas ayudas pueden ser implementadas en otros compiladores o con opciones similares de compilación y viceversa.

Transcript of AVR04027: Ayudas y Trucos para optimizar tu código C...

Traducción Nota de Aplicación AVR4027: Ayudas y Trucos para optimizar tu código C

para microcontroladores AVR de 8 bits

1 Hecho en Bolivia | SuaCh

AVR04027: Ayudas y Trucos para optimizar tu código C para

microcontroladores AVR de 8 bits

Nota del Autor.- Este documento es una traducción no oficial del documento AVR4027 de ATMEL

CORPORATION. Ha sido realizada por consentimiento y criterio del autor, los errores de traducción no tienen que ver con ATMEL CORPORATION. Sugerencias y comentarios a: [email protected]

Autor’s Note.- This document is a non-oficial translation from the documment AVR4027 from ATMEL

CORPORATION It has been made by the autor’s consideration, translation mistakes have nothing to

do with ATMEL CORPORATION. Feedback me at: [email protected]

Características:

Núcleo Atmel® AVR® e introducción Atmel AVR GCC

Ayuda y Trucos para reducir el tamaño del código

Ayuda y Trucos para reducir el tiempo de ejecución

Ejemplos de Aplicación

1. INTRODUCCION

El núcleo AVR es una arquitectura RISC sintonizada para código en lenguaje C. Asegura el desarrollo

de buenos productos con mas prestaciones a menor costo.

Cuando se habla de optimización, usualmente nos referimos a dos aspectos: tamaño del código y

velocidad de ejecución del código. En nuestros días, los compiladores de C tienen diferentes

opciones de optimización para ayudar a los desarrolladores a obtener un código eficiente tanto en

tamaño o velocidad.

Sin embargo, una buena codificación en C brinda más oportunidades a los compiladores para

optimizar el código como se desee. Y en algunos casos, la optimización para uno de los dos

aspectos afecta o incluso causa degradación en el otro, entonces un desarrollador tiene que

balancear los dos de acuerdo a sus necesidades específicas. Un entendimiento de algunos trucos y

ayudas acerca de la codificación en C para un AVR de 8 bits ayuda a los desarrolladores a saber

donde enfocarse en la mejora de eficiencia de código.

En esta nota de aplicación, las ayudas están basadas en avr-gcc (compilador de lenguaje C). Sin

embargo estas ayudas pueden ser implementadas en otros compiladores o con opciones similares

de compilación y viceversa.

Traducción Nota de Aplicación AVR4027: Ayudas y Trucos para optimizar tu código C

para microcontroladores AVR de 8 bits

2 Hecho en Bolivia | SuaCh

2. CONOCIENDO EL NUCLEO AVR Y ATMEL AVR GCC

Antes de optimizar software de sistemas embebidos, es necesario tener un buen entendimiento de cómo está estructurado el núcleo AVR y que estrategias usa el AVR GCC para generar código eficiente para este procesador.

2.1 Arquitectura AVR 8-bit

AVR utiliza la arquitectura Harvard- con buses y memorias de programa y datos separados. Tiene un archivo de registro de rápido acceso de 32 x 8 registros de propósito general con un tiempo de acceso en un ciclo de reloj. Los 32 registros de trabajo son una de las llaves para la codificación eficiente en C. Estos registros tienen la misma función que la del tradicional acumulador, excepto que hay 32 de ellos. Las instrucciones aritméticas y lógicas del AVR trabajan en estos registros, de ahí toman menos espacio de instrucciones. En un ciclo de reloj, el AVR puede alimentar dos registros arbitrarios desde el archivo de registro a la ALU (autor> unidad aritmética lógica), realizando una operación, y respondiendo el resultado al archivo de registro. Las instrucciones en la memoria de programa son ejecutadas con un nivel simple de conducción a través de una tubería. Mientras una instrucción está siendo ejecutada, la siguiente instrucción es pre-cargada desde la memoria de programa. Este concepto permite a las instrucciones ser ejecutadas en cada ciclo de reloj. La mayoría de las instrucciones del AVR tienen una palabra de formato 16-bit. Cada dirección de la memoria de programa contiene una instrucción de 16 o 32 bits. Para más detalles, por favor remitirse a la sección "núcleo CPU AVR" en la hoja de datos del dispositivo.

2.2 AVR GCC

GCC representa a la colección de compiladores GNU. Cuando GCC es usado para AVR, este es comúnmente conocido con AVR GCC. El programa actual "gcc" es prefijado con "avr-" es decir, "avr-gcc". AVR GCC provee varios niveles de optimización. Estos son -O0, -O1, -O2, -O3 y -Os. En cada nivel, hay diferentes opciones de optimización disponibles, excepto -O0 que significa no optimización. Además de las opciones habilitadas en niveles de optimización, usted puede también habilitar separar las opciones de optimización para obtener una optimización específica. Por favor remítase al manual de colección de compiladores GNU como abajo para una completa lista de opciones y niveles de optimización. http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#Optimize-Options

Traducción Nota de Aplicación AVR4027: Ayudas y Trucos para optimizar tu código C

para microcontroladores AVR de 8 bits

3 Hecho en Bolivia | SuaCh

Además "avr-gcc", usa muchas otras herramientas trabajando juntas para producir la aplicación ejecutable final para el microcontrolador AVR. El grupo de herramientas es llamado toolchain (autor> conjunto de herramientas). En este toolchain de AVR, avr-libc sirve como una importante librería en C la cual provee muchas de las mismas funciones encontradas en una librería C regular Estándar y muchas funciones de librerías adicionales que son específicas para un AVR. El paquete AVR Libc provee un subconjunto de la librería estándar C para microcontroladores RISC AVR de 8 bits. Adicionalmente, la librería provee el código básico de inicio para la mayoría de las aplicaciones. Por favor compruebe el enlace de abajo para el manual de avr-libc,

http://www.nongnu.org/avr-libc/user-manual/

2.3 Plataforma de Desarrollo

Los ejemplos de código y resultados de pruebas en este documento están basados en la siguiente plataforma y dispositivo,

1. Entorno integrado de desarrollo (IDE): Atmel AVR Studio® 5 (Version: 5.0.1119).

2. AVR GCC 8-bit Toolchain Version: AVR_8_bit_GNU_Toolchain_3.2.1_292 (gcc version 4.5.1)

3. Dispositivo Objetivo: Atmel ATmega88PA.

Traducción Nota de Aplicación AVR4027: Ayudas y Trucos para optimizar tu código C

para microcontroladores AVR de 8 bits

4 Hecho en Bolivia | SuaCh

3. AYUDAS Y TRUCOS PARA REDUCIR EL TAMAÑO DEL CODIGO En esta sección, listaremos algunas ayudas acerca de cómo reducir el tamaño del código. Para cada ayuda están dados la descripción y código de muestra.

3.1 Ayuda #1 - Tipo de datos y tamaño

Use el más pequeño tipo de dato aplicable como sea posible. Evalué su código y en particular los tipos de datos. Para leer un valor de 8 bits (1 byte) desde un registro se requiere una variable de 1-byte y no una variable de doble-byte, de este modo se ahorra espacio de código.

El tamaño de tipos de datos sobre un AVR de 8 bits puede ser encontrado en la librería de cabecera <stdint.h> y esta resumida en la Tabla 3-1.

Este consiente que ciertos cambios de compilador pueden cambiar esto (avr-gcc -mint8 cambia tipos de datos enteros a enteros de 8 bits).

Los dos ejemplos en la Tabla 3-2 muestran el efecto de los diferentes tipos de datos y tamaños. La salida desde la utilidad avr-size muestra el espacio de código que hemos usado cuando esta aplicación es construida con -Os (optimización por tamaño).

En el ejemplo de la izquierda, utilizamos el tipo de dato int (2-bytes) como valor de retorno desde la función readADC() y en la variable temporal usada para almacenar el valor de retorno desde la función readADC().

Traducción Nota de Aplicación AVR4027: Ayudas y Trucos para optimizar tu código C

para microcontroladores AVR de 8 bits

5 Hecho en Bolivia | SuaCh

En vez de eso en el ejemplo de la derecha estamos usando char (1-byte). La respuesta desde el registro ADCH es solo de ocho bits, y esto significa que un char es suficiente. Dos bytes grabados para retornar el valor de la función readADC() y la variable temporal en main son cambiados de int (2-bytes) a char (1-byte).

NOTA Hay un código de inicio antes de la ejecución desde main(). Esa es la razón porque un simple código en C consume cerca de 90 Bytes.

3.2 Ayuda #2 - Variables locales y globales

En la mayoría de los casos, El uso de variables globales no es recomendado. Use variables locales cuando sea posible. Si una variable es usada solo en una función, entonces deberá ser declarada dentro la función como una variable local.

En teoría, la elección de si una variable debe ser declarada como global o local debe ser decidido por cómo es utilizada.

Si una variable global es declarada, una dirección única en la SRAM será asignada para esta variable a tiempo de unir el programa. También para acceder a una variable global típicamente se necesitará bytes extras (usualmente dos bytes para una dirección de 16 bits de longitud) para obtener sus direcciones.

Las variables locales son preferentemente asignadas a un registro o asignadas a la pila si son

soportadas al declararse. Cuando una función se activa, las variables locales de la función también se activan. Una vez que la función sale (autor> termina), las variables locales de la función pueden ser removidas.

En la tabla 3-3 hay dos ejemplos mostrando el efecto de las variables locales y globales.

En el ejemplo de la izquierda, hemos declarado una variable global de 1 byte. La salida desde la utilidad avr-size muestra que usamos 104 bytes de espacio de código y un byte de espacio de memoria de datos con nivel de optimizacion -Os (optimización por tamaño).

Traducción Nota de Aplicación AVR4027: Ayudas y Trucos para optimizar tu código C

para microcontroladores AVR de 8 bits

6 Hecho en Bolivia | SuaCh

En el ejemplo de la derecha, hemos declarado una variable dentro la función main() como local, el espacio de código se reduce a 84 bytes y no se utiliza la memoria SRAM.

3.3 Ayuda #3 - Indice del bucle

Los bucles son ampliamente utilizados en un código AVR 8 de bits. Están el bucle "while(){}", bucle "for()" y el bulce "do{}while()". Si la opción de optimización -Os está habilitada; El compilador optimizara los bucles automáticamente para tener el mismo tamaño de código.

Sin embargo aun podemos reducir el tamaño del código levemente. Si utilizamos un bucle "do{}while()", un incremento o un decremento en el índice del bucle genera un tamaño de código diferente.

Usualmente escribimos nuestros bucles contando desde cero al máximo valor (incremento), pero es más eficiente contar el bucle desde el máximo valor a cero (decremento). Esto es porque en un bucle de incremento, se necesita una instrucción de comparación para comparar el índice del bucle con el valor máximo en cada bucle para comprobar si el índice de bucle alcanza el valor máximo.

Cuando usamos un bucle de decremento, esta comparación no es necesaria porque el resultado del decremento del índice del bucle pondrá a 1 la bandera Z (cero) en SREG si este llega a cero.

En la Tabla 3-4 hay dos ejemplos mostrando el código generado por un bucle "do{}while()" con índices del bucle con incremento y decremento. El nivel de optimización utilizado aquí es -Os (optimización por tamaño).

Traducción Nota de Aplicación AVR4027: Ayudas y Trucos para optimizar tu código C

para microcontroladores AVR de 8 bits

7 Hecho en Bolivia | SuaCh

Para tener una comparación clara en líneas de código C, este ejemplo está escrito como

"do{conteo--;}while(conteo)" y no como "do{}while(--conteo);" usualmente utilizado en libros de

lenguaje C. Los dos estilos generan el mismo código.

3.4 Ayuda #4 - Interferencia de bucle

La interferencia de bucle aquí se refiere a integrar declaraciones y operaciones de bucles

diferentes a menos bucles o a un bucle, esto reduce el número de bucles en el código. En

algunos casos, varios bucles son implementados uno por uno. Y esto puede llevar una larga lista

de iteraciones. En este caso, interferir el bucle puede ayudar a incrementar la eficiencia de

código por tener en realidad bucles combinados en uno.

Interferir bucles reduce el tamaño de código y hace al código ejecutarse más rápido así como

elimina la iteración encima de él. Del ejemplo en la Tabla 3-5, podemos ver cómo trabajan las

interferencias de bucle.

Traducción Nota de Aplicación AVR4027: Ayudas y Trucos para optimizar tu código C

para microcontroladores AVR de 8 bits

8 Hecho en Bolivia | SuaCh

3.5 Ayuda #5 - Constantes en el espacio de programa

Muchas aplicaciones exceden el tamaño de la SRAM, en las cuales se almacena datos, antes de

que excedan el tamaño de la Flash. Variables constantes globales, tablas o arrays que nunca

cambian, deberían ser colocadas en la sección de solo lectura (Flash o EEPROM en un AVR de 8

bits). Y de esta manera podemos ahorrar espacio precioso en la SRAM.

En este ejemplo no utilizamos la palabra reservada de lenguaje C "const". Declarando un objeto

"const" se entiende que este valor no será cambiado. "const" es utilizado para decirle al

compilador que el dato es solo pare ser leído e incrementa las oportunidades de optimización.

Esto no identifica donde debería ser almacenado el dato.

Para almacenar datos dentro el espacio de la memoria de programa (solo-lectura) y recibirlos

desde la memoria de programa, AVR-Libc provee un simple macro "PROGMEM" y un macro

"pgm_read_byte". El macro PROGMEM y la función pgm_read_byte están definidas en el archivo

sistema de cabecera <avr/pgmspace.h>.

El siguiente ejemplo en la Tabla 3-6 muestra como ahorramos SRAM moviendo la cadena

global dentro el espacio de memoria de programa.

Después que localizamos las constantes dentro la memoria de programa, vemos que el espacio

de uso de la memoria de programa y de la memoria de datos se reducen. Sin embargo, Hay un

pequeño costo cuando leemos el dato, porque la función de ejecución será más lenta que leer

directamente de la SRAM.

Traducción Nota de Aplicación AVR4027: Ayudas y Trucos para optimizar tu código C

para microcontroladores AVR de 8 bits

9 Hecho en Bolivia | SuaCh

Si el dato almacenado en la memoria flash usa tiempos múltiples en el código, obtenemos un

tamaño más pequeño usando una variable temporal en lugar de usar directamente el macro

"pgm_read_byte" varias veces.

Hay más macros y funciones en el archivo de sistema de cabecera <avr/pgmspace.h> para

almacenar o recuperar diferentes tipos de datos desde/hacia la memoria de programa. Por favor

vea el manual de usuario de avr-libc para más detalles.

3.6 Ayuda #6 - Tipos de Acceso: Static

Para datos globales, use la palabra reservada static cuando sea posible. Si hay variables globales

declaradas con la palabra reservada static, puede accederse a ellas solo desde el archivo en el

cual fueron definidas. Esto previene el uso no planeado de la variable (como variable externa)

por otros archivos del código.

Por otro lado, debería ser evitado declarar variables locales dentro una función como static. El

valor de una variable local "static" necesita ser preservado entre llamadas a la función y la

variable persiste por todo el programa. De este modo requiere un espacio de almacenamiento

de datos (SRAM) permanente y código extra para acceder a la variable. Esto es similar a una

variable global excepto que su ámbito está en la función donde fue definida.

Una función static es más fácil de optimizar, porque su nombre es invisible fuera del archivo

donde está declarada y no será llamada desde ningún otro archivo.

Si una función static es llamada solo una vez en el archivo con optimización (-O1, -O2, -O3 y -

Os) activada, la función será optimizada automáticamente por el compilador como una función

en-línea y ningún código assembler es producido para esta función. Por favor compruebe el

ejemplo en la Tabla 3-7 para el efecto.

Traducción Nota de Aplicación AVR4027: Ayudas y Trucos para optimizar tu código C

para microcontroladores AVR de 8 bits

10 Hecho en Bolivia | SuaCh

NOTA Si la función es llamada múltiples veces, no será optimizada a una función en-línea, porque esto

generará más código que la simple llamada a la función.

3.7 Ayuda #7 - Instrucciones assembler de bajo nivel

Las instrucciones en assembler bien codificadas siempre son el código mejor optimizado. Un

inconveniente del código assembler es su sintaxis no-portable, así que no es recomendado para

programadores en la mayoría de los casos.

Sin embargo usando macros assembler se reduce la dificultad a menudo asociada al código

assembler y mejora la portabilidad y entendimiento. Use macros assembler en vez de funciones

para tareas que generan menos de 2 a 3 líneas de código assembler. El ejemplo un la Tabla 3-8

muestra el uso de código de un macro assembler comparado con el uso de una función.

Traducción Nota de Aplicación AVR4027: Ayudas y Trucos para optimizar tu código C

para microcontroladores AVR de 8 bits

11 Hecho en Bolivia | SuaCh

Para más detalles de cómo usar lenguaje assembler (autor> ensamblador) con C en AVR de 8 bits,

por favor diríjase a la sección "Inline Assembler Cookbook" en el manual de usario de avr-libc.

Traducción Nota de Aplicación AVR4027: Ayudas y Trucos para optimizar tu código C

para microcontroladores AVR de 8 bits

12 Hecho en Bolivia | SuaCh

4. AYUDAS Y TRUCOS PARA RECUDIR EL TIEMPO DE EJECUCION

En esta sección, listamos algunos trucos de cómo reducir el tiempo de ejecución. Para cada truco,

están dadas algo de descripción y código de muestra.

4.1 Ayuda #8 - Tipos de datos y tamaño

Además de reducir el tamaño del código, seleccionando un tipo de dato y tamaño apropiado

también reducirá el tiempo de ejecución. Para AVR de 8 bits, El acceso al valor de 8 bits (Byte)

siempre es el camino más efectivo.

Por favor compruebe el ejemplo en la Tabla 4-1 para ver la diferencia de una variable de 8 bits y

una de 16 bits.

NOTA El bucle será desenrollado automáticamente por el compilador con la opción -O3. Después el

bucle será expandido en operaciones repetitivas indicadas por el índice del bucle, así que para

este ejemplo no hay diferencia con la opción -O3 habilitada.

Traducción Nota de Aplicación AVR4027: Ayudas y Trucos para optimizar tu código C

para microcontroladores AVR de 8 bits

13 Hecho en Bolivia | SuaCh

4.2 Ayuda#9 - Declaración Condicional

Usualmente un pre-decremento o post-decremento (o pre-incrementos y post-decrementos) en

líneas normales de código no hace diferencia. Por ejemplo, "i--" e "--i", simplemente generan el

mismo código. Sin embargo, usando estos operadores como índices de bucles y en

declaraciones condicionales hacen al código generado diferente.

Como se explica en la Ayuda #3 - índice de bucle, usando un índice de bucle de decremento

resulta en un código más pequeño. Esto es también algo útil para obtener un código más veloz

en declaraciones condicionales.

Es más, el pre-decremento y post-decremento tienen también resultados diferentes. Desde los

ejemplos en la Tabla 4-2, podemos ver que se genera un código más veloz con una declaración

condicional de pre-decremento. El contador de ciclos representa el tiempo de ejecución del

bucle más largo.

La variable "loop_cnt" esta asignada con diferentes valores en los dos ejemplos en la Tabla 4-2

para asegurarse que el ejemplo trabaje igual: PORTC0 es cambiado nueve veces mientras

PORTB0es cambiado nueve veces en cada ejecución del bucle.

Traducción Nota de Aplicación AVR4027: Ayudas y Trucos para optimizar tu código C

para microcontroladores AVR de 8 bits

14 Hecho en Bolivia | SuaCh

4.3 Ayuda#10 - Bucles desenrollados

En algunos casos, podemos desenrollar bucles para acelerar la ejecución del código. Esto es

especialmente efectivo para bucles cortos. Después que un bucle es desenrollado, no hay

índices de bucle para ser comprobados y menos ramificaciones son ejecutadas en cada ronda en

el bucle.

El ejemplo en la Tabla 4-3 intercambiará un pin de un puerto diez veces.

Al desenrollar el bucle do{} while(), la velocidad del código se incrementa significativamente de

80 a 50 ciclos de reloj.

Sea consciente que el tamaño del código se incrementa de 94 a 142 bytes después de

desenrollar el bucle. Esto es también un ejemplo del sacrificio de optimización entre velocidad y

tamaño de código.

NOTA Si la opción -O3 está habilitada en este ejemplo, el compilador desenrollará el bucle

automáticamente y generará el mismo código como el bucle desenrollado manualmente.

Traducción Nota de Aplicación AVR4027: Ayudas y Trucos para optimizar tu código C

para microcontroladores AVR de 8 bits

15 Hecho en Bolivia | SuaCh

4.4 Ayuda#11 - Control de flujo: if-else y switch-case

"if-else" y "switch-case" son ampliamente usados en código C; una organización apropiada de

las ramificaciones puede reducir la ejecución del código.

Para "if-else", siempre coloque las condiciones más probables en primer lugar. Después coloque

las condiciones que son menos probables de ejecutarse. Así de esta manera se ahorra tiempo

para la mayoría de los casos.

Usando "switch-case" se puede eliminar los inconvenientes de "if-else", porque para un "switch-

case", el compilador usualmente genera tablas de búsqueda con índice y salto directamente al

lugar correcto.

Si es difícil de usar "switch-case", se puede dividir la ramas "if-else" en sub-ramas más pequeñas.

Este método reduce ejecuciones para el caso de la condición más improbable. En el ejemplo de

abajo, se toma datos desde el ADC y luego se envía vía USART. "ad_result<=240" es el caso

menos probable.

Traducción Nota de Aplicación AVR4027: Ayudas y Trucos para optimizar tu código C

para microcontroladores AVR de 8 bits

16 Hecho en Bolivia | SuaCh

Podemos ver que se requiere menos tiempo para alcanzar la rama en el peor de los casos.

También podemos notar que el tamaño del código se incrementa. Así de este modo deberíamos

balancear el resultado de acuerdo al requerimiento específico de tamaño o velocidad.

Traducción Nota de Aplicación AVR4027: Ayudas y Trucos para optimizar tu código C

para microcontroladores AVR de 8 bits

17 Hecho en Bolivia | SuaCh

5. APLICACIÓN DE EJEMPLO Y PRUEBA DE RESULTADO

Un ejemplo de aplicación es usado para mostrar el efecto de las ayudas y trucos mencionados

arriba. La opción de optimización por tamaño -s está habilitada en este ejemplo.

Varias (no todas) ayudas y trucos son utilizadas para optimizar el ejemplo de aplicación.

En este ejemplo, un canal ADC está siendo usado para muestrear la entrada y el resultado es

enviado vía USART cada cinco segundos. Si el resultado del ADC está fuera de rango, se envía

una alarma por 30 segundos antes que la aplicación sea bloqueada en estado de error. En el

resto del bucle principal, el dispositivo es colocado en modo de ahorro de energía.

Los resultados de velocidad y optimización del ejemplo de aplicación antes y después de la

optimización están enlistados en la Tabla 5-1.

Nota: 1. Un bucle incluye cinco muestras del ADC y uno la transmisión USART.

6. CONCLUSION

En este documento, se ha listado algunas ayudas y trucos acerca de eficiencia de código en

tamaño y velocidad. Gracias a los compiladores modernos de C, que son inteligentes e invocan

opciones de optimización diferentes en casos diferentes. Sin embargo, ningún compilador

conoce el código mejor que el desarrollador, así que una buena codificación siempre es

importante.

Como se muestra en los ejemplos, optimizar un aspecto puede tener un efecto sobre el otro.

Necesitamos balancear entre tamaño de código y velocidad de ejecución basándonos en

nuestras necesidades específicas.

Aunque tengamos estos trucos y ayudas para optimización de código C, para un uso mejor de

ellos, es muy necesario un buen entendimiento del dispositivo y compilador con el que usted

está trabajando. Y definitivamente hay otras habilidades y métodos para optimizar la eficiencia

de código en diferentes casos de aplicación.

Traducción Realizada en Julio de 2012

Traducción Nota de Aplicación AVR4027: Ayudas y Trucos para optimizar tu código C

para microcontroladores AVR de 8 bits

18 Hecho en Bolivia | SuaCh

7. TABLA DE CONTENIDO

Características ………………………………………………………………………………..1

1. INTRODUCCION…………………………………………………………………………1 2. CONOCIENDO EL NUCLEO AVR Y ATMEL AVR GCC…………………….......2

2.1 Arquitectura AVR 8-bit………………………………………………………………………......2 2.2 AVR GCC………………………………………………………………………………………………....2 2.3 Plataforma de Desarrollo……………………………………………………..............................3 3. AYUDAS Y TRUCOS PARA REDUCIR EL TAMAÑO DEL CODIGO…….....…4 3.1 Ayuda #1 - Tipo de datos y tamaño…………………………………………………........4 3.2 Ayuda #2 - Variables locales y globales…………………………………………..….….5 3.3 Ayuda #3 - Indice del bucle………………………………………………………….…….…..6 3.4 Ayuda #4 - Interferencia de bucle……………………………………………………….….7 3.5 Ayuda #5 - Constantes en el espacio de programa…………………………………..8

3.6 Ayuda #6 - Tipos de Acceso: Static……………………………………………………...….9

3.7 Ayuda #7 - Instrucciones assembler de bajo nivel………………………….……......10 4. AYUDAS Y TRUCOS PARA RECUDIR EL TIEMPO DE EJECUCION……….…..12

4.1 Ayuda #8 - Tipos de datos y tamaño……………………………………………….……….…..12

4.2 Ayuda#9 - Declaración Condicional………………………………………………………….….13

4.3 Ayuda#10 - Bucles desenrollados…………………………………………………….….……….14

4.4 Ayuda#11 - Control de flujo: if-else y switch-case………………………….……………15

5. APLICACIÓN DE EJEMPLO Y PRUEBA DE RESULTADO……………………….17

6. CONCLUSION……………………………………………………………………………17