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.
|
||||
* All rights reserved.
|
||||
* Copyright 2016-2017 NXP
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* 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
|
||||
* 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
|
||||
* 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);
|
||||
|
||||
/*!
|
||||
* @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
|
||||
* transfer state.
|
||||
|
@ -137,8 +150,10 @@ static I2C_Type *const s_i2cBases[] = I2C_BASE_PTRS;
|
|||
/*! @brief Pointers to i2c IRQ number for each instance. */
|
||||
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. */
|
||||
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. */
|
||||
static i2c_isr_t s_i2cMasterIsr;
|
||||
|
@ -155,7 +170,7 @@ uint32_t I2C_GetInstance(I2C_Type *base)
|
|||
uint32_t instance;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
status_t result = kStatus_Success;
|
||||
i2c_direction_t direction = xfer->direction;
|
||||
uint16_t timeout = UINT16_MAX;
|
||||
|
||||
/* Initialize the handle transfer information. */
|
||||
handle->transfer = *xfer;
|
||||
|
@ -183,27 +245,13 @@ static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t
|
|||
/* Initial transfer state. */
|
||||
if (handle->transfer.subaddressSize > 0)
|
||||
{
|
||||
handle->state = kSendCommandState;
|
||||
if (xfer->direction == kI2C_Read)
|
||||
{
|
||||
direction = kI2C_Write;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
handle->state = kCheckAddressState;
|
||||
|
||||
/* Clear all status before transfer. */
|
||||
I2C_MasterClearStatusFlags(base, kClearFlags);
|
||||
|
@ -265,34 +313,41 @@ static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_han
|
|||
result = kStatus_Success;
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Handle Check address state to check the slave address is Acked in slave
|
||||
probe application. */
|
||||
if (handle->state == kCheckAddressState)
|
||||
{
|
||||
if (statusFlags & kI2C_ReceiveNakFlag)
|
||||
{
|
||||
return kStatus_I2C_Nak;
|
||||
result = kStatus_I2C_Addr_Nak;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (handle->transfer.direction == kI2C_Write)
|
||||
if (handle->transfer.subaddressSize > 0)
|
||||
{
|
||||
/* Next state, send data. */
|
||||
handle->state = kSendDataState;
|
||||
handle->state = kSendCommandState;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Next state, receive data begin. */
|
||||
handle->state = kReceiveDataBeginState;
|
||||
if (handle->transfer.direction == kI2C_Write)
|
||||
{
|
||||
/* Next state, send data. */
|
||||
handle->state = kSendDataState;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Next state, receive data begin. */
|
||||
handle->state = kReceiveDataBeginState;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Run state machine. */
|
||||
switch (handle->state)
|
||||
{
|
||||
|
@ -375,6 +430,10 @@ static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_han
|
|||
{
|
||||
result = I2C_MasterStop(base);
|
||||
}
|
||||
else
|
||||
{
|
||||
base->C1 |= I2C_C1_TX_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Send NAK at the last receive byte. */
|
||||
|
@ -407,6 +466,7 @@ static void I2C_TransferCommonIRQHandler(I2C_Type *base, void *handle)
|
|||
{
|
||||
s_i2cSlaveIsr(base, handle);
|
||||
}
|
||||
__DSB();
|
||||
}
|
||||
|
||||
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. */
|
||||
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
|
||||
uint8_t s2Reg;
|
||||
#endif
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
/* Enable I2C clock. */
|
||||
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. */
|
||||
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. */
|
||||
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. */
|
||||
fltReg = base->FLT;
|
||||
|
||||
|
@ -472,8 +536,10 @@ void I2C_MasterDeinit(I2C_Type *base)
|
|||
/* Disable I2C module. */
|
||||
I2C_Enable(base, false);
|
||||
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
/* Disable I2C clock. */
|
||||
CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
||||
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||
}
|
||||
|
||||
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. */
|
||||
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. */
|
||||
#if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF
|
||||
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);
|
||||
|
||||
/* 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. */
|
||||
base->F = savedMult;
|
||||
|
@ -721,7 +782,7 @@ uint32_t I2C_MasterGetStatusFlags(I2C_Type *base)
|
|||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
volatile uint8_t dummy = 0;
|
||||
|
@ -817,8 +887,16 @@ status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize)
|
|||
/* Single byte use case. */
|
||||
if (rxSize == 0)
|
||||
{
|
||||
/* Read the final byte. */
|
||||
result = I2C_MasterStop(base);
|
||||
if (!(flags & kI2C_TransferNoStopFlag))
|
||||
{
|
||||
/* Issue STOP command before reading last byte. */
|
||||
result = I2C_MasterStop(base);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Change direction to Tx to avoid extra clocks. */
|
||||
base->C1 |= I2C_C1_TX_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
if (rxSize == 1)
|
||||
|
@ -871,72 +949,6 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
|
|||
return result;
|
||||
}
|
||||
|
||||
/* Send subaddress. */
|
||||
if (xfer->subaddressSize)
|
||||
{
|
||||
do
|
||||
{
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
||||
/* Clear interrupt pending flag. */
|
||||
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;
|
||||
}
|
||||
|
||||
xfer->subaddressSize--;
|
||||
base->D = ((xfer->subaddress) >> (8 * xfer->subaddressSize));
|
||||
|
||||
} while ((xfer->subaddressSize > 0) && (result == kStatus_Success));
|
||||
|
||||
if (xfer->direction == kI2C_Read)
|
||||
{
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
||||
/* Clear pending flag. */
|
||||
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. */
|
||||
result = I2C_MasterRepeatedStart(base, xfer->slaveAddress, kI2C_Read);
|
||||
|
||||
/* Return if error. */
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait until address + command transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
@ -949,32 +961,92 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
|
|||
{
|
||||
if (result == kStatus_I2C_Nak)
|
||||
{
|
||||
result = kStatus_I2C_Addr_Nak;
|
||||
|
||||
I2C_MasterStop(base);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Send subaddress. */
|
||||
if (xfer->subaddressSize)
|
||||
{
|
||||
do
|
||||
{
|
||||
/* Clear interrupt pending flag. */
|
||||
base->S = kI2C_IntPendingFlag;
|
||||
|
||||
xfer->subaddressSize--;
|
||||
base->D = ((xfer->subaddress) >> (8 * xfer->subaddressSize));
|
||||
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(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;
|
||||
}
|
||||
|
||||
} while ((xfer->subaddressSize > 0) && (result == kStatus_Success));
|
||||
|
||||
if (xfer->direction == kI2C_Read)
|
||||
{
|
||||
/* Clear pending flag. */
|
||||
base->S = kI2C_IntPendingFlag;
|
||||
|
||||
/* Send repeated start and slave address. */
|
||||
result = I2C_MasterRepeatedStart(base, xfer->slaveAddress, kI2C_Read);
|
||||
|
||||
/* Return if error. */
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
||||
/* Check if there's transfer error. */
|
||||
result = I2C_CheckAndClearError(base, base->S);
|
||||
|
||||
if (result)
|
||||
{
|
||||
if (result == kStatus_I2C_Nak)
|
||||
{
|
||||
result = kStatus_I2C_Addr_Nak;
|
||||
|
||||
I2C_MasterStop(base);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Transmit data. */
|
||||
if ((xfer->direction == kI2C_Write) && (xfer->dataSize > 0))
|
||||
{
|
||||
/* Send Data. */
|
||||
result = I2C_MasterWriteBlocking(base, xfer->data, xfer->dataSize);
|
||||
|
||||
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);
|
||||
}
|
||||
result = I2C_MasterWriteBlocking(base, xfer->data, xfer->dataSize, xfer->flags);
|
||||
}
|
||||
|
||||
/* Receive Data. */
|
||||
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;
|
||||
|
@ -1037,11 +1109,37 @@ void I2C_MasterTransferAbort(I2C_Type *base, i2c_master_handle_t *handle)
|
|||
{
|
||||
assert(handle);
|
||||
|
||||
volatile uint8_t dummy = 0;
|
||||
|
||||
/* Add this to avoid build warning. */
|
||||
dummy++;
|
||||
|
||||
/* Disable interrupt. */
|
||||
I2C_DisableInterrupts(base, kI2C_GlobalInterruptEnable);
|
||||
|
||||
/* Reset the state to idle. */
|
||||
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)
|
||||
|
@ -1075,7 +1173,8 @@ void I2C_MasterTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
|||
if (isDone || result)
|
||||
{
|
||||
/* 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. */
|
||||
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);
|
||||
|
||||
uint8_t tmpReg;
|
||||
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
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. */
|
||||
switch (slaveConfig->addressingMode)
|
||||
|
@ -1132,14 +1246,10 @@ void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig)
|
|||
tmpReg &= ~I2C_C1_WUEN_MASK;
|
||||
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 &= ~(I2C_C2_SBRC_MASK | I2C_C2_GCAEN_MASK);
|
||||
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;
|
||||
|
||||
/* 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);
|
||||
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)
|
||||
|
@ -1154,8 +1267,10 @@ void I2C_SlaveDeinit(I2C_Type *base)
|
|||
/* Disable I2C module. */
|
||||
I2C_Enable(base, false);
|
||||
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
/* Disable I2C clock. */
|
||||
CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
||||
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||
}
|
||||
|
||||
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. */
|
||||
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. */
|
||||
slaveConfig->enableBaudRateCtl = false;
|
||||
|
||||
|
@ -1184,6 +1294,9 @@ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig)
|
|||
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. */
|
||||
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. */
|
||||
dummy = base->D;
|
||||
|
||||
result = I2C_MasterWriteBlocking(base, txBuff, txSize);
|
||||
result = I2C_MasterWriteBlocking(base, txBuff, txSize, kI2C_TransferDefaultFlag);
|
||||
|
||||
/* Switch to receive mode. */
|
||||
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;
|
||||
|
||||
/* 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. */
|
||||
I2C_SlaveClearStatusFlags(base, kClearFlags);
|
||||
|
@ -1412,7 +1525,10 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
|||
}
|
||||
}
|
||||
|
||||
return;
|
||||
if (!(status & kI2C_AddressMatchFlag))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif /* I2C_HAS_STOP_DETECT */
|
||||
|
||||
|
@ -1482,11 +1598,6 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
|||
handle->isBusy = true;
|
||||
xfer->event = kI2C_SlaveAddressMatchEvent;
|
||||
|
||||
if ((handle->eventMask & xfer->event) && (handle->callback))
|
||||
{
|
||||
handle->callback(base, xfer, handle->userData);
|
||||
}
|
||||
|
||||
/* Slave transmit, master reading from slave. */
|
||||
if (status & kI2C_TransferDirectionFlag)
|
||||
{
|
||||
|
@ -1502,6 +1613,16 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
|||
|
||||
/* 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. */
|
||||
|
@ -1607,27 +1728,30 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(I2C0)
|
||||
void I2C0_DriverIRQHandler(void)
|
||||
{
|
||||
I2C_TransferCommonIRQHandler(I2C0, s_i2cHandle[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (FSL_FEATURE_SOC_I2C_COUNT > 1)
|
||||
#if defined(I2C1)
|
||||
void I2C1_DriverIRQHandler(void)
|
||||
{
|
||||
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)
|
||||
{
|
||||
I2C_TransferCommonIRQHandler(I2C2, s_i2cHandle[2]);
|
||||
}
|
||||
#endif /* I2C COUNT > 2 */
|
||||
#if (FSL_FEATURE_SOC_I2C_COUNT > 3)
|
||||
#endif
|
||||
|
||||
#if defined(I2C3)
|
||||
void I2C3_DriverIRQHandler(void)
|
||||
{
|
||||
I2C_TransferCommonIRQHandler(I2C3, s_i2cHandle[3]);
|
||||
}
|
||||
#endif /* I2C COUNT > 3 */
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* 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,
|
||||
* 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
|
||||
* 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
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
|
@ -37,15 +37,14 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief I2C driver version 2.0.1. */
|
||||
#define FSL_I2C_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))
|
||||
/*! @brief I2C driver version 2.0.3. */
|
||||
#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 || \
|
||||
|
@ -61,6 +60,7 @@ enum _i2c_status
|
|||
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_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 */
|
||||
};
|
||||
|
||||
/*! @brief Direction of master and slave transfers. */
|
||||
/*! @brief The direction of master and slave transfers. */
|
||||
typedef enum _i2c_direction
|
||||
{
|
||||
kI2C_Write = 0x0U, /*!< Master transmit to slave. */
|
||||
kI2C_Read = 0x1U, /*!< Master receive from slave. */
|
||||
kI2C_Write = 0x0U, /*!< Master transmits to the slave. */
|
||||
kI2C_Read = 0x1U, /*!< Master receives from the slave. */
|
||||
} i2c_direction_t;
|
||||
|
||||
/*! @brief Addressing mode. */
|
||||
|
@ -125,17 +125,17 @@ typedef enum _i2c_slave_address_mode
|
|||
/*! @brief I2C transfer control flag. */
|
||||
enum _i2c_master_transfer_flags
|
||||
{
|
||||
kI2C_TransferDefaultFlag = 0x0U, /*!< Transfer starts with a start signal, stops with a stop signal. */
|
||||
kI2C_TransferNoStartFlag = 0x1U, /*!< Transfer starts without a start signal. */
|
||||
kI2C_TransferRepeatedStartFlag = 0x2U, /*!< Transfer starts with a repeated start signal. */
|
||||
kI2C_TransferNoStopFlag = 0x4U, /*!< Transfer ends without a stop signal. */
|
||||
kI2C_TransferDefaultFlag = 0x0U, /*!< A transfer starts with a start signal, stops with a stop signal. */
|
||||
kI2C_TransferNoStartFlag = 0x1U, /*!< A transfer starts without a start signal. */
|
||||
kI2C_TransferRepeatedStartFlag = 0x2U, /*!< A transfer starts with a repeated start signal. */
|
||||
kI2C_TransferNoStopFlag = 0x4U, /*!< A transfer ends without a stop signal. */
|
||||
};
|
||||
|
||||
/*!
|
||||
* @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
|
||||
* 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
|
||||
* parameter.
|
||||
*
|
||||
|
@ -144,36 +144,34 @@ enum _i2c_master_transfer_flags
|
|||
typedef enum _i2c_slave_transfer_event
|
||||
{
|
||||
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). */
|
||||
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). */
|
||||
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
|
||||
kI2C_SlaveStartEvent = 0x10U, /*!< A start/repeated start was detected. */
|
||||
#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 |
|
||||
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||
kI2C_SlaveStartEvent |
|
||||
#endif
|
||||
kI2C_SlaveCompletionEvent,
|
||||
kI2C_SlaveCompletionEvent | kI2C_SlaveGenaralcallEvent,
|
||||
} i2c_slave_transfer_event_t;
|
||||
|
||||
/*! @brief I2C master user configuration. */
|
||||
typedef struct _i2c_master_config
|
||||
{
|
||||
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
|
||||
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
|
||||
bool enableDoubleBuffering; /*!< Controls double buffer enable; notice that
|
||||
enabling the double buffer disables the clock stretch. */
|
||||
#endif
|
||||
uint32_t baudRate_Bps; /*!< Baud rate configuration of I2C peripheral. */
|
||||
|
@ -184,19 +182,20 @@ typedef struct _i2c_master_config
|
|||
typedef struct _i2c_slave_config
|
||||
{
|
||||
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. */
|
||||
#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
|
||||
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. */
|
||||
#endif
|
||||
bool enableBaudRateCtl; /*!< Enables/disables independent slave baud rate on SCL in very fast I2C modes. */
|
||||
uint16_t slaveAddress; /*!< Slave address configuration. */
|
||||
uint16_t upperAddress; /*!< Maximum boundary slave address used in range matching mode. */
|
||||
i2c_slave_address_mode_t addressingMode; /*!< Addressing mode configuration of i2c_slave_address_mode_config_t. */
|
||||
uint16_t slaveAddress; /*!< A slave address configuration. */
|
||||
uint16_t upperAddress; /*!< A maximum boundary slave address used in a range matching mode. */
|
||||
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;
|
||||
|
||||
/*! @brief I2C master handle typedef. */
|
||||
|
@ -214,13 +213,13 @@ typedef struct _i2c_slave_handle i2c_slave_handle_t;
|
|||
/*! @brief I2C master transfer structure. */
|
||||
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. */
|
||||
i2c_direction_t direction; /*!< Transfer direction, read or write. */
|
||||
uint32_t subaddress; /*!< Sub address. Transferred MSB first. */
|
||||
uint8_t subaddressSize; /*!< Size of command buffer. */
|
||||
uint8_t *volatile data; /*!< Transfer buffer. */
|
||||
volatile size_t dataSize; /*!< Transfer size. */
|
||||
i2c_direction_t direction; /*!< A transfer direction, read or write. */
|
||||
uint32_t subaddress; /*!< A sub address. Transferred MSB first. */
|
||||
uint8_t subaddressSize; /*!< A size of the command buffer. */
|
||||
uint8_t *volatile data; /*!< A transfer buffer. */
|
||||
volatile size_t dataSize; /*!< A transfer size. */
|
||||
} i2c_master_transfer_t;
|
||||
|
||||
/*! @brief I2C master handle structure. */
|
||||
|
@ -228,20 +227,21 @@ struct _i2c_master_handle
|
|||
{
|
||||
i2c_master_transfer_t transfer; /*!< I2C master transfer copy. */
|
||||
size_t transferSize; /*!< Total bytes to be transferred. */
|
||||
uint8_t state; /*!< Transfer state maintained during transfer. */
|
||||
i2c_master_transfer_callback_t completionCallback; /*!< Callback function called when transfer finished. */
|
||||
void *userData; /*!< Callback parameter passed to callback function. */
|
||||
uint8_t state; /*!< A transfer state maintained during transfer. */
|
||||
i2c_master_transfer_callback_t completionCallback; /*!< A callback function called when the transfer is finished. */
|
||||
void *userData; /*!< A callback parameter passed to the callback function. */
|
||||
};
|
||||
|
||||
/*! @brief I2C slave transfer structure. */
|
||||
typedef struct _i2c_slave_transfer
|
||||
{
|
||||
i2c_slave_transfer_event_t event; /*!< Reason the callback is being invoked. */
|
||||
uint8_t *volatile data; /*!< Transfer buffer. */
|
||||
volatile size_t dataSize; /*!< Transfer size. */
|
||||
i2c_slave_transfer_event_t event; /*!< A reason that the callback is invoked. */
|
||||
uint8_t *volatile data; /*!< A transfer buffer. */
|
||||
volatile size_t dataSize; /*!< A transfer size. */
|
||||
status_t completionStatus; /*!< Success or error code describing how the transfer completed. Only applies for
|
||||
#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;
|
||||
|
||||
/*! @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. */
|
||||
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. */
|
||||
uint32_t eventMask; /*!< Mask of enabled events. */
|
||||
i2c_slave_transfer_callback_t callback; /*!< Callback function called at transfer event. */
|
||||
void *userData; /*!< Callback parameter passed to callback. */
|
||||
uint32_t eventMask; /*!< A mask of enabled events. */
|
||||
i2c_slave_transfer_callback_t callback; /*!< A callback function called at the transfer event. */
|
||||
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
|
||||
* and configure the I2C with master configuration.
|
||||
*
|
||||
* @note This API should be called at the beginning of the application to use
|
||||
* the I2C driver, or any operation to the I2C module may cause a hard fault
|
||||
* because clock is not enabled. The configuration structure can be filled by user
|
||||
* from scratch, or be set with default values by I2C_MasterGetDefaultConfig().
|
||||
* @note This API should be called at the beginning of the application.
|
||||
* Otherwise, any operation to the I2C module can cause a hard fault
|
||||
* because the clock is not enabled. The configuration structure can be custom filled
|
||||
* or it can be set with default values by using the I2C_MasterGetDefaultConfig().
|
||||
* After calling this API, the master is ready to transfer.
|
||||
* Example:
|
||||
* This is an example.
|
||||
* @code
|
||||
* i2c_master_config_t config = {
|
||||
* .enableMaster = true,
|
||||
|
@ -292,20 +292,20 @@ extern "C" {
|
|||
* @endcode
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
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
|
||||
* 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
|
||||
* the I2C driver, or any operation to the I2C module can cause a hard fault
|
||||
* @note This API should be called at the beginning of the application.
|
||||
* 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
|
||||
* with default values by I2C_SlaveGetDefaultConfig(), or can be filled by the user.
|
||||
* Example
|
||||
* with default values by I2C_SlaveGetDefaultConfig() or it can be custom filled by the user.
|
||||
* This is an example.
|
||||
* @code
|
||||
* i2c_slave_config_t config = {
|
||||
* .enableSlave = true,
|
||||
|
@ -314,15 +314,17 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin
|
|||
* .slaveAddress = 0x1DU,
|
||||
* .enableWakeUp = false,
|
||||
* .enablehighDrive = false,
|
||||
* .enableBaudRateCtl = false
|
||||
* .enableBaudRateCtl = false,
|
||||
* .sclStopHoldTime_ns = 4000
|
||||
* };
|
||||
* I2C_SlaveInit(I2C0, &config);
|
||||
* I2C_SlaveInit(I2C0, &config, 12000000U);
|
||||
* @endcode
|
||||
*
|
||||
* @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.
|
||||
|
@ -342,28 +344,28 @@ void I2C_SlaveDeinit(I2C_Type *base);
|
|||
* @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().
|
||||
* Use the initialized structure unchanged in I2C_MasterConfigure(), or modify some fields of
|
||||
* the structure before calling I2C_MasterConfigure().
|
||||
* Example:
|
||||
* Use the initialized structure unchanged in the I2C_MasterConfigure() or modify
|
||||
* the structure before calling the I2C_MasterConfigure().
|
||||
* This is an example.
|
||||
* @code
|
||||
* i2c_master_config_t config;
|
||||
* I2C_MasterGetDefaultConfig(&config);
|
||||
* @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);
|
||||
|
||||
/*!
|
||||
* @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().
|
||||
* Example:
|
||||
* This is an example.
|
||||
* @code
|
||||
* i2c_slave_config_t config;
|
||||
* I2C_SlaveGetDefaultConfig(&config);
|
||||
* @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);
|
||||
|
||||
|
@ -371,7 +373,7 @@ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig);
|
|||
* @brief Enables or disabless the I2C peripheral operation.
|
||||
*
|
||||
* @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)
|
||||
{
|
||||
|
@ -414,7 +416,7 @@ static inline uint32_t I2C_SlaveGetStatusFlags(I2C_Type *base)
|
|||
/*!
|
||||
* @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 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.
|
||||
*
|
||||
* 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 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);
|
||||
|
||||
/*!
|
||||
* @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 txBuff The pointer to 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_I2C_ArbitrationLost Transfer error, arbitration lost.
|
||||
* @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.
|
||||
* 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 rxBuff The pointer to the data to store the received data.
|
||||
* @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_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.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* 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,
|
||||
* 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
|
||||
* 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
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
|
@ -203,7 +223,6 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
|||
assert(xfer);
|
||||
|
||||
status_t result = kStatus_Success;
|
||||
uint16_t timeout = UINT16_MAX;
|
||||
|
||||
if (handle->state != kIdleState)
|
||||
{
|
||||
|
@ -221,16 +240,6 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
|||
|
||||
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. */
|
||||
I2C_MasterClearStatusFlags(base, kClearFlags);
|
||||
|
||||
|
@ -250,22 +259,55 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
|||
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. */
|
||||
if (handle->transfer.subaddressSize)
|
||||
{
|
||||
do
|
||||
{
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
||||
/* Clear interrupt pending flag. */
|
||||
base->S = kI2C_IntPendingFlag;
|
||||
|
||||
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. */
|
||||
result = I2C_CheckAndClearError(base, base->S);
|
||||
|
||||
|
@ -278,34 +320,34 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
|||
|
||||
if (handle->transfer.direction == kI2C_Read)
|
||||
{
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
||||
/* Clear pending flag. */
|
||||
base->S = kI2C_IntPendingFlag;
|
||||
|
||||
/* Send repeated start and slave address. */
|
||||
result = I2C_MasterRepeatedStart(base, handle->transfer.slaveAddress, kI2C_Read);
|
||||
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
||||
/* Check if there's transfer error. */
|
||||
result = I2C_CheckAndClearError(base, base->S);
|
||||
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
||||
/* Clear pending flag. */
|
||||
base->S = kI2C_IntPendingFlag;
|
||||
|
||||
/* Check if there's transfer error. */
|
||||
result = I2C_CheckAndClearError(base, base->S);
|
||||
}
|
||||
|
||||
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.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);
|
||||
}
|
||||
else
|
||||
{
|
||||
transfer_config.majorLoopCounts = handle->transfer.dataSize;
|
||||
}
|
||||
|
||||
transfer_config.majorLoopCounts = (handle->transfer.dataSize - 1);
|
||||
transfer_config.srcTransferSize = kEDMA_TransferSize1Bytes;
|
||||
transfer_config.srcOffset = 0;
|
||||
transfer_config.destTransferSize = kEDMA_TransferSize1Bytes;
|
||||
|
@ -348,6 +380,9 @@ static void I2C_MasterTransferEDMAConfig(I2C_Type *base, i2c_master_edma_handle_
|
|||
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_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)
|
||||
{
|
||||
/* 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. */
|
||||
dummy = base->D;
|
||||
|
@ -479,6 +514,11 @@ status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle
|
|||
{
|
||||
result = I2C_MasterStop(base);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Change direction to send. */
|
||||
base->C1 |= I2C_C1_TX_MASK;
|
||||
}
|
||||
|
||||
/* Read the last byte of data. */
|
||||
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)
|
||||
{
|
||||
*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
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* 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,
|
||||
* 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
|
||||
* 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
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
|
@ -39,7 +39,6 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
@ -56,13 +55,14 @@ typedef void (*i2c_master_edma_transfer_callback_t)(I2C_Type *base,
|
|||
/*! @brief I2C master eDMA transfer structure. */
|
||||
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. */
|
||||
uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */
|
||||
uint8_t state; /*!< I2C master transfer status. */
|
||||
edma_handle_t *dmaHandle; /*!< The eDMA handler used. */
|
||||
i2c_master_edma_transfer_callback_t
|
||||
completionCallback; /*!< Callback function called after eDMA transfer finished. */
|
||||
void *userData; /*!< Callback parameter passed to callback function. */
|
||||
completionCallback; /*!< A callback function called after the eDMA transfer is finished. */
|
||||
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 handle pointer to i2c_master_edma_handle_t structure.
|
||||
* @param callback pointer to user callback function.
|
||||
* @param userData user param passed to the callback function.
|
||||
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||
* @param callback A pointer to the user callback function.
|
||||
* @param userData A user parameter passed to the callback function.
|
||||
* @param edmaHandle eDMA handle pointer.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param base I2C peripheral base address.
|
||||
* @param handle pointer to i2c_master_edma_handle_t structure.
|
||||
* @param xfer pointer to transfer structure of i2c_master_transfer_t.
|
||||
* @retval kStatus_Success Sucessully complete the data transmission.
|
||||
* @retval kStatus_I2C_Busy Previous transmission still not finished.
|
||||
* @retval kStatus_I2C_Timeout Transfer error, wait signal timeout.
|
||||
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||
* @param xfer A pointer to the transfer structure of i2c_master_transfer_t.
|
||||
* @retval kStatus_Success Sucessfully completed the data transmission.
|
||||
* @retval kStatus_I2C_Busy A previous transmission is still not finished.
|
||||
* @retval kStatus_I2C_Timeout Transfer error, waits for a signal timeout.
|
||||
* @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);
|
||||
|
||||
/*!
|
||||
* @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 handle pointer to i2c_master_edma_handle_t structure.
|
||||
* @param count Number of bytes transferred so far by the non-blocking transaction.
|
||||
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||
* @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);
|
||||
|
||||
/*!
|
||||
* @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 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);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* 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,
|
||||
* 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
|
||||
* 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
|
||||
* 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);
|
||||
|
||||
/*!
|
||||
* @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
|
||||
* transfer state.
|
||||
|
@ -137,8 +150,10 @@ static I2C_Type *const s_i2cBases[] = I2C_BASE_PTRS;
|
|||
/*! @brief Pointers to i2c IRQ number for each instance. */
|
||||
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. */
|
||||
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. */
|
||||
static i2c_isr_t s_i2cMasterIsr;
|
||||
|
@ -155,7 +170,7 @@ uint32_t I2C_GetInstance(I2C_Type *base)
|
|||
uint32_t instance;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
status_t result = kStatus_Success;
|
||||
i2c_direction_t direction = xfer->direction;
|
||||
uint16_t timeout = UINT16_MAX;
|
||||
|
||||
/* Initialize the handle transfer information. */
|
||||
handle->transfer = *xfer;
|
||||
|
@ -183,27 +245,13 @@ static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t
|
|||
/* Initial transfer state. */
|
||||
if (handle->transfer.subaddressSize > 0)
|
||||
{
|
||||
handle->state = kSendCommandState;
|
||||
if (xfer->direction == kI2C_Read)
|
||||
{
|
||||
direction = kI2C_Write;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
handle->state = kCheckAddressState;
|
||||
|
||||
/* Clear all status before transfer. */
|
||||
I2C_MasterClearStatusFlags(base, kClearFlags);
|
||||
|
@ -265,34 +313,41 @@ static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_han
|
|||
result = kStatus_Success;
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Handle Check address state to check the slave address is Acked in slave
|
||||
probe application. */
|
||||
if (handle->state == kCheckAddressState)
|
||||
{
|
||||
if (statusFlags & kI2C_ReceiveNakFlag)
|
||||
{
|
||||
return kStatus_I2C_Nak;
|
||||
result = kStatus_I2C_Addr_Nak;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (handle->transfer.direction == kI2C_Write)
|
||||
if (handle->transfer.subaddressSize > 0)
|
||||
{
|
||||
/* Next state, send data. */
|
||||
handle->state = kSendDataState;
|
||||
handle->state = kSendCommandState;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Next state, receive data begin. */
|
||||
handle->state = kReceiveDataBeginState;
|
||||
if (handle->transfer.direction == kI2C_Write)
|
||||
{
|
||||
/* Next state, send data. */
|
||||
handle->state = kSendDataState;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Next state, receive data begin. */
|
||||
handle->state = kReceiveDataBeginState;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Run state machine. */
|
||||
switch (handle->state)
|
||||
{
|
||||
|
@ -375,6 +430,10 @@ static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_han
|
|||
{
|
||||
result = I2C_MasterStop(base);
|
||||
}
|
||||
else
|
||||
{
|
||||
base->C1 |= I2C_C1_TX_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Send NAK at the last receive byte. */
|
||||
|
@ -407,6 +466,7 @@ static void I2C_TransferCommonIRQHandler(I2C_Type *base, void *handle)
|
|||
{
|
||||
s_i2cSlaveIsr(base, handle);
|
||||
}
|
||||
__DSB();
|
||||
}
|
||||
|
||||
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. */
|
||||
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
|
||||
uint8_t s2Reg;
|
||||
#endif
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
/* Enable I2C clock. */
|
||||
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. */
|
||||
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. */
|
||||
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. */
|
||||
fltReg = base->FLT;
|
||||
|
||||
|
@ -472,8 +536,10 @@ void I2C_MasterDeinit(I2C_Type *base)
|
|||
/* Disable I2C module. */
|
||||
I2C_Enable(base, false);
|
||||
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
/* Disable I2C clock. */
|
||||
CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
||||
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||
}
|
||||
|
||||
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. */
|
||||
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. */
|
||||
#if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF
|
||||
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);
|
||||
|
||||
/* 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. */
|
||||
base->F = savedMult;
|
||||
|
@ -721,7 +782,7 @@ uint32_t I2C_MasterGetStatusFlags(I2C_Type *base)
|
|||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
volatile uint8_t dummy = 0;
|
||||
|
@ -817,8 +887,16 @@ status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize)
|
|||
/* Single byte use case. */
|
||||
if (rxSize == 0)
|
||||
{
|
||||
/* Read the final byte. */
|
||||
result = I2C_MasterStop(base);
|
||||
if (!(flags & kI2C_TransferNoStopFlag))
|
||||
{
|
||||
/* Issue STOP command before reading last byte. */
|
||||
result = I2C_MasterStop(base);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Change direction to Tx to avoid extra clocks. */
|
||||
base->C1 |= I2C_C1_TX_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
if (rxSize == 1)
|
||||
|
@ -871,72 +949,6 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
|
|||
return result;
|
||||
}
|
||||
|
||||
/* Send subaddress. */
|
||||
if (xfer->subaddressSize)
|
||||
{
|
||||
do
|
||||
{
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
||||
/* Clear interrupt pending flag. */
|
||||
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;
|
||||
}
|
||||
|
||||
xfer->subaddressSize--;
|
||||
base->D = ((xfer->subaddress) >> (8 * xfer->subaddressSize));
|
||||
|
||||
} while ((xfer->subaddressSize > 0) && (result == kStatus_Success));
|
||||
|
||||
if (xfer->direction == kI2C_Read)
|
||||
{
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
||||
/* Clear pending flag. */
|
||||
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. */
|
||||
result = I2C_MasterRepeatedStart(base, xfer->slaveAddress, kI2C_Read);
|
||||
|
||||
/* Return if error. */
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait until address + command transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
@ -949,32 +961,92 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
|
|||
{
|
||||
if (result == kStatus_I2C_Nak)
|
||||
{
|
||||
result = kStatus_I2C_Addr_Nak;
|
||||
|
||||
I2C_MasterStop(base);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Send subaddress. */
|
||||
if (xfer->subaddressSize)
|
||||
{
|
||||
do
|
||||
{
|
||||
/* Clear interrupt pending flag. */
|
||||
base->S = kI2C_IntPendingFlag;
|
||||
|
||||
xfer->subaddressSize--;
|
||||
base->D = ((xfer->subaddress) >> (8 * xfer->subaddressSize));
|
||||
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(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;
|
||||
}
|
||||
|
||||
} while ((xfer->subaddressSize > 0) && (result == kStatus_Success));
|
||||
|
||||
if (xfer->direction == kI2C_Read)
|
||||
{
|
||||
/* Clear pending flag. */
|
||||
base->S = kI2C_IntPendingFlag;
|
||||
|
||||
/* Send repeated start and slave address. */
|
||||
result = I2C_MasterRepeatedStart(base, xfer->slaveAddress, kI2C_Read);
|
||||
|
||||
/* Return if error. */
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
||||
/* Check if there's transfer error. */
|
||||
result = I2C_CheckAndClearError(base, base->S);
|
||||
|
||||
if (result)
|
||||
{
|
||||
if (result == kStatus_I2C_Nak)
|
||||
{
|
||||
result = kStatus_I2C_Addr_Nak;
|
||||
|
||||
I2C_MasterStop(base);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Transmit data. */
|
||||
if ((xfer->direction == kI2C_Write) && (xfer->dataSize > 0))
|
||||
{
|
||||
/* Send Data. */
|
||||
result = I2C_MasterWriteBlocking(base, xfer->data, xfer->dataSize);
|
||||
|
||||
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);
|
||||
}
|
||||
result = I2C_MasterWriteBlocking(base, xfer->data, xfer->dataSize, xfer->flags);
|
||||
}
|
||||
|
||||
/* Receive Data. */
|
||||
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;
|
||||
|
@ -1037,11 +1109,37 @@ void I2C_MasterTransferAbort(I2C_Type *base, i2c_master_handle_t *handle)
|
|||
{
|
||||
assert(handle);
|
||||
|
||||
volatile uint8_t dummy = 0;
|
||||
|
||||
/* Add this to avoid build warning. */
|
||||
dummy++;
|
||||
|
||||
/* Disable interrupt. */
|
||||
I2C_DisableInterrupts(base, kI2C_GlobalInterruptEnable);
|
||||
|
||||
/* Reset the state to idle. */
|
||||
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)
|
||||
|
@ -1075,7 +1173,8 @@ void I2C_MasterTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
|||
if (isDone || result)
|
||||
{
|
||||
/* 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. */
|
||||
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);
|
||||
|
||||
uint8_t tmpReg;
|
||||
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
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. */
|
||||
switch (slaveConfig->addressingMode)
|
||||
|
@ -1132,14 +1246,10 @@ void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig)
|
|||
tmpReg &= ~I2C_C1_WUEN_MASK;
|
||||
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 &= ~(I2C_C2_SBRC_MASK | I2C_C2_GCAEN_MASK);
|
||||
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;
|
||||
|
||||
/* 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);
|
||||
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)
|
||||
|
@ -1154,8 +1267,10 @@ void I2C_SlaveDeinit(I2C_Type *base)
|
|||
/* Disable I2C module. */
|
||||
I2C_Enable(base, false);
|
||||
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
/* Disable I2C clock. */
|
||||
CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
||||
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||
}
|
||||
|
||||
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. */
|
||||
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. */
|
||||
slaveConfig->enableBaudRateCtl = false;
|
||||
|
||||
|
@ -1184,6 +1294,9 @@ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig)
|
|||
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. */
|
||||
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. */
|
||||
dummy = base->D;
|
||||
|
||||
result = I2C_MasterWriteBlocking(base, txBuff, txSize);
|
||||
result = I2C_MasterWriteBlocking(base, txBuff, txSize, kI2C_TransferDefaultFlag);
|
||||
|
||||
/* Switch to receive mode. */
|
||||
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;
|
||||
|
||||
/* 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. */
|
||||
I2C_SlaveClearStatusFlags(base, kClearFlags);
|
||||
|
@ -1412,7 +1525,10 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
|||
}
|
||||
}
|
||||
|
||||
return;
|
||||
if (!(status & kI2C_AddressMatchFlag))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif /* I2C_HAS_STOP_DETECT */
|
||||
|
||||
|
@ -1482,11 +1598,6 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
|||
handle->isBusy = true;
|
||||
xfer->event = kI2C_SlaveAddressMatchEvent;
|
||||
|
||||
if ((handle->eventMask & xfer->event) && (handle->callback))
|
||||
{
|
||||
handle->callback(base, xfer, handle->userData);
|
||||
}
|
||||
|
||||
/* Slave transmit, master reading from slave. */
|
||||
if (status & kI2C_TransferDirectionFlag)
|
||||
{
|
||||
|
@ -1502,6 +1613,16 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
|||
|
||||
/* 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. */
|
||||
|
@ -1607,27 +1728,30 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(I2C0)
|
||||
void I2C0_DriverIRQHandler(void)
|
||||
{
|
||||
I2C_TransferCommonIRQHandler(I2C0, s_i2cHandle[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (FSL_FEATURE_SOC_I2C_COUNT > 1)
|
||||
#if defined(I2C1)
|
||||
void I2C1_DriverIRQHandler(void)
|
||||
{
|
||||
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)
|
||||
{
|
||||
I2C_TransferCommonIRQHandler(I2C2, s_i2cHandle[2]);
|
||||
}
|
||||
#endif /* I2C COUNT > 2 */
|
||||
#if (FSL_FEATURE_SOC_I2C_COUNT > 3)
|
||||
#endif
|
||||
|
||||
#if defined(I2C3)
|
||||
void I2C3_DriverIRQHandler(void)
|
||||
{
|
||||
I2C_TransferCommonIRQHandler(I2C3, s_i2cHandle[3]);
|
||||
}
|
||||
#endif /* I2C COUNT > 3 */
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* 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,
|
||||
* 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
|
||||
* 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
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
|
@ -37,15 +37,14 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief I2C driver version 2.0.1. */
|
||||
#define FSL_I2C_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))
|
||||
/*! @brief I2C driver version 2.0.3. */
|
||||
#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 || \
|
||||
|
@ -61,6 +60,7 @@ enum _i2c_status
|
|||
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_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 */
|
||||
};
|
||||
|
||||
/*! @brief Direction of master and slave transfers. */
|
||||
/*! @brief The direction of master and slave transfers. */
|
||||
typedef enum _i2c_direction
|
||||
{
|
||||
kI2C_Write = 0x0U, /*!< Master transmit to slave. */
|
||||
kI2C_Read = 0x1U, /*!< Master receive from slave. */
|
||||
kI2C_Write = 0x0U, /*!< Master transmits to the slave. */
|
||||
kI2C_Read = 0x1U, /*!< Master receives from the slave. */
|
||||
} i2c_direction_t;
|
||||
|
||||
/*! @brief Addressing mode. */
|
||||
|
@ -125,17 +125,17 @@ typedef enum _i2c_slave_address_mode
|
|||
/*! @brief I2C transfer control flag. */
|
||||
enum _i2c_master_transfer_flags
|
||||
{
|
||||
kI2C_TransferDefaultFlag = 0x0U, /*!< Transfer starts with a start signal, stops with a stop signal. */
|
||||
kI2C_TransferNoStartFlag = 0x1U, /*!< Transfer starts without a start signal. */
|
||||
kI2C_TransferRepeatedStartFlag = 0x2U, /*!< Transfer starts with a repeated start signal. */
|
||||
kI2C_TransferNoStopFlag = 0x4U, /*!< Transfer ends without a stop signal. */
|
||||
kI2C_TransferDefaultFlag = 0x0U, /*!< A transfer starts with a start signal, stops with a stop signal. */
|
||||
kI2C_TransferNoStartFlag = 0x1U, /*!< A transfer starts without a start signal. */
|
||||
kI2C_TransferRepeatedStartFlag = 0x2U, /*!< A transfer starts with a repeated start signal. */
|
||||
kI2C_TransferNoStopFlag = 0x4U, /*!< A transfer ends without a stop signal. */
|
||||
};
|
||||
|
||||
/*!
|
||||
* @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
|
||||
* 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
|
||||
* parameter.
|
||||
*
|
||||
|
@ -144,36 +144,34 @@ enum _i2c_master_transfer_flags
|
|||
typedef enum _i2c_slave_transfer_event
|
||||
{
|
||||
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). */
|
||||
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). */
|
||||
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
|
||||
kI2C_SlaveStartEvent = 0x10U, /*!< A start/repeated start was detected. */
|
||||
#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 |
|
||||
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||
kI2C_SlaveStartEvent |
|
||||
#endif
|
||||
kI2C_SlaveCompletionEvent,
|
||||
kI2C_SlaveCompletionEvent | kI2C_SlaveGenaralcallEvent,
|
||||
} i2c_slave_transfer_event_t;
|
||||
|
||||
/*! @brief I2C master user configuration. */
|
||||
typedef struct _i2c_master_config
|
||||
{
|
||||
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
|
||||
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
|
||||
bool enableDoubleBuffering; /*!< Controls double buffer enable; notice that
|
||||
enabling the double buffer disables the clock stretch. */
|
||||
#endif
|
||||
uint32_t baudRate_Bps; /*!< Baud rate configuration of I2C peripheral. */
|
||||
|
@ -184,19 +182,20 @@ typedef struct _i2c_master_config
|
|||
typedef struct _i2c_slave_config
|
||||
{
|
||||
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. */
|
||||
#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
|
||||
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. */
|
||||
#endif
|
||||
bool enableBaudRateCtl; /*!< Enables/disables independent slave baud rate on SCL in very fast I2C modes. */
|
||||
uint16_t slaveAddress; /*!< Slave address configuration. */
|
||||
uint16_t upperAddress; /*!< Maximum boundary slave address used in range matching mode. */
|
||||
i2c_slave_address_mode_t addressingMode; /*!< Addressing mode configuration of i2c_slave_address_mode_config_t. */
|
||||
uint16_t slaveAddress; /*!< A slave address configuration. */
|
||||
uint16_t upperAddress; /*!< A maximum boundary slave address used in a range matching mode. */
|
||||
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;
|
||||
|
||||
/*! @brief I2C master handle typedef. */
|
||||
|
@ -214,13 +213,13 @@ typedef struct _i2c_slave_handle i2c_slave_handle_t;
|
|||
/*! @brief I2C master transfer structure. */
|
||||
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. */
|
||||
i2c_direction_t direction; /*!< Transfer direction, read or write. */
|
||||
uint32_t subaddress; /*!< Sub address. Transferred MSB first. */
|
||||
uint8_t subaddressSize; /*!< Size of command buffer. */
|
||||
uint8_t *volatile data; /*!< Transfer buffer. */
|
||||
volatile size_t dataSize; /*!< Transfer size. */
|
||||
i2c_direction_t direction; /*!< A transfer direction, read or write. */
|
||||
uint32_t subaddress; /*!< A sub address. Transferred MSB first. */
|
||||
uint8_t subaddressSize; /*!< A size of the command buffer. */
|
||||
uint8_t *volatile data; /*!< A transfer buffer. */
|
||||
volatile size_t dataSize; /*!< A transfer size. */
|
||||
} i2c_master_transfer_t;
|
||||
|
||||
/*! @brief I2C master handle structure. */
|
||||
|
@ -228,20 +227,21 @@ struct _i2c_master_handle
|
|||
{
|
||||
i2c_master_transfer_t transfer; /*!< I2C master transfer copy. */
|
||||
size_t transferSize; /*!< Total bytes to be transferred. */
|
||||
uint8_t state; /*!< Transfer state maintained during transfer. */
|
||||
i2c_master_transfer_callback_t completionCallback; /*!< Callback function called when transfer finished. */
|
||||
void *userData; /*!< Callback parameter passed to callback function. */
|
||||
uint8_t state; /*!< A transfer state maintained during transfer. */
|
||||
i2c_master_transfer_callback_t completionCallback; /*!< A callback function called when the transfer is finished. */
|
||||
void *userData; /*!< A callback parameter passed to the callback function. */
|
||||
};
|
||||
|
||||
/*! @brief I2C slave transfer structure. */
|
||||
typedef struct _i2c_slave_transfer
|
||||
{
|
||||
i2c_slave_transfer_event_t event; /*!< Reason the callback is being invoked. */
|
||||
uint8_t *volatile data; /*!< Transfer buffer. */
|
||||
volatile size_t dataSize; /*!< Transfer size. */
|
||||
i2c_slave_transfer_event_t event; /*!< A reason that the callback is invoked. */
|
||||
uint8_t *volatile data; /*!< A transfer buffer. */
|
||||
volatile size_t dataSize; /*!< A transfer size. */
|
||||
status_t completionStatus; /*!< Success or error code describing how the transfer completed. Only applies for
|
||||
#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;
|
||||
|
||||
/*! @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. */
|
||||
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. */
|
||||
uint32_t eventMask; /*!< Mask of enabled events. */
|
||||
i2c_slave_transfer_callback_t callback; /*!< Callback function called at transfer event. */
|
||||
void *userData; /*!< Callback parameter passed to callback. */
|
||||
uint32_t eventMask; /*!< A mask of enabled events. */
|
||||
i2c_slave_transfer_callback_t callback; /*!< A callback function called at the transfer event. */
|
||||
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
|
||||
* and configure the I2C with master configuration.
|
||||
*
|
||||
* @note This API should be called at the beginning of the application to use
|
||||
* the I2C driver, or any operation to the I2C module may cause a hard fault
|
||||
* because clock is not enabled. The configuration structure can be filled by user
|
||||
* from scratch, or be set with default values by I2C_MasterGetDefaultConfig().
|
||||
* @note This API should be called at the beginning of the application.
|
||||
* Otherwise, any operation to the I2C module can cause a hard fault
|
||||
* because the clock is not enabled. The configuration structure can be custom filled
|
||||
* or it can be set with default values by using the I2C_MasterGetDefaultConfig().
|
||||
* After calling this API, the master is ready to transfer.
|
||||
* Example:
|
||||
* This is an example.
|
||||
* @code
|
||||
* i2c_master_config_t config = {
|
||||
* .enableMaster = true,
|
||||
|
@ -292,20 +292,20 @@ extern "C" {
|
|||
* @endcode
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
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
|
||||
* 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
|
||||
* the I2C driver, or any operation to the I2C module can cause a hard fault
|
||||
* @note This API should be called at the beginning of the application.
|
||||
* 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
|
||||
* with default values by I2C_SlaveGetDefaultConfig(), or can be filled by the user.
|
||||
* Example
|
||||
* with default values by I2C_SlaveGetDefaultConfig() or it can be custom filled by the user.
|
||||
* This is an example.
|
||||
* @code
|
||||
* i2c_slave_config_t config = {
|
||||
* .enableSlave = true,
|
||||
|
@ -314,15 +314,17 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin
|
|||
* .slaveAddress = 0x1DU,
|
||||
* .enableWakeUp = false,
|
||||
* .enablehighDrive = false,
|
||||
* .enableBaudRateCtl = false
|
||||
* .enableBaudRateCtl = false,
|
||||
* .sclStopHoldTime_ns = 4000
|
||||
* };
|
||||
* I2C_SlaveInit(I2C0, &config);
|
||||
* I2C_SlaveInit(I2C0, &config, 12000000U);
|
||||
* @endcode
|
||||
*
|
||||
* @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.
|
||||
|
@ -342,28 +344,28 @@ void I2C_SlaveDeinit(I2C_Type *base);
|
|||
* @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().
|
||||
* Use the initialized structure unchanged in I2C_MasterConfigure(), or modify some fields of
|
||||
* the structure before calling I2C_MasterConfigure().
|
||||
* Example:
|
||||
* Use the initialized structure unchanged in the I2C_MasterConfigure() or modify
|
||||
* the structure before calling the I2C_MasterConfigure().
|
||||
* This is an example.
|
||||
* @code
|
||||
* i2c_master_config_t config;
|
||||
* I2C_MasterGetDefaultConfig(&config);
|
||||
* @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);
|
||||
|
||||
/*!
|
||||
* @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().
|
||||
* Example:
|
||||
* This is an example.
|
||||
* @code
|
||||
* i2c_slave_config_t config;
|
||||
* I2C_SlaveGetDefaultConfig(&config);
|
||||
* @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);
|
||||
|
||||
|
@ -371,7 +373,7 @@ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig);
|
|||
* @brief Enables or disabless the I2C peripheral operation.
|
||||
*
|
||||
* @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)
|
||||
{
|
||||
|
@ -414,7 +416,7 @@ static inline uint32_t I2C_SlaveGetStatusFlags(I2C_Type *base)
|
|||
/*!
|
||||
* @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 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.
|
||||
*
|
||||
* 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 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);
|
||||
|
||||
/*!
|
||||
* @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 txBuff The pointer to 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_I2C_ArbitrationLost Transfer error, arbitration lost.
|
||||
* @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.
|
||||
* 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 rxBuff The pointer to the data to store the received data.
|
||||
* @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_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.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* 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,
|
||||
* 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
|
||||
* 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
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
|
@ -203,7 +223,6 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
|||
assert(xfer);
|
||||
|
||||
status_t result = kStatus_Success;
|
||||
uint16_t timeout = UINT16_MAX;
|
||||
|
||||
if (handle->state != kIdleState)
|
||||
{
|
||||
|
@ -221,16 +240,6 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
|||
|
||||
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. */
|
||||
I2C_MasterClearStatusFlags(base, kClearFlags);
|
||||
|
||||
|
@ -250,22 +259,55 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
|||
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. */
|
||||
if (handle->transfer.subaddressSize)
|
||||
{
|
||||
do
|
||||
{
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
||||
/* Clear interrupt pending flag. */
|
||||
base->S = kI2C_IntPendingFlag;
|
||||
|
||||
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. */
|
||||
result = I2C_CheckAndClearError(base, base->S);
|
||||
|
||||
|
@ -278,34 +320,34 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
|||
|
||||
if (handle->transfer.direction == kI2C_Read)
|
||||
{
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
||||
/* Clear pending flag. */
|
||||
base->S = kI2C_IntPendingFlag;
|
||||
|
||||
/* Send repeated start and slave address. */
|
||||
result = I2C_MasterRepeatedStart(base, handle->transfer.slaveAddress, kI2C_Read);
|
||||
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
||||
/* Check if there's transfer error. */
|
||||
result = I2C_CheckAndClearError(base, base->S);
|
||||
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
||||
/* Clear pending flag. */
|
||||
base->S = kI2C_IntPendingFlag;
|
||||
|
||||
/* Check if there's transfer error. */
|
||||
result = I2C_CheckAndClearError(base, base->S);
|
||||
}
|
||||
|
||||
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.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);
|
||||
}
|
||||
else
|
||||
{
|
||||
transfer_config.majorLoopCounts = handle->transfer.dataSize;
|
||||
}
|
||||
|
||||
transfer_config.majorLoopCounts = (handle->transfer.dataSize - 1);
|
||||
transfer_config.srcTransferSize = kEDMA_TransferSize1Bytes;
|
||||
transfer_config.srcOffset = 0;
|
||||
transfer_config.destTransferSize = kEDMA_TransferSize1Bytes;
|
||||
|
@ -348,6 +380,9 @@ static void I2C_MasterTransferEDMAConfig(I2C_Type *base, i2c_master_edma_handle_
|
|||
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_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)
|
||||
{
|
||||
/* 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. */
|
||||
dummy = base->D;
|
||||
|
@ -479,6 +514,11 @@ status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle
|
|||
{
|
||||
result = I2C_MasterStop(base);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Change direction to send. */
|
||||
base->C1 |= I2C_C1_TX_MASK;
|
||||
}
|
||||
|
||||
/* Read the last byte of data. */
|
||||
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)
|
||||
{
|
||||
*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
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* 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,
|
||||
* 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
|
||||
* 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
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
|
@ -39,7 +39,6 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
@ -56,13 +55,14 @@ typedef void (*i2c_master_edma_transfer_callback_t)(I2C_Type *base,
|
|||
/*! @brief I2C master eDMA transfer structure. */
|
||||
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. */
|
||||
uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */
|
||||
uint8_t state; /*!< I2C master transfer status. */
|
||||
edma_handle_t *dmaHandle; /*!< The eDMA handler used. */
|
||||
i2c_master_edma_transfer_callback_t
|
||||
completionCallback; /*!< Callback function called after eDMA transfer finished. */
|
||||
void *userData; /*!< Callback parameter passed to callback function. */
|
||||
completionCallback; /*!< A callback function called after the eDMA transfer is finished. */
|
||||
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 handle pointer to i2c_master_edma_handle_t structure.
|
||||
* @param callback pointer to user callback function.
|
||||
* @param userData user param passed to the callback function.
|
||||
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||
* @param callback A pointer to the user callback function.
|
||||
* @param userData A user parameter passed to the callback function.
|
||||
* @param edmaHandle eDMA handle pointer.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param base I2C peripheral base address.
|
||||
* @param handle pointer to i2c_master_edma_handle_t structure.
|
||||
* @param xfer pointer to transfer structure of i2c_master_transfer_t.
|
||||
* @retval kStatus_Success Sucessully complete the data transmission.
|
||||
* @retval kStatus_I2C_Busy Previous transmission still not finished.
|
||||
* @retval kStatus_I2C_Timeout Transfer error, wait signal timeout.
|
||||
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||
* @param xfer A pointer to the transfer structure of i2c_master_transfer_t.
|
||||
* @retval kStatus_Success Sucessfully completed the data transmission.
|
||||
* @retval kStatus_I2C_Busy A previous transmission is still not finished.
|
||||
* @retval kStatus_I2C_Timeout Transfer error, waits for a signal timeout.
|
||||
* @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);
|
||||
|
||||
/*!
|
||||
* @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 handle pointer to i2c_master_edma_handle_t structure.
|
||||
* @param count Number of bytes transferred so far by the non-blocking transaction.
|
||||
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||
* @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);
|
||||
|
||||
/*!
|
||||
* @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 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);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* 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,
|
||||
* 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
|
||||
* 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
|
||||
* 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);
|
||||
|
||||
/*!
|
||||
* @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
|
||||
* transfer state.
|
||||
|
@ -137,8 +150,10 @@ static I2C_Type *const s_i2cBases[] = I2C_BASE_PTRS;
|
|||
/*! @brief Pointers to i2c IRQ number for each instance. */
|
||||
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. */
|
||||
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. */
|
||||
static i2c_isr_t s_i2cMasterIsr;
|
||||
|
@ -155,7 +170,7 @@ uint32_t I2C_GetInstance(I2C_Type *base)
|
|||
uint32_t instance;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
status_t result = kStatus_Success;
|
||||
i2c_direction_t direction = xfer->direction;
|
||||
uint16_t timeout = UINT16_MAX;
|
||||
|
||||
/* Initialize the handle transfer information. */
|
||||
handle->transfer = *xfer;
|
||||
|
@ -183,27 +245,13 @@ static status_t I2C_InitTransferStateMachine(I2C_Type *base, i2c_master_handle_t
|
|||
/* Initial transfer state. */
|
||||
if (handle->transfer.subaddressSize > 0)
|
||||
{
|
||||
handle->state = kSendCommandState;
|
||||
if (xfer->direction == kI2C_Read)
|
||||
{
|
||||
direction = kI2C_Write;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
handle->state = kCheckAddressState;
|
||||
|
||||
/* Clear all status before transfer. */
|
||||
I2C_MasterClearStatusFlags(base, kClearFlags);
|
||||
|
@ -265,34 +313,41 @@ static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_han
|
|||
result = kStatus_Success;
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Handle Check address state to check the slave address is Acked in slave
|
||||
probe application. */
|
||||
if (handle->state == kCheckAddressState)
|
||||
{
|
||||
if (statusFlags & kI2C_ReceiveNakFlag)
|
||||
{
|
||||
return kStatus_I2C_Nak;
|
||||
result = kStatus_I2C_Addr_Nak;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (handle->transfer.direction == kI2C_Write)
|
||||
if (handle->transfer.subaddressSize > 0)
|
||||
{
|
||||
/* Next state, send data. */
|
||||
handle->state = kSendDataState;
|
||||
handle->state = kSendCommandState;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Next state, receive data begin. */
|
||||
handle->state = kReceiveDataBeginState;
|
||||
if (handle->transfer.direction == kI2C_Write)
|
||||
{
|
||||
/* Next state, send data. */
|
||||
handle->state = kSendDataState;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Next state, receive data begin. */
|
||||
handle->state = kReceiveDataBeginState;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Run state machine. */
|
||||
switch (handle->state)
|
||||
{
|
||||
|
@ -375,6 +430,10 @@ static status_t I2C_MasterTransferRunStateMachine(I2C_Type *base, i2c_master_han
|
|||
{
|
||||
result = I2C_MasterStop(base);
|
||||
}
|
||||
else
|
||||
{
|
||||
base->C1 |= I2C_C1_TX_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Send NAK at the last receive byte. */
|
||||
|
@ -407,6 +466,7 @@ static void I2C_TransferCommonIRQHandler(I2C_Type *base, void *handle)
|
|||
{
|
||||
s_i2cSlaveIsr(base, handle);
|
||||
}
|
||||
__DSB();
|
||||
}
|
||||
|
||||
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. */
|
||||
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
|
||||
uint8_t s2Reg;
|
||||
#endif
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
/* Enable I2C clock. */
|
||||
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. */
|
||||
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. */
|
||||
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. */
|
||||
fltReg = base->FLT;
|
||||
|
||||
|
@ -472,8 +536,10 @@ void I2C_MasterDeinit(I2C_Type *base)
|
|||
/* Disable I2C module. */
|
||||
I2C_Enable(base, false);
|
||||
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
/* Disable I2C clock. */
|
||||
CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
||||
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||
}
|
||||
|
||||
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. */
|
||||
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. */
|
||||
#if defined(FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF) && FSL_FEATURE_I2C_HAS_STOP_HOLD_OFF
|
||||
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);
|
||||
|
||||
/* 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. */
|
||||
base->F = savedMult;
|
||||
|
@ -721,7 +782,7 @@ uint32_t I2C_MasterGetStatusFlags(I2C_Type *base)
|
|||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
volatile uint8_t dummy = 0;
|
||||
|
@ -817,8 +887,16 @@ status_t I2C_MasterReadBlocking(I2C_Type *base, uint8_t *rxBuff, size_t rxSize)
|
|||
/* Single byte use case. */
|
||||
if (rxSize == 0)
|
||||
{
|
||||
/* Read the final byte. */
|
||||
result = I2C_MasterStop(base);
|
||||
if (!(flags & kI2C_TransferNoStopFlag))
|
||||
{
|
||||
/* Issue STOP command before reading last byte. */
|
||||
result = I2C_MasterStop(base);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Change direction to Tx to avoid extra clocks. */
|
||||
base->C1 |= I2C_C1_TX_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
if (rxSize == 1)
|
||||
|
@ -871,72 +949,6 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
|
|||
return result;
|
||||
}
|
||||
|
||||
/* Send subaddress. */
|
||||
if (xfer->subaddressSize)
|
||||
{
|
||||
do
|
||||
{
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
||||
/* Clear interrupt pending flag. */
|
||||
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;
|
||||
}
|
||||
|
||||
xfer->subaddressSize--;
|
||||
base->D = ((xfer->subaddress) >> (8 * xfer->subaddressSize));
|
||||
|
||||
} while ((xfer->subaddressSize > 0) && (result == kStatus_Success));
|
||||
|
||||
if (xfer->direction == kI2C_Read)
|
||||
{
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
||||
/* Clear pending flag. */
|
||||
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. */
|
||||
result = I2C_MasterRepeatedStart(base, xfer->slaveAddress, kI2C_Read);
|
||||
|
||||
/* Return if error. */
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait until address + command transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
@ -949,32 +961,92 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
|
|||
{
|
||||
if (result == kStatus_I2C_Nak)
|
||||
{
|
||||
result = kStatus_I2C_Addr_Nak;
|
||||
|
||||
I2C_MasterStop(base);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Send subaddress. */
|
||||
if (xfer->subaddressSize)
|
||||
{
|
||||
do
|
||||
{
|
||||
/* Clear interrupt pending flag. */
|
||||
base->S = kI2C_IntPendingFlag;
|
||||
|
||||
xfer->subaddressSize--;
|
||||
base->D = ((xfer->subaddress) >> (8 * xfer->subaddressSize));
|
||||
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(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;
|
||||
}
|
||||
|
||||
} while ((xfer->subaddressSize > 0) && (result == kStatus_Success));
|
||||
|
||||
if (xfer->direction == kI2C_Read)
|
||||
{
|
||||
/* Clear pending flag. */
|
||||
base->S = kI2C_IntPendingFlag;
|
||||
|
||||
/* Send repeated start and slave address. */
|
||||
result = I2C_MasterRepeatedStart(base, xfer->slaveAddress, kI2C_Read);
|
||||
|
||||
/* Return if error. */
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
||||
/* Check if there's transfer error. */
|
||||
result = I2C_CheckAndClearError(base, base->S);
|
||||
|
||||
if (result)
|
||||
{
|
||||
if (result == kStatus_I2C_Nak)
|
||||
{
|
||||
result = kStatus_I2C_Addr_Nak;
|
||||
|
||||
I2C_MasterStop(base);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Transmit data. */
|
||||
if ((xfer->direction == kI2C_Write) && (xfer->dataSize > 0))
|
||||
{
|
||||
/* Send Data. */
|
||||
result = I2C_MasterWriteBlocking(base, xfer->data, xfer->dataSize);
|
||||
|
||||
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);
|
||||
}
|
||||
result = I2C_MasterWriteBlocking(base, xfer->data, xfer->dataSize, xfer->flags);
|
||||
}
|
||||
|
||||
/* Receive Data. */
|
||||
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;
|
||||
|
@ -1037,11 +1109,37 @@ void I2C_MasterTransferAbort(I2C_Type *base, i2c_master_handle_t *handle)
|
|||
{
|
||||
assert(handle);
|
||||
|
||||
volatile uint8_t dummy = 0;
|
||||
|
||||
/* Add this to avoid build warning. */
|
||||
dummy++;
|
||||
|
||||
/* Disable interrupt. */
|
||||
I2C_DisableInterrupts(base, kI2C_GlobalInterruptEnable);
|
||||
|
||||
/* Reset the state to idle. */
|
||||
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)
|
||||
|
@ -1075,7 +1173,8 @@ void I2C_MasterTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
|||
if (isDone || result)
|
||||
{
|
||||
/* 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. */
|
||||
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);
|
||||
|
||||
uint8_t tmpReg;
|
||||
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
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. */
|
||||
switch (slaveConfig->addressingMode)
|
||||
|
@ -1132,14 +1246,10 @@ void I2C_SlaveInit(I2C_Type *base, const i2c_slave_config_t *slaveConfig)
|
|||
tmpReg &= ~I2C_C1_WUEN_MASK;
|
||||
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 &= ~(I2C_C2_SBRC_MASK | I2C_C2_GCAEN_MASK);
|
||||
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;
|
||||
|
||||
/* 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);
|
||||
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)
|
||||
|
@ -1154,8 +1267,10 @@ void I2C_SlaveDeinit(I2C_Type *base)
|
|||
/* Disable I2C module. */
|
||||
I2C_Enable(base, false);
|
||||
|
||||
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
||||
/* Disable I2C clock. */
|
||||
CLOCK_DisableClock(s_i2cClocks[I2C_GetInstance(base)]);
|
||||
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
|
||||
}
|
||||
|
||||
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. */
|
||||
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. */
|
||||
slaveConfig->enableBaudRateCtl = false;
|
||||
|
||||
|
@ -1184,6 +1294,9 @@ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig)
|
|||
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. */
|
||||
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. */
|
||||
dummy = base->D;
|
||||
|
||||
result = I2C_MasterWriteBlocking(base, txBuff, txSize);
|
||||
result = I2C_MasterWriteBlocking(base, txBuff, txSize, kI2C_TransferDefaultFlag);
|
||||
|
||||
/* Switch to receive mode. */
|
||||
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;
|
||||
|
||||
/* 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. */
|
||||
I2C_SlaveClearStatusFlags(base, kClearFlags);
|
||||
|
@ -1412,7 +1525,10 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
|||
}
|
||||
}
|
||||
|
||||
return;
|
||||
if (!(status & kI2C_AddressMatchFlag))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif /* I2C_HAS_STOP_DETECT */
|
||||
|
||||
|
@ -1482,11 +1598,6 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
|||
handle->isBusy = true;
|
||||
xfer->event = kI2C_SlaveAddressMatchEvent;
|
||||
|
||||
if ((handle->eventMask & xfer->event) && (handle->callback))
|
||||
{
|
||||
handle->callback(base, xfer, handle->userData);
|
||||
}
|
||||
|
||||
/* Slave transmit, master reading from slave. */
|
||||
if (status & kI2C_TransferDirectionFlag)
|
||||
{
|
||||
|
@ -1502,6 +1613,16 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
|||
|
||||
/* 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. */
|
||||
|
@ -1607,27 +1728,30 @@ void I2C_SlaveTransferHandleIRQ(I2C_Type *base, void *i2cHandle)
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(I2C0)
|
||||
void I2C0_DriverIRQHandler(void)
|
||||
{
|
||||
I2C_TransferCommonIRQHandler(I2C0, s_i2cHandle[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (FSL_FEATURE_SOC_I2C_COUNT > 1)
|
||||
#if defined(I2C1)
|
||||
void I2C1_DriverIRQHandler(void)
|
||||
{
|
||||
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)
|
||||
{
|
||||
I2C_TransferCommonIRQHandler(I2C2, s_i2cHandle[2]);
|
||||
}
|
||||
#endif /* I2C COUNT > 2 */
|
||||
#if (FSL_FEATURE_SOC_I2C_COUNT > 3)
|
||||
#endif
|
||||
|
||||
#if defined(I2C3)
|
||||
void I2C3_DriverIRQHandler(void)
|
||||
{
|
||||
I2C_TransferCommonIRQHandler(I2C3, s_i2cHandle[3]);
|
||||
}
|
||||
#endif /* I2C COUNT > 3 */
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* 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,
|
||||
* 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
|
||||
* 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
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
|
@ -37,15 +37,14 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief I2C driver version 2.0.1. */
|
||||
#define FSL_I2C_DRIVER_VERSION (MAKE_VERSION(2, 0, 1))
|
||||
/*! @brief I2C driver version 2.0.3. */
|
||||
#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 || \
|
||||
|
@ -61,6 +60,7 @@ enum _i2c_status
|
|||
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_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 */
|
||||
};
|
||||
|
||||
/*! @brief Direction of master and slave transfers. */
|
||||
/*! @brief The direction of master and slave transfers. */
|
||||
typedef enum _i2c_direction
|
||||
{
|
||||
kI2C_Write = 0x0U, /*!< Master transmit to slave. */
|
||||
kI2C_Read = 0x1U, /*!< Master receive from slave. */
|
||||
kI2C_Write = 0x0U, /*!< Master transmits to the slave. */
|
||||
kI2C_Read = 0x1U, /*!< Master receives from the slave. */
|
||||
} i2c_direction_t;
|
||||
|
||||
/*! @brief Addressing mode. */
|
||||
|
@ -125,17 +125,17 @@ typedef enum _i2c_slave_address_mode
|
|||
/*! @brief I2C transfer control flag. */
|
||||
enum _i2c_master_transfer_flags
|
||||
{
|
||||
kI2C_TransferDefaultFlag = 0x0U, /*!< Transfer starts with a start signal, stops with a stop signal. */
|
||||
kI2C_TransferNoStartFlag = 0x1U, /*!< Transfer starts without a start signal. */
|
||||
kI2C_TransferRepeatedStartFlag = 0x2U, /*!< Transfer starts with a repeated start signal. */
|
||||
kI2C_TransferNoStopFlag = 0x4U, /*!< Transfer ends without a stop signal. */
|
||||
kI2C_TransferDefaultFlag = 0x0U, /*!< A transfer starts with a start signal, stops with a stop signal. */
|
||||
kI2C_TransferNoStartFlag = 0x1U, /*!< A transfer starts without a start signal. */
|
||||
kI2C_TransferRepeatedStartFlag = 0x2U, /*!< A transfer starts with a repeated start signal. */
|
||||
kI2C_TransferNoStopFlag = 0x4U, /*!< A transfer ends without a stop signal. */
|
||||
};
|
||||
|
||||
/*!
|
||||
* @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
|
||||
* 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
|
||||
* parameter.
|
||||
*
|
||||
|
@ -144,36 +144,34 @@ enum _i2c_master_transfer_flags
|
|||
typedef enum _i2c_slave_transfer_event
|
||||
{
|
||||
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). */
|
||||
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). */
|
||||
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
|
||||
kI2C_SlaveStartEvent = 0x10U, /*!< A start/repeated start was detected. */
|
||||
#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 |
|
||||
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||
kI2C_SlaveStartEvent |
|
||||
#endif
|
||||
kI2C_SlaveCompletionEvent,
|
||||
kI2C_SlaveCompletionEvent | kI2C_SlaveGenaralcallEvent,
|
||||
} i2c_slave_transfer_event_t;
|
||||
|
||||
/*! @brief I2C master user configuration. */
|
||||
typedef struct _i2c_master_config
|
||||
{
|
||||
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
|
||||
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
|
||||
bool enableDoubleBuffering; /*!< Controls double buffer enable; notice that
|
||||
enabling the double buffer disables the clock stretch. */
|
||||
#endif
|
||||
uint32_t baudRate_Bps; /*!< Baud rate configuration of I2C peripheral. */
|
||||
|
@ -184,19 +182,20 @@ typedef struct _i2c_master_config
|
|||
typedef struct _i2c_slave_config
|
||||
{
|
||||
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. */
|
||||
#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
|
||||
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. */
|
||||
#endif
|
||||
bool enableBaudRateCtl; /*!< Enables/disables independent slave baud rate on SCL in very fast I2C modes. */
|
||||
uint16_t slaveAddress; /*!< Slave address configuration. */
|
||||
uint16_t upperAddress; /*!< Maximum boundary slave address used in range matching mode. */
|
||||
i2c_slave_address_mode_t addressingMode; /*!< Addressing mode configuration of i2c_slave_address_mode_config_t. */
|
||||
uint16_t slaveAddress; /*!< A slave address configuration. */
|
||||
uint16_t upperAddress; /*!< A maximum boundary slave address used in a range matching mode. */
|
||||
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;
|
||||
|
||||
/*! @brief I2C master handle typedef. */
|
||||
|
@ -214,13 +213,13 @@ typedef struct _i2c_slave_handle i2c_slave_handle_t;
|
|||
/*! @brief I2C master transfer structure. */
|
||||
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. */
|
||||
i2c_direction_t direction; /*!< Transfer direction, read or write. */
|
||||
uint32_t subaddress; /*!< Sub address. Transferred MSB first. */
|
||||
uint8_t subaddressSize; /*!< Size of command buffer. */
|
||||
uint8_t *volatile data; /*!< Transfer buffer. */
|
||||
volatile size_t dataSize; /*!< Transfer size. */
|
||||
i2c_direction_t direction; /*!< A transfer direction, read or write. */
|
||||
uint32_t subaddress; /*!< A sub address. Transferred MSB first. */
|
||||
uint8_t subaddressSize; /*!< A size of the command buffer. */
|
||||
uint8_t *volatile data; /*!< A transfer buffer. */
|
||||
volatile size_t dataSize; /*!< A transfer size. */
|
||||
} i2c_master_transfer_t;
|
||||
|
||||
/*! @brief I2C master handle structure. */
|
||||
|
@ -228,20 +227,21 @@ struct _i2c_master_handle
|
|||
{
|
||||
i2c_master_transfer_t transfer; /*!< I2C master transfer copy. */
|
||||
size_t transferSize; /*!< Total bytes to be transferred. */
|
||||
uint8_t state; /*!< Transfer state maintained during transfer. */
|
||||
i2c_master_transfer_callback_t completionCallback; /*!< Callback function called when transfer finished. */
|
||||
void *userData; /*!< Callback parameter passed to callback function. */
|
||||
uint8_t state; /*!< A transfer state maintained during transfer. */
|
||||
i2c_master_transfer_callback_t completionCallback; /*!< A callback function called when the transfer is finished. */
|
||||
void *userData; /*!< A callback parameter passed to the callback function. */
|
||||
};
|
||||
|
||||
/*! @brief I2C slave transfer structure. */
|
||||
typedef struct _i2c_slave_transfer
|
||||
{
|
||||
i2c_slave_transfer_event_t event; /*!< Reason the callback is being invoked. */
|
||||
uint8_t *volatile data; /*!< Transfer buffer. */
|
||||
volatile size_t dataSize; /*!< Transfer size. */
|
||||
i2c_slave_transfer_event_t event; /*!< A reason that the callback is invoked. */
|
||||
uint8_t *volatile data; /*!< A transfer buffer. */
|
||||
volatile size_t dataSize; /*!< A transfer size. */
|
||||
status_t completionStatus; /*!< Success or error code describing how the transfer completed. Only applies for
|
||||
#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;
|
||||
|
||||
/*! @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. */
|
||||
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. */
|
||||
uint32_t eventMask; /*!< Mask of enabled events. */
|
||||
i2c_slave_transfer_callback_t callback; /*!< Callback function called at transfer event. */
|
||||
void *userData; /*!< Callback parameter passed to callback. */
|
||||
uint32_t eventMask; /*!< A mask of enabled events. */
|
||||
i2c_slave_transfer_callback_t callback; /*!< A callback function called at the transfer event. */
|
||||
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
|
||||
* and configure the I2C with master configuration.
|
||||
*
|
||||
* @note This API should be called at the beginning of the application to use
|
||||
* the I2C driver, or any operation to the I2C module may cause a hard fault
|
||||
* because clock is not enabled. The configuration structure can be filled by user
|
||||
* from scratch, or be set with default values by I2C_MasterGetDefaultConfig().
|
||||
* @note This API should be called at the beginning of the application.
|
||||
* Otherwise, any operation to the I2C module can cause a hard fault
|
||||
* because the clock is not enabled. The configuration structure can be custom filled
|
||||
* or it can be set with default values by using the I2C_MasterGetDefaultConfig().
|
||||
* After calling this API, the master is ready to transfer.
|
||||
* Example:
|
||||
* This is an example.
|
||||
* @code
|
||||
* i2c_master_config_t config = {
|
||||
* .enableMaster = true,
|
||||
|
@ -292,20 +292,20 @@ extern "C" {
|
|||
* @endcode
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
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
|
||||
* 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
|
||||
* the I2C driver, or any operation to the I2C module can cause a hard fault
|
||||
* @note This API should be called at the beginning of the application.
|
||||
* 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
|
||||
* with default values by I2C_SlaveGetDefaultConfig(), or can be filled by the user.
|
||||
* Example
|
||||
* with default values by I2C_SlaveGetDefaultConfig() or it can be custom filled by the user.
|
||||
* This is an example.
|
||||
* @code
|
||||
* i2c_slave_config_t config = {
|
||||
* .enableSlave = true,
|
||||
|
@ -314,15 +314,17 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin
|
|||
* .slaveAddress = 0x1DU,
|
||||
* .enableWakeUp = false,
|
||||
* .enablehighDrive = false,
|
||||
* .enableBaudRateCtl = false
|
||||
* .enableBaudRateCtl = false,
|
||||
* .sclStopHoldTime_ns = 4000
|
||||
* };
|
||||
* I2C_SlaveInit(I2C0, &config);
|
||||
* I2C_SlaveInit(I2C0, &config, 12000000U);
|
||||
* @endcode
|
||||
*
|
||||
* @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.
|
||||
|
@ -342,28 +344,28 @@ void I2C_SlaveDeinit(I2C_Type *base);
|
|||
* @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().
|
||||
* Use the initialized structure unchanged in I2C_MasterConfigure(), or modify some fields of
|
||||
* the structure before calling I2C_MasterConfigure().
|
||||
* Example:
|
||||
* Use the initialized structure unchanged in the I2C_MasterConfigure() or modify
|
||||
* the structure before calling the I2C_MasterConfigure().
|
||||
* This is an example.
|
||||
* @code
|
||||
* i2c_master_config_t config;
|
||||
* I2C_MasterGetDefaultConfig(&config);
|
||||
* @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);
|
||||
|
||||
/*!
|
||||
* @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().
|
||||
* Example:
|
||||
* This is an example.
|
||||
* @code
|
||||
* i2c_slave_config_t config;
|
||||
* I2C_SlaveGetDefaultConfig(&config);
|
||||
* @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);
|
||||
|
||||
|
@ -371,7 +373,7 @@ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig);
|
|||
* @brief Enables or disabless the I2C peripheral operation.
|
||||
*
|
||||
* @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)
|
||||
{
|
||||
|
@ -414,7 +416,7 @@ static inline uint32_t I2C_SlaveGetStatusFlags(I2C_Type *base)
|
|||
/*!
|
||||
* @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 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.
|
||||
*
|
||||
* 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 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);
|
||||
|
||||
/*!
|
||||
* @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 txBuff The pointer to 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_I2C_ArbitrationLost Transfer error, arbitration lost.
|
||||
* @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.
|
||||
* 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 rxBuff The pointer to the data to store the received data.
|
||||
* @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_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.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* 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,
|
||||
* 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
|
||||
* 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
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
|
@ -203,7 +223,6 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
|||
assert(xfer);
|
||||
|
||||
status_t result = kStatus_Success;
|
||||
uint16_t timeout = UINT16_MAX;
|
||||
|
||||
if (handle->state != kIdleState)
|
||||
{
|
||||
|
@ -221,16 +240,6 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
|||
|
||||
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. */
|
||||
I2C_MasterClearStatusFlags(base, kClearFlags);
|
||||
|
||||
|
@ -250,22 +259,55 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
|||
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. */
|
||||
if (handle->transfer.subaddressSize)
|
||||
{
|
||||
do
|
||||
{
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
||||
/* Clear interrupt pending flag. */
|
||||
base->S = kI2C_IntPendingFlag;
|
||||
|
||||
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. */
|
||||
result = I2C_CheckAndClearError(base, base->S);
|
||||
|
||||
|
@ -278,34 +320,34 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
|||
|
||||
if (handle->transfer.direction == kI2C_Read)
|
||||
{
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
||||
/* Clear pending flag. */
|
||||
base->S = kI2C_IntPendingFlag;
|
||||
|
||||
/* Send repeated start and slave address. */
|
||||
result = I2C_MasterRepeatedStart(base, handle->transfer.slaveAddress, kI2C_Read);
|
||||
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
||||
/* Check if there's transfer error. */
|
||||
result = I2C_CheckAndClearError(base, base->S);
|
||||
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
||||
/* Clear pending flag. */
|
||||
base->S = kI2C_IntPendingFlag;
|
||||
|
||||
/* Check if there's transfer error. */
|
||||
result = I2C_CheckAndClearError(base, base->S);
|
||||
}
|
||||
|
||||
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.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);
|
||||
}
|
||||
else
|
||||
{
|
||||
transfer_config.majorLoopCounts = handle->transfer.dataSize;
|
||||
}
|
||||
|
||||
transfer_config.majorLoopCounts = (handle->transfer.dataSize - 1);
|
||||
transfer_config.srcTransferSize = kEDMA_TransferSize1Bytes;
|
||||
transfer_config.srcOffset = 0;
|
||||
transfer_config.destTransferSize = kEDMA_TransferSize1Bytes;
|
||||
|
@ -348,6 +380,9 @@ static void I2C_MasterTransferEDMAConfig(I2C_Type *base, i2c_master_edma_handle_
|
|||
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_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)
|
||||
{
|
||||
/* 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. */
|
||||
dummy = base->D;
|
||||
|
@ -479,6 +514,11 @@ status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle
|
|||
{
|
||||
result = I2C_MasterStop(base);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Change direction to send. */
|
||||
base->C1 |= I2C_C1_TX_MASK;
|
||||
}
|
||||
|
||||
/* Read the last byte of data. */
|
||||
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)
|
||||
{
|
||||
*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
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* 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,
|
||||
* 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
|
||||
* 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
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
|
@ -39,7 +39,6 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
@ -56,13 +55,14 @@ typedef void (*i2c_master_edma_transfer_callback_t)(I2C_Type *base,
|
|||
/*! @brief I2C master eDMA transfer structure. */
|
||||
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. */
|
||||
uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */
|
||||
uint8_t state; /*!< I2C master transfer status. */
|
||||
edma_handle_t *dmaHandle; /*!< The eDMA handler used. */
|
||||
i2c_master_edma_transfer_callback_t
|
||||
completionCallback; /*!< Callback function called after eDMA transfer finished. */
|
||||
void *userData; /*!< Callback parameter passed to callback function. */
|
||||
completionCallback; /*!< A callback function called after the eDMA transfer is finished. */
|
||||
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 handle pointer to i2c_master_edma_handle_t structure.
|
||||
* @param callback pointer to user callback function.
|
||||
* @param userData user param passed to the callback function.
|
||||
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||
* @param callback A pointer to the user callback function.
|
||||
* @param userData A user parameter passed to the callback function.
|
||||
* @param edmaHandle eDMA handle pointer.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param base I2C peripheral base address.
|
||||
* @param handle pointer to i2c_master_edma_handle_t structure.
|
||||
* @param xfer pointer to transfer structure of i2c_master_transfer_t.
|
||||
* @retval kStatus_Success Sucessully complete the data transmission.
|
||||
* @retval kStatus_I2C_Busy Previous transmission still not finished.
|
||||
* @retval kStatus_I2C_Timeout Transfer error, wait signal timeout.
|
||||
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||
* @param xfer A pointer to the transfer structure of i2c_master_transfer_t.
|
||||
* @retval kStatus_Success Sucessfully completed the data transmission.
|
||||
* @retval kStatus_I2C_Busy A previous transmission is still not finished.
|
||||
* @retval kStatus_I2C_Timeout Transfer error, waits for a signal timeout.
|
||||
* @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);
|
||||
|
||||
/*!
|
||||
* @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 handle pointer to i2c_master_edma_handle_t structure.
|
||||
* @param count Number of bytes transferred so far by the non-blocking transaction.
|
||||
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||
* @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);
|
||||
|
||||
/*!
|
||||
* @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 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);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* 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,
|
||||
* 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
|
||||
* 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
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
|
@ -37,16 +37,14 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
/*! @file */
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @name Driver version */
|
||||
/*@{*/
|
||||
/*! @brief I2C driver version 2.0.0. */
|
||||
#define FSL_I2C_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
|
||||
/*! @brief I2C driver version 2.0.3. */
|
||||
#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 || \
|
||||
|
@ -62,6 +60,7 @@ enum _i2c_status
|
|||
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_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 */
|
||||
};
|
||||
|
||||
/*! @brief Direction of master and slave transfers. */
|
||||
/*! @brief The direction of master and slave transfers. */
|
||||
typedef enum _i2c_direction
|
||||
{
|
||||
kI2C_Write = 0x0U, /*!< Master transmit to slave. */
|
||||
kI2C_Read = 0x1U, /*!< Master receive from slave. */
|
||||
kI2C_Write = 0x0U, /*!< Master transmits to the slave. */
|
||||
kI2C_Read = 0x1U, /*!< Master receives from the slave. */
|
||||
} i2c_direction_t;
|
||||
|
||||
/*! @brief Addressing mode. */
|
||||
|
@ -126,17 +125,17 @@ typedef enum _i2c_slave_address_mode
|
|||
/*! @brief I2C transfer control flag. */
|
||||
enum _i2c_master_transfer_flags
|
||||
{
|
||||
kI2C_TransferDefaultFlag = 0x0U, /*!< Transfer starts with a start signal, stops with a stop signal. */
|
||||
kI2C_TransferNoStartFlag = 0x1U, /*!< Transfer starts without a start signal. */
|
||||
kI2C_TransferRepeatedStartFlag = 0x2U, /*!< Transfer starts with a repeated start signal. */
|
||||
kI2C_TransferNoStopFlag = 0x4U, /*!< Transfer ends without a stop signal. */
|
||||
kI2C_TransferDefaultFlag = 0x0U, /*!< A transfer starts with a start signal, stops with a stop signal. */
|
||||
kI2C_TransferNoStartFlag = 0x1U, /*!< A transfer starts without a start signal. */
|
||||
kI2C_TransferRepeatedStartFlag = 0x2U, /*!< A transfer starts with a repeated start signal. */
|
||||
kI2C_TransferNoStopFlag = 0x4U, /*!< A transfer ends without a stop signal. */
|
||||
};
|
||||
|
||||
/*!
|
||||
* @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
|
||||
* 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
|
||||
* parameter.
|
||||
*
|
||||
|
@ -145,33 +144,35 @@ enum _i2c_master_transfer_flags
|
|||
typedef enum _i2c_slave_transfer_event
|
||||
{
|
||||
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). */
|
||||
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). */
|
||||
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
|
||||
kI2C_SlaveRepeatedStartEvent = 0x10U, /*!< A repeated start was detected. */
|
||||
kI2C_SlaveStartEvent = 0x10U, /*!< A start/repeated start was detected. */
|
||||
#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 |
|
||||
#if defined(FSL_FEATURE_I2C_HAS_START_STOP_DETECT) && FSL_FEATURE_I2C_HAS_START_STOP_DETECT
|
||||
kI2C_SlaveRepeatedStartEvent |
|
||||
kI2C_SlaveStartEvent |
|
||||
#endif
|
||||
kI2C_SlaveCompletionEvent,
|
||||
kI2C_SlaveCompletionEvent | kI2C_SlaveGenaralcallEvent,
|
||||
} i2c_slave_transfer_event_t;
|
||||
|
||||
/*! @brief I2C master user configuration. */
|
||||
typedef struct _i2c_master_config
|
||||
{
|
||||
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
|
||||
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
|
||||
uint32_t baudRate_Bps; /*!< Baud rate configuration of I2C peripheral. */
|
||||
uint8_t glitchFilterWidth; /*!< Controls the width of the glitch. */
|
||||
|
@ -181,15 +182,20 @@ typedef struct _i2c_master_config
|
|||
typedef struct _i2c_slave_config
|
||||
{
|
||||
bool enableSlave; /*!< Enables the I2C peripheral at initialization time. */
|
||||
bool enableGeneralCall; /*!< Enable general call addressing 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. */
|
||||
bool enableGeneralCall; /*!< Enables the general call addressing mode. */
|
||||
bool enableWakeUp; /*!< Enables/disables waking up MCU from low-power mode. */
|
||||
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFER_ENABLE
|
||||
bool enableDoubleBuffering; /*!< Controls a double buffer enable; notice that
|
||||
enabling the double buffer disables the clock stretch. */
|
||||
#endif
|
||||
bool enableBaudRateCtl; /*!< Enables/disables independent slave baud rate on SCL in very fast I2C modes. */
|
||||
uint16_t slaveAddress; /*!< Slave address configuration. */
|
||||
uint16_t upperAddress; /*!< Maximum boundary slave address used in range matching mode. */
|
||||
i2c_slave_address_mode_t addressingMode; /*!< Addressing mode configuration of i2c_slave_address_mode_config_t. */
|
||||
uint16_t slaveAddress; /*!< A slave address configuration. */
|
||||
uint16_t upperAddress; /*!< A maximum boundary slave address used in a range matching mode. */
|
||||
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;
|
||||
|
||||
/*! @brief I2C master handle typedef. */
|
||||
|
@ -207,13 +213,13 @@ typedef struct _i2c_slave_handle i2c_slave_handle_t;
|
|||
/*! @brief I2C master transfer structure. */
|
||||
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. */
|
||||
i2c_direction_t direction; /*!< Transfer direction, read or write. */
|
||||
uint32_t subaddress; /*!< Sub address. Transferred MSB first. */
|
||||
uint8_t subaddressSize; /*!< Size of command buffer. */
|
||||
uint8_t *volatile data; /*!< Transfer buffer. */
|
||||
volatile size_t dataSize; /*!< Transfer size. */
|
||||
i2c_direction_t direction; /*!< A transfer direction, read or write. */
|
||||
uint32_t subaddress; /*!< A sub address. Transferred MSB first. */
|
||||
uint8_t subaddressSize; /*!< A size of the command buffer. */
|
||||
uint8_t *volatile data; /*!< A transfer buffer. */
|
||||
volatile size_t dataSize; /*!< A transfer size. */
|
||||
} i2c_master_transfer_t;
|
||||
|
||||
/*! @brief I2C master handle structure. */
|
||||
|
@ -221,20 +227,21 @@ struct _i2c_master_handle
|
|||
{
|
||||
i2c_master_transfer_t transfer; /*!< I2C master transfer copy. */
|
||||
size_t transferSize; /*!< Total bytes to be transferred. */
|
||||
uint8_t state; /*!< Transfer state maintained during transfer. */
|
||||
i2c_master_transfer_callback_t completionCallback; /*!< Callback function called when transfer finished. */
|
||||
void *userData; /*!< Callback parameter passed to callback function. */
|
||||
uint8_t state; /*!< A transfer state maintained during transfer. */
|
||||
i2c_master_transfer_callback_t completionCallback; /*!< A callback function called when the transfer is finished. */
|
||||
void *userData; /*!< A callback parameter passed to the callback function. */
|
||||
};
|
||||
|
||||
/*! @brief I2C slave transfer structure. */
|
||||
typedef struct _i2c_slave_transfer
|
||||
{
|
||||
i2c_slave_transfer_event_t event; /*!< Reason the callback is being invoked. */
|
||||
uint8_t *volatile data; /*!< Transfer buffer. */
|
||||
volatile size_t dataSize; /*!< Transfer size. */
|
||||
i2c_slave_transfer_event_t event; /*!< A reason that the callback is invoked. */
|
||||
uint8_t *volatile data; /*!< A transfer buffer. */
|
||||
volatile size_t dataSize; /*!< A transfer size. */
|
||||
status_t completionStatus; /*!< Success or error code describing how the transfer completed. Only applies for
|
||||
#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;
|
||||
|
||||
/*! @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. */
|
||||
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. */
|
||||
uint32_t eventMask; /*!< Mask of enabled events. */
|
||||
i2c_slave_transfer_callback_t callback; /*!< Callback function called at transfer event. */
|
||||
void *userData; /*!< Callback parameter passed to callback. */
|
||||
uint32_t eventMask; /*!< A mask of enabled events. */
|
||||
i2c_slave_transfer_callback_t callback; /*!< A callback function called at the transfer event. */
|
||||
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
|
||||
* and configure the I2C with master configuration.
|
||||
*
|
||||
* @note This API should be called at the beginning of the application to use
|
||||
* the I2C driver, or any operation to the I2C module could cause hard fault
|
||||
* because clock is not enabled. The configuration structure can be filled by user
|
||||
* from scratch, or be set with default values by I2C_MasterGetDefaultConfig().
|
||||
* @note This API should be called at the beginning of the application.
|
||||
* Otherwise, any operation to the I2C module can cause a hard fault
|
||||
* because the clock is not enabled. The configuration structure can be custom filled
|
||||
* or it can be set with default values by using the I2C_MasterGetDefaultConfig().
|
||||
* After calling this API, the master is ready to transfer.
|
||||
* Example:
|
||||
* This is an example.
|
||||
* @code
|
||||
* i2c_master_config_t config = {
|
||||
* .enableMaster = true,
|
||||
|
@ -285,20 +292,20 @@ extern "C" {
|
|||
* @endcode
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
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
|
||||
* 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
|
||||
* the I2C driver, or any operation to the I2C module can cause a hard fault
|
||||
* @note This API should be called at the beginning of the application.
|
||||
* 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
|
||||
* with default values by I2C_SlaveGetDefaultConfig(), or can be filled by the user.
|
||||
* Example
|
||||
* with default values by I2C_SlaveGetDefaultConfig() or it can be custom filled by the user.
|
||||
* This is an example.
|
||||
* @code
|
||||
* i2c_slave_config_t config = {
|
||||
* .enableSlave = true,
|
||||
|
@ -307,15 +314,17 @@ void I2C_MasterInit(I2C_Type *base, const i2c_master_config_t *masterConfig, uin
|
|||
* .slaveAddress = 0x1DU,
|
||||
* .enableWakeUp = false,
|
||||
* .enablehighDrive = false,
|
||||
* .enableBaudRateCtl = false
|
||||
* .enableBaudRateCtl = false,
|
||||
* .sclStopHoldTime_ns = 4000
|
||||
* };
|
||||
* I2C_SlaveInit(I2C0, &config);
|
||||
* I2C_SlaveInit(I2C0, &config, 12000000U);
|
||||
* @endcode
|
||||
*
|
||||
* @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.
|
||||
|
@ -335,28 +344,28 @@ void I2C_SlaveDeinit(I2C_Type *base);
|
|||
* @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().
|
||||
* Use the initialized structure unchanged in I2C_MasterConfigure(), or modify some fields of
|
||||
* the structure before calling I2C_MasterConfigure().
|
||||
* Example:
|
||||
* Use the initialized structure unchanged in the I2C_MasterConfigure() or modify
|
||||
* the structure before calling the I2C_MasterConfigure().
|
||||
* This is an example.
|
||||
* @code
|
||||
* i2c_master_config_t config;
|
||||
* I2C_MasterGetDefaultConfig(&config);
|
||||
* @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);
|
||||
|
||||
/*!
|
||||
* @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().
|
||||
* Example:
|
||||
* This is an example.
|
||||
* @code
|
||||
* i2c_slave_config_t config;
|
||||
* I2C_SlaveGetDefaultConfig(&config);
|
||||
* @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);
|
||||
|
||||
|
@ -364,7 +373,7 @@ void I2C_SlaveGetDefaultConfig(i2c_slave_config_t *slaveConfig);
|
|||
* @brief Enables or disabless the I2C peripheral operation.
|
||||
*
|
||||
* @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)
|
||||
{
|
||||
|
@ -389,7 +398,7 @@ static inline void I2C_Enable(I2C_Type *base, bool enable)
|
|||
* @brief Gets the I2C status flags.
|
||||
*
|
||||
* @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);
|
||||
|
||||
|
@ -397,7 +406,7 @@ uint32_t I2C_MasterGetStatusFlags(I2C_Type *base);
|
|||
* @brief Gets the I2C status flags.
|
||||
*
|
||||
* @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)
|
||||
{
|
||||
|
@ -407,11 +416,11 @@ static inline uint32_t I2C_SlaveGetStatusFlags(I2C_Type *base)
|
|||
/*!
|
||||
* @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 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_StopDetectFlag (if available)
|
||||
* @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.
|
||||
*
|
||||
* 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 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_StopDetectFlag (if available)
|
||||
* @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);
|
||||
|
||||
/*!
|
||||
* @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 txBuff The pointer to 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_I2C_ArbitrationLost Transfer error, arbitration lost.
|
||||
* @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.
|
||||
* 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 rxBuff The pointer to the data to store the received data.
|
||||
* @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_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.
|
||||
|
@ -650,7 +663,7 @@ status_t I2C_MasterTransferBlocking(I2C_Type *base, i2c_master_transfer_t *xfer)
|
|||
* @param base I2C base pointer.
|
||||
* @param handle pointer to i2c_master_handle_t structure to store the transfer state.
|
||||
* @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,
|
||||
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.
|
||||
*
|
||||
* @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
|
||||
* 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.
|
||||
*
|
||||
* @param base I2C base pointer.
|
||||
* @param handle pointer to i2c_master_handle_t structure which stores the transfer state.
|
||||
* @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_Timeout Transfer error, wait signal timeout.
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* 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,
|
||||
* 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
|
||||
* 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
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
|
@ -203,7 +223,6 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
|||
assert(xfer);
|
||||
|
||||
status_t result = kStatus_Success;
|
||||
uint16_t timeout = UINT16_MAX;
|
||||
|
||||
if (handle->state != kIdleState)
|
||||
{
|
||||
|
@ -221,16 +240,6 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
|||
|
||||
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. */
|
||||
I2C_MasterClearStatusFlags(base, kClearFlags);
|
||||
|
||||
|
@ -250,22 +259,55 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
|||
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. */
|
||||
if (handle->transfer.subaddressSize)
|
||||
{
|
||||
do
|
||||
{
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
||||
/* Clear interrupt pending flag. */
|
||||
base->S = kI2C_IntPendingFlag;
|
||||
|
||||
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. */
|
||||
result = I2C_CheckAndClearError(base, base->S);
|
||||
|
||||
|
@ -278,34 +320,34 @@ static status_t I2C_InitTransferStateMachineEDMA(I2C_Type *base,
|
|||
|
||||
if (handle->transfer.direction == kI2C_Read)
|
||||
{
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
||||
/* Clear pending flag. */
|
||||
base->S = kI2C_IntPendingFlag;
|
||||
|
||||
/* Send repeated start and slave address. */
|
||||
result = I2C_MasterRepeatedStart(base, handle->transfer.slaveAddress, kI2C_Read);
|
||||
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
||||
/* Check if there's transfer error. */
|
||||
result = I2C_CheckAndClearError(base, base->S);
|
||||
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Wait until data transfer complete. */
|
||||
while (!(base->S & kI2C_IntPendingFlag))
|
||||
{
|
||||
}
|
||||
|
||||
/* Clear pending flag. */
|
||||
base->S = kI2C_IntPendingFlag;
|
||||
|
||||
/* Check if there's transfer error. */
|
||||
result = I2C_CheckAndClearError(base, base->S);
|
||||
}
|
||||
|
||||
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.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);
|
||||
}
|
||||
else
|
||||
{
|
||||
transfer_config.majorLoopCounts = handle->transfer.dataSize;
|
||||
}
|
||||
|
||||
transfer_config.majorLoopCounts = (handle->transfer.dataSize - 1);
|
||||
transfer_config.srcTransferSize = kEDMA_TransferSize1Bytes;
|
||||
transfer_config.srcOffset = 0;
|
||||
transfer_config.destTransferSize = kEDMA_TransferSize1Bytes;
|
||||
|
@ -348,6 +380,9 @@ static void I2C_MasterTransferEDMAConfig(I2C_Type *base, i2c_master_edma_handle_
|
|||
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_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)
|
||||
{
|
||||
/* 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. */
|
||||
dummy = base->D;
|
||||
|
@ -479,6 +514,11 @@ status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle
|
|||
{
|
||||
result = I2C_MasterStop(base);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Change direction to send. */
|
||||
base->C1 |= I2C_C1_TX_MASK;
|
||||
}
|
||||
|
||||
/* Read the last byte of data. */
|
||||
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)
|
||||
{
|
||||
*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
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* 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,
|
||||
* 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
|
||||
* 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
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
|
@ -39,31 +39,30 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
/*! @file */
|
||||
|
||||
/*******************************************************************************
|
||||
* Definitions
|
||||
******************************************************************************/
|
||||
|
||||
/*! @brief I2C master edma handle typedef. */
|
||||
/*! @brief I2C master eDMA handle typedef. */
|
||||
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,
|
||||
i2c_master_edma_handle_t *handle,
|
||||
status_t status,
|
||||
void *userData);
|
||||
|
||||
/*! @brief I2C master edma transfer structure. */
|
||||
/*! @brief I2C master eDMA transfer structure. */
|
||||
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. */
|
||||
uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */
|
||||
uint8_t state; /*!< I2C master transfer status. */
|
||||
edma_handle_t *dmaHandle; /*!< The eDMA handler used. */
|
||||
i2c_master_edma_transfer_callback_t
|
||||
completionCallback; /*!< Callback function called after edma transfer finished. */
|
||||
void *userData; /*!< Callback parameter passed to callback function. */
|
||||
completionCallback; /*!< A callback function called after the eDMA transfer is finished. */
|
||||
void *userData; /*!< A callback parameter passed to the callback function. */
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -75,18 +74,18 @@ extern "C" {
|
|||
#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 handle pointer to i2c_master_edma_handle_t structure.
|
||||
* @param callback pointer to user callback function.
|
||||
* @param userData user param passed to the callback function.
|
||||
* @param edmaHandle EDMA handle pointer.
|
||||
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||
* @param callback A pointer to the user callback function.
|
||||
* @param userData A user parameter passed to the callback function.
|
||||
* @param edmaHandle eDMA handle pointer.
|
||||
*/
|
||||
void I2C_MasterCreateEDMAHandle(I2C_Type *base,
|
||||
i2c_master_edma_handle_t *handle,
|
||||
|
@ -95,33 +94,33 @@ void I2C_MasterCreateEDMAHandle(I2C_Type *base,
|
|||
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 handle pointer to i2c_master_edma_handle_t structure.
|
||||
* @param xfer pointer to transfer structure of i2c_master_transfer_t.
|
||||
* @retval kStatus_Success Sucessully complete the data transmission.
|
||||
* @retval kStatus_I2C_Busy Previous transmission still not finished.
|
||||
* @retval kStatus_I2C_Timeout Transfer error, wait signal timeout.
|
||||
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||
* @param xfer A pointer to the transfer structure of i2c_master_transfer_t.
|
||||
* @retval kStatus_Success Sucessfully completed the data transmission.
|
||||
* @retval kStatus_I2C_Busy A previous transmission is still not finished.
|
||||
* @retval kStatus_I2C_Timeout Transfer error, waits for a signal timeout.
|
||||
* @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);
|
||||
|
||||
/*!
|
||||
* @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 handle pointer to i2c_master_edma_handle_t structure.
|
||||
* @param count Number of bytes transferred so far by the non-blocking transaction.
|
||||
* @param handle A pointer to the i2c_master_edma_handle_t structure.
|
||||
* @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);
|
||||
|
||||
/*!
|
||||
* @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 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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue