¿Existen métodos de prueba estándar para código bare metal?

Quiero saber si el código bare metal, especialmente cosas como el código de inicialización del dispositivo/periférico, tiene algún método de prueba, ya que hay poco o nada que pueda salir mal al escribir en los registros (una vez que sepa que todas las direcciones están asignadas correctamente). Además, este tipo de código generalmente tiene muy pocas ramas/rutas cuando el dispositivo se configura para una sola función, entonces, ¿qué tipo de prueba sería necesaria o aplicable aquí?

Respuestas (1)

Lo primero que verifico en una placa nueva, ya sea usando un oscilador interno o un cristal externo, es que tengo la frecuencia de reloj configurada correctamente. Esto es importante porque muchos de los periféricos, como UART, SPI, I2C y temporizadores, dependen de él.

La forma en que lo verifico es escribir un programa con un ciclo corto, ya sea en lenguaje ensamblador donde puedo contar los ciclos manualmente, o C siempre que pueda obtener una lista de desensamblaje y hacer lo mismo, y encender un LED y fuera. Configuré un bucle para que se ejecute una vez por segundo. Ejecuto el código y compruebo que el LED parpadea 60 veces en un minuto.

En lo que respecta a los periféricos, la mejor manera de verificarlos es usar un osciloscopio si tiene uno, y mirar la línea RX para UART, las líneas CLK, MOSI y chip select para SPI, y las líneas SDA y SCL para I2C, y verifique que las líneas estén alternando y que el tiempo parezca correcto.

Si no tiene un osciloscopio, puede colocar LED en estas líneas y luego habilitar o deshabilitar los periféricos. Cuando está deshabilitado, la mayoría de las líneas estarán bajas (LED apagado), pero algunas estarán altas, como el cable RX. de la UART (LED encendido). Cuando el periférico está habilitado, la mayoría de los LED deben atenuarse, ya que las líneas se alternarán. Al ejecutarse en un bucle (deshabilitado/habilitado), es más fácil ver la diferencia entre encendido o atenuado.

Para el UART, puede conectar la línea TX a la línea RX como un bucle. También puede conectar luego a un cable UART a USB , y en la PC real una terminal un programa como RealTerm . Además de probar la interfaz, esto será útil para otras depuraciones posteriores.

Para otras piezas de código, utilizo múltiples LED según sea necesario para mostrar que se están ejecutando varias rutas en el código. Si tiene el UART funcionando y conectado a una PC, puede rociar su código con llamadas a una subrutina para generar un mensaje que muestre qué puntos ha alcanzado el programa (o use printf si tiene las bibliotecas C estándar disponibles). Pero como Vladimir Cravero señala en un comentario a continuación, esto puede ralentizar un poco su código (a 115,200 baudios, no demasiado, ya que el tiempo de un carácter es < 10 µs). Pero en ISR y otros códigos de tiempo crítico, solo use LED.

Como Al Bundy señala en un comentario a continuación, los depuradores en circuito también pueden ser útiles, particularmente si uno puede establecer múltiples puntos de interrupción, y aún más útil si puede cambiar un punto de interrupción en una ubicación de memoria. No todos los depuradores tienen esa característica.

Sin embargo, no uso mucho los depuradores a menos que sea necesario, por ejemplo, para mirar bits en un registro periférico; o para rastrear un error que no puedo encontrar por inspección; o al análisis de cobertura de código rudimentario. Pero, en general, me gusta ejecutar programas a su velocidad "normal", ya que generalmente aparecerán muchos problemas que pueden no aparecer cuando el programa es de un solo paso. La mayoría de mis programas usan muchas interrupciones, lo que interfiere con el uso de un depurador.

Usted dijo casi todo, solo agregaría que, por lo general, rociar su código con fprintf lo ralentizará mucho, es algo que debe usar si es necesario y si sabe lo que está haciendo. He visto algunas preguntas (y he tenido algunos problemas) sobre un fprintf en un ISR o algo así.
@VladimirCravero De acuerdo, por eso me gusta usar LED.
Gracias por la respuesta. ¿Algún consejo sobre qué herramientas/configuración usaría para la cobertura del código en caso de que solo tenga un simulador pero no el hardware real?
¿Qué pasa con el depurador? ¿No vale la pena mencionarlo?
@ user4934 Las herramientas de cobertura de código dependen mucho del procesador y el compilador/IDE que esté utilizando, por lo que no puedo recomendar ninguna. Además, pueden ser muy costosos, en miles de dólares. En su lugar, puede implementar sus propias herramientas de cobertura de código utilizando algunas de las técnicas de este artículo . (Nota: los ejemplos están en Perl, pero son muy parecidos a C). En cuanto a probar qué rutas toma un programa, puede establecer puntos de interrupción en una o ambas ramas siempre que tenga una decisión.
Estoy absolutamente de acuerdo con usted, pero como ARM se está volviendo cada vez más popular, me gustaría recordar que GCC y GDB (ambos admiten ARM) son herramientas gratuitas y vale la pena tenerlas en cuenta al elegir el dispositivo para el proyecto.
@AlBundy No uso mucho los depuradores a menos que tenga que hacerlo, por ejemplo, para mirar bits en un registro periférico; o para rastrear un error que no puedo encontrar por inspección; o para realizar un análisis de cobertura de código rudimentario como mencioné en mi comentario al OP. Pero, en general, me gusta ejecutar los programas a su velocidad "normal", ya que generalmente aparecerán muchos problemas que no aparecerían cuando el programa es de un solo paso. La mayoría de mis programas usan muchas interrupciones, lo que interfiere con el uso de un depurador. Agregaré algunos de estos comentarios en mi respuesta.
Tener un depurador en circuito que funcione puede ahorrar mucho tiempo en comparación con no tenerlo, especialmente una vez que el sistema se vuelve complejo. El simple hecho de poder colocar un punto de interrupción en trampas inesperadas del sistema es valioso.
@ pjc50 Estoy totalmente de acuerdo; No puedo pensar en ningún proyecto que haya hecho en las últimas dos décadas en el que no tuviera un depurador en el circuito. (Empecé a finales de los 70, donde el programa estaba en una EPROM separada, no en una EEPROM, y no había depuración en el circuito a menos que quisieras pagarle a Intel $5500 por un ICE-86, no recuerdo si alguien otros vendieron ICE. El suyo tenía un cable que se enchufaba en el zócalo de su microprocesador.) Trabajo principalmente con PIC, y tengo un ICD 3 y un RealICE, este último permite usar la interfaz JTAG integrada en el PIC32.