Open maxekman opened 6 years ago
I don't know anything about SVD. Quick check in Google and I known that there is something like CMSIS-SVD and It looks interesting.
Currently packages in stm32/hal/raw are automatically generated from ST Cube MX C header files but it isn't a perfect solution.
Yes, CMSIS-SVD is the format they are parsing, apart from that I don't know much about it.
If I get some time to experiment with it and start on a parser I'll let you know.
Currently Emgo has something called xgen.
See for example this file that describes SPI peripheral in STM32L476:
https://github.com/ziutek/emgo/blob/master/egpath/src/stm32/hal/raw/spi/l476xx--spi.go
The top comment describes the peripheral, its instances and registers:
// Peripheral: SPI_Periph Serial Peripheral Interface.
// Instances:
// SPI2 mmap.SPI2_BASE
// SPI3 mmap.SPI3_BASE
// SPI1 mmap.SPI1_BASE
// Registers:
// 0x00 32 CR1 Control register 1.
// 0x04 32 CR2 Control register 2.
// 0x08 32 SR Status register.
// 0x0C 32 DR Data register.
// 0x10 32 CRCPR CRC polynomial register.
// 0x14 32 RXCRCR Rx CRC register.
// 0x18 32 TXCRCR Tx CRC register.
// Import:
// stm32/o/l476xx/mmap
package spi
This is easy to write and read. Next the file contains constants that describe all bits/bitfields of these registers:
const (
CPHA CR1 = 0x01 << 0 //+ Clock Phase.
CPOL CR1 = 0x01 << 1 //+ Clock Polarity.
MSTR CR1 = 0x01 << 2 //+ Master Selection.
BR CR1 = 0x07 << 3 //+ BR[2:0] bits (Baud Rate Control).
BR_0 CR1 = 0x01 << 3 // Bit 0.
BR_1 CR1 = 0x02 << 3 // Bit 1.
BR_2 CR1 = 0x04 << 3 // Bit 2.
SPE CR1 = 0x01 << 6 //+ SPI Enable.
LSBFIRST CR1 = 0x01 << 7 //+ Frame Format.
SSI CR1 = 0x01 << 8 //+ Internal slave select.
SSM CR1 = 0x01 << 9 //+ Software slave management.
RXONLY CR1 = 0x01 << 10 //+ Receive only.
CRCL CR1 = 0x01 << 11 //+ CRC Length.
CRCNEXT CR1 = 0x01 << 12 //+ Transmit CRC next.
CRCEN CR1 = 0x01 << 13 //+ Hardware CRC calculation enable.
BIDIOE CR1 = 0x01 << 14 //+ Output enable in bidirectional mode.
BIDIMODE CR1 = 0x01 << 15 //+ Bidirectional data mode enable.
)
const (
CPHAn = 0
CPOLn = 1
MSTRn = 2
BRn = 3
SPEn = 6
LSBFIRSTn = 7
SSIn = 8
SSMn = 9
RXONLYn = 10
CRCLn = 11
CRCNEXTn = 12
CRCENn = 13
BIDIOEn = 14
BIDIMODEn = 15
)
The xgen parses this peripheral file and generates the remaining code that allows you to write:
if spi.SPI2.CR1.Load() & spi.LSBFIRST != 0 {
//...
}
or even
if spi.SPI2.LSBFIRST().Load() != 0 {
//...
}
See generated code:
https://github.com/ziutek/emgo/blob/master/egpath/src/stm32/hal/raw/spi/f746xx--xgen_spi.go
In this case even the peripheral file isn't written by hand but the stm32xgen generates it from STM32 Cube MX C header file.
Because the peripherals are not identical, the stm32/hal/spi package try to provide unified interface to the SPI peripheral and default driver that uses DMA and IRQ.
Summarizing:
The stm32/hal/raw and stm32/hal/irq contain automatically generated packages that allow raw access the peripherals and names all IRQs. Other packages in stm32/hal are written by hand to provide unified interface and drivers.
Thanks for the description, looks pretty neat.
I was just reading an issue on embedded Rust regarding how they plan to handle boards and targets in the future, could be interesting as inspiration for emgo also: https://github.com/rust-lang-nursery/embedded-wg/issues/101
Are there any plans for generating board/arch definitions using SVD files? The Rust embedded effort uses a tool called svd2rust to generate type safe memory mappings (I’m not familiar with all the details in Rust as I’m a Go developer).