> 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 https://sourceforge.net/projects/mecrisp/ 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

memmap

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

...

register-reference

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 svd2forth-v2.1.0.zip **HERE**

See the README contained in the release for more detailed instructions.

Bonus Peripheral Register Print Words

Svd2Forth’s “memmap.fs” (memory mapped Word file) also contains Peripheral Register Print Words to display Register contents, for all Peripherals enabled in ‘template.xml’. To print any Peripheral just add a ”.” after the name, i.e. GPIOA becomes GPIOA. or RCC becomes 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. The automatic file generation means that generic ‘one bit’ labelling applies as in the following listing.

gpioa. GPIOA_MODER (read-write) $28280000
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 1 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

GPIOA_OTYPER (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_OSPEEDR (read-write) $0C000000
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 1 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

GPIOA_PUPDR (read-write) $24000000
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 1 0 0 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

GPIOA_IDR (read-only) $0000BDFE
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 1 0 1 1 1 1 0 1 1 1 1 1 1 0 1 0

GPIOA_ODR (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_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) $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_AFRH (read-write) $00000110
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 1 0 0 0 1 0 0 0 0

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

Register Reference File

A Register Bitfield programmer development reference file is created to suit your choice of MCU. For every Peripheral selected in ‘template.xml’ a paragraph like the following example is generated.

Example

Short Usage Guide: Please refer to the Dictionary for the full details.

Note

Replace ‘bi?’ with ‘bit@’ to test bit, ‘bis!’ to SET bit, ‘bic!’ to CLEAR bit etc.

################################### GPIOC ###################################
GPIOC_MODER (read-write)
$00000000 CONSTANT RESET_GPIOC_MODER
 %xx  30 lshift GPIOC_MODER bi?        \ GPIOC_MODER15 Bit-30  Width-2
 %xx  28 lshift GPIOC_MODER bi?        \ GPIOC_MODER14 Bit-28  Width-2
 %xx  26 lshift GPIOC_MODER bi?        \ GPIOC_MODER13 Bit-26  Width-2
 %xx  24 lshift GPIOC_MODER bi?        \ GPIOC_MODER12 Bit-24  Width-2
 %xx  22 lshift GPIOC_MODER bi?        \ GPIOC_MODER11 Bit-22  Width-2
 %xx  20 lshift GPIOC_MODER bi?        \ GPIOC_MODER10 Bit-20  Width-2
 %xx  18 lshift GPIOC_MODER bi?        \ GPIOC_MODER9  Bit-18  Width-2
 %xx  16 lshift GPIOC_MODER bi?        \ GPIOC_MODER8  Bit-16  Width-2
 %xx  14 lshift GPIOC_MODER bi?        \ GPIOC_MODER7  Bit-14  Width-2
 %xx  12 lshift GPIOC_MODER bi?        \ GPIOC_MODER6  Bit-12  Width-2
 %xx  10 lshift GPIOC_MODER bi?        \ GPIOC_MODER5  Bit-10  Width-2
 %xx  8 lshift GPIOC_MODER bi?        \ GPIOC_MODER4   Bit-8   Width-2
 %xx  6 lshift GPIOC_MODER bi?        \ GPIOC_MODER3   Bit-6   Width-2
 %xx  4 lshift GPIOC_MODER bi?        \ GPIOC_MODER2   Bit-4   Width-2
 %xx  2 lshift GPIOC_MODER bi?        \ GPIOC_MODER1   Bit-2   Width-2
 %xx  0 lshift GPIOC_MODER bi?        \ GPIOC_MODER0   Bit-0   Width-2

Set GPIO-A1 to OUTPUT MODE

%10  2 lshift GPIOA_MODER bis!

TEST GPIO-A1 In OUTPUT MODE

Note

-1 is TRUE, 0 is FALSE

%10  2 lshift GPIOA_MODER bit@ .
-1  ok.

Set GPIO-A1 to INPUT MODE

%10  2 lshift GPIOA_MODER bic!

TEST GPIO-A1 IS NOT In OUTPUT MODE

%10  2 lshift GPIOA_MODER bit@ .
0  ok.