mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #6310 from codeauroraforum/Fix_K82F_I2C
MCUXpresso: Fix test failures seen with ci-test shieldpull/6211/merge
commit
842a86ad7c
|
@ -36,7 +36,7 @@
|
||||||
/* Array for I2C module clocks */
|
/* Array for I2C module clocks */
|
||||||
#define I2C_CLOCK_FREQS \
|
#define I2C_CLOCK_FREQS \
|
||||||
{ \
|
{ \
|
||||||
I2C0_CLK_SRC, I2C1_CLK_SRC, I2C2_CLK_SRC \
|
I2C0_CLK_SRC, I2C1_CLK_SRC, I2C2_CLK_SRC, I2C3_CLK_SRC \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Array for DSPI module clocks */
|
/* Array for DSPI module clocks */
|
||||||
|
|
|
@ -36,6 +36,9 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl)
|
||||||
{
|
{
|
||||||
uint32_t i2c_sda = pinmap_peripheral(sda, PinMap_I2C_SDA);
|
uint32_t i2c_sda = pinmap_peripheral(sda, PinMap_I2C_SDA);
|
||||||
uint32_t i2c_scl = pinmap_peripheral(scl, PinMap_I2C_SCL);
|
uint32_t i2c_scl = pinmap_peripheral(scl, PinMap_I2C_SCL);
|
||||||
|
PORT_Type *port_addrs[] = PORT_BASE_PTRS;
|
||||||
|
PORT_Type *base = port_addrs[sda >> GPIO_PORT_SHIFT];
|
||||||
|
|
||||||
obj->instance = pinmap_merge(i2c_sda, i2c_scl);
|
obj->instance = pinmap_merge(i2c_sda, i2c_scl);
|
||||||
obj->next_repeated_start = 0;
|
obj->next_repeated_start = 0;
|
||||||
MBED_ASSERT((int)obj->instance != NC);
|
MBED_ASSERT((int)obj->instance != NC);
|
||||||
|
@ -49,10 +52,11 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl)
|
||||||
pinmap_pinout(sda, PinMap_I2C_SDA);
|
pinmap_pinout(sda, PinMap_I2C_SDA);
|
||||||
pinmap_pinout(scl, PinMap_I2C_SCL);
|
pinmap_pinout(scl, PinMap_I2C_SCL);
|
||||||
|
|
||||||
#if defined(FSL_FEATURE_PORT_HAS_OPEN_DRAIN) && FSL_FEATURE_PORT_HAS_OPEN_DRAIN
|
/* Enable internal pullup resistor */
|
||||||
PORT_Type *port_addrs[] = PORT_BASE_PTRS;
|
base->PCR[sda & 0xFF] |= (PORT_PCR_PE_MASK | PORT_PCR_PS_MASK);
|
||||||
PORT_Type *base = port_addrs[sda >> GPIO_PORT_SHIFT];
|
base->PCR[scl & 0xFF] |= (PORT_PCR_PE_MASK | PORT_PCR_PS_MASK);
|
||||||
|
|
||||||
|
#if defined(FSL_FEATURE_PORT_HAS_OPEN_DRAIN) && FSL_FEATURE_PORT_HAS_OPEN_DRAIN
|
||||||
base->PCR[sda & 0xFF] |= PORT_PCR_ODE_MASK;
|
base->PCR[sda & 0xFF] |= PORT_PCR_ODE_MASK;
|
||||||
base->PCR[scl & 0xFF] |= PORT_PCR_ODE_MASK;
|
base->PCR[scl & 0xFF] |= PORT_PCR_ODE_MASK;
|
||||||
#endif
|
#endif
|
||||||
|
@ -63,12 +67,14 @@ int i2c_start(i2c_t *obj)
|
||||||
I2C_Type *base = i2c_addrs[obj->instance];
|
I2C_Type *base = i2c_addrs[obj->instance];
|
||||||
uint32_t statusFlags = I2C_MasterGetStatusFlags(base);
|
uint32_t statusFlags = I2C_MasterGetStatusFlags(base);
|
||||||
|
|
||||||
/* Return an error if the bus is already in use. */
|
/* Check if the bus is already in use. */
|
||||||
if (statusFlags & kI2C_BusBusyFlag) {
|
if (statusFlags & kI2C_BusBusyFlag) {
|
||||||
return 1;
|
/* Send a repeat START signal. */
|
||||||
}
|
base->C1 |= I2C_C1_RSTA_MASK;
|
||||||
|
} else {
|
||||||
/* Send the START signal. */
|
/* Send the START signal. */
|
||||||
base->C1 |= I2C_C1_MST_MASK | I2C_C1_TX_MASK;
|
base->C1 |= I2C_C1_MST_MASK | I2C_C1_TX_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFERING) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFERING
|
#if defined(FSL_FEATURE_I2C_HAS_DOUBLE_BUFFERING) && FSL_FEATURE_I2C_HAS_DOUBLE_BUFFERING
|
||||||
while (!(base->S2 & I2C_S2_EMPTY_MASK))
|
while (!(base->S2 & I2C_S2_EMPTY_MASK))
|
||||||
|
@ -81,7 +87,6 @@ int i2c_start(i2c_t *obj)
|
||||||
|
|
||||||
int i2c_stop(i2c_t *obj)
|
int i2c_stop(i2c_t *obj)
|
||||||
{
|
{
|
||||||
obj->next_repeated_start = 0;
|
|
||||||
if (I2C_MasterStop(i2c_addrs[obj->instance]) != kStatus_Success) {
|
if (I2C_MasterStop(i2c_addrs[obj->instance]) != kStatus_Success) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -179,39 +184,64 @@ int i2c_byte_read(i2c_t *obj, int last)
|
||||||
{
|
{
|
||||||
uint8_t data;
|
uint8_t data;
|
||||||
I2C_Type *base = i2c_addrs[obj->instance];
|
I2C_Type *base = i2c_addrs[obj->instance];
|
||||||
i2c_master_transfer_t master_xfer;
|
|
||||||
|
|
||||||
memset(&master_xfer, 0, sizeof(master_xfer));
|
/* Setup the I2C peripheral to receive data. */
|
||||||
master_xfer.slaveAddress = i2c_address;
|
base->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK);
|
||||||
master_xfer.direction = kI2C_Read;
|
|
||||||
master_xfer.data = &data;
|
|
||||||
master_xfer.dataSize = 1;
|
|
||||||
|
|
||||||
/* The below function will issue a STOP signal at the end of the transfer.
|
if (last) {
|
||||||
* This is required by the hardware in order to receive the last byte
|
base->C1 |= I2C_C1_TXAK_MASK; // NACK
|
||||||
*/
|
|
||||||
if (I2C_MasterTransferBlocking(base, &master_xfer) != kStatus_Success) {
|
|
||||||
return I2C_ERROR_NO_SLAVE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data = (base->D & 0xFF);
|
||||||
|
|
||||||
|
/* Change direction to Tx to avoid extra clocks. */
|
||||||
|
base->C1 |= I2C_C1_TX_MASK;
|
||||||
|
|
||||||
|
/* Wait until data transfer complete. */
|
||||||
|
while (!(base->S & kI2C_IntPendingFlag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear the IICIF flag. */
|
||||||
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
int i2c_byte_write(i2c_t *obj, int data)
|
int i2c_byte_write(i2c_t *obj, int data)
|
||||||
{
|
{
|
||||||
status_t ret_value;
|
int ret_value = 1;
|
||||||
#if FSL_I2C_DRIVER_VERSION > MAKE_VERSION(2, 0, 1)
|
uint8_t statusFlags = 0;
|
||||||
ret_value = I2C_MasterWriteBlocking(i2c_addrs[obj->instance], (uint8_t *)(&data), 1, kI2C_TransferNoStopFlag);
|
I2C_Type *base = i2c_addrs[obj->instance];
|
||||||
#else
|
|
||||||
ret_value = I2C_MasterWriteBlocking(i2c_addrs[obj->instance], (uint8_t *)(&data), 1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ret_value == kStatus_Success) {
|
/* Setup the I2C peripheral to transmit data. */
|
||||||
return 1;
|
base->C1 |= I2C_C1_TX_MASK;
|
||||||
} else if (ret_value == kStatus_I2C_Nak) {
|
|
||||||
return 0;
|
/* Send a byte of data. */
|
||||||
} else {
|
base->D = data;
|
||||||
return 2;
|
|
||||||
|
/* Wait until data transfer complete. */
|
||||||
|
while (!(base->S & kI2C_IntPendingFlag)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
statusFlags = base->S;
|
||||||
|
|
||||||
|
/* Clear the IICIF flag. */
|
||||||
|
base->S = kI2C_IntPendingFlag;
|
||||||
|
|
||||||
|
/* Check if arbitration lost */
|
||||||
|
if (statusFlags & kI2C_ArbitrationLostFlag) {
|
||||||
|
base->S = kI2C_ArbitrationLostFlag;
|
||||||
|
ret_value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if no acknowledgement (NAK) */
|
||||||
|
if (statusFlags & kI2C_ReceiveNakFlag) {
|
||||||
|
base->S = kI2C_ReceiveNakFlag;
|
||||||
|
ret_value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue