mirror of https://github.com/ARMmbed/mbed-os.git
MCUXpresso: Update I2C SDK driver
Use the K66F driver that has the latest Signed-off-by: Mahesh Mahadevan <mahesh.mahadevan@nxp.com>pull/11308/head
parent
8022ca918f
commit
eda75fd02a
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||||
* All rights reserved.
|
* Copyright 2016-2017 NXP
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
* other materials provided with the distribution.
|
* other materials provided with the distribution.
|
||||||
*
|
*
|
||||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
* o Neither the name of the copyright holder nor the names of its
|
||||||
* contributors may be used to endorse or promote products derived from this
|
* contributors may be used to endorse or promote products derived from this
|
||||||
* software without specific prior written permission.
|
* software without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -75,6 +75,19 @@ typedef void (*i2c_isr_t)(I2C_Type *base, void *i2cHandle);
|
||||||
*/
|
*/
|
||||||
uint32_t I2C_GetInstance(I2C_Type *base);
|
uint32_t I2C_GetInstance(I2C_Type *base);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Set SCL/SDA hold time, this API receives SCL stop hold time, calculate the
|
||||||
|
* closest SCL divider and MULT value for the SDA hold time, SCL start and SCL stop
|
||||||
|
* hold time. To reduce the ROM size, SDA/SCL hold value mapping table is not provided,
|
||||||
|
* assume SCL divider = SCL stop hold value *2 to get the closest SCL divider value and MULT
|
||||||
|
* value, then the related SDA hold time, SCL start and SCL stop hold time is used.
|
||||||
|
*
|
||||||
|
* @param base I2C peripheral base address.
|
||||||
|
* @param sourceClock_Hz I2C functional clock frequency in Hertz.
|
||||||
|
* @param sclStopHoldTime_ns SCL stop hold time in ns.
|
||||||
|
*/
|
||||||
|
static void I2C_SetHoldTime(I2C_Type *base, uint32_t sclStopHoldTime_ns, uint32_t sourceClock_Hz);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Set up master transfer, send slave address and decide the initial
|
* @brief Set up master transfer, send slave address and decide the initial
|
||||||
* transfer state.
|
* transfer state.
|
||||||
|
@ -137,8 +150,10 @@ static I2C_Type *const s_i2cBases[] = I2C_BASE_PTRS;
|
||||||
/*! @brief Pointers to i2c IRQ number for each instance. */
|
/*! @brief Pointers to i2c IRQ number for each instance. */
|
||||||
static const IRQn_Type s_i2cIrqs[] = I2C_IRQS;
|
static const IRQn_Type s_i2cIrqs[] = I2C_IRQS;
|
||||||
|
|
||||||
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||||
/*! @brief Pointers to i2c clocks for each instance. */
|
/*! @brief Pointers to i2c clocks for each instance. */
|
||||||
static const clock_ip_name_t s_i2cClocks[] = I2C_CLOCKS;
|
static const clock_ip_name_t s_i2cClocks[] = I2C_CLOCKS;
|
||||||
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||||
|
|
||||||
/*! @brief Pointer to master IRQ handler for each instance. */
|
/*! @brief Pointer to master IRQ handler for each instance. */
|
||||||
static i2c_isr_t s_i2cMasterIsr;
|
static i2c_isr_t s_i2cMasterIsr;
|
||||||
|
@ -155,7 +170,7 @@ uint32_t I2C_GetInstance(I2C_Type *base)
|
||||||
uint32_t instance;
|
uint32_t instance;
|
||||||
|
|
||||||
/* Find the instance index from base address mappings. */
|
/* Find the instance index from base address mappings. */
|
||||||
for (instance = 0; instance < FSL_FEATURE_SOC_I2C_COUNT; instance++)
|
for (instance = 0; instance < ARRAY_SIZE(s_i2cBases); instance++)
|
||||||
{
|
{
|
||||||
if (s_i2cBases[instance] == base)
|
if (s_i2cBases[instance] == base)
|
||||||
{
|
{
|
||||||
|
@ -163,16 +178,63 @@ uint32_t I2C_GetInstance(I2C_Type *base)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(instance < FSL_FEATURE_SOC_I2C_COUNT);
|
assert(instance < ARRAY_SIZE(s_i2cBases));
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void I2C_SetHoldTime(I2C_Type *base, uint32_t sclStopHoldTime_ns, uint32_t sourceClock_Hz)
|
||||||
|
{
|
||||||
|
uint32_t multiplier;
|
||||||
|
uint32_t computedSclHoldTime;
|
||||||
|
uint32_t absError;
|
||||||
|
uint32_t bestError = UINT32_MAX;
|
||||||
|
uint32_t bestMult = 0u;
|
||||||
|
uint32_t bestIcr = 0u;
|
||||||
|
uint8_t mult;
|
||||||
|
uint8_t i;
|
||||||
|
|
||||||
|
/* Search for the settings with the lowest error. Mult is the MULT field of the I2C_F register,
|
||||||
|
* and ranges from 0-2. It selects the multiplier factor for the divider. */
|
||||||
|
/* SDA hold time = bus period (s) * mul * SDA hold value. */
|
||||||
|
/* SCL start hold time = bus period (s) * mul * SCL start hold value. */
|
||||||
|
/* SCL stop hold time = bus period (s) * mul * SCL stop hold value. */
|
||||||
|
|
||||||
|
for (mult = 0u; (mult <= 2u) && (bestError != 0); ++mult)
|
||||||
|
{
|
||||||
|
multiplier = 1u << mult;
|
||||||
|
|
||||||
|
/* Scan table to find best match. */
|
||||||
|
for (i = 0u; i < sizeof(s_i2cDividerTable) / sizeof(s_i2cDividerTable[0]); ++i)
|
||||||
|
{
|
||||||
|
/* Assume SCL hold(stop) value = s_i2cDividerTable[i]/2. */
|
||||||
|
computedSclHoldTime = ((multiplier * s_i2cDividerTable[i]) * 500000000U) / sourceClock_Hz;
|
||||||
|
absError = sclStopHoldTime_ns > computedSclHoldTime ? (sclStopHoldTime_ns - computedSclHoldTime) :
|
||||||
|
(computedSclHoldTime - sclStopHoldTime_ns);
|
||||||
|
|
||||||
|
if (absError < bestError)
|
||||||
|
{
|
||||||
|
bestMult = mult;
|
||||||
|
bestIcr = i;
|
||||||
|
bestError = absError;
|
||||||
|
|
||||||
|
/* If the error is 0, then we can stop searching because we won't find a better match. */
|
||||||
|
if (absError == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set frequency register based on best settings. */
|
||||||
|
base->F = I2C_F_MULT(bestMult) | I2C_F_ICR(bestIcr);
|
||||||
|
}
|
||||||
|
|
||||||
static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t *handle, i2c_master_transfer_t *xfer)
|
static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t *handle, i2c_master_transfer_t *xfer)
|
||||||
{
|
{
|
||||||
status_t result = kStatus_Success;
|
status_t result = kStatus_Success;
|
||||||
i2c_direction_t direction = xfer->direction;
|
i2c_direction_t direction = xfer->direction;
|
||||||
uint16_t timeout = UINT16_MAX;
|
|
||||||
|
|
||||||
/* Initialize the handle transfer information. */
|
/* Initialize the handle transfer information. */
|
||||||
handle->transfer = *xfer;
|
handle->transfer = *xfer;
|
||||||
|
@ -183,27 +245,13 @@ static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t
|
||||||
/* Initial transfer state. */
|
/* Initial transfer state. */
|
||||||
if (handle->transfer.subaddressSize > 0)
|
if (handle->transfer.subaddressSize > 0)
|
||||||
{
|
{
|
||||||
handle->state = kSendCommandState;
|
|
||||||
if (xfer->direction == kI2C_Read)
|
if (xfer->direction == kI2C_Read)
|
||||||
{
|
{
|
||||||
direction = kI2C_Write;
|
direction = kI2C_Write;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
handle->state = kCheckAddressState;
|
handle->state = kCheckAddressState;
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait until the data register is ready for transmit. */
|
|
||||||
while ((!(base->S & kI2C_TransferCompleteFlag)) && (--timeout))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Failed to start the transfer. */
|
|
||||||
if (timeout == 0)
|
|
||||||
{
|
|
||||||
return kStatus_I2C_Timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear all status before transfer. */
|
/* Clear all status before transfer. */
|
||||||
I2C_MasterClearStatusFlags(base, kClearFlags);
|
I2C_MasterClearStatusFlags(base, kClearFlags);
|
||||||
|
@ -265,18 +313,19 @@ static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_han
|
||||||
result = kStatus_Success;
|
result = kStatus_Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle Check address state to check the slave address is Acked in slave
|
/* Handle Check address state to check the slave address is Acked in slave
|
||||||
probe application. */
|
probe application. */
|
||||||
if (handle->state == kCheckAddressState)
|
if (handle->state == kCheckAddressState)
|
||||||
{
|
{
|
||||||
if (statusFlags & kI2C_ReceiveNakFlag)
|
if (statusFlags & kI2C_ReceiveNakFlag)
|
||||||
{
|
{
|
||||||
return kStatus_I2C_Nak;
|
result = kStatus_I2C_Addr_Nak;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (handle->transfer.subaddressSize > 0)
|
||||||
|
{
|
||||||
|
handle->state = kSendCommandState;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -292,6 +341,12 @@ static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_han
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* Run state machine. */
|
/* Run state machine. */
|
||||||
switch (handle->state)
|
switch (handle->state)
|
||||||
|
@ -375,6 +430,10 @@ static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_han
|
||||||
{
|
{
|
||||||
result = I2C_MasterStop(base);
|
result = I2C_MasterStop(base);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base->C1 |= I2C_C1_TX_MASK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send NAK at the last receive byte. */
|
/* Send NAK at the last receive byte. */
|
||||||
|
@ -407,6 +466,7 @@ static void I2C_TransferCommonIRQHandler(I2C_Type *base, void *handle)
|
||||||
{
|
{
|
||||||
s_i2cSlaveIsr(base, handle);
|
s_i2cSlaveIsr(base, handle);
|
||||||
}
|
}
|
||||||
|
__DSB();
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz)
|
void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz)
|
||||||
|
@ -415,14 +475,26 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin
|
||||||
|
|
||||||
/* Temporary register for filter read. */
|
/* Temporary register for filter read. */
|
||||||
uint8_t fltReg;
|
uint8_t fltReg;
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
uint8_t c2Reg;
|
|
||||||
#endif
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
||||||
uint8_t s2Reg;
|
uint8_t s2Reg;
|
||||||
#endif
|
#endif
|
||||||
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||||
/* Enable I2C clock. */
|
/* Enable I2C clock. */
|
||||||
CLOCK_EnableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
CLOCK_EnableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
||||||
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||||
|
|
||||||
|
/* Reset the module. */
|
||||||
|
base->A1 = 0;
|
||||||
|
base->F = 0;
|
||||||
|
base->C1 = 0;
|
||||||
|
base->S = 0xFFU;
|
||||||
|
base->C2 = 0;
|
||||||
|
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||||
|
base->FLT = 0x50U;
|
||||||
|
#elif defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT
|
||||||
|
base->FLT = 0x40U;
|
||||||
|
#endif
|
||||||
|
base->RA = 0;
|
||||||
|
|
||||||
/* Disable I2C prior to configuring it. */
|
/* Disable I2C prior to configuring it. */
|
||||||
base->C1 &= ~(I2C_C1_IICEN_MASK);
|
base->C1 &= ~(I2C_C1_IICEN_MASK);
|
||||||
|
@ -433,14 +505,6 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin
|
||||||
/* Configure baud rate. */
|
/* Configure baud rate. */
|
||||||
I2C_MasterSetBaudRate(base, masterConfig->baudRate_Bps, srcClock_Hz);
|
I2C_MasterSetBaudRate(base, masterConfig->baudRate_Bps, srcClock_Hz);
|
||||||
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
/* Configure high drive feature. */
|
|
||||||
c2Reg = base->C2;
|
|
||||||
c2Reg &= ~(I2C_C2_HDRS_MASK);
|
|
||||||
c2Reg |= I2C_C2_HDRS(masterConfig->enableHighDrive);
|
|
||||||
base->C2 = c2Reg;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Read out the FLT register. */
|
/* Read out the FLT register. */
|
||||||
fltReg = base->FLT;
|
fltReg = base->FLT;
|
||||||
|
|
||||||
|
@ -472,8 +536,10 @@ void I2C_MasterDeinit(I2C_Type *base)
|
||||||
/* Disable I2C module. */
|
/* Disable I2C module. */
|
||||||
I2C_Enable(base, false);
|
I2C_Enable(base, false);
|
||||||
|
|
||||||
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||||
/* Disable I2C clock. */
|
/* Disable I2C clock. */
|
||||||
CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
||||||
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig)
|
void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig)
|
||||||
|
@ -483,11 +549,6 @@ void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig)
|
||||||
/* Default baud rate at 100kbps. */
|
/* Default baud rate at 100kbps. */
|
||||||
masterConfig->baudRate_Bps = 100000U;
|
masterConfig->baudRate_Bps = 100000U;
|
||||||
|
|
||||||
/* Default pin high drive is disabled. */
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
masterConfig->enableHighDrive = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Default stop hold enable is disabled. */
|
/* Default stop hold enable is disabled. */
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF
|
#if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF
|
||||||
masterConfig->enableStopHold = false;
|
masterConfig->enableStopHold = false;
|
||||||
|
@ -654,7 +715,7 @@ status_t I2C_MasterRepeatedStart(I2C_Type *base, uint8_t address, i2c_direction_
|
||||||
base->F = savedMult & (~I2C_F_MULT_MASK);
|
base->F = savedMult & (~I2C_F_MULT_MASK);
|
||||||
|
|
||||||
/* We are already in a transfer, so send a repeated start. */
|
/* We are already in a transfer, so send a repeated start. */
|
||||||
base->C1 |= I2C_C1_RSTA_MASK;
|
base->C1 |= I2C_C1_RSTA_MASK | I2C_C1_TX_MASK;
|
||||||
|
|
||||||
/* Restore the multiplier factor. */
|
/* Restore the multiplier factor. */
|
||||||
base->F = savedMult;
|
base->F = savedMult;
|
||||||
|
@ -721,7 +782,7 @@ uint32_t I2C_MasterGetStatusFlags(I2C_Type *base)
|
||||||
return statusFlags;
|
return statusFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize)
|
status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize, uint32_t flags)
|
||||||
{
|
{
|
||||||
status_t result = kStatus_Success;
|
status_t result = kStatus_Success;
|
||||||
uint8_t statusFlags = 0;
|
uint8_t statusFlags = 0;
|
||||||
|
@ -772,10 +833,19 @@ status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (((result == kStatus_Success) && (!(flags & kI2C_TransferNoStopFlag))) || (result == kStatus_I2C_Nak))
|
||||||
|
{
|
||||||
|
/* Clear the IICIF flag. */
|
||||||
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
|
/* Send stop. */
|
||||||
|
result = I2C_MasterStop(base);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize)
|
status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize, uint32_t flags)
|
||||||
{
|
{
|
||||||
status_t result = kStatus_Success;
|
status_t result = kStatus_Success;
|
||||||
volatile uint8_t dummy = 0;
|
volatile uint8_t dummy = 0;
|
||||||
|
@ -817,9 +887,17 @@ status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize)
|
||||||
/* Single byte use case. */
|
/* Single byte use case. */
|
||||||
if (rxSize == 0)
|
if (rxSize == 0)
|
||||||
{
|
{
|
||||||
/* Read the final byte. */
|
if (!(flags & kI2C_TransferNoStopFlag))
|
||||||
|
{
|
||||||
|
/* Issue STOP command before reading last byte. */
|
||||||
result = I2C_MasterStop(base);
|
result = I2C_MasterStop(base);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Change direction to Tx to avoid extra clocks. */
|
||||||
|
base->C1 |= I2C_C1_TX_MASK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (rxSize == 1)
|
if (rxSize == 1)
|
||||||
{
|
{
|
||||||
|
@ -871,19 +949,42 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if there's transfer error. */
|
||||||
|
result = I2C_CheckAndClearError(base, base->S);
|
||||||
|
|
||||||
|
/* Return if error. */
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
if (result == kStatus_I2C_Nak)
|
||||||
|
{
|
||||||
|
result = kStatus_I2C_Addr_Nak;
|
||||||
|
|
||||||
|
I2C_MasterStop(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* Send subaddress. */
|
/* Send subaddress. */
|
||||||
if (xfer->subaddressSize)
|
if (xfer->subaddressSize)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
/* Clear interrupt pending flag. */
|
||||||
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
|
xfer->subaddressSize--;
|
||||||
|
base->D = ((xfer->subaddress) >> (8 * xfer->subaddressSize));
|
||||||
|
|
||||||
/* Wait until data transfer complete. */
|
/* Wait until data transfer complete. */
|
||||||
while (!(base->S & kI2C_IntPendingFlag))
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear interrupt pending flag. */
|
|
||||||
base->S = kI2C_IntPendingFlag;
|
|
||||||
|
|
||||||
/* Check if there's transfer error. */
|
/* Check if there's transfer error. */
|
||||||
result = I2C_CheckAndClearError(base, base->S);
|
result = I2C_CheckAndClearError(base, base->S);
|
||||||
|
|
||||||
|
@ -897,34 +998,13 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
xfer->subaddressSize--;
|
|
||||||
base->D = ((xfer->subaddress) >> (8 * xfer->subaddressSize));
|
|
||||||
|
|
||||||
} while ((xfer->subaddressSize > 0) && (result == kStatus_Success));
|
} while ((xfer->subaddressSize > 0) && (result == kStatus_Success));
|
||||||
|
|
||||||
if (xfer->direction == kI2C_Read)
|
if (xfer->direction == kI2C_Read)
|
||||||
{
|
{
|
||||||
/* Wait until data transfer complete. */
|
|
||||||
while (!(base->S & kI2C_IntPendingFlag))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear pending flag. */
|
/* Clear pending flag. */
|
||||||
base->S = kI2C_IntPendingFlag;
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
/* Check if there's transfer error. */
|
|
||||||
result = I2C_CheckAndClearError(base, base->S);
|
|
||||||
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
if (result == kStatus_I2C_Nak)
|
|
||||||
{
|
|
||||||
I2C_MasterStop(base);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send repeated start and slave address. */
|
/* Send repeated start and slave address. */
|
||||||
result = I2C_MasterRepeatedStart(base, xfer->slaveAddress, kI2C_Read);
|
result = I2C_MasterRepeatedStart(base, xfer->slaveAddress, kI2C_Read);
|
||||||
|
|
||||||
|
@ -933,10 +1013,8 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait until address + command transfer complete. */
|
/* Wait until data transfer complete. */
|
||||||
while (!(base->S & kI2C_IntPendingFlag))
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -944,37 +1022,31 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
|
||||||
/* Check if there's transfer error. */
|
/* Check if there's transfer error. */
|
||||||
result = I2C_CheckAndClearError(base, base->S);
|
result = I2C_CheckAndClearError(base, base->S);
|
||||||
|
|
||||||
/* Return if error. */
|
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
if (result == kStatus_I2C_Nak)
|
if (result == kStatus_I2C_Nak)
|
||||||
{
|
{
|
||||||
|
result = kStatus_I2C_Addr_Nak;
|
||||||
|
|
||||||
I2C_MasterStop(base);
|
I2C_MasterStop(base);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Transmit data. */
|
/* Transmit data. */
|
||||||
if ((xfer->direction == kI2C_Write) && (xfer->dataSize > 0))
|
if ((xfer->direction == kI2C_Write) && (xfer->dataSize > 0))
|
||||||
{
|
{
|
||||||
/* Send Data. */
|
/* Send Data. */
|
||||||
result = I2C_MasterWriteBlocking(base, xfer->data, xfer->dataSize);
|
result = I2C_MasterWriteBlocking(base, xfer->data, xfer->dataSize, xfer->flags);
|
||||||
|
|
||||||
if (((result == kStatus_Success) && (!(xfer->flags & kI2C_TransferNoStopFlag))) || (result == kStatus_I2C_Nak))
|
|
||||||
{
|
|
||||||
/* Clear the IICIF flag. */
|
|
||||||
base->S = kI2C_IntPendingFlag;
|
|
||||||
|
|
||||||
/* Send stop. */
|
|
||||||
result = I2C_MasterStop(base);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Receive Data. */
|
/* Receive Data. */
|
||||||
if ((xfer->direction == kI2C_Read) && (xfer->dataSize > 0))
|
if ((xfer->direction == kI2C_Read) && (xfer->dataSize > 0))
|
||||||
{
|
{
|
||||||
result = I2C_MasterReadBlocking(base, xfer->data, xfer->dataSize);
|
result = I2C_MasterReadBlocking(base, xfer->data, xfer->dataSize, xfer->flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -1037,11 +1109,37 @@ void I2C_MasterTransferAbort(I2C_Type *base, i2c_master_handle_t *handle)
|
||||||
{
|
{
|
||||||
assert(handle);
|
assert(handle);
|
||||||
|
|
||||||
|
volatile uint8_t dummy = 0;
|
||||||
|
|
||||||
|
/* Add this to avoid build warning. */
|
||||||
|
dummy++;
|
||||||
|
|
||||||
/* Disable interrupt. */
|
/* Disable interrupt. */
|
||||||
I2C_DisableInterrupts(base, kI2C_GlobalInterruptEnable);
|
I2C_DisableInterrupts(base, kI2C_GlobalInterruptEnable);
|
||||||
|
|
||||||
/* Reset the state to idle. */
|
/* Reset the state to idle. */
|
||||||
handle->state = kIdleState;
|
handle->state = kIdleState;
|
||||||
|
|
||||||
|
/* Send STOP signal. */
|
||||||
|
if (handle->transfer.direction == kI2C_Read)
|
||||||
|
{
|
||||||
|
base->C1 |= I2C_C1_TXAK_MASK;
|
||||||
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
|
base->C1 &= ~(I2C_C1_MST_MASK | I2C_C1_TX_MASK | I2C_C1_TXAK_MASK);
|
||||||
|
dummy = base->D;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
base->C1 &= ~(I2C_C1_MST_MASK | I2C_C1_TX_MASK | I2C_C1_TXAK_MASK);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t I2C_MasterTransferGetCount(I2C_Type *base, i2c_master_handle_t *handle, size_t *count)
|
status_t I2C_MasterTransferGetCount(I2C_Type *base, i2c_master_handle_t *handle, size_t *count)
|
||||||
|
@ -1075,7 +1173,8 @@ void I2C_MasterTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
if (isDone || result)
|
if (isDone || result)
|
||||||
{
|
{
|
||||||
/* Send stop command if transfer done or received Nak. */
|
/* Send stop command if transfer done or received Nak. */
|
||||||
if ((!(handle->transfer.flags & kI2C_TransferNoStopFlag)) || (result == kStatus_I2C_Nak))
|
if ((!(handle->transfer.flags & kI2C_TransferNoStopFlag)) || (result == kStatus_I2C_Nak) ||
|
||||||
|
(result == kStatus_I2C_Addr_Nak))
|
||||||
{
|
{
|
||||||
/* Ensure stop command is a need. */
|
/* Ensure stop command is a need. */
|
||||||
if ((base->C1 & I2C_C1_MST_MASK))
|
if ((base->C1 & I2C_C1_MST_MASK))
|
||||||
|
@ -1101,13 +1200,28 @@ void I2C_MasterTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig)
|
void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig, uint32_t srcClock_Hz)
|
||||||
{
|
{
|
||||||
assert(slaveConfig);
|
assert(slaveConfig);
|
||||||
|
|
||||||
uint8_t tmpReg;
|
uint8_t tmpReg;
|
||||||
|
|
||||||
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||||
CLOCK_EnableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
CLOCK_EnableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
||||||
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||||
|
|
||||||
|
/* Reset the module. */
|
||||||
|
base->A1 = 0;
|
||||||
|
base->F = 0;
|
||||||
|
base->C1 = 0;
|
||||||
|
base->S = 0xFFU;
|
||||||
|
base->C2 = 0;
|
||||||
|
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||||
|
base->FLT = 0x50U;
|
||||||
|
#elif defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT
|
||||||
|
base->FLT = 0x40U;
|
||||||
|
#endif
|
||||||
|
base->RA = 0;
|
||||||
|
|
||||||
/* Configure addressing mode. */
|
/* Configure addressing mode. */
|
||||||
switch (slaveConfig->addressingMode)
|
switch (slaveConfig->addressingMode)
|
||||||
|
@ -1132,14 +1246,10 @@ void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig)
|
||||||
tmpReg &= ~I2C_C1_WUEN_MASK;
|
tmpReg &= ~I2C_C1_WUEN_MASK;
|
||||||
base->C1 = tmpReg | I2C_C1_WUEN(slaveConfig->enableWakeUp) | I2C_C1_IICEN(slaveConfig->enableSlave);
|
base->C1 = tmpReg | I2C_C1_WUEN(slaveConfig->enableWakeUp) | I2C_C1_IICEN(slaveConfig->enableSlave);
|
||||||
|
|
||||||
/* Configure general call & baud rate control & high drive feature. */
|
/* Configure general call & baud rate control. */
|
||||||
tmpReg = base->C2;
|
tmpReg = base->C2;
|
||||||
tmpReg &= ~(I2C_C2_SBRC_MASK | I2C_C2_GCAEN_MASK);
|
tmpReg &= ~(I2C_C2_SBRC_MASK | I2C_C2_GCAEN_MASK);
|
||||||
tmpReg |= I2C_C2_SBRC(slaveConfig->enableBaudRateCtl) | I2C_C2_GCAEN(slaveConfig->enableGeneralCall);
|
tmpReg |= I2C_C2_SBRC(slaveConfig->enableBaudRateCtl) | I2C_C2_GCAEN(slaveConfig->enableGeneralCall);
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
tmpReg &= ~I2C_C2_HDRS_MASK;
|
|
||||||
tmpReg |= I2C_C2_HDRS(slaveConfig->enableHighDrive);
|
|
||||||
#endif
|
|
||||||
base->C2 = tmpReg;
|
base->C2 = tmpReg;
|
||||||
|
|
||||||
/* Enable/Disable double buffering. */
|
/* Enable/Disable double buffering. */
|
||||||
|
@ -1147,6 +1257,9 @@ void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig)
|
||||||
tmpReg = base->S2 & (~I2C_S2_DFEN_MASK);
|
tmpReg = base->S2 & (~I2C_S2_DFEN_MASK);
|
||||||
base->S2 = tmpReg | I2C_S2_DFEN(slaveConfig->enableDoubleBuffering);
|
base->S2 = tmpReg | I2C_S2_DFEN(slaveConfig->enableDoubleBuffering);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Set hold time. */
|
||||||
|
I2C_SetHoldTime(base, slaveConfig->sclStopHoldTime_ns, srcClock_Hz);
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2C_SlaveDeinit(I2C_Type *base)
|
void I2C_SlaveDeinit(I2C_Type *base)
|
||||||
|
@ -1154,8 +1267,10 @@ void I2C_SlaveDeinit(I2C_Type *base)
|
||||||
/* Disable I2C module. */
|
/* Disable I2C module. */
|
||||||
I2C_Enable(base, false);
|
I2C_Enable(base, false);
|
||||||
|
|
||||||
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||||
/* Disable I2C clock. */
|
/* Disable I2C clock. */
|
||||||
CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
||||||
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig)
|
void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig)
|
||||||
|
@ -1171,11 +1286,6 @@ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig)
|
||||||
/* Slave address match waking up MCU from low power mode is disabled. */
|
/* Slave address match waking up MCU from low power mode is disabled. */
|
||||||
slaveConfig->enableWakeUp = false;
|
slaveConfig->enableWakeUp = false;
|
||||||
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
/* Default pin high drive is disabled. */
|
|
||||||
slaveConfig->enableHighDrive = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Independent slave mode baud rate at maximum frequency is disabled. */
|
/* Independent slave mode baud rate at maximum frequency is disabled. */
|
||||||
slaveConfig->enableBaudRateCtl = false;
|
slaveConfig->enableBaudRateCtl = false;
|
||||||
|
|
||||||
|
@ -1184,6 +1294,9 @@ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig)
|
||||||
slaveConfig->enableDoubleBuffering = true;
|
slaveConfig->enableDoubleBuffering = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Set default SCL stop hold time to 4us which is minimum requirement in I2C spec. */
|
||||||
|
slaveConfig->sclStopHoldTime_ns = 4000;
|
||||||
|
|
||||||
/* Enable the I2C peripheral. */
|
/* Enable the I2C peripheral. */
|
||||||
slaveConfig->enableSlave = true;
|
slaveConfig->enableSlave = true;
|
||||||
}
|
}
|
||||||
|
@ -1215,7 +1328,7 @@ status_t I2C_SlaveWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t tx
|
||||||
/* Read dummy to release bus. */
|
/* Read dummy to release bus. */
|
||||||
dummy = base->D;
|
dummy = base->D;
|
||||||
|
|
||||||
result = I2C_MasterWriteBlocking(base, txBuff, txSize);
|
result = I2C_MasterWriteBlocking(base, txBuff, txSize, kI2C_TransferDefaultFlag);
|
||||||
|
|
||||||
/* Switch to receive mode. */
|
/* Switch to receive mode. */
|
||||||
base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK);
|
base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK);
|
||||||
|
@ -1323,7 +1436,7 @@ status_t I2C_SlaveTransferNonBlocking(I2C_Type *base, i2c_slave_handle_t *handle
|
||||||
handle->isBusy = true;
|
handle->isBusy = true;
|
||||||
|
|
||||||
/* Set up event mask. tx and rx are always enabled. */
|
/* Set up event mask. tx and rx are always enabled. */
|
||||||
handle->eventMask = eventMask | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent;
|
handle->eventMask = eventMask | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent | kI2C_SlaveGenaralcallEvent;
|
||||||
|
|
||||||
/* Clear all flags. */
|
/* Clear all flags. */
|
||||||
I2C_SlaveClearStatusFlags(base, kClearFlags);
|
I2C_SlaveClearStatusFlags(base, kClearFlags);
|
||||||
|
@ -1412,8 +1525,11 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(status & kI2C_AddressMatchFlag))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif /* I2C_HAS_STOP_DETECT */
|
#endif /* I2C_HAS_STOP_DETECT */
|
||||||
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||||
|
@ -1482,11 +1598,6 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
handle->isBusy = true;
|
handle->isBusy = true;
|
||||||
xfer->event = kI2C_SlaveAddressMatchEvent;
|
xfer->event = kI2C_SlaveAddressMatchEvent;
|
||||||
|
|
||||||
if ((handle->eventMask & xfer->event) && (handle->callback))
|
|
||||||
{
|
|
||||||
handle->callback(base, xfer, handle->userData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Slave transmit, master reading from slave. */
|
/* Slave transmit, master reading from slave. */
|
||||||
if (status & kI2C_TransferDirectionFlag)
|
if (status & kI2C_TransferDirectionFlag)
|
||||||
{
|
{
|
||||||
|
@ -1502,6 +1613,16 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
|
|
||||||
/* Read dummy to release the bus. */
|
/* Read dummy to release the bus. */
|
||||||
dummy = base->D;
|
dummy = base->D;
|
||||||
|
|
||||||
|
if (dummy == 0)
|
||||||
|
{
|
||||||
|
xfer->event = kI2C_SlaveGenaralcallEvent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((handle->eventMask & xfer->event) && (handle->callback))
|
||||||
|
{
|
||||||
|
handle->callback(base, xfer, handle->userData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Check transfer complete flag. */
|
/* Check transfer complete flag. */
|
||||||
|
@ -1607,27 +1728,30 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(I2C0)
|
||||||
void I2C0_DriverIRQHandler(void)
|
void I2C0_DriverIRQHandler(void)
|
||||||
{
|
{
|
||||||
I2C_TransferCommonIRQHandler(I2C0, s_i2cHandle[0]);
|
I2C_TransferCommonIRQHandler(I2C0, s_i2cHandle[0]);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (FSL_FEATURE_SOC_I2C_COUNT > 1)
|
#if defined(I2C1)
|
||||||
void I2C1_DriverIRQHandler(void)
|
void I2C1_DriverIRQHandler(void)
|
||||||
{
|
{
|
||||||
I2C_TransferCommonIRQHandler(I2C1, s_i2cHandle[1]);
|
I2C_TransferCommonIRQHandler(I2C1, s_i2cHandle[1]);
|
||||||
}
|
}
|
||||||
#endif /* I2C COUNT > 1 */
|
#endif
|
||||||
|
|
||||||
#if (FSL_FEATURE_SOC_I2C_COUNT > 2)
|
#if defined(I2C2)
|
||||||
void I2C2_DriverIRQHandler(void)
|
void I2C2_DriverIRQHandler(void)
|
||||||
{
|
{
|
||||||
I2C_TransferCommonIRQHandler(I2C2, s_i2cHandle[2]);
|
I2C_TransferCommonIRQHandler(I2C2, s_i2cHandle[2]);
|
||||||
}
|
}
|
||||||
#endif /* I2C COUNT > 2 */
|
#endif
|
||||||
#if (FSL_FEATURE_SOC_I2C_COUNT > 3)
|
|
||||||
|
#if defined(I2C3)
|
||||||
void I2C3_DriverIRQHandler(void)
|
void I2C3_DriverIRQHandler(void)
|
||||||
{
|
{
|
||||||
I2C_TransferCommonIRQHandler(I2C3, s_i2cHandle[3]);
|
I2C_TransferCommonIRQHandler(I2C3, s_i2cHandle[3]);
|
||||||
}
|
}
|
||||||
#endif /* I2C COUNT > 3 */
|
#endif
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||||
* All rights reserved.
|
* Copyright 2016-2017 NXP
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
* other materials provided with the distribution.
|
* other materials provided with the distribution.
|
||||||
*
|
*
|
||||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
* o Neither the name of the copyright holder nor the names of its
|
||||||
* contributors may be used to endorse or promote products derived from this
|
* contributors may be used to endorse or promote products derived from this
|
||||||
* software without specific prior written permission.
|
* software without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -37,15 +37,14 @@
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Definitions
|
* Definitions
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
/*! @name Driver version */
|
/*! @name Driver version */
|
||||||
/*@{*/
|
/*@{*/
|
||||||
/*! @brief I2C driver version 2.0.1. */
|
/*! @brief I2C driver version 2.0.3. */
|
||||||
#define FSL_I2C_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))
|
#define FSL_I2C_DRIVER_VERSION (MAKE_VERSION(2, 0, 3))
|
||||||
/*@}*/
|
/*@}*/
|
||||||
|
|
||||||
#if (defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT || \
|
#if (defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT || \
|
||||||
|
@ -61,6 +60,7 @@ enum _i2c_status
|
||||||
kStatus_I2C_Nak = MAKE_STATUS(kStatusGroup_I2C, 2), /*!< NAK received during transfer. */
|
kStatus_I2C_Nak = MAKE_STATUS(kStatusGroup_I2C, 2), /*!< NAK received during transfer. */
|
||||||
kStatus_I2C_ArbitrationLost = MAKE_STATUS(kStatusGroup_I2C, 3), /*!< Arbitration lost during transfer. */
|
kStatus_I2C_ArbitrationLost = MAKE_STATUS(kStatusGroup_I2C, 3), /*!< Arbitration lost during transfer. */
|
||||||
kStatus_I2C_Timeout = MAKE_STATUS(kStatusGroup_I2C, 4), /*!< Wait event timeout. */
|
kStatus_I2C_Timeout = MAKE_STATUS(kStatusGroup_I2C, 4), /*!< Wait event timeout. */
|
||||||
|
kStatus_I2C_Addr_Nak = MAKE_STATUS(kStatusGroup_I2C, 5), /*!< NAK received during the address probe. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -108,11 +108,11 @@ enum _i2c_interrupt_enable
|
||||||
#endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */
|
#endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! @brief Direction of master and slave transfers. */
|
/*! @brief The direction of master and slave transfers. */
|
||||||
typedef enum _i2c_direction
|
typedef enum _i2c_direction
|
||||||
{
|
{
|
||||||
kI2C_Write = 0x0U, /*!< Master transmit to slave. */
|
kI2C_Write = 0x0U, /*!< Master transmits to the slave. */
|
||||||
kI2C_Read = 0x1U, /*!< Master receive from slave. */
|
kI2C_Read = 0x1U, /*!< Master receives from the slave. */
|
||||||
} i2c_direction_t;
|
} i2c_direction_t;
|
||||||
|
|
||||||
/*! @brief Addressing mode. */
|
/*! @brief Addressing mode. */
|
||||||
|
@ -125,17 +125,17 @@ typedef enum _i2c_slave_address_mode
|
||||||
/*! @brief I2C transfer control flag. */
|
/*! @brief I2C transfer control flag. */
|
||||||
enum _i2c_master_transfer_flags
|
enum _i2c_master_transfer_flags
|
||||||
{
|
{
|
||||||
kI2C_TransferDefaultFlag = 0x0U, /*!< Transfer starts with a start signal, stops with a stop signal. */
|
kI2C_TransferDefaultFlag = 0x0U, /*!< A transfer starts with a start signal, stops with a stop signal. */
|
||||||
kI2C_TransferNoStartFlag = 0x1U, /*!< Transfer starts without a start signal. */
|
kI2C_TransferNoStartFlag = 0x1U, /*!< A transfer starts without a start signal. */
|
||||||
kI2C_TransferRepeatedStartFlag = 0x2U, /*!< Transfer starts with a repeated start signal. */
|
kI2C_TransferRepeatedStartFlag = 0x2U, /*!< A transfer starts with a repeated start signal. */
|
||||||
kI2C_TransferNoStopFlag = 0x4U, /*!< Transfer ends without a stop signal. */
|
kI2C_TransferNoStopFlag = 0x4U, /*!< A transfer ends without a stop signal. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Set of events sent to the callback for nonblocking slave transfers.
|
* @brief Set of events sent to the callback for nonblocking slave transfers.
|
||||||
*
|
*
|
||||||
* These event enumerations are used for two related purposes. First, a bit mask created by OR'ing together
|
* These event enumerations are used for two related purposes. First, a bit mask created by OR'ing together
|
||||||
* events is passed to I2C_SlaveTransferNonBlocking() in order to specify which events to enable.
|
* events is passed to I2C_SlaveTransferNonBlocking() to specify which events to enable.
|
||||||
* Then, when the slave callback is invoked, it is passed the current event through its @a transfer
|
* Then, when the slave callback is invoked, it is passed the current event through its @a transfer
|
||||||
* parameter.
|
* parameter.
|
||||||
*
|
*
|
||||||
|
@ -144,36 +144,34 @@ enum _i2c_master_transfer_flags
|
||||||
typedef enum _i2c_slave_transfer_event
|
typedef enum _i2c_slave_transfer_event
|
||||||
{
|
{
|
||||||
kI2C_SlaveAddressMatchEvent = 0x01U, /*!< Received the slave address after a start or repeated start. */
|
kI2C_SlaveAddressMatchEvent = 0x01U, /*!< Received the slave address after a start or repeated start. */
|
||||||
kI2C_SlaveTransmitEvent = 0x02U, /*!< Callback is requested to provide data to transmit
|
kI2C_SlaveTransmitEvent = 0x02U, /*!< A callback is requested to provide data to transmit
|
||||||
(slave-transmitter role). */
|
(slave-transmitter role). */
|
||||||
kI2C_SlaveReceiveEvent = 0x04U, /*!< Callback is requested to provide a buffer in which to place received
|
kI2C_SlaveReceiveEvent = 0x04U, /*!< A callback is requested to provide a buffer in which to place received
|
||||||
data (slave-receiver role). */
|
data (slave-receiver role). */
|
||||||
kI2C_SlaveTransmitAckEvent = 0x08U, /*!< Callback needs to either transmit an ACK or NACK. */
|
kI2C_SlaveTransmitAckEvent = 0x08U, /*!< A callback needs to either transmit an ACK or NACK. */
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||||
kI2C_SlaveStartEvent = 0x10U, /*!< A start/repeated start was detected. */
|
kI2C_SlaveStartEvent = 0x10U, /*!< A start/repeated start was detected. */
|
||||||
#endif
|
#endif
|
||||||
kI2C_SlaveCompletionEvent = 0x20U, /*!< A stop was detected or finished transfer, completing the transfer. */
|
kI2C_SlaveCompletionEvent = 0x20U, /*!< A stop was detected or finished transfer, completing the transfer. */
|
||||||
|
kI2C_SlaveGenaralcallEvent = 0x40U, /*!< Received the general call address after a start or repeated start. */
|
||||||
|
|
||||||
/*! Bit mask of all available events. */
|
/*! A bit mask of all available events. */
|
||||||
kI2C_SlaveAllEvents = kI2C_SlaveAddressMatchEvent | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent |
|
kI2C_SlaveAllEvents = kI2C_SlaveAddressMatchEvent | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent |
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||||
kI2C_SlaveStartEvent |
|
kI2C_SlaveStartEvent |
|
||||||
#endif
|
#endif
|
||||||
kI2C_SlaveCompletionEvent,
|
kI2C_SlaveCompletionEvent | kI2C_SlaveGenaralcallEvent,
|
||||||
} i2c_slave_transfer_event_t;
|
} i2c_slave_transfer_event_t;
|
||||||
|
|
||||||
/*! @brief I2C master user configuration. */
|
/*! @brief I2C master user configuration. */
|
||||||
typedef struct _i2c_master_config
|
typedef struct _i2c_master_config
|
||||||
{
|
{
|
||||||
bool enableMaster; /*!< Enables the I2C peripheral at initialization time. */
|
bool enableMaster; /*!< Enables the I2C peripheral at initialization time. */
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
bool enableHighDrive; /*!< Controls the drive capability of the I2C pads. */
|
|
||||||
#endif
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF
|
#if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF
|
||||||
bool enableStopHold; /*!< Controls the stop hold enable. */
|
bool enableStopHold; /*!< Controls the stop hold enable. */
|
||||||
#endif
|
#endif
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
||||||
bool enableDoubleBuffering; /*!< Controls double buffer enable, notice that
|
bool enableDoubleBuffering; /*!< Controls double buffer enable; notice that
|
||||||
enabling the double buffer disables the clock stretch. */
|
enabling the double buffer disables the clock stretch. */
|
||||||
#endif
|
#endif
|
||||||
uint32_t baudRate_Bps; /*!< Baud rate configuration of I2C peripheral. */
|
uint32_t baudRate_Bps; /*!< Baud rate configuration of I2C peripheral. */
|
||||||
|
@ -184,19 +182,20 @@ typedef struct _i2c_master_config
|
||||||
typedef struct _i2c_slave_config
|
typedef struct _i2c_slave_config
|
||||||
{
|
{
|
||||||
bool enableSlave; /*!< Enables the I2C peripheral at initialization time. */
|
bool enableSlave; /*!< Enables the I2C peripheral at initialization time. */
|
||||||
bool enableGeneralCall; /*!< Enable general call addressing mode. */
|
bool enableGeneralCall; /*!< Enables the general call addressing mode. */
|
||||||
bool enableWakeUp; /*!< Enables/disables waking up MCU from low-power mode. */
|
bool enableWakeUp; /*!< Enables/disables waking up MCU from low-power mode. */
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
bool enableHighDrive; /*!< Controls the drive capability of the I2C pads. */
|
|
||||||
#endif
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
||||||
bool enableDoubleBuffering; /*!< Controls double buffer enable, notice that
|
bool enableDoubleBuffering; /*!< Controls a double buffer enable; notice that
|
||||||
enabling the double buffer disables the clock stretch. */
|
enabling the double buffer disables the clock stretch. */
|
||||||
#endif
|
#endif
|
||||||
bool enableBaudRateCtl; /*!< Enables/disables independent slave baud rate on SCL in very fast I2C modes. */
|
bool enableBaudRateCtl; /*!< Enables/disables independent slave baud rate on SCL in very fast I2C modes. */
|
||||||
uint16_t slaveAddress; /*!< Slave address configuration. */
|
uint16_t slaveAddress; /*!< A slave address configuration. */
|
||||||
uint16_t upperAddress; /*!< Maximum boundary slave address used in range matching mode. */
|
uint16_t upperAddress; /*!< A maximum boundary slave address used in a range matching mode. */
|
||||||
i2c_slave_address_mode_t addressingMode; /*!< Addressing mode configuration of i2c_slave_address_mode_config_t. */
|
i2c_slave_address_mode_t
|
||||||
|
addressingMode; /*!< An addressing mode configuration of i2c_slave_address_mode_config_t. */
|
||||||
|
uint32_t sclStopHoldTime_ns; /*!< the delay from the rising edge of SCL (I2C clock) to the rising edge of SDA (I2C
|
||||||
|
data) while SCL is high (stop condition), SDA hold time and SCL start hold time
|
||||||
|
are also configured according to the SCL stop hold time. */
|
||||||
} i2c_slave_config_t;
|
} i2c_slave_config_t;
|
||||||
|
|
||||||
/*! @brief I2C master handle typedef. */
|
/*! @brief I2C master handle typedef. */
|
||||||
|
@ -214,13 +213,13 @@ typedef struct _i2c_slave_handle i2c_slave_handle_t;
|
||||||
/*! @brief I2C master transfer structure. */
|
/*! @brief I2C master transfer structure. */
|
||||||
typedef struct _i2c_master_transfer
|
typedef struct _i2c_master_transfer
|
||||||
{
|
{
|
||||||
uint32_t flags; /*!< Transfer flag which controls the transfer. */
|
uint32_t flags; /*!< A transfer flag which controls the transfer. */
|
||||||
uint8_t slaveAddress; /*!< 7-bit slave address. */
|
uint8_t slaveAddress; /*!< 7-bit slave address. */
|
||||||
i2c_direction_t direction; /*!< Transfer direction, read or write. */
|
i2c_direction_t direction; /*!< A transfer direction, read or write. */
|
||||||
uint32_t subaddress; /*!< Sub address. Transferred MSB first. */
|
uint32_t subaddress; /*!< A sub address. Transferred MSB first. */
|
||||||
uint8_t subaddressSize; /*!< Size of command buffer. */
|
uint8_t subaddressSize; /*!< A size of the command buffer. */
|
||||||
uint8_t *volatile data; /*!< Transfer buffer. */
|
uint8_t *volatile data; /*!< A transfer buffer. */
|
||||||
volatile size_t dataSize; /*!< Transfer size. */
|
volatile size_t dataSize; /*!< A transfer size. */
|
||||||
} i2c_master_transfer_t;
|
} i2c_master_transfer_t;
|
||||||
|
|
||||||
/*! @brief I2C master handle structure. */
|
/*! @brief I2C master handle structure. */
|
||||||
|
@ -228,20 +227,21 @@ struct _i2c_master_handle
|
||||||
{
|
{
|
||||||
i2c_master_transfer_t transfer; /*!< I2C master transfer copy. */
|
i2c_master_transfer_t transfer; /*!< I2C master transfer copy. */
|
||||||
size_t transferSize; /*!< Total bytes to be transferred. */
|
size_t transferSize; /*!< Total bytes to be transferred. */
|
||||||
uint8_t state; /*!< Transfer state maintained during transfer. */
|
uint8_t state; /*!< A transfer state maintained during transfer. */
|
||||||
i2c_master_transfer_callback_t completionCallback; /*!< Callback function called when transfer finished. */
|
i2c_master_transfer_callback_t completionCallback; /*!< A callback function called when the transfer is finished. */
|
||||||
void *userData; /*!< Callback parameter passed to callback function. */
|
void *userData; /*!< A callback parameter passed to the callback function. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! @brief I2C slave transfer structure. */
|
/*! @brief I2C slave transfer structure. */
|
||||||
typedef struct _i2c_slave_transfer
|
typedef struct _i2c_slave_transfer
|
||||||
{
|
{
|
||||||
i2c_slave_transfer_event_t event; /*!< Reason the callback is being invoked. */
|
i2c_slave_transfer_event_t event; /*!< A reason that the callback is invoked. */
|
||||||
uint8_t *volatile data; /*!< Transfer buffer. */
|
uint8_t *volatile data; /*!< A transfer buffer. */
|
||||||
volatile size_t dataSize; /*!< Transfer size. */
|
volatile size_t dataSize; /*!< A transfer size. */
|
||||||
status_t completionStatus; /*!< Success or error code describing how the transfer completed. Only applies for
|
status_t completionStatus; /*!< Success or error code describing how the transfer completed. Only applies for
|
||||||
#kI2C_SlaveCompletionEvent. */
|
#kI2C_SlaveCompletionEvent. */
|
||||||
size_t transferredCount; /*!< Number of bytes actually transferred since start or last repeated start. */
|
size_t transferredCount; /*!< A number of bytes actually transferred since the start or since the last repeated
|
||||||
|
start. */
|
||||||
} i2c_slave_transfer_t;
|
} i2c_slave_transfer_t;
|
||||||
|
|
||||||
/*! @brief I2C slave transfer callback typedef. */
|
/*! @brief I2C slave transfer callback typedef. */
|
||||||
|
@ -250,11 +250,11 @@ typedef void (*i2c_slave_transfer_callback_t)(I2C_Type *base, i2c_slave_transfer
|
||||||
/*! @brief I2C slave handle structure. */
|
/*! @brief I2C slave handle structure. */
|
||||||
struct _i2c_slave_handle
|
struct _i2c_slave_handle
|
||||||
{
|
{
|
||||||
bool isBusy; /*!< Whether transfer is busy. */
|
volatile bool isBusy; /*!< Indicates whether a transfer is busy. */
|
||||||
i2c_slave_transfer_t transfer; /*!< I2C slave transfer copy. */
|
i2c_slave_transfer_t transfer; /*!< I2C slave transfer copy. */
|
||||||
uint32_t eventMask; /*!< Mask of enabled events. */
|
uint32_t eventMask; /*!< A mask of enabled events. */
|
||||||
i2c_slave_transfer_callback_t callback; /*!< Callback function called at transfer event. */
|
i2c_slave_transfer_callback_t callback; /*!< A callback function called at the transfer event. */
|
||||||
void *userData; /*!< Callback parameter passed to callback. */
|
void *userData; /*!< A callback parameter passed to the callback. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
@ -274,12 +274,12 @@ extern "C" {
|
||||||
* @brief Initializes the I2C peripheral. Call this API to ungate the I2C clock
|
* @brief Initializes the I2C peripheral. Call this API to ungate the I2C clock
|
||||||
* and configure the I2C with master configuration.
|
* and configure the I2C with master configuration.
|
||||||
*
|
*
|
||||||
* @note This API should be called at the beginning of the application to use
|
* @note This API should be called at the beginning of the application.
|
||||||
* the I2C driver, or any operation to the I2C module may cause a hard fault
|
* Otherwise, any operation to the I2C module can cause a hard fault
|
||||||
* because clock is not enabled. The configuration structure can be filled by user
|
* because the clock is not enabled. The configuration structure can be custom filled
|
||||||
* from scratch, or be set with default values by I2C_MasterGetDefaultConfig().
|
* or it can be set with default values by using the I2C_MasterGetDefaultConfig().
|
||||||
* After calling this API, the master is ready to transfer.
|
* After calling this API, the master is ready to transfer.
|
||||||
* Example:
|
* This is an example.
|
||||||
* @code
|
* @code
|
||||||
* i2c_master_config_t config = {
|
* i2c_master_config_t config = {
|
||||||
* .enableMaster = true,
|
* .enableMaster = true,
|
||||||
|
@ -292,20 +292,20 @@ extern "C" {
|
||||||
* @endcode
|
* @endcode
|
||||||
*
|
*
|
||||||
* @param base I2C base pointer
|
* @param base I2C base pointer
|
||||||
* @param masterConfig pointer to master configuration structure
|
* @param masterConfig A pointer to the master configuration structure
|
||||||
* @param srcClock_Hz I2C peripheral clock frequency in Hz
|
* @param srcClock_Hz I2C peripheral clock frequency in Hz
|
||||||
*/
|
*/
|
||||||
void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz);
|
void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Initializes the I2C peripheral. Call this API to ungate the I2C clock
|
* @brief Initializes the I2C peripheral. Call this API to ungate the I2C clock
|
||||||
* and initializes the I2C with slave configuration.
|
* and initialize the I2C with the slave configuration.
|
||||||
*
|
*
|
||||||
* @note This API should be called at the beginning of the application to use
|
* @note This API should be called at the beginning of the application.
|
||||||
* the I2C driver, or any operation to the I2C module can cause a hard fault
|
* Otherwise, any operation to the I2C module can cause a hard fault
|
||||||
* because the clock is not enabled. The configuration structure can partly be set
|
* because the clock is not enabled. The configuration structure can partly be set
|
||||||
* with default values by I2C_SlaveGetDefaultConfig(), or can be filled by the user.
|
* with default values by I2C_SlaveGetDefaultConfig() or it can be custom filled by the user.
|
||||||
* Example
|
* This is an example.
|
||||||
* @code
|
* @code
|
||||||
* i2c_slave_config_t config = {
|
* i2c_slave_config_t config = {
|
||||||
* .enableSlave = true,
|
* .enableSlave = true,
|
||||||
|
@ -314,15 +314,17 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin
|
||||||
* .slaveAddress = 0x1DU,
|
* .slaveAddress = 0x1DU,
|
||||||
* .enableWakeUp = false,
|
* .enableWakeUp = false,
|
||||||
* .enablehighDrive = false,
|
* .enablehighDrive = false,
|
||||||
* .enableBaudRateCtl = false
|
* .enableBaudRateCtl = false,
|
||||||
|
* .sclStopHoldTime_ns = 4000
|
||||||
* };
|
* };
|
||||||
* I2C_SlaveInit(I2C0, &config);
|
* I2C_SlaveInit(I2C0, &config, 12000000U);
|
||||||
* @endcode
|
* @endcode
|
||||||
*
|
*
|
||||||
* @param base I2C base pointer
|
* @param base I2C base pointer
|
||||||
* @param slaveConfig pointer to slave configuration structure
|
* @param slaveConfig A pointer to the slave configuration structure
|
||||||
|
* @param srcClock_Hz I2C peripheral clock frequency in Hz
|
||||||
*/
|
*/
|
||||||
void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig);
|
void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig, uint32_t srcClock_Hz);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief De-initializes the I2C master peripheral. Call this API to gate the I2C clock.
|
* @brief De-initializes the I2C master peripheral. Call this API to gate the I2C clock.
|
||||||
|
@ -342,28 +344,28 @@ void I2C_SlaveDeinit(I2C_Type *base);
|
||||||
* @brief Sets the I2C master configuration structure to default values.
|
* @brief Sets the I2C master configuration structure to default values.
|
||||||
*
|
*
|
||||||
* The purpose of this API is to get the configuration structure initialized for use in the I2C_MasterConfigure().
|
* The purpose of this API is to get the configuration structure initialized for use in the I2C_MasterConfigure().
|
||||||
* Use the initialized structure unchanged in I2C_MasterConfigure(), or modify some fields of
|
* Use the initialized structure unchanged in the I2C_MasterConfigure() or modify
|
||||||
* the structure before calling I2C_MasterConfigure().
|
* the structure before calling the I2C_MasterConfigure().
|
||||||
* Example:
|
* This is an example.
|
||||||
* @code
|
* @code
|
||||||
* i2c_master_config_t config;
|
* i2c_master_config_t config;
|
||||||
* I2C_MasterGetDefaultConfig(&config);
|
* I2C_MasterGetDefaultConfig(&config);
|
||||||
* @endcode
|
* @endcode
|
||||||
* @param masterConfig Pointer to the master configuration structure.
|
* @param masterConfig A pointer to the master configuration structure.
|
||||||
*/
|
*/
|
||||||
void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig);
|
void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Sets the I2C slave configuration structure to default values.
|
* @brief Sets the I2C slave configuration structure to default values.
|
||||||
*
|
*
|
||||||
* The purpose of this API is to get the configuration structure initialized for use in I2C_SlaveConfigure().
|
* The purpose of this API is to get the configuration structure initialized for use in the I2C_SlaveConfigure().
|
||||||
* Modify fields of the structure before calling the I2C_SlaveConfigure().
|
* Modify fields of the structure before calling the I2C_SlaveConfigure().
|
||||||
* Example:
|
* This is an example.
|
||||||
* @code
|
* @code
|
||||||
* i2c_slave_config_t config;
|
* i2c_slave_config_t config;
|
||||||
* I2C_SlaveGetDefaultConfig(&config);
|
* I2C_SlaveGetDefaultConfig(&config);
|
||||||
* @endcode
|
* @endcode
|
||||||
* @param slaveConfig Pointer to the slave configuration structure.
|
* @param slaveConfig A pointer to the slave configuration structure.
|
||||||
*/
|
*/
|
||||||
void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig);
|
void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig);
|
||||||
|
|
||||||
|
@ -371,7 +373,7 @@ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig);
|
||||||
* @brief Enables or disabless the I2C peripheral operation.
|
* @brief Enables or disabless the I2C peripheral operation.
|
||||||
*
|
*
|
||||||
* @param base I2C base pointer
|
* @param base I2C base pointer
|
||||||
* @param enable pass true to enable module, false to disable module
|
* @param enable Pass true to enable and false to disable the module.
|
||||||
*/
|
*/
|
||||||
static inline void I2C_Enable(I2C_Type *base, bool enable)
|
static inline void I2C_Enable(I2C_Type *base, bool enable)
|
||||||
{
|
{
|
||||||
|
@ -414,7 +416,7 @@ static inline uint32_t I2C_SlaveGetStatusFlags(I2C_Type *base)
|
||||||
/*!
|
/*!
|
||||||
* @brief Clears the I2C status flag state.
|
* @brief Clears the I2C status flag state.
|
||||||
*
|
*
|
||||||
* The following status register flags can be cleared: kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag
|
* The following status register flags can be cleared kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag.
|
||||||
*
|
*
|
||||||
* @param base I2C base pointer
|
* @param base I2C base pointer
|
||||||
* @param statusMask The status flag mask, defined in type i2c_status_flag_t.
|
* @param statusMask The status flag mask, defined in type i2c_status_flag_t.
|
||||||
|
@ -449,7 +451,7 @@ static inline void I2C_MasterClearStatusFlags(I2C_Type *base, uint32_t statusMas
|
||||||
/*!
|
/*!
|
||||||
* @brief Clears the I2C status flag state.
|
* @brief Clears the I2C status flag state.
|
||||||
*
|
*
|
||||||
* The following status register flags can be cleared: kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag
|
* The following status register flags can be cleared kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag
|
||||||
*
|
*
|
||||||
* @param base I2C base pointer
|
* @param base I2C base pointer
|
||||||
* @param statusMask The status flag mask, defined in type i2c_status_flag_t.
|
* @param statusMask The status flag mask, defined in type i2c_status_flag_t.
|
||||||
|
@ -581,19 +583,21 @@ status_t I2C_MasterStop(I2C_Type *base);
|
||||||
status_t I2C_MasterRepeatedStart(I2C_Type *base, uint8_t address, i2c_direction_t direction);
|
status_t I2C_MasterRepeatedStart(I2C_Type *base, uint8_t address, i2c_direction_t direction);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Performs a polling send transaction on the I2C bus without a STOP signal.
|
* @brief Performs a polling send transaction on the I2C bus.
|
||||||
*
|
*
|
||||||
* @param base The I2C peripheral base pointer.
|
* @param base The I2C peripheral base pointer.
|
||||||
* @param txBuff The pointer to the data to be transferred.
|
* @param txBuff The pointer to the data to be transferred.
|
||||||
* @param txSize The length in bytes of the data to be transferred.
|
* @param txSize The length in bytes of the data to be transferred.
|
||||||
|
* @param flags Transfer control flag to decide whether need to send a stop, use kI2C_TransferDefaultFlag
|
||||||
|
* to issue a stop and kI2C_TransferNoStop to not send a stop.
|
||||||
* @retval kStatus_Success Successfully complete the data transmission.
|
* @retval kStatus_Success Successfully complete the data transmission.
|
||||||
* @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
|
* @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
|
||||||
* @retval kStataus_I2C_Nak Transfer error, receive NAK during transfer.
|
* @retval kStataus_I2C_Nak Transfer error, receive NAK during transfer.
|
||||||
*/
|
*/
|
||||||
status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize);
|
status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize, uint32_t flags);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Performs a polling receive transaction on the I2C bus with a STOP signal.
|
* @brief Performs a polling receive transaction on the I2C bus.
|
||||||
*
|
*
|
||||||
* @note The I2C_MasterReadBlocking function stops the bus before reading the final byte.
|
* @note The I2C_MasterReadBlocking function stops the bus before reading the final byte.
|
||||||
* Without stopping the bus prior for the final read, the bus issues another read, resulting
|
* Without stopping the bus prior for the final read, the bus issues another read, resulting
|
||||||
|
@ -602,10 +606,12 @@ status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t t
|
||||||
* @param base I2C peripheral base pointer.
|
* @param base I2C peripheral base pointer.
|
||||||
* @param rxBuff The pointer to the data to store the received data.
|
* @param rxBuff The pointer to the data to store the received data.
|
||||||
* @param rxSize The length in bytes of the data to be received.
|
* @param rxSize The length in bytes of the data to be received.
|
||||||
|
* @param flags Transfer control flag to decide whether need to send a stop, use kI2C_TransferDefaultFlag
|
||||||
|
* to issue a stop and kI2C_TransferNoStop to not send a stop.
|
||||||
* @retval kStatus_Success Successfully complete the data transmission.
|
* @retval kStatus_Success Successfully complete the data transmission.
|
||||||
* @retval kStatus_I2C_Timeout Send stop signal failed, timeout.
|
* @retval kStatus_I2C_Timeout Send stop signal failed, timeout.
|
||||||
*/
|
*/
|
||||||
status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize);
|
status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize, uint32_t flags);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Performs a polling send transaction on the I2C bus.
|
* @brief Performs a polling send transaction on the I2C bus.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||||
* All rights reserved.
|
* Copyright 2016-2017 NXP
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
* other materials provided with the distribution.
|
* other materials provided with the distribution.
|
||||||
*
|
*
|
||||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
* o Neither the name of the copyright holder nor the names of its
|
||||||
* contributors may be used to endorse or promote products derived from this
|
* contributors may be used to endorse or promote products derived from this
|
||||||
* software without specific prior written permission.
|
* software without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -162,6 +162,26 @@ static void I2C_MasterTransferCallbackEDMA(edma_handle_t *handle, void *userData
|
||||||
result = I2C_MasterStop(i2cPrivateHandle->base);
|
result = I2C_MasterStop(i2cPrivateHandle->base);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (i2cPrivateHandle->handle->transfer.direction == kI2C_Read)
|
||||||
|
{
|
||||||
|
/* Change to send NAK at the last byte. */
|
||||||
|
i2cPrivateHandle->base->C1 |= I2C_C1_TXAK_MASK;
|
||||||
|
|
||||||
|
/* Wait the last data to be received. */
|
||||||
|
while (!(i2cPrivateHandle->base->S & kI2C_TransferCompleteFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Change direction to send. */
|
||||||
|
i2cPrivateHandle->base->C1 |= I2C_C1_TX_MASK;
|
||||||
|
|
||||||
|
/* Read the last data byte. */
|
||||||
|
*(i2cPrivateHandle->handle->transfer.data + i2cPrivateHandle->handle->transfer.dataSize - 1) =
|
||||||
|
i2cPrivateHandle->base->D;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
i2cPrivateHandle->handle->state = kIdleState;
|
i2cPrivateHandle->handle->state = kIdleState;
|
||||||
|
|
||||||
|
@ -203,7 +223,6 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
||||||
assert(xfer);
|
assert(xfer);
|
||||||
|
|
||||||
status_t result = kStatus_Success;
|
status_t result = kStatus_Success;
|
||||||
uint16_t timeout = UINT16_MAX;
|
|
||||||
|
|
||||||
if (handle->state != kIdleState)
|
if (handle->state != kIdleState)
|
||||||
{
|
{
|
||||||
|
@ -221,16 +240,6 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
||||||
|
|
||||||
handle->state = kTransferDataState;
|
handle->state = kTransferDataState;
|
||||||
|
|
||||||
/* Wait until ready to complete. */
|
|
||||||
while ((!(base->S & kI2C_TransferCompleteFlag)) && (--timeout))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Failed to start the transfer. */
|
|
||||||
if (timeout == 0)
|
|
||||||
{
|
|
||||||
return kStatus_I2C_Timeout;
|
|
||||||
}
|
|
||||||
/* Clear all status before transfer. */
|
/* Clear all status before transfer. */
|
||||||
I2C_MasterClearStatusFlags(base, kClearFlags);
|
I2C_MasterClearStatusFlags(base, kClearFlags);
|
||||||
|
|
||||||
|
@ -250,22 +259,55 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
||||||
result = I2C_MasterStart(base, handle->transfer.slaveAddress, direction);
|
result = I2C_MasterStart(base, handle->transfer.slaveAddress, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if there's transfer error. */
|
||||||
|
result = I2C_CheckAndClearError(base, base->S);
|
||||||
|
|
||||||
|
/* Return if error. */
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
if (result == kStatus_I2C_Nak)
|
||||||
|
{
|
||||||
|
result = kStatus_I2C_Addr_Nak;
|
||||||
|
|
||||||
|
if (I2C_MasterStop(base) != kStatus_Success)
|
||||||
|
{
|
||||||
|
result = kStatus_I2C_Timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle->completionCallback)
|
||||||
|
{
|
||||||
|
(handle->completionCallback)(base, handle, result, handle->userData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* Send subaddress. */
|
/* Send subaddress. */
|
||||||
if (handle->transfer.subaddressSize)
|
if (handle->transfer.subaddressSize)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
/* Wait until data transfer complete. */
|
|
||||||
while (!(base->S & kI2C_IntPendingFlag))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear interrupt pending flag. */
|
/* Clear interrupt pending flag. */
|
||||||
base->S = kI2C_IntPendingFlag;
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
handle->transfer.subaddressSize--;
|
handle->transfer.subaddressSize--;
|
||||||
base->D = ((handle->transfer.subaddress) >> (8 * handle->transfer.subaddressSize));
|
base->D = ((handle->transfer.subaddress) >> (8 * handle->transfer.subaddressSize));
|
||||||
|
|
||||||
|
/* Wait until data transfer complete. */
|
||||||
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if there's transfer error. */
|
/* Check if there's transfer error. */
|
||||||
result = I2C_CheckAndClearError(base, base->S);
|
result = I2C_CheckAndClearError(base, base->S);
|
||||||
|
|
||||||
|
@ -278,18 +320,11 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
||||||
|
|
||||||
if (handle->transfer.direction == kI2C_Read)
|
if (handle->transfer.direction == kI2C_Read)
|
||||||
{
|
{
|
||||||
/* Wait until data transfer complete. */
|
|
||||||
while (!(base->S & kI2C_IntPendingFlag))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear pending flag. */
|
/* Clear pending flag. */
|
||||||
base->S = kI2C_IntPendingFlag;
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
/* Send repeated start and slave address. */
|
/* Send repeated start and slave address. */
|
||||||
result = I2C_MasterRepeatedStart(base, handle->transfer.slaveAddress, kI2C_Read);
|
result = I2C_MasterRepeatedStart(base, handle->transfer.slaveAddress, kI2C_Read);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
|
@ -301,11 +336,18 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear pending flag. */
|
|
||||||
base->S = kI2C_IntPendingFlag;
|
|
||||||
|
|
||||||
/* Check if there's transfer error. */
|
/* Check if there's transfer error. */
|
||||||
result = I2C_CheckAndClearError(base, base->S);
|
result = I2C_CheckAndClearError(base, base->S);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear pending flag. */
|
||||||
|
base->S = kI2C_IntPendingFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -319,17 +361,7 @@ static void I2C_MasterTransferEDMAConfig(I2C_Type *base, i2c_master_edma_handle_
|
||||||
{
|
{
|
||||||
transfer_config.srcAddr = (uint32_t)I2C_GetDataRegAddr(base);
|
transfer_config.srcAddr = (uint32_t)I2C_GetDataRegAddr(base);
|
||||||
transfer_config.destAddr = (uint32_t)(handle->transfer.data);
|
transfer_config.destAddr = (uint32_t)(handle->transfer.data);
|
||||||
|
|
||||||
/* Send stop if kI2C_TransferNoStop flag is not asserted. */
|
|
||||||
if (!(handle->transfer.flags & kI2C_TransferNoStopFlag))
|
|
||||||
{
|
|
||||||
transfer_config.majorLoopCounts = (handle->transfer.dataSize - 1);
|
transfer_config.majorLoopCounts = (handle->transfer.dataSize - 1);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
transfer_config.majorLoopCounts = handle->transfer.dataSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
transfer_config.srcTransferSize = kEDMA_TransferSize1Bytes;
|
transfer_config.srcTransferSize = kEDMA_TransferSize1Bytes;
|
||||||
transfer_config.srcOffset = 0;
|
transfer_config.srcOffset = 0;
|
||||||
transfer_config.destTransferSize = kEDMA_TransferSize1Bytes;
|
transfer_config.destTransferSize = kEDMA_TransferSize1Bytes;
|
||||||
|
@ -348,6 +380,9 @@ static void I2C_MasterTransferEDMAConfig(I2C_Type *base, i2c_master_edma_handle_
|
||||||
transfer_config.minorLoopBytes = 1;
|
transfer_config.minorLoopBytes = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Store the initially configured eDMA minor byte transfer count into the I2C handle */
|
||||||
|
handle->nbytes = transfer_config.minorLoopBytes;
|
||||||
|
|
||||||
EDMA_SubmitTransfer(handle->dmaHandle, &transfer_config);
|
EDMA_SubmitTransfer(handle->dmaHandle, &transfer_config);
|
||||||
EDMA_StartTransfer(handle->dmaHandle);
|
EDMA_StartTransfer(handle->dmaHandle);
|
||||||
}
|
}
|
||||||
|
@ -427,7 +462,7 @@ status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle
|
||||||
if (handle->transfer.direction == kI2C_Read)
|
if (handle->transfer.direction == kI2C_Read)
|
||||||
{
|
{
|
||||||
/* Change direction for receive. */
|
/* Change direction for receive. */
|
||||||
base->C1 &= ~I2C_C1_TX_MASK;
|
base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK);
|
||||||
|
|
||||||
/* Read dummy to release the bus. */
|
/* Read dummy to release the bus. */
|
||||||
dummy = base->D;
|
dummy = base->D;
|
||||||
|
@ -479,6 +514,11 @@ status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle
|
||||||
{
|
{
|
||||||
result = I2C_MasterStop(base);
|
result = I2C_MasterStop(base);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Change direction to send. */
|
||||||
|
base->C1 |= I2C_C1_TX_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read the last byte of data. */
|
/* Read the last byte of data. */
|
||||||
if (handle->transfer.direction == kI2C_Read)
|
if (handle->transfer.direction == kI2C_Read)
|
||||||
|
@ -504,7 +544,9 @@ status_t I2C_MasterTransferGetCountEDMA(I2C_Type *base, i2c_master_edma_handle_t
|
||||||
|
|
||||||
if (kIdleState != handle->state)
|
if (kIdleState != handle->state)
|
||||||
{
|
{
|
||||||
*count = (handle->transferSize - EDMA_GetRemainingBytes(handle->dmaHandle->base, handle->dmaHandle->channel));
|
*count = (handle->transferSize -
|
||||||
|
(uint32_t)handle->nbytes *
|
||||||
|
EDMA_GetRemainingMajorLoopCount(handle->dmaHandle->base, handle->dmaHandle->channel));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||||
* All rights reserved.
|
* Copyright 2016-2017 NXP
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
* other materials provided with the distribution.
|
* other materials provided with the distribution.
|
||||||
*
|
*
|
||||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
* o Neither the name of the copyright holder nor the names of its
|
||||||
* contributors may be used to endorse or promote products derived from this
|
* contributors may be used to endorse or promote products derived from this
|
||||||
* software without specific prior written permission.
|
* software without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -39,7 +39,6 @@
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Definitions
|
* Definitions
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
@ -56,13 +55,14 @@ typedef void (*i2c_master_edma_transfer_callback_t)(I2C_Type *base,
|
||||||
/*! @brief I2C master eDMA transfer structure. */
|
/*! @brief I2C master eDMA transfer structure. */
|
||||||
struct _i2c_master_edma_handle
|
struct _i2c_master_edma_handle
|
||||||
{
|
{
|
||||||
i2c_master_transfer_t transfer; /*!< I2C master transfer struct. */
|
i2c_master_transfer_t transfer; /*!< I2C master transfer structure. */
|
||||||
size_t transferSize; /*!< Total bytes to be transferred. */
|
size_t transferSize; /*!< Total bytes to be transferred. */
|
||||||
|
uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */
|
||||||
uint8_t state; /*!< I2C master transfer status. */
|
uint8_t state; /*!< I2C master transfer status. */
|
||||||
edma_handle_t *dmaHandle; /*!< The eDMA handler used. */
|
edma_handle_t *dmaHandle; /*!< The eDMA handler used. */
|
||||||
i2c_master_edma_transfer_callback_t
|
i2c_master_edma_transfer_callback_t
|
||||||
completionCallback; /*!< Callback function called after eDMA transfer finished. */
|
completionCallback; /*!< A callback function called after the eDMA transfer is finished. */
|
||||||
void *userData; /*!< Callback parameter passed to callback function. */
|
void *userData; /*!< A callback parameter passed to the callback function. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
@ -79,12 +79,12 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Init the I2C handle which is used in transcational functions.
|
* @brief Initializes the I2C handle which is used in transcational functions.
|
||||||
*
|
*
|
||||||
* @param base I2C peripheral base address.
|
* @param base I2C peripheral base address.
|
||||||
* @param handle pointer to i2c_master_edma_handle_t structure.
|
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||||
* @param callback pointer to user callback function.
|
* @param callback A pointer to the user callback function.
|
||||||
* @param userData user param passed to the callback function.
|
* @param userData A user parameter passed to the callback function.
|
||||||
* @param edmaHandle eDMA handle pointer.
|
* @param edmaHandle eDMA handle pointer.
|
||||||
*/
|
*/
|
||||||
void I2C_MasterCreateEDMAHandle(I2C_Type *base,
|
void I2C_MasterCreateEDMAHandle(I2C_Type *base,
|
||||||
|
@ -97,30 +97,30 @@ void I2C_MasterCreateEDMAHandle(I2C_Type *base,
|
||||||
* @brief Performs a master eDMA non-blocking transfer on the I2C bus.
|
* @brief Performs a master eDMA non-blocking transfer on the I2C bus.
|
||||||
*
|
*
|
||||||
* @param base I2C peripheral base address.
|
* @param base I2C peripheral base address.
|
||||||
* @param handle pointer to i2c_master_edma_handle_t structure.
|
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||||
* @param xfer pointer to transfer structure of i2c_master_transfer_t.
|
* @param xfer A pointer to the transfer structure of i2c_master_transfer_t.
|
||||||
* @retval kStatus_Success Sucessully complete the data transmission.
|
* @retval kStatus_Success Sucessfully completed the data transmission.
|
||||||
* @retval kStatus_I2C_Busy Previous transmission still not finished.
|
* @retval kStatus_I2C_Busy A previous transmission is still not finished.
|
||||||
* @retval kStatus_I2C_Timeout Transfer error, wait signal timeout.
|
* @retval kStatus_I2C_Timeout Transfer error, waits for a signal timeout.
|
||||||
* @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
|
* @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
|
||||||
* @retval kStataus_I2C_Nak Transfer error, receive Nak during transfer.
|
* @retval kStataus_I2C_Nak Transfer error, receive NAK during transfer.
|
||||||
*/
|
*/
|
||||||
status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle, i2c_master_transfer_t *xfer);
|
status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle, i2c_master_transfer_t *xfer);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Get master transfer status during a eDMA non-blocking transfer.
|
* @brief Gets a master transfer status during the eDMA non-blocking transfer.
|
||||||
*
|
*
|
||||||
* @param base I2C peripheral base address.
|
* @param base I2C peripheral base address.
|
||||||
* @param handle pointer to i2c_master_edma_handle_t structure.
|
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||||
* @param count Number of bytes transferred so far by the non-blocking transaction.
|
* @param count A number of bytes transferred by the non-blocking transaction.
|
||||||
*/
|
*/
|
||||||
status_t I2C_MasterTransferGetCountEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle, size_t *count);
|
status_t I2C_MasterTransferGetCountEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle, size_t *count);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Abort a master eDMA non-blocking transfer in a early time.
|
* @brief Aborts a master eDMA non-blocking transfer early.
|
||||||
*
|
*
|
||||||
* @param base I2C peripheral base address.
|
* @param base I2C peripheral base address.
|
||||||
* @param handle pointer to i2c_master_edma_handle_t structure.
|
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||||
*/
|
*/
|
||||||
void I2C_MasterTransferAbortEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle);
|
void I2C_MasterTransferAbortEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||||
* All rights reserved.
|
* Copyright 2016-2017 NXP
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
* other materials provided with the distribution.
|
* other materials provided with the distribution.
|
||||||
*
|
*
|
||||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
* o Neither the name of the copyright holder nor the names of its
|
||||||
* contributors may be used to endorse or promote products derived from this
|
* contributors may be used to endorse or promote products derived from this
|
||||||
* software without specific prior written permission.
|
* software without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -75,6 +75,19 @@ typedef void (*i2c_isr_t)(I2C_Type *base, void *i2cHandle);
|
||||||
*/
|
*/
|
||||||
uint32_t I2C_GetInstance(I2C_Type *base);
|
uint32_t I2C_GetInstance(I2C_Type *base);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Set SCL/SDA hold time, this API receives SCL stop hold time, calculate the
|
||||||
|
* closest SCL divider and MULT value for the SDA hold time, SCL start and SCL stop
|
||||||
|
* hold time. To reduce the ROM size, SDA/SCL hold value mapping table is not provided,
|
||||||
|
* assume SCL divider = SCL stop hold value *2 to get the closest SCL divider value and MULT
|
||||||
|
* value, then the related SDA hold time, SCL start and SCL stop hold time is used.
|
||||||
|
*
|
||||||
|
* @param base I2C peripheral base address.
|
||||||
|
* @param sourceClock_Hz I2C functional clock frequency in Hertz.
|
||||||
|
* @param sclStopHoldTime_ns SCL stop hold time in ns.
|
||||||
|
*/
|
||||||
|
static void I2C_SetHoldTime(I2C_Type *base, uint32_t sclStopHoldTime_ns, uint32_t sourceClock_Hz);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Set up master transfer, send slave address and decide the initial
|
* @brief Set up master transfer, send slave address and decide the initial
|
||||||
* transfer state.
|
* transfer state.
|
||||||
|
@ -137,8 +150,10 @@ static I2C_Type *const s_i2cBases[] = I2C_BASE_PTRS;
|
||||||
/*! @brief Pointers to i2c IRQ number for each instance. */
|
/*! @brief Pointers to i2c IRQ number for each instance. */
|
||||||
static const IRQn_Type s_i2cIrqs[] = I2C_IRQS;
|
static const IRQn_Type s_i2cIrqs[] = I2C_IRQS;
|
||||||
|
|
||||||
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||||
/*! @brief Pointers to i2c clocks for each instance. */
|
/*! @brief Pointers to i2c clocks for each instance. */
|
||||||
static const clock_ip_name_t s_i2cClocks[] = I2C_CLOCKS;
|
static const clock_ip_name_t s_i2cClocks[] = I2C_CLOCKS;
|
||||||
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||||
|
|
||||||
/*! @brief Pointer to master IRQ handler for each instance. */
|
/*! @brief Pointer to master IRQ handler for each instance. */
|
||||||
static i2c_isr_t s_i2cMasterIsr;
|
static i2c_isr_t s_i2cMasterIsr;
|
||||||
|
@ -155,7 +170,7 @@ uint32_t I2C_GetInstance(I2C_Type *base)
|
||||||
uint32_t instance;
|
uint32_t instance;
|
||||||
|
|
||||||
/* Find the instance index from base address mappings. */
|
/* Find the instance index from base address mappings. */
|
||||||
for (instance = 0; instance < FSL_FEATURE_SOC_I2C_COUNT; instance++)
|
for (instance = 0; instance < ARRAY_SIZE(s_i2cBases); instance++)
|
||||||
{
|
{
|
||||||
if (s_i2cBases[instance] == base)
|
if (s_i2cBases[instance] == base)
|
||||||
{
|
{
|
||||||
|
@ -163,16 +178,63 @@ uint32_t I2C_GetInstance(I2C_Type *base)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(instance < FSL_FEATURE_SOC_I2C_COUNT);
|
assert(instance < ARRAY_SIZE(s_i2cBases));
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void I2C_SetHoldTime(I2C_Type *base, uint32_t sclStopHoldTime_ns, uint32_t sourceClock_Hz)
|
||||||
|
{
|
||||||
|
uint32_t multiplier;
|
||||||
|
uint32_t computedSclHoldTime;
|
||||||
|
uint32_t absError;
|
||||||
|
uint32_t bestError = UINT32_MAX;
|
||||||
|
uint32_t bestMult = 0u;
|
||||||
|
uint32_t bestIcr = 0u;
|
||||||
|
uint8_t mult;
|
||||||
|
uint8_t i;
|
||||||
|
|
||||||
|
/* Search for the settings with the lowest error. Mult is the MULT field of the I2C_F register,
|
||||||
|
* and ranges from 0-2. It selects the multiplier factor for the divider. */
|
||||||
|
/* SDA hold time = bus period (s) * mul * SDA hold value. */
|
||||||
|
/* SCL start hold time = bus period (s) * mul * SCL start hold value. */
|
||||||
|
/* SCL stop hold time = bus period (s) * mul * SCL stop hold value. */
|
||||||
|
|
||||||
|
for (mult = 0u; (mult <= 2u) && (bestError != 0); ++mult)
|
||||||
|
{
|
||||||
|
multiplier = 1u << mult;
|
||||||
|
|
||||||
|
/* Scan table to find best match. */
|
||||||
|
for (i = 0u; i < sizeof(s_i2cDividerTable) / sizeof(s_i2cDividerTable[0]); ++i)
|
||||||
|
{
|
||||||
|
/* Assume SCL hold(stop) value = s_i2cDividerTable[i]/2. */
|
||||||
|
computedSclHoldTime = ((multiplier * s_i2cDividerTable[i]) * 500000000U) / sourceClock_Hz;
|
||||||
|
absError = sclStopHoldTime_ns > computedSclHoldTime ? (sclStopHoldTime_ns - computedSclHoldTime) :
|
||||||
|
(computedSclHoldTime - sclStopHoldTime_ns);
|
||||||
|
|
||||||
|
if (absError < bestError)
|
||||||
|
{
|
||||||
|
bestMult = mult;
|
||||||
|
bestIcr = i;
|
||||||
|
bestError = absError;
|
||||||
|
|
||||||
|
/* If the error is 0, then we can stop searching because we won't find a better match. */
|
||||||
|
if (absError == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set frequency register based on best settings. */
|
||||||
|
base->F = I2C_F_MULT(bestMult) | I2C_F_ICR(bestIcr);
|
||||||
|
}
|
||||||
|
|
||||||
static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t *handle, i2c_master_transfer_t *xfer)
|
static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t *handle, i2c_master_transfer_t *xfer)
|
||||||
{
|
{
|
||||||
status_t result = kStatus_Success;
|
status_t result = kStatus_Success;
|
||||||
i2c_direction_t direction = xfer->direction;
|
i2c_direction_t direction = xfer->direction;
|
||||||
uint16_t timeout = UINT16_MAX;
|
|
||||||
|
|
||||||
/* Initialize the handle transfer information. */
|
/* Initialize the handle transfer information. */
|
||||||
handle->transfer = *xfer;
|
handle->transfer = *xfer;
|
||||||
|
@ -183,27 +245,13 @@ static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t
|
||||||
/* Initial transfer state. */
|
/* Initial transfer state. */
|
||||||
if (handle->transfer.subaddressSize > 0)
|
if (handle->transfer.subaddressSize > 0)
|
||||||
{
|
{
|
||||||
handle->state = kSendCommandState;
|
|
||||||
if (xfer->direction == kI2C_Read)
|
if (xfer->direction == kI2C_Read)
|
||||||
{
|
{
|
||||||
direction = kI2C_Write;
|
direction = kI2C_Write;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
handle->state = kCheckAddressState;
|
handle->state = kCheckAddressState;
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait until the data register is ready for transmit. */
|
|
||||||
while ((!(base->S & kI2C_TransferCompleteFlag)) && (--timeout))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Failed to start the transfer. */
|
|
||||||
if (timeout == 0)
|
|
||||||
{
|
|
||||||
return kStatus_I2C_Timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear all status before transfer. */
|
/* Clear all status before transfer. */
|
||||||
I2C_MasterClearStatusFlags(base, kClearFlags);
|
I2C_MasterClearStatusFlags(base, kClearFlags);
|
||||||
|
@ -265,18 +313,19 @@ static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_han
|
||||||
result = kStatus_Success;
|
result = kStatus_Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle Check address state to check the slave address is Acked in slave
|
/* Handle Check address state to check the slave address is Acked in slave
|
||||||
probe application. */
|
probe application. */
|
||||||
if (handle->state == kCheckAddressState)
|
if (handle->state == kCheckAddressState)
|
||||||
{
|
{
|
||||||
if (statusFlags & kI2C_ReceiveNakFlag)
|
if (statusFlags & kI2C_ReceiveNakFlag)
|
||||||
{
|
{
|
||||||
return kStatus_I2C_Nak;
|
result = kStatus_I2C_Addr_Nak;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (handle->transfer.subaddressSize > 0)
|
||||||
|
{
|
||||||
|
handle->state = kSendCommandState;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -292,6 +341,12 @@ static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_han
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* Run state machine. */
|
/* Run state machine. */
|
||||||
switch (handle->state)
|
switch (handle->state)
|
||||||
|
@ -375,6 +430,10 @@ static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_han
|
||||||
{
|
{
|
||||||
result = I2C_MasterStop(base);
|
result = I2C_MasterStop(base);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base->C1 |= I2C_C1_TX_MASK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send NAK at the last receive byte. */
|
/* Send NAK at the last receive byte. */
|
||||||
|
@ -407,6 +466,7 @@ static void I2C_TransferCommonIRQHandler(I2C_Type *base, void *handle)
|
||||||
{
|
{
|
||||||
s_i2cSlaveIsr(base, handle);
|
s_i2cSlaveIsr(base, handle);
|
||||||
}
|
}
|
||||||
|
__DSB();
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz)
|
void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz)
|
||||||
|
@ -415,14 +475,26 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin
|
||||||
|
|
||||||
/* Temporary register for filter read. */
|
/* Temporary register for filter read. */
|
||||||
uint8_t fltReg;
|
uint8_t fltReg;
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
uint8_t c2Reg;
|
|
||||||
#endif
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
||||||
uint8_t s2Reg;
|
uint8_t s2Reg;
|
||||||
#endif
|
#endif
|
||||||
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||||
/* Enable I2C clock. */
|
/* Enable I2C clock. */
|
||||||
CLOCK_EnableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
CLOCK_EnableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
||||||
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||||
|
|
||||||
|
/* Reset the module. */
|
||||||
|
base->A1 = 0;
|
||||||
|
base->F = 0;
|
||||||
|
base->C1 = 0;
|
||||||
|
base->S = 0xFFU;
|
||||||
|
base->C2 = 0;
|
||||||
|
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||||
|
base->FLT = 0x50U;
|
||||||
|
#elif defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT
|
||||||
|
base->FLT = 0x40U;
|
||||||
|
#endif
|
||||||
|
base->RA = 0;
|
||||||
|
|
||||||
/* Disable I2C prior to configuring it. */
|
/* Disable I2C prior to configuring it. */
|
||||||
base->C1 &= ~(I2C_C1_IICEN_MASK);
|
base->C1 &= ~(I2C_C1_IICEN_MASK);
|
||||||
|
@ -433,14 +505,6 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin
|
||||||
/* Configure baud rate. */
|
/* Configure baud rate. */
|
||||||
I2C_MasterSetBaudRate(base, masterConfig->baudRate_Bps, srcClock_Hz);
|
I2C_MasterSetBaudRate(base, masterConfig->baudRate_Bps, srcClock_Hz);
|
||||||
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
/* Configure high drive feature. */
|
|
||||||
c2Reg = base->C2;
|
|
||||||
c2Reg &= ~(I2C_C2_HDRS_MASK);
|
|
||||||
c2Reg |= I2C_C2_HDRS(masterConfig->enableHighDrive);
|
|
||||||
base->C2 = c2Reg;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Read out the FLT register. */
|
/* Read out the FLT register. */
|
||||||
fltReg = base->FLT;
|
fltReg = base->FLT;
|
||||||
|
|
||||||
|
@ -472,8 +536,10 @@ void I2C_MasterDeinit(I2C_Type *base)
|
||||||
/* Disable I2C module. */
|
/* Disable I2C module. */
|
||||||
I2C_Enable(base, false);
|
I2C_Enable(base, false);
|
||||||
|
|
||||||
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||||
/* Disable I2C clock. */
|
/* Disable I2C clock. */
|
||||||
CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
||||||
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig)
|
void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig)
|
||||||
|
@ -483,11 +549,6 @@ void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig)
|
||||||
/* Default baud rate at 100kbps. */
|
/* Default baud rate at 100kbps. */
|
||||||
masterConfig->baudRate_Bps = 100000U;
|
masterConfig->baudRate_Bps = 100000U;
|
||||||
|
|
||||||
/* Default pin high drive is disabled. */
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
masterConfig->enableHighDrive = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Default stop hold enable is disabled. */
|
/* Default stop hold enable is disabled. */
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF
|
#if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF
|
||||||
masterConfig->enableStopHold = false;
|
masterConfig->enableStopHold = false;
|
||||||
|
@ -654,7 +715,7 @@ status_t I2C_MasterRepeatedStart(I2C_Type *base, uint8_t address, i2c_direction_
|
||||||
base->F = savedMult & (~I2C_F_MULT_MASK);
|
base->F = savedMult & (~I2C_F_MULT_MASK);
|
||||||
|
|
||||||
/* We are already in a transfer, so send a repeated start. */
|
/* We are already in a transfer, so send a repeated start. */
|
||||||
base->C1 |= I2C_C1_RSTA_MASK;
|
base->C1 |= I2C_C1_RSTA_MASK | I2C_C1_TX_MASK;
|
||||||
|
|
||||||
/* Restore the multiplier factor. */
|
/* Restore the multiplier factor. */
|
||||||
base->F = savedMult;
|
base->F = savedMult;
|
||||||
|
@ -721,7 +782,7 @@ uint32_t I2C_MasterGetStatusFlags(I2C_Type *base)
|
||||||
return statusFlags;
|
return statusFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize)
|
status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize, uint32_t flags)
|
||||||
{
|
{
|
||||||
status_t result = kStatus_Success;
|
status_t result = kStatus_Success;
|
||||||
uint8_t statusFlags = 0;
|
uint8_t statusFlags = 0;
|
||||||
|
@ -772,10 +833,19 @@ status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (((result == kStatus_Success) && (!(flags & kI2C_TransferNoStopFlag))) || (result == kStatus_I2C_Nak))
|
||||||
|
{
|
||||||
|
/* Clear the IICIF flag. */
|
||||||
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
|
/* Send stop. */
|
||||||
|
result = I2C_MasterStop(base);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize)
|
status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize, uint32_t flags)
|
||||||
{
|
{
|
||||||
status_t result = kStatus_Success;
|
status_t result = kStatus_Success;
|
||||||
volatile uint8_t dummy = 0;
|
volatile uint8_t dummy = 0;
|
||||||
|
@ -817,9 +887,17 @@ status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize)
|
||||||
/* Single byte use case. */
|
/* Single byte use case. */
|
||||||
if (rxSize == 0)
|
if (rxSize == 0)
|
||||||
{
|
{
|
||||||
/* Read the final byte. */
|
if (!(flags & kI2C_TransferNoStopFlag))
|
||||||
|
{
|
||||||
|
/* Issue STOP command before reading last byte. */
|
||||||
result = I2C_MasterStop(base);
|
result = I2C_MasterStop(base);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Change direction to Tx to avoid extra clocks. */
|
||||||
|
base->C1 |= I2C_C1_TX_MASK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (rxSize == 1)
|
if (rxSize == 1)
|
||||||
{
|
{
|
||||||
|
@ -871,19 +949,42 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if there's transfer error. */
|
||||||
|
result = I2C_CheckAndClearError(base, base->S);
|
||||||
|
|
||||||
|
/* Return if error. */
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
if (result == kStatus_I2C_Nak)
|
||||||
|
{
|
||||||
|
result = kStatus_I2C_Addr_Nak;
|
||||||
|
|
||||||
|
I2C_MasterStop(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* Send subaddress. */
|
/* Send subaddress. */
|
||||||
if (xfer->subaddressSize)
|
if (xfer->subaddressSize)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
/* Clear interrupt pending flag. */
|
||||||
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
|
xfer->subaddressSize--;
|
||||||
|
base->D = ((xfer->subaddress) >> (8 * xfer->subaddressSize));
|
||||||
|
|
||||||
/* Wait until data transfer complete. */
|
/* Wait until data transfer complete. */
|
||||||
while (!(base->S & kI2C_IntPendingFlag))
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear interrupt pending flag. */
|
|
||||||
base->S = kI2C_IntPendingFlag;
|
|
||||||
|
|
||||||
/* Check if there's transfer error. */
|
/* Check if there's transfer error. */
|
||||||
result = I2C_CheckAndClearError(base, base->S);
|
result = I2C_CheckAndClearError(base, base->S);
|
||||||
|
|
||||||
|
@ -897,34 +998,13 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
xfer->subaddressSize--;
|
|
||||||
base->D = ((xfer->subaddress) >> (8 * xfer->subaddressSize));
|
|
||||||
|
|
||||||
} while ((xfer->subaddressSize > 0) && (result == kStatus_Success));
|
} while ((xfer->subaddressSize > 0) && (result == kStatus_Success));
|
||||||
|
|
||||||
if (xfer->direction == kI2C_Read)
|
if (xfer->direction == kI2C_Read)
|
||||||
{
|
{
|
||||||
/* Wait until data transfer complete. */
|
|
||||||
while (!(base->S & kI2C_IntPendingFlag))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear pending flag. */
|
/* Clear pending flag. */
|
||||||
base->S = kI2C_IntPendingFlag;
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
/* Check if there's transfer error. */
|
|
||||||
result = I2C_CheckAndClearError(base, base->S);
|
|
||||||
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
if (result == kStatus_I2C_Nak)
|
|
||||||
{
|
|
||||||
I2C_MasterStop(base);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send repeated start and slave address. */
|
/* Send repeated start and slave address. */
|
||||||
result = I2C_MasterRepeatedStart(base, xfer->slaveAddress, kI2C_Read);
|
result = I2C_MasterRepeatedStart(base, xfer->slaveAddress, kI2C_Read);
|
||||||
|
|
||||||
|
@ -933,10 +1013,8 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait until address + command transfer complete. */
|
/* Wait until data transfer complete. */
|
||||||
while (!(base->S & kI2C_IntPendingFlag))
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -944,37 +1022,31 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
|
||||||
/* Check if there's transfer error. */
|
/* Check if there's transfer error. */
|
||||||
result = I2C_CheckAndClearError(base, base->S);
|
result = I2C_CheckAndClearError(base, base->S);
|
||||||
|
|
||||||
/* Return if error. */
|
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
if (result == kStatus_I2C_Nak)
|
if (result == kStatus_I2C_Nak)
|
||||||
{
|
{
|
||||||
|
result = kStatus_I2C_Addr_Nak;
|
||||||
|
|
||||||
I2C_MasterStop(base);
|
I2C_MasterStop(base);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Transmit data. */
|
/* Transmit data. */
|
||||||
if ((xfer->direction == kI2C_Write) && (xfer->dataSize > 0))
|
if ((xfer->direction == kI2C_Write) && (xfer->dataSize > 0))
|
||||||
{
|
{
|
||||||
/* Send Data. */
|
/* Send Data. */
|
||||||
result = I2C_MasterWriteBlocking(base, xfer->data, xfer->dataSize);
|
result = I2C_MasterWriteBlocking(base, xfer->data, xfer->dataSize, xfer->flags);
|
||||||
|
|
||||||
if (((result == kStatus_Success) && (!(xfer->flags & kI2C_TransferNoStopFlag))) || (result == kStatus_I2C_Nak))
|
|
||||||
{
|
|
||||||
/* Clear the IICIF flag. */
|
|
||||||
base->S = kI2C_IntPendingFlag;
|
|
||||||
|
|
||||||
/* Send stop. */
|
|
||||||
result = I2C_MasterStop(base);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Receive Data. */
|
/* Receive Data. */
|
||||||
if ((xfer->direction == kI2C_Read) && (xfer->dataSize > 0))
|
if ((xfer->direction == kI2C_Read) && (xfer->dataSize > 0))
|
||||||
{
|
{
|
||||||
result = I2C_MasterReadBlocking(base, xfer->data, xfer->dataSize);
|
result = I2C_MasterReadBlocking(base, xfer->data, xfer->dataSize, xfer->flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -1037,11 +1109,37 @@ void I2C_MasterTransferAbort(I2C_Type *base, i2c_master_handle_t *handle)
|
||||||
{
|
{
|
||||||
assert(handle);
|
assert(handle);
|
||||||
|
|
||||||
|
volatile uint8_t dummy = 0;
|
||||||
|
|
||||||
|
/* Add this to avoid build warning. */
|
||||||
|
dummy++;
|
||||||
|
|
||||||
/* Disable interrupt. */
|
/* Disable interrupt. */
|
||||||
I2C_DisableInterrupts(base, kI2C_GlobalInterruptEnable);
|
I2C_DisableInterrupts(base, kI2C_GlobalInterruptEnable);
|
||||||
|
|
||||||
/* Reset the state to idle. */
|
/* Reset the state to idle. */
|
||||||
handle->state = kIdleState;
|
handle->state = kIdleState;
|
||||||
|
|
||||||
|
/* Send STOP signal. */
|
||||||
|
if (handle->transfer.direction == kI2C_Read)
|
||||||
|
{
|
||||||
|
base->C1 |= I2C_C1_TXAK_MASK;
|
||||||
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
|
base->C1 &= ~(I2C_C1_MST_MASK | I2C_C1_TX_MASK | I2C_C1_TXAK_MASK);
|
||||||
|
dummy = base->D;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
base->C1 &= ~(I2C_C1_MST_MASK | I2C_C1_TX_MASK | I2C_C1_TXAK_MASK);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t I2C_MasterTransferGetCount(I2C_Type *base, i2c_master_handle_t *handle, size_t *count)
|
status_t I2C_MasterTransferGetCount(I2C_Type *base, i2c_master_handle_t *handle, size_t *count)
|
||||||
|
@ -1075,7 +1173,8 @@ void I2C_MasterTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
if (isDone || result)
|
if (isDone || result)
|
||||||
{
|
{
|
||||||
/* Send stop command if transfer done or received Nak. */
|
/* Send stop command if transfer done or received Nak. */
|
||||||
if ((!(handle->transfer.flags & kI2C_TransferNoStopFlag)) || (result == kStatus_I2C_Nak))
|
if ((!(handle->transfer.flags & kI2C_TransferNoStopFlag)) || (result == kStatus_I2C_Nak) ||
|
||||||
|
(result == kStatus_I2C_Addr_Nak))
|
||||||
{
|
{
|
||||||
/* Ensure stop command is a need. */
|
/* Ensure stop command is a need. */
|
||||||
if ((base->C1 & I2C_C1_MST_MASK))
|
if ((base->C1 & I2C_C1_MST_MASK))
|
||||||
|
@ -1101,13 +1200,28 @@ void I2C_MasterTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig)
|
void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig, uint32_t srcClock_Hz)
|
||||||
{
|
{
|
||||||
assert(slaveConfig);
|
assert(slaveConfig);
|
||||||
|
|
||||||
uint8_t tmpReg;
|
uint8_t tmpReg;
|
||||||
|
|
||||||
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||||
CLOCK_EnableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
CLOCK_EnableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
||||||
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||||
|
|
||||||
|
/* Reset the module. */
|
||||||
|
base->A1 = 0;
|
||||||
|
base->F = 0;
|
||||||
|
base->C1 = 0;
|
||||||
|
base->S = 0xFFU;
|
||||||
|
base->C2 = 0;
|
||||||
|
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||||
|
base->FLT = 0x50U;
|
||||||
|
#elif defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT
|
||||||
|
base->FLT = 0x40U;
|
||||||
|
#endif
|
||||||
|
base->RA = 0;
|
||||||
|
|
||||||
/* Configure addressing mode. */
|
/* Configure addressing mode. */
|
||||||
switch (slaveConfig->addressingMode)
|
switch (slaveConfig->addressingMode)
|
||||||
|
@ -1132,14 +1246,10 @@ void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig)
|
||||||
tmpReg &= ~I2C_C1_WUEN_MASK;
|
tmpReg &= ~I2C_C1_WUEN_MASK;
|
||||||
base->C1 = tmpReg | I2C_C1_WUEN(slaveConfig->enableWakeUp) | I2C_C1_IICEN(slaveConfig->enableSlave);
|
base->C1 = tmpReg | I2C_C1_WUEN(slaveConfig->enableWakeUp) | I2C_C1_IICEN(slaveConfig->enableSlave);
|
||||||
|
|
||||||
/* Configure general call & baud rate control & high drive feature. */
|
/* Configure general call & baud rate control. */
|
||||||
tmpReg = base->C2;
|
tmpReg = base->C2;
|
||||||
tmpReg &= ~(I2C_C2_SBRC_MASK | I2C_C2_GCAEN_MASK);
|
tmpReg &= ~(I2C_C2_SBRC_MASK | I2C_C2_GCAEN_MASK);
|
||||||
tmpReg |= I2C_C2_SBRC(slaveConfig->enableBaudRateCtl) | I2C_C2_GCAEN(slaveConfig->enableGeneralCall);
|
tmpReg |= I2C_C2_SBRC(slaveConfig->enableBaudRateCtl) | I2C_C2_GCAEN(slaveConfig->enableGeneralCall);
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
tmpReg &= ~I2C_C2_HDRS_MASK;
|
|
||||||
tmpReg |= I2C_C2_HDRS(slaveConfig->enableHighDrive);
|
|
||||||
#endif
|
|
||||||
base->C2 = tmpReg;
|
base->C2 = tmpReg;
|
||||||
|
|
||||||
/* Enable/Disable double buffering. */
|
/* Enable/Disable double buffering. */
|
||||||
|
@ -1147,6 +1257,9 @@ void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig)
|
||||||
tmpReg = base->S2 & (~I2C_S2_DFEN_MASK);
|
tmpReg = base->S2 & (~I2C_S2_DFEN_MASK);
|
||||||
base->S2 = tmpReg | I2C_S2_DFEN(slaveConfig->enableDoubleBuffering);
|
base->S2 = tmpReg | I2C_S2_DFEN(slaveConfig->enableDoubleBuffering);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Set hold time. */
|
||||||
|
I2C_SetHoldTime(base, slaveConfig->sclStopHoldTime_ns, srcClock_Hz);
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2C_SlaveDeinit(I2C_Type *base)
|
void I2C_SlaveDeinit(I2C_Type *base)
|
||||||
|
@ -1154,8 +1267,10 @@ void I2C_SlaveDeinit(I2C_Type *base)
|
||||||
/* Disable I2C module. */
|
/* Disable I2C module. */
|
||||||
I2C_Enable(base, false);
|
I2C_Enable(base, false);
|
||||||
|
|
||||||
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||||
/* Disable I2C clock. */
|
/* Disable I2C clock. */
|
||||||
CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
||||||
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig)
|
void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig)
|
||||||
|
@ -1171,11 +1286,6 @@ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig)
|
||||||
/* Slave address match waking up MCU from low power mode is disabled. */
|
/* Slave address match waking up MCU from low power mode is disabled. */
|
||||||
slaveConfig->enableWakeUp = false;
|
slaveConfig->enableWakeUp = false;
|
||||||
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
/* Default pin high drive is disabled. */
|
|
||||||
slaveConfig->enableHighDrive = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Independent slave mode baud rate at maximum frequency is disabled. */
|
/* Independent slave mode baud rate at maximum frequency is disabled. */
|
||||||
slaveConfig->enableBaudRateCtl = false;
|
slaveConfig->enableBaudRateCtl = false;
|
||||||
|
|
||||||
|
@ -1184,6 +1294,9 @@ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig)
|
||||||
slaveConfig->enableDoubleBuffering = true;
|
slaveConfig->enableDoubleBuffering = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Set default SCL stop hold time to 4us which is minimum requirement in I2C spec. */
|
||||||
|
slaveConfig->sclStopHoldTime_ns = 4000;
|
||||||
|
|
||||||
/* Enable the I2C peripheral. */
|
/* Enable the I2C peripheral. */
|
||||||
slaveConfig->enableSlave = true;
|
slaveConfig->enableSlave = true;
|
||||||
}
|
}
|
||||||
|
@ -1215,7 +1328,7 @@ status_t I2C_SlaveWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t tx
|
||||||
/* Read dummy to release bus. */
|
/* Read dummy to release bus. */
|
||||||
dummy = base->D;
|
dummy = base->D;
|
||||||
|
|
||||||
result = I2C_MasterWriteBlocking(base, txBuff, txSize);
|
result = I2C_MasterWriteBlocking(base, txBuff, txSize, kI2C_TransferDefaultFlag);
|
||||||
|
|
||||||
/* Switch to receive mode. */
|
/* Switch to receive mode. */
|
||||||
base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK);
|
base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK);
|
||||||
|
@ -1323,7 +1436,7 @@ status_t I2C_SlaveTransferNonBlocking(I2C_Type *base, i2c_slave_handle_t *handle
|
||||||
handle->isBusy = true;
|
handle->isBusy = true;
|
||||||
|
|
||||||
/* Set up event mask. tx and rx are always enabled. */
|
/* Set up event mask. tx and rx are always enabled. */
|
||||||
handle->eventMask = eventMask | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent;
|
handle->eventMask = eventMask | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent | kI2C_SlaveGenaralcallEvent;
|
||||||
|
|
||||||
/* Clear all flags. */
|
/* Clear all flags. */
|
||||||
I2C_SlaveClearStatusFlags(base, kClearFlags);
|
I2C_SlaveClearStatusFlags(base, kClearFlags);
|
||||||
|
@ -1412,8 +1525,11 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(status & kI2C_AddressMatchFlag))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif /* I2C_HAS_STOP_DETECT */
|
#endif /* I2C_HAS_STOP_DETECT */
|
||||||
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||||
|
@ -1482,11 +1598,6 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
handle->isBusy = true;
|
handle->isBusy = true;
|
||||||
xfer->event = kI2C_SlaveAddressMatchEvent;
|
xfer->event = kI2C_SlaveAddressMatchEvent;
|
||||||
|
|
||||||
if ((handle->eventMask & xfer->event) && (handle->callback))
|
|
||||||
{
|
|
||||||
handle->callback(base, xfer, handle->userData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Slave transmit, master reading from slave. */
|
/* Slave transmit, master reading from slave. */
|
||||||
if (status & kI2C_TransferDirectionFlag)
|
if (status & kI2C_TransferDirectionFlag)
|
||||||
{
|
{
|
||||||
|
@ -1502,6 +1613,16 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
|
|
||||||
/* Read dummy to release the bus. */
|
/* Read dummy to release the bus. */
|
||||||
dummy = base->D;
|
dummy = base->D;
|
||||||
|
|
||||||
|
if (dummy == 0)
|
||||||
|
{
|
||||||
|
xfer->event = kI2C_SlaveGenaralcallEvent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((handle->eventMask & xfer->event) && (handle->callback))
|
||||||
|
{
|
||||||
|
handle->callback(base, xfer, handle->userData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Check transfer complete flag. */
|
/* Check transfer complete flag. */
|
||||||
|
@ -1607,27 +1728,30 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(I2C0)
|
||||||
void I2C0_DriverIRQHandler(void)
|
void I2C0_DriverIRQHandler(void)
|
||||||
{
|
{
|
||||||
I2C_TransferCommonIRQHandler(I2C0, s_i2cHandle[0]);
|
I2C_TransferCommonIRQHandler(I2C0, s_i2cHandle[0]);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (FSL_FEATURE_SOC_I2C_COUNT > 1)
|
#if defined(I2C1)
|
||||||
void I2C1_DriverIRQHandler(void)
|
void I2C1_DriverIRQHandler(void)
|
||||||
{
|
{
|
||||||
I2C_TransferCommonIRQHandler(I2C1, s_i2cHandle[1]);
|
I2C_TransferCommonIRQHandler(I2C1, s_i2cHandle[1]);
|
||||||
}
|
}
|
||||||
#endif /* I2C COUNT > 1 */
|
#endif
|
||||||
|
|
||||||
#if (FSL_FEATURE_SOC_I2C_COUNT > 2)
|
#if defined(I2C2)
|
||||||
void I2C2_DriverIRQHandler(void)
|
void I2C2_DriverIRQHandler(void)
|
||||||
{
|
{
|
||||||
I2C_TransferCommonIRQHandler(I2C2, s_i2cHandle[2]);
|
I2C_TransferCommonIRQHandler(I2C2, s_i2cHandle[2]);
|
||||||
}
|
}
|
||||||
#endif /* I2C COUNT > 2 */
|
#endif
|
||||||
#if (FSL_FEATURE_SOC_I2C_COUNT > 3)
|
|
||||||
|
#if defined(I2C3)
|
||||||
void I2C3_DriverIRQHandler(void)
|
void I2C3_DriverIRQHandler(void)
|
||||||
{
|
{
|
||||||
I2C_TransferCommonIRQHandler(I2C3, s_i2cHandle[3]);
|
I2C_TransferCommonIRQHandler(I2C3, s_i2cHandle[3]);
|
||||||
}
|
}
|
||||||
#endif /* I2C COUNT > 3 */
|
#endif
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||||
* All rights reserved.
|
* Copyright 2016-2017 NXP
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
* other materials provided with the distribution.
|
* other materials provided with the distribution.
|
||||||
*
|
*
|
||||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
* o Neither the name of the copyright holder nor the names of its
|
||||||
* contributors may be used to endorse or promote products derived from this
|
* contributors may be used to endorse or promote products derived from this
|
||||||
* software without specific prior written permission.
|
* software without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -37,15 +37,14 @@
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Definitions
|
* Definitions
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
/*! @name Driver version */
|
/*! @name Driver version */
|
||||||
/*@{*/
|
/*@{*/
|
||||||
/*! @brief I2C driver version 2.0.1. */
|
/*! @brief I2C driver version 2.0.3. */
|
||||||
#define FSL_I2C_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))
|
#define FSL_I2C_DRIVER_VERSION (MAKE_VERSION(2, 0, 3))
|
||||||
/*@}*/
|
/*@}*/
|
||||||
|
|
||||||
#if (defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT || \
|
#if (defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT || \
|
||||||
|
@ -61,6 +60,7 @@ enum _i2c_status
|
||||||
kStatus_I2C_Nak = MAKE_STATUS(kStatusGroup_I2C, 2), /*!< NAK received during transfer. */
|
kStatus_I2C_Nak = MAKE_STATUS(kStatusGroup_I2C, 2), /*!< NAK received during transfer. */
|
||||||
kStatus_I2C_ArbitrationLost = MAKE_STATUS(kStatusGroup_I2C, 3), /*!< Arbitration lost during transfer. */
|
kStatus_I2C_ArbitrationLost = MAKE_STATUS(kStatusGroup_I2C, 3), /*!< Arbitration lost during transfer. */
|
||||||
kStatus_I2C_Timeout = MAKE_STATUS(kStatusGroup_I2C, 4), /*!< Wait event timeout. */
|
kStatus_I2C_Timeout = MAKE_STATUS(kStatusGroup_I2C, 4), /*!< Wait event timeout. */
|
||||||
|
kStatus_I2C_Addr_Nak = MAKE_STATUS(kStatusGroup_I2C, 5), /*!< NAK received during the address probe. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -108,11 +108,11 @@ enum _i2c_interrupt_enable
|
||||||
#endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */
|
#endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! @brief Direction of master and slave transfers. */
|
/*! @brief The direction of master and slave transfers. */
|
||||||
typedef enum _i2c_direction
|
typedef enum _i2c_direction
|
||||||
{
|
{
|
||||||
kI2C_Write = 0x0U, /*!< Master transmit to slave. */
|
kI2C_Write = 0x0U, /*!< Master transmits to the slave. */
|
||||||
kI2C_Read = 0x1U, /*!< Master receive from slave. */
|
kI2C_Read = 0x1U, /*!< Master receives from the slave. */
|
||||||
} i2c_direction_t;
|
} i2c_direction_t;
|
||||||
|
|
||||||
/*! @brief Addressing mode. */
|
/*! @brief Addressing mode. */
|
||||||
|
@ -125,17 +125,17 @@ typedef enum _i2c_slave_address_mode
|
||||||
/*! @brief I2C transfer control flag. */
|
/*! @brief I2C transfer control flag. */
|
||||||
enum _i2c_master_transfer_flags
|
enum _i2c_master_transfer_flags
|
||||||
{
|
{
|
||||||
kI2C_TransferDefaultFlag = 0x0U, /*!< Transfer starts with a start signal, stops with a stop signal. */
|
kI2C_TransferDefaultFlag = 0x0U, /*!< A transfer starts with a start signal, stops with a stop signal. */
|
||||||
kI2C_TransferNoStartFlag = 0x1U, /*!< Transfer starts without a start signal. */
|
kI2C_TransferNoStartFlag = 0x1U, /*!< A transfer starts without a start signal. */
|
||||||
kI2C_TransferRepeatedStartFlag = 0x2U, /*!< Transfer starts with a repeated start signal. */
|
kI2C_TransferRepeatedStartFlag = 0x2U, /*!< A transfer starts with a repeated start signal. */
|
||||||
kI2C_TransferNoStopFlag = 0x4U, /*!< Transfer ends without a stop signal. */
|
kI2C_TransferNoStopFlag = 0x4U, /*!< A transfer ends without a stop signal. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Set of events sent to the callback for nonblocking slave transfers.
|
* @brief Set of events sent to the callback for nonblocking slave transfers.
|
||||||
*
|
*
|
||||||
* These event enumerations are used for two related purposes. First, a bit mask created by OR'ing together
|
* These event enumerations are used for two related purposes. First, a bit mask created by OR'ing together
|
||||||
* events is passed to I2C_SlaveTransferNonBlocking() in order to specify which events to enable.
|
* events is passed to I2C_SlaveTransferNonBlocking() to specify which events to enable.
|
||||||
* Then, when the slave callback is invoked, it is passed the current event through its @a transfer
|
* Then, when the slave callback is invoked, it is passed the current event through its @a transfer
|
||||||
* parameter.
|
* parameter.
|
||||||
*
|
*
|
||||||
|
@ -144,36 +144,34 @@ enum _i2c_master_transfer_flags
|
||||||
typedef enum _i2c_slave_transfer_event
|
typedef enum _i2c_slave_transfer_event
|
||||||
{
|
{
|
||||||
kI2C_SlaveAddressMatchEvent = 0x01U, /*!< Received the slave address after a start or repeated start. */
|
kI2C_SlaveAddressMatchEvent = 0x01U, /*!< Received the slave address after a start or repeated start. */
|
||||||
kI2C_SlaveTransmitEvent = 0x02U, /*!< Callback is requested to provide data to transmit
|
kI2C_SlaveTransmitEvent = 0x02U, /*!< A callback is requested to provide data to transmit
|
||||||
(slave-transmitter role). */
|
(slave-transmitter role). */
|
||||||
kI2C_SlaveReceiveEvent = 0x04U, /*!< Callback is requested to provide a buffer in which to place received
|
kI2C_SlaveReceiveEvent = 0x04U, /*!< A callback is requested to provide a buffer in which to place received
|
||||||
data (slave-receiver role). */
|
data (slave-receiver role). */
|
||||||
kI2C_SlaveTransmitAckEvent = 0x08U, /*!< Callback needs to either transmit an ACK or NACK. */
|
kI2C_SlaveTransmitAckEvent = 0x08U, /*!< A callback needs to either transmit an ACK or NACK. */
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||||
kI2C_SlaveStartEvent = 0x10U, /*!< A start/repeated start was detected. */
|
kI2C_SlaveStartEvent = 0x10U, /*!< A start/repeated start was detected. */
|
||||||
#endif
|
#endif
|
||||||
kI2C_SlaveCompletionEvent = 0x20U, /*!< A stop was detected or finished transfer, completing the transfer. */
|
kI2C_SlaveCompletionEvent = 0x20U, /*!< A stop was detected or finished transfer, completing the transfer. */
|
||||||
|
kI2C_SlaveGenaralcallEvent = 0x40U, /*!< Received the general call address after a start or repeated start. */
|
||||||
|
|
||||||
/*! Bit mask of all available events. */
|
/*! A bit mask of all available events. */
|
||||||
kI2C_SlaveAllEvents = kI2C_SlaveAddressMatchEvent | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent |
|
kI2C_SlaveAllEvents = kI2C_SlaveAddressMatchEvent | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent |
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||||
kI2C_SlaveStartEvent |
|
kI2C_SlaveStartEvent |
|
||||||
#endif
|
#endif
|
||||||
kI2C_SlaveCompletionEvent,
|
kI2C_SlaveCompletionEvent | kI2C_SlaveGenaralcallEvent,
|
||||||
} i2c_slave_transfer_event_t;
|
} i2c_slave_transfer_event_t;
|
||||||
|
|
||||||
/*! @brief I2C master user configuration. */
|
/*! @brief I2C master user configuration. */
|
||||||
typedef struct _i2c_master_config
|
typedef struct _i2c_master_config
|
||||||
{
|
{
|
||||||
bool enableMaster; /*!< Enables the I2C peripheral at initialization time. */
|
bool enableMaster; /*!< Enables the I2C peripheral at initialization time. */
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
bool enableHighDrive; /*!< Controls the drive capability of the I2C pads. */
|
|
||||||
#endif
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF
|
#if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF
|
||||||
bool enableStopHold; /*!< Controls the stop hold enable. */
|
bool enableStopHold; /*!< Controls the stop hold enable. */
|
||||||
#endif
|
#endif
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
||||||
bool enableDoubleBuffering; /*!< Controls double buffer enable, notice that
|
bool enableDoubleBuffering; /*!< Controls double buffer enable; notice that
|
||||||
enabling the double buffer disables the clock stretch. */
|
enabling the double buffer disables the clock stretch. */
|
||||||
#endif
|
#endif
|
||||||
uint32_t baudRate_Bps; /*!< Baud rate configuration of I2C peripheral. */
|
uint32_t baudRate_Bps; /*!< Baud rate configuration of I2C peripheral. */
|
||||||
|
@ -184,19 +182,20 @@ typedef struct _i2c_master_config
|
||||||
typedef struct _i2c_slave_config
|
typedef struct _i2c_slave_config
|
||||||
{
|
{
|
||||||
bool enableSlave; /*!< Enables the I2C peripheral at initialization time. */
|
bool enableSlave; /*!< Enables the I2C peripheral at initialization time. */
|
||||||
bool enableGeneralCall; /*!< Enable general call addressing mode. */
|
bool enableGeneralCall; /*!< Enables the general call addressing mode. */
|
||||||
bool enableWakeUp; /*!< Enables/disables waking up MCU from low-power mode. */
|
bool enableWakeUp; /*!< Enables/disables waking up MCU from low-power mode. */
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
bool enableHighDrive; /*!< Controls the drive capability of the I2C pads. */
|
|
||||||
#endif
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
||||||
bool enableDoubleBuffering; /*!< Controls double buffer enable, notice that
|
bool enableDoubleBuffering; /*!< Controls a double buffer enable; notice that
|
||||||
enabling the double buffer disables the clock stretch. */
|
enabling the double buffer disables the clock stretch. */
|
||||||
#endif
|
#endif
|
||||||
bool enableBaudRateCtl; /*!< Enables/disables independent slave baud rate on SCL in very fast I2C modes. */
|
bool enableBaudRateCtl; /*!< Enables/disables independent slave baud rate on SCL in very fast I2C modes. */
|
||||||
uint16_t slaveAddress; /*!< Slave address configuration. */
|
uint16_t slaveAddress; /*!< A slave address configuration. */
|
||||||
uint16_t upperAddress; /*!< Maximum boundary slave address used in range matching mode. */
|
uint16_t upperAddress; /*!< A maximum boundary slave address used in a range matching mode. */
|
||||||
i2c_slave_address_mode_t addressingMode; /*!< Addressing mode configuration of i2c_slave_address_mode_config_t. */
|
i2c_slave_address_mode_t
|
||||||
|
addressingMode; /*!< An addressing mode configuration of i2c_slave_address_mode_config_t. */
|
||||||
|
uint32_t sclStopHoldTime_ns; /*!< the delay from the rising edge of SCL (I2C clock) to the rising edge of SDA (I2C
|
||||||
|
data) while SCL is high (stop condition), SDA hold time and SCL start hold time
|
||||||
|
are also configured according to the SCL stop hold time. */
|
||||||
} i2c_slave_config_t;
|
} i2c_slave_config_t;
|
||||||
|
|
||||||
/*! @brief I2C master handle typedef. */
|
/*! @brief I2C master handle typedef. */
|
||||||
|
@ -214,13 +213,13 @@ typedef struct _i2c_slave_handle i2c_slave_handle_t;
|
||||||
/*! @brief I2C master transfer structure. */
|
/*! @brief I2C master transfer structure. */
|
||||||
typedef struct _i2c_master_transfer
|
typedef struct _i2c_master_transfer
|
||||||
{
|
{
|
||||||
uint32_t flags; /*!< Transfer flag which controls the transfer. */
|
uint32_t flags; /*!< A transfer flag which controls the transfer. */
|
||||||
uint8_t slaveAddress; /*!< 7-bit slave address. */
|
uint8_t slaveAddress; /*!< 7-bit slave address. */
|
||||||
i2c_direction_t direction; /*!< Transfer direction, read or write. */
|
i2c_direction_t direction; /*!< A transfer direction, read or write. */
|
||||||
uint32_t subaddress; /*!< Sub address. Transferred MSB first. */
|
uint32_t subaddress; /*!< A sub address. Transferred MSB first. */
|
||||||
uint8_t subaddressSize; /*!< Size of command buffer. */
|
uint8_t subaddressSize; /*!< A size of the command buffer. */
|
||||||
uint8_t *volatile data; /*!< Transfer buffer. */
|
uint8_t *volatile data; /*!< A transfer buffer. */
|
||||||
volatile size_t dataSize; /*!< Transfer size. */
|
volatile size_t dataSize; /*!< A transfer size. */
|
||||||
} i2c_master_transfer_t;
|
} i2c_master_transfer_t;
|
||||||
|
|
||||||
/*! @brief I2C master handle structure. */
|
/*! @brief I2C master handle structure. */
|
||||||
|
@ -228,20 +227,21 @@ struct _i2c_master_handle
|
||||||
{
|
{
|
||||||
i2c_master_transfer_t transfer; /*!< I2C master transfer copy. */
|
i2c_master_transfer_t transfer; /*!< I2C master transfer copy. */
|
||||||
size_t transferSize; /*!< Total bytes to be transferred. */
|
size_t transferSize; /*!< Total bytes to be transferred. */
|
||||||
uint8_t state; /*!< Transfer state maintained during transfer. */
|
uint8_t state; /*!< A transfer state maintained during transfer. */
|
||||||
i2c_master_transfer_callback_t completionCallback; /*!< Callback function called when transfer finished. */
|
i2c_master_transfer_callback_t completionCallback; /*!< A callback function called when the transfer is finished. */
|
||||||
void *userData; /*!< Callback parameter passed to callback function. */
|
void *userData; /*!< A callback parameter passed to the callback function. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! @brief I2C slave transfer structure. */
|
/*! @brief I2C slave transfer structure. */
|
||||||
typedef struct _i2c_slave_transfer
|
typedef struct _i2c_slave_transfer
|
||||||
{
|
{
|
||||||
i2c_slave_transfer_event_t event; /*!< Reason the callback is being invoked. */
|
i2c_slave_transfer_event_t event; /*!< A reason that the callback is invoked. */
|
||||||
uint8_t *volatile data; /*!< Transfer buffer. */
|
uint8_t *volatile data; /*!< A transfer buffer. */
|
||||||
volatile size_t dataSize; /*!< Transfer size. */
|
volatile size_t dataSize; /*!< A transfer size. */
|
||||||
status_t completionStatus; /*!< Success or error code describing how the transfer completed. Only applies for
|
status_t completionStatus; /*!< Success or error code describing how the transfer completed. Only applies for
|
||||||
#kI2C_SlaveCompletionEvent. */
|
#kI2C_SlaveCompletionEvent. */
|
||||||
size_t transferredCount; /*!< Number of bytes actually transferred since start or last repeated start. */
|
size_t transferredCount; /*!< A number of bytes actually transferred since the start or since the last repeated
|
||||||
|
start. */
|
||||||
} i2c_slave_transfer_t;
|
} i2c_slave_transfer_t;
|
||||||
|
|
||||||
/*! @brief I2C slave transfer callback typedef. */
|
/*! @brief I2C slave transfer callback typedef. */
|
||||||
|
@ -250,11 +250,11 @@ typedef void (*i2c_slave_transfer_callback_t)(I2C_Type *base, i2c_slave_transfer
|
||||||
/*! @brief I2C slave handle structure. */
|
/*! @brief I2C slave handle structure. */
|
||||||
struct _i2c_slave_handle
|
struct _i2c_slave_handle
|
||||||
{
|
{
|
||||||
bool isBusy; /*!< Whether transfer is busy. */
|
volatile bool isBusy; /*!< Indicates whether a transfer is busy. */
|
||||||
i2c_slave_transfer_t transfer; /*!< I2C slave transfer copy. */
|
i2c_slave_transfer_t transfer; /*!< I2C slave transfer copy. */
|
||||||
uint32_t eventMask; /*!< Mask of enabled events. */
|
uint32_t eventMask; /*!< A mask of enabled events. */
|
||||||
i2c_slave_transfer_callback_t callback; /*!< Callback function called at transfer event. */
|
i2c_slave_transfer_callback_t callback; /*!< A callback function called at the transfer event. */
|
||||||
void *userData; /*!< Callback parameter passed to callback. */
|
void *userData; /*!< A callback parameter passed to the callback. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
@ -274,12 +274,12 @@ extern "C" {
|
||||||
* @brief Initializes the I2C peripheral. Call this API to ungate the I2C clock
|
* @brief Initializes the I2C peripheral. Call this API to ungate the I2C clock
|
||||||
* and configure the I2C with master configuration.
|
* and configure the I2C with master configuration.
|
||||||
*
|
*
|
||||||
* @note This API should be called at the beginning of the application to use
|
* @note This API should be called at the beginning of the application.
|
||||||
* the I2C driver, or any operation to the I2C module may cause a hard fault
|
* Otherwise, any operation to the I2C module can cause a hard fault
|
||||||
* because clock is not enabled. The configuration structure can be filled by user
|
* because the clock is not enabled. The configuration structure can be custom filled
|
||||||
* from scratch, or be set with default values by I2C_MasterGetDefaultConfig().
|
* or it can be set with default values by using the I2C_MasterGetDefaultConfig().
|
||||||
* After calling this API, the master is ready to transfer.
|
* After calling this API, the master is ready to transfer.
|
||||||
* Example:
|
* This is an example.
|
||||||
* @code
|
* @code
|
||||||
* i2c_master_config_t config = {
|
* i2c_master_config_t config = {
|
||||||
* .enableMaster = true,
|
* .enableMaster = true,
|
||||||
|
@ -292,20 +292,20 @@ extern "C" {
|
||||||
* @endcode
|
* @endcode
|
||||||
*
|
*
|
||||||
* @param base I2C base pointer
|
* @param base I2C base pointer
|
||||||
* @param masterConfig pointer to master configuration structure
|
* @param masterConfig A pointer to the master configuration structure
|
||||||
* @param srcClock_Hz I2C peripheral clock frequency in Hz
|
* @param srcClock_Hz I2C peripheral clock frequency in Hz
|
||||||
*/
|
*/
|
||||||
void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz);
|
void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Initializes the I2C peripheral. Call this API to ungate the I2C clock
|
* @brief Initializes the I2C peripheral. Call this API to ungate the I2C clock
|
||||||
* and initializes the I2C with slave configuration.
|
* and initialize the I2C with the slave configuration.
|
||||||
*
|
*
|
||||||
* @note This API should be called at the beginning of the application to use
|
* @note This API should be called at the beginning of the application.
|
||||||
* the I2C driver, or any operation to the I2C module can cause a hard fault
|
* Otherwise, any operation to the I2C module can cause a hard fault
|
||||||
* because the clock is not enabled. The configuration structure can partly be set
|
* because the clock is not enabled. The configuration structure can partly be set
|
||||||
* with default values by I2C_SlaveGetDefaultConfig(), or can be filled by the user.
|
* with default values by I2C_SlaveGetDefaultConfig() or it can be custom filled by the user.
|
||||||
* Example
|
* This is an example.
|
||||||
* @code
|
* @code
|
||||||
* i2c_slave_config_t config = {
|
* i2c_slave_config_t config = {
|
||||||
* .enableSlave = true,
|
* .enableSlave = true,
|
||||||
|
@ -314,15 +314,17 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin
|
||||||
* .slaveAddress = 0x1DU,
|
* .slaveAddress = 0x1DU,
|
||||||
* .enableWakeUp = false,
|
* .enableWakeUp = false,
|
||||||
* .enablehighDrive = false,
|
* .enablehighDrive = false,
|
||||||
* .enableBaudRateCtl = false
|
* .enableBaudRateCtl = false,
|
||||||
|
* .sclStopHoldTime_ns = 4000
|
||||||
* };
|
* };
|
||||||
* I2C_SlaveInit(I2C0, &config);
|
* I2C_SlaveInit(I2C0, &config, 12000000U);
|
||||||
* @endcode
|
* @endcode
|
||||||
*
|
*
|
||||||
* @param base I2C base pointer
|
* @param base I2C base pointer
|
||||||
* @param slaveConfig pointer to slave configuration structure
|
* @param slaveConfig A pointer to the slave configuration structure
|
||||||
|
* @param srcClock_Hz I2C peripheral clock frequency in Hz
|
||||||
*/
|
*/
|
||||||
void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig);
|
void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig, uint32_t srcClock_Hz);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief De-initializes the I2C master peripheral. Call this API to gate the I2C clock.
|
* @brief De-initializes the I2C master peripheral. Call this API to gate the I2C clock.
|
||||||
|
@ -342,28 +344,28 @@ void I2C_SlaveDeinit(I2C_Type *base);
|
||||||
* @brief Sets the I2C master configuration structure to default values.
|
* @brief Sets the I2C master configuration structure to default values.
|
||||||
*
|
*
|
||||||
* The purpose of this API is to get the configuration structure initialized for use in the I2C_MasterConfigure().
|
* The purpose of this API is to get the configuration structure initialized for use in the I2C_MasterConfigure().
|
||||||
* Use the initialized structure unchanged in I2C_MasterConfigure(), or modify some fields of
|
* Use the initialized structure unchanged in the I2C_MasterConfigure() or modify
|
||||||
* the structure before calling I2C_MasterConfigure().
|
* the structure before calling the I2C_MasterConfigure().
|
||||||
* Example:
|
* This is an example.
|
||||||
* @code
|
* @code
|
||||||
* i2c_master_config_t config;
|
* i2c_master_config_t config;
|
||||||
* I2C_MasterGetDefaultConfig(&config);
|
* I2C_MasterGetDefaultConfig(&config);
|
||||||
* @endcode
|
* @endcode
|
||||||
* @param masterConfig Pointer to the master configuration structure.
|
* @param masterConfig A pointer to the master configuration structure.
|
||||||
*/
|
*/
|
||||||
void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig);
|
void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Sets the I2C slave configuration structure to default values.
|
* @brief Sets the I2C slave configuration structure to default values.
|
||||||
*
|
*
|
||||||
* The purpose of this API is to get the configuration structure initialized for use in I2C_SlaveConfigure().
|
* The purpose of this API is to get the configuration structure initialized for use in the I2C_SlaveConfigure().
|
||||||
* Modify fields of the structure before calling the I2C_SlaveConfigure().
|
* Modify fields of the structure before calling the I2C_SlaveConfigure().
|
||||||
* Example:
|
* This is an example.
|
||||||
* @code
|
* @code
|
||||||
* i2c_slave_config_t config;
|
* i2c_slave_config_t config;
|
||||||
* I2C_SlaveGetDefaultConfig(&config);
|
* I2C_SlaveGetDefaultConfig(&config);
|
||||||
* @endcode
|
* @endcode
|
||||||
* @param slaveConfig Pointer to the slave configuration structure.
|
* @param slaveConfig A pointer to the slave configuration structure.
|
||||||
*/
|
*/
|
||||||
void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig);
|
void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig);
|
||||||
|
|
||||||
|
@ -371,7 +373,7 @@ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig);
|
||||||
* @brief Enables or disabless the I2C peripheral operation.
|
* @brief Enables or disabless the I2C peripheral operation.
|
||||||
*
|
*
|
||||||
* @param base I2C base pointer
|
* @param base I2C base pointer
|
||||||
* @param enable pass true to enable module, false to disable module
|
* @param enable Pass true to enable and false to disable the module.
|
||||||
*/
|
*/
|
||||||
static inline void I2C_Enable(I2C_Type *base, bool enable)
|
static inline void I2C_Enable(I2C_Type *base, bool enable)
|
||||||
{
|
{
|
||||||
|
@ -414,7 +416,7 @@ static inline uint32_t I2C_SlaveGetStatusFlags(I2C_Type *base)
|
||||||
/*!
|
/*!
|
||||||
* @brief Clears the I2C status flag state.
|
* @brief Clears the I2C status flag state.
|
||||||
*
|
*
|
||||||
* The following status register flags can be cleared: kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag
|
* The following status register flags can be cleared kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag.
|
||||||
*
|
*
|
||||||
* @param base I2C base pointer
|
* @param base I2C base pointer
|
||||||
* @param statusMask The status flag mask, defined in type i2c_status_flag_t.
|
* @param statusMask The status flag mask, defined in type i2c_status_flag_t.
|
||||||
|
@ -449,7 +451,7 @@ static inline void I2C_MasterClearStatusFlags(I2C_Type *base, uint32_t statusMas
|
||||||
/*!
|
/*!
|
||||||
* @brief Clears the I2C status flag state.
|
* @brief Clears the I2C status flag state.
|
||||||
*
|
*
|
||||||
* The following status register flags can be cleared: kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag
|
* The following status register flags can be cleared kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag
|
||||||
*
|
*
|
||||||
* @param base I2C base pointer
|
* @param base I2C base pointer
|
||||||
* @param statusMask The status flag mask, defined in type i2c_status_flag_t.
|
* @param statusMask The status flag mask, defined in type i2c_status_flag_t.
|
||||||
|
@ -581,19 +583,21 @@ status_t I2C_MasterStop(I2C_Type *base);
|
||||||
status_t I2C_MasterRepeatedStart(I2C_Type *base, uint8_t address, i2c_direction_t direction);
|
status_t I2C_MasterRepeatedStart(I2C_Type *base, uint8_t address, i2c_direction_t direction);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Performs a polling send transaction on the I2C bus without a STOP signal.
|
* @brief Performs a polling send transaction on the I2C bus.
|
||||||
*
|
*
|
||||||
* @param base The I2C peripheral base pointer.
|
* @param base The I2C peripheral base pointer.
|
||||||
* @param txBuff The pointer to the data to be transferred.
|
* @param txBuff The pointer to the data to be transferred.
|
||||||
* @param txSize The length in bytes of the data to be transferred.
|
* @param txSize The length in bytes of the data to be transferred.
|
||||||
|
* @param flags Transfer control flag to decide whether need to send a stop, use kI2C_TransferDefaultFlag
|
||||||
|
* to issue a stop and kI2C_TransferNoStop to not send a stop.
|
||||||
* @retval kStatus_Success Successfully complete the data transmission.
|
* @retval kStatus_Success Successfully complete the data transmission.
|
||||||
* @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
|
* @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
|
||||||
* @retval kStataus_I2C_Nak Transfer error, receive NAK during transfer.
|
* @retval kStataus_I2C_Nak Transfer error, receive NAK during transfer.
|
||||||
*/
|
*/
|
||||||
status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize);
|
status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize, uint32_t flags);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Performs a polling receive transaction on the I2C bus with a STOP signal.
|
* @brief Performs a polling receive transaction on the I2C bus.
|
||||||
*
|
*
|
||||||
* @note The I2C_MasterReadBlocking function stops the bus before reading the final byte.
|
* @note The I2C_MasterReadBlocking function stops the bus before reading the final byte.
|
||||||
* Without stopping the bus prior for the final read, the bus issues another read, resulting
|
* Without stopping the bus prior for the final read, the bus issues another read, resulting
|
||||||
|
@ -602,10 +606,12 @@ status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t t
|
||||||
* @param base I2C peripheral base pointer.
|
* @param base I2C peripheral base pointer.
|
||||||
* @param rxBuff The pointer to the data to store the received data.
|
* @param rxBuff The pointer to the data to store the received data.
|
||||||
* @param rxSize The length in bytes of the data to be received.
|
* @param rxSize The length in bytes of the data to be received.
|
||||||
|
* @param flags Transfer control flag to decide whether need to send a stop, use kI2C_TransferDefaultFlag
|
||||||
|
* to issue a stop and kI2C_TransferNoStop to not send a stop.
|
||||||
* @retval kStatus_Success Successfully complete the data transmission.
|
* @retval kStatus_Success Successfully complete the data transmission.
|
||||||
* @retval kStatus_I2C_Timeout Send stop signal failed, timeout.
|
* @retval kStatus_I2C_Timeout Send stop signal failed, timeout.
|
||||||
*/
|
*/
|
||||||
status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize);
|
status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize, uint32_t flags);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Performs a polling send transaction on the I2C bus.
|
* @brief Performs a polling send transaction on the I2C bus.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||||
* All rights reserved.
|
* Copyright 2016-2017 NXP
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
* other materials provided with the distribution.
|
* other materials provided with the distribution.
|
||||||
*
|
*
|
||||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
* o Neither the name of the copyright holder nor the names of its
|
||||||
* contributors may be used to endorse or promote products derived from this
|
* contributors may be used to endorse or promote products derived from this
|
||||||
* software without specific prior written permission.
|
* software without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -162,6 +162,26 @@ static void I2C_MasterTransferCallbackEDMA(edma_handle_t *handle, void *userData
|
||||||
result = I2C_MasterStop(i2cPrivateHandle->base);
|
result = I2C_MasterStop(i2cPrivateHandle->base);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (i2cPrivateHandle->handle->transfer.direction == kI2C_Read)
|
||||||
|
{
|
||||||
|
/* Change to send NAK at the last byte. */
|
||||||
|
i2cPrivateHandle->base->C1 |= I2C_C1_TXAK_MASK;
|
||||||
|
|
||||||
|
/* Wait the last data to be received. */
|
||||||
|
while (!(i2cPrivateHandle->base->S & kI2C_TransferCompleteFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Change direction to send. */
|
||||||
|
i2cPrivateHandle->base->C1 |= I2C_C1_TX_MASK;
|
||||||
|
|
||||||
|
/* Read the last data byte. */
|
||||||
|
*(i2cPrivateHandle->handle->transfer.data + i2cPrivateHandle->handle->transfer.dataSize - 1) =
|
||||||
|
i2cPrivateHandle->base->D;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
i2cPrivateHandle->handle->state = kIdleState;
|
i2cPrivateHandle->handle->state = kIdleState;
|
||||||
|
|
||||||
|
@ -203,7 +223,6 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
||||||
assert(xfer);
|
assert(xfer);
|
||||||
|
|
||||||
status_t result = kStatus_Success;
|
status_t result = kStatus_Success;
|
||||||
uint16_t timeout = UINT16_MAX;
|
|
||||||
|
|
||||||
if (handle->state != kIdleState)
|
if (handle->state != kIdleState)
|
||||||
{
|
{
|
||||||
|
@ -221,16 +240,6 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
||||||
|
|
||||||
handle->state = kTransferDataState;
|
handle->state = kTransferDataState;
|
||||||
|
|
||||||
/* Wait until ready to complete. */
|
|
||||||
while ((!(base->S & kI2C_TransferCompleteFlag)) && (--timeout))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Failed to start the transfer. */
|
|
||||||
if (timeout == 0)
|
|
||||||
{
|
|
||||||
return kStatus_I2C_Timeout;
|
|
||||||
}
|
|
||||||
/* Clear all status before transfer. */
|
/* Clear all status before transfer. */
|
||||||
I2C_MasterClearStatusFlags(base, kClearFlags);
|
I2C_MasterClearStatusFlags(base, kClearFlags);
|
||||||
|
|
||||||
|
@ -250,22 +259,55 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
||||||
result = I2C_MasterStart(base, handle->transfer.slaveAddress, direction);
|
result = I2C_MasterStart(base, handle->transfer.slaveAddress, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if there's transfer error. */
|
||||||
|
result = I2C_CheckAndClearError(base, base->S);
|
||||||
|
|
||||||
|
/* Return if error. */
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
if (result == kStatus_I2C_Nak)
|
||||||
|
{
|
||||||
|
result = kStatus_I2C_Addr_Nak;
|
||||||
|
|
||||||
|
if (I2C_MasterStop(base) != kStatus_Success)
|
||||||
|
{
|
||||||
|
result = kStatus_I2C_Timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle->completionCallback)
|
||||||
|
{
|
||||||
|
(handle->completionCallback)(base, handle, result, handle->userData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* Send subaddress. */
|
/* Send subaddress. */
|
||||||
if (handle->transfer.subaddressSize)
|
if (handle->transfer.subaddressSize)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
/* Wait until data transfer complete. */
|
|
||||||
while (!(base->S & kI2C_IntPendingFlag))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear interrupt pending flag. */
|
/* Clear interrupt pending flag. */
|
||||||
base->S = kI2C_IntPendingFlag;
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
handle->transfer.subaddressSize--;
|
handle->transfer.subaddressSize--;
|
||||||
base->D = ((handle->transfer.subaddress) >> (8 * handle->transfer.subaddressSize));
|
base->D = ((handle->transfer.subaddress) >> (8 * handle->transfer.subaddressSize));
|
||||||
|
|
||||||
|
/* Wait until data transfer complete. */
|
||||||
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if there's transfer error. */
|
/* Check if there's transfer error. */
|
||||||
result = I2C_CheckAndClearError(base, base->S);
|
result = I2C_CheckAndClearError(base, base->S);
|
||||||
|
|
||||||
|
@ -278,18 +320,11 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
||||||
|
|
||||||
if (handle->transfer.direction == kI2C_Read)
|
if (handle->transfer.direction == kI2C_Read)
|
||||||
{
|
{
|
||||||
/* Wait until data transfer complete. */
|
|
||||||
while (!(base->S & kI2C_IntPendingFlag))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear pending flag. */
|
/* Clear pending flag. */
|
||||||
base->S = kI2C_IntPendingFlag;
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
/* Send repeated start and slave address. */
|
/* Send repeated start and slave address. */
|
||||||
result = I2C_MasterRepeatedStart(base, handle->transfer.slaveAddress, kI2C_Read);
|
result = I2C_MasterRepeatedStart(base, handle->transfer.slaveAddress, kI2C_Read);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
|
@ -301,11 +336,18 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear pending flag. */
|
|
||||||
base->S = kI2C_IntPendingFlag;
|
|
||||||
|
|
||||||
/* Check if there's transfer error. */
|
/* Check if there's transfer error. */
|
||||||
result = I2C_CheckAndClearError(base, base->S);
|
result = I2C_CheckAndClearError(base, base->S);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear pending flag. */
|
||||||
|
base->S = kI2C_IntPendingFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -319,17 +361,7 @@ static void I2C_MasterTransferEDMAConfig(I2C_Type *base, i2c_master_edma_handle_
|
||||||
{
|
{
|
||||||
transfer_config.srcAddr = (uint32_t)I2C_GetDataRegAddr(base);
|
transfer_config.srcAddr = (uint32_t)I2C_GetDataRegAddr(base);
|
||||||
transfer_config.destAddr = (uint32_t)(handle->transfer.data);
|
transfer_config.destAddr = (uint32_t)(handle->transfer.data);
|
||||||
|
|
||||||
/* Send stop if kI2C_TransferNoStop flag is not asserted. */
|
|
||||||
if (!(handle->transfer.flags & kI2C_TransferNoStopFlag))
|
|
||||||
{
|
|
||||||
transfer_config.majorLoopCounts = (handle->transfer.dataSize - 1);
|
transfer_config.majorLoopCounts = (handle->transfer.dataSize - 1);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
transfer_config.majorLoopCounts = handle->transfer.dataSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
transfer_config.srcTransferSize = kEDMA_TransferSize1Bytes;
|
transfer_config.srcTransferSize = kEDMA_TransferSize1Bytes;
|
||||||
transfer_config.srcOffset = 0;
|
transfer_config.srcOffset = 0;
|
||||||
transfer_config.destTransferSize = kEDMA_TransferSize1Bytes;
|
transfer_config.destTransferSize = kEDMA_TransferSize1Bytes;
|
||||||
|
@ -348,6 +380,9 @@ static void I2C_MasterTransferEDMAConfig(I2C_Type *base, i2c_master_edma_handle_
|
||||||
transfer_config.minorLoopBytes = 1;
|
transfer_config.minorLoopBytes = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Store the initially configured eDMA minor byte transfer count into the I2C handle */
|
||||||
|
handle->nbytes = transfer_config.minorLoopBytes;
|
||||||
|
|
||||||
EDMA_SubmitTransfer(handle->dmaHandle, &transfer_config);
|
EDMA_SubmitTransfer(handle->dmaHandle, &transfer_config);
|
||||||
EDMA_StartTransfer(handle->dmaHandle);
|
EDMA_StartTransfer(handle->dmaHandle);
|
||||||
}
|
}
|
||||||
|
@ -427,7 +462,7 @@ status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle
|
||||||
if (handle->transfer.direction == kI2C_Read)
|
if (handle->transfer.direction == kI2C_Read)
|
||||||
{
|
{
|
||||||
/* Change direction for receive. */
|
/* Change direction for receive. */
|
||||||
base->C1 &= ~I2C_C1_TX_MASK;
|
base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK);
|
||||||
|
|
||||||
/* Read dummy to release the bus. */
|
/* Read dummy to release the bus. */
|
||||||
dummy = base->D;
|
dummy = base->D;
|
||||||
|
@ -479,6 +514,11 @@ status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle
|
||||||
{
|
{
|
||||||
result = I2C_MasterStop(base);
|
result = I2C_MasterStop(base);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Change direction to send. */
|
||||||
|
base->C1 |= I2C_C1_TX_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read the last byte of data. */
|
/* Read the last byte of data. */
|
||||||
if (handle->transfer.direction == kI2C_Read)
|
if (handle->transfer.direction == kI2C_Read)
|
||||||
|
@ -504,7 +544,9 @@ status_t I2C_MasterTransferGetCountEDMA(I2C_Type *base, i2c_master_edma_handle_t
|
||||||
|
|
||||||
if (kIdleState != handle->state)
|
if (kIdleState != handle->state)
|
||||||
{
|
{
|
||||||
*count = (handle->transferSize - EDMA_GetRemainingBytes(handle->dmaHandle->base, handle->dmaHandle->channel));
|
*count = (handle->transferSize -
|
||||||
|
(uint32_t)handle->nbytes *
|
||||||
|
EDMA_GetRemainingMajorLoopCount(handle->dmaHandle->base, handle->dmaHandle->channel));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||||
* All rights reserved.
|
* Copyright 2016-2017 NXP
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
* other materials provided with the distribution.
|
* other materials provided with the distribution.
|
||||||
*
|
*
|
||||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
* o Neither the name of the copyright holder nor the names of its
|
||||||
* contributors may be used to endorse or promote products derived from this
|
* contributors may be used to endorse or promote products derived from this
|
||||||
* software without specific prior written permission.
|
* software without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -39,7 +39,6 @@
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Definitions
|
* Definitions
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
@ -56,13 +55,14 @@ typedef void (*i2c_master_edma_transfer_callback_t)(I2C_Type *base,
|
||||||
/*! @brief I2C master eDMA transfer structure. */
|
/*! @brief I2C master eDMA transfer structure. */
|
||||||
struct _i2c_master_edma_handle
|
struct _i2c_master_edma_handle
|
||||||
{
|
{
|
||||||
i2c_master_transfer_t transfer; /*!< I2C master transfer struct. */
|
i2c_master_transfer_t transfer; /*!< I2C master transfer structure. */
|
||||||
size_t transferSize; /*!< Total bytes to be transferred. */
|
size_t transferSize; /*!< Total bytes to be transferred. */
|
||||||
|
uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */
|
||||||
uint8_t state; /*!< I2C master transfer status. */
|
uint8_t state; /*!< I2C master transfer status. */
|
||||||
edma_handle_t *dmaHandle; /*!< The eDMA handler used. */
|
edma_handle_t *dmaHandle; /*!< The eDMA handler used. */
|
||||||
i2c_master_edma_transfer_callback_t
|
i2c_master_edma_transfer_callback_t
|
||||||
completionCallback; /*!< Callback function called after eDMA transfer finished. */
|
completionCallback; /*!< A callback function called after the eDMA transfer is finished. */
|
||||||
void *userData; /*!< Callback parameter passed to callback function. */
|
void *userData; /*!< A callback parameter passed to the callback function. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
@ -79,12 +79,12 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Init the I2C handle which is used in transcational functions.
|
* @brief Initializes the I2C handle which is used in transcational functions.
|
||||||
*
|
*
|
||||||
* @param base I2C peripheral base address.
|
* @param base I2C peripheral base address.
|
||||||
* @param handle pointer to i2c_master_edma_handle_t structure.
|
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||||
* @param callback pointer to user callback function.
|
* @param callback A pointer to the user callback function.
|
||||||
* @param userData user param passed to the callback function.
|
* @param userData A user parameter passed to the callback function.
|
||||||
* @param edmaHandle eDMA handle pointer.
|
* @param edmaHandle eDMA handle pointer.
|
||||||
*/
|
*/
|
||||||
void I2C_MasterCreateEDMAHandle(I2C_Type *base,
|
void I2C_MasterCreateEDMAHandle(I2C_Type *base,
|
||||||
|
@ -97,30 +97,30 @@ void I2C_MasterCreateEDMAHandle(I2C_Type *base,
|
||||||
* @brief Performs a master eDMA non-blocking transfer on the I2C bus.
|
* @brief Performs a master eDMA non-blocking transfer on the I2C bus.
|
||||||
*
|
*
|
||||||
* @param base I2C peripheral base address.
|
* @param base I2C peripheral base address.
|
||||||
* @param handle pointer to i2c_master_edma_handle_t structure.
|
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||||
* @param xfer pointer to transfer structure of i2c_master_transfer_t.
|
* @param xfer A pointer to the transfer structure of i2c_master_transfer_t.
|
||||||
* @retval kStatus_Success Sucessully complete the data transmission.
|
* @retval kStatus_Success Sucessfully completed the data transmission.
|
||||||
* @retval kStatus_I2C_Busy Previous transmission still not finished.
|
* @retval kStatus_I2C_Busy A previous transmission is still not finished.
|
||||||
* @retval kStatus_I2C_Timeout Transfer error, wait signal timeout.
|
* @retval kStatus_I2C_Timeout Transfer error, waits for a signal timeout.
|
||||||
* @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
|
* @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
|
||||||
* @retval kStataus_I2C_Nak Transfer error, receive Nak during transfer.
|
* @retval kStataus_I2C_Nak Transfer error, receive NAK during transfer.
|
||||||
*/
|
*/
|
||||||
status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle, i2c_master_transfer_t *xfer);
|
status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle, i2c_master_transfer_t *xfer);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Get master transfer status during a eDMA non-blocking transfer.
|
* @brief Gets a master transfer status during the eDMA non-blocking transfer.
|
||||||
*
|
*
|
||||||
* @param base I2C peripheral base address.
|
* @param base I2C peripheral base address.
|
||||||
* @param handle pointer to i2c_master_edma_handle_t structure.
|
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||||
* @param count Number of bytes transferred so far by the non-blocking transaction.
|
* @param count A number of bytes transferred by the non-blocking transaction.
|
||||||
*/
|
*/
|
||||||
status_t I2C_MasterTransferGetCountEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle, size_t *count);
|
status_t I2C_MasterTransferGetCountEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle, size_t *count);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Abort a master eDMA non-blocking transfer in a early time.
|
* @brief Aborts a master eDMA non-blocking transfer early.
|
||||||
*
|
*
|
||||||
* @param base I2C peripheral base address.
|
* @param base I2C peripheral base address.
|
||||||
* @param handle pointer to i2c_master_edma_handle_t structure.
|
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||||
*/
|
*/
|
||||||
void I2C_MasterTransferAbortEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle);
|
void I2C_MasterTransferAbortEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||||
* All rights reserved.
|
* Copyright 2016-2017 NXP
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
* other materials provided with the distribution.
|
* other materials provided with the distribution.
|
||||||
*
|
*
|
||||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
* o Neither the name of the copyright holder nor the names of its
|
||||||
* contributors may be used to endorse or promote products derived from this
|
* contributors may be used to endorse or promote products derived from this
|
||||||
* software without specific prior written permission.
|
* software without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -75,6 +75,19 @@ typedef void (*i2c_isr_t)(I2C_Type *base, void *i2cHandle);
|
||||||
*/
|
*/
|
||||||
uint32_t I2C_GetInstance(I2C_Type *base);
|
uint32_t I2C_GetInstance(I2C_Type *base);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Set SCL/SDA hold time, this API receives SCL stop hold time, calculate the
|
||||||
|
* closest SCL divider and MULT value for the SDA hold time, SCL start and SCL stop
|
||||||
|
* hold time. To reduce the ROM size, SDA/SCL hold value mapping table is not provided,
|
||||||
|
* assume SCL divider = SCL stop hold value *2 to get the closest SCL divider value and MULT
|
||||||
|
* value, then the related SDA hold time, SCL start and SCL stop hold time is used.
|
||||||
|
*
|
||||||
|
* @param base I2C peripheral base address.
|
||||||
|
* @param sourceClock_Hz I2C functional clock frequency in Hertz.
|
||||||
|
* @param sclStopHoldTime_ns SCL stop hold time in ns.
|
||||||
|
*/
|
||||||
|
static void I2C_SetHoldTime(I2C_Type *base, uint32_t sclStopHoldTime_ns, uint32_t sourceClock_Hz);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Set up master transfer, send slave address and decide the initial
|
* @brief Set up master transfer, send slave address and decide the initial
|
||||||
* transfer state.
|
* transfer state.
|
||||||
|
@ -137,8 +150,10 @@ static I2C_Type *const s_i2cBases[] = I2C_BASE_PTRS;
|
||||||
/*! @brief Pointers to i2c IRQ number for each instance. */
|
/*! @brief Pointers to i2c IRQ number for each instance. */
|
||||||
static const IRQn_Type s_i2cIrqs[] = I2C_IRQS;
|
static const IRQn_Type s_i2cIrqs[] = I2C_IRQS;
|
||||||
|
|
||||||
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||||
/*! @brief Pointers to i2c clocks for each instance. */
|
/*! @brief Pointers to i2c clocks for each instance. */
|
||||||
static const clock_ip_name_t s_i2cClocks[] = I2C_CLOCKS;
|
static const clock_ip_name_t s_i2cClocks[] = I2C_CLOCKS;
|
||||||
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||||
|
|
||||||
/*! @brief Pointer to master IRQ handler for each instance. */
|
/*! @brief Pointer to master IRQ handler for each instance. */
|
||||||
static i2c_isr_t s_i2cMasterIsr;
|
static i2c_isr_t s_i2cMasterIsr;
|
||||||
|
@ -155,7 +170,7 @@ uint32_t I2C_GetInstance(I2C_Type *base)
|
||||||
uint32_t instance;
|
uint32_t instance;
|
||||||
|
|
||||||
/* Find the instance index from base address mappings. */
|
/* Find the instance index from base address mappings. */
|
||||||
for (instance = 0; instance < FSL_FEATURE_SOC_I2C_COUNT; instance++)
|
for (instance = 0; instance < ARRAY_SIZE(s_i2cBases); instance++)
|
||||||
{
|
{
|
||||||
if (s_i2cBases[instance] == base)
|
if (s_i2cBases[instance] == base)
|
||||||
{
|
{
|
||||||
|
@ -163,16 +178,63 @@ uint32_t I2C_GetInstance(I2C_Type *base)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(instance < FSL_FEATURE_SOC_I2C_COUNT);
|
assert(instance < ARRAY_SIZE(s_i2cBases));
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void I2C_SetHoldTime(I2C_Type *base, uint32_t sclStopHoldTime_ns, uint32_t sourceClock_Hz)
|
||||||
|
{
|
||||||
|
uint32_t multiplier;
|
||||||
|
uint32_t computedSclHoldTime;
|
||||||
|
uint32_t absError;
|
||||||
|
uint32_t bestError = UINT32_MAX;
|
||||||
|
uint32_t bestMult = 0u;
|
||||||
|
uint32_t bestIcr = 0u;
|
||||||
|
uint8_t mult;
|
||||||
|
uint8_t i;
|
||||||
|
|
||||||
|
/* Search for the settings with the lowest error. Mult is the MULT field of the I2C_F register,
|
||||||
|
* and ranges from 0-2. It selects the multiplier factor for the divider. */
|
||||||
|
/* SDA hold time = bus period (s) * mul * SDA hold value. */
|
||||||
|
/* SCL start hold time = bus period (s) * mul * SCL start hold value. */
|
||||||
|
/* SCL stop hold time = bus period (s) * mul * SCL stop hold value. */
|
||||||
|
|
||||||
|
for (mult = 0u; (mult <= 2u) && (bestError != 0); ++mult)
|
||||||
|
{
|
||||||
|
multiplier = 1u << mult;
|
||||||
|
|
||||||
|
/* Scan table to find best match. */
|
||||||
|
for (i = 0u; i < sizeof(s_i2cDividerTable) / sizeof(s_i2cDividerTable[0]); ++i)
|
||||||
|
{
|
||||||
|
/* Assume SCL hold(stop) value = s_i2cDividerTable[i]/2. */
|
||||||
|
computedSclHoldTime = ((multiplier * s_i2cDividerTable[i]) * 500000000U) / sourceClock_Hz;
|
||||||
|
absError = sclStopHoldTime_ns > computedSclHoldTime ? (sclStopHoldTime_ns - computedSclHoldTime) :
|
||||||
|
(computedSclHoldTime - sclStopHoldTime_ns);
|
||||||
|
|
||||||
|
if (absError < bestError)
|
||||||
|
{
|
||||||
|
bestMult = mult;
|
||||||
|
bestIcr = i;
|
||||||
|
bestError = absError;
|
||||||
|
|
||||||
|
/* If the error is 0, then we can stop searching because we won't find a better match. */
|
||||||
|
if (absError == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set frequency register based on best settings. */
|
||||||
|
base->F = I2C_F_MULT(bestMult) | I2C_F_ICR(bestIcr);
|
||||||
|
}
|
||||||
|
|
||||||
static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t *handle, i2c_master_transfer_t *xfer)
|
static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t *handle, i2c_master_transfer_t *xfer)
|
||||||
{
|
{
|
||||||
status_t result = kStatus_Success;
|
status_t result = kStatus_Success;
|
||||||
i2c_direction_t direction = xfer->direction;
|
i2c_direction_t direction = xfer->direction;
|
||||||
uint16_t timeout = UINT16_MAX;
|
|
||||||
|
|
||||||
/* Initialize the handle transfer information. */
|
/* Initialize the handle transfer information. */
|
||||||
handle->transfer = *xfer;
|
handle->transfer = *xfer;
|
||||||
|
@ -183,27 +245,13 @@ static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t
|
||||||
/* Initial transfer state. */
|
/* Initial transfer state. */
|
||||||
if (handle->transfer.subaddressSize > 0)
|
if (handle->transfer.subaddressSize > 0)
|
||||||
{
|
{
|
||||||
handle->state = kSendCommandState;
|
|
||||||
if (xfer->direction == kI2C_Read)
|
if (xfer->direction == kI2C_Read)
|
||||||
{
|
{
|
||||||
direction = kI2C_Write;
|
direction = kI2C_Write;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
handle->state = kCheckAddressState;
|
handle->state = kCheckAddressState;
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait until the data register is ready for transmit. */
|
|
||||||
while ((!(base->S & kI2C_TransferCompleteFlag)) && (--timeout))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Failed to start the transfer. */
|
|
||||||
if (timeout == 0)
|
|
||||||
{
|
|
||||||
return kStatus_I2C_Timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear all status before transfer. */
|
/* Clear all status before transfer. */
|
||||||
I2C_MasterClearStatusFlags(base, kClearFlags);
|
I2C_MasterClearStatusFlags(base, kClearFlags);
|
||||||
|
@ -265,18 +313,19 @@ static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_han
|
||||||
result = kStatus_Success;
|
result = kStatus_Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle Check address state to check the slave address is Acked in slave
|
/* Handle Check address state to check the slave address is Acked in slave
|
||||||
probe application. */
|
probe application. */
|
||||||
if (handle->state == kCheckAddressState)
|
if (handle->state == kCheckAddressState)
|
||||||
{
|
{
|
||||||
if (statusFlags & kI2C_ReceiveNakFlag)
|
if (statusFlags & kI2C_ReceiveNakFlag)
|
||||||
{
|
{
|
||||||
return kStatus_I2C_Nak;
|
result = kStatus_I2C_Addr_Nak;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (handle->transfer.subaddressSize > 0)
|
||||||
|
{
|
||||||
|
handle->state = kSendCommandState;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -292,6 +341,12 @@ static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_han
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* Run state machine. */
|
/* Run state machine. */
|
||||||
switch (handle->state)
|
switch (handle->state)
|
||||||
|
@ -375,6 +430,10 @@ static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_han
|
||||||
{
|
{
|
||||||
result = I2C_MasterStop(base);
|
result = I2C_MasterStop(base);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base->C1 |= I2C_C1_TX_MASK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send NAK at the last receive byte. */
|
/* Send NAK at the last receive byte. */
|
||||||
|
@ -407,6 +466,7 @@ static void I2C_TransferCommonIRQHandler(I2C_Type *base, void *handle)
|
||||||
{
|
{
|
||||||
s_i2cSlaveIsr(base, handle);
|
s_i2cSlaveIsr(base, handle);
|
||||||
}
|
}
|
||||||
|
__DSB();
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz)
|
void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz)
|
||||||
|
@ -415,14 +475,26 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin
|
||||||
|
|
||||||
/* Temporary register for filter read. */
|
/* Temporary register for filter read. */
|
||||||
uint8_t fltReg;
|
uint8_t fltReg;
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
uint8_t c2Reg;
|
|
||||||
#endif
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
||||||
uint8_t s2Reg;
|
uint8_t s2Reg;
|
||||||
#endif
|
#endif
|
||||||
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||||
/* Enable I2C clock. */
|
/* Enable I2C clock. */
|
||||||
CLOCK_EnableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
CLOCK_EnableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
||||||
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||||
|
|
||||||
|
/* Reset the module. */
|
||||||
|
base->A1 = 0;
|
||||||
|
base->F = 0;
|
||||||
|
base->C1 = 0;
|
||||||
|
base->S = 0xFFU;
|
||||||
|
base->C2 = 0;
|
||||||
|
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||||
|
base->FLT = 0x50U;
|
||||||
|
#elif defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT
|
||||||
|
base->FLT = 0x40U;
|
||||||
|
#endif
|
||||||
|
base->RA = 0;
|
||||||
|
|
||||||
/* Disable I2C prior to configuring it. */
|
/* Disable I2C prior to configuring it. */
|
||||||
base->C1 &= ~(I2C_C1_IICEN_MASK);
|
base->C1 &= ~(I2C_C1_IICEN_MASK);
|
||||||
|
@ -433,14 +505,6 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin
|
||||||
/* Configure baud rate. */
|
/* Configure baud rate. */
|
||||||
I2C_MasterSetBaudRate(base, masterConfig->baudRate_Bps, srcClock_Hz);
|
I2C_MasterSetBaudRate(base, masterConfig->baudRate_Bps, srcClock_Hz);
|
||||||
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
/* Configure high drive feature. */
|
|
||||||
c2Reg = base->C2;
|
|
||||||
c2Reg &= ~(I2C_C2_HDRS_MASK);
|
|
||||||
c2Reg |= I2C_C2_HDRS(masterConfig->enableHighDrive);
|
|
||||||
base->C2 = c2Reg;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Read out the FLT register. */
|
/* Read out the FLT register. */
|
||||||
fltReg = base->FLT;
|
fltReg = base->FLT;
|
||||||
|
|
||||||
|
@ -472,8 +536,10 @@ void I2C_MasterDeinit(I2C_Type *base)
|
||||||
/* Disable I2C module. */
|
/* Disable I2C module. */
|
||||||
I2C_Enable(base, false);
|
I2C_Enable(base, false);
|
||||||
|
|
||||||
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||||
/* Disable I2C clock. */
|
/* Disable I2C clock. */
|
||||||
CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
||||||
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig)
|
void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig)
|
||||||
|
@ -483,11 +549,6 @@ void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig)
|
||||||
/* Default baud rate at 100kbps. */
|
/* Default baud rate at 100kbps. */
|
||||||
masterConfig->baudRate_Bps = 100000U;
|
masterConfig->baudRate_Bps = 100000U;
|
||||||
|
|
||||||
/* Default pin high drive is disabled. */
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
masterConfig->enableHighDrive = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Default stop hold enable is disabled. */
|
/* Default stop hold enable is disabled. */
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF
|
#if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF
|
||||||
masterConfig->enableStopHold = false;
|
masterConfig->enableStopHold = false;
|
||||||
|
@ -654,7 +715,7 @@ status_t I2C_MasterRepeatedStart(I2C_Type *base, uint8_t address, i2c_direction_
|
||||||
base->F = savedMult & (~I2C_F_MULT_MASK);
|
base->F = savedMult & (~I2C_F_MULT_MASK);
|
||||||
|
|
||||||
/* We are already in a transfer, so send a repeated start. */
|
/* We are already in a transfer, so send a repeated start. */
|
||||||
base->C1 |= I2C_C1_RSTA_MASK;
|
base->C1 |= I2C_C1_RSTA_MASK | I2C_C1_TX_MASK;
|
||||||
|
|
||||||
/* Restore the multiplier factor. */
|
/* Restore the multiplier factor. */
|
||||||
base->F = savedMult;
|
base->F = savedMult;
|
||||||
|
@ -721,7 +782,7 @@ uint32_t I2C_MasterGetStatusFlags(I2C_Type *base)
|
||||||
return statusFlags;
|
return statusFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize)
|
status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize, uint32_t flags)
|
||||||
{
|
{
|
||||||
status_t result = kStatus_Success;
|
status_t result = kStatus_Success;
|
||||||
uint8_t statusFlags = 0;
|
uint8_t statusFlags = 0;
|
||||||
|
@ -772,10 +833,19 @@ status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (((result == kStatus_Success) && (!(flags & kI2C_TransferNoStopFlag))) || (result == kStatus_I2C_Nak))
|
||||||
|
{
|
||||||
|
/* Clear the IICIF flag. */
|
||||||
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
|
/* Send stop. */
|
||||||
|
result = I2C_MasterStop(base);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize)
|
status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize, uint32_t flags)
|
||||||
{
|
{
|
||||||
status_t result = kStatus_Success;
|
status_t result = kStatus_Success;
|
||||||
volatile uint8_t dummy = 0;
|
volatile uint8_t dummy = 0;
|
||||||
|
@ -817,9 +887,17 @@ status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize)
|
||||||
/* Single byte use case. */
|
/* Single byte use case. */
|
||||||
if (rxSize == 0)
|
if (rxSize == 0)
|
||||||
{
|
{
|
||||||
/* Read the final byte. */
|
if (!(flags & kI2C_TransferNoStopFlag))
|
||||||
|
{
|
||||||
|
/* Issue STOP command before reading last byte. */
|
||||||
result = I2C_MasterStop(base);
|
result = I2C_MasterStop(base);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Change direction to Tx to avoid extra clocks. */
|
||||||
|
base->C1 |= I2C_C1_TX_MASK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (rxSize == 1)
|
if (rxSize == 1)
|
||||||
{
|
{
|
||||||
|
@ -871,19 +949,42 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if there's transfer error. */
|
||||||
|
result = I2C_CheckAndClearError(base, base->S);
|
||||||
|
|
||||||
|
/* Return if error. */
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
if (result == kStatus_I2C_Nak)
|
||||||
|
{
|
||||||
|
result = kStatus_I2C_Addr_Nak;
|
||||||
|
|
||||||
|
I2C_MasterStop(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* Send subaddress. */
|
/* Send subaddress. */
|
||||||
if (xfer->subaddressSize)
|
if (xfer->subaddressSize)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
/* Clear interrupt pending flag. */
|
||||||
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
|
xfer->subaddressSize--;
|
||||||
|
base->D = ((xfer->subaddress) >> (8 * xfer->subaddressSize));
|
||||||
|
|
||||||
/* Wait until data transfer complete. */
|
/* Wait until data transfer complete. */
|
||||||
while (!(base->S & kI2C_IntPendingFlag))
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear interrupt pending flag. */
|
|
||||||
base->S = kI2C_IntPendingFlag;
|
|
||||||
|
|
||||||
/* Check if there's transfer error. */
|
/* Check if there's transfer error. */
|
||||||
result = I2C_CheckAndClearError(base, base->S);
|
result = I2C_CheckAndClearError(base, base->S);
|
||||||
|
|
||||||
|
@ -897,34 +998,13 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
xfer->subaddressSize--;
|
|
||||||
base->D = ((xfer->subaddress) >> (8 * xfer->subaddressSize));
|
|
||||||
|
|
||||||
} while ((xfer->subaddressSize > 0) && (result == kStatus_Success));
|
} while ((xfer->subaddressSize > 0) && (result == kStatus_Success));
|
||||||
|
|
||||||
if (xfer->direction == kI2C_Read)
|
if (xfer->direction == kI2C_Read)
|
||||||
{
|
{
|
||||||
/* Wait until data transfer complete. */
|
|
||||||
while (!(base->S & kI2C_IntPendingFlag))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear pending flag. */
|
/* Clear pending flag. */
|
||||||
base->S = kI2C_IntPendingFlag;
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
/* Check if there's transfer error. */
|
|
||||||
result = I2C_CheckAndClearError(base, base->S);
|
|
||||||
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
if (result == kStatus_I2C_Nak)
|
|
||||||
{
|
|
||||||
I2C_MasterStop(base);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send repeated start and slave address. */
|
/* Send repeated start and slave address. */
|
||||||
result = I2C_MasterRepeatedStart(base, xfer->slaveAddress, kI2C_Read);
|
result = I2C_MasterRepeatedStart(base, xfer->slaveAddress, kI2C_Read);
|
||||||
|
|
||||||
|
@ -933,10 +1013,8 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait until address + command transfer complete. */
|
/* Wait until data transfer complete. */
|
||||||
while (!(base->S & kI2C_IntPendingFlag))
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -944,37 +1022,31 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
|
||||||
/* Check if there's transfer error. */
|
/* Check if there's transfer error. */
|
||||||
result = I2C_CheckAndClearError(base, base->S);
|
result = I2C_CheckAndClearError(base, base->S);
|
||||||
|
|
||||||
/* Return if error. */
|
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
if (result == kStatus_I2C_Nak)
|
if (result == kStatus_I2C_Nak)
|
||||||
{
|
{
|
||||||
|
result = kStatus_I2C_Addr_Nak;
|
||||||
|
|
||||||
I2C_MasterStop(base);
|
I2C_MasterStop(base);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Transmit data. */
|
/* Transmit data. */
|
||||||
if ((xfer->direction == kI2C_Write) && (xfer->dataSize > 0))
|
if ((xfer->direction == kI2C_Write) && (xfer->dataSize > 0))
|
||||||
{
|
{
|
||||||
/* Send Data. */
|
/* Send Data. */
|
||||||
result = I2C_MasterWriteBlocking(base, xfer->data, xfer->dataSize);
|
result = I2C_MasterWriteBlocking(base, xfer->data, xfer->dataSize, xfer->flags);
|
||||||
|
|
||||||
if (((result == kStatus_Success) && (!(xfer->flags & kI2C_TransferNoStopFlag))) || (result == kStatus_I2C_Nak))
|
|
||||||
{
|
|
||||||
/* Clear the IICIF flag. */
|
|
||||||
base->S = kI2C_IntPendingFlag;
|
|
||||||
|
|
||||||
/* Send stop. */
|
|
||||||
result = I2C_MasterStop(base);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Receive Data. */
|
/* Receive Data. */
|
||||||
if ((xfer->direction == kI2C_Read) && (xfer->dataSize > 0))
|
if ((xfer->direction == kI2C_Read) && (xfer->dataSize > 0))
|
||||||
{
|
{
|
||||||
result = I2C_MasterReadBlocking(base, xfer->data, xfer->dataSize);
|
result = I2C_MasterReadBlocking(base, xfer->data, xfer->dataSize, xfer->flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -1037,11 +1109,37 @@ void I2C_MasterTransferAbort(I2C_Type *base, i2c_master_handle_t *handle)
|
||||||
{
|
{
|
||||||
assert(handle);
|
assert(handle);
|
||||||
|
|
||||||
|
volatile uint8_t dummy = 0;
|
||||||
|
|
||||||
|
/* Add this to avoid build warning. */
|
||||||
|
dummy++;
|
||||||
|
|
||||||
/* Disable interrupt. */
|
/* Disable interrupt. */
|
||||||
I2C_DisableInterrupts(base, kI2C_GlobalInterruptEnable);
|
I2C_DisableInterrupts(base, kI2C_GlobalInterruptEnable);
|
||||||
|
|
||||||
/* Reset the state to idle. */
|
/* Reset the state to idle. */
|
||||||
handle->state = kIdleState;
|
handle->state = kIdleState;
|
||||||
|
|
||||||
|
/* Send STOP signal. */
|
||||||
|
if (handle->transfer.direction == kI2C_Read)
|
||||||
|
{
|
||||||
|
base->C1 |= I2C_C1_TXAK_MASK;
|
||||||
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
|
base->C1 &= ~(I2C_C1_MST_MASK | I2C_C1_TX_MASK | I2C_C1_TXAK_MASK);
|
||||||
|
dummy = base->D;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
base->C1 &= ~(I2C_C1_MST_MASK | I2C_C1_TX_MASK | I2C_C1_TXAK_MASK);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t I2C_MasterTransferGetCount(I2C_Type *base, i2c_master_handle_t *handle, size_t *count)
|
status_t I2C_MasterTransferGetCount(I2C_Type *base, i2c_master_handle_t *handle, size_t *count)
|
||||||
|
@ -1075,7 +1173,8 @@ void I2C_MasterTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
if (isDone || result)
|
if (isDone || result)
|
||||||
{
|
{
|
||||||
/* Send stop command if transfer done or received Nak. */
|
/* Send stop command if transfer done or received Nak. */
|
||||||
if ((!(handle->transfer.flags & kI2C_TransferNoStopFlag)) || (result == kStatus_I2C_Nak))
|
if ((!(handle->transfer.flags & kI2C_TransferNoStopFlag)) || (result == kStatus_I2C_Nak) ||
|
||||||
|
(result == kStatus_I2C_Addr_Nak))
|
||||||
{
|
{
|
||||||
/* Ensure stop command is a need. */
|
/* Ensure stop command is a need. */
|
||||||
if ((base->C1 & I2C_C1_MST_MASK))
|
if ((base->C1 & I2C_C1_MST_MASK))
|
||||||
|
@ -1101,13 +1200,28 @@ void I2C_MasterTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig)
|
void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig, uint32_t srcClock_Hz)
|
||||||
{
|
{
|
||||||
assert(slaveConfig);
|
assert(slaveConfig);
|
||||||
|
|
||||||
uint8_t tmpReg;
|
uint8_t tmpReg;
|
||||||
|
|
||||||
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||||
CLOCK_EnableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
CLOCK_EnableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
||||||
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||||
|
|
||||||
|
/* Reset the module. */
|
||||||
|
base->A1 = 0;
|
||||||
|
base->F = 0;
|
||||||
|
base->C1 = 0;
|
||||||
|
base->S = 0xFFU;
|
||||||
|
base->C2 = 0;
|
||||||
|
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||||
|
base->FLT = 0x50U;
|
||||||
|
#elif defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT
|
||||||
|
base->FLT = 0x40U;
|
||||||
|
#endif
|
||||||
|
base->RA = 0;
|
||||||
|
|
||||||
/* Configure addressing mode. */
|
/* Configure addressing mode. */
|
||||||
switch (slaveConfig->addressingMode)
|
switch (slaveConfig->addressingMode)
|
||||||
|
@ -1132,14 +1246,10 @@ void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig)
|
||||||
tmpReg &= ~I2C_C1_WUEN_MASK;
|
tmpReg &= ~I2C_C1_WUEN_MASK;
|
||||||
base->C1 = tmpReg | I2C_C1_WUEN(slaveConfig->enableWakeUp) | I2C_C1_IICEN(slaveConfig->enableSlave);
|
base->C1 = tmpReg | I2C_C1_WUEN(slaveConfig->enableWakeUp) | I2C_C1_IICEN(slaveConfig->enableSlave);
|
||||||
|
|
||||||
/* Configure general call & baud rate control & high drive feature. */
|
/* Configure general call & baud rate control. */
|
||||||
tmpReg = base->C2;
|
tmpReg = base->C2;
|
||||||
tmpReg &= ~(I2C_C2_SBRC_MASK | I2C_C2_GCAEN_MASK);
|
tmpReg &= ~(I2C_C2_SBRC_MASK | I2C_C2_GCAEN_MASK);
|
||||||
tmpReg |= I2C_C2_SBRC(slaveConfig->enableBaudRateCtl) | I2C_C2_GCAEN(slaveConfig->enableGeneralCall);
|
tmpReg |= I2C_C2_SBRC(slaveConfig->enableBaudRateCtl) | I2C_C2_GCAEN(slaveConfig->enableGeneralCall);
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
tmpReg &= ~I2C_C2_HDRS_MASK;
|
|
||||||
tmpReg |= I2C_C2_HDRS(slaveConfig->enableHighDrive);
|
|
||||||
#endif
|
|
||||||
base->C2 = tmpReg;
|
base->C2 = tmpReg;
|
||||||
|
|
||||||
/* Enable/Disable double buffering. */
|
/* Enable/Disable double buffering. */
|
||||||
|
@ -1147,6 +1257,9 @@ void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig)
|
||||||
tmpReg = base->S2 & (~I2C_S2_DFEN_MASK);
|
tmpReg = base->S2 & (~I2C_S2_DFEN_MASK);
|
||||||
base->S2 = tmpReg | I2C_S2_DFEN(slaveConfig->enableDoubleBuffering);
|
base->S2 = tmpReg | I2C_S2_DFEN(slaveConfig->enableDoubleBuffering);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Set hold time. */
|
||||||
|
I2C_SetHoldTime(base, slaveConfig->sclStopHoldTime_ns, srcClock_Hz);
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2C_SlaveDeinit(I2C_Type *base)
|
void I2C_SlaveDeinit(I2C_Type *base)
|
||||||
|
@ -1154,8 +1267,10 @@ void I2C_SlaveDeinit(I2C_Type *base)
|
||||||
/* Disable I2C module. */
|
/* Disable I2C module. */
|
||||||
I2C_Enable(base, false);
|
I2C_Enable(base, false);
|
||||||
|
|
||||||
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||||
/* Disable I2C clock. */
|
/* Disable I2C clock. */
|
||||||
CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
||||||
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig)
|
void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig)
|
||||||
|
@ -1171,11 +1286,6 @@ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig)
|
||||||
/* Slave address match waking up MCU from low power mode is disabled. */
|
/* Slave address match waking up MCU from low power mode is disabled. */
|
||||||
slaveConfig->enableWakeUp = false;
|
slaveConfig->enableWakeUp = false;
|
||||||
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
/* Default pin high drive is disabled. */
|
|
||||||
slaveConfig->enableHighDrive = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Independent slave mode baud rate at maximum frequency is disabled. */
|
/* Independent slave mode baud rate at maximum frequency is disabled. */
|
||||||
slaveConfig->enableBaudRateCtl = false;
|
slaveConfig->enableBaudRateCtl = false;
|
||||||
|
|
||||||
|
@ -1184,6 +1294,9 @@ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig)
|
||||||
slaveConfig->enableDoubleBuffering = true;
|
slaveConfig->enableDoubleBuffering = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Set default SCL stop hold time to 4us which is minimum requirement in I2C spec. */
|
||||||
|
slaveConfig->sclStopHoldTime_ns = 4000;
|
||||||
|
|
||||||
/* Enable the I2C peripheral. */
|
/* Enable the I2C peripheral. */
|
||||||
slaveConfig->enableSlave = true;
|
slaveConfig->enableSlave = true;
|
||||||
}
|
}
|
||||||
|
@ -1215,7 +1328,7 @@ status_t I2C_SlaveWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t tx
|
||||||
/* Read dummy to release bus. */
|
/* Read dummy to release bus. */
|
||||||
dummy = base->D;
|
dummy = base->D;
|
||||||
|
|
||||||
result = I2C_MasterWriteBlocking(base, txBuff, txSize);
|
result = I2C_MasterWriteBlocking(base, txBuff, txSize, kI2C_TransferDefaultFlag);
|
||||||
|
|
||||||
/* Switch to receive mode. */
|
/* Switch to receive mode. */
|
||||||
base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK);
|
base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK);
|
||||||
|
@ -1323,7 +1436,7 @@ status_t I2C_SlaveTransferNonBlocking(I2C_Type *base, i2c_slave_handle_t *handle
|
||||||
handle->isBusy = true;
|
handle->isBusy = true;
|
||||||
|
|
||||||
/* Set up event mask. tx and rx are always enabled. */
|
/* Set up event mask. tx and rx are always enabled. */
|
||||||
handle->eventMask = eventMask | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent;
|
handle->eventMask = eventMask | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent | kI2C_SlaveGenaralcallEvent;
|
||||||
|
|
||||||
/* Clear all flags. */
|
/* Clear all flags. */
|
||||||
I2C_SlaveClearStatusFlags(base, kClearFlags);
|
I2C_SlaveClearStatusFlags(base, kClearFlags);
|
||||||
|
@ -1412,8 +1525,11 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(status & kI2C_AddressMatchFlag))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif /* I2C_HAS_STOP_DETECT */
|
#endif /* I2C_HAS_STOP_DETECT */
|
||||||
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||||
|
@ -1482,11 +1598,6 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
handle->isBusy = true;
|
handle->isBusy = true;
|
||||||
xfer->event = kI2C_SlaveAddressMatchEvent;
|
xfer->event = kI2C_SlaveAddressMatchEvent;
|
||||||
|
|
||||||
if ((handle->eventMask & xfer->event) && (handle->callback))
|
|
||||||
{
|
|
||||||
handle->callback(base, xfer, handle->userData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Slave transmit, master reading from slave. */
|
/* Slave transmit, master reading from slave. */
|
||||||
if (status & kI2C_TransferDirectionFlag)
|
if (status & kI2C_TransferDirectionFlag)
|
||||||
{
|
{
|
||||||
|
@ -1502,6 +1613,16 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
|
|
||||||
/* Read dummy to release the bus. */
|
/* Read dummy to release the bus. */
|
||||||
dummy = base->D;
|
dummy = base->D;
|
||||||
|
|
||||||
|
if (dummy == 0)
|
||||||
|
{
|
||||||
|
xfer->event = kI2C_SlaveGenaralcallEvent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((handle->eventMask & xfer->event) && (handle->callback))
|
||||||
|
{
|
||||||
|
handle->callback(base, xfer, handle->userData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Check transfer complete flag. */
|
/* Check transfer complete flag. */
|
||||||
|
@ -1607,27 +1728,30 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(I2C0)
|
||||||
void I2C0_DriverIRQHandler(void)
|
void I2C0_DriverIRQHandler(void)
|
||||||
{
|
{
|
||||||
I2C_TransferCommonIRQHandler(I2C0, s_i2cHandle[0]);
|
I2C_TransferCommonIRQHandler(I2C0, s_i2cHandle[0]);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (FSL_FEATURE_SOC_I2C_COUNT > 1)
|
#if defined(I2C1)
|
||||||
void I2C1_DriverIRQHandler(void)
|
void I2C1_DriverIRQHandler(void)
|
||||||
{
|
{
|
||||||
I2C_TransferCommonIRQHandler(I2C1, s_i2cHandle[1]);
|
I2C_TransferCommonIRQHandler(I2C1, s_i2cHandle[1]);
|
||||||
}
|
}
|
||||||
#endif /* I2C COUNT > 1 */
|
#endif
|
||||||
|
|
||||||
#if (FSL_FEATURE_SOC_I2C_COUNT > 2)
|
#if defined(I2C2)
|
||||||
void I2C2_DriverIRQHandler(void)
|
void I2C2_DriverIRQHandler(void)
|
||||||
{
|
{
|
||||||
I2C_TransferCommonIRQHandler(I2C2, s_i2cHandle[2]);
|
I2C_TransferCommonIRQHandler(I2C2, s_i2cHandle[2]);
|
||||||
}
|
}
|
||||||
#endif /* I2C COUNT > 2 */
|
#endif
|
||||||
#if (FSL_FEATURE_SOC_I2C_COUNT > 3)
|
|
||||||
|
#if defined(I2C3)
|
||||||
void I2C3_DriverIRQHandler(void)
|
void I2C3_DriverIRQHandler(void)
|
||||||
{
|
{
|
||||||
I2C_TransferCommonIRQHandler(I2C3, s_i2cHandle[3]);
|
I2C_TransferCommonIRQHandler(I2C3, s_i2cHandle[3]);
|
||||||
}
|
}
|
||||||
#endif /* I2C COUNT > 3 */
|
#endif
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||||
* All rights reserved.
|
* Copyright 2016-2017 NXP
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
* other materials provided with the distribution.
|
* other materials provided with the distribution.
|
||||||
*
|
*
|
||||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
* o Neither the name of the copyright holder nor the names of its
|
||||||
* contributors may be used to endorse or promote products derived from this
|
* contributors may be used to endorse or promote products derived from this
|
||||||
* software without specific prior written permission.
|
* software without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -37,15 +37,14 @@
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Definitions
|
* Definitions
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
/*! @name Driver version */
|
/*! @name Driver version */
|
||||||
/*@{*/
|
/*@{*/
|
||||||
/*! @brief I2C driver version 2.0.1. */
|
/*! @brief I2C driver version 2.0.3. */
|
||||||
#define FSL_I2C_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))
|
#define FSL_I2C_DRIVER_VERSION (MAKE_VERSION(2, 0, 3))
|
||||||
/*@}*/
|
/*@}*/
|
||||||
|
|
||||||
#if (defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT || \
|
#if (defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT || \
|
||||||
|
@ -61,6 +60,7 @@ enum _i2c_status
|
||||||
kStatus_I2C_Nak = MAKE_STATUS(kStatusGroup_I2C, 2), /*!< NAK received during transfer. */
|
kStatus_I2C_Nak = MAKE_STATUS(kStatusGroup_I2C, 2), /*!< NAK received during transfer. */
|
||||||
kStatus_I2C_ArbitrationLost = MAKE_STATUS(kStatusGroup_I2C, 3), /*!< Arbitration lost during transfer. */
|
kStatus_I2C_ArbitrationLost = MAKE_STATUS(kStatusGroup_I2C, 3), /*!< Arbitration lost during transfer. */
|
||||||
kStatus_I2C_Timeout = MAKE_STATUS(kStatusGroup_I2C, 4), /*!< Wait event timeout. */
|
kStatus_I2C_Timeout = MAKE_STATUS(kStatusGroup_I2C, 4), /*!< Wait event timeout. */
|
||||||
|
kStatus_I2C_Addr_Nak = MAKE_STATUS(kStatusGroup_I2C, 5), /*!< NAK received during the address probe. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -108,11 +108,11 @@ enum _i2c_interrupt_enable
|
||||||
#endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */
|
#endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! @brief Direction of master and slave transfers. */
|
/*! @brief The direction of master and slave transfers. */
|
||||||
typedef enum _i2c_direction
|
typedef enum _i2c_direction
|
||||||
{
|
{
|
||||||
kI2C_Write = 0x0U, /*!< Master transmit to slave. */
|
kI2C_Write = 0x0U, /*!< Master transmits to the slave. */
|
||||||
kI2C_Read = 0x1U, /*!< Master receive from slave. */
|
kI2C_Read = 0x1U, /*!< Master receives from the slave. */
|
||||||
} i2c_direction_t;
|
} i2c_direction_t;
|
||||||
|
|
||||||
/*! @brief Addressing mode. */
|
/*! @brief Addressing mode. */
|
||||||
|
@ -125,17 +125,17 @@ typedef enum _i2c_slave_address_mode
|
||||||
/*! @brief I2C transfer control flag. */
|
/*! @brief I2C transfer control flag. */
|
||||||
enum _i2c_master_transfer_flags
|
enum _i2c_master_transfer_flags
|
||||||
{
|
{
|
||||||
kI2C_TransferDefaultFlag = 0x0U, /*!< Transfer starts with a start signal, stops with a stop signal. */
|
kI2C_TransferDefaultFlag = 0x0U, /*!< A transfer starts with a start signal, stops with a stop signal. */
|
||||||
kI2C_TransferNoStartFlag = 0x1U, /*!< Transfer starts without a start signal. */
|
kI2C_TransferNoStartFlag = 0x1U, /*!< A transfer starts without a start signal. */
|
||||||
kI2C_TransferRepeatedStartFlag = 0x2U, /*!< Transfer starts with a repeated start signal. */
|
kI2C_TransferRepeatedStartFlag = 0x2U, /*!< A transfer starts with a repeated start signal. */
|
||||||
kI2C_TransferNoStopFlag = 0x4U, /*!< Transfer ends without a stop signal. */
|
kI2C_TransferNoStopFlag = 0x4U, /*!< A transfer ends without a stop signal. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Set of events sent to the callback for nonblocking slave transfers.
|
* @brief Set of events sent to the callback for nonblocking slave transfers.
|
||||||
*
|
*
|
||||||
* These event enumerations are used for two related purposes. First, a bit mask created by OR'ing together
|
* These event enumerations are used for two related purposes. First, a bit mask created by OR'ing together
|
||||||
* events is passed to I2C_SlaveTransferNonBlocking() in order to specify which events to enable.
|
* events is passed to I2C_SlaveTransferNonBlocking() to specify which events to enable.
|
||||||
* Then, when the slave callback is invoked, it is passed the current event through its @a transfer
|
* Then, when the slave callback is invoked, it is passed the current event through its @a transfer
|
||||||
* parameter.
|
* parameter.
|
||||||
*
|
*
|
||||||
|
@ -144,36 +144,34 @@ enum _i2c_master_transfer_flags
|
||||||
typedef enum _i2c_slave_transfer_event
|
typedef enum _i2c_slave_transfer_event
|
||||||
{
|
{
|
||||||
kI2C_SlaveAddressMatchEvent = 0x01U, /*!< Received the slave address after a start or repeated start. */
|
kI2C_SlaveAddressMatchEvent = 0x01U, /*!< Received the slave address after a start or repeated start. */
|
||||||
kI2C_SlaveTransmitEvent = 0x02U, /*!< Callback is requested to provide data to transmit
|
kI2C_SlaveTransmitEvent = 0x02U, /*!< A callback is requested to provide data to transmit
|
||||||
(slave-transmitter role). */
|
(slave-transmitter role). */
|
||||||
kI2C_SlaveReceiveEvent = 0x04U, /*!< Callback is requested to provide a buffer in which to place received
|
kI2C_SlaveReceiveEvent = 0x04U, /*!< A callback is requested to provide a buffer in which to place received
|
||||||
data (slave-receiver role). */
|
data (slave-receiver role). */
|
||||||
kI2C_SlaveTransmitAckEvent = 0x08U, /*!< Callback needs to either transmit an ACK or NACK. */
|
kI2C_SlaveTransmitAckEvent = 0x08U, /*!< A callback needs to either transmit an ACK or NACK. */
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||||
kI2C_SlaveStartEvent = 0x10U, /*!< A start/repeated start was detected. */
|
kI2C_SlaveStartEvent = 0x10U, /*!< A start/repeated start was detected. */
|
||||||
#endif
|
#endif
|
||||||
kI2C_SlaveCompletionEvent = 0x20U, /*!< A stop was detected or finished transfer, completing the transfer. */
|
kI2C_SlaveCompletionEvent = 0x20U, /*!< A stop was detected or finished transfer, completing the transfer. */
|
||||||
|
kI2C_SlaveGenaralcallEvent = 0x40U, /*!< Received the general call address after a start or repeated start. */
|
||||||
|
|
||||||
/*! Bit mask of all available events. */
|
/*! A bit mask of all available events. */
|
||||||
kI2C_SlaveAllEvents = kI2C_SlaveAddressMatchEvent | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent |
|
kI2C_SlaveAllEvents = kI2C_SlaveAddressMatchEvent | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent |
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||||
kI2C_SlaveStartEvent |
|
kI2C_SlaveStartEvent |
|
||||||
#endif
|
#endif
|
||||||
kI2C_SlaveCompletionEvent,
|
kI2C_SlaveCompletionEvent | kI2C_SlaveGenaralcallEvent,
|
||||||
} i2c_slave_transfer_event_t;
|
} i2c_slave_transfer_event_t;
|
||||||
|
|
||||||
/*! @brief I2C master user configuration. */
|
/*! @brief I2C master user configuration. */
|
||||||
typedef struct _i2c_master_config
|
typedef struct _i2c_master_config
|
||||||
{
|
{
|
||||||
bool enableMaster; /*!< Enables the I2C peripheral at initialization time. */
|
bool enableMaster; /*!< Enables the I2C peripheral at initialization time. */
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
bool enableHighDrive; /*!< Controls the drive capability of the I2C pads. */
|
|
||||||
#endif
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF
|
#if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF
|
||||||
bool enableStopHold; /*!< Controls the stop hold enable. */
|
bool enableStopHold; /*!< Controls the stop hold enable. */
|
||||||
#endif
|
#endif
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
||||||
bool enableDoubleBuffering; /*!< Controls double buffer enable, notice that
|
bool enableDoubleBuffering; /*!< Controls double buffer enable; notice that
|
||||||
enabling the double buffer disables the clock stretch. */
|
enabling the double buffer disables the clock stretch. */
|
||||||
#endif
|
#endif
|
||||||
uint32_t baudRate_Bps; /*!< Baud rate configuration of I2C peripheral. */
|
uint32_t baudRate_Bps; /*!< Baud rate configuration of I2C peripheral. */
|
||||||
|
@ -184,19 +182,20 @@ typedef struct _i2c_master_config
|
||||||
typedef struct _i2c_slave_config
|
typedef struct _i2c_slave_config
|
||||||
{
|
{
|
||||||
bool enableSlave; /*!< Enables the I2C peripheral at initialization time. */
|
bool enableSlave; /*!< Enables the I2C peripheral at initialization time. */
|
||||||
bool enableGeneralCall; /*!< Enable general call addressing mode. */
|
bool enableGeneralCall; /*!< Enables the general call addressing mode. */
|
||||||
bool enableWakeUp; /*!< Enables/disables waking up MCU from low-power mode. */
|
bool enableWakeUp; /*!< Enables/disables waking up MCU from low-power mode. */
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
bool enableHighDrive; /*!< Controls the drive capability of the I2C pads. */
|
|
||||||
#endif
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
||||||
bool enableDoubleBuffering; /*!< Controls double buffer enable, notice that
|
bool enableDoubleBuffering; /*!< Controls a double buffer enable; notice that
|
||||||
enabling the double buffer disables the clock stretch. */
|
enabling the double buffer disables the clock stretch. */
|
||||||
#endif
|
#endif
|
||||||
bool enableBaudRateCtl; /*!< Enables/disables independent slave baud rate on SCL in very fast I2C modes. */
|
bool enableBaudRateCtl; /*!< Enables/disables independent slave baud rate on SCL in very fast I2C modes. */
|
||||||
uint16_t slaveAddress; /*!< Slave address configuration. */
|
uint16_t slaveAddress; /*!< A slave address configuration. */
|
||||||
uint16_t upperAddress; /*!< Maximum boundary slave address used in range matching mode. */
|
uint16_t upperAddress; /*!< A maximum boundary slave address used in a range matching mode. */
|
||||||
i2c_slave_address_mode_t addressingMode; /*!< Addressing mode configuration of i2c_slave_address_mode_config_t. */
|
i2c_slave_address_mode_t
|
||||||
|
addressingMode; /*!< An addressing mode configuration of i2c_slave_address_mode_config_t. */
|
||||||
|
uint32_t sclStopHoldTime_ns; /*!< the delay from the rising edge of SCL (I2C clock) to the rising edge of SDA (I2C
|
||||||
|
data) while SCL is high (stop condition), SDA hold time and SCL start hold time
|
||||||
|
are also configured according to the SCL stop hold time. */
|
||||||
} i2c_slave_config_t;
|
} i2c_slave_config_t;
|
||||||
|
|
||||||
/*! @brief I2C master handle typedef. */
|
/*! @brief I2C master handle typedef. */
|
||||||
|
@ -214,13 +213,13 @@ typedef struct _i2c_slave_handle i2c_slave_handle_t;
|
||||||
/*! @brief I2C master transfer structure. */
|
/*! @brief I2C master transfer structure. */
|
||||||
typedef struct _i2c_master_transfer
|
typedef struct _i2c_master_transfer
|
||||||
{
|
{
|
||||||
uint32_t flags; /*!< Transfer flag which controls the transfer. */
|
uint32_t flags; /*!< A transfer flag which controls the transfer. */
|
||||||
uint8_t slaveAddress; /*!< 7-bit slave address. */
|
uint8_t slaveAddress; /*!< 7-bit slave address. */
|
||||||
i2c_direction_t direction; /*!< Transfer direction, read or write. */
|
i2c_direction_t direction; /*!< A transfer direction, read or write. */
|
||||||
uint32_t subaddress; /*!< Sub address. Transferred MSB first. */
|
uint32_t subaddress; /*!< A sub address. Transferred MSB first. */
|
||||||
uint8_t subaddressSize; /*!< Size of command buffer. */
|
uint8_t subaddressSize; /*!< A size of the command buffer. */
|
||||||
uint8_t *volatile data; /*!< Transfer buffer. */
|
uint8_t *volatile data; /*!< A transfer buffer. */
|
||||||
volatile size_t dataSize; /*!< Transfer size. */
|
volatile size_t dataSize; /*!< A transfer size. */
|
||||||
} i2c_master_transfer_t;
|
} i2c_master_transfer_t;
|
||||||
|
|
||||||
/*! @brief I2C master handle structure. */
|
/*! @brief I2C master handle structure. */
|
||||||
|
@ -228,20 +227,21 @@ struct _i2c_master_handle
|
||||||
{
|
{
|
||||||
i2c_master_transfer_t transfer; /*!< I2C master transfer copy. */
|
i2c_master_transfer_t transfer; /*!< I2C master transfer copy. */
|
||||||
size_t transferSize; /*!< Total bytes to be transferred. */
|
size_t transferSize; /*!< Total bytes to be transferred. */
|
||||||
uint8_t state; /*!< Transfer state maintained during transfer. */
|
uint8_t state; /*!< A transfer state maintained during transfer. */
|
||||||
i2c_master_transfer_callback_t completionCallback; /*!< Callback function called when transfer finished. */
|
i2c_master_transfer_callback_t completionCallback; /*!< A callback function called when the transfer is finished. */
|
||||||
void *userData; /*!< Callback parameter passed to callback function. */
|
void *userData; /*!< A callback parameter passed to the callback function. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! @brief I2C slave transfer structure. */
|
/*! @brief I2C slave transfer structure. */
|
||||||
typedef struct _i2c_slave_transfer
|
typedef struct _i2c_slave_transfer
|
||||||
{
|
{
|
||||||
i2c_slave_transfer_event_t event; /*!< Reason the callback is being invoked. */
|
i2c_slave_transfer_event_t event; /*!< A reason that the callback is invoked. */
|
||||||
uint8_t *volatile data; /*!< Transfer buffer. */
|
uint8_t *volatile data; /*!< A transfer buffer. */
|
||||||
volatile size_t dataSize; /*!< Transfer size. */
|
volatile size_t dataSize; /*!< A transfer size. */
|
||||||
status_t completionStatus; /*!< Success or error code describing how the transfer completed. Only applies for
|
status_t completionStatus; /*!< Success or error code describing how the transfer completed. Only applies for
|
||||||
#kI2C_SlaveCompletionEvent. */
|
#kI2C_SlaveCompletionEvent. */
|
||||||
size_t transferredCount; /*!< Number of bytes actually transferred since start or last repeated start. */
|
size_t transferredCount; /*!< A number of bytes actually transferred since the start or since the last repeated
|
||||||
|
start. */
|
||||||
} i2c_slave_transfer_t;
|
} i2c_slave_transfer_t;
|
||||||
|
|
||||||
/*! @brief I2C slave transfer callback typedef. */
|
/*! @brief I2C slave transfer callback typedef. */
|
||||||
|
@ -250,11 +250,11 @@ typedef void (*i2c_slave_transfer_callback_t)(I2C_Type *base, i2c_slave_transfer
|
||||||
/*! @brief I2C slave handle structure. */
|
/*! @brief I2C slave handle structure. */
|
||||||
struct _i2c_slave_handle
|
struct _i2c_slave_handle
|
||||||
{
|
{
|
||||||
bool isBusy; /*!< Whether transfer is busy. */
|
volatile bool isBusy; /*!< Indicates whether a transfer is busy. */
|
||||||
i2c_slave_transfer_t transfer; /*!< I2C slave transfer copy. */
|
i2c_slave_transfer_t transfer; /*!< I2C slave transfer copy. */
|
||||||
uint32_t eventMask; /*!< Mask of enabled events. */
|
uint32_t eventMask; /*!< A mask of enabled events. */
|
||||||
i2c_slave_transfer_callback_t callback; /*!< Callback function called at transfer event. */
|
i2c_slave_transfer_callback_t callback; /*!< A callback function called at the transfer event. */
|
||||||
void *userData; /*!< Callback parameter passed to callback. */
|
void *userData; /*!< A callback parameter passed to the callback. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
@ -274,12 +274,12 @@ extern "C" {
|
||||||
* @brief Initializes the I2C peripheral. Call this API to ungate the I2C clock
|
* @brief Initializes the I2C peripheral. Call this API to ungate the I2C clock
|
||||||
* and configure the I2C with master configuration.
|
* and configure the I2C with master configuration.
|
||||||
*
|
*
|
||||||
* @note This API should be called at the beginning of the application to use
|
* @note This API should be called at the beginning of the application.
|
||||||
* the I2C driver, or any operation to the I2C module may cause a hard fault
|
* Otherwise, any operation to the I2C module can cause a hard fault
|
||||||
* because clock is not enabled. The configuration structure can be filled by user
|
* because the clock is not enabled. The configuration structure can be custom filled
|
||||||
* from scratch, or be set with default values by I2C_MasterGetDefaultConfig().
|
* or it can be set with default values by using the I2C_MasterGetDefaultConfig().
|
||||||
* After calling this API, the master is ready to transfer.
|
* After calling this API, the master is ready to transfer.
|
||||||
* Example:
|
* This is an example.
|
||||||
* @code
|
* @code
|
||||||
* i2c_master_config_t config = {
|
* i2c_master_config_t config = {
|
||||||
* .enableMaster = true,
|
* .enableMaster = true,
|
||||||
|
@ -292,20 +292,20 @@ extern "C" {
|
||||||
* @endcode
|
* @endcode
|
||||||
*
|
*
|
||||||
* @param base I2C base pointer
|
* @param base I2C base pointer
|
||||||
* @param masterConfig pointer to master configuration structure
|
* @param masterConfig A pointer to the master configuration structure
|
||||||
* @param srcClock_Hz I2C peripheral clock frequency in Hz
|
* @param srcClock_Hz I2C peripheral clock frequency in Hz
|
||||||
*/
|
*/
|
||||||
void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz);
|
void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Initializes the I2C peripheral. Call this API to ungate the I2C clock
|
* @brief Initializes the I2C peripheral. Call this API to ungate the I2C clock
|
||||||
* and initializes the I2C with slave configuration.
|
* and initialize the I2C with the slave configuration.
|
||||||
*
|
*
|
||||||
* @note This API should be called at the beginning of the application to use
|
* @note This API should be called at the beginning of the application.
|
||||||
* the I2C driver, or any operation to the I2C module can cause a hard fault
|
* Otherwise, any operation to the I2C module can cause a hard fault
|
||||||
* because the clock is not enabled. The configuration structure can partly be set
|
* because the clock is not enabled. The configuration structure can partly be set
|
||||||
* with default values by I2C_SlaveGetDefaultConfig(), or can be filled by the user.
|
* with default values by I2C_SlaveGetDefaultConfig() or it can be custom filled by the user.
|
||||||
* Example
|
* This is an example.
|
||||||
* @code
|
* @code
|
||||||
* i2c_slave_config_t config = {
|
* i2c_slave_config_t config = {
|
||||||
* .enableSlave = true,
|
* .enableSlave = true,
|
||||||
|
@ -314,15 +314,17 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin
|
||||||
* .slaveAddress = 0x1DU,
|
* .slaveAddress = 0x1DU,
|
||||||
* .enableWakeUp = false,
|
* .enableWakeUp = false,
|
||||||
* .enablehighDrive = false,
|
* .enablehighDrive = false,
|
||||||
* .enableBaudRateCtl = false
|
* .enableBaudRateCtl = false,
|
||||||
|
* .sclStopHoldTime_ns = 4000
|
||||||
* };
|
* };
|
||||||
* I2C_SlaveInit(I2C0, &config);
|
* I2C_SlaveInit(I2C0, &config, 12000000U);
|
||||||
* @endcode
|
* @endcode
|
||||||
*
|
*
|
||||||
* @param base I2C base pointer
|
* @param base I2C base pointer
|
||||||
* @param slaveConfig pointer to slave configuration structure
|
* @param slaveConfig A pointer to the slave configuration structure
|
||||||
|
* @param srcClock_Hz I2C peripheral clock frequency in Hz
|
||||||
*/
|
*/
|
||||||
void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig);
|
void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig, uint32_t srcClock_Hz);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief De-initializes the I2C master peripheral. Call this API to gate the I2C clock.
|
* @brief De-initializes the I2C master peripheral. Call this API to gate the I2C clock.
|
||||||
|
@ -342,28 +344,28 @@ void I2C_SlaveDeinit(I2C_Type *base);
|
||||||
* @brief Sets the I2C master configuration structure to default values.
|
* @brief Sets the I2C master configuration structure to default values.
|
||||||
*
|
*
|
||||||
* The purpose of this API is to get the configuration structure initialized for use in the I2C_MasterConfigure().
|
* The purpose of this API is to get the configuration structure initialized for use in the I2C_MasterConfigure().
|
||||||
* Use the initialized structure unchanged in I2C_MasterConfigure(), or modify some fields of
|
* Use the initialized structure unchanged in the I2C_MasterConfigure() or modify
|
||||||
* the structure before calling I2C_MasterConfigure().
|
* the structure before calling the I2C_MasterConfigure().
|
||||||
* Example:
|
* This is an example.
|
||||||
* @code
|
* @code
|
||||||
* i2c_master_config_t config;
|
* i2c_master_config_t config;
|
||||||
* I2C_MasterGetDefaultConfig(&config);
|
* I2C_MasterGetDefaultConfig(&config);
|
||||||
* @endcode
|
* @endcode
|
||||||
* @param masterConfig Pointer to the master configuration structure.
|
* @param masterConfig A pointer to the master configuration structure.
|
||||||
*/
|
*/
|
||||||
void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig);
|
void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Sets the I2C slave configuration structure to default values.
|
* @brief Sets the I2C slave configuration structure to default values.
|
||||||
*
|
*
|
||||||
* The purpose of this API is to get the configuration structure initialized for use in I2C_SlaveConfigure().
|
* The purpose of this API is to get the configuration structure initialized for use in the I2C_SlaveConfigure().
|
||||||
* Modify fields of the structure before calling the I2C_SlaveConfigure().
|
* Modify fields of the structure before calling the I2C_SlaveConfigure().
|
||||||
* Example:
|
* This is an example.
|
||||||
* @code
|
* @code
|
||||||
* i2c_slave_config_t config;
|
* i2c_slave_config_t config;
|
||||||
* I2C_SlaveGetDefaultConfig(&config);
|
* I2C_SlaveGetDefaultConfig(&config);
|
||||||
* @endcode
|
* @endcode
|
||||||
* @param slaveConfig Pointer to the slave configuration structure.
|
* @param slaveConfig A pointer to the slave configuration structure.
|
||||||
*/
|
*/
|
||||||
void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig);
|
void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig);
|
||||||
|
|
||||||
|
@ -371,7 +373,7 @@ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig);
|
||||||
* @brief Enables or disabless the I2C peripheral operation.
|
* @brief Enables or disabless the I2C peripheral operation.
|
||||||
*
|
*
|
||||||
* @param base I2C base pointer
|
* @param base I2C base pointer
|
||||||
* @param enable pass true to enable module, false to disable module
|
* @param enable Pass true to enable and false to disable the module.
|
||||||
*/
|
*/
|
||||||
static inline void I2C_Enable(I2C_Type *base, bool enable)
|
static inline void I2C_Enable(I2C_Type *base, bool enable)
|
||||||
{
|
{
|
||||||
|
@ -414,7 +416,7 @@ static inline uint32_t I2C_SlaveGetStatusFlags(I2C_Type *base)
|
||||||
/*!
|
/*!
|
||||||
* @brief Clears the I2C status flag state.
|
* @brief Clears the I2C status flag state.
|
||||||
*
|
*
|
||||||
* The following status register flags can be cleared: kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag
|
* The following status register flags can be cleared kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag.
|
||||||
*
|
*
|
||||||
* @param base I2C base pointer
|
* @param base I2C base pointer
|
||||||
* @param statusMask The status flag mask, defined in type i2c_status_flag_t.
|
* @param statusMask The status flag mask, defined in type i2c_status_flag_t.
|
||||||
|
@ -449,7 +451,7 @@ static inline void I2C_MasterClearStatusFlags(I2C_Type *base, uint32_t statusMas
|
||||||
/*!
|
/*!
|
||||||
* @brief Clears the I2C status flag state.
|
* @brief Clears the I2C status flag state.
|
||||||
*
|
*
|
||||||
* The following status register flags can be cleared: kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag
|
* The following status register flags can be cleared kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag
|
||||||
*
|
*
|
||||||
* @param base I2C base pointer
|
* @param base I2C base pointer
|
||||||
* @param statusMask The status flag mask, defined in type i2c_status_flag_t.
|
* @param statusMask The status flag mask, defined in type i2c_status_flag_t.
|
||||||
|
@ -581,19 +583,21 @@ status_t I2C_MasterStop(I2C_Type *base);
|
||||||
status_t I2C_MasterRepeatedStart(I2C_Type *base, uint8_t address, i2c_direction_t direction);
|
status_t I2C_MasterRepeatedStart(I2C_Type *base, uint8_t address, i2c_direction_t direction);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Performs a polling send transaction on the I2C bus without a STOP signal.
|
* @brief Performs a polling send transaction on the I2C bus.
|
||||||
*
|
*
|
||||||
* @param base The I2C peripheral base pointer.
|
* @param base The I2C peripheral base pointer.
|
||||||
* @param txBuff The pointer to the data to be transferred.
|
* @param txBuff The pointer to the data to be transferred.
|
||||||
* @param txSize The length in bytes of the data to be transferred.
|
* @param txSize The length in bytes of the data to be transferred.
|
||||||
|
* @param flags Transfer control flag to decide whether need to send a stop, use kI2C_TransferDefaultFlag
|
||||||
|
* to issue a stop and kI2C_TransferNoStop to not send a stop.
|
||||||
* @retval kStatus_Success Successfully complete the data transmission.
|
* @retval kStatus_Success Successfully complete the data transmission.
|
||||||
* @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
|
* @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
|
||||||
* @retval kStataus_I2C_Nak Transfer error, receive NAK during transfer.
|
* @retval kStataus_I2C_Nak Transfer error, receive NAK during transfer.
|
||||||
*/
|
*/
|
||||||
status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize);
|
status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize, uint32_t flags);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Performs a polling receive transaction on the I2C bus with a STOP signal.
|
* @brief Performs a polling receive transaction on the I2C bus.
|
||||||
*
|
*
|
||||||
* @note The I2C_MasterReadBlocking function stops the bus before reading the final byte.
|
* @note The I2C_MasterReadBlocking function stops the bus before reading the final byte.
|
||||||
* Without stopping the bus prior for the final read, the bus issues another read, resulting
|
* Without stopping the bus prior for the final read, the bus issues another read, resulting
|
||||||
|
@ -602,10 +606,12 @@ status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t t
|
||||||
* @param base I2C peripheral base pointer.
|
* @param base I2C peripheral base pointer.
|
||||||
* @param rxBuff The pointer to the data to store the received data.
|
* @param rxBuff The pointer to the data to store the received data.
|
||||||
* @param rxSize The length in bytes of the data to be received.
|
* @param rxSize The length in bytes of the data to be received.
|
||||||
|
* @param flags Transfer control flag to decide whether need to send a stop, use kI2C_TransferDefaultFlag
|
||||||
|
* to issue a stop and kI2C_TransferNoStop to not send a stop.
|
||||||
* @retval kStatus_Success Successfully complete the data transmission.
|
* @retval kStatus_Success Successfully complete the data transmission.
|
||||||
* @retval kStatus_I2C_Timeout Send stop signal failed, timeout.
|
* @retval kStatus_I2C_Timeout Send stop signal failed, timeout.
|
||||||
*/
|
*/
|
||||||
status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize);
|
status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize, uint32_t flags);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Performs a polling send transaction on the I2C bus.
|
* @brief Performs a polling send transaction on the I2C bus.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||||
* All rights reserved.
|
* Copyright 2016-2017 NXP
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
* other materials provided with the distribution.
|
* other materials provided with the distribution.
|
||||||
*
|
*
|
||||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
* o Neither the name of the copyright holder nor the names of its
|
||||||
* contributors may be used to endorse or promote products derived from this
|
* contributors may be used to endorse or promote products derived from this
|
||||||
* software without specific prior written permission.
|
* software without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -162,6 +162,26 @@ static void I2C_MasterTransferCallbackEDMA(edma_handle_t *handle, void *userData
|
||||||
result = I2C_MasterStop(i2cPrivateHandle->base);
|
result = I2C_MasterStop(i2cPrivateHandle->base);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (i2cPrivateHandle->handle->transfer.direction == kI2C_Read)
|
||||||
|
{
|
||||||
|
/* Change to send NAK at the last byte. */
|
||||||
|
i2cPrivateHandle->base->C1 |= I2C_C1_TXAK_MASK;
|
||||||
|
|
||||||
|
/* Wait the last data to be received. */
|
||||||
|
while (!(i2cPrivateHandle->base->S & kI2C_TransferCompleteFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Change direction to send. */
|
||||||
|
i2cPrivateHandle->base->C1 |= I2C_C1_TX_MASK;
|
||||||
|
|
||||||
|
/* Read the last data byte. */
|
||||||
|
*(i2cPrivateHandle->handle->transfer.data + i2cPrivateHandle->handle->transfer.dataSize - 1) =
|
||||||
|
i2cPrivateHandle->base->D;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
i2cPrivateHandle->handle->state = kIdleState;
|
i2cPrivateHandle->handle->state = kIdleState;
|
||||||
|
|
||||||
|
@ -203,7 +223,6 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
||||||
assert(xfer);
|
assert(xfer);
|
||||||
|
|
||||||
status_t result = kStatus_Success;
|
status_t result = kStatus_Success;
|
||||||
uint16_t timeout = UINT16_MAX;
|
|
||||||
|
|
||||||
if (handle->state != kIdleState)
|
if (handle->state != kIdleState)
|
||||||
{
|
{
|
||||||
|
@ -221,16 +240,6 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
||||||
|
|
||||||
handle->state = kTransferDataState;
|
handle->state = kTransferDataState;
|
||||||
|
|
||||||
/* Wait until ready to complete. */
|
|
||||||
while ((!(base->S & kI2C_TransferCompleteFlag)) && (--timeout))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Failed to start the transfer. */
|
|
||||||
if (timeout == 0)
|
|
||||||
{
|
|
||||||
return kStatus_I2C_Timeout;
|
|
||||||
}
|
|
||||||
/* Clear all status before transfer. */
|
/* Clear all status before transfer. */
|
||||||
I2C_MasterClearStatusFlags(base, kClearFlags);
|
I2C_MasterClearStatusFlags(base, kClearFlags);
|
||||||
|
|
||||||
|
@ -250,22 +259,55 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
||||||
result = I2C_MasterStart(base, handle->transfer.slaveAddress, direction);
|
result = I2C_MasterStart(base, handle->transfer.slaveAddress, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if there's transfer error. */
|
||||||
|
result = I2C_CheckAndClearError(base, base->S);
|
||||||
|
|
||||||
|
/* Return if error. */
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
if (result == kStatus_I2C_Nak)
|
||||||
|
{
|
||||||
|
result = kStatus_I2C_Addr_Nak;
|
||||||
|
|
||||||
|
if (I2C_MasterStop(base) != kStatus_Success)
|
||||||
|
{
|
||||||
|
result = kStatus_I2C_Timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle->completionCallback)
|
||||||
|
{
|
||||||
|
(handle->completionCallback)(base, handle, result, handle->userData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* Send subaddress. */
|
/* Send subaddress. */
|
||||||
if (handle->transfer.subaddressSize)
|
if (handle->transfer.subaddressSize)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
/* Wait until data transfer complete. */
|
|
||||||
while (!(base->S & kI2C_IntPendingFlag))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear interrupt pending flag. */
|
/* Clear interrupt pending flag. */
|
||||||
base->S = kI2C_IntPendingFlag;
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
handle->transfer.subaddressSize--;
|
handle->transfer.subaddressSize--;
|
||||||
base->D = ((handle->transfer.subaddress) >> (8 * handle->transfer.subaddressSize));
|
base->D = ((handle->transfer.subaddress) >> (8 * handle->transfer.subaddressSize));
|
||||||
|
|
||||||
|
/* Wait until data transfer complete. */
|
||||||
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if there's transfer error. */
|
/* Check if there's transfer error. */
|
||||||
result = I2C_CheckAndClearError(base, base->S);
|
result = I2C_CheckAndClearError(base, base->S);
|
||||||
|
|
||||||
|
@ -278,18 +320,11 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
||||||
|
|
||||||
if (handle->transfer.direction == kI2C_Read)
|
if (handle->transfer.direction == kI2C_Read)
|
||||||
{
|
{
|
||||||
/* Wait until data transfer complete. */
|
|
||||||
while (!(base->S & kI2C_IntPendingFlag))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear pending flag. */
|
/* Clear pending flag. */
|
||||||
base->S = kI2C_IntPendingFlag;
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
/* Send repeated start and slave address. */
|
/* Send repeated start and slave address. */
|
||||||
result = I2C_MasterRepeatedStart(base, handle->transfer.slaveAddress, kI2C_Read);
|
result = I2C_MasterRepeatedStart(base, handle->transfer.slaveAddress, kI2C_Read);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
|
@ -301,11 +336,18 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear pending flag. */
|
|
||||||
base->S = kI2C_IntPendingFlag;
|
|
||||||
|
|
||||||
/* Check if there's transfer error. */
|
/* Check if there's transfer error. */
|
||||||
result = I2C_CheckAndClearError(base, base->S);
|
result = I2C_CheckAndClearError(base, base->S);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear pending flag. */
|
||||||
|
base->S = kI2C_IntPendingFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -319,17 +361,7 @@ static void I2C_MasterTransferEDMAConfig(I2C_Type *base, i2c_master_edma_handle_
|
||||||
{
|
{
|
||||||
transfer_config.srcAddr = (uint32_t)I2C_GetDataRegAddr(base);
|
transfer_config.srcAddr = (uint32_t)I2C_GetDataRegAddr(base);
|
||||||
transfer_config.destAddr = (uint32_t)(handle->transfer.data);
|
transfer_config.destAddr = (uint32_t)(handle->transfer.data);
|
||||||
|
|
||||||
/* Send stop if kI2C_TransferNoStop flag is not asserted. */
|
|
||||||
if (!(handle->transfer.flags & kI2C_TransferNoStopFlag))
|
|
||||||
{
|
|
||||||
transfer_config.majorLoopCounts = (handle->transfer.dataSize - 1);
|
transfer_config.majorLoopCounts = (handle->transfer.dataSize - 1);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
transfer_config.majorLoopCounts = handle->transfer.dataSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
transfer_config.srcTransferSize = kEDMA_TransferSize1Bytes;
|
transfer_config.srcTransferSize = kEDMA_TransferSize1Bytes;
|
||||||
transfer_config.srcOffset = 0;
|
transfer_config.srcOffset = 0;
|
||||||
transfer_config.destTransferSize = kEDMA_TransferSize1Bytes;
|
transfer_config.destTransferSize = kEDMA_TransferSize1Bytes;
|
||||||
|
@ -348,6 +380,9 @@ static void I2C_MasterTransferEDMAConfig(I2C_Type *base, i2c_master_edma_handle_
|
||||||
transfer_config.minorLoopBytes = 1;
|
transfer_config.minorLoopBytes = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Store the initially configured eDMA minor byte transfer count into the I2C handle */
|
||||||
|
handle->nbytes = transfer_config.minorLoopBytes;
|
||||||
|
|
||||||
EDMA_SubmitTransfer(handle->dmaHandle, &transfer_config);
|
EDMA_SubmitTransfer(handle->dmaHandle, &transfer_config);
|
||||||
EDMA_StartTransfer(handle->dmaHandle);
|
EDMA_StartTransfer(handle->dmaHandle);
|
||||||
}
|
}
|
||||||
|
@ -427,7 +462,7 @@ status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle
|
||||||
if (handle->transfer.direction == kI2C_Read)
|
if (handle->transfer.direction == kI2C_Read)
|
||||||
{
|
{
|
||||||
/* Change direction for receive. */
|
/* Change direction for receive. */
|
||||||
base->C1 &= ~I2C_C1_TX_MASK;
|
base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK);
|
||||||
|
|
||||||
/* Read dummy to release the bus. */
|
/* Read dummy to release the bus. */
|
||||||
dummy = base->D;
|
dummy = base->D;
|
||||||
|
@ -479,6 +514,11 @@ status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle
|
||||||
{
|
{
|
||||||
result = I2C_MasterStop(base);
|
result = I2C_MasterStop(base);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Change direction to send. */
|
||||||
|
base->C1 |= I2C_C1_TX_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read the last byte of data. */
|
/* Read the last byte of data. */
|
||||||
if (handle->transfer.direction == kI2C_Read)
|
if (handle->transfer.direction == kI2C_Read)
|
||||||
|
@ -504,7 +544,9 @@ status_t I2C_MasterTransferGetCountEDMA(I2C_Type *base, i2c_master_edma_handle_t
|
||||||
|
|
||||||
if (kIdleState != handle->state)
|
if (kIdleState != handle->state)
|
||||||
{
|
{
|
||||||
*count = (handle->transferSize - EDMA_GetRemainingBytes(handle->dmaHandle->base, handle->dmaHandle->channel));
|
*count = (handle->transferSize -
|
||||||
|
(uint32_t)handle->nbytes *
|
||||||
|
EDMA_GetRemainingMajorLoopCount(handle->dmaHandle->base, handle->dmaHandle->channel));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||||
* All rights reserved.
|
* Copyright 2016-2017 NXP
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
* other materials provided with the distribution.
|
* other materials provided with the distribution.
|
||||||
*
|
*
|
||||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
* o Neither the name of the copyright holder nor the names of its
|
||||||
* contributors may be used to endorse or promote products derived from this
|
* contributors may be used to endorse or promote products derived from this
|
||||||
* software without specific prior written permission.
|
* software without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -39,7 +39,6 @@
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Definitions
|
* Definitions
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
@ -56,13 +55,14 @@ typedef void (*i2c_master_edma_transfer_callback_t)(I2C_Type *base,
|
||||||
/*! @brief I2C master eDMA transfer structure. */
|
/*! @brief I2C master eDMA transfer structure. */
|
||||||
struct _i2c_master_edma_handle
|
struct _i2c_master_edma_handle
|
||||||
{
|
{
|
||||||
i2c_master_transfer_t transfer; /*!< I2C master transfer struct. */
|
i2c_master_transfer_t transfer; /*!< I2C master transfer structure. */
|
||||||
size_t transferSize; /*!< Total bytes to be transferred. */
|
size_t transferSize; /*!< Total bytes to be transferred. */
|
||||||
|
uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */
|
||||||
uint8_t state; /*!< I2C master transfer status. */
|
uint8_t state; /*!< I2C master transfer status. */
|
||||||
edma_handle_t *dmaHandle; /*!< The eDMA handler used. */
|
edma_handle_t *dmaHandle; /*!< The eDMA handler used. */
|
||||||
i2c_master_edma_transfer_callback_t
|
i2c_master_edma_transfer_callback_t
|
||||||
completionCallback; /*!< Callback function called after eDMA transfer finished. */
|
completionCallback; /*!< A callback function called after the eDMA transfer is finished. */
|
||||||
void *userData; /*!< Callback parameter passed to callback function. */
|
void *userData; /*!< A callback parameter passed to the callback function. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
@ -79,12 +79,12 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Init the I2C handle which is used in transcational functions.
|
* @brief Initializes the I2C handle which is used in transcational functions.
|
||||||
*
|
*
|
||||||
* @param base I2C peripheral base address.
|
* @param base I2C peripheral base address.
|
||||||
* @param handle pointer to i2c_master_edma_handle_t structure.
|
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||||
* @param callback pointer to user callback function.
|
* @param callback A pointer to the user callback function.
|
||||||
* @param userData user param passed to the callback function.
|
* @param userData A user parameter passed to the callback function.
|
||||||
* @param edmaHandle eDMA handle pointer.
|
* @param edmaHandle eDMA handle pointer.
|
||||||
*/
|
*/
|
||||||
void I2C_MasterCreateEDMAHandle(I2C_Type *base,
|
void I2C_MasterCreateEDMAHandle(I2C_Type *base,
|
||||||
|
@ -97,30 +97,30 @@ void I2C_MasterCreateEDMAHandle(I2C_Type *base,
|
||||||
* @brief Performs a master eDMA non-blocking transfer on the I2C bus.
|
* @brief Performs a master eDMA non-blocking transfer on the I2C bus.
|
||||||
*
|
*
|
||||||
* @param base I2C peripheral base address.
|
* @param base I2C peripheral base address.
|
||||||
* @param handle pointer to i2c_master_edma_handle_t structure.
|
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||||
* @param xfer pointer to transfer structure of i2c_master_transfer_t.
|
* @param xfer A pointer to the transfer structure of i2c_master_transfer_t.
|
||||||
* @retval kStatus_Success Sucessully complete the data transmission.
|
* @retval kStatus_Success Sucessfully completed the data transmission.
|
||||||
* @retval kStatus_I2C_Busy Previous transmission still not finished.
|
* @retval kStatus_I2C_Busy A previous transmission is still not finished.
|
||||||
* @retval kStatus_I2C_Timeout Transfer error, wait signal timeout.
|
* @retval kStatus_I2C_Timeout Transfer error, waits for a signal timeout.
|
||||||
* @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
|
* @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
|
||||||
* @retval kStataus_I2C_Nak Transfer error, receive Nak during transfer.
|
* @retval kStataus_I2C_Nak Transfer error, receive NAK during transfer.
|
||||||
*/
|
*/
|
||||||
status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle, i2c_master_transfer_t *xfer);
|
status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle, i2c_master_transfer_t *xfer);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Get master transfer status during a eDMA non-blocking transfer.
|
* @brief Gets a master transfer status during the eDMA non-blocking transfer.
|
||||||
*
|
*
|
||||||
* @param base I2C peripheral base address.
|
* @param base I2C peripheral base address.
|
||||||
* @param handle pointer to i2c_master_edma_handle_t structure.
|
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||||
* @param count Number of bytes transferred so far by the non-blocking transaction.
|
* @param count A number of bytes transferred by the non-blocking transaction.
|
||||||
*/
|
*/
|
||||||
status_t I2C_MasterTransferGetCountEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle, size_t *count);
|
status_t I2C_MasterTransferGetCountEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle, size_t *count);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Abort a master eDMA non-blocking transfer in a early time.
|
* @brief Aborts a master eDMA non-blocking transfer early.
|
||||||
*
|
*
|
||||||
* @param base I2C peripheral base address.
|
* @param base I2C peripheral base address.
|
||||||
* @param handle pointer to i2c_master_edma_handle_t structure.
|
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||||
*/
|
*/
|
||||||
void I2C_MasterTransferAbortEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle);
|
void I2C_MasterTransferAbortEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||||
* All rights reserved.
|
* Copyright 2016-2017 NXP
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
* other materials provided with the distribution.
|
* other materials provided with the distribution.
|
||||||
*
|
*
|
||||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
* o Neither the name of the copyright holder nor the names of its
|
||||||
* contributors may be used to endorse or promote products derived from this
|
* contributors may be used to endorse or promote products derived from this
|
||||||
* software without specific prior written permission.
|
* software without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -75,6 +75,19 @@ typedef void (*i2c_isr_t)(I2C_Type *base, void *i2cHandle);
|
||||||
*/
|
*/
|
||||||
uint32_t I2C_GetInstance(I2C_Type *base);
|
uint32_t I2C_GetInstance(I2C_Type *base);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Set SCL/SDA hold time, this API receives SCL stop hold time, calculate the
|
||||||
|
* closest SCL divider and MULT value for the SDA hold time, SCL start and SCL stop
|
||||||
|
* hold time. To reduce the ROM size, SDA/SCL hold value mapping table is not provided,
|
||||||
|
* assume SCL divider = SCL stop hold value *2 to get the closest SCL divider value and MULT
|
||||||
|
* value, then the related SDA hold time, SCL start and SCL stop hold time is used.
|
||||||
|
*
|
||||||
|
* @param base I2C peripheral base address.
|
||||||
|
* @param sourceClock_Hz I2C functional clock frequency in Hertz.
|
||||||
|
* @param sclStopHoldTime_ns SCL stop hold time in ns.
|
||||||
|
*/
|
||||||
|
static void I2C_SetHoldTime(I2C_Type *base, uint32_t sclStopHoldTime_ns, uint32_t sourceClock_Hz);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Set up master transfer, send slave address and decide the initial
|
* @brief Set up master transfer, send slave address and decide the initial
|
||||||
* transfer state.
|
* transfer state.
|
||||||
|
@ -125,20 +138,22 @@ static void I2C_TransferCommonIRQHandler(I2C_Type *base, void *handle);
|
||||||
static void *s_i2cHandle[FSL_FEATURE_SOC_I2C_COUNT] = {NULL};
|
static void *s_i2cHandle[FSL_FEATURE_SOC_I2C_COUNT] = {NULL};
|
||||||
|
|
||||||
/*! @brief SCL clock divider used to calculate baudrate. */
|
/*! @brief SCL clock divider used to calculate baudrate. */
|
||||||
const uint16_t s_i2cDividerTable[] = {20, 22, 24, 26, 28, 30, 34, 40, 28, 32, 36, 40, 44,
|
static const uint16_t s_i2cDividerTable[] = {
|
||||||
48, 56, 68, 48, 56, 64, 72, 80, 88, 104, 128, 80, 96,
|
20, 22, 24, 26, 28, 30, 34, 40, 28, 32, 36, 40, 44, 48, 56, 68,
|
||||||
112, 128, 144, 160, 192, 240, 160, 192, 224, 256, 288, 320, 384,
|
48, 56, 64, 72, 80, 88, 104, 128, 80, 96, 112, 128, 144, 160, 192, 240,
|
||||||
480, 320, 384, 448, 512, 576, 640, 768, 960, 640, 768, 896, 1024,
|
160, 192, 224, 256, 288, 320, 384, 480, 320, 384, 448, 512, 576, 640, 768, 960,
|
||||||
1152, 1280, 1536, 1920, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 3840};
|
640, 768, 896, 1024, 1152, 1280, 1536, 1920, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 3840};
|
||||||
|
|
||||||
/*! @brief Pointers to i2c bases for each instance. */
|
/*! @brief Pointers to i2c bases for each instance. */
|
||||||
static I2C_Type *const s_i2cBases[] = I2C_BASE_PTRS;
|
static I2C_Type *const s_i2cBases[] = I2C_BASE_PTRS;
|
||||||
|
|
||||||
/*! @brief Pointers to i2c IRQ number for each instance. */
|
/*! @brief Pointers to i2c IRQ number for each instance. */
|
||||||
const IRQn_Type s_i2cIrqs[] = I2C_IRQS;
|
static const IRQn_Type s_i2cIrqs[] = I2C_IRQS;
|
||||||
|
|
||||||
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||||
/*! @brief Pointers to i2c clocks for each instance. */
|
/*! @brief Pointers to i2c clocks for each instance. */
|
||||||
const clock_ip_name_t s_i2cClocks[] = I2C_CLOCKS;
|
static const clock_ip_name_t s_i2cClocks[] = I2C_CLOCKS;
|
||||||
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||||
|
|
||||||
/*! @brief Pointer to master IRQ handler for each instance. */
|
/*! @brief Pointer to master IRQ handler for each instance. */
|
||||||
static i2c_isr_t s_i2cMasterIsr;
|
static i2c_isr_t s_i2cMasterIsr;
|
||||||
|
@ -155,7 +170,7 @@ uint32_t I2C_GetInstance(I2C_Type *base)
|
||||||
uint32_t instance;
|
uint32_t instance;
|
||||||
|
|
||||||
/* Find the instance index from base address mappings. */
|
/* Find the instance index from base address mappings. */
|
||||||
for (instance = 0; instance < FSL_FEATURE_SOC_I2C_COUNT; instance++)
|
for (instance = 0; instance < ARRAY_SIZE(s_i2cBases); instance++)
|
||||||
{
|
{
|
||||||
if (s_i2cBases[instance] == base)
|
if (s_i2cBases[instance] == base)
|
||||||
{
|
{
|
||||||
|
@ -163,16 +178,63 @@ uint32_t I2C_GetInstance(I2C_Type *base)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(instance < FSL_FEATURE_SOC_I2C_COUNT);
|
assert(instance < ARRAY_SIZE(s_i2cBases));
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void I2C_SetHoldTime(I2C_Type *base, uint32_t sclStopHoldTime_ns, uint32_t sourceClock_Hz)
|
||||||
|
{
|
||||||
|
uint32_t multiplier;
|
||||||
|
uint32_t computedSclHoldTime;
|
||||||
|
uint32_t absError;
|
||||||
|
uint32_t bestError = UINT32_MAX;
|
||||||
|
uint32_t bestMult = 0u;
|
||||||
|
uint32_t bestIcr = 0u;
|
||||||
|
uint8_t mult;
|
||||||
|
uint8_t i;
|
||||||
|
|
||||||
|
/* Search for the settings with the lowest error. Mult is the MULT field of the I2C_F register,
|
||||||
|
* and ranges from 0-2. It selects the multiplier factor for the divider. */
|
||||||
|
/* SDA hold time = bus period (s) * mul * SDA hold value. */
|
||||||
|
/* SCL start hold time = bus period (s) * mul * SCL start hold value. */
|
||||||
|
/* SCL stop hold time = bus period (s) * mul * SCL stop hold value. */
|
||||||
|
|
||||||
|
for (mult = 0u; (mult <= 2u) && (bestError != 0); ++mult)
|
||||||
|
{
|
||||||
|
multiplier = 1u << mult;
|
||||||
|
|
||||||
|
/* Scan table to find best match. */
|
||||||
|
for (i = 0u; i < sizeof(s_i2cDividerTable) / sizeof(s_i2cDividerTable[0]); ++i)
|
||||||
|
{
|
||||||
|
/* Assume SCL hold(stop) value = s_i2cDividerTable[i]/2. */
|
||||||
|
computedSclHoldTime = ((multiplier * s_i2cDividerTable[i]) * 500000000U) / sourceClock_Hz;
|
||||||
|
absError = sclStopHoldTime_ns > computedSclHoldTime ? (sclStopHoldTime_ns - computedSclHoldTime) :
|
||||||
|
(computedSclHoldTime - sclStopHoldTime_ns);
|
||||||
|
|
||||||
|
if (absError < bestError)
|
||||||
|
{
|
||||||
|
bestMult = mult;
|
||||||
|
bestIcr = i;
|
||||||
|
bestError = absError;
|
||||||
|
|
||||||
|
/* If the error is 0, then we can stop searching because we won't find a better match. */
|
||||||
|
if (absError == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set frequency register based on best settings. */
|
||||||
|
base->F = I2C_F_MULT(bestMult) | I2C_F_ICR(bestIcr);
|
||||||
|
}
|
||||||
|
|
||||||
static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t *handle, i2c_master_transfer_t *xfer)
|
static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t *handle, i2c_master_transfer_t *xfer)
|
||||||
{
|
{
|
||||||
status_t result = kStatus_Success;
|
status_t result = kStatus_Success;
|
||||||
i2c_direction_t direction = xfer->direction;
|
i2c_direction_t direction = xfer->direction;
|
||||||
uint16_t timeout = UINT16_MAX;
|
|
||||||
|
|
||||||
/* Initialize the handle transfer information. */
|
/* Initialize the handle transfer information. */
|
||||||
handle->transfer = *xfer;
|
handle->transfer = *xfer;
|
||||||
|
@ -183,27 +245,13 @@ static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t
|
||||||
/* Initial transfer state. */
|
/* Initial transfer state. */
|
||||||
if (handle->transfer.subaddressSize > 0)
|
if (handle->transfer.subaddressSize > 0)
|
||||||
{
|
{
|
||||||
handle->state = kSendCommandState;
|
|
||||||
if (xfer->direction == kI2C_Read)
|
if (xfer->direction == kI2C_Read)
|
||||||
{
|
{
|
||||||
direction = kI2C_Write;
|
direction = kI2C_Write;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
handle->state = kCheckAddressState;
|
handle->state = kCheckAddressState;
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait until the data register is ready for transmit. */
|
|
||||||
while ((!(base->S & kI2C_TransferCompleteFlag)) && (--timeout))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Failed to start the transfer. */
|
|
||||||
if (timeout == 0)
|
|
||||||
{
|
|
||||||
return kStatus_I2C_Timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear all status before transfer. */
|
/* Clear all status before transfer. */
|
||||||
I2C_MasterClearStatusFlags(base, kClearFlags);
|
I2C_MasterClearStatusFlags(base, kClearFlags);
|
||||||
|
@ -265,18 +313,19 @@ static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_han
|
||||||
result = kStatus_Success;
|
result = kStatus_Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle Check address state to check the slave address is Acked in slave
|
/* Handle Check address state to check the slave address is Acked in slave
|
||||||
probe application. */
|
probe application. */
|
||||||
if (handle->state == kCheckAddressState)
|
if (handle->state == kCheckAddressState)
|
||||||
{
|
{
|
||||||
if (statusFlags & kI2C_ReceiveNakFlag)
|
if (statusFlags & kI2C_ReceiveNakFlag)
|
||||||
{
|
{
|
||||||
return kStatus_I2C_Nak;
|
result = kStatus_I2C_Addr_Nak;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (handle->transfer.subaddressSize > 0)
|
||||||
|
{
|
||||||
|
handle->state = kSendCommandState;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -292,6 +341,12 @@ static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_han
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* Run state machine. */
|
/* Run state machine. */
|
||||||
switch (handle->state)
|
switch (handle->state)
|
||||||
|
@ -375,6 +430,10 @@ static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_han
|
||||||
{
|
{
|
||||||
result = I2C_MasterStop(base);
|
result = I2C_MasterStop(base);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base->C1 |= I2C_C1_TX_MASK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send NAK at the last receive byte. */
|
/* Send NAK at the last receive byte. */
|
||||||
|
@ -407,6 +466,7 @@ static void I2C_TransferCommonIRQHandler(I2C_Type *base, void *handle)
|
||||||
{
|
{
|
||||||
s_i2cSlaveIsr(base, handle);
|
s_i2cSlaveIsr(base, handle);
|
||||||
}
|
}
|
||||||
|
__DSB();
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz)
|
void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz)
|
||||||
|
@ -415,12 +475,26 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin
|
||||||
|
|
||||||
/* Temporary register for filter read. */
|
/* Temporary register for filter read. */
|
||||||
uint8_t fltReg;
|
uint8_t fltReg;
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
||||||
uint8_t c2Reg;
|
uint8_t s2Reg;
|
||||||
#endif
|
#endif
|
||||||
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||||
/* Enable I2C clock. */
|
/* Enable I2C clock. */
|
||||||
CLOCK_EnableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
CLOCK_EnableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
||||||
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||||
|
|
||||||
|
/* Reset the module. */
|
||||||
|
base->A1 = 0;
|
||||||
|
base->F = 0;
|
||||||
|
base->C1 = 0;
|
||||||
|
base->S = 0xFFU;
|
||||||
|
base->C2 = 0;
|
||||||
|
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||||
|
base->FLT = 0x50U;
|
||||||
|
#elif defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT
|
||||||
|
base->FLT = 0x40U;
|
||||||
|
#endif
|
||||||
|
base->RA = 0;
|
||||||
|
|
||||||
/* Disable I2C prior to configuring it. */
|
/* Disable I2C prior to configuring it. */
|
||||||
base->C1 &= ~(I2C_C1_IICEN_MASK);
|
base->C1 &= ~(I2C_C1_IICEN_MASK);
|
||||||
|
@ -431,14 +505,6 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin
|
||||||
/* Configure baud rate. */
|
/* Configure baud rate. */
|
||||||
I2C_MasterSetBaudRate(base, masterConfig->baudRate_Bps, srcClock_Hz);
|
I2C_MasterSetBaudRate(base, masterConfig->baudRate_Bps, srcClock_Hz);
|
||||||
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
/* Configure high drive feature. */
|
|
||||||
c2Reg = base->C2;
|
|
||||||
c2Reg &= ~(I2C_C2_HDRS_MASK);
|
|
||||||
c2Reg |= I2C_C2_HDRS(masterConfig->enableHighDrive);
|
|
||||||
base->C2 = c2Reg;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Read out the FLT register. */
|
/* Read out the FLT register. */
|
||||||
fltReg = base->FLT;
|
fltReg = base->FLT;
|
||||||
|
|
||||||
|
@ -455,6 +521,12 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin
|
||||||
/* Write the register value back to the filter register. */
|
/* Write the register value back to the filter register. */
|
||||||
base->FLT = fltReg;
|
base->FLT = fltReg;
|
||||||
|
|
||||||
|
/* Enable/Disable double buffering. */
|
||||||
|
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
||||||
|
s2Reg = base->S2 & (~I2C_S2_DFEN_MASK);
|
||||||
|
base->S2 = s2Reg | I2C_S2_DFEN(masterConfig->enableDoubleBuffering);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Enable the I2C peripheral based on the configuration. */
|
/* Enable the I2C peripheral based on the configuration. */
|
||||||
base->C1 = I2C_C1_IICEN(masterConfig->enableMaster);
|
base->C1 = I2C_C1_IICEN(masterConfig->enableMaster);
|
||||||
}
|
}
|
||||||
|
@ -464,8 +536,10 @@ void I2C_MasterDeinit(I2C_Type *base)
|
||||||
/* Disable I2C module. */
|
/* Disable I2C module. */
|
||||||
I2C_Enable(base, false);
|
I2C_Enable(base, false);
|
||||||
|
|
||||||
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||||
/* Disable I2C clock. */
|
/* Disable I2C clock. */
|
||||||
CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
||||||
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig)
|
void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig)
|
||||||
|
@ -475,11 +549,6 @@ void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig)
|
||||||
/* Default baud rate at 100kbps. */
|
/* Default baud rate at 100kbps. */
|
||||||
masterConfig->baudRate_Bps = 100000U;
|
masterConfig->baudRate_Bps = 100000U;
|
||||||
|
|
||||||
/* Default pin high drive is disabled. */
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
masterConfig->enableHighDrive = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Default stop hold enable is disabled. */
|
/* Default stop hold enable is disabled. */
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF
|
#if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF
|
||||||
masterConfig->enableStopHold = false;
|
masterConfig->enableStopHold = false;
|
||||||
|
@ -488,12 +557,21 @@ void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig)
|
||||||
/* Default glitch filter value is no filter. */
|
/* Default glitch filter value is no filter. */
|
||||||
masterConfig->glitchFilterWidth = 0U;
|
masterConfig->glitchFilterWidth = 0U;
|
||||||
|
|
||||||
|
/* Default enable double buffering. */
|
||||||
|
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
||||||
|
masterConfig->enableDoubleBuffering = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Enable the I2C peripheral. */
|
/* Enable the I2C peripheral. */
|
||||||
masterConfig->enableMaster = true;
|
masterConfig->enableMaster = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2C_EnableInterrupts(I2C_Type *base, uint32_t mask)
|
void I2C_EnableInterrupts(I2C_Type *base, uint32_t mask)
|
||||||
{
|
{
|
||||||
|
#ifdef I2C_HAS_STOP_DETECT
|
||||||
|
uint8_t fltReg;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (mask & kI2C_GlobalInterruptEnable)
|
if (mask & kI2C_GlobalInterruptEnable)
|
||||||
{
|
{
|
||||||
base->C1 |= I2C_C1_IICIE_MASK;
|
base->C1 |= I2C_C1_IICIE_MASK;
|
||||||
|
@ -502,14 +580,28 @@ void I2C_EnableInterrupts(I2C_Type *base, uint32_t mask)
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT
|
#if defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT
|
||||||
if (mask & kI2C_StopDetectInterruptEnable)
|
if (mask & kI2C_StopDetectInterruptEnable)
|
||||||
{
|
{
|
||||||
base->FLT |= I2C_FLT_STOPIE_MASK;
|
fltReg = base->FLT;
|
||||||
|
|
||||||
|
/* Keep STOPF flag. */
|
||||||
|
fltReg &= ~I2C_FLT_STOPF_MASK;
|
||||||
|
|
||||||
|
/* Stop detect enable. */
|
||||||
|
fltReg |= I2C_FLT_STOPIE_MASK;
|
||||||
|
base->FLT = fltReg;
|
||||||
}
|
}
|
||||||
#endif /* FSL_FEATURE_I2C_HAS_STOP_DETECT */
|
#endif /* FSL_FEATURE_I2C_HAS_STOP_DETECT */
|
||||||
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||||
if (mask & kI2C_StartStopDetectInterruptEnable)
|
if (mask & kI2C_StartStopDetectInterruptEnable)
|
||||||
{
|
{
|
||||||
base->FLT |= I2C_FLT_SSIE_MASK;
|
fltReg = base->FLT;
|
||||||
|
|
||||||
|
/* Keep STARTF and STOPF flags. */
|
||||||
|
fltReg &= ~(I2C_FLT_STOPF_MASK | I2C_FLT_STARTF_MASK);
|
||||||
|
|
||||||
|
/* Start and stop detect enable. */
|
||||||
|
fltReg |= I2C_FLT_SSIE_MASK;
|
||||||
|
base->FLT = fltReg;
|
||||||
}
|
}
|
||||||
#endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */
|
#endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */
|
||||||
}
|
}
|
||||||
|
@ -524,14 +616,14 @@ void I2C_DisableInterrupts(I2C_Type *base, uint32_t mask)
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT
|
#if defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT
|
||||||
if (mask & kI2C_StopDetectInterruptEnable)
|
if (mask & kI2C_StopDetectInterruptEnable)
|
||||||
{
|
{
|
||||||
base->FLT &= ~I2C_FLT_STOPIE_MASK;
|
base->FLT &= ~(I2C_FLT_STOPIE_MASK | I2C_FLT_STOPF_MASK);
|
||||||
}
|
}
|
||||||
#endif /* FSL_FEATURE_I2C_HAS_STOP_DETECT */
|
#endif /* FSL_FEATURE_I2C_HAS_STOP_DETECT */
|
||||||
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||||
if (mask & kI2C_StartStopDetectInterruptEnable)
|
if (mask & kI2C_StartStopDetectInterruptEnable)
|
||||||
{
|
{
|
||||||
base->FLT &= ~I2C_FLT_SSIE_MASK;
|
base->FLT &= ~(I2C_FLT_SSIE_MASK | I2C_FLT_STOPF_MASK | I2C_FLT_STARTF_MASK);
|
||||||
}
|
}
|
||||||
#endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */
|
#endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */
|
||||||
}
|
}
|
||||||
|
@ -623,7 +715,7 @@ status_t I2C_MasterRepeatedStart(I2C_Type *base, uint8_t address, i2c_direction_
|
||||||
base->F = savedMult & (~I2C_F_MULT_MASK);
|
base->F = savedMult & (~I2C_F_MULT_MASK);
|
||||||
|
|
||||||
/* We are already in a transfer, so send a repeated start. */
|
/* We are already in a transfer, so send a repeated start. */
|
||||||
base->C1 |= I2C_C1_RSTA_MASK;
|
base->C1 |= I2C_C1_RSTA_MASK | I2C_C1_TX_MASK;
|
||||||
|
|
||||||
/* Restore the multiplier factor. */
|
/* Restore the multiplier factor. */
|
||||||
base->F = savedMult;
|
base->F = savedMult;
|
||||||
|
@ -690,7 +782,7 @@ uint32_t I2C_MasterGetStatusFlags(I2C_Type *base)
|
||||||
return statusFlags;
|
return statusFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize)
|
status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize, uint32_t flags)
|
||||||
{
|
{
|
||||||
status_t result = kStatus_Success;
|
status_t result = kStatus_Success;
|
||||||
uint8_t statusFlags = 0;
|
uint8_t statusFlags = 0;
|
||||||
|
@ -728,7 +820,7 @@ status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t t
|
||||||
result = kStatus_I2C_ArbitrationLost;
|
result = kStatus_I2C_ArbitrationLost;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (statusFlags & kI2C_ReceiveNakFlag)
|
if ((statusFlags & kI2C_ReceiveNakFlag) && txSize)
|
||||||
{
|
{
|
||||||
base->S = kI2C_ReceiveNakFlag;
|
base->S = kI2C_ReceiveNakFlag;
|
||||||
result = kStatus_I2C_Nak;
|
result = kStatus_I2C_Nak;
|
||||||
|
@ -741,10 +833,19 @@ status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (((result == kStatus_Success) && (!(flags & kI2C_TransferNoStopFlag))) || (result == kStatus_I2C_Nak))
|
||||||
|
{
|
||||||
|
/* Clear the IICIF flag. */
|
||||||
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
|
/* Send stop. */
|
||||||
|
result = I2C_MasterStop(base);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize)
|
status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize, uint32_t flags)
|
||||||
{
|
{
|
||||||
status_t result = kStatus_Success;
|
status_t result = kStatus_Success;
|
||||||
volatile uint8_t dummy = 0;
|
volatile uint8_t dummy = 0;
|
||||||
|
@ -786,9 +887,17 @@ status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize)
|
||||||
/* Single byte use case. */
|
/* Single byte use case. */
|
||||||
if (rxSize == 0)
|
if (rxSize == 0)
|
||||||
{
|
{
|
||||||
/* Read the final byte. */
|
if (!(flags & kI2C_TransferNoStopFlag))
|
||||||
|
{
|
||||||
|
/* Issue STOP command before reading last byte. */
|
||||||
result = I2C_MasterStop(base);
|
result = I2C_MasterStop(base);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Change direction to Tx to avoid extra clocks. */
|
||||||
|
base->C1 |= I2C_C1_TX_MASK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (rxSize == 1)
|
if (rxSize == 1)
|
||||||
{
|
{
|
||||||
|
@ -840,19 +949,42 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if there's transfer error. */
|
||||||
|
result = I2C_CheckAndClearError(base, base->S);
|
||||||
|
|
||||||
|
/* Return if error. */
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
if (result == kStatus_I2C_Nak)
|
||||||
|
{
|
||||||
|
result = kStatus_I2C_Addr_Nak;
|
||||||
|
|
||||||
|
I2C_MasterStop(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* Send subaddress. */
|
/* Send subaddress. */
|
||||||
if (xfer->subaddressSize)
|
if (xfer->subaddressSize)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
/* Clear interrupt pending flag. */
|
||||||
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
|
xfer->subaddressSize--;
|
||||||
|
base->D = ((xfer->subaddress) >> (8 * xfer->subaddressSize));
|
||||||
|
|
||||||
/* Wait until data transfer complete. */
|
/* Wait until data transfer complete. */
|
||||||
while (!(base->S & kI2C_IntPendingFlag))
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear interrupt pending flag. */
|
|
||||||
base->S = kI2C_IntPendingFlag;
|
|
||||||
|
|
||||||
/* Check if there's transfer error. */
|
/* Check if there's transfer error. */
|
||||||
result = I2C_CheckAndClearError(base, base->S);
|
result = I2C_CheckAndClearError(base, base->S);
|
||||||
|
|
||||||
|
@ -866,34 +998,13 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
xfer->subaddressSize--;
|
|
||||||
base->D = ((xfer->subaddress) >> (8 * xfer->subaddressSize));
|
|
||||||
|
|
||||||
} while ((xfer->subaddressSize > 0) && (result == kStatus_Success));
|
} while ((xfer->subaddressSize > 0) && (result == kStatus_Success));
|
||||||
|
|
||||||
if (xfer->direction == kI2C_Read)
|
if (xfer->direction == kI2C_Read)
|
||||||
{
|
{
|
||||||
/* Wait until data transfer complete. */
|
|
||||||
while (!(base->S & kI2C_IntPendingFlag))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear pending flag. */
|
/* Clear pending flag. */
|
||||||
base->S = kI2C_IntPendingFlag;
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
/* Check if there's transfer error. */
|
|
||||||
result = I2C_CheckAndClearError(base, base->S);
|
|
||||||
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
if (result == kStatus_I2C_Nak)
|
|
||||||
{
|
|
||||||
I2C_MasterStop(base);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send repeated start and slave address. */
|
/* Send repeated start and slave address. */
|
||||||
result = I2C_MasterRepeatedStart(base, xfer->slaveAddress, kI2C_Read);
|
result = I2C_MasterRepeatedStart(base, xfer->slaveAddress, kI2C_Read);
|
||||||
|
|
||||||
|
@ -902,10 +1013,8 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait until address + command transfer complete. */
|
/* Wait until data transfer complete. */
|
||||||
while (!(base->S & kI2C_IntPendingFlag))
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -913,37 +1022,31 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
|
||||||
/* Check if there's transfer error. */
|
/* Check if there's transfer error. */
|
||||||
result = I2C_CheckAndClearError(base, base->S);
|
result = I2C_CheckAndClearError(base, base->S);
|
||||||
|
|
||||||
/* Return if error. */
|
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
if (result == kStatus_I2C_Nak)
|
if (result == kStatus_I2C_Nak)
|
||||||
{
|
{
|
||||||
|
result = kStatus_I2C_Addr_Nak;
|
||||||
|
|
||||||
I2C_MasterStop(base);
|
I2C_MasterStop(base);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Transmit data. */
|
/* Transmit data. */
|
||||||
if ((xfer->direction == kI2C_Write) && (xfer->dataSize > 0))
|
if ((xfer->direction == kI2C_Write) && (xfer->dataSize > 0))
|
||||||
{
|
{
|
||||||
/* Send Data. */
|
/* Send Data. */
|
||||||
result = I2C_MasterWriteBlocking(base, xfer->data, xfer->dataSize);
|
result = I2C_MasterWriteBlocking(base, xfer->data, xfer->dataSize, xfer->flags);
|
||||||
|
|
||||||
if (((result == kStatus_Success) && (!(xfer->flags & kI2C_TransferNoStopFlag))) || (result == kStatus_I2C_Nak))
|
|
||||||
{
|
|
||||||
/* Clear the IICIF flag. */
|
|
||||||
base->S = kI2C_IntPendingFlag;
|
|
||||||
|
|
||||||
/* Send stop. */
|
|
||||||
result = I2C_MasterStop(base);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Receive Data. */
|
/* Receive Data. */
|
||||||
if ((xfer->direction == kI2C_Read) && (xfer->dataSize > 0))
|
if ((xfer->direction == kI2C_Read) && (xfer->dataSize > 0))
|
||||||
{
|
{
|
||||||
result = I2C_MasterReadBlocking(base, xfer->data, xfer->dataSize);
|
result = I2C_MasterReadBlocking(base, xfer->data, xfer->dataSize, xfer->flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -1006,11 +1109,37 @@ void I2C_MasterTransferAbort(I2C_Type *base, i2c_master_handle_t *handle)
|
||||||
{
|
{
|
||||||
assert(handle);
|
assert(handle);
|
||||||
|
|
||||||
|
volatile uint8_t dummy = 0;
|
||||||
|
|
||||||
|
/* Add this to avoid build warning. */
|
||||||
|
dummy++;
|
||||||
|
|
||||||
/* Disable interrupt. */
|
/* Disable interrupt. */
|
||||||
I2C_DisableInterrupts(base, kI2C_GlobalInterruptEnable);
|
I2C_DisableInterrupts(base, kI2C_GlobalInterruptEnable);
|
||||||
|
|
||||||
/* Reset the state to idle. */
|
/* Reset the state to idle. */
|
||||||
handle->state = kIdleState;
|
handle->state = kIdleState;
|
||||||
|
|
||||||
|
/* Send STOP signal. */
|
||||||
|
if (handle->transfer.direction == kI2C_Read)
|
||||||
|
{
|
||||||
|
base->C1 |= I2C_C1_TXAK_MASK;
|
||||||
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
|
base->C1 &= ~(I2C_C1_MST_MASK | I2C_C1_TX_MASK | I2C_C1_TXAK_MASK);
|
||||||
|
dummy = base->D;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
base->C1 &= ~(I2C_C1_MST_MASK | I2C_C1_TX_MASK | I2C_C1_TXAK_MASK);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t I2C_MasterTransferGetCount(I2C_Type *base, i2c_master_handle_t *handle, size_t *count)
|
status_t I2C_MasterTransferGetCount(I2C_Type *base, i2c_master_handle_t *handle, size_t *count)
|
||||||
|
@ -1044,7 +1173,8 @@ void I2C_MasterTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
if (isDone || result)
|
if (isDone || result)
|
||||||
{
|
{
|
||||||
/* Send stop command if transfer done or received Nak. */
|
/* Send stop command if transfer done or received Nak. */
|
||||||
if ((!(handle->transfer.flags & kI2C_TransferNoStopFlag)) || (result == kStatus_I2C_Nak))
|
if ((!(handle->transfer.flags & kI2C_TransferNoStopFlag)) || (result == kStatus_I2C_Nak) ||
|
||||||
|
(result == kStatus_I2C_Addr_Nak))
|
||||||
{
|
{
|
||||||
/* Ensure stop command is a need. */
|
/* Ensure stop command is a need. */
|
||||||
if ((base->C1 & I2C_C1_MST_MASK))
|
if ((base->C1 & I2C_C1_MST_MASK))
|
||||||
|
@ -1070,13 +1200,28 @@ void I2C_MasterTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig)
|
void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig, uint32_t srcClock_Hz)
|
||||||
{
|
{
|
||||||
assert(slaveConfig);
|
assert(slaveConfig);
|
||||||
|
|
||||||
uint8_t tmpReg;
|
uint8_t tmpReg;
|
||||||
|
|
||||||
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||||
CLOCK_EnableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
CLOCK_EnableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
||||||
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||||
|
|
||||||
|
/* Reset the module. */
|
||||||
|
base->A1 = 0;
|
||||||
|
base->F = 0;
|
||||||
|
base->C1 = 0;
|
||||||
|
base->S = 0xFFU;
|
||||||
|
base->C2 = 0;
|
||||||
|
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||||
|
base->FLT = 0x50U;
|
||||||
|
#elif defined(FSL_FEATURE_I2C_HAS_STOP_DETECT) && FSL_FEATURE_I2C_HAS_STOP_DETECT
|
||||||
|
base->FLT = 0x40U;
|
||||||
|
#endif
|
||||||
|
base->RA = 0;
|
||||||
|
|
||||||
/* Configure addressing mode. */
|
/* Configure addressing mode. */
|
||||||
switch (slaveConfig->addressingMode)
|
switch (slaveConfig->addressingMode)
|
||||||
|
@ -1101,15 +1246,20 @@ void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig)
|
||||||
tmpReg &= ~I2C_C1_WUEN_MASK;
|
tmpReg &= ~I2C_C1_WUEN_MASK;
|
||||||
base->C1 = tmpReg | I2C_C1_WUEN(slaveConfig->enableWakeUp) | I2C_C1_IICEN(slaveConfig->enableSlave);
|
base->C1 = tmpReg | I2C_C1_WUEN(slaveConfig->enableWakeUp) | I2C_C1_IICEN(slaveConfig->enableSlave);
|
||||||
|
|
||||||
/* Configure general call & baud rate control & high drive feature. */
|
/* Configure general call & baud rate control. */
|
||||||
tmpReg = base->C2;
|
tmpReg = base->C2;
|
||||||
tmpReg &= ~(I2C_C2_SBRC_MASK | I2C_C2_GCAEN_MASK);
|
tmpReg &= ~(I2C_C2_SBRC_MASK | I2C_C2_GCAEN_MASK);
|
||||||
tmpReg |= I2C_C2_SBRC(slaveConfig->enableBaudRateCtl) | I2C_C2_GCAEN(slaveConfig->enableGeneralCall);
|
tmpReg |= I2C_C2_SBRC(slaveConfig->enableBaudRateCtl) | I2C_C2_GCAEN(slaveConfig->enableGeneralCall);
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
tmpReg &= ~I2C_C2_HDRS_MASK;
|
|
||||||
tmpReg |= I2C_C2_HDRS(slaveConfig->enableHighDrive);
|
|
||||||
#endif
|
|
||||||
base->C2 = tmpReg;
|
base->C2 = tmpReg;
|
||||||
|
|
||||||
|
/* Enable/Disable double buffering. */
|
||||||
|
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
||||||
|
tmpReg = base->S2 & (~I2C_S2_DFEN_MASK);
|
||||||
|
base->S2 = tmpReg | I2C_S2_DFEN(slaveConfig->enableDoubleBuffering);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Set hold time. */
|
||||||
|
I2C_SetHoldTime(base, slaveConfig->sclStopHoldTime_ns, srcClock_Hz);
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2C_SlaveDeinit(I2C_Type *base)
|
void I2C_SlaveDeinit(I2C_Type *base)
|
||||||
|
@ -1117,8 +1267,10 @@ void I2C_SlaveDeinit(I2C_Type *base)
|
||||||
/* Disable I2C module. */
|
/* Disable I2C module. */
|
||||||
I2C_Enable(base, false);
|
I2C_Enable(base, false);
|
||||||
|
|
||||||
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||||
/* Disable I2C clock. */
|
/* Disable I2C clock. */
|
||||||
CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
||||||
|
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig)
|
void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig)
|
||||||
|
@ -1134,48 +1286,106 @@ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig)
|
||||||
/* Slave address match waking up MCU from low power mode is disabled. */
|
/* Slave address match waking up MCU from low power mode is disabled. */
|
||||||
slaveConfig->enableWakeUp = false;
|
slaveConfig->enableWakeUp = false;
|
||||||
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
/* Default pin high drive is disabled. */
|
|
||||||
slaveConfig->enableHighDrive = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Independent slave mode baud rate at maximum frequency is disabled. */
|
/* Independent slave mode baud rate at maximum frequency is disabled. */
|
||||||
slaveConfig->enableBaudRateCtl = false;
|
slaveConfig->enableBaudRateCtl = false;
|
||||||
|
|
||||||
|
/* Default enable double buffering. */
|
||||||
|
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
||||||
|
slaveConfig->enableDoubleBuffering = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Set default SCL stop hold time to 4us which is minimum requirement in I2C spec. */
|
||||||
|
slaveConfig->sclStopHoldTime_ns = 4000;
|
||||||
|
|
||||||
/* Enable the I2C peripheral. */
|
/* Enable the I2C peripheral. */
|
||||||
slaveConfig->enableSlave = true;
|
slaveConfig->enableSlave = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t I2C_SlaveWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize)
|
status_t I2C_SlaveWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize)
|
||||||
{
|
{
|
||||||
return I2C_MasterWriteBlocking(base, txBuff, txSize);
|
status_t result = kStatus_Success;
|
||||||
|
volatile uint8_t dummy = 0;
|
||||||
|
|
||||||
|
/* Add this to avoid build warning. */
|
||||||
|
dummy++;
|
||||||
|
|
||||||
|
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||||
|
/* Check start flag. */
|
||||||
|
while (!(base->FLT & I2C_FLT_STARTF_MASK))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
/* Clear STARTF flag. */
|
||||||
|
base->FLT |= I2C_FLT_STARTF_MASK;
|
||||||
|
/* Clear the IICIF flag. */
|
||||||
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
#endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */
|
||||||
|
|
||||||
|
/* Wait for address match flag. */
|
||||||
|
while (!(base->S & kI2C_AddressMatchFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read dummy to release bus. */
|
||||||
|
dummy = base->D;
|
||||||
|
|
||||||
|
result = I2C_MasterWriteBlocking(base, txBuff, txSize, kI2C_TransferDefaultFlag);
|
||||||
|
|
||||||
|
/* Switch to receive mode. */
|
||||||
|
base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK);
|
||||||
|
|
||||||
|
/* Read dummy to release bus. */
|
||||||
|
dummy = base->D;
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2C_SlaveReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize)
|
void I2C_SlaveReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize)
|
||||||
{
|
{
|
||||||
/* Clear the IICIF flag. */
|
volatile uint8_t dummy = 0;
|
||||||
base->S = kI2C_IntPendingFlag;
|
|
||||||
|
|
||||||
/* Wait until the data register is ready for receive. */
|
/* Add this to avoid build warning. */
|
||||||
while (!(base->S & kI2C_TransferCompleteFlag))
|
dummy++;
|
||||||
|
|
||||||
|
/* Wait until address match. */
|
||||||
|
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||||
|
/* Check start flag. */
|
||||||
|
while (!(base->FLT & I2C_FLT_STARTF_MASK))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
/* Clear STARTF flag. */
|
||||||
|
base->FLT |= I2C_FLT_STARTF_MASK;
|
||||||
|
/* Clear the IICIF flag. */
|
||||||
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
#endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */
|
||||||
|
|
||||||
|
/* Wait for address match and int pending flag. */
|
||||||
|
while (!(base->S & kI2C_AddressMatchFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read dummy to release bus. */
|
||||||
|
dummy = base->D;
|
||||||
|
|
||||||
|
/* Clear the IICIF flag. */
|
||||||
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
/* Setup the I2C peripheral to receive data. */
|
/* Setup the I2C peripheral to receive data. */
|
||||||
base->C1 &= ~(I2C_C1_TX_MASK);
|
base->C1 &= ~(I2C_C1_TX_MASK);
|
||||||
|
|
||||||
while (rxSize--)
|
while (rxSize--)
|
||||||
{
|
{
|
||||||
|
/* Wait until data transfer complete. */
|
||||||
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
/* Clear the IICIF flag. */
|
/* Clear the IICIF flag. */
|
||||||
base->S = kI2C_IntPendingFlag;
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
/* Read from the data register. */
|
/* Read from the data register. */
|
||||||
*rxBuff++ = base->D;
|
*rxBuff++ = base->D;
|
||||||
|
|
||||||
/* Wait until data transfer complete. */
|
|
||||||
while (!(base->S & kI2C_IntPendingFlag))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1226,7 +1436,7 @@ status_t I2C_SlaveTransferNonBlocking(I2C_Type *base, i2c_slave_handle_t *handle
|
||||||
handle->isBusy = true;
|
handle->isBusy = true;
|
||||||
|
|
||||||
/* Set up event mask. tx and rx are always enabled. */
|
/* Set up event mask. tx and rx are always enabled. */
|
||||||
handle->eventMask = eventMask | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent;
|
handle->eventMask = eventMask | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent | kI2C_SlaveGenaralcallEvent;
|
||||||
|
|
||||||
/* Clear all flags. */
|
/* Clear all flags. */
|
||||||
I2C_SlaveClearStatusFlags(base, kClearFlags);
|
I2C_SlaveClearStatusFlags(base, kClearFlags);
|
||||||
|
@ -1315,8 +1525,11 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(status & kI2C_AddressMatchFlag))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif /* I2C_HAS_STOP_DETECT */
|
#endif /* I2C_HAS_STOP_DETECT */
|
||||||
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||||
|
@ -1328,7 +1541,7 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
/* Clear the interrupt flag. */
|
/* Clear the interrupt flag. */
|
||||||
base->S = kI2C_IntPendingFlag;
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
xfer->event = kI2C_SlaveRepeatedStartEvent;
|
xfer->event = kI2C_SlaveStartEvent;
|
||||||
|
|
||||||
if ((handle->eventMask & xfer->event) && (handle->callback))
|
if ((handle->eventMask & xfer->event) && (handle->callback))
|
||||||
{
|
{
|
||||||
|
@ -1385,31 +1598,12 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
handle->isBusy = true;
|
handle->isBusy = true;
|
||||||
xfer->event = kI2C_SlaveAddressMatchEvent;
|
xfer->event = kI2C_SlaveAddressMatchEvent;
|
||||||
|
|
||||||
if ((handle->eventMask & xfer->event) && (handle->callback))
|
|
||||||
{
|
|
||||||
handle->callback(base, xfer, handle->userData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Slave transmit, master reading from slave. */
|
/* Slave transmit, master reading from slave. */
|
||||||
if (status & kI2C_TransferDirectionFlag)
|
if (status & kI2C_TransferDirectionFlag)
|
||||||
{
|
{
|
||||||
/* Change direction to send data. */
|
/* Change direction to send data. */
|
||||||
base->C1 |= I2C_C1_TX_MASK;
|
base->C1 |= I2C_C1_TX_MASK;
|
||||||
|
|
||||||
/* If we're out of data, invoke callback to get more. */
|
|
||||||
if ((!xfer->data) || (!xfer->dataSize))
|
|
||||||
{
|
|
||||||
xfer->event = kI2C_SlaveTransmitEvent;
|
|
||||||
|
|
||||||
if (handle->callback)
|
|
||||||
{
|
|
||||||
handle->callback(base, xfer, handle->userData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear the transferred count now that we have a new buffer. */
|
|
||||||
xfer->transferredCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
doTransmit = true;
|
doTransmit = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1417,6 +1611,30 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
/* Slave receive, master writing to slave. */
|
/* Slave receive, master writing to slave. */
|
||||||
base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK);
|
base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK);
|
||||||
|
|
||||||
|
/* Read dummy to release the bus. */
|
||||||
|
dummy = base->D;
|
||||||
|
|
||||||
|
if (dummy == 0)
|
||||||
|
{
|
||||||
|
xfer->event = kI2C_SlaveGenaralcallEvent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((handle->eventMask & xfer->event) && (handle->callback))
|
||||||
|
{
|
||||||
|
handle->callback(base, xfer, handle->userData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Check transfer complete flag. */
|
||||||
|
else if (status & kI2C_TransferCompleteFlag)
|
||||||
|
{
|
||||||
|
/* Slave transmit, master reading from slave. */
|
||||||
|
if (status & kI2C_TransferDirectionFlag)
|
||||||
|
{
|
||||||
|
doTransmit = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* If we're out of data, invoke callback to get more. */
|
/* If we're out of data, invoke callback to get more. */
|
||||||
if ((!xfer->data) || (!xfer->dataSize))
|
if ((!xfer->data) || (!xfer->dataSize))
|
||||||
{
|
{
|
||||||
|
@ -1431,20 +1649,6 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
xfer->transferredCount = 0;
|
xfer->transferredCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read dummy to release the bus. */
|
|
||||||
dummy = base->D;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Check transfer complete flag. */
|
|
||||||
else if (status & kI2C_TransferCompleteFlag)
|
|
||||||
{
|
|
||||||
/* Slave transmit, master reading from slave. */
|
|
||||||
if (status & kI2C_TransferDirectionFlag)
|
|
||||||
{
|
|
||||||
doTransmit = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Slave receive, master writing to slave. */
|
/* Slave receive, master writing to slave. */
|
||||||
uint8_t data = base->D;
|
uint8_t data = base->D;
|
||||||
|
|
||||||
|
@ -1480,6 +1684,20 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
/* Send data if there is the need. */
|
/* Send data if there is the need. */
|
||||||
if (doTransmit)
|
if (doTransmit)
|
||||||
{
|
{
|
||||||
|
/* If we're out of data, invoke callback to get more. */
|
||||||
|
if ((!xfer->data) || (!xfer->dataSize))
|
||||||
|
{
|
||||||
|
xfer->event = kI2C_SlaveTransmitEvent;
|
||||||
|
|
||||||
|
if (handle->callback)
|
||||||
|
{
|
||||||
|
handle->callback(base, xfer, handle->userData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear the transferred count now that we have a new buffer. */
|
||||||
|
xfer->transferredCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (handle->transfer.dataSize)
|
if (handle->transfer.dataSize)
|
||||||
{
|
{
|
||||||
/* Send data. */
|
/* Send data. */
|
||||||
|
@ -1510,27 +1728,30 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(I2C0)
|
||||||
void I2C0_DriverIRQHandler(void)
|
void I2C0_DriverIRQHandler(void)
|
||||||
{
|
{
|
||||||
I2C_TransferCommonIRQHandler(I2C0, s_i2cHandle[0]);
|
I2C_TransferCommonIRQHandler(I2C0, s_i2cHandle[0]);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (FSL_FEATURE_SOC_I2C_COUNT > 1)
|
#if defined(I2C1)
|
||||||
void I2C1_DriverIRQHandler(void)
|
void I2C1_DriverIRQHandler(void)
|
||||||
{
|
{
|
||||||
I2C_TransferCommonIRQHandler(I2C1, s_i2cHandle[1]);
|
I2C_TransferCommonIRQHandler(I2C1, s_i2cHandle[1]);
|
||||||
}
|
}
|
||||||
#endif /* I2C COUNT > 1 */
|
#endif
|
||||||
|
|
||||||
#if (FSL_FEATURE_SOC_I2C_COUNT > 2)
|
#if defined(I2C2)
|
||||||
void I2C2_DriverIRQHandler(void)
|
void I2C2_DriverIRQHandler(void)
|
||||||
{
|
{
|
||||||
I2C_TransferCommonIRQHandler(I2C2, s_i2cHandle[2]);
|
I2C_TransferCommonIRQHandler(I2C2, s_i2cHandle[2]);
|
||||||
}
|
}
|
||||||
#endif /* I2C COUNT > 2 */
|
#endif
|
||||||
#if (FSL_FEATURE_SOC_I2C_COUNT > 3)
|
|
||||||
|
#if defined(I2C3)
|
||||||
void I2C3_DriverIRQHandler(void)
|
void I2C3_DriverIRQHandler(void)
|
||||||
{
|
{
|
||||||
I2C_TransferCommonIRQHandler(I2C3, s_i2cHandle[3]);
|
I2C_TransferCommonIRQHandler(I2C3, s_i2cHandle[3]);
|
||||||
}
|
}
|
||||||
#endif /* I2C COUNT > 3 */
|
#endif
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||||
* All rights reserved.
|
* Copyright 2016-2017 NXP
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
* other materials provided with the distribution.
|
* other materials provided with the distribution.
|
||||||
*
|
*
|
||||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
* o Neither the name of the copyright holder nor the names of its
|
||||||
* contributors may be used to endorse or promote products derived from this
|
* contributors may be used to endorse or promote products derived from this
|
||||||
* software without specific prior written permission.
|
* software without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -37,16 +37,14 @@
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*! @file */
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Definitions
|
* Definitions
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
/*! @name Driver version */
|
/*! @name Driver version */
|
||||||
/*@{*/
|
/*@{*/
|
||||||
/*! @brief I2C driver version 2.0.0. */
|
/*! @brief I2C driver version 2.0.3. */
|
||||||
#define FSL_I2C_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
|
#define FSL_I2C_DRIVER_VERSION (MAKE_VERSION(2, 0, 3))
|
||||||
/*@}*/
|
/*@}*/
|
||||||
|
|
||||||
#if (defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT || \
|
#if (defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT || \
|
||||||
|
@ -62,6 +60,7 @@ enum _i2c_status
|
||||||
kStatus_I2C_Nak = MAKE_STATUS(kStatusGroup_I2C, 2), /*!< NAK received during transfer. */
|
kStatus_I2C_Nak = MAKE_STATUS(kStatusGroup_I2C, 2), /*!< NAK received during transfer. */
|
||||||
kStatus_I2C_ArbitrationLost = MAKE_STATUS(kStatusGroup_I2C, 3), /*!< Arbitration lost during transfer. */
|
kStatus_I2C_ArbitrationLost = MAKE_STATUS(kStatusGroup_I2C, 3), /*!< Arbitration lost during transfer. */
|
||||||
kStatus_I2C_Timeout = MAKE_STATUS(kStatusGroup_I2C, 4), /*!< Wait event timeout. */
|
kStatus_I2C_Timeout = MAKE_STATUS(kStatusGroup_I2C, 4), /*!< Wait event timeout. */
|
||||||
|
kStatus_I2C_Addr_Nak = MAKE_STATUS(kStatusGroup_I2C, 5), /*!< NAK received during the address probe. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -109,11 +108,11 @@ enum _i2c_interrupt_enable
|
||||||
#endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */
|
#endif /* FSL_FEATURE_I2C_HAS_START_STOP_DETECT */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! @brief Direction of master and slave transfers. */
|
/*! @brief The direction of master and slave transfers. */
|
||||||
typedef enum _i2c_direction
|
typedef enum _i2c_direction
|
||||||
{
|
{
|
||||||
kI2C_Write = 0x0U, /*!< Master transmit to slave. */
|
kI2C_Write = 0x0U, /*!< Master transmits to the slave. */
|
||||||
kI2C_Read = 0x1U, /*!< Master receive from slave. */
|
kI2C_Read = 0x1U, /*!< Master receives from the slave. */
|
||||||
} i2c_direction_t;
|
} i2c_direction_t;
|
||||||
|
|
||||||
/*! @brief Addressing mode. */
|
/*! @brief Addressing mode. */
|
||||||
|
@ -126,17 +125,17 @@ typedef enum _i2c_slave_address_mode
|
||||||
/*! @brief I2C transfer control flag. */
|
/*! @brief I2C transfer control flag. */
|
||||||
enum _i2c_master_transfer_flags
|
enum _i2c_master_transfer_flags
|
||||||
{
|
{
|
||||||
kI2C_TransferDefaultFlag = 0x0U, /*!< Transfer starts with a start signal, stops with a stop signal. */
|
kI2C_TransferDefaultFlag = 0x0U, /*!< A transfer starts with a start signal, stops with a stop signal. */
|
||||||
kI2C_TransferNoStartFlag = 0x1U, /*!< Transfer starts without a start signal. */
|
kI2C_TransferNoStartFlag = 0x1U, /*!< A transfer starts without a start signal. */
|
||||||
kI2C_TransferRepeatedStartFlag = 0x2U, /*!< Transfer starts with a repeated start signal. */
|
kI2C_TransferRepeatedStartFlag = 0x2U, /*!< A transfer starts with a repeated start signal. */
|
||||||
kI2C_TransferNoStopFlag = 0x4U, /*!< Transfer ends without a stop signal. */
|
kI2C_TransferNoStopFlag = 0x4U, /*!< A transfer ends without a stop signal. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Set of events sent to the callback for nonblocking slave transfers.
|
* @brief Set of events sent to the callback for nonblocking slave transfers.
|
||||||
*
|
*
|
||||||
* These event enumerations are used for two related purposes. First, a bit mask created by OR'ing together
|
* These event enumerations are used for two related purposes. First, a bit mask created by OR'ing together
|
||||||
* events is passed to I2C_SlaveTransferNonBlocking() in order to specify which events to enable.
|
* events is passed to I2C_SlaveTransferNonBlocking() to specify which events to enable.
|
||||||
* Then, when the slave callback is invoked, it is passed the current event through its @a transfer
|
* Then, when the slave callback is invoked, it is passed the current event through its @a transfer
|
||||||
* parameter.
|
* parameter.
|
||||||
*
|
*
|
||||||
|
@ -145,33 +144,35 @@ enum _i2c_master_transfer_flags
|
||||||
typedef enum _i2c_slave_transfer_event
|
typedef enum _i2c_slave_transfer_event
|
||||||
{
|
{
|
||||||
kI2C_SlaveAddressMatchEvent = 0x01U, /*!< Received the slave address after a start or repeated start. */
|
kI2C_SlaveAddressMatchEvent = 0x01U, /*!< Received the slave address after a start or repeated start. */
|
||||||
kI2C_SlaveTransmitEvent = 0x02U, /*!< Callback is requested to provide data to transmit
|
kI2C_SlaveTransmitEvent = 0x02U, /*!< A callback is requested to provide data to transmit
|
||||||
(slave-transmitter role). */
|
(slave-transmitter role). */
|
||||||
kI2C_SlaveReceiveEvent = 0x04U, /*!< Callback is requested to provide a buffer in which to place received
|
kI2C_SlaveReceiveEvent = 0x04U, /*!< A callback is requested to provide a buffer in which to place received
|
||||||
data (slave-receiver role). */
|
data (slave-receiver role). */
|
||||||
kI2C_SlaveTransmitAckEvent = 0x08U, /*!< Callback needs to either transmit an ACK or NACK. */
|
kI2C_SlaveTransmitAckEvent = 0x08U, /*!< A callback needs to either transmit an ACK or NACK. */
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||||
kI2C_SlaveRepeatedStartEvent = 0x10U, /*!< A repeated start was detected. */
|
kI2C_SlaveStartEvent = 0x10U, /*!< A start/repeated start was detected. */
|
||||||
#endif
|
#endif
|
||||||
kI2C_SlaveCompletionEvent = 0x20U, /*!< A stop was detected or finished transfer, completing the transfer. */
|
kI2C_SlaveCompletionEvent = 0x20U, /*!< A stop was detected or finished transfer, completing the transfer. */
|
||||||
|
kI2C_SlaveGenaralcallEvent = 0x40U, /*!< Received the general call address after a start or repeated start. */
|
||||||
|
|
||||||
/*! Bit mask of all available events. */
|
/*! A bit mask of all available events. */
|
||||||
kI2C_SlaveAllEvents = kI2C_SlaveAddressMatchEvent | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent |
|
kI2C_SlaveAllEvents = kI2C_SlaveAddressMatchEvent | kI2C_SlaveTransmitEvent | kI2C_SlaveReceiveEvent |
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||||
kI2C_SlaveRepeatedStartEvent |
|
kI2C_SlaveStartEvent |
|
||||||
#endif
|
#endif
|
||||||
kI2C_SlaveCompletionEvent,
|
kI2C_SlaveCompletionEvent | kI2C_SlaveGenaralcallEvent,
|
||||||
} i2c_slave_transfer_event_t;
|
} i2c_slave_transfer_event_t;
|
||||||
|
|
||||||
/*! @brief I2C master user configuration. */
|
/*! @brief I2C master user configuration. */
|
||||||
typedef struct _i2c_master_config
|
typedef struct _i2c_master_config
|
||||||
{
|
{
|
||||||
bool enableMaster; /*!< Enables the I2C peripheral at initialization time. */
|
bool enableMaster; /*!< Enables the I2C peripheral at initialization time. */
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
|
||||||
bool enableHighDrive; /*!< Controls the drive capability of the I2C pads. */
|
|
||||||
#endif
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF
|
#if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF
|
||||||
bool enableStopHold; /*!< Controls the stop hold enable. */
|
bool enableStopHold; /*!< Controls the stop hold enable. */
|
||||||
|
#endif
|
||||||
|
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
||||||
|
bool enableDoubleBuffering; /*!< Controls double buffer enable; notice that
|
||||||
|
enabling the double buffer disables the clock stretch. */
|
||||||
#endif
|
#endif
|
||||||
uint32_t baudRate_Bps; /*!< Baud rate configuration of I2C peripheral. */
|
uint32_t baudRate_Bps; /*!< Baud rate configuration of I2C peripheral. */
|
||||||
uint8_t glitchFilterWidth; /*!< Controls the width of the glitch. */
|
uint8_t glitchFilterWidth; /*!< Controls the width of the glitch. */
|
||||||
|
@ -181,15 +182,20 @@ typedef struct _i2c_master_config
|
||||||
typedef struct _i2c_slave_config
|
typedef struct _i2c_slave_config
|
||||||
{
|
{
|
||||||
bool enableSlave; /*!< Enables the I2C peripheral at initialization time. */
|
bool enableSlave; /*!< Enables the I2C peripheral at initialization time. */
|
||||||
bool enableGeneralCall; /*!< Enable general call addressing mode. */
|
bool enableGeneralCall; /*!< Enables the general call addressing mode. */
|
||||||
bool enableWakeUp; /*!< Enables/disables waking up MCU from low power mode. */
|
bool enableWakeUp; /*!< Enables/disables waking up MCU from low-power mode. */
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION) && FSL_FEATURE_I2C_HAS_HIGH_DRIVE_SELECTION
|
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
||||||
bool enableHighDrive; /*!< Controls the drive capability of the I2C pads. */
|
bool enableDoubleBuffering; /*!< Controls a double buffer enable; notice that
|
||||||
|
enabling the double buffer disables the clock stretch. */
|
||||||
#endif
|
#endif
|
||||||
bool enableBaudRateCtl; /*!< Enables/disables independent slave baud rate on SCL in very fast I2C modes. */
|
bool enableBaudRateCtl; /*!< Enables/disables independent slave baud rate on SCL in very fast I2C modes. */
|
||||||
uint16_t slaveAddress; /*!< Slave address configuration. */
|
uint16_t slaveAddress; /*!< A slave address configuration. */
|
||||||
uint16_t upperAddress; /*!< Maximum boundary slave address used in range matching mode. */
|
uint16_t upperAddress; /*!< A maximum boundary slave address used in a range matching mode. */
|
||||||
i2c_slave_address_mode_t addressingMode; /*!< Addressing mode configuration of i2c_slave_address_mode_config_t. */
|
i2c_slave_address_mode_t
|
||||||
|
addressingMode; /*!< An addressing mode configuration of i2c_slave_address_mode_config_t. */
|
||||||
|
uint32_t sclStopHoldTime_ns; /*!< the delay from the rising edge of SCL (I2C clock) to the rising edge of SDA (I2C
|
||||||
|
data) while SCL is high (stop condition), SDA hold time and SCL start hold time
|
||||||
|
are also configured according to the SCL stop hold time. */
|
||||||
} i2c_slave_config_t;
|
} i2c_slave_config_t;
|
||||||
|
|
||||||
/*! @brief I2C master handle typedef. */
|
/*! @brief I2C master handle typedef. */
|
||||||
|
@ -207,13 +213,13 @@ typedef struct _i2c_slave_handle i2c_slave_handle_t;
|
||||||
/*! @brief I2C master transfer structure. */
|
/*! @brief I2C master transfer structure. */
|
||||||
typedef struct _i2c_master_transfer
|
typedef struct _i2c_master_transfer
|
||||||
{
|
{
|
||||||
uint32_t flags; /*!< Transfer flag which controls the transfer. */
|
uint32_t flags; /*!< A transfer flag which controls the transfer. */
|
||||||
uint8_t slaveAddress; /*!< 7-bit slave address. */
|
uint8_t slaveAddress; /*!< 7-bit slave address. */
|
||||||
i2c_direction_t direction; /*!< Transfer direction, read or write. */
|
i2c_direction_t direction; /*!< A transfer direction, read or write. */
|
||||||
uint32_t subaddress; /*!< Sub address. Transferred MSB first. */
|
uint32_t subaddress; /*!< A sub address. Transferred MSB first. */
|
||||||
uint8_t subaddressSize; /*!< Size of command buffer. */
|
uint8_t subaddressSize; /*!< A size of the command buffer. */
|
||||||
uint8_t *volatile data; /*!< Transfer buffer. */
|
uint8_t *volatile data; /*!< A transfer buffer. */
|
||||||
volatile size_t dataSize; /*!< Transfer size. */
|
volatile size_t dataSize; /*!< A transfer size. */
|
||||||
} i2c_master_transfer_t;
|
} i2c_master_transfer_t;
|
||||||
|
|
||||||
/*! @brief I2C master handle structure. */
|
/*! @brief I2C master handle structure. */
|
||||||
|
@ -221,20 +227,21 @@ struct _i2c_master_handle
|
||||||
{
|
{
|
||||||
i2c_master_transfer_t transfer; /*!< I2C master transfer copy. */
|
i2c_master_transfer_t transfer; /*!< I2C master transfer copy. */
|
||||||
size_t transferSize; /*!< Total bytes to be transferred. */
|
size_t transferSize; /*!< Total bytes to be transferred. */
|
||||||
uint8_t state; /*!< Transfer state maintained during transfer. */
|
uint8_t state; /*!< A transfer state maintained during transfer. */
|
||||||
i2c_master_transfer_callback_t completionCallback; /*!< Callback function called when transfer finished. */
|
i2c_master_transfer_callback_t completionCallback; /*!< A callback function called when the transfer is finished. */
|
||||||
void *userData; /*!< Callback parameter passed to callback function. */
|
void *userData; /*!< A callback parameter passed to the callback function. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! @brief I2C slave transfer structure. */
|
/*! @brief I2C slave transfer structure. */
|
||||||
typedef struct _i2c_slave_transfer
|
typedef struct _i2c_slave_transfer
|
||||||
{
|
{
|
||||||
i2c_slave_transfer_event_t event; /*!< Reason the callback is being invoked. */
|
i2c_slave_transfer_event_t event; /*!< A reason that the callback is invoked. */
|
||||||
uint8_t *volatile data; /*!< Transfer buffer. */
|
uint8_t *volatile data; /*!< A transfer buffer. */
|
||||||
volatile size_t dataSize; /*!< Transfer size. */
|
volatile size_t dataSize; /*!< A transfer size. */
|
||||||
status_t completionStatus; /*!< Success or error code describing how the transfer completed. Only applies for
|
status_t completionStatus; /*!< Success or error code describing how the transfer completed. Only applies for
|
||||||
#kI2C_SlaveCompletionEvent. */
|
#kI2C_SlaveCompletionEvent. */
|
||||||
size_t transferredCount; /*!< Number of bytes actually transferred since start or last repeated start. */
|
size_t transferredCount; /*!< A number of bytes actually transferred since the start or since the last repeated
|
||||||
|
start. */
|
||||||
} i2c_slave_transfer_t;
|
} i2c_slave_transfer_t;
|
||||||
|
|
||||||
/*! @brief I2C slave transfer callback typedef. */
|
/*! @brief I2C slave transfer callback typedef. */
|
||||||
|
@ -243,11 +250,11 @@ typedef void (*i2c_slave_transfer_callback_t)(I2C_Type *base, i2c_slave_transfer
|
||||||
/*! @brief I2C slave handle structure. */
|
/*! @brief I2C slave handle structure. */
|
||||||
struct _i2c_slave_handle
|
struct _i2c_slave_handle
|
||||||
{
|
{
|
||||||
bool isBusy; /*!< Whether transfer is busy. */
|
volatile bool isBusy; /*!< Indicates whether a transfer is busy. */
|
||||||
i2c_slave_transfer_t transfer; /*!< I2C slave transfer copy. */
|
i2c_slave_transfer_t transfer; /*!< I2C slave transfer copy. */
|
||||||
uint32_t eventMask; /*!< Mask of enabled events. */
|
uint32_t eventMask; /*!< A mask of enabled events. */
|
||||||
i2c_slave_transfer_callback_t callback; /*!< Callback function called at transfer event. */
|
i2c_slave_transfer_callback_t callback; /*!< A callback function called at the transfer event. */
|
||||||
void *userData; /*!< Callback parameter passed to callback. */
|
void *userData; /*!< A callback parameter passed to the callback. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
@ -267,12 +274,12 @@ extern "C" {
|
||||||
* @brief Initializes the I2C peripheral. Call this API to ungate the I2C clock
|
* @brief Initializes the I2C peripheral. Call this API to ungate the I2C clock
|
||||||
* and configure the I2C with master configuration.
|
* and configure the I2C with master configuration.
|
||||||
*
|
*
|
||||||
* @note This API should be called at the beginning of the application to use
|
* @note This API should be called at the beginning of the application.
|
||||||
* the I2C driver, or any operation to the I2C module could cause hard fault
|
* Otherwise, any operation to the I2C module can cause a hard fault
|
||||||
* because clock is not enabled. The configuration structure can be filled by user
|
* because the clock is not enabled. The configuration structure can be custom filled
|
||||||
* from scratch, or be set with default values by I2C_MasterGetDefaultConfig().
|
* or it can be set with default values by using the I2C_MasterGetDefaultConfig().
|
||||||
* After calling this API, the master is ready to transfer.
|
* After calling this API, the master is ready to transfer.
|
||||||
* Example:
|
* This is an example.
|
||||||
* @code
|
* @code
|
||||||
* i2c_master_config_t config = {
|
* i2c_master_config_t config = {
|
||||||
* .enableMaster = true,
|
* .enableMaster = true,
|
||||||
|
@ -285,20 +292,20 @@ extern "C" {
|
||||||
* @endcode
|
* @endcode
|
||||||
*
|
*
|
||||||
* @param base I2C base pointer
|
* @param base I2C base pointer
|
||||||
* @param masterConfig pointer to master configuration structure
|
* @param masterConfig A pointer to the master configuration structure
|
||||||
* @param srcClock_Hz I2C peripheral clock frequency in Hz
|
* @param srcClock_Hz I2C peripheral clock frequency in Hz
|
||||||
*/
|
*/
|
||||||
void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz);
|
void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uint32_t srcClock_Hz);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Initializes the I2C peripheral. Call this API to ungate the I2C clock
|
* @brief Initializes the I2C peripheral. Call this API to ungate the I2C clock
|
||||||
* and initializes the I2C with slave configuration.
|
* and initialize the I2C with the slave configuration.
|
||||||
*
|
*
|
||||||
* @note This API should be called at the beginning of the application to use
|
* @note This API should be called at the beginning of the application.
|
||||||
* the I2C driver, or any operation to the I2C module can cause a hard fault
|
* Otherwise, any operation to the I2C module can cause a hard fault
|
||||||
* because the clock is not enabled. The configuration structure can partly be set
|
* because the clock is not enabled. The configuration structure can partly be set
|
||||||
* with default values by I2C_SlaveGetDefaultConfig(), or can be filled by the user.
|
* with default values by I2C_SlaveGetDefaultConfig() or it can be custom filled by the user.
|
||||||
* Example
|
* This is an example.
|
||||||
* @code
|
* @code
|
||||||
* i2c_slave_config_t config = {
|
* i2c_slave_config_t config = {
|
||||||
* .enableSlave = true,
|
* .enableSlave = true,
|
||||||
|
@ -307,15 +314,17 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin
|
||||||
* .slaveAddress = 0x1DU,
|
* .slaveAddress = 0x1DU,
|
||||||
* .enableWakeUp = false,
|
* .enableWakeUp = false,
|
||||||
* .enablehighDrive = false,
|
* .enablehighDrive = false,
|
||||||
* .enableBaudRateCtl = false
|
* .enableBaudRateCtl = false,
|
||||||
|
* .sclStopHoldTime_ns = 4000
|
||||||
* };
|
* };
|
||||||
* I2C_SlaveInit(I2C0, &config);
|
* I2C_SlaveInit(I2C0, &config, 12000000U);
|
||||||
* @endcode
|
* @endcode
|
||||||
*
|
*
|
||||||
* @param base I2C base pointer
|
* @param base I2C base pointer
|
||||||
* @param slaveConfig pointer to slave configuration structure
|
* @param slaveConfig A pointer to the slave configuration structure
|
||||||
|
* @param srcClock_Hz I2C peripheral clock frequency in Hz
|
||||||
*/
|
*/
|
||||||
void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig);
|
void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig, uint32_t srcClock_Hz);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief De-initializes the I2C master peripheral. Call this API to gate the I2C clock.
|
* @brief De-initializes the I2C master peripheral. Call this API to gate the I2C clock.
|
||||||
|
@ -335,28 +344,28 @@ void I2C_SlaveDeinit(I2C_Type *base);
|
||||||
* @brief Sets the I2C master configuration structure to default values.
|
* @brief Sets the I2C master configuration structure to default values.
|
||||||
*
|
*
|
||||||
* The purpose of this API is to get the configuration structure initialized for use in the I2C_MasterConfigure().
|
* The purpose of this API is to get the configuration structure initialized for use in the I2C_MasterConfigure().
|
||||||
* Use the initialized structure unchanged in I2C_MasterConfigure(), or modify some fields of
|
* Use the initialized structure unchanged in the I2C_MasterConfigure() or modify
|
||||||
* the structure before calling I2C_MasterConfigure().
|
* the structure before calling the I2C_MasterConfigure().
|
||||||
* Example:
|
* This is an example.
|
||||||
* @code
|
* @code
|
||||||
* i2c_master_config_t config;
|
* i2c_master_config_t config;
|
||||||
* I2C_MasterGetDefaultConfig(&config);
|
* I2C_MasterGetDefaultConfig(&config);
|
||||||
* @endcode
|
* @endcode
|
||||||
* @param masterConfig Pointer to the master configuration structure.
|
* @param masterConfig A pointer to the master configuration structure.
|
||||||
*/
|
*/
|
||||||
void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig);
|
void I2C_MasterGetDefaultConfig(i2c_master_config_t *masterConfig);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Sets the I2C slave configuration structure to default values.
|
* @brief Sets the I2C slave configuration structure to default values.
|
||||||
*
|
*
|
||||||
* The purpose of this API is to get the configuration structure initialized for use in I2C_SlaveConfigure().
|
* The purpose of this API is to get the configuration structure initialized for use in the I2C_SlaveConfigure().
|
||||||
* Modify fields of the structure before calling the I2C_SlaveConfigure().
|
* Modify fields of the structure before calling the I2C_SlaveConfigure().
|
||||||
* Example:
|
* This is an example.
|
||||||
* @code
|
* @code
|
||||||
* i2c_slave_config_t config;
|
* i2c_slave_config_t config;
|
||||||
* I2C_SlaveGetDefaultConfig(&config);
|
* I2C_SlaveGetDefaultConfig(&config);
|
||||||
* @endcode
|
* @endcode
|
||||||
* @param slaveConfig Pointer to the slave configuration structure.
|
* @param slaveConfig A pointer to the slave configuration structure.
|
||||||
*/
|
*/
|
||||||
void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig);
|
void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig);
|
||||||
|
|
||||||
|
@ -364,7 +373,7 @@ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig);
|
||||||
* @brief Enables or disabless the I2C peripheral operation.
|
* @brief Enables or disabless the I2C peripheral operation.
|
||||||
*
|
*
|
||||||
* @param base I2C base pointer
|
* @param base I2C base pointer
|
||||||
* @param enable pass true to enable module, false to disable module
|
* @param enable Pass true to enable and false to disable the module.
|
||||||
*/
|
*/
|
||||||
static inline void I2C_Enable(I2C_Type *base, bool enable)
|
static inline void I2C_Enable(I2C_Type *base, bool enable)
|
||||||
{
|
{
|
||||||
|
@ -389,7 +398,7 @@ static inline void I2C_Enable(I2C_Type *base, bool enable)
|
||||||
* @brief Gets the I2C status flags.
|
* @brief Gets the I2C status flags.
|
||||||
*
|
*
|
||||||
* @param base I2C base pointer
|
* @param base I2C base pointer
|
||||||
* @return status flag, use status flag to AND #_i2c_flags could get the related status.
|
* @return status flag, use status flag to AND #_i2c_flags to get the related status.
|
||||||
*/
|
*/
|
||||||
uint32_t I2C_MasterGetStatusFlags(I2C_Type *base);
|
uint32_t I2C_MasterGetStatusFlags(I2C_Type *base);
|
||||||
|
|
||||||
|
@ -397,7 +406,7 @@ uint32_t I2C_MasterGetStatusFlags(I2C_Type *base);
|
||||||
* @brief Gets the I2C status flags.
|
* @brief Gets the I2C status flags.
|
||||||
*
|
*
|
||||||
* @param base I2C base pointer
|
* @param base I2C base pointer
|
||||||
* @return status flag, use status flag to AND #_i2c_flags could get the related status.
|
* @return status flag, use status flag to AND #_i2c_flags to get the related status.
|
||||||
*/
|
*/
|
||||||
static inline uint32_t I2C_SlaveGetStatusFlags(I2C_Type *base)
|
static inline uint32_t I2C_SlaveGetStatusFlags(I2C_Type *base)
|
||||||
{
|
{
|
||||||
|
@ -407,11 +416,11 @@ static inline uint32_t I2C_SlaveGetStatusFlags(I2C_Type *base)
|
||||||
/*!
|
/*!
|
||||||
* @brief Clears the I2C status flag state.
|
* @brief Clears the I2C status flag state.
|
||||||
*
|
*
|
||||||
* The following status register flags can be cleared: kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag
|
* The following status register flags can be cleared kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag.
|
||||||
*
|
*
|
||||||
* @param base I2C base pointer
|
* @param base I2C base pointer
|
||||||
* @param statusMask The status flag mask, defined in type i2c_status_flag_t.
|
* @param statusMask The status flag mask, defined in type i2c_status_flag_t.
|
||||||
* The parameter could be any combination of the following values:
|
* The parameter can be any combination of the following values:
|
||||||
* @arg kI2C_StartDetectFlag (if available)
|
* @arg kI2C_StartDetectFlag (if available)
|
||||||
* @arg kI2C_StopDetectFlag (if available)
|
* @arg kI2C_StopDetectFlag (if available)
|
||||||
* @arg kI2C_ArbitrationLostFlag
|
* @arg kI2C_ArbitrationLostFlag
|
||||||
|
@ -442,11 +451,11 @@ static inline void I2C_MasterClearStatusFlags(I2C_Type *base, uint32_t statusMas
|
||||||
/*!
|
/*!
|
||||||
* @brief Clears the I2C status flag state.
|
* @brief Clears the I2C status flag state.
|
||||||
*
|
*
|
||||||
* The following status register flags can be cleared: kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag
|
* The following status register flags can be cleared kI2C_ArbitrationLostFlag and kI2C_IntPendingFlag
|
||||||
*
|
*
|
||||||
* @param base I2C base pointer
|
* @param base I2C base pointer
|
||||||
* @param statusMask The status flag mask, defined in type i2c_status_flag_t.
|
* @param statusMask The status flag mask, defined in type i2c_status_flag_t.
|
||||||
* The parameter could be any combination of the following values:
|
* The parameter can be any combination of the following values:
|
||||||
* @arg kI2C_StartDetectFlag (if available)
|
* @arg kI2C_StartDetectFlag (if available)
|
||||||
* @arg kI2C_StopDetectFlag (if available)
|
* @arg kI2C_StopDetectFlag (if available)
|
||||||
* @arg kI2C_ArbitrationLostFlag
|
* @arg kI2C_ArbitrationLostFlag
|
||||||
|
@ -574,19 +583,21 @@ status_t I2C_MasterStop(I2C_Type *base);
|
||||||
status_t I2C_MasterRepeatedStart(I2C_Type *base, uint8_t address, i2c_direction_t direction);
|
status_t I2C_MasterRepeatedStart(I2C_Type *base, uint8_t address, i2c_direction_t direction);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Performs a polling send transaction on the I2C bus without a STOP signal.
|
* @brief Performs a polling send transaction on the I2C bus.
|
||||||
*
|
*
|
||||||
* @param base The I2C peripheral base pointer.
|
* @param base The I2C peripheral base pointer.
|
||||||
* @param txBuff The pointer to the data to be transferred.
|
* @param txBuff The pointer to the data to be transferred.
|
||||||
* @param txSize The length in bytes of the data to be transferred.
|
* @param txSize The length in bytes of the data to be transferred.
|
||||||
|
* @param flags Transfer control flag to decide whether need to send a stop, use kI2C_TransferDefaultFlag
|
||||||
|
* to issue a stop and kI2C_TransferNoStop to not send a stop.
|
||||||
* @retval kStatus_Success Successfully complete the data transmission.
|
* @retval kStatus_Success Successfully complete the data transmission.
|
||||||
* @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
|
* @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
|
||||||
* @retval kStataus_I2C_Nak Transfer error, receive NAK during transfer.
|
* @retval kStataus_I2C_Nak Transfer error, receive NAK during transfer.
|
||||||
*/
|
*/
|
||||||
status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize);
|
status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t txSize, uint32_t flags);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Performs a polling receive transaction on the I2C bus with a STOP signal.
|
* @brief Performs a polling receive transaction on the I2C bus.
|
||||||
*
|
*
|
||||||
* @note The I2C_MasterReadBlocking function stops the bus before reading the final byte.
|
* @note The I2C_MasterReadBlocking function stops the bus before reading the final byte.
|
||||||
* Without stopping the bus prior for the final read, the bus issues another read, resulting
|
* Without stopping the bus prior for the final read, the bus issues another read, resulting
|
||||||
|
@ -595,10 +606,12 @@ status_t I2C_MasterWriteBlocking(I2C_Type *base, const uint8_t *txBuff, size_t t
|
||||||
* @param base I2C peripheral base pointer.
|
* @param base I2C peripheral base pointer.
|
||||||
* @param rxBuff The pointer to the data to store the received data.
|
* @param rxBuff The pointer to the data to store the received data.
|
||||||
* @param rxSize The length in bytes of the data to be received.
|
* @param rxSize The length in bytes of the data to be received.
|
||||||
|
* @param flags Transfer control flag to decide whether need to send a stop, use kI2C_TransferDefaultFlag
|
||||||
|
* to issue a stop and kI2C_TransferNoStop to not send a stop.
|
||||||
* @retval kStatus_Success Successfully complete the data transmission.
|
* @retval kStatus_Success Successfully complete the data transmission.
|
||||||
* @retval kStatus_I2C_Timeout Send stop signal failed, timeout.
|
* @retval kStatus_I2C_Timeout Send stop signal failed, timeout.
|
||||||
*/
|
*/
|
||||||
status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize);
|
status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize, uint32_t flags);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Performs a polling send transaction on the I2C bus.
|
* @brief Performs a polling send transaction on the I2C bus.
|
||||||
|
@ -650,7 +663,7 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
|
||||||
* @param base I2C base pointer.
|
* @param base I2C base pointer.
|
||||||
* @param handle pointer to i2c_master_handle_t structure to store the transfer state.
|
* @param handle pointer to i2c_master_handle_t structure to store the transfer state.
|
||||||
* @param callback pointer to user callback function.
|
* @param callback pointer to user callback function.
|
||||||
* @param userData user paramater passed to the callback function.
|
* @param userData user parameter passed to the callback function.
|
||||||
*/
|
*/
|
||||||
void I2C_MasterTransferCreateHandle(I2C_Type *base,
|
void I2C_MasterTransferCreateHandle(I2C_Type *base,
|
||||||
i2c_master_handle_t *handle,
|
i2c_master_handle_t *handle,
|
||||||
|
@ -660,15 +673,15 @@ void I2C_MasterTransferCreateHandle(I2C_Type *base,
|
||||||
/*!
|
/*!
|
||||||
* @brief Performs a master interrupt non-blocking transfer on the I2C bus.
|
* @brief Performs a master interrupt non-blocking transfer on the I2C bus.
|
||||||
*
|
*
|
||||||
* @note Calling the API will return immediately after transfer initiates, user needs
|
* @note Calling the API returns immediately after transfer initiates. The user needs
|
||||||
* to call I2C_MasterGetTransferCount to poll the transfer status to check whether
|
* to call I2C_MasterGetTransferCount to poll the transfer status to check whether
|
||||||
* the transfer is finished, if the return status is not kStatus_I2C_Busy, the transfer
|
* the transfer is finished. If the return status is not kStatus_I2C_Busy, the transfer
|
||||||
* is finished.
|
* is finished.
|
||||||
*
|
*
|
||||||
* @param base I2C base pointer.
|
* @param base I2C base pointer.
|
||||||
* @param handle pointer to i2c_master_handle_t structure which stores the transfer state.
|
* @param handle pointer to i2c_master_handle_t structure which stores the transfer state.
|
||||||
* @param xfer pointer to i2c_master_transfer_t structure.
|
* @param xfer pointer to i2c_master_transfer_t structure.
|
||||||
* @retval kStatus_Success Sucessully start the data transmission.
|
* @retval kStatus_Success Successfully start the data transmission.
|
||||||
* @retval kStatus_I2C_Busy Previous transmission still not finished.
|
* @retval kStatus_I2C_Busy Previous transmission still not finished.
|
||||||
* @retval kStatus_I2C_Timeout Transfer error, wait signal timeout.
|
* @retval kStatus_I2C_Timeout Transfer error, wait signal timeout.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||||
* All rights reserved.
|
* Copyright 2016-2017 NXP
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
* other materials provided with the distribution.
|
* other materials provided with the distribution.
|
||||||
*
|
*
|
||||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
* o Neither the name of the copyright holder nor the names of its
|
||||||
* contributors may be used to endorse or promote products derived from this
|
* contributors may be used to endorse or promote products derived from this
|
||||||
* software without specific prior written permission.
|
* software without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -162,6 +162,26 @@ static void I2C_MasterTransferCallbackEDMA(edma_handle_t *handle, void *userData
|
||||||
result = I2C_MasterStop(i2cPrivateHandle->base);
|
result = I2C_MasterStop(i2cPrivateHandle->base);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (i2cPrivateHandle->handle->transfer.direction == kI2C_Read)
|
||||||
|
{
|
||||||
|
/* Change to send NAK at the last byte. */
|
||||||
|
i2cPrivateHandle->base->C1 |= I2C_C1_TXAK_MASK;
|
||||||
|
|
||||||
|
/* Wait the last data to be received. */
|
||||||
|
while (!(i2cPrivateHandle->base->S & kI2C_TransferCompleteFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Change direction to send. */
|
||||||
|
i2cPrivateHandle->base->C1 |= I2C_C1_TX_MASK;
|
||||||
|
|
||||||
|
/* Read the last data byte. */
|
||||||
|
*(i2cPrivateHandle->handle->transfer.data + i2cPrivateHandle->handle->transfer.dataSize - 1) =
|
||||||
|
i2cPrivateHandle->base->D;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
i2cPrivateHandle->handle->state = kIdleState;
|
i2cPrivateHandle->handle->state = kIdleState;
|
||||||
|
|
||||||
|
@ -203,7 +223,6 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
||||||
assert(xfer);
|
assert(xfer);
|
||||||
|
|
||||||
status_t result = kStatus_Success;
|
status_t result = kStatus_Success;
|
||||||
uint16_t timeout = UINT16_MAX;
|
|
||||||
|
|
||||||
if (handle->state != kIdleState)
|
if (handle->state != kIdleState)
|
||||||
{
|
{
|
||||||
|
@ -221,16 +240,6 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
||||||
|
|
||||||
handle->state = kTransferDataState;
|
handle->state = kTransferDataState;
|
||||||
|
|
||||||
/* Wait until ready to complete. */
|
|
||||||
while ((!(base->S & kI2C_TransferCompleteFlag)) && (--timeout))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Failed to start the transfer. */
|
|
||||||
if (timeout == 0)
|
|
||||||
{
|
|
||||||
return kStatus_I2C_Timeout;
|
|
||||||
}
|
|
||||||
/* Clear all status before transfer. */
|
/* Clear all status before transfer. */
|
||||||
I2C_MasterClearStatusFlags(base, kClearFlags);
|
I2C_MasterClearStatusFlags(base, kClearFlags);
|
||||||
|
|
||||||
|
@ -250,22 +259,55 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
||||||
result = I2C_MasterStart(base, handle->transfer.slaveAddress, direction);
|
result = I2C_MasterStart(base, handle->transfer.slaveAddress, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if there's transfer error. */
|
||||||
|
result = I2C_CheckAndClearError(base, base->S);
|
||||||
|
|
||||||
|
/* Return if error. */
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
if (result == kStatus_I2C_Nak)
|
||||||
|
{
|
||||||
|
result = kStatus_I2C_Addr_Nak;
|
||||||
|
|
||||||
|
if (I2C_MasterStop(base) != kStatus_Success)
|
||||||
|
{
|
||||||
|
result = kStatus_I2C_Timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle->completionCallback)
|
||||||
|
{
|
||||||
|
(handle->completionCallback)(base, handle, result, handle->userData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* Send subaddress. */
|
/* Send subaddress. */
|
||||||
if (handle->transfer.subaddressSize)
|
if (handle->transfer.subaddressSize)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
/* Wait until data transfer complete. */
|
|
||||||
while (!(base->S & kI2C_IntPendingFlag))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear interrupt pending flag. */
|
/* Clear interrupt pending flag. */
|
||||||
base->S = kI2C_IntPendingFlag;
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
handle->transfer.subaddressSize--;
|
handle->transfer.subaddressSize--;
|
||||||
base->D = ((handle->transfer.subaddress) >> (8 * handle->transfer.subaddressSize));
|
base->D = ((handle->transfer.subaddress) >> (8 * handle->transfer.subaddressSize));
|
||||||
|
|
||||||
|
/* Wait until data transfer complete. */
|
||||||
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if there's transfer error. */
|
/* Check if there's transfer error. */
|
||||||
result = I2C_CheckAndClearError(base, base->S);
|
result = I2C_CheckAndClearError(base, base->S);
|
||||||
|
|
||||||
|
@ -278,18 +320,11 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
||||||
|
|
||||||
if (handle->transfer.direction == kI2C_Read)
|
if (handle->transfer.direction == kI2C_Read)
|
||||||
{
|
{
|
||||||
/* Wait until data transfer complete. */
|
|
||||||
while (!(base->S & kI2C_IntPendingFlag))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear pending flag. */
|
/* Clear pending flag. */
|
||||||
base->S = kI2C_IntPendingFlag;
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
/* Send repeated start and slave address. */
|
/* Send repeated start and slave address. */
|
||||||
result = I2C_MasterRepeatedStart(base, handle->transfer.slaveAddress, kI2C_Read);
|
result = I2C_MasterRepeatedStart(base, handle->transfer.slaveAddress, kI2C_Read);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
|
@ -301,11 +336,18 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear pending flag. */
|
|
||||||
base->S = kI2C_IntPendingFlag;
|
|
||||||
|
|
||||||
/* Check if there's transfer error. */
|
/* Check if there's transfer error. */
|
||||||
result = I2C_CheckAndClearError(base, base->S);
|
result = I2C_CheckAndClearError(base, base->S);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear pending flag. */
|
||||||
|
base->S = kI2C_IntPendingFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -319,17 +361,7 @@ static void I2C_MasterTransferEDMAConfig(I2C_Type *base, i2c_master_edma_handle_
|
||||||
{
|
{
|
||||||
transfer_config.srcAddr = (uint32_t)I2C_GetDataRegAddr(base);
|
transfer_config.srcAddr = (uint32_t)I2C_GetDataRegAddr(base);
|
||||||
transfer_config.destAddr = (uint32_t)(handle->transfer.data);
|
transfer_config.destAddr = (uint32_t)(handle->transfer.data);
|
||||||
|
|
||||||
/* Send stop if kI2C_TransferNoStop flag is not asserted. */
|
|
||||||
if (!(handle->transfer.flags & kI2C_TransferNoStopFlag))
|
|
||||||
{
|
|
||||||
transfer_config.majorLoopCounts = (handle->transfer.dataSize - 1);
|
transfer_config.majorLoopCounts = (handle->transfer.dataSize - 1);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
transfer_config.majorLoopCounts = handle->transfer.dataSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
transfer_config.srcTransferSize = kEDMA_TransferSize1Bytes;
|
transfer_config.srcTransferSize = kEDMA_TransferSize1Bytes;
|
||||||
transfer_config.srcOffset = 0;
|
transfer_config.srcOffset = 0;
|
||||||
transfer_config.destTransferSize = kEDMA_TransferSize1Bytes;
|
transfer_config.destTransferSize = kEDMA_TransferSize1Bytes;
|
||||||
|
@ -348,6 +380,9 @@ static void I2C_MasterTransferEDMAConfig(I2C_Type *base, i2c_master_edma_handle_
|
||||||
transfer_config.minorLoopBytes = 1;
|
transfer_config.minorLoopBytes = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Store the initially configured eDMA minor byte transfer count into the I2C handle */
|
||||||
|
handle->nbytes = transfer_config.minorLoopBytes;
|
||||||
|
|
||||||
EDMA_SubmitTransfer(handle->dmaHandle, &transfer_config);
|
EDMA_SubmitTransfer(handle->dmaHandle, &transfer_config);
|
||||||
EDMA_StartTransfer(handle->dmaHandle);
|
EDMA_StartTransfer(handle->dmaHandle);
|
||||||
}
|
}
|
||||||
|
@ -427,7 +462,7 @@ status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle
|
||||||
if (handle->transfer.direction == kI2C_Read)
|
if (handle->transfer.direction == kI2C_Read)
|
||||||
{
|
{
|
||||||
/* Change direction for receive. */
|
/* Change direction for receive. */
|
||||||
base->C1 &= ~I2C_C1_TX_MASK;
|
base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK);
|
||||||
|
|
||||||
/* Read dummy to release the bus. */
|
/* Read dummy to release the bus. */
|
||||||
dummy = base->D;
|
dummy = base->D;
|
||||||
|
@ -479,6 +514,11 @@ status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle
|
||||||
{
|
{
|
||||||
result = I2C_MasterStop(base);
|
result = I2C_MasterStop(base);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Change direction to send. */
|
||||||
|
base->C1 |= I2C_C1_TX_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read the last byte of data. */
|
/* Read the last byte of data. */
|
||||||
if (handle->transfer.direction == kI2C_Read)
|
if (handle->transfer.direction == kI2C_Read)
|
||||||
|
@ -504,7 +544,9 @@ status_t I2C_MasterTransferGetCountEDMA(I2C_Type *base, i2c_master_edma_handle_t
|
||||||
|
|
||||||
if (kIdleState != handle->state)
|
if (kIdleState != handle->state)
|
||||||
{
|
{
|
||||||
*count = (handle->transferSize - EDMA_GetRemainingBytes(handle->dmaHandle->base, handle->dmaHandle->channel));
|
*count = (handle->transferSize -
|
||||||
|
(uint32_t)handle->nbytes *
|
||||||
|
EDMA_GetRemainingMajorLoopCount(handle->dmaHandle->base, handle->dmaHandle->channel));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||||
* All rights reserved.
|
* Copyright 2016-2017 NXP
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
* are permitted provided that the following conditions are met:
|
* are permitted provided that the following conditions are met:
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
* other materials provided with the distribution.
|
* other materials provided with the distribution.
|
||||||
*
|
*
|
||||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
* o Neither the name of the copyright holder nor the names of its
|
||||||
* contributors may be used to endorse or promote products derived from this
|
* contributors may be used to endorse or promote products derived from this
|
||||||
* software without specific prior written permission.
|
* software without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -39,31 +39,30 @@
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*! @file */
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Definitions
|
* Definitions
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
/*! @brief I2C master edma handle typedef. */
|
/*! @brief I2C master eDMA handle typedef. */
|
||||||
typedef struct _i2c_master_edma_handle i2c_master_edma_handle_t;
|
typedef struct _i2c_master_edma_handle i2c_master_edma_handle_t;
|
||||||
|
|
||||||
/*! @brief I2C master edma transfer callback typedef. */
|
/*! @brief I2C master eDMA transfer callback typedef. */
|
||||||
typedef void (*i2c_master_edma_transfer_callback_t)(I2C_Type *base,
|
typedef void (*i2c_master_edma_transfer_callback_t)(I2C_Type *base,
|
||||||
i2c_master_edma_handle_t *handle,
|
i2c_master_edma_handle_t *handle,
|
||||||
status_t status,
|
status_t status,
|
||||||
void *userData);
|
void *userData);
|
||||||
|
|
||||||
/*! @brief I2C master edma transfer structure. */
|
/*! @brief I2C master eDMA transfer structure. */
|
||||||
struct _i2c_master_edma_handle
|
struct _i2c_master_edma_handle
|
||||||
{
|
{
|
||||||
i2c_master_transfer_t transfer; /*!< I2C master transfer struct. */
|
i2c_master_transfer_t transfer; /*!< I2C master transfer structure. */
|
||||||
size_t transferSize; /*!< Total bytes to be transferred. */
|
size_t transferSize; /*!< Total bytes to be transferred. */
|
||||||
|
uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */
|
||||||
uint8_t state; /*!< I2C master transfer status. */
|
uint8_t state; /*!< I2C master transfer status. */
|
||||||
edma_handle_t *dmaHandle; /*!< The eDMA handler used. */
|
edma_handle_t *dmaHandle; /*!< The eDMA handler used. */
|
||||||
i2c_master_edma_transfer_callback_t
|
i2c_master_edma_transfer_callback_t
|
||||||
completionCallback; /*!< Callback function called after edma transfer finished. */
|
completionCallback; /*!< A callback function called after the eDMA transfer is finished. */
|
||||||
void *userData; /*!< Callback parameter passed to callback function. */
|
void *userData; /*!< A callback parameter passed to the callback function. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
@ -75,18 +74,18 @@ extern "C" {
|
||||||
#endif /*_cplusplus. */
|
#endif /*_cplusplus. */
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @name I2C Block EDMA Transfer Operation
|
* @name I2C Block eDMA Transfer Operation
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Init the I2C handle which is used in transcational functions.
|
* @brief Initializes the I2C handle which is used in transcational functions.
|
||||||
*
|
*
|
||||||
* @param base I2C peripheral base address.
|
* @param base I2C peripheral base address.
|
||||||
* @param handle pointer to i2c_master_edma_handle_t structure.
|
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||||
* @param callback pointer to user callback function.
|
* @param callback A pointer to the user callback function.
|
||||||
* @param userData user param passed to the callback function.
|
* @param userData A user parameter passed to the callback function.
|
||||||
* @param edmaHandle EDMA handle pointer.
|
* @param edmaHandle eDMA handle pointer.
|
||||||
*/
|
*/
|
||||||
void I2C_MasterCreateEDMAHandle(I2C_Type *base,
|
void I2C_MasterCreateEDMAHandle(I2C_Type *base,
|
||||||
i2c_master_edma_handle_t *handle,
|
i2c_master_edma_handle_t *handle,
|
||||||
|
@ -95,33 +94,33 @@ void I2C_MasterCreateEDMAHandle(I2C_Type *base,
|
||||||
edma_handle_t *edmaHandle);
|
edma_handle_t *edmaHandle);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Performs a master edma non-blocking transfer on the I2C bus.
|
* @brief Performs a master eDMA non-blocking transfer on the I2C bus.
|
||||||
*
|
*
|
||||||
* @param base I2C peripheral base address.
|
* @param base I2C peripheral base address.
|
||||||
* @param handle pointer to i2c_master_edma_handle_t structure.
|
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||||
* @param xfer pointer to transfer structure of i2c_master_transfer_t.
|
* @param xfer A pointer to the transfer structure of i2c_master_transfer_t.
|
||||||
* @retval kStatus_Success Sucessully complete the data transmission.
|
* @retval kStatus_Success Sucessfully completed the data transmission.
|
||||||
* @retval kStatus_I2C_Busy Previous transmission still not finished.
|
* @retval kStatus_I2C_Busy A previous transmission is still not finished.
|
||||||
* @retval kStatus_I2C_Timeout Transfer error, wait signal timeout.
|
* @retval kStatus_I2C_Timeout Transfer error, waits for a signal timeout.
|
||||||
* @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
|
* @retval kStatus_I2C_ArbitrationLost Transfer error, arbitration lost.
|
||||||
* @retval kStataus_I2C_Nak Transfer error, receive Nak during transfer.
|
* @retval kStataus_I2C_Nak Transfer error, receive NAK during transfer.
|
||||||
*/
|
*/
|
||||||
status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle, i2c_master_transfer_t *xfer);
|
status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle, i2c_master_transfer_t *xfer);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Get master transfer status during a edma non-blocking transfer.
|
* @brief Gets a master transfer status during the eDMA non-blocking transfer.
|
||||||
*
|
*
|
||||||
* @param base I2C peripheral base address.
|
* @param base I2C peripheral base address.
|
||||||
* @param handle pointer to i2c_master_edma_handle_t structure.
|
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||||
* @param count Number of bytes transferred so far by the non-blocking transaction.
|
* @param count A number of bytes transferred by the non-blocking transaction.
|
||||||
*/
|
*/
|
||||||
status_t I2C_MasterTransferGetCountEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle, size_t *count);
|
status_t I2C_MasterTransferGetCountEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle, size_t *count);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* @brief Abort a master edma non-blocking transfer in a early time.
|
* @brief Aborts a master eDMA non-blocking transfer early.
|
||||||
*
|
*
|
||||||
* @param base I2C peripheral base address.
|
* @param base I2C peripheral base address.
|
||||||
* @param handle pointer to i2c_master_edma_handle_t structure.
|
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||||
*/
|
*/
|
||||||
void I2C_MasterTransferAbortEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle);
|
void I2C_MasterTransferAbortEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue