stm32: fix i2c and add stm32f407 i2c
Этот коммит содержится в:
родитель
24976a6974
коммит
66f76833ad
4 изменённых файлов: 99 добавлений и 15 удалений
|
@ -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,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче