Bitfields

Warning

This page is for embedded Forth people, others may find it far too esoteric.

A Word about Bitfields

Non embedded programmers generally don’t think in terms of bitfields because neat word or byte boundaries are the norm in their world.

Embedded C programmers normally get their bitfields bundled up in structures organised by functionality. I.e. a disparate collection of bitfields from a number of different registers become a GPIO structure and so on.

I do my embedded programming using bitfields and group them by register.

Furthermore I also pre-process the bitfields so that their names assist comprehension and maintenance.

It’s true that the bitfields are just BITs but there are different ways of interpreting them.

Some ways are a maintainers nightmare and help spread the (untrue) rumour that Forth is ‘read only’.

While Forth source can easily be written as ‘read only’ so can any other language, here are some examples.

Write Only Code

This source code works, but it’s very painful and tedious to decode. You need the Technical Reference Manual and a hex calculator at hand. There is no way to tell what it’s doing just by reading it.

It does however compile into the most compact code.

$40000 $40021014 bis!
1 $48000400 bis!
$C $48000400 bis!

This code example was derived from the ‘Better Code’ example below, the register names were replaced by their hex address.

Better Code

This code sample uses register names, which increases comprehension and maintenance enormously, it also requires preloading all register hex addresses.

Because bitfield names are not used, the Technical Reference Manual is again required to understand this code.

constant $40021014 RCC_AHBENR
constant $48000400 GPIOB_MODE

\ Enable GPIOB peripheral clock, set pin PB0 as led output (push-pull) and set PB1 as analog input
%1 18 lshift RCC_AHBENR bis!
%01 GPIOB_MODER bis!
%11 2 lshift GPIOB_MODER bis!

Svd2forth-v6

This source has the same functionality as above, but uses Svd2forth-v6. There is no need for constants or bitfields to be predefined as this is done automatically when the source is read and a ‘includes.fs’ file containing these dependencies is created. This is uploaded before this source.

This is done using the Gema ‘preprocessor’ <http://gema.sourceforge.net/new/index.shtml> .

The register and bitfields only need be named in the source.

Source

RCC_AHBENR_IOPBEN RCC_AHBENR bis!     \ enable GPIOB peripheral clock
OUTPUT GPIOB_MODER_MODER0<<           \ set PB0 to OUTPUT
ANALOG GPIOB_MODER_MODER1<<           \ set PB1 to ANALOG
+ GPIOB_MODER bis!

Includes.fs

Preloaded automatically before the source is loaded.

$40021014 constant RCC_AHBENR
$48000400 constant GPIOB_MODER
: GPIOB_MODER_MODER0<<   ( %2 --  x )             ; \ rw","2","0","Port x configuration bits y =  0..15
: GPIOB_MODER_MODER1<<   ( %2 --  x )   2 lshift  ; \ rw","2","2","Port x configuration bits y =  0..15

Where further technical assistance is needed, the includes.fs file offers more bitfield information such as stack diagram, bitfield access-type (read-write, etc), bitfield Width and Offset, and description.

Intelligent Processing

Svd2forth-V6 uses a combination of ‘access type’, ‘bitWidth’ and ‘bitOffset’ to intelligently optimise each bitfield action as tabled below.

This is still under construction @ Jul 2021

Suffix

Access?

bitW, bitOff

Stack Comment

Example

Comment

Automatic Word Action

<<

rw

bw 2, bo 30

( %2 – x )

ANALOG GPIOB_MODER_MODER15<< GPIOB_MODER BIS!

Set PB15 to ANALOG (%11)

30 lshift

?

ro

bw 1, bo 25

( – 1|0 )

DO RCC_CR_PLLRDY? LOOP

Wait until PLLRDY is set

1 25 lshift RCC_CR bit@

!

wo

bw 1, bo 31

( – )

GPIOF_BSRR_BR15!

Reset PF15

1 31 lshift GPIOF_BSRR !

@

rw

bw 2, bo 2

( – x )

RCC_CFGR_SWS@

fetch System Clock Switch Status

2 bitwidthmask 2 lshift RCC_CFGR @ and 2 rshift

Bitfield Viewer

This is a preview of my prototype Bitfield Viewer and select tool.

The aim was to make a easy to use Bitfield viewer that can preselect any peripheral and then easily scroll to find the right bitfield before copying it to the programmers source.

The bitfield data resides in a Sqlite3 database built automatically by swd2forth-v6, which means any client that can read Sqlite3 databases can use it. In this picture the reader is https://github.com/inloop/sqlite-viewer

Visual Simplification

