cancel
Showing results for 
Search instead for 
Did you mean: 

stm32f0 disco usart1 rx using interrupt

Nimit Vachhani
Associate III
Posted on December 06, 2016 at 11:56

 

 

The original post was too long to process during our migration. Please click on the attachment to read the original post.
8 REPLIES 8
Radek RIPA
ST Employee
Posted on December 06, 2016 at 12:14

Hello,

It is possible that when the IRQ was called and the routineHAL_UART_IRQHandler executed. That in this time anerroroccurred(overrun). In this time the rx function is not called.

Please check the

huart.ErrorCode state

Try to implement theHAL_UART_ErrorCallback and there you can restart the receiving process.

Best regards

Radek

Posted on December 06, 2016 at 12:56

huart.ErrorCode IS 0

.

HAL_UART_ErrorCallback is not being called.

joemccarr
Senior
Posted on December 06, 2016 at 14:00

I have not used hal for usart comms but here is a check list of steps to review.

Got this from stm32f0xx_hal_uart.c file.

(#) Declare a UART_HandleTypeDef handle structure (eg. UART_HandleTypeDef huart).

    (#) Initialize the UART low level resources by implementing the HAL_UART_MspInit() API:

        (++) Enable the USARTx interface clock.

        (++) UART pins configuration:

            (+++) Enable the clock for the UART GPIOs.

            (+++) Configure these UART pins as alternate function pull-up.

        (++) NVIC configuration if you need to use interrupt process (HAL_UART_Transmit_IT()

             and HAL_UART_Receive_IT() APIs):

            (+++) Configure the USARTx interrupt priority.

            (+++) Enable the NVIC USART IRQ handle.

        (++) UART interrupts handling:

              -@@-  The specific UART interrupts (Transmission complete interrupt,

                RXNE interrupt and Error Interrupts) are managed using the macros

                __HAL_UART_ENABLE_IT() and __HAL_UART_DISABLE_IT() inside the transmit and receive processes.

(#) Program the Baud Rate, Word Length, Stop Bit, Parity, Hardware

        flow control and Mode (Receiver/Transmitter) in the huart handle Init structure.

    (#) If required, program UART advanced features (TX/RX pins swap, auto Baud rate detection,...)

        in the huart handle AdvancedInit structure.

    (#) For the UART asynchronous mode, initialize the UART registers by calling

        the HAL_UART_Init() API.

 These APIs(HAL_UART_Init(), HAL_HalfDuplex_Init(), HAL_MultiProcessor_Init(),

        also configure the low level Hardware GPIO, CLOCK, CORTEX...etc) by

        calling the customized HAL_UART_MspInit() API.

 *** Interrupt mode IO operation ***    

     ===================================

     [..]    

       Send an amount of data in non blocking mode using HAL_UART_Transmit_IT()

       At transmission end of half transfer HAL_UART_TxHalfCpltCallback is executed and user can

            add his own code by customization of function pointer HAL_UART_TxHalfCpltCallback

       At transmission end of transfer HAL_UART_TxCpltCallback is executed and user can

            add his own code by customization of function pointer HAL_UART_TxCpltCallback

       Receive an amount of data in non blocking mode using HAL_UART_Receive_IT()

       At reception end of half transfer HAL_UART_RxHalfCpltCallback is executed and user can

            add his own code by customization of function pointer HAL_UART_RxHalfCpltCallback

       At reception end of transfer HAL_UART_RxCpltCallback is executed and user can

            add his own code by customization of function pointer HAL_UART_RxCpltCallback                                      

       In case of transfer Error, HAL_UART_ErrorCallback() function is executed and user can

            add his own code by customization of function pointer HAL_UART_ErrorCallback
Walid FTITI_O
Senior II
Posted on December 06, 2016 at 18:36

Hi

,

You are configuring USART to receive 1 byte , this is why you receive only 'H'. Try to increase the amount of data to receive insideHAL_UART_Receive() and initialize rx_data as a buffer. Then you should check the state of the UART to wait for the end of transfer. See the following:

/* Buffer used for reception (Global variable)*/uint8_t aRxBuffer[RXBUFFERSIZE];HAL_UART_Receive(&UartHandle, (uint8_t *)aRxBuffer, RXBUFFERSIZE);while (HAL_UART_GetState(&UartHandle) != HAL_UART_STATE_READY) { }�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

For other help, try to check the read-to-use example '

UART_HyperTerminal_DMA'

in

http://www.st.com/content/st_com/en/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32cube-embedded-software/stm32cubef0.html

at this path:STM32Cube_FW_F0_V1.6.0\Projects\STM32072B_EVAL\Examples\UART\UART_HyperTerminal_DMA

-Walid FTITI-

Ifthe response is useful, you would mention that by clicking the correct botton. Thank you for the contribution

Posted on December 06, 2016 at 20:25

many things that could be commented on. However the elephant in the room is this code that apparently intializes your receive buffer to all zeros when starting a new input buffer:

if(rx_indx == 0){for (int i=0;i<100;i++) rx_buff[i]=0;}

note that it clears 100 elements while this array is declared to only have 32 elements:

unsigned char rx_buff[32];

It is unclear how these variables, declared in one file are even visible in the other file (are you doing extern declarations in a .h file?)

Creating a variable named cr and assigning 0x0d to it is a bit convoluted since you could just use the immediate value ' ' and again, having the declaration in main() where it is not used, and using it in the _it.c file is confusing at best.

I would suggest putting ALL of your service routines in a separate file that you create, rather than inserting stuff into the CubeMX generated files. It will keep things easier to understand and you won't risk having your hours of coding erased when Cube decides you put them someplace that it doesn't save. Putting additional routines in the CubeMX generated _it.c file is just not a great way to organize your project.

Final comment: Trying to have the interrupt service routine use a call to another interrupt setup routine is at best ugly and at worst unworkable. You should set up simple ISRs that transmit and receive buffers of data, and non-interrupt functions that query or load the buffers that the ISRs use. In those non-interrupt functions you can echo characters and do whatever else you need to do with the data. But don't call the RxSetup HAL call within either of the Rx or Tx ISR, and vice-versa. On the transmit side, you could have a TxDone variable as a flag that is 1 when the program starts, is 0 when a transmission starts, and is set back to 1 by the TxComplete ISR. That way you can avoid trying to start another transmission before the previous one is completed. On the receive side you can have the Rx ISR (which gets an interrupt for each character- one at a time is fine) manage a circular buffer. Another routine can be called to get data from the buffer which uses the same head and tail indexes as the ISR, but does not interfere with the ISR work.

Mark Shoe
Senior
Posted on January 25, 2017 at 16:44

This is exactly what happens in my callback if 1 byte to receive. If they are from the keyboard it is slow enough to work but now i want to make a bootloader and no more receive irq's

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

{

   HAL_GPIO_TogglePin(GPIOD, LD4_Pin); //Green

   if (huart->Instance == USART2) //current UART

   HAL_UART_Receive_IT(&huart2, Rx_data2, 1); //activate UART receive interrupt every time

}

In my main i start the irq with:

 HAL_UART_Receive_IT(&huart2, Rx_data2, 1);

Now every received char wil change the LD4 led. When i paste a buffer of 100 chars to terraterm the led is dead so no irq's are recieved.

What is a better solution? My buffer can only be 1 byte i do not know how many char's to receive. I just want a callback on every char.

Posted on January 25, 2017 at 22:28

Mark,

No matter how fast the Teraterm transfer is, you should be getting interrupts.  You might want to make sure that you send an odd number of characters so that the LED will be in the opposite state after each transfer if things are working correctly.

Not sure if you are using the same processor as the original question, but if not you are only running faster.  So even at 115k baud, you receive a character  every 10 uS.  The processor is running at 50 MHz or more,  so that would be 500 instruction times.  More than enough to service your interrupt.  And even if it wasn't you would miss characters, not lose interrupts altogether.

So I would guess one of two things is happening.  Either you never enable the UART interrupt in the first place, or your code above is checking for something that doesn't happen..  ie: when you look for the *.instance => USART2 do you know this test is passing?  if not, you will never restart the interrupt so you'll never get another.

The other thing that is not clear from your code is the the Declaration of your receive buffer.  You say it is only one byte.  If so, you may just have it declared as a byte or uint8_t.  If that is the case, it could be a problem since the HAL receive function expects a pointer to your receive buffer.  If it is an array, just using the name of the array will pass a pointer, but if it is a single data value you must precede it with an & like: &Rx_data2 to have the address passed instead of the value.  Without that, the HAL routine is interpreting the value in your buffer as an address and writing to that location producing undefined behavior.

Posted on February 08, 2017 at 18:01

The receiving interrupts will stop if you are receiving and transmitting at the same time. Possibly the receive buffer will overflow and does not trigger anymore. I have made a que to store the transmitting and receiving data. I had to write my own HAL_UART_IRQHandler(&huart1); function because when i started the buffer empty irq with USART_CR1_TXEIE to program locks in the irq function.

What is the idea of the HAL drivers to print using HAL_UART_Transmit_IT

I want to use a print function that will fill the que and the irq print function has the handle the buffer in the background, so no blocking printf

Any example? My goal is a bootloader with x or y modem. Someone to share?