This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

twi busy error 17

Hello guys, i randomly get twi error busy 17.

i have #define TWI_DEFAULT_CONFIG_IRQ_PRIORITY 7 in sdk_config.h and .interrupt_priority = APP_IRQ_PRIORITY_LOW in init function.

This is my code:

void twi_init(void)
{
  if(twi_init_status) return;
  ret_code_t err_code;

  const nrf_drv_twi_config_t twi_mma_7660_config = {
    .scl                = SCL,
    .sda                = SDA,
    .frequency          = NRF_TWI_FREQ_100K,
    .interrupt_priority = APP_IRQ_PRIORITY_LOW
  };

  err_code = nrf_drv_twi_init(&twi_instance, &twi_mma_7660_config, twi_handler, NULL);
  APP_ERROR_CHECK(err_code);

  nrf_drv_twi_enable(&twi_instance);
  nrf_delay_ms(200);
  twi_init_status = true;
}

void twi_handler(nrf_drv_twi_evt_t const * p_event, void * p_context)
{
  switch(p_event->type)
  {
    case NRF_DRV_TWI_EVT_DONE:
      m_xfer_done = true;
      break;
    default:
      break;
  }
}

and this are my read and write functions:

void twi_write(uint8_t dev_addres, uint8_t reg_addres, uint8_t data[], uint8_t length)
{
  uint8_t buffer[length];
  buffer[0] = reg_addres;
  for(int i = 0; i < length; i++) buffer[i+1] = data[i];

  m_xfer_done = false;
  ret_code_t err_code = nrf_drv_twi_tx(&twi_instance, dev_addres, buffer, sizeof(buffer) + 1, false);
  APP_ERROR_CHECK(err_code);
  while (!m_xfer_done);
}

void twi_write_no_register(uint8_t dev_addres, uint8_t data[], uint8_t length)
{
  m_xfer_done = false;
  ret_code_t err_code = nrf_drv_twi_tx(&twi_instance, dev_addres, data, length, false);
  APP_ERROR_CHECK(err_code);
  while (!m_xfer_done);
}

void twi_read(uint8_t dev_addres, uint8_t reg_addres, uint8_t *data_pointer, uint8_t length)
{
  ret_code_t err_code;
  uint8_t buffer[length];
  buffer[0] = reg_addres;

  m_xfer_done = false;
  err_code = nrf_drv_twi_tx(&twi_instance, dev_addres, buffer, 1, false); // sends ADDR+W, dev_addres, reg_addres
  APP_ERROR_CHECK(err_code);
  while (!m_xfer_done);

  m_xfer_done = false;
  err_code = nrf_drv_twi_rx(&twi_instance, dev_addres, buffer, length); // reads from reg_addres #(length) of bytes
  APP_ERROR_CHECK(err_code);
  while (!m_xfer_done);

  for(int i=0;i<length;i++)
  {
    *data_pointer=buffer[i];
    data_pointer++;
  }
}

I was reading posts about this problem but coudn't find a solution. I tried to put delays after twi functions but it didn't resolve the issue. Is this something i should handle in my code (if yes how would be helpfull)? I have also tried blocking mode and the error is the same. Sometimes it works for hours and sometime error occures right away.

Thanks.

  • I am also experiencing the same problem. TWI randomly hangs with m_xfer_done = false.

    It hangs in hardware initialization phase, before BLE and any timers are started (BUT GPIOTE INTERRUPTS WERE ENABLED, HERE WAS THE PROBLEM). So there shouldn't be any double access to TWI. Twi (I2C) is used to communicate with MMA8453 accelerometer. At initialization phase it writes some accelerometer configuration bytes at different addresses. Example:

    res = MMA8453_writeByte(hndl->addr, MMA8453_CTRL_REG5, 0b00010000); //Step 6: Route the Transient Interrupt to INT 2 hardware pin (CTRL_REG5)
    CHECK_RES();
    

    And hangs at about writing 9'th or 10'th register.

  • Program is found hanging at

    while (m_xfer_done == false);
    

    "m_xfer_done" should be set to TRUE at "twi_handler(nrf_drv_twi_evt_t const * p_event)" I have tried to clear it at "p_event->type = NRF_DRV_TWI_EVT_DONE" as suggested in example. And also at start of handler, without checking event type. Had the same result. So it looks like that twi_handler is not called in every possible situation. My write function:

        MMA_res MMA8453_writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data){
    ret_code_t res;
    //Size of twi_tx_buff must be 2 or higher. It should be checked in header file and not there to increase speed
    twi_tx_buff[0] = regAddr;
    twi_tx_buff[1] = data;
    m_xfer_done = false;
    do
    {
        res = nrf_drv_twi_tx(&m_twi, devAddr, twi_tx_buff, 2, false);
    }
    while (res == NRF_ERROR_BUSY);
    while (m_xfer_done == false);
    return res;
    

    }

  • In my case problem was that another communication was initiated from GPIOTE interrupt... So better TWI access solution should be used, or just have to switch to TWI_manager instead of using direct drivers.

Related