15
15
#include "esp32-hal-i2c.h"
16
16
#include "freertos/FreeRTOS.h"
17
17
#include "freertos/task.h"
18
+ #include "freertos/semphr.h"
18
19
#include "rom/ets_sys.h"
19
20
#include "soc/i2c_reg.h"
20
21
#include "soc/dport_reg.h"
21
22
22
- #define I2C_DEV (i ) (volatile i2c_dev_t *)((i)?DR_REG_I2C1_EXT_BASE:DR_REG_I2C_EXT_BASE)
23
- //#define I2C_DEV(i) ((i2c_dev_t *)(REG_I2C_BASE(i)))
24
23
#define I2C_SCL_IDX (p ) ((p==0)?I2CEXT0_SCL_OUT_IDX:((p==1)?I2CEXT1_SCL_OUT_IDX:0))
25
24
#define I2C_SDA_IDX (p ) ((p==0)?I2CEXT0_SDA_OUT_IDX:((p==1)?I2CEXT1_SDA_OUT_IDX:0))
26
25
26
+
27
+ struct i2c_struct_t {
28
+ i2c_dev_t * dev ;
29
+ xSemaphoreHandle lock ;
30
+ uint8_t num ;
31
+ };
32
+
33
+ enum {
34
+ I2C_CMD_RSTART ,
35
+ I2C_CMD_WRITE ,
36
+ I2C_CMD_READ ,
37
+ I2C_CMD_STOP ,
38
+ I2C_CMD_END
39
+ };
40
+
41
+ #define I2C_MUTEX_LOCK () do {} while (xSemaphoreTake(i2c->lock, portMAX_DELAY) != pdPASS)
42
+ #define I2C_MUTEX_UNLOCK () xSemaphoreGive(i2c->lock)
43
+
44
+ static i2c_t _i2c_bus_array [2 ] = {
45
+ {(volatile i2c_dev_t * )(DR_REG_I2C_EXT_BASE ), NULL , 0 },
46
+ {(volatile i2c_dev_t * )(DR_REG_I2C1_EXT_BASE ), NULL , 1 }
47
+ };
48
+
27
49
void i2cAttachSCL (i2c_t * i2c , int8_t scl )
28
50
{
51
+ if (i2c == NULL ){
52
+ return ;
53
+ }
54
+ I2C_MUTEX_LOCK ();
29
55
pinMode (scl , OUTPUT );
30
56
pinMatrixOutAttach (scl , I2C_SCL_IDX (i2c -> num ), false, false);
31
57
pinMatrixInAttach (scl , I2C_SCL_IDX (i2c -> num ), false);
58
+ I2C_MUTEX_UNLOCK ();
32
59
}
33
60
34
61
void i2cDetachSCL (i2c_t * i2c , int8_t scl )
35
62
{
63
+ if (i2c == NULL ){
64
+ return ;
65
+ }
66
+ I2C_MUTEX_LOCK ();
36
67
pinMatrixOutDetach (scl , false, false);
37
68
pinMatrixInDetach (I2C_SCL_IDX (i2c -> num ), false, false);
38
69
pinMode (scl , INPUT );
70
+ I2C_MUTEX_UNLOCK ();
39
71
}
40
72
41
73
void i2cAttachSDA (i2c_t * i2c , int8_t sda )
42
74
{
75
+ if (i2c == NULL ){
76
+ return ;
77
+ }
78
+ I2C_MUTEX_LOCK ();
43
79
pinMode (sda , OUTPUT_OPEN_DRAIN );
44
80
pinMatrixOutAttach (sda , I2C_SDA_IDX (i2c -> num ), false, false);
45
81
pinMatrixInAttach (sda , I2C_SDA_IDX (i2c -> num ), false);
82
+ I2C_MUTEX_UNLOCK ();
46
83
}
47
84
48
85
void i2cDetachSDA (i2c_t * i2c , int8_t sda )
49
86
{
87
+ if (i2c == NULL ){
88
+ return ;
89
+ }
90
+ I2C_MUTEX_LOCK ();
50
91
pinMatrixOutDetach (sda , false, false);
51
92
pinMatrixInDetach (I2C_SDA_IDX (i2c -> num ), false, false);
52
93
pinMode (sda , INPUT );
94
+ I2C_MUTEX_UNLOCK ();
53
95
}
54
96
55
- enum {
56
- I2C_CMD_RSTART ,
57
- I2C_CMD_WRITE ,
58
- I2C_CMD_READ ,
59
- I2C_CMD_STOP ,
60
- I2C_CMD_END
61
- };
62
-
63
97
/*
64
98
* index - command index (0 to 15)
65
99
* op_code - is the command
@@ -78,13 +112,27 @@ void i2cSetCmd(i2c_t * i2c, uint8_t index, uint8_t op_code, uint8_t byte_num, bo
78
112
i2c -> dev -> command [index ].op_code = op_code ;
79
113
}
80
114
115
+ void i2cResetFiFo (i2c_t * i2c )
116
+ {
117
+ i2c -> dev -> fifo_conf .tx_fifo_rst = 1 ;
118
+ i2c -> dev -> fifo_conf .tx_fifo_rst = 0 ;
119
+ i2c -> dev -> fifo_conf .rx_fifo_rst = 1 ;
120
+ i2c -> dev -> fifo_conf .rx_fifo_rst = 0 ;
121
+ }
122
+
81
123
int i2cWrite (i2c_t * i2c , uint16_t address , bool addr_10bit , uint8_t * data , uint8_t len , bool sendStop )
82
124
{
83
125
int i ;
84
126
uint8_t index = 0 ;
85
127
uint8_t dataLen = len + (addr_10bit ?2 :1 );
86
128
address = (address << 1 );
87
129
130
+ if (i2c == NULL ){
131
+ return 4 ;
132
+ }
133
+
134
+ I2C_MUTEX_LOCK ();
135
+
88
136
while (dataLen ) {
89
137
uint8_t willSend = (dataLen > 32 )?32 :dataLen ;
90
138
uint8_t dataSend = willSend ;
@@ -129,18 +177,21 @@ int i2cWrite(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uin
129
177
//Bus failed (maybe check for this while waiting?
130
178
if (i2c -> dev -> int_raw .arbitration_lost ) {
131
179
//log_e("Bus Fail! Addr: %x", address >> 1);
180
+ I2C_MUTEX_UNLOCK ();
132
181
return 4 ;
133
182
}
134
183
135
184
//Bus timeout
136
185
if (i2c -> dev -> int_raw .time_out ) {
137
186
//log_e("Bus Timeout! Addr: %x", address >> 1);
187
+ I2C_MUTEX_UNLOCK ();
138
188
return 3 ;
139
189
}
140
190
141
191
//Transmission did not finish and ACK_ERR is set
142
192
if (i2c -> dev -> int_raw .ack_err ) {
143
193
//log_e("Ack Error! Addr: %x", address >> 1);
194
+ I2C_MUTEX_UNLOCK ();
144
195
return 1 ;
145
196
}
146
197
@@ -152,6 +203,7 @@ int i2cWrite(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uin
152
203
}
153
204
154
205
}
206
+ I2C_MUTEX_UNLOCK ();
155
207
return 0 ;
156
208
}
157
209
@@ -163,6 +215,12 @@ int i2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uint
163
215
uint8_t cmdIdx ;
164
216
uint8_t willRead ;
165
217
218
+ if (i2c == NULL ){
219
+ return 4 ;
220
+ }
221
+
222
+ I2C_MUTEX_LOCK ();
223
+
166
224
i2cResetFiFo (i2c );
167
225
168
226
//CMD START
@@ -204,18 +262,21 @@ int i2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uint
204
262
//Bus failed (maybe check for this while waiting?
205
263
if (i2c -> dev -> int_raw .arbitration_lost ) {
206
264
//log_e("Bus Fail! Addr: %x", address >> 1);
265
+ I2C_MUTEX_UNLOCK ();
207
266
return -4 ;
208
267
}
209
268
210
269
//Bus timeout
211
270
if (i2c -> dev -> int_raw .time_out ) {
212
271
//log_e("Bus Timeout! Addr: %x", address >> 1);
272
+ I2C_MUTEX_UNLOCK ();
213
273
return -3 ;
214
274
}
215
275
216
276
//Transmission did not finish and ACK_ERR is set
217
277
if (i2c -> dev -> int_raw .ack_err ) {
218
278
//log_e("Ack Error! Addr: %x", address >> 1);
279
+ I2C_MUTEX_UNLOCK ();
219
280
return -1 ;
220
281
}
221
282
if (i2c -> dev -> ctr .trans_start || i2c -> dev -> status_reg .bus_busy || !(i2c -> dev -> int_raw .trans_complete ) || !(i2c -> dev -> command [cmdIdx - 1 ].done )) {
@@ -232,22 +293,19 @@ int i2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uint
232
293
}
233
294
len -= willRead ;
234
295
}
296
+ I2C_MUTEX_UNLOCK ();
235
297
return 0 ;
236
298
}
237
299
238
- void i2cResetFiFo (i2c_t * i2c )
239
- {
240
- //TX FIFO
241
- i2c -> dev -> fifo_conf .tx_fifo_rst = 1 ;
242
- i2c -> dev -> fifo_conf .tx_fifo_rst = 0 ;
243
- //RX FIFO
244
- i2c -> dev -> fifo_conf .rx_fifo_rst = 1 ;
245
- i2c -> dev -> fifo_conf .rx_fifo_rst = 0 ;
246
- }
247
-
248
300
void i2cSetFrequency (i2c_t * i2c , uint32_t clk_speed )
249
301
{
250
302
uint32_t period = (APB_CLK_FREQ /clk_speed ) / 2 ;
303
+
304
+ if (i2c == NULL ){
305
+ return ;
306
+ }
307
+
308
+ I2C_MUTEX_LOCK ();
251
309
i2c -> dev -> scl_low_period .scl_low_period = period ;
252
310
i2c -> dev -> scl_high_period .period = period ;
253
311
@@ -259,10 +317,15 @@ void i2cSetFrequency(i2c_t * i2c, uint32_t clk_speed)
259
317
260
318
i2c -> dev -> sda_hold .time = 25 ;
261
319
i2c -> dev -> sda_sample .time = 25 ;
320
+ I2C_MUTEX_UNLOCK ();
262
321
}
263
322
264
323
uint32_t i2cGetFrequency (i2c_t * i2c )
265
324
{
325
+ if (i2c == NULL ){
326
+ return 0 ;
327
+ }
328
+
266
329
return APB_CLK_FREQ /(i2c -> dev -> scl_low_period .scl_low_period + i2c -> dev -> scl_high_period .period );
267
330
}
268
331
@@ -274,18 +337,23 @@ uint32_t i2cGetFrequency(i2c_t * i2c)
274
337
275
338
i2c_t * i2cInit (uint8_t i2c_num , uint16_t slave_addr , bool addr_10bit_en )
276
339
{
277
- i2c_t * i2c = (i2c_t * ) malloc (sizeof (i2c_t ));
278
- if (i2c == 0 ) {
340
+ if (i2c_num > 1 ){
279
341
return NULL ;
280
342
}
281
343
282
- i2c -> num = i2c_num ;
283
- i2c -> dev = I2C_DEV (i2c_num );
344
+ i2c_t * i2c = & _i2c_bus_array [i2c_num ];
345
+
346
+ if (i2c -> lock == NULL ){
347
+ i2c -> lock = xSemaphoreCreateMutex ();
348
+ if (i2c -> lock == NULL ) {
349
+ return NULL ;
350
+ }
351
+ }
284
352
285
- if (i2c -> num == 0 ) {
353
+ if (i2c_num == 0 ) {
286
354
SET_PERI_REG_MASK (DPORT_PERIP_CLK_EN_REG ,DPORT_I2C_EXT0_CLK_EN );
287
355
CLEAR_PERI_REG_MASK (DPORT_PERIP_RST_EN_REG ,DPORT_I2C_EXT0_RST );
288
- } else if ( i2c -> num == 1 ) {
356
+ } else {
289
357
SET_PERI_REG_MASK (DPORT_PERIP_CLK_EN_REG ,DPORT_I2C_EXT1_CLK_EN );
290
358
CLEAR_PERI_REG_MASK (DPORT_PERIP_RST_EN_REG ,DPORT_I2C_EXT1_RST );
291
359
}
0 commit comments