MSP430G2201 Counter

_images/MSP430G2201-pinouts.jpg _images/f4disco-roundpcb-2.jpg

This article reuses the small ‘roundpcb’ testboard previously featured in the blinky demo to investigate Timer-A0 using Mecrisp-Across. Bitfields.fs is used to supply the register names needed in the configuration and demonstrate the syntax.

The Program

All it does is configure the timer to run freely, then reads it eight times to see how the values change.

No big deal ?

Bear in mind that the MSP430 terminal I’m using actually doesn’t exist, the terminal is a emulation of a MSP430 terminal generated by Mecrisp-Across running under Mecrisp-Stellaris on a STM32F407 Discovery board as in the picture above.

In fact the Target MSP430 MCU doesn’t even HAVE a USART for a terminal of its own!

Mecrisp-Across supplies the emulated terminal, and using JTAG (the 4 wires in the pictures above) reads and writes registers on the MSP430 target.

Source Code

Those who read my Mecrisp-Stellaris Doc site will know that I’m a technician who programs, not a programmer.

Technicians have completely different goals to programmers, we design and fix hardware and programming is only a small part of the overall task for us.

As such I value the following attributes in my source code, stated in order of importance.

  • Readability

  • Maintainability

  • Traceability

  • Serviceability

Attribute

Description

Readability

No clever code, no magic numbers. This readability is for technicians like me.

Maintainability

10 years later, when the device is broken in some way, it needs to be fixed, the code has to make this part easy, not harder.

Traceability

Register names have to be MCU manufacturer technical manual compliant so hours don’t have to be wasted decoding ‘magic numbers’ and what they mean.

Serviceability

The source should have built in Test Words, such as make a stepper motor rotate once, clockwise, just to test it isn’t jammed.

IMPORTANT NOTE: Although the MSP430G2201 target has only 2KB of flash, the source doesn’t have to be made into the smallest size to fit because its running in the EMULATOR which has 64KB of ‘flash’. Mecrisp-Across is possibly one of the strongest optimizing Forth cross compilers you have ever seen. Out of the box, it does

  • Constant folding

  • Register allocation for both data and return stack

  • Dead code elimination (imagine a constant feed into case)

  • Register allocation across control structures

  • Determination which definitions are in use,

  • Automatic inlining of definitions used one time only

  • Interrupt handler framing depending on register usage

  • Finally, the Target binary image will be compiled to machine code before it’s flashed. This results in a tiny bootable image, for instance only 58 bytes for a Blinky.

Source Description

A BIG THANK YOU to Vadzim Dambrouski, https://github.com/pftbest/msp430_svd, who took DSlite files released by TI and processed them with the Rust programming language into SVD files suitable for my XML transforms.

All my recent SVD2Forth Bitfield transforms now follow this general syntax. This particular layout is only possible for the msp430.svd.

Bitfield Rules for the MSP430

  • The bitfield.fs file lists all the bitfields in the MCU.

  • All MCU registers are broken into segments of varying length and are used to configure peripherals. I call these segments Bitfields.

  • Configuring a MCU is all about configuring Bitfields.

  • Bitfield Words which require a input parameter have a “<<” appended to them to denote this. Words without the “<<” have no input parameter.

  • Where a Bitfield Word takes a parameter, the choices of parameter are listed directly below (in the bitfields.fs file), indented by six spaces for clarity.

  • Multiple Bitfields within the same Register may be added (+) together before being saved to that Register.

  • All Bitfield Words require the name of the Register followed by cbis!, cbic!, bis! or bic! to fully configure that register. These four Words do NOT affect the contents 0f other Bitfields.

Source

  • lines 31 - 34 instruct Mecrisp-Across to use emulation.

  • lines 36 - 55 are copied from the Bitfields.fs file IN THIS TARBALL

  • lines 59 - 60 configure the timer clock, only one Bitfield namely “BCSCTL3_LFXT1S<<” is needed. It can be clearly seen that the parameter “LFXT1S_2” is used.

  • lines 62 - 66 add multiple Bitfields to save to the Register “TA0CTL”

  • lines 68 - 80 run the program.

~/projects/programming-languages/forth/mecrisp-across/roundpcb-blinky/timertest.fs.html
 1 \ Program Name: timertest.fs
 2 \ Date: 17 Feb 2022 
 3 \ Copyright 2022  t.porter licensed under the GPL
 4 \ For Mecrisp-Across by Matthias Koch
 5 \ http://mecrisp.sourceforge.net/  features:
 6 \ chip: MSP430G2201 IRSA16R
 7 \ Aim: code a free running up counter and print its value eight consecutive times.
 8 
 9 \ 5.2.2 Internal Very-Low-Power Low-Frequency Oscillator (VLO)
