Skip to content

Commit 627e6de

Browse files
NRF52: fix i2c byte read/write implementation
1 parent 7d5f6cf commit 627e6de

File tree

1 file changed

+110
-55
lines changed
  • targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52

1 file changed

+110
-55
lines changed

targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/i2c_api.c

Lines changed: 110 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,106 @@ int i2c_start(i2c_t *obj)
343343
return 0;
344344
}
345345

346+
static uint8_t twi_byte_write(NRF_TWI_Type *twi, uint8_t data)
347+
{
348+
uint32_t t0;
349+
nrf_twi_event_clear(twi, NRF_TWI_EVENT_TXDSENT);
350+
nrf_twi_event_clear(twi, NRF_TWI_EVENT_ERROR);
351+
nrf_twi_event_clear(twi, NRF_TWI_EVENT_BB);
352+
(void)nrf_twi_errorsrc_get_and_clear(twi);
353+
354+
nrf_twi_txd_set(twi, data);
355+
356+
uint32_t start_us = tick2us * lp_ticker_read();
357+
uint8_t ret = 2;
358+
359+
do {
360+
if (nrf_twi_event_check(twi, NRF_TWI_EVENT_TXDSENT)) {
361+
nrf_twi_event_clear(twi, NRF_TWI_EVENT_TXDSENT);
362+
ret = 1; // ACK received
363+
break;
364+
}
365+
if (nrf_twi_event_check(twi, NRF_TWI_EVENT_ERROR)) {
366+
nrf_twi_event_clear(twi, NRF_TWI_EVENT_ERROR);
367+
ret = 0; // some error occurred
368+
break;
369+
}
370+
} while (((tick2us * (uint32_t)lp_ticker_read()) - start_us) < MAXIMUM_TIMEOUT_US);
371+
372+
return ret; // timeout;
373+
}
374+
375+
static int twi_start_write(NRF_TWI_Type *twi, int address)
376+
{
377+
nrf_twi_event_clear(twi, NRF_TWI_EVENT_STOPPED);
378+
nrf_twi_event_clear(twi, NRF_TWI_EVENT_TXDSENT);
379+
nrf_twi_event_clear(twi, NRF_TWI_EVENT_ERROR);
380+
nrf_twi_event_clear(twi, NRF_TWI_EVENT_BB);
381+
(void)nrf_twi_errorsrc_get_and_clear(twi);
382+
383+
nrf_twi_shorts_set(twi, 0);
384+
385+
nrf_twi_address_set(twi, address >> 1);
386+
nrf_twi_task_trigger(twi, NRF_TWI_TASK_RESUME);
387+
nrf_twi_task_trigger(twi, NRF_TWI_TASK_STARTTX);
388+
389+
/* Setup stop watch for timeout. */
390+
uint32_t start_us = tick2us * lp_ticker_read();
391+
uint32_t now_us = start_us;
392+
393+
/* Block until timeout or an address error has been detected. */
394+
while (((now_us - start_us) < 150) &&
395+
!(nrf_twi_event_check(twi, NRF_TWI_EVENT_TXDSENT))) {
396+
now_us = tick2us * lp_ticker_read();
397+
}
398+
399+
/* Check error register and update return value if an address NACK was detected. */
400+
uint32_t error = nrf_twi_errorsrc_get_and_clear(twi);
401+
402+
if (error & NRF_TWI_ERROR_ADDRESS_NACK) {
403+
return 0; // set NACK
404+
} else if (now_us - start_us >= DEFAULT_TIMEOUT_US) {
405+
return 2; // set timeout
406+
}
407+
408+
return 1; // ACK
409+
}
410+
411+
static int twi_start_read(NRF_TWI_Type *twi, int address)
412+
{
413+
nrf_twi_event_clear(twi, NRF_TWI_EVENT_STOPPED);
414+
nrf_twi_event_clear(twi, NRF_TWI_EVENT_RXDREADY);
415+
nrf_twi_event_clear(twi, NRF_TWI_EVENT_ERROR);
416+
(void)nrf_twi_errorsrc_get_and_clear(twi);
417+
418+
nrf_twi_shorts_set(twi, NRF_TWI_SHORT_BB_SUSPEND_MASK);
419+
420+
nrf_twi_address_set(twi, address >> 1);
421+
nrf_twi_task_trigger(twi, NRF_TWI_TASK_RESUME);
422+
nrf_twi_task_trigger(twi, NRF_TWI_TASK_STARTRX);
423+
424+
/* Setup stop watch for timeout. */
425+
uint32_t start_us = tick2us * lp_ticker_read();
426+
uint32_t now_us = start_us;
427+
428+
/* Block until timeout or an address error has been detected. */
429+
while (((now_us - start_us) < 150) &&
430+
!(nrf_twi_event_check(twi, NRF_TWI_EVENT_TXDSENT))) {
431+
now_us = tick2us * lp_ticker_read();
432+
}
433+
434+
/* Check error register and update return value if an address NACK was detected. */
435+
uint32_t error = nrf_twi_errorsrc_get_and_clear(twi);
436+
437+
if (error & NRF_TWI_ERROR_ADDRESS_NACK) {
438+
return 0; // set NACK
439+
} else if (now_us - start_us >= DEFAULT_TIMEOUT_US) {
440+
return 2; // set timeout
441+
}
442+
443+
return 1; // ACK
444+
}
445+
346446
/** Write one byte
347447
*
348448
* @param obj The I2C object
@@ -359,72 +459,27 @@ int i2c_byte_write(i2c_t *obj, int data)
359459
struct i2c_s *config = obj;
360460
#endif
361461

362-
int instance = config->instance;
462+
NRF_TWI_Type *p_twi = nordic_nrf5_twi_register[config->instance];
363463
int result = 1; // default to ACK
364464

365-
/* Check if this is the first byte to be transferred. If it is, then send start signal and address. */
366465
if (config->state == NORDIC_TWI_STATE_START) {
367466
config->state = NORDIC_TWI_STATE_BUSY;
368467

369-
/* Beginning of new transaction, configure peripheral if necessary. */
468+
config->update = true;
370469
i2c_configure_twi_instance(obj);
371470

372-
/* Set I2C device address. NOTE: due to hardware limitations only 7-bit addresses are supported. */
373-
nrf_twi_address_set(nordic_nrf5_twi_register[instance], data >> 1);
374-
375-
/* If read bit is set, trigger read task otherwise trigger write task. */
376471
if (data & I2C_READ_BIT) {
377-
/* For timing reasons, reading bytes requires shorts to suspend peripheral after each byte. */
378-
nrf_twi_shorts_set(nordic_nrf5_twi_register[instance], NRF_TWI_SHORT_BB_SUSPEND_MASK);
379-
nrf_twi_task_trigger(nordic_nrf5_twi_register[instance], NRF_TWI_TASK_STARTRX);
380-
} else {
381-
/* Reset shorts register. */
382-
nrf_twi_shorts_set(nordic_nrf5_twi_register[instance], 0);
383-
nrf_twi_task_trigger(nordic_nrf5_twi_register[instance], NRF_TWI_TASK_STARTTX);
384-
}
385-
386-
/* Setup stop watch for timeout. */
387-
uint32_t start_us = tick2us * lp_ticker_read();
388-
uint32_t now_us = start_us;
389-
390-
/* Block until timeout or an address error has been detected. */
391-
while (((now_us - start_us) < DEFAULT_TIMEOUT_US) &&
392-
!(nrf_twi_event_check(nordic_nrf5_twi_register[instance], NRF_TWI_EVENT_ERROR))) {
393-
now_us = tick2us * lp_ticker_read();
394-
}
395-
396-
/* Check error register and update return value if an address NACK was detected. */
397-
uint32_t error = nrf_twi_errorsrc_get_and_clear(nordic_nrf5_twi_register[instance]);
398-
399-
if (error & NRF_TWI_ERROR_ADDRESS_NACK) {
400-
result = 0; // set NACK
472+
return twi_start_read(p_twi, data);
401473
} else {
402-
/* Normal write. Send next byte after clearing event flag. */
403-
nrf_twi_event_clear(nordic_nrf5_twi_register[instance], NRF_TWI_EVENT_TXDSENT);
404-
nrf_twi_txd_set(nordic_nrf5_twi_register[instance], data);
405-
406-
/* Setup stop watch for timeout. */
407-
uint32_t start_us = tick2us * lp_ticker_read();
408-
uint32_t now_us = start_us;
409-
410-
/* Block until timeout or the byte has been sent. */
411-
while (((now_us - start_us) < MAXIMUM_TIMEOUT_US) &&
412-
!(nrf_twi_event_check(nordic_nrf5_twi_register[instance], NRF_TWI_EVENT_TXDSENT))) {
413-
now_us = tick2us * lp_ticker_read();
414-
}
415-
416-
/* Check the error code to see if the byte was acknowledged. */
417-
uint32_t error = nrf_twi_errorsrc_get_and_clear(nordic_nrf5_twi_register[instance]);
418-
419-
if (error & NRF_TWI_ERROR_DATA_NACK) {
420-
result = 0; // set NACK
421-
} else if (now_us - start_us >= MAXIMUM_TIMEOUT_US) {
422-
result = 2; // set timeout
423-
}
474+
return twi_start_write(p_twi, data);
424475
}
476+
} else {
477+
nrf_twi_task_trigger(p_twi, NRF_TWI_TASK_RESUME);
478+
// 0 - TWI signaled error (NAK is the only possibility here)
479+
// 1 - ACK received
480+
// 2 - timeout (clock stretched for too long?)
481+
return twi_byte_write(p_twi, (uint8_t)data);
425482
}
426-
427-
return result;
428483
}
429484

430485
/** Read one byte

0 commit comments

Comments
 (0)