This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

uart irq_handler

Hi everyone.
I've got a problem using the UART irq_Handler.

I'm working with an STM32E ev board and i want to receive data from an AHRS throught the COM port.
I've to manage a message of many bytes and i need to use an UART interrupt handler to pass charater to a task that will collect all the bytes of the mesage and then, when complete, send it to another task.
The problem is that i never get into the UART IRQ_Handler routine and i cannot understand why.

Here is the code:

/*----- Usart Interrupt Service routine----- */

void USART2_IRQHandler(void)
{
    char *char_ptr;
    char char_rec;

     _init_box(charpool,sizeof(charpool),sizeof(U32));

     while(1){
        os_mbx_init(MsgBoxA,sizeof(MsgBoxA));
        char_ptr = _alloc_box(charpool);
        char_rec = getkey();
        char_ptr = &char_rec;
        os_mbx_send(MsgBoxA,char_ptr,0xffff);
        GLCD_displayStringLn(Line4, "  Get some  ");
        }
}
/*----------------------------------------------------------------------------
*   Task getAhrs: receive the character, then switch the state of the machine and collect the
*                  payload character in a buffer to send to the manage task
*---------------------------------------------------------------------------*/

__task void getAhrs(void){

        char *car_rec;
        U32 *buf_ptr;

        os_mbx_init(MsgBoxB,sizeof(MsgBoxB));              /*init the mailbox B */

        GLCD_displayStringLn(Line3, "In the task get");

        while(1){
                switch (buf_count){
                        case 0: buf_ptr = _alloc_box(bufpool_0);        /*memory allocation */
                                        break;
                        case 1: buf_ptr = _alloc_box(bufpool_1);
                                        break;
                        case 2: buf_ptr = _alloc_box(bufpool_2);
                                        break;
                        }

                os_mbx_wait(MsgBoxA,(void**)&car_rec,0xffff);                  /*receive the
                                                                             mailbox from the
                                                                                 IRQ_hanlder*/
                current_char = *car_rec;

The code then goes on managing the character and colecting it into a buffer pointed by buf_ptr.

When I ebug it I get o errors, but, using the breakpoints i can see that it never step into the IRQ_Hanler.

A clarification:

I set up the UART in the starter task that is as follow:

/*----------------------------------------------------------------------------
 *   Task starter:  init and configure the UART and create all the tasks
 *---------------------------------------------------------------------------*/
__task void starter (void){

        USART_InitStructure.USART_BaudRate = 115200;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
        USART_InitStructure.USART_Parity = USART_Parity_No;
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        USART_InitStructure.USART_Mode = USART_Mode_Rx;

  /* Configure USART2 */
        USART_Init(USART2, &USART_InitStructure);

        USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); /* enable usart2 receive interrupt*/
        USART_Cmd(USART2, ENABLE);

        state = IDLE;           /*state machine in IDLE state */

        _init_box(mpool,sizeof(mpool),sizeof(U32));               /*mailboxes memory spaces */
        _init_box(bufpool_0,sizeof(bufpool_0),sizeof(U32));
        _init_box(bufpool_1,sizeof(bufpool_1),sizeof(U32));
        _init_box(bufpool_2,sizeof(bufpool_2),sizeof(U32));

        GLCD_setBackColor(Green);
        GLCD_setTextColor(Red);

        os_tsk_create(printLCD,1);
        os_tsk_create(manageAhrs,2);
        os_tsk_create(getAhrs,3);

        os_tsk_delete_self();
}

If anyone coul explain me where i wrong... i've also tried to look at some eamples but also them did not work.. It's a problem of my board or maybe i don't set something very important?
Thanks

Parents
  • I think you should throw away the getkey() function, unless you modify it to pick up data from a circular receive buffer filled with data from the UART.

    Your ISR should check the status flag of the UART, so it knows _why_ it gets activated.

    You should let the ISR do the time-critical part - pick up the received character. It can then post this character using a mailbox. No need to post a pointer to a mail. The pointer value can be used as character value.

    Or the ISR should insert the character in a ring buffer, and can then send an event notifying the consumer thread that there are one or more characters available to consume from the ring buffer.

    Have you really looked at any example source code for an UART ISR for your processor? Not only do they check what needs servicing. They also acknowledge the interrupt source (sometimes by reading out the received data, ometimes by setting/clearing a specific bit in a UART register). And depending on processor core, they may need a special keyword to let the compiler produce a different set of enter/leave code compared to a "normal" function. The Cortex chips are an exception. Some other processors may have a specific assembler stub that gets activated first and then calls the ISR, also allowing the ISR to be a standard C function.

Reply
  • I think you should throw away the getkey() function, unless you modify it to pick up data from a circular receive buffer filled with data from the UART.

    Your ISR should check the status flag of the UART, so it knows _why_ it gets activated.

    You should let the ISR do the time-critical part - pick up the received character. It can then post this character using a mailbox. No need to post a pointer to a mail. The pointer value can be used as character value.

    Or the ISR should insert the character in a ring buffer, and can then send an event notifying the consumer thread that there are one or more characters available to consume from the ring buffer.

    Have you really looked at any example source code for an UART ISR for your processor? Not only do they check what needs servicing. They also acknowledge the interrupt source (sometimes by reading out the received data, ometimes by setting/clearing a specific bit in a UART register). And depending on processor core, they may need a special keyword to let the compiler produce a different set of enter/leave code compared to a "normal" function. The Cortex chips are an exception. Some other processors may have a specific assembler stub that gets activated first and then calls the ISR, also allowing the ISR to be a standard C function.

Children
  • I've read about the last thing and i've seen that with the Cortex M3 i don't need to modify the assemler. When i debug the code i check the UART register and i've setted it right: the UART receive interrupt is enabled.

    About te first part of the message:
    do you mean that i've to catch the character directly in the isr from the USART->DR (data register) field and send it using a mailbox to the task getAhrs? And i've to do this after i checked that the flag that signal me that the register isn't empty is set to 1?

  • If having enabled a received FIFO in the UART, you _could_ just have the interrupt signal a thread that the UART has data to read out. But that is not good. And many processors will not support this because they will try to issue a new interrupt directly since the FIFO will still be almost full.

    So the way you do it (with or without FIFO enabled) is to have the ISR pick up one or more characters from the UART and either send them as mailbox messages or place them in a ring buffer.

    The task either waits for mailbox events (that contains the received data) or for an event that the ISR have added data to the ring buffer.

    So the ISR checks the status flags of the UART and when it sees there is available data it directly unloads the data. This makes sure that the UART has room for more data even if the consumer thread has quite low priority and takes some time until it gets activated.

    Remember that the RTOS will always select the highest prioritized thread that is ready to run - and that may not be your UART-processing thread.