Browse Source

stm32: fix i2c and add stm32f407 i2c

pull/1674/head
Kenneth Bell 4 years ago
committed by Ron Evans
parent
commit
66f76833ad
  1. 12
      src/machine/board_stm32f4disco.go
  2. 2
      src/machine/i2c.go
  3. 22
      src/machine/machine_stm32_i2c.go
  4. 78
      src/machine/machine_stm32f407.go

12
src/machine/board_stm32f4disco.go

@ -66,3 +66,15 @@ var (
} }
SPI1 = &SPI0 SPI1 = &SPI0
) )
const (
I2C0_SCL_PIN = PB6
I2C0_SDA_PIN = PB9
)
var (
I2C0 = I2C{
Bus: stm32.I2C1,
AltFuncSelector: AF4_I2C1_2_3,
}
)

2
src/machine/i2c.go

@ -1,4 +1,4 @@
// +build avr nrf sam stm32,!stm32f407,!stm32f7x2,!stm32l5x2,!stm32l0 fe310 k210 // +build avr nrf sam stm32,!stm32f7x2,!stm32l5x2,!stm32l0 fe310 k210
package machine package machine

22
src/machine/machine_stm32_i2c.go

@ -1,4 +1,4 @@
// +build stm32,!stm32f103,!stm32f407,!stm32f7x2,!stm32l5x2,!stm32l0 // +build stm32,!stm32f103,!stm32f7x2,!stm32l5x2,!stm32l0
package machine package machine
@ -151,7 +151,7 @@ func (i2c I2C) Configure(config I2CConfig) error {
i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_ENGC | stm32.I2C_CR1_NOSTRETCH) i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_ENGC | stm32.I2C_CR1_NOSTRETCH)
// enable I2C interface // enable I2C interface
i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_PE) i2c.Bus.CR1.SetBits(stm32.I2C_CR1_PE)
return nil return nil
} }
@ -161,9 +161,13 @@ func (i2c I2C) Tx(addr uint16, w, r []byte) error {
if err := i2c.controllerTransmit(addr, w); nil != err { if err := i2c.controllerTransmit(addr, w); nil != err {
return err return err
} }
if err := i2c.controllerReceive(addr, r); nil != err {
return err if len(r) > 0 {
if err := i2c.controllerReceive(addr, r); nil != err {
return err
}
} }
return nil return nil
} }
@ -173,11 +177,6 @@ func (i2c I2C) controllerTransmit(addr uint16, w []byte) error {
return errI2CBusReadyTimeout return errI2CBusReadyTimeout
} }
// ensure peripheral is enabled
if !i2c.Bus.CR1.HasBits(stm32.I2C_CR1_PE) {
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_PE)
}
// disable POS // disable POS
i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_POS) i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_POS)
@ -256,11 +255,6 @@ func (i2c I2C) controllerReceive(addr uint16, r []byte) error {
return errI2CBusReadyTimeout return errI2CBusReadyTimeout
} }
// ensure peripheral is enabled
if !i2c.Bus.CR1.HasBits(stm32.I2C_CR1_PE) {
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_PE)
}
// disable POS // disable POS
i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_POS) i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_POS)

78
src/machine/machine_stm32f407.go

@ -120,3 +120,81 @@ func (spi SPI) configurePins(config SPIConfig) {
config.SDO.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDO}, spi.AltFuncSelector) config.SDO.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDO}, spi.AltFuncSelector)
config.SDI.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDI}, spi.AltFuncSelector) config.SDI.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDI}, spi.AltFuncSelector)
} }
// -- I2C ----------------------------------------------------------------------
type I2C struct {
Bus *stm32.I2C_Type
AltFuncSelector uint8
}
func (i2c I2C) configurePins(config I2CConfig) {
config.SCL.ConfigureAltFunc(PinConfig{Mode: PinModeI2CSCL}, i2c.AltFuncSelector)
config.SDA.ConfigureAltFunc(PinConfig{Mode: PinModeI2CSDA}, i2c.AltFuncSelector)
}
func (i2c I2C) getFreqRange(config I2CConfig) uint32 {
// all I2C interfaces are on APB1 (42 MHz)
clock := CPUFrequency() / 4
// convert to MHz
clock /= 1000000
// must be between 2 MHz (or 4 MHz for fast mode (Fm)) and 50 MHz, inclusive
var min, max uint32 = 2, 50
if config.Frequency > 100000 {
min = 4 // fast mode (Fm)
}
if clock < min {
clock = min
} else if clock > max {
clock = max
}
return clock << stm32.I2C_CR2_FREQ_Pos
}
func (i2c I2C) getRiseTime(config I2CConfig) uint32 {
// These bits must be programmed with the maximum SCL rise time given in the
// I2C bus specification, incremented by 1.
// For instance: in Sm mode, the maximum allowed SCL rise time is 1000 ns.
// If, in the I2C_CR2 register, the value of FREQ[5:0] bits is equal to 0x08
// and PCLK1 = 125 ns, therefore the TRISE[5:0] bits must be programmed with
// 09h (1000 ns / 125 ns = 8 + 1)
freqRange := i2c.getFreqRange(config)
if config.Frequency > 100000 {
// fast mode (Fm) adjustment
freqRange *= 300
freqRange /= 1000
}
return (freqRange + 1) << stm32.I2C_TRISE_TRISE_Pos
}
func (i2c I2C) getSpeed(config I2CConfig) uint32 {
ccr := func(pclk uint32, freq uint32, coeff uint32) uint32 {
return (((pclk - 1) / (freq * coeff)) + 1) & stm32.I2C_CCR_CCR_Msk
}
sm := func(pclk uint32, freq uint32) uint32 { // standard mode (Sm)
if s := ccr(pclk, freq, 2); s < 4 {
return 4
} else {
return s
}
}
fm := func(pclk uint32, freq uint32, duty uint8) uint32 { // fast mode (Fm)
if duty == DutyCycle2 {
return ccr(pclk, freq, 3)
} else {
return ccr(pclk, freq, 25) | stm32.I2C_CCR_DUTY
}
}
// all I2C interfaces are on APB1 (42 MHz)
clock := CPUFrequency() / 4
if config.Frequency <= 100000 {
return sm(clock, config.Frequency)
} else {
s := fm(clock, config.Frequency, config.DutyCycle)
if (s & stm32.I2C_CCR_CCR_Msk) == 0 {
return 1
} else {
return s | stm32.I2C_CCR_F_S
}
}
}

Loading…
Cancel
Save