Esto es más bien una entrada del blog, pero ahí va:
Si escribes en C, puedes compilar tu código y ejecutarlo en tu escritorio. Esto no probará los controladores de hardware de bajo nivel, pero puede probar todo el código lógico.
Recomendaciones sobre este enfoque:
- Si estás en ARM, puedes usar el mismo compilador (gcc) para ambos propósitos. Entonces cualquier extensión específica del compilador seguirá funcionando.
- Pero las extensiones específicas del compilador no son deseables, así que podrías compilar la versión de escritorio con Clang/LLVM en su lugar (con el beneficio de mejores mensajes de error).
- Mi escritorio es un PC con Linux. Nada de este enfoque es específico de Linux. Pero Linux es un buen entorno de desarrollo en C.
- Utilice
stdint.h
y tipos como uint64_t
en lugar de " unsigned long int
". Esto le permite obtener el mismo comportamiento cuando se compila en diferentes sistemas.
- Pero cuidado con la promoción integral de C's. Si es posible (está en ARM) utiliza un PC de 32 bits para probar el código ARM de 32 bits.
- En cuanto a los controladores de hardware, he encontrado dos enfoques beneficiosos.
- Haz un prototipo en vivo en el PC. El PC tiene un reloj en tiempo real y una conexión de red, así como una pantalla y entradas, por lo que todo eso está resuelto. (Mi PC tiene incluso un acelerómetro.) Puedes usar libSDL para animar una imagen de tu producto final y recibir las pulsaciones de las teclas. Para otras funciones de tu placa conecta placas de desarrollo, o finge. La ventaja de este enfoque es que puedes usarlo en el sistema en vivo y ahorrarte la molestia de hacer hardware si encuentras que no resuelve el problema que necesitas resolver.
- Haz un prototipo muerto que lea los eventos de entrada de un archivo y escriba los eventos de salida en un archivo. Ahora, para las pruebas, puedes grabar (o sintetizar) eventos que correspondan a escenarios específicos que quieras probar. Y entonces puedes verificar que las cosas correctas se escriben en la salida. La ventaja de esto es que deja una suite de pruebas automatizada completa que puedes ejecutar en tiempo de construcción para detectar regresiones.
- Utiliza las opciones del compilador -Wall -Wextra -Werror y mantén tu código libre de advertencias. Pasarás algo de tiempo Parcheando las advertencias, pero hace que la codificación sea más rápida al reducir el tiempo de depuración.
- Compilar la versión para PC con guardabarros . Esto atrapa muchas travesuras de los punteros. Algunas personas recomiendan Valgrind, pero no es tan útil para el código que nunca utiliza
malloc()
o free()
.
- Para la depuración en el PC, utilice GDB o DDD o
printf()
al gusto. Existe una gran variedad de herramientas de depuración de escritorio maduras y útiles.
- Incluso si no hago la configuración completa de depuración en el PC, a menudo incluiré una prueba de unidad
main()
al final de un archivo que es #define
se ha ido. Este main()
intenta cualquier función complicada en el archivo y devuelve 0 para todos los pases o asserts()
para fallar. Luego añado un objetivo "test" en el makefile que compila y ejecuta cada una de las pruebas de los archivos individuales.
- Hay muchas plataformas de pruebas unitarias que puedes utilizar. Hay muchas porque son muy fáciles de escribir. Yo no las uso. No quiero un bonito informe de "porcentaje de pruebas superadas". Quiero que mi prueba muera al primer fallo. Visual Basic solía tener una característica irrisoria llamada ' en caso de error, reanudar el siguiente '. No sé por qué querrías esa función para las pruebas unitarias.
Si haces pruebas unitarias independientes de esta manera, encontrarás que tienes muy poca necesidad de depuración en el chip. Además, encontrarás que la portabilidad a diferentes plataformas de hardware es mucho más fácil porque la lógica del núcleo y los controladores de hardware están bien separados.