Skip to content

Commit ff7d7aa

Browse files
committed
Merge pull request #1776 from adamgreen/i2cRepeatedStartFix
Fix NXP LPCxxxx i2c_start() handling of repeated start
2 parents 5ac648f + 61e2296 commit ff7d7aa

File tree

10 files changed

+117
-57
lines changed

10 files changed

+117
-57
lines changed

hal/targets/hal/TARGET_NXP/TARGET_LPC11U6X/i2c_api.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,20 +111,26 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
111111

112112
inline int i2c_start(i2c_t *obj) {
113113
int status = 0;
114+
int isInterrupted = I2C_CONSET(obj) & (1 << 3);
115+
114116
// 8.1 Before master mode can be entered, I2CON must be initialised to:
115117
// - I2EN STA STO SI AA - -
116-
// - 1 0 0 0 x - -
118+
// - 1 0 0 x x - -
117119
// if AA = 0, it can't enter slave mode
118-
i2c_conclr(obj, 1, 1, 1, 1);
119-
120+
i2c_conclr(obj, 1, 1, 0, 1);
121+
120122
// The master mode may now be entered by setting the STA bit
121123
// this will generate a start condition when the bus becomes free
122124
i2c_conset(obj, 1, 0, 0, 1);
123-
125+
// Clearing SI bit when it wasn't set on entry can jump past state
126+
// 0x10 or 0x08 and erroneously send uninitialized slave address.
127+
if (isInterrupted)
128+
i2c_clear_SI(obj);
129+
124130
i2c_wait_SI(obj);
125131
status = i2c_status(obj);
126-
127-
// Clear start bit now transmitted, and interrupt bit
132+
133+
// Clear start bit now that it's transmitted
128134
i2c_conclr(obj, 1, 0, 0, 0);
129135
return status;
130136
}

hal/targets/hal/TARGET_NXP/TARGET_LPC11UXX/i2c_api.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,20 +94,26 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
9494

9595
inline int i2c_start(i2c_t *obj) {
9696
int status = 0;
97+
int isInterrupted = I2C_CONSET(obj) & (1 << 3);
98+
9799
// 8.1 Before master mode can be entered, I2CON must be initialised to:
98100
// - I2EN STA STO SI AA - -
99-
// - 1 0 0 0 x - -
101+
// - 1 0 0 x x - -
100102
// if AA = 0, it can't enter slave mode
101-
i2c_conclr(obj, 1, 1, 1, 1);
102-
103+
i2c_conclr(obj, 1, 1, 0, 1);
104+
103105
// The master mode may now be entered by setting the STA bit
104106
// this will generate a start condition when the bus becomes free
105107
i2c_conset(obj, 1, 0, 0, 1);
106-
108+
// Clearing SI bit when it wasn't set on entry can jump past state
109+
// 0x10 or 0x08 and erroneously send uninitialized slave address.
110+
if (isInterrupted)
111+
i2c_clear_SI(obj);
112+
107113
i2c_wait_SI(obj);
108114
status = i2c_status(obj);
109-
110-
// Clear start bit now transmitted, and interrupt bit
115+
116+
// Clear start bit now that it's transmitted
111117
i2c_conclr(obj, 1, 0, 0, 0);
112118
return status;
113119
}

hal/targets/hal/TARGET_NXP/TARGET_LPC11XX_11CXX/i2c_api.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,20 +104,26 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
104104

105105
inline int i2c_start(i2c_t *obj) {
106106
int status = 0;
107+
int isInterrupted = I2C_CONSET(obj) & (1 << 3);
108+
107109
// 8.1 Before master mode can be entered, I2CON must be initialised to:
108110
// - I2EN STA STO SI AA - -
109-
// - 1 0 0 0 x - -
111+
// - 1 0 0 x x - -
110112
// if AA = 0, it can't enter slave mode
111-
i2c_conclr(obj, 1, 1, 1, 1);
112-
113+
i2c_conclr(obj, 1, 1, 0, 1);
114+
113115
// The master mode may now be entered by setting the STA bit
114116
// this will generate a start condition when the bus becomes free
115117
i2c_conset(obj, 1, 0, 0, 1);
116-
118+
// Clearing SI bit when it wasn't set on entry can jump past state
119+
// 0x10 or 0x08 and erroneously send uninitialized slave address.
120+
if (isInterrupted)
121+
i2c_clear_SI(obj);
122+
117123
i2c_wait_SI(obj);
118124
status = i2c_status(obj);
119-
120-
// Clear start bit now transmitted, and interrupt bit
125+
126+
// Clear start bit now that it's transmitted
121127
i2c_conclr(obj, 1, 0, 0, 0);
122128
return status;
123129
}

hal/targets/hal/TARGET_NXP/TARGET_LPC13XX/i2c_api.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,20 +104,26 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
104104

