13
13
// limitations under the License.
14
14
15
15
#include "esp32-hal-i2c.h"
16
+ #include "esp32-hal.h"
16
17
#include "freertos/FreeRTOS.h"
17
18
#include "freertos/task.h"
19
+ #include "freertos/semphr.h"
18
20
#include "rom/ets_sys.h"
19
21
#include "soc/i2c_reg.h"
22
+ #include "soc/i2c_struct.h"
20
23
#include "soc/dport_reg.h"
21
24
22
- #define I2C_DEV (i ) (volatile i2c_dev_t *)((i)?DR_REG_I2C1_EXT_BASE:DR_REG_I2C_EXT_BASE)
25
+ // #define I2C_DEV(i) (volatile i2c_dev_t *)((i)?DR_REG_I2C1_EXT_BASE:DR_REG_I2C_EXT_BASE)
23
26
//#define I2C_DEV(i) ((i2c_dev_t *)(REG_I2C_BASE(i)))
24
27
#define I2C_SCL_IDX (p ) ((p==0)?I2CEXT0_SCL_OUT_IDX:((p==1)?I2CEXT1_SCL_OUT_IDX:0))
25
28
#define I2C_SDA_IDX (p ) ((p==0)?I2CEXT0_SDA_OUT_IDX:((p==1)?I2CEXT1_SDA_OUT_IDX:0))
26
29
27
- void i2cAttachSCL (i2c_t * i2c , int8_t scl )
30
+
31
+ struct i2c_struct_t {
32
+ i2c_dev_t * dev ;
33
+ xSemaphoreHandle lock ;
34
+ uint8_t num ;
35
+ };
36
+
37
+ enum {
38
+ I2C_CMD_RSTART ,
39
+ I2C_CMD_WRITE ,
40
+ I2C_CMD_READ ,
41
+ I2C_CMD_STOP ,
42
+ I2C_CMD_END
43
+ };
44
+
45
+ #define I2C_MUTEX_LOCK () do {} while (xSemaphoreTake(i2c->lock, portMAX_DELAY) != pdPASS)
46
+ #define I2C_MUTEX_UNLOCK () xSemaphoreGive(i2c->lock)
47
+
48
+ static i2c_t _i2c_bus_array [2 ] = {
49
+ {(volatile i2c_dev_t * )(DR_REG_I2C_EXT_BASE ), NULL , 0 },
50
+ {(volatile i2c_dev_t * )(DR_REG_I2C1_EXT_BASE ), NULL , 1 }
51
+ };
52
+
53
+ i2c_err_t i2cAttachSCL (i2c_t * i2c , int8_t scl )
28
54
{
55
+ if (i2c == NULL ){
56
+ return I2C_ERROR_DEV ;
57
+ }
29
58
pinMode (scl , OUTPUT );
30
59
pinMatrixOutAttach (scl , I2C_SCL_IDX (i2c -> num ), false, false);
31
60
pinMatrixInAttach (scl , I2C_SCL_IDX (i2c -> num ), false);
61
+ return I2C_ERROR_OK ;
32
62
}
33
63
34
- void i2cDetachSCL (i2c_t * i2c , int8_t scl )
64
+ i2c_err_t i2cDetachSCL (i2c_t * i2c , int8_t scl )
35
65
{
66
+ if (i2c == NULL ){
67
+ return I2C_ERROR_DEV ;
68
+ }
36
69
pinMatrixOutDetach (scl , false, false);
37
70
pinMatrixInDetach (I2C_SCL_IDX (i2c -> num ), false, false);
38
71
pinMode (scl , INPUT );
72
+ return I2C_ERROR_OK ;
39
73
}
40
74
41
- void i2cAttachSDA (i2c_t * i2c , int8_t sda )
75
+ i2c_err_t i2cAttachSDA (i2c_t * i2c , int8_t sda )
42
76
{
77
+ if (i2c == NULL ){
78
+ return I2C_ERROR_DEV ;
79
+ }
43
80
pinMode (sda , OUTPUT_OPEN_DRAIN );
44
81
pinMatrixOutAttach (sda , I2C_SDA_IDX (i2c -> num ), false, false);
45
82
pinMatrixInAttach (sda , I2C_SDA_IDX (i2c -> num ), false);
83
+ return I2C_ERROR_OK ;
46
84
}
47
85
48
- void i2cDetachSDA (i2c_t * i2c , int8_t sda )
86
+ i2c_err_t i2cDetachSDA (i2c_t * i2c , int8_t sda )
49
87
{
88
+ if (i2c == NULL ){
89
+ return I2C_ERROR_DEV ;
90
+ }
50
91
pinMatrixOutDetach (sda , false, false);
51
92
pinMatrixInDetach (I2C_SDA_IDX (i2c -> num ), false, false);
52
93
pinMode (sda , INPUT );
94
+ return I2C_ERROR_OK ;
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
81
- int i2cWrite (i2c_t * i2c , uint16_t address , bool addr_10bit , uint8_t * data , uint8_t len , bool sendStop )
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
+
123
+ i2c_err_t 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 I2C_ERROR_DEV ;
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,19 +177,22 @@ 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);
132
- return 4 ;
180
+ I2C_MUTEX_UNLOCK ();
181
+ return I2C_ERROR_BUS ;
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);
138
- return 3 ;
187
+ I2C_MUTEX_UNLOCK ();
188
+ return I2C_ERROR_TIMEOUT ;
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);
144
- return 1 ;
194
+ I2C_MUTEX_UNLOCK ();
195
+ return I2C_ERROR_ACK ;
145
196
}
146
197
147
198
if (i2c -> dev -> ctr .trans_start || i2c -> dev -> status_reg .bus_busy || !(i2c -> dev -> int_raw .trans_complete ) || !(i2c -> dev -> command [2 ].done )) {
@@ -152,17 +203,24 @@ int i2cWrite(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uin
152
203
}
153
204
154
205
}
155
- return 0 ;
206
+ I2C_MUTEX_UNLOCK ();
207
+ return I2C_ERROR_OK ;
156
208
}
157
209
158
- int i2cRead (i2c_t * i2c , uint16_t address , bool addr_10bit , uint8_t * data , uint8_t len , bool sendStop )
210
+ i2c_err_t i2cRead (i2c_t * i2c , uint16_t address , bool addr_10bit , uint8_t * data , uint8_t len , bool sendStop )
159
211
{
160
212
address = (address << 1 ) | 1 ;
161
213
uint8_t addrLen = (addr_10bit ?2 :1 );
162
214
uint8_t index = 0 ;
163
215
uint8_t cmdIdx ;
164
216
uint8_t willRead ;
165
217
218
+ if (i2c == NULL ){
219
+ return I2C_ERROR_DEV ;
220
+ }
221
+
222
+ I2C_MUTEX_LOCK ();
223
+
166
224
i2cResetFiFo (i2c );
167
225
168
226
//CMD START
@@ -204,19 +262,22 @@ 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);
207
- return -4 ;
265
+ I2C_MUTEX_UNLOCK ();
266
+ return I2C_ERROR_BUS ;
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);
213
- return -3 ;
272
+ I2C_MUTEX_UNLOCK ();
273
+ return I2C_ERROR_TIMEOUT ;
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);
219
- return -1 ;
279
+ I2C_MUTEX_UNLOCK ();
280
+ return I2C_ERROR_ACK ;
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 )) {
222
283
continue ;
@@ -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
}
235
- return 0 ;
236
- }
237
-
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 ;
296
+ I2C_MUTEX_UNLOCK ();
297
+ return I2C_ERROR_OK ;
246
298
}
247
299
248
- void i2cSetFrequency (i2c_t * i2c , uint32_t clk_speed )
300
+ i2c_err_t 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 I2C_ERROR_DEV ;
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,16 @@ 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 ();
321
+ return I2C_ERROR_OK ;
262
322
}
263
323
264
324
uint32_t i2cGetFrequency (i2c_t * i2c )
265
325
{
326
+ if (i2c == NULL ){
327
+ return 0 ;
328
+ }
329
+
266
330
return APB_CLK_FREQ /(i2c -> dev -> scl_low_period .scl_low_period + i2c -> dev -> scl_high_period .period );
267
331
}
268
332
@@ -274,22 +338,28 @@ uint32_t i2cGetFrequency(i2c_t * i2c)
274
338
275
339
i2c_t * i2cInit (uint8_t i2c_num , uint16_t slave_addr , bool addr_10bit_en )
276
340
{
277
- i2c_t * i2c = (i2c_t * ) malloc (sizeof (i2c_t ));
278
- if (i2c == 0 ) {
341
+ if (i2c_num > 1 ){
279
342
return NULL ;
280
343
}
281
344
282
- i2c -> num = i2c_num ;
283
- i2c -> dev = I2C_DEV (i2c_num );
345
+ i2c_t * i2c = & _i2c_bus_array [i2c_num ];
284
346
285
- if (i2c -> num == 0 ) {
347
+ if (i2c -> lock == NULL ){
348
+ i2c -> lock = xSemaphoreCreateMutex ();
349
+ if (i2c -> lock == NULL ) {
350
+ return NULL ;
351
+ }
352
+ }
353
+
354
+ if (i2c_num == 0 ) {
286
355
SET_PERI_REG_MASK (DPORT_PERIP_CLK_EN_REG ,DPORT_I2C_EXT0_CLK_EN );
287
356
CLEAR_PERI_REG_MASK (DPORT_PERIP_RST_EN_REG ,DPORT_I2C_EXT0_RST );
288
- } else if ( i2c -> num == 1 ) {
357
+ } else {
289
358
SET_PERI_REG_MASK (DPORT_PERIP_CLK_EN_REG ,DPORT_I2C_EXT1_CLK_EN );
290
359
CLEAR_PERI_REG_MASK (DPORT_PERIP_RST_EN_REG ,DPORT_I2C_EXT1_RST );
291
360
}
292
-
361
+
362
+ I2C_MUTEX_LOCK ();
293
363
i2c -> dev -> ctr .val = 0 ;
294
364
i2c -> dev -> ctr .ms_mode = (slave_addr == 0 );
295
365
i2c -> dev -> ctr .sda_force_out = 1 ;
@@ -304,6 +374,7 @@ i2c_t * i2cInit(uint8_t i2c_num, uint16_t slave_addr, bool addr_10bit_en)
304
374
i2c -> dev -> slave_addr .addr = slave_addr ;
305
375
i2c -> dev -> slave_addr .en_10bit = addr_10bit_en ;
306
376
}
377
+ I2C_MUTEX_UNLOCK ();
307
378
308
379
return i2c ;
309
380
}
0 commit comments