Skip to content

Commit 9f9fb41

Browse files
committed
Merge branch 'i2c-thread-safe'
* i2c-thread-safe: remove unnecessary locks return proper errors implement thread-safe i2c
2 parents 9a9ef06 + 988bcbf commit 9f9fb41

File tree

2 files changed

+131
-56
lines changed

2 files changed

+131
-56
lines changed

cores/esp32/esp32-hal-i2c.c

Lines changed: 112 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -13,53 +13,87 @@
1313
// limitations under the License.
1414

1515
#include "esp32-hal-i2c.h"
16+
#include "esp32-hal.h"
1617
#include "freertos/FreeRTOS.h"
1718
#include "freertos/task.h"
19+
#include "freertos/semphr.h"
1820
#include "rom/ets_sys.h"
1921
#include "soc/i2c_reg.h"
22+
#include "soc/i2c_struct.h"
2023
#include "soc/dport_reg.h"
2124

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)
2326
//#define I2C_DEV(i) ((i2c_dev_t *)(REG_I2C_BASE(i)))
2427
#define I2C_SCL_IDX(p) ((p==0)?I2CEXT0_SCL_OUT_IDX:((p==1)?I2CEXT1_SCL_OUT_IDX:0))
2528
#define I2C_SDA_IDX(p) ((p==0)?I2CEXT0_SDA_OUT_IDX:((p==1)?I2CEXT1_SDA_OUT_IDX:0))
2629

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)
2854
{
55+
if(i2c == NULL){
56+
return I2C_ERROR_DEV;
57+
}
2958
pinMode(scl, OUTPUT);
3059
pinMatrixOutAttach(scl, I2C_SCL_IDX(i2c->num), false, false);
3160
pinMatrixInAttach(scl, I2C_SCL_IDX(i2c->num), false);
61+
return I2C_ERROR_OK;
3262
}
3363

34-
void i2cDetachSCL(i2c_t * i2c, int8_t scl)
64+
i2c_err_t i2cDetachSCL(i2c_t * i2c, int8_t scl)
3565
{
66+
if(i2c == NULL){
67+
return I2C_ERROR_DEV;
68+
}
3669
pinMatrixOutDetach(scl, false, false);
3770
pinMatrixInDetach(I2C_SCL_IDX(i2c->num), false, false);
3871
pinMode(scl, INPUT);
72+
return I2C_ERROR_OK;
3973
}
4074

41-
void i2cAttachSDA(i2c_t * i2c, int8_t sda)
75+
i2c_err_t i2cAttachSDA(i2c_t * i2c, int8_t sda)
4276
{
77+
if(i2c == NULL){
78+
return I2C_ERROR_DEV;
79+
}
4380
pinMode(sda, OUTPUT_OPEN_DRAIN);
4481
pinMatrixOutAttach(sda, I2C_SDA_IDX(i2c->num), false, false);
4582
pinMatrixInAttach(sda, I2C_SDA_IDX(i2c->num), false);
83+
return I2C_ERROR_OK;
4684
}
4785

48-
void i2cDetachSDA(i2c_t * i2c, int8_t sda)
86+
i2c_err_t i2cDetachSDA(i2c_t * i2c, int8_t sda)
4987
{
88+
if(i2c == NULL){
89+
return I2C_ERROR_DEV;
90+
}
5091
pinMatrixOutDetach(sda, false, false);
5192
pinMatrixInDetach(I2C_SDA_IDX(i2c->num), false, false);
5293
pinMode(sda, INPUT);
94+
return I2C_ERROR_OK;
5395
}
5496

