Svd2db-v2 README

Author Copyright 2023,2023 by T.J.Porter https://mecrisp-stellaris-folkdoc.sourceforge.io/index.html license: MIT, please see COPYING

Svd2db was featured in Hackaday in November 2022:

https://hackaday.com/2022/11/21/making-svd-files-searchable-with-svd2db/

Abstract

Svd2db is made to assist designers who may use Gcc, Assembly, Forth, PicoLisp etc, or any new embedded language that does not come with ready made includes or header files containing specific hardware information necessary for embedded programming.

In many cases this means the STMicro Technical Reference Manual PDF is the main designer resource.

However using the Reference Manual for programming consumes a *great deal of time* and is error prone by way of typos. It also encourages the temptation to shorten CMSIS-SVD Peripheral_Register_Bitfield names making them non-standard.

Non-standard CMSIS-SVD Peripheral_Register_Bitfield names decreases traceability, increases maintennance difficulty and prevents source sharing.

Svd2db is a bit like a *Unix MAN Page* for embedded and is designed for fast searching and listing. Svd2db gets its data from the same place that the Technical Manual does, namely the mcu CMSIS-SVD file.

Programs

Svd2db: Creates the Sqlite3 database file named svd2db.db given a SVD file as input, ie “make asm SVD=stm32f051.svd”

Readdb: A Getopt CLI application that searches and reads the database, ie “./readdb -L”. Readdb requires a database file named “svd2db.db” in the same directory.

Download

https://sourceforge.net/projects/mecrisp-stellaris-folkdoc/files/svd2db-v2.zip/download

This release contains a sample stm32f051.svd and svd2db.db database so you don’t have to build anything to test by running ./readdb

Changelog for V2

  • Description field bug fixed; last two words were often joined together

  • Everything except style files has been reweitten

  • Makefile is totally new. Much better layout and more user error handling and messages.

  • Gemma now does all text processing, no more SED and shell scripts. Much cleaner source.

  • Makefile variable ‘ARGS’ changed to ‘SVD’, i.e. “make asm SVD=mcu-model.svd”

Database Reader

Readdb is a CLI based program and entering ‘./readdb’ will print instructions and help.

Alternate DB Readers

However the Svd2db database does not not require readdb because it is a Sqlite database and there are many other free alternatives such as:

Readdb Example

List all bitfields containg ‘sleep’ in the description field of the PWR peripheral.

‘Ar’ means Access Rights, ‘bw’ is BitWidth and ‘bo’ is BitOffset. ‘Address’ is the absolute memory location of the PWR_CR register.

./readdb -p pwr -b lpds -T
name                            address     ar  bw  bo  description
------------------------------  ----------  --  --  --  --------------------------------------------------
PWR_CR_LPDS                     0x40007000  rw  1   0   Low Power Deep Sleep

Database Information

  • The MCU model the database was built for.

  • CMSIS-SVD compliant Peripheral_Register_Bitfield names.

  • Absolute Memory Register Addresses. Theae are not available in the Reference Manual.

  • Description Field.

  • Bitfield attributes:

    • BitOffset (bo)

    • BitWidth (bw)

    • Access type

      • read-only (ro)

      • write-only (wo)

      • read-wrote (rw)

Database Creation

There are two types of database that can be created, the first uses ‘0x’ as the hexadecimal prefix, and the second is ‘$’.

  • 0x is used when writing C and Assembly (asm) source.

  • $ is used when writing Forth source.

Syntax

The commands below are entered in the release directory. The only difference between the two database types is the hexadecimal prefix as above. These are supplied as a programmer convenience.

0x Prefix

make asm SVD=STM32F051.svd

This will create a database named:

svd2db.db

$ Prefix

make forth SVD=STM32F051.svd

This will create a database named:

svd2db.db

Note

Yes, the database names are the same, but the old one is auto deleted before the new one is created. This way ./readdb will always have the right database name to use when invoked.

Supported Mcu’s

Any STM32 Cortex-M MCU with a SVD file.

Dependencies

Unix, Gema (http://gema.sourceforge.net/new/index.shtml), Make, xsltproc, getopt. These should all be available in any unix repo.

SVD

The CMSIS System View Description format (CMSIS-SVD) formalizes the description of the system contained in Arm Cortex-M processor-based micro controllers, in particular, the memory mapped registers of peripherals. The detail contained in system view descriptions is comparable to the data in device reference manuals. The information ranges from high level functional descriptions of a peripheral all the way down to the definition and purpose of an individual bit field in a memory mapped register.

  • Are XML text files detailing all peripheral registers for ARM MCU families.

  • May be downloaded from https://github.com/posborne/cmsis-svd/archive/master.zip (39MB) and elsewhere.

  • Keil, now owned by ARM, have SVD PACKS for all the MCU’s which may be downloaded from their site.

  • Do not contain ARM specific information such as SYSTICK etc.

License

MIT, please see COPYING

Author

Terry Porter Copyright 2023

Details and Usage

Number Bases

Number Base

Prefix

Hexadecimal

0x or $

Decimal

None

Readdb switches

./readdb <search switches> <listing switch>

Search switches, any combination

-p    peripheral name (required by all searches)
-b    bitfield name or part off
-r    register name or part off
-d    Description phrase

Listing switches, only one

-L    List Peripherals (takes precedence over any other search switches)
-T    Technical listing, lists all the registers in a peripheral by name ascending.
-M    Tech Manual Listing, requires -r

Note

./readdb isn’t perfect, but it’s stable and reliable. If your search returns nothing it usually means a incompatible use of switches. If you don’t like it, change it, only shell, getopt and sqlite skills are needed. Please send me a copy of your improved version :)

Examples

SD Card Reader

You’re designing a SD card reader and need to set the SPI BAUD RATE bitfield, what is it ?

Sure, you’ll still probably need to consult the ref manual to find the three bit code for the Baudrate you need, but you can code the rest first using Svd2db.

Enter

./readdb -p spi1 -d baud -T

Output

name                            address     ar  bw  bo  description
------------------------------  ----------  --  --  --  --------------------------------------------------
SPI1_CR1_BR                     0x40013000  rw  3   3   Baud rate control

Display all the Peripherals

./readdb -L

Output

ADC1    CRC     EXTI    GPIOC   IWDG    RTC     TIM1    USART1  WWDG
AFIO    DBG     FLASH   GPIOD   NVIC    SDIO    TIM2    USART2
BKP     DMA1    GPIOA   I2C1    PWR     SPI1    TIM3    USART3
CAN     DMA2    GPIOB   I2C2    RCC     SPI2    TIM4    USB

Display all the Register Data

./readdb -p pwr -T

Output

name                            address     ar  bw  bo  description
------------------------------  ----------  --  --  --  --------------------------------------------------
PWR                             NULL        --  --  99  STM32F103xx: Power control Peripheral
PWR_CR                          0x40007000  --  --  98  Reset:0x00000000  Address: 0x40007000
PWR_CR_CSBF                     0x40007000  rw  1   3   Clear STANDBY Flag
PWR_CR_CWUF                     0x40007000  rw  1   2   Clear Wake-up Flag
PWR_CR_DBP                      0x40007000  rw  1   8   Disable Backup Domain write protection
PWR_CR_LPDS                     0x40007000  rw  1   0   Low Power Deep Sleep
PWR_CR_PDDS                     0x40007000  rw  1   1   Power Down Deep Sleep
PWR_CR_PLS                      0x40007000  rw  3   5   PVD Level Selection
PWR_CR_PVDE                     0x40007000  rw  1   4   Power Voltage DetectorEnable
PWR_CSR                         0x40007004  --  --  98  Reset:0x00000000  Address: 0x40007004
PWR_CSR_EWUP                    0x40007004  rw  1   8   Enable WKUP pin
PWR_CSR_PVDO                    0x40007004  ro  1   2   PVD Output
PWR_CSR_SBF                     0x40007004  ro  1   1   STANDBY Flag
PWR_CSR_WUF                     0x40007004  ro  1   0   Wake-Up Flag

Display All Register Names

Ignore any “NULL” names

./readdb -p pwr -R

register = CR
register = CSR
register = NULL

Display Contents of named Register in a Peripheral, sorted by BitOffset

