BITFIELDS, DECLARE EARLY ?

This article is an addition to my bitfield series:

  1. keil c v/s svd2forth

  2. Bitfields and Structures

Why I Use and Declare Bitfields Early

I believe there are two Forth styles:

1. Programmer Style

This style deals with Forth programming, is efficient, well written and easily understood. It’s everything a Forth user appreciates.

\ Memmap
$40002800 constant RTC
RTC $C + CONSTANT RTC_ISR
RTC $10 + CONSTANT RTC_PRER

\ Program Code
: rtc-cal-set-on
$80 RTC_ISR bis!
BEGIN $40 RTC_ISR BIT@ UNTIL    \ Calendar registers update is allowed.
$7f00ff RTC_PRER !              \ From LSI, LSE - $ff
$7f00ff RTC_PRER !
;

2. My Electronics Technician Style

My style (below) looks like it was written by a bored programmer on Friday afternoon. It’s longer than the code above and most programmers would want to factor out Bitfields below as much of it seems redundant to them. The Forth programmer mind simply cannot resist factoring everything into its most basic form.

And that’s a very good thing, a highly honed efficiency skill that is somewhat rare in a world of excess computing resources.

Then why do I use bitfields, what information do they provide that the Programmer Style above does not ?

The answer for the impatient is HARDWARE INFORMATION which it totally lacking in the Programmer Style above. Please permit me to explain below.

\ Memmap
$40002800 constant RTC
RTC $C + CONSTANT RTC_ISR
RTC $10 + CONSTANT RTC_PRER


\ Bitfields
\ RTC_ISR () Reset:0x00000007
: RTC_ISR_INIT ( -- x addr ) 7 bit RTC_ISR ;                     \ RTC_ISR_INIT, Initialization mode
: RTC_ISR_INITF? ( -- x addr ) 6 bit RTC_ISR bit@ ;              \ RTC_ISR_INITF, Initialization flag

\ RTC_PRER (read-write) Reset:0x007F00FF
: RTC_PRER_PREDIV_A ( %bbbbbbb -- x addr ) 16 lshift RTC_PRER ;  \ RTC_PRER_PREDIV_A, Asynchronous prescaler  factor
: RTC_PRER_PREDIV_S ( %bbbbbbbbbbbbbbb -- x addr ) RTC_PRER ;    \ RTC_PRER_PREDIV_S, Synchronous prescaler  factor


\ Program Code
: rtc-cal-set-on
  RTC_ISR_INIT BIS!                                              \ Enter RTC Initialization mode
  begin RTC_ISR_INITF? until                                     \ Loop until Calendar has been initialized
  %1111111 RTC_PRER_PREDIV_A bis!                                \ Asynchronous prescaler factor
  %11111111 RTC_PRER_PREDIV_S bis!                               \ Synchronous prescaler factor
;

Programmer Style Example

In this example I use source from the Mecrisp-Stellaris user contributions to deconstruct a code segment and analyse the configuration of hardware involved.

We can’t see how it works without referring to the Technical Reference for the MCU involved. This can be very time consuming especially if has to be done for every peripheral register used in the source.

$40002800 constant RTC
RTC $C + CONSTANT RTC_ISR
RTC $10 + CONSTANT RTC_PRER

: rtc-cal-set-on
$80 RTC_ISR bis!
BEGIN $40 RTC_ISR BIT@ UNTIL \ Calendar registers update is allowed.
$7f00ff RTC_PRER !           \ From LSI, LSE - $ff
$7f00ff RTC_PRER !
;

Deconstructing the Programmer Style Example

$80 RTC_ISR bis!

This means “set bit 7 of RTC_ISR”.

$80 bin. $00000080
3322222222221111111111
10987654321098765432109876543210
00000000000000000000000010000000

But what IS bit7 ? We need to look in the Technical manual to find that out that bit7 is the RTC init mode

