3 WHAT IS FAST FORTH FOR MSP430FR ?
5 FAST FORTH IS IT AN IDE ?
6 HOW TO MIX ASSEMBLY and FORTH ?
8 ASSEMBLY WITHOUT LABEL ?
9 SYMBOLIC ASSEMBLER ? YES !
10 COMPILE FAST FORTH FOR YOUR MODULE
12 Case of MSP430FR2xxx family (with FLL)
15 WHAT IS FAST FORTH FOR MSP430FRxxxx ?
18 FAST FORTH is a FORTH program written in MSP430 assembly and it runs on TI's LAUNCHPAD :
19 MSP-EXP430FR5739, MSP-EXP430FR5969, MSP-EXP430FR6989... or any MSP430 FRAM device.
20 Its core is ANS FORTH standard compliant.
22 Built-in assembler allows you to program an application using interruptions and LPMX modes.
24 If you are beginner in FORTH, a vastefull literature is available on the web, try: http://www.forth.org/tutorials.html.
25 Select "starting Forth" of Leo Brodie, that is sufficient for our purpose.
26 In addition, as you can see in forthMSP430FR.asm, each FORTH word definition includes a reference to the ANS standard.
33 a TI launchpad, the basic MSP-EXP430FR5969 or the MSP_EXP4305994 with SD card slot.
35 an UARTtoUSB cable with a PL2303TA (best choice) :
37 RX and TX wires are 3.3V level.
39 BE CAREFULL ! if you plan to supply your MSP430FRxxxx device with the PL2303TA cable,
40 you MUST open it to weld the red wire (+) onto the 3.3V pad !!!
44 or UARTtoUSB bridge with CP2102 device :
45 search on ebay :"UART to USB CP2102"
46 Check for a 3.3V pin before paying !
49 If you want to test RC5toLCD.f :
51 a standard LCD DISPLAY 2x16 or 2x20 chars,
52 a VISHAY IR receiver TSOP32236 or equivalent plus an IR remote with RC5/RC6 Philips protocol,
53 a piece of PCB to wire the diode, resistor and two capacitors of the LCD_Vo booster. See RC5toLCD.f
55 And to use the SD_Card extension :
57 http://www.ebay.com/itm/2-PCS-SD-Card-Module-Slot-Socket-Reader-For-Arduino-MCU-/181211954262?pt=LH_DefaultDomain_0&hash=item2a3112fc56
58 http://fr.aliexpress.com/item/5V-3-3V-Compatible-Perfect-SD-Card-Module-Slot-Socket-Reader-For-ARM-MCU-Read/32223868267.html?isOrigTitle=true
63 I suggest you to wire constantly the RX0 TX0 pins of your LAUNCHPAD (RX1 TX1 pins for MSP-EXP430FR6989 launchpad) to a free USB socket on your PC via the cable UARTtoUSB PL2303TA.
64 So you can drag and drop HEX file on MSP-EXP430FRxxxxprog.bat to regenerate FORTH kernel or download RC5toLCD.f without doing anything else...
67 FAST FORTH IS IT AN IDE ?
70 YES, if you admit that you can program in FORTH / in assembler, not C... Look at "RC5toLCD.f".
72 In fact, you have an IDE with two languages, one low level other high level, and it's easy to mix them.
75 HOW TO MIX assembly and FORTH ?
78 FAST FORTH knows two kinds of words :
80 low level assembly words start with CODE <name> and end with ENDCODE.
82 high level FORTH words begin with : <name> and end with ;
87 CODE ADD \ Assembly word, alias of word +
93 : NOOP \ FORTH word, do nothing
100 To end a low level assembly word, the instruction MOV @IP+,PC jumps to the next FORTH word. This faster (4 cycles) and shorter (one word) instruction replaces the famous pair of assembly instructions : CALL #LABEL ... RET (4+4 cycles, 2+1 words). The register IP is the Interpretative Pointer.
102 High level FORTH word starts with a boot code DOCOL that save the IP pointer, load it with the first address of a list of execution addresses, then perform a postincrement branch to this first address. The list ends with the address of another piece of code EXIT (6 cycles) that restores IP before the instruction MOV @IP+,PC.
105 here, the compilation of low level word ADD :
107 preamble \ compiled by the word CODE
108 execution addr ADD @PSP+,TOS
109 MOV @IP+,PC \ instruction called NEXT
111 and the one of the high level word NOOP :
113 preamble \ compiled by the word :
114 execution addr PUSH IP \ boot code compiled by the word :
115 CALL rEXIT \ boot code compiled by the word :
116 addr of DUP \ execution addr of DUP
117 addr of DROP \ execution addr of DROP
118 addr of EXIT \ execution addr of EXIT compiled by the word ;
121 _A high level FORTH word is a list of execution addresses preceded by a boot code and ending with EXIT address._
127 any low level FORTH words must be ended with the instruction MOV @IP+,PC (NEXT).
129 CODE TEST \ CODE starts a low level word
130 asm1 \ assembly instruction 1
131 asm2 \ assembly instruction 2
133 ENDCODE \ end of low level word
136 If you want to use the IP register, save it before and restore it before NEXT
138 CODE TEST1 \ CODE starts a low level word
139 asm1 \ assembly instructions
141 PUSH IP \ save IP before use
142 MOV #1,IP \ assembly instruction that uses IP
143 ... \ assembly instructions
144 MOV @RSP+,IP \ restore IP
146 ENDCODE \ end of low level word
149 A little more complex, the case of mixing FORTH and assembly that is enabled by the words HI2LO, LO2HI and COLON
151 : MIX_FORTH_ASM \ definition of a FORTH word starts with :
154 HI2LO \ FORTH to assembler switch
155 asm1 \ assembly instruction
156 asm2 \ assembly instruction
157 ... \ you can freely use IP !
158 ... \ assembly instructions
159 MOV @RSP+,IP \ restore IP
161 ENDCODE \ end of low level word
163 If we see the code "MIX\_FORTH\_ASM" after compilation :
165 preamble \ compiled by :
166 exec@ PUSH IP \ save IP compiled by :
167 CALL rEXIT \ execute EXIT compiled by :
168 addr \ execution addr of SWAP
169 addr \ execution addr of DUP
170 next addr \ addr of asm1, compiled by HI2LO
171 asm1 \ assembly instruction
172 asm2 \ assembly instruction
173 ... \ you can freely use IP !
174 ... \ assembly instructions
175 MOV @RSP+,IP \ restore IP saved by :
178 the instruction "CALL rEXIT" (CALL R7), have EXIT address as rEXIT content.
181 going a step further :
183 CODE MIX_ASM_FORTH \ CODE starts a low level word
184 asm1 \ assembly instruction 1
185 asm2 \ assembly instruction 2
186 COLON \ starts high level
189 ; \ end of high level word
192 If we see this code "MIX\_ASM\_FORTH" after compilation :
194 preamble \ compiled by CODE
195 exec@ asm1 \ assembly instruction 1
196 asm2 \ assembly instruction 2
197 PUSH IP \ save IP compiled by COLON
198 CALL rEXIT \ execute EXIT compiled by COLON
201 addr of EXIT \ the word ; compiles EXIT that restores IP then executes MOV @IP+,PC
206 the first time, at the start of FORTH word, after save IP:
208 EXIT MOV @RSP+,IP \ 2 pop into IP next PC pushed on return stack by CALL rEXIT
209 MOV @IP+,PC \ 4 execute the routine pointed by the the address next "CALL rEXIT"
211 then at the end of FORTH word :
213 EXIT MOV @RSP+,IP \ 2 pop old IP from return stack
214 MOV @IP+,PC \ 4 execute the routine pointed by the old IP
219 : MIX_FORTH_ASM_FORTH \ definition of a FORTH word starts with :
223 HI2LO \ FORTH to assembler switch
224 MOV #0,IP \ IP is free for use
227 LO2HI \ assembler to FORTH switch
230 ; \ end of high level word
234 preamble \ compiled by :
235 exec@ PUSH IP \ save IP compiled by :
236 CALL rEXIT \ move next PC from return stack into IP, compiled by :
240 next addr \ compiled by HI2LO
241 MOV #0,IP \ IP is free for use
242 asm1 \ assembly instruction
244 CALL rEXIT \ compiled by LO2HI (10 cycles switch)
251 CODE MIX_ASM_FORTH_ASM \ CODE starts a low level word
252 asm1 \ assembly instruction
253 asm2 \ assembly instruction
254 COLON \ starts high level
257 HI2LO \ FORTH to assembler switch
258 asm3 \ assembly instruction
259 asm4 \ assembly instruction
260 MOV @RSP+,IP \ restore IP
262 ENDCODE \ end of low level word
264 In fact, an exclusive of FAST FORTH, the start of a word FORTH can be placed anywhere :
266 CODE MIX_ASM_FORTH_ASM_FORTH
270 COLON \ starts high level
274 HI2LO \ FORTH to assembler switch
278 LO2HI \ assembler to FORTH switch
282 ; \ end of high level word
284 with the compiled result :
286 preamble \ compiled by CODE
289 PUSH IP \ compiled by COLON
290 CALL rEXIT \ compiled by COLON
293 next address \ compiled by HI2LO
296 CALL rEXIT \ compiled by LO2HI
299 EXIT addr \ that restores IP from return stack and then executes MOV @IP+,PC
301 As we see, IP is saved only once, it's logical.
304 ASSEMBLY WITHOUT LABEL ?
307 Yes ! the assembly syntax borrows FORTH's one for jumps :
310 CMP #1,R8 \ set Z,N,V, flags
311 0= IF \ irritating, the "IF =" upside down, isn't it?
312 ADD R8,R9 \ true part of comparaison
315 MOV @IP+,PC \ don't forget...
316 ENDCODE \ don't forget...
318 and the complete version :
320 CODE TEST_IF_ELSE_THEN
321 CMP #1,R8 \ set Z,N,V, flags
323 ADD R8,R9 \ true part of comparaison
325 SUB R8,R9 \ false part of comparaison
327 ... \ following for the two branches
328 MOV @IP+,PC \ don't forget...
329 ENDCODE \ don't forget...
331 test for loop back version BEGIN ... UNTIL
333 CODE TEST_BEGIN_UNTIL
336 SUB #1,R10 \ set Z,N,V flags
337 0= UNTIL \ loop back to BEGIN if flag Z is set
342 test for out of loop version BEGIN ... WHILE ... REPEAT
344 CODE TEST_BEGIN_WHILE_REPEAT
347 SUB #1,R10 \ set Z,N,V flags
348 0<> WHILE \ go to out of loop if X=0 (Z flag =1)
350 REPEAT \ unconditionnal loop back to BEGIN
351 ... \ out of loop here
357 CODE TEST_BEGIN_AGAIN
360 AGAIN \ unconditionnal loop back to BEGIN
363 to quit this infinite loop, press <reset>
366 We can nest several conditional branches :
368 CODE TEST_NESTED_IF_ELSE
385 CODE TEST_NESTED_BEGIN_AGAIN_IF
390 MOV @IP+,PC \ out of test_NESTED_BEGIN_AGAIN_IF
397 you can also MIX conditional branches with a mix of FORTH/assembly :
399 see TEST5 in the demo file \MSP430-FORTH\TESTASM.4TH
405 unconditionnal backward jump :
410 JMP TEST \ jump backward to the word TEST
413 conditionnal backward jump :
418 S< ?JMP TEST \ jump backward to TEST if negative
423 FAST FORTH have one pass assembler, not able to make forward jump.
425 I have added possibility of several "non canonical" jumps, up to 3 backward and up to 3 forward imbricated jumps to label :
427 \ C UM/MOD udlo|udhi u1 -- ur uq
429 MOV @PSP+,W \ 2 W = DIVIDENDhi
430 MOV @PSP,S \ 2 S = DIVIDENDlo
431 \ T.I. ROUTINE Section 5.1.5 of MSP430 Family Application Reports
432 MOV #0,Y \ 1 CLEAR RESULT
433 MOV #16,X \ 2 INITIALIZE LOOP COUNTER
435 U< ?GOTO FW1 \ 2 if not carry
436 SUB TOS,W \ 1 if carry DIVIDENDhi-divisor
437 FW1 \ FW1 label is resolved therefore reusable
438 BW2 ADDC Y,Y \ 1 RLC quotient
439 U>= ?GOTO FW1 \ 2 if carry Error: result > 16 bits
440 SUB #1,X \ 1 Decrement loop counter
441 <0 ?GOTO FW2 \ 2 if 0< terminate w/o error
442 ADD S,S \ 1 RLA DIVIDENDlo
443 ADDC W,W \ 1 RLC DIVIDENDhi
444 U< ?GOTO BW1 \ 2 if not carry 14~ loop
445 SUB TOS,W \ 1 if carry DIVIDENDhi-divisor
447 GOTO BW2 \ 2 14~ loop
448 FW2 BIC #1,SR \ 1 CLRC No error, C = 0
449 FW1 \ Error indication in C
450 \ END T.I. ROUTINE Section 5.1.5 of MSP430 Family Application Reports
451 MOV W,0(PSP) \ 3 remainder on stack
452 MOV Y,TOS \ 1 quotient in TOS
457 SYMBOLIC ASSEMBLER ? YES !
460 I have discovered a little semantic preprocessor "GEMA", just like that FAST FORTH have its symbolic assembler !
462 \config\gema\MSP430FR_FastForth.pat contains variables FORTH for all devices
463 \config\gema\MSP430FR57xx.pat contains declarations for FR57 family
464 \config\gema\MSP430FR5x6x.pat ... for FR59/FR69 families
465 \config\gema\MSP430FR2x4x.pat ... for FR2/FR4 families.
466 \config\gema\DEVICE.pat contains memory map and vectors for a specified DEVICE
467 \MSP430-FORTH\LAUNCHPAD.pat is the I/O config file for specific LAUNCHPAD or application
469 gema translates also FORTH registers in ASM registers (R0 to R15)
471 If you have created a network drive from your local gitlab directory, it's easy :
472 with scite editor open a file.f, then select in the menu "tools" the items "preprocess..."
474 furnished examples : see \MSP430-FORTH\
477 Try SD\_TEST.f to build a SD\_Card test.
480 COMPILE FAST FORTH FOR YOUR MODULE
483 The principle is to create (or modify) first existing configuration files only to compile FAST FORTH.
485 1- in forthMSP430FR.asm "TARGET configuration SWITCHES" create a line for your target, example:
487 ;MY_MSP430FR5738_1 ; compile for my own MSP430FR5738 miniboard
489 2- in Target.inc add one item:
491 .IFDEF MY_MSP430FR5738_1
492 .warning "Code for MY_MSP430FR5738_1"
493 DEVICE = "MSP430FR5738" ; for family.inc file below, defines your device
494 ;CHIP .equ 5738 ; not used
495 UCA0_UART ; for family.inc file below, defines uart used by FORTH input terminal
496 LF_XTAL ; for family.inc file below, defines if your module have a 32768 Hz xtal, to enable it.
497 UCB0_SD ; for family.inc file below, defines UC used for SD Card driver if used
498 .include "MSP430FR57xx.inc" ; include family declarations file: MSP430FR2x4x.inc, MSP430FR57xx.inc or MSP430FR5x6x.inc
499 .ENDIF ; MY_MSP430FR5738_1
501 3- complete family.inc file with declarations for your device if not exists.
502 take care to verify they not already exist in common part at the end of the file.
504 4- include an item in TargetInit.asm:
505 .IFDEF MY_MSP430FR5738_1
506 .include "MSP430FR5738_1.asm"
509 5- create your target MSP430FR5738_1.asm from another target.asm as model, then customize declarations.
512 6- if you use SD Card you must add an item in the forthMSP430FR_SD_INIT.asm file. Proceed as target.asm:
514 .IFDEF MY_MSP430FR5738_1
516 ; COLD default state : Px{DIR,SEL0,SEL1,SELC,IE,IFG,IV} = 0 ; PX{OUT,REN} = 1 ; Px{IN,IES} = ?
525 BIS.B #SD_CS,&P2DIR ; SD_CS output high
527 ; P2.2/UCB0CLK ---> SD_CardAdapter CLK (SCK) default value
528 ; P1.6/UCB0SIMO/UCB0SDA/TA0.0 ---> SD_CardAdapter SDI (MOSI) default value
529 ; P1.7/UCB0SOMI/UCB0SCL/TA1.0 <--- SD_CardAdapter SDO (MISO) default value
530 BIS #04C0h,&PASEL1 ; Configure UCB0 pins: P2.2 as UCB0CLK, P1.6 as UCB0SIMO & P1.7 as UCB0SOMI
531 ; P2DIR.x is controlled by eUSCI_B0 module
532 BIC #04C0h,&PAREN ; disable pullup resistors for SIMO/SOMI/CLK pins
536 Then, for the needs of syntactic preprocessor:
538 1- create a \config\gema\device.pat file if not exist, from analog device.pat file
540 2- create your MSP430-FORTH\target.pat file from analog target.pat file, include same forth declarations as target.asm and complete it for your application
542 Best practice, I suggest you that all digital pins you define (input or output) in your projects have their idle state high, with external pull up resistor
548 How to start your project ?
550 I show you, assuming you are working from the scite editor with its enhanced tools menu.
552 First you create two files : project.f and test.f
556 ; ----------------------------------------------------
557 ; MSP430FR5969 MSP_EXP430FR5969 8MHZ 921600bds PROJECT
558 ; ----------------------------------------------------
559 WIPE ; restore the content of your target.txt HEX file
561 here you append your already tested routines :
563 CODE FIRST \ assembler CODE words are FORTH executable
568 ASM TWO \ assembler ASM words are not FORTH executable and can only be used in assembler mode
569 ... \ used to define interrupt routines, or subroutines as here.
575 CALL #TWO \ CALL only ASM words (finishing with RET(I))...
580 ASM WDT_INT \ interrupt routine
583 BIC #WDTIFG,&SFRIFG1 \ reset WDT_INT flag
584 BIC #$F8,0(RSP) \ set CPU ON and GIE OFF in retiSR
590 then finish with this 2 "magic" words plus one optional : START, STOP and optional BACKGROUND
592 ASM BACKGROUND \ (optional)
593 ... \ insert here your background task
596 MOV #(SLEEP),PC \ Must be the last statement of BACKGROUND
599 CODE START \ to init your app
600 ... \ init assembly part
603 MOV #SLEEP,X \ redirect default background task to yours (optional)
604 MOV #BACKGROUND,2(X) \
607 ... \ init FORTH part
609 \ NOECHO \ uncomment if your app runs without terminal
610 LIT RECURSE IS WARM \ insert START (so your init app) in the FORTH init process
611 (WARM) \ then continue the FORTH init process
615 CODE STOP \ to properly stop your app
616 MOV #SLEEP,X \ restore the default background (optional)
617 MOV #(SLEEP),2(X) \ (words SLEEP and (SLEEP) can only be used in assembler mode)
618 \ (thus "['] (SLEEP) IS SLEEP" don't works.)
620 ['] (WARM) IS WARM \ remove START from FORTH init process
621 ECHO \ to retrieve FORTH input terminal
622 COLD \ reset CPU, interrupt vectors and restart FORTH.
627 RST_HERE ; thus allowing to restart your app with <reset> or COLD
633 Each time you download this project file in LAUNCHPAD, the word WIPE returns the dictionary set as it was in TXT file.
634 And the word RST_HERE protects the PROJECT against <RESET\>.
636 The word START allows to include your app init into FORTH's one.
637 The word STOP unlink your app.
639 Look at the file RC5toLCD.f to retrieve this structure.
645 \ ----------------------------------
646 \ MSP-EXP430FR5969_8MHZ_TEST.f
647 \ ----------------------------------
648 RST_STATE \ restore the state defined by PROJECT.f
650 here you write your routine to test
659 PWR_HERE \ test.f content is protected against POWER OFF, but volatile with <reset>
663 Each time you download this test file, the word RST\_STATE returns the <RESET\> dictionary set (i.e. PROJECT). The word PWR\_HERE protects the test against POWER OFF. without the word PWR\_HERE, the test is lost when power down.
668 With the SCITE menu tools : send a file.f, you download first your project.f file, then your test.f file that include the routine to test.
670 If the test don't work, modify it in the test.f file, then reload it.
672 When the routine "test" works as you want, you cut it in test.f file and copy it in project.f, then when you reload it, test is done !
678 Case of MSP430FR2xxx family (with FLL)
682 Difficult to download CORETEST.4th on CHIPSTICK @ 8MHz without error (tested with USBtoUART device = CP2102).
684 To resolve, I was forced to speed the clock up to 8.29 MHz ! (see ChipStick_fr2433.inc)
686 And there is no this problem @ 16MHz !
688 Is a problem that affects this device only, or corrupt TLV area during welding?
690 If you ever encounter the same difficulty, recompile + download CORETEST.4th several times by increasing each time by 2 the FLLN value until you reach the good compromising...
696 The embedded assembler don't recognize the (useless) TI's symbolic addressing mode: ADD.B EDE,TONI.
698 REGISTERS correspondence
700 ASM TI FASTFORTH comment
702 R0 PC PC Program Counter
703 R1 SP RSP Return Stack Pointer
704 R2 SR/CG1 SR Status Register/Constant Generator 1
705 R3 CG2 Constant Generator 2
706 R4 R4 rDODOES contents address of xdodoes
707 R5 R5 rDOCON contents address of xdocon
708 R6 R6 rDOVAR contents address of RFROM
709 R7 R7 rEXIT contents address of EXIT
710 R8 R8 Y scratch register
711 R9 R9 X scratch register
712 R10 R10 W scratch register
713 R11 R11 T scratch register
714 R12 R12 S scratch register
715 R13 R13 IP Interpretation Pointer
716 R14 R14 TOS Top Of parameters Stack
717 R15 R15 PSP Parameters Stack Pointer
719 FASTFORTH registers must be preprocessed by gema.exe before sending to the embedded assembler.
720 (don't use R3 and use R2 only with register addressing mode).
724 The FASTFORTH registers rDOCOL, rDOVAR, rDOCON and rDODOES must be preserved.
725 PUSHM R13,R10 before use and POPM R10,R13 after.
730 The register TOS (Top Of Stack) is the first cell of the Parameters stack.
731 The register PSP (Parameters Stack Pointer) points the second cell.
733 to push one cell on the PSP stack :
735 SUB #2,PSP \ insert a empty 2th cell
736 MOV TOS,0(PSP) \ mov first cell in this empty 2th cell
737 MOV <what you want>,TOS \ or MOV.B <what you want>,TOS ; i.e. in first cell
740 to pop one cell from the PSP stack :
742 MOV @PSP+,TOS \ first cell TOS is lost
745 don't never pop a byte with instruction MOV.B @PSP+, ...
749 register RSP is the Return Stack Pointer (SP).
751 to push one cell on the RSP stack :
753 PUSH <what you want> \
756 to pop one cell from the RSP stack :
758 MOV @RSP+,<where you want> \
761 don't never pop a byte with instruction MOV.B @RSP+, ...
764 to push multiple registers on the RSP stack :
769 to pop multiple registers from the RSP stack :
774 CPUx instructions PUSHM / POPM (my own syntax, not the TI's one, too bad :-)
776 PUSHM order : PSP,TOS,IP, S, T, W, X, Y, R7, R6, R5, R4
778 example : PUSHM IP,Y \ push IP, S, T, W, X, Y registers onto the stack RSP
781 POPM order : R4, R5, R6, R7, Y, X, W, T, S, IP,TOS,PSP
783 example : POPM Y,IP \ pop Y, X, W, T, S, IP registers from the stack RSP
785 error occurs if bad order (PUSHM Y,IP for example)
788 CPUx instructions RRCM,RRAM,RLAM,RRUM
790 example : RRUM #3,R8 \ R8 register is Unsigned Right shifted by n=3
792 error occurs if 1 > n > 4
795 conditionnal jumps use with symbolic assembler
797 0= { IF UNTIL WHILE ?JMP ?GOTO }
798 0<> { IF UNTIL WHILE ?JMP ?GOTO }
799 U>= { IF UNTIL WHILE ?JMP ?GOTO }
800 U< { IF UNTIL WHILE ?JMP ?GOTO }
801 S< { IF UNTIL WHILE ?JMP ?GOTO }
802 S>= { IF UNTIL WHILE ?JMP ?GOTO }
803 0>= { IF UNTIL WHILE }