xStreamBufferReceive(…, portMAX_DELAY) Task Moved to Suspended and Never Wakes on Data

Did you try removing printf?

Then you should be able to write a minimal application to repro the problem: one task which sends data to the stream buffer and other task which receives the data from the stream buffer. If you can do that and share the application, I can give it a try on a different hardware.

For a test I changed original task code:

void task1_task(void *pvParameters) {
	(void) pvParameters;
	TickType_t xLastWakeTime;
	xLastWakeTime = xTaskGetTickCount();
	while (1) {
		vTaskDelayUntil(&xLastWakeTime, 60);
		FreeRTOS_printf(( "A%03u, %04u\n", (int16_t) DebugUARTbuffFreeBytesGet(), (uint16_t)uxTaskGetStackHighWaterMark(NULL) ));
		vLEDtoggle(GPIOA, GPIO_Pin_0);
	}
}

void task2_task(void *pvParameters) {
	(void) pvParameters;
	TickType_t xLastWakeTime;
	xLastWakeTime = xTaskGetTickCount();
	while (1) {
		vTaskDelayUntil(&xLastWakeTime, 61);
		FreeRTOS_printf(( "B%03u, %04u\n", (int16_t) DebugUARTbuffFreeBytesGet(), (uint16_t)uxTaskGetStackHighWaterMark(NULL) ));
		vLEDtoggle(GPIOA, GPIO_Pin_1);
	}
}

to simpler printing:

void task1_task(void *pvParameters) {
	(void) pvParameters;
	TickType_t xLastWakeTime;
	xLastWakeTime = xTaskGetTickCount();
	while (1) {
		vTaskDelayUntil(&xLastWakeTime, 60);
		__write(0,"tsk1\n",5);
		vLEDtoggle(GPIOA, GPIO_Pin_0);
	}
}

void task2_task(void *pvParameters) {
	(void) pvParameters;
	TickType_t xLastWakeTime;
	xLastWakeTime = xTaskGetTickCount();
	while (1) {
		vTaskDelayUntil(&xLastWakeTime, 61);
		__write(0,"tsk2\n",5);
		vLEDtoggle(GPIOA, GPIO_Pin_1);
	}
}

But the same behavior: the buffer is full but DebugUART is suspended with usNotifyState==taskNOTIFICATION_RECEIVED.

My hardware is somewhat new and probably different. Currently it’s WCH CH32V317 MCU with QuingKe4F CPU core. It lacks RISC-V mtime timer and it’s comparator but has SysTick like in ARM Cortex-M cores but 64 bit wide. So the context switching is done though timer interrupt or software interrupt (SWI) depending on the moment the switch is needed.
I can imagine that the problem is in the port itself. Something related to critical sections, task switching or tick timer interrupt control.
Not sure my example will not run on your hardware.
Can you describe the process of task notification to let me investigate my port problem (or RTOS problem if any)?

To fulfill your recommendation, I tested the stream sending from writing tasks directly:

void task1_task(void *pvParameters) {
	(void) pvParameters;
	TickType_t xLastWakeTime;
	xLastWakeTime = xTaskGetTickCount();
	while (1) {
		vTaskDelayUntil(&xLastWakeTime, 60);
		xStreamBufferSend(xDebugMsgStream, "tsk1\n", 5, 0);
		vLEDtoggle(GPIOA, GPIO_Pin_0);
	}
}

void task2_task(void *pvParameters) {
	(void) pvParameters;
	TickType_t xLastWakeTime;
	xLastWakeTime = xTaskGetTickCount();
	while (1) {
		vTaskDelayUntil(&xLastWakeTime, 61);
		xStreamBufferSend(xDebugMsgStream, "tsk2\n", 5, 0);
		vLEDtoggle(GPIOA, GPIO_Pin_1);
	}
}

No changes. Receiving task is eSuspened, usNotifyState==taskNOTIFICATION_RECEIVED, buffer is full.

Okay. It was not too hard.
Here is main.c which is demonstrating the problem in my environment:

/*
 * main.c
 *
 *  Created on: Aug 15, 2025
 *      Author: nikolaypo
 */

#define DebugUART_PRIO 5
#define TASK1_TASK_PRIO 4
#define TASK2_TASK_PRIO 3

#define TASK1_STK_SIZE 256
#define TASK2_STK_SIZE 256
#define DebugUART_STK_SIZE 256 //Stack size for debug background output handler

//#define DebugUARTtxSize 320 //Size of debug UART Tx buffer
//#define xBufferSizeBytes DebugUARTtxSize

#include "FreeRTOS.h"
#include "task.h"
#include "stream_buffer.h"
#include "message_buffer.h"

//Static tasks memory
TaskHandle_t xDebugUART; //Debug background output handler for RTOS tasks
StaticTask_t xDebugUART_TCB; //Task data structure
StackType_t puxDbgUARTstkBuf[DebugUART_STK_SIZE]; //Static task stack buffer

