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
264324uint32_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
275339i2c_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}
0 commit comments