_images/rtc_isr.jpg _images/rtc_isr-2.jpg

BEGIN $40 RTC_ISR BIT@ UNTIL

This code reads bit 6 (INITF) of the RTC_ISR, looping until it is HIGH

$40 bin. $00000040
3322222222221111111111
10987654321098765432109876543210
00000000000000000000000001000000

$7f00ff RTC_PRER !

Writes $7f00ff to the RTC_PRER register. But why twice ?

$7f00ff RTC_PRER !           \ From LSI, LSE - $ff
$7f00ff RTC_PRER !

RTC_PRER Register

_images/rtc_prer.jpg

The RTC_PRER register has two bitfields, “RTC_PRER_PREDIV_A” and “RTC_PRER_PREDIV_S”.

It’s obvious the coder is writing both the RTC_PRER_PREDIV_A and RTC_PRER_PREDIV_S bitfields at the same time by writing to the RTC_PRER register with a CELL wide value. But why is this done TWICE ? It’s because the RTC prescaler register (RTC_PRER) initialization must be performed in two separate write accesses, i.e. once for RTC_PRER_PREDIV_A and once for RTC_PRER_PREDIV_S

Looking at the binary value being written into register RTC_PRER. One can see that the $7F part will be written to “RTC_PRER_PREDIV_A” and the $FF part to “RTC_PRER_PREDIV_S” at the same time. This is then done again to complete the required sequence.

$7f00ff RTC_PRER !           \ From LSI, LSE - $ff

$7f00ff bin. $007F00FF
3322222222221111111111
10987654321098765432109876543210
00000000011111110000000011111111

Electronics Technician Style

Otherwise known as “Declare Bitfields Early”, this style uses bitfield definitions derived from the CMSIS-SVD file released by the manufacturer of the MCU and transformed by XSLT.

The Bitfields paragraph contains vital hardware information, necessary for the easy maintenance of this code years later and possibly negating the requirement of having a Technical Reference on hand ?

The bitfield definitions tells me whether a bitfield is a single bit that requires setting, clearing or testing or whether it is a multi bit choice and how many bits there are. The comments field also provides a terse summary of the bitfield function.

Finally the name of the bitfield definition is CMSIS-SVD compliant and can be used to search a technical reference PDF for more information.

\ Memmap
$40002800 constant RTC
RTC $C + CONSTANT RTC_ISR
RTC $10 + CONSTANT RTC_PRER


\ Bitfields
\ RTC_ISR () Reset:0x00000007
: RTC_ISR_INIT ( -- x addr ) 7 bit RTC_ISR ;                     \ RTC_ISR_INIT, Initialization mode
: RTC_ISR_INITF? ( -- x addr ) 6 bit RTC_ISR bit@ ;              \ RTC_ISR_INITF, Initialization flag
\ RTC_PRER (read-write) Reset:0x007F00FF
: RTC_PRER_PREDIV_A ( %bbbbbbb -- x addr ) 16 lshift RTC_PRER ;  \ RTC_PRER_PREDIV_A, Asynchronous prescaler  factor
: RTC_PRER_PREDIV_S ( %bbbbbbbbbbbbbbb -- x addr ) RTC_PRER ;    \ RTC_PRER_PREDIV_S, Synchronous prescaler  factor


\ Program Code
: rtc-cal-set-on
  RTC_ISR_INIT BIS!                                              \ Enter RTC Initialization mode
  begin RTC_ISR_INITF? until                                     \ Loop until Calendar has been initialized
  %1111111 RTC_PRER_PREDIV_A bis!                                \ Asynchronous prescaler factor
  %11111111 RTC_PRER_PREDIV_S bis!                               \ Synchronous prescaler factor
;

Summary

Embedded programmers have to worry about the hardware and the software, they are of equal importance, now when the program is written, and years later when it’s maintained, upgraded or just repaired.

Removing all the hardware information isn’t embedded programming, it’s just programming.