furs

bfs!
Login

bfs!

In this page FURS is used to make a new Embedded Forth Word named 'bfs!' or 'set and store bit(field)

Audience - Forth programmers

A note on style: FURS uses the following styles:

CMSIS

Forth doesn't come with any Words that support CMSIS-SVD nomenclature, mainly because Forth is only the programming language, and has no knowledge of the peripherals, just like the C programming language. C gains this knowledge thru Header and Include files of libraries etc all of which use CMSIS to do so.

And Forth gains peripheral knowledge thru FURS which uses CMSIS as well.

New Word are Needed

In embedded design I often need to set or clear the value of a bitfield, to configure one aspect of a peripheral. So two new Words are needed bfs! and bfc!.

bfs! and bfc! Usage

In this example, the value of IOPDEN will be set to 1 (default = 0), and in FURS it would be expressed this way:

RCC_AHBENR_IOPDEN bfs! \ I/O port D clock enable

: bfs! ( cmsis-name x -- )

In practice, FURS will replace those words with values below before upload to the $(MCU), transforming the command like this

$40021014 1 20

Where :

Designing bfs! and bfc!
$40021014  ( 1 ) 20 1 .s Stack: [3 ]3  42 1073877012 20 1  ok.
swap .s Stack: [3 ]3  42 1073877012 1 20  ok.
lshift .s Stack: [2 ]2  42 1073877012 1048576  ok.
swap .s Stack: [2 ]2  42 1048576 1073877012  ok.
bis! .s Stack: [0 ]0  42  ok.    (or bic! for bfc!)

note: The Forth designer needed a 'placeholder' to show the stack was working properly, and he chose "the answer to everything", because why not ? So ignore the '42' as it's not counted by the stack counter (the number in square brackets).

note: bis! and bic!. The ( stack comments -- ) for these two Words show they take two parameters a mask and an address, then they output a value x. What the comment doesn't show is that they also first read the value at the address, AND it with the mask and that is the output x. So what does all this mean ?

it means two things:

1. these Words will only alter the targeted bits at an address while leaving all other bits untouched. The clue is the "mask" word in the stack comment.

2. This word is complex and takes 12 bytes as does bic!

see bis!
000019D8: CF03  ldmia r7 { r0  r1 }
000019DA: 6832  ldr r2 [ r6 #0 ] r6 #0 
000019DC: 4302  orrs r2 r0
000019DE: 6032  str r2 [ r6 #0 ] r6 #0 
000019E0: 000E  lsls r6 r1 #0
000019E2: 4770  bx lr
Bytes: 12  ok.
bis! ( mask a-addr -- x ) Set bit in word-location
bic! ( mask a-addr -- x ) Clear bit in word-location

SET the bit(s)

: bfs! ( cmsis-name x -- x ) swap lshift swap bis! ;

CLEAR the bit(s)

: bfc! ( cmsis-name x -- x ) swap lshift swap bic! ;

Dissasembly

see bfc!
0000EC98: CF08  ldmia r7 { r3 }
0000EC9A: 409E  lsls r6 r3
0000EC9C: CF08  ldmia r7 { r3 }
0000EC9E: 681A  ldr r2 [ r3 #0 ] r3 #0 
0000ECA0: 43B2  bics r2 r6
0000ECA2: 601A  str r2 [ r3 #0 ] r3 #0 
0000ECA4: CF40  ldmia r7 { r6 }
0000ECA6: 4770  bx lr
Bytes: 16  ok.

see bfs! 0000EC60: CF08 ldmia r7 { r3 } 0000EC62: 409E lsls r6 r3 0000EC64: CF08 ldmia r7 { r3 } 0000EC66: 681A ldr r2 [ r3 #0 ] r3 #0 0000EC68: 4316 orrs r6 r2 0000EC6A: 601E str r6 [ r3 #0 ] r3 #0 0000EC6C: CF40 ldmia r7 { r6 } 0000EC6E: 4770 bx lr Bytes: 16 ok.

Remember that bis! and bic! take 12 bytes themselves, so my words really only add another 4 bytes.

The testing results are correct. Here the IOPDEN bit(field) is set to 1, then cleared to 0.

$40021014  ( 1 ) 20 1 bfs!
rcc_ahbenr.  RW   $00100014
                  I   I I I I                         F
              T   O   O O O O                         L   S
              S   P   P P P P                     C   I   R   D
              C   F   D C B A                     R   T   A   M
              E   E   E E E E                     C   F   M   A
              N   N   N N N N                     E   E   E   E
             |2| |2| |2|1|1|1|                    N   N   N   N
~|~|~|~|~|~|~|4|~|2|~|0|9|8|7|~|~|~|~|~|~|~|~|~|~|6|~|4|~|2|~|0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0
$40021014  ( 1 ) 20 1 bfc!
rcc_ahbenr.  RW   $00000014
                  I   I I I I                         F
              T   O   O O O O                         L   S
              S   P   P P P P                     C   I   R   D
              C   F   D C B A                     R   T   A   M
              E   E   E E E E                     C   F   M   A
              N   N   N N N N                     E   E   E   E
             |2| |2| |2|1|1|1|                    N   N   N   N
~|~|~|~|~|~|~|4|~|2|~|0|9|8|7|~|~|~|~|~|~|~|~|~|~|6|~|4|~|2|~|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 1 0 1 0 0

Let's test how long bfs! and bfc! takes to run ?

Finally, all these cool print statements and timing measurements are made possible by swdcom.