4343// Rounded up to a nice power of 2 and multiple of cache lines
4444#define PRU_I2C_MAX_BYTES_PER_TXN 512
4545
46+ // Number of times we try the operation before NAK is raised as an IO error.
47+ #define PRU_I2C_MAX_NUM_TRIES_ON_NAK (2)
48+
4649static uint8_t pbdrv_i2c_buffers [PBDRV_RPROC_EV3_PRU1_NUM_I2C_BUSES ][PRU_I2C_MAX_BYTES_PER_TXN ] PBDRV_DMA_BUF ;
4750
4851struct _pbdrv_i2c_dev_t {
@@ -51,6 +54,7 @@ struct _pbdrv_i2c_dev_t {
5154 bool is_initialized ;
5255 uint8_t pru_i2c_idx ;
5356 pbio_os_timer_t timer ;
57+ size_t try_count ;
5458};
5559
5660static pbdrv_i2c_dev_t i2c_devs [PBDRV_RPROC_EV3_PRU1_NUM_I2C_BUSES ];
@@ -131,53 +135,58 @@ pbio_error_t pbdrv_i2c_write_then_read(
131135 memcpy (i2c_dev -> buffer , wdata , wlen );
132136 }
133137
134- if (nxt_quirk ) {
135- // NXT sensors affected by the quirk can't be accessed too quickly.
136- // This ensures a minimum delay without slowing down code that polls
137- // less frequently.
138- PBIO_OS_AWAIT_UNTIL (state , pbio_os_timer_is_expired (& i2c_dev -> timer ));
139- pbio_os_timer_set (& i2c_dev -> timer , 100 );
140- }
141-
142- i2c_dev -> is_busy = true;
143- pbdrv_cache_prepare_before_dma (i2c_dev -> buffer , PRU_I2C_MAX_BYTES_PER_TXN );
144-
145- // Kick off transfer
146- pbdrv_rproc_ev3_pru1_shared_ram .i2c [i2c_dev -> pru_i2c_idx ].flags = PBDRV_RPROC_EV3_PRU1_I2C_PACK_FLAGS (
147- dev_addr ,
148- rlen ,
149- wlen ,
150- PBDRV_RPROC_EV3_PRU1_I2C_CMD_START | (nxt_quirk ? PBDRV_RPROC_EV3_PRU1_I2C_CMD_NXT_QUIRK : 0 )
151- );
152-
153- // Wait for transfer to finish
154- PBIO_OS_AWAIT_WHILE (state , i2c_dev -> is_busy );
155-
156- uint32_t flags = pbdrv_rproc_ev3_pru1_shared_ram .i2c [i2c_dev -> pru_i2c_idx ].flags ;
157- debug_pr ("i2c %d done flags %08x\r\n" , i2c_dev -> pru_i2c_idx , flags );
158- if (!(flags & PBDRV_RPROC_EV3_PRU1_I2C_STAT_DONE )) {
159- debug_pr ("i2c %d not actually done???\r\n" , i2c_dev -> pru_i2c_idx );
160- return PBIO_ERROR_FAILED ;
161- }
162- switch (flags & PBDRV_RPROC_EV3_PRU1_I2C_STAT_MASK ) {
163- case PBDRV_RPROC_EV3_PRU1_I2C_STAT_OK :
164- break ;
165- case PBDRV_RPROC_EV3_PRU1_I2C_STAT_TIMEOUT :
138+ for (i2c_dev -> try_count = 0 ; i2c_dev -> try_count < PRU_I2C_MAX_NUM_TRIES_ON_NAK ; i2c_dev -> try_count ++ ) {
139+
140+ if (nxt_quirk ) {
141+ // NXT sensors affected by the quirk can't be accessed too quickly.
142+ // The timer is set after awaiting so we don't unnecessarily slow
143+ // down code that polls less frequently.
144+ PBIO_OS_AWAIT_UNTIL (state , pbio_os_timer_is_expired (& i2c_dev -> timer ));
145+ pbio_os_timer_set (& i2c_dev -> timer , 100 );
146+ }
147+
148+ i2c_dev -> is_busy = true;
149+ pbdrv_cache_prepare_before_dma (i2c_dev -> buffer , PRU_I2C_MAX_BYTES_PER_TXN );
150+
151+ // Kick off transfer
152+ pbdrv_rproc_ev3_pru1_shared_ram .i2c [i2c_dev -> pru_i2c_idx ].flags = PBDRV_RPROC_EV3_PRU1_I2C_PACK_FLAGS (
153+ dev_addr ,
154+ rlen ,
155+ wlen ,
156+ PBDRV_RPROC_EV3_PRU1_I2C_CMD_START | (nxt_quirk ? PBDRV_RPROC_EV3_PRU1_I2C_CMD_NXT_QUIRK : 0 )
157+ );
158+
159+ // Wait for transfer to finish
160+ PBIO_OS_AWAIT_WHILE (state , i2c_dev -> is_busy );
161+
162+ uint32_t flags = pbdrv_rproc_ev3_pru1_shared_ram .i2c [i2c_dev -> pru_i2c_idx ].flags ;
163+ debug_pr ("i2c %d done flags %08x\r\n" , i2c_dev -> pru_i2c_idx , flags );
164+ if (!(flags & PBDRV_RPROC_EV3_PRU1_I2C_STAT_DONE )) {
165+ debug_pr ("i2c %d not actually done\r\n" , i2c_dev -> pru_i2c_idx );
166+ return PBIO_ERROR_FAILED ;
167+ }
168+
169+ flags &= PBDRV_RPROC_EV3_PRU1_I2C_STAT_MASK ;
170+
171+ if (flags == PBDRV_RPROC_EV3_PRU1_I2C_STAT_OK ) {
172+ // Success, exit loop.
173+ pbdrv_cache_prepare_after_dma (i2c_dev -> buffer , PRU_I2C_MAX_BYTES_PER_TXN );
174+ if (rlen ) {
175+ * rdata = & i2c_dev -> buffer [wlen ];
176+ }
177+ return PBIO_SUCCESS ;
178+ } else if (flags == PBDRV_RPROC_EV3_PRU1_I2C_STAT_TIMEOUT ) {
166179 return PBIO_ERROR_TIMEDOUT ;
167- case PBDRV_RPROC_EV3_PRU1_I2C_STAT_NAK :
168- return PBIO_ERROR_IO ;
169- default :
170- debug_pr ("i2c %d unknown error occurred??? \r\n" , i2c_dev -> pru_i2c_idx );
180+ } else if ( flags != PBDRV_RPROC_EV3_PRU1_I2C_STAT_NAK ) {
181+ // Many known NXT devices occasionally get NAK. Retrying usually
182+ // helps. Everything else is unexpected and raised immediately.
183+ debug_pr ("i2c %d unknown error occurred\r\n" , i2c_dev -> pru_i2c_idx );
171184 return PBIO_ERROR_FAILED ;
185+ }
172186 }
173187
174- // If we got here, there's no error. Tell caller where to read RX data.
175- pbdrv_cache_prepare_after_dma (i2c_dev -> buffer , PRU_I2C_MAX_BYTES_PER_TXN );
176- if (rlen ) {
177- * rdata = & i2c_dev -> buffer [wlen ];
178- }
179-
180- PBIO_OS_ASYNC_END (PBIO_SUCCESS );
188+ // Didn't succeed even after trying allowed number of times.
189+ PBIO_OS_ASYNC_END (PBIO_ERROR_IO );
181190}
182191
183192static pbio_os_process_t ev3_i2c_init_process ;
0 commit comments