Understanding Cortex-M peripheral registers and bitfields can be daunting because of their abundance, so the Bitfield Viewer was also designed to present this information in a simpler way.

  • By selecting one peripheral at a time to reduce visual noise.

  • listing the number of rows in a peripheral. Apart from the “Reset Value” row at start of each register, all the other rows are bitfields. For instance TIM6 has 22 rows, but TIM1 has 150, so straight away you can see which is the more complex timer.

Tim6 Peripheral View

_images/bitfield-viewer-tim6-sml.jpg

Cli Input Selections

Prefer a CLI method ?

sqlite3 bitfields.db ".mode column" ".headers on" ".width 25 22 20 6 6 6 40" "SELECT * FROM tim6"

name                       stack                   word                  access  bitwid  bitoff  description
-------------------------  ----------------------  --------------------  ------  ------  ------  ----------------------------------------
 Basic-timers              -                       -                     -       -       -       -
 TIM6_CR1                   Reset Value $0000      -                     -       -       -       -
 TIM6_CR1_ARPE                 ( --  x )             1 7 lshift            rw    1       7       Auto-reload preload enable
 TIM6_CR1_OPM                  ( --  x )             1 3 lshift            rw    1       3       One-pulse mode
 TIM6_CR1_URS                  ( --  x )             1 2 lshift            rw    1       2       Update request source
 TIM6_CR1_UDIS                 ( --  x )             1 1 lshift            rw    1       1       Update disable
 TIM6_CR1_CEN                  ( --  1 )             1                     rw    1       0       Counter enable
 TIM6_CR2                   Reset Value $0000      -                     -       -       -       -
 TIM6_CR2_MMS<<               ( %3 --  x )          4 lshift               rw    3       4       Master mode selection
 TIM6_DIER                  Reset Value $0000      -                     -       -       -       -
 TIM6_DIER_UDE                 ( --  x )             1 8 lshift            rw    1       8       Update DMA request enable
 TIM6_DIER_UIE                 ( --  1 )             1                     rw    1       0       Update interrupt enable
 TIM6_SR                    Reset Value $0000      -                     -       -       -       -
 TIM6_SR_UIF                   ( --  1 )             1                     rw    1       0       Update interrupt flag
 TIM6_EGR                   Reset Value $0000      -                     -       -       -       -
 TIM6_EGR_UG!                  ( --  )               1 TIM6_EGR bis!       wo    1       0       Update generation
 TIM6_CNT                   Reset Value $00000000  -                     -       -       -       -
 TIM6_CNT_CNT<<               ( %16 --  x )                                rw    16      0       Low counter value
 TIM6_PSC                   Reset Value $0000      -                     -       -       -       -
 TIM6_PSC_PSC<<               ( %16 --  x )                                rw    16      0       Prescaler value
 TIM6_ARR                   Reset Value $00000000  -                     -       -       -       -
 TIM6_ARR_ARR<<               ( %16 --  x )                                rw    16      0       Low Auto-reload value

IWDG Peripheral View

How complex is the Watchdog peripheral ?

_images/svd2forth-v6-bitfields-database-viewer2-sml.jpg

Peripheral Selection View

All the MCU (STM32F051) peripherals are in this list for easy choice.

_images/svd2forth-v6-bitfields-database-viewer-sml.jpg

Perhaps you prefer the CLI ?

% sqlite3 bitfields.db
SQLite version 3.26.0 2018-12-01 12:34:55
Enter ".help" for usage hints.
sqlite> .tables
ADC     DAC     Flash   GPIOD   I2C2    RCC     SYSCFG  TIM16   TIM6    WWDG
CEC     DBGMCU  GPIOA   GPIOE   IWDG    RTC     TIM1    TIM17   TSC
COMP    DMA     GPIOB   GPIOF   NVIC    SPI1    TIM14   TIM2    USART1
CRC     EXTI    GPIOC   I2C1    PWR     SPI2    TIM15   TIM3    USART2