Same as in the Reference Manual.

./readdb -p pwr -r cr -M
name                            ar  bw  bo  description
------------------------------  --  --  --  --------------------------------------------------
PWR                             --  --  99  STM32F0xx: Power control Peripheral
PWR_CR                          --  --  98  Reset:0x00000000  Address: 0x40007000
PWR_CR_FPDS                     rw  1   9   Flash power down in Stop mode
PWR_CR_DBP                      rw  1   8   Disable backup domain write protection
PWR_CR_PLS                      rw  3   5   PVD level selection
PWR_CR_PVDE                     rw  1   4   Power voltage detector enable
PWR_CR_CSBF                     rw  1   3   Clear standby flag
PWR_CR_CWUF                     rw  1   2   Clear wakeup flag
PWR_CR_PDDS                     rw  1   1   Power down deepsleep
PWR_CR_LPDS                     rw  1   0   Low-power deep sleep

Forth Blinky

\ ***********************************************************
\ filename: main.fs
\ For Mecrisp-Stellaris by Matthias Koch
\ by: Terry Porter 2022, released under the GPL License
\ Demo of SVD2DB and READDB https:\mecrisp-stellaris-folkdoc.sourceforge.io/readdb.html
\ CPU: STM32F051 running at default 8MHz clock
\ SVD: STM32F051.svd
\ BLUE LED = PC8, blinks about once per second.
\ ***********************************************************

constant $40021000 RCC_CR
constant $40021014 RCC_AHBENR
constant $48000800 GPIOC_MODER
constant $48000818 GPIOC_BSRR

: init ( -- )
   1 19 lshift RCC_AHBENR bis!     \ I/O port C clock enable
   %01 16 lshift GPIOC_MODER bis!   \ set Port C, bit 8 Mode to 01: General purpose output mode
:

: delay ( -- )
   800000 0 do loop
;

: main ( -- )
   init
     begin
     1 8 lshift GPIOC_BSRR !    \ SET PC8 high. led ON
     delay
     1 25 lshift GPIOC_BSRR !   \ CLR PC8, led OF
     delay
   again
:

Forth Write-only Blinky

Kidding. A real write-only would be ‘magic number’ source only with no comments.

: init ( -- )
    1 19 lshift $40021014 bis!  \ I/O port C clock enable
  %01 16 lshift $48000800 bis!  \ set Port C, bit 8 Mode to 01: General purpose output mode
;

: delay ( -- )
   800000 0 do loop
;

: main ( -- )
   init
     begin
     1 8 lshift $48000818 !     \ SET PC8 high. led ON
     delay
     1 25 lshift $48000818 !    \ CLR PC8, led OF
     delay
   again
;

How were the addresses and bitfields derived ?

Comments show how:

\ ./readdb -p rcc -r ahbenr -M
\ --->  RCC_AHBENR  --  --  98  Reset:$00000014  Address: $40021014

constant $40021014 RCC_AHBENR

\ ./readdb -p gpioc -r moder -M
\ --->  GPIOC_MODER --  --  98  Reset:$00000000  Address: $48000800

constant $48000800 GPIOC_MODER

\ ./readdb -p gpioc -r bsrr -M
\ --->  GPIOC_BSRR --  --  98  Reset:$00000000  Address: $48000818

constant $48000818 GPIOC_BSRR


: init ( -- )
   \ ./readdb -p rcc -r ahbenr -T
   \ --->  RCC_AHBENR_IOPCEN $40021014  rw  1   19  I/O port C clock enable

   1 19 lshift RCC_AHBENR bis!     \ I/O port C clock enable

   \ ./readdb -p gpioc -r moder -T
   \ --->  GPIOC_MODER_MODER8 $48000800  rw  2   16  Port x configuration bits (y =0..15)

   %01 16 lshift GPIOC_MODER bis!   \ set Port C, bit 8 Mode to 01: General purpose output mode
:

: delay ( -- )
   800000 0 do loop
;

