Sending Data from ISR to one Task and sending to another task with two queues

Hi,
I have created 3 tasks and two queues.

Here is the initialization for tasks and queues. I am using STM32 microcontroller and eclipse IDE.

int main(void)
{
  Queue01Handle = osMessageQueueNew(256, sizeof(uint8_t),&Queue01_attributes);
	qGpsHandle = osMessageQueueNew(256, sizeof(uint8_t),&qGps_attributes);


	if(Queue01Handle == NULL)
	{
		ConsolePrint("Queue01Handle Failed\r\n");
	}
	else
	{
		ConsolePrint("Queue01Handle Created\r\n");
	}
	if(qGpsHandle == NULL)
		{
			ConsolePrint("qGpsHandle Failed\r\n");
		}
		else
		{
			ConsolePrint("qGpsHandle Created\r\n");
		}
/* creation of defaultTask_LED */

	defaultTask_LEDHandle = osThreadNew(LED_Task_Default, NULL, &defaultTask_LED_attributes);
/* creation of Sender1 */
	Sender1Handle = osThreadNew(UART3RxFrameProcess, NULL, &Sender1_attributes);

	/* creation of Receiver1 */
	Receiver1Handle = osThreadNew(UART2TxSend_Task, NULL, &Receiver1_attributes);

/* Start scheduler */
	osKernelStart();

while (1)
	{
		/* USER CODE END WHILE */

		/* USER CODE BEGIN 3 */
	}

}

//Here is my ISR code. It receives a byte of data from uart peripheral and sends to UART3RxFrameProcess task. The UART3RxFrameProcess task receives the byte of data and keeps it in a buffer. The frame is correctly received in Queue01Handle.

When the frame is ready UART3RxFrameProcess task has to sent the buffer to another task UART2TxSend_Task using qGpsHandle . But UART2TxSend_Task is not receiving the data in qGpsHandle.

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	char GpsRxByte;
	static portBASE_TYPE xHigherPriorityTaskWoken;

	GpsRxByte = GpsUart.RxByte;
	xHigherPriorityTaskWoken = pdFALSE;

	xQueueSendFromISR(Queue01Handle, &GpsRxByte,&xHigherPriorityTaskWoken);

	HAL_UART_Receive_IT(&huartGps, (uint8_t *)&GpsUart.RxByte, 1); //Restart receive interrupt

	portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
void UART2TxSend_Task(void *argument)
{

	char *pGpsRxData=NULL;

	for(;;)
	{

		if(pdTRUE == xQueueReceive(qGpsHandle, &pGpsRxData , 100))
		{
    		        ConsolePrint((char *)pGpsRxData);
 
		}
 
	}
	osDelay(1);
}

void UART3RxFrameProcess(void *argument)
{
	/* USER CODE BEGIN Sender1_Task Sender1Handle */
	char GpsRxByte;
	const GPS_MESSAGE *pGpsRxData = NULL;

	/* Infinite loop */
	for(;;)
	{
		/*Process the UART */

		if(pdPASS == xQueueReceive(Queue01Handle, &GpsRxByte, 100))
		{
			if(GpsUart.RxCount >= 1024)//Overflow judgment
			{
				GpsUart.RxCount = 0;
				memset(GpsUart.RxBuffer,0x00,sizeof(GpsUart.RxBuffer));
				HAL_UART_Transmit(&huartSerial, (uint8_t *)&cAlmStr, sizeof(cAlmStr),0xFFFF);
			}
			else
			{
				switch(GpsUart.RxFrameState)
				{
				case UART_FRAME_IDLE  :
					if((GpsRxByte == GpsUart.RxStartByte1) || (GpsRxByte == GpsUart.RxStartByte2))
					{
						GpsUart.RxCount = 0;
						GpsUart.RxBuffer[GpsUart.RxCount++] = GpsRxByte;
						GpsUart.RxFrameState = UART_FRAME_START;
					}
					else
					{
					}
					break;
				case UART_FRAME_START :
					if((GpsRxByte == GpsUart.RxEndByte1) || (GpsRxByte == GpsUart.RxEndByte2))
					{
						GpsUart.RxBuffer[GpsUart.RxCount++] = GpsRxByte;
						GpsUart.RxFrameState = UART_FRAME_READY;
						memset(GpsMsg.Data,0x00,sizeof(GpsMsg.Data));
						strcpy(GpsMsg.Data, (char *)GpsUart.RxBuffer);
						pGpsRxData = (GPS_MESSAGE *)&GpsMsg.Data;

  						ConsolePrint((char *)pGpsRxData);
					    xQueueSend(qGpsHandle, &pGpsRxData, 100);
						memset(GpsUart.RxBuffer,0x00,sizeof(GpsUart.RxBuffer));
 					}
					else
					{
						GpsUart.RxBuffer[GpsUart.RxCount++] = GpsRxByte;
					}
					break;


				default :
					GpsUart.RxFrameState = UART_FRAME_IDLE;
					break;
				}
			}
		}
	}
	osDelay(1);
}

