cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F7 HAL_Uart_receive_IT revisited

Christopher Pappas
Senior II
Posted on July 12, 2017 at 18:03

STM32F7 HAL_Uart_receive_IT trying to receive and process one byte at a time, and like many others in the forum, I get one byte ok, then the HAL Receive Callback routine will not run again. Here are the basic code pieces that I am using now..

FROM MAIN.H

----------------------------------------------------------

/* Definition for USARTx clock resources */

&sharpdefine USARTx USART3

&sharpdefine USARTx_CLK_ENABLE() __HAL_RCC_USART3_CLK_ENABLE();

&sharpdefine USARTx_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE()

&sharpdefine USARTx_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE()

&sharpdefine USARTx_FORCE_RESET() __HAL_RCC_USART3_FORCE_RESET()

&sharpdefine USARTx_RELEASE_RESET() __HAL_RCC_USART3_RELEASE_RESET()

/* Definition for USARTx Pins */

&sharpdefine USARTx_TX_PIN GPIO_PIN_8

&sharpdefine USARTx_TX_GPIO_PORT GPIOD

&sharpdefine USARTx_TX_AF GPIO_AF7_USART3

&sharpdefine USARTx_RX_PIN GPIO_PIN_9

&sharpdefine USARTx_RX_GPIO_PORT GPIOD

&sharpdefine USARTx_RX_AF GPIO_AF7_USART3

&sharpdefine USARTx_IRQn USART3_IRQn

&sharpdefine USARTx_IRQHandler USART3_IRQHandler

FROM MAIN.C

----------------------------------------------------------

UART_HandleTypeDef UartHandle;

/* Buffer used for reception */

uint8_t aRxBuffer[1];

int main(void)

{

/* Enable the CPU Cache */

CPU_CACHE_Enable();

/* STM32F7xx HAL library initialization */

HAL_Init();

/* Configure the system clock to 216 MHz */

SystemClock_Config();

/* Initialize all configured peripherals */

MX_UART_Init();

HAL_UART_Receive_IT(&UartHandle, (uint8_t *)aRxBuffer, 1);

while (1)

{

}

}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)

{

BSP_LED_Toggle(LED2);

}

/* UART init function */

void MX_UART_Init(void)

{

UartHandle.Instance = USARTx;

UartHandle.Init.BaudRate = 921600;

UartHandle.Init.WordLength = UART_WORDLENGTH_8B;

UartHandle.Init.StopBits = UART_STOPBITS_1;

UartHandle.Init.Parity = UART_PARITY_NONE;

UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;

UartHandle.Init.Mode = UART_MODE_TX_RX;

UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;

if (HAL_UART_Init(&UartHandle) != HAL_OK)

{

/* Initialization Error */

Error_Handler();

}

}

FROM IT.C

-----------------------------------------------------------------

extern UART_HandleTypeDef UartHandle;

void USARTx_IRQHandler(void)

{

HAL_UART_IRQHandler(& UartHandle);

}

FROM MSP.C

-----------------------------------------------------------------

void HAL_UART_MspInit(UART_HandleTypeDef *huart)

{

GPIO_InitTypeDef GPIO_InitStruct;

RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit;

/* Enable GPIO TX/RX clock */

USARTx_TX_GPIO_CLK_ENABLE();

USARTx_RX_GPIO_CLK_ENABLE();

/* Select SysClk as source of USART1 clocks */

RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1;

RCC_PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_SYSCLK;

HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);

/* Enable USARTx clock */

USARTx_CLK_ENABLE();

Does anybody have any ideas of suggestions to make this very simple standard HAL code work properly?

Thanks all!

Chris

#hal-uart-rcv
1 ACCEPTED SOLUTION

Accepted Solutions
Christopher Pappas
Senior II
Posted on July 13, 2017 at 18:12

Here is the solution. Yank out all the HAL UART code, and replace it with LL USART equivalents.

FROM MAIN.H

----------------------------------------------------------

#include 'stm32f7xx_hal.h'

