Skip to content

Commit 66f7683

Browse files
kenbelldeadprogram
authored andcommitted
stm32: fix i2c and add stm32f407 i2c
1 parent 24976a6 commit 66f7683

File tree

4 files changed

+99
-15
lines changed

4 files changed

+99
-15
lines changed

src/machine/board_stm32f4disco.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,15 @@ var (
6666
}
6767
SPI1 = &SPI0
6868
)
69+
70+
const (
71+
I2C0_SCL_PIN = PB6
72+
I2C0_SDA_PIN = PB9
73+
)
74+
75+
var (
76+
I2C0 = I2C{
77+
Bus: stm32.I2C1,
78+
AltFuncSelector: AF4_I2C1_2_3,
79+
}
80+
)

src/machine/i2c.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// +build avr nrf sam stm32,!stm32f407,!stm32f7x2,!stm32l5x2,!stm32l0 fe310 k210
1+
// +build avr nrf sam stm32,!stm32f7x2,!stm32l5x2,!stm32l0 fe310 k210
22

33
package machine
44

src/machine/machine_stm32_i2c.go

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// +build stm32,!stm32f103,!stm32f407,!stm32f7x2,!stm32l5x2,!stm32l0
1+
// +build stm32,!stm32f103,!stm32f7x2,!stm32l5x2,!stm32l0
22

33
package machine
44

@@ -151,7 +151,7 @@ func (i2c I2C) Configure(config I2CConfig) error {
151151
i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_ENGC | stm32.I2C_CR1_NOSTRETCH)
152152

153153
// enable I2C interface
154-
i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_PE)
154+
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_PE)
155155

156156
return nil
157157
}
@@ -161,9 +161,13 @@ func (i2c I2C) Tx(addr uint16, w, r []byte) error {
161161
if err := i2c.controllerTransmit(addr, w); nil != err {
162162
return err
163163
}
164-
if err := i2c.controllerReceive(addr, r); nil != err {
165-
return err
164+
165+
if len(r) > 0 {
166+
if err := i2c.controllerReceive(addr, r); nil != err {
167+
return err
168+
}
166169
}
170+
167171
return nil
168172
}
169173

@@ -173,11 +177,6 @@ func (i2c I2C) controllerTransmit(addr uint16, w []byte) error {
173177
return errI2CBusReadyTimeout
174178
}
175179

176-
// ensure peripheral is enabled
177-
if !i2c.Bus.CR1.HasBits(stm32.I2C_CR1_PE) {
178-
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_PE)
179-
}
180-
181180
// disable POS
182181
i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_POS)
183182

@@ -256,11 +255,6 @@ func (i2c I2C) controllerReceive(addr uint16, r []byte) error {
256255
return errI2CBusReadyTimeout
257256
}
258257

259-
// ensure peripheral is enabled
260-
if !i2c.Bus.CR1.HasBits(stm32.I2C_CR1_PE) {
261-
i2c.Bus.CR1.SetBits(stm32.I2C_CR1_PE)
262-
}
263-
264258
// disable POS
265259
i2c.Bus.CR1.ClearBits(stm32.I2C_CR1_POS)
266260

src/machine/machine_stm32f407.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,81 @@ func (spi SPI) configurePins(config SPIConfig) {
120120
config.SDO.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDO}, spi.AltFuncSelector)
121121
config.SDI.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDI}, spi.AltFuncSelector)
122122
}
123+
124+
// -- I2C ----------------------------------------------------------------------
125+
126+
type I2C struct {
127+
Bus *stm32.I2C_Type
128+
AltFuncSelector uint8
129+
}
130+
131+
func (i2c I2C) configurePins(config I2CConfig) {
132+
config.SCL.ConfigureAltFunc(PinConfig{Mode: PinModeI2CSCL}, i2c.AltFuncSelector)
133+
config.SDA.ConfigureAltFunc(PinConfig{Mode: PinModeI2CSDA}, i2c.AltFuncSelector)
134+
}
135+
136+
func (i2c I2C) getFreqRange(config I2CConfig) uint32 {
137+
// all I2C interfaces are on APB1 (42 MHz)
138+
clock := CPUFrequency() / 4
139+
// convert to MHz
140+
clock /= 1000000
141+
// must be between 2 MHz (or 4 MHz for fast mode (Fm)) and 50 MHz, inclusive
142+
var min, max uint32 = 2, 50
143+
if config.Frequency > 100000 {
144+
min = 4 // fast mode (Fm)
145+
}
146+
if clock < min {
147+
clock = min
148+
} else if clock > max {
149+
clock = max
150+
}
151+
return clock << stm32.I2C_CR2_FREQ_Pos
152+
}
153+
154+
func (i2c I2C) getRiseTime(config I2CConfig) uint32 {
155+
// These bits must be programmed with the maximum SCL rise time given in the
156+
// I2C bus specification, incremented by 1.
157+
// For instance: in Sm mode, the maximum allowed SCL rise time is 1000 ns.
158+
// If, in the I2C_CR2 register, the value of FREQ[5:0] bits is equal to 0x08
159+
// and PCLK1 = 125 ns, therefore the TRISE[5:0] bits must be programmed with
160+
// 09h (1000 ns / 125 ns = 8 + 1)
161+
freqRange := i2c.getFreqRange(config)
162+
if config.Frequency > 100000 {
163+
// fast mode (Fm) adjustment
164+
freqRange *= 300
165+
freqRange /= 1000
166+
}
167+
return (freqRange + 1) << stm32.I2C_TRISE_TRISE_Pos
168+
}
169+
170+
func (i2c I2C) getSpeed(config I2CConfig) uint32 {
171+
ccr := func(pclk uint32, freq uint32, coeff uint32) uint32 {
172+
return (((pclk - 1) / (freq * coeff)) + 1) & stm32.I2C_CCR_CCR_Msk
173+
}
174+
sm := func(pclk uint32, freq uint32) uint32 { // standard mode (Sm)
175+
if s := ccr(pclk, freq, 2); s < 4 {
176+
return 4
177+
} else {
178+
return s
179+
}
180+
}
181+
fm := func(pclk uint32, freq uint32, duty uint8) uint32 { // fast mode (Fm)
182+
if duty == DutyCycle2 {
183+
return ccr(pclk, freq, 3)
184+
} else {
185+
return ccr(pclk, freq, 25) | stm32.I2C_CCR_DUTY
186+
}
187+
}
188+
// all I2C interfaces are on APB1 (42 MHz)
189+
clock := CPUFrequency() / 4
190+
if config.Frequency <= 100000 {
191+
return sm(clock, config.Frequency)
192+
} else {
193+
s := fm(clock, config.Frequency, config.DutyCycle)
194+
if (s & stm32.I2C_CCR_CCR_Msk) == 0 {
195+
return 1
196+
} else {
197+
return s | stm32.I2C_CCR_F_S
198+
}
199+
}
200+
}

0 commit comments

Comments
 (0)