Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
9 years, 6 months ago.
STM32F401-Serial Interrupt handler with C++ interface not getting called
Hello,
I am working on STM32F401RE board and using a serial port Serial bt_uart(PA_9, PA_10);
And using the below initialisation
bt_uart.baud(115200);
bt_uart.format(8, Serial::Even, 1);
bt_uart.attach(&UART_RX_IRQHandler,Serial::RxIrq);
With the above C++ initialisation my Interrupt handler is never getting called.
However when I tried using the C interface as below (from the standard serial_api.c) my interrupt handler is called,
serial_t test;
SerialParity x=ParityEven;
SerialIrq z=RxIrq;
serial_init(&test,PA_9,PA_10);
serial_baud(&test,115200);
serial_format(&test,8,x,1);
serial_irq_handler(&test,UART_RX_IRQHandler,1);
serial_irq_set(&test,z,1);
I want to use the standard C++ API interface due to project needs and not C API. Does the C++ interface has some problem ?
-ykd
2 Answers
9 years, 6 months ago.
When using RTOS the serial IRQ will block indefinately on getc(), locking your program. This is because it uses stdio, which places a mutex on getc/putc, which is not allowed within interrupt context.
The solution to this is using RawSerial, which is (almost) the same as Serial, but does not use stdio, thereby circumventing those mutexes.
Hi Erik, thanks for your inputs. yes i tried with RawSerial but the result is the same. My Rx interrupt handler is never called. As you suggested i changed Serial to RawSerial as below when I declare the object.
So now instead of Serial bt_uart(PA_9, PA_10);
I now have RawSerial bt_uart(PA_9, PA_10);
Hope I have understood you correctly. Is there any other change that i must do along with this ?
Regards Ykd
posted by 23 Jun 2015Hi Erik, UART_Rx_IRQHandler() is as below. It reads a byte.
void UART_RX_IRQHandler(void)
{
pc.printf(" In ...UART_RX_IRQHandler\n");
if(bt_uart.readable())
{
uint8_t byte = bt_uart.getc();
if (byte == 0xC0)
{
if(rx_frame == 0)
{
rx_frame = 1;
}
else if(rx_frame == 1)
{
rx_frame = 2;
}
}
}
}
posted by 23 Jun 20159 years, 6 months ago.
Hi Yogesh,
How do you know that your interrupt handler is never called? Maybe it is called and then hangs somewhere inside?
Try your UART_RX_IRQHandler like this:
very simple IRQ routine
... uint8_t rx_byte; ... void UART_RX_IRQHandler(void) { rx_byte = bt_uart.getc(); }
and then output rx_byte outside UART_RX_IRQHandler() using printf. Check if this works, i.e. if received character is printed.
- If yes, expand your IRQHandler line-by-line and check where the problem occurs.
- If no, then program probably doesn't enter the IRQHandler(). :( Then it would be good if you can post your C++ code, at least the basic things you wrote regarding serial port operations.
Regards, Miloje
i tried as you said , but rx_byte is not getting any data. I can say it is never called because with serial_api.c interface it works fine and i got the print statement always coming inside the ISR . With C++ interface code it did not work (even with rawSerial). I will post my C++ code related to serial port settings below.
RawSerial bt_uart(PA_9, PA_10);
static uint8_t rx_frame = 0;
static uint16_t rx_frame_count = 0;
void UartInit(void) {
bt_uart.baud(115200); 115200
bt_uart.format(8, Serial::Even, 1);
bt_uart.attach(&UART_RX_IRQHandler,Serial::RxIrq); Interrupt callback func
printf("UART init OK\n");
}
void Tx_Data_send(void) {
uint8_t i=0;
uint8_t CmdBuffer[10] = {0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA};
for (i = 0; i < 10; i++) {
while(bt_uart.writeable() == 0) {}
bt_uart.putc(CmdBuffer[i]);
}
}
void UART_RX_IRQHandler(void)
{
static uint8_t isRxBufferFull = 0; if(bt_uart.readable() && (isRxBufferFull == 0))
{ uint8_t byte = bt_uart.getc();
/* Token detector */ if (byte == 0xC0)
{
if(rx_frame == 0) {
rx_frame = 1;
} else if(rx_frame == 1) { rx_frame = 2;
}
} rx_frame_count++;
if (rx_frame_count >= UART_RX_BUFFER_SIZE)
{
isRxBufferFull = 1;
}
if (rx_frame == 2)
{ rx_frame_count = 0; rx_frame = 0; }
}
}
Sorry for the brackets (the code is not looking properly indented after i pasted it here) but I tried to be as clear as possible . I will try with another hardware and see if the problem occurs.
posted by 25 Jun 2015Hi Yogesh,
Just a small hint - when you post some code, use word "code" within << >> to format it in a more readable way (in a right bottom corner of message window there is "Editing tips" help).
Code from Yogesh
RawSerial bt_uart(PA_9, PA_10); static uint8_t rx_frame = 0; static uint16_t rx_frame_count = 0; void UartInit(void) { bt_uart.baud(115200); // 115200 bt_uart.format(8, Serial::Even, 1); bt_uart.attach(&UART_RX_IRQHandler,Serial::RxIrq); //Interrupt callback func printf("UART init OK\n"); } void Tx_Data_send(void) { uint8_t i = 0; uint8_t CmdBuffer[10] = {0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA}; for (i = 0; i < 10; i++) { while(bt_uart.writeable() == 0) {} bt_uart.putc(CmdBuffer[i]); } } void UART_RX_IRQHandler(void) { static uint8_t isRxBufferFull = 0; if(bt_uart.readable() && (isRxBufferFull == 0)) { uint8_t byte = bt_uart.getc(); /* Token detector */ if (byte == 0xC0) { if(rx_frame == 0) { rx_frame = 1; } else if(rx_frame == 1) { rx_frame = 2; } } rx_frame_count++; if (rx_frame_count >= UART_RX_BUFFER_SIZE) { isRxBufferFull = 1; } if (rx_frame == 2) { rx_frame_count = 0; rx_frame = 0; } } }
Try to write very simple program to test if C++ api is a problem. Something similar like the code you posted and execute it without RTOS - just initialize uart, attach IRQHandler and see if it works.
posted by 25 Jun 2015
Are you using RTOS also or other relevant code?
posted by Erik - 22 Jun 2015Yes RTOS is used (RTX rtos).
posted by yogesh kulkarni 22 Jun 2015