dsP30F4013 starving tasd problems

leviatan1 wrote on Monday, June 23, 2014:

Hello, i managed to compile my code for my dsp30f project as follows:

main.c

xQueueHandle Queue_I2C_DataHander=0x0000;
xQueueHandle Queue_I2C_ACK=0x0000;

/******************Semaphores and Task Handles****************/

xSemaphoreHandle Mutex_I2C_Rx =0;
xSemaphoreHandle Mutex_I2C_Tx=0;
xSemaphoreHandle Mutex_I2C_Ctrl=0;
xTaskHandle I2C_HANDLE;

int main( void )
{
/* Create the standar Queues*/

Queue_I2C_DataHander = xQueueCreate(3, sizeof(unsigned short));
Queue_I2C_ACK = xQueueCreate(3, sizeof(unsigned short));

/* Create standard Semaphores and Mutexes*/

Mutex_I2C_Rx = xSemaphoreCreateMutex();
Mutex_I2C_Tx = xSemaphoreCreateMutex();
Mutex_I2C_Ctrl= xSemaphoreCreateMutex();

/* Create the standard tasks. */

xTaskCreate(prep_HARD,"Config Hardware",100,NULL,6,NULL);
xTaskCreate(data_I2C_HANDLE,"Handle I2C",100,NULL,4,&I2C_HANDLE);
xTaskCreate(rx_I2C,"Recepcion SPI",128,NULL,4,NULL);
xTaskCreate(tx_I2C,"Transmision SPI",128,NULL,4,NULL);


/* Finally start the scheduler. */

vTaskStartScheduler();

/* Will only reach here if there is insufficient heap available to start
the scheduler. */
return 0;
}

now i have another filte to define the tasks:

subfunctions.h

/*********************DEFINICIONES DE TAREAS*********************/
void prep_HARD(void *pvParameters)//Task configs Hardware
    {
	//Variables que usa la Funcion
	unsigned short usI2CCONValue;
    unsigned short usI2CBRGValue;//ACA VA el valor del Baud gen para 100KHz
for(;;)
	{
	//Funciones que configuran el hardware
	//OSC: ((10MHz/2)*8)/4 = FCY = 10 Mhz
	TRISFbits.TRISF6 = 0;        //Output RF6/SCK1
	TRISFbits.TRISF2 = 1;        //Input  RF2/SDI1
	TRISFbits.TRISF3 = 0;        //Output RF3/SDO1
	ADPCFGbits.PCFG2 = 1;          //Pin RB2 analgoni
	TRISBbits.TRISB2 = 0;        //Output RB2 (SDC_CS RB2)
	LATBbits.LATB2 = 1;
	usI2CBRGValue = 0x05A; //100Khz para 10 MHZ de FCY
	usI2CCONValue = I2C_ON &
                    I2C_IDLE_CON &
                    I2C_CLK_REL &
                    I2C_IPMI_DIS &
                    I2C_7BIT_ADD &
                    I2C_SLW_DIS &
                    I2C_SM_DIS &
                    I2C_GCALL_DIS &
                    I2C_STR_DIS &
                    I2C_ACK &
                    I2C_ACK_DIS &
                    I2C_RCV_DIS &
                    I2C_STOP_DIS &
                    I2C_RESTART_DIS &
                    I2C_START_DIS;
   	OpenI2C(usI2CCONValue,usI2CBRGValue);
	vTaskDelete (NULL);//vTaskDelete se activa en FREERTOSconfig.h
	} 
    }


void data_I2C_HANDLE(void *pvParameters)//Task HANDLE I2C DATA I/O
{
	//Variables que usa la Funcion INTERNAMENTE
	usAnalisis_data=0x00;

for(;;)
	{
	//Funcion que maneja entrada y salida del I2C
	
	xQueueReceive(Queue_I2C_DataHander,&usHan_data,100);
	if(usHan_data==0x00)
		{
		//vTaskSuspend(NULL);
		}
	xQueuePeek(Queue_I2C_DataHander,&usHan_data,100);
	if(usHan_data==0xAA)
		{
		usTx_data==0x00;
		xQueueReceive(Queue_I2C_DataHander,&usAnalisis_data,100);
		//mover motores, podria hacer una rutina que mueva motores
		//y llamarla con un "for" para la cantidad de pasos
		//ahora enviar dato para jeringas ACK 0xFX
		usTx_add=(SLAVE_ADD1&W_I2C);
		usTx_data=0xFF;//para este caso el analisis es F entonces
						//ACK= 0xFX + F = 0xFF
			 
			
		}
	usRx_data=0xBB;			
	}
//El codigo siguiente es en caso que la tarea salga del for
//si esto pasa la tarea se borra
vTaskDelete(NULL); 
}




