I2C implementation for STM32

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.
User avatar
barthess
Posts: 861
Joined: Wed Dec 08, 2010 7:55 pm
Been thanked: 7 times

Re: I2C implementation for STM32

Post by barthess »

Hi.
I have realized GPT "waiting" method. It works, but now I have not any free GPTs to test functionality with IRQ storm in my real application. Polling wait method also realized -- you can switch it on by setting STM32_I2C_I2C1_USE_POLLING_WAIT and STM32_I2C_I2C2_USE_POLLING_WAIT to TRUE.
User avatar
barthess
Posts: 861
Joined: Wed Dec 08, 2010 7:55 pm
Been thanked: 7 times

Re: I2C implementation for STM32

Post by barthess »

Hi, Matis.
I can not say "stable" in relation to driver, because I2C cell in STM32 is too problematic. Driver huge and ugly but it works in my project. Anyway, you can backport driver in stable branch of ChibiOS. About new stable OS version it is better to ask Giovanni.
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 implementation for STM32

Post by Giovanni »

Hi Matis,

Barthess is right, the driver seems to be functional in its current state and could easily be back-ported to the stable version.

I cannot say if it will be integrated in its current form because the STM32 I2C cell is proving really troublesome, I am considering to try a switch to an I2C driver model without callbacks in order to allow simpler implementations (I wish feedback about this) and save space. Anyway, the plan is to have a working I2C subsystem in 2.4.x.

About ChibiOS 2.2.1, I recommend updating to the latest stable version.

Giovanni
matis
Posts: 53
Joined: Fri Jul 01, 2011 1:46 pm

Re: I2C implementation for STM32

Post by matis »

Thanks guys for your extensive replies. I downloaded the ChibiOS 2.2.6 from SVN and will port the existing code to that version.

After that I'll look into backporting the I2C development into the project. then I'll test it for its stability and maturity.

Thanks so far for your replies :)

Happy Coding!
berkenb
Posts: 3
Joined: Mon Mar 21, 2011 2:44 am

Re: I2C implementation for STM32

Post by berkenb »

FIrst of all: great work on the I2C driver for STM32!
Regarding Giovannis proposal to switch to an I2C driver model without callbacks: I vote strongly for this. I realize that Barthless' approach is much more flexible and powerfull, but I find that in many applications a simple blocking read/write in a separate thread does the job just as well with a lot less overhead for setting up callbacks and such.
I have been using a really old implementation by Balázs (described in the old forum at http://sourceforge.net/projects/chibios ... ic/3763912) and even shoe-horned it into ChibiOS 2.2.x.
It would be nice to have I2C officially supported by the OS considering the large number of sensors/peripherals using it.
Marko
User avatar
barthess
Posts: 861
Joined: Wed Dec 08, 2010 7:55 pm
Been thanked: 7 times

Re: I2C implementation for STM32

Post by barthess »

I spent way too much effort to implement callback based driver to vote against it. But my earliest realization was synchronous and used blocking read/write. Is it possible to include in OS both this drivers with possibility to select between them? If yes, than I can dig into the depths of repository and revive it.
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 implementation for STM32

Post by Giovanni »

I understand your position Barthess, in general I prefer drivers based to callback too.

The problem is that the driver grew unreasonably large and complicated, Of course it is not your fault, it is the STM32 I2C peripheral that requires way too many workarounds, special cases etc and we still have to try to use the DMA, probably it would become even larger.

An intermediate solution could be to offer a synchronous API as default and an optional callback-based API if the LLD implementation supports it. Then we could have two STM32 implementations, a simplified synchronous-only one and the current one as an alternative.

The LLD could export a macro HAL_I2C_SUPPORTS_CALLBACKS, the HLD would switch the asynchronous functions on and off depending on what the LLD supports.

This would also enable my idea of offering a generic cross platform bit-banged driver, it would be synchronous only of course.

Please don't start implementing it right away :-) we are just discussing options.

Giovanni
matis
Posts: 53
Joined: Fri Jul 01, 2011 1:46 pm

Re: I2C implementation for STM32

Post by matis »

Yesterday I checked out the i2c_dev branch from SVN for testing. I used the testhal/I2C demo as a guideline to control my MAX7311.
On the MAX7311 we have port IO08 to IO15 connected as status output. The chip is on physical address 0x48 so logical address 0x24. As a test I want to set all the status outputs high during boot / initialization.

To (theoretically) aquire that, I have the following code (simplified):

Code: Select all

/* main.c */
int main(void)
{
   halInit();
   chSysInit();
   I2CInit_pns();
   while (TRUE)
   {
      chThdSleepMilliseconds(500);
   }
}


Code: Select all

/* i2c_handler.c */
/* I2C1 */
static const I2CConfig i2cfg1 = {
      .op_mode = OPMODE_I2C,
      .clock_speed = 100000,
      .duty_cycle = STD_DUTY_CYCLE,
      .own_addr_7 = 0,
      .own_addr_10 = 0,
      .ack = 1,
      .nbit_own_addr = 0,
};
void I2CInit_pns(void)
{
   i2cInit();
   i2cStart(&I2CD1, &i2cfg1);
#if 0
   /* Forced in board.h */
   /* tune ports for I2C1*/
   palSetPadMode(IOPORT2, 6, PAL_MODE_STM32_ALTERNATE_OPENDRAIN);
   palSetPadMode(IOPORT2, 7, PAL_MODE_STM32_ALTERNATE_OPENDRAIN);
#endif
   /* startups. Pauses added just to be safe */
   chThdSleepMilliseconds(100);
   init_max7311();
   chThdSleepMilliseconds(100);
}


Code: Select all

/* max7311.c */
#define max7311_addr 0x24

void init_max7311(void)
{
#define RXBYTES 0
#define TXBYTES 4
   max7311_tx_data[0] = 0x07; /* Config register IO08 - IO15*/
   max7311_tx_data[1] = 0xFF; /* Set IO08-IO15 as output */
   max7311_tx_data[2] = 0x03; /* Output register IO08 - IO15*/
   max7311_tx_data[3] = 0xFF; /* Set IO08 - IO15 high */

   /* transmit out 4 bytes */
   i2cAcquireBus(&I2CD1);
   i2cMasterTransmit(&I2CD1, &max7311, max7311_addr, max7311_tx_data, TXBYTES, max7311_rx_data, RXBYTES);
   while (I2CD1.id_state != I2C_READY)
   {
      chThdSleepMilliseconds(1);
   }
   i2cReleaseBus(&I2CD1);
#undef RXBYTES
#undef TXBYTES
}


This produces the following bit train
Image

The MAX7311 doesn't react to his command, maybe because of the spikes.
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 implementation for STM32

Post by Giovanni »

It is interesting the spike in the 3rd column, is that supposed to be a stop condition?

Giovanni
matis
Posts: 53
Joined: Fri Jul 01, 2011 1:46 pm

Re: I2C implementation for STM32

Post by matis »

Giovanni wrote:It is interesting the spike in the 3rd column, is that supposed to be a stop condition?

Giovanni

Giovanni,

I think that's the ACK from the MAX7311 (thus slave). That should be triggered at falling edge of bit 9 (0 indexed with Start condition as bit 0).
If it is indeed an ACK from the slave, that makes it weird, that there is no spike after the COMMAND BYTE (bit 19). That might be the resolution of the scope. The PORT DATA 1 and PORT DATA 2 are both ACKed at bit 26 and 37 respectively.

I'll enhance the resolution of the scope and get back to you :)
Post Reply