mirror of https://github.com/ARMmbed/mbed-os.git
NCS36510: I2C idle delay of 1us
It is added between I2C commands as I2C_COMMAND_FIFO is too fast to push commands out.pull/3837/head
parent
6e4d261df8
commit
e5e32ac348
|
@ -83,14 +83,18 @@
|
|||
#define I2C_APB_CLK_DIVIDER_VAL_MASK 0x1FE0
|
||||
|
||||
/* Error check */
|
||||
#define I2C_UFL_CHECK (d->membase->STATUS.WORD & 0x80)
|
||||
#define FIFO_OFL_CHECK (d->membase->STATUS.WORD & 0x10)
|
||||
#define I2C_BUS_ERR_CHECK (d->membase->STATUS.WORD & 0x04)
|
||||
#define RD_DATA_READY (d->membase->STATUS.WORD & 0x02)
|
||||
#define I2C_UFL_CHECK (obj->membase->STATUS.WORD & 0x80)
|
||||
#define I2C_FIFO_FULL (obj->membase->STATUS.WORD & 0x20)
|
||||
#define FIFO_OFL_CHECK (obj->membase->STATUS.WORD & 0x10)
|
||||
#define I2C_BUS_ERR_CHECK (obj->membase->STATUS.WORD & 0x04)
|
||||
#define RD_DATA_READY (obj->membase->STATUS.WORD & 0x02)
|
||||
#define I2C_FIFO_EMPTY (obj->membase->STATUS.WORD & 0x01)
|
||||
|
||||
#define I2C_API_STATUS_SUCCESS 0
|
||||
#define PAD_REG_ADRS_BYTE_SIZE 4
|
||||
|
||||
#define SEND_COMMAND(cmd) while(!I2C_FIFO_EMPTY); wait_us(1); obj->membase->CMD_REG = cmd;
|
||||
|
||||
/** Init I2C device.
|
||||
* @details
|
||||
* Sets the necessary registers. The baud rate is set default to 100K
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include "i2c.h"
|
||||
#include "i2c_api.h"
|
||||
#include "wait_api.h"
|
||||
|
||||
#define I2C_READ_WRITE_BIT_MASK 0xFE
|
||||
|
||||
|
@ -151,10 +152,10 @@ int i2c_byte_read(i2c_t *obj, int last) /* TODO return size can be uint8_t */
|
|||
}
|
||||
if(last) {
|
||||
/* ACK */
|
||||
obj->membase->CMD_REG = I2C_CMD_WDAT0;
|
||||
SEND_COMMAND(I2C_CMD_WDAT0);
|
||||
} else {
|
||||
/* No ACK */
|
||||
obj->membase->CMD_REG = I2C_CMD_WDAT1;
|
||||
SEND_COMMAND(I2C_CMD_WDAT1);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
@ -168,8 +169,6 @@ int i2c_byte_write(i2c_t *obj, int data)
|
|||
return Count;
|
||||
}
|
||||
|
||||
obj->membase->CMD_REG = I2C_CMD_VRFY_ACK; /* Verify ACK */
|
||||
|
||||
while(obj->membase->STATUS.WORD & I2C_STATUS_CMD_FIFO_OFL_BIT); /* Wait till command overflow ends */
|
||||
|
||||
if(obj->membase->STATUS.WORD & I2C_STATUS_BUS_ERR_BIT) {
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
*/
|
||||
#if DEVICE_I2C
|
||||
#include "i2c.h"
|
||||
#include "wait_api.h"
|
||||
|
||||
/* See i2c.h for details */
|
||||
void fI2cInit(i2c_t *obj,PinName sda,PinName scl)
|
||||
|
@ -135,7 +136,7 @@ void fI2cFrequency(i2c_t *obj, uint32_t hz)
|
|||
int32_t fI2cStart(i2c_t *obj)
|
||||
{
|
||||
/* Send start bit */
|
||||
obj->membase->CMD_REG = I2C_CMD_START;
|
||||
SEND_COMMAND(I2C_CMD_START);
|
||||
return I2C_API_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -143,7 +144,7 @@ int32_t fI2cStart(i2c_t *obj)
|
|||
int32_t fI2cStop(i2c_t *obj)
|
||||
{
|
||||
/* Send stop bit */
|
||||
obj->membase->CMD_REG = I2C_CMD_STOP;
|
||||
SEND_COMMAND(I2C_CMD_STOP);
|
||||
if (obj->membase->STATUS.WORD & (I2C_STATUS_CMD_FIFO_FULL_BIT |
|
||||
I2C_STATUS_CMD_FIFO_OFL_BIT |
|
||||
I2C_STATUS_BUS_ERR_BIT)) {
|
||||
|
@ -154,23 +155,26 @@ int32_t fI2cStop(i2c_t *obj)
|
|||
}
|
||||
|
||||
/* See i2c.h for details */
|
||||
int32_t fI2cReadB(i2c_t *d, char *buf, int len)
|
||||
int32_t fI2cReadB(i2c_t *obj, char *buf, int len)
|
||||
{
|
||||
int32_t read = 0;
|
||||
|
||||
while (read < len) {
|
||||
/* Send read command */
|
||||
d->membase->CMD_REG = I2C_CMD_RDAT8;
|
||||
SEND_COMMAND(I2C_CMD_RDAT8);
|
||||
while(!RD_DATA_READY) {
|
||||
if (I2C_BUS_ERR_CHECK) {
|
||||
/* Bus error occured */
|
||||
return I2C_ERROR_BUS_BUSY;
|
||||
}
|
||||
}
|
||||
buf[read++] = d->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 */
|
||||
d->membase->CMD_REG=I2C_CMD_WDAT0; /* TODO based on requirement generate ACK or NACK Based on the requirement. */
|
||||
SEND_COMMAND(I2C_CMD_WDAT0); /* TODO based on requirement generate ACK or NACK Based on the requirement. */
|
||||
} else {
|
||||
/* No ack */
|
||||
SEND_COMMAND(I2C_CMD_WDAT1);
|
||||
}
|
||||
|
||||
/* check for FIFO underflow */
|
||||
|
@ -187,39 +191,46 @@ int32_t fI2cReadB(i2c_t *d, char *buf, int len)
|
|||
}
|
||||
|
||||
/* See i2c.h for details */
|
||||
int32_t fI2cWriteB(i2c_t *d, const char *buf, int len)
|
||||
int32_t fI2cWriteB(i2c_t *obj, const char *buf, int len)
|
||||
{
|
||||
int32_t write = 0;
|
||||
|
||||
while (write < len) {
|
||||
/* Send write command */
|
||||
d->membase->CMD_REG = I2C_CMD_WDAT8;
|
||||
SEND_COMMAND(I2C_CMD_WDAT8);
|
||||
|
||||
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)
|
||||
then as the command is read out (i.e. the FIFO goes empty), the WDAT8 command will be misinterpreted as a
|
||||
RDAT8 command by the data FSM; resulting in an I2C bus error (NACK instead of an ACK). */
|
||||
/* Send 0x13 bit wise */
|
||||
d->membase->CMD_REG = I2C_CMD_WDAT0;
|
||||
d->membase->CMD_REG = I2C_CMD_WDAT0;
|
||||
d->membase->CMD_REG = I2C_CMD_WDAT0;
|
||||
d->membase->CMD_REG = I2C_CMD_WDAT1;
|
||||
SEND_COMMAND(I2C_CMD_WDAT0);
|
||||
|
||||
d->membase->CMD_REG = I2C_CMD_WDAT0;
|
||||
d->membase->CMD_REG = I2C_CMD_WDAT0;
|
||||
d->membase->CMD_REG = I2C_CMD_WDAT1;
|
||||
d->membase->CMD_REG = I2C_CMD_WDAT1;
|
||||
SEND_COMMAND(I2C_CMD_WDAT0);
|
||||
|
||||
SEND_COMMAND(I2C_CMD_WDAT0);
|
||||
|
||||
SEND_COMMAND(I2C_CMD_WDAT1);
|
||||
|
||||
SEND_COMMAND(I2C_CMD_WDAT0);
|
||||
|
||||
SEND_COMMAND(I2C_CMD_WDAT0);
|
||||
|
||||
SEND_COMMAND(I2C_CMD_WDAT1);
|
||||
|
||||
SEND_COMMAND(I2C_CMD_WDAT1);
|
||||
} else {
|
||||
/* Send data */
|
||||
d->membase->CMD_REG = buf[write++];
|
||||
SEND_COMMAND(buf[write++]);
|
||||
}
|
||||
d->membase->CMD_REG = I2C_CMD_VRFY_ACK; /* TODO Verify ACK based on requirement, Do we need? */
|
||||
|
||||
while(FIFO_OFL_CHECK); /* Wait till command overflow ends */
|
||||
SEND_COMMAND(I2C_CMD_VRFY_ACK); /* TODO Verify ACK based on requirement, Do we need? */
|
||||
|
||||
if (I2C_BUS_ERR_CHECK) {
|
||||
/* Bus error */
|
||||
return I2C_ERROR_BUS_BUSY;
|
||||
}
|
||||
|
||||
while(FIFO_OFL_CHECK); /* Wait till command overflow ends */
|
||||
}
|
||||
|
||||
return write;
|
||||
|
|
Loading…
Reference in New Issue