Misceláneos

Optimización de código en microcontroladores

Autor: Laura McKinney
Fecha De Creación: 4 Abril 2021
Fecha De Actualización: 16 Mayo 2024
Anonim
Sistemas Operativos 2020-05-21: Sistemas de archivos: Estructura en el dispositivo
Video: Sistemas Operativos 2020-05-21: Sistemas de archivos: Estructura en el dispositivo

Contenido

El autor completó su proyecto de ingeniería de último año con los microcontroladores dsPic, obteniendo una visión amplia de estos dispositivos.

El código en lenguaje C de un microcontrolador puede requerir optimización en ciertas aplicaciones avanzadas. Esta optimización de código se practica para reducir dos cosas cruciales:

  1. Tamaño del código: Los microcontroladores pueden almacenar datos e instrucciones limitados debido al tamaño limitado de su RAM. Por lo tanto, el código debe optimizarse, de modo que la memoria de datos e instrucciones disponibles se pueda utilizar de la manera más eficiente.
  2. Tiempos de ejecución del código: Los microcontroladores son dispositivos secuenciales que ejecutan una instrucción a la vez. Cada instrucción de ensamblaje consume una cierta cantidad de ciclos de reloj para ejecutarse. Por lo tanto, el código debe optimizarse para garantizar que realiza la tarea requerida en el menor número de ciclos de reloj o instrucciones de ensamblaje. Cuantos menos ciclos de reloj utilice un código, más rápido se ejecutará. Esto significa que las aplicaciones pueden ejecutarse más rápido porque se minimizan los tiempos de procesamiento.

Este artículo presenta consejos y trucos que pueden emplearse para reducir el tamaño y el tiempo de ejecución de un código de microcontrolador.


El IDE de desarrollo MplabX de Microchip se utilizará para demostrar ejemplos cuando sea apropiado.

Cómo medir el tiempo de ejecución del código de forma experimental

Para tener una idea de cuánto tiempo tarda su código en ejecutarse en tiempo real, debe medirlo de forma experimental. Un analizador lógico se puede usar convenientemente para medir el tiempo de ejecución del código y los interesados ​​pueden consultarme sobre el proceso por correo electrónico. Además de esto:

  • Algunos compiladores tienen la capacidad de contar los ciclos de reloj que consumirá un código.
  • Algunos depuradores, por ejemplo, el ICD 3 de microchip, pueden medir directamente el tiempo de ejecución a través de un cronómetro.

1. Conozca la potencia de procesamiento y el tamaño de la memoria de su microcontrolador

No siempre es la frecuencia de reloj (Mhz) la que da la imagen real de la velocidad de procesamiento de un microcontrolador, una medida más realista es MIPS (megainstrucciones por segundo) o la cantidad de instrucciones que MCU puede ejecutar en un segundo.

Las MCU suelen oscilar entre 60 y 70 MIPS en la categoría de gama alta y 20 AVR de 8 bits MIPS. Es probable que un microcontrolador de MIPS alto sea más caro que un dispositivo de gama baja, por lo que aquí tiene un compromiso entre el costo y la velocidad de procesamiento.


Los microcontroladores tienen una memoria separada para almacenar datos y código de programa. El tamaño de ambos se puede encontrar en la hoja de datos. Es posible que necesite una MCU con un tamaño de memoria más grande si su código es sustancialmente grande.

2. Elección de variables para la optimización en el tamaño del código

Los microcontroladores tienen una memoria de datos limitada, que suele oscilar entre 1 y 4 Kbytes. En este caso, es aconsejable elegir el tipo de variable más apropiado de acuerdo con el rango esperado de la fecha que se almacena. La siguiente tabla resume estas variables:

Resumen de variables utilizadas en lenguaje C.

Tipo de variableTamaño en bytesDistancia

bool

1

0 o 1 solamente

carbonizarse

1


-128 hasta 127

En t

2

-32.768 hasta 32.767

int sin firmar

2

0 hasta 65.535

largo

4

-2,147,483,648 a 2,147,483,647

