Lsm6dsox interrupt task

Hello,
I want to implement an application in STm32 cube ide using freertos cimsis V2.
There are tasks with the same priority in the application. the task I will create will have the same priority. I want the task to perform some operations according to this interrupt by taking an interrupt from a sensor in this task. I tried using semaphore but without success. It does not branch to this newly created task while it is constantly continuing other task operations. (preemptive scheduling.) When this interrupt comes, it should stop other task execution. so they are all set to same priority. but it cannot switch to the interrupt task. semaphore didn’t work. What could be the reason? Can you give an idea?

You should show the code of the ISR and post-processing task. Otherwise it’s impossible to guess. Interrupt priority might be also important. Which MCU are you using and which FreeRTOS version ?
Stopping all other tasks on interrupt sounds strange (I’d say broken) and might be hard to get right.

void Thread_CheckButton(void *argument)
{
	(void) argument;
	UINT8 file_metadata_u8[512] = { 0 };
	UINT  bytes_written = 0;
	UINT32 timestamp_u32 = 0;
	struct calendar_date datetime_t = { 0 };
	UINT8 filename_u8[20] = { 0 };
	FRESULT fres;
	UINT8 record_error = 0;


	/* Infinite loop */
	for(;;)
	{
		osDelay(100);
		if (GPIO_PIN_SET != HAL_GPIO_ReadPin(MCU_BUTTON_GPIO_Port, MCU_BUTTON_Pin))
		{
			osThreadYield();

			switch (GL_device_t.state_t.recording_state)
				{
					case RS_NOT_STARTED:
					{
						if (GPIO_PIN_SET == HAL_GPIO_ReadPin(MCU_LED1_B_GPIO_Port, MCU_LED1_B_Pin))
						{
							HAL_GPIO_WritePin(MCU_LED1_B_GPIO_Port, MCU_LED1_B_Pin, GPIO_PIN_RESET);
						}

						if (GPIO_PIN_SET == HAL_GPIO_ReadPin(MCU_LED1_R_GPIO_Port, MCU_LED1_R_Pin))
						{
							HAL_GPIO_WritePin(MCU_LED1_R_GPIO_Port, MCU_LED1_R_Pin, GPIO_PIN_RESET);
						}

						if (GPIO_PIN_SET == HAL_GPIO_ReadPin(MCU_LED1_G_GPIO_Port, MCU_LED1_G_Pin))
						{
							HAL_GPIO_WritePin(MCU_LED1_G_GPIO_Port, MCU_LED1_G_Pin, GPIO_PIN_RESET);
						}
						//Yellow
						HAL_GPIO_WritePin(MCU_LED1_R_GPIO_Port, MCU_LED1_R_Pin, GPIO_PIN_SET);
						HAL_GPIO_WritePin(MCU_LED1_G_GPIO_Port, MCU_LED1_G_Pin, GPIO_PIN_SET);

						break;
					}

					case RS_STARTED:
					{

						if (GPIO_PIN_SET == HAL_GPIO_ReadPin(MCU_LED1_B_GPIO_Port, MCU_LED1_B_Pin))
						{
							HAL_GPIO_WritePin(MCU_LED1_B_GPIO_Port, MCU_LED1_B_Pin, GPIO_PIN_RESET);
						}

						if (GPIO_PIN_SET == HAL_GPIO_ReadPin(MCU_LED1_R_GPIO_Port, MCU_LED1_R_Pin))
						{
							HAL_GPIO_WritePin(MCU_LED1_R_GPIO_Port, MCU_LED1_R_Pin, GPIO_PIN_RESET);
						}

						if (GPIO_PIN_SET == HAL_GPIO_ReadPin(MCU_LED1_G_GPIO_Port, MCU_LED1_G_Pin))
						{
							HAL_GPIO_WritePin(MCU_LED1_G_GPIO_Port, MCU_LED1_G_Pin, GPIO_PIN_RESET);
						}
						//
						HAL_GPIO_WritePin(MCU_LED1_G_GPIO_Port, MCU_LED1_G_Pin, GPIO_PIN_SET);

						break;
					}

					default:
						if (record_error != 1)
						{
							if (GPIO_PIN_SET == HAL_GPIO_ReadPin(MCU_LED1_B_GPIO_Port, MCU_LED1_B_Pin))
							{
								HAL_GPIO_WritePin(MCU_LED1_B_GPIO_Port, MCU_LED1_B_Pin, GPIO_PIN_RESET);
							}

							if (GPIO_PIN_SET == HAL_GPIO_ReadPin(MCU_LED1_R_GPIO_Port, MCU_LED1_R_Pin))
							{
								HAL_GPIO_WritePin(MCU_LED1_R_GPIO_Port, MCU_LED1_R_Pin, GPIO_PIN_RESET);
							}

							if (GPIO_PIN_SET == HAL_GPIO_ReadPin(MCU_LED1_G_GPIO_Port, MCU_LED1_G_Pin))
							{
								HAL_GPIO_WritePin(MCU_LED1_G_GPIO_Port, MCU_LED1_G_Pin, GPIO_PIN_RESET);
							}
							//
							HAL_GPIO_WritePin(MCU_LED1_R_GPIO_Port, MCU_LED1_R_Pin, GPIO_PIN_SET);

						}
						break;
				}

			continue;
		}
		osDelay(100);

		record_error = 1;

		switch (GL_device_t.state_t.recording_state)
		{
		osDelay(3000);

			case RS_NOT_STARTED:
			{

				 //
				portENTER_CRITICAL();
				fres = f_mount(&GL_FatFs_t, "", 1); //1=mount now
				if (fres == FR_OK) {
					//Get RTC Time
					datetime_t = rtc_calendar_to_datetime();
					sprintf(filename_u8, "%02u%02u%02u%02u.ecg", (datetime_t.date+1) ,datetime_t.hour, datetime_t.minute, datetime_t.second);
					fres = f_open(&GL_file_t, filename_u8, FA_WRITE | FA_OPEN_ALWAYS | FA_CREATE_ALWAYS);	//"DATAmmss.ecg"

					HAL_Delay(1000);

					if (fres == FR_OK){
						memcpy(GL_file_w_t.dosya_adi_u8, filename_u8, sizeof(GL_file_w_t.dosya_adi_u8));
						GL_file_w_t.baslangic_ts_u32 = rtc_calendar_to_timestamp();
						init_threads(WriteSDCard);
						GL_device_t.state_t.recording_state = RS_STARTED;
						record_error = 0;
					}

				}
				portEXIT_CRITICAL();

				break;
			}

			case RS_STARTED:
			{

				portENTER_CRITICAL();
				if (GL_file_t.obj.fs != NULL)
				{

					GL_file_w_t.bitis_ts_u32 = rtc_calendar_to_timestamp();

					//Write file metadata
					pack_file_metadata(file_metadata_u8, &GL_comm_settings_t, &GL_file_w_t, &GL_ADS1298_prob_t, &GL_kritik_durum_t);

					f_lseek(&GL_file_t, 0);
					f_write(&GL_file_t, file_metadata_u8, 512, &bytes_written);
					f_eof(&GL_file_t);
					f_close(&GL_file_t);
					f_mount(NULL, "", 0);

					GL_device_t.state_t.recording_state = RS_NOT_STARTED;
				}
				portEXIT_CRITICAL();

				osThreadTerminate(Handle_WriteSDCard);
				osSemaphoreRelease(Semaphore_AccessSDCard);

				break;
			}

			default:
				break;

		}/*switch (GL_device_t.state_t.recording_state)*/

	}/*for(;;)*/

}