#include 'stm32f7xx_ll_bus.h'

#include 'stm32f7xx_ll_rcc.h'

#include 'stm32f7xx_ll_system.h'

#include 'stm32f7xx_ll_utils.h'

#include 'stm32f7xx_ll_gpio.h'

#include 'stm32f7xx_ll_exti.h'

#include 'stm32f7xx_ll_usart.h'

#include 'stm32f7xx_ll_pwr.h'

#define USARTx_INSTANCE USART3

#define USARTx_CLK_ENABLE() LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART3)

#define USARTx_CLK_SOURCE() LL_RCC_SetUSARTClockSource(LL_RCC_USART3_CLKSOURCE_PCLK1)

#define USARTx_IRQn USART3_IRQn

#define USARTx_IRQHandler USART3_IRQHandler

#define USARTx_GPIO_CLK_ENABLE() LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOD) /* Enable the peripheral clock of GPIOD */

#define USARTx_TX_PIN LL_GPIO_PIN_8

#define USARTx_TX_GPIO_PORT GPIOD

#define USARTx_SET_TX_GPIO_AF() LL_GPIO_SetAFPin_8_15(GPIOD, LL_GPIO_PIN_8, LL_GPIO_AF_7)

#define USARTx_RX_PIN LL_GPIO_PIN_9

#define USARTx_RX_GPIO_PORT GPIOD

#define USARTx_SET_RX_GPIO_AF() LL_GPIO_SetAFPin_8_15(GPIOD, LL_GPIO_PIN_9, LL_GPIO_AF_7)

#define APB_Div 4

FROM MAIN.C

----------------------------------------------------------

void Configure_USART(void)

{

/* Enable the peripheral clock of GPIO Port */

USARTx_GPIO_CLK_ENABLE();

/* Configure Tx Pin as : Alternate function, High Speed, Push pull, Pull up */

LL_GPIO_SetPinMode(USARTx_TX_GPIO_PORT, USARTx_TX_PIN, LL_GPIO_MODE_ALTERNATE);

USARTx_SET_TX_GPIO_AF();

LL_GPIO_SetPinSpeed(USARTx_TX_GPIO_PORT, USARTx_TX_PIN, LL_GPIO_SPEED_FREQ_HIGH);

LL_GPIO_SetPinOutputType(USARTx_TX_GPIO_PORT, USARTx_TX_PIN, LL_GPIO_OUTPUT_PUSHPULL);

LL_GPIO_SetPinPull(USARTx_TX_GPIO_PORT, USARTx_TX_PIN, LL_GPIO_PULL_UP);

/* Configure Rx Pin as : Alternate function, High Speed, Push pull, Pull up */

LL_GPIO_SetPinMode(USARTx_RX_GPIO_PORT, USARTx_RX_PIN, LL_GPIO_MODE_ALTERNATE);

USARTx_SET_RX_GPIO_AF();

LL_GPIO_SetPinSpeed(USARTx_RX_GPIO_PORT, USARTx_RX_PIN, LL_GPIO_SPEED_FREQ_HIGH);

LL_GPIO_SetPinOutputType(USARTx_RX_GPIO_PORT, USARTx_RX_PIN, LL_GPIO_OUTPUT_PUSHPULL);

LL_GPIO_SetPinPull(USARTx_RX_GPIO_PORT, USARTx_RX_PIN, LL_GPIO_PULL_UP);

/* - Set priority for USARTx_IRQn */

/* - Enable USARTx_IRQn */

NVIC_SetPriority(USARTx_IRQn, 0);

NVIC_EnableIRQ(USARTx_IRQn);

/* Enable USART peripheral clock */

USARTx_CLK_ENABLE();

/* Set clock source */

USARTx_CLK_SOURCE();

/* Configure USART functional parameters */

/* TX/RX direction */

LL_USART_SetTransferDirection(USARTx_INSTANCE, LL_USART_DIRECTION_TX_RX);

/* 8 data bit, 1 start bit, 1 stop bit, no parity */

LL_USART_ConfigCharacter(USARTx_INSTANCE, LL_USART_DATAWIDTH_8B, LL_USART_PARITY_NONE, LL_USART_STOPBITS_1);

/* No Hardware Flow control */

/* Reset value is LL_USART_HWCONTROL_NONE */

// LL_USART_SetHWFlowCtrl(USARTx_INSTANCE, LL_USART_HWCONTROL_NONE);

/* Oversampling by 16 */

/* Reset value is LL_USART_OVERSAMPLING_16 */

//LL_USART_SetOverSampling(USARTx_INSTANCE, LL_USART_OVERSAMPLING_16);

/* Set Baudrate to 115200 using APB frequency set to 216000000/APB_Div Hz */

/* Frequency available for USART peripheral can also be calculated through LL RCC macro */

/* Ex :

Periphclk = LL_RCC_GetUSARTClockFreq(Instance); or LL_RCC_GetUARTClockFreq(Instance); depending on USART/UART instance

In this example, Peripheral Clock is expected to be equal to 216000000/APB_Div Hz => equal to SystemCoreClock/APB_Div

*/

LL_USART_SetBaudRate(USARTx_INSTANCE, SystemCoreClock/APB_Div, LL_USART_OVERSAMPLING_16, 115200);

/* (5) Enable USART *********************************************************/

LL_USART_Enable(USARTx_INSTANCE);

/* Enable RXNE and Error interrupts */

LL_USART_EnableIT_RXNE(USARTx_INSTANCE);

LL_USART_EnableIT_ERROR(USARTx_INSTANCE);

}