flotador

4

Precisa hasta 6 lugares decimales

doble

8

Preciso hasta 15 lugares decimales

doble largo

10

Precisa hasta 19 posiciones decimales

Ejemplo:

  • Si se van a sumar dos variables X e Y y el resultado se va a almacenar en Z pero se espera que el valor de Z sea superior a 65 535 después de la adición, entonces Z puede declararse como long y X e Y pueden declararse sin signo int, tampoco se espera que los valores de X e Y sean negativos. Esto guardará 04 bytes en la memoria de datos que de otro modo se habrían agotado si todas las variables fueran declaradas tan largas.
  • Dos variables X e Y, cuyos valores se espera que estén en números enteros, deben dividirse, pero el resultado de la división puede producir un decimal, luego X e Y pueden declararse int y el resultado puede declararse flotante o doble dependiendo de la precisión requerida.

La elección del tipo de datos puede ser crucial al declarar matrices que contienen una gran cantidad de elementos.

3. Elección de variables para la optimización en el tiempo de ejecución del código

  • Es un hecho establecido que los cálculos de punto flotante toman más tiempo que los cálculos de punto fijo. No utilice una variable de punto flotante donde no se requiera un valor decimal. Trabaje con enteros sin signo siempre que sea posible.
  • Se prefieren las variables locales a las globales. Si una variable se usa solo en una función, entonces debe declararse en esa función porque acceder a las variables globales es más lento que a las variables locales.
  • Una MCU de 8 bits encontrará una variable de tamaño de un solo byte más rápido para acceder y una MCU de 16 bits encontrará una variable de 2 bytes más fácil de acceder debido a la longitud de la dirección generada.

4. Optimización de operaciones aritméticas

Las operaciones aritméticas se pueden optimizar de las siguientes formas.

  1. Utilice tablas de búsqueda de valores precalculados en lugar de evaluar un seno o cualquier otra función trigonométrica o cualquier otra operación cuyo resultado se pueda conocer de antemano en el código.
  2. En caso de que una tabla de búsqueda de seno ya esté almacenada en la memoria, se puede evaluar un coseno avanzando el puntero de matriz equivalente a 90 grados.
  3. Entre las cuatro operaciones aritméticas, la división y la multiplicación toman el mayor tiempo de procesamiento, en la práctica puede estar en el rango de cientos de microsegundos más o menos en el caso de valores de punto flotante.
  4. Utilice instrucciones de desplazamiento de bits en lugar de división y multiplicación. Una instrucción de desplazamiento a la derecha 3 sirve para dividir por 23 donde como instrucción de desplazamiento a la izquierda 1 servirá para multiplicar por 21.

5. Utilice un microcontrolador con capacidad DSP para cálculos intensivos

Algunos microcontroladores tienen una unidad de procesamiento DSP distinta de la ALU convencional incorporada en su arquitectura. Este motor DSP está diseñado para realizar cálculos aritméticos muy rápidamente en el menor número de ciclos de reloj (uno en la mayoría de los casos) muchas veces más rápido que la ALU.

Las instrucciones que un procesador DSP puede realizar más rápido que una ALU son:

  • Instrucciones de cambio y rotación de bits.
  • Multiplicaciones, divisiones y otras operaciones aritméticas.
  • Evaluación de senos y otras funciones trigonométricas.
  • Todas las operaciones DSP como FFT, DFT, convolución y filtrado FIR.

El uso del motor DSP de un microcontrolador requiere que:

  • Se incorporan al proyecto bibliotecas de DSP independientes.
  • Los nombres de las funciones son diferentes de la biblioteca matemática estándar del lenguaje C. La documentación de estas bibliotecas y funciones puede obtenerse en el sitio web de los respectivos fabricantes.
  • El motor DSP utiliza un tipo de variable diferente "fraccional". Aprenda a usar variables de tipo fraccionario antes de continuar con las funciones de la biblioteca dsp.

Tenga en cuenta que las funciones de la biblioteca matemática estándar no invocarán el motor DSP porque se traducen en instrucciones de ensamblaje de ALU.