Let me know any thing is required in UART2TxSend_Task.

Looks okay at first glance. Would you please check if the following send call succeeds:

 xQueueSend(qGpsHandle, &pGpsRxData, 100);

The other thing to do is to put something in the else block of UART2TxSend_Task to check if it running at all:

if(pdTRUE == xQueueReceive(qGpsHandle, &pGpsRxData , 100))
{
    ConsolePrint((char *)pGpsRxData);
}
else
{
    ConsolePrint("[UART2TxSend_Task] Timeout!");
}

Thanks.

Hi Mr. Gaurav,
Thanks for the reply.
I have added the else statement in UART2TxSend_Task I have noticed the following.

I am correctly receiving the data from ISR API xQueueSendFromISR to UART3RxFrameProcess task

xQueueReceive(Queue01Handle, &GpsRxByte, 100))

But when I am sending the message xQueueSend(qGpsHandle, &pGpsRxData, 100); to another task UART2TxSend_Task its not receiving

if(pdTRUE == xQueueReceive(qGpsHandle, &pGpsRxData , 100))

and I have this following output of Junk messages. When I check the return value of

pdTRUE == xQueueReceive(qGpsHandle, &pGpsRxData , 100))

it is true.

I am doubting the task priority
Here are task priorities.

/* Definitions for defaultTask_LED */
osThreadId_t defaultTask_LEDHandle;
const osThreadAttr_t defaultTask_LED_attributes = {
		.name = "defaultTask_LED",
		.priority = (osPriority_t) osPriorityNormal,
		.stack_size = 128
};
/* Definitions for Sender1 */
osThreadId_t Sender1Handle;
const osThreadAttr_t Sender1_attributes = {
		.name = "Sender1",
		.priority = (osPriority_t) osPriorityAboveNormal1 ,
		.stack_size = 256
};
/* Definitions for Receiver1 */
osThreadId_t Receiver1Handle;
const osThreadAttr_t Receiver1_attributes = {
		.name = "Receiver1",
		.priority = (osPriority_t) osPriorityAboveNormal,
		.stack_size = 256
};

Let me know any thing is required.

Regards,
Kumar

Looking at the code below, you are creating 2 queues, each for message size 1 byte:

    Queue01Handle = osMessageQueueNew(256, sizeof(uint8_t),&Queue01_attributes);
    qGpsHandle = osMessageQueueNew(256, sizeof(uint8_t),&qGps_attributes);

The first queue is used correctly to send/receive a character which is one byte. The code is trying to send/receive a GPS_MESSAGE to the second queue which is not one byte. You may:

  • Either copy the whole message to the queue in which case the size of the message in the queue should be set to sizeof(GPS_MESSAGE ).
  • Or you can send a pointer to GPS_MESSAGE in which case the size of the message in the queue should be set to sizeof(GPS_MESSAGE *). Note that in this case you will need to make sure that the content of the actual message does not change when the UART2TxSend_Task is processing it.

Thanks.

Hi Gaurav,
Thanks for the reply.

I will change the code as per your suggestions and get back to you.

Hi Gaurav,
I had made some progress.
I have tested the code as per your suggestions and I have got the output but with some problems below. The first problem is the code is working for some time.

I came across three problems. But I got this correct output for pGpsTxData in UART3RxFrameProcess.

Another problem is in debug mode for the below task, UART2TxSend_Task I have to receive the below string in the pointer pGpsRxData
$GPGSV,4,1,15,10,35,308,09,14,17,217,22,15,19,038,21,16,00,277,17*"

But I am overwriting this pointer to buffer sometimes and I am getting wrong values. Here is the debugger screen shot for pGpsRxData as $5.00,V,040720,N*

Please verify any point I am missing. so that I can get through.

void UART2TxSend_Task(void *argument)
{

	char *pGpsRxData=NULL;

	for(;;)
	{

		if(pdTRUE == xQueueReceive(qGpsHandle, (char *) &pGpsRxData , 100))
		{
			ConsolePrint((char *)pGpsRxData);
//			ConsolePrint("Hello");

		}
		else
		{
//			ConsolePrint("[UART2TxSend_Task] Timeout!");
		}
	}
	osDelay(1);
}

The second problem is, the code is going into unknown state some times. When I run the program in debug mode it is not running. And when I pause it is going to portmacro.h file. Here is the screen shot

Second problem is the control is going into hard fault handler some times.

Here is the code for the above problems.

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	char GpsRxByte;
	static portBASE_TYPE xHigherPriorityTaskWoken;

	GpsRxByte = GpsUart.RxByte;
	xHigherPriorityTaskWoken = pdFALSE;

	xQueueSendFromISR(Queue01Handle, &GpsRxByte,&xHigherPriorityTaskWoken);

	HAL_UART_Receive_IT(&huartGps, (uint8_t *)&GpsUart.RxByte, 1); //Restart receive interrupt

	portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

void UART2TxSend_Task(void *argument)
{

	char *pGpsRxData=NULL;

	for(;;)
	{

		if(pdTRUE == xQueueReceive(qGpsHandle, (char *) &pGpsRxData , 100))
		{
//			ConsolePrint((char *)pGpsRxData);
//			ConsolePrint("Hello");

		}
		else
		{
//			ConsolePrint("[UART2TxSend_Task] Timeout!");
		}
	}
	osDelay(1);
}

void UART3RxFrameProcess(void *argument)
{
	/* USER CODE BEGIN Sender1_Task */
	char GpsRxByte;
	const GPS_MESSAGE *pGpsTxData = NULL;

	/* Infinite loop */
	for(;;)
	{
		/*Process the UART */


		if(pdPASS == xQueueReceive(Queue01Handle, &GpsRxByte,100))
		{
			if(GpsUart.RxCount >= 1024)//Overflow judgment
			{
				GpsUart.RxCount = 0;
				memset(GpsUart.RxBuffer,0x00,sizeof(GpsUart.RxBuffer));
				HAL_UART_Transmit(&huartSerial, (uint8_t *)&cAlmStr, sizeof(cAlmStr),0xFFFF);
			}
			else
			{
				switch(GpsUart.RxFrameState)
				{
				case UART_FRAME_IDLE  :
					if((GpsRxByte == GpsUart.RxStartByte1) || (GpsRxByte == GpsUart.RxStartByte2))
					{
						GpsUart.RxCount = 0;
						GpsUart.RxBuffer[GpsUart.RxCount++] = GpsRxByte;
						GpsUart.RxFrameState = UART_FRAME_START;
					}
					else
					{
					}
					break;
				case UART_FRAME_START :
					if((GpsRxByte == GpsUart.RxEndByte1) || (GpsRxByte == GpsUart.RxEndByte2))
					{
						GpsUart.RxBuffer[GpsUart.RxCount++] = GpsRxByte;
						GpsUart.RxFrameState = UART_FRAME_READY;
						memset(GpsMsg.Data,0x00,sizeof(GpsMsg.Data));
						strcpy(GpsMsg.Data, (char *)GpsUart.RxBuffer);
						pGpsTxData = (GPS_MESSAGE *)&GpsMsg.Data;

//						ConsolePrint((char *)pGpsRxData);
						xQueueSend(qGpsHandle, (GPS_MESSAGE *)&pGpsTxData, 100);
						memset(GpsUart.RxBuffer,0x00,sizeof(GpsUart.RxBuffer));
					}
					else
					{
						GpsUart.RxBuffer[GpsUart.RxCount++] = GpsRxByte;
					}
					break;


				default :
					GpsUart.RxFrameState = UART_FRAME_IDLE;
					break;
				}
			}
		}
	}
	osDelay(1);
}

int _write(int file, char *ptr, int len)
{
	HAL_UART_Transmit(&huartSerial,(uint8_t *)ptr,len,10);
	return len;
}