TaskHandle_t Task1Task_Handler;
StaticTask_t xTask1Buffer;
StackType_t uxTask1StackBuffer[TASK1_STK_SIZE];

TaskHandle_t Task2Task_Handler;
StaticTask_t xTask2Buffer;
StackType_t uxTask2StackBuffer[TASK2_STK_SIZE];


//FreeRTOS debug messages static stream buffer
uint8_t pucDbgMsgBufStor[320/*xBufferSizeBytes*/]; //Debug message buffer storage area
StaticMessageBuffer_t xDbgMsgBufStruct; //Debug message buffer structure
StreamBufferHandle_t xDebugMsgStream; //Debug message buffer handler

//UART message buffer receiver task stuff

static const char HelloString[] = "\nUART started\n"; //Printed each time the UART is configured or re-configured

void task1_task(void *pvParameters) {
	(void) pvParameters;
	TickType_t xLastWakeTime;
	xLastWakeTime = xTaskGetTickCount();
	while (1) {
		vTaskDelayUntil(&xLastWakeTime, 60);
		xStreamBufferSend(xDebugMsgStream, "tsk1\n", 5, 0);
	}
}

void task2_task(void *pvParameters) {
	(void) pvParameters;
	TickType_t xLastWakeTime;
	xLastWakeTime = xTaskGetTickCount();
	while (1) {
		vTaskDelayUntil(&xLastWakeTime, 61);
		xStreamBufferSend(xDebugMsgStream, "tsk2\n", 5, 0);
	}
}

void vUART_DMAtx(void *pvParameters) {
	(void) pvParameters;
	char Buff[320/*xBufferSizeBytes*/];
	xStreamBufferSend(xDebugMsgStream, (const void*) HelloString, sizeof(HelloString) - 1, 0); //Send helloString to fill the buffer by first message
	for (;;) {
		size_t Size = xStreamBufferReceive(xDebugMsgStream, (void*) Buff, sizeof(Buff), portMAX_DELAY); //Wait for next message
		if (Size > 0) { //Sanity check for size of data requested for a transmission
			//Some data need to be transferred
			asm volatile ("NOP");
			//I'm getting here only first time after calling xStreamBufferSend() above at first entering to vUART_DMAtx()
		} else {
			//Size of request is zero or there is no request. Do nothing.
		}
	} //Repeat forever
}

int main(void) {
	//Create background debug stream buffer for sending debug messages to UART
	xDebugMsgStream = xStreamBufferCreateStatic(320/*xBufferSizeBytes*/, 1, pucDbgMsgBufStor, &xDbgMsgBufStruct);

	/* create tasks */
	xDebugUART = xTaskCreateStatic(vUART_DMAtx, (const char*) "DebugUART", DebugUART_STK_SIZE, (void*) 1, DebugUART_PRIO, puxDbgUARTstkBuf, &xDebugUART_TCB);

	Task1Task_Handler = xTaskCreateStatic((TaskFunction_t) task1_task, (const char*) "task1", (uint16_t) TASK1_STK_SIZE, (void*) NULL,
			(UBaseType_t) TASK1_TASK_PRIO, uxTask1StackBuffer, &xTask1Buffer);

	Task2Task_Handler = xTaskCreateStatic((TaskFunction_t) task2_task, (const char*) "task2", (uint16_t) TASK2_STK_SIZE, (void*) NULL,
			(UBaseType_t) TASK2_TASK_PRIO, uxTask2StackBuffer, &xTask2Buffer);

	/* Start the RTOS scheduler. */
	vTaskStartScheduler();
	for (;;) {
		asm volatile ("NOP");
		//Shouldn't run at here
	}
}

UPD: archived file is attached.
StreamBufferNotifyFailureTest.zip (1.4 KB)

This tiny test even without hardware initialization and interrupt enabling except the port code exhibits the same behavior: xDebugUART task is in eSuspended state and usNotifyState value is 2 which is taskNOTIFICATION_RECEIVED.
What should I check in my port to debugging that?

I do not know if this still applies to the current state of the problem report, but note that both critical sections and Suspend/ResumeAll are like nuclear war heads shooting at robins and should be avoided. It seems as if your use case cries for muteces. By suspending ALL tasks, you a) risk very subtle deadlocks even between tasks that do not care about the resources you need to protect and b) do not have any control over where all of your tasks are in their control flow.

Thanks for an opinion. Currently I flattened the code to absolute minimum with no critical sections and with no suspending on user part. But the problem persists

you should definitely check for the return values of your calls to xStreamBufferSend() to get an idea of how the buffer fills and whether you run into conditions where the receiver starves out or something the like. Do NOT use debug output for that but in-memory counters or message arrays that you can evaluate posthumously.