void USART_CharReception_Callback(void)

{

__IO uint32_t received_char;

/* Read Received character. RXNE flag is cleared by reading of RDR register */

received_char = LL_USART_ReceiveData8(USARTx_INSTANCE);

/* Check if received value is corresponding to specific one : S or s */

if ((received_char == 'S') || (received_char == 's'))

{

/* Toggle LED2 : Expected character has been received */

HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_7); //blink LED

}

/* Echo received character on TX */

LL_USART_TransmitData8(USARTx_INSTANCE, received_char);

}

FROM IT.C

-----------------------------------------------------------------

void USARTx_IRQHandler(void)

{

/* Check RXNE flag value in ISR register */

if(LL_USART_IsActiveFlag_RXNE(USARTx_INSTANCE) && LL_USART_IsEnabledIT_RXNE (USARTx_INSTANCE))

{

/* RXNE flag will be cleared by reading of RDR register (done in call) */

/* Call function in charge of handling Character reception */

USART_CharReception_Callback();

}

}

Everything is working fine now. Thanks again to everybody for assisting me!!!!

Chris

View solution in original post

7 REPLIES 7
Christopher Pappas
Senior II
Posted on July 13, 2017 at 12:28

I'm wondering if a LL chunk of USART code can be mixed in with HAL to get it working right. The LL Example for USART that comes with the Nucleo-F767 firmware looks promising. I'll give it a try.

bbee
Associate III
Posted on July 13, 2017 at 12:46

You have to restart the reception again.  With HAL_UART_Receive_IT(&UartHandle, (uint8_t *)aRxBuffer, 1); you are telling the UART to receive only one byte. When it has been received the RXNE interrupt will be automatically disabled. So put your HAL_UART_Receive_IT(&UartHandle, (uint8_t *)aRxBuffer, 1); into the while loop and your LED will toggle like hell.

Tilen MAJERLE
ST Employee
Posted on July 13, 2017 at 14:59

Hello

Pappas.Chris

‌,

you can, of course, mix HAL and LL together in single project. You can for example use HAL for initialization and LL for everything else including enabling RXNE interrupt.

Later, you can use LL to implement your own USART IRQ handler routine and not HAL implementation.

Posted on July 13, 2017 at 14:40

