i2c randombly fails

jesseb
Posts: 29
Joined: Tue Jan 10, 2017 5:36 pm

i2c randombly fails

Postby jesseb » Fri Jun 16, 2017 6:33 pm

I've had issues with i2c intermittently ever since I started using the i2c driver provided. I follow the i2c example very closely. It seems that the issues happen during transmit.

In the code, I get 1 of 3 types of errors. After the error the i2c will not recover until reset.
  • timeout error (263) returned from i2c_master_cmd_begin,
  • a general error (-1) is returned from i2c_master_cmd_begin
  • I get an assert on line 600 of xRingbufferReceiveUpToFromISR, only called by i2c driver in my code
.
Here's my code:

Code: Select all

#include <stddef.h>
#include <stdbool.h>
#include <stdlib.h>
#include <i2c_master.h>
#include <driver/gpio.h>
#include <driver/periph_ctrl.h>
#include <driver/i2c.h>
#include <freertos/FreeRTOS.h>



enum
{
    i2c_master_sclIo            = 16,  // gpio number for I2C master clock
    i2c_master_sdaIo           = 17,  // gpio number for I2C master data

    i2c_master_txBufDisable   =  0,   // I2C master do not need buffer
    i2c_master_rxBufDisable   =  0,   // I2C master do not need buffer
    i2c_master_freqHz             =  400000,     // I2C master clock frequency
};

enum
{
    writeMask = 0xFE,
    readMask = 0x01,
};

static const i2c_port_t I2C_MASTER_NUM = I2C_NUM_0;   // I2C port number for master dev

static const bool ACK_CHECK_EN  = 0x1;     // I2C master will check ack from slave
static const bool ACK_CHECK_DIS = 0x0;     // I2C master will not check ack from slave
static const bool ACK_VAL    = 0x0;        // I2C ack value
static const bool NACK_VAL   = 0x1;        // I2C nack value

static bool init = 0x0;



size_t myI2c_master_transmit(uint8_t slaveAddress, const uint8_t* txBuf, size_t size, bool sendStopBit)
{
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    esp_err_t ret = i2c_master_start(cmd);                                     //queue send start command
    ret |= i2c_master_write_byte(cmd, ( slaveAddress ) & writeMask, true);     //queue write address command
    ret |= i2c_master_write(cmd, (uint8_t*)txBuf, size, ACK_CHECK_EN);        //queue write data command
    ret |= i2c_master_stop(cmd);                                           //queue send stop command


    if( ret != ESP_OK )
    {
        i2c_cmd_link_delete(cmd);
        printf("i2c queue transmit commands error: %d\n", ret);
        return 0;
    }

    ret = i2c_master_cmd_begin((i2c_port_t) I2C_MASTER_NUM, cmd, 500 / portTICK_RATE_MS);
        //start execution of all commands that have been queued
    i2c_cmd_link_delete(cmd);

    if( ret != ESP_OK )
    {
        printf("slave Address: %02X\n", slaveAddress);
        printf("i2c transmit error: %d\n", ret);
        return 0;
    }

    return size;
}


size_t myI2c_master_receive(uint8_t slaveAddress, uint8_t* rxBuf, size_t size)
{
    if ( size == 0 )
    {
        return 0;
    }

    i2c_cmd_handle_t cmd = i2c_cmd_link_create();                           //create new handler for set of commands
    esp_err_t ret = i2c_master_start(cmd);                                        //queue send start command
    ret |= i2c_master_write_byte(cmd, (slaveAddress | readMask), ACK_CHECK_EN);  //queue write address command
    if (size > 1) {
        ret |= i2c_master_read(cmd, rxBuf, size - 1, ACK_VAL);                     //queue read data
    }
    ret |= i2c_master_read_byte(cmd, (rxBuf + size - 1), NACK_VAL);                  //queue read last byte of data
        //i2c protocol requires nack on last byte of data read from slave
    ret |= i2c_master_stop(cmd);                                                   //queue send stop command

    if( ret != ESP_OK )
    {
        i2c_cmd_link_delete(cmd);
        printf("i2c queue receive commands error: %d\n", ret);
        return 0;
    }

    ret = i2c_master_cmd_begin((i2c_port_t) I2C_MASTER_NUM, cmd, 500 / portTICK_RATE_MS);
        //start execution of all commands that have been queued
    i2c_cmd_link_delete(cmd);

    if( ret != ESP_OK )
    {
        printf("i2c receive error: %d\n", ret);
        return 0;
    }

    return size;
}


