¿Cómo puedo registrar información del código en IAR Embedded Workbench en un archivo de registro?

Estoy tratando de desarrollar una aplicación para el microcontrolador NXP LPC1788 y me gustaría poder registrar cadenas formateadas en puntos arbitrarios dentro del código fuente en un archivo de registro de una manera que tenga un impacto insignificante en el rendimiento del programa. Esencialmente, me gustaría algo lo más parecido posible a las utilidades Logger que obtienes con Java.

Actualmente, estoy usando un depurador iJet y con eso puedo imprimir valores numéricos individuales de 8 o 32 bits en la ventana de eventos IAR EW usando ITM_EVENT8_WITH_PCy ITM_EVENT32_WITH_PC, junto con el contador del programa y la marca de tiempo. Sin embargo, los números por sí solos no son lo suficientemente descriptivos y estoy limitado a cuatro canales. Esto significa que a menudo tengo que elegir una pequeña parte del programa para iniciar sesión en cualquier momento, comentando las llamadas en ITM_EVENT...partes no relacionadas y agregando otras nuevas o descomentando las existentes en la parte que quiero monitorear de cerca. Esto no es realmente un enfoque muy eficiente.

Una cosa que he intentado investigar es crear un archivo de macro que contenga una función que tome una cadena como parámetro y la pase a la macro LogMessageintegrada . __messageSin embargo, no estoy seguro de cómo puedo incluir esta macro en el programa para poder invocarla LogMessagedentro del código fuente. Intenté especificarla en Debugger -> Setup Macros, pero esto no se vincula LogMessagecon el código fuente.

Cualquier ayuda sería apreciada.

EDITAR

Cómo se hace en Java

Para dar un ejemplo de cómo se puede usar el marco Logger (específicamente de la variedad SLF4J) en Java, tomaré el del manual SLF4J y explicaré lo que está sucediendo:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HelloWorld {
  public static void main(String[] args) {
    Logger logger = LoggerFactory.getLogger(HelloWorld.class);
    logger.info("Hello World");
  }
}

En este caso, estamos creando una clase con un mainmétodo estático que sirve como punto de entrada a la aplicación. Luego, llamamos a un método de fábrica getLoggerpara producir un objeto de registro que hacemos consciente de la clase en la que lo instanciamos: HelloWorld.class. Esta información se puede configurar para que se incluya en las salidas de registro.

Luego podemos usar este objeto de registro para producir registros de diferentes niveles de registro según la importancia y la naturaleza de lo que estamos registrando. En el ejemplo, generamos "Hello World" en el INFOnivel de registro, que se usa para registrar información relativamente importante, y el marco de registro tratará esa salida de manera adecuada en función de su nivel de registro y la configuración del marco; esto puede incluir enviarlo a stdout o guardarlo en un archivo.

como me gustaria hacerlo

Sería bueno si pudiera obtener algo similar trabajando con las aplicaciones IAR Embedded Workbench. Discutí el problema con un colega y descubrí que podíamos enrutar datos desde los puertos de estímulo ITM a la ventana Terminal IO a través de I-jet/JTAGjet -> SWO Configuration...la barra de menú en la parte superior y luego registrar la ventana Terminal I/O. Puede iniciar sesión directamente desde los puertos ITM a un archivo de registro, pero parece que sobrescribe el archivo cada vez que escribe un nuevo valor en un puerto ITM por algún motivo.

Lo que estoy experimentando ahora es crear un método como logData(uint16_t logId, uint8_t logLevel, uint32_t value), que hará que los datos se guarden en un archivo de registro de una manera particular:

  • logId es un identificador que es único para cada mensaje de registro
  • logLevel será análogo a los niveles de registro en SLF4J (y eventualmente debería reemplazarse con una enumeración)
  • valor es un valor único para asociar con el mensaje de registro (y eventualmente debe reemplazarse con un parámetro variable, para aceptar cualquier número de valores)

El archivo de registro producido no es legible, pero podría armar una secuencia de comandos de Python que tomará el archivo de registro generado y producirá uno legible por humanos con un buen formato en el mismo estilo que un archivo de registro SLF4J.

Al menos esa es la idea.

EDITAR 2