55-
enum {
56-
I2C_CMD_RSTART,
57-
I2C_CMD_WRITE,
58-
I2C_CMD_READ,
59-
I2C_CMD_STOP,
60-
I2C_CMD_END
61-
};
62-
6397
/*
6498
* index - command index (0 to 15)
6599
* 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
78112
i2c->dev->command[index].op_code = op_code;
79113
}
80114

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)
82124
{
83125
int i;
84126
uint8_t index = 0;
85127
uint8_t dataLen = len + (addr_10bit?2:1);
86128
address = (address << 1);
87129

130+
if(i2c == NULL){
131+
return I2C_ERROR_DEV;
132+
}
133+
134+
I2C_MUTEX_LOCK();
135+
88136
while(dataLen) {
89137
uint8_t willSend = (dataLen > 32)?32:dataLen;
90138
uint8_t dataSend = willSend;
@@ -129,19 +177,22 @@ int i2cWrite(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uin
129177
//Bus failed (maybe check for this while waiting?
130178
if(i2c->dev->int_raw.arbitration_lost) {
131179
//log_e("Bus Fail! Addr: %x", address >> 1);
132-
return 4;
180+
I2C_MUTEX_UNLOCK();
181+
return I2C_ERROR_BUS;
133182
}
134183

135184
//Bus timeout
136185
if(i2c->dev->int_raw.time_out) {
137186
//log_e("Bus Timeout! Addr: %x", address >> 1);
138-
return 3;
187+
I2C_MUTEX_UNLOCK();
188+
return I2C_ERROR_TIMEOUT;
139189
}
140190

141191
//Transmission did not finish and ACK_ERR is set
142192
if(i2c->dev->int_raw.ack_err) {
143193
//log_e("Ack Error! Addr: %x", address >> 1);
144-
return 1;
194+
I2C_MUTEX_UNLOCK();
195+
return I2C_ERROR_ACK;
145196
}
146197

147198
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
152203
}
153204

154205
}
155-
return 0;
206+
I2C_MUTEX_UNLOCK();
207+
return I2C_ERROR_OK;
156208
}
157209

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)
159211
{
160212
address = (address << 1) | 1;
161213
uint8_t addrLen = (addr_10bit?2:1);
162214
uint8_t index = 0;
163215
uint8_t cmdIdx;
164216
uint8_t willRead;
165217

218+
if(i2c == NULL){
219+
return I2C_ERROR_DEV;
220+
}
221+
222+
I2C_MUTEX_LOCK();
223+
166224
i2cResetFiFo(i2c);
167225

168226
//CMD START
@@ -204,19 +262,22 @@ int i2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uint
204262
//Bus failed (maybe check for this while waiting?
205263
if(i2c->dev->int_raw.arbitration_lost) {
206264
//log_e("Bus Fail! Addr: %x", address >> 1);
207-
return -4;
265+
I2C_MUTEX_UNLOCK();
266+
return I2C_ERROR_BUS;
208267
}
209268

210269
//Bus timeout
211270
if(i2c->dev->int_raw.time_out) {
212271
//log_e("Bus Timeout! Addr: %x", address >> 1);
213-
return -3;
272+
I2C_MUTEX_UNLOCK();
273+
return I2C_ERROR_TIMEOUT;
214274
}
215275

216276
//Transmission did not finish and ACK_ERR is set
217277
if(i2c->dev->int_raw.ack_err) {
218278
//log_e("Ack Error! Addr: %x", address >> 1);
219-
return -1;
279+
I2C_MUTEX_UNLOCK();
280+
return I2C_ERROR_ACK;
220281
}
221282
if(i2c->dev->ctr.trans_start || i2c->dev->status_reg.bus_busy || !(i2c->dev->int_raw.trans_complete) || !(i2c->dev->command[cmdIdx-1].done)) {
222283
continue;
@@ -232,22 +293,19 @@ int i2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uint
232293
}
233294
len -= willRead;
234295
}
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;
246298
}
247299

248-
void i2cSetFrequency(i2c_t * i2c, uint32_t clk_speed)
300+
i2c_err_t i2cSetFrequency(i2c_t * i2c, uint32_t clk_speed)
249301
{
250302
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();
251309
i2c->dev->scl_low_period.scl_low_period = period;
252310
i2c->dev->scl_high_period.period = period;
253311

@@ -259,10 +317,16 @@ void i2cSetFrequency(i2c_t * i2c, uint32_t clk_speed)
259317

260318
i2c->dev->sda_hold.time = 25;
261319
i2c->dev->sda_sample.time = 25;
320+
I2C_MUTEX_UNLOCK();
321+
return I2C_ERROR_OK;
262322
}
263323

264324
uint32_t i2cGetFrequency(i2c_t * i2c)
265325
{
326+
if(i2c == NULL){
327+
return 0;
328+
}
329+
266330
return APB_CLK_FREQ/(i2c->dev->scl_low_period.scl_low_period+i2c->dev->scl_high_period.period);
267331
}
268332

@@ -274,22 +338,28 @@ uint32_t i2cGetFrequency(i2c_t * i2c)
274338

275339
i2c_t * i2cInit(uint8_t i2c_num, uint16_t slave_addr, bool addr_10bit_en)
276340
{
277-
i2c_t* i2c = (i2c_t*) malloc(sizeof(i2c_t));
278-
if(i2c == 0) {
341+
if(i2c_num > 1){
279342
return NULL;
280343
}
281344

282-
i2c->num = i2c_num;
283-
i2c->dev = I2C_DEV(i2c_num);
345+
i2c_t * i2c = &_i2c_bus_array[i2c_num];
284346

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) {
286355
SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG,DPORT_I2C_EXT0_CLK_EN);
287356
CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG,DPORT_I2C_EXT0_RST);
288-
} else if(i2c->num == 1) {
357+
} else {
289358
SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG,DPORT_I2C_EXT1_CLK_EN);
290359
CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG,DPORT_I2C_EXT1_RST);
291360
}
292-
361+
362+
I2C_MUTEX_LOCK();
293363
i2c->dev->ctr.val = 0;
294364
i2c->dev->ctr.ms_mode = (slave_addr == 0);
295365
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)
304374
i2c->dev->slave_addr.addr = slave_addr;
305375
i2c->dev->slave_addr.en_10bit = addr_10bit_en;
306376
}
377+
I2C_MUTEX_UNLOCK();
307378

308379
return i2c;
309380
}

cores/esp32/esp32-hal-i2c.h

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,32 @@
1919
extern "C" {
2020
#endif
2121

22-
#include "esp32-hal.h"
23-
#include "soc/i2c_struct.h"
22+
#include <stdint.h>
23+
#include <stdbool.h>
2424

25-
typedef struct {
26-
i2c_dev_t * dev;
27-
uint8_t num;
28-
} i2c_t;
25+
typedef enum {
26+
I2C_ERROR_OK,
27+
I2C_ERROR_DEV,
28+
I2C_ERROR_ACK,
29+
I2C_ERROR_TIMEOUT,
30+
I2C_ERROR_BUS
31+
} i2c_err_t;
32+
33+
struct i2c_struct_t;
34+
typedef struct i2c_struct_t i2c_t;
2935

3036
i2c_t * i2cInit(uint8_t i2c_num, uint16_t slave_addr, bool addr_10bit_en);
3137

32-
void i2cSetFrequency(i2c_t * i2c, uint32_t clk_speed);
38+
i2c_err_t i2cSetFrequency(i2c_t * i2c, uint32_t clk_speed);
3339
uint32_t i2cGetFrequency(i2c_t * i2c);
3440

35-
void i2cResetFiFo(i2c_t * i2c);
36-
37-
void i2cAttachSCL(i2c_t * i2c, int8_t scl);
38-
void i2cDetachSCL(i2c_t * i2c, int8_t scl);
39-
void i2cAttachSDA(i2c_t * i2c, int8_t sda);
40-
void i2cDetachSDA(i2c_t * i2c, int8_t sda);
41+
i2c_err_t i2cAttachSCL(i2c_t * i2c, int8_t scl);
42+
i2c_err_t i2cDetachSCL(i2c_t * i2c, int8_t scl);
43+
i2c_err_t i2cAttachSDA(i2c_t * i2c, int8_t sda);
44+
i2c_err_t i2cDetachSDA(i2c_t * i2c, int8_t sda);
4145

42-
int i2cWrite(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uint8_t len, bool sendStop);
43-
int i2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uint8_t len, bool sendStop);
46+
i2c_err_t i2cWrite(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uint8_t len, bool sendStop);
47+
i2c_err_t i2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data, uint8_t len, bool sendStop);
4448

4549

4650
#ifdef __cplusplus

0 commit comments

Comments
 (0)