I2C Problem with STM32F4DISCOVERY in v2.4.0

ChibiOS public support forum for all topics not covered by a specific support forum.

Moderators: RoccoMarco, lbednarz, tfAteba

nactus
Posts: 5
Joined: Fri Dec 23, 2011 11:09 pm

I2C Problem with STM32F4DISCOVERY in v2.4.0

Post by nactus »

I tried to read the ID-Register from the audio-dac (CS43L22) on the discovery board which is connected to the i2c1 on the stm32f4.

During this i encounterd three problems:
1. you cant receive exactly 1 byte. 0 and >1 works - i think this is a bug in i2c_lld_master_transmit_timeout:

Code: Select all

  chDbgCheck(((rxbytes == 0) || ((rxbytes > 1) && (rxbuf != NULL))),
             "i2c_lld_master_transmit_timeout");

this fails if rxbytes is exactly 1.

2. if i send only one byte it sends two bytes where the second one is 0x00.
the second time you send one byte it sends 0x00 first and then the byte you inteded to send.
the third time is like the fist again and so on...

3. if you send 2 or more bytes it works correctly the fist time you call i2cMasterTransmit.
the second time it sends (assuming you send 3 bytes) 0x00, 0x04, 0x00.
the third time is like the first again and so on...


I used a logic analyzer to watch what it sends and receives and made a screenshot of the 2. problem:

Image

In my code example i send 1 byte two times (if you repeat this the result repeats).
Then i send 3 bytes (2 times).

main.c:

Code: Select all

#include "ch.hpp"
#include "hal.h"

using namespace chibios_rt;

static const I2CConfig i2cfg =
{
    OPMODE_I2C,
    100000,
    STD_DUTY_CYCLE,
};

int main(void)
{
  halInit();
  System::Init();

  i2cStart(&I2CD1, &i2cfg);

  while (TRUE) {

    unsigned char addr = 0x94;
    unsigned char rxdata[] = {0, 0};
    unsigned char regAddr[] = {0x01, 0xFE, 0xFF};

    ((*(volatile uint32_t*)0x40020C14)) |= (1<<(4)); //chip select for audio-dac

    i2cAcquireBus(&I2CD1);
    i2cMasterTransmit(&I2CD1, addr >> 1, regAddr, 1, rxdata, 2);
    i2cReleaseBus(&I2CD1);
    regAddr[0] = 0x01; //just to make sure
    i2cAcquireBus(&I2CD1);
    i2cMasterTransmit(&I2CD1, addr >> 1, regAddr, 1, rxdata, 2);
    i2cReleaseBus(&I2CD1);

    i2cAcquireBus(&I2CD1);
    i2cMasterTransmit(&I2CD1, addr >> 1, regAddr, 3, rxdata, 2);
    i2cReleaseBus(&I2CD1);
    regAddr[0] = 0x01; //just to make sure
    i2cAcquireBus(&I2CD1);
    i2cMasterTransmit(&I2CD1, addr >> 1, regAddr, 3, rxdata, 2);
    i2cReleaseBus(&I2CD1);

    chThdSleepMilliseconds(10);
  }
}


So i was wondering why this is, because with the i2c driver in 2.3.4 it worked.

Andi
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: I2C Problem with STM32F4DISCOVERY in v2.4.0

Post by Giovanni »

Hi,

I think this is a question for barthess, he has a much deeper understanding of the I2C driver.

Giovanni
DrunkenDonkey
Posts: 124
Joined: Sun Aug 28, 2011 5:16 pm

Re: I2C Problem with STM32F4DISCOVERY in v2.4.0

Post by DrunkenDonkey »

1. Is ST issue, it is like that, if you want to read 1 byte read 2 and take the first, I have wrapped my i2c functions to do that
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: I2C Problem with STM32F4DISCOVERY in v2.4.0

Post by Giovanni »

The driver in 2.3.4 was very different so it is possible a bug has been introduced, I'll give it a try in the weekend, it looks like weirdness in reinitializing the DMA.

Giovanni
User avatar
barthess
Posts: 861
Joined: Wed Dec 08, 2010 7:55 pm
Been thanked: 7 times

Re: I2C Problem with STM32F4DISCOVERY in v2.4.0

Post by barthess »

I have no logical analyzer to watch what exactly happens on bus in my case, but all my devices works as expected. I can look in problem closer only on Monday (with oscilloscope on my job).
nactus
Posts: 5
Joined: Fri Dec 23, 2011 11:09 pm

