> What’s New ? <

CMSIS-SVD

_images/cmsis-compliant.jpg

Let’s assume you’re new to ARM Cortex-M MCU’s, you have a nice new board of some kind, perhaps a STM32 Discovery Board, or a Tiva Connected Launchpad etc and you have installed Mecrisp-Stellaris Forth by Mathias Koch http://mecrisp.sourceforge.net/ on it.

Now you’d like to begin programming, but where do you start, the Cortex-M documentation is vast, and there are a LOT of Registers involved. Can you imagine the work involved in manually creating the Forth Words for Registers and Bitfields ?

Some statistics for various MCU’s that run Mecrisp or Mecrisp Stellaris.

MCU Peripherals Registers Register Bitfields
MSP430G2553 17 113 503
STM32F0xx 37 413 3044
STM32F303x 38 549 3857
STM32F103xx 53 722 4833
TM4C129x 65 2137 7347
STM32F7x 89 1737 14091

CMIS-SVD

ARM created CMSIS-SVD to automate the job of telling the industry ‘standard’ C programs about Cortex-M Peripherals, Registers and Register Bitfields with SVDConv.exe, however that is of no use to Forth users so svd2forth (and others) were develped, initially based on work by Ralph Doering as cmsis-svd-fth (https://github.com/ralfdoering/cmsis-svd-fth).

Depending on the size of your MCU Flash memory, it’s quite possible to install all the Register Memory Mapped Words in Flash, so that Mecrisp-Stellaris knows about every Register, or you can just select the Memory Mapped Words you need.

CMIS-SVD files

  • Are XML text files detailing all Registers (or most of them at least) for MCU families and not individual parts.
  • May be downloaded from https://github.com/posborne/cmsis-svd/archive/master.zip (39MB) or found in some of the packages here for which svd files have been specially created.
  • Programming language MCU specific files are created by applying XSLT stylesheets to the CMIS-SVD files.

Note

Do you use MSP430 ? Svd2mecrisp is now available for MSP430xx.

Note

Do you use Tiva Connected Launchpad ? Dslite2forth is now available for tm4c129x

Svd2forth

  • Was created to use CMSIS-SVD files for automated Mecrisp-Stellaris Forth memory-mapped Word production, making target software development easier and less error prone, especially for Forth beginners.
  • Enforces CMSIS compliant naming across all Mecrisp-Stellaris programs, enabling code reuse.
  • Developed on FreeBSD but also tested on a Ubuntu 16.04.1 x64 VM. This is for Unix and won’t run on Microsoft Windows unless you install all the stuff that turns Windows into Unix.

Svd2forth-v1

Svd2forth-v1 uses a ARM CMSIS-SVD XML file, to produce a Mecrisp-Stellaris Memory Map and Register reference file for a STM32Fx MCU. Unlike svd2forth-v2, Svd2forth-v1 creates bare bones, minimal files with no extra pretty Register printing Words. Svd2forth-v1 is for STM32F users who don’t want any extras.

STM32F0 with all Register Words loaded into Flash

Loading all the Register Words is highly unlikely in practice, this table just demonstrates it can be done.

MCU Flash Size Free after installing Mecrisp-Stellaris Free after loading all registers memory map from SVD2Forth-v1 (15052 bytes)
STM32F0 64KB 44772 Bytes 29720

DOWNLOAD the latest svd2forth-v1 release **HERE**

Svd2forth-v1 Example

STM32F0xx.svd.uf.svd.memmap.fs

Maps Registers to memory.

$40023000 constant CRC
CRC $0 +  constant  CRC_DR
CRC $4 +  constant  CRC_IDR
CRC $8 +  constant  CRC_CR
CRC $C +  constant  CRC_INIT

$48001400 constant GPIOF
GPIOF $0 +  constant  GPIOF_MODER
GPIOF $4 +  constant  GPIOF_OTYPER
GPIOF $8 +  constant  GPIOF_OSPEEDR
GPIOF $C +  constant  GPIOF_PUPDR
GPIOF $10 +  constant  GPIOF_IDR
GPIOF $14 +  constant  GPIOF_ODR
GPIOF $18 +  constant  GPIOF_BSRR
GPIOF $1C +  constant  GPIOF_LCKR
GPIOF $20 +  constant  GPIOF_AFRL
GPIOF $24 +  constant  GPIOF_AFRH
GPIOF $28 +  constant  GPIOF_BRR

...

$4001001C constant COMP
COMP $0 +  constant  COMP_CSR

...

STM32F0xx.svd.uf.svd.register-reference.fs

A programmers reference.

################################### CRC ###################################
CRC_DR (read-write)
$FFFFFFFF CONSTANT RESET_CRC_DR
%xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx  0 lshift CRC_DR bis!       \ CRC_DR Bit 0    Width 32

CRC_IDR (read-write)
$00000000 CONSTANT RESET_CRC_IDR
%xxxxxxxx  0 lshift CRC_IDR bis!                              \ CRC_IDR        Bit 0    Width 8

CRC_CR (read-write)
$00000000 CONSTANT RESET_CRC_CR
%1  0 lshift CRC_CR bis!                                      \ CRC_RESET      Bit 0    Width 1
%xx  5 lshift CRC_CR bis!                                     \ CRC_REV_IN     Bit 5    Width 2
%1  7 lshift CRC_CR bis!                                      \ CRC_REV_OUT    Bit 7    Width 1

CRC_INIT (read-write)
$FFFFFFFF CONSTANT RESET_CRC_INIT
%xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx  0 lshift CRC_INIT bis!     \ CRC_INIT       Bit 0    Width 32


################################### GPIOF ###################################
GPIOF_MODER (read-write)
$00000000 CONSTANT RESET_GPIOF_MODER
%xx  30 lshift GPIOF_MODER bis!        \ GPIOF_MODER15       Bit 30     Width 2
%xx  28 lshift GPIOF_MODER bis!        \ GPIOF_MODER14       Bit 28     Width 2
%xx  26 lshift GPIOF_MODER bis!        \ GPIOF_MODER13       Bit 26     Width 2
%xx  24 lshift GPIOF_MODER bis!        \ GPIOF_MODER12       Bit 24     Width 2
%xx  22 lshift GPIOF_MODER bis!        \ GPIOF_MODER11       Bit 22     Width 2
%xx  20 lshift GPIOF_MODER bis!        \ GPIOF_MODER10       Bit 20     Width 2
%xx  18 lshift GPIOF_MODER bis!        \ GPIOF_MODER9        Bit 18     Width 2
%xx  16 lshift GPIOF_MODER bis!        \ GPIOF_MODER8        Bit 16     Width 2
%xx  14 lshift GPIOF_MODER bis!        \ GPIOF_MODER7        Bit 14     Width 2
%xx  12 lshift GPIOF_MODER bis!        \ GPIOF_MODER6        Bit 12     Width 2
%xx  10 lshift GPIOF_MODER bis!        \ GPIOF_MODER5        Bit 10     Width 2
%xx  8 lshift GPIOF_MODER bis!         \ GPIOF_MODER4        Bit 8      Width 2
%xx  6 lshift GPIOF_MODER bis!         \ GPIOF_MODER3        Bit 6      Width 2
%xx  4 lshift GPIOF_MODER bis!         \ GPIOF_MODER2        Bit 4      Width 2
%xx  2 lshift GPIOF_MODER bis!         \ GPIOF_MODER1        Bit 2      Width 2
%xx  0 lshift GPIOF_MODER bis!         \ GPIOF_MODER0        Bit 0      Width 2

...

################################### COMP ###################################
COMP_CSR ()
$00000000 CONSTANT RESET_COMP_CSR
%1  0 lshift COMP_CSR bis!           \ COMP_COMP1EN          Bit 0      Width 1
%1  1 lshift COMP_CSR bis!           \ COMP_COMP1_INP_DAC    Bit 1      Width 1
%xx  2 lshift COMP_CSR bis!          \ COMP_COMP1MODE        Bit 2      Width 2
%xxx  4 lshift COMP_CSR bis!         \ COMP_COMP1INSEL       Bit 4      Width 3
%xxx  8 lshift COMP_CSR bis!         \ COMP_COMP1OUTSEL      Bit 8      Width 3
%1  11 lshift COMP_CSR bis!          \ COMP_COMP1POL         Bit 11     Width 1
%xx  12 lshift COMP_CSR bis!         \ COMP_COMP1HYST        Bit 12     Width 2
%1  14 lshift COMP_CSR bis!          \ COMP_COMP1OUT         Bit 14     Width 1
%1  15 lshift COMP_CSR bis!          \ COMP_COMP1LOCK        Bit 15     Width 1
%1  16 lshift COMP_CSR bis!          \ COMP_COMP2EN          Bit 16     Width 1
%xx  18 lshift COMP_CSR bis!         \ COMP_COMP2MODE        Bit 18     Width 2
%xxx  20 lshift COMP_CSR bis!        \ COMP_COMP2INSEL       Bit 20     Width 3
%1  23 lshift COMP_CSR bis!          \ COMP_WNDWEN           Bit 23     Width 1
%xxx  24 lshift COMP_CSR bis!        \ COMP_COMP2OUTSEL      Bit 24     Width 3
%1  27 lshift COMP_CSR bis!          \ COMP_COMP2POL         Bit 27     Width 1
%xx  28 lshift COMP_CSR bis!         \ COMP_COMP2HYST        Bit 28     Width 2
%1  30 lshift COMP_CSR bis!          \ COMP_COMP2OUT         Bit 30     Width 1
%1  31 lshift COMP_CSR bis!          \ COMP_COMP2LOCK        Bit 31     Width 1

...

Usage Example

You want to set bit 15 of GPIOF as a OUTPUT, the STM32F0 Reference tells you that MODER15 is the GPIO BitField you need and that it must be set to %01. Searching for for “moder15” in the STM32F0xx.svd.uf.svd.register-reference.fs file soon gives you the following line with example code to SET this BitField with “bis” (Bit Set).

%xx  30 lshift GPIOF_MODER bis!        \ GPIOF_MODER15       Bit 30     Width 2

So your code to SET bit 15 of GPIOF to a OUTPUT is :-

%01 30 lshift GPIOF_MODER bis!     \ Set bit 15 of GPIOF to a OUTPUT

Svd2forth-v2

Svd2forth-v2 is similar to Svd2forth-v1 but adds Register Pretty printing as a development aid.

DOWNLOAD the latest svd2forth-v2 release **HERE**

Svd2forth-v2 Example

Here all but the “COMP” Register (as it’s so simple) have been commented out in template.xml and “make” was run. The file “m” is then uploaded to the Mecrisp-Stellaris system MCU via your serial terminal

The following (non bold text) are terminal screendumps:-

words <enter>

— Flash Dictionary —
Address: 00004000 Link: 00004048 Flags: 00000000 Code: 00004010 Name: b32loop.
Address: 00004048 Link: 000040EC Flags: 00000000 Code: 00004052 Name: 1b.
Address: 000040EC Link: 00004148 Flags: 00000000 Code: 000040FA Name: b8loop.
Address: 00004148 Link: 0000419C Flags: 00000000 Code: 00004152 Name: 4b.
Address: 0000419C Link: 000041EC Flags: 00000000 Code: 000041AC Name: b16loop.
Address: 000041EC Link: 00004248 Flags: 00000000 Code: 000041F6 Name: 2b.
Address: 00004248 Link: 00004264 Flags: 00000040 Code: 00004254 Name: COMP
Address: 00004264 Link: 00004284 Flags: 00000040 Code: 00004274 Name: COMP_CSR
Address: 00004284 Link: FFFFFFFF Flags: 00000000 Code: 00004290 Name: COMP.

The word “comp.” lists the contents of the COMP_CSR Register in the default one bit format (1b.)

comp. <enter>

COMP_CSR $00000000
3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1
1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ok.

It can be displayed with different print formats:-

comp_csr 2b. <enter>

15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
comp_csr 4b. <enter>

07 06 05 04 03 02 01 00
0000 0000 0000 0000 0000 0000 0000 0000

Finally let’s read the Registers.text file which shows how to set any of the bitfields in a copy/paste friendly way

# cat registers.text

######################### COMP ###########################
COMP_CSR (read-write)
$00000000 CONSTANT RESET_COMP_CSR
bit pos arg Register name bitfield name bit width
: %1 0 lshift COMP_CSR bis! ; \ COMP_COMP1EN Bit 0 Width 1
: %1 1 lshift COMP_CSR bis! ; \ COMP_COMP1_INP_DAC Bit 1 Width 1
: %xx 2 lshift COMP_CSR bis! ; \ COMP_COMP1MODE Bit 2 Width 2
: %xxx 4 lshift COMP_CSR bis! ; \ COMP_COMP1INSEL Bit 4 Width 3
: %xxx 8 lshift COMP_CSR bis! ; \ COMP_COMP1OUTSEL Bit 8 Width 3
: %1 11 lshift COMP_CSR bis! ; \ COMP_COMP1POL Bit 11 Width 1
: %xx 12 lshift COMP_CSR bis! ; \ COMP_COMP1HYST Bit 12 Width 2
: %1 14 lshift COMP_CSR bis! ; \ COMP_COMP1OUT Bit 14 Width 1
: %1 15 lshift COMP_CSR bis! ; \ COMP_COMP1LOCK Bit 15 Width 1
: %1 16 lshift COMP_CSR bis! ; \ COMP_COMP2EN Bit 16 Width 1
: %xx 18 lshift COMP_CSR bis! ; \ COMP_COMP2MODE Bit 18 Width 2
: %xxx 20 lshift COMP_CSR bis! ; \ COMP_COMP2INSEL Bit 20 Width 3
: %1 23 lshift COMP_CSR bis! ; \ COMP_WNDWEN Bit 23 Width 1
: %xxx 24 lshift COMP_CSR bis! ; \ COMP_COMP2OUTSEL Bit 24 Width 3
: %1 27 lshift COMP_CSR bis! ; \ COMP_COMP2POL Bit 27 Width 1
: %xx 28 lshift COMP_CSR bis! ; \ COMP_COMP2HYST Bit 28 Width 2
: %1 30 lshift COMP_CSR bis! ; \ COMP_COMP2OUT Bit 30 Width 1
: %1 31 lshift COMP_CSR bis! ; \ COMP_COMP2LOCK Bit 31 Width 1

Bonus Words

Svd2Forth’s “m” (memory mapped Word file) also contains Register Print Words to display the Register contents, for all Registers enabled in ‘template.xml’. To print any Register just add a ”.” after the name, i.e. GPIOA. or RCC. etc.

Assuming you have enabled GPIOA, the “GPIOA.” Word should be in your Dictionary and produce similar results to the Cortex M0 listing below. I have attempted to label and space the bitfields as per the actual STM documentation, but where a custom label has not been created, generic labelling applies.

gpioa.

 GPIOA_MODER (read-write) $000000A0
 15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00
 00 00 00 00 00 00 00 00 00 00 00 00 10 10 00 00

 GPIOA_OTYPER (read-write) $00000000
 1|1|1|1|1|1|
 5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

 GPIOA_OSPEEDR (read-write) $0C000000
 15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00
 00 00 11 00 00 00 00 00 00 00 00 00 00 00 00 00

 GPIOA_PUPDR (read-write) $242AAAA0
 15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00
 00 10 01 00 00 10 10 10 10 10 10 10 10 10 00 00

 GPIOA_IDR (read-only) $00002008
 1|1|1|1|1|1|
 5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0
 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0

 GPIOA_ODR (read-write) $00000000
 1|1|1|1|1|1|
 5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

 GPIOA_BSRR (write-only) $00000000
 3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1|
 1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

 GPIOA_LCKR (read-write) $00000000
 3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1|
 1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

 GPIOA_AFRL (read-write) $00001100
  07   06   05   04   03   02   01   00
 0000 0000 0000 0000 0001 0001 0000 0000

 GPIOA_AFRH (read-write) $00000000
  15   14   13   12   11   10   09   08
 0000 0000 0000 0000 0000 0000 0000 0000

 GPIOA_BRR (write-only) $00000000
 3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1|
 1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

ok.