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:
- CAPITALS: all CMSIS-SVD Words, i.e. MODER14
- lower case: all Forth Words, including user created Words, i.e. bf@
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 :
- RCC_AHBENR = $40021014
- IOPAEN = BitWidth BitOffset = 1 20
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.