@@ -162,20 +162,22 @@ static mp_obj_t write_then_read(size_t n_args, const mp_obj_t *pos_args, mp_map_
162162
163163 // Pre-allocate the return value so we have something to write the result to.
164164 size_t len = pb_obj_get_positive_int (read_length_in );
165+ mp_obj_str_t * read_result ;
165166 if (len ) {
166- self -> read_result = mp_obj_new_bytes (NULL , len );
167- self -> read_result -> hash = 0 ;
168- self -> read_result -> data = m_new (byte , self -> read_result -> len );
167+ read_result = mp_obj_new_bytes (NULL , len );
168+ read_result -> hash = 0 ;
169+ read_result -> data = m_new (byte , read_result -> len );
169170 } else {
170- self -> read_result = (mp_obj_str_t * )& mp_const_empty_bytes_obj ;
171+ read_result = (mp_obj_str_t * )& mp_const_empty_bytes_obj ;
171172 }
172173
173174 // Kick off the operation. This will immediately raise if a transaction is
174175 // in progress.
176+ pbio_os_state_t state = 0 ;
175177 pbio_error_t err = pbdrv_i2c_write_then_read (
176- & self -> state , self -> i2c_dev , self -> address ,
178+ & state , self -> i2c_dev , self -> address ,
177179 write_data , self -> write_len ,
178- (uint8_t * )self -> read_result -> data , self -> read_result -> len , self -> nxt_quirk );
180+ (uint8_t * )read_result -> data , read_result -> len , self -> nxt_quirk );
179181
180182 // Expect yield after the initial call.
181183 if (err == PBIO_SUCCESS ) {
@@ -184,6 +186,13 @@ static mp_obj_t write_then_read(size_t n_args, const mp_obj_t *pos_args, mp_map_
184186 pb_assert (err );
185187 }
186188
189+ // The initial operation above can fail if an I2C transaction is already in
190+ // progress. If so, we don't want to reset it state or allow the return
191+ // result to be garbage collected. Now that the first iteration succeeded,
192+ // save the state and assign the new result buffer.
193+ self -> state = state ;
194+ self -> read_result = read_result ;
195+
187196 // If runloop active, return an awaitable object.
188197 if (pb_module_tools_run_loop_is_active ()) {
189198 operation_obj_t * operation = mp_obj_malloc (operation_obj_t , & operation_type );
0 commit comments