: main ( -- )
   init

   begin
     \ ./readdb -p gpioc -R
     \ --->  register = BSRR
     \ ./readdb -p gpioc -r bsrr -M
     \ --->  GPIOC_BSRR_BS8 wo  1   8   Port x SET BIT y (y=0..15)

     1 8 lshift GPIOC_BSRR !    \ SET PC8 high. led ON
     delay

     \ --->  GPIOC_BSRR_BR8 wo  1   24  Port x RESET BIT y (y =0..15)

     1 25 lshift GPIOC_BSRR !   \ CLR PC8, led OF
     delay
   again
:

C Blinky

// ***********************************************************
// filename: main.c
// Original Author: Frank Duignan http://eleceng.dit.ie/frank/arm/BareMetalSTM32F0Discovery/
// Many changes by: Terry Porter 2022, released under the MIT License
// Demo of SVD2DB and READDB https://mecrisp-stellaris-folkdoc.sourceforge.io/readdb.html
// This demo uses no libraries or headers whilst creating a Blinky for a STM32F0 Discovery board
// CPU: STM32F051 running at default 8MHz clock
// SVD: STM32F051.svd
// BLUE LED = PC8, blinks about once per second.https://dpaste.com/2BCNX3LZX
// ***********************************************************


volatile int count;

#define  REGISTER_32(ADDRESS) (*((volatile unsigned int *)(ADDRESS)))
#define RCC_AHBENR     REGISTER_32(0x40021014)
#define GPIOC_MODER    REGISTER_32(0x48000800)
#define GPIOC_BSRR     REGISTER_32(0x48000818)


void init(void)
{
   RCC_AHBENR |= 1 << 19;       // I/O port C clock enable
   GPIOC_MODER |= 0x01 << 16;   // set Port C, bit 8 Mode to 01: General purpose output mode
}

void delay(void)
{
 count = 4;
// large for visible blinking
// count = 800000;
while(count--);
}


int main()
{
   init();

   while(1)
   {
   GPIOC_BSRR = 1 << 8;                 // SET PC8 high. led ON
   delay();
   GPIOC_BSRR = 1 << 24;        // CLR PC8, led OFF
   delay();
   }
   return 0;
}

How were the addresses and bitfields derived ?

volatile int count;

#define  REGISTER_32(ADDRESS) (*((volatile unsigned int *)(ADDRESS)))
 // ./readdb -p rcc -r ahbenr -M
 // --->  RCC_AHBENR  --  --  98  Reset:0x00000014  Address: 0x40021014
#define RCC_AHBENR     REGISTER_32(0x40021014)
 // ./readdb -p gpioc -r moder -M
 // --->  GPIOC_MODER --  --  98  Reset:0x00000000  Address: 0x48000800
#define GPIOC_MODER    REGISTER_32(0x48000800)
 // ./readdb -p gpioc -r bsrr -M
 // --->  GPIOC_BSRR --  --  98  Reset:0x00000000  Address: 0x48000818
#define GPIOC_BSRR     REGISTER_32(0x48000818)


void init(void)
{
   // ./readdb -p rcc -r ahbenr -T
   // --->  RCC_AHBENR_IOPCEN 0x40021014  rw  1   19  I/O port C clock enable
   RCC_AHBENR |= 1 << 19;       // I/O port C clock enable

   // ./readdb -p gpioc -r moder -T
   // --->  GPIOC_MODER_MODER8 0x48000800  rw  2   16  Port x configuration bits (y =0..15)
   GPIOC_MODER |= 0x01 << 16;   // set Port C, bit 8 Mode to 01: General purpose output mode
}

void delay(void)
{
   // small for gdb testing
   count = 4;
   // large for visible blinking
   // count = 800000;
   while(count--);
}


int main()
{
   init();

   while(1)
   {
   // ./readdb -p gpioc -R
   // --->  register = BSRR
   // ./readdb -p gpioc -r bsrr -M
   // --->  GPIOC_BSRR_BS8 wo  1   8   Port x SET BIT y (y=0..15)
   GPIOC_BSRR = 1 << 8;                 // SET PC8 high. led ON
   delay();
   // --->  GPIOC_BSRR_BR8 wo  1   24  Port x RESET BIT y (y =0..15)
   GPIOC_BSRR = 1 << 24;        // CLR PC8, led OFF
   delay();
   }
   return 0;
}