Skip to content

Commit e5e32ac

Browse files
pradeep-gradbridge
authored andcommitted
NCS36510: I2C idle delay of 1us
It is added between I2C commands as I2C_COMMAND_FIFO is too fast to push commands out.
1 parent 6e4d261 commit e5e32ac

File tree

3 files changed

+46
-32
lines changed

3 files changed

+46
-32
lines changed

targets/TARGET_ONSEMI/TARGET_NCS36510/i2c.h

+9-5
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,18 @@
8383
#define I2C_APB_CLK_DIVIDER_VAL_MASK 0x1FE0
8484

8585
/* Error check */
86-
#define I2C_UFL_CHECK (d->membase->STATUS.WORD & 0x80)
87-
#define FIFO_OFL_CHECK (d->membase->STATUS.WORD & 0x10)
88-
#define I2C_BUS_ERR_CHECK (d->membase->STATUS.WORD & 0x04)
89-
#define RD_DATA_READY (d->membase->STATUS.WORD & 0x02)
86+
#define I2C_UFL_CHECK (obj->membase->STATUS.WORD & 0x80)
87+
#define I2C_FIFO_FULL (obj->membase->STATUS.WORD & 0x20)
88+
#define FIFO_OFL_CHECK (obj->membase->STATUS.WORD & 0x10)
89+
#define I2C_BUS_ERR_CHECK (obj->membase->STATUS.WORD & 0x04)
90+
#define RD_DATA_READY (obj->membase->STATUS.WORD & 0x02)
91+
#define I2C_FIFO_EMPTY (obj->membase->STATUS.WORD & 0x01)
9092

9193
#define I2C_API_STATUS_SUCCESS 0
9294
#define PAD_REG_ADRS_BYTE_SIZE 4
9395

96+
#define SEND_COMMAND(cmd) while(!I2C_FIFO_EMPTY); wait_us(1); obj->membase->CMD_REG = cmd;
97+
9498
/** Init I2C device.
9599
* @details
96100
* Sets the necessary registers. The baud rate is set default to 100K
@@ -154,4 +158,4 @@ extern int32_t fI2cReadB(i2c_t *d, char *buf, int len);
154158
*/
155159
extern int32_t fI2cWriteB(i2c_t *d, const char *buf, int len);
156160

157-
#endif /* I2C_H_ */
161+
#endif /* I2C_H_ */

targets/TARGET_ONSEMI/TARGET_NCS36510/i2c_api.c

+4-5
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
#include "i2c.h"
3333
#include "i2c_api.h"
34+
#include "wait_api.h"
3435

3536
#define I2C_READ_WRITE_BIT_MASK 0xFE
3637

@@ -151,10 +152,10 @@ int i2c_byte_read(i2c_t *obj, int last) /* TODO return size can be uint8_t */
151152
}
152153
if(last) {
153154
/* ACK */
154-
obj->membase->CMD_REG = I2C_CMD_WDAT0;
155+
SEND_COMMAND(I2C_CMD_WDAT0);
155156
} else {
156157
/* No ACK */
157-
obj->membase->CMD_REG = I2C_CMD_WDAT1;
158+
SEND_COMMAND(I2C_CMD_WDAT1);
158159
}
159160
return data;
160161
}
@@ -168,8 +169,6 @@ int i2c_byte_write(i2c_t *obj, int data)
168169
return Count;
169170
}
170171

171-
obj->membase->CMD_REG = I2C_CMD_VRFY_ACK; /* Verify ACK */
172-
173172
while(obj->membase->STATUS.WORD & I2C_STATUS_CMD_FIFO_OFL_BIT); /* Wait till command overflow ends */
174173

175174
if(obj->membase->STATUS.WORD & I2C_STATUS_BUS_ERR_BIT) {
@@ -181,4 +180,4 @@ int i2c_byte_write(i2c_t *obj, int data)
181180
}
182181
}
183182

184-
#endif /* DEVICE_I2C */
183+
#endif /* DEVICE_I2C */

targets/TARGET_ONSEMI/TARGET_NCS36510/ncs36510_i2c.c

+33-22
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
*/
6161
#if DEVICE_I2C
6262
#include "i2c.h"
63+
#include "wait_api.h"
6364

6465
/* See i2c.h for details */
6566
void fI2cInit(i2c_t *obj,PinName sda,PinName scl)
@@ -135,15 +136,15 @@ void fI2cFrequency(i2c_t *obj, uint32_t hz)
135136
int32_t fI2cStart(i2c_t *obj)
136137
{
137138
/* Send start bit */
138-
obj->membase->CMD_REG = I2C_CMD_START;
139+
SEND_COMMAND(I2C_CMD_START);
139140
return I2C_API_STATUS_SUCCESS;
140141
}
141142