105105
inline int i2c_start(i2c_t *obj) {
106106
int status = 0;
107+
int isInterrupted = I2C_CONSET(obj) & (1 << 3);
108+
107109
// 8.1 Before master mode can be entered, I2CON must be initialised to:
108110
// - I2EN STA STO SI AA - -
109-
// - 1 0 0 0 x - -
111+
// - 1 0 0 x x - -
110112
// if AA = 0, it can't enter slave mode
111-
i2c_conclr(obj, 1, 1, 1, 1);
112-
113+
i2c_conclr(obj, 1, 1, 0, 1);
114+
113115
// The master mode may now be entered by setting the STA bit
114116
// this will generate a start condition when the bus becomes free
115117
i2c_conset(obj, 1, 0, 0, 1);
116-
118+
// Clearing SI bit when it wasn't set on entry can jump past state
119+
// 0x10 or 0x08 and erroneously send uninitialized slave address.
120+
if (isInterrupted)
121+
i2c_clear_SI(obj);
122+
117123
i2c_wait_SI(obj);
118124
status = i2c_status(obj);
119-
120-
// Clear start bit now transmitted, and interrupt bit
125+
126+
// Clear start bit now that it's transmitted
121127
i2c_conclr(obj, 1, 0, 0, 0);
122128
return status;
123129
}

hal/targets/hal/TARGET_NXP/TARGET_LPC176X/i2c_api.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,20 +112,26 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
112112

113113
inline int i2c_start(i2c_t *obj) {
114114
int status = 0;
115+
int isInterrupted = I2C_CONSET(obj) & (1 << 3);
116+
115117
// 8.1 Before master mode can be entered, I2CON must be initialised to:
116118
// - I2EN STA STO SI AA - -
117-
// - 1 0 0 0 x - -
119+
// - 1 0 0 x x - -
118120
// if AA = 0, it can't enter slave mode
119-
i2c_conclr(obj, 1, 1, 1, 1);
120-
121+
i2c_conclr(obj, 1, 1, 0, 1);
122+
121123
// The master mode may now be entered by setting the STA bit
122124
// this will generate a start condition when the bus becomes free
123125
i2c_conset(obj, 1, 0, 0, 1);
124-
126+
// Clearing SI bit when it wasn't set on entry can jump past state
127+
// 0x10 or 0x08 and erroneously send uninitialized slave address.
128+
if (isInterrupted)
129+
i2c_clear_SI(obj);
130+
125131
i2c_wait_SI(obj);
126132
status = i2c_status(obj);
127-
128-
// Clear start bit now transmitted, and interrupt bit
133+
134+
// Clear start bit now that it's transmitted
129135
i2c_conclr(obj, 1, 0, 0, 0);
130136
return status;
131137
}

hal/targets/hal/TARGET_NXP/TARGET_LPC23XX/i2c_api.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,20 +111,26 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
111111

112112
inline int i2c_start(i2c_t *obj) {
113113
int status = 0;
114+
int isInterrupted = I2C_CONSET(obj) & (1 << 3);
115+
114116
// 8.1 Before master mode can be entered, I2CON must be initialised to:
115117
// - I2EN STA STO SI AA - -
116-
// - 1 0 0 0 x - -
118+
// - 1 0 0 x x - -
117119
// if AA = 0, it can't enter slave mode
118-
i2c_conclr(obj, 1, 1, 1, 1);
119-
120+
i2c_conclr(obj, 1, 1, 0, 1);
121+
120122
// The master mode may now be entered by setting the STA bit
121123
// this will generate a start condition when the bus becomes free
122124
i2c_conset(obj, 1, 0, 0, 1);
123-
125+
// Clearing SI bit when it wasn't set on entry can jump past state
126+
// 0x10 or 0x08 and erroneously send uninitialized slave address.
127+
if (isInterrupted)
128+
i2c_clear_SI(obj);
129+
124130
i2c_wait_SI(obj);
125131
status = i2c_status(obj);
126-
127-
// Clear start bit now transmitted, and interrupt bit
132+
133+
// Clear start bit now that it's transmitted
128134
i2c_conclr(obj, 1, 0, 0, 0);
129135
return status;
130136
}

hal/targets/hal/TARGET_NXP/TARGET_LPC2460/i2c_api.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -117,20 +117,26 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
117117

118118
inline int i2c_start(i2c_t *obj) {
119119
int status = 0;
120+
int isInterrupted = I2C_CONSET(obj) & (1 << 3);
121+
120122
// 8.1 Before master mode can be entered, I2CON must be initialised to:
121123
// - I2EN STA STO SI AA - -
122-
// - 1 0 0 0 x - -
124+
// - 1 0 0 x x - -
123125
// if AA = 0, it can't enter slave mode
124-
i2c_conclr(obj, 1, 1, 1, 1);
125-
126+
i2c_conclr(obj, 1, 1, 0, 1);
127+
126128
// The master mode may now be entered by setting the STA bit
127129
// this will generate a start condition when the bus becomes free
128130
i2c_conset(obj, 1, 0, 0, 1);
129-
131+
// Clearing SI bit when it wasn't set on entry can jump past state
132+
// 0x10 or 0x08 and erroneously send uninitialized slave address.
133+
if (isInterrupted)
134+
i2c_clear_SI(obj);
135+
130136
i2c_wait_SI(obj);
131137
status = i2c_status(obj);
132-
133-
// Clear start bit now transmitted, and interrupt bit
138+
139+
// Clear start bit now that it's transmitted
134140
i2c_conclr(obj, 1, 0, 0, 0);
135141
return status;
136142
}

