machine: make machine_stm32f407.go equivalent to machine_stm32f405.go
The only differences are a more general SPI.getBaudRate and a different frequency limit in I2C.getFreqRange. This is a first step towards adding stm32f469 support: a follow-up merges machine_stm32f407.go and machine_stm32f405.go, another adds frequency tweaks for stm32f469.
Этот коммит содержится в:
родитель
a4f9e5e552
коммит
81dbbc89d3
1 изменённых файлов: 38 добавлений и 45 удалений
|
@ -1,3 +1,4 @@
|
||||||
|
//go:build stm32f407
|
||||||
// +build stm32f407
|
// +build stm32f407
|
||||||
|
|
||||||
package machine
|
package machine
|
||||||
|
@ -6,6 +7,7 @@ package machine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"device/stm32"
|
"device/stm32"
|
||||||
|
"math/bits"
|
||||||
)
|
)
|
||||||
|
|
||||||
func CPUFrequency() uint32 {
|
func CPUFrequency() uint32 {
|
||||||
|
@ -80,57 +82,48 @@ func (spi SPI) config8Bits() {
|
||||||
// no-op on this series
|
// no-op on this series
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set baud rate for SPI
|
|
||||||
func (spi SPI) getBaudRate(config SPIConfig) uint32 {
|
|
||||||
var conf uint32
|
|
||||||
|
|
||||||
localFrequency := config.Frequency
|
|
||||||
if spi.Bus != stm32.SPI1 {
|
|
||||||
// Assume it's SPI2 or SPI3 on APB1 at 1/2 the clock frequency of APB2, so
|
|
||||||
// we want to pretend to request 2x the baudrate asked for
|
|
||||||
localFrequency = localFrequency * 2
|
|
||||||
}
|
|
||||||
|
|
||||||
// set frequency dependent on PCLK prescaler. Since these are rather weird
|
|
||||||
// speeds due to the CPU freqency, pick a range up to that frquency for
|
|
||||||
// clients to use more human-understandable numbers, e.g. nearest 100KHz
|
|
||||||
|
|
||||||
// These are based on APB2 clock frquency (84MHz on the discovery board)
|
|
||||||
// TODO: also include the MCU/APB clock setting in the equation
|
|
||||||
switch true {
|
|
||||||
case localFrequency < 328125:
|
|
||||||
conf = stm32.SPI_CR1_BR_Div256
|
|
||||||
case localFrequency < 656250:
|
|
||||||
conf = stm32.SPI_CR1_BR_Div128
|
|
||||||
case localFrequency < 1312500:
|
|
||||||
conf = stm32.SPI_CR1_BR_Div64
|
|
||||||
case localFrequency < 2625000:
|
|
||||||
conf = stm32.SPI_CR1_BR_Div32
|
|
||||||
case localFrequency < 5250000:
|
|
||||||
conf = stm32.SPI_CR1_BR_Div16
|
|
||||||
case localFrequency < 10500000:
|
|
||||||
conf = stm32.SPI_CR1_BR_Div8
|
|
||||||
// NOTE: many SPI components won't operate reliably (or at all) above 10MHz
|
|
||||||
// Check the datasheet of the part
|
|
||||||
case localFrequency < 21000000:
|
|
||||||
conf = stm32.SPI_CR1_BR_Div4
|
|
||||||
case localFrequency < 42000000:
|
|
||||||
conf = stm32.SPI_CR1_BR_Div2
|
|
||||||
default:
|
|
||||||
// None of the specific baudrates were selected; choose the lowest speed
|
|
||||||
conf = stm32.SPI_CR1_BR_Div256
|
|
||||||
}
|
|
||||||
|
|
||||||
return conf << stm32.SPI_CR1_BR_Pos
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure SPI pins for input output and clock
|
|
||||||
func (spi SPI) configurePins(config SPIConfig) {
|
func (spi SPI) configurePins(config SPIConfig) {
|
||||||
config.SCK.ConfigureAltFunc(PinConfig{Mode: PinModeSPICLK}, spi.AltFuncSelector)
|
config.SCK.ConfigureAltFunc(PinConfig{Mode: PinModeSPICLK}, spi.AltFuncSelector)
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (spi SPI) getBaudRate(config SPIConfig) uint32 {
|
||||||
|
var clock uint32
|
||||||
|
switch spi.Bus {
|
||||||
|
case stm32.SPI1:
|
||||||
|
clock = CPUFrequency() / 2
|
||||||
|
case stm32.SPI2, stm32.SPI3:
|
||||||
|
clock = CPUFrequency() / 4
|
||||||
|
}
|
||||||
|
|
||||||
|
// limit requested frequency to bus frequency and min frequency (DIV256)
|
||||||
|
freq := config.Frequency
|
||||||
|
if min := clock / 256; freq < min {
|
||||||
|
freq = min
|
||||||
|
} else if freq > clock {
|
||||||
|
freq = clock
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate the exact clock divisor (freq=clock/div -> div=clock/freq).
|
||||||
|
// truncation is fine, since it produces a less-than-or-equal divisor, and
|
||||||
|
// thus a greater-than-or-equal frequency.
|
||||||
|
// divisors only come in consecutive powers of 2, so we can use log2 (or,
|
||||||
|
// equivalently, bits.Len - 1) to convert to respective enum value.
|
||||||
|
div := bits.Len32(clock/freq) - 1
|
||||||
|
|
||||||
|
// but DIV1 (2^0) is not permitted, as the least divisor is DIV2 (2^1), so
|
||||||
|
// subtract 1 from the log2 value, keeping a lower bound of 0
|
||||||
|
if div < 0 {
|
||||||
|
div = 0
|
||||||
|
} else if div > 0 {
|
||||||
|
div--
|
||||||
|
}
|
||||||
|
|
||||||
|
// finally, shift the enumerated value into position for SPI CR1
|
||||||
|
return uint32(div) << stm32.SPI_CR1_BR_Pos
|
||||||
|
}
|
||||||
|
|
||||||
// -- I2C ----------------------------------------------------------------------
|
// -- I2C ----------------------------------------------------------------------
|
||||||
|
|
||||||
type I2C struct {
|
type I2C struct {
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче