What is the best way to access I2C in a MQX project?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

What is the best way to access I2C in a MQX project?

1,640 Views
mjohn
Contributor III

uPC: MK21FN1M0A

IDE: KDS 2.0.0

SDK: KSDK1.1.0_K21FA_1.0.0

Hello

I have a project that uses MQX OS with several tasks that access two I2C ports. Currently, I am using the SDK I2C component from Processor Expert for all I2C operations. I seem to run across some issues with this I2C driver when multiple tasks are trying to access the I2C ports, specifically an assert statement will fail in the driver code. In order to make sure the I2C is thread safe, I use a mutex for accessing each I2C resource. Also, the driver code seemed sensitive when preempted by another task, so I disable preemption whenever the I2C is accessed.

Considering these issues, I am wondering if this is the best method of accessing I2C in a MQX OS environment? Are there better methods of accessing the I2C than what I am doing currently?

Thanks

Matt

Here are some snippets of relevant code:

assert statement that fails: fsl_i2c_hal.c

i2c_status_t I2C_HAL_SendStop(uint32_t baseAddr)

{

    assert(BR_I2C_C1_MST(baseAddr) == 1);

    uint32_t i = 0;

    /* Start the STOP signal */

    HW_I2C_C1_CLR(baseAddr, BM_I2C_C1_MST | BM_I2C_C1_TX);

    /* Wait for the STOP signal finish. */

    while(I2C_HAL_GetStatusFlag(baseAddr, kI2CBusBusy))

    {

        if (++i == 0x400U)

        {

            /* Something is wrong because the bus is still busy. */

            return kStatus_I2C_StopSignalFail;

        }

        else

        {

            __asm("nop");

        }

    }

    return kStatus_I2C_Success;

}

Current function that accesses I2C through the I2C SDK component driver:

i2c_status_t i2c_stat;

if (instance == FSL_I2CCOM0){if (lockMutex(&i2c0_mutex) != MQX_OK){return kStatus_I2C_Fail;}}

else if (instance == FSL_I2CCOM2){if (lockMutex(&i2c2_mutex) != MQX_OK){return kStatus_I2C_Fail;}}

  else {return kStatus_I2C_Fail;}

_task_stop_preemption();

i2c_stat = I2C_DRV_MasterSendDataBlocking(instance, device, cmdBuff, cmdSize, txBuff, txSize, timeout_ms);

_task_start_preemption();

if (instance == FSL_I2CCOM0){if (unlockMutex(&i2c0_mutex) != MQX_OK){return kStatus_I2C_Fail;}}

else if (instance == FSL_I2CCOM2){if (unlockMutex(&i2c2_mutex) != MQX_OK){return kStatus_I2C_Fail;}}

return i2c_stat;

0 Kudos
Reply
5 Replies

1,270 Views
DavidS
NXP Employee
NXP Employee

Hi Matt,

The Freescale Xtrinsic Sensor library for Kinetis (XTRINSIC_FUSION_LIB_KINMCU) has good example of using KDS+PE to access multiple sensors on I2C interface.

The software is targeted to KL46, K20D50M, K64F, KL25Z, and KL26Z Freedom boards that then plug into the FRDM-FXS-MULTI sensor board.

This should be a good reference for setting up on your K21.

Regards,

David

1,270 Views
mjohn
Contributor III

Thanks for the reference. I'll look into that.

0 Kudos
Reply

1,270 Views
DavidS
NXP Employee
NXP Employee
0 Kudos
Reply

1,270 Views
matthewkendall
Contributor V

I am using the MQX I2C driver, as described in the "MQX I/O User's Guide" MQXIOUG. Set BSPCFG_ENABLE_I2C0 true in user_config.h to enable it in the BSP. That gets you the polled driver. You can enable the interrupt-based driver instead but I have not used that.

It installs as a standard I/O driver so the the API is the standard fopen(), read(), write(), fclose(), and ioctl(). There are some examples of how to use it in the MQX distribution.

I am using it to access a temperature sensor and an EEPROM on the same bus, in an environment where there are dozens of tasks, most of which are higher priority then those using I2C, and I have not seen any problems.

I am using CodeWarrior with MQX 4.1.1 and a K60. I know nothing about KSD or KSDK.

1,270 Views
mjohn
Contributor III

Thanks for the help. I've been using the Processor Expert MQX component, which seems to be generated a little differently? If I don't make any headway using the PEx components, I'll give this a shot.

0 Kudos
Reply