While this actually does make the code work, it is dependent on the speed of the while loop. I have time delays in the actual while loop code, so it definitely leads to missed chars. I want to try some direct register solutions but it seems that this will probably break the HAL code completely. Low Level Libraries may be the only real solution, since they can be used along with existing HAL code and not cause conflicts. I'm working on it now, I will post here if I find a useable solution. Thanks for replying, ra!

Christopher Pappas
Senior II
Posted on July 13, 2017 at 18:12

Here is the solution. Yank out all the HAL UART code, and replace it with LL USART equivalents.

FROM MAIN.H

----------------------------------------------------------

#include 'stm32f7xx_hal.h'

#include 'stm32f7xx_ll_bus.h'

#include 'stm32f7xx_ll_rcc.h'

#include 'stm32f7xx_ll_system.h'

#include 'stm32f7xx_ll_utils.h'

#include 'stm32f7xx_ll_gpio.h'

#include 'stm32f7xx_ll_exti.h'

#include 'stm32f7xx_ll_usart.h'

#include 'stm32f7xx_ll_pwr.h'

#define USARTx_INSTANCE USART3

#define USARTx_CLK_ENABLE() LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART3)

#define USARTx_CLK_SOURCE() LL_RCC_SetUSARTClockSource(LL_RCC_USART3_CLKSOURCE_PCLK1)

#define USARTx_IRQn USART3_IRQn

#define USARTx_IRQHandler USART3_IRQHandler

#define USARTx_GPIO_CLK_ENABLE() LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOD) /* Enable the peripheral clock of GPIOD */

#define USARTx_TX_PIN LL_GPIO_PIN_8

#define USARTx_TX_GPIO_PORT GPIOD

#define USARTx_SET_TX_GPIO_AF() LL_GPIO_SetAFPin_8_15(GPIOD, LL_GPIO_PIN_8, LL_GPIO_AF_7)

#define USARTx_RX_PIN LL_GPIO_PIN_9

#define USARTx_RX_GPIO_PORT GPIOD

#define USARTx_SET_RX_GPIO_AF() LL_GPIO_SetAFPin_8_15(GPIOD, LL_GPIO_PIN_9, LL_GPIO_AF_7)

#define APB_Div 4

FROM MAIN.C

----------------------------------------------------------

void Configure_USART(void)