void myI2c_master_init(void)
{
    if( !init )
    {
        int i2c_master_port = I2C_MASTER_NUM;

        i2c_config_t conf;
        conf.mode = I2C_MODE_MASTER;
        conf.sda_io_num = i2c_master_sdaIo;
        conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
        conf.scl_io_num = i2c_master_sclIo;
        conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
        conf.master.clk_speed = i2c_master_freqHz;
        i2c_param_config(i2c_master_port, &conf);

        i2c_driver_install(i2c_master_port, conf.mode, i2c_master_rxBufDisable, i2c_master_txBufDisable, 0);

        init = true;
    }
}
With logic analyzer output, i2c commands run fine but then 1 of 2 problems occur:
  • a write continues indefinitely, writing 0xFF or a random byte. (the images below are of the same i2c write)
    Capture1.PNG
    Capture1.PNG (8.86 KiB) Viewed 25923 times
    Capture2.PNG
    Capture2.PNG (6.32 KiB) Viewed 25923 times
  • esp32 starts a write with a bogus address and gets NAK. This continues indefinitely until reset. Also, the address passed into myI2c write is always correct.
Capture3.PNG
Capture3.PNG (8.01 KiB) Viewed 25923 times

jesseb
Posts: 29
Joined: Tue Jan 10, 2017 5:36 pm

Re: i2c randombly fails

Postby jesseb » Wed Jul 12, 2017 6:44 pm

So I've come back to this after leaving it for some time.

I have written my own driver that is eerily similar to the arduino low level i2c driver.

It seems that the i2c peripheral itself has some issues:
  • The done bit on an end command never gets set even though the end_detect interrupt fired.
  • A read or write cannot directly follow an end command. Rather, one must send a start command after each end command. If one does not do this the bus is seen as busy when one tries to execute commands again. The technical reference manual states differently. If one tries to do a read or write directly after the end command the driver will timeout and the bus busy bit of the i2c status register is set.
  • The peripheral will send or receive continuously until the driver times out - so far no one knows how to reset the peripheral without resetting the chip.

Note: these problems happen when one uses the i2c fifo or not.

Here is the i2c driver I wrote (based on arduino esp32 i2c driver). One can run in fifo mode or nonfifo mode based on value of NON_FIFO_ENABLE.

Code: Select all

// i2c_master_esp32.c



#include <stddef.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>

#include "soc/i2c_struct.h"
#include "soc/i2c_reg.h"
#include "soc/gpio_sig_map.h"

#include "rom/ets_sys.h"

#include "driver/gpio.h"
#include "driver/periph_ctrl.h"

#include "esp_err.h"
#include "esp_intr.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/xtensa_api.h"
#include "freertos/semphr.h"
#include "freertos/event_groups.h"

#include "i2c_master.h"



#define NON_FIFO_ENABLE 1

#define I2C_TIMEOUT_MS  13
#define I2C_WAIT_MS     500

#define TRACE(x)        (void)( printf x, fflush(stdout) )
#define xTRACE(x)       ((void)0)

enum
{
    i2c_esp32Frequency = 400000,
    peripheralClkFreq  = 80000000, //APB_CLK_FREQ  
};

enum
{    
    //Measured in apb clock cycles
    i2c_scl_half_cycle          = (peripheralClkFreq / i2c_esp32Frequency) /2,
    i2c_scl_low_period          = i2c_scl_half_cycle,
    i2c_scl_high_period         = i2c_scl_half_cycle,

    i2c_scl_rstart_setup_time   = i2c_scl_half_cycle / 2, //(0.6 us minimum) == (peripheralClkFreq *(6)) / (10000000)
    i2c_scl_start_hold_time     = i2c_scl_half_cycle / 2, //"
    i2c_scl_stop_hold_time      = i2c_scl_half_cycle / 2, //"
    i2c_scl_stop_setup_time     = i2c_scl_half_cycle / 2, //(0.6 us minimum)
    i2c_sda_hold_time           = i2c_scl_half_cycle / 4, //(0 us minimum)
    i2c_sda_sample_time         = i2c_scl_half_cycle / 4, //(0.3 us minimum)