sqlite> .mode column
sqlite> .width 15 15 15 4 2 2 50
sqlite> SELECT * FROM 'TIM1' LIMIT 0,30 ;
Advanced-timer  -                -                -     -   -   -
TIM1_CR1         Reset Value $0  -                -     -   -   -
TIM1_CR1_CKD<<     ( %2 --  x )   8 lshift          rw  2   8   Clock division
TIM1_CR1_ARPE       ( --  x )      1 7 lshift       rw  1   7   Auto-reload preload enable
TIM1_CR1_CMS<<     ( %2 --  x )   5 lshift          rw  2   5   Center-aligned mode  selection
TIM1_CR1_DIR        ( --  x )      1 4 lshift       rw  1   4   Direction
TIM1_CR1_OPM        ( --  x )      1 3 lshift       rw  1   3   One-pulse mode
TIM1_CR1_URS        ( --  x )      1 2 lshift       rw  1   2   Update request source
TIM1_CR1_UDIS       ( --  x )      1 1 lshift       rw  1   1   Update disable
TIM1_CR1_CEN        ( --  1 )      1                rw  1   0   Counter enable
TIM1_CR2         Reset Value $0  -                -     -   -   -
TIM1_CR2_OIS4       ( --  x )      1 14 lshift      rw  1   14  Output Idle state 4
TIM1_CR2_OIS3N      ( --  x )      1 13 lshift      rw  1   13  Output Idle state 3
TIM1_CR2_OIS3       ( --  x )      1 12 lshift      rw  1   12  Output Idle state 3
TIM1_CR2_OIS2N      ( --  x )      1 11 lshift      rw  1   11  Output Idle state 2
TIM1_CR2_OIS2       ( --  x )      1 10 lshift      rw  1   10  Output Idle state 2
TIM1_CR2_OIS1N      ( --  x )      1 9 lshift       rw  1   9   Output Idle state 1
TIM1_CR2_OIS1       ( --  x )      1 8 lshift       rw  1   8   Output Idle state 1
TIM1_CR2_TI1S       ( --  x )      1 7 lshift       rw  1   7   TI1 selection
TIM1_CR2_MMS<<     ( %3 --  x )   4 lshift          rw  3   4   Master mode selection
TIM1_CR2_CCDS       ( --  x )      1 3 lshift       rw  1   3   Capture/compare DMA  selection
TIM1_CR2_CCUS       ( --  x )      1 2 lshift       rw  1   2   Capture/compare control update  selection
TIM1_CR2_CCPC       ( --  1 )      1                rw  1   0   Capture/compare preloaded  control
TIM1_SMCR        Reset Value $0  -                -     -   -   -
TIM1_SMCR_ETP       ( --  x )      1 15 lshift      rw  1   15  External trigger polarity
TIM1_SMCR_ECE       ( --  x )      1 14 lshift      rw  1   14  External clock enable
TIM1_SMCR_ETPS     ( %2 --  x )   12 lshift         rw  2   12  External trigger prescaler
TIM1_SMCR_ETF<     ( %4 --  x )   8 lshift          rw  4   8   External trigger filter
TIM1_SMCR_MSM       ( --  x )      1 7 lshift       rw  1   7   Master/Slave mode
TIM1_SMCR_TS<<     ( %3 --  x )   4 lshift          rw  3   4   Trigger selection

Search Gui

_images/sqlite-gui-search-sml.jpg

Search

.mode column
.width 20 15 15 4 2 2 50
sqlite> SELECT * FROM 'RCC'  WHERE name LIKE '%APB1ENR%';
RCC_APB1ENR           Reset Value $0  -                -     -   -   -
RCC_APB1ENR_TIM2EN       ( --  1 )      1                rw  1   0   Timer 2 clock enable
RCC_APB1ENR_TIM3EN       ( --  x )      1 1 lshift       rw  1   1   Timer 3 clock enable
RCC_APB1ENR_TIM6EN       ( --  x )      1 4 lshift       rw  1   4   Timer 6 clock enable
RCC_APB1ENR_TIM14EN      ( --  x )      1 8 lshift       rw  1   8   Timer 14 clock enable
RCC_APB1ENR_WWDGEN       ( --  x )      1 11 lshift      rw  1   11  Window watchdog clock  enable
RCC_APB1ENR_SPI2EN       ( --  x )      1 14 lshift      rw  1   14  SPI 2 clock enable
RCC_APB1ENR_USART2E      ( --  x )      1 17 lshift      rw  1   17  USART 2 clock enable
RCC_APB1ENR_I2C1EN       ( --  x )      1 21 lshift      rw  1   21  I2C 1 clock enable
RCC_APB1ENR_I2C2EN       ( --  x )      1 22 lshift      rw  1   22  I2C 2 clock enable
RCC_APB1ENR_PWREN        ( --  x )      1 28 lshift      rw  1   28  Power interface clock  enable
RCC_APB1ENR_DACEN        ( --  x )      1 29 lshift      rw  1   29  DAC interface clock enable
RCC_APB1ENR_CECEN        ( --  x )      1 30 lshift      rw  1   30  HDMI CEC interface clock  enable

See also

PLANG

See also

PLANG Reader

f0 disco lmt01 gema

Back to: f0 disco lmt01 gema

Or

Back to: Quadrature Rotary Switch