void rx_I2C(void *pvParameters)//Task receiving I2C data
{
	//Variables que usa la Funcion INTERNAMENTE A LA TAREA


for(;;)
	{
	//Esta tarea espera el mutex para poder usar la queue
	//Funcion que lee el buffer I2C
	

	if(xSemaphoreTake(Mutex_I2C_Ctrl, 50))
		{
		usRx_data=0xAA;
		xQueueSend(Queue_I2C_DataHander, &usRx_data,100);//Pone el dato en la queue
		xSemaphoreGive(Mutex_I2C_Ctrl);
		}
	vTaskDelay(200);	
	
	//vTaskResume(I2C_HANDLE);
	
	}
//El codigo siguiente es en caso que la tarea salga del for
//si esto pasa la tarea se borra
vTaskDelete(NULL); 
} 

void tx_I2C(void *pvParameters)//Task sending I2C data
{
//Variables que usa la Funcion INTERNAMENTE

for(;;)
	{
	//Funcion que escribe el buffer I2C
	if(xSemaphoreTake(Mutex_I2C_Ctrl, 50))
		{
		usRx_data=0xBB;
		xQueueSend(Queue_I2C_DataHander, &usRx_data,100);//Pone el dato en la queue
		xSemaphoreGive(Mutex_I2C_Ctrl);
		}
	vTaskDelay(200);
	/*IdleI2C();
    StartI2C();
	while(I2CCONbits.SEN);//se pone low cuando la secuencia start termina
	MasterWriteI2C(usTx_add);//slave address entre parentesis mas bit R/W
	IdleI2C();
    MasterWriteI2C(usTx_data);
    StopI2C();*/
	
	
	}
//El codigo siguiente es en caso que la tarea salga del for
//si esto pasa la tarea se borra
vTaskDelete(NULL); 
}

The higher task runs once and deletes itself this is ok. Now the other 3 task have the same priority

1-the “data_I2C_HANDLE” Task is blockes waiting the queue this is ok.
2-the “rx_I2C” task takes the semaphore and goes one iteration then give the semaphore and blocks.
3-the “rx_I2C” task takes the semaphore after the previous task exceutes and gives the semaphore but it takes the semaphore again and again starving the other two tasks.

after that i get a loop inside the task.c arround this code:

static portTASK_FUNCTION( prvIdleTask, pvParameters )
{
/* Stop warnings. */
( void ) pvParameters;

for( ;; )
{
	/* See if any tasks have been deleted. */
	prvCheckTasksWaitingTermination();

and i keep here forever… could you help me? thanks.

edwards3 wrote on Monday, June 23, 2014:

Because the tasks all have the same priority how it runs will depend on which task is created first. One possible scenario would be

data_I2C_HANDLE blocks to wait for data.

rx_I2C takes the mutex then posts to the queue, causing a task switch

tx_I2C runs but cant get the mutex as rx_I2C still has it

data_I2C_HANDLE runs and removes the data from the queue, then peeks on the queue. The queue must be empty so there is another task switch

rx_I2C runs again and gives back the semaphore so tx_I2C starts to run

tx_I2C takes the semaphore and writes to the queue, another task switch

Queue_I2C_DataHander runs again and the peek completes. There is still data in the queue and Queue_I2C_DataHander reads the queue again removing the data before blocking on a peek again

tx_I2C runs again giving the semaphore back before blocking for 200 ticks

rx_I2C runs again and blocks for 200 ticks too

Now all the tasks are blocked. Queue_I2C_DataHander is blocked for 100 ticks and the other two tasks for 200 ticks so the idle task will run for 100 ticks, after which Queue_I2C_DataHander will unblock because it times out. Even though the queue must be empty Queue_I2C_DataHander tries to process the non existing peeked data because it does not test the QueuePeek return value to see if any data was actually received. That is presumably an an error.

I guess this is not how you want the code to run. The structure is very confused, for example, why create a task that does not do anything other than initialize the hardware before it deletes itself rather than initialize the hardware from a simple function call in main() or in another task?

leviatan1 wrote on Monday, June 23, 2014:

these task are “dummy” because i want to check that all task get CPU time when the others are in delay, after that i will add the true code, but i need that i2c hander task get blocked from queue, and i need that the other 2 task just wait there reading or writing acordingly i need it.

But for now im testing that rx and tx task switch between them but it wont happen tx task will give the semaphore and take it again before rx task so rx task remains blocked and tx keeps running forever, i dont know if i should use task yield or change the priority. the problem is that this shouldnt happen.
For what i understand when a task enter delay the next task should star because it was more time in the blocked state.

leviatan1 wrote on Tuesday, June 24, 2014:

i MUST ADD, I CHANGED MY FOR(;:wink: INTO WHILE(1) AND IT STARTED TO WORK MORE CONSISTENT. I DONT KNOW IF IT HAS SOMETHING TO DO, BUT IT IS HAPPENNING ALSO I USED SOME PRIORITY CHANGE FOR THE TASK AND IT SEEMS TO BEAHAVE MORE ACCORDINGLY TO WHAT I NEED. im sorry my CAPS ill update later with the code.