Why does the address of a Queue change?

Hello everyone, I am currently using an STM32F103RCT6 microcontroller to run FreeRTOS.
I’m currently trying to pass multiple parameters to a Task Function using an array of structures , including a Queue and an int32_t data.
After compiling my code, I found that the program did not run as expected. While debugging in Keil, I discovered that the program eventually entered into the HardFault_Handler() function within the stm32f10x.c file.

My program is as follows:

/*Variable declarations*/
typedef struct {
    QueueHandle_t xQueue;
    int32_t data;
} Queue_parameter;

QueueHandle_t Queue0 = NULL;
QueueHandle_t Queue1 = NULL;
QueueSetHandle_t Queue_Set = NULL;

main():

int main{
    SEGGER_RTT_Init();
    /*Create two Queues to receive data*/
    Queue0 = xQueueCreate(4, sizeof(int32_t));
    Queue1 = xQueueCreate(4, sizeof(int32_t));
    /*Printing the address of a Queue using the J-Link RTT tool.*/
    SEGGER_RTT_SetTerminal(0);
    SEGGER_RTT_printf(0, "1:Queue0:%p,Queue1:%p\n",Queue0,Queue1);
    /*Create a  Queue Set*/
    Queue_Set = xQueueCreateSet(8 * (sizeof(int32_t)));
    xQueueAddToSet(Queue0, Queue_Set);
    xQueueAddToSet(Queue1, Queue_Set);
    /*Data to be sent*/
    const Queue_parameter Queue_data[2] = {
            {Queue0, 48},
            {Queue1, 65}
    };
    SEGGER_RTT_printf(0, "2:Queue0:%p,Queue1:%p\n",Queue0,Queue1);
		
    Queue_parameter* queue_param_ptr0 = (Queue_parameter*) &Queue_data[0];
    QueueHandle_t Q = queue_param_ptr0->xQueue;
    SEGGER_RTT_printf(0, "3:Queue0:%p\n",Q);
    /*Pass multiple parameters to a Task Function using an array of structures*/		
    xTaskCreate(Send_data_to_queue, "Send_Task0", 400,  (void *)queue_param_ptr0, 1, NULL);
    xTaskCreate(Receive_data_from_Queueset, "Receive_data", 400, NULL, 2, NULL);
    
    vTaskStartScheduler();
}

Send_data_to_queue() Function:

static void Send_data_to_queue(void *parameter) {
	    BaseType_t state;		
        Queue_parameter *param = (Queue_parameter *) parameter;
        QueueHandle_t queue = param->xQueue;
        int32_t data = param->data;
    while (1) {				
	    SEGGER_RTT_SetTerminal(0);
	    SEGGER_RTT_printf(0, "4:Queue0:%p\n",queue);
	    /*Not work*/		
        state = xQueueSendToBack(queue,&data, 0);
        /*Woked*/
	    //state = xQueueSendToBack(Queue0,"1",0);

        vTaskDelay(pdMS_TO_TICKS(2000));
    }
}

Output:

00> 1:Queue0:20000CE0,Queue1:20000D48
00> 2:Queue0:20000CE0,Queue1:20000D48
00> 3:Queue0:20000CE0
00> 4:Queue0:00000400

We can see that after passing Queue0 into Send_data_to_queue(), its address has changed.
The program operated as expected when I ran state = xQueueSendToBack(Queue0,"1",0); .

I’m curious as to why the address of Queue0 changes. If my approach is incorrect, are there any other ways to accomplish passing multiple parameters to a task?

Make the parameter struct e.g. static but do not use the main stack.
The main stack is reset and reused as ISR stack on Cortex-M MCUs after starting the scheduler.

See bullet 3 “main() stack” on this page: https://freertos.org/FAQHelp.html

1 Like

Thanks , the problem has been solved