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
|
||||
|
||||
package machine
|
||||
|
@ -6,6 +7,7 @@ package machine
|
|||
|
||||
import (
|
||||
"device/stm32"
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
func CPUFrequency() uint32 {
|
||||
|
@ -80,57 +82,48 @@ func (spi SPI) config8Bits() {
|
|||
// 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) {
|
||||
config.SCK.ConfigureAltFunc(PinConfig{Mode: PinModeSPICLK}, spi.AltFuncSelector)
|
||||
config.SDO.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDO}, 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 ----------------------------------------------------------------------
|
||||
|
||||
type I2C struct {
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче