Skip to content

Commit 0aa8b93

Browse files
committed
NUCLEO_F103RB: Add I2C master api
1 parent 3bcf77e commit 0aa8b93

File tree

3 files changed

+322
-2
lines changed

3 files changed

+322
-2
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
#define DEVICE_SERIAL 1
2929

30-
#define DEVICE_I2C 0
30+
#define DEVICE_I2C 1
3131
#define DEVICE_I2CSLAVE 0
3232

3333
#define DEVICE_SPI 1
Lines changed: 321 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,321 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2006-2013 ARM Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#include "i2c_api.h"
17+
18+
#if DEVICE_I2C
19+
20+
#include "cmsis.h"
21+
#include "pinmap.h"
22+
#include "error.h"
23+
24+
/* Timeout values for flags and events waiting loops. These timeouts are
25+
not based on accurate values, they just guarantee that the application will
26+
not remain stuck if the I2C communication is corrupted. */
27+
#define FLAG_TIMEOUT ((int)0x1000)
28+
#define LONG_TIMEOUT ((int)0x8000)
29+
30+
// Functions exit codes
31+
#define EXIT_OK (0)
32+
#define EXIT_FAIL (1)
33+
#define EXIT_TIMEOUT (0xFFFFFFFF)
34+
35+
static const PinMap PinMap_I2C_SDA[] = {
36+
//{PB_7, I2C_1, STM_PIN_DATA(GPIO_Mode_AF_OD, 0)}, // Cannot be used due to TIM4
37+
{PB_9, I2C_1, STM_PIN_DATA(GPIO_Mode_AF_OD, 7)}, // GPIO_Remap_I2C1
38+
{NC, NC, 0}
39+
};
40+
41+
static const PinMap PinMap_I2C_SCL[] = {
42+
//{PB_6, I2C_1, STM_PIN_DATA(GPIO_Mode_AF_OD, 0)}, // // Cannot be used due to TIM4
43+
{PB_8, I2C_1, STM_PIN_DATA(GPIO_Mode_AF_OD, 7)}, // GPIO_Remap_I2C1
44+
{NC, NC, 0}
45+
};
46+
47+
void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
48+
// Determine the I2C to use
49+
I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
50+
I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);
51+
52+
obj->i2c = (I2CName)pinmap_merge(i2c_sda, i2c_scl);
53+
54+
if (obj->i2c == (I2CName)NC) {
55+
error("I2C pin mapping failed");
56+
}
57+
58+
// Enable I2C clock
59+
if (obj->i2c == I2C_1) {
60+
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
61+
}
62+
if (obj->i2c == I2C_2) {
63+
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
64+
}
65+
66+
// Configure I2C pins
67+
pinmap_pinout(sda, PinMap_I2C_SDA);
68+
pinmap_pinout(scl, PinMap_I2C_SCL);
69+
pin_mode(sda, OpenDrain);
70+
pin_mode(scl, OpenDrain);
71+
72+
// Reset to clear pending flags if any
73+
i2c_reset(obj);
74+
75+
// I2C configuration
76+
i2c_frequency(obj, 100000); // 100 kHz per default
77+
}
78+
79+
void i2c_frequency(i2c_t *obj, int hz) {
80+
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
81+
I2C_InitTypeDef I2C_InitStructure;
82+
83+
if ((hz != 0) && (hz <= 400000)) {
84+
// I2C configuration
85+
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
86+
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
87+
I2C_InitStructure.I2C_OwnAddress1 = 0;
88+
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
89+
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
90+
I2C_InitStructure.I2C_ClockSpeed = hz;
91+
I2C_Cmd(i2c, ENABLE);
92+
I2C_Init(i2c, &I2C_InitStructure);
93+
}
94+
}
95+
96+
inline int i2c_start(i2c_t *obj) {
97+
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
98+
int timeout;
99+
100+
I2C_ClearFlag(i2c, I2C_FLAG_AF); // Clear Acknowledge failure flag
101+
102+
// Generate the START condition
103+
I2C_GenerateSTART(i2c, ENABLE);
104+
105+
// Wait the START condition has been correctly sent
106+
timeout = FLAG_TIMEOUT;
107+
//while (I2C_CheckEvent(i2c, I2C_EVENT_MASTER_MODE_SELECT) == ERROR) {
108+
while (I2C_GetFlagStatus(i2c, I2C_FLAG_SB) == RESET) {
109+
if ((timeout--) == 0) {
110+
return EXIT_TIMEOUT;
111+
}
112+
}
113+
114+
return EXIT_OK;
115+
}
116+
117+
inline int i2c_stop(i2c_t *obj) {
118+
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
119+
I2C_GenerateSTOP(i2c, ENABLE);
120+
return EXIT_OK;
121+
}
122+
123+
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
124+
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
125+
int timeout;
126+
int count;
127+
int value;
128+
129+
if (length == 0) return 0;
130+
131+
/*
132+
// Wait until the bus is not busy anymore
133+
timeout = LONG_TIMEOUT;
134+
while (I2C_GetFlagStatus(i2c, I2C_FLAG_BUSY) == SET) {
135+
if ((timeout--) == 0) {
136+
return EXIT_TIMEOUT;
137+
}
138+
}
139+
*/
140+
141+
i2c_start(obj);
142+
143+
// Send slave address for read
144+
I2C_Send7bitAddress(i2c, address, I2C_Direction_Receiver);
145+
146+
// Wait address is acknowledged
147+
timeout = FLAG_TIMEOUT;
148+
while (I2C_CheckEvent(i2c, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) == ERROR) {
149+
if ((timeout--) == 0) {
150+
return EXIT_TIMEOUT;
151+
}
152+
}
153+
154+
// Read all bytes except last one
155+
for (count = 0; count < (length - 1); count++) {
156+
value = i2c_byte_read(obj, 0);
157+
data[count] = (char)value;
158+
}
159+
160+
// If not repeated start, send stop.
161+
// Warning: must be done BEFORE the data is read.
162+
if (stop) {
163+
i2c_stop(obj);
164+
}
165+
166+
// Read the last byte
167+
value = i2c_byte_read(obj, 1);
168+
data[count] = (char)value;
169+
170+
return length;
171+
}
172+
173+
int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
174+
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
175+
int timeout;
176+
int count;
177+
178+
if (length == 0) return 0;
179+
180+
/*
181+
// Wait until the bus is not busy anymore
182+
timeout = LONG_TIMEOUT;
183+
while (I2C_GetFlagStatus(i2c, I2C_FLAG_BUSY) == SET) {
184+
if ((timeout--) == 0) {
185+
return EXIT_TIMEOUT;
186+
}
187+
}
188+
*/
189+
190+
i2c_start(obj);
191+
192+
// Send slave address for write
193+
I2C_Send7bitAddress(i2c, address, I2C_Direction_Transmitter);
194+
195+
// Wait address is acknowledged
196+
timeout = FLAG_TIMEOUT;
197+
while (I2C_CheckEvent(i2c, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) == ERROR) {
198+
if ((timeout--) == 0) {
199+
return EXIT_TIMEOUT;
200+
}
201+
}
202+
203+
for (count = 0; count < length; count++) {
204+
if (i2c_byte_write(obj, data[count]) != EXIT_OK) {
205+
return EXIT_FAIL;
206+
}
207+
}
208+
209+
// If not repeated start, send stop.
210+
if (stop) {
211+
i2c_stop(obj);
212+
}
213+
214+
return count;
215+
}
216+
217+
int i2c_byte_read(i2c_t *obj, int last) {
218+
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
219+
uint8_t data;
220+
int timeout;
221+
222+
if (last) {
223+
// Don't acknowledge the last byte
224+
I2C_AcknowledgeConfig(i2c, DISABLE);
225+
} else {
226+
// Acknowledge the byte
227+
I2C_AcknowledgeConfig(i2c, ENABLE);
228+
}
229+
230+
// Wait until the byte is received
231+
timeout = FLAG_TIMEOUT;
232+
while (I2C_GetFlagStatus(i2c, I2C_FLAG_RXNE) == RESET) {
233+
if ((timeout--) == 0) {
234+
return EXIT_TIMEOUT;
235+
}
236+
}
237+
238+
data = I2C_ReceiveData(i2c);
239+
240+
return (int)data;
241+
}
242+
243+
int i2c_byte_write(i2c_t *obj, int data) {
244+
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
245+
int timeout;
246+
247+
I2C_SendData(i2c, (uint8_t)data);
248+
249+
// Wait until the byte is transmitted
250+
timeout = FLAG_TIMEOUT;
251+
//while (I2C_CheckEvent(i2c, I2C_EVENT_MASTER_BYTE_TRANSMITTED) == ERROR) {
252+
while ((I2C_GetFlagStatus(i2c, I2C_FLAG_TXE) == RESET) &&
253+
(I2C_GetFlagStatus(i2c, I2C_FLAG_BTF) == RESET)) {
254+
if ((timeout--) == 0) {
255+
return EXIT_TIMEOUT;
256+
}
257+
}
258+
259+
return EXIT_OK;
260+
}
261+
262+
void i2c_reset(i2c_t *obj) {
263+
if (obj->i2c == I2C_1) {
264+
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE);
265+
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE);
266+
}
267+
if (obj->i2c == I2C_2) {
268+
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C2, ENABLE);
269+
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C2, DISABLE);
270+
}
271+
}
272+
273+
#if DEVICE_I2CSLAVE
274+
275+
void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) {
276+
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
277+
uint16_t tmpreg;
278+
279+
// Get the old register value
280+
tmpreg = i2c->OAR1;
281+
// Reset address bits
282+
tmpreg &= 0xFC00;
283+
// Set new address
284+
tmpreg |= (uint16_t)((uint16_t)address & (uint16_t)0x00FE); // 7-bits
285+
// Store the new register value
286+
i2c->OAR1 = tmpreg;
287+
}
288+
289+
void i2c_slave_mode(i2c_t *obj, int enable_slave) {
290+
// Nothing to do
291+
}
292+
293+
#define NoData 0
294+
#define ReadAddressed 1
295+
#define WriteGeneral 2
296+
#define WriteAddressed 3
297+
298+
int i2c_slave_receive(i2c_t *obj) {
299+
//I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
300+
int retval = NoData;
301+
//int status;
302+
303+
//if (I2C_GetFlagStatus(i2c, I2C_FLAG_GENCALL) == SET) retval = WriteGeneral;
304+
305+
//status = I2C_GetLastEvent(i2c);
306+
307+
return(retval);
308+
}
309+
310+
int i2c_slave_read(i2c_t *obj, char *data, int length) {
311+
return 0;
312+
}
313+
314+
int i2c_slave_write(i2c_t *obj, const char *data, int length) {
315+
return 0;
316+
}
317+
318+
319+
#endif // DEVICE_I2CSLAVE
320+
321+
#endif // DEVICE_I2C

libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/objects.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ struct spi_s {
6565

6666
struct i2c_s {
6767
I2CName i2c;
68-
uint32_t clk_speed;
6968
};
7069

7170
struct pwmout_s {

0 commit comments

Comments
 (0)