Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

TWI I2C problem with implementation.

Hello,

I have a problem through which unfortunately I'm not able to come across alone. I'm using nRF52832 with softdevice and UART central example from SDK14.2 (..\examples\ble_central\ble_app_uart_c\pca10040\s132\arm5_no_packs). Right now I'm trying to communicate my nordic device with LED display which is using ssd1306 libraries. Problem occures at the moment when I'm trying to use nrf_drv_twi_tx() function to transmit datas over TWI.

Of course I've set all necessary items in sdk_config file as below:

// <e> TWI_ENABLED - nrf_drv_twi - TWI/TWIM peripheral driver
//==========================================================
#ifndef TWI_ENABLED
#define TWI_ENABLED 1
#endif
// <o> TWI_DEFAULT_CONFIG_FREQUENCY  - Frequency
 
// <26738688=> 100k 
// <67108864=> 250k 
// <104857600=> 400k 

#ifndef TWI_DEFAULT_CONFIG_FREQUENCY
#define TWI_DEFAULT_CONFIG_FREQUENCY 26738688
#endif

// <q> TWI_DEFAULT_CONFIG_CLR_BUS_INIT  - Enables bus clearing procedure during init
 

#ifndef TWI_DEFAULT_CONFIG_CLR_BUS_INIT
#define TWI_DEFAULT_CONFIG_CLR_BUS_INIT 0
#endif

// <q> TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT  - Enables bus holding after uninit
 

#ifndef TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT
#define TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT 0
#endif

// <o> TWI_DEFAULT_CONFIG_IRQ_PRIORITY  - Interrupt priority
 

// <i> Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice
// <0=> 0 (highest) 
// <1=> 1 
// <2=> 2 
// <3=> 3 
// <4=> 4 
// <5=> 5 
// <6=> 6 
// <7=> 7 

#ifndef TWI_DEFAULT_CONFIG_IRQ_PRIORITY
#define TWI_DEFAULT_CONFIG_IRQ_PRIORITY 7
#endif

// <e> TWI0_ENABLED - Enable TWI0 instance
//==========================================================
#ifndef TWI0_ENABLED
#define TWI0_ENABLED 1
#endif
// <q> TWI0_USE_EASY_DMA  - Use EasyDMA (if present)
 

#ifndef TWI0_USE_EASY_DMA
#define TWI0_USE_EASY_DMA 1
#endif

// </e>

// <e> TWI1_ENABLED - Enable TWI1 instance
//==========================================================
#ifndef TWI1_ENABLED
#define TWI1_ENABLED 1
#endif
// <q> TWI1_USE_EASY_DMA  - Use EasyDMA (if present)
 

#ifndef TWI1_USE_EASY_DMA
#define TWI1_USE_EASY_DMA 1
#endif

Below I've paste  my twi init code:

#define SSD1306_CONFIG_SCL_PIN  ARDUINO_SCL_PIN     //from pca10040.h  27 SCL signal pin
#define SSD1306_CONFIG_SDA_PIN  ARDUINO_SDA_PIN     //from pca10040.h  26 SDA signal pin

...

void ssd1306init() {
	ssd1306_init_i2c(SSD1306_CONFIG_SCL_PIN, SSD1306_CONFIG_SDA_PIN);
	ssd1306_begin(SSD1306_EXTERNALVCC, SSD1306_I2C_ADDRESS, false);
}

Than in ssd1306_init_i2c() function:

void ssd1306_init_i2c(uint32_t scl, uint32_t sda)
{
    _i2caddr = SSD1306_I2C_ADDRESS;
    use_i2c = true;
    twi_master_init(scl, sda);
}

void twi_master_init(uint32_t scl, uint32_t sda)
{
    ret_code_t ret;
    const nrf_drv_twi_config_t config = {
        .scl                = scl,
        .sda                = sda,
        .frequency          = NRF_TWI_FREQ_100K,
        .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
        .clear_bus_init     = true
    };

    do {
	ret = nrf_drv_twi_init(&m_twi_master, &config, twi_handler, NULL);
        if (NRF_SUCCESS != ret) {
            break;
        }
        nrf_drv_twi_enable(&m_twi_master);
    }
    while (0);
    return;
}

And than in ssd1306_begin() function i call ssd1306_command() function  which looks like this:

void ssd1306_command(uint8_t c)
{
    if (use_i2c) {
        ret_code_t ret;
        uint8_t dta_send[] = {0x00, c};
		while(!m_xfer_done);
		m_xfer_done = false;
        ret = nrf_drv_twi_tx(&m_twi_master, _i2caddr, dta_send, 2, false);
		APP_ERROR_CHECK(ret);
        UNUSED_VARIABLE(ret);
    }
    else {
        _HI_CS();
        _LO_DC();
        _LO_CS();
        _HI_CS();
    }
}


m_xfer_done is hendled in twi_hendler which looks like this:

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;
    }
}

Summarazing whole problem. All code stucks because NRF_DRV_TWI_EVT_DONE is never done actually. Something cosue that nrf_drv_twi_tx() function doesn't work properly and I can not figure out why. I'll be super grateful if someone could help me in solving this problem. So far I've been trying to use higher priority levels for example because I've read on this formu that it could cause some problems regarding to softdevice, but of course it didn't help.

Related