cancel
Showing results for 
Search instead for 
Did you mean: 

UART Receive Interrupt on STM32f0 using CubeMX / Keil (how?)

Mnemocron
Associate III
Posted on February 16, 2016 at 09:02

My tools:

STM32f072rb (NUCLEO)

MCP2200 uart to usb board

STM32CubeMX (4.12.0)

Keil uVision 5 (5.17)

What I'm trying to do:

Running a program in the main loop and reading UART transmission into a ring buffer.

(as soon as Rx signal is present, an interrupt is triggered which reads the incomming data)

Init code was generated using CubeMX, setting up

UART2, 8Bits 9600 Baud, no HW flow control, on STLink debugger

UART1, 8Bits 9600 Baud, no HW flow control, on MCP2200

One attempt of mine was connecting the Rx2 pin to EXTI6, triggering a GPIO interrupt and readingfrom there.

(Receiving char on UART2, echo it to UART1)

This worked well for only one char and is imo. a really dirty solution.

In CubeMX, under NVIC the UART2 global interrupt through EXTI line 26 is selected, and the USART2_IRQHandler() is generated into stm32f0xx_it.c

When trying to test it by toggling the LD2 led, nothing happens on an incomming Rx signal. It does work when calling HAL_UART_Transmit_IT()

void USART2_IRQHandler(void)

{

  /* USER CODE BEGIN USART2_IRQn 0 */

    HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);

  /* USER CODE END USART2_IRQn 0 */

  HAL_UART_IRQHandler(&huart2);

  /* USER CODE BEGIN USART2_IRQn 1 */

  /* USER CODE END USART2_IRQn 1 */

}

After hours of googling, there seems to be a possible solution using Rx interrupts.

However I have not found a way to implement it with the tools I am using.

Some attempts use NVIC

NVIC_InitTypeDef NVIC_InitStructure;

NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

However the NVIC_InitTypeDef is not present within the HAL libraries.

Does anyone see any obvious flaws?

Thanks in advance

#uart #cubemx #stm32f0 #hal
4 REPLIES 4
mark239955_stm1
Associate II
Posted on February 16, 2016 at 11:38

I know this isn't really specific to your problem, but some advice of a more general nature: don't use Cube for running the simpler peripherals like UART's and GPIO.  Dig into the reference manual, read the relevant sections thoroughly, several times, and then make it happen yourself.  Don't be shy about asking for help, either through various forums (including here) or just googling for how to do things.

Cube is reasonable if you either don't care about understanding how a peripheral actually works or can't be bothered writing or porting complex protocol stacks yourself.  It's biggest problem is that if all you learn is Cube, you'll have learnt nothing portable.  It's like the difference between learning how to program, and learning how to use an operating system to open applications and copy files.

Mnemocron
Associate III
Posted on February 18, 2016 at 08:43

Well I guess this is true. The Cube philisophy is a bit strange, comming from microchip pic.

HAL isn't portable at all I guess. I might state at the end of the project, that HAL is possibly not be the best option.

However, my job is to write a ringbuffer module for the UART Rx. And therefore only the module needs to be portable. I quite like the cube there, because I won't have to read the manuals.

Mnemocron
Associate III
Posted on February 18, 2016 at 08:52

I did the Rx interrupt somehow. For the sake of completeness, here's my solution:

Calling

HAL_UART_Receive_IT(&huart2, &char_buf, 1);

before the endless loop in the main routine enables the interrupt for 1 char to received.

In the stm32f0xx_it.c where all the interrupts are handles is a function called

USART2_IRQHandler(void)

which gets triggered as soon as an Rx signal is present.

Within the function I put the received char into my ring buffer and

re-enable

the interrupt for the next char. Like this:

void USART2_IRQHandler(void)

{

  /* USER CODE BEGIN USART2_IRQn 0 */

    HAL_UART_RxCpltCallback(&huart2);

    RingBuffer_AppendChar(&uart2buf, char_buf);

  /* USER CODE END USART2_IRQn 0 */

  HAL_UART_IRQHandler(&huart2);

  /* USER CODE BEGIN USART2_IRQn 1 */

    HAL_UART_Receive_IT(&huart2, &char_buf, 1);

  /* USER CODE END USART2_IRQn 1 */

}

I am not sure about the function

HAL_UART_RxCpltCallback(&huart2);

If it is necessary or not or what it is good for. (It works with and without).

mark239955_stm1
Associate II
Posted on February 18, 2016 at 12:09

HAL_UART_RxCpltCallback() is a “callbackâ€� function.  Callbacks are a programming mechanism used under a sequential programming model to somewhat mimic an event-driven model.  In C they are typically implemented with function pointers, weak function declarations, or #defines; I think (but I am not certain, because reading Cube’s code output causes me physical pain) that Cube uses weak function declarations.  Callbacks provide a reasonably flexible way for one task to advise another task that something has occurred, e.g. that a receive interrupt has been fired by a UART.  In your case it seems to be irrelevant, because you’ve already handled the receive event by storing the received data in your ring buffer.  Also, because you presumably haven’t declared a function of the same name, and assuming that I’m right about Cube using weak function declarations for callbacks, the compiler calls the weak function stub in the Cube code.  You could explore what's actually happening by debugging and following execution through the interrupt handler.