ziutek / emgo

Emgo: Bare metal Go (language for programming embedded systems)
BSD 3-Clause "New" or "Revised" License
1.07k stars 69 forks source link

Support for SVD files #13

Open maxekman opened 6 years ago

maxekman commented 6 years ago

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).

ziutek commented 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.

maxekman commented 6 years ago

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.

ziutek commented 6 years ago

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.

maxekman commented 6 years ago

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