xSemaphoreTake (binary) not waiting to be given?

leviatan1 wrote on Wednesday, August 06, 2014:

Hello, i have this dspic30F project im using interrupts from uart module, i have organized my projec into 3 files. “main.c” “subfunctions.c” and “subfunctions.h”

The problem i have is that one task should be unblocked from the RX UART ISR taking a binary semaphore, but it seems to take the semaphore and unblock even if the semaphore in not “given”.

i will put the code regarding the malfunction only, i have no warnings or errors.

main.c:

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

xSemaphoreHandle Mutex_I2C_Rx = 0;
xSemaphoreHandle Mutex_I2C_Tx = 0;		//viejo
SemaphoreHandle_t Sem_Ctrl = 0;			//nuevo
xTaskHandle I2C_HANDLE;
xTaskHandle I2C_RX;
xTaskHandle I2C_TX;	

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

        Queue_I2C_DataHander = xQueueCreate(5, sizeof(unsigned char));
        Queue_I2C_ACK = xQueueCreate(3, sizeof(unsigned char));

        /* Create standard Semaphores and Mutexes*/
        Mutex_I2C_Rx = xSemaphoreCreateMutex();
        Mutex_I2C_Tx = xSemaphoreCreateMutex();
        vSemaphoreCreateBinary(Sem_Ctrl);  //xSemaphoreCreatBinary WONT WORK GIVES ERROR

        /* Create the standard tasks. */
        xTaskCreate(data_I2C_HANDLE,"Handle I2C",128,NULL,4,&I2C_HANDLE);
        xTaskCreate(rx_I2C,"Recepcion SPI",128,NULL,5,&I2C_RX);
        xTaskCreate(tx_I2C,"Transmision SPI",128,NULL,3,&I2C_TX);

        /* Finally start the scheduler. */
        vTaskStartScheduler();

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

Subfunctions.h

INTERRUPT ROUTINE:

//INTERRUPCION RX UART
void _ISRFASTPSV _U1RXInterrupt()
    {
    IFS0bits.U1RXIF = 0;			//LIMPIO FLAG

    xSemaphoreGiveFromISR(Sem_Ctrl,NULL);
    }

TASK THAT SHOULD BE BLOCKED BUT SOMETIMES IT JUST GET THE SEMAPHORE WHEN INTERRUPT HAS NOT OCCURRED:

void rx_I2C(void *pvParameters)//Task receiving I2C data
{
//Variables que usa la Funcion INTERNAMENTE A LA TAREA
int i;
while(1)
	{
	//Esta tarea espera el mutex para poder usar la queue
	//Funcion que lee el buffer I2C
	if(xSemaphoreTake(Sem_Ctrl, portMAX_DELAY))
		{
		//usRx_data = ReadUART1();
		vTaskDelay(500/portTICK_RATE_MS);
		if(U1STAbits.OERR ==1)
			{
			U1STAbits.OERR = 0;
			}			


		}
	vTaskDelay(10);
	
	
	
//El codigo siguiente es en caso que la tarea salga del for
//si esto pasa la tarea se borra
vTaskDelete(NULL); 
} 

ADDITIONAL INFORMATION: EVERY TIME DATA ENTERS DE UART RX AN INTERRUPT IS GENERATED WHILE SIMULATING SOMETIMES Y RE-ENTER THE INTERRUPT 3 TIMES, WOULD THIS MAKE 3 SEMAPHORES AVAILABLE? EVEN IF MY SEMAPHORE ISN’T A COUNTING SEMAPHORE?

Should i use another method? should i use port yield from ISR? Which is the correct function for YIELD fromISR for dspic?

Any help is very apreciated thank you very much!

rtel wrote on Wednesday, August 06, 2014:

If you are using vSemaphoreCreateBinary() then the first call to xSemaphoreTake() will pass, even if the semaphore has not first been given. If you look at the implementation of vSemaphoreCreateBinary() you will see that it is created in the ‘available’ state.

vSemaphoreCreateBinary() is no longer the recommended way of creating a binary semaphore. Use xSemaphoreCreateBinary() instead.

WOULD THIS MAKE 3 SEMAPHORES AVAILABLE?

As this is a binary semaphore then it can only ever be available or not available (hence binary), so the task that takes the semaphore must ensure all events have been processed each time it is unblocked. If it were a counting semaphore then the task can just process one event each time it is unblocked as the semaphore effectively latches each event.

should i use port yield from ISR

It depends on your application. If it is important that the unblocked task executes immediately then yes it is important that you use the second parameter to the xSemaphoreGiveFromISR() function. Please see the documentation page for xSemaphoreGiveFromISR() for information (see the API documentation on the FreeRTOS.org website, and if you cannot locate it see the links provided to it in the quick start guide). The documentation page for the PIC24/dsPIC page will provide PIC24/dsPIC specific information on how to yield in the interrupt - and the official PIC24/dsPIC example application in the main FreeRTOS .zip file download will provide an example you can copy.

Note the UART examples in the FreeRTOS download are intended to test the RTOS port by deliberately loading the system rather than doing what a driver should normally do, which is minimise the system load by using FIFOs or DMA, etc.

Regards.

leviatan1 wrote on Wednesday, August 06, 2014:

When i use xSemaphoreCreateBinary(); this error pops UP

macro "xSemaphoreCreateBinary" passed 1 arguments, but takes just 0
In function 'main':
main.c:137: error: 'xSemaphoreCreateBinary' undeclared (first use in this function)
main.c:137: error: (Each undeclared identifier is reported only once
main.c:137: error: for each function it appears in.)

i asume because i have backward compatibility set to 1?

rtel wrote on Wednesday, August 06, 2014:

macro “xSemaphoreCreateBinary” passed 1 arguments, but takes just 0

Well xSemaphoreCreateBinary() doesn’t take any parameters, and I guess
that error is because you are passing in a parameter?

http://www.freertos.org/xSemaphoreCreateBinary.html