mirror of https://github.com/ARMmbed/mbed-os.git
commit
d8d8c28e11
|
@ -48,7 +48,6 @@
|
||||||
#define I2C_SPEED_400K_AT_8MHZ (uint8_t)0x03
|
#define I2C_SPEED_400K_AT_8MHZ (uint8_t)0x03
|
||||||
#define I2C_SPEED_400K_AT_16MHZ (uint8_t)0x08
|
#define I2C_SPEED_400K_AT_16MHZ (uint8_t)0x08
|
||||||
|
|
||||||
|
|
||||||
/* I2C commands */
|
/* I2C commands */
|
||||||
#define I2C_CMD_NULL 0x00
|
#define I2C_CMD_NULL 0x00
|
||||||
#define I2C_CMD_WDAT0 0x10
|
#define I2C_CMD_WDAT0 0x10
|
||||||
|
@ -93,7 +92,10 @@
|
||||||
#define I2C_API_STATUS_SUCCESS 0
|
#define I2C_API_STATUS_SUCCESS 0
|
||||||
#define PAD_REG_ADRS_BYTE_SIZE 4
|
#define PAD_REG_ADRS_BYTE_SIZE 4
|
||||||
|
|
||||||
#define SEND_COMMAND(cmd) while(!I2C_FIFO_EMPTY); wait_us(1); obj->membase->CMD_REG = cmd;
|
// The wait_us(0) command is needed so the I2C state machines have enough
|
||||||
|
// time for data to settle across all clock domain crossings in their
|
||||||
|
// synchronizers, both directions.
|
||||||
|
#define SEND_COMMAND(cmd) wait_us(0); obj->membase->CMD_REG = cmd; wait_us(0);
|
||||||
|
|
||||||
/** Init I2C device.
|
/** Init I2C device.
|
||||||
* @details
|
* @details
|
||||||
|
|
|
@ -169,9 +169,7 @@ int i2c_byte_write(i2c_t *obj, int data)
|
||||||
return Count;
|
return Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
while(obj->membase->STATUS.WORD & I2C_STATUS_CMD_FIFO_OFL_BIT); /* Wait till command overflow ends */
|
if(I2C_BUS_ERR_CHECK) {
|
||||||
|
|
||||||
if(obj->membase->STATUS.WORD & I2C_STATUS_BUS_ERR_BIT) {
|
|
||||||
/* Bus error means NAK received */
|
/* Bus error means NAK received */
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -65,7 +65,6 @@
|
||||||
/* See i2c.h for details */
|
/* See i2c.h for details */
|
||||||
void fI2cInit(i2c_t *obj,PinName sda,PinName scl)
|
void fI2cInit(i2c_t *obj,PinName sda,PinName scl)
|
||||||
{
|
{
|
||||||
uint32_t clockDivisor;
|
|
||||||
/* determine the I2C to use */
|
/* determine the I2C to use */
|
||||||
I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
|
I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
|
||||||
I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);
|
I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);
|
||||||
|
@ -93,9 +92,7 @@ void fI2cInit(i2c_t *obj,PinName sda,PinName scl)
|
||||||
obj->membase->CR.BITS.I2C_APB_CD_EN = True;
|
obj->membase->CR.BITS.I2C_APB_CD_EN = True;
|
||||||
|
|
||||||
/* set default baud rate at 100k */
|
/* set default baud rate at 100k */
|
||||||
clockDivisor = ((fClockGetPeriphClockfrequency() / 100000) >> 2) - 2;
|
fI2cFrequency(obj, 100000);
|
||||||
obj->membase->CR.BITS.CD_VAL = (clockDivisor & I2C_CLOCKDIVEDER_VAL_MASK);
|
|
||||||
obj->membase->PRE_SCALE_REG = (clockDivisor & I2C_APB_CLK_DIVIDER_VAL_MASK) >> 5; /**< Zero pre-scale value not allowed */
|
|
||||||
|
|
||||||
/* Cross bar setting */
|
/* Cross bar setting */
|
||||||
pinmap_pinout(sda, PinMap_I2C_SDA);
|
pinmap_pinout(sda, PinMap_I2C_SDA);
|
||||||
|
@ -110,8 +107,8 @@ void fI2cInit(i2c_t *obj,PinName sda,PinName scl)
|
||||||
PadReg_t *padRegScl = (PadReg_t*)(PADREG_BASE + (scl * PAD_REG_ADRS_BYTE_SIZE));
|
PadReg_t *padRegScl = (PadReg_t*)(PADREG_BASE + (scl * PAD_REG_ADRS_BYTE_SIZE));
|
||||||
|
|
||||||
CLOCK_ENABLE(CLOCK_PAD);
|
CLOCK_ENABLE(CLOCK_PAD);
|
||||||
padRegSda->PADIO0.BITS.POWER = 1; /* sda: Drive strength */
|
padRegSda->PADIO0.BITS.POWER = 3; /* sda: Drive strength */
|
||||||
padRegScl->PADIO0.BITS.POWER = 1; /* scl: Drive strength */
|
padRegScl->PADIO0.BITS.POWER = 3; /* scl: Drive strength */
|
||||||
CLOCK_DISABLE(CLOCK_PAD);
|
CLOCK_DISABLE(CLOCK_PAD);
|
||||||
|
|
||||||
CLOCK_ENABLE(CLOCK_GPIO);
|
CLOCK_ENABLE(CLOCK_GPIO);
|
||||||
|
@ -160,6 +157,9 @@ int32_t fI2cReadB(i2c_t *obj, char *buf, int len)
|
||||||
int32_t read = 0;
|
int32_t read = 0;
|
||||||
|
|
||||||
while (read < len) {
|
while (read < len) {
|
||||||
|
|
||||||
|
while(FIFO_OFL_CHECK); /* Wait till command overflow ends */
|
||||||
|
|
||||||
/* Send read command */
|
/* Send read command */
|
||||||
SEND_COMMAND(I2C_CMD_RDAT8);
|
SEND_COMMAND(I2C_CMD_RDAT8);
|
||||||
while(!RD_DATA_READY) {
|
while(!RD_DATA_READY) {
|
||||||
|
@ -170,8 +170,8 @@ int32_t fI2cReadB(i2c_t *obj, char *buf, int len)
|
||||||
}
|
}
|
||||||
buf[read++] = obj->membase->RD_FIFO_REG; /**< Reading 'read FIFO register' will clear status register */
|
buf[read++] = obj->membase->RD_FIFO_REG; /**< Reading 'read FIFO register' will clear status register */
|
||||||
|
|
||||||
if(!(read>=len)) { /* No ACK will be generated for the last read, upper level I2C protocol should generate */
|
if(!(read>=len)) {
|
||||||
SEND_COMMAND(I2C_CMD_WDAT0); /* TODO based on requirement generate ACK or NACK Based on the requirement. */
|
SEND_COMMAND(I2C_CMD_WDAT0);
|
||||||
} else {
|
} else {
|
||||||
/* No ack */
|
/* No ack */
|
||||||
SEND_COMMAND(I2C_CMD_WDAT1);
|
SEND_COMMAND(I2C_CMD_WDAT1);
|
||||||
|
@ -179,7 +179,7 @@ int32_t fI2cReadB(i2c_t *obj, char *buf, int len)
|
||||||
|
|
||||||
/* check for FIFO underflow */
|
/* check for FIFO underflow */
|
||||||
if(I2C_UFL_CHECK) {
|
if(I2C_UFL_CHECK) {
|
||||||
return I2C_ERROR_NO_SLAVE; /* TODO No error available for this in i2c_api.h */
|
return I2C_EVENT_ERROR;
|
||||||
}
|
}
|
||||||
if(I2C_BUS_ERR_CHECK) {
|
if(I2C_BUS_ERR_CHECK) {
|
||||||
/* Bus error */
|
/* Bus error */
|
||||||
|
@ -196,8 +196,8 @@ int32_t fI2cWriteB(i2c_t *obj, const char *buf, int len)
|
||||||
int32_t write = 0;
|
int32_t write = 0;
|
||||||
|
|
||||||
while (write < len) {
|
while (write < len) {
|
||||||
/* Send write command */
|
|
||||||
SEND_COMMAND(I2C_CMD_WDAT8);
|
while(FIFO_OFL_CHECK); /* Wait till command overflow ends */
|
||||||
|
|
||||||
if(buf[write] == I2C_CMD_RDAT8) {
|
if(buf[write] == I2C_CMD_RDAT8) {
|
||||||
/* SW work around to counter FSM issue. If the only command in the CMD FIFO is the WDAT8 command (data of 0x13)
|
/* SW work around to counter FSM issue. If the only command in the CMD FIFO is the WDAT8 command (data of 0x13)
|
||||||
|
@ -205,34 +205,26 @@ int32_t fI2cWriteB(i2c_t *obj, const char *buf, int len)
|
||||||
RDAT8 command by the data FSM; resulting in an I2C bus error (NACK instead of an ACK). */
|
RDAT8 command by the data FSM; resulting in an I2C bus error (NACK instead of an ACK). */
|
||||||
/* Send 0x13 bit wise */
|
/* Send 0x13 bit wise */
|
||||||
SEND_COMMAND(I2C_CMD_WDAT0);
|
SEND_COMMAND(I2C_CMD_WDAT0);
|
||||||
|
|
||||||
SEND_COMMAND(I2C_CMD_WDAT0);
|
SEND_COMMAND(I2C_CMD_WDAT0);
|
||||||
|
|
||||||
SEND_COMMAND(I2C_CMD_WDAT0);
|
SEND_COMMAND(I2C_CMD_WDAT0);
|
||||||
|
|
||||||
SEND_COMMAND(I2C_CMD_WDAT1);
|
SEND_COMMAND(I2C_CMD_WDAT1);
|
||||||
|
|
||||||
SEND_COMMAND(I2C_CMD_WDAT0);
|
SEND_COMMAND(I2C_CMD_WDAT0);
|
||||||
|
|
||||||
SEND_COMMAND(I2C_CMD_WDAT0);
|
SEND_COMMAND(I2C_CMD_WDAT0);
|
||||||
|
|
||||||
SEND_COMMAND(I2C_CMD_WDAT1);
|
SEND_COMMAND(I2C_CMD_WDAT1);
|
||||||
|
|
||||||
SEND_COMMAND(I2C_CMD_WDAT1);
|
SEND_COMMAND(I2C_CMD_WDAT1);
|
||||||
|
write++;
|
||||||
} else {
|
} else {
|
||||||
/* Send data */
|
/* Send data */
|
||||||
|
SEND_COMMAND(I2C_CMD_WDAT8);
|
||||||
SEND_COMMAND(buf[write++]);
|
SEND_COMMAND(buf[write++]);
|
||||||
}
|
}
|
||||||
SEND_COMMAND(I2C_CMD_VRFY_ACK); /* TODO Verify ACK based on requirement, Do we need? */
|
SEND_COMMAND(I2C_CMD_VRFY_ACK);
|
||||||
|
|
||||||
if (I2C_BUS_ERR_CHECK) {
|
if (I2C_BUS_ERR_CHECK) {
|
||||||
/* Bus error */
|
/* Bus error */
|
||||||
return I2C_ERROR_BUS_BUSY;
|
return I2C_ERROR_BUS_BUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
while(FIFO_OFL_CHECK); /* Wait till command overflow ends */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return write;
|
return write;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue