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 se pueden usar para ayudar a mejorar la confiabilidad del código. Me gustaría saber más. ¿Qué estándares o herramientas podrían ser apropiados para mi contexto?
La validación del código integrado es complicada, especialmente cuando se trata de partes de recursos limitados como los PIC. A menudo no puede darse 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" que se realiza 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 lo que 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 golpeado, etc. - una teoría de la operación, diagramas de flujo, cualquier cosa es mejor que nada.
Comenta tu código: el hecho de que algo sea obvio para ti no significa que sea obvio (o correcto) para otra persona. Los comentarios en lenguaje sencillo son necesarios tanto para la revisión como para la mantenibilidad del código.
Codifique a la defensiva: no solo incluya código para entradas normales. Maneje las entradas que faltan, las entradas que están fuera de rango, los desbordamientos matemáticos, etc. Cuantas más esquinas cubra con 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 abrumador la cantidad de errores que las herramientas como PC-lint pueden encontrar en su código. Considere un análisis estático limpio como un buen punto de partida para realizar 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. Deja tu ego en la puerta y considera seriamente cualquier crítica o sugerencia que te haga.
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 maneras que no puede imaginar. Pruebe todas las condiciones válidas y todas las condiciones no válidas que se le ocurran. Use PRNG y alimente datos basura. Haga todo lo que pueda para romper las cosas, luego repárelas e inténtelo de nuevo. Si tiene suerte, podrá ejecutar su código en modo de depuración y echar un vistazo a los registros y variables; si no, deberá ser astuto y alternar LED/señales digitales para tener una idea del estado de su dispositivo. Haz lo que sea necesario para obtener la retroalimentación que necesitas.
Mire debajo del capó: no tenga miedo de mirar el código de máquina generado por su compilador de C. Es posible que encuentre (¿encontrará?) lugares donde su hermoso código C se ha disparado 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?) tarda tanto en ejecutarse que múltiples interrupciones han despedido e invalidado las condiciones. Si algo se vuelve terriblemente ineficiente, refactorícelo y vuelva a intentarlo.
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. Si bien los lenguajes como Ada pueden ofrecer algunas garantías menores, es fácil caer en la trampa de pensar que el lenguaje promete más de lo que realmente hace.
MISRA-C es de hecho muy útil para mejorar la calidad general del código y minimizar errores. Solo asegúrese de leer y comprender todas las reglas, la mayoría de ellas son buenas, pero algunas no tienen ningún sentido.
Una advertencia aquí. El documento MISRA asume que el lector es alguien con un amplio conocimiento del lenguaje C. Si no tiene un veterano de C tan endurecido en su equipo, pero decide obtener un analizador estático y luego seguir ciegamente todas las advertencias dadas, lo más probable es que resulte en un código de menor calidad , ya que podría estar reduciendo la legibilidad e introduciendo 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 se pueden aplicar. MISRA-C:2004, que sigue siendo el estándar de facto de la industria integrada actual. O el nuevo MISRA-C:2012 que soporta el estándar C99. Si nunca antes ha usado MISRA-C, le recomiendo que implemente este último.
Sin embargo, tenga en cuenta que los proveedores de herramientas generalmente se refieren a MISRA-C:2004 cuando dicen que tienen 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 aún es limitado. Creo que solo algunos analizadores estáticos lo han implementado hasta ahora: Klocwork, LDRA, PRQA y Polyspace. Puede ser más, pero definitivamente necesita verificar qué versión de MISRA admite.
Antes de decidir, por supuesto, puede comenzar leyendo el documento MISRA y ver lo que implica. Se puede comprar por £ 10 en misra.org , bastante asequible en comparación con los precios de las normas ISO.
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, lint y similares, sugeriría una definición y un diseño cuidadosos de las interfaces (con un proceso de revisión formal) y un análisis de cobertura de código.
También es posible que desee consultar las pautas para el diseño de códigos críticos para la seguridad, incluido MISRA, pero también los estándares UL1998 e IEC 61508.
Para obtener una respuesta completa a esta pregunta, suprimiría la idea de "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 escríbalos e inspecciónelos. 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 debe ser finalmente atribuible a un requisito, incluso si es tan simple/obvio como "la fuente de alimentación generará 5 V CC si la entrada está entre 12 y 36 V CC". 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 se supone. Por ejemplo, el código puede tener una línea que dice output = 3 * setpoint / (4 - (current * 5));
¿Es current == 4/5
una entrada válida que podría provocar 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 en 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 correctamente ese diseño.
Junto con eso, la inspección del código debe verificar si hay errores comunes que su IDE no detecta (usted está usando un IDE, ¿verdad?) ' 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.
usuario_1818839
Esteban Collings
usuario_1818839
usuario_1818839
Lundin