Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 9f9fb41

Browse files
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)

AltStyle によって変換されたページ (->オリジナル) /