The other task (which i have problem) is :

void Thread_Lsm6dsox(void *argument)
{
	(void) argument;
	 lsm6dsox_all_src_t all_source;
	lsm6dsox_all_int_src_t ints;
	uint8_t* INT1;
	INT1=&ints;
	int32_t ret_int;
	ret_int = lsm6dsox_read_reg(&hi2c3,LSM6DSOX_READ, LSM6DSOX_ALL_INT_SRC,INT1, 1);
	/* Check if Single Tap events */
	lsm6dsox_all_sources_get(&hi2c3, &all_source);

	  for(;;) {

	if (ints.single_tap) {

	  /* Wait Events */
	 	HAL_GPIO_WritePin(MCU_LED1_R_GPIO_Port, MCU_LED1_R_Pin, GPIO_PIN_SET);
	    osDelay(1000);
	    HAL_GPIO_WritePin(MCU_LED3_GPIO_Port, MCU_LED3_Pin, GPIO_PIN_RESET);
}

	  }

}

MCU: stm32wb5 …
freertos : cmsis v2
mode: prememtive. and all tasks priority is same…

FreeRTOS version is something like 10.4.4.
Where is the ISR / the interrupt handling ?

if (ints.single_tap) {

  /* Wait Events */
 	HAL_GPIO_WritePin(MCU_LED1_R_GPIO_Port, MCU_LED1_R_Pin, GPIO_PIN_SET);
    osDelay(1000);
    HAL_GPIO_WritePin(MCU_LED3_GPIO_Port, MCU_LED3_Pin, GPIO_PIN_RESET);

}
there is no ISR. imean i tried to implement single tap (interrupt) from IMU sensor by putting it inside the task ?? Is it possible like that ?
Anyway , - Version is CMSIS_V2

