binary semaphore doesn't work if created in task that uses it ?

pataga
Posts: 33
Joined: Sat Aug 12, 2017 5:53 am

binary semaphore doesn't work if created in task that uses it ?

Postby pataga » Mon Jan 15, 2018 5:21 am

I am using a binary semaphore given from an isr that notifies a task to read new data from a device. The device generates data ready interrupts at approximately 400Hz, so the task should be also getting notifications from the semaphore at the same rate.

If i create the global semaphore in the task that uses it, then the task gets notifications at roughly the FreeRTOS tick rate ( in this case, 500Hz ) with some gaps.

If i create the semaphore in app_main before creating the task that uses it, everything works as expected, the notifications are processed at the data ready interrupt rate (~400Hz) without missing any.

Not sure if this is correct behavior, in any case, it would be nice to have an explanation.

Code: Select all

volatile SemaphoreHandle_t imuSemaphore;
	

void drdyHandler(void) {
	xSemaphoreGiveFromISR(imuSemaphore, NULL);
	}
	
static void imu_task() {

        // does not work if created here !
	//imuSemaphore = xSemaphoreCreateBinary();
	//attachInterrupt(pinDRDYINT, drdyHandler, RISING);

	// initialize device to generate data and data  ready interrupts ...

	while (1) {		
		if (xSemaphoreTake(imuSemaphore, portMAX_DELAY)) {
			LED_ON();
			// read the data from device
			LED_OFF();
			}
		}  
	}	


void app_main() {
	// init stuff ...
	
	// works if semaphore created here
	imuSemaphore = xSemaphoreCreateBinary();
	attachInterrupt(pinDRDYINT, drdyHandler, RISING);
	
	xTaskCreatePinnedToCore(&imu_task, "imutask", 2048, NULL, 20, NULL, 1);
	
	while(1) {
	        // do some stuff			
		delayMs(30);
		}		
	}
	
	
sem_good.png
sem_good.png (10.91 KiB) Viewed 1531 times
sem_bad.png
sem_bad.png (15.8 KiB) Viewed 1531 times

ESP_Sprite
Posts: 2262
Joined: Thu Nov 26, 2015 4:08 am

Re: binary semaphore doesn't work if created in task that uses it ?

Postby ESP_Sprite » Mon Jan 15, 2018 8:03 am

Do you get the same weird behaviour if you pin the task to CPU 0 instead of 1?

pataga
Posts: 33
Joined: Sat Aug 12, 2017 5:53 am

Re: binary semaphore doesn't work if created in task that uses it ?

Postby pataga » Mon Jan 15, 2018 11:16 am

Do you get the same weird behaviour if you pin the task to CPU 0 instead of 1?
OK, this is even stranger. If I pin the task to cpu 0, then the notification doesn't work correctly whether I create the semaphore and register the handler in app_main or in the task initialization code.

In both cases, I get the notifications at 500Hz with some skips every 3 or 4 notifications.

Went back to original configuration with task pinned to core 1 and semaphore/isr registration in app_main, and it works fine.
So at least my working configuration is repeatable :-D

Am using esp-idf downloaded on Jan 11.

ESP_igrr
Posts: 1359
Joined: Tue Dec 01, 2015 8:37 am

Re: binary semaphore doesn't work if created in task that uses it ?

Postby ESP_igrr » Mon Jan 15, 2018 12:44 pm

Please don't forget to pass 2nd BOOL* argument to xSemaphoreGiveFromISR and call portYIELD_FROM_ISR if it gets set to pdTRUE.
If you don't do that, preemption will only happen on the next FreeRTOS tick.

pataga
Posts: 33
Joined: Sat Aug 12, 2017 5:53 am

Re: binary semaphore doesn't work if created in task that uses it ?

Postby pataga » Mon Jan 15, 2018 1:55 pm

Please don't forget to pass 2nd BOOL* argument to xSemaphoreGiveFromISR and call portYIELD_FROM_ISR if it gets set to pdTRUE.
If you don't do that, preemption will only happen on the next FreeRTOS tick.
Ah ... so i was using it wrong all this time ! I found a correct example of semaphore usage, and fixed the ISR

Code: Select all

void drdyHandler(void) {
	static BaseType_t xHigherPriorityTaskWoken = pdFALSE;
	xSemaphoreGiveFromISR(imuSemaphore, &xHigherPriorityTaskWoken);
    if( xHigherPriorityTaskWoken == pdTRUE) {
        portYIELD_FROM_ISR(); // this wakes up imu_task immediately instead of on next FreeRTOS tick
		}
	}
	
and now it works fine. Thanks much ...

ESP_igrr
Posts: 1359
Joined: Tue Dec 01, 2015 8:37 am

Re: binary semaphore doesn't work if created in task that uses it ?

Postby ESP_igrr » Mon Jan 15, 2018 3:52 pm

Good to know. The variable does not need to be static, by the way.

JPMJPM
Posts: 8
Joined: Fri Oct 13, 2017 4:35 pm

Re: binary semaphore doesn't work if created in task that uses it ?

Postby JPMJPM » Wed Jan 30, 2019 8:50 pm

I have the same problem with an interrupt every 125 uS from a HW timer.

Any help ?.

Regards.

Code: Select all

SemaphoreHandle_t I2CSemaphore = NULL;

void IRAM_ATTR timer_group0_isr(void *para) {
	int timer_idx = (int) para;
  	uint32_t intr_status = TIMERG0.int_st_timers.val;
    	if((intr_status & BIT(timer_idx)) && timer_idx == TIMER_0) {
      		TIMERG0.hw_timer[timer_idx].update = 1;
		TIMERG0.int_clr_timers.t0 = 1;
      		TIMERG0.hw_timer[timer_idx].config.alarm_en = 1;
			
      		//gpio_set_level(test_pin, temp);
      		//temp = !temp;

		BaseType_t xHigherPriorityTaskWoken = pdFALSE;
		xSemaphoreGiveFromISR(I2CSemaphore, &xHigherPriorityTaskWoken);
    		if( xHigherPriorityTaskWoken == pdTRUE) {
        		portYIELD_FROM_ISR();
		}

		//xSemaphoreGiveFromISR(I2CSemaphore, NULL);
	}
}

static void IRAM_ATTR I2Chandler(void *pvParameter) {
	while (1) {
    		if (xSemaphoreTake(I2CSemaphore, portMAX_DELAY) == pdTRUE) {
			gpio_set_level(test_pin, temp);
      			temp = !temp;
    		}
  	}
}

void app_main() {

	I2CSemaphore = xSemaphoreCreateBinary();

	xTaskCreatePinnedToCore(&I2Chandler, "I2Chandler", 2048, NULL, 10, NULL, 1);

	example_tg0_timer0_init();
}
ok.png
gpio_set_level() only inside timer_group0_isr()
ok.png (4.74 KiB) Viewed 350 times
error.png
gpio_set_level() only inside I2Chandler()
error.png (7.11 KiB) Viewed 350 times

ESP_Sprite
Posts: 2262
Joined: Thu Nov 26, 2015 4:08 am

Re: binary semaphore doesn't work if created in task that uses it ?

Postby ESP_Sprite » Thu Jan 31, 2019 7:30 am

If anything, this is not the same problem, as if it were I'd expect the toggle rate to be the FreeRTOS tick frequency (depends on your configuration, but max 1KHz.) Do you happen to do stuff that writes to the flash? Because that will disable your interrupt and task temporarily.

JPMJPM
Posts: 8
Joined: Fri Oct 13, 2017 4:35 pm

Re: binary semaphore doesn't work if created in task that uses it ?

Postby JPMJPM » Thu Jan 31, 2019 11:50 am

There is not stuff that writes to the flash.

Anyway I changed FreeRTOS tick frequency from 100 Hz to 1 KHz in menuconfig
but the problem persists.

ESP_Sprite
Posts: 2262
Joined: Thu Nov 26, 2015 4:08 am

Re: binary semaphore doesn't work if created in task that uses it ?

Postby ESP_Sprite » Fri Feb 01, 2019 3:02 am

Can you try initializing the timer on CPU 1? (Put example_tg0_timer0_init(); within the task that you created, instead of in main.)

Who is online

Users browsing this forum: No registered users and 3 guests