Atmega4809 USART asíncrono no activa la interrupción de registro de datos vacío - error iom4809.h

0

TLDR ATmega4809, ISR mal etiquetado en iom4809.h. ¿Cómo puedo definir un ISR sin usar estos valores predefinidos mal etiquetados de iom4809?

Utilizando la placa de evaluación ATmega4809 Xplained Pro, estoy configurando la transmisión asíncrona de USART, usando el registro de datos de interrupción en vacío para enviar siempre el siguiente byte disponible. Si no hay más bytes para enviar, deshabilito la interrupción. Estoy usando el proyecto USART de ejemplo de MicroChip, directamente del generador de proyectos de Atmel Studio.

/* Interrupt service routine for Data Register Empty */
ISR(USART1_DRE_vect)
{
     // I need to handle this interrupt.
} 


int8_t USART_0_init()
{

    USART1.BAUD = (uint16_t)USART1_BAUD_RATE(9600); /* set baud rate register */

    USART1.CTRLA = 0 << USART_ABEIE_bp    /* Auto-baud Error Interrupt Enable: disabled */
                   | 0 << USART_DREIE_bp  /* Data Register Empty Interrupt Enable: disabled */
                   | 0 << USART_LBME_bp   /* Loop-back Mode Enable: disabled */
                   | USART_RS485_OFF_gc   /* RS485 Mode disabled */
                   | 0 << USART_RXCIE_bp  /* Receive Complete Interrupt Enable: enabled */
                   | 0 << USART_RXSIE_bp  /* Receiver Start Frame Interrupt Enable: disabled */
                   | 0 << USART_TXCIE_bp; /* Transmit Complete Interrupt Enable: disabled */

    USART1.CTRLB = 0 << USART_MPCM_bp       /* Multi-processor Communication Mode: disabled */
                   | 0 << USART_ODME_bp     /* Open Drain Mode Enable: disabled */
                   | 0 << USART_RXEN_bp     /* Reciever enable: disabled */
                   | USART_RXMODE_NORMAL_gc /* Normal mode */
                   | 0 << USART_SFDEN_bp    /* Start Frame Detection Enable: disabled */
                   | 1 << USART_TXEN_bp;    /* Transmitter Enable: enabled */

    USART1.CTRLC = USART_CMODE_ASYNCHRONOUS_gc /* Asynchronous Mode */
             | USART_CHSIZE_8BIT_gc /* Character size: 8 bit */
             | USART_PMODE_DISABLED_gc /* No Parity */
             | USART_SBMODE_1BIT_gc; /* 1 stop bit */
}

No importa lo que haya intentado, parece que no pude hacer que el registro de datos esté vacío. Me di cuenta de que había una incoherencia entre la hoja de datos y la biblioteca que define el vector de interrupción.

De la hoja de datos 4809:

  

26 0x1A 0x34 USART1 - Recepción completa

     

27 0x1B 0x36 USART1 - Registro de datos vacío

     

28 0x1C 0x38 USART1 - Transmisión completa

Desde iom4809.h

¡Esto no coincide! Es la interrupción número 27 en la hoja de datos y la interrupción número 26 en la biblioteca iom4809.

#define USART1_DRE_vect_num  26
#define USART1_DRE_vect      _VECTOR(26)
#define USART1_RXC_vect_num  27
#define USART1_RXC_vect      _VECTOR(27)
#define USART1_TXC_vect_num  28
#define USART1_TXC_vect      _VECTOR(28)

¿Cómo puedo definir un ISR sin usar estos valores predefinidos mal etiquetados de iom4809?

    
pregunta Scampbell

1 respuesta

2

Actualización: hay un paquete de dispositivos en Atmel Studio para reparar la biblioteca iom4809.h.

  

Actualice ATmega DFP desde el administrador de paquetes disponible desde Studio:   Herramientas - > Administrador de paquetes de dispositivos.

     

En caso de que obtenga un error de tiempo de espera al instalar los paquetes desde   Estudio: Herramientas - > Device Pack Manager, los paquetes de dispositivos pueden ser directamente   descargado de enlace

     

Una vez descargado el paquete requerido, haga doble clic en el archivo atpack para   abrir e instalar el mismo.

Lo único que hacen estas macros es definir una ubicación vectorial desde un número hasta _VECTOR ().

Puede hacerlo con un estilo de "pirateo rápido", simplemente insertando _VECTOR (27) en su ISR y etiquetándolo como / * Este es un hotfix, ya que el vector DRE está mal etiquetado en la biblioteca ASF, 27 es DRE. * /.

Eso se consideraría "Codificación de número mágico", que es esencialmente una mala práctica, pero para una prueba rápida es una opción.

Pero, también puedes hacerlo más inteligente y limpio, puedes no definir una constante usando #undef.

También puedes verificar los valores con #if.

Para comenzar simple, puedes escribir:

#if (USART1_DRE_vect_num == 26)
  #undef USART1_DRE_vect
  #undef USART1_DRE_vect_num
  #define USART1_DRE_vect_num    27
  #define USART1_DRE_vect        _VECTOR(27)
#endif

Y puedes incluso, para que sea más limpio agregar una comprobación de tipo de dispositivo a su alrededor, hay muchos ejemplos de eso en las propias bibliotecas. Creo que Atmel Studio usa el identificador "DEVICE" o "TARGET" para eso por defecto, pero no estoy en mi laboratorio de desarrollo, por lo que no puedo verificarlo ahora mismo.

Luego, puedes hacer un encabezado completo de "Limpieza" para todos los errores que comprueban si todavía existen en la biblioteca. Quizás también puedas agregar una línea como:

#warning "Overrode a default Atmel identifier as they do not conform to the datasheet"

Luego, si después de una actualización desaparecen las advertencias, sabrá que puede desactivar su encabezado.

Asegúrese de incluir un encabezado de anulación en último lugar, de lo contrario, es posible que su definición no se active, ya que una variable no definida no activa el "== 26".

De hecho, técnicamente, debes agregar defined(USART1_DRE_vect_num) a tu cláusula #if para verificar eso por ti mismo, para que tu código sea universalmente compatible. Pero entonces, es probable que desee revisar más extensamente y agregar más advertencias o errores, porque en ese caso, algo saldrá mal en la línea de todos modos.

Si NO te importa en absoluto la portabilidad de tu proyecto a otras computadoras, también puedes editar el archivo del encabezado, pero te sugiero que intentes evitarlo como cuestión de práctica estándar.

Última nota: Tengo la corazonada de que alguien en algún momento en el futuro dirá algo incomprensiblemente estúpido como "Solo usa el vector con el número correcto". Lo que crea al menos un código mal documentado y es peligroso. Su código se leerá como si estuviera haciendo algo muy tonto en una interrupción nombrada completamente diferente. (Y dejará de funcionar cuando solucionen el error)

¡Oh, y, presenta un informe de error!

Para resumir la "solución alternativa" hasta que MicroChip arregle la biblioteca:

#if (defined(USART1_DRE_vect_num) && USART1_DRE_vect_num == 26)
    #warning "Overrode a default Atmel identifier as they do not conform to the datasheet"
    #undef USART1_DRE_vect
    #undef USART1_DRE_vect_num
    #undef USART1_RXC_vect
    #undef USART1_RXC_vect_num
    // Redefine to vector numbers to match the ATmega4809 datasheet
    #define USART1_DRE_vect_num    27
    #define USART1_DRE_vect        _VECTOR(27)
    #define USART1_RXC_vect_num    26
    #define USART1_RXC_vect        _VECTOR(26)
#endif
    
respondido por el Asmyldof

Lea otras preguntas en las etiquetas