6 years, 6 months ago.

serial interface TX interrupt problem

Hi,

I used the following code snippets to communicate via serial Rx and Tx interrupts:

Serial stComX(D1,D0); /* UART - communication (Txd(D1)/Rxd(D0)) to PC virtual COM-Port */

void vIsrRxComX( void ){ /* Rx-ISR */ if(stComX.readable()){ ... receive one byte } }

void vIsrTxComX( void ){ /* Tx-ISR */ if(stComX.writeable()){ .... send the next byte } }

int main(){

/* initialisation of the interrupt service routines */ stComX.attach(&vIsrRxComX, Serial::RxIrq); /* (1) ISR for Rx-Data */ stComX.attach(&vIsrTxComX, Serial::TxIrq); /* (2) ISR for Tx-Data */ .... }

The software was established two years ago and works well. But with the newest compiler version I have to comment the line "stComX.attach(&vIsrTxComX, Serial::TxIrq);" If I activate the TxIrq the software project crashes immediatly. If I don't use the TxIrq I cannot send in the ISR, but the other software parts works well.

I have no idea where the problem is. The problem occurs only when I put the unchanged older software source files into an new project.

It would be great if anyone could give me a hint.

Best regards,

Jens

1 Answer

6 years, 6 months ago.

Hello Jens,

The code below worked with a NUCLEO-F103RB using the latest mbed library :

#include "mbed.h"

DigitalOut  led1(LED1);
Serial      stComX(D1,D0); /* USART2 - communication (Txd(D1)/Rxd(D0)) to PC virtual COM-Port */

void vIsrRxComX( void ){ /* Rx-ISR */ 
    if (stComX.readable()) { 
        /*... receive one byte*/ 
    } 
}

void vIsrTxComX( void ){ /* Tx-ISR */ 
    if (stComX.writeable()){
        /* .... send the next byte*/
        stComX.putc('A');
    }
    NVIC_DisableIRQ(USART2_IRQn);   // prevent recursive Tx-ISR
}

int main(){
    /* initialisation of the interrupt service routines */ 
    stComX.attach(&vIsrRxComX, Serial::RxIrq); /* (1) ISR for Rx-Data */ 
    stComX.attach(&vIsrTxComX, Serial::TxIrq); /* (2) ISR for Tx-Data */
    
    while(1) {
        NVIC_EnableIRQ(USART2_IRQn);
        led1 = !led1;
        wait(1.0);
    }
}

Dear Zoltan,

I made some tests how the Serial API interrupts works. You suggest to lock/unlock the TXE interrupt bit, that works well. In my opinion, the TC bit should be used. In comercial projekt I work with Rowley Crossworks and I use the TC interrupt bit. The resulting code is easy and stable. The interrupt occurs if the transmission is complete. As well as no transmission is pending, no interrupt will be generated. /media/uploads/prof_al/rowley_int.jpg

I cannot understand why the Mbed library uses the TXE bit. The TXEIE bit has to be edited every time. That's a lot more complicated than using the TC flag, isn't it? This must be a bug in the library, especially since in earlier versions the use of send and receive interrupts has been easier. Thanks again for your suggestions and ideas. This allows me to program a workaround for my students.

Best regards,

Jens

posted by Jens Altenburg 17 Nov 2017

Hello Jens,

I'm sorry for suggesting to use NVIC_EnableIRQ(USART2_IRQn) and NVIC_DisableIRQ(USART2_IRQn). A better solution is to keep receive interrupts enabled as below:

Enable Tx interrupts

...
//NVIC_EnableIRQ(USART2_IRQn);
USART2->CR1 |= USART_CR1_TXEIE;
...

Disable Tx interrupts

...
//NVIC_DisableIRQ(USART2_IRQn);
USART2->CR1 &= ~USART_CR1_TXEIE;
...

With best regards, Zoltan.

posted by Zoltan Hudak 17 Nov 2017