10 \ ------------------------------------------------------------
11 \ The internal very-low-power low-frequency oscillator (VLO) provides a typical frequency of 12 kHz (see
12 \ device-specific data sheet for parameters) without requiring a crystal. VLOCLK source is selected by
13 \ setting LFXT1Sx = 10 when XTS = 0. The OSCOFF bit disables the VLO for LPM4. The LFXT1 crystal
14 \ oscillators are disabled when the VLO is selected reducing current consumption. The VLO consumes no
15 \ power when not being used.
16 \
17 \ Not all clock features are available on all MSP430x2xx devices:
18 \ MSP430G2201, LFXT1 does not support HF mode, XT2 is not present, ROSC is not supported.
19 \
20 \ Results
21 \ 6 
22 \ 23 
23 \ 50 
24 \ 77 
25 \ 104 
26 \ 141 
27 \ 178 
28 \ 215
29 \ ------------------------------------------------------------
30 
31 host
32 new
33 +jtag
34 target
35 
36 : TA0CTL_MC<< ( x -- ) 4 lshift ; \ Timer A mode control 1
37      0 constant MC_0      \ Timer A mode control: 0 - Stop  
38      1 constant MC_1      \ Timer A mode control: 1 - Up to CCR0  
39      2 constant MC_2      \ Timer A mode control: 2 - Continous up  
40      3 constant MC_3      \ Timer A mode control: 3 - Up/Down  
41 : TA0CTL_ID<< ( x -- ) 6 lshift ; \ Timer A clock input divider 1
42      0 constant ID_0      \ Timer A input divider: 0 - /1  
43      1 constant ID_1      \ Timer A input divider: 1 - /2  
44      2 constant ID_2      \ Timer A input divider: 2 - /4  
45      3 constant ID_3      \ Timer A input divider: 3 - /8  
46 : TA0CTL_TASSEL<< ( x -- ) 8 lshift ; \ Timer A clock source select 1
47      0 constant TASSEL_0      \ Timer A clock source select: 0 - TACLK  
48      1 constant TASSEL_1      \ Timer A clock source select: 1 - ACLK  
49      2 constant TASSEL_2      \ Timer A clock source select: 2 - SMCLK  
50      3 constant TASSEL_3      \ Timer A clock source select: 3 - INCLK
51 : BCSCTL3_LFXT1S<< ( x -- ) 4 lshift ; \ Mode 0 for LFXT1 (XTS = 0)
52      0 constant LFXT1S_0      \ Mode 0 for LFXT1 : Normal operation  
53      1 constant LFXT1S_1      \ Mode 1 for LFXT1 : Reserved  
54      2 constant LFXT1S_2      \ Mode 2 for LFXT1 : VLO  
55      3 constant LFXT1S_3      \ Mode 3 for LFXT1 : Digital input signal
56 
57 : configure ( -- )
58 \ timer clock                    \ LFXT1 feeds ACLK
59  LFXT1S_2 BCSCTL3_LFXT1S<<       \ VLO = 12 kHz  (or LFXT1S_0 = 32768-Hz crystal on MSP430G2201)
60              BCSCTL3 cbis!       \ note: XTS = 1 is not supported in MSP430G2201 devices
61 \ timer
62   MC_2 TA0CTL_MC<<
63    ID_0 TA0CTL_ID<<
64     TASSEL_1 TA0CTL_TASSEL<<
65              + + TA0CTL bis!     \ TA0CTL @ bin. 0000000100100001 ok.    
66 ;
67 
68 : main ( -- ) cr
69   configure
70   0 TA0R !        \ clear counter
71   TA0R @ . cr     \ read free running counter
72   TA0R @ . cr
73   TA0R @ . cr
74   TA0R @ . cr
75   TA0R @ . cr
76   TA0R @ . cr
77   TA0R @ . cr
78   TA0R @ . cr
79 ;
80 
81 main

Results

clear free running counter
free running counter = 7
free running counter = 24
free running counter = 52
free running counter = 79
free running counter = 107
free running counter = 144
free running counter = 182
free running counter = 220

Conclusion

If you’re still wondering what the compiled binary size would be, even tho it’s pointless running this on the target as is (because it has nothing to print with) …

With the “TA0R @ . cr” print commands removed, it compiled to only 46 bytes.

see configure
: configure
00009758 : 0000 : $00000002
00009764 : 0000 : BCSCTL3_LFXT1S<<
00009770 : 0000 : $00000053
0000977C : 0000 : cbis!
00009788 : 0000 : $00000002
00009794 : 0000 : TA0CTL_MC<<
000097A0 : 0000 : $00000000
000097AC : 0000 : TA0CTL_ID<<
000097B8 : 0000 : $00000001
000097C4 : 0000 : TA0CTL_TASSEL<<
000097D0 : 0000 : +
000097DC : 0000 : +
000097E8 : 0000 : $00000160
000097F4 : 0000 : bis!
00009800 : 0000 : ;
ok.

see main
: main
00009848 : 0000 : $0000000A
00009854 : 0000 : <--
0000988C : 0000 : $00000002
00009898 : 0000 : $00000003
000098A4 : 0000 : cbit@
000098B0 : 0000 : 0-Branch $00009854
000098BC : 0000 : $00000067
000098C8 : 0000 : c!
000098D4 : 0000 : configure
000098E0 : 0000 : $00000000
000098EC : 0000 : $00000170
000098F8 : 0000 : !
00009904 : 0000 : ;

main


host
disimage

F800: 40B2  mov.w #5A80h, &120h
F802: 5A80
F804: 0120
F806: 4031  mov.w #280h, r1
F808: 0280
F80A: 4034  mov.w #260h, r4
F80C: 0260
F80E: 4037  mov.w #Ah, r7
F810: 000A
F812: B3E2  bit.b #2h, &3h
F814: 0003
F816: 27FD  jz F812
F818: 47C2  mov.b r7, &67h
F81A: 0067
F81C: D0F2  bis.b #20h, &53h
F81E: 0020
F820: 0053
F822: D0B2  bis.w #120h, &160h
F824: 0120
F826: 0160
F828: 4382  mov.w #0h, &170h
F82A: 0170
F82C: 3FFF  jmp F82C

Memory usage in Flash without vector table 46 bytes.
Memory usage in RAM   without stacks       0 bytes.

$FFFE vector main crosscompile
Required passes: 1