2727// This file is never compiled standalone, it's included directly from
2828// extmod/machine_i2c_target.c via MICROPY_PY_MACHINE_I2C_TARGET_INCLUDEFILE.
2929
30- #include "pico/i2c_slave .h"
30+ #include "hardware/i2c .h"
3131
3232// TODO: should be in a common i2c header
3333#ifdef MICROPY_HW_I2C_NO_DEFAULT_PINS
@@ -75,6 +75,7 @@ typedef struct _machine_i2c_target_obj_t {
7575 i2c_inst_t * const i2c_inst ;
7676 mp_hal_pin_obj_t scl ;
7777 mp_hal_pin_obj_t sda ;
78+ uint8_t state ;
7879} machine_i2c_target_obj_t ;
7980
8081static machine_i2c_target_data_t i2c_target_data [4 ];
@@ -85,41 +86,102 @@ static machine_i2c_target_obj_t machine_i2c_target_obj[] = {
8586};
8687
8788/******************************************************************************/
88- // pico-sdk bindings
89+ // RP2xxx hardware bindings
8990
90- static void i2c_target_handler (i2c_inst_t * i2c , i2c_slave_event_t event ) {
91+ static void i2c_target_handler (i2c_inst_t * i2c ) {
9192 unsigned int i2c_id = i2c == i2c0 ? 0 : 1 ;
9293 machine_i2c_target_obj_t * self = & machine_i2c_target_obj [i2c_id ];
9394 machine_i2c_target_data_t * data = & i2c_target_data [i2c_id ];
9495
95- switch (event ) {
96+ // Get the interrupt status.
97+ uint32_t intr_stat = i2c -> hw -> intr_stat ;
98+
99+ if (intr_stat & I2C_IC_INTR_STAT_R_TX_ABRT_BITS ) {
100+ // Clear the TX_ABRT condition.
101+ (void )i2c -> hw -> clr_tx_abrt ;
102+ }
103+
104+ if (intr_stat & I2C_IC_INTR_STAT_R_RX_FULL_BITS ) {
96105 // Data from controller is available for reading.
97- case I2C_SLAVE_RECEIVE :
98- if (data -> state == STATE_IDLE ) {
99- machine_i2c_target_data_addr_match (data , false);
100- }
101- machine_i2c_target_data_write_request (self , data );
102- break ;
106+ // Mask interrupt until I2C_DATA_CMD is read from.
107+ i2c -> hw -> intr_mask &= ~I2C_IC_INTR_MASK_M_RX_FULL_BITS ;
108+ if (self -> state != STATE_WRITING ) {
109+ machine_i2c_target_data_addr_match (data , false);
110+ }
111+ machine_i2c_target_data_write_request (self , data );
112+ self -> state = STATE_WRITING ;
113+ }
103114
115+ if (intr_stat & (I2C_IC_INTR_STAT_R_RD_REQ_BITS | I2C_IC_INTR_STAT_R_RX_DONE_BITS )) {
104116 // Controller is requesting data.
105- case I2C_SLAVE_REQUEST : {
106- if (data -> state == STATE_IDLE ) {
107- machine_i2c_target_data_addr_match (data , true);
108- }
109- // i2c_write_byte_raw(i2c, 0x12);
110- // break;
111- machine_i2c_target_data_read_request (self , data );
112- break ;
117+ (void )i2c -> hw -> clr_rx_done ;
118+ (void )i2c -> hw -> clr_rd_req ;
119+ i2c -> hw -> intr_mask &= ~I2C_IC_INTR_MASK_M_RD_REQ_BITS ;
120+ if (self -> state != STATE_READING ) {
121+ machine_i2c_target_data_addr_match (data , true);
113122 }
123+ machine_i2c_target_data_read_request (self , data );
124+ self -> state = STATE_READING ;
125+ }
114126
115- // Controller has sent a Stop or Restart signal.
116- case I2C_SLAVE_FINISH :
117- // TODO handle the fact this could be a restart
118- machine_i2c_target_data_restart_or_stop (data );
119- break ;
127+ if (intr_stat & I2C_IC_INTR_STAT_R_STOP_DET_BITS ) {
128+ // Controller has generated a stop condition.
129+ (void )i2c -> hw -> clr_stop_det ;
130+ if (self -> state == STATE_IDLE ) {
131+ machine_i2c_target_data_addr_match (data , false);
132+ }
133+ machine_i2c_target_data_restart_or_stop (data );
134+ self -> state = STATE_IDLE ;
120135 }
121136}
122137
138+ static void i2c_slave_irq_handler (void ) {
139+ uint i2c_index = __get_current_exception () - VTABLE_FIRST_IRQ - I2C0_IRQ ;
140+ i2c_inst_t * i2c = i2c_get_instance (i2c_index );
141+ i2c_target_handler (i2c );
142+ }
143+
144+ static void i2c_slave_init (i2c_inst_t * i2c , uint16_t addr , bool addr_10bit ) {
145+ i2c -> hw -> enable = 0 ;
146+
147+ // Note: The I2C slave does clock stretching implicitly after a RD_REQ, while the Tx FIFO is empty.
148+ // Clock stretching while the Rx FIFO is full is also enabled by default.
149+ i2c -> hw -> con = I2C_IC_CON_STOP_DET_IFADDRESSED_BITS ;
150+ if (addr_10bit ) {
151+ i2c -> hw -> con |= I2C_IC_CON_IC_10BITADDR_SLAVE_BITS ;
152+ }
153+ i2c -> hw -> sar = addr ;
154+ i2c -> hw -> tx_tl = 1 ;
155+ i2c -> hw -> rx_tl = 0 ; // interrupt when at least 1 byte is available
156+
157+ // Enable interrupts.
158+ i2c -> hw -> intr_mask =
159+ I2C_IC_INTR_MASK_M_STOP_DET_BITS
160+ | I2C_IC_INTR_MASK_M_RX_DONE_BITS
161+ | I2C_IC_INTR_MASK_M_TX_ABRT_BITS
162+ | I2C_IC_INTR_MASK_M_RD_REQ_BITS
163+ | I2C_IC_INTR_MASK_M_RX_FULL_BITS
164+ ;
165+
166+ i2c -> hw -> enable = 1 ;
167+
168+ // Enable interrupt for current core.
169+ uint i2c_index = i2c_hw_index (i2c );
170+ uint num = I2C0_IRQ + i2c_index ;
171+ irq_set_exclusive_handler (num , i2c_slave_irq_handler );
172+ irq_set_enabled (num , true);
173+ }
174+
175+ static void i2c_slave_deinit (i2c_inst_t * i2c ) {
176+ uint i2c_index = i2c_hw_index (i2c );
177+ uint num = I2C0_IRQ + i2c_index ;
178+ irq_set_enabled (num , false);
179+ irq_remove_handler (num , i2c_slave_irq_handler );
180+
181+ i2c -> hw -> intr_mask = 0 ;
182+ i2c -> hw -> enable = 0 ;
183+ }
184+
123185/******************************************************************************/
124186// I2CTarget port implementation
125187
@@ -131,16 +193,29 @@ static void mp_machine_i2c_target_event_callback(machine_i2c_target_irq_obj_t *i
131193}
132194
133195static mp_int_t mp_machine_i2c_target_read_bytes (machine_i2c_target_obj_t * self , size_t len , uint8_t * buf ) {
134- i2c_hw_t * i2c_hw = i2c_get_hw (self -> i2c_inst );
196+ i2c_hw_t * i2c_hw = self -> i2c_inst -> hw ;
197+
198+ // Read from the RX FIFO.
135199 mp_int_t i = 0 ;
136- while (i < len && i2c_hw -> status & I2C_IC_STATUS_RFNE_BITS ) {
137- buf [i ++ ] = i2c_read_byte_raw ( self -> i2c_inst ) ;
200+ while (i < len && ( i2c_hw -> status & I2C_IC_STATUS_RFNE_BITS ) ) {
201+ buf [i ++ ] = i2c_hw -> data_cmd ;
138202 }
203+
204+ // Re-enable RX_FULL interrupt.
205+ i2c_hw -> intr_mask |= I2C_IC_INTR_MASK_M_RX_FULL_BITS ;
206+
139207 return i ;
140208}
141209
142210static mp_int_t mp_machine_i2c_target_write_bytes (machine_i2c_target_obj_t * self , size_t len , const uint8_t * buf ) {
143- i2c_write_byte_raw (self -> i2c_inst , buf [0 ]);
211+ i2c_hw_t * i2c_hw = self -> i2c_inst -> hw ;
212+
213+ // Write to the TX FIFO.
214+ i2c_hw -> data_cmd = buf [0 ];
215+
216+ // Re-enable RD_REQ interrupt.
217+ i2c_hw -> intr_mask |= I2C_IC_INTR_MASK_M_RD_REQ_BITS ;
218+
144219 return 1 ;
145220}
146221
@@ -179,6 +254,7 @@ static mp_obj_t mp_machine_i2c_target_make_new(const mp_obj_type_t *type, size_t
179254 machine_i2c_target_obj_t * self = & machine_i2c_target_obj [i2c_id ];
180255
181256 // Initialise data.
257+ self -> state = STATE_IDLE ;
182258 MP_STATE_PORT (i2c_target_mem_obj )[i2c_id ] = args [ARG_mem ].u_obj ;
183259 machine_i2c_target_data_t * data = & i2c_target_data [i2c_id ];
184260 machine_i2c_target_data_init (data , args [ARG_mem ].u_obj , args [ARG_mem_addrsize ].u_int );
@@ -201,7 +277,7 @@ static mp_obj_t mp_machine_i2c_target_make_new(const mp_obj_type_t *type, size_t
201277
202278 // Initialise the I2C target.
203279 // TODO: don't reinitialize if no arguments given.
204- i2c_slave_init (self -> i2c_inst , args [ARG_addr ].u_int , i2c_target_handler );
280+ i2c_slave_init (self -> i2c_inst , args [ARG_addr ].u_int , args [ ARG_addrsize ]. u_int == 10 );
205281 gpio_set_function (self -> scl , GPIO_FUNC_I2C );
206282 gpio_set_function (self -> sda , GPIO_FUNC_I2C );
207283 gpio_set_pulls (self -> scl , true, 0 );
0 commit comments