Normalmente programo PIC en C, generalmente para convertidores de modo conmutado. He oído hablar de varias herramientas y estándares de análisis estático como MISRA C que pueden usarse para ayudar a mejorar la confiabilidad del código. Me gustaría saber más ¿Qué estándares o herramientas pueden ser apropiados para mi contexto?
9
Respuestas:
La validación de código incorporado es complicada, especialmente cuando se trata de partes de recursos limitados como PIC. A menudo no tiene el lujo de codificar en casos de prueba debido a las limitaciones de memoria de la pieza y la programación a menudo "en tiempo real" realizada en este tipo de dispositivos.
Estas son algunas de mis pautas:
Escriba una especificación si no hay una: si no está codificando contra una especificación, documente qué se supone que debe hacer su código, cuáles son las entradas válidas, cuáles son las salidas esperadas, cuánto tiempo debe tomar cada rutina, qué puede y qué no puede obtener clobbered, etc. - una teoría de operación, diagramas de flujo, cualquier cosa es mejor que nada.
Comente su código: el hecho de que algo sea obvio para usted no significa que sea obvio (o correcto) para otra persona. Los comentarios en lenguaje sencillo son necesarios tanto para la revisión como para el mantenimiento del código.
Código defensivo: no solo incluya código para entradas normales. Maneje las entradas que faltan, las entradas que están fuera del rango, los desbordamientos matemáticos, etc. - Cuantas más esquinas cubra el diseño de su código, menos grados de libertad tendrá el código cuando se implemente.
Use herramientas de análisis estático: puede ser humillante la cantidad de errores que las herramientas como PC-lint pueden encontrar en su código. Considere una ejecución de análisis estático limpio como un buen punto de partida para pruebas serias.
Las revisiones por pares son esenciales: su código debe estar lo suficientemente limpio y bien documentado para que una parte independiente pueda revisarlo de manera eficiente. Revise su ego en la puerta y considere seriamente cualquier crítica o sugerencia hecha.
La prueba es esencial: debe hacer su propia validación, así como tener una validación independiente del código. Otros pueden descifrar su código de formas que posiblemente no pueda imaginar. Pruebe cada condición válida y cada condición inválida que pueda imaginar. Use los PRNG y alimente los datos basura. Haga lo que pueda para romper cosas, luego repare e intente nuevamente. Si tiene suerte, podrá ejecutar su código en modo de depuración y echar un vistazo a los registros y las variables; de lo contrario, deberá ser astuto y alternar LED / señales digitales para tener una idea del estado de su dispositivo. Haga lo que sea necesario para obtener los comentarios que necesita.
Mire debajo del capó: no tenga miedo de mirar el código de máquina generado por su compilador de C. Puede (¿encontrará?) Encontrar lugares donde su hermoso código C se ha convertido en decenas, si no cientos, de operaciones, donde algo que debería ser seguro (ya que es solo una línea de código, ¿verdad?) Toma tanto tiempo ejecutar múltiples interrupciones han despedido e invalidado las condiciones. Si algo se vuelve terriblemente ineficiente, refactorícelo e intente nuevamente.
fuente
La mayoría de las mismas técnicas para crear software confiable en una PC también son aplicables al desarrollo integrado. Es útil separar sus algoritmos del código específico del hardware y probarlos por separado con pruebas unitarias, simulaciones, análisis estático y herramientas como Valgrind. De esa manera, hay mucho menos código que solo se prueba en el hardware.
No abandonaría C. Aunque los idiomas como Ada pueden ofrecer algunas garantías menores, es fácil caer en la trampa de pensar que el idioma promete más de lo que realmente hace.
fuente
MISRA-C es realmente muy útil para mejorar la calidad del código general y minimizar los errores. Solo asegúrese de leer y comprender cada regla, la mayoría de ellas son buenas, pero algunas de ellas no tienen ningún sentido.
Una advertencia aquí. El documento MISRA supone que el lector es alguien con un amplio conocimiento del lenguaje C. Si no tiene un veterano C tan duro en su equipo, pero decide obtener un analizador estático y luego sigue ciegamente cada advertencia dada, lo más probable es que resulte en un código de menor calidad , ya que podría estar reduciendo la legibilidad e introducir errores por accidente. He visto que esto sucede muchas veces, convertir el código al cumplimiento de MISRA no es una tarea trivial.
Hay dos versiones del documento MISRA-C que pueden aplicarse. O bien MISRA-C: 2004, que sigue siendo el estándar de facto integrado de la industria actual. O el nuevo MISRA-C: 2012 que admite el estándar C99. Si nunca ha usado MISRA-C antes, le recomendaría que implemente el último.
Sin embargo, tenga en cuenta que los proveedores de herramientas generalmente se refieren a MISRA-C: 2004 cuando dicen que tienen una verificación de MISRA (a veces incluso se refieren a la versión obsoleta de MISRA-C: 1998). Hasta donde yo sé, el soporte de herramientas para MISRA-C: 2012 todavía es limitado. Creo que solo algunos analizadores estáticos lo han implementado hasta ahora: Klocwork, LDRA, PRQA y Polyspace. Podría ser más, pero definitivamente debe verificar qué versión de MISRA admite.
Antes de decidir, por supuesto, puede comenzar leyendo el documento MISRA y ver qué implica. Se puede comprar por £ 10 en misra.org , bastante asequible en comparación con los precios de las normas ISO.
fuente
Mathworks (la gente de MATLAB) tiene una herramienta de análisis de código estático llamada Polyspace .
Además del análisis de código estático, pelusa y similares, sugeriría una definición y diseño cuidadosos de las interfaces (con un proceso de revisión formal) y un análisis de cobertura de código.
También puede consultar las pautas para el diseño de códigos críticos para la seguridad, incluidos MISRA, pero también los estándares UL1998 e IEC 61508.
fuente
Para obtener una respuesta completa a esta pregunta, suprimiría el pensamiento sobre la "confiabilidad del código" y en su lugar pensaría en la "confiabilidad del diseño", porque el código es solo la expresión final del diseño.
Entonces, comience con los requisitos y escriba e inspeccione esos. Si no tiene un documento de requisitos, señale una línea de código aleatoria y pregúntese "¿por qué se necesita esa línea?" La necesidad de cualquier línea de código eventualmente debería ser rastreable a un requisito, incluso si es tan simple / obvio como "la fuente de alimentación emitirá 5VDC si la entrada está entre 12-36VDC". Una forma de pensar en esto es que si esa línea de código no se puede rastrear hasta un requisito, entonces, ¿cómo sabe que es el código correcto o que es necesario?
A continuación, verifique su diseño. Está bien si está completamente en el código (por ejemplo, en los comentarios), pero eso hace que sea más difícil saber si el código está haciendo lo que realmente significa. Por ejemplo, el código puede tener una línea que dice
output = 3 * setpoint / (4 - (current * 5));
¿Escurrent == 4/5
una entrada válida que podría causar un bloqueo? ¿Qué se debe hacer en este caso para evitar la división por cero? ¿Evita la operación por completo o degrada la salida en su lugar? Tener una nota general en su documento de diseño sobre cómo manejar estos casos extremos hace que sea mucho más fácil verificar el diseño a un nivel superior. Entonces, ahora la inspección del código es más fácil porque se trata de verificar si el código implementa ese diseño correctamente.Junto con eso, la inspección del código debe verificar si hay errores comunes que su IDE no detecta (está utilizando un IDE, ¿verdad?) Como '=' cuando quiso decir '==', faltan llaves que cambian el significado de 'if 'declaraciones, punto y coma donde no deberían estar, etc.
Mientras escribo esto, se me ocurre que es realmente difícil resumir años de capacitación / experiencia en calidad de software en una sola publicación. Escribo código para dispositivos médicos y lo anterior es un resumen extremadamente simplificado de cómo lo abordamos.
fuente