6. Trabajar con interrupciones

Utilice interrupciones para realizar funciones específicas como:

  • Lectura de valores ADC.
  • Envío y recepción de UART.
  • Actualización de registros de ciclo de trabajo de PWM.
  • Comunicación CAN o I2C.

Las interrupciones darán servicio a estas funciones rápidamente en comparación con realizarlas en el cuerpo principal mediante una llamada de función o código en línea.

Las interrupciones también se activarán solo cuando sea necesario, mientras que si se codifica en el cuerpo principal, el código se ejecutará en cada iteración del ciclo while (1).

7. Utilice los mejores compiladores disponibles

Los compiladores pueden implementar automáticamente algunas de las optimizaciones discutidas anteriormente mientras traducen el código del lenguaje C al lenguaje ensamblador si se configura correctamente. Busque opciones de optimización en su compilador y, si es posible, actualice a versiones profesionales de compiladores porque son optimizadores de código más potentes.

8. Utilice declaraciones condicionales de forma inteligente

  • Cuando utilice una serie de declaraciones if-else, mantenga primero la condición más probable. De esta manera, la MCU no tendrá que escanear todas las condiciones después de encontrar la condición verdadera.
  • Una sentencia switch-case suele ser más rápida que una if-else.
  • Utilice declaraciones if-else anidadas en lugar de una serie de declaraciones. Un bloque if-else que tiene muchas declaraciones puede dividirse en sub-ramas más pequeñas para optimizarlo para la condición del peor caso (último).

9. Utilice funciones en línea

Las funciones que se utilizarán solo una vez en el código se pueden declarar como estáticas. Esto hará que el compilador optimice esa función a una función en línea y, por lo tanto, no se traducirá ningún código ensamblador para la llamada a la función.

  • Una función puede declararse en línea usando la palabra clave 'estática' con ella.

10. Utilice bucles decrementados

Un bucle decrementado generará menos código ensamblador en comparación con un bucle incrementado.

Esto se debe a que en un ciclo de incremento, se necesita una instrucción de comparación para comparar el índice de ciclo con el valor máximo en cada ciclo para verificar si el índice de ciclo alcanza el valor máximo. Por el contrario, en un ciclo decreciente, esta comparación ya no es necesaria porque el resultado decreciente del índice del ciclo establecerá la bandera de cero en SREG si llega a cero.

Dado que el ciclo tiene que repetirse cien veces, reducir una instrucción del ciclo evitará que se ejecute cien veces, por lo que es probable que el impacto sea más significativo cuando el ciclo tiene que repetirse muchas veces.

Terminando

Estos consejos pueden ser útiles, pero su verdadera aplicación y potencia depende de la habilidad del programador y del comando que tenga en su código. Recuerde, el tamaño del programa no siempre determina los tiempos de ejecución, algunas instrucciones pueden consumir más ciclos de reloj que la otra, por lo que una vez más las habilidades del programa deben desempeñar su papel.

Este artículo es exacto y verdadero según el leal saber y entender del autor. El contenido es solo para fines informativos o de entretenimiento y no sustituye el asesoramiento personal o el asesoramiento profesional en asuntos comerciales, financieros, legales o técnicos.

Nuevos Artículos

Fascinantemente

Intel Pentium G4560 frente a AMD Ryzen 3 1200 con puntos de referencia
Ordenadores

Intel Pentium G4560 frente a AMD Ryzen 3 1200 con puntos de referencia

olo oy un chico de poca monta que trabaja en un trabajo normal como a i tente médico. Mi pa ión e con truir PC y probar / revi ar hardware de PC.Hola a todo . erá aquí y hoy, e to...
Cómo evitar que los vendedores por teléfono falsifiquen su número
Los Telefonos

Cómo evitar que los vendedores por teléfono falsifiquen su número

Laura e una e critora independiente que vive en Florida. Tiene una mae tría en inglé .Al principio, olo recibía alguna llamada cada poco día . A vece eran men aje de texto al azar ...