AnsweredAssumed Answered

Using I2C and freeRTOS to read data from Accel/Gyro

Question asked by Leandro Fabián Rocco on Jul 11, 2020
Latest reply on Aug 7, 2020 by Daniel Chen

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.

Attachments

Outcomes