I2C implementation for STM32
Re: I2C implementation for STM32
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.
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.
Re: I2C implementation for STM32
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.
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.
- 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
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
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
Re: I2C implementation for STM32
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!
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!
Re: I2C implementation for STM32
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
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
Re: I2C implementation for STM32
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.
- 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
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
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
Giovanni
Re: I2C implementation for STM32
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):
This produces the following bit train

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

The MAX7311 doesn't react to his command, maybe because of the spikes.
- 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
It is interesting the spike in the 3rd column, is that supposed to be a stop condition?
Giovanni
Giovanni
Re: I2C implementation for STM32
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