diff --git a/.gitmodules b/.gitmodules index c877bbaf..f4138be5 100644 --- a/.gitmodules +++ b/.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 diff --git a/Makefile b/Makefile index 5b3cb8f5..601735a4 100644 --- a/Makefile +++ b/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 diff --git a/lib/stm32-svd b/lib/stm32-svd new file mode 160000 index 00000000..9ec99824 --- /dev/null +++ b/lib/stm32-svd @@ -0,0 +1 @@ +Subproject commit 9ec99824859540e61076a81149019222dc19b780 diff --git a/src/device/stm32/stm32-moder-bitfields.go b/src/device/stm32/stm32-moder-bitfields.go deleted file mode 100644 index 176d09c2..00000000 --- a/src/device/stm32/stm32-moder-bitfields.go +++ /dev/null @@ -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 -) diff --git a/src/device/stm32/stm32f103xx-bitfields.go b/src/device/stm32/stm32f103xx-bitfields.go deleted file mode 100644 index 5e68bc84..00000000 --- a/src/device/stm32/stm32f103xx-bitfields.go +++ /dev/null @@ -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 -) diff --git a/src/device/stm32/stm32f4-altfunc-bitfields.go b/src/device/stm32/stm32f4-altfunc-bitfields.go deleted file mode 100644 index 8dca2bf2..00000000 --- a/src/device/stm32/stm32f4-altfunc-bitfields.go +++ /dev/null @@ -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 -) diff --git a/src/machine/board_feather-stm32f405.go b/src/machine/board_feather-stm32f405.go index 29c7d35d..16b0ac8e 100644 --- a/src/machine/board_feather-stm32f405.go +++ b/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 ) diff --git a/src/machine/board_lgt92.go b/src/machine/board_lgt92.go index ed2e6b5e..29376df1 100644 --- a/src/machine/board_lgt92.go +++ b/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, } diff --git a/src/machine/board_stm32f4disco.go b/src/machine/board_stm32f4disco.go index 20e37a32..7c10b3ed 100644 --- a/src/machine/board_stm32f4disco.go +++ b/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 ) diff --git a/src/machine/machine_stm32_i2c.go b/src/machine/machine_stm32_i2c.go index b502582e..471077d5 100644 --- a/src/machine/machine_stm32_i2c.go +++ b/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 diff --git a/src/machine/machine_stm32_moder_gpio.go b/src/machine/machine_stm32_moder_gpio.go index 69d5ab8e..be4d636f 100644 --- a/src/machine/machine_stm32_moder_gpio.go +++ b/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 diff --git a/src/machine/machine_stm32f103xx.go b/src/machine/machine_stm32f103.go similarity index 97% rename from src/machine/machine_stm32f103xx.go rename to src/machine/machine_stm32f103.go index 4b88fd2f..28b4b814 100644 --- a/src/machine/machine_stm32f103xx.go +++ b/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 { diff --git a/src/machine/machine_stm32f405.go b/src/machine/machine_stm32f405.go index a1b50107..de11e792 100644 --- a/src/machine/machine_stm32f405.go +++ b/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) { diff --git a/src/machine/machine_stm32f407.go b/src/machine/machine_stm32f407.go index 232b8e3d..ae1ba0c8 100644 --- a/src/machine/machine_stm32f407.go +++ b/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 diff --git a/src/machine/machine_stm32f7x2.go b/src/machine/machine_stm32f7x2.go index 632a7700..7ebca01e 100644 --- a/src/machine/machine_stm32f7x2.go +++ b/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. diff --git a/src/machine/machine_stm32l0.go b/src/machine/machine_stm32l0.go index 115e0ec4..81cb2c11 100644 --- a/src/machine/machine_stm32l0.go +++ b/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 diff --git a/src/runtime/runtime_stm32f103xx.go b/src/runtime/runtime_stm32f103.go similarity index 83% rename from src/runtime/runtime_stm32f103xx.go rename to src/runtime/runtime_stm32f103.go index a59c2a01..9ecfcfd1 100644 --- a/src/runtime/runtime_stm32f103xx.go +++ b/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) diff --git a/src/runtime/runtime_stm32f405.go b/src/runtime/runtime_stm32f405.go index 8e542fff..6be208dd 100644 --- a/src/runtime/runtime_stm32f405.go +++ b/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 ) diff --git a/src/runtime/runtime_stm32f407.go b/src/runtime/runtime_stm32f407.go index 626dabd9..57739eeb 100644 --- a/src/runtime/runtime_stm32f407.go +++ b/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 { diff --git a/src/runtime/runtime_stm32f7x2.go b/src/runtime/runtime_stm32f7x2.go index 76c80ace..da6d9aa5 100644 --- a/src/runtime/runtime_stm32f7x2.go +++ b/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) diff --git a/src/runtime/runtime_stm32l0.go b/src/runtime/runtime_stm32l0.go index daab1276..8a3bc44e 100644 --- a/src/runtime/runtime_stm32l0.go +++ b/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) diff --git a/targets/bluepill.json b/targets/bluepill.json index fbd5e7cd..6b6b0469 100644 --- a/targets/bluepill.json +++ b/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", diff --git a/targets/nucleo-f103rb.json b/targets/nucleo-f103rb.json index b45d8dec..894e4227 100644 --- a/targets/nucleo-f103rb.json +++ b/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", diff --git a/tools/gen-device-svd/gen-device-svd.go b/tools/gen-device-svd/gen-device-svd.go index b8f1aeab..ec2cf17c 100755 --- a/tools/gen-device-svd/gen-device-svd.go +++ b/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 }