Global pointer & MIPS & FreeRTOS

Hello!

Can anybody help in my question?, please

Im trying to porting FreeRTOS on my MIPS64 and Ive noticed some dependences which follow some problem with data initialization.

Execution of my program is stopped in the fololwing cases but after the same instruction(reason):
1)

void vTaskSuspendAll( void )
{
ffffffffb5012f34:	67bdfff0 	daddiu	$29,$29,-16
ffffffffb5012f38:	ffbe0008 	sd	$30,8($29)
ffffffffb5012f3c:	03a0f025 	or	$30,$29,$0
	/* A critical section is not required as the variable is of type
	BaseType_t.  Please read Richard Barry's reply in the following link to a
	post in the FreeRTOS support forum before reporting this as a bug! -
	http://goo.gl/wu4acr */
	++uxSchedulerSuspended;
ffffffffb5012f40:	df8280b0 	ld	$2,-32592($28)
ffffffffb5012f44:	64420001 	daddiu	$2,$2,1
ffffffffb5012f48:	ff8280b0 	sd	$2,-32592($28)
	...
}
/* If uxSchedulerSuspended is zero then this function does not match a
	previous call to vTaskSuspendAll(). */
	configASSERT( uxSchedulerSuspended );
ffffffffb5012f84:	df8280b0 	ld	$2,-32592($28)
ffffffffb5012f88:	1440000c 	bnez	$2,ffffffffb5012fbc <xTaskResumeAll+0x50>
ffffffffb5012f8c:	00000000 	sll	$0,$0,0x0
ffffffffb5012f90:	00000000 	sll	$0,$0,0x0
ffffffffb5012f94:	24050820 	addiu	$5,$0,2080
ffffffffb5012f98:	3c020000 	lui	$2,0x0
ffffffffb5012f9c:	64420000 	daddiu	$2,$2,0
ffffffffb5012fa0:	00021438 	dsll	$2,$2,0x10
ffffffffb5012fa4:	6442b502 	daddiu	$2,$2,-19198
ffffffffb5012fa8:	00021438 	dsll	$2,$2,0x10
ffffffffb5012fac:	64449c70 	daddiu	$4,$2,-25488
ffffffffb5012fb0:	0d4045eb 	jal	ffffffffb50117ac <vAssertCalled>
ffffffffb5012fb4:	00000000 	sll	$0,$0,0x0
ffffffffb5012fb8:	00000000 	sll	$0,$0,0x0

	if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
ffffffffb5013ab4:	df8280b0 	ld	$2,-32592($28)

The reason in “ld $2,-32592($28)”
As reault I move to the address of unintialized data

In linker script I paste gp between data and sdata sections

	.data :
  	{
		_data_start = ALIGN(8);		
    		*(.data)
    		*(.data.*)
		_data_end = ALIGN(8);	
  	} 
	  . = .;
	  _gp = ALIGN(16) + 0x7ff0;
	.sdata ALIGN(8) :
  {
    _sdata_begin = . ;
    . = ALIGN(8) ;
    *(.sdata)
    *(.sdata.*)
    _sdata_end = . ;
  } 

In this situations I dont understand why FreeRTOS in these cases aleways go to the address _gp -32592 ?

@addi

Are you basing this off existing code I can reference? From what I understand our PIC32M ports are MIPS based.

	configASSERT( uxSchedulerSuspended );
ffffffffb5012f84:	df8280b0 	ld	$2,-32592($28)
ffffffffb5012f88:	1440000c 	bnez	$2,ffffffffb5012fbc

Appears it’s loading uxSchedulerSuspended to check, and possibly branch, based on its value. The actual address of it should be assigned during compilation/linkage. I’m not sure I understand the issue. Is this value uninitialized or is the issue that you’re trying to access inaccessible memory? Or that it’s at an unexpected address?

Which section is uxSchedulerSuspended being placed in? _gp is being aligned to 32768 boundary. It’s assignment _gp = ALIGN(16) + 0x7ff0 won’t adjust the linker’s location counter, if that’s what was intended. What is _gp for?

Hello!

Thank you very much for your support!

Yes, strarting using your port files in another project for MIPS32
Previous problem I have solved by sbss section initializzation

Now I have to continue launch FreeRTOS based project which contain already FreeRTOS porting on MIPS64 by another person

As result I have only one task launch from several and in practice I see that after one task lauching happens the following loop:

/* Is there room on the queue now?  The running task must be the
			highest priority task wanting to access the queue.  If the head item
			in the queue is to be overwritten then it does not matter if the
			queue is full. */
			if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
ffffffffb5015c60:	dfc20008 	ld	$2,8($30)
ffffffffb5015c64:	dc430070 	ld	$3,112($2)
ffffffffb5015c68:	dfc20008 	ld	$2,8($30)
ffffffffb5015c6c:	0040a025 	or	$20,$2,$0
ffffffffb5015c70:	de820078 	ld	$2,120($20)
ffffffffb5015c74:	0062102b 	sltu	$2,$3,$2
ffffffffb5015c78:	14400007 	bnez	$2,ffffffffb5015c98 <xQueueGenericSend+0x194>
ffffffffb5015c7c:	00000000 	sll	$0,$0,0x0
ffffffffb5015c80:	00000000 	sll	$0,$0,0x0
ffffffffb5015c84:	dfc30048 	ld	$3,72($30)
ffffffffb5015c88:	24020002 	addiu	$2,$0,2
ffffffffb5015c8c:	1462002e 	bne	$3,$2,ffffffffb5015d48 <xQueueGenericSend+0x244>
ffffffffb5015c90:	00000000 	sll	$0,$0,0x0
ffffffffb5015c94:	00000000 	sll	$0,$0,0x0
			{
				traceQUEUE_SEND( pxQueue );
				xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
ffffffffb5015c98:	dfc60048 	ld	$6,72($30)
ffffffffb5015c9c:	dfc50038 	ld	$5,56($30)
ffffffffb5015ca0:	dfc40008 	ld	$4,8($30)
ffffffffb5015ca4:	0d405d18 	jal	ffffffffb5017460 <prvCopyDataToQueue>
ffffffffb5015ca8:	00000000 	sll	$0,$0,0x0
ffffffffb5015cac:	00000000 	sll	$0,$0,0x0
ffffffffb5015cb0:	ffc20010 	sd	$2,16($30)
				}
				#else /* configUSE_QUEUE_SETS */
				{
					/* If there was a task waiting for data to arrive on the
					queue then unblock it now. */
					if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
ffffffffb5015cb4:	dfc20008 	ld	$2,8($30)
ffffffffb5015cb8:	0040a025 	or	$20,$2,$0
ffffffffb5015cbc:	de820048 	ld	$2,72($20)
ffffffffb5015cc0:	10400012 	beqz	$2,ffffffffb5015d0c <xQueueGenericSend+0x208>
ffffffffb5015cc4:	00000000 	sll	$0,$0,0x0
ffffffffb5015cc8:	00000000 	sll	$0,$0,0x0
					{
						if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
ffffffffb5015ccc:	dfc20008 	ld	$2,8($30)
ffffffffb5015cd0:	64420048 	daddiu	$2,$2,72
ffffffffb5015cd4:	00402025 	or	$4,$2,$0
ffffffffb5015cd8:	0d404ea0 	jal	ffffffffb5013a80 <xTaskRemoveFromEventList>
ffffffffb5015cdc:	00000000 	sll	$0,$0,0x0
ffffffffb5015ce0:	00000000 	sll	$0,$0,0x0
ffffffffb5015ce4:	10400011 	beqz	$2,ffffffffb5015d2c <xQueueGenericSend+0x228>
ffffffffb5015ce8:	00000000 	sll	$0,$0,0x0
ffffffffb5015cec:	00000000 	sll	$0,$0,0x0
						{
							/* The unblocked task has a priority higher than
							our own so yield immediately.  Yes it is ok to do
							this from within the critical section - the kernel
							takes care of that. */
							queueYIELD_IF_USING_PREEMPTION();
ffffffffb5015cf0:	24040001 	addiu	$4,$0,1
ffffffffb5015cf4:	0d4046a5 	jal	ffffffffb5011a94 <mips_eic0_seticureq>
ffffffffb5015cf8:	00000000 	sll	$0,$0,0x0
ffffffffb5015cfc:	00000000 	sll	$0,$0,0x0
ffffffffb5015d00:	1000000a 	beqz	$0,ffffffffb5015d2c <xQueueGenericSend+0x228>
ffffffffb5015d04:	00000000 	sll	$0,$0,0x0
ffffffffb5015d08:	00000000 	sll	$0,$0,0x0
						else
						{
							mtCOVERAGE_TEST_MARKER();
						}
					}
					else if( xYieldRequired != pdFALSE )
ffffffffb5015d0c:	dfc20010 	ld	$2,16($30)
ffffffffb5015d10:	10400006 	beqz	$2,ffffffffb5015d2c <xQueueGenericSend+0x228>
ffffffffb5015d14:	00000000 	sll	$0,$0,0x0
ffffffffb5015d18:	00000000 	sll	$0,$0,0x0
					{
						/* This path is a special case that will only get
						executed if the task was holding multiple mutexes and
						the mutexes were given back in an order that is
						different to that in which they were taken. */
						queueYIELD_IF_USING_PREEMPTION();
ffffffffb5015d1c:	24040001 	addiu	$4,$0,1
ffffffffb5015d20:	0d4046a5 	jal	ffffffffb5011a94 <mips_eic0_seticureq>
ffffffffb5015d24:	00000000 	sll	$0,$0,0x0
ffffffffb5015d28:	00000000 	sll	$0,$0,0x0
						mtCOVERAGE_TEST_MARKER();
					}
				}
				#endif /* configUSE_QUEUE_SETS */

				taskEXIT_CRITICAL();
ffffffffb5015d2c:	0d40514a 	jal	ffffffffb5014528 <vTaskExitCritical>
ffffffffb5015d30:	00000000 	sll	$0,$0,0x0
ffffffffb5015d34:	00000000 	sll	$0,$0,0x0
				return pdPASS;
ffffffffb5015d38:	24020001 	addiu	$2,$0,1
ffffffffb5015d3c:	10000074 	beqz	$0,ffffffffb5015f10 <xQueueGenericSend+0x40c>
ffffffffb5015d40:	00000000 	sll	$0,$0,0x0
ffffffffb5015d44:	00000000 	sll	$0,$0,0x0
			}
			else
			{
				if( xTicksToWait == ( TickType_t ) 0 )
ffffffffb5015d48:	8fc20040 	lw	$2,64($30)
ffffffffb5015d4c:	14400009 	bnez	$2,ffffffffb5015d74 <xQueueGenericSend+0x270>
ffffffffb5015d50:	00000000 	sll	$0,$0,0x0
ffffffffb5015d54:	00000000 	sll	$0,$0,0x0
				{
					/* The queue was full and no block time is specified (or
					the block time has expired) so leave now. */
					taskEXIT_CRITICAL();

.....

....

...


#if( configUSE_TASK_NOTIFICATIONS == 1 )

	uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait )
	{
ffffffffb50145f4:	67bdffd0 	daddiu	$29,$29,-48
ffffffffb50145f8:	ffbf0028 	sd	$31,40($29)
ffffffffb50145fc:	ffbe0020 	sd	$30,32($29)
ffffffffb5014600:	03a0f025 	or	$30,$29,$0
ffffffffb5014604:	ffc40010 	sd	$4,16($30)
ffffffffb5014608:	00a01025 	or	$2,$5,$0
ffffffffb501460c:	00021000 	sll	$2,$2,0x0
ffffffffb5014610:	afc20018 	sw	$2,24($30)
	uint32_t ulReturn;

		taskENTER_CRITICAL();
ffffffffb5014614:	0d405136 	jal	ffffffffb50144d8 <vTaskEnterCritical>
ffffffffb5014618:	00000000 	sll	$0,$0,0x0
ffffffffb501461c:	00000000 	sll	$0,$0,0x0
		{
			/* Only block if the notification count is not already non-zero. */
			if( pxCurrentTCB->ulNotifiedValue == 0UL )
ffffffffb5014620:	df828040 	ld	$2,-32704($28)
ffffffffb5014624:	0040a025 	or	$20,$2,$0
ffffffffb5014628:	8e820080 	lw	$2,128($20)
ffffffffb501462c:	14400013 	bnez	$2,ffffffffb501467c <ulTaskNotifyTake+0x88>
ffffffffb5014630:	00000000 	sll	$0,$0,0x0
ffffffffb5014634:	00000000 	sll	$0,$0,0x0
			{
				/* Mark this task as waiting for a notification. */
				pxCurrentTCB->ucNotifyState = taskWAITING_NOTIFICATION;
ffffffffb5014638:	df828040 	ld	$2,-32704($28)
ffffffffb501463c:	24030001 	addiu	$3,$0,1
ffffffffb5014640:	a0430084 	sb	$3,132($2)

				if( xTicksToWait > ( TickType_t ) 0 )
ffffffffb5014644:	8fc20018 	lw	$2,24($30)
ffffffffb5014648:	1040000c 	beqz	$2,ffffffffb501467c <ulTaskNotifyTake+0x88>
ffffffffb501464c:	00000000 	sll	$0,$0,0x0
ffffffffb5014650:	00000000 	sll	$0,$0,0x0
				{
					prvAddCurrentTaskToDelayedList( xTicksToWait, pdTRUE );
ffffffffb5014654:	8fc20018 	lw	$2,24($30)
ffffffffb5014658:	24050001 	addiu	$5,$0,1
ffffffffb501465c:	00402025 	or	$4,$2,$0
ffffffffb5014660:	0d40548e 	jal	ffffffffb5015238 <prvAddCurrentTaskToDelayedList>
ffffffffb5014664:	00000000 	sll	$0,$0,0x0
ffffffffb5014668:	00000000 	sll	$0,$0,0x0

					/* All ports are written to allow a yield in a critical
					section (some will yield immediately, others wait until the
					critical section exits) - but it is not something that
					application code should ever do. */
					portYIELD_WITHIN_API();
ffffffffb501466c:	24040001 	addiu	$4,$0,1
ffffffffb5014670:	0d4046a5 	jal	ffffffffb5011a94 <mips_eic0_seticureq>
ffffffffb5014674:	00000000 	sll	$0,$0,0x0
ffffffffb5014678:	00000000 	sll	$0,$0,0x0
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
		}
		taskEXIT_CRITICAL();
ffffffffb501467c:	0d40514a 	jal	ffffffffb5014528 <vTaskExitCritical>
ffffffffb5014680:	00000000 	sll	$0,$0,0x0
ffffffffb5014684:	00000000 	sll	$0,$0,0x0

That project is here:

I can lauch only “FillTask” task, receive(CheckTask) task doesnt execute

Can somebody check the proting and prompt the reason of context switching absence?, please

I am not clear about your problem but does the data initialization work correctly when you do not use FreeRTOS (i.e. a bare metal application)? I’d suggest to first get a bare metal application up and running correctly and then add FreeRTOS.

Thank you for your replay!
I checked in simple project, data initialization seems worked
Can you explain what data section I must to initialize and how?, please
Now I do initialization for bss, sbss only

Do you not need to initialize the initialized data section? Can you create some global variables with some different non-zero initial values and then verify in the debugger that those values are correct when the control reaches main?

Thank you for your replay!

I checked global variable initialization - it has value at initialization

But I still hasnt got queue data transferring from task to another
I see what even I do TaskSuspend or TaskDelete I stay in for cycle in first task

Here my simple main:

/* Kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

#include "iolib.h"
int var1_addr;// = 0x1503FF00;
int var2_addr;// = 0x1503FF01;
int var3_addr;// = 0x1503FF03;
	var1_addr = 0xFFFFFFFFB503FF00;//0x07FFFF00;//0x1503FF00;
	var2_addr = 0xFFFFFFFFB503FF08;//0x07FFFF08;//0x1503FF01;
	var3_addr = 0xFFFFFFFFB503FF0B;//0x07FFFF0B;
/* The rate at which data is sent to the queue, specified in milliseconds. */
#define mainQUEUE_SEND_FREQUENCY_MS			( 10 )
#define IOP1_BASE			0xffffffffB610FF50


/* The number of items the queue can hold.  This is 1 as the receive task
will remove items as they are added, meaning the send task should always find
the queue empty. */
#define mainQUEUE_LENGTH					( 16 )


/* Priorities at which the tasks are created. */
#define mainQUEUE_SEND_TASK_PRIORITY	( tskIDLE_PRIORITY + 1 )
#define mainQUEUE_RECEIVE_TASK_PRIORITY	( tskIDLE_PRIORITY + 2 )


/*-----------------------------------------------------------*/

/*
 * The tasks as described in the accompanying PDF application note.
 */
 
static void CheckTask( void *pvParameters );
static void FillTask( void *pvParameters );
static void taskA( void* );
static void taskB( void* );

/*-----------------------------------------------------------*/

/* The queue used by both tasks. */
static xQueueHandle xQueue = NULL;

/* One array position is used for each task created by this demo.  The
variables in this array are set and cleared by the trace macros within
FreeRTOS, and displayed on the logic analyzer window within the Keil IDE -
the result of which being that the logic analyzer shows which task is
running when. */
unsigned long ulTaskNumber[ 3 ];

uint8_t data[16];

/*-----------------------------------------------------------*/
void main(void)
{
  

*((volatile uint16_t* const)(IOP1_BASE  )) = 0x0000;
	*((volatile uint16_t* const)(IOP1_BASE + 0x04)) = 0xAA55;

	xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( unsigned long ) );

	if( xQueue != NULL )
	{
		 xTaskCreate( CheckTask, ( signed char * ) "CheckTask",	configMINIMAL_STACK_SIZE, NULL,  ( tskIDLE_PRIORITY + 2 ), NULL ); // tskIDLE_PRIORITY + 2 , NULL );
		 xTaskCreate( FillTask, ( signed char * ) "FillTask", configMINIMAL_STACK_SIZE, NULL,  ( tskIDLE_PRIORITY + 2 ), NULL ); //tskIDLE_PRIORITY + 1 , NULL );
		/* xTaskCreate( taskA, ( signed char * ) "taskA", 100, NULL, ( tskIDLE_PRIORITY + 1), NULL );
		 xTaskCreate( taskB, ( signed char * ) "taskB", 100, NULL, (tskIDLE_PRIORITY + 1), NULL );
*/
		/* Start the tasks running. */
		// запуск таймера Count
					*((volatile uint16_t* const)(IOP1_BASE + 0x04)) = 0xAA50;
		
		vTaskStartScheduler();
	}

	OutString("WARNING! This point in main must not be reached!\n");
	/* If all is well we will never reach here as the scheduler will now be
	running.  If we do reach here then it is likely that there was insufficient
	heap available for the idle task to be created. */
	for( ;; );
}
/*-----------------------------------------------------------*/
void vApplicationIdleHook( void )
{
    for( ;; ){
				*((volatile uint16_t* const)(IOP1_BASE + 0x04)) = 0xAA51;
        // mips_getrand();
        SendByte('.');


	
    }
}


/*-----------------------------------------------------------*/

static void FillTask( void *pvParameters )
{
portTickType xNextWakeTime;
const unsigned long ulValueToSend = 8;
	/**((volatile uint16_t* const)(IOP1_BASE + 0x04)) = 0xAA54;*/
    for(int i = 0; i < 16; i++)
        data[i] = i + 5;

	/* Initialise xNextWakeTime - this only needs to be done once. */
	/*xNextWakeTime = xTaskGetTickCount();*/
	
///*((volatile uint64_t* const)(var3_addr)) = 0x0000FFFF000015A1;
for( ;;)
{
	/**((volatile uint16_t* const)(IOP1_BASE + 0x04)) = 0xAA54;*/
	/*vTaskDelayUntil( &xNextWakeTime, mainQUEUE_SEND_FREQUENCY_MS );
*/
	/* Send to the queue - causing the queue receive task to unblock and
	print out a message.  0 is used as the block time so the sending
	operation will not block - it shouldn't need to block as the queue
	should always be empty at this point in the code. */
	if( xQueueSend( xQueue, &ulValueToSend, 0 ) != pdPASS )
	 
	*((volatile uint16_t* const)(IOP1_BASE + 0x04)) = 0xAA01;
	else
		*((volatile uint16_t* const)(IOP1_BASE + 0x04)) = 0xAA03;
	vTaskDelete(NULL);
	*((volatile uint16_t* const)(IOP1_BASE + 0x04)) = 0xAA00;
}
	
}
/*-----------------------------------------------------------*/

static void CheckTask( void *pvParameters )
{
unsigned long ulReceivedValue;

	/* Wait until something arrives in the queue - this task will block
	indefinitely provided INCLUDE_vTaskSuspend is set to 1 in
	FreeRTOSConfig.h. */
	*((volatile uint16_t* const)(IOP1_BASE + 0x04)) = 0x55AA;

    for(;;){
	/*  To get here something must have been received from the queue, but
	is it the expected value?  If it is, print out a pass message, if no,
	print out a fail message. */

	
	xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY );
    	if( ulReceivedValue == 8 )
    	{*((volatile uint16_t* const)(IOP1_BASE + 0x04)) = 0x55AA;
            OutString("Test #1: ");
            for(int i = 0;i < 16;i++)
                if(data[i] != i + 5){
                    OutString("FAILED\n");
                    vTaskDelete(NULL);
                }
            // asm("pause");
    		OutString("PASSED\n");
           /* vTaskDelete(NULL);*/
    	}
    }
}
/*-----------------------------------------------------------*/
void vAssertCalled( const char *pcFileName, unsigned long ulLine )
{
    asm("di");
		*((volatile uint16_t* const)(IOP1_BASE + 0x04)) = 0xAA56;
	*((volatile uint64_t* const)(var3_addr)) = 0x0000FFFF0000AA56;
	OutString("\nin progress..in ");
	OutString(pcFileName);
    OutString(": 0x"); 
	//OutReg32((reg_t)ulLine); 
	OutReg32((reg_t)0xAA5555AA);
	SendByte('\n');

    OutString("\nfail in line");
	for (;;);
}

Other than the call to vTaskDelete, nothing stands out. Are you writing a new FreeRTOS port? If yes, then it may be an issue in the port itself. To narrow it down, can you create 2 tasks which just increment one variable each and verify that those are working?

I thouth that too, But for cycle over task delete/suspend starts again
Yes I trying to port but the seed of my question is in the problem of context switching
I also already noticed what problem in already ported STM32 FreeRTOS
It happens in case of two tasks with the same priority, after send data to queue, xqueuereceive do not triggered and idle condition processed only

That does not seem correct. I tried the following code -


QueueHandle_t xQueue;
/*-----------------------------------------------------------*/

static void prvSenderTask( void *pvParams )
{
    uint32_t valueToSend = 1;

    ( void ) pvParams;

    for( ;; )
    {
        xQueueSend( xQueue, &( valueToSend ), 0 );
        valueToSend++;

        vTaskDelay( pdMS_TO_TICKS( 100 ) );
    }
}
/*-----------------------------------------------------------*/

static void prvReceiverTask( void *pvParams )
{
    uint32_t receivedValue;

    ( void ) pvParams;

    for( ;; )
    {
        xQueueReceive( xQueue, &( receivedValue ), portMAX_DELAY );
        fprintf( stderr, "Received Value = %lu. \r\n", receivedValue ) ;
    }
}
/*-----------------------------------------------------------*/

void app_main( void )
{
	xQueue = xQueueCreate( 5, sizeof( uint32_t ) );

    xTaskCreate( prvSenderTask, "Sender", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
    xTaskCreate( prvReceiverTask, "Reveiver", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );

    vTaskStartScheduler();
}
/*-----------------------------------------------------------*/

And here is the output I see -

Received Value = 1.
Received Value = 2.
Received Value = 3.
Received Value = 4.
Received Value = 5.
Received Value = 6.
Received Value = 7.
Received Value = 8.
Received Value = 9.
Received Value = 10.

Clearly receiver task is executing.

Thank you for your en example!
I tried to execute your exam and I got what I after start sheduler I havent got into any task
Instead of that Im stay in cycle between foolowing functions:

  1. portTASK_FUNCTION
  2. if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 )
  3. static void prvCheckTasksWaitingTermination( void )

Now I see what you right, its seems to be the porting problem…

I am closing this thread. Feel free to open a new one if you need any more help.