Wait for callback function of udp_recv()

I am trying to implement a simple client that waits for a udp frame to arrive. I use udp_recv() to receive a frame. If this happens, a callback function my_callback is called. However, udp_recv() does not seem to be blocking. Hence, the subsequent code is executed before the frame arrives, which, however, must be prevented, since it relies on the already received UDP frame.

Is there a way to implement a waiting mechanism such that the code after udp_recv() is only executed when a frame has been received or a timeout occurs? This could easily be realized using sockets, but in this example I have to use udp_recv().

I stumbled across xTaskNotifyWait, but I do not now how to notify the waiting task from the callback function. Here’s my code:

void my_callback( void* arg,   struct udp_pcb* upcb,  struct pbuf* p, const ip_addr_t* addr, u16_t port )         
{

	// process datagram here
	// inform the waiting main task. How do I do that?
	// xTaskNotifyGive();

	pbuf_free(p);
}


void process_frame(){ 

	// receive udp frame
	udp_recv(cn->m_pcb, my_callback, NULL);
	uint32_t ulNotifiedValue;
	xTaskNotifyWait(0x00, ULONG_MAX, &ulNotifiedValue, portMAX_DELAY);

	// ... only execute this code after having received the incoming frame
	// ...
}

Thank you in advance.

You will need to know the handle for the task waiting for the frame and give that as the handle parameter.

The other option would be to use a Queue that the call back writes to and the task reads from if different tasks might be waiting for the response.

Thank you. Since I am not a FreeRTOS expert, I have some follow-up questions:

  1. Does this mean the callback function is executed in another thread, although I do not actively create a new task?

  2. How do I get the handle of the current task? According to this questions (h ttps://www.freertos.org/FreeRTOS_Support_Forum_Archive/June_2005/freertos_Get_task_handle_1311096.html), I have to pass NULL, but the alternative way is to modify tasks.c, a kernel file, which does not seem to be a good solution for such apparently common problem.

  3. When it comes to a queue, do you think a binary semaphore would also be a solution? In my case, there is no other task waiting for the response, only the main task.

The callback is executed in the context of whichever task calls it.

https://freertos.org/a00021.html#xTaskGetCurrentTaskHandle - although I don’t think that is what you want. You need the handle of the task to which you are sending the notification. That handle can be stored when the task is created, or obtained from the tasks’s name.

If you want to use a semaphore I would suggest a counting semaphore rather than a binary semaphore to ensure you don’t miss events. However as you say there is only one task waiting then a direct to task notification will achieve the same thing in a much leaner way.

Which task calls process_frame function? You should store the handle of that task at the time of task creation - see the output parameter pxCreatedTask here. You should use the same handle when calling xTaskNotifyGive in my_callback.

The function process_frame is called by a thread that has been earlier created by sys_thread_new. I suppose a thread is treated like a task in FreeRTOS?!

Unlike the xTaskCreate, the sys_thread_new does not provide a reference parameter to the task handle. However, it returns a sys_thread_t. Is it possible to use this return value as a handle for xTaskNotifyGive? I currently do not have the opportunity to test the code, but I would still appreciate your opinion. Once it is possible, I’ll try to implement your advices and give feedback.

That depends on how sys_thread_new is implemented and how sys_thread_t is defined. These are not from FreeRTOS. Where did you get these functions from? Can you share these definitions?

Do you have access to your sources ? You should easily find the implementation of the sys_thread abstraction for your platform/MCU you’re using.
E.g. for SAM MCUs ASF comes with sam/include/arch/sys_arch.h containing
typedef xTaskHandle sys_thread_t
Even though sys_thread_new is used there are only FreeRTOS tasks in a FreeRTOS based application. Remember, it’s just an abstraction.

Thank you for your help. I eventually figured out a solution. The xTAskGetCurrentTaskHandle function provides indeed a handle of the current task which I pass to the callback function. Inside this function I call xTaskNotifyGive that releases the xTaskNotifyWait that follows udp_recv.

Thank you for taking time to report back.