Repository navigation
Support for SVD files #13
Description
Activity
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: rust-embedded/wg#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).