Reuní lo que se siente como un marco de registro lo suficientemente decente para mis requisitos, aunque aún no he intentado usarlo ampliamente para ver cómo resiste bajo presión.

En el método de mi aplicación de microcontrolador main, puedo hacer una llamada como LOGGER_Init(LOG_LEVEL_DEBUG, 5);, donde el primer argumento es el nivel de registro del registrador y el segundo argumento es el puerto de estímulo ITM para imprimir los datos de registro. El registrador solo imprimirá mensajes de registro con un nivel de registro igual o superior al suyo (p. ej., un registrador configurado en LOG_LEVEL_INFOimprimirá LOG_LEVEL_WARNmensajes y LOG_LEVEL_INFOmensajes pero no LOG_LEVEL_DEBUGmensajes).

Entonces puedo registrar datos de la siguiente manera:

LOGGER_Info(0x1, 0x20);
LOGGER_Debug(0x2, 0x3A, 0xFF);

Estos métodos tratan el primer valor como un identificador de registro y los argumentos restantes se tratan de forma variable como datos de registro.

En un archivo de 'mapa de registro', mantengo una asignación de identificadores de registro a mensajes de salida de registro de marcador de posición, donde '{}' representa un valor de marcador de posición como en SLF4J:

static const LOG_MAP_T logMappings[] = {
  {1, "The first log message in main provides {}"},
  {2, "The second log message provides {} and also {}"}
};

El registrador imprime mensajes de registro de los niveles apropiados al puerto de estímulo ITM configurado, que luego lo envía a través de la ventana de E/S de la terminal donde se guarda en un archivo de registro.

Luego tengo un script de Python que pasa por las salidas de registro y el archivo de mapeo y une todo para producir algo como esto:

>>> 
INFO  The first log message in main provides 32
DEBUG The second log message provides 58 and also 255
¿Puede usar las funciones de E/S estándar con la ventana de E/S de terminal (tenga en cuenta que es posible que tenga que jugar con las opciones de semihospedaje en la configuración del proyecto). ¿Tienes algún puerto serie disponible? Con 176x, generalmente tengo UART0 como puerto de depuración, porque usa los mismos pines que la interfaz ISP. Probablemente debería agregar un pequeño ejemplo de código sobre cómo usaría esto, ya que es posible que las personas no estén familiarizadas con Logger de Java (incluido yo).
@user694733 Hola, tengo semihosting configurado pero es muy lento. Sin embargo, analicé el problema con un colega y descubrimos que podíamos enrutar datos desde los puertos ITM a la ventana de E/S de la terminal (página 10: iar.com/Global/Resources/Developers_Toolbox/… ), y luego registrar la Terminal ventana de E/S. Es posible guardar datos de los puertos ITM directamente en un archivo de registro, pero me doy cuenta de que esto no funciona muy bien por alguna razón. Actualizaré el OP con un Logger ex.
Esta pregunta es un poco relevante.
@ user694733 Gracias por la información, pero ahora tengo algo funcionando con lo que estoy contento por el momento (ver la última edición). Probaré lo que tengo mañana para asegurarme de que puede mantenerse bajo presión, y si no es así, volveré aquí y daré una mirada más detallada a lo que has vinculado para ver si puede ayudar.
Un muy buen sistema de registro es Segger RTT (Real Time Transfer). Pero requiere un depurador Segger. De todos modos, ¿quizás valga la pena echarle un vistazo?

Respuestas (1)

Le recomendaría que habilite la función ETM del chip LPC que está utilizando. La macrocelda de seguimiento incrustada es esencialmente una ubicación de memoria en la que puede escribir caracteres que se abrirán camino a través de la conexión JTAG/SWD a su EWARM en las ventanas de la terminal (o incluso en el complemento de Eclipse).

Simplemente puede escribir una macro para escribir los caracteres directamente en la dirección de memoria, o puede usar lo que IAR llama "modo de host", creo que piratean su salida estándar y lo hacen por usted. Luego, simplemente use printf de cualquier envoltorio que desee.

Busque la nota de aplicación en su sitio e ignore todas las capacidades de seguimiento sofisticadas que proporciona ETM (si no las necesita) y solo busque las cosas de salida de depuración.

Si está en mantenimiento, llame a la oficina de IAR más cercana y solicite un FAE y lo guiarán.