2024-10-30 03:44 AM
Hi
I use the HAL library and CMSIS-RTOS2
infinite loops should not be used in the thread, but I need to wait, for example, for the packet to be sent via I2C, because I need to write and read right after each other, and if I don't wait for the HAL_I2C_STATE_READY state, only writing is performed, but reading does not take place
is the solution to use osThreadYield() ?
static void Task1(void *argument)
{
while(1)
{
HAL_I2C_Master_Transmit_IT(&hi2c1, I2C_addr, write_data_array,sizeof(write_data_array));
while(hi2c1.State != HAL_I2C_STATE_READY)
{
osThreadYield() ;
}
HAL_I2C_Master_Receive_IT(&hi2c1, I2C_addr, read_data_array,sizeof(read_data_array));
while(hi2c1.State != HAL_I2C_STATE_READY)
{
osThreadYield() ;
}
}
}
or set a semaphore(event) in the I2C interrupt handler and watch it in the thread?
osSemaphoreId_t I2C_semaphore;
void I2C1_EV_IRQHandler(void)
{
HAL_I2C_EV_IRQHandler(&hi2c1);
if(hi2c1.State == HAL_I2C_STATE_READY)
osSemaphoreRelease(I2C_semaphore);
}
static void Task1(void *argument)
{
while(1)
{
HAL_I2C_Master_Transmit_IT(&hi2c1, I2C_addr, write_data_array,sizeof(write_data_array));
osSemaphoreAcquire(I2C_semaphore, 100);
HAL_I2C_Master_Receive_IT(&hi2c1, I2C_addr, read_data_array,sizeof(read_data_array));
osSemaphoreAcquire(I2C_semaphore, 100);
}
}
or not solve it, because it cannot happen that the I2C peripheral never reaches the Ready state?
static void Task1(void *argument)
{
while(1)
{
HAL_I2C_Master_Transmit_IT(&hi2c1, I2C_addr, write_data_array,sizeof(write_data_array));
while(hi2c1.State != HAL_I2C_STATE_READY);
HAL_I2C_Master_Receive_IT(&hi2c1, I2C_addr, read_data_array,sizeof(read_data_array));
while(hi2c1.State != HAL_I2C_STATE_READY);
}
}
all variants work, but I'd like to get it right
Solved! Go to Solution.
2024-10-30 05:59 AM
Hello @PNova.2
Using semaphores for synchronizing I2C operations in an RTOS environment is a more efficient and robust approach compared to using infinite loops or busy waiting. Semaphores allow the thread to block and wait for the I2C operation to complete, which is signaled by the I2C complete callback functions. This method avoids unnecessary CPU usage, ensuring that the system remains responsive and efficient. Below is an example of how to implement this approach:
osSemaphoreId_t I2C_semaphore;
I2C_HandleTypeDef hi2c1;
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c)
{
if(hi2c->State == HAL_I2C_STATE_READY)
{
osSemaphoreRelease(I2C_semaphore);
}
}
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
if(hi2c->State == HAL_I2C_STATE_READY)
{
osSemaphoreRelease(I2C_semaphore);
}
}
static void Task1(void *argument)
{
while(1)
{
HAL_I2C_Master_Transmit_IT(&hi2c1, I2C_addr, write_data_array, sizeof(write_data_array));
osSemaphoreAcquire(I2C_semaphore, 100);
HAL_I2C_Master_Receive_IT(&hi2c1, I2C_addr, read_data_array, sizeof(read_data_array));
osSemaphoreAcquire(I2C_semaphore, 100);
}
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_Init();
I2C_semaphore = osSemaphoreNew(1, 0, NULL);
osKernelInitialize();
osThreadNew(Task1, NULL, NULL);
osKernelStart();
while (1)
{
}
}
2024-10-30 05:59 AM
Hello @PNova.2
Using semaphores for synchronizing I2C operations in an RTOS environment is a more efficient and robust approach compared to using infinite loops or busy waiting. Semaphores allow the thread to block and wait for the I2C operation to complete, which is signaled by the I2C complete callback functions. This method avoids unnecessary CPU usage, ensuring that the system remains responsive and efficient. Below is an example of how to implement this approach:
osSemaphoreId_t I2C_semaphore;
I2C_HandleTypeDef hi2c1;
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c)
{
if(hi2c->State == HAL_I2C_STATE_READY)
{
osSemaphoreRelease(I2C_semaphore);
}
}
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
if(hi2c->State == HAL_I2C_STATE_READY)
{
osSemaphoreRelease(I2C_semaphore);
}
}
static void Task1(void *argument)
{
while(1)
{
HAL_I2C_Master_Transmit_IT(&hi2c1, I2C_addr, write_data_array, sizeof(write_data_array));
osSemaphoreAcquire(I2C_semaphore, 100);
HAL_I2C_Master_Receive_IT(&hi2c1, I2C_addr, read_data_array, sizeof(read_data_array));
osSemaphoreAcquire(I2C_semaphore, 100);
}
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_Init();
I2C_semaphore = osSemaphoreNew(1, 0, NULL);
osKernelInitialize();
osThreadNew(Task1, NULL, NULL);
osKernelStart();
while (1)
{
}
}
2024-10-30 12:22 PM
Thanks for the explanation. I wasn't sure and I want to use the most efficient and secure code.