Skip to content

Commit ffcaadf

Browse files
committed
Merge pull request #310 from dbestm/master
[NUCLEO_F302R8] Add I2C slave, enhance I2C master
2 parents e7f82df + 9d459ba commit ffcaadf

File tree

3 files changed

+113
-63
lines changed

3 files changed

+113
-63
lines changed

libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F030R8/i2c_api.c

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -178,46 +178,54 @@ inline int i2c_stop(i2c_t *obj) {
178178
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
179179
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
180180
int count;
181+
int timeout;
181182
int value;
182183

183184
if (length == 0) return 0;
184185

185186
// Configure slave address, nbytes, reload, end mode and start or stop generation
186-
I2C_TransferHandling(i2c, address, length, I2C_AutoEnd_Mode, I2C_Generate_Start_Read);
187+
I2C_TransferHandling(i2c, address, length, I2C_SoftEnd_Mode, I2C_Generate_Start_Read);
187188

188189
// Read all bytes
189190
for (count = 0; count < length; count++) {
190191
value = i2c_byte_read(obj, 0);
191192
data[count] = (char)value;
192193
}
193194

195+
timeout = FLAG_TIMEOUT;
196+
while(!I2C_GetFlagStatus(i2c, I2C_FLAG_TC)) {
197+
timeout--;
198+
if (timeout == 0) return 0;
199+
}
200+
201+
if(stop) i2c_stop(obj);
202+
194203
return length;
195204
}
196205

197206
int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
198207
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
199-
//int timeout;
208+
int timeout;
200209
int count;
201210

202211
if (length == 0) return 0;
203212

