Using I2C and freeRTOS to read data from Accel/Gyro

cancel
Showing results for 
Search instead for 
Did you mean: 

Using I2C and freeRTOS to read data from Accel/Gyro

Jump to solution
378 Views
Contributor III

Hello, I am using FRDM-K64F board and MCUXpresso to develop a program to read data from MPU6050 sensor through the I2C1 module.

My program is made up of 3 tasks:

  1. One task to toggle a RED LED each 250ms. (works fine!!)
  2. One task to receive data from a bluetooth module through UART4 module (works fine!!!)
  3. One task to read data from MPU sensor through I2C1 module. (It doesn't work)

My main function is as follow:

int main(void)
{
   // Initialization of board hardware
    BOARD_InitBootPins();
    BOARD_InitBootClocks();
    BOARD_InitBootPeripherals();
   // Initialization of FSL debug console.
    BOARD_InitDebugConsole();

    // Variables
    BaseType_t pass_or_nopass;

    /*********************************************
    * Task creation goes here
    *********************************************/
    // Task for print in console
    pass_or_nopass = xTaskCreate(vRedLEDToggleTask,
      "RED_LED Toggle",
   configMINIMAL_STACK_SIZE,
   NULL,
   configMAX_PRIORITIES - 1,
   NULL);
    if (pass_or_nopass != pdPASS)
    {
  PRINTF("vRedLEDToggleTask creation failed!.\r\n");
  while (1);
    }

    // Task for UART4 module
    NVIC_SetPriority(UART_RX_TX_IRQn, 5);
    pass_or_nopass = xTaskCreate(UART_Rx_Task,
      "UART4 Task",
   configMINIMAL_STACK_SIZE + 100,
   NULL,
   configMAX_PRIORITIES - 1,
   NULL);
    if (pass_or_nopass != pdPASS)
    {
     PRINTF("UART_Rx_Task creation failed.\r\n");
     while (1);
    }

    // Task for I2C1 module
    NVIC_SetPriority(I2C1_IRQN, 5);
    pass_or_nopass = xTaskCreate(I2C1_master_task,
      "I2C1 Task",
   configMINIMAL_STACK_SIZE + 300,
   NULL,
   configMAX_PRIORITIES - 1,
   NULL);


    /*********************************************
    * Initialization of task scheduler
 *********************************************/
    vTaskStartScheduler();

    /********************************************/
    for (;;);
    return 0 ;
}

My I2C1_master_task is as follow:

void I2C1_master_task(void *pvParameters)
{
    i2c_rtos_handle_t master_rtos_handle;
    i2c_master_config_t masterConfig;
    //i2c_master_transfer_t masterXfer;
    uint32_t sourceClock;
    status_t status;

    /*
     * masterConfig.baudRate_Bps = 100000U;
     * masterConfig.enableStopHold = false;
     * masterConfig.glitchFilterWidth = 0U;
     * masterConfig.enableMaster = true;
     */
    I2C_MasterGetDefaultConfig(&masterConfig);
    masterConfig.baudRate_Bps = I2C1_BAUDRATE;
    sourceClock               = I2C1_CLK_FREQ;

    status = I2C_RTOS_Init(&master_rtos_handle, I2C1, &masterConfig, sourceClock);
    if (status != kStatus_Success)
    {
        PRINTF("I2C master: error during init, %d", status);
    }


    PRINTF("I2C1 module initialized!\r\n");
    const TickType_t xDelay250ms = pdMS_TO_TICKS(250);
    bool isOK;
    for (;;)
    {
     isOK = MPU6050_ReadSensorWhoAmI(&master_rtos_handle);
     if (isOK)
      PRINTF("WHO AM I received!!\r\n");
     else
      PRINTF("No device found!!\r\n");
     vTaskDelay(xDelay250ms);
    }
}

And the Who_am_I read functions is as follow:

bool MPU6050_ReadSensorWhoAmI(i2c_rtos_handle_t *master_handle)
{
 status_t status;
 uint8_t who_am_i_reg          = MPU6050_WHO_AM_I;
 uint8_t who_am_i_value        = 0x00;
 i2c_master_transfer_t masterXfer;
 memset(&masterXfer, 0, sizeof(masterXfer));

 // START + Slave_address (write_bit); Reg_address
 masterXfer.slaveAddress   = MPU6050_DEVICE_ADDRESS_0;
 masterXfer.direction      = kI2C_Write;
 masterXfer.subaddress     = 0;
 masterXfer.subaddressSize = 0;
 masterXfer.data           = &who_am_i_reg;
 masterXfer.dataSize       = 1;
 masterXfer.flags          = kI2C_TransferNoStopFlag;

 status = I2C_RTOS_Transfer(&master_handle, &masterXfer);
 if (status != kStatus_Success)
 {
  PRINTF("I2C master: error during write transaction, %d", status);
  return false;
 }


 // START + Slave_address (read_bit); recibo dato
 masterXfer.direction      = kI2C_Read;
 masterXfer.subaddress     = 0;
 masterXfer.subaddressSize = 0;
 masterXfer.data           = &who_am_i_value;
 masterXfer.dataSize       = 1;
 masterXfer.flags          = kI2C_TransferRepeatedStartFlag;
 status = I2C_RTOS_Transfer(&master_handle, &masterXfer);
 if (status != kStatus_Success)
 {
  PRINTF("I2C master: error during write transaction, %d", status);
  return false;
 }


 return true;
}

The problem is that the code is stuck on the line

configASSERT( ( pxQueue ) );

inside queue.c file (line 1427) inside function xQueueSemaphoreTake().

I have noticed that when the function MPU6050_ReadSensorWhoAmI() calls to I2C_RTOS_Transfer(), the i2c_rtos_handle_t is passed ok, but when the function I2C_RTOS_Transfer() make the following check:

/* Lock resource mutex */
    if (xSemaphoreTake(handle->mutex, portMAX_DELAY) != pdTRUE)
    {
        return kStatus_I2C_Busy;
    }

the handle->mutex is passed as 0x0, and for this reason the code is stuck in the line I comment earlier.

Can you help me understand this error?

I attach my FreeRTOSConfig.h file for reference.

Also, is there any documentation to get started with the freeRTOS drivers from the NXP SDK?

Best regards.

Labels (1)
0 Kudos
1 Solution
82 Views
Contributor III

Hello, I was working again to find the error and I found it !!!

The error is very silly, in the MPU6050_ReadSensorWhoAmI() function I am calling I2C_RTOS_Transfer() and passing it the master_handle argument as a reference, but this handle is already a pointer, and I should not use & to pass it to the function.

Now my code is working. Thank you anyway.

Regards.

View solution in original post

0 Kudos
7 Replies
83 Views
Contributor III

Hello, I was working again to find the error and I found it !!!

The error is very silly, in the MPU6050_ReadSensorWhoAmI() function I am calling I2C_RTOS_Transfer() and passing it the master_handle argument as a reference, but this handle is already a pointer, and I should not use & to pass it to the function.

Now my code is working. Thank you anyway.

Regards.

View solution in original post

0 Kudos
132 Views
NXP TechSupport
NXP TechSupport

Hi Leandro:

The handle->mutex is created in  I2C_RTOS_INIT function, can you please check this mutex created successfully?

If you run I2C1 task only, does it work?

Regards

Daniel

0 Kudos
132 Views
Contributor III

Hi Daniel, thanks for responding.

If I run I2C1 task only, the problem is the same. The program is stuck in configASSERT( ( pxQueue ) );

I check inside I2C_RTOS_INIT function, and the handle->mutex is created ok.

I still can't find the error.

Regards.

Leandro.

0 Kudos
132 Views
NXP TechSupport
NXP TechSupport

I would suggest you check the register value of i2c1, is it configured correctly?  check the i2c1 clock?

If still not work, could you please attach your source file for me to reproduce your issue on my side?

Regards

Daniel

0 Kudos
132 Views
Contributor III

Hi Daniel, thanks for responding and sorry for my delay.

I set the interrupt priority to 3 and 2 but the code is stuck in the same place. I attach here my full code. Also, I leave here my hithub link of this project.

GitHub - leandroGHsoft/FRDM-K64F_FreeRTOS_Quadcopter: Quadcopter based on FreeRTOS software 

Regards.

0 Kudos
107 Views
Contributor III

Hi Daniel, do you have some news about this? Thanks

0 Kudos
132 Views
NXP TechSupport
NXP TechSupport

Hi Leandro:

Can you adjust the I2C1_IRQN  interrupt priority? using NVIC_SetPriority to set priority to 3 or 2?

Regards

Daniel

0 Kudos