void EXTI15_10_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI15_10_IRQn 0 */

  /* USER CODE END EXTI15_10_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(MCU_CHARGER_STAT1_Pin);
  HAL_GPIO_EXTI_IRQHandler(MCU_IMU_INTERRUPT1_Pin);
  BaseType_t checkIfYieldRequired;
  checkIfYieldRequired = xTaskResumeFromISR(Thread_Lsm6dsox);
  portYIELD_FROM_ISR(checkIfYieldRequired);
  /* USER CODE BEGIN EXTI15_10_IRQn 1 */

  /* USER CODE END EXTI15_10_IRQn 1 */
}

I have added the ISR to the code. but problem continue!

Note, "xTaskResumeFromISR() will only affect a task that has been suspended via xTaskSuspend(), and not affect a task that is in a delay or waiting for a semaphore.

Also, if you want a task to start as soon as it is signaled, it needs to be higher priority than the currently running task.

for(;; ) {
HAL_GPIO_WritePin(MCU_LED1_R_GPIO_Port, MCU_LED1_R_Pin, GPIO_PIN_SET);
	    osDelay(1000);
	    HAL_GPIO_WritePin(MCU_LED3_GPIO_Port, MCU_LED3_Pin, GPIO_PIN_RESET);
	    vTaskSuspend(NULL);
}

i take priority of my interrupt task (Thread_Lsm6dsox) higher…
I used xTaskSuspend() inside the task.(interrupt)
But result is negative!
Any idea please ?