142143
/* See i2c.h for details */
143144
int32_t fI2cStop(i2c_t *obj)
144145
{
145146
/* Send stop bit */
146-
obj->membase->CMD_REG = I2C_CMD_STOP;
147+
SEND_COMMAND(I2C_CMD_STOP);
147148
if (obj->membase->STATUS.WORD & (I2C_STATUS_CMD_FIFO_FULL_BIT |
148149
I2C_STATUS_CMD_FIFO_OFL_BIT |
149150
I2C_STATUS_BUS_ERR_BIT)) {
@@ -154,23 +155,26 @@ int32_t fI2cStop(i2c_t *obj)
154155
}
155156

156157
/* See i2c.h for details */
157-
int32_t fI2cReadB(i2c_t *d, char *buf, int len)
158+
int32_t fI2cReadB(i2c_t *obj, char *buf, int len)
158159
{
159160
int32_t read = 0;
160161

161162
while (read < len) {
162163
/* Send read command */
163-
d->membase->CMD_REG = I2C_CMD_RDAT8;
164+
SEND_COMMAND(I2C_CMD_RDAT8);
164165
while(!RD_DATA_READY) {
165166
if (I2C_BUS_ERR_CHECK) {
166167
/* Bus error occured */
167168
return I2C_ERROR_BUS_BUSY;
168169
}
169170
}
170-
buf[read++] = d->membase->RD_FIFO_REG; /**< Reading 'read FIFO register' will clear status register */
171+
buf[read++] = obj->membase->RD_FIFO_REG; /**< Reading 'read FIFO register' will clear status register */
171172

172173
if(!(read>=len)) { /* No ACK will be generated for the last read, upper level I2C protocol should generate */
173-
d->membase->CMD_REG=I2C_CMD_WDAT0; /* TODO based on requirement generate ACK or NACK Based on the requirement. */
174+
SEND_COMMAND(I2C_CMD_WDAT0); /* TODO based on requirement generate ACK or NACK Based on the requirement. */
175+
} else {
176+
/* No ack */
177+
SEND_COMMAND(I2C_CMD_WDAT1);
174178
}
175179

176180
/* check for FIFO underflow */
@@ -187,42 +191,49 @@ int32_t fI2cReadB(i2c_t *d, char *buf, int len)
187191
}
188192

189193
/* See i2c.h for details */
190-
int32_t fI2cWriteB(i2c_t *d, const char *buf, int len)
194+
int32_t fI2cWriteB(i2c_t *obj, const char *buf, int len)
191195
{
192196
int32_t write = 0;
193197

194198
while (write < len) {
195199
/* Send write command */
196-
d->membase->CMD_REG = I2C_CMD_WDAT8;
200+
SEND_COMMAND(I2C_CMD_WDAT8);
201+
197202
if(buf[write] == I2C_CMD_RDAT8) {
198203
/* SW work around to counter FSM issue. If the only command in the CMD FIFO is the WDAT8 command (data of 0x13)
199204
then as the command is read out (i.e. the FIFO goes empty), the WDAT8 command will be misinterpreted as a
200205
RDAT8 command by the data FSM; resulting in an I2C bus error (NACK instead of an ACK). */
201206
/* Send 0x13 bit wise */
202-
d->membase->CMD_REG = I2C_CMD_WDAT0;
203-
d->membase->CMD_REG = I2C_CMD_WDAT0;
204-
d->membase->CMD_REG = I2C_CMD_WDAT0;
205-
d->membase->CMD_REG = I2C_CMD_WDAT1;
206-
207-
d->membase->CMD_REG = I2C_CMD_WDAT0;
208-
d->membase->CMD_REG = I2C_CMD_WDAT0;
209-
d->membase->CMD_REG = I2C_CMD_WDAT1;
210-
d->membase->CMD_REG = I2C_CMD_WDAT1;
207+
SEND_COMMAND(I2C_CMD_WDAT0);
208+
209+
SEND_COMMAND(I2C_CMD_WDAT0);
210+
211+
SEND_COMMAND(I2C_CMD_WDAT0);
212+
213+
SEND_COMMAND(I2C_CMD_WDAT1);
214+
215+
SEND_COMMAND(I2C_CMD_WDAT0);
216+
217+
SEND_COMMAND(I2C_CMD_WDAT0);
218+
219+
SEND_COMMAND(I2C_CMD_WDAT1);
220+
221+
SEND_COMMAND(I2C_CMD_WDAT1);
211222
} else {
212223
/* Send data */
213-
d->membase->CMD_REG = buf[write++];
224+
SEND_COMMAND(buf[write++]);
214225
}
215-
d->membase->CMD_REG = I2C_CMD_VRFY_ACK; /* TODO Verify ACK based on requirement, Do we need? */
216-
217-
while(FIFO_OFL_CHECK); /* Wait till command overflow ends */
226+
SEND_COMMAND(I2C_CMD_VRFY_ACK); /* TODO Verify ACK based on requirement, Do we need? */
218227

219228
if (I2C_BUS_ERR_CHECK) {
220229
/* Bus error */
221230
return I2C_ERROR_BUS_BUSY;
222231
}
232+
233+
while(FIFO_OFL_CHECK); /* Wait till command overflow ends */
223234
}
224235

225236
return write;
226237
}
227238

228-
#endif /* DEVICE_I2C */
239+
#endif /* DEVICE_I2C */

0 commit comments

Comments
 (0)