Reputation: 1
i'm actually working on my final project for graduation. I'm using FreeRTOS on STM32F4 discovery. It all works properly, but the tasks are not ordered as i like. they execute in this cycle : task3 twice, task2 once, then again task3 twice and tas2 once and then task1 once. I want them to execute iin this order : task1 then task2 then task3. Thank you!
Here is a portion of my code:
/* The period of the example software timer, specified in milliseconds, and converted to ticks using the portTICK_RATE_MS constant. */
#define mainSOFTWARE_TIMER_PERIOD_MS ( 1000 / portTICK_RATE_MS )
int main(void)
{
/* Configure the system ready to run the demo. The clock configuration
can be done here if it was not done before main() was called. */
prvSetupHardware();
/* Create the queue used by the queue send and queue receive tasks.
http://www.freertos.org/a00116.html */
xQueue = xQueueCreate( mainQUEUE_LENGTH, /* The number of items the queue can hold. */
sizeof( uint32_t ) ); /* The size of each item the queue holds. */
/* Add to the registry, for the benefit of kernel aware debugging. */
vQueueAddToRegistry( xQueue, ( signed char * ) "MainQueue" );
/* Create the semaphore used by the FreeRTOS tick hook function and the
event semaphore task. */
vSemaphoreCreateBinary( xEventSemaphore );
/* Add to the registry, for the benefit of kernel aware debugging. */
vQueueAddToRegistry( xEventSemaphore, ( signed char * ) "xEventSemaphore" );
/* Create the MPXV7002DP task */
xTaskCreate( vMPXV7002DPTask, /* The function that implements the task. */
( signed char * ) "MPXV7002DP", /* Text name for the task, just to help debugging. */
configMINIMAL_STACK_SIZE, /* The size (in words) of the stack that should be created for the task. */
NULL, /* A parameter that can be passed into the task. Not used in this simple demo. */
configMAX_PRIORITIES - 1, /* The priority to assign to the task. tskIDLE_PRIORITY (which is 0) is the lowest priority. configMAX_PRIORITIES - 1 is the highest priority. */
NULL ); /* Used to obtain a handle to the created task. Not used in this simple demo, so set to NULL. */
/* Create the MPU9250 task */
xTaskCreate( vMPU9250Task,
( signed char * ) "MPU9250",
configMINIMAL_STACK_SIZE,
NULL,
configMAX_PRIORITIES - 1,
NULL );
/* Create the MPL3115A2 task */
xTaskCreate( vMPL3115A2Task,
( signed char * ) "MPL3115A2",
configMINIMAL_STACK_SIZE,
NULL,
configMAX_PRIORITIES - 1,
NULL );
/* Create the TOPC task */
//xTaskCreate( vToPcTask,
// ( signed char * ) "ToPc",
// configMINIMAL_STACK_SIZE,
// NULL,
//configMAX_PRIORITIES - 4,
//NULL );
/* Start the tasks and timer running. */
vTaskStartScheduler();
}
static void vMPXV7002DPTask(void *pvParameters)
{
int convertedValue,pressure,v;
for(;;)
{
if(xSemaphoreTake( xEventSemaphore, mainSOFTWARE_TIMER_PERIOD_MS ))
{USART_puts(USART1, "mpxv begin\n\r");
ADC_SoftwareStartConv(ADC1);//Start the conversion
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));//Processing the conversion
convertedValue = ADC_GetConversionValue(ADC1); //Return the converted dat
convertedValue=(5*convertedValue)/255;
pressure=(convertedValue+0.0625*4)-0.5;
v=sqrt((2*pressure)/1.293);
USART_puts(USART1, "mpxv end\n\r");
xSemaphoreGive( xEventSemaphore );
}
vTaskDelay( mainSOFTWARE_TIMER_PERIOD_MS );
}
}
static void vMPU9250Task(void *pvParameters)
{
int16_t xa,ya,za,xg,yg,zg,xm,ym,zm;
uint8_t res[22];
for( ;; )
{
if(xSemaphoreTake( xEventSemaphore, mainSOFTWARE_TIMER_PERIOD_MS ))
{USART_puts(USART1, "mpu begin\n\r");
SPI_Tx(0x25,0x0C|0x80);//read from slv0
SPI_Tx(0x26,0x03);//reg from which start reading
SPI_Tx(0x27,0x87);//read 7 bytes
SPI_Rx_seq(0x3A,res,22);
xa=((int16_t)res[1]<<8)|res[2];
xa/=8192;
ya=((int16_t)res[3]<<8)|res[4];
ya/=8192;
za=((int16_t)res[5]<<8)|res[6];
za/=8192;
xg=((int16_t)res[9]<<8)|res[10];
xg/=131;
yg=((int16_t)res[11]<<8)|res[12];
yg/=131;
zg=((int16_t)res[13]<<8)|res[14];
zg/=131;
//AK8963_Rx_seq( 0x03, mag_asax, 7);
//SPI_Rx_seq(0x49,mag_asax,7);
xm=((int16_t)res[16]<<8)|res[15];
ym=((int16_t)res[18]<<8)|res[17];
zm=((int16_t)res[20]<<8)|res[19];
USART_puts(USART1, "mpu end\n\r");
xSemaphoreGive( xEventSemaphore );
}
vTaskDelay( mainSOFTWARE_TIMER_PERIOD_MS/2 );
}
}
static void vMPL3115A2Task( void *pvParameters )
{
uint8_t altitude[3];
uint32_t x;
char alt[1];
for( ;; )
{
if(xSemaphoreTake( xEventSemaphore, mainSOFTWARE_TIMER_PERIOD_MS ))
{USART_puts(USART1, "mpl begin\n\r");
Read_IIC1_seq(0x60<<1, 0x01, altitude, 3);
x=altitude[0];x<<=8;
x|=altitude[1];x<<=8;
x|=altitude[2];x>>=4;
x/=49920;
USART_puts(USART1, "mpl end\n\r");
xSemaphoreGive( xEventSemaphore );
}
vTaskDelay( mainSOFTWARE_TIMER_PERIOD_MS/4 );
}
}
Upvotes: 0
Views: 925
Reputation: 7057
Look at the call to vTaskDelay()
in each task function. One task delays for PERIOD
, the next for PERIOD/2
, and the third for PERIOD/4
. The task that delays for PERIOD/4
will be ready to run four times for every time that the task that delays for PERIOD
will be ready to run. This is why you are seeing one task run four times, the next two times, and the third once. Why did you use different delay periods if you want the tasks to run at the same rate?
As for which task runs first at the beginning, that is going to depend on how the FreeRTOS scheduler is implemented. You assigned the same priority (configMAX_PRIORITIES - 1
) to each task in the calls to xTaskCreate()
. The FreeRTOS scheduler is probably using its round-robin scheduling algorithm for tasks with the same priority. And I'm guessing that the scheduler readies the tasks in the order they were created (or maybe reverse order). So you might be able to affect the ready order by changing the creation order. But I'm just guessing and you should look at the source code for the FreeRTOS scheduler to learn what it does. Or maybe you should give the tasks different priorities. Then the FreeRTOS scheduler should make the task with the highest priority ready to run first.
Upvotes: 2