Your approach is broken. As Richard pointed out resuming a task that is currently blocked in osDelay or executing any other code will do nothing. When the task suspends later on it keeps being suspended until the next resume. You’ll miss interrupt events.
In general task suspend/resume are special functions and used rarely.
Why not using a semaphore signaled from the ISR and let the interrupt post-processing task just wait for the semaphore being signaled without any useless osDelay ?
That’s common practice and there surely are lots of examples implemented this way.
Also take care of setting the NVIC interrupt priority right that it works with FreeRTOS.
PS Please enclose code blocks with 3 tildes ‘~’ or backticks ‘`’ for better readability.

Thanks HArtmut.
I will try semaphores.

I tried to implement binary semaphore . but not succeded yet.
can you look into that ?

{
  /* EXTI line interrupt detected */
  if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
  {
	  if(GPIO_Pin==MCU_IMU_INTERRUPT1_Pin){
	  extern SemaphoreHandle_t xInterruptSemaphore;
	  xInterruptSemaphore= xSemaphoreCreateBinary();
	  BaseType_t  xHigherPriorityTaskWoken = pdFALSE;
	  xSemaphoreGiveFromISR(xInterruptSemaphore,&xHigherPriorityTaskWoken);
	  portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
	  __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
	     HAL_GPIO_EXTI_Callback(GPIO_Pin);
  }
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
    HAL_GPIO_EXTI_Callback(GPIO_Pin);
  }
}
void Thread_Lsm6dsox(void *argument)
{
	(void) argument;
//	 lsm6dsox_all_src_t all_source;
//	lsm6dsox_all_int_src_t ints;
//	uint8_t* INT1;
//	INT1=&ints;
//	int32_t ret_int;
//	ret_int = lsm6dsox_read_reg(&hi2c3,LSM6DSOX_READ, LSM6DSOX_ALL_INT_SRC,INT1, 1);
//	/* Check if Single Tap events */
//	lsm6dsox_all_sources_get(&hi2c3, &all_source);

	  for(;;) {
	if (xSemaphoreTake(xInterruptSemaphore,portMAX_DELAY)==pdPASS) {

	  /* Wait Events */
	 	HAL_GPIO_WritePin(MCU_LED1_R_GPIO_Port, MCU_LED1_R_Pin, GPIO_PIN_SET);
	    vTaskDelay(1000);
	    HAL_GPIO_WritePin(MCU_LED1_R_GPIO_Port, MCU_LED1_R_Pin, GPIO_PIN_RESET);
	  //  vTaskSuspend(NULL);
	   // osThreadYield();
}

	  }

}

has to be done once during application init and before enabling the interrupt, of course. It’s a global resource.

The system does not allow me to createbinary;
when i add the line ;
xInterruptSemaphore=xSemaphoreCreateBinary();
error occur. (conflicting types)
Do you know anything about this Hartmut ?

You should tell the error :wink: otherwise … you know, it’s hard to guess.
But if you simply follow the documentation and example I’m sure it will work.

Error is : ‘xInterruptSemaphore’ undeclared (first use in this function)
. i have to include “extern SemaphoreHandle_t xInterruptSemaphore” inside the interrupt handler. (HAL_GPIO_EXTI_IRQHandler - i copied above.) If I do not include this , The error will occur.And ı can not get the interrupt yet?

Just add the extern SemaphoreHandle_t xInterruptSemaphore; declaration to the files where it’s used (but not defined) as with any other global variable.
I’d it globally to the whole file / at file scope.

Ok. I passed that.
When I start debuggig ; The code stuck in the configASSERT…

void vPortEnterCritical( void )
{
	portDISABLE_INTERRUPTS();
	uxCriticalNesting++;

	/* This is not the interrupt safe version of the enter critical function so
	assert() if it is being called from an interrupt context.  Only API
	functions that end in "FromISR" can be used in an interrupt.  Only assert if
	the critical nesting count is 1 to protect against recursive calls if the
	assert function also uses a critical section. */
	if( uxCriticalNesting == 1 )
	{
		configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
	}
}

What do you think Mr HArmut??

What’s the callstack / backtrace ? Find out which call of your code finally caused the assertion to maybe get an idea what’s wrong.
However, I guess you didn’t setup the NVIC interrupt priority correctly as I already mentioned. Did you verify your chosen priority ?
When in doubt, have a look at this related documentation:

and this very good forum posts:

Ok. I made it.
Another question … :slight_smile:
I get the interrupt. when i get the interrupt a ISR task is ON. But This Interrupt task process block my main task (another task.) I want it not to block my main task (i mean sd card recording.)
In my Freertos Config file.
Preemptive is 1 .
So Why this ISR to Task (interrupt task) block my main(sd card recording.) task ?
CAn I prevent this and how ?
DEar helpful Harmut ? :slight_smile:

How should the interrupt processing task block another task ?
It’s just waiting for the semaphore being signaled to do something.
Well, except there are interrupts all the time at a very high frequency and the interrupt processing task has a higher priority than the other task(s) (and the task doesn’t contain a delay, which would also cause giving up the CPU to be used by other tasks).
Then you could lower the priority of the interrupt processing task and I’d recommend to check, if there are really so many interrupts. That would be a problem, right ?