void ConsolePrint(char *msg)
{
	osMutexWait(Mutex01_PrintfHandle,10);
	printf(msg);
	printf("\r\n");
	osMutexRelease(Mutex01_PrintfHandle);
}
int main(void)
{
	/* USER CODE BEGIN 1 */

	/* USER CODE END 1 */

	/* MCU Configuration--------------------------------------------------------*/

	/* Reset of all peripherals, Initializes the Flash interface and the Sys tick. */

	HAL_Init();

	/* USER CODE BEGIN Init */

	/* USER CODE END Init */

	/* Configure the system clock */
	SystemClock_Config();

	/* USER CODE BEGIN SysInit */

	/* USER CODE END SysInit */

	/* Initialize all configured peripherals */
	MX_GPIO_Init();
	MX_I2C1_Init();
	MX_I2S3_Init();
	MX_SPI1_Init();
	MX_USART2_UART_Init();
	MX_USART3_UART_Init();

	/* USER CODE BEGIN 2 */
	GpsUart.RxStartByte1 = '$';
	GpsUart.RxEndByte1   = '*';
	GpsUart.RxStartByte2 = '$';
	GpsUart.RxEndByte2   = '*';
	Gps.Fix = RESET ;
	Gps.State = GPS_IDLE;

	//	HAL_NVIC_SetPriorityGrouping(0);
//	while(1)
	ConsolePrint("Application starting\r\n");

	HAL_UART_Receive_IT(&huartGps, (uint8_t *)&GpsUart.RxByte, 1); //Restart receive interrupt


	/* USER CODE END 2 */
	/* Init scheduler */
	osKernelInitialize();
	/* Create the mutex(es) */
	/* creation of Mutex01_Printf */
	Mutex01_PrintfHandle = osMutexNew(&Mutex01_Printf_attributes);

	/* USER CODE BEGIN RTOS_MUTEX */
	/* add mutexes, ... */
	/* USER CODE END RTOS_MUTEX */

	/* USER CODE BEGIN RTOS_SEMAPHORES */
	/* add semaphores, ... */
	/* USER CODE END RTOS_SEMAPHORES */

	/* USER CODE BEGIN RTOS_TIMERS */
	/* start timers, add new ones, ... */
	/* USER CODE END RTOS_TIMERS */

	/* Create the queue(s) */
	Queue01Handle = osMessageQueueNew(256, sizeof(uint8_t),&Queue01_attributes);
	qGpsHandle = osMessageQueueNew(256, sizeof(GPS_MESSAGE *),&qGps_attributes);
	/* creation of Queue01 */


	/* USER CODE BEGIN RTOS_QUEUES */
	/* add queues, ... */
	if(Queue01Handle == NULL)
	{
		ConsolePrint("Queue01Handle Failed\r\n");
	}
	else
	{
		ConsolePrint("Queue01Handle Created\r\n");
	}
	if(qGpsHandle == NULL)
		{
			ConsolePrint("qGpsHandle Failed\r\n");
		}
		else
		{
			ConsolePrint("qGpsHandle Created\r\n");
		}

	/* USER CODE END RTOS_QUEUES */

	/* Create the thread(s) */
	/* creation of defaultTask_LED */

	defaultTask_LEDHandle = osThreadNew(LED_Task_Default, NULL, &defaultTask_LED_attributes);

	/* creation of Sender1 */
	Sender1Handle = osThreadNew(UART3RxFrameProcess, NULL, &Sender1_attributes);

	/* creation of Receiver1 */
	Receiver1Handle = osThreadNew(UART2TxSend_Task, NULL, &Receiver1_attributes);

	/* USER CODE BEGIN RTOS_THREADS */
	/* add threads, ... */
	/* USER CODE END RTOS_THREADS */
	//		ConsolePrint("Message Queue Created Successfully\r\n");

	/* Start scheduler */
	osKernelStart();

	/* We should never get here as control is now taken by the scheduler */
	/* Infinite loop */
	/* USER CODE BEGIN WHILE */
	while (1)
	{
		/* USER CODE END WHILE */

		/* USER CODE BEGIN 3 */
	}
	/* USER CODE END 3 */
}

Moreover the code is only working in debug mode with setting Optimize for Debug and also sometimes. Here are the debugger settings.

Any suggestions would be great.

Thanks again

Lets just look at one problem at a time. Please re-post with an explanation of just one of the above problems so that can be worked through before moving to the next. It might even be best to have a separate thread per problem so the subject line matches what is in the post.

Mr. Richard,
The code is working fine. But I am facing only one problem. The code is running for some time and getting stopped after that. To know that I have run the program in debug mode. The control is going into Hard fault Handler.

Here is the disassembly code screenshot for first signal handler and second signal handler


Let me know anything to look after.

First comment, the addresses “FFFFFFFD” and “FFFFFFF1” are special codes that interrupts/trap use, and not really addresses. The FFFFFFFD means that when tracing back, you really should switch back from the interrupt stack to the main program stack (which many debuggers unfortunately aren’t smart enough to do).

One thing to make sure you do is define configASSERT in a way that you can tell if it gets called, which typically means having it disable interrupts and then going into an infinite loop. This will have FreeRTOS check a number of aspects of the setup to find a number of the common problems. One very common problem is using FreeRTOS functions in an ISR with to high of a priority (too small of a value), which makes the critical sections non-functional, and some of the data structures inside FreeRTOS get corrupted.

As mentioned by Richard, please define configASSERT to catch interrupt priority configuration or other issues. You can also use the information on this page to debug hard fault: https://www.freertos.org/Debugging-Hard-Faults-On-Cortex-M-Microcontrollers.html

Thanks,
Gaurav

I will define configASSERT and let you know further.