3
votes

I'm new here and I'm trying to solve my projects problem. I'm trying to send send data over UART from Raspberry Pi B+ to my STM32F407 and process that data in real-time. My problem is: How to actually synchronize main() thred and UART interruption handler not to stop for a long time my UART interruption. Data sent from Raspberry looks like (where n is number): nwnx Code:

void UART4_IRQHandler(void)
{
    if(USART_GetITStatus(UART4, USART_IT_RXNE))
    {
        if(!flag)
        {
            processing = true;
            widthTemp[j] = USART_ReceiveData(UART4);
            USART_ClearITPendingBit(UART4, USART_IT_RXNE);

            if(widthTemp[j] != 'w')
            {
                j++;
            }
            else
            {
                j = 0;
                flaga = true;
                processing = false;
                //__disable_irq();
                NVIC_DisableIRQ(UART4_IRQn);
            }
        }else if(flag)
        {
            processing = true;
            heightTemp[j] = USART_ReceiveData(UART4);
            USART_ClearITPendingBit(UART4, USART_IT_RXNE);

            if(heightTemp[j] != 'x')
            {
                j++;
            }
            else
            {
                j++;
                heightTemp[j] = '\n';
                j = 0;
                processing = false;
                flag = false;
                NVIC_DisableIRQ(UART4_IRQn);
            }
        }
    }
}

and now main code:

while (1)
{
    if(!NVIC_GetPendingIRQ(UART4_IRQn))
    {
        //if()
        if(flag == true && processing == false)
        {
            sscanf(heightTemp, "%d", &height );
            USART_puts(UART4, heightTemp); // sending back data to raspberry (temporary)
            for(i = 0; i< sizeof(widthTemp);i++)
            {
                heightTemp[i] = '\0';
            }
            NVIC_EnableIRQ(UART4_IRQn);
        }
        if(flag == false && processing == false)
        {
            sscanf(widthTemp, "%d", &width );
            USART_puts(UART4, widthTemp); // sending back data to raspberry (temporary)
            for(i = 0; i< sizeof(widthTemp);i++)
            {
                widthTemp[i] = '\0';
            }
            NVIC_EnableIRQ(UART4_IRQn);
        }
    }
}

My problem is that at some point rasbperry is starting to have huge delays in recieved data.

Questions: 1. Can I disable interruptions in interruption handler like I did in my code to let my main() know that it can proceed data ? And if yes, do I check good register for this task ? 2. Is there a better way to send buffer (widthTemp f.e.) to some variable ? Maybe I don't need to complicate my code like this. 3. Can I use maybe threding in my code ? Will it help ? 4. This is my first post so any information about how to format questions, advices about the code etc. will be nice.

2
1. Yes you can there is a global interrupt enable bit which you are supposed to disable whenever you go into an interrupt handle. 2. YES, you should NOT process the data in your interrupt handler this is a very bad practice. You should instead put it in a buffer with a flag saying hey main process the new data. 3. You don't need threads. 4. Your post is decently formatted.arduic
@arduic : There is a global interrupt enable/disable, but you are not "supposed" to disable it in an interrupt handler. Cortex-M has a priority based preemptive interrupt controller and nested interrupts are supported - disabling interrupts globally defeats that function. Beyond that you have posted what looks like an answer as a comment. Your other points 2 and 3 would be better expressed as an answer.Clifford
@Clifford right sorry used to more attiny kinda stuff. Well either way your interrupt handler should be much smaller. Typically people prefer if your handler is something of the pseudo code. Report handling of interrupt, Put data interrupt is passing into some kind of buffer, Mark data for processing, exit interrupt. Then in main you have a while(1) loop checking if the data mark for processing ever shows up. By putting all your code inside the interrupt you risk taking to long to process the interrupt before the next comes in.arduic
1) Don't use that bloat STlib. It just adds complexity without solving anything or making anything more clear. 2) Normally, there is no need to manually clear the pending bits. 3) You should read more about the Cortex-M4 interrupt system in general and that of the STM32F specifically before fiddling at this level.too honest for this site
@arduic: The Cortex-M interrupt system is no way comparable to that of the AVR8. And the STM32F adds additional complexity (and complication). Actually most imlementations with Cortex-M do. And prioritisation allows a different approach when handling interrupt data. Depending on system-design, you can very well process the data in the handler - provided you can guarantee timing constraints, of course.too honest for this site

2 Answers

2
votes

In general, your UART ISR should do little more than:

  • For a receive interrupt, place character from RXD in a ring buffer
  • for a transmit interrupt, get character from a ring buffer and place it in TXD. On STM32, if the ring buffer is empty, you must explicitly switch off the transmitter.
  • clear interrupt flags (handling of error flags optional).

Then your main thread (or some other thread/task if using an thread scheduler or RTOS), simply reads from the Rx ring buffer (or writes to the Tx ring buffer).

Note that on STM32 if the transmitter is not running, the first character should be placed directly in TXD, and the transmitter started, subsequent characters are then places in the Tx ring buffer.

If using an RTOS or other OS, you might use a queue or mailbox rather then implementing your own ring buffer. Some care is required to ensure consistent buffer control when more than one context is accessing the control data.

Note that the STM32 is capable of using DMA transfers to UART operation which may offer an alternative solution, especially if the data rate is very fast, since the STM32 UART has no FIFO and will overrun the RXD if each character is not removed from RXD in the time taken to receive another.

-1
votes

As said in @arduic comment, you should not process data in the interrupt. You should keep interrupt service routine as short (and quick) as possible. Therefore, you will not need to disable them, preventing for losing data in the case of UART RX interrupt.