cancel
Showing results for 
Search instead for 
Did you mean: 

STM32CubeIDE + FreeRTOS: sharing I2C in DMA mode between two tasks using notify from ISR

Petr3
Associate III

Hello,

i need help how to share I2C in DMA mode between two FreeRTOS tasks.

I have two tasks:

Task 1:

 

 

osMutexAcquire(I2C1_MutexHandle, HAL_MAX_DELAY);
Task_Notification_I2C1 = WM8731;
configASSERT(xTaskToNotifyI2C1_WM8731 == NULL );
xTaskToNotifyI2C1_WM8731 = xTaskGetCurrentTaskHandle();
Status = HAL_I2C_Master_Transmit_DMA(&hi2c1, (uint16_t)WM8731_I2C_ADDRESS, data, 2);

ulNotificationValue = ulTaskNotifyTake(pdFALSE, HAL_MAX_DELAY);
if(ulNotificationValue)
	osMutexRelease(I2C1_MutexHandle);
else
	DEBUGOUT("WM8731_Set_Register I2C timeout...\r\n");

 

 

 

Task 2:

 

 

osMutexAcquire(I2C1_MutexHandle, HAL_MAX_DELAY);
Task_Notification_I2C1 = FT5426;
configASSERT(xTaskToNotifyI2C1_FT5426 == NULL );
xTaskToNotifyI2C1_FT5426 = xTaskGetCurrentTaskHandle();
Status = HAL_I2C_Master_Receive_DMA(&hi2c1, (uint16_t)FT5426_I2C_ADDRESS, data, 64);

ulNotificationValue = ulTaskNotifyTake(pdFALSE, HAL_MAX_DELAY);
if(ulNotificationValue)
	osMutexRelease(I2C1_MutexHandle);
else
	DEBUGOUT("FT5426_Read_Complete I2C timeout...\r\n");

 

 

 

And ISR:

 

 

void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c)
{
	BaseType_t xHigherPriorityTaskWoken = pdFALSE;

	if(hi2c->Instance == I2C1)
	{
		if(xTaskToNotifyI2C1_WM8731 != NULL)
		{
			configASSERT( xTaskToNotifyI2C1_WM8731 != NULL );
			vTaskNotifyGiveFromISR(xTaskToNotifyI2C1_WM8731, &xHigherPriorityTaskWoken);
			xTaskToNotifyI2C1_WM8731 = NULL;
			portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
		}
		else if(xTaskToNotifyI2C1_FT5426 != NULL)
		{
			configASSERT( xTaskToNotifyI2C1_FT5426 != NULL );
			vTaskNotifyGiveFromISR(xTaskToNotifyI2C1_FT5426, &xHigherPriorityTaskWoken);
			xTaskToNotifyI2C1_FT5426 = NULL;
			portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
		}
	}
}

 

 

 

That isnt working. The mutex cannot be acquired by second task so it is in blocked state.

 

I dont want to use additional task for handling I2C1, i would like to use notification from ISR.

 

Any ideas?

Thanks

1 ACCEPTED SOLUTION

Accepted Solutions
Petr3
Associate III

I found the problem - I2C address. I forgot that the HAL driver wants I2C address shifted by 1 (Address + !W). So i used 0x34 instead of wrong 0x1A mentioned in datasheet and it seems to work now. With 0x1A I2C driver got NAK after address and raised error flag.

View solution in original post

3 REPLIES 3
Pavel A.
Evangelist III

That isnt working. The mutex cannot be acquired by second task so it is in blocked state.

Why? as you've coded it, both tasks will release the mutex as soon as they receive notification. Tried to debug?

 

Hi Pavel,

i tried to debug it a little bit. When the task 2 is alone for I2C1 periphery, the notification from ISR and acquiring of mutex works fine. When i added the task 1 with its own xTaskToNotify_I2C1 the I2C1 is not reachable from the second one - mutex is still taken.

The second task should access I2C1 periodically - it is task for reading from touch screen controller.

I want to look on the I2C bus by oscilloscope or logic analyzer and look what was last operation on the I2C1 bus.

I hope i'll find the problem when i look on the I2C1 bus.

UPDATE:

I connected logic analyzer on I2C1 bus and i saw that only device address of WM8731 slave was sent(task 1). I add breakpoint into DMA Error and Abort IRQ handlers and it goes into HAL_DMA_STATE_ABORT state and I2C goes into HAL_I2C_ErrorCallback(). Now i dont have idea why. It worked fine with one task. I'll continue with debugging.

Petr

Petr3
Associate III

I found the problem - I2C address. I forgot that the HAL driver wants I2C address shifted by 1 (Address + !W). So i used 0x34 instead of wrong 0x1A mentioned in datasheet and it seems to work now. With 0x1A I2C driver got NAK after address and raised error flag.