    i2c_timeout_clockcycles     = (peripheralClkFreq * I2C_TIMEOUT_MS)/1000, //(13.107 ms maximum)

    i2c_scl_filter_thresh       = (peripheralClkFreq *(5)) / (100000000),    //(50 ns maximum) == (peripheralClkFreq *(5)) / (100000000)
    i2c_sda_filter_thresh       = (peripheralClkFreq *(5)) / (100000000),    //(50 ns maximum)
};

enum
{
    maxSendSize = 30,
    maxReadSize = 30,
};

enum
{
    writeMask  = 0xFE,
    readMask   = 0x01,
    intClrMask = 0xFFFFFFFF,
};

typedef enum 
{
    rstart   = 0,
    writeCmd = 1,
    readCmd  = 2,
    stop     = 3,
    end      = 4,
} i2c_command_t;


static const bool ACK = false;
static const bool NAK = true;

static bool init;



void i2c_reset(void)
{
    CLEAR_PERI_REG_MASK(I2C_INT_ENA_REG(0), intClrMask);
    periph_module_disable(PERIPH_I2C0_MODULE);
    ets_delay_us(1000);
    i2c_master_init();
}



static void i2cResetFifo()
{
    I2C0.fifo_conf.rx_fifo_rst = 1;      //Reset the rx fifo
    I2C0.fifo_conf.rx_fifo_rst = 0;
    I2C0.fifo_conf.tx_fifo_rst = 1;     //Reset the tx fifo
    I2C0.fifo_conf.tx_fifo_rst = 0;
}



static void i2cResetCmd()
{
    int i;
    for(i=0; i<16; i++)
    {
        I2C0.command[i].val = 0;
    }
}



static void i2cSetCmd(uint8_t index, uint8_t op_code, uint8_t byte_num, bool ack_val, bool ack_exp, bool ack_check)
{
    I2C0.command[index].val = 0;    //This covers all fields, setting all to 0
    I2C0.command[index].ack_en = ack_check;
    I2C0.command[index].ack_exp = ack_exp;
    I2C0.command[index].ack_val = ack_val;
    I2C0.command[index].byte_num = byte_num;
    I2C0.command[index].op_code = op_code;
}



static void i2cInitFix(void)
{
    i2cResetFifo();
    i2cResetCmd();
    I2C0.int_clr.val = 0xFFFFFFFF;
    i2cSetCmd(0, rstart, 0, false, false, false);
    I2C0.fifo_data.data = 0;
    i2cSetCmd(1, writeCmd, 1, false, false, false);
    i2cSetCmd(2, stop, 0, false, false, false);
    I2C0.ctr.trans_start = 1;
    while(!I2C0.command[2].done);
}



