I2C access with BCM943362WCD4

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

Hi Wiced Engineers,

Does the BCM943362WCD4 platform support I2C peripheral access.  I was not able to see initialization of platform_i2c_peripherals in the BCM943362WCD4 platform.c file.   Are there any examples of I2C access.

Thanks

0 Likes
15 Replies
SeyhanA_31
Employee
Employee
250 replies posted 100 replies posted 50 replies posted

Hi,

The wiced_i2c_init( wiced_i2c_device_t*) call in .../include/wiced_platform.h will initialize the I2C interface.

The wiced_i2c_device_t is also defined in the header file.

There are supporting functions  wiced_i2c_...(...) help you to send and receive data over I2C.

You may fine help in .../Doc/API/group__i2c.html for functions.

-Seyhan

Anonymous
Not applicable

Thanks for your response Seyhan.  I did notice the functions you pointed out but in the implementation of the function wiced_i2c_init() notice the following

wiced_result_t wiced_i2c_init( wiced_i2c_device_t* device )

{

...

    result = platform_i2c_init( &platform_i2c_peripherals[device->port], &config );

The platform_i2c_peripherals variable is defined in platforms/BCM*/platform.c files and I was not able to see that for BCM943362WCD4.  Since STM's M3 itself supports I2C, I would imagine, it should be possible to do I2C, but as-is the SDK doesnot seem to have all the hooks in place for BCM943362WCD4.

Are you saying that I2C access is working for you with the BCM943362WCD4?

Regards,

0 Likes

Hi,

Yes I2C is not included with BCM943362WCD4 platform files but it could be updated with I2C support. You may update the platform files similar to SPI or UART. Also you could check out other platform files where I2C is included in the platform files for sample.

I will updated the BCM943362WCD4 platform files with I2C support and share.

-Seyhan

Anonymous
Not applicable

Thanks for your response Seyhan.  It is good to know that it is workable.  It will be great if you can share the files, meanwhile I will try to look at the pin muxing and look at other platform files as well.

Best Regards

0 Likes
JoDa_1711826
Level 1
Level 1
First like received

Are there any known issues with wiced_result_t wiced_i2c_deinit( wiced_i2c_device_t* device )? It seems that when this is run then wiced_result_t wiced_i2c_init( wiced_i2c_device_t* device ) is run again, the I2C bus will not longer work. This is on our custom hardware but uses the API to perform the initialization.

0 Likes

I use wiced_i2c_deinit() then wiced_i2c_init() to recover from I2C failures. Reading errata for STM32F2 ARM processor they suggest a software reset on I2C to recover from I2C hanging in busy state.

My recover code:

wiced_i2c_deinit(&device);

/* I2C Software reset */

i2c_mapping[device.port].i2c->CR1 = 0x8000u;

wiced_rtos_delay_milliseconds(100 * MILLISECONDS);

i2c_mapping[device.port].i2c->CR1 = 0x0000u;


wiced_i2c_init(&device);


It works most of the time but sometimes I2C still hangs in busy state.


Any suggestions are welcome

//Peter

0 Likes

I did read up on the errata for i2C on the ST microprocessor too before I posted the inquiry. The I2C behavior after after wiced_i2c_deinit(); is called followed by wiced_i2c_init() becomes intermittent afterwards. I will try the the software reset as you suggested. I've looked at this for a while trying to understand what is happening. On my platform, I built a NoOS NoFS variant to test I2C directly and the issue appeared to go away. It seems that the issue is with the ThreadX implementation perhaps. I was able to reproduce some of the unusual behavior on the Eval Platform.

I posted some more details up on Broadcom Support as some of this pertains to different hardware.

0 Likes

Did you solve your issue?  I would be very interested in some more details of your findings.  What did you use for settings for platform_i2c_peripherals (I am moving onto WICED 3.1.2 and the setup is different).  I am converting my working code over from WICED 2.4.1 where I used the following to reset:

wiced_result_t resetI2C(wiced_i2c_device_t *device)

{

  wiced_result_t result = wiced_i2c_deinit(device);

  if (WICED_SUCCESS != result)

    WPRINT_APP_INFO(("I2C de-initialize failed with error:%d\r\n", result));

  else

  {

    result = wiced_i2c_init(device);

  }

  return result;

}

0 Likes

Yes. It had to do with DMA (we had it enabled).

Locate:

  platform_result_t platform_i2c_deinit( const platform_i2c_t* i2c, const platform_i2c_config_t* config )

Comment out:

  RCC_AHB1PeriphClockCmd( i2c->tx_dma_peripheral_clock, DISABLE );

This was disabling the UART so the system would hang. Bug still exists in SDK3.1.2.

We are currently porting to 3.1.2 and have testing planned. Preliminary results look good so far.

Bug exists in both WICED/platform/MCU/STM32F2xx, STM32F4xx

Thanks for the quick reply.  I'll give that a try!  Let's keep each other posted on the move to 3.1.2.  BTW, what did you use for platform_i2c_peripherals?  I have:

const platform_i2c_t platform_i2c_peripherals[] =

{

        [WICED_I2C_1] =

        {

        .port                    = I2C1,

        .pin_scl                 = &platform_gpio_pins[WICED_GPIO_11],

        .pin_sda                 = &platform_gpio_pins[WICED_GPIO_12],

        .peripheral_clock_reg    = RCC_APB1Periph_I2C1,

        .tx_dma                  = DMA1,

        .tx_dma_peripheral_clock = RCC_AHB1Periph_DMA1,

        .tx_dma_stream           = DMA1_Stream7,

        .rx_dma_stream           = DMA1_Stream5,

        .tx_dma_stream_id        = 7,

        .rx_dma_stream_id        = 5,

        .tx_dma_channel          = DMA_Channel_1,

        .rx_dma_channel          = DMA_Channel_1,

        .gpio_af                 = GPIO_AF_I2C1

    },

};

0 Likes

Hi!

After a lot of experimenting I came up with a solution thats works for me.

If I get an error I try to reset the I2C module.

If that doesn't work I generate 9 clock cycles on the bus with GPIO and reset the I2C module.

That has solved every hickup so far.

I don't use i2c_deinit() because it worked better without. Don't know why.

Reading SR causes some flags to reset. Don't remember which ones.

Example I2C Read:

result = wiced_i2c_init_rx_message(&message, buf, nbyte, 1 , WICED_TRUE);

if (result == WICED_SUCCESS) {

    result = wiced_i2c_transfer(&device, &message, 1);

    if (result != WICED_SUCCESS) {

        i2c_reset();

        result = wiced_i2c_transfer(&device, &message, 1);

        if (result != WICED_SUCCESS) {

            i2c_clock_recovery();

            result = wiced_i2c_transfer(&device, &message, 1);

            if (result != WICED_SUCCESS) i2c_reset();

        }

    }

}

void i2c_reset() {

    log_info("I2C busy reset recovery sequence");

    /* Log before status */

    logf_info("I2C SR1 = %04X, SR2 = %04X", i2c_mapping[device.port].i2c->SR1, i2c_mapping[device.port].i2c->SR2);

    /* Reset I2C */

    i2c_mapping[device.port].i2c->CR1 = 0x8000u;

    wiced_rtos_delay_milliseconds(10 * MILLISECONDS);

    i2c_mapping[device.port].i2c->CR1 = 0x0000u;

    /* Reinitialize I2C again */

    wiced_i2c_init(&device);

    /* Log exit status */

    logf_info("I2C SR1 = %04X, SR2 = %04X", i2c_mapping[device.port].i2c->SR1, i2c_mapping[device.port].i2c->SR2);

}

i2c_clock_recovery() {

    int i;

    log_info("I2C busy clock recovery sequence");

    /* Log before status */

    logf_info("I2C SR1 = %04X, SR2 = %04X", i2c_mapping[device.port].i2c->SR1, i2c_mapping[device.port].i2c->SR2);

    /* Reset I2C */

    i2c_mapping[device.port].i2c->CR1 = 0x8000u;

    wiced_rtos_delay_milliseconds(10 * MILLISECONDS);

    i2c_mapping[device.port].i2c->CR1 = 0x0000u;

    /* Set SCL & SDA as GPIO outputs */

    wiced_gpio_init (WICED_GPIO_18,  OUTPUT_OPEN_DRAIN_NO_PULL);

    wiced_gpio_init (WICED_GPIO_19,  OUTPUT_OPEN_DRAIN_NO_PULL);

    wiced_gpio_output_high(WICED_GPIO_18);

    wiced_gpio_output_high(WICED_GPIO_19);

    /* Ripple clock to unhang external devices */

    for (i = 0; i < 9; i++) {

        wiced_gpio_output_low(WICED_GPIO_18);

        wiced_rtos_delay_milliseconds(1 * MILLISECONDS);

        wiced_gpio_output_high(WICED_GPIO_18);

        wiced_rtos_delay_milliseconds(1 * MILLISECONDS);

    }

    /* Reinitialize I2C again */

    wiced_i2c_init(&device);

    /* Log exit status */

    logf_info("I2C SR1 = %04X, SR2 = %04X", i2c_mapping[device.port].i2c->SR1, i2c_mapping[device.port].i2c->SR2);

}

I don't know about platform_i2c_peripherals but used:

const platform_i2c_mapping_t i2c_mapping[] =

{

    [WICED_I2C_1] =

    {

        .i2c = I2C1,

        .pin_scl                = &gpio_mapping[WICED_GPIO_18],

        .pin_sda                = &gpio_mapping[WICED_GPIO_19],

        .peripheral_clock_reg    = RCC_APB1Periph_I2C1,

        .tx_dma                  = DMA1,

        .tx_dma_peripheral_clock = RCC_AHB1Periph_DMA1,

        .tx_dma_stream          = DMA1_Stream7,

        .rx_dma_stream          = DMA1_Stream5,

        .tx_dma_stream_id        = 7,

        .rx_dma_stream_id        = 5,

        .tx_dma_channel          = DMA_Channel_1,

        .rx_dma_channel          = DMA_Channel_1,

        .gpio_af                = GPIO_AF_I2C1

    },

};

const platform_i2c_t platform_i2c_peripherals[] =

{

    [WICED_I2C_1] =

    {

        .port = I2C1,

        .pin_scl                 = &platform_gpio_pins[WICED_GPIO_17],

        .pin_sda                 = &platform_gpio_pins[WICED_GPIO_18],

        .peripheral_clock_reg    = RCC_APB1Periph_I2C1,

        .tx_dma                  = DMA1,

        .tx_dma_peripheral_clock = RCC_AHB1Periph_DMA1,

        .tx_dma_stream           = DMA1_Stream7,

        .rx_dma_stream           = DMA1_Stream0,

        .tx_dma_stream_id        = 7,

        .rx_dma_stream_id        = 0,

        .tx_dma_channel          = DMA_Channel_1,

        .rx_dma_channel          = DMA_Channel_1,

        .gpio_af                 = GPIO_AF_I2C1

    },

Thanks to the answers so far.  Very helpful.

0 Likes

Hi,

This example may help you to communicate with I2C devices using WICED APIs, I2C Interface Example with WICED SDK-3.x

Seyhan

This validates what I did based on above notes.  I have been running flawlessly with it for several hours now.  Seems very stable.  BTW, I am using this with an Inventek module.

0 Likes