hal/targets/hal/TARGET_NXP/TARGET_LPC408X/TARGET_LPC4088/i2c_api.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -133,20 +133,26 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
133133

134134
inline int i2c_start(i2c_t *obj) {
135135
int status = 0;
136+
int isInterrupted = I2C_CONSET(obj) & (1 << 3);
137+
136138
// 8.1 Before master mode can be entered, I2CON must be initialised to:
137139
// - I2EN STA STO SI AA - -
138-
// - 1 0 0 0 x - -
140+
// - 1 0 0 x x - -
139141
// if AA = 0, it can't enter slave mode
140-
i2c_conclr(obj, 1, 1, 1, 1);
141-
142+
i2c_conclr(obj, 1, 1, 0, 1);
143+
142144
// The master mode may now be entered by setting the STA bit
143145
// this will generate a start condition when the bus becomes free
144146
i2c_conset(obj, 1, 0, 0, 1);
145-
147+
// Clearing SI bit when it wasn't set on entry can jump past state
148+
// 0x10 or 0x08 and erroneously send uninitialized slave address.
149+
if (isInterrupted)
150+
i2c_clear_SI(obj);
151+
146152
i2c_wait_SI(obj);
147153
status = i2c_status(obj);
148-
149-
// Clear start bit now transmitted, and interrupt bit
154+
155+
// Clear start bit now that it's transmitted
150156
i2c_conclr(obj, 1, 0, 0, 0);
151157
return status;
152158
}

hal/targets/hal/TARGET_NXP/TARGET_LPC408X/TARGET_LPC4088_DM/i2c_api.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,20 +119,26 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
119119

120120
inline int i2c_start(i2c_t *obj) {
121121
int status = 0;
122+
int isInterrupted = I2C_CONSET(obj) & (1 << 3);
123+
122124
// 8.1 Before master mode can be entered, I2CON must be initialised to:
123125
// - I2EN STA STO SI AA - -
124-
// - 1 0 0 0 x - -
126+
// - 1 0 0 x x - -
125127
// if AA = 0, it can't enter slave mode
126-
i2c_conclr(obj, 1, 1, 1, 1);
128+
i2c_conclr(obj, 1, 1, 0, 1);
127129

128130
// The master mode may now be entered by setting the STA bit
129131
// this will generate a start condition when the bus becomes free
130132
i2c_conset(obj, 1, 0, 0, 1);
133+
// Clearing SI bit when it wasn't set on entry can jump past state
134+
// 0x10 or 0x08 and erroneously send uninitialized slave address.
135+
if (isInterrupted)
136+
i2c_clear_SI(obj);
131137

132138
i2c_wait_SI(obj);
133139
status = i2c_status(obj);
134140

135-
// Clear start bit now transmitted, and interrupt bit
141+
// Clear start bit now that it's transmitted
136142
i2c_conclr(obj, 1, 0, 0, 0);
137143
return status;
138144
}

hal/targets/hal/TARGET_NXP/TARGET_LPC43XX/i2c_api.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,20 +113,26 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
113113

114114
inline int i2c_start(i2c_t *obj) {
115115
int status = 0;
116+
int isInterrupted = I2C_CONSET(obj) & (1 << 3);
117+
116118
// 8.1 Before master mode can be entered, I2CON must be initialised to:
117119
// - I2EN STA STO SI AA - -
118-
// - 1 0 0 0 x - -
120+
// - 1 0 0 x x - -
119121
// if AA = 0, it can't enter slave mode
120-
i2c_conclr(obj, 1, 1, 1, 1);
121-
122+
i2c_conclr(obj, 1, 1, 0, 1);
123+
122124
// The master mode may now be entered by setting the STA bit
123125
// this will generate a start condition when the bus becomes free
124126
i2c_conset(obj, 1, 0, 0, 1);
125-
127+
// Clearing SI bit when it wasn't set on entry can jump past state
128+
// 0x10 or 0x08 and erroneously send uninitialized slave address.
129+
if (isInterrupted)
130+
i2c_clear_SI(obj);
131+
126132
i2c_wait_SI(obj);
127133
status = i2c_status(obj);
128-
129-
// Clear start bit now transmitted, and interrupt bit
134+
135+
// Clear start bit now that it's transmitted
130136
i2c_conclr(obj, 1, 0, 0, 0);
131137
return status;
132138
}

0 commit comments

Comments
 (0)