[DONE] I2C driver for STM32F0

This forum is dedicated to feedback, discussions about ongoing or future developments, ideas and suggestions regarding the ChibiOS projects are welcome. This forum is NOT for support.
steved
Posts: 834
Joined: Fri Nov 09, 2012 2:22 pm
Has thanked: 12 times
Been thanked: 138 times

[DONE] I2C driver for STM32F0

Post by steved »

Is anyone already working on this driver? If so, I'll be happy to help test.

Otherwise, I might have a go myself, but definitely the wrong person to be doing it (very new to both Chibios and STM32 family, so would need all the help I could get!)

(From comments in the forum, sounds as if the same driver would be needed for some of the new STM32F3xx devices)
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: I2C driver for STM32F0

Post by Giovanni »

Hi,

Correct, the F3 has the same I2C peripheral of the F0, if somebody else does not step up I will give it a try after finishing the current work on the SAM4L.

Giovanni
doceme
Posts: 4
Joined: Wed Feb 06, 2013 6:06 am

Re: I2C driver for STM32F0

Post by doceme »

steved, I made an attempt to add support for I2Cv2 found in STM32F0xx and STM32F3xx chips. I added a feature request to the SourceForge tracker page and uploaded my patch. Feel free to give it a try. Only master mode is supported. The tracker ID is 3603507.
vibrolax
Posts: 9
Joined: Sat Jan 05, 2013 3:23 pm

Re: I2C driver for STM32F0

Post by vibrolax »

doceme,

Thanks for providing this. I will try this on my STM32F3Discovery sometime next week.

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

Re: I2C driver for STM32F0

Post by Giovanni »

Could you post it as a zip file in the contributions forum? I will look into integrating it in the main line when I will have some time. In the meanwhile I would appreciate any feedback.

thanks,
Giovanni
steved
Posts: 834
Joined: Fri Nov 09, 2012 2:22 pm
Has thanked: 12 times
Been thanked: 138 times

Re: I2C driver for STM32F0

Post by steved »

doceme,

Thankyou for doing this - I did start to look at it in odd moments, but never really got beyond the timing register!

I've tested this talking to two different devices - a DS1340 TOD clock, and a FM24V02 32Kbyte FRAM. I think only at 100kbit/sec on the I2C (assuming I've worked out the timing register data correctly - will check later). All basically seems OK. (Using an STM32F051 Discovery as the base).

There seems to be a slight interaction with the serial on UART1 - I'm using serial to report progress, and I got some odd things happening. No serial data would appear if I just ran the code straight through - but if I put a breakpoint after the I2C initialisation, and ran from there, serial worked fine! Sending some serial data prior to initialising the I2C seemed to solve the problem. Tentative theory is that there's some sort of DMA channel conflict. Something to investigate further.

And a slight gotcha (to a newbie, anyway) - size_t is a byte, so 258-byte transfers don't work very well....

The timeout is working - aborts transaction if its taking too long.

Anyway, all looking good so far. Certainly working well enough to commit to SVN, IMO.

Edit: Now also tested at nominal 400kHz (using values from Table 72 on page 538 of the manual), and down at around 20kHz - all fine.
goeck
Posts: 92
Joined: Mon Feb 11, 2013 12:00 pm

Re: I2C driver for STM32F0

Post by goeck »

Hey guys,

I want to use I2C on STM32F0... I found, the compiler throughs "i2c_lld.h missing" at me all the time.
When can the driver be used, When is it in trunk? ...or is it actually, so it's my fault?

Keep it up!
Cheers
Stefan
steved
Posts: 834
Joined: Fri Nov 09, 2012 2:22 pm
Has thanked: 12 times
Been thanked: 138 times

Re: I2C driver for STM32F0

Post by steved »

goeck wrote:I want to use I2C on STM32F0... I found, the compiler throughs "i2c_lld.h missing" at me all the time.
When can the driver be used, When is it in trunk? ...or is it actually, so it's my fault?

The driver isn't in the trunk; its only just been ported to the STM32F0 by doceme, and the link to his patch is a few post up in this thread. I've been running it on the latest SVN; not sure if it would also work on 2.4x
The patch adds a new I2Cv2 subdirectory to the STM32 platform, and modifies the STM32F0 makefile to include it.
goeck
Posts: 92
Joined: Mon Feb 11, 2013 12:00 pm

Re: I2C driver for STM32F0

Post by goeck »

Hey steved,

