Closed mikepurvis closed 8 years ago
Comparing the two init functions reveals that the HAL version initializes more register values than the standard peripheral version. Notably:
ENGC
in I2C_CR1
(general call mode) is configured.NOSTRETCH
in I2C_CR1
is configured.ACK
in I2C_CR1
is not configured.I2C_OAR2
(own address 2) is configured.Also perhaps notable is that I2C_CR1
and I2C_OAR1
in the standard peripheral library are configured while the peripheral is enabled. In the HAL they leave it disabled while configuring those two registers.
ENGC
can be configured in stdperiph by calling I2C_GeneralCallCmd()
, NOSTRETCH
by calling I2C_StretchClockCmd()
and OAR2
can be set by calling I2C_OwnAddress2Config
. It would be interesting to see if calling these three has the same effect as calling the HAL initialiser.
This is a work in progress, but we're dealing with a peripheral which requires a bit-banged initialization sequence (don't ask), so the I2C pins are being brought up first as GPIOs, and then afterward as hardware I2C. This shouldn't be a problem, but the I2C peripheral seems to get into a nasty loop where it reports bus-error status and all writes fail, even after a peripheral reset (#136) clears the BERR flag.
However, the really interesting thing about this is that linking in a separate translation unit that uses the ST HAL 1.8.0 library allows me to use their I2C initialization functions. The following invocation, called between the stm32plus I2C initialization, and actual use of the peripheral, corrects the issue:
Note that the peripheral reset is required; without it the second initialization fails. And it also isn't enough to put the reset ahead of the stm32plus I2C initialization. There's something in the
HAL_I2C_Init
function that is more thorough than the stdperiph routine which backs stm32plus. It'd be great to figure out what it is.For reference, I've gisted the HAL source: https://gist.github.com/mikepurvis/d7c52178d41ba6565700#file-stm32f4xx_hal_i2c-c-L289