Re: I2C Problem with STM32F4DISCOVERY in v2.4.0

Post by nactus »

Hi,

I have uploaded my test code so you can easily test it with my whole os setup:
i2c_error_2.4.0__a.zip

So if any of you have the STM32F4DISCOVERY board please test if you get the same result i got to figure out if it is indeed an driver bug.
The upper nibble of the response byte should be 0xE (Device id of audio-dac).
In my case the whole byte is 0xE3 (where the 3 is the chip revision, which can vary i guess).

If you don't have a logic analyzer you can add some lines of code to check against this value.


Thanks,
Andreas
nactus
Posts: 5
Joined: Fri Dec 23, 2011 11:09 pm

Re: I2C Problem with STM32F4DISCOVERY in v2.4.0

Post by nactus »

As for the first problem, i think the driver should check if you want to receive only one byte and if so, it souldn't use dma as it is useless in this situation (but as DrunkenDonkey said, this can be solved by his workaroud and has therefore no priority).

And could it be that the first part of the second problem (where it adds a 0x00 byte if you want to write only one byte) is because you can't send only one byte
over dma, like DrunkenDonkey wrote, so it adds the second byte which is (for no apparent reason) 0x00?
Or is this "minimum of two byte bug" only for "peripheral to memory" dma and not the other way around?
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: I2C Problem with STM32F4DISCOVERY in v2.4.0

Post by Giovanni »

Hi,

Thanks for the test case, I will give it a try tomorrow.

Giovanni
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: I2C Problem with STM32F4DISCOVERY in v2.4.0

Post by Giovanni »

HI,

After some trouble with my analyzer I run your test, I had to copy it into a demo because it won't build using your project.

The problem is that in my tests the I2C behaves exactly as expected, the first two transmission transmit one byte and receive two bytes, the 3rd and 4th transmissions send 3 bytes and receive two without differences among them.

I ran the test using -O0 and -O2, same result.

Note that I am using the trunk code but the I2C driver it is no different from 2.4.0.

Could it be a measurement error or some error in your project setup? try using the demo as-is pasting your code immediately chSysInit() and verify if you get the same problem.

Probably Barthess will verify too but it is unlikely he will find problems, he is working a lot with this driver.

My main():

Code: Select all

/*
 * Application entry point.
 */
int main(void) {

  /*
   * System initializations.
   * - HAL initialization, this also initializes the configured device drivers
   *   and performs the board-specific initializations.
   * - Kernel initialization, the main() function becomes a thread and the
   *   RTOS is active.
   */
  halInit();
  chSysInit();

  i2cStart(&I2CD1, &i2cfg);
  ((*(volatile uint32_t*)0x40020C14)) |= (1<<(4)); //chip select for audio-dac

  while (TRUE) {
    unsigned char addr = 0x94;
    unsigned char rxdata[] = {0, 0};
    unsigned char regAddr[] = {0x01, 0xFE, 0xFF};


    i2cAcquireBus(&I2CD1);
    i2cMasterTransmit(&I2CD1, addr >> 1, regAddr, 1, rxdata, 2);
    i2cReleaseBus(&I2CD1);
    regAddr[0] = 0x01; //just to make sure
    i2cAcquireBus(&I2CD1);
    i2cMasterTransmit(&I2CD1, addr >> 1, regAddr, 1, rxdata, 2);
    i2cReleaseBus(&I2CD1);

    i2cAcquireBus(&I2CD1);
    i2cMasterTransmit(&I2CD1, addr >> 1, regAddr, 3, rxdata, 2);
    i2cReleaseBus(&I2CD1);
    regAddr[0] = 0x01; //just to make sure
    i2cAcquireBus(&I2CD1);
    i2cMasterTransmit(&I2CD1, addr >> 1, regAddr, 3, rxdata, 2);
    i2cReleaseBus(&I2CD1);

    chThdSleepMilliseconds(10);
  }
}


THE difference is that it is a C program not a C++ one.

Giovanni
DrunkenDonkey
Posts: 124
Joined: Sun Aug 28, 2011 5:16 pm

Re: I2C Problem with STM32F4DISCOVERY in v2.4.0

Post by DrunkenDonkey »

I have to add I have never seen issue when transmitting a single byte over i2c, receiving one is mission impossible tho. Using 2.4.0 stable too.
ps: And for completeness - the same brand logic analyzer as you - Logic16 :D
Post Reply