thanks for the hints. I got it up and running. Had to figure out why TortoiseSVN would'nt apply the patch properly...use TortoiseMerge directly. Enable I2C in halconf.h and mcuconf.h files. Ok..done.
Now I have the following sequence:

Code: Select all

static const I2CConfig i2cconfig = {  100000  };
i2cInit();
palSetPadMode(GPIOB, 6, PAL_MODE_ALTERNATE(1));       // I2C SCL
palSetPadMode(GPIOB, 7, PAL_MODE_ALTERNATE(1));       // I2C SDA
i2cStart(&I2CD1, &i2cconfig);

i2cAcquireBus(&I2CD1);
i2cMasterTransmitTimeout(&I2CD1, 0xC0>>1, txBuf, 2, rxBuf, 0, TIME_INFINITE);
i2cReleaseBus(&I2CD1);

i2cStop(&I2CD1);


It gives me the slave adress (0xC0) on the bus wires, indicating write, but no payload gets transmitted. Anything wrong here?

EDIT:
OK, here we have the little bast***.
I had to change the speed in order to get more than one byte pumped out on the bus wires since the I2C engine seems to stops polluting the bus when nobody aknowldges the sent bytes. Because wiring had to be improved, but most of all because my slaves dont understand that fast communication (800KHz measured) and stay quitly therefor, I had to lower the speed to previously used 100KHz (with AVRs). This had to be done by

Code: Select all

static I2CConfig i2cconfig;
i2cconfig.clock_timing = 0x1045061D;

The timing value comes from ST sample code and the St I2C config utility (xls).
Also the I2CConfig struct looks different than it had to be used. I don't get the structure here, but in i2c_lld.c it is obvious that this is the way to go right now.

Thanks for the help!
Cheers
steved
Posts: 834
Joined: Fri Nov 09, 2012 2:22 pm
Has thanked: 12 times
Been thanked: 138 times

Re: I2C driver for STM32F0

Post by steved »

Hi goek, glad you've got something happening.

I used the following initialisation:

Code: Select all

static const I2CConfig i2cfg1 = {
    OPMODE_I2C,
    0x10420f13,     // clock timing - 100kHz with 8MHz clock
  //0x00310309,     // Hopefully 400kHz
                    // Just scale bits 28..31 if not 8MHz clock
    0,              // CR1
    0,              // CR2
};
  i2cInit();

  i2cStart(&I2CD1, &i2cfg1);

  /* tune ports for I2C1*/
  palSetPadMode(IOPORT2, 6, PAL_STM32_OTYPE_OPENDRAIN | PAL_MODE_ALTERNATE(1));
  palSetPadMode(IOPORT2, 7, PAL_STM32_OTYPE_OPENDRAIN | PAL_MODE_ALTERNATE(1));

You have to work out your own clock timings now - and having tried to write some code to calculate them, I can see why! (I used a table in the manual to get the values)
I couldn't see any need to initialise CR1 and CR2, so just set them to zero, as you can see.


I've now moved on to talking to a DS2483 one-wire bus driver, and that's highlighted the relative inefficiency of a DMA-driven driver with this type of device. Firstly, a lot of transfers are only a few bytes at most - typically a one or two-byte command, and zero to two bytes returned. So it may be more efficient overall to use interrupts for this type of transfer (ideally, the driver would make the decision of DMA or interrupts for you).

Secondly, there are some sequences in the Dallas example code, looking much as follows:

Code: Select all

   I2C_start();
   I2C_write(I2C_address | I2C_WRITE, EXPECT_ACK);
   I2C_write(CMD_1WRS, EXPECT_ACK);
   I2C_rep_start();
   I2C_write(I2C_address | I2C_READ, EXPECT_ACK);

   // loop checking 1WB bit for completion of 1-Wire operation
   // abort if poll limit reached
   status = I2C_read(ACK);
   do
   {
      status = I2C_read(status & STATUS_1WB);
   }
   while ((status & STATUS_1WB) && (poll_count++ < POLL_LIMIT));

   I2C_stop();

The first part of that code is readily replaced with a standard i2cMasterTransmitTimeout() call.
The 'do' loop is more interesting - in the Dallas code it just keeps on reading bytes until the 'busy' status bit clears, without starting a new bus transaction. Not very practical in an RTOS. I've replaced it with a i2cMasterReceiveTimeout() call, which does the job fine, but seems overkill to read one byte!
I mention this because it seems to me that an interrupt-driven driver might be more use here - a standard driver would need modification to handle the Dallas-specific aspects, but would at least provide a good foundation for the changes.

Anyway, more confirmation that doceme's driver works.
Post Reply