3131#define DR_REG_I2C_EXT_BASE_FIXED 0x60013000
3232#define DR_REG_I2C1_EXT_BASE_FIXED 0x60027000
3333
34+ #define COMMAND_BUFFER_LENGTH 16
35+
3436struct i2c_struct_t {
3537 i2c_dev_t * dev ;
3638#if !CONFIG_DISABLE_HAL_LOCKS
@@ -127,26 +129,25 @@ void i2cSetCmd(i2c_t * i2c, uint8_t index, uint8_t op_code, uint8_t byte_num, bo
127129 i2c -> dev -> command [index ].op_code = op_code ;
128130}
129131
130- void i2cResetCmd (i2c_t * i2c ){
131- int i ;
132+ void i2cResetCmd (i2c_t * i2c ) {
133+ uint8_t i ;
132134 for (i = 0 ;i < 16 ;i ++ ){
133135 i2c -> dev -> command [i ].val = 0 ;
134136 }
135137}
136138
137- void i2cResetFiFo (i2c_t * i2c )
138- {
139+ void i2cResetFiFo (i2c_t * i2c ) {
139140 i2c -> dev -> fifo_conf .tx_fifo_rst = 1 ;
140141 i2c -> dev -> fifo_conf .tx_fifo_rst = 0 ;
141142 i2c -> dev -> fifo_conf .rx_fifo_rst = 1 ;
142143 i2c -> dev -> fifo_conf .rx_fifo_rst = 0 ;
143144}
144145
145- i2c_err_t i2cWrite (i2c_t * i2c , uint16_t address , bool addr_10bit , uint8_t * data , uint8_t len , bool sendStop )
146+ i2c_err_t i2cWrite (i2c_t * i2c , uint16_t address , bool addr_10bit , uint8_t * data , uint16_t len , bool sendStop )
146147{
147148 int i ;
148- uint8_t index = 0 ;
149- uint8_t dataLen = len + (addr_10bit ?2 :1 );
149+ uint16_t index = 0 ;
150+ uint16_t dataLen = len + (addr_10bit ?2 :1 );
150151 address = (address << 1 );
151152
152153 if (i2c == NULL ){
@@ -247,12 +248,25 @@ i2c_err_t i2cWrite(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * dat
247248 return I2C_ERROR_OK ;
248249}
249250
250- i2c_err_t i2cRead (i2c_t * i2c , uint16_t address , bool addr_10bit , uint8_t * data , uint8_t len , bool sendStop )
251+ uint8_t inc ( uint8_t * index )
252+ {
253+ uint8_t i = index [ 0 ];
254+ if (++ index [ 0 ] == COMMAND_BUFFER_LENGTH )
255+ {
256+ index [ 0 ] = 0 ;
257+ }
258+
259+ return i ;
260+ }
261+
262+ i2c_err_t i2cRead (i2c_t * i2c , uint16_t address , bool addr_10bit , uint8_t * data , uint16_t len , bool sendStop )
251263{
252264 address = (address << 1 ) | 1 ;
253265 uint8_t addrLen = (addr_10bit ?2 :1 );
254- uint8_t index = 0 ;
255- uint8_t cmdIdx ;
266+ uint8_t amountRead [16 ];
267+ uint16_t index = 0 ;
268+ uint8_t cmdIdx = 0 , currentCmdIdx = 0 , nextCmdCount ;
269+ bool stopped = false, isEndNear = false;
256270 uint8_t willRead ;
257271
258272 if (i2c == NULL ){
@@ -272,90 +286,93 @@ i2c_err_t i2cRead(i2c_t * i2c, uint16_t address, bool addr_10bit, uint8_t * data
272286 i2cResetCmd (i2c );
273287
274288 //CMD START
275- i2cSetCmd (i2c , 0 , I2C_CMD_RSTART , 0 , false, false, false);
289+ i2cSetCmd (i2c , cmdIdx ++ , I2C_CMD_RSTART , 0 , false, false, false);
276290
277291 //CMD WRITE ADDRESS
278- if (addr_10bit ){ // address is leftshifted with Read/Write bit set
292+ if (addr_10bit ) { // address is left-shifted with Read/Write bit set
279293 i2c -> dev -> fifo_data .data = (((address >> 8 ) & 0x6 ) | 0xF1 ); // send a9:a8 plus 1111 0xxR mask
280294 i2c -> dev -> fifo_data .data = ((address >> 1 ) & 0xFF ); // send a7:a0, remove R bit (7bit address style)
281295 }
282296 else { // 7bit address
283297 i2c -> dev -> fifo_data .data = address & 0xFF ;
284298 }
299+ i2cSetCmd (i2c , cmdIdx ++ , I2C_CMD_WRITE , addrLen , false, false, true);
300+ nextCmdCount = cmdIdx ;
285301
286- i2cSetCmd (i2c , 1 , I2C_CMD_WRITE , addrLen , false, false, true);
287-
288- while (len ) {
289- cmdIdx = (index )?0 :2 ;
290- willRead = (len > 32 )?32 :(len - 1 );
291- if (cmdIdx ){
292- i2cResetFiFo (i2c );
293- }
294-
295- if (willRead ){
296- i2cSetCmd (i2c , cmdIdx ++ , I2C_CMD_READ , willRead , false, false, false);
297- }
298-
299- if ((len - willRead ) > 1 ) {
300- i2cSetCmd (i2c , cmdIdx ++ , I2C_CMD_END , 0 , false, false, false);
301- } else {
302- willRead ++ ;
303- i2cSetCmd (i2c , cmdIdx ++ , I2C_CMD_READ , 1 , true, false, false);
304- if (sendStop ) {
305- i2cSetCmd (i2c , cmdIdx ++ , I2C_CMD_STOP , 0 , false, false, false);
306- }
307- }
308-
309- //Clear Interrupts
310- i2c -> dev -> int_clr .val = 0xFFFFFFFF ;
311-
312- //START Transmission
313- i2c -> dev -> ctr .trans_start = 1 ;
302+ //Clear Interrupts
303+ i2c -> dev -> int_clr .val = 0x00001FFF ;
314304
305+ //START Transmission
306+ i2c -> dev -> ctr .trans_start = 1 ;
307+ while (!stopped ) {
315308 //WAIT Transmission
316309 uint32_t startAt = millis ();
317310 while (1 ) {
318311 //have been looping for too long
319- if ((millis () - startAt )> 50 ){
320- log_e ("Timeout! Addr: %x" , address >> 1 );
312+ if ((millis () - startAt )> 50 ) {
313+ log_e ("Timeout! Addr: %x, index %d " , ( address >> 1 ), index );
321314 I2C_MUTEX_UNLOCK ();
322315 return I2C_ERROR_BUS ;
323316 }
324317
325318 //Bus failed (maybe check for this while waiting?
326319 if (i2c -> dev -> int_raw .arbitration_lost ) {
327- log_e ("Bus Fail! Addr: %x" , address >> 1 );
320+ log_e ("Bus Fail! Addr: %x" , ( address >> 1 ) );
328321 I2C_MUTEX_UNLOCK ();
329322 return I2C_ERROR_BUS ;
330323 }
331324
332325 //Bus timeout
333326 if (i2c -> dev -> int_raw .time_out ) {
334- log_e ("Bus Timeout! Addr: %x" , address >> 1 );
327+ log_e ("Bus Timeout! Addr: %x, index %d " , ( address >> 1 ), index );
335328 I2C_MUTEX_UNLOCK ();
336329 return I2C_ERROR_TIMEOUT ;
337330 }
338331
339332 //Transmission did not finish and ACK_ERR is set
340333 if (i2c -> dev -> int_raw .ack_err ) {
341334 log_w ("Ack Error! Addr: %x" , address >> 1 );
335+ while ((i2c -> dev -> status_reg .bus_busy ) && ((millis () - startAt )< 50 ));
342336 I2C_MUTEX_UNLOCK ();
343337 return I2C_ERROR_ACK ;
344338 }
345339
346- if (i2c -> dev -> command [cmdIdx - 1 ].done ) {
347- break ;
340+ // Save bytes from the buffer as they arrive instead of doing them at the end of the loop since there is no
341+ // pause from an END operation in this approach.
342+ if ((!isEndNear ) && (nextCmdCount < 2 )) {
343+ if (willRead = ((len > 32 )?32 :len )) {
344+ if (willRead > 1 ) {
345+ i2cSetCmd (i2c , cmdIdx , I2C_CMD_READ , (amountRead [ inc ( & cmdIdx ) ] = willRead - 1 ), false, false, false);
346+ nextCmdCount ++ ;
347+ }
348+ i2cSetCmd (i2c , cmdIdx , I2C_CMD_READ , (amountRead [ inc ( & cmdIdx ) ] = 1 ), (len <=32 ), false, false);
349+ nextCmdCount ++ ;
350+ len -= willRead ;
351+ } else {
352+ i2cSetCmd (i2c , inc ( & cmdIdx ), I2C_CMD_STOP , 0 , false, false, false);
353+ isEndNear = true;
354+ nextCmdCount ++ ;
355+ }
348356 }
349- }
350357
351- int i = 0 ;
352- while (i < willRead ) {
353- i ++ ;
354- data [index ++ ] = i2c -> dev -> fifo_data .val & 0xFF ;
358+ if (i2c -> dev -> command [currentCmdIdx ].done ) {
359+ nextCmdCount -- ;
360+ if (i2c -> dev -> command [currentCmdIdx ].op_code == I2C_CMD_READ ) {
361+ while (amountRead [currentCmdIdx ]> 0 ) {
362+ data [index ++ ] = i2c -> dev -> fifo_data .val & 0xFF ;
363+ amountRead [currentCmdIdx ]-- ;
364+ }
365+ i2cResetFiFo (i2c );
366+ } else if (i2c -> dev -> command [currentCmdIdx ].op_code == I2C_CMD_STOP ) {
367+ stopped = true;
368+ }
369+ inc ( & currentCmdIdx );
370+ break ;
371+ }
355372 }
356- len -= willRead ;
357373 }
358374 I2C_MUTEX_UNLOCK ();
375+
359376 return I2C_ERROR_OK ;
360377}
361378
@@ -432,7 +449,7 @@ i2c_t * i2cInit(uint8_t i2c_num, uint16_t slave_addr, bool addr_10bit_en)
432449 DPORT_SET_PERI_REG_MASK (DPORT_PERIP_CLK_EN_REG ,DPORT_I2C_EXT1_CLK_EN );
433450 DPORT_CLEAR_PERI_REG_MASK (DPORT_PERIP_RST_EN_REG ,DPORT_I2C_EXT1_RST );
434451 }
435-
452+
436453 I2C_MUTEX_LOCK ();
437454 i2c -> dev -> ctr .val = 0 ;
438455 i2c -> dev -> ctr .ms_mode = (slave_addr == 0 );
@@ -441,7 +458,7 @@ i2c_t * i2cInit(uint8_t i2c_num, uint16_t slave_addr, bool addr_10bit_en)
441458 i2c -> dev -> ctr .clk_en = 1 ;
442459
443460 //the max clock number of receiving a data
444- i2c -> dev -> timeout .tout = 400000 ;//clocks max=1048575
461+ i2c -> dev -> timeout .tout = 1048575 ;//clocks max=1048575
445462 //disable apb nonfifo access
446463 i2c -> dev -> fifo_conf .nonfifo_en = 0 ;
447464
0 commit comments