204-
// Configure slave address, nbytes, reload, end mode and start or stop generation
205-
if (stop) {
206-
I2C_TransferHandling(i2c, address, length, I2C_AutoEnd_Mode, I2C_Generate_Start_Write);
207-
208-
}
209-
else {
213+
// Configure slave address, nbytes, reload, end mode and start generation
210214
I2C_TransferHandling(i2c, address, length, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
211-
}
212215

213216
// Write all bytes
214217
for (count = 0; count < length; count++) {
215-
if (i2c_byte_write(obj, data[count]) != 1) {
216-
if(!stop) i2c_stop(obj);
217-
return 0;
218+
i2c_byte_write(obj, data[count]);
218219
}
220+
221+
timeout = FLAG_TIMEOUT;
222+
while(!I2C_GetFlagStatus(i2c, I2C_FLAG_TC)) {
223+
timeout--;
224+
if (timeout == 0) return 0;
219225
}
220226

227+
if(stop) i2c_stop(obj);
228+
221229
return count;
222230
}
223231

libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F302R8/device.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
#define DEVICE_SERIAL 1
4343

4444
#define DEVICE_I2C 1
45-
#define DEVICE_I2CSLAVE 0 // Not yet supported
45+
#define DEVICE_I2CSLAVE 1
4646

4747
#define DEVICE_SPI 1
4848
#define DEVICE_SPISLAVE 0 // Not yet supported

libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F302R8/i2c_api.c

Lines changed: 92 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
7676
// Enable I2C clock
7777
if (obj->i2c == I2C_1) {
7878
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
79+
RCC_I2CCLKConfig(RCC_I2C1CLK_SYSCLK);
7980
}
8081
if (obj->i2c == I2C_2) {
8182
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
@@ -113,35 +114,66 @@ void i2c_frequency(i2c_t *obj, int hz) {
113114
* Fast Mode (up to 400 kHz)
114115
* Fast Mode Plus (up to 1 MHz)
115116
Below values obtained with:
116-
- I2C clock source = 8 MHz (HSI clock per default)
117+
- I2C clock source = 64 MHz (System Clock w/ HSI) or 72 (System Clock w/ HSE)
117118
- Analog filter delay = ON
118119
- Digital filter coefficient = 0
119120
- Rise time = 100 ns
120121
- Fall time = 10ns
121122
*/
122-
switch (hz) {
123-
case 100000:
124-
tim = 0x00201D2B; // Standard mode
123+
if (SystemCoreClock == 64000000) {
124+
switch (hz) {
125+
case 100000:
126+
tim = 0x60302730; // Standard mode
125127
break;
126-
case 200000:
127-
tim = 0x0010021E; // Fast Mode
128+
case 200000:
129+
tim = 0x00C07AB3; // Fast Mode
128130
break;
129-
case 400000:
130-
tim = 0x0010020A; // Fast Mode
131+
case 400000:
132+
tim = 0x00C0216C; // Fast Mode
131133
break;
132-
case 1000000:
133-
tim = 0x00100001; // Fast Mode Plus
134-
// Enable the Fast Mode Plus capability
135-
if (obj->i2c == I2C_1) {
136-
SYSCFG_I2CFastModePlusConfig(SYSCFG_I2CFastModePlus_I2C1, ENABLE);
137-
}
138-
if (obj->i2c == I2C_2) {
139-
SYSCFG_I2CFastModePlusConfig(SYSCFG_I2CFastModePlus_I2C2, ENABLE);
140-
}
134+
case 1000000:
135+
tim = 0x00900B22; // Fast Mode Plus
136+
// Enable the Fast Mode Plus capability
137+
if (obj->i2c == I2C_1) {
138+
SYSCFG_I2CFastModePlusConfig(SYSCFG_I2CFastModePlus_I2C1, ENABLE);
139+
}
140+
if (obj->i2c == I2C_2) {
141+
SYSCFG_I2CFastModePlusConfig(SYSCFG_I2CFastModePlus_I2C2, ENABLE);
142+
}
141143
break;
142-
default:
143-
error("Only 100kHz, 200kHz, 400kHz and 1MHz I2C frequencies are supported.");
144+
default:
145+
error("Only 100kHz, 200kHz, 400kHz and 1MHz I2C frequencies are supported.");
144146
break;
147+
}
148+
}
149+
else if (SystemCoreClock == 72000000) {
150+
switch (hz) {
151+
case 100000:
152+
tim = 0x10C08DCF; // Standard mode
153+
break;
154+
case 200000:
155+
tim = 0xA010031A; // Fast Mode
156+
break;
157+
case 400000:
158+
tim = 0x00E0257A; // Fast Mode
159+
break;
160+
case 1000000:
161+
tim = 0x00A00D26; // Fast Mode Plus
162+
// Enable the Fast Mode Plus capability
163+
if (obj->i2c == I2C_1) {
164+
SYSCFG_I2CFastModePlusConfig(SYSCFG_I2CFastModePlus_I2C1, ENABLE);
165+
}
166+
if (obj->i2c == I2C_2) {
167+
SYSCFG_I2CFastModePlusConfig(SYSCFG_I2CFastModePlus_I2C2, ENABLE);
168+
}
169+
break;
170+
default:
171+
error("Only 100kHz, 200kHz, 400kHz and 1MHz I2C frequencies are supported.");
172+
break;
173+
}
174+
}
175+
else {
176+
error("System clock setting is not supported.");
145177
}
146178

147179
// I2C configuration
@@ -184,64 +216,58 @@ inline int i2c_stop(i2c_t *obj) {
184216
return 0;
185217
}
186218

219+
187220
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
188221
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
189222
int count;
223+
int timeout;
190224
int value;
191225

192226
if (length == 0) return 0;
193227

194228
// Configure slave address, nbytes, reload, end mode and start or stop generation
195-
I2C_TransferHandling(i2c, address, length, I2C_AutoEnd_Mode, I2C_Generate_Start_Read);
229+
I2C_TransferHandling(i2c, address, length, I2C_SoftEnd_Mode, I2C_Generate_Start_Read);
196230

197231
// Read all bytes
198232
for (count = 0; count < length; count++) {
199233
value = i2c_byte_read(obj, 0);
200234
data[count] = (char)value;
201235
}
202236

237+
timeout = FLAG_TIMEOUT;
238+
while(!I2C_GetFlagStatus(i2c, I2C_FLAG_TC)) {
239+
timeout--;
240+
if (timeout == 0) return 0;
241+
}
242+
243+
if(stop) i2c_stop(obj);
244+
203245
return length;
204246
}
205247

248+
206249
int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
207250
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
208-
//int timeout;
251+
int timeout;
209252
int count;
210253

211254
if (length == 0) return 0;
212255

213-
// [TODO] The stop is always sent even with I2C_SoftEnd_Mode. To be corrected.
214-
215-
// Configure slave address, nbytes, reload, end mode and start or stop generation
216-
//if (stop) {
217-
I2C_TransferHandling(i2c, address, length, I2C_AutoEnd_Mode, I2C_Generate_Start_Write);
218-
//}
219-
//else {
220-
// I2C_TransferHandling(i2c, address, length, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
221-
//}
256+
// Configure slave address, nbytes, reload, end mode and start generation
257+
I2C_TransferHandling(i2c, address, length, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
222258

223259
// Write all bytes
224260
for (count = 0; count < length; count++) {
225-
if (i2c_byte_write(obj, data[count]) != 1) {
226-
i2c_stop(obj);
227-
return 0;
228-
}
261+
i2c_byte_write(obj, data[count]);
229262
}
230263

231-
/*
232-
if (stop) {
233-
// Wait until STOPF flag is set
234-
timeout = LONG_TIMEOUT;
235-
while (I2C_GetFlagStatus(i2c, I2C_ISR_STOPF) == RESET) {
236-
timeout--;
237-
if (timeout == 0) {
238-
return 0;
239-
}
240-
}
241-
// Clear STOPF flag
242-
I2C_ClearFlag(i2c, I2C_ICR_STOPCF);
264+
timeout = FLAG_TIMEOUT;
265+
while(!I2C_GetFlagStatus(i2c, I2C_FLAG_TC)) {
266+
timeout--;
267+
if (timeout == 0) return 0;
243268
}
244-
*/
269+
270+
if(stop) i2c_stop(obj);
245271

246272
return count;
247273
}
@@ -304,14 +330,17 @@ void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) {
304330
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
305331
uint16_t tmpreg;
306332

333+
// reset own address enable
334+
i2c->OAR1 &=~ I2C_OAR1_OA1EN;
335+
307336
// Get the old register value
308337
tmpreg = i2c->OAR1;
309338
// Reset address bits
310339
tmpreg &= 0xFC00;
311340
// Set new address
312341
tmpreg |= (uint16_t)((uint16_t)address & (uint16_t)0x00FE); // 7-bits
313342
// Store the new register value
314-
i2c->OAR1 = tmpreg;
343+
i2c->OAR1 = tmpreg | I2C_OAR1_OA1EN;
315344
}
316345

317346
void i2c_slave_mode(i2c_t *obj, int enable_slave) {
@@ -325,8 +354,21 @@ void i2c_slave_mode(i2c_t *obj, int enable_slave) {
325354
#define WriteAddressed 3 // the master is writing to this slave (slave = receiver)
326355

327356
int i2c_slave_receive(i2c_t *obj) {
328-
// TO BE DONE
329-
return (0);
357+
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
358+
int event = NoData;
359+
360+
if(I2C_GetFlagStatus(i2c, I2C_ISR_BUSY) == SET) {
361+
if(I2C_GetFlagStatus(i2c, I2C_ISR_ADDR) == SET) {
362+
// Check direction
363+
if (I2C_GetFlagStatus(i2c, I2C_ISR_DIR) == SET) {
364+
event = ReadAddressed;
365+
}
366+
else event = WriteAddressed;
367+
// Clear adress match flag to generate an acknowledge
368+
i2c->ICR |= I2C_ICR_ADDRCF;
369+
}
370+
}
371+
return event;
330372
}
331373

332374
int i2c_slave_read(i2c_t *obj, char *data, int length) {

0 commit comments

Comments
 (0)