6565#define DEBUG_PRINTF (...)
6666#endif
6767
68- #define DEFAULT_TIMEOUT_US (1000) // timeout for waiting for address NACK
69- #define MAXIMUM_TIMEOUT_US (10000) // timeout for waiting for RX
68+ #define MAXIMUM_TIMEOUT_US (10000) // timeout for waiting for RX/TX
7069#define I2C_READ_BIT 0x01 // read bit
7170
71+ static uint32_t tick2us = 1 ;
72+
7273/* Keep track of what mode the peripheral is in. On NRF52, Driver mode can use TWIM. */
7374typedef enum {
7475 NORDIC_I2C_MODE_NONE ,
@@ -106,6 +107,9 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl)
106107 struct i2c_s * config = obj ;
107108#endif
108109
110+ const ticker_info_t * ti = lp_ticker_get_info ();
111+ tick2us = 1000000 / ti -> frequency ;
112+
109113 /* Get instance from pin configuration. */
110114 int instance = pin_instance_i2c (sda , scl );
111115 MBED_ASSERT (instance < NRFX_TWI_ENABLED_COUNT );
@@ -169,6 +173,21 @@ void i2c_frequency(i2c_t *obj, int hz)
169173 config -> update = true;
170174}
171175
176+ static uint32_t byte_timeout (nrf_twi_frequency_t frequency )
177+ {
178+ uint32_t timeout = 0 ;
179+ // set timeout in [us] as: 10 [bits] * 1000000 / frequency
180+ if (frequency == NRF_TWI_FREQ_100K ) {
181+ timeout = 100 ; // 10 * 10us
182+ } else if (frequency == NRF_TWI_FREQ_250K ) {
183+ timeout = 40 ; // 10 * 4us
184+ } else if (frequency == NRF_TWI_FREQ_400K ) {
185+ timeout = 25 ; // 10 * 2.5us
186+ }
187+
188+ return timeout ;
189+ }
190+
172191const PinMap * i2c_master_sda_pinmap ()
173192{
174193 return PinMap_I2C_testing ;
@@ -354,69 +373,71 @@ int i2c_byte_write(i2c_t *obj, int data)
354373 struct i2c_s * config = obj ;
355374#endif
356375
357- int instance = config -> instance ;
376+ NRF_TWI_Type * p_twi = nordic_nrf5_twi_register [ config -> instance ] ;
358377 int result = 1 ; // default to ACK
378+ uint32_t start_us , now_us , timeout ;
359379
360- /* Check if this is the first byte to be transferred. If it is, then send start signal and address. */
361380 if (config -> state == NORDIC_TWI_STATE_START ) {
362381 config -> state = NORDIC_TWI_STATE_BUSY ;
363382
364- /* Beginning of new transaction, configure peripheral if necessary. */
383+ config -> update = true;
365384 i2c_configure_twi_instance (obj );
366385
367- /* Set I2C device address. NOTE: due to hardware limitations only 7-bit addresses are supported. */
368- nrf_twi_address_set (nordic_nrf5_twi_register [instance ], data >> 1 );
369-
370- /* If read bit is set, trigger read task otherwise trigger write task. */
371386 if (data & I2C_READ_BIT ) {
372- /* For timing reasons, reading bytes requires shorts to suspend peripheral after each byte. */
373- nrf_twi_shorts_set (nordic_nrf5_twi_register [instance ], NRF_TWI_SHORT_BB_SUSPEND_MASK );
374- nrf_twi_task_trigger (nordic_nrf5_twi_register [instance ], NRF_TWI_TASK_STARTRX );
387+ nrf_twi_event_clear (p_twi , NRF_TWI_EVENT_STOPPED );
388+ nrf_twi_event_clear (p_twi , NRF_TWI_EVENT_RXDREADY );
389+ nrf_twi_event_clear (p_twi , NRF_TWI_EVENT_ERROR );
390+ (void )nrf_twi_errorsrc_get_and_clear (p_twi );
391+
392+ nrf_twi_shorts_set (p_twi , NRF_TWI_SHORT_BB_SUSPEND_MASK );
393+
394+ nrf_twi_address_set (p_twi , data >> 1 );
395+ nrf_twi_task_trigger (p_twi , NRF_TWI_TASK_RESUME );
396+ nrf_twi_task_trigger (p_twi , NRF_TWI_TASK_STARTRX );
375397 } else {
376- /* Reset shorts register. */
377- nrf_twi_shorts_set (nordic_nrf5_twi_register [instance ], 0 );
378- nrf_twi_task_trigger (nordic_nrf5_twi_register [instance ], NRF_TWI_TASK_STARTTX );
379- }
398+ nrf_twi_event_clear (p_twi , NRF_TWI_EVENT_STOPPED );
399+ nrf_twi_event_clear (p_twi , NRF_TWI_EVENT_TXDSENT );
400+ nrf_twi_event_clear (p_twi , NRF_TWI_EVENT_ERROR );
401+ nrf_twi_event_clear (p_twi , NRF_TWI_EVENT_BB );
402+ (void )nrf_twi_errorsrc_get_and_clear (p_twi );
380403
381- /* Setup stop watch for timeout. */
382- uint32_t start_us = lp_ticker_read ();
383- uint32_t now_us = start_us ;
404+ nrf_twi_shorts_set (p_twi , 0 );
384405
385- /* Block until timeout or an address error has been detected. */
386- while (((now_us - start_us ) < DEFAULT_TIMEOUT_US ) &&
387- !(nrf_twi_event_check (nordic_nrf5_twi_register [instance ], NRF_TWI_EVENT_ERROR ))) {
388- now_us = lp_ticker_read ();
406+ nrf_twi_address_set (p_twi , data >> 1 );
407+ nrf_twi_task_trigger (p_twi , NRF_TWI_TASK_RESUME );
408+ nrf_twi_task_trigger (p_twi , NRF_TWI_TASK_STARTTX );
389409 }
410+ /* Wait two byte duration for address ACK */
411+ timeout = 2 * byte_timeout (config -> frequency );
412+ } else {
413+ nrf_twi_event_clear (p_twi , NRF_TWI_EVENT_TXDSENT );
414+ nrf_twi_event_clear (p_twi , NRF_TWI_EVENT_ERROR );
415+ nrf_twi_event_clear (p_twi , NRF_TWI_EVENT_BB );
416+ (void )nrf_twi_errorsrc_get_and_clear (p_twi );
417+
418+ nrf_twi_task_trigger (p_twi , NRF_TWI_TASK_RESUME );
419+ nrf_twi_txd_set (p_twi , data );
420+ /* Wait ten byte duration for data ACK */
421+ timeout = 10 * byte_timeout (config -> frequency );
422+ }
390423
391- /* Check error register and update return value if an address NACK was detected. */
392- uint32_t error = nrf_twi_errorsrc_get_and_clear ( nordic_nrf5_twi_register [ instance ]) ;
424+ start_us = tick2us * lp_ticker_read ();
425+ now_us = start_us ;
393426
394- if (error & NRF_TWI_ERROR_ADDRESS_NACK ) {
395- result = 0 ; // set NACK
396- } else {
397- /* Normal write. Send next byte after clearing event flag. */
398- nrf_twi_event_clear (nordic_nrf5_twi_register [instance ], NRF_TWI_EVENT_TXDSENT );
399- nrf_twi_txd_set (nordic_nrf5_twi_register [instance ], data );
400-
401- /* Setup stop watch for timeout. */
402- uint32_t start_us = lp_ticker_read ();
403- uint32_t now_us = start_us ;
404-
405- /* Block until timeout or the byte has been sent. */
406- while (((now_us - start_us ) < MAXIMUM_TIMEOUT_US ) &&
407- !(nrf_twi_event_check (nordic_nrf5_twi_register [instance ], NRF_TWI_EVENT_TXDSENT ))) {
408- now_us = lp_ticker_read ();
409- }
410-
411- /* Check the error code to see if the byte was acknowledged. */
412- uint32_t error = nrf_twi_errorsrc_get_and_clear (nordic_nrf5_twi_register [instance ]);
413-
414- if (error & NRF_TWI_ERROR_DATA_NACK ) {
415- result = 0 ; // set NACK
416- } else if (now_us - start_us >= MAXIMUM_TIMEOUT_US ) {
417- result = 2 ; // set timeout
418- }
419- }
427+ /* Block until timeout or an address/data error has been detected. */
428+ while (((now_us - start_us ) < timeout ) &&
429+ !nrf_twi_event_check (p_twi , NRF_TWI_EVENT_TXDSENT ) &&
430+ !nrf_twi_event_check (p_twi , NRF_TWI_EVENT_ERROR )) {
431+ now_us = tick2us * lp_ticker_read ();
432+ }
433+
434+ /* Check error register and update return value if an address/data NACK was detected. */
435+ uint32_t error = nrf_twi_errorsrc_get_and_clear (p_twi );
436+
437+ if ((error & NRF_TWI_ERROR_ADDRESS_NACK ) || (error & NRF_TWI_ERROR_DATA_NACK )) {
438+ result = 0 ; // NACK
439+ } else if (now_us - start_us >= timeout ) {
440+ result = 2 ; // timeout
420441 }
421442
422443 return result ;
@@ -441,9 +462,6 @@ int i2c_byte_read(i2c_t *obj, int last)
441462 int instance = config -> instance ;
442463 int retval = I2C_ERROR_NO_SLAVE ;
443464
444- uint32_t start_us = 0 ;
445- uint32_t now_us = 0 ;
446-
447465 /* Due to hardware limitations, the stop condition must triggered through a short before
448466 * reading the last byte.
449467 */
@@ -465,18 +483,20 @@ int i2c_byte_read(i2c_t *obj, int last)
465483 /* No data available, resume reception. */
466484 nrf_twi_task_trigger (nordic_nrf5_twi_register [instance ], NRF_TWI_TASK_RESUME );
467485
486+ /* Wait ten byte duration for data */
487+ uint32_t timeout = 10 * byte_timeout (config -> frequency );
468488 /* Setup timeout */
469- start_us = lp_ticker_read ();
470- now_us = start_us ;
489+ uint32_t start_us = tick2us * lp_ticker_read ();
490+ uint32_t now_us = start_us ;
471491
472492 /* Block until timeout or data ready event has been signaled. */
473- while (((now_us - start_us ) < MAXIMUM_TIMEOUT_US ) &&
493+ while (((now_us - start_us ) < timeout ) &&
474494 !(nrf_twi_event_check (nordic_nrf5_twi_register [instance ], NRF_TWI_EVENT_RXDREADY ))) {
475- now_us = lp_ticker_read ();
495+ now_us = tick2us * lp_ticker_read ();
476496 }
477497
478498 /* Retrieve data from buffer. */
479- if ((now_us - start_us ) < MAXIMUM_TIMEOUT_US ) {
499+ if ((now_us - start_us ) < timeout ) {
480500 retval = nrf_twi_rxd_get (nordic_nrf5_twi_register [instance ]);
481501 nrf_twi_event_clear (nordic_nrf5_twi_register [instance ], NRF_TWI_EVENT_RXDREADY );
482502 }
@@ -506,12 +526,12 @@ int i2c_stop(i2c_t *obj)
506526 nrf_twi_task_trigger (nordic_nrf5_twi_register [instance ], NRF_TWI_TASK_STOP );
507527
508528 /* Block until stop signal has been generated. */
509- uint32_t start_us = lp_ticker_read ();
529+ uint32_t start_us = tick2us * lp_ticker_read ();
510530 uint32_t now_us = start_us ;
511531
512532 while (((now_us - start_us ) < MAXIMUM_TIMEOUT_US ) &&
513533 !(nrf_twi_event_check (nordic_nrf5_twi_register [instance ], NRF_TWI_EVENT_STOPPED ))) {
514- now_us = lp_ticker_read ();
534+ now_us = tick2us * lp_ticker_read ();
515535 }
516536
517537 /* Reset state. */
0 commit comments