{

/* Enable the peripheral clock of GPIO Port */

USARTx_GPIO_CLK_ENABLE();

/* Configure Tx Pin as : Alternate function, High Speed, Push pull, Pull up */

LL_GPIO_SetPinMode(USARTx_TX_GPIO_PORT, USARTx_TX_PIN, LL_GPIO_MODE_ALTERNATE);

USARTx_SET_TX_GPIO_AF();

LL_GPIO_SetPinSpeed(USARTx_TX_GPIO_PORT, USARTx_TX_PIN, LL_GPIO_SPEED_FREQ_HIGH);

LL_GPIO_SetPinOutputType(USARTx_TX_GPIO_PORT, USARTx_TX_PIN, LL_GPIO_OUTPUT_PUSHPULL);

LL_GPIO_SetPinPull(USARTx_TX_GPIO_PORT, USARTx_TX_PIN, LL_GPIO_PULL_UP);

/* Configure Rx Pin as : Alternate function, High Speed, Push pull, Pull up */

LL_GPIO_SetPinMode(USARTx_RX_GPIO_PORT, USARTx_RX_PIN, LL_GPIO_MODE_ALTERNATE);

USARTx_SET_RX_GPIO_AF();

LL_GPIO_SetPinSpeed(USARTx_RX_GPIO_PORT, USARTx_RX_PIN, LL_GPIO_SPEED_FREQ_HIGH);

LL_GPIO_SetPinOutputType(USARTx_RX_GPIO_PORT, USARTx_RX_PIN, LL_GPIO_OUTPUT_PUSHPULL);

LL_GPIO_SetPinPull(USARTx_RX_GPIO_PORT, USARTx_RX_PIN, LL_GPIO_PULL_UP);

/* - Set priority for USARTx_IRQn */

/* - Enable USARTx_IRQn */

NVIC_SetPriority(USARTx_IRQn, 0);

NVIC_EnableIRQ(USARTx_IRQn);

/* Enable USART peripheral clock */

USARTx_CLK_ENABLE();

/* Set clock source */

USARTx_CLK_SOURCE();

/* Configure USART functional parameters */

/* TX/RX direction */

LL_USART_SetTransferDirection(USARTx_INSTANCE, LL_USART_DIRECTION_TX_RX);

/* 8 data bit, 1 start bit, 1 stop bit, no parity */

LL_USART_ConfigCharacter(USARTx_INSTANCE, LL_USART_DATAWIDTH_8B, LL_USART_PARITY_NONE, LL_USART_STOPBITS_1);

/* No Hardware Flow control */

/* Reset value is LL_USART_HWCONTROL_NONE */

// LL_USART_SetHWFlowCtrl(USARTx_INSTANCE, LL_USART_HWCONTROL_NONE);

/* Oversampling by 16 */

/* Reset value is LL_USART_OVERSAMPLING_16 */

//LL_USART_SetOverSampling(USARTx_INSTANCE, LL_USART_OVERSAMPLING_16);

/* Set Baudrate to 115200 using APB frequency set to 216000000/APB_Div Hz */

/* Frequency available for USART peripheral can also be calculated through LL RCC macro */

/* Ex :

Periphclk = LL_RCC_GetUSARTClockFreq(Instance); or LL_RCC_GetUARTClockFreq(Instance); depending on USART/UART instance

In this example, Peripheral Clock is expected to be equal to 216000000/APB_Div Hz => equal to SystemCoreClock/APB_Div

*/

LL_USART_SetBaudRate(USARTx_INSTANCE, SystemCoreClock/APB_Div, LL_USART_OVERSAMPLING_16, 115200);

/* (5) Enable USART *********************************************************/

LL_USART_Enable(USARTx_INSTANCE);

/* Enable RXNE and Error interrupts */

LL_USART_EnableIT_RXNE(USARTx_INSTANCE);

LL_USART_EnableIT_ERROR(USARTx_INSTANCE);

}

void USART_CharReception_Callback(void)

{

__IO uint32_t received_char;

/* Read Received character. RXNE flag is cleared by reading of RDR register */

received_char = LL_USART_ReceiveData8(USARTx_INSTANCE);

/* Check if received value is corresponding to specific one : S or s */

if ((received_char == 'S') || (received_char == 's'))

{

/* Toggle LED2 : Expected character has been received */

HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_7); //blink LED

}

/* Echo received character on TX */

LL_USART_TransmitData8(USARTx_INSTANCE, received_char);

}

FROM IT.C

-----------------------------------------------------------------

void USARTx_IRQHandler(void)

{

/* Check RXNE flag value in ISR register */

if(LL_USART_IsActiveFlag_RXNE(USARTx_INSTANCE) && LL_USART_IsEnabledIT_RXNE (USARTx_INSTANCE))

{

/* RXNE flag will be cleared by reading of RDR register (done in call) */

/* Call function in charge of handling Character reception */

USART_CharReception_Callback();

}

}

Everything is working fine now. Thanks again to everybody for assisting me!!!!

Chris

m8r-xuulk51
Associate II
Posted on July 14, 2017 at 08:44

For reference:

If you want to stick with the HAL-Library, you could trythis method:

https://community.st.com/0D50X00009XkfrWSAR

Posted on July 14, 2017 at 12:32

Yes, I saw that thread already, but at this point since I am only working on

https://community.st.com/0D50X00009bMM4jSAG

, I'm thinking I may move away from HAL, and slowly adapt/fold-in/replace Low-Layer code instead.

One benefit I can see from this is that direct-register code will not break LL as it seems to do in HAL.

The main drawback is that now I have ported my project from SPL to HAL, and now once again I am porting from HAL to LL. 

Also, the LL drivers are not complete for all STM32 devices yet, so it will be hard to port my project to other devices/boards.