size_t i2c_master_transmit(uint8_t slaveAddress, const uint8_t* txBuf, size_t size, bool sendStopBit)
{
    static uint32_t errCountTx = 0;

    int txBufIndex = 0;
    size_t currentSendSize;
    uint32_t totalSendSize = size;

    uint32_t currentEndCode;
    uint32_t finalEndCode = (sendStopBit ? stop: end);

    xTRACE(("i2c write started: %x,    %x,    %d\n", I2C0.status_reg.val, I2C0.int_raw.val, size));

    while(size > 0)
    {
        if( size > maxSendSize )
        {
            currentSendSize = maxSendSize;
            size           -= maxSendSize;
            currentEndCode  = end;
        }
        else
        {
            currentSendSize = size;
            size            = 0;
            currentEndCode  = finalEndCode;
        }

        uint32_t commandIndex = 0;

        i2cResetFifo();
        i2cResetCmd();

        I2C0.int_clr.val |= intClrMask;

        bool sendAddress = true; //Should be sendAddress = (txBufIndex == 0); but doesn't work
        if( sendAddress )
        {
            #if NON_FIFO_ENABLE
                I2C0.ram_data[0] = slaveAddress & writeMask;
            #else
                I2C0.fifo_data.val = slaveAddress & writeMask;
            #endif

            i2cSetCmd(commandIndex++, rstart, 0, false, false, false);
        }

        #if NON_FIFO_ENABLE
            int fifoIndex = sendAddress ? 1 : 0;
            while( fifoIndex < currentSendSize+sendAddress )
            {
                I2C0.ram_data[fifoIndex] = (uint32_t)txBuf[txBufIndex++];
                ++fifoIndex;
            }
            currentSendSize = I2C0.status_reg.tx_fifo_cnt;
        #else
            int j = 0;
            while( j < currentSendSize )
            {
                ++j;
                I2C0.fifo_data.val = (uint32_t)txBuf[txBufIndex++];
                while( I2C0.status_reg.tx_fifo_cnt < j );
            }
            currentSendSize = I2C0.status_reg.tx_fifo_cnt;
        #endif

        i2cSetCmd(commandIndex++, writeCmd, currentSendSize, ACK, ACK, true);
            //write data
        i2cSetCmd(commandIndex, currentEndCode, 0, false, false, false);
            //Stop bit if there is no more data to send, otherwise end bit

        I2C0.ctr.trans_start = 1;        //Start command execution

        uint32_t count = 0;
        while(1)
        {
            ets_delay_us(1000);

            if(   I2C0.int_raw.arbitration_lost
               || I2C0.int_raw.time_out
               || I2C0.int_raw.ack_err
               || count >= I2C_WAIT_MS
              )
            {
                TRACE(("I2C TX Error: %08X,  %04X,  %d,  %d\n", I2C0.status_reg.val, I2C0.int_raw.val, I2C0.status_reg.tx_fifo_cnt, count));
                if( errCountTx++ > 5 )
                {
                    i2c_reset();
                }
                size = 0;
                totalSendSize = 0;
                break;
            }

            if(    (I2C0.command[commandIndex].done && I2C0.int_raw.trans_complete) 
                || (/*I2C0.command[commandIndex].done &&*/ I2C0.int_raw.end_detect) //Commented because end command's done bit never gets set
              )
            {
                errCountTx = 0;
                break;
            }

            ++count;
        }
    }

    xTRACE(("Write complete: %x,    %x,    %d\n", I2C0.status_reg.val, I2C0.int_raw.val, I2C0.status_reg.tx_fifo_cnt));

    return totalSendSize;
}


size_t i2c_master_receive(uint8_t slaveAddress, uint8_t* rxBuf, size_t size)
{
    static uint32_t errCountRx = 0;

    int rxBufIndex = 0;
    size_t currentReadSize;
    uint32_t endCode;
    uint32_t commandIndex = 0;

    uint8_t dummyRx;

    xTRACE(("Read start: %x,    %x,    %d\n", I2C0.status_reg.val, I2C0.int_raw.val, size));
    while(size > 0)
    {
        if( size > maxReadSize )
        {
            currentReadSize = maxReadSize;
            endCode         = end;
            size           -= maxReadSize;
        }
        else
        {
            currentReadSize = size;
            endCode         = stop;
            size            = 0;
        }

        commandIndex = 0;

        i2cResetFifo();
        i2cResetCmd();

        I2C0.int_clr.val |= intClrMask;

        bool sendAddress = true; //rxBufIndex == 0;
        if( sendAddress )
        {
            #if NON_FIFO_ENABLE
                I2C0.ram_data[0] = slaveAddress | readMask;
            #else
                I2C0.fifo_data.val = slaveAddress | readMask;
            #endif

            i2cSetCmd(commandIndex++, rstart, 0, false, false, false);
            i2cSetCmd(commandIndex++, writeCmd, 1, ACK, ACK, true);
        }

        if( endCode == stop && size == 0 )
        {
            i2cSetCmd(commandIndex++, readCmd, currentReadSize-1, ACK, false, false);
            i2cSetCmd(commandIndex++, readCmd, 1, NAK, false, false);
                //i2c protocol specifies no ack before stop bit on last byte of read
        }
        else
        {
            i2cSetCmd(commandIndex++, readCmd, currentReadSize, ACK, false, false);
        }
        i2cSetCmd(commandIndex, endCode, 0, false, false, false);

        I2C0.ctr.trans_start = 1;

        uint32_t count = 0;
        while(1)
        {
            ets_delay_us(1000);

            if(   I2C0.int_raw.arbitration_lost
               || I2C0.int_raw.time_out
               || I2C0.int_raw.ack_err
               || count >= I2C_WAIT_MS
              )
            {
                TRACE(("I2C RX Error: %08X,  %04X,  %d,  %d\n", I2C0.status_reg.val, I2C0.int_raw.val, I2C0.status_reg.rx_fifo_cnt, count));
                if( errCountRx++ > 5 )
                {
                    i2c_reset();
                }
                size = 0;
                break;
            }

            if(    (I2C0.command[commandIndex].done && I2C0.int_raw.trans_complete) 
                || (/*I2C0.command[commandIndex].done &&*/ I2C0.int_raw.end_detect)  //Commented because end command's done bit never gets set
              )
            {
                errCountRx = 0;
                break;
            }

            ++count;
        }

        for(int j = 0; j < currentReadSize; ++j)
        {
            //Read data received on the fifo
            #if NON_FIFO_ENABLE
                rxBuf[rxBufIndex] = (uint8_t)I2C0.ram_data[j] ;
            #else
                rxBuf[rxBufIndex] = (uint8_t)I2C0.fifo_data.val;
            #endif
            ets_delay_us(1000);
            ++rxBufIndex;
        }
    }

    xTRACE(("Read complete: %x,    %x,    %d\n", I2C0.status_reg.val, I2C0.int_raw.val, size));

    return rxBufIndex;
}



void i2c_master_close(void)
{
    i2cResetCmd();
    i2cSetCmd(0, rstart, 0, false, false, false);
    i2cSetCmd(1, stop, 0, false, false, false);

    I2C0.int_clr.val     = 0xFFFFFFFF;
    I2C0.ctr.trans_start = 1;
}



void i2c_master_init(void)
{
    //Initialize peripheral
    periph_module_enable(PERIPH_I2C0_MODULE); //Sets dport perph clock to enabled for i2c

    //Set control characteristics of i2c
    I2C0.ctr.val = 0 ;
    I2C0.ctr.ms_mode = 1;
    I2C0.ctr.sda_force_out = 1 ;
    I2C0.ctr.scl_force_out = 1 ;
    I2C0.ctr.clk_en = 1;
    I2C0.ctr.sample_scl_level = 0 ;
    I2C0.ctr.rx_lsb_first = 0 ;
    I2C0.ctr.tx_lsb_first = 0 ;

    I2C0.timeout.val = i2c_timeout_clockcycles;
    #if NON_FIFO_ENABLE
        I2C0.fifo_conf.nonfifo_en = 1;
    #else
        I2C0.fifo_conf.nonfifo_en = 0;
    #endif

    I2C0.fifo_conf.tx_fifo_empty_thrhd = 0;
    I2C0.fifo_conf.rx_fifo_full_thrhd  = 30;
    I2C0.fifo_conf.nonfifo_rx_thres    = 32;
    I2C0.fifo_conf.nonfifo_tx_thres    = 32;


    //Set the i2c frequency and clock characteristics
    I2C0.scl_low_period.period   = i2c_scl_low_period;
    I2C0.scl_high_period.period  = i2c_scl_high_period;
    I2C0.scl_start_hold.time     = i2c_scl_start_hold_time;
    I2C0.scl_rstart_setup.time   = i2c_scl_rstart_setup_time;
    I2C0.scl_stop_hold.time      = i2c_scl_stop_hold_time;
    I2C0.scl_stop_setup.time     = i2c_scl_stop_setup_time;
    I2C0.sda_hold.time           = i2c_sda_hold_time;
    I2C0.sda_sample.time         = i2c_sda_sample_time;
    I2C0.scl_filter_cfg.en       = 0;                         //disable scl filter
    I2C0.sda_filter_cfg.en       = 0;                         //disable sda filter
    //I2C0.scl_filter_cfg.thres = i2c_scl_filter_thresh;
    //I2C0.sda_filter_cfg.thres = i2c_sda_filter_thresh;

    I2C0.int_ena.val = 0; //Disable all I2C interrupts

    //Attach scl to gpio pin 16
    gpio_config_t io_conf;
    io_conf.intr_type    = GPIO_INTR_DISABLE;              //disable interrupt
    io_conf.mode         = GPIO_MODE_INPUT_OUTPUT_OD;      //set as output mode
    io_conf.pin_bit_mask = GPIO_SEL_16;                    //bit mask of the pins that you want to set,e.g.GPIO21/22
    io_conf.pull_down_en = 0;                              //disable pull-down mode
    io_conf.pull_up_en   = 0;                              //enable pull-up mode
    gpio_config(&io_conf);                                 //configure GPIO with the given settings
    gpio_matrix_out(16, I2CEXT0_SCL_OUT_IDX, 0, 0);        //set output signal for io_matrix
    gpio_matrix_in( 16, I2CEXT0_SCL_IN_IDX, 0);            //set input signal for io_matrix

    //Attach sda to gpio pin 17
    io_conf.intr_type    = GPIO_INTR_DISABLE;              //disable interrupt
    io_conf.mode         = GPIO_MODE_INPUT_OUTPUT_OD;      //set as output mode
    io_conf.pin_bit_mask = GPIO_SEL_17;                    //bit mask of the pins that you want to set,e.g.GPIO21/22
    io_conf.pull_down_en = 0;                              //disable pull-down mode
    io_conf.pull_up_en   = 0;                              //enable pull-up mode
    gpio_config(&io_conf);                                 //configure GPIO with the given settings
    gpio_matrix_out(17, I2CEXT0_SDA_OUT_IDX, 0, 0);        //set output signal for io_matrix
    gpio_matrix_in( 17, I2CEXT0_SDA_IN_IDX, 0);            //set input signal for io_matrix

    init = true;
}



// EOF
My i2c errors only seem to occur while mbedtls is configuring/connecting. I did lots of checking to see if memory related to my i2c was getting corrupted but couldn't seem to find any corruptions or leaks. I also checked i2c peripheral registers. All the registers had the expected values but the i2c ram may have been corrupted (I'm not sure on that because I only checked this in fifo mode so far).

Here's my code for tls start and stop.

Code: Select all

static mbedtls_ssl_context      sslContext;
static mbedtls_entropy_context  entropy;
static mbedtls_ctr_drbg_context ctr_drbg;
static mbedtls_ssl_config       conf;
static mbedtls_x509_crt         caCert;

    static bool startTls(mbedtls_net_context* tlsSocket, const char* ipAddressStr, const char* caRootCertificate)
    {
        int              error;

        // Configure TLS
        mbedtls_net_init(tlsSocket);
        mbedtls_ssl_init(&sslContext);
        mbedtls_ssl_config_init(&conf);
        mbedtls_x509_crt_init(&caCert);
        mbedtls_ctr_drbg_init(&ctr_drbg);
        mbedtls_entropy_init(&entropy);

        if( ( error = mbedtls_entropy_self_test(1)) != 0)
        {
            TRACE(("Error: mbedtls_entropy_self_test failed!\n"));
        }

        if(    error == 0
            && (error = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0)) != 0
          )
        {
            TRACE(( "Error: mbedtls_ctr_drbg_seed returned -0x%X\n", -error));
        }

        if(    error == 0
            && (error = mbedtls_x509_crt_parse(&caCert, (uint8_t*)caRootCertificate, strlen(caRootCertificate) + 1))
          )
        {
            TRACE(("mbedtls_x509_crt_parse returned -0x%X\n", -error));
        }

        if(    error == 0
            && (error = mbedtls_ssl_set_hostname(&sslContext, "openSSL TLS Server 1")) != 0
          )
        {
            TRACE(( "Error: mbedtls_ssl_set_hostname returned -0x%X\n", -error));
        }

        char ipString[5];
        itoa(serverPortNum, ipString, 10);
        if(    error == 0
            && (error = mbedtls_net_connect(tlsSocket, ipAddressStr, ipString, MBEDTLS_NET_PROTO_TCP)) != 0 )
        {
            TRACE(( " failed\n  ! mbedtls_net_connect returned -0x%X\n", -error));
        }

        if( error == 0 )
        {
            error = mbedtls_ssl_config_defaults(  &conf
                                                , MBEDTLS_SSL_IS_CLIENT
                                                , MBEDTLS_SSL_TRANSPORT_STREAM
                                                , MBEDTLS_SSL_PRESET_DEFAULT
                                               );

            if( error != 0 )
            {
                TRACE(( "Error: mbedtls_ssl_config_defaults returned -0x%X\n", -error));
            }
        }

        if( error == 0 )
        {
            mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL); // TODO: enable verify
            mbedtls_ssl_conf_ca_chain(&conf, &caCert, NULL);
            mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );

            error = mbedtls_ssl_setup(&sslContext, &conf);

            if( error != 0 )
            {
                TRACE(("mbedtls_ssl_setup returned -0x%X\n", -error));
            }
        }

        TRACE_LINE;

        if( error == 0 )
        {
            mbedtls_ssl_set_bio(&sslContext, &tlsSocket->fd, mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout);

            if( (error = mbedtls_ssl_handshake(&sslContext)) != 0 )
            {
                TRACE(( "Error: mbedtls_ssl_handshake returned -0x%X\n", -error));
            }
        }

        return error == 0;
    }



    static bool stopTls(mbedtls_net_context *tlsSocket)
    {
        mbedtls_ssl_close_notify(&sslContext);

        // Clean up
        mbedtls_net_free( tlsSocket );  //Calls shutdown and close for the tcp socket
        mbedtls_x509_crt_free( &caCert );
        mbedtls_ssl_free( &sslContext );
        mbedtls_ssl_config_free( &conf );
        mbedtls_ctr_drbg_free( &ctr_drbg );
        mbedtls_entropy_free( &entropy );
        return true;
    }
I've checked the i2c signals with a scope and the lines have stable transitions.

WiFive
Posts: 3529
Joined: Tue Dec 01, 2015 7:35 am

Re: i2c randombly fails

Postby WiFive » Wed Jul 12, 2017 8:18 pm

Do you think it is related to eco 3.10? Do you have latest SDK that disables hw crypto? Have you tried single core mode?

jesseb
Posts: 29
Joined: Tue Jan 10, 2017 5:36 pm

Re: i2c randombly fails

Postby jesseb » Wed Jul 12, 2017 8:47 pm

It may be related to the chip version. It is a revision 0 chip. I haven't looked into what went wrong with that chip revision. Do I need a new chip?

No I'm on commit ff6a3b1a11032798565d7b78319444aa81881542. I'll try updating to the latest.

I previously ran in single core mode but I couldn't get the performance I wanted with gpio interrupts.

WiFive
Posts: 3529
Joined: Tue Dec 01, 2015 7:35 am

Re: i2c randombly fails

Postby WiFive » Wed Jul 12, 2017 9:24 pm


gregstewart90
Posts: 59
Joined: Thu Jan 19, 2017 5:17 pm

Re: i2c randombly fails

Postby gregstewart90 » Thu Jul 13, 2017 4:09 pm

I have the same problem. Here is my post. The reset seems to be the only fix. Your driver looks nice.

Anyone from Espressif have a fix that can be integrated into the IDF? I'm resetting when I detect the issue, but that's kind of a bad solution.

jesseb
Posts: 29
Joined: Tue Jan 10, 2017 5:36 pm

Re: i2c randombly fails

Postby jesseb » Tue Jul 25, 2017 8:37 pm

I got it working. Sorry to everyone for not posting when I did. WiFive pointed me in the right direction. I had wifi using flash storage by calling esp_wifi_set_storage with WIFI_STORAGE_FLASH as the parameter. Changing that to use WIFI_STORAGE_RAM seemed to fix the issues. I also disabled hardware acceleration for tls encryption as well, just to be safe. After those simple changes I haven't had any issues with the i2c. I tested the new code on both rev 0 and 1 of the hardware though I haven't tested the previous code on rev 1 hardware to see if there were issues there as well.

WiFive
Posts: 3529
Joined: Tue Dec 01, 2015 7:35 am

Re: i2c randombly fails

Postby WiFive » Tue Jul 25, 2017 11:29 pm

So the other three issues you mention are still unresolved, your driver just works around them?

jesseb
Posts: 29
Joined: Tue Jan 10, 2017 5:36 pm

Re: i2c randombly fails

Postby jesseb » Wed Jul 26, 2017 3:11 pm

My driver has remained the same. I have also run it using espressif's driver and it works fine with that too. It seemed that the issues above were caused by some bug with wifi, tls or in the hardware dealing with wifi accessing the flash and tls using hardware acceleration for encryption. It is possible that this issue could still come up but so far, I haven't seen it again. Before I could cause i2c errors easily with connecting, disconnecting and reconnecting my tls socket. I changed the wifi storage type and turned off tls hardware encryption acceleration to get it working. So there is still an underlying problem somewhere but right now I'm avoiding it with these changes.

WiFive
Posts: 3529
Joined: Tue Dec 01, 2015 7:35 am

Re: i2c randombly fails

Postby WiFive » Thu Jul 27, 2017 12:18 am

So these two still true?
  • The done bit on an end command never gets set
  • A read or write cannot directly follow an end command.

Who is online

Users browsing this forum: No registered users and 349 guests