Browse Source

stm32: use stm32-rs SVDs which are of much higher quality

This commit changes the number of wait states for the stm32f103 chip to
2 instead of 4. This gets it back in line with the datasheet, but it
also has the side effect of breaking I2C. Therefore, another (seemingly
unrelated) change is needed: the i2cTimeout constant must be increased
to a higher value to adjust to the lower flash wait states - presumably
because the lower number of wait states allows the chip to run code
faster.
pull/1537/head
Ayke van Laethem 4 years ago
committed by Ron Evans
parent
commit
154c7c691b
  1. 3
      .gitmodules
  2. 2
      Makefile
  3. 1
      lib/stm32-svd
  4. 57
      src/device/stm32/stm32-moder-bitfields.go
  5. 88
      src/device/stm32/stm32f103xx-bitfields.go
  6. 28
      src/device/stm32/stm32f4-altfunc-bitfields.go
  7. 18
      src/machine/board_feather-stm32f405.go
  8. 2
      src/machine/board_lgt92.go
  9. 4
      src/machine/board_stm32f4disco.go
  10. 6
      src/machine/machine_stm32_i2c.go
  11. 93
      src/machine/machine_stm32_moder_gpio.go
  12. 20
      src/machine/machine_stm32f103.go
  13. 26
      src/machine/machine_stm32f405.go
  14. 42
      src/machine/machine_stm32f407.go
  15. 2
      src/machine/machine_stm32f7x2.go
  16. 28
      src/machine/machine_stm32l0.go
  17. 20
      src/runtime/runtime_stm32f103.go
  18. 18
      src/runtime/runtime_stm32f405.go
  19. 12
      src/runtime/runtime_stm32f407.go
  20. 6
      src/runtime/runtime_stm32f7x2.go
  21. 24
      src/runtime/runtime_stm32l0.go
  22. 4
      targets/bluepill.json
  23. 4
      targets/nucleo-f103rb.json
  24. 84
      tools/gen-device-svd/gen-device-svd.go

3
.gitmodules

@ -20,3 +20,6 @@
[submodule "lib/picolibc"]
path = lib/picolibc
url = https://github.com/keith-packard/picolibc.git
[submodule "lib/stm32-svd"]
path = lib/stm32-svd
url = https://github.com/tinygo-org/stm32-svd

2
Makefile

@ -130,7 +130,7 @@ gen-device-kendryte: build/gen-device-svd
GO111MODULE=off $(GO) fmt ./src/device/kendryte
gen-device-stm32: build/gen-device-svd
./build/gen-device-svd -source=https://github.com/posborne/cmsis-svd/tree/master/data/STMicro lib/cmsis-svd/data/STMicro/ src/device/stm32/
./build/gen-device-svd -source=https://github.com/tinygo-org/stm32-svd lib/stm32-svd/svd src/device/stm32/
GO111MODULE=off $(GO) fmt ./src/device/stm32

1
lib/stm32-svd

@ -0,0 +1 @@
Subproject commit 9ec99824859540e61076a81149019222dc19b780

57
src/device/stm32/stm32-moder-bitfields.go

@ -1,57 +0,0 @@
// Hand created file. DO NOT DELETE.
// STM32FXXX (except stm32f1xx) bitfield definitions that are not
// auto-generated by gen-device-svd.go
// These apply to the stm32 families that use the MODER, OTYPE amd PUPDR
// registers for managing GPIO functionality.
// Add in other families that use the same settings, e.g. stm32f0xx, etc
// +build stm32,!stm32f103xx
package stm32
// AltFunc represents the alternate function peripherals that can be mapped to
// the GPIO ports. Since these differ by what is supported on the stm32 family
// they are defined in the more specific files
type AltFunc uint8
// Family-wide common post-reset AltFunc. This represents
// normal GPIO operation of the pins
const AF0_SYSTEM AltFunc = 0
const (
// Register values for the chip
// GPIOx_MODER
GPIOModeInput = 0
GPIOModeOutputGeneral = 1
GPIOModeOutputAltFunc = 2
GPIOModeAnalog = 3
// GPIOx_OTYPER
GPIOOutputTypePushPull = 0
GPIOOutputTypeOpenDrain = 1
// GPIOx_OSPEEDR
GPIOSpeedLow = 0
GPIOSpeedMid = 1
GPIOSpeedHigh = 2 // Note: this is also low speed on stm32f0, see RM0091
GPIOSpeedVeryHigh = 3
// GPIOx_PUPDR
GPIOPUPDRFloating = 0
GPIOPUPDRPullUp = 1
GPIOPUPDRPullDown = 2
)
// SPI prescaler values fPCLK / X
const (
SPI_PCLK_2 = 0
SPI_PCLK_4 = 1
SPI_PCLK_8 = 2
SPI_PCLK_16 = 3
SPI_PCLK_32 = 4
SPI_PCLK_64 = 5
SPI_PCLK_128 = 6
SPI_PCLK_256 = 7
)

88
src/device/stm32/stm32f103xx-bitfields.go

@ -1,88 +0,0 @@
// Hand created file. DO NOT DELETE.
// STM32F103XX bitfield definitions that are not auto-generated by gen-device-svd.go
// +build stm32,stm32f103xx
package stm32
const (
// Flash Access Control Register flag values.
FLASH_ACR_LATENCY_0 = 0x00000001
FLASH_ACR_LATENCY_1 = 0x00000002
FLASH_ACR_LATENCY_2 = 0x00000004
// Reset and Clock Control Control Register flag values.
// System Clock source
RCC_CFGR_SW_HSI = 0
RCC_CFGR_SW_HSE = 1
RCC_CFGR_SW_PLL = 2
// Flags for when System Clock source is set.
RCC_CFGR_SWS_HSI = 0x00000000
RCC_CFGR_SWS_HSE = 0x00000004
RCC_CFGR_SWS_PLL = 0x00000008
// Sets PCLK1
RCC_CFGR_PPRE1_DIV_NONE = 0x00000000
RCC_CFGR_PPRE1_DIV_2 = 0x00000400
RCC_CFGR_PPRE1_DIV_4 = 0x00000500
RCC_CFGR_PPRE1_DIV_8 = 0x00000600
RCC_CFGR_PPRE1_DIV_16 = 0x00000700
// Sets PCLK2
RCC_CFGR_PPRE2_DIV_NONE = 0x00000000
RCC_CFGR_PPRE2_DIV_2 = 0x00002000
RCC_CFGR_PPRE2_DIV_4 = 0x00002800
RCC_CFGR_PPRE2_DIV_8 = 0x00003000
RCC_CFGR_PPRE2_DIV_16 = 0x00003800
// Sets PLL multiplier
RCC_CFGR_PLLMUL_2 = 0x00000000
RCC_CFGR_PLLMUL_3 = 0x00040000
RCC_CFGR_PLLMUL_4 = 0x00080000
RCC_CFGR_PLLMUL_5 = 0x000C0000
RCC_CFGR_PLLMUL_6 = 0x00100000
RCC_CFGR_PLLMUL_7 = 0x00140000
RCC_CFGR_PLLMUL_8 = 0x00180000
RCC_CFGR_PLLMUL_9 = 0x001C0000
RCC_CFGR_PLLMUL_10 = 0x00200000
RCC_CFGR_PLLMUL_11 = 0x00240000
RCC_CFGR_PLLMUL_12 = 0x00280000
RCC_CFGR_PLLMUL_13 = 0x002C0000
RCC_CFGR_PLLMUL_14 = 0x00300000
RCC_CFGR_PLLMUL_15 = 0x00340000
RCC_CFGR_PLLMUL_16 = 0x00380000
// RTC clock source
RCC_RTCCLKSource_LSE = 0x00000100
RCC_RTCCLKSource_LSI = 0x00000200
RCC_RTCCLKSource_HSE_Div128 = 0x00000300
// SPI settings
SPI_FirstBit_MSB = 0x0000
SPI_FirstBit_LSB = 0x0080
SPI_BaudRatePrescaler_2 = 0x0000
SPI_BaudRatePrescaler_4 = 0x0008
SPI_BaudRatePrescaler_8 = 0x0010
SPI_BaudRatePrescaler_16 = 0x0018
SPI_BaudRatePrescaler_32 = 0x0020
SPI_BaudRatePrescaler_64 = 0x0028
SPI_BaudRatePrescaler_128 = 0x0030
SPI_BaudRatePrescaler_256 = 0x0038
SPI_Direction_2Lines_FullDuplex = 0x0000
SPI_Direction_2Lines_RxOnly = 0x0400
SPI_Direction_1Line_Rx = 0x8000
SPI_Direction_1Line_Tx = 0xC000
SPI_Mode_Master = 0x0104
SPI_Mode_Slave = 0x0000
SPI_NSS_Soft = 0x0200
SPI_NSS_Hard = 0x0000
SPI_NSSInternalSoft_Set = 0x0100
SPI_NSSInternalSoft_Reset = 0xFEFF
)

28
src/device/stm32/stm32f4-altfunc-bitfields.go

@ -1,28 +0,0 @@
// Hand created file. DO NOT DELETE.
// STM32FXXX (except stm32f1xx) bitfield definitions that are not
// auto-generated by gen-device-svd.go
// +build stm32f4
// Alternate function settings on the stm32f4 series
package stm32
const (
// Alternative peripheral pin functions
// AF0_SYSTEM is defined im the common bitfields package
AF1_TIM1_2 AltFunc = 1
AF2_TIM3_4_5 = 2
AF3_TIM8_9_10_11 = 3
AF4_I2C1_2_3 = 4
AF5_SPI1_SPI2 = 5
AF6_SPI3 = 6
AF7_USART1_2_3 = 7
AF8_USART4_5_6 = 8
AF9_CAN1_CAN2_TIM12_13_14 = 9
AF10_OTG_FS_OTG_HS = 10
AF11_ETH = 11
AF12_FSMC_SDIO_OTG_HS_1 = 12
AF13_DCMI = 13
AF14 = 14
AF15_EVENTOUT = 15
)

18
src/machine/board_feather-stm32f405.go

@ -122,17 +122,17 @@ var (
UART1 = UART{
Buffer: NewRingBuffer(),
Bus: stm32.USART3,
AltFuncSelector: stm32.AF7_USART1_2_3,
AltFuncSelector: AF7_USART1_2_3,
}
UART2 = UART{
Buffer: NewRingBuffer(),
Bus: stm32.USART6,
AltFuncSelector: stm32.AF8_USART4_5_6,
AltFuncSelector: AF8_USART4_5_6,
}
UART3 = UART{
Buffer: NewRingBuffer(),
Bus: stm32.USART1,
AltFuncSelector: stm32.AF7_USART1_2_3,
AltFuncSelector: AF7_USART1_2_3,
}
UART0 = UART1
)
@ -181,15 +181,15 @@ const (
var (
SPI1 = SPI{
Bus: stm32.SPI2,
AltFuncSelector: stm32.AF5_SPI1_SPI2,
AltFuncSelector: AF5_SPI1_SPI2,
}
SPI2 = SPI{
Bus: stm32.SPI3,
AltFuncSelector: stm32.AF6_SPI3,
AltFuncSelector: AF6_SPI3,
}
SPI3 = SPI{
Bus: stm32.SPI1,
AltFuncSelector: stm32.AF5_SPI1_SPI2,
AltFuncSelector: AF5_SPI1_SPI2,
}
SPI0 = SPI1
)
@ -229,15 +229,15 @@ const (
var (
I2C1 = I2C{
Bus: stm32.I2C1,
AltFuncSelector: stm32.AF4_I2C1_2_3,
AltFuncSelector: AF4_I2C1_2_3,
}
I2C2 = I2C{
Bus: stm32.I2C2,
AltFuncSelector: stm32.AF4_I2C1_2_3,
AltFuncSelector: AF4_I2C1_2_3,
}
I2C3 = I2C{
Bus: stm32.I2C1,
AltFuncSelector: stm32.AF4_I2C1_2_3,
AltFuncSelector: AF4_I2C1_2_3,
}
I2C0 = I2C1
)

2
src/machine/board_lgt92.go

@ -55,7 +55,7 @@ var (
// Console UART (LPUSART1)
UART0 = UART{
Buffer: NewRingBuffer(),
Bus: stm32.LPUSART1,
Bus: stm32.LPUART1,
AltFuncSelector: 6,
}

4
src/machine/board_stm32f4disco.go

@ -30,7 +30,7 @@ var (
UART0 = UART{
Buffer: NewRingBuffer(),
Bus: stm32.USART2,
AltFuncSelector: stm32.AF7_USART1_2_3,
AltFuncSelector: AF7_USART1_2_3,
}
UART1 = &UART0
)
@ -62,7 +62,7 @@ const (
var (
SPI0 = SPI{
Bus: stm32.SPI1,
AltFuncSelector: stm32.AF5_SPI1_SPI2,
AltFuncSelector: AF5_SPI1_SPI2,
}
SPI1 = &SPI0
)

6
src/machine/machine_stm32_i2c.go

@ -1,4 +1,4 @@
// +build stm32,!stm32f103xx,!stm32f407,!stm32f7x2,!stm32l0
// +build stm32,!stm32f103,!stm32f407,!stm32f7x2,!stm32l0
package machine
@ -110,10 +110,10 @@ type (
)
func (sa address7Bit) toRead() uint32 {
return uint32(((uint8(sa) << 1) | uint8(stm32.I2C_OAR1_ADD0)) & 0xFF)
return uint32(((uint8(sa) << 1) | 1) & 0xFF)
}
func (sa address7Bit) toWrite() uint32 {
return uint32(((uint8(sa) << 1) & ^(uint8(stm32.I2C_OAR1_ADD0))) & 0xFF)
return uint32((uint8(sa) << 1) & 0xFF)
}
func (sa address7Bit) bitSize() uint8 { return 7 } // 7-bit addresses

93
src/machine/machine_stm32_moder_gpio.go

@ -1,4 +1,4 @@
// +build stm32,!stm32f103xx
// +build stm32,!stm32f103
package machine
@ -38,85 +38,106 @@ const (
// TBD
)
// Define several bitfields that have different names across chip families but
// essentially have the same meaning.
const (
// MODER bitfields.
gpioModeInput = 0
gpioModeOutput = 1
gpioModeAlternate = 2
gpioModeAnalog = 3
gpioModeMask = 0x3
// PUPDR bitfields.
gpioPullFloating = 0
gpioPullUp = 1
gpioPullDown = 2
gpioPullMask = 0x3
// OSPEED bitfields.
gpioOutputSpeedHigh = 2
gpioOutputSpeedLow = 0
gpioOutputSpeedMask = 0x3
)
// Configure this pin with the given configuration
func (p Pin) Configure(config PinConfig) {
// Use the default system alternate function; this
// will only be used if you try to call this with
// one of the peripheral modes instead of vanilla GPIO.
p.ConfigureAltFunc(config, stm32.AF0_SYSTEM)
p.ConfigureAltFunc(config, 0)
}
// Configure this pin with the given configuration including alternate
// function mapping if necessary.
func (p Pin) ConfigureAltFunc(config PinConfig, altFunc stm32.AltFunc) {
func (p Pin) ConfigureAltFunc(config PinConfig, altFunc uint8) {
// Configure the GPIO pin.
p.enableClock()
port := p.getPort()
pin := uint8(p) % 16
pos := pin * 2
pos := (uint8(p) % 16) * 2 // assume each field is two bits in size (with mask 0x3)
switch config.Mode {
// GPIO
case PinInputFloating:
port.MODER.ReplaceBits(stm32.GPIOModeInput, 0x3, pos)
port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
port.MODER.ReplaceBits(gpioModeInput, gpioModeMask, pos)
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
case PinInputPulldown:
port.MODER.ReplaceBits(stm32.GPIOModeInput, 0x3, pos)
port.PUPDR.ReplaceBits(stm32.GPIOPUPDRPullDown, 0x3, pos)
port.MODER.ReplaceBits(gpioModeInput, gpioModeMask, pos)
port.PUPDR.ReplaceBits(gpioPullDown, gpioPullMask, pos)
case PinInputPullup:
port.MODER.ReplaceBits(stm32.GPIOModeInput, 0x3, pos)
port.PUPDR.ReplaceBits(stm32.GPIOPUPDRPullUp, 0x3, pos)
port.MODER.ReplaceBits(gpioModeInput, gpioModeMask, pos)
port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos)
case PinOutput:
port.MODER.ReplaceBits(stm32.GPIOModeOutputGeneral, 0x3, pos)
port.OSPEEDR.ReplaceBits(stm32.GPIOSpeedHigh, 0x3, pos)
port.MODER.ReplaceBits(gpioModeOutput, gpioModeMask, pos)
port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)
// UART
case PinModeUARTTX:
port.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, pos)
port.OSPEEDR.ReplaceBits(stm32.GPIOSpeedHigh, 0x3, pos)
port.PUPDR.ReplaceBits(stm32.GPIOPUPDRPullUp, 0x3, pos)
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
port.OSPEEDR.ReplaceBits(gpioOutputSpeedHigh, gpioOutputSpeedMask, pos)
port.PUPDR.ReplaceBits(gpioPullUp, gpioPullMask, pos)
p.SetAltFunc(altFunc)
case PinModeUARTRX:
port.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, pos)
port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
p.SetAltFunc(altFunc)
// I2C
case PinModeI2CSCL:
port.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, pos)
port.OTYPER.ReplaceBits(stm32.GPIOOutputTypeOpenDrain, 0x1, pos)
port.OSPEEDR.ReplaceBits(stm32.GPIOSpeedLow, 0x3, pos)
port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
port.OTYPER.ReplaceBits(stm32.GPIO_OTYPER_OT0_OpenDrain, stm32.GPIO_OTYPER_OT0_Msk, pos/2)
port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
p.SetAltFunc(altFunc)
case PinModeI2CSDA:
port.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, pos)
port.OTYPER.ReplaceBits(stm32.GPIOOutputTypeOpenDrain, 0x1, pos)
port.OSPEEDR.ReplaceBits(stm32.GPIOSpeedLow, 0x3, pos)
port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
port.OTYPER.ReplaceBits(stm32.GPIO_OTYPER_OT0_OpenDrain, stm32.GPIO_OTYPER_OT0_Msk, pos/2)
port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
p.SetAltFunc(altFunc)
// SPI
case PinModeSPICLK:
port.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, pos)
port.OSPEEDR.ReplaceBits(stm32.GPIOSpeedLow, 0x3, pos)
port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
p.SetAltFunc(altFunc)
case PinModeSPISDO:
port.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, pos)
port.OSPEEDR.ReplaceBits(stm32.GPIOSpeedLow, 0x3, pos)
port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
p.SetAltFunc(altFunc)
case PinModeSPISDI:
port.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, pos)
port.OSPEEDR.ReplaceBits(stm32.GPIOSpeedLow, 0x3, pos)
port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
port.MODER.ReplaceBits(gpioModeAlternate, gpioModeMask, pos)
port.OSPEEDR.ReplaceBits(gpioOutputSpeedLow, gpioOutputSpeedMask, pos)
port.PUPDR.ReplaceBits(gpioPullFloating, gpioPullMask, pos)
p.SetAltFunc(altFunc)
}
}
// SetAltFunc maps the given alternative function to the I/O pin
func (p Pin) SetAltFunc(af stm32.AltFunc) {
func (p Pin) SetAltFunc(af uint8) {
port := p.getPort()
pin := uint8(p) % 16
pos := (pin % 8) * 4

20
src/machine/machine_stm32f103xx.go → src/machine/machine_stm32f103.go

@ -1,4 +1,4 @@
// +build stm32,stm32f103xx
// +build stm32,stm32f103
package machine
@ -169,21 +169,21 @@ func (spi SPI) getBaudRate(config SPIConfig) uint32 {
switch config.Frequency {
case 125000:
// Note: impossible to achieve lower frequency with current PCLK2!
conf |= stm32.SPI_BaudRatePrescaler_256
conf |= stm32.SPI_CR1_BR_Div256
case 250000:
conf |= stm32.SPI_BaudRatePrescaler_256
conf |= stm32.SPI_CR1_BR_Div256
case 500000:
conf |= stm32.SPI_BaudRatePrescaler_128
conf |= stm32.SPI_CR1_BR_Div128
case 1000000:
conf |= stm32.SPI_BaudRatePrescaler_64
conf |= stm32.SPI_CR1_BR_Div64
case 2000000:
conf |= stm32.SPI_BaudRatePrescaler_32
conf |= stm32.SPI_CR1_BR_Div32
case 4000000:
conf |= stm32.SPI_BaudRatePrescaler_16
conf |= stm32.SPI_CR1_BR_Div16
case 8000000:
conf |= stm32.SPI_BaudRatePrescaler_8
conf |= stm32.SPI_CR1_BR_Div8
default:
conf |= stm32.SPI_BaudRatePrescaler_256
conf |= stm32.SPI_CR1_BR_Div256
}
return conf
}
@ -542,7 +542,7 @@ func (i2c I2C) Tx(addr uint16, w, r []byte) error {
return nil
}
const i2cTimeout = 500
const i2cTimeout = 1000
// signalStart sends a start signal.
func (i2c I2C) signalStart() error {

26
src/machine/machine_stm32f405.go

@ -14,13 +14,33 @@ func CPUFrequency() uint32 {
return 168000000
}
// Alternative peripheral pin functions
const (
AF0_SYSTEM = 0
AF1_TIM1_2 = 1
AF2_TIM3_4_5 = 2
AF3_TIM8_9_10_11 = 3
AF4_I2C1_2_3 = 4
AF5_SPI1_SPI2 = 5
AF6_SPI3 = 6
AF7_USART1_2_3 = 7
AF8_USART4_5_6 = 8
AF9_CAN1_CAN2_TIM12_13_14 = 9
AF10_OTG_FS_OTG_HS = 10
AF11_ETH = 11
AF12_FSMC_SDIO_OTG_HS_1 = 12
AF13_DCMI = 13
AF14 = 14
AF15_EVENTOUT = 15
)
// -- UART ---------------------------------------------------------------------
type UART struct {
Buffer *RingBuffer
Bus *stm32.USART_Type
Interrupt interrupt.Interrupt
AltFuncSelector stm32.AltFunc
AltFuncSelector uint8
}
func (uart UART) configurePins(config UARTConfig) {
@ -44,7 +64,7 @@ func (uart UART) getBaudRateDivisor(baudRate uint32) uint32 {
type SPI struct {
Bus *stm32.SPI_Type
AltFuncSelector stm32.AltFunc
AltFuncSelector uint8
}
func (spi SPI) configurePins(config SPIConfig) {
@ -93,7 +113,7 @@ func (spi SPI) getBaudRate(config SPIConfig) uint32 {
type I2C struct {
Bus *stm32.I2C_Type
AltFuncSelector stm32.AltFunc
AltFuncSelector uint8
}
func (i2c I2C) configurePins(config I2CConfig) {

42
src/machine/machine_stm32f407.go

@ -13,6 +13,26 @@ func CPUFrequency() uint32 {
return 168000000
}
// Alternative peripheral pin functions
const (
AF0_SYSTEM = 0
AF1_TIM1_2 = 1
AF2_TIM3_4_5 = 2
AF3_TIM8_9_10_11 = 3
AF4_I2C1_2_3 = 4
AF5_SPI1_SPI2 = 5
AF6_SPI3 = 6
AF7_USART1_2_3 = 7
AF8_USART4_5_6 = 8
AF9_CAN1_CAN2_TIM12_13_14 = 9
AF10_OTG_FS_OTG_HS = 10
AF11_ETH = 11
AF12_FSMC_SDIO_OTG_HS_1 = 12
AF13_DCMI = 13
AF14 = 14
AF15_EVENTOUT = 15
)
//---------- UART related types and code
// UART representation
@ -20,7 +40,7 @@ type UART struct {
Buffer *RingBuffer
Bus *stm32.USART_Type
Interrupt interrupt.Interrupt
AltFuncSelector stm32.AltFunc
AltFuncSelector uint8
}
// Configure the UART.
@ -48,7 +68,7 @@ func (uart UART) getBaudRateDivisor(baudRate uint32) uint32 {
// SPI on the STM32Fxxx using MODER / alternate function pins
type SPI struct {
Bus *stm32.SPI_Type
AltFuncSelector stm32.AltFunc
AltFuncSelector uint8
}
// Set baud rate for SPI
@ -70,26 +90,26 @@ func (spi SPI) getBaudRate(config SPIConfig) uint32 {
// TODO: also include the MCU/APB clock setting in the equation
switch true {
case localFrequency < 328125:
conf = stm32.SPI_PCLK_256
conf = stm32.SPI_CR1_BR_Div256
case localFrequency < 656250:
conf = stm32.SPI_PCLK_128
conf = stm32.SPI_CR1_BR_Div128
case localFrequency < 1312500:
conf = stm32.SPI_PCLK_64
conf = stm32.SPI_CR1_BR_Div64
case localFrequency < 2625000:
conf = stm32.SPI_PCLK_32
conf = stm32.SPI_CR1_BR_Div32
case localFrequency < 5250000:
conf = stm32.SPI_PCLK_16
conf = stm32.SPI_CR1_BR_Div16
case localFrequency < 10500000:
conf = stm32.SPI_PCLK_8
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_PCLK_4
conf = stm32.SPI_CR1_BR_Div4
case localFrequency < 42000000:
conf = stm32.SPI_PCLK_2
conf = stm32.SPI_CR1_BR_Div2
default:
// None of the specific baudrates were selected; choose the lowest speed
conf = stm32.SPI_PCLK_256
conf = stm32.SPI_CR1_BR_Div256
}
return conf << stm32.SPI_CR1_BR_Pos

2
src/machine/machine_stm32f7x2.go

@ -20,7 +20,7 @@ type UART struct {
Buffer *RingBuffer
Bus *stm32.USART_Type
Interrupt interrupt.Interrupt
AltFuncSelector stm32.AltFunc
AltFuncSelector uint8
}
// Configure the UART.

28
src/machine/machine_stm32l0.go

@ -164,7 +164,7 @@ func enableAltFuncClock(bus unsafe.Pointer) {
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART2EN)
case unsafe.Pointer(stm32.SPI2): // SPI2 clock enable
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_SPI2EN)
case unsafe.Pointer(stm32.LPUSART1): // LPUSART1 clock enable
case unsafe.Pointer(stm32.LPUART1): // LPUART1 clock enable
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_LPUART1EN)
case unsafe.Pointer(stm32.WWDG): // Window watchdog clock enable
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_WWDGEN)
@ -176,7 +176,7 @@ func enableAltFuncClock(bus unsafe.Pointer) {
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM3EN)
case unsafe.Pointer(stm32.TIM2): // TIM2 clock enable
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM2EN)
case unsafe.Pointer(stm32.SYSCFG_COMP): // System configuration controller clock enable
case unsafe.Pointer(stm32.SYSCFG): // System configuration controller clock enable
stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SYSCFGEN)
case unsafe.Pointer(stm32.SPI1): // SPI1 clock enable
stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SPI1EN)
@ -194,7 +194,7 @@ type UART struct {
Buffer *RingBuffer
Bus *stm32.USART_Type
Interrupt interrupt.Interrupt
AltFuncSelector stm32.AltFunc
AltFuncSelector uint8
}
// Configure the UART.
@ -208,7 +208,7 @@ func (uart UART) configurePins(config UARTConfig) {
func (uart UART) getBaudRateDivisor(baudRate uint32) uint32 {
var clock, rate uint32
switch uart.Bus {
case stm32.LPUSART1:
case stm32.LPUART1:
clock = CPUFrequency() / 2 // APB1 Frequency
rate = uint32((256 * clock) / baudRate)
case stm32.USART1:
@ -227,7 +227,7 @@ func (uart UART) getBaudRateDivisor(baudRate uint32) uint32 {
// SPI on the STM32Fxxx using MODER / alternate function pins
type SPI struct {
Bus *stm32.SPI_Type
AltFuncSelector stm32.AltFunc
AltFuncSelector uint8
}
// Set baud rate for SPI
@ -255,26 +255,26 @@ func (spi SPI) getBaudRate(config SPIConfig) uint32 {
// TODO: also include the MCU/APB clock setting in the equation
switch {
case localFrequency < 328125:
conf = stm32.SPI_PCLK_256
conf = stm32.SPI_CR1_BR_Div256
case localFrequency < 656250:
conf = stm32.SPI_PCLK_128
conf = stm32.SPI_CR1_BR_Div128
case localFrequency < 1312500:
conf = stm32.SPI_PCLK_64
conf = stm32.SPI_CR1_BR_Div64
case localFrequency < 2625000:
conf = stm32.SPI_PCLK_32
conf = stm32.SPI_CR1_BR_Div32
case localFrequency < 5250000:
conf = stm32.SPI_PCLK_16
conf = stm32.SPI_CR1_BR_Div16
case localFrequency < 10500000:
conf = stm32.SPI_PCLK_8
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_PCLK_4
conf = stm32.SPI_CR1_BR_Div4
case localFrequency < 42000000:
conf = stm32.SPI_PCLK_2
conf = stm32.SPI_CR1_BR_Div2
default:
// None of the specific baudrates were selected; choose the lowest speed
conf = stm32.SPI_PCLK_256
conf = stm32.SPI_CR1_BR_Div256
}
return conf << stm32.SPI_CR1_BR_Pos

20
src/runtime/runtime_stm32f103xx.go → src/runtime/runtime_stm32f103.go

@ -1,4 +1,4 @@
// +build stm32,stm32f103xx
// +build stm32,stm32f103
package runtime
@ -23,10 +23,10 @@ func putchar(c byte) {
// initCLK sets clock to 72MHz using HSE 8MHz crystal w/ PLL X 9 (8MHz x 9 = 72MHz).
func initCLK() {
stm32.FLASH.ACR.SetBits(stm32.FLASH_ACR_LATENCY_2) // Two wait states, per datasheet
stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE1_DIV_2) // prescale PCLK1 = HCLK/2
stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE2_DIV_NONE) // prescale PCLK2 = HCLK/1
stm32.RCC.CR.SetBits(stm32.RCC_CR_HSEON) // enable HSE clock
stm32.FLASH.ACR.SetBits(stm32.FLASH_ACR_LATENCY_WS2) // Two wait states, per datasheet
stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE1_Div2 << stm32.RCC_CFGR_PPRE1_Pos) // prescale PCLK1 = HCLK/2
stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE2_Div1 << stm32.RCC_CFGR_PPRE2_Pos) // prescale PCLK2 = HCLK/1
stm32.RCC.CR.SetBits(stm32.RCC_CR_HSEON) // enable HSE clock
// wait for the HSEREADY flag
for !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSERDY) {
@ -38,9 +38,9 @@ func initCLK() {
for !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSIRDY) {
}
stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PLLSRC) // set PLL source to HSE
stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PLLMUL_9) // multiply by 9
stm32.RCC.CR.SetBits(stm32.RCC_CR_PLLON) // enable the PLL
stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PLLSRC) // set PLL source to HSE
stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PLLMUL_Mul9 << stm32.RCC_CFGR_PLLMUL_Pos) // multiply by 9
stm32.RCC.CR.SetBits(stm32.RCC_CR_PLLON) // enable the PLL
// wait for the PLLRDY flag
for !stm32.RCC.CR.HasBits(stm32.RCC_CR_PLLRDY) {
@ -49,7 +49,7 @@ func initCLK() {
stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_SW_PLL) // set clock source to pll
// wait for PLL to be CLK
for !stm32.RCC.CFGR.HasBits(stm32.RCC_CFGR_SWS_PLL) {
for !stm32.RCC.CFGR.HasBits(stm32.RCC_CFGR_SWS_PLL << stm32.RCC_CFGR_SWS_Pos) {
}
}
@ -75,7 +75,7 @@ func initRTC() {
}
// Select LSE
stm32.RCC.BDCR.SetBits(stm32.RCC_RTCCLKSource_LSE)
stm32.RCC.BDCR.SetBits(stm32.RCC_BDCR_RTCSEL_LSE << stm32.RCC_BDCR_RTCSEL_Pos)
// set prescaler to "max" per datasheet
stm32.RTC.PRLH.Set(stm32.RTC_PRLH_PRLH_Msk)

18
src/runtime/runtime_stm32f405.go

@ -39,17 +39,17 @@ const (
PLL_SRC_HSE = 1 << stm32.RCC_PLLCFGR_PLLSRC_Pos // use HSE for PLL and PLLI2S
PLL_SRC_HSI = 0 // use HSI for PLL and PLLI2S
PLL_DIV_M = 6 << stm32.RCC_PLLCFGR_PLLM0_Pos
PLL_MLT_N = 168 << stm32.RCC_PLLCFGR_PLLN0_Pos
PLL_DIV_P = ((2 >> 1) - 1) << stm32.RCC_PLLCFGR_PLLP0_Pos
PLL_DIV_Q = 7 << stm32.RCC_PLLCFGR_PLLQ0_Pos
PLL_DIV_M = 6 << stm32.RCC_PLLCFGR_PLLM_Pos
PLL_MLT_N = 168 << stm32.RCC_PLLCFGR_PLLN_Pos
PLL_DIV_P = ((2 >> 1) - 1) << stm32.RCC_PLLCFGR_PLLP_Pos
PLL_DIV_Q = 7 << stm32.RCC_PLLCFGR_PLLQ_Pos
SYSCLK_SRC_PLL = 2 << stm32.RCC_CFGR_SW0_Pos
SYSCLK_STAT_PLL = 2 << stm32.RCC_CFGR_SWS0_Pos
SYSCLK_SRC_PLL = stm32.RCC_CFGR_SW_PLL << stm32.RCC_CFGR_SW_Pos
SYSCLK_STAT_PLL = stm32.RCC_CFGR_SWS_PLL << stm32.RCC_CFGR_SWS_Pos
RCC_DIV_PCLK1 = 5 << stm32.RCC_CFGR_PPRE1_Pos // HCLK / 4
RCC_DIV_PCLK2 = 4 << stm32.RCC_CFGR_PPRE2_Pos // HCLK / 2
RCC_DIV_HCLK = 0 << stm32.RCC_CFGR_HPRE_Pos // SYSCLK / 1
RCC_DIV_PCLK1 = stm32.RCC_CFGR_PPRE1_Div4 << stm32.RCC_CFGR_PPRE1_Pos // HCLK / 4
RCC_DIV_PCLK2 = stm32.RCC_CFGR_PPRE2_Div2 << stm32.RCC_CFGR_PPRE2_Pos // HCLK / 2
RCC_DIV_HCLK = stm32.RCC_CFGR_HPRE_Div1 << stm32.RCC_CFGR_HPRE_Pos // SYSCLK / 1
CLK_CCM_RAM = 1 << 20
)

12
src/runtime/runtime_stm32f407.go

@ -77,11 +77,11 @@ func initCLK() {
stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN)
stm32.PWR.CR.SetBits(0x4000) // PWR_CR_VOS
// HCLK = SYSCLK / 1
stm32.RCC.CFGR.SetBits(0x0 << stm32.RCC_CFGR_HPRE_Pos)
stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_HPRE_Div1 << stm32.RCC_CFGR_HPRE_Pos)
// PCLK2 = HCLK / 2
stm32.RCC.CFGR.SetBits(0x4 << stm32.RCC_CFGR_PPRE2_Pos)
stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE2_Div2 << stm32.RCC_CFGR_PPRE2_Pos)
// PCLK1 = HCLK / 4
stm32.RCC.CFGR.SetBits(0x5 << stm32.RCC_CFGR_PPRE1_Pos)
stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE1_Div4 << stm32.RCC_CFGR_PPRE1_Pos)
// Configure the main PLL
// PLL Options - See RM0090 Reference Manual pg. 95
stm32.RCC.PLLCFGR.Set(PLL_M | (PLL_N << 6) | (((PLL_P >> 1) - 1) << 16) |
@ -94,9 +94,9 @@ func initCLK() {
// Configure Flash prefetch, Instruction cache, Data cache and wait state
stm32.FLASH.ACR.Set(stm32.FLASH_ACR_ICEN | stm32.FLASH_ACR_DCEN | (5 << stm32.FLASH_ACR_LATENCY_Pos))
// Select the main PLL as system clock source
stm32.RCC.CFGR.ClearBits(stm32.RCC_CFGR_SW0 | stm32.RCC_CFGR_SW1)
stm32.RCC.CFGR.SetBits(0x2 << stm32.RCC_CFGR_SW0_Pos)
for (stm32.RCC.CFGR.Get() & (0x3 << stm32.RCC_CFGR_SWS0_Pos)) != (0x2 << stm32.RCC_CFGR_SWS0_Pos) {
stm32.RCC.CFGR.ClearBits(stm32.RCC_CFGR_SW_Msk)
stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_SW_PLL << stm32.RCC_CFGR_SW_Pos)
for (stm32.RCC.CFGR.Get() & stm32.RCC_CFGR_SWS_Msk) != (stm32.RCC_CFGR_SWS_PLL << stm32.RCC_CFGR_SWS_Pos) {
}
} else {

6
src/runtime/runtime_stm32f7x2.go

@ -93,9 +93,9 @@ func initOsc() {
stm32.RCC.PLLCFGR.Set(0x20000000 |
(1 << stm32.RCC_PLLCFGR_PLLSRC_Pos) | // 1 = HSE
PLL_M |
(PLL_N << stm32.RCC_PLLCFGR_PLLN0_Pos) |
(((PLL_P >> 1) - 1) << stm32.RCC_PLLCFGR_PLLP0_Pos) |
(PLL_Q << stm32.RCC_PLLCFGR_PLLQ0_Pos))
(PLL_N << stm32.RCC_PLLCFGR_PLLN_Pos) |
(((PLL_P >> 1) - 1) << stm32.RCC_PLLCFGR_PLLP_Pos) |
(PLL_Q << stm32.RCC_PLLCFGR_PLLQ_Pos))
// Enable the PLL, wait until ready
stm32.RCC.CR.SetBits(stm32.RCC_CR_PLLON)

24
src/runtime/runtime_stm32l0.go

@ -10,22 +10,6 @@ import (
"runtime/volatile"
)
const (
// Sets PCLK1
RCC_CFGR_PPRE1_DIV_NONE = 0x00000000
RCC_CFGR_PPRE1_DIV_2 = 0x00000400
RCC_CFGR_PPRE1_DIV_4 = 0x00000500
RCC_CFGR_PPRE1_DIV_8 = 0x00000600
RCC_CFGR_PPRE1_DIV_16 = 0x00000700
// Sets PCLK2
RCC_CFGR_PPRE2_DIV_NONE = 0x00000000
RCC_CFGR_PPRE2_DIV_2 = 0x00002000
RCC_CFGR_PPRE2_DIV_4 = 0x00002800
RCC_CFGR_PPRE2_DIV_8 = 0x00003000
RCC_CFGR_PPRE2_DIV_16 = 0x00003800
)
func init() {
initCLK()
initRTC()
@ -44,11 +28,11 @@ func initCLK() {
// Set the Flash ACR to use 1 wait-state
// enable the prefetch buffer and pre-read for performance
stm32.Flash.ACR.SetBits(stm32.Flash_ACR_LATENCY | stm32.Flash_ACR_PRFTEN | stm32.Flash_ACR_PRE_READ)
stm32.FLASH.ACR.SetBits(stm32.Flash_ACR_LATENCY | stm32.Flash_ACR_PRFTEN | stm32.Flash_ACR_PRE_READ)
// Set presaclers so half system clock (PCLKx = HCLK/2)
stm32.RCC.CFGR.SetBits(RCC_CFGR_PPRE1_DIV_2)
stm32.RCC.CFGR.SetBits(RCC_CFGR_PPRE2_DIV_2)
stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE1_Div2 << stm32.RCC_CFGR_PPRE1_Pos)
stm32.RCC.CFGR.SetBits(stm32.RCC_CFGR_PPRE2_Div2 << stm32.RCC_CFGR_PPRE2_Pos)
// Enable the HSI16 oscillator, since the L0 series boots to the MSI one.
stm32.RCC.CR.SetBits(stm32.RCC_CR_HSI16ON)
@ -202,7 +186,7 @@ func timerSleep(ticks uint32) {
if ticks < 200 {
ticks = 200
}
stm32.TIM3.ARR.Set(ticks/100 - 1) // convert from microseconds to 0.1 ms
stm32.TIM3.ARR.Set(uint16(ticks/100 - 1)) // convert from microseconds to 0.1 ms
// Enable the hardware interrupt.
stm32.TIM3.DIER.SetBits(stm32.TIM_DIER_UIE)

4
targets/bluepill.json

@ -1,14 +1,14 @@
{
"inherits": ["cortex-m"],
"llvm-target": "armv7m-none-eabi",
"build-tags": ["bluepill", "stm32f103xx", "stm32"],
"build-tags": ["bluepill", "stm32f103", "stm32"],
"cflags": [
"--target=armv7m-none-eabi",
"-Qunused-arguments"
],
"linkerscript": "targets/stm32.ld",
"extra-files": [
"src/device/stm32/stm32f103xx.s"
"src/device/stm32/stm32f103.s"
],
"flash-method": "openocd",
"openocd-interface": "stlink-v2",

4
targets/nucleo-f103rb.json

@ -1,14 +1,14 @@
{
"inherits": ["cortex-m"],
"llvm-target": "armv7m-none-eabi",
"build-tags": ["nucleof103rb", "stm32f103xx", "stm32"],
"build-tags": ["nucleof103rb", "stm32f103", "stm32"],
"cflags": [
"--target=armv7m-none-eabi",
"-Qunused-arguments"
],
"linkerscript": "targets/stm32f103rb.ld",
"extra-files": [
"src/device/stm32/stm32f103xx.s"
"src/device/stm32/stm32f103.s"
],
"flash-method": "openocd",
"openocd-interface": "stlink-v2-1",

84
tools/gen-device-svd/gen-device-svd.go

@ -60,11 +60,15 @@ type SVDField struct {
BitOffset *uint32 `xml:"bitOffset"`
BitWidth *uint32 `xml:"bitWidth"`
BitRange *string `xml:"bitRange"`
EnumeratedValues []struct {
Name string `xml:"name"`
Description string `xml:"description"`
Value string `xml:"value"`
} `xml:"enumeratedValues>enumeratedValue"`
EnumeratedValues struct {
DerivedFrom string `xml:"derivedFrom,attr"`
Name string `xml:"name"`
EnumeratedValue []struct {
Name string `xml:"name"`
Description string `xml:"description"`
Value string `xml:"value"`
} `xml:"enumeratedValue"`
} `xml:"enumeratedValues"`
}
type SVDCluster struct {
@ -444,7 +448,7 @@ func addInterrupt(interrupts map[string]*interrupt, name, interruptName string,
if interrupts[name].Value != index {
// Note: some SVD files like the one for STM32H7x7 contain mistakes.
// Instead of throwing an error, simply log it.
fmt.Fprintf(os.Stderr, "interrupt with the same name has different indexes: %s (%d vs %d)",
fmt.Fprintf(os.Stderr, "interrupt with the same name has different indexes: %s (%d vs %d)\n",
name, interrupts[name].Value, index)
}
parts := strings.Split(interrupts[name].Description, " // ")
@ -470,7 +474,7 @@ func addInterrupt(interrupts map[string]*interrupt, name, interruptName string,
func parseBitfields(groupName, regName string, fieldEls []*SVDField, bitfieldPrefix string) []Bitfield {
var fields []Bitfield
enumSeen := map[string]bool{}
enumSeen := map[string]int64{}
for _, fieldEl := range fieldEls {
// Some bitfields (like the STM32H7x7) contain invalid bitfield
// names like "CNT[31]". Replace invalid characters with "_" when
@ -511,6 +515,32 @@ func parseBitfields(groupName, regName string, fieldEls []*SVDField, bitfieldPre
continue
}
// The enumerated values can be the same as another field, so to avoid
// duplication SVD files can simply refer to another set of enumerated
// values in the same register.
// See: https://www.keil.com/pack/doc/CMSIS/SVD/html/elem_registers.html#elem_enumeratedValues
enumeratedValues := fieldEl.EnumeratedValues
if enumeratedValues.DerivedFrom != "" {
parts := strings.Split(enumeratedValues.DerivedFrom, ".")
if len(parts) == 1 {
found := false
for _, otherFieldEl := range fieldEls {
if otherFieldEl.EnumeratedValues.Name == parts[0] {
found = true
enumeratedValues = otherFieldEl.EnumeratedValues
}
}
if !found {
fmt.Fprintf(os.Stderr, "Warning: could not find enumeratedValue.derivedFrom of %s for register field %s\n", enumeratedValues.DerivedFrom, fieldName)
}
} else {
// The derivedFrom attribute may also point to enumerated values
// in other registers and even peripherals, but this feature
// isn't often used in SVD files.
fmt.Fprintf(os.Stderr, "TODO: enumeratedValue.derivedFrom to a different register: %s\n", enumeratedValues.DerivedFrom)
}
}
fields = append(fields, Bitfield{
name: fmt.Sprintf("%s_%s%s_%s_Pos", groupName, bitfieldPrefix, regName, fieldName),
description: fmt.Sprintf("Position of %s field.", fieldName),
@ -528,7 +558,7 @@ func parseBitfields(groupName, regName string, fieldEls []*SVDField, bitfieldPre
value: 1 << lsb,
})
}
for _, enumEl := range fieldEl.EnumeratedValues {
for _, enumEl := range enumeratedValues.EnumeratedValue {
enumName := enumEl.Name
if strings.EqualFold(enumName, "reserved") || !validName.MatchString(enumName) {
continue
@ -557,8 +587,35 @@ func parseBitfields(groupName, regName string, fieldEls []*SVDField, bitfieldPre
}
}
enumName = fmt.Sprintf("%s_%s%s_%s_%s", groupName, bitfieldPrefix, regName, fieldName, enumName)
_, seen := enumSeen[enumName]
enumSeen[enumName] = seen
// Avoid duplicate values. Duplicate names with the same value are
// allowed, but the same name with a different value is not. Instead
// of trying to work around those cases, remove the value entirely
// as there is probably not one correct answer in such a case.
// For example, SVD files from NXP have enums limited to 20
// characters, leading to lots of duplicates when these enum names
// are long. Nothing here can really fix those cases.
previousEnumValue, seenBefore := enumSeen[enumName]
if seenBefore {
if previousEnumValue < 0 {
// There was a mismatch before, ignore all equally named fields.
continue
}
if int64(enumValue) != previousEnumValue {
// There is a mismatch. Mark it as such, and remove the
// existing enum bitfield value.
enumSeen[enumName] = -1
for i, field := range fields {
if field.name == enumName {
fields = append(fields[:i], fields[i+1:]...)
break
}
}
}
continue
}
enumSeen[enumName] = int64(enumValue)
fields = append(fields, Bitfield{
name: enumName,
description: enumDescription,
@ -566,13 +623,6 @@ func parseBitfields(groupName, regName string, fieldEls []*SVDField, bitfieldPre
})
}
}
// check if any of the field names appeared more than once. if so, append
// its value onto its name to ensure each name is unique.
for i, field := range fields {
if dup, seen := enumSeen[field.name]; dup && seen {
fields[i].name = fmt.Sprintf("%s_%d", field.name, field.value)
}
}
return fields
}

Loading…
Cancel
Save