send struct between tasks

simob47 wrote on Thursday, September 20, 2018:

Hey,

I need to send a structure between the two tasks below.
How do I recover the contents of my structure in the second task ?
Mtree it’s a tree.

help please

`
xQueueHandle Globale_Queue_handle2 = 0;
Globale_Queue_handle2 = xQueueCreate(10, sizeof(mt_t));

typedef struct merkle_tree {
uint32_t elems;
mt_al_t *level[TREE_LEVELS];
} mt_t;

void task1(void *vParameters){

while(1){
    mt_t* mtree = mt_test_tree(leaf, pt->buffer);
	vPortFree(pt);
	vTaskDelay(3000);

	if(!xQueueSend(Globale_Queue_handle2, (void *) &mtree, 1000)){ 
		printf("Failed to send value to queue \n\r");
	}
}

}

void task2(void *vParameters){

int choice_leaf;

while(1){

	mt_integrity *mi = pvPortCalloc(1, sizeof(mt_integrity));
	mt_t* mtree;

	if(!xQueueReceive(Globale_Queue_handle2, &mtree, 2000 )) { 
		witness(choice_leaf, mi->wit_check, mtree);
		vPortFree(mi);

	}else{
		printf("waiting for mtree from queue... \n\r");
	}
}

}
`

richarddamon wrote on Thursday, September 20, 2018:

FreeRTOS queue transfer the VALUE of the provided object. In your code, you Queue is defined to transfer a ‘mt_t’ which is a structure, but you are passing not the address of a structure, but the address of a pointer to that structure, which is too small.

If your create call used a sizeof(*mt_t) , then it would match your calls.

rtel wrote on Thursday, September 20, 2018:

First - how big is the structure? If it is small you can queue the
entire structure - that is copy the entire structure into the queue then
copy the entire structure out of the queue again - so you don’t need to
do anything to get to the data again. If it is large then it is
probably best to queue a pointer to the structure rather than all the
data in the structure.

In your code you are queuing the address of a pointer, so you are
copying a pointer to a pointer into the queue - specifically you are
copying the address of the mtree variable which is on the stack of task1

  • I don’t think that is what you want to do. You can just copy the
    value of the pointer into the queue to make it simpler - just just use
    (void*)mtree as the parameter to the queue send and receive functions,
    rather than (void*)&mtree. Then you will be copying the address of
    whatever mtree is pointing to - which I think is what you meant to do -
    and when you read it out of the queue again you can dereference the
    pointer in task2 in exactly the way you do in task1 - you will have two
    separate pointers (one on the stack of task1 and one on the stack of
    task2) that point to the same tree object.

simob47 wrote on Thursday, September 20, 2018:

Thank you for ur reply.

I thank it’s good for sending the structure. but for reception, task2 is blocked.
I go through another structure but it does not solve the problem.

`
xQueueHandle Globale_Queue_handle2 = 0;
Globale_Queue_handle2 = xQueueCreate(10, sizeof(mt_t));

typedef struct merkle_tree {
uint32_t elems;
mt_al_t *level[TREE_LEVELS];
} mt_t;

typedef struct __pt_mtree
{
mt_t* mtree;
} pt_mtree;

void task1(void *vParameters){

while(1){
pt_mtree* mt0 = 0;
mt0->mtree = mt_test_tree(leaf, pt->buffer);
vPortFree(pt);
vTaskDelay(3000);

if(!xQueueSend(Globale_Queue_handle2, mt0->mtree, 1000)){ 
    printf("Failed to send value to queue \n\r");
}

}

}

void task2(void *vParameters){

int choice_leaf;

while(1){

mt_integrity *mi = pvPortCalloc(1, sizeof(mt_integrity));
pt_mtree* mt1 = 0;

if(!xQueueReceive(Globale_Queue_handle2, mt1->mtree, 2000 )) { 
    witness(choice_leaf, mi->wit_check, mt1->mtree);
    vPortFree(mi);

}else{
    printf("waiting for mtree from queue... \n\r");
}

}

}
`

richarddamon wrote on Thursday, September 20, 2018:

Your return test is backwards. xQueueReceive returns ‘True’ on success, and 0 on failure,

Also, you are beginning by setting mtl to NULL, then using mtl->mtree which dereferences a NULL pointer, and pass the results to xQueueReceive

simob47 wrote on Thursday, September 20, 2018:

So how can i dereference structur mt_t ?

simob47 wrote on Thursday, September 20, 2018:

I solved my problem, Semaphore was more efficient. Thank you

richard_damon wrote on Thursday, September 20, 2018:

Perhaps you don’t understand how a FreeRTOS queue works. When you send a item, you pass FreeRTOS the address of it, and it copies the item into the memory space inside the queue, and then when you receive it, it is then copied from the queue to the place proviced in the receive call. The item sent can be a struct itself (preferably for smaller structs as the contents get copied twice) and the receiver end up with a COPY of the original structure (sort of like doing an assignment). You can also pass a pointer to a structure, in which case FreeRTOS just moves the pointer from place to place, but then the send needs to pass the ADDRESS of that pointer, and the receiver passes an ADDRESS of a corresponding pointer to receive the value. In this later case, the receiver uses the exact same structure as the sender sent (just the pointer was copied), so the sender shouldn’t change the data after sending. If you want to do this case, then you create the queue based on the sizeof a struct* type, not a struct type.