77#include <string.h>
88#include <sys/param.h>
99#include <sys/lock.h>
10+ #include "esp_rom_sys.h"
1011#include "sdkconfig.h"
1112#include "esp_types.h"
1213#include "esp_attr.h"
@@ -291,14 +292,62 @@ static bool s_i2c_read_command(i2c_master_bus_handle_t i2c_master, i2c_operation
291292
292293 i2c_master -> contains_read = true;
293294#if !SOC_I2C_STOP_INDEPENDENT
295+ /*
296+ * If the remaining bytes is less than the hardware fifo length - 1,
297+ * it means the read command can be sent out in one time.
298+ * So, we set the status to I2C_STATUS_READ_ALL.
299+ */
294300 if (remaining_bytes < I2C_FIFO_LEN (i2c_master -> base -> port_num ) - 1 ) {
301+ atomic_store (& i2c_master -> status , I2C_STATUS_READ_ALL );
295302 if (i2c_operation -> hw_cmd .ack_val == I2C_ACK_VAL ) {
296303 if (remaining_bytes != 0 ) {
297- i2c_ll_master_write_cmd_reg (hal -> dev , hw_cmd , i2c_master -> cmd_idx );
298- i2c_master -> read_len_static = i2c_master -> rx_cnt ;
299- i2c_master -> cmd_idx ++ ;
304+ // If the next transaction is a read command, and the ack value is I2C_ACK_VAL,
305+ // that means we have multi read jobs. We send out this read command first.
306+ // Otherwise, we can mix with other commands, like stop.
307+ i2c_operation_t next_transaction = i2c_master -> i2c_trans .ops [i2c_master -> trans_idx + 1 ];
308+ if (next_transaction .hw_cmd .op_code == I2C_LL_CMD_READ && next_transaction .hw_cmd .ack_val == I2C_ACK_VAL ) {
309+ portENTER_CRITICAL_SAFE (& handle -> spinlock );
310+ i2c_master -> read_len_static = i2c_master -> rx_cnt ;
311+ i2c_ll_master_write_cmd_reg (hal -> dev , hw_cmd , i2c_master -> cmd_idx );
312+ i2c_ll_master_write_cmd_reg (hal -> dev , hw_end_cmd , i2c_master -> cmd_idx + 1 );
313+ i2c_master -> cmd_idx = 0 ;
314+ i2c_master -> read_buf_pos = i2c_master -> trans_idx ;
315+ i2c_master -> trans_idx ++ ;
316+ i2c_master -> i2c_trans .cmd_count -- ;
317+ portEXIT_CRITICAL_SAFE (& handle -> spinlock );
318+ if (i2c_master -> async_trans == false) {
319+ i2c_hal_master_trans_start (hal );
320+ } else {
321+ i2c_master -> async_break = true;
322+ }
323+ } else {
324+ portENTER_CRITICAL_SAFE (& handle -> spinlock );
325+ i2c_ll_master_write_cmd_reg (hal -> dev , hw_cmd , i2c_master -> cmd_idx );
326+ i2c_master -> read_len_static = i2c_master -> rx_cnt ;
327+ i2c_master -> cmd_idx ++ ;
328+ i2c_master -> read_buf_pos = i2c_master -> trans_idx ;
329+ i2c_master -> trans_idx ++ ;
330+ i2c_master -> i2c_trans .cmd_count -- ;
331+ portEXIT_CRITICAL_SAFE (& handle -> spinlock );
332+ if (i2c_master -> async_trans == false) {
333+ if (xPortInIsrContext ()) {
334+ xSemaphoreGiveFromISR (i2c_master -> cmd_semphr , do_yield );
335+ } else {
336+ xSemaphoreGive (i2c_master -> cmd_semphr );
337+ }
338+ }
339+ }
340+ } else {
341+ i2c_master -> trans_idx ++ ;
342+ i2c_master -> i2c_trans .cmd_count -- ;
343+ if (i2c_master -> async_trans == false) {
344+ if (xPortInIsrContext ()) {
345+ xSemaphoreGiveFromISR (i2c_master -> cmd_semphr , do_yield );
346+ } else {
347+ xSemaphoreGive (i2c_master -> cmd_semphr );
348+ }
349+ }
300350 }
301- i2c_master -> read_buf_pos = i2c_master -> trans_idx ;
302351 } else {
303352 i2c_ll_master_write_cmd_reg (hal -> dev , hw_cmd , i2c_master -> cmd_idx );
304353 // If the read position has not been marked, that means the transaction doesn't contain read-ack
@@ -309,19 +358,20 @@ static bool s_i2c_read_command(i2c_master_bus_handle_t i2c_master, i2c_operation
309358 i2c_master -> read_len_static = i2c_master -> rx_cnt ;
310359 }
311360 i2c_master -> cmd_idx ++ ;
312- }
313- i2c_master -> trans_idx ++ ;
314- i2c_master -> i2c_trans . cmd_count -- ;
315- if ( i2c_master -> async_trans == false ) {
316- if ( xPortInIsrContext ()) {
317- xSemaphoreGiveFromISR ( i2c_master -> cmd_semphr , do_yield );
318- } else {
319- xSemaphoreGive ( i2c_master -> cmd_semphr );
361+ i2c_master -> trans_idx ++ ;
362+ i2c_master -> i2c_trans . cmd_count -- ;
363+ if ( i2c_master -> async_trans == false) {
364+ if ( xPortInIsrContext () ) {
365+ xSemaphoreGiveFromISR ( i2c_master -> cmd_semphr , do_yield );
366+ } else {
367+ xSemaphoreGive ( i2c_master -> cmd_semphr );
368+ }
320369 }
321370 }
322371 } else {
323372 atomic_store (& i2c_master -> status , I2C_STATUS_READ );
324373 portENTER_CRITICAL_SAFE (& handle -> spinlock );
374+ i2c_master -> read_buf_pos = i2c_master -> trans_idx ;
325375 i2c_ll_master_write_cmd_reg (hal -> dev , hw_cmd , i2c_master -> cmd_idx );
326376 i2c_ll_master_write_cmd_reg (hal -> dev , hw_end_cmd , i2c_master -> cmd_idx + 1 );
327377 if (i2c_master -> async_trans == false) {
@@ -342,6 +392,7 @@ static bool s_i2c_read_command(i2c_master_bus_handle_t i2c_master, i2c_operation
342392 i2c_master -> i2c_trans .cmd_count -- ;
343393 }
344394 }
395+ i2c_master -> read_buf_pos = i2c_master -> trans_idx ;
345396 i2c_ll_master_write_cmd_reg (hal -> dev , hw_cmd , i2c_master -> cmd_idx );
346397 i2c_ll_master_write_cmd_reg (hal -> dev , hw_end_cmd , i2c_master -> cmd_idx + 1 );
347398 portEXIT_CRITICAL_SAFE (& handle -> spinlock );
@@ -672,7 +723,7 @@ I2C_MASTER_ISR_ATTR static void i2c_isr_receive_handler(i2c_master_bus_t *i2c_ma
672723 i2c_hal_context_t * hal = & i2c_master -> base -> hal ;
673724
674725 if (atomic_load (& i2c_master -> status ) == I2C_STATUS_READ ) {
675- i2c_operation_t * i2c_operation = & i2c_master -> i2c_trans .ops [i2c_master -> trans_idx ];
726+ i2c_operation_t * i2c_operation = & i2c_master -> i2c_trans .ops [i2c_master -> read_buf_pos ];
676727 portENTER_CRITICAL_ISR (& i2c_master -> base -> spinlock );
677728 i2c_ll_read_rxfifo (hal -> dev , i2c_operation -> data + i2c_operation -> bytes_used , i2c_master -> rx_cnt );
678729 /* rx_cnt bytes have just been read, increment the number of bytes used from the buffer */
@@ -686,6 +737,7 @@ I2C_MASTER_ISR_ATTR static void i2c_isr_receive_handler(i2c_master_bus_t *i2c_ma
686737 i2c_master -> read_buf_pos = i2c_master -> trans_idx ;
687738 i2c_master -> trans_idx ++ ;
688739 i2c_operation -> bytes_used = 0 ;
740+ i2c_master -> read_len_static = 0 ;
689741 }
690742 portEXIT_CRITICAL_ISR (& i2c_master -> base -> spinlock );
691743 }
@@ -695,10 +747,11 @@ I2C_MASTER_ISR_ATTR static void i2c_isr_receive_handler(i2c_master_bus_t *i2c_ma
695747 portENTER_CRITICAL_ISR (& i2c_master -> base -> spinlock );
696748 i2c_ll_read_rxfifo (hal -> dev , i2c_operation -> data + i2c_operation -> bytes_used , i2c_master -> read_len_static );
697749 // If the read command only contain nack marker, no read it for the second time.
698- if (i2c_master -> i2c_trans .ops [i2c_master -> read_buf_pos + 1 ].data ) {
750+ if (i2c_master -> i2c_trans .ops [i2c_master -> read_buf_pos + 1 ].data && i2c_master -> i2c_trans . ops [ i2c_master -> read_buf_pos + 1 ]. hw_cmd . ack_val == I2C_NACK_VAL ) {
699751 i2c_ll_read_rxfifo (hal -> dev , i2c_master -> i2c_trans .ops [i2c_master -> read_buf_pos + 1 ].data , 1 );
700752 }
701753 i2c_master -> w_r_size = i2c_master -> read_len_static + 1 ;
754+ i2c_master -> read_len_static = 0 ;
702755 i2c_master -> contains_read = false;
703756 portEXIT_CRITICAL_ISR (& i2c_master -> base -> spinlock );
704757 }
0 commit comments