[STM32F4] Creating a queue between two tasks corrupts data sent to vTaskDelayUntil

benoitdes wrote on Tuesday, April 15, 2014:

Hi everyone,

I’m using coocox and yagarto on a STM32F427 with FreeRTOS 7.5.2. I have 5 tasks running simultaneously with several priorities. All interrupts are set to NVIC_PriorityGroup_4 and until now preemption priorities were right.

TASK 1 : Higher priority (4). Synchronized with a timer interrupt and a binary semaphore. Receive messages through a queue from task 2 (buttons task). OK

TASK 2 : Priority (3). Check buttons of user interface periodically. Task delayed with a vTaskDelayUntil(). OK

TASK 3 : Priority (2). Show leds periodically. Task delayed with a vTaskDelayUntil(). OK

TASK 4 : Priority (1). Screen task. Cyclic task delayed with a vTaskDelayUntil(). Until now, OK

TASK 5 : Priority (1). Low priority and frequency task. Doesn’t do anything.

All of this worked well. I tried to add a queue filled by TASK 1 and read by TASK 4 (when it’s possible). Since this change, when i receive a message in the TASK 4 the values of pxPreviousWakeTime and xTimeIncrement seemed to be corrupted (become a random very large number).
And this TASK no longer executes periodically. Before receiving a message from this queue everything works fine.

I precise that i have enough heap configured, i use heap_4 and HighWaterMark of each task is sufficient.

Do you know what it could be ?

And do you know if there is a way to Block TASK 4 until a message arrive in the queue whereas this TASK has a lower priority than the sender ?

Thanks !

dumarjo wrote on Tuesday, April 15, 2014:

Hi,

Without showing the code that is use to fill the queue is hard to help.

Jonathan

rtel wrote on Tuesday, April 15, 2014:

In addition to Jonathan’s reply, are you using a recent version of FreeRTOS with configASSERT() defined? The most recent versions include additional assert() calls to help track down common configuration errors.

Regards.

benoitdes wrote on Tuesday, April 15, 2014:

Thanks for your answers,

Well, my code is like this.

In the main :


xQueueHandle xQueueMidiMessages;
xQueueHandle xQueueScreenMessages;
/* Declare a variable of type xSemaphoreHandle.  This is used to reference the
semaphore that is used to synchronize a task with an interrupt. */
xSemaphoreHandle xBinarySemaphoreCoreLoop;

int main(void)
{
	/* System Initialization. */
	SystemInit();
	SystemCoreClockUpdate();

	/* Before a semaphore is used it must be explicitly created */
	xBinarySemaphoreCoreLoop = xSemaphoreCreateCounting(3,0);

	// We need to know the size of an internal midi message ! 20 messages of uint32_t they said.
	xQueueMidiMessages = xQueueGenericCreate(20, 32, (unsigned char)0);
	xQueueScreenMessages = xQueueGenericCreate(5, 32, (unsigned char)0);

	GPIO_Config();			// Config des E/S et des RCC

	Reset_all_high_luminosity_step();
	Update_leds_registers(0,0,0);
	Display_Led_Startup();

	Interrupt_Config(); 	// BPM & Encoders 1, 2, 4, 5, 6 interrupt config

	SPI2_Config(); 			// Config SPI pour l'ecran

	DAC_Config();
	USART_Config(); 		// Config du midi in, midi out et de l'interruption sur midi in

	Interrupt_Config(); 	// BPM & Encoders 1, 2, 4, 5, 6 interrupt config

	i2C_Config();			// Config i2C pour le touchpad
	ADC_Config(); 			// Config des 4 entrees analogiques

	screen_init();
	tab_screen_init();
	set_zone_white(0,0,127,63);

	//USB_Stop();
	USB_Config();

	// Force analog outputs at 0V
	GPIO_ResetBits(GPIOB, GPIO_Pin_11); //GATE
	Set_DAC_Ch1_Voltage(0); // CV
	Set_DAC_Ch2_Voltage(0); // ANALOG

	// All note off (MIDI + USB)
	Send_All_Note_Off();

	if (xBinarySemaphoreCoreLoop != NULL && xQueueMidiMessages != NULL && xQueueScreenMessages != NULL) {

		// Allumage de la led de debug SWD
		Switch_Leds(LED_SWD_OFF);

		// This is the timer for the core loop (accuracy => us) TIM2
		TIM_Config();
		// Interrupt triggered by the timer TIM2
		EnableTimerInterrupt();

		//vTrack_Loop needs a stack size in bytes after the task name
		xTaskCreate(vTrack_Loop, (signed char *)"Core_Loop", 512, NULL, 4, NULL);

		// vIHM_Checker is launched every 5 ms, can you believe it ?
		xTaskCreate(vIHM_Checker, (signed char *)"IHM_Loop", 128, NULL, 3, NULL);

		// vDisplay_Led is launched every 1 ms
		xTaskCreate(vDisplay_Led, (signed char *)"Led_Loop", 128, NULL, 2, NULL);

		// vUpdate_Screen is launched every 30 ms
		xTaskCreate(vUpdate_Screen, (signed char *)"Screen_Loop", 128, NULL, 1, NULL);

		// vCheck_Slowly is launched every 2 seconds
//		xTaskCreate(vCheck_Slowly, (signed char *)"Slow_Loop", 1024, NULL, 1, NULL);

		uint16_t prio = configKERNEL_INTERRUPT_PRIORITY;

		vTaskStartScheduler();
	}

	for(;;);

	while(1);
}

From Core_loop, the Sender :


extern xQueueHandle xQueueScreenMessages;


void Send_To_Screen(uint8_t message_type, uint16_t content){

	uint32_t mess_to_send = (message_type << 16) | content;

	xQueueGenericSend(xQueueScreenMessages, &mess_to_send, 0, pdFALSE);
}

In Screen_Loop, the receiver :

/*
 * The purpose of this task is to update the screen
 */
void vUpdate_Screen( void *pvParameters )
{
	uint32_t uxHighWaterMark;
	/* Inspect our own high water mark on entering the task. */
	uxHighWaterMark = uxTaskGetStackHighWaterMark( NULL );

	portTickType xLastWakeTime;
	xLastWakeTime = xTaskGetTickCount();
	/* This task is launched every 30ms */
	portTickType currentPortTick = 30/(portTICK_RATE_MS);
	portBASE_TYPE xStatus = pdFALSE;
	const uint32_t message_from_core;

	/* Variables */
	static uint8_t Count = 0;
	static uint8_t Logo_OFF = FALSE;

	/* Start of the task vSystem_Timer */
	TASK_LOOP
	{
		// DEBUG
		if (uxHighWaterMark < 10){while(1);}

		xStatus = xQueueReceive(xQueueScreenMessages, &message_from_core, 0);
		if (xStatus == pdPASS) {ReadAndDecodeFromCore(message_from_core);}
	
			/* Delay */
		vTaskDelayUntil( &xLastWakeTime, currentPortTick);
	}
} 

The first time i receive something through the queue, when returning from xQueueReceive, xLastWakeTime and currentPortTick seemed corrupted.

I have this kind of assert defined :

define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }

The new types of assert are in version 8.0.0 of FreeRTOS ?

Regards,

Benoit

dumarjo wrote on Tuesday, April 15, 2014:

Hi,

Le 2014-04-15 09:31, BenoitDes a écrit :

Thanks for your answers,

Well, my code is like this.

In the main :

xQueueHandle xQueueMidiMessages;
xQueueHandle xQueueScreenMessages;
/* Declare a variable of type xSemaphoreHandle. This is used to reference the
semaphore that is used to synchronize a task with an interrupt. */
xSemaphoreHandle xBinarySemaphoreCoreLoop;

int main(void)
{
/* System Initialization. */
SystemInit();
SystemCoreClockUpdate();

 /* Before a semaphore is used it must be explicitly created */
 xBinarySemaphoreCoreLoop = xSemaphoreCreateCounting(3,0);

 // We need to know the size of an internal midi message ! 20 messages of uint32_t they said.
 xQueueMidiMessages = xQueueGenericCreate(20, 32, (unsigned char)0);
 xQueueScreenMessages = xQueueGenericCreate(5, 32, (unsigned char)0);

why not using the macro to create your queue directly ?
Also from the comment above the creation of the Midi queue this should
look like this

xQueueMidiMessages = xQueueCreate(20, sizeof(uint32_t));
xQueueScreenMessages = xQueueCreate(20, sizeof(uint32_t));

 GPIO_Config();          // Config des E/S et des RCC

 Reset_all_high_luminosity_step();
 Update_leds_registers(0,0,0);
 Display_Led_Startup();

 Interrupt_Config();     // BPM & Encoders 1, 2, 4, 5, 6 interrupt config

 SPI2_Config();          // Config SPI pour l'ecran

 DAC_Config();
 USART_Config();         // Config du midi in, midi out et de l'interruption sur midi in

 Interrupt_Config();     // BPM & Encoders 1, 2, 4, 5, 6 interrupt config

 i2C_Config();           // Config i2C pour le touchpad
 ADC_Config();           // Config des 4 entrees analogiques

 screen_init();
 tab_screen_init();
 set_zone_white(0,0,127,63);

 //USB_Stop();
 USB_Config();

 // Force analog outputs at 0V
 GPIO_ResetBits(GPIOB, GPIO_Pin_11); //GATE
 Set_DAC_Ch1_Voltage(0); // CV
 Set_DAC_Ch2_Voltage(0); // ANALOG

 // All note off (MIDI + USB)
 Send_All_Note_Off();

 if (xBinarySemaphoreCoreLoop != NULL && xQueueMidiMessages != NULL && xQueueScreenMessages != NULL) {

     // Allumage de la led de debug SWD
     Switch_Leds(LED_SWD_OFF);

     // This is the timer for the core loop (accuracy => us) TIM2
     TIM_Config();
     // Interrupt triggered by the timer TIM2
     EnableTimerInterrupt();

     //vTrack_Loop needs a stack size in bytes after the task name
     xTaskCreate(vTrack_Loop, (signed char *)"Core_Loop", 512, NULL, 4, NULL);

     // vIHM_Checker is launched every 5 ms, can you believe it ?
     xTaskCreate(vIHM_Checker, (signed char *)"IHM_Loop", 128, NULL, 3, NULL);

     // vDisplay_Led is launched every 1 ms
     xTaskCreate(vDisplay_Led, (signed char *)"Led_Loop", 128, NULL, 2, NULL);

     // vUpdate_Screen is launched every 30 ms
     xTaskCreate(vUpdate_Screen, (signed char *)"Screen_Loop", 128, NULL, 1, NULL);

     // vCheck_Slowly is launched every 2 seconds

// xTaskCreate(vCheck_Slowly, (signed char *)“Slow_Loop”, 1024, NULL, 1, NULL);

     uint16_t prio = configKERNEL_INTERRUPT_PRIORITY;

     vTaskStartScheduler();
 }

 for(;;);

 while(1);

}

From Core_loop, the Sender :

extern xQueueHandle xQueueScreenMessages;

void Send_To_Screen(uint8_t message_type, uint16_t content){

 uint32_t mess_to_send = (message_type << 16) | content;

 xQueueGenericSend(xQueueScreenMessages, &mess_to_send, 0, pdFALSE);

}

In Screen_Loop, the receiver :

/*

  • The purpose of this task is to update the screen
    */
    void vUpdate_Screen( void pvParameters )
    {
    uint32_t uxHighWaterMark;
    /
    Inspect our own high water mark on entering the task. */
    uxHighWaterMark = uxTaskGetStackHighWaterMark( NULL );

    portTickType xLastWakeTime;
    xLastWakeTime = xTaskGetTickCount();
    /* This task is launched every 30ms */
    portTickType currentPortTick = 30/(portTICK_RATE_MS);
    portBASE_TYPE xStatus = pdFALSE;
    const uint32_t message_from_core;

    /* Variables */
    static uint8_t Count = 0;
    static uint8_t Logo_OFF = FALSE;

    /* Start of the task vSystem_Timer */
    TASK_LOOP
    {
    // DEBUG
    if (uxHighWaterMark < 10){while(1);}

     xStatus = xQueueReceive(xQueueScreenMessages, &message_from_core, 0);
     if (xStatus == pdPASS) {ReadAndDecodeFromCore(message_from_core);}
    
         /* Delay */
     vTaskDelayUntil( &xLastWakeTime, currentPortTick);
    

    }
    }
    the first look look OK to me. What happend if you don’t call
    ReadAndDecodeFromCore ?

regards

Jonathan


Ce courrier électronique ne contient aucun virus ou logiciel malveillant parce que la protection avast! Antivirus est active.
http://www.avast.com

rtel wrote on Tuesday, April 15, 2014:

A couple of points:

uxHighWaterMark only ever seems to be set on entry into the task - which is before the task has really used much stack. Try updating it on every loop. Do you have a stack overflow hook defined? If not I would definitely recommend defining one: http://www.freertos.org/Stacks-and-stack-overflow-checking.html

message_from_core is defined as a const but its value is not being set at definition (as would need to be the case for a const), and then you are trying to update it by passing it into xQueueReceive() despite it being declared const. I’m not sure what the compiler will make of that, probably nothing at low optimisation levesl, but a lot at high optimisation levels. I would expect this to generate multiple compiler warnings.

You are calling xQueueGenericSend() which is not part of the documented API. You should be calling xQueueSend(), xQueueSendToBack() (which is the same as xQueueSend()), or xQueueSendToFront().

Likewise you are calling xQueueGenericCreate() which is not a part of the documented API. You should be calling xQueueCreate(). When you do create xQueueScreenMessages (using the wrong API function) you are setting the item size to 32, but when you send and receive from the queue you are using a variable that has a size of 4 -> this will definitely cause corruption and is no doubt the root cause of your problem.

Regards.

dumarjo wrote on Tuesday, April 15, 2014:

Hi.

Le 2014-04-15 09:58, Real Time Engineers ltd. a écrit :

A couple of points:

uxHighWaterMark only ever seems to be set on entry into the task -
which is before the task has really used much stack. Try updating it
on every loop. Do you have a stack overflow hook defined? If not I
would definitely recommend defining one:
http://www.freertos.org/Stacks-and-stack-overflow-checking.html

message_from_core is defined as a const but its value is not being set
at definition (as would need to be the case for a const), and then you
are trying to update it by passing it into xQueueReceive() despite it
being declared const. I’m not sure what the compiler will make of
that, probably nothing at low optimisation levesl, but a lot at high
optimisation levels. I would expect this to generate multiple compiler
warnings.

You are calling xQueueGenericSend() which is not part of the
documented API. You should be calling xQueueSend(), xQueueSendToBack()
(which is the same as xQueueSend()), or xQueueSendToFront().

Likewise you are calling xQueueGenericCreate() which is not a part
of the documented API. You should be calling xQueueCreate(). When you
do create xQueueScreenMessages (using the wrong API function) you are
setting the item size to 32, but when you send and receive from the
queue you are using a variable that has a size of 4 -> this will
definitely cause corruption and is no doubt the root cause of your
problem.

i’ missed that one :slight_smile:

Regards.


[STM32F4] Creating a queue between two tasks corrupts data sent to
vTaskDelayUntil
https://sourceforge.net/p/freertos/discussion/382005/thread/91ecf944/?limit=25#012e


Sent from sourceforge.net because you indicated interest in
https://sourceforge.net/p/freertos/discussion/382005/

To unsubscribe from further messages, please visit
https://sourceforge.net/auth/subscriptions/


This message has been scanned for viruses and
dangerous content by MailScanner http://www.mailscanner.info/, and is
believed to be clean.


Ce courrier électronique ne contient aucun virus ou logiciel malveillant parce que la protection avast! Antivirus est active.
http://www.avast.com

benoitdes wrote on Tuesday, April 15, 2014:

I was sure it was a dumb cause…

I tried several things that’s why generic functions where used. All the points are corrected. And of course now it works well. Strange i didn’t see this memory issue before with xQueueMidiMessages which i use for two month now…

Thanks a lot !

Benoit

dumarjo wrote on Tuesday, April 15, 2014:

Hi,

it’s only a chance that you don’t have seen the bug.

Jonathan