cancel
Showing results for 
Search instead for 
Did you mean: 

How to see the contents of osMessageQueue through an interrupt point?

jessie_chiu
Associate III

 

Hi Community,

I'm using the STM32U5A9-DK development board and trying to get the UART messages to show up on the screen.

Using osMessageQueue to pass messages between the main and the Model.

But I'm experiencing the problem described in this post , and I've found that the breakpoints don't work in the callback function.


I'm not sure if the message is being put into the queue correctly.


Has anyone else experienced a similar problem or know how to solve it?

 

This is my code:

Default Task:

 

 

void StartDefaultTask(void *argument)
{
  /* USER CODE BEGIN defaultTask */
	extern UART_HandleTypeDef huart1;
	extern char RxData[256]; // received data from UART
	HAL_UART_Transmit(&huart1, "UART1 ready...\n", 15, 0xffff);

	char cmd[42] =  "send_string \"Hello\"\n"
			"\n";

	HAL_UART_Transmit(&huart1, cmd, sizeof(cmd), 0xffff);
	HAL_Delay(50);


  /* Infinite loop */
  for(;;)
  {
	HAL_UARTEx_ReceiveToIdle_IT(&huart1, RxData, 256);
    osDelay(1);
  }
  /* USER CODE END defaultTask */
}

 

 

Callback function:

 

 

extern osMessageQueueId_t uartQueueHandle;
char RxData[256]; // received data from UART
char DataBuffer[256]; // store full message

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{	
    memcpy(DataBuffer, RxData, Size+1);
    HAL_UART_Transmit(&huart1, (uint8_t *)DataBuffer, Size, 0xffff);

	if (osMessageQueueGetSpace(uartQueueHandle)>0)
	{
		osMessageQueuePut(uartQueueHandle, DataBuffer, 0 ,0);
	}
	HAL_Delay(100);
}

 

 

 

Model.c

 

#include <gui/model/Model.hpp>
#include <gui/model/ModelListener.hpp>

#include "cmsis_os2.h"
#include <cstring>
#include <stm32u5xx.h>

extern osMessageQueueId_t uartQueueHandle;


Model::Model() : modelListener(0)
{

}


char string[256];
char RData[256];

extern UART_HandleTypeDef huart1;

void Model::tick()
{
	if(osMessageQueueGet(uartQueueHandle, &string, 0, 0xffff) == osOK)
	{
		strncpy(RData, string, sizeof(string));

		modelListener -> uart_Data(RData);
	}
}

 

 

3 REPLIES 3
Karl Yamashita
Lead II

You're not using HAL_UARTEx_ReceiveToIdle_IT correctly. You just need to initiate once before the for loop and within the callback

 

 

 

 

 

 

void StartDefaultTask(void *argument)
{
  /* USER CODE BEGIN defaultTask */
	extern UART_HandleTypeDef huart1;
	extern char RxData[256]; // received data from UART

     HAL_UARTEx_ReceiveToIdle_IT(&huart1, RxData, 256);
	HAL_UART_Transmit_IT(&huart1, "UART1 ready...\n", strlen("UART1 ready...\n"));

	char cmd[42] =  "send_string \"Hello\"\n" // start and end quote but missing semicolon?
			"\n"; // what is this?

	HAL_UART_Transmit_IT(&huart1, cmd, strlen(cmd)); // use interrupt and strlen
	HAL_Delay(50);

  /* Infinite loop */
  for(;;)
  {
	
    osDelay(1);
  }
  /* USER CODE END defaultTask */
}

 

 

 

 

 

Don't use HAL_UART_Transmit inside of an interrupt because it is blocking. Use HAL_UART_Transmit_IT instead. Also, you should just set a flag when you get a callback. Then check the flag and do your memcpy and osMessageQueuePut in the StartDefaultTask for loop

 

 

 

 

extern osMessageQueueId_t uartQueueHandle;
char RxData[256]; // received data from UART
char DataBuffer[256]; // store full message

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{	
    memcpy(DataBuffer, RxData, Size+1);
    HAL_UART_Transmit_IT(&huart1, (uint8_t *)DataBuffer, Size);

	if (osMessageQueueGetSpace(uartQueueHandle)>0)
	{
		osMessageQueuePut(uartQueueHandle, DataBuffer, 0 ,0);
	}
	//HAL_Delay(100); // why delay? not needed.
        HAL_UARTEx_ReceiveToIdle_IT(&huart1, RxData, 256); // enable interrupt again
}

 

 

 

 

 

@Karl Yamashita Thank you for such a clear reply!!!


Although the same problem still exists after the modification, I understand that there was a problem with the call sequence in the previous code.

However, I don't understand why I need to set a flag in the call back?

For best practice you want to exit the interrupt quickly. Because you're copying data and transmitting, you could potentially miss more incoming data, and any other interrupts won't trigger, unless you adjust those interrupts as higher priority.

 

Also i just noticed that you have two HAL_UART_Transmit_IT back to back, so your second transmit may not get sent because the first one is still in the process of sending. So you can either go back to using HAL_UART_Transmit or you can learn to use a ring buffer and queue your messages for transmit.

 

So i just looked at your other thread. You should follow this example https://www.keil.com/pack/doc/CMSIS/RTOS2/html/group__CMSIS__RTOS__Message.html#gaa515fc8b956f721a8f72b2c505813bfc

 

And for the queue you would set it up like this 

KarlYamashita